From 36eef8f58d35b5d4a30a3dff4b74d6f2326d0caa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maksymilian=20Wilczy=C5=84ski?= Date: Wed, 28 Oct 2026 15:18:43 +0100 Subject: [PATCH] replace nob with ms' build, move disk creation to build.bat, major comment cleanup, remove old and stupid tests, overhaul interrupt management with per-CPU vector allocation, affinity migration and safe teardown, add proper IOAPIC routing and PCI MSI/MSI-X/INTx support, migrate drivers to the new interrupt API, integrate ACPICA with a proper OS services layer, move ACPI firmware events, power button handling and S5 shutdown into acpi.sys, add parallel driver startup and atomic publication, replace PnP arrays with dynamic lists, redesign service startup again to be asynchronous, add delayed startup mode for services, allow omitting keys in services.ini, fix acpi ec deferred work handling, fix kernel threads having garbage exit code. --- .gitignore | 21 +- OVMF/OVMF_VARS_4M_d.fd | Bin 540672 -> 540672 bytes build.bat | 137 +- code/boot.ini | 4 +- code/boot/dirs | 1 + code/boot/uefi/main.c | 3 - code/boot/uefi/makefile | 1 + code/boot/uefi/sources | 11 + code/build/build.c | 715 --- code/build/nob.h | 3286 ------------ code/common/dirs | 1 + code/common/libc.c | 15 - code/common/libc/makefile | 1 + code/common/libc/sources | 5 + code/common/printf/makefile | 1 + code/common/printf/sources | 5 + code/ddk/makefile | 1 + code/ddk/sources | 5 + code/dirs | 1 + code/{drivers => }/drivers.ini | 11 +- code/drivers/audio/dirs | 1 + code/drivers/audio/hda/hda.c | 133 +- code/drivers/audio/hda/hda.h | 2 +- code/drivers/audio/hda/makefile | 1 + code/drivers/audio/hda/sources | 7 + code/drivers/bus/dirs | 1 + code/drivers/bus/pci/makefile | 1 + code/drivers/bus/pci/pci.c | 375 +- code/drivers/bus/pci/pci.h | 5 +- code/drivers/bus/pci/sources | 8 + code/drivers/bus/usb/makefile | 1 + code/drivers/bus/usb/sources | 8 + code/drivers/bus/usb/usb.h | 5 +- code/drivers/bus/usb/usb_bus.c | 19 - code/drivers/bus/usb/usb_composite.c | 4 - code/drivers/bus/usb/usb_core.c | 4 - code/drivers/bus/usb/usb_hid.c | 15 - code/drivers/bus/usb/usb_hub.c | 31 - code/drivers/bus/usb/usb_storage.c | 17 - code/drivers/bus/usb/usb_xhci.c | 169 +- code/drivers/dirs | 1 + code/drivers/display/dirs | 1 + code/drivers/display/vmwaresvga/makefile | 1 + code/drivers/display/vmwaresvga/sources | 7 + code/drivers/display/vmwaresvga/vmwaresvga.c | 31 - code/drivers/fs/dirs | 1 + code/drivers/fs/ext4/ext4_driver.c | 8 +- code/drivers/fs/ext4/makefile | 1 + code/drivers/fs/ext4/sources | 11 + code/drivers/fs/fat/fat.c | 10 - code/drivers/fs/fat/fat_async.c | 8 - code/drivers/fs/fat/fat_directory.c | 13 - code/drivers/fs/fat/fat_driver.c | 8 +- code/drivers/fs/fat/makefile | 1 + code/drivers/fs/fat/sources | 7 + code/drivers/fs/ntfs/dirs | 1 + code/drivers/fs/ntfs/ntfs.c | 8 +- code/drivers/fs/ntfs/ntfs3g/makefile | 1 + code/drivers/fs/ntfs/ntfs3g/ntfs3g_driver.c | 6 +- code/drivers/fs/ntfs/ntfs3g/sources | 13 + code/drivers/input/dirs | 1 + code/drivers/input/ps2/makefile | 1 + code/drivers/input/ps2/ps2.c | 66 +- code/drivers/input/ps2/ps2_i8042.c | 11 - code/drivers/input/ps2/sources | 7 + code/drivers/input/serial/makefile | 1 + code/drivers/input/serial/serial.c | 26 +- code/drivers/input/serial/sources | 7 + code/drivers/net/dirs | 1 + code/drivers/net/lwip/lwip_stack.c | 27 - code/drivers/net/lwip/lwip_sys_arch.c | 12 - code/drivers/net/lwip/makefile | 1 + code/drivers/net/lwip/sources | 15 + code/drivers/net/rtl8139/makefile | 1 + code/drivers/net/rtl8139/rtl8139.c | 128 +- code/drivers/net/rtl8139/rtl8139.h | 2 +- code/drivers/net/rtl8139/sources | 7 + code/drivers/net/rtl816x/makefile | 1 + code/drivers/net/rtl816x/rtl816x.c | 169 +- code/drivers/net/rtl816x/rtl816x.h | 2 +- code/drivers/net/rtl816x/sources | 7 + code/drivers/platform/acpi/acpi.c | 157 + code/drivers/platform/acpi/acpi_ec.c | 249 + code/drivers/platform/acpi/acpi_local.h | 26 + code/drivers/platform/acpi/acpi_osl.c | 473 ++ code/drivers/platform/acpi/acpica_sources.txt | 164 + code/drivers/platform/acpi/makefile | 1 + code/drivers/platform/acpi/sources | 35 + .../third_party/acpica/LICENSE.BSD-3-Clause | 28 + .../third_party/acpica/LICENSE.GPL-2.0-only | 338 ++ .../acpica/components/dispatcher/dsargs.c | 410 ++ .../acpica/components/dispatcher/dscontrol.c | 388 ++ .../acpica/components/dispatcher/dsdebug.c | 227 + .../acpica/components/dispatcher/dsfield.c | 878 ++++ .../acpica/components/dispatcher/dsinit.c | 244 + .../acpica/components/dispatcher/dsmethod.c | 958 ++++ .../acpica/components/dispatcher/dsmthdat.c | 749 +++ .../acpica/components/dispatcher/dsobject.c | 560 +++ .../acpica/components/dispatcher/dsopcode.c | 812 +++ .../acpica/components/dispatcher/dspkginit.c | 564 +++ .../acpica/components/dispatcher/dsutils.c | 917 ++++ .../acpica/components/dispatcher/dswexec.c | 790 +++ .../acpica/components/dispatcher/dswload.c | 615 +++ .../acpica/components/dispatcher/dswload2.c | 770 +++ .../acpica/components/dispatcher/dswscope.c | 203 + .../acpica/components/dispatcher/dswstate.c | 817 +++ .../acpica/components/events/evevent.c | 311 ++ .../acpica/components/events/evglock.c | 354 ++ .../acpica/components/events/evgpe.c | 1034 ++++ .../acpica/components/events/evgpeblk.c | 539 ++ .../acpica/components/events/evgpeinit.c | 437 ++ .../acpica/components/events/evgpeutil.c | 368 ++ .../acpica/components/events/evhandler.c | 595 +++ .../acpica/components/events/evmisc.c | 346 ++ .../acpica/components/events/evregion.c | 946 ++++ .../acpica/components/events/evrgnini.c | 693 +++ .../acpica/components/events/evsci.c | 391 ++ .../acpica/components/events/evxface.c | 1238 +++++ .../acpica/components/events/evxfevnt.c | 421 ++ .../acpica/components/events/evxfgpe.c | 1217 +++++ .../acpica/components/events/evxfregn.c | 339 ++ .../acpica/components/executer/exconcat.c | 570 +++ .../acpica/components/executer/exconfig.c | 769 +++ .../acpica/components/executer/exconvrt.c | 786 +++ .../acpica/components/executer/excreate.c | 660 +++ .../acpica/components/executer/exdebug.c | 323 ++ .../acpica/components/executer/exdump.c | 1282 +++++ .../acpica/components/executer/exfield.c | 465 ++ .../acpica/components/executer/exfldio.c | 1018 ++++ .../acpica/components/executer/exmisc.c | 643 +++ .../acpica/components/executer/exmutex.c | 555 +++ .../acpica/components/executer/exnames.c | 447 ++ .../acpica/components/executer/exoparg1.c | 1131 +++++ .../acpica/components/executer/exoparg2.c | 612 +++ .../acpica/components/executer/exoparg3.c | 417 ++ .../acpica/components/executer/exoparg6.c | 465 ++ .../acpica/components/executer/exprep.c | 637 +++ .../acpica/components/executer/exregion.c | 571 +++ .../acpica/components/executer/exresnte.c | 262 + .../acpica/components/executer/exresolv.c | 563 +++ .../acpica/components/executer/exresop.c | 702 +++ .../acpica/components/executer/exserial.c | 393 ++ .../acpica/components/executer/exstore.c | 630 +++ .../acpica/components/executer/exstoren.c | 274 + .../acpica/components/executer/exstorob.c | 210 + .../acpica/components/executer/exsystem.c | 324 ++ .../acpica/components/executer/extrace.c | 431 ++ .../acpica/components/executer/exutils.c | 477 ++ .../acpica/components/hardware/hwacpi.c | 191 + .../acpica/components/hardware/hwesleep.c | 238 + .../acpica/components/hardware/hwgpe.c | 659 +++ .../acpica/components/hardware/hwpci.c | 433 ++ .../acpica/components/hardware/hwregs.c | 874 ++++ .../acpica/components/hardware/hwsleep.c | 344 ++ .../acpica/components/hardware/hwtimer.c | 210 + .../acpica/components/hardware/hwvalid.c | 334 ++ .../acpica/components/hardware/hwxface.c | 508 ++ .../acpica/components/hardware/hwxfsleep.c | 485 ++ .../acpica/components/namespace/nsaccess.c | 781 +++ .../acpica/components/namespace/nsalloc.c | 570 +++ .../acpica/components/namespace/nsarguments.c | 291 ++ .../acpica/components/namespace/nsconvert.c | 536 ++ .../acpica/components/namespace/nsdump.c | 1058 ++++ .../acpica/components/namespace/nsdumpdv.c | 265 + .../acpica/components/namespace/nseval.c | 460 ++ .../acpica/components/namespace/nsinit.c | 739 +++ .../acpica/components/namespace/nsload.c | 328 ++ .../acpica/components/namespace/nsnames.c | 547 ++ .../acpica/components/namespace/nsobject.c | 499 ++ .../acpica/components/namespace/nsparse.c | 301 ++ .../acpica/components/namespace/nspredef.c | 406 ++ .../acpica/components/namespace/nsprepkg.c | 769 +++ .../acpica/components/namespace/nsrepair.c | 601 +++ .../acpica/components/namespace/nsrepair2.c | 1052 ++++ .../acpica/components/namespace/nssearch.c | 423 ++ .../acpica/components/namespace/nsutils.c | 856 ++++ .../acpica/components/namespace/nswalk.c | 358 ++ .../acpica/components/namespace/nsxfeval.c | 1075 ++++ .../acpica/components/namespace/nsxfname.c | 689 +++ .../acpica/components/namespace/nsxfobj.c | 251 + .../acpica/components/parser/psargs.c | 1161 +++++ .../acpica/components/parser/psloop.c | 574 +++ .../acpica/components/parser/psobject.c | 748 +++ .../acpica/components/parser/psopcode.c | 314 ++ .../acpica/components/parser/psopinfo.c | 254 + .../acpica/components/parser/psparse.c | 722 +++ .../acpica/components/parser/psscope.c | 270 + .../acpica/components/parser/pstree.c | 333 ++ .../acpica/components/parser/psutils.c | 264 + .../acpica/components/parser/pswalk.c | 116 + .../acpica/components/parser/psxface.c | 380 ++ .../acpica/components/resources/rsaddr.c | 381 ++ .../acpica/components/resources/rscalc.c | 855 ++++ .../acpica/components/resources/rscreate.c | 480 ++ .../acpica/components/resources/rsdump.c | 695 +++ .../acpica/components/resources/rsdumpinfo.c | 424 ++ .../acpica/components/resources/rsinfo.c | 266 + .../acpica/components/resources/rsio.c | 270 + .../acpica/components/resources/rsirq.c | 288 ++ .../acpica/components/resources/rslist.c | 258 + .../acpica/components/resources/rsmemory.c | 217 + .../acpica/components/resources/rsmisc.c | 805 +++ .../acpica/components/resources/rsserial.c | 875 ++++ .../acpica/components/resources/rsutils.c | 840 ++++ .../acpica/components/resources/rsxface.c | 714 +++ .../acpica/components/tables/tbdata.c | 1299 +++++ .../acpica/components/tables/tbfadt.c | 758 +++ .../acpica/components/tables/tbfind.c | 147 + .../acpica/components/tables/tbinstal.c | 331 ++ .../acpica/components/tables/tbprint.c | 171 + .../acpica/components/tables/tbutils.c | 483 ++ .../acpica/components/tables/tbxface.c | 609 +++ .../acpica/components/tables/tbxfload.c | 514 ++ .../acpica/components/tables/tbxfroot.c | 307 ++ .../acpica/components/utilities/utaddress.c | 285 ++ .../acpica/components/utilities/utalloc.c | 379 ++ .../acpica/components/utilities/utascii.c | 131 + .../acpica/components/utilities/utbuffer.c | 340 ++ .../acpica/components/utilities/utcache.c | 324 ++ .../acpica/components/utilities/utcksum.c | 197 + .../acpica/components/utilities/utclib.c | 1030 ++++ .../acpica/components/utilities/utcopy.c | 1055 ++++ .../acpica/components/utilities/utdebug.c | 705 +++ .../acpica/components/utilities/utdecode.c | 663 +++ .../acpica/components/utilities/utdelete.c | 800 +++ .../acpica/components/utilities/uterror.c | 372 ++ .../acpica/components/utilities/uteval.c | 349 ++ .../acpica/components/utilities/utexcep.c | 149 + .../acpica/components/utilities/utglobal.c | 210 + .../acpica/components/utilities/uthex.c | 126 + .../acpica/components/utilities/utids.c | 448 ++ .../acpica/components/utilities/utinit.c | 321 ++ .../acpica/components/utilities/utlock.c | 172 + .../acpica/components/utilities/utmath.c | 586 +++ .../acpica/components/utilities/utmisc.c | 435 ++ .../acpica/components/utilities/utmutex.c | 387 ++ .../acpica/components/utilities/utnonansi.c | 222 + .../acpica/components/utilities/utobject.c | 754 +++ .../acpica/components/utilities/utosi.c | 533 ++ .../acpica/components/utilities/utownerid.c | 215 + .../acpica/components/utilities/utpredef.c | 420 ++ .../acpica/components/utilities/utprint.c | 1016 ++++ .../acpica/components/utilities/utresdecode.c | 345 ++ .../acpica/components/utilities/utresrc.c | 665 +++ .../acpica/components/utilities/utstate.c | 324 ++ .../acpica/components/utilities/utstring.c | 247 + .../acpica/components/utilities/utstrsuppt.c | 525 ++ .../acpica/components/utilities/utstrtoul64.c | 364 ++ .../acpica/components/utilities/uttrack.c | 771 +++ .../acpica/components/utilities/utuuid.c | 121 + .../acpica/components/utilities/utxface.c | 613 +++ .../acpica/components/utilities/utxferror.c | 324 ++ .../acpica/components/utilities/utxfinit.c | 292 ++ .../acpica/components/utilities/utxfmutex.c | 185 + .../acpi/third_party/acpica/include/acapps.h | 205 + .../third_party/acpica/include/acbuffer.h | 234 + .../acpi/third_party/acpica/include/acclib.h | 293 ++ .../third_party/acpica/include/accommon.h | 37 + .../third_party/acpica/include/acconfig.h | 239 + .../third_party/acpica/include/acconvert.h | 173 + .../acpi/third_party/acpica/include/acdebug.h | 488 ++ .../third_party/acpica/include/acdisasm.h | 1507 ++++++ .../third_party/acpica/include/acdispat.h | 461 ++ .../third_party/acpica/include/acevents.h | 374 ++ .../acpi/third_party/acpica/include/acexcep.h | 348 ++ .../third_party/acpica/include/acglobal.h | 399 ++ .../acpi/third_party/acpica/include/achware.h | 201 + .../third_party/acpica/include/acinterp.h | 758 +++ .../acpi/third_party/acpica/include/aclocal.h | 1527 ++++++ .../third_party/acpica/include/acmacros.h | 509 ++ .../acpi/third_party/acpica/include/acnames.h | 68 + .../third_party/acpica/include/acnamesp.h | 555 +++ .../third_party/acpica/include/acobject.h | 569 +++ .../third_party/acpica/include/acopcode.h | 303 ++ .../third_party/acpica/include/acoutput.h | 481 ++ .../third_party/acpica/include/acparser.h | 338 ++ .../acpi/third_party/acpica/include/acpi.h | 37 + .../third_party/acpica/include/acpiosxf.h | 567 +++ .../acpi/third_party/acpica/include/acpixf.h | 1312 +++++ .../third_party/acpica/include/acpredef.h | 1171 +++++ .../acpi/third_party/acpica/include/acresrc.h | 569 +++ .../third_party/acpica/include/acrestyp.h | 820 +++ .../third_party/acpica/include/acstruct.h | 255 + .../third_party/acpica/include/actables.h | 245 + .../third_party/acpica/include/actbinfo.h | 449 ++ .../acpi/third_party/acpica/include/actbl.h | 441 ++ .../acpi/third_party/acpica/include/actbl1.h | 2637 ++++++++++ .../acpi/third_party/acpica/include/actbl2.h | 4429 +++++++++++++++++ .../acpi/third_party/acpica/include/actbl3.h | 906 ++++ .../acpi/third_party/acpica/include/actypes.h | 1449 ++++++ .../acpi/third_party/acpica/include/acutils.h | 1170 +++++ .../acpi/third_party/acpica/include/acuuid.h | 89 + .../acpi/third_party/acpica/include/amlcode.h | 480 ++ .../third_party/acpica/include/amlresrc.h | 762 +++ .../acpica/include/platform/accygwin.h | 71 + .../acpica/include/platform/acdragonfly.h | 236 + .../acpica/include/platform/acdragonflyex.h | 54 + .../acpica/include/platform/acefi.h | 285 ++ .../acpica/include/platform/acefiex.h | 1034 ++++ .../acpica/include/platform/acenv.h | 390 ++ .../acpica/include/platform/acenvex.h | 52 + .../acpica/include/platform/acfreebsd.h | 91 + .../acpica/include/platform/acgcc.h | 97 + .../acpica/include/platform/acgccex.h | 28 + .../acpica/include/platform/achaiku.h | 81 + .../acpica/include/platform/acintel.h | 60 + .../acpica/include/platform/aclinux.h | 218 + .../acpica/include/platform/aclinuxex.h | 138 + .../acpica/include/platform/acmacosx.h | 27 + .../acpica/include/platform/acmsvc.h | 204 + .../acpica/include/platform/acmsvcex.h | 67 + .../acpica/include/platform/acnetbsd.h | 83 + .../acpica/include/platform/acntlite.h | 7 + .../acpica/include/platform/acos2.h | 68 + .../acpica/include/platform/acqnx.h | 41 + .../acpica/include/platform/acwin.h | 174 + .../acpica/include/platform/acwin64.h | 96 + .../acpica/include/platform/aczephyr.h | 199 + code/drivers/platform/dirs | 1 + code/drivers/storage/ahci/ahci.c | 141 +- code/drivers/storage/ahci/ahci.h | 2 +- code/drivers/storage/ahci/ahci_port.c | 8 - code/drivers/storage/ahci/makefile | 1 + code/drivers/storage/ahci/sources | 7 + code/drivers/storage/ata/ata.c | 13 - code/drivers/storage/ata/makefile | 1 + code/drivers/storage/ata/sources | 7 + code/drivers/storage/dirs | 1 + code/kernel/core/makefile | 1 + code/kernel/core/sources | 21 + code/kernel/dirs | 1 + code/kernel/dm_config.c | 5 +- code/kernel/driver_module.c | 95 +- code/kernel/hal/hal_apic.c | 270 +- code/kernel/hal/hal_main.c | 126 +- code/kernel/hal/hal_pci.c | 1 - code/kernel/hal/hal_rtc.c | 10 - code/kernel/hal/hal_screen.c | 8 - code/kernel/hal/hal_timer.c | 16 +- code/kernel/hal/makefile | 1 + code/kernel/hal/sources | 11 + code/kernel/include/kernel/dm_config.h | 1 + code/kernel/include/kernel/driver_module.h | 5 +- code/kernel/include/kernel/hal/hal_api.h | 26 +- code/kernel/include/kernel/hal/hal_apic.h | 18 +- code/kernel/include/kernel/io_pnp.h | 4 +- code/kernel/include/kernel/ke_boot_config.h | 2 - code/kernel/include/kernel/ke_firmware.h | 8 + code/kernel/include/kernel/ke_idt.h | 4 +- code/kernel/include/kernel/ke_irq.h | 19 +- code/kernel/include/kernel/ke_irql.h | 4 +- code/kernel/include/kernel/ke_power.h | 5 +- code/kernel/include/kernel/ke_vectors.h | 12 + code/kernel/include/kernel/ldr_image.h | 7 +- code/kernel/include/kernel/syscall_nr.h | 2 +- code/kernel/io_ddk.c | 131 +- code/kernel/io_device.c | 27 +- code/kernel/io_file.c | 4 - code/kernel/io_pnp.c | 242 +- code/kernel/io_volume.c | 4 +- code/kernel/ke_apc.c | 8 - code/kernel/ke_audio.c | 1 - code/kernel/ke_boot_config.c | 5 - code/kernel/ke_debug.c | 84 +- code/kernel/ke_display.c | 36 - code/kernel/ke_dpc.c | 2 - code/kernel/ke_event.c | 1 - code/kernel/ke_firmware.c | 106 + code/kernel/ke_hal.c | 6 +- code/kernel/ke_idt.c | 323 +- code/kernel/ke_input.c | 9 - code/kernel/ke_irp.c | 5 - code/kernel/ke_irq.c | 697 ++- code/kernel/ke_irql.c | 33 +- code/kernel/ke_power.c | 150 +- code/kernel/ke_sched.c | 30 - code/kernel/ke_semaphore.c | 2 - code/kernel/ke_smp.c | 13 - code/kernel/ke_syscall.asm | 158 +- code/kernel/ke_syscall.c | 8 +- code/kernel/ke_thread.c | 19 +- code/kernel/ke_time.c | 15 - code/kernel/ke_timer.c | 1 - code/kernel/ke_trap.c | 3 - code/kernel/kmain.c | 292 +- code/kernel/ldr_image.c | 140 +- code/kernel/mm_pool.c | 5 - code/kernel/mm_virt.c | 7 +- code/kernel/net_device.c | 7 - code/kernel/net_stack.c | 3 - code/public/ntlite/ddi/pci.h | 21 +- code/public/ntlite/ddk/ddk.h | 1 + code/public/ntlite/ddk/debug.h | 3 +- code/public/ntlite/ddk/interrupt.h | 53 +- code/public/ntlite/ddk/memory.h | 5 + code/public/ntlite/ddk/module.h | 54 +- code/public/ntlite/ddk/platform.h | 5 + code/public/ntlite/ddk/power.h | 36 + code/public/ntlite/ddk/thread.h | 3 + code/public/ntlite/native_heap.h | 10 + code/public/ntlite/string_view.h | 13 - code/public/ntlite/syscall.h | 2 +- code/services.ini | 43 +- code/tests/ddk/module_export_smoke.c | 10 - code/tests/ddk/pci_caps_test.c | 37 - code/tests/driver_manager/README.md | 13 - code/tests/driver_manager/config_test.c | 138 - .../pnp_mock/include/kernel/ke_debug.h | 2 - .../pnp_mock/include/kernel/ke_event.h | 10 - .../pnp_mock/include/kernel/ke_spinlock.h | 7 - .../pnp_mock/include/kernel/ke_thread.h | 9 - .../pnp_mock/include/kernel/ke_time.h | 4 - .../pnp_mock/include/kernel/ke_work.h | 9 - .../pnp_mock/include/kernel/mm_virt.h | 4 - .../pnp_mock/include/ntlite/ddi/io_driver.h | 60 - code/tests/driver_manager/pnp_test.c | 350 -- code/tests/host/service_control_contract.c | 65 - code/tests/memtop_host/test.c | 62 - code/tests/service_grants_host/test.c | 72 - code/tests/service_publication_host/test.c | 30 - code/tests/service_restart_host/test.c | 18 - code/user/apps/dirs | 1 + code/user/apps/doom/doom.c | 2 +- code/user/apps/doom/doom_audio.c | 2 +- code/user/apps/doom/makefile | 1 + code/user/apps/doom/sources | 7 + code/user/apps/edit/edit.c | 12 - code/user/apps/edit/makefile | 1 + code/user/apps/edit/sources | 7 + code/user/apps/httpget/httpget.c | 6 - code/user/apps/httpget/makefile | 1 + code/user/apps/httpget/sources | 7 + code/user/apps/memtop/makefile | 1 + code/user/apps/memtop/sources | 7 + code/user/apps/ping/makefile | 1 + code/user/apps/ping/ping.c | 5 - code/user/apps/ping/sources | 7 + code/user/apps/resolve/makefile | 1 + code/user/apps/resolve/resolve.c | 1 - code/user/apps/resolve/sources | 7 + code/user/apps/shell_native/makefile | 1 + code/user/apps/shell_native/shell_native.c | 12 - code/user/apps/shell_native/sources | 7 + code/user/apps/shell_posix/makefile | 1 + code/user/apps/shell_posix/shell_posix.c | 6 - code/user/apps/shell_posix/sources | 7 + code/user/apps/shell_win32/makefile | 1 + code/user/apps/shell_win32/shell_win32.c | 4 - code/user/apps/shell_win32/sources | 7 + code/user/apps/tcpserve/makefile | 1 + code/user/apps/tcpserve/sources | 7 + code/user/apps/tcpserve/tcpserve.c | 2 - code/user/apps/udp/makefile | 1 + code/user/apps/udp/sources | 7 + code/user/apps/udp/udp.c | 2 - code/user/apps/video/makefile | 1 + code/user/apps/video/sources | 7 + code/user/dirs | 2 + code/user/personalities/dirs | 1 + code/user/personalities/posix/makefile | 1 + code/user/personalities/posix/posix_dir.c | 5 - code/user/personalities/posix/posix_socket.c | 15 - code/user/personalities/posix/posix_thread.c | 8 - code/user/personalities/posix/posix_vfork.asm | 2 +- code/user/personalities/posix/sources | 13 + code/user/personalities/win32/gdi32.c | 2 +- code/user/personalities/win32/kernel32.c | 53 +- code/user/personalities/win32/makefile | 1 + code/user/personalities/win32/ole32.c | 3 +- code/user/personalities/win32/sources | 10 + code/user/personalities/win32/user32.c | 2 - code/user/personalities/win32/winmm_waveout.c | 2 +- code/user/runtime/dirs | 1 + code/user/runtime/heap.c | 5 - code/user/runtime/native_runtime/makefile | 1 + code/user/runtime/native_runtime/sources | 5 + code/user/runtime/posix_start/makefile | 1 + code/user/runtime/posix_start/sources | 5 + code/user/syscall/dirs | 1 + code/user/syscall/dynamic/makefile | 1 + code/user/syscall/dynamic/sources | 12 + code/user/syscall/static/makefile | 1 + code/user/syscall/static/sources | 9 + code/user/syscall/syscall_stubs.asm | 6 +- code/user/system/dirs | 1 + code/user/system/dwm/dwm.c | 2 +- code/user/system/dwm/makefile | 1 + code/user/system/dwm/sources | 7 + code/user/system/init/init.c | 430 +- code/user/system/init/makefile | 1 + code/user/system/init/restart_budget.h | 21 +- code/user/system/init/service_config.c | 210 +- code/user/system/init/service_config.h | 11 + code/user/system/init/sources | 7 + code/user/system/posixsrv/makefile | 1 + code/user/system/posixsrv/posixsrv.c | 2 +- code/user/system/posixsrv/sources | 7 + code/user/system/rssrv/console.c | 2 +- code/user/system/rssrv/input.c | 2 +- code/user/system/rssrv/makefile | 1 + code/user/system/rssrv/namespace.c | 2 +- code/user/system/rssrv/resource_service.c | 2 +- code/user/system/rssrv/sources | 8 + code/user/system/rssrv/volume.c | 2 +- code/user/tests/all_tests/all_tests.c | 5 - code/user/tests/all_tests/makefile | 1 + code/user/tests/all_tests/sources | 7 + .../anonymous_queue_smoke.c | 5 - .../user/tests/anonymous_queue_smoke/makefile | 1 + code/user/tests/anonymous_queue_smoke/sources | 7 + .../tests/apc_return_smoke/apc_return_smoke.c | 1 - code/user/tests/apc_return_smoke/makefile | 1 + code/user/tests/apc_return_smoke/sources | 7 + code/user/tests/async_apc/makefile | 1 + code/user/tests/async_apc/sources | 7 + code/user/tests/async_cancel/makefile | 1 + code/user/tests/async_cancel/sources | 7 + .../audio_stream_smoke/audio_stream_smoke.c | 7 - code/user/tests/audio_stream_smoke/makefile | 1 + code/user/tests/audio_stream_smoke/sources | 7 + .../console_service_smoke.c | 2 - .../user/tests/console_service_smoke/makefile | 1 + code/user/tests/console_service_smoke/sources | 7 + code/user/tests/cwd_userspace_smoke/makefile | 1 + code/user/tests/cwd_userspace_smoke/sources | 7 + code/user/tests/desktop_smoke/desktop_smoke.c | 2 - code/user/tests/desktop_smoke/makefile | 1 + code/user/tests/desktop_smoke/sources | 7 + code/user/tests/dirs | 1 + code/user/tests/dirty_writeback/makefile | 1 + code/user/tests/dirty_writeback/sources | 7 + .../exception_dispatcher_smoke.c | 5 - .../tests/exception_dispatcher_smoke/makefile | 1 + .../tests/exception_dispatcher_smoke/sources | 7 + .../tests/exception_smoke/exception_smoke.c | 5 - code/user/tests/exception_smoke/makefile | 1 + code/user/tests/exception_smoke/sources | 7 + .../tests/file_lock_smoke/file_lock_smoke.c | 6 - code/user/tests/file_lock_smoke/makefile | 1 + code/user/tests/file_lock_smoke/sources | 7 + .../tests/file_stat_smoke/file_stat_smoke.c | 5 - code/user/tests/file_stat_smoke/makefile | 1 + code/user/tests/file_stat_smoke/sources | 7 + .../tests/handle_dup_smoke/handle_dup_smoke.c | 5 - code/user/tests/handle_dup_smoke/makefile | 1 + code/user/tests/handle_dup_smoke/sources | 7 + .../tests/input_api_smoke/input_api_smoke.c | 5 - .../input_model_smoke/input_model_smoke.c | 5 - .../input_service_smoke/input_service_smoke.c | 2 - code/user/tests/input_service_smoke/makefile | 1 + code/user/tests/input_service_smoke/sources | 7 + code/user/tests/mmap_smoke/makefile | 1 + code/user/tests/mmap_smoke/sources | 7 + code/user/tests/module_load_smoke/makefile | 1 + code/user/tests/module_load_smoke/sources | 7 + .../named_queue_lifetime_smoke.c | 5 - .../native_exception_runtime_smoke/makefile | 1 + .../native_exception_runtime_smoke.c | 5 - .../native_exception_runtime_smoke/sources | 7 + .../native_raise_exception_smoke/makefile | 1 + .../native_raise_exception_smoke.c | 5 - .../native_raise_exception_smoke/sources | 7 + code/user/tests/net_irp_smoke/makefile | 1 + code/user/tests/net_irp_smoke/net_irp_smoke.c | 5 - code/user/tests/net_irp_smoke/sources | 7 + code/user/tests/pcache_invalidate/makefile | 1 + code/user/tests/pcache_invalidate/sources | 7 + .../tests/pcache_mmap_read_reuse/makefile | 1 + .../user/tests/pcache_mmap_read_reuse/sources | 7 + code/user/tests/pcache_multithread/makefile | 1 + code/user/tests/pcache_multithread/sources | 7 + code/user/tests/pcache_pressure/makefile | 1 + code/user/tests/pcache_pressure/sources | 7 + code/user/tests/pcache_smoke/makefile | 1 + code/user/tests/pcache_smoke/sources | 7 + code/user/tests/port_ipc_smoke/makefile | 1 + .../tests/port_ipc_smoke/port_ipc_smoke.c | 2 - code/user/tests/port_ipc_smoke/sources | 7 + code/user/tests/posix_fd_smoke/makefile | 1 + .../tests/posix_fd_smoke/posix_fd_smoke.c | 2 - code/user/tests/posix_fd_smoke/sources | 7 + code/user/tests/posix_module_smoke/makefile | 1 + .../posix_module_smoke/posix_module_smoke.c | 3 - code/user/tests/posix_module_smoke/sources | 7 + code/user/tests/posix_pipe_smoke/makefile | 1 + .../tests/posix_pipe_smoke/posix_pipe_smoke.c | 1 - code/user/tests/posix_pipe_smoke/sources | 7 + code/user/tests/posix_process_smoke/makefile | 1 + .../posix_process_smoke/posix_process_smoke.c | 1 - code/user/tests/posix_process_smoke/sources | 7 + code/user/tests/posix_runtime_smoke/makefile | 1 + .../posix_runtime_smoke/posix_runtime_smoke.c | 1 - code/user/tests/posix_runtime_smoke/sources | 7 + code/user/tests/posix_service_smoke/makefile | 1 + .../posix_service_smoke/posix_service_smoke.c | 1 - code/user/tests/posix_service_smoke/sources | 7 + code/user/tests/posix_signal_smoke/makefile | 1 + .../posix_signal_smoke/posix_signal_smoke.c | 2 - code/user/tests/posix_signal_smoke/sources | 7 + .../user/tests/process_builder_smoke/makefile | 1 + code/user/tests/process_builder_smoke/sources | 7 + .../process_exit_multithread_smoke/makefile | 1 + .../process_exit_multithread_smoke.c | 2 - .../process_exit_multithread_smoke/sources | 7 + .../tests/process_protection_smoke/makefile | 1 + .../process_protection_smoke.c | 4 - .../tests/process_protection_smoke/sources | 7 + code/user/tests/realpath_smoke/makefile | 1 + code/user/tests/realpath_smoke/sources | 7 + .../tests/resource_service_smoke/makefile | 1 + .../user/tests/resource_service_smoke/sources | 7 + code/user/tests/security_smoke/makefile | 1 + .../tests/security_smoke/security_smoke.c | 2 - code/user/tests/security_smoke/sources | 7 + code/user/tests/shared_mmap/makefile | 1 + code/user/tests/shared_mmap/shared_mmap.c | 1 - code/user/tests/shared_mmap/sources | 7 + code/user/tests/socket_addr_smoke/makefile | 1 + .../socket_addr_smoke/socket_addr_smoke.c | 5 - code/user/tests/socket_addr_smoke/sources | 7 + code/user/tests/stats_abi_smoke/makefile | 1 + code/user/tests/stats_abi_smoke/sources | 7 + .../tests/stats_abi_smoke/stats_abi_smoke.c | 5 - .../surface_cross_process_smoke/makefile | 1 + .../tests/surface_cross_process_smoke/sources | 7 + .../surface_cross_process_smoke.c | 3 - code/user/tests/surface_invalid_rect/makefile | 1 + code/user/tests/surface_invalid_rect/sources | 7 + .../tests/surface_multithread_commit/makefile | 1 + .../tests/surface_multithread_commit/sources | 7 + code/user/tests/surface_smoke/makefile | 1 + code/user/tests/surface_smoke/sources | 7 + .../tests/syscall_contract_smoke/makefile | 1 + .../user/tests/syscall_contract_smoke/sources | 7 + .../syscall_contract_smoke.c | 5 - code/user/tests/thread_name_smoke/makefile | 1 + code/user/tests/thread_name_smoke/sources | 7 + .../thread_name_smoke/thread_name_smoke.c | 3 - code/user/tests/timer_smoke/makefile | 1 + code/user/tests/timer_smoke/sources | 7 + code/user/tests/timer_smoke/timer_smoke.c | 5 - .../win32_condition_variable_smoke/makefile | 1 + .../win32_condition_variable_smoke/sources | 7 + .../win32_condition_variable_smoke.c | 1 - .../user/tests/win32_exception_smoke/makefile | 1 + code/user/tests/win32_exception_smoke/sources | 7 + .../win32_exception_smoke.c | 5 - .../tests/win32_module_lookup_smoke/makefile | 1 + .../tests/win32_module_lookup_smoke/sources | 7 + .../win32_module_lookup_smoke.c | 2 - code/user/tests/win32_mutex_smoke/makefile | 1 + code/user/tests/win32_mutex_smoke/sources | 7 + .../win32_mutex_smoke/win32_mutex_smoke.c | 3 - code/user/tests/win32_seh_smoke/makefile | 1 + code/user/tests/win32_seh_smoke/sources | 7 + .../tests/win32_seh_smoke/win32_seh_smoke.c | 5 - .../tests/win32_thread_suspend_smoke/makefile | 1 + .../tests/win32_thread_suspend_smoke/sources | 7 + .../win32_thread_suspend_smoke.c | 2 - code/user/tests/winmm_waveout_smoke/makefile | 1 + code/user/tests/winmm_waveout_smoke/sources | 7 + .../winmm_waveout_smoke/winmm_waveout_smoke.c | 2 - code/user/tests/would_block_smoke/makefile | 1 + code/user/tests/would_block_smoke/sources | 7 + .../would_block_smoke/would_block_smoke.c | 5 - dirs | 1 + image.png | Bin 387088 -> 0 bytes makefile.def | 137 + project.mk | 1 + readme.md | 4 - roadmap.md | 131 +- sdktools/build.bat | 34 + sdktools/build.c | 1731 +++++++ sdktools/build.h | 1094 ++++ sdktools/build.htm | 331 ++ sdktools/builddb.c | 2081 ++++++++ sdktools/buildexe.c | 3143 ++++++++++++ sdktools/buildglobals.c | 122 + sdktools/buildinc.c | 540 ++ sdktools/buildmak.c | 3485 +++++++++++++ sdktools/buildscn.c | 844 ++++ sdktools/buildscr.cpp | 467 ++ sdktools/buildscr.h | 35 + sdktools/buildsrc.c | 2177 ++++++++ sdktools/buildutl.c | 1818 +++++++ sdktools/docs/build.cnt | 0 sdktools/docs/build.doc | Bin 0 -> 220672 bytes sdktools/docs/build.hlp | Bin 0 -> 101982 bytes sdktools/docs/build.hpj | 93 + sdktools/docs/build.rbh | 27 + sdktools/docs/build.rta | Bin 0 -> 59 bytes sdktools/docs/build.rtf | 1846 +++++++ sdktools/docs/build.rtk | Bin 0 -> 9365 bytes sdktools/docs/build.rts | Bin 0 -> 11973 bytes sdktools/scrproc.h | 3038 +++++++++++ sdktools/watch.c | 191 + 696 files changed, 147281 insertions(+), 7530 deletions(-) create mode 100644 code/boot/dirs create mode 100644 code/boot/uefi/makefile create mode 100644 code/boot/uefi/sources delete mode 100644 code/build/build.c delete mode 100644 code/build/nob.h create mode 100644 code/common/dirs create mode 100644 code/common/libc/makefile create mode 100644 code/common/libc/sources create mode 100644 code/common/printf/makefile create mode 100644 code/common/printf/sources create mode 100644 code/ddk/makefile create mode 100644 code/ddk/sources create mode 100644 code/dirs rename code/{drivers => }/drivers.ini (77%) create mode 100644 code/drivers/audio/dirs create mode 100644 code/drivers/audio/hda/makefile create mode 100644 code/drivers/audio/hda/sources create mode 100644 code/drivers/bus/dirs create mode 100644 code/drivers/bus/pci/makefile create mode 100644 code/drivers/bus/pci/sources create mode 100644 code/drivers/bus/usb/makefile create mode 100644 code/drivers/bus/usb/sources create mode 100644 code/drivers/dirs create mode 100644 code/drivers/display/dirs create mode 100644 code/drivers/display/vmwaresvga/makefile create mode 100644 code/drivers/display/vmwaresvga/sources create mode 100644 code/drivers/fs/dirs create mode 100644 code/drivers/fs/ext4/makefile create mode 100644 code/drivers/fs/ext4/sources create mode 100644 code/drivers/fs/fat/makefile create mode 100644 code/drivers/fs/fat/sources create mode 100644 code/drivers/fs/ntfs/dirs create mode 100644 code/drivers/fs/ntfs/ntfs3g/makefile create mode 100644 code/drivers/fs/ntfs/ntfs3g/sources create mode 100644 code/drivers/input/dirs create mode 100644 code/drivers/input/ps2/makefile create mode 100644 code/drivers/input/ps2/sources create mode 100644 code/drivers/input/serial/makefile create mode 100644 code/drivers/input/serial/sources create mode 100644 code/drivers/net/dirs create mode 100644 code/drivers/net/lwip/makefile create mode 100644 code/drivers/net/lwip/sources create mode 100644 code/drivers/net/rtl8139/makefile create mode 100644 code/drivers/net/rtl8139/sources create mode 100644 code/drivers/net/rtl816x/makefile create mode 100644 code/drivers/net/rtl816x/sources create mode 100644 code/drivers/platform/acpi/acpi.c create mode 100644 code/drivers/platform/acpi/acpi_ec.c create mode 100644 code/drivers/platform/acpi/acpi_local.h create mode 100644 code/drivers/platform/acpi/acpi_osl.c create mode 100644 code/drivers/platform/acpi/acpica_sources.txt create mode 100644 code/drivers/platform/acpi/makefile create mode 100644 code/drivers/platform/acpi/sources create mode 100644 code/drivers/platform/acpi/third_party/acpica/LICENSE.BSD-3-Clause create mode 100644 code/drivers/platform/acpi/third_party/acpica/LICENSE.GPL-2.0-only create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsargs.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dscontrol.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsdebug.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsfield.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsinit.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsmethod.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsmthdat.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsobject.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsopcode.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dspkginit.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsutils.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswexec.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswload.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswload2.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswscope.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswstate.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/events/evevent.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/events/evglock.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/events/evgpe.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/events/evgpeblk.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/events/evgpeinit.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/events/evgpeutil.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/events/evhandler.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/events/evmisc.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/events/evregion.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/events/evrgnini.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/events/evsci.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/events/evxface.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/events/evxfevnt.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/events/evxfgpe.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/events/evxfregn.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exconcat.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exconfig.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exconvrt.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/excreate.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exdebug.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exdump.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exfield.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exfldio.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exmisc.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exmutex.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exnames.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg1.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg2.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg3.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg6.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exprep.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exregion.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exresnte.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exresolv.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exresop.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exserial.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exstore.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exstoren.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exstorob.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exsystem.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/extrace.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/executer/exutils.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/hardware/hwacpi.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/hardware/hwesleep.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/hardware/hwgpe.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/hardware/hwpci.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/hardware/hwregs.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/hardware/hwsleep.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/hardware/hwtimer.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/hardware/hwvalid.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/hardware/hwxface.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/hardware/hwxfsleep.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsaccess.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsalloc.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsarguments.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsconvert.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsdump.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsdumpdv.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nseval.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsinit.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsload.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsnames.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsobject.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsparse.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nspredef.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsprepkg.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsrepair.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsrepair2.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nssearch.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsutils.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nswalk.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsxfeval.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsxfname.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/namespace/nsxfobj.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/parser/psargs.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/parser/psloop.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/parser/psobject.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/parser/psopcode.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/parser/psopinfo.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/parser/psparse.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/parser/psscope.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/parser/pstree.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/parser/psutils.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/parser/pswalk.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/parser/psxface.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/resources/rsaddr.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/resources/rscalc.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/resources/rscreate.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/resources/rsdump.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/resources/rsdumpinfo.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/resources/rsinfo.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/resources/rsio.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/resources/rsirq.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/resources/rslist.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/resources/rsmemory.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/resources/rsmisc.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/resources/rsserial.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/resources/rsutils.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/resources/rsxface.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/tables/tbdata.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/tables/tbfadt.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/tables/tbfind.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/tables/tbinstal.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/tables/tbprint.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/tables/tbutils.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/tables/tbxface.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/tables/tbxfload.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/tables/tbxfroot.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utaddress.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utalloc.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utascii.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utbuffer.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utcache.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utcksum.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utclib.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utcopy.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utdebug.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utdecode.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utdelete.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/uterror.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/uteval.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utexcep.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utglobal.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/uthex.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utids.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utinit.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utlock.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utmath.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utmisc.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utmutex.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utnonansi.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utobject.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utosi.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utownerid.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utpredef.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utprint.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utresdecode.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utresrc.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utstate.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utstring.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utstrsuppt.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utstrtoul64.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/uttrack.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utuuid.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utxface.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utxferror.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utxfinit.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/components/utilities/utxfmutex.c create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acapps.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acbuffer.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acclib.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/accommon.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acconfig.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acconvert.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acdebug.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acdisasm.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acdispat.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acevents.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acexcep.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acglobal.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/achware.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acinterp.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/aclocal.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acmacros.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acnames.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acnamesp.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acobject.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acopcode.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acoutput.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acparser.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acpi.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acpiosxf.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acpixf.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acpredef.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acresrc.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acrestyp.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acstruct.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/actables.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/actbinfo.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/actbl.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/actbl1.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/actbl2.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/actbl3.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/actypes.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acutils.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/acuuid.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/amlcode.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/amlresrc.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/accygwin.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acdragonfly.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acdragonflyex.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acefi.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acefiex.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acenv.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acenvex.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acfreebsd.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acgcc.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acgccex.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/achaiku.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acintel.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/aclinux.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/aclinuxex.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acmacosx.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acmsvc.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acmsvcex.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acnetbsd.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acntlite.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acos2.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acqnx.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acwin.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/acwin64.h create mode 100644 code/drivers/platform/acpi/third_party/acpica/include/platform/aczephyr.h create mode 100644 code/drivers/platform/dirs create mode 100644 code/drivers/storage/ahci/makefile create mode 100644 code/drivers/storage/ahci/sources create mode 100644 code/drivers/storage/ata/makefile create mode 100644 code/drivers/storage/ata/sources create mode 100644 code/drivers/storage/dirs create mode 100644 code/kernel/core/makefile create mode 100644 code/kernel/core/sources create mode 100644 code/kernel/dirs create mode 100644 code/kernel/hal/makefile create mode 100644 code/kernel/hal/sources create mode 100644 code/kernel/include/kernel/ke_firmware.h create mode 100644 code/kernel/include/kernel/ke_vectors.h create mode 100644 code/kernel/ke_firmware.c create mode 100644 code/public/ntlite/ddk/power.h create mode 100644 code/public/ntlite/native_heap.h delete mode 100644 code/tests/ddk/module_export_smoke.c delete mode 100644 code/tests/ddk/pci_caps_test.c delete mode 100644 code/tests/driver_manager/README.md delete mode 100644 code/tests/driver_manager/config_test.c delete mode 100644 code/tests/driver_manager/pnp_mock/include/kernel/ke_debug.h delete mode 100644 code/tests/driver_manager/pnp_mock/include/kernel/ke_event.h delete mode 100644 code/tests/driver_manager/pnp_mock/include/kernel/ke_spinlock.h delete mode 100644 code/tests/driver_manager/pnp_mock/include/kernel/ke_thread.h delete mode 100644 code/tests/driver_manager/pnp_mock/include/kernel/ke_time.h delete mode 100644 code/tests/driver_manager/pnp_mock/include/kernel/ke_work.h delete mode 100644 code/tests/driver_manager/pnp_mock/include/kernel/mm_virt.h delete mode 100644 code/tests/driver_manager/pnp_mock/include/ntlite/ddi/io_driver.h delete mode 100644 code/tests/driver_manager/pnp_test.c delete mode 100644 code/tests/host/service_control_contract.c delete mode 100644 code/tests/memtop_host/test.c delete mode 100644 code/tests/service_grants_host/test.c delete mode 100644 code/tests/service_publication_host/test.c delete mode 100644 code/tests/service_restart_host/test.c create mode 100644 code/user/apps/dirs create mode 100644 code/user/apps/doom/makefile create mode 100644 code/user/apps/doom/sources create mode 100644 code/user/apps/edit/makefile create mode 100644 code/user/apps/edit/sources create mode 100644 code/user/apps/httpget/makefile create mode 100644 code/user/apps/httpget/sources create mode 100644 code/user/apps/memtop/makefile create mode 100644 code/user/apps/memtop/sources create mode 100644 code/user/apps/ping/makefile create mode 100644 code/user/apps/ping/sources create mode 100644 code/user/apps/resolve/makefile create mode 100644 code/user/apps/resolve/sources create mode 100644 code/user/apps/shell_native/makefile create mode 100644 code/user/apps/shell_native/sources create mode 100644 code/user/apps/shell_posix/makefile create mode 100644 code/user/apps/shell_posix/sources create mode 100644 code/user/apps/shell_win32/makefile create mode 100644 code/user/apps/shell_win32/sources create mode 100644 code/user/apps/tcpserve/makefile create mode 100644 code/user/apps/tcpserve/sources create mode 100644 code/user/apps/udp/makefile create mode 100644 code/user/apps/udp/sources create mode 100644 code/user/apps/video/makefile create mode 100644 code/user/apps/video/sources create mode 100644 code/user/dirs create mode 100644 code/user/personalities/dirs create mode 100644 code/user/personalities/posix/makefile create mode 100644 code/user/personalities/posix/sources create mode 100644 code/user/personalities/win32/makefile create mode 100644 code/user/personalities/win32/sources create mode 100644 code/user/runtime/dirs create mode 100644 code/user/runtime/native_runtime/makefile create mode 100644 code/user/runtime/native_runtime/sources create mode 100644 code/user/runtime/posix_start/makefile create mode 100644 code/user/runtime/posix_start/sources create mode 100644 code/user/syscall/dirs create mode 100644 code/user/syscall/dynamic/makefile create mode 100644 code/user/syscall/dynamic/sources create mode 100644 code/user/syscall/static/makefile create mode 100644 code/user/syscall/static/sources create mode 100644 code/user/system/dirs create mode 100644 code/user/system/dwm/makefile create mode 100644 code/user/system/dwm/sources create mode 100644 code/user/system/init/makefile create mode 100644 code/user/system/init/sources create mode 100644 code/user/system/posixsrv/makefile create mode 100644 code/user/system/posixsrv/sources create mode 100644 code/user/system/rssrv/makefile create mode 100644 code/user/system/rssrv/sources create mode 100644 code/user/tests/all_tests/makefile create mode 100644 code/user/tests/all_tests/sources create mode 100644 code/user/tests/anonymous_queue_smoke/makefile create mode 100644 code/user/tests/anonymous_queue_smoke/sources create mode 100644 code/user/tests/apc_return_smoke/makefile create mode 100644 code/user/tests/apc_return_smoke/sources create mode 100644 code/user/tests/async_apc/makefile create mode 100644 code/user/tests/async_apc/sources create mode 100644 code/user/tests/async_cancel/makefile create mode 100644 code/user/tests/async_cancel/sources create mode 100644 code/user/tests/audio_stream_smoke/makefile create mode 100644 code/user/tests/audio_stream_smoke/sources create mode 100644 code/user/tests/console_service_smoke/makefile create mode 100644 code/user/tests/console_service_smoke/sources create mode 100644 code/user/tests/cwd_userspace_smoke/makefile create mode 100644 code/user/tests/cwd_userspace_smoke/sources create mode 100644 code/user/tests/desktop_smoke/makefile create mode 100644 code/user/tests/desktop_smoke/sources create mode 100644 code/user/tests/dirs create mode 100644 code/user/tests/dirty_writeback/makefile create mode 100644 code/user/tests/dirty_writeback/sources create mode 100644 code/user/tests/exception_dispatcher_smoke/makefile create mode 100644 code/user/tests/exception_dispatcher_smoke/sources create mode 100644 code/user/tests/exception_smoke/makefile create mode 100644 code/user/tests/exception_smoke/sources create mode 100644 code/user/tests/file_lock_smoke/makefile create mode 100644 code/user/tests/file_lock_smoke/sources create mode 100644 code/user/tests/file_stat_smoke/makefile create mode 100644 code/user/tests/file_stat_smoke/sources create mode 100644 code/user/tests/handle_dup_smoke/makefile create mode 100644 code/user/tests/handle_dup_smoke/sources create mode 100644 code/user/tests/input_service_smoke/makefile create mode 100644 code/user/tests/input_service_smoke/sources create mode 100644 code/user/tests/mmap_smoke/makefile create mode 100644 code/user/tests/mmap_smoke/sources create mode 100644 code/user/tests/module_load_smoke/makefile create mode 100644 code/user/tests/module_load_smoke/sources create mode 100644 code/user/tests/native_exception_runtime_smoke/makefile create mode 100644 code/user/tests/native_exception_runtime_smoke/sources create mode 100644 code/user/tests/native_raise_exception_smoke/makefile create mode 100644 code/user/tests/native_raise_exception_smoke/sources create mode 100644 code/user/tests/net_irp_smoke/makefile create mode 100644 code/user/tests/net_irp_smoke/sources create mode 100644 code/user/tests/pcache_invalidate/makefile create mode 100644 code/user/tests/pcache_invalidate/sources create mode 100644 code/user/tests/pcache_mmap_read_reuse/makefile create mode 100644 code/user/tests/pcache_mmap_read_reuse/sources create mode 100644 code/user/tests/pcache_multithread/makefile create mode 100644 code/user/tests/pcache_multithread/sources create mode 100644 code/user/tests/pcache_pressure/makefile create mode 100644 code/user/tests/pcache_pressure/sources create mode 100644 code/user/tests/pcache_smoke/makefile create mode 100644 code/user/tests/pcache_smoke/sources create mode 100644 code/user/tests/port_ipc_smoke/makefile create mode 100644 code/user/tests/port_ipc_smoke/sources create mode 100644 code/user/tests/posix_fd_smoke/makefile create mode 100644 code/user/tests/posix_fd_smoke/sources create mode 100644 code/user/tests/posix_module_smoke/makefile create mode 100644 code/user/tests/posix_module_smoke/sources create mode 100644 code/user/tests/posix_pipe_smoke/makefile create mode 100644 code/user/tests/posix_pipe_smoke/sources create mode 100644 code/user/tests/posix_process_smoke/makefile create mode 100644 code/user/tests/posix_process_smoke/sources create mode 100644 code/user/tests/posix_runtime_smoke/makefile create mode 100644 code/user/tests/posix_runtime_smoke/sources create mode 100644 code/user/tests/posix_service_smoke/makefile create mode 100644 code/user/tests/posix_service_smoke/sources create mode 100644 code/user/tests/posix_signal_smoke/makefile create mode 100644 code/user/tests/posix_signal_smoke/sources create mode 100644 code/user/tests/process_builder_smoke/makefile create mode 100644 code/user/tests/process_builder_smoke/sources create mode 100644 code/user/tests/process_exit_multithread_smoke/makefile create mode 100644 code/user/tests/process_exit_multithread_smoke/sources create mode 100644 code/user/tests/process_protection_smoke/makefile create mode 100644 code/user/tests/process_protection_smoke/sources create mode 100644 code/user/tests/realpath_smoke/makefile create mode 100644 code/user/tests/realpath_smoke/sources create mode 100644 code/user/tests/resource_service_smoke/makefile create mode 100644 code/user/tests/resource_service_smoke/sources create mode 100644 code/user/tests/security_smoke/makefile create mode 100644 code/user/tests/security_smoke/sources create mode 100644 code/user/tests/shared_mmap/makefile create mode 100644 code/user/tests/shared_mmap/sources create mode 100644 code/user/tests/socket_addr_smoke/makefile create mode 100644 code/user/tests/socket_addr_smoke/sources create mode 100644 code/user/tests/stats_abi_smoke/makefile create mode 100644 code/user/tests/stats_abi_smoke/sources create mode 100644 code/user/tests/surface_cross_process_smoke/makefile create mode 100644 code/user/tests/surface_cross_process_smoke/sources create mode 100644 code/user/tests/surface_invalid_rect/makefile create mode 100644 code/user/tests/surface_invalid_rect/sources create mode 100644 code/user/tests/surface_multithread_commit/makefile create mode 100644 code/user/tests/surface_multithread_commit/sources create mode 100644 code/user/tests/surface_smoke/makefile create mode 100644 code/user/tests/surface_smoke/sources create mode 100644 code/user/tests/syscall_contract_smoke/makefile create mode 100644 code/user/tests/syscall_contract_smoke/sources create mode 100644 code/user/tests/thread_name_smoke/makefile create mode 100644 code/user/tests/thread_name_smoke/sources create mode 100644 code/user/tests/timer_smoke/makefile create mode 100644 code/user/tests/timer_smoke/sources create mode 100644 code/user/tests/win32_condition_variable_smoke/makefile create mode 100644 code/user/tests/win32_condition_variable_smoke/sources create mode 100644 code/user/tests/win32_exception_smoke/makefile create mode 100644 code/user/tests/win32_exception_smoke/sources create mode 100644 code/user/tests/win32_module_lookup_smoke/makefile create mode 100644 code/user/tests/win32_module_lookup_smoke/sources create mode 100644 code/user/tests/win32_mutex_smoke/makefile create mode 100644 code/user/tests/win32_mutex_smoke/sources create mode 100644 code/user/tests/win32_seh_smoke/makefile create mode 100644 code/user/tests/win32_seh_smoke/sources create mode 100644 code/user/tests/win32_thread_suspend_smoke/makefile create mode 100644 code/user/tests/win32_thread_suspend_smoke/sources create mode 100644 code/user/tests/winmm_waveout_smoke/makefile create mode 100644 code/user/tests/winmm_waveout_smoke/sources create mode 100644 code/user/tests/would_block_smoke/makefile create mode 100644 code/user/tests/would_block_smoke/sources create mode 100644 dirs delete mode 100644 image.png create mode 100644 makefile.def create mode 100644 project.mk create mode 100644 sdktools/build.bat create mode 100644 sdktools/build.c create mode 100644 sdktools/build.h create mode 100644 sdktools/build.htm create mode 100644 sdktools/builddb.c create mode 100644 sdktools/buildexe.c create mode 100644 sdktools/buildglobals.c create mode 100644 sdktools/buildinc.c create mode 100644 sdktools/buildmak.c create mode 100644 sdktools/buildscn.c create mode 100644 sdktools/buildscr.cpp create mode 100644 sdktools/buildscr.h create mode 100644 sdktools/buildsrc.c create mode 100644 sdktools/buildutl.c create mode 100644 sdktools/docs/build.cnt create mode 100644 sdktools/docs/build.doc create mode 100644 sdktools/docs/build.hlp create mode 100644 sdktools/docs/build.hpj create mode 100644 sdktools/docs/build.rbh create mode 100644 sdktools/docs/build.rta create mode 100644 sdktools/docs/build.rtf create mode 100644 sdktools/docs/build.rtk create mode 100644 sdktools/docs/build.rts create mode 100644 sdktools/scrproc.h create mode 100644 sdktools/watch.c diff --git a/.gitignore b/.gitignore index bd8eb9a..944d03d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,18 @@ -build.obj bin/ -obj/ +sdktools/out/ + +*.vhd +*.vhdx +*.iso +*.img +*.bin +*.log +*.zip + qemu.log -disk.vhd usbfatroot/ -code.zip -code/build/build.exe -code/build/build.exe.old \ No newline at end of file + +**/obj/ +build.dat + +.vscode/ diff --git a/OVMF/OVMF_VARS_4M_d.fd b/OVMF/OVMF_VARS_4M_d.fd index 2bbd2e34d7e347da65808ca04dc674820bb3a134..8fd8f1c359cc885a3fb36a141ba2d0b0b51427f5 100644 GIT binary patch delta 1230 zcmZo@P;6*W+#qK(d69|IW(T8BT$8OV)HX-h9%Gy=Wv4c|$Kc3h4u^G39z&Yu(k=XwF$5<6W}la0N26ck^lez delta 59 zcmZo@P;6*W+#qK(oo_v()8+)DOI+79->{$QLrt3iOPc^| On*dvz0Q)il4g&zKQWbOn diff --git a/build.bat b/build.bat index ffc64e4..d1e36f3 100644 --- a/build.bat +++ b/build.bat @@ -1,9 +1,134 @@ @echo off -:: If the build system binary doesn't exist, bootstrap it! -if not exist "code\build\build.exe" ( - echo Bootstrapping build system... - cl.exe /nologo /Fe"code\build\build.exe" "code\build\build.c" +setlocal EnableExtensions DisableDelayedExpansion +pushd "%~dp0" || exit /b 1 + +if not exist "sdktools\out\build.exe" ( + call "sdktools\build.bat" + if errorlevel 1 goto :fail +) +rem BUILD scans includes separately from the NMAKE compiler flags. +set "INCLUDE=%CD%\code\public;%CD%\code\common\include;%INCLUDE%" +"sdktools\out\build.exe" %* +if errorlevel 1 goto :fail +if /I "%NTL_SKIP_VHD%"=="1" goto :done + +for %%T in (mformat mdir mmd mcopy) do ( + where %%T >nul 2>&1 + if errorlevel 1 ( + echo Missing mtools utility: %%T 1>&2 + goto :fail + ) ) -:: Run the build system, passing any args along -"code\build\build.exe" %* +if exist "disk.vhd" ( + call :ValidateVhd || goto :fail +) else ( + call :CreateVhd || goto :fail +) + +set "ESP=disk.vhd@@1M" +set "SYS=disk.vhd@@65M" +for %%D in (EFI EFI/BOOT EFI/NTLite EFI/NTLite/fs) do ( + call :EnsureDir "%ESP%" "%%D" || goto :fail +) +for %%D in (apps system drivers) do ( + call :EnsureDir "%SYS%" "%%D" || goto :fail +) + +call :CopyFat "bin\bootx64.efi" "%ESP%" "EFI/BOOT/bootx64.efi" || goto :fail +call :CopyFat "code\boot.ini" "%ESP%" "boot.ini" || goto :fail +for %%F in ("code\boot\uefi\fs\*.efi") do ( + if exist "%%~fF" ( + call :CopyFat "%%~fF" "%ESP%" "EFI/NTLite/fs/%%~nxF" || goto :fail + ) +) + +call :CopyFat "bin\kernel.exe" "%SYS%" "system/colonel.exe" || goto :fail +for %%F in ( + bin\hal.dll bin\syscall.dll bin\win32.dll bin\posix.dll + bin\init.exe bin\rssrv.exe bin\posixsrv.exe bin\dwm.exe + code\settings.ini code\services.ini +) do ( + call :CopyFat "%%F" "%SYS%" "system/%%~nxF" || goto :fail +) +for %%F in ( + bin\pci.sys bin\ps2.sys bin\hda.sys bin\ata.sys bin\ahci.sys + bin\fat.sys bin\ntfs.sys bin\ext4.sys bin\vmwaresvga.sys + bin\lwip.sys bin\usb.sys bin\acpi.sys bin\rtl816x.sys bin\rtl8139.sys + code\drivers.ini +) do ( + call :CopyFat "%%F" "%SYS%" "drivers/%%~nxF" || goto :fail +) +call :CopyFat "bin\serial.sys" "%SYS%" "drivers/cereal.sys" || goto :fail +for %%F in ( + bin\shell_win32.exe bin\shell_posix.exe bin\shell_native.exe + bin\edit.exe bin\httpget.exe bin\tcpserve.exe bin\udp.exe + bin\resolve.exe bin\ping.exe bin\doom.exe bin\video.exe bin\memtop.exe +) do ( + call :CopyFat "%%F" "%SYS%" "apps/%%~nxF" || goto :fail +) +for %%F in ( + code\user\apps\video\bink2w64.dll + code\user\apps\video\video.bk2 + code\user\apps\doom\doom1.wad +) do ( + if exist "%%F" ( + call :CopyFat "%%F" "%SYS%" "apps/%%~nxF" || goto :fail + ) +) +if /I "%NTL_WITH_TESTS%"=="1" ( + call :EnsureDir "%SYS%" "tests" || goto :fail + for /D %%D in ("code\user\tests\*") do ( + if exist "%%~fD\sources" ( + call :CopyFat "bin\%%~nxD.exe" "%SYS%" "tests/%%~nxD.exe" || goto :fail + ) + ) +) + +echo Updated disk.vhd +:done +popd +exit /b 0 + +:fail +echo Build or VHD packaging failed. 1>&2 +popd +exit /b 1 + +:EnsureDir +mdir -i "%~1" "::%~2" >nul 2>&1 +if not errorlevel 1 exit /b 0 +mmd -i "%~1" "::%~2" +exit /b %errorlevel% + +:CopyFat +if not exist "%~1" ( + echo Missing build artifact: %~1 1>&2 + exit /b 1 +) +mcopy -o -i "%~2" "%~1" "::%~3" +exit /b %errorlevel% + +:ValidateVhd +powershell -NoProfile -Command "$ErrorActionPreference='Stop'; $f=[IO.File]::OpenRead('disk.vhd'); try { $m=New-Object byte[] 512; if ($f.Length -ne 536871424 -or $f.Read($m,0,512) -ne 512) {throw 'Unexpected VHD size'}; if ([BitConverter]::ToUInt32($m,440) -ne 0x4E544C31 -or $m[510] -ne 85 -or $m[511] -ne 170) {throw 'Unexpected disk signature'}; if ([BitConverter]::ToUInt32($m,454) -ne 2048 -or [BitConverter]::ToUInt32($m,458) -ne 131072 -or [BitConverter]::ToUInt32($m,470) -ne 133120 -or [BitConverter]::ToUInt32($m,474) -ne 524288) {throw 'Unexpected partition layout'}; $f.Position=536870912; $v=New-Object byte[] 512; if ($f.Read($v,0,512) -ne 512 -or [Text.Encoding]::ASCII.GetString($v,0,8) -ne 'conectix') {throw 'Invalid VHD footer'} } finally {$f.Dispose()}" +exit /b %errorlevel% + +:CreateVhd +if exist "disk.vhd.new" ( + echo disk.vhd.new already exists; resolve it before initializing a disk. 1>&2 + exit /b 1 +) +echo Creating 512 MiB fixed VHD... +powershell -NoProfile -Command "$ErrorActionPreference='Stop'; function Be([byte[]]$a,[int]$o,[uint64]$v,[int]$n) {for($i=0;$i -lt $n;$i++) {$a[$o+$i]=[byte](($v -shr (8*($n-$i-1))) -band 255)}}; $s=[IO.File]::Open('disk.vhd.new',[IO.FileMode]::CreateNew,[IO.FileAccess]::ReadWrite); try { $s.SetLength(536871424); $m=New-Object byte[] 512; [BitConverter]::GetBytes([uint32]0x4E544C31).CopyTo($m,440); $m[510]=85; $m[511]=170; [byte[]]$p=0x80,0,2,0,12,254,255,255; [Array]::Copy($p,0,$m,446,8); [BitConverter]::GetBytes([uint32]2048).CopyTo($m,454); [BitConverter]::GetBytes([uint32]131072).CopyTo($m,458); [byte[]]$p=0,0,1,8,12,254,255,255; [Array]::Copy($p,0,$m,462,8); [BitConverter]::GetBytes([uint32]133120).CopyTo($m,470); [BitConverter]::GetBytes([uint32]524288).CopyTo($m,474); $s.Write($m,0,512); $v=New-Object byte[] 512; [Text.Encoding]::ASCII.GetBytes('conectix').CopyTo($v,0); $v[11]=2; $v[13]=1; for($i=16;$i -lt 24;$i++) {$v[$i]=255}; [Text.Encoding]::ASCII.GetBytes('qemu').CopyTo($v,28); $v[33]=2; [Text.Encoding]::ASCII.GetBytes('Wi2k').CopyTo($v,36); Be $v 40 ([uint64]536870912) 8; Be $v 48 ([uint64]536870912) 8; $v[56]=4; $v[58]=16; $v[59]=63; $v[63]=2; [byte[]]$id=0xA1,0xB2,0xC3,0xD4,0xE5,0xF6,0x78,0x90,0x12,0x34,0x56,0x78,0x9A,0xBC,0xDE,0xF0; [Array]::Copy($id,0,$v,68,16); $sum=0; foreach($b in $v) {$sum+=$b}; Be $v 64 ([uint64]([uint32]::MaxValue - [uint32]$sum)) 4; $s.Position=536870912; $s.Write($v,0,512) } finally {$s.Dispose()}" +if errorlevel 1 goto :CreateFailed +mformat -i "disk.vhd.new@@1M" -F -T 131072 -H 2048 +if errorlevel 1 goto :CreateFailed +mformat -i "disk.vhd.new@@65M" -F -T 524288 -H 133120 +if errorlevel 1 goto :CreateFailed +move /y "disk.vhd.new" "disk.vhd" >nul +if errorlevel 1 goto :CreateFailed +exit /b 0 + +:CreateFailed +if exist "disk.vhd.new" del /q "disk.vhd.new" +exit /b 1 diff --git a/code/boot.ini b/code/boot.ini index 0bf213d..2bf8c12 100644 --- a/code/boot.ini +++ b/code/boot.ini @@ -8,7 +8,5 @@ system_volume = mbr/4E544C31/2 ; Debug bitmask. Values are defined canonically in ntlite/ddk/debug.h. ; 0x001 console output, 0x002 explicit kernel diagnostics, 0x004 file log. ; 0x008 pool canaries, 0x010 pool poison, 0x020 pool quarantine, 0x040 pool caller tracking. -; 0x080 display assertions, 0x100 intrusive-list checks. +; 0x080 display assertions, 0x100 intrusive-list checks, 0x200 ACPICA informational output. debug = 0x004 -[init] -commandline = apps/shell_native.exe diff --git a/code/boot/dirs b/code/boot/dirs new file mode 100644 index 0000000..7e9d3f2 --- /dev/null +++ b/code/boot/dirs @@ -0,0 +1 @@ +DIRS=uefi diff --git a/code/boot/uefi/main.c b/code/boot/uefi/main.c index 3760ac9..d334ab9 100644 --- a/code/boot/uefi/main.c +++ b/code/boot/uefi/main.c @@ -34,7 +34,6 @@ int _fltused = 0; #endif #endif -// Implements the ascii Str To Unicode Str S operation. static int AsciiStrToUnicodeStrS(const char* Source, CHAR16* Dest, size_t DestMax) { if (!Source || !Dest || !DestMax) return -1; @@ -46,7 +45,6 @@ static int AsciiStrToUnicodeStrS(const char* Source, CHAR16* Dest, size_t DestMa return -1; // Buffer too small } -// Implements the ascii Str Cpy S operation. static int AsciiStrCpyS(char* Dest, size_t DestMax, const char* Source) { if (!Dest || !Source || !DestMax) return -1; @@ -79,7 +77,6 @@ static UINT64* AllocPage(EFI_PHYSICAL_ADDRESS* physOut) { static UINT64* gPml4; -// Implements the ensure Table operation. static UINT64* EnsureTable(UINT64* parent, UINTN index) { if (!parent) return NULL; diff --git a/code/boot/uefi/makefile b/code/boot/uefi/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/boot/uefi/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/boot/uefi/sources b/code/boot/uefi/sources new file mode 100644 index 0000000..2431014 --- /dev/null +++ b/code/boot/uefi/sources @@ -0,0 +1,11 @@ +TARGETNAME=bootx64 +TARGETPATH=obj +TARGETTYPE=PROGRAM +IMAGE_KIND=EFI +TARGETEXT=efi +FLAVOR=BOOT +EXTRA_CFLAGS=/I"$(BASEDIR)\code\boot\uefi\include" +TARGETLIBS="$(BASEDIR)\code\boot\uefi\efilib.lib" "$(BASEDIR)\bin\libc.lib" +EXTRA_LFLAGS=/FORCE:MULTIPLE /ENTRY:UefiMain +INCLUDES=$(BASEDIR)\code\boot\uefi\include +SOURCES=@/code/boot/uefi/boot_pe.c @/code/boot/uefi/main.c @/code/common/boot_volume_selector.c diff --git a/code/build/build.c b/code/build/build.c deleted file mode 100644 index 1bb8841..0000000 --- a/code/build/build.c +++ /dev/null @@ -1,715 +0,0 @@ -// Project build orchestrator. This file describes the Windows/MSVC build graph and keeps driver dependencies explicit. - -#define NOB_IMPLEMENTATION -#include "nob.h" - -// Compiler and linker flags stay in macros so they can be used in file-scope aggregate initializers. -// MSVC C rejects initializing a static object from another object, even when the source object is const. -// Drivers and user binaries do not inherit kernel include paths so private dependencies fail at compile time. -#define COMMON_CFLAGS_LITERAL "/nologo /W3 /WX /O2 /GS- /Gs999999 /Gz /Gy /EHsc- /GR- /Oi- /Z7 /std:c17 /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS /Icode\\public /Icode\\common\\include" -#define KERNEL_CFLAGS_LITERAL COMMON_CFLAGS_LITERAL " /Icode\\kernel\\include" -#define DRIVER_CFLAGS_LITERAL COMMON_CFLAGS_LITERAL -#define USER_CFLAGS_LITERAL COMMON_CFLAGS_LITERAL -// POSIX targets own their standard C/POSIX headers; /X prevents the host UCRT from entering the target ABI. -#define POSIX_USER_CFLAGS_LITERAL "/X /Icode\\public\\posix /Icode\\public\\freestanding " USER_CFLAGS_LITERAL -#define BOOT_CFLAGS_LITERAL KERNEL_CFLAGS_LITERAL -#define USER_HEAP_OBJS_LITERAL "obj\\runtime\\user_heap.obj obj\\runtime\\user_heap_exports.obj" -#define NATIVE_RUNTIME_OBJS_LITERAL "obj\\runtime\\native_exception.obj obj\\runtime\\native_start.obj" -#define NATIVE_EXE_LIBS_LITERAL "bin\\syscall.lib obj\\libc.obj " USER_HEAP_OBJS_LITERAL " " NATIVE_RUNTIME_OBJS_LITERAL -#define NATIVE_INIT_LIBS_LITERAL "bin\\syscall_s.lib obj\\libc.obj obj\\runtime\\native_exception.obj" -#define NATIVE_SERVICE_LIBS_LITERAL "bin\\syscall_s.lib obj\\libc.obj " USER_HEAP_OBJS_LITERAL " obj\\runtime\\native_exception.obj" -#define WIN32_EXE_LIBS_LITERAL "bin\\win32.lib bin\\syscall.lib obj\\libc.obj obj\\runtime\\native_start.obj" -#define POSIX_EXE_LIBS_LITERAL "bin\\posix.lib bin\\syscall.lib obj\\libc.obj obj\\runtime\\posix_start.obj" -#define NATIVE_EXE_ENTRY_LITERAL "/ENTRY:NtlNativeStart" -#define USER_IMAGE_FLAGS_LITERAL "/DYNAMICBASE /HIGHENTROPYVA" -#define LWIP_CFLAGS_LITERAL DRIVER_CFLAGS_LITERAL " /Icode\\drivers\\net\\lwip\\include /Icode\\drivers\\net\\lwip\\third_party\\lwip\\src\\include /wd4005 /wd4100 /wd4103 /wd4127 /wd4244 /wd4267 /wd4706" -#define EXT4_CFLAGS_LITERAL DRIVER_CFLAGS_LITERAL " /Icode\\drivers\\fs\\ext4\\include /Icode\\drivers\\fs\\ext4\\third_party\\lwext4\\include /DCONFIG_USE_DEFAULT_CFG=1 /DCONFIG_HAVE_OWN_ERRNO=1 /DCONFIG_DEBUG_PRINTF=0 /DCONFIG_DEBUG_ASSERT=0 /DCONFIG_BLOCK_DEV_ENABLE_STATS=0 /DCONFIG_EXT4_BLOCKDEVS_COUNT=8 /DCONFIG_EXT4_MOUNTPOINTS_COUNT=8 /wd4005 /wd4100 /wd4101 /wd4103 /wd4127 /wd4244 /wd4267 /wd4706 /wd4996" -#define NTFS3G_CFLAGS_LITERAL DRIVER_CFLAGS_LITERAL " /Icode\\drivers\\fs\\ntfs\\ntfs3g\\include /Icode\\drivers\\fs\\ntfs\\ntfs3g\\third_party\\ntfs-3g\\include /Icode\\drivers\\fs\\ntfs\\ntfs3g\\third_party\\ntfs-3g\\include\\ntfs-3g /DHAVE_CONFIG_H=1 /DNO_NTFS_DEVICE_DEFAULT_IO_OPS=1 /wd4005 /wd4018 /wd4100 /wd4101 /wd4103 /wd4127 /wd4133 /wd4146 /wd4244 /wd4267 /wd4305 /wd4311 /wd4312 /wd4706 /wd4996" -#define LFLAGS_LITERAL "/nologo /NODEFAULTLIB /DEBUG" - -// Partition offsets inside disk.vhd -#define VHD_PART1 "disk.vhd@@1M" // ESP / Partition 1 (Offset 1MB) -#define VHD_PART2 "disk.vhd@@65M" // Test/Data / Partition 2 (Offset 65MB) -#define DEFAULT_VHD_DISK_SIGNATURE 0x4E544C31u - -const char* CommonCflags = COMMON_CFLAGS_LITERAL; -const char* KernelCflags = KERNEL_CFLAGS_LITERAL; -const char* UserCflags = USER_CFLAGS_LITERAL; -const char* PosixUserCflags = POSIX_USER_CFLAGS_LITERAL; -const char* BootCflags = BOOT_CFLAGS_LITERAL; -const char* LwipCflags = LWIP_CFLAGS_LITERAL; -const char* Ext4Cflags = EXT4_CFLAGS_LITERAL; -const char* Ntfs3gCflags = NTFS3G_CFLAGS_LITERAL; -const char* LFLAGS = LFLAGS_LITERAL; - -typedef struct Driver_Target { - const char* name; - const char* obj_dir; - const char* sources; - const char* cflags; - const char* libs; - const char* entry_flag; -} Driver_Target; - -#define DRIVER_TARGET(name_, obj_dir_, sources_) { (name_), (obj_dir_), (sources_), DRIVER_CFLAGS_LITERAL, "", "/NOENTRY" } -#define DRIVER_TARGET_LIBS(name_, obj_dir_, sources_, libs_) { (name_), (obj_dir_), (sources_), DRIVER_CFLAGS_LITERAL, (libs_), "/NOENTRY" } -#define DRIVER_TARGET_FLAGS(name_, obj_dir_, sources_, cflags_) { (name_), (obj_dir_), (sources_), (cflags_), "", "/NOENTRY" } -#define DRIVER_TARGET_DECLARATIVE(name_, obj_dir_, sources_) { (name_), (obj_dir_), (sources_), DRIVER_CFLAGS_LITERAL, "", "/NOENTRY" } - -static const Driver_Target PCI_BUS_DRIVER = - DRIVER_TARGET_FLAGS("pci", "obj\\drivers\\pci", "code\\drivers\\bus\\pci\\pci.c", DRIVER_CFLAGS_LITERAL " /DPCI_SYS_BUILD"); - -static const Driver_Target STANDALONE_DRIVERS[] = { - DRIVER_TARGET("ps2", "obj\\drivers\\ps2", "code\\drivers\\input\\ps2\\ps2.c code\\drivers\\input\\ps2\\ps2_i8042.c"), - DRIVER_TARGET_DECLARATIVE("serial", "obj\\drivers\\serial", "code\\drivers\\input\\serial\\serial.c"), - DRIVER_TARGET_LIBS("hda", "obj\\drivers\\hda", "code\\drivers\\audio\\hda\\hda.c code\\drivers\\audio\\hda\\hda_transport.c code\\drivers\\audio\\hda\\hda_codec.c", "bin\\pci.lib"), - DRIVER_TARGET_LIBS("ata", "obj\\drivers\\ata", "code\\drivers\\storage\\ata\\ata.c", "bin\\pci.lib"), - DRIVER_TARGET_LIBS("ahci", "obj\\drivers\\ahci", "code\\drivers\\storage\\ahci\\ahci.c code\\drivers\\storage\\ahci\\ahci_port.c", "bin\\pci.lib"), - DRIVER_TARGET("fat", "obj\\drivers\\fat", "code\\drivers\\fs\\fat\\fat.c code\\drivers\\fs\\fat\\fat_directory.c code\\drivers\\fs\\fat\\fat_file.c code\\drivers\\fs\\fat\\fat_async.c code\\drivers\\fs\\fat\\fat_driver.c code\\drivers\\fs\\fat\\fat_mount.c"), - DRIVER_TARGET_LIBS("vmwaresvga", "obj\\drivers\\vmwaresvga", "code\\drivers\\display\\vmwaresvga\\vmwaresvga.c", "bin\\pci.lib"), - DRIVER_TARGET_LIBS("usb", "obj\\drivers\\usb", "code\\drivers\\bus\\usb\\usb.c code\\drivers\\bus\\usb\\usb_bus.c code\\drivers\\bus\\usb\\usb_composite.c code\\drivers\\bus\\usb\\usb_core.c code\\drivers\\bus\\usb\\usb_xhci.c code\\drivers\\bus\\usb\\usb_hid.c code\\drivers\\bus\\usb\\usb_storage.c code\\drivers\\bus\\usb\\usb_hub.c", "bin\\pci.lib"), - DRIVER_TARGET_LIBS("rtl816x", "obj\\drivers\\rtl816x", "code\\drivers\\net\\rtl816x\\rtl816x.c", "bin\\pci.lib"), - DRIVER_TARGET_LIBS("rtl8139", "obj\\drivers\\rtl8139", "code\\drivers\\net\\rtl8139\\rtl8139.c", "bin\\pci.lib"), -}; - -// Creates layout. -void create_layout() { - const char* dirs[] = { - "obj", "bin", "obj\\boot", "obj\\ddk", "obj\\kernel", "obj\\lwip", "obj\\ext4", "obj\\ntfs3g", "obj\\hal", - "obj\\syscall", "obj\\runtime", "obj\\win32", "obj\\posix", "obj\\drivers", "obj\\init", "obj\\rssrv", "obj\\posixsrv", "obj\\dwm", - "obj\\shell_win32", "obj\\shell_posix", "obj\\shell_native", - "obj\\async_apc", "obj\\async_cancel", "obj\\apc_return_smoke", "obj\\edit", "obj\\httpget", - "obj\\tcpserve", "obj\\udp", "obj\\resolve", "obj\\ping", "obj\\doom", "obj\\video", "obj\\memtop", - "obj\\file_stat_smoke", "obj\\handle_dup_smoke", "obj\\security_smoke", "obj\\port_ipc_smoke", "obj\\resource_service_smoke", "obj\\anonymous_queue_smoke", "obj\\input_service_smoke", "obj\\console_service_smoke", "obj\\desktop_smoke", "obj\\timer_smoke", "obj\\stats_abi_smoke", "obj\\realpath_smoke", "obj\\file_lock_smoke", "obj\\process_protection_smoke", "obj\\process_exit_multithread_smoke", "obj\\thread_name_smoke", "obj\\process_builder_smoke", "obj\\socket_addr_smoke", "obj\\syscall_contract_smoke", "obj\\would_block_smoke", "obj\\audio_stream_smoke", "obj\\winmm_waveout_smoke", "obj\\win32_condition_variable_smoke", "obj\\win32_mutex_smoke", "obj\\win32_thread_suspend_smoke", "obj\\win32_module_lookup_smoke", "obj\\cwd_userspace_smoke", "obj\\mmap_smoke", "obj\\pcache_smoke", "obj\\pcache_pressure", "obj\\dirty_writeback", "obj\\shared_mmap", - "obj\\pcache_invalidate", "obj\\pcache_mmap_read_reuse", "obj\\pcache_multithread", - "obj\\all_tests", "obj\\posix_service_smoke", "obj\\surface_smoke", "obj\\surface_invalid_rect", "obj\\surface_multithread_commit", "obj\\surface_cross_process_smoke", "obj\\net_irp_smoke", "obj\\module_load_smoke", "obj\\posix_module_smoke", "obj\\posix_runtime_smoke", "obj\\posix_fd_smoke", "obj\\posix_process_smoke", "obj\\posix_signal_smoke", "obj\\posix_pipe_smoke", "obj\\exception_dispatcher_smoke", "obj\\native_exception_runtime_smoke", "obj\\native_raise_exception_smoke", "obj\\exception_smoke", "obj\\win32_exception_smoke", "obj\\win32_seh_smoke" - }; - for (size_t i = 0; i < NOB_ARRAY_LEN(dirs); i++) nob_mkdir_if_not_exists(dirs[i]); - nob_mkdir_if_not_exists(PCI_BUS_DRIVER.obj_dir); - for (size_t i = 0; i < NOB_ARRAY_LEN(STANDALONE_DRIVERS); i++) nob_mkdir_if_not_exists(STANDALONE_DRIVERS[i].obj_dir); -} - -// Runs a shell command and waits for it to finish. -bool run_sync(const char* cmd_str) { - Nob_Cmd cmd = {0}; - nob_cmd_append(&cmd, "cmd.exe", "/c", cmd_str); - bool ok = nob_cmd_run_sync(cmd); - nob_cmd_free(cmd); - return ok; -} - -// Launches a shell command while the build graph continues. -Nob_Proc run_async(const char* cmd_str) { - Nob_Cmd cmd = {0}; - nob_cmd_append(&cmd, "cmd.exe", "/c", cmd_str); - Nob_Proc proc = nob_cmd_run_async(cmd); - nob_cmd_free(cmd); - return proc; -} - -// Deletes stale object files from a target directory before compiling into it. -bool clean_object_directory(const char* obj_dir) { - const char* cmd = nob_temp_sprintf("if exist %s\\*.obj del /q %s\\*.obj", obj_dir, obj_dir); - return run_sync(cmd); -} - -// Cleans object directories that are linked through wildcards. -bool clean_build_object_directories(void) { - const char* dirs[] = { - "obj\\boot", "obj\\ddk", "obj\\kernel", "obj\\lwip", "obj\\ext4", "obj\\hal", - "obj\\syscall", "obj\\runtime", "obj\\win32", "obj\\posix", - "obj\\init", "obj\\rssrv", "obj\\posixsrv", "obj\\dwm", "obj\\shell_win32", "obj\\shell_posix", "obj\\shell_native", - "obj\\async_apc", "obj\\async_cancel", "obj\\apc_return_smoke", "obj\\edit", "obj\\httpget", - "obj\\tcpserve", "obj\\udp", "obj\\resolve", "obj\\ping", - "obj\\doom", "obj\\video", "obj\\memtop", "obj\\file_stat_smoke", "obj\\handle_dup_smoke", "obj\\security_smoke", "obj\\port_ipc_smoke", "obj\\resource_service_smoke", "obj\\anonymous_queue_smoke", "obj\\input_service_smoke", "obj\\console_service_smoke", "obj\\desktop_smoke", "obj\\timer_smoke", "obj\\stats_abi_smoke", "obj\\realpath_smoke", "obj\\file_lock_smoke", "obj\\process_protection_smoke", "obj\\process_exit_multithread_smoke", "obj\\thread_name_smoke", "obj\\process_builder_smoke", "obj\\socket_addr_smoke", "obj\\syscall_contract_smoke", "obj\\would_block_smoke", "obj\\audio_stream_smoke", "obj\\winmm_waveout_smoke", "obj\\win32_condition_variable_smoke", "obj\\win32_mutex_smoke", "obj\\win32_thread_suspend_smoke", "obj\\win32_module_lookup_smoke", "obj\\cwd_userspace_smoke", "obj\\mmap_smoke", "obj\\pcache_smoke", "obj\\pcache_pressure", "obj\\dirty_writeback", "obj\\shared_mmap", - "obj\\pcache_invalidate", "obj\\pcache_mmap_read_reuse", "obj\\pcache_multithread", - "obj\\all_tests", "obj\\posix_service_smoke", "obj\\surface_smoke", "obj\\surface_invalid_rect", "obj\\surface_multithread_commit", "obj\\surface_cross_process_smoke", "obj\\net_irp_smoke", "obj\\module_load_smoke", "obj\\posix_module_smoke", "obj\\posix_runtime_smoke", "obj\\posix_fd_smoke", "obj\\posix_process_smoke", "obj\\posix_signal_smoke", "obj\\posix_pipe_smoke", "obj\\exception_dispatcher_smoke", "obj\\native_exception_runtime_smoke", "obj\\native_raise_exception_smoke", "obj\\exception_smoke", "obj\\win32_exception_smoke", "obj\\win32_seh_smoke" - }; - - for (size_t i = 0; i < NOB_ARRAY_LEN(dirs); i++) { - if (!clean_object_directory(dirs[i])) return false; - } - - if (!clean_object_directory(PCI_BUS_DRIVER.obj_dir)) return false; - for (size_t i = 0; i < NOB_ARRAY_LEN(STANDALONE_DRIVERS); i++) { - if (!clean_object_directory(STANDALONE_DRIVERS[i].obj_dir)) return false; - } - - return true; -} - -// Creates the USB fat root once and leaves its contents alone between builds. -bool create_usbfatroot_if_missing(void) { - return nob_mkdir_if_not_exists("usbfatroot"); -} - -// Copies one local file into a FAT image using mcopy without admin rights. -bool mcopy_file(const char* src, const char* vhd_target, const char* dst_path) { - const char* cmd = nob_temp_sprintf("mcopy -o -i %s %s ::%s", vhd_target, src, dst_path); - return run_sync(cmd); -} - -// Copies several same-name files into one FAT directory with a single mcopy process. -bool mcopy_files_to_dir(const char* vhd_target, - const char* dst_dir, - const char* const* sources, - size_t source_count) { - if (!vhd_target || !dst_dir || (!sources && source_count)) - return false; - if (!source_count) - return true; - - Nob_String_Builder command = {0}; - nob_sb_appendf(&command, "mcopy -o -i %s", vhd_target); - for (size_t i = 0; i < source_count; ++i) - nob_sb_appendf(&command, " %s", sources[i]); - nob_sb_appendf(&command, " ::%s", dst_dir); - nob_sb_append_null(&command); - - bool ok = run_sync(command.items); - nob_sb_free(command); - return ok; -} - -// Utility to create a directory in a FAT image using mmd. -bool mmd_dir(const char* vhd_target, const char* dir_path) { - const char* cmd = nob_temp_sprintf("mmd -i %s ::%s 2>nul", vhd_target, dir_path); - run_sync(cmd); - return true; -} - -// Writes a 512-byte Connectix VHD Fixed Disk Footer at the end of the file. -static void write_vpc_footer(FILE* f, uint64_t disk_size_bytes) { - uint8_t footer[512] = {0}; - - memcpy(&footer[0], "conectix", 8); - - // Features: 0x00000002 (Big Endian) - footer[11] = 0x02; - - // File Format Version: 0x00010000 - footer[13] = 0x01; - - // Data Offset: 0xFFFFFFFFFFFFFFFF (Fixed disk) - memset(&footer[16], 0xFF, 8); - - // Creator Application: "qemu" - memcpy(&footer[28], "qemu", 4); - - // Creator Version: 0x00020000 - footer[33] = 0x02; - - // Creator Host OS: "Wi2k" - memcpy(&footer[36], "Wi2k", 4); - - // Original & Current Size (uint64_t Big Endian) - for (int i = 0; i < 8; i++) { - uint8_t b = (uint8_t)(disk_size_bytes >> ((7 - i) * 8)); - footer[40 + i] = b; - footer[48 + i] = b; - } - - // Geometry for 512MB: 1024 Cylinders (0x0400), 16 Heads, 63 Sectors/Track - footer[56] = 0x04; - footer[57] = 0x00; - footer[58] = 16; - footer[59] = 63; - - // Disk Type: 2 (Fixed Hard Disk) - footer[63] = 0x02; - - // Unique ID GUID - static const uint8_t guid[16] = { - 0xA1, 0xB2, 0xC3, 0xD4, 0xE5, 0xF6, 0x78, 0x90, - 0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0 - }; - memcpy(&footer[68], guid, 16); - - // Checksum: 1's complement sum of all bytes in footer with checksum cleared - uint32_t sum = 0; - for (int i = 0; i < 512; i++) { - sum += footer[i]; - } - uint32_t checksum = ~sum; - - footer[64] = (uint8_t)(checksum >> 24); - footer[65] = (uint8_t)(checksum >> 16); - footer[66] = (uint8_t)(checksum >> 8); - footer[67] = (uint8_t)(checksum & 0xFF); - - fseek(f, (long)disk_size_bytes, SEEK_SET); - fwrite(footer, 1, 512, f); -} - -// Ensures the managed development VHD carries the stable identity used by boot.ini. -static bool ensure_disk_vhd_signature(void) { - FILE* f = fopen("disk.vhd", "r+b"); - if (!f) return false; - - uint32_t signature = DEFAULT_VHD_DISK_SIGNATURE; - if (fseek(f, 440, SEEK_SET) != 0 || - fwrite(&signature, sizeof(signature), 1, f) != 1) { - fclose(f); - return false; - } - - fclose(f); - return true; -} - -// Creates a 512 MB partitioned disk.vhd image with a valid VPC footer. -bool create_disk_vhd_if_missing(void) { - if (nob_file_exists("disk.vhd")) return ensure_disk_vhd_signature(); - - nob_log(NOB_INFO, "disk.vhd missing, creating new 512 MB fixed VHD image..."); - - const uint64_t disk_size = (uint64_t)512 * 1024 * 1024; // 512 MB Payload - FILE* f = fopen("disk.vhd", "wb"); - if (!f) { - nob_log(NOB_ERROR, "Failed to create disk.vhd file!"); - return false; - } - - // Expand file to 512MB payload - if (fseek(f, (long)(disk_size - 1), SEEK_SET) != 0) { - fclose(f); - return false; - } - fputc(0, f); - - // Build standard MBR partition table (Sector 0) - uint8_t mbr[512] = {0}; - uint32_t disk_signature = DEFAULT_VHD_DISK_SIGNATURE; - memcpy(&mbr[440], &disk_signature, sizeof(disk_signature)); - mbr[510] = 0x55; - mbr[511] = 0xAA; - - // Partition 1 Entry: 64MB FAT32 @ LBA 2048 (1MB offset) - uint8_t* p1 = &mbr[0x01BE]; - p1[0] = 0x80; // Active / Bootable - p1[1] = 0x00; p1[2] = 0x02; p1[3] = 0x00; // CHS Start - p1[4] = 0x0C; // FAT32 LBA - p1[5] = 0xFE; p1[6] = 0xFF; p1[7] = 0xFF; // CHS End (LBA boundary) - uint32_t p1_lba = 2048; - uint32_t p1_sectors = 131072; // 64 MB - memcpy(&p1[8], &p1_lba, 4); - memcpy(&p1[12], &p1_sectors, 4); - - // Partition 2 Entry: 256MB FAT32 @ LBA 133120 (65MB offset) - uint8_t* p2 = &mbr[0x01CE]; - p2[0] = 0x00; // Inactive - p2[1] = 0x00; p2[2] = 0x01; p2[3] = 0x08; // CHS Start - p2[4] = 0x0C; // FAT32 LBA - p2[5] = 0xFE; p2[6] = 0xFF; p2[7] = 0xFF; // CHS End (LBA boundary) - uint32_t p2_lba = 133120; - uint32_t p2_sectors = 524288; // 256 MB - memcpy(&p2[8], &p2_lba, 4); - memcpy(&p2[12], &p2_sectors, 4); - - // Write Sector 0 - fseek(f, 0, SEEK_SET); - fwrite(mbr, 1, 512, f); - - // Append 512-byte Connectix VPC Footer - write_vpc_footer(f, disk_size); - - fclose(f); - - nob_log(NOB_INFO, "Formatting disk.vhd partitions with mformat..."); - if (!run_sync("mformat -i " VHD_PART1 " -F")) return false; - if (!run_sync("mformat -i " VHD_PART2 " -F")) return false; - - return true; -} - -// Runs the requested operation. -int main(int argc, char** argv) { - NOB_GO_REBUILD_URSELF(argc, argv); - bool with_tests = argc == 2 && strcmp(argv[1], "--with-tests") == 0; - if (argc != 1 && !with_tests) { - nob_log(NOB_ERROR, "Usage: build.exe [--with-tests]"); - return 1; - } - - if (!create_disk_vhd_if_missing()) return 1; - if (!create_usbfatroot_if_missing()) return 1; - create_layout(); - if (!nob_file_exists("code\\drivers\\fs\\ext4\\third_party\\lwext4\\src\\ext4.c")) { - nob_log(NOB_ERROR, "lwext4 is not vendored. Run: powershell -ExecutionPolicy Bypass -File code\\drivers\\fs\\ext4\\vendor_lwext4.ps1"); - return 1; - } - if (!nob_file_exists("code\\drivers\\fs\\ntfs\\ntfs3g\\third_party\\ntfs-3g\\libntfs-3g\\volume.c")) { - nob_log(NOB_ERROR, "ntfs-3g is not vendored. Run: powershell -ExecutionPolicy Bypass -File code\\drivers\\fs\\ntfs\\ntfs3g\\vendor_ntfs3g.ps1"); - return 1; - } - if (!clean_build_object_directories()) return 1; - - nob_log(NOB_INFO, "--- Building Core Subsystems ---"); - - const char* core_tasks[] = { - "ml64 /nologo /c /Foobj\\kernel\\ke_switch.obj code\\kernel\\ke_switch.asm", - "ml64 /nologo /c /Foobj\\kernel\\ke_syscall_asm.obj code\\kernel\\ke_syscall.asm", - "ml64 /nologo /c /Foobj\\kernel\\ke_gdt_reload.obj code\\kernel\\ke_gdt_reload.asm", - "ml64 /nologo /c /Foobj\\syscall\\stubs.obj code\\user\\syscall\\syscall_stubs.asm", - "ml64 /nologo /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\stubs_s.obj code\\user\\syscall\\syscall_stubs.asm", - nob_temp_sprintf("cl %s /DNTL_SYSCALL_BUILD /c /Foobj\\syscall\\pe_loader.obj code\\user\\syscall\\pe_loader.c", UserCflags), - nob_temp_sprintf("cl %s /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\pe_loader_s.obj code\\user\\syscall\\pe_loader.c", UserCflags), - nob_temp_sprintf("cl %s /DNTL_SYSCALL_BUILD /c /Foobj\\syscall\\module_loader.obj code\\user\\syscall\\module_loader.c", UserCflags), - nob_temp_sprintf("cl %s /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\module_loader_s.obj code\\user\\syscall\\module_loader.c", UserCflags), - nob_temp_sprintf("cl %s /DNTL_SYSCALL_BUILD /c /Foobj\\syscall\\process_loader.obj code\\user\\syscall\\process_loader.c", UserCflags), - nob_temp_sprintf("cl %s /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\process_loader_s.obj code\\user\\syscall\\process_loader.c", UserCflags), - nob_temp_sprintf("cl %s /DNTL_SYSCALL_BUILD /c /Foobj\\syscall\\resource.obj code\\user\\syscall\\resource.c", UserCflags), - nob_temp_sprintf("cl %s /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\resource_s.obj code\\user\\syscall\\resource.c", UserCflags), - nob_temp_sprintf("cl %s /DNTL_SYSCALL_BUILD /c /Foobj\\syscall\\input_service.obj code\\user\\syscall\\input_service.c", UserCflags), - nob_temp_sprintf("cl %s /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\input_service_s.obj code\\user\\syscall\\input_service.c", UserCflags), - nob_temp_sprintf("cl %s /DNTL_SYSCALL_BUILD /c /Foobj\\syscall\\console_service.obj code\\user\\syscall\\console_service.c", UserCflags), - nob_temp_sprintf("cl %s /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\console_service_s.obj code\\user\\syscall\\console_service.c", UserCflags), - nob_temp_sprintf("cl %s /DNTL_SYSCALL_BUILD /c /Foobj\\syscall\\desktop.obj code\\user\\syscall\\desktop.c", UserCflags), - nob_temp_sprintf("cl %s /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\desktop_s.obj code\\user\\syscall\\desktop.c", UserCflags), - nob_temp_sprintf("cl %s /DNTL_SYSCALL_BUILD /c /Foobj\\syscall\\path.obj code\\user\\syscall\\path.c", UserCflags), - nob_temp_sprintf("cl %s /DNTL_SYSCALL_STATIC /c /Foobj\\syscall\\path_s.obj code\\user\\syscall\\path.c", UserCflags), - "for %f in (code\\boot\\uefi\\*.asm) do ml64 /nologo /c /Fo\"obj\\boot\\%~nf.obj\" \"%f\"", - - nob_temp_sprintf("cl %s /MP /c /Foobj\\ code\\common\\printf.c", CommonCflags), - "cl /nologo /c /Foobj\\libc.obj code\\common\\libc.c", - nob_temp_sprintf("cl %s /c /Foobj\\runtime\\user_heap.obj code\\user\\runtime\\heap.c", UserCflags), - nob_temp_sprintf("cl %s /c /Foobj\\runtime\\user_heap_exports.obj code\\user\\runtime\\heap_exports.c", UserCflags), - nob_temp_sprintf("cl %s /c /Foobj\\runtime\\native_exception.obj code\\user\\runtime\\native_exception.c", UserCflags), - nob_temp_sprintf("cl %s /c /Foobj\\runtime\\native_start.obj code\\user\\runtime\\native_start.c", UserCflags), - nob_temp_sprintf("cl %s /c /Foobj\\runtime\\posix_start.obj code\\user\\runtime\\posix_start.c", PosixUserCflags), - - // Bootloader. - nob_temp_sprintf("cl %s /MP /c /Icode\\boot\\uefi\\include /Foobj\\boot\\ code\\boot\\uefi\\*.c code\\common\\boot_volume_selector.c && link %s /FORCE:MULTIPLE /SUBSYSTEM:EFI_APPLICATION /ENTRY:UefiMain /OUT:bin\\bootx64.efi obj\\libc.obj code\\boot\\uefi\\efilib.lib obj\\boot\\*.obj", BootCflags, LFLAGS), - - // HAL. - nob_temp_sprintf("cl %s /DNTL_HAL_BUILD /MP /c /Foobj\\hal\\ code\\kernel\\hal\\*.c && link %s /DLL /FIXED /DYNAMICBASE:NO /HIGHENTROPYVA:NO /RELEASE /BASE:0xFFFF800010000000 /OUT:bin\\hal.dll /NOENTRY /IGNORE:4216 obj\\printf.obj obj\\libc.obj obj\\hal\\*.obj", KernelCflags, LFLAGS), - - // Kernel. - nob_temp_sprintf("cl %s /DNTL_KERNEL_BUILD /DKE_DISPLAY_BUILD /MP /c /Foobj\\kernel\\ code\\kernel\\*.c code\\common\\boot_volume_selector.c && link %s /SUBSYSTEM:NATIVE /FIXED /DYNAMICBASE:NO /HIGHENTROPYVA:NO /RELEASE /BASE:0xFFFF800000000000 /ENTRY:KernelMain /MAP:bin\\kernel.map /OUT:bin\\kernel.exe bin\\hal.lib obj\\printf.obj obj\\libc.obj obj\\kernel\\*.obj", KernelCflags, LFLAGS), - - // Subsystem DLLs. - "link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL " USER_IMAGE_FLAGS_LITERAL " /OUT:bin\\syscall.dll obj\\syscall\\stubs.obj obj\\syscall\\pe_loader.obj obj\\syscall\\module_loader.obj obj\\syscall\\process_loader.obj obj\\syscall\\resource.obj obj\\syscall\\input_service.obj obj\\syscall\\console_service.obj obj\\syscall\\desktop.obj obj\\syscall\\path.obj obj\\libc.obj", - "lib /nologo /OUT:bin\\syscall_s.lib obj\\syscall\\stubs_s.obj obj\\syscall\\pe_loader_s.obj obj\\syscall\\module_loader_s.obj obj\\syscall\\process_loader_s.obj obj\\syscall\\resource_s.obj obj\\syscall\\input_service_s.obj obj\\syscall\\console_service_s.obj obj\\syscall\\desktop_s.obj obj\\syscall\\path_s.obj", - nob_temp_sprintf("cl %s /DUSER_HEAP_EXPORTS /DNTL_EXCEPTION_EXPORTS /MP /c /Foobj\\win32\\ code\\user\\runtime\\heap.c code\\user\\runtime\\heap_exports.c code\\user\\runtime\\native_exception.c code\\user\\personalities\\win32\\*.c && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL " USER_IMAGE_FLAGS_LITERAL " /OUT:bin\\win32.dll bin\\syscall.lib obj\\libc.obj obj\\win32\\*.obj", UserCflags), - "ml64 /nologo /Icode\\user\\syscall /c /Foobj\\posix\\posix_vfork_asm.obj code\\user\\personalities\\posix\\posix_vfork.asm", - nob_temp_sprintf("cl %s /DNTL_POSIX_BUILD /DUSER_HEAP_EXPORTS /DNTL_EXCEPTION_EXPORTS /MP /c /Foobj\\posix\\ code\\user\\runtime\\heap.c code\\user\\runtime\\heap_exports.c code\\user\\runtime\\native_exception.c code\\user\\personalities\\posix\\*.c && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL " USER_IMAGE_FLAGS_LITERAL " /OUT:bin\\posix.dll bin\\syscall.lib obj\\libc.obj obj\\posix\\*.obj", PosixUserCflags) - }; - - for (size_t i = 0; i < NOB_ARRAY_LEN(core_tasks); i++) { - if (!run_sync(core_tasks[i])) return 1; - } - - // The support library contains only driver-side helpers, never kernel policy. - if (!run_sync(nob_temp_sprintf( - "cl %s /MP /c /Foobj\\ddk\\ code\\ddk\\*.c && lib /nologo /OUT:bin\\ntlddk.lib obj\\ddk\\*.obj", - DRIVER_CFLAGS_LITERAL))) return 1; - - nob_log(NOB_INFO, "--- Building Bus Drivers ---"); - const char* pci_cmd = nob_temp_sprintf( - "cl %s /MP /c /Fo%s\\ %s && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\%s.sys /IMPLIB:bin\\%s.lib /NOENTRY bin\\kernel.lib bin\\ntlddk.lib obj\\printf.obj obj\\libc.obj %s\\*.obj", - PCI_BUS_DRIVER.cflags, PCI_BUS_DRIVER.obj_dir, PCI_BUS_DRIVER.sources, - PCI_BUS_DRIVER.name, PCI_BUS_DRIVER.name, PCI_BUS_DRIVER.obj_dir - ); - if (!run_sync(pci_cmd)) return 1; - - nob_log(NOB_INFO, "--- Compiling Drivers and Apps in Parallel ---"); - Nob_Procs procs = {0}; - - for (size_t i = 0; i < NOB_ARRAY_LEN(STANDALONE_DRIVERS); i++) { - const Driver_Target* driver = &STANDALONE_DRIVERS[i]; - const char* cmd = nob_temp_sprintf( - "cl %s /MP /c /Fo%s\\ %s && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\%s.sys %s bin\\kernel.lib %s obj\\libc.obj %s\\*.obj", - driver->cflags, driver->obj_dir, driver->sources, driver->name, - driver->entry_flag, driver->libs ? driver->libs : "", driver->obj_dir - ); - nob_da_append(&procs, run_async(cmd)); - } - - Nob_String_Builder sb = {0}, lwip_files = {0}; - if (nob_read_entire_file("code\\drivers\\net\\lwip\\lwip_sources.txt", &sb)) { - Nob_String_View sv = nob_sv_from_parts(sb.items, sb.count); - while (sv.count > 0) { - Nob_String_View line = nob_sv_trim(nob_sv_chop_by_delim(&sv, '\n')); - if (line.count > 0 && line.data[0] != '#') { - nob_sb_append_cstr(&lwip_files, "code\\"); - for (size_t i = 0; i < line.count; i++) nob_sb_append_buf(&lwip_files, &(char){line.data[i] == '/' ? '\\' : line.data[i]}, 1); - nob_sb_append_cstr(&lwip_files, " "); - } - } - nob_sb_append_null(&lwip_files); - nob_da_append(&procs, run_async(nob_temp_sprintf("cl %s /MP /c /Foobj\\lwip\\ %s && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\lwip.sys /NOENTRY bin\\kernel.lib obj\\libc.obj obj\\lwip\\*.obj", LwipCflags, lwip_files.items))); - } - - Nob_String_Builder ext4_sb = {0}, ext4_files = {0}; - if (nob_read_entire_file("code\\drivers\\fs\\ext4\\lwext4_sources.txt", &ext4_sb)) { - Nob_String_View sv = nob_sv_from_parts(ext4_sb.items, ext4_sb.count); - while (sv.count > 0) { - Nob_String_View line = nob_sv_trim(nob_sv_chop_by_delim(&sv, '\n')); - if (line.count > 0 && line.data[0] != '#') { - nob_sb_append_cstr(&ext4_files, "code\\"); - for (size_t i = 0; i < line.count; i++) nob_sb_append_buf(&ext4_files, &(char){line.data[i] == '/' ? '\\' : line.data[i]}, 1); - nob_sb_append_cstr(&ext4_files, " "); - } - } - nob_sb_append_null(&ext4_files); - nob_da_append(&procs, run_async(nob_temp_sprintf("cl %s /MP /c /Foobj\\ext4\\ %s && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\ext4.sys /NOENTRY bin\\kernel.lib obj\\libc.obj obj\\ext4\\*.obj", Ext4Cflags, ext4_files.items))); - } - - Nob_String_Builder ntfs3g_sb = {0}, ntfs3g_files = {0}; - if (nob_read_entire_file("code\\drivers\\fs\\ntfs\\ntfs3g\\ntfs3g_sources.txt", &ntfs3g_sb)) { - Nob_String_View sv = nob_sv_from_parts(ntfs3g_sb.items, ntfs3g_sb.count); - while (sv.count > 0) { - Nob_String_View line = nob_sv_trim(nob_sv_chop_by_delim(&sv, '\n')); - if (line.count > 0 && line.data[0] != '#') { - nob_sb_append_cstr(&ntfs3g_files, "code\\"); - for (size_t i = 0; i < line.count; i++) nob_sb_append_buf(&ntfs3g_files, &(char){line.data[i] == '/' ? '\\' : line.data[i]}, 1); - nob_sb_append_cstr(&ntfs3g_files, " "); - } - } - nob_sb_append_null(&ntfs3g_files); - nob_da_append(&procs, run_async(nob_temp_sprintf("cl %s /MP /c /Foobj\\ntfs3g\\ %s && link /nologo /SUBSYSTEM:NATIVE /NODEFAULTLIB /DLL /OUT:bin\\ntfs.sys /NOENTRY bin\\kernel.lib obj\\printf.obj obj\\libc.obj obj\\ntfs3g\\*.obj", Ntfs3gCflags, ntfs3g_files.items))); - } - - - const char* apps[][4] = { - {"system\\init", NATIVE_INIT_LIBS_LITERAL, "init", "/ENTRY:_start"}, - {"system\\rssrv", NATIVE_SERVICE_LIBS_LITERAL, "rssrv", "/ENTRY:_start"}, - {"system\\posixsrv", NATIVE_SERVICE_LIBS_LITERAL, "posixsrv", "/ENTRY:_start"}, - {"system\\dwm", NATIVE_SERVICE_LIBS_LITERAL, "dwm", "/ENTRY:_start"}, - {"tests\\all_tests", NATIVE_EXE_LIBS_LITERAL, "all_tests", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\posix_service_smoke", NATIVE_EXE_LIBS_LITERAL, "posix_service_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"apps\\shell_win32", WIN32_EXE_LIBS_LITERAL, "shell_win32", NATIVE_EXE_ENTRY_LITERAL}, - {"apps\\shell_posix", POSIX_EXE_LIBS_LITERAL, "shell_posix", "/ENTRY:PosixStart"}, - {"apps\\shell_native", NATIVE_EXE_LIBS_LITERAL, "shell_native", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\async_apc", NATIVE_EXE_LIBS_LITERAL, "async_apc", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\apc_return_smoke", NATIVE_EXE_LIBS_LITERAL, "apc_return_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\async_cancel", NATIVE_EXE_LIBS_LITERAL, "async_cancel", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\file_stat_smoke", NATIVE_EXE_LIBS_LITERAL, "file_stat_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\handle_dup_smoke", NATIVE_EXE_LIBS_LITERAL, "handle_dup_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\security_smoke", NATIVE_EXE_LIBS_LITERAL, "security_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\port_ipc_smoke", NATIVE_EXE_LIBS_LITERAL, "port_ipc_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\resource_service_smoke", NATIVE_EXE_LIBS_LITERAL, "resource_service_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\anonymous_queue_smoke", NATIVE_EXE_LIBS_LITERAL, "anonymous_queue_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\input_service_smoke", NATIVE_EXE_LIBS_LITERAL, "input_service_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\console_service_smoke", NATIVE_EXE_LIBS_LITERAL, "console_service_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\desktop_smoke", NATIVE_EXE_LIBS_LITERAL, "desktop_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\timer_smoke", NATIVE_EXE_LIBS_LITERAL, "timer_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\stats_abi_smoke", NATIVE_EXE_LIBS_LITERAL, "stats_abi_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\realpath_smoke", NATIVE_EXE_LIBS_LITERAL, "realpath_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\file_lock_smoke", NATIVE_EXE_LIBS_LITERAL, "file_lock_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\process_protection_smoke", NATIVE_EXE_LIBS_LITERAL, "process_protection_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\process_exit_multithread_smoke", NATIVE_EXE_LIBS_LITERAL, "process_exit_multithread_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\thread_name_smoke", NATIVE_EXE_LIBS_LITERAL, "thread_name_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\process_builder_smoke", "bin\\syscall_s.lib obj\\libc.obj " NATIVE_RUNTIME_OBJS_LITERAL, "process_builder_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\socket_addr_smoke", NATIVE_EXE_LIBS_LITERAL, "socket_addr_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\net_irp_smoke", NATIVE_EXE_LIBS_LITERAL, "net_irp_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\module_load_smoke", NATIVE_EXE_LIBS_LITERAL, "module_load_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\posix_module_smoke", POSIX_EXE_LIBS_LITERAL, "posix_module_smoke", "/ENTRY:PosixStart"}, - {"tests\\posix_runtime_smoke", POSIX_EXE_LIBS_LITERAL, "posix_runtime_smoke", "/ENTRY:PosixStart"}, - {"tests\\posix_fd_smoke", POSIX_EXE_LIBS_LITERAL, "posix_fd_smoke", "/ENTRY:PosixStart"}, - {"tests\\posix_process_smoke", POSIX_EXE_LIBS_LITERAL, "posix_process_smoke", "/ENTRY:PosixStart"}, - {"tests\\posix_signal_smoke", POSIX_EXE_LIBS_LITERAL, "posix_signal_smoke", "/ENTRY:PosixStart"}, - {"tests\\posix_pipe_smoke", POSIX_EXE_LIBS_LITERAL, "posix_pipe_smoke", "/ENTRY:PosixStart"}, - {"tests\\exception_dispatcher_smoke", NATIVE_EXE_LIBS_LITERAL, "exception_dispatcher_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\native_exception_runtime_smoke", NATIVE_EXE_LIBS_LITERAL, "native_exception_runtime_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\native_raise_exception_smoke", NATIVE_EXE_LIBS_LITERAL, "native_raise_exception_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\exception_smoke", NATIVE_EXE_LIBS_LITERAL, "exception_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\win32_exception_smoke", WIN32_EXE_LIBS_LITERAL, "win32_exception_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\win32_seh_smoke", WIN32_EXE_LIBS_LITERAL, "win32_seh_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\syscall_contract_smoke", NATIVE_EXE_LIBS_LITERAL, "syscall_contract_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\would_block_smoke", NATIVE_EXE_LIBS_LITERAL, "would_block_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\audio_stream_smoke", NATIVE_EXE_LIBS_LITERAL, "audio_stream_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\winmm_waveout_smoke", WIN32_EXE_LIBS_LITERAL, "winmm_waveout_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\win32_condition_variable_smoke", WIN32_EXE_LIBS_LITERAL, "win32_condition_variable_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\win32_mutex_smoke", WIN32_EXE_LIBS_LITERAL, "win32_mutex_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\win32_thread_suspend_smoke", WIN32_EXE_LIBS_LITERAL, "win32_thread_suspend_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\win32_module_lookup_smoke", WIN32_EXE_LIBS_LITERAL, "win32_module_lookup_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\cwd_userspace_smoke", NATIVE_EXE_LIBS_LITERAL, "cwd_userspace_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\mmap_smoke", NATIVE_EXE_LIBS_LITERAL, "mmap_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\pcache_smoke", NATIVE_EXE_LIBS_LITERAL, "pcache_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\pcache_pressure", NATIVE_EXE_LIBS_LITERAL, "pcache_pressure", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\dirty_writeback", NATIVE_EXE_LIBS_LITERAL, "dirty_writeback", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\shared_mmap", NATIVE_EXE_LIBS_LITERAL, "shared_mmap", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\pcache_invalidate", NATIVE_EXE_LIBS_LITERAL, "pcache_invalidate", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\pcache_mmap_read_reuse", NATIVE_EXE_LIBS_LITERAL, "pcache_mmap_read_reuse", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\pcache_multithread", NATIVE_EXE_LIBS_LITERAL, "pcache_multithread", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\surface_smoke", NATIVE_EXE_LIBS_LITERAL, "surface_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\surface_invalid_rect", NATIVE_EXE_LIBS_LITERAL, "surface_invalid_rect", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\surface_multithread_commit", NATIVE_EXE_LIBS_LITERAL, "surface_multithread_commit", NATIVE_EXE_ENTRY_LITERAL}, - {"tests\\surface_cross_process_smoke", NATIVE_EXE_LIBS_LITERAL, "surface_cross_process_smoke", NATIVE_EXE_ENTRY_LITERAL}, - {"apps\\edit", NATIVE_EXE_LIBS_LITERAL, "edit", NATIVE_EXE_ENTRY_LITERAL}, - {"apps\\httpget", NATIVE_EXE_LIBS_LITERAL, "httpget", NATIVE_EXE_ENTRY_LITERAL}, - {"apps\\tcpserve", NATIVE_EXE_LIBS_LITERAL, "tcpserve", NATIVE_EXE_ENTRY_LITERAL}, - {"apps\\udp", NATIVE_EXE_LIBS_LITERAL, "udp", NATIVE_EXE_ENTRY_LITERAL}, - {"apps\\resolve", NATIVE_EXE_LIBS_LITERAL, "resolve", NATIVE_EXE_ENTRY_LITERAL}, - {"apps\\ping", NATIVE_EXE_LIBS_LITERAL, "ping", NATIVE_EXE_ENTRY_LITERAL}, - {"apps\\doom", NATIVE_EXE_LIBS_LITERAL, "doom", NATIVE_EXE_ENTRY_LITERAL}, - {"apps\\video", "bin\\syscall.lib obj\\libc.obj " NATIVE_RUNTIME_OBJS_LITERAL " code\\user\\apps\\video\\bink2w64.lib", "video", NATIVE_EXE_ENTRY_LITERAL}, - {"apps\\memtop", NATIVE_EXE_LIBS_LITERAL, "memtop", NATIVE_EXE_ENTRY_LITERAL} - }; - - for (size_t i = 0; i < NOB_ARRAY_LEN(apps); i++) { - if (!with_tests && strncmp(apps[i][0], "tests\\", 6) == 0) - continue; - const char* appCflags = strcmp(apps[i][3], "/ENTRY:PosixStart") == 0 - ? PosixUserCflags - : UserCflags; - const char* cmd = nob_temp_sprintf( - "cl %s /MP /c /Foobj\\%s\\ code\\user\\%s\\*.c && link %s /SUBSYSTEM:NATIVE " USER_IMAGE_FLAGS_LITERAL " %s /OUT:bin\\%s.exe /PDB:bin\\%s.pdb %s obj\\%s\\*.obj", - appCflags, apps[i][2], apps[i][0], LFLAGS, apps[i][3], apps[i][2], apps[i][2], apps[i][1], apps[i][2] - ); - nob_da_append(&procs, run_async(cmd)); - } - - if (!nob_procs_wait(procs)) { - nob_log(NOB_ERROR, "One or more parallel build jobs failed!"); - return 1; - } - - // 4. Formatting and Packing VHD via mtools (No Admin, Fast). - nob_log(NOB_INFO, "--- Formatting & Packing disk.vhd with mtools ---"); - - run_sync("mformat -i " VHD_PART1 " -F"); - run_sync("mformat -i " VHD_PART2 " -F"); - - mmd_dir(VHD_PART1, "EFI"); - mmd_dir(VHD_PART1, "EFI/BOOT"); - mmd_dir(VHD_PART1, "EFI/NTLite"); - mmd_dir(VHD_PART1, "EFI/NTLite/fs"); - mmd_dir(VHD_PART2, "apps"); - mmd_dir(VHD_PART2, "system"); - mmd_dir(VHD_PART2, "drivers"); - if (with_tests) mmd_dir(VHD_PART2, "tests"); - - // The ESP is only the boot anchor; the configured system volume carries the OS payload. - if (!mcopy_file("bin\\bootx64.efi", VHD_PART1, "EFI/BOOT/bootx64.efi")) return 1; - if (!mcopy_file("code\\boot.ini", VHD_PART1, "boot.ini")) return 1; - if (!run_sync("if exist code\\boot\\uefi\\fs\\*.efi mcopy -o -i " VHD_PART1 " code\\boot\\uefi\\fs\\*.efi ::EFI/NTLite/fs/")) return 1; - - if (!mcopy_file("bin\\kernel.exe", VHD_PART2, "system/colonel.exe")) return 1; - - const char* system_files[] = { - "bin\\hal.dll", - "bin\\syscall.dll", - "bin\\win32.dll", - "bin\\posix.dll", - "code\\settings.ini", - "code\\services.ini", - "bin\\init.exe", - "bin\\rssrv.exe", - "bin\\posixsrv.exe", - "bin\\dwm.exe", - }; - if (!mcopy_files_to_dir(VHD_PART2, "system/", system_files, NOB_ARRAY_LEN(system_files))) return 1; - - const char* driver_files[] = { - "bin\\pci.sys", - "bin\\ps2.sys", - "bin\\hda.sys", - "bin\\ata.sys", - "bin\\ahci.sys", - "bin\\fat.sys", - "bin\\ntfs.sys", - "bin\\ext4.sys", - "bin\\vmwaresvga.sys", - "bin\\lwip.sys", - "bin\\usb.sys", - "bin\\rtl816x.sys", - "bin\\rtl8139.sys", - "code\\drivers\\drivers.ini", - }; - if (!mcopy_files_to_dir(VHD_PART2, "drivers/", driver_files, NOB_ARRAY_LEN(driver_files))) return 1; - // The build artifact keeps the descriptive target name; the installed serial driver gets the cereal joke. - if (!mcopy_file("bin\\serial.sys", VHD_PART2, "drivers/cereal.sys")) return 1; - - const char* app_files[] = { - "bin\\shell_win32.exe", - "bin\\shell_posix.exe", - "bin\\shell_native.exe", - "bin\\edit.exe", - "bin\\httpget.exe", - "bin\\tcpserve.exe", - "bin\\udp.exe", - "bin\\resolve.exe", - "bin\\ping.exe", - "bin\\doom.exe", - "bin\\video.exe", - "bin\\memtop.exe", - }; - if (!mcopy_files_to_dir(VHD_PART2, "apps/", app_files, NOB_ARRAY_LEN(app_files))) return 1; - - const char* test_files[] = { - "bin\\all_tests.exe", - "bin\\posix_service_smoke.exe", - "bin\\async_apc.exe", - "bin\\async_cancel.exe", - "bin\\apc_return_smoke.exe", - "bin\\file_stat_smoke.exe", - "bin\\handle_dup_smoke.exe", - "bin\\security_smoke.exe", - "bin\\port_ipc_smoke.exe", - "bin\\resource_service_smoke.exe", - "bin\\anonymous_queue_smoke.exe", - "bin\\input_service_smoke.exe", - "bin\\console_service_smoke.exe", - "bin\\desktop_smoke.exe", - "bin\\timer_smoke.exe", - "bin\\stats_abi_smoke.exe", - "bin\\realpath_smoke.exe", - "bin\\file_lock_smoke.exe", - "bin\\process_protection_smoke.exe", - "bin\\process_exit_multithread_smoke.exe", - "bin\\thread_name_smoke.exe", - "bin\\process_builder_smoke.exe", - "bin\\socket_addr_smoke.exe", - "bin\\net_irp_smoke.exe", - "bin\\module_load_smoke.exe", - "bin\\posix_module_smoke.exe", - "bin\\posix_runtime_smoke.exe", - "bin\\posix_fd_smoke.exe", - "bin\\posix_process_smoke.exe", - "bin\\posix_signal_smoke.exe", - "bin\\posix_pipe_smoke.exe", - "bin\\exception_dispatcher_smoke.exe", - "bin\\native_exception_runtime_smoke.exe", - "bin\\native_raise_exception_smoke.exe", - "bin\\exception_smoke.exe", - "bin\\win32_exception_smoke.exe", - "bin\\win32_seh_smoke.exe", - "bin\\syscall_contract_smoke.exe", - "bin\\would_block_smoke.exe", - "bin\\audio_stream_smoke.exe", - "bin\\winmm_waveout_smoke.exe", - "bin\\win32_condition_variable_smoke.exe", - "bin\\win32_mutex_smoke.exe", - "bin\\win32_thread_suspend_smoke.exe", - "bin\\win32_module_lookup_smoke.exe", - "bin\\cwd_userspace_smoke.exe", - "bin\\mmap_smoke.exe", - "bin\\pcache_smoke.exe", - "bin\\pcache_pressure.exe", - "bin\\dirty_writeback.exe", - "bin\\shared_mmap.exe", - "bin\\pcache_invalidate.exe", - "bin\\pcache_mmap_read_reuse.exe", - "bin\\pcache_multithread.exe", - "bin\\surface_smoke.exe", - "bin\\surface_invalid_rect.exe", - "bin\\surface_multithread_commit.exe", - "bin\\surface_cross_process_smoke.exe", - }; - if (with_tests && !mcopy_files_to_dir(VHD_PART2, "tests/", test_files, NOB_ARRAY_LEN(test_files))) return 1; - - const char* optional_app_files[3]; - size_t optional_app_count = 0; - if (nob_file_exists("code\\user\\apps\\video\\bink2w64.dll")) - optional_app_files[optional_app_count++] = "code\\user\\apps\\video\\bink2w64.dll"; - if (nob_file_exists("code\\user\\apps\\video\\video.bk2")) - optional_app_files[optional_app_count++] = "code\\user\\apps\\video\\video.bk2"; - if (nob_file_exists("code\\user\\apps\\doom\\doom1.wad")) - optional_app_files[optional_app_count++] = "code\\user\\apps\\doom\\doom1.wad"; - if (!mcopy_files_to_dir(VHD_PART2, "apps/", optional_app_files, optional_app_count)) return 1; - - nob_log(NOB_INFO, "Build complete!"); - return 0; -} diff --git a/code/build/nob.h b/code/build/nob.h deleted file mode 100644 index c1a6a1a..0000000 --- a/code/build/nob.h +++ /dev/null @@ -1,3286 +0,0 @@ -/* nob - v3.8.2 - Public Domain - https://github.com/tsoding/nob.h - - This library is the next generation of the [NoBuild](https://github.com/tsoding/nobuild) idea. - - # Quick Example - - ```c - // nob.c - #define NOB_IMPLEMENTATION - #include "nob.h" - - int main(int argc, char **argv) - { - NOB_GO_REBUILD_URSELF(argc, argv); - Nob_Cmd cmd = {0}; - nob_cmd_append(&cmd, "cc", "-Wall", "-Wextra", "-o", "main", "main.c"); - if (!nob_cmd_run(&cmd)) return 1; - return 0; - } - ``` - - ```console - $ cc -o nob nob.c - $ ./nob - ``` - - The `nob` automatically rebuilds itself if `nob.c` is modified thanks to - the `NOB_GO_REBUILD_URSELF` macro (don't forget to check out how it works below) - - # Stripping off `nob_` Prefixes - - Since Pure C does not have any namespaces we prefix each name of the API with the `nob_` to avoid any - potential conflicts with any other names in your code. But sometimes it is very annoying and makes - the code noisy. Because of that you can drop the `nob_` prefix. - - ```c - // nob.c - #define NOB_IMPLEMENTATION - #include "nob.h" - - int main(int argc, char **argv) - { - GO_REBUILD_URSELF(argc, argv); - Cmd cmd = {0}; - cmd_append(&cmd, "cc", "-Wall", "-Wextra", "-o", "main", "main.c"); - if (!cmd_run(&cmd)) return 1; - return 0; - } - ``` - - If the lack of prefixes causes any problems you can disable the prefix stripping by defining - `NOB_UNSTRIP_PREFIX` feature macro before including "nob.h". - - Not all the names have strippable prefixes. All the redefinable names like `NOB_REBUILD_URSELF` - for instance will retain their prefix always. Notable exception is the nob_log() function. Stripping - away the prefix results in log() which was historically always referring to the natural logarithmic - function that is already defined in math.h. So there is no reason to strip off the prefix for nob_log(). - Another exception is nob_rename() which collides with the widely known POSIX function rename(2) if you - strip the prefix off. - - The prefixes are stripped off only on the level of the preprocessor. The names of the functions in the - compiled object file will still retain the `nob_` prefix. Keep that in mind when you FFI with nob.h - from other languages (for whatever reason). - - If only few specific names create conflicts for you, you can just #undef those names after the - `#include ` without enabling `NOB_UNSTRIP_PREFIX` since they are macros anyway. - - # Macro Interface - - All these macros are `#define`d by the user before including nob.h - - ## Flags - - Enable or disable certain aspects of nob.h - - - NOB_IMPLEMENTATION - Enable definitions of the functions. By default only declarations are included. - See https://github.com/nothings/stb/blob/f58f558c120e9b32c217290b80bad1a0729fbb2c/docs/stb_howto.txt - for more info. - - NOB_WARN_DEPRECATED - Warn about the usage of deprecated function. We rarely actually remove deprecated functions, - but if you want to know what is discouraged you may want to enable this flag. - - NOB_EXPERIMENTAL_DELETE_OLD - Experimental feature that automatically removes `nob.old` files. It's unclear how well - it works on Windows, so it's experimental for now. - - NOB_UNSTRIP_PREFIX - do not strip the `nob_` prefixes from non-redefinable names. - - NOB_NO_ECHO - do not echo the actions various nob functions are doing (like nob_cmd_run(), nob_mkdir_if_not_exists(), etc). - - ## Redefinable Macros - - Redefine default behaviors of nob.h. - - - NOBDEF - Appends additional things to function declarations. You can do something like `#define NOBDEF static inline`. - - NOB_ASSERT(condition) - Redefine which assert() nob.h shall use. - - NOB_REALLOC(oldptr, size) - Redefine which realloc() nob.h shall use. - - NOB_FREE(ptr) - Redefine which free() nob.h shall use. - - NOB_DEPRECATED(message) - Redefine how nob.h shall mark functions as deprecated. - - NOB_DA_INIT_CAP - Redefine initial capacity of Dynamic Arrays. - - NOB_TEMP_CAPACITY - Redefine the capacity of the temporary storate. - - NOB_REBUILD_URSELF(binary_path, source_path) - redefine how nob.h shall rebuild itself. - - NOB_WIN32_ERR_MSG_SIZE - Redefine the capacity of the buffer for error message on Windows. -*/ - -#ifndef NOB_H_ -#define NOB_H_ -#ifdef _WIN32 -# ifndef _CRT_SECURE_NO_WARNINGS -# define _CRT_SECURE_NO_WARNINGS (1) -# endif // _CRT_SECURE_NO_WARNINGS -#endif // _WIN32 - -#ifndef NOBDEF -/* - Goes before declarations and definitions of the nob functions. Useful to `#define NOBDEF static inline` - if your source code is a single file and you want the compiler to remove unused functions. -*/ -#define NOBDEF -#endif /* NOBDEF */ - -#ifndef NOB_ASSERT -#include -#define NOB_ASSERT assert -#endif /* NOB_ASSERT */ - -#ifndef NOB_REALLOC -#include -#define NOB_REALLOC realloc -#endif /* NOB_REALLOC */ - -#ifndef NOB_FREE -#include -#define NOB_FREE free -#endif /* NOB_FREE */ - -#ifdef NOB_WARN_DEPRECATED -# ifndef NOB_DEPRECATED -# if defined(__GNUC__) || defined(__clang__) -# define NOB_DEPRECATED(message) __attribute__((deprecated(message))) -# elif defined(_MSC_VER) -# define NOB_DEPRECATED(message) __declspec(deprecated(message)) -# else -# define NOB_DEPRECATED(...) -# endif -# endif /* NOB_DEPRECATED */ -#else -# define NOB_DEPRECATED(...) -#endif /* NOB_WARN_DEPRECATED */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef _WIN32 -# define WIN32_LEAN_AND_MEAN -# define _WINUSER_ -# define _WINGDI_ -# define _IMM_ -# define _WINCON_ -# include -# include -# include -# include -#else -# ifdef __APPLE__ -# include -# endif -# ifdef __FreeBSD__ -# include -# endif -# include -# include -# include -# include -# include -# include -#endif - -#ifdef __HAIKU__ -# include -#endif - -#ifdef _WIN32 -# define NOB_LINE_END "\r\n" -#else -# define NOB_LINE_END "\n" -#endif - -#if defined(__GNUC__) || defined(__clang__) -// https://gcc.gnu.org/onlinedocs/gcc-4.7.2/gcc/Function-Attributes.html -# ifdef __MINGW_PRINTF_FORMAT -# define NOB_PRINTF_FORMAT(STRING_INDEX, FIRST_TO_CHECK) __attribute__ ((format (__MINGW_PRINTF_FORMAT, STRING_INDEX, FIRST_TO_CHECK))) -# else -# define NOB_PRINTF_FORMAT(STRING_INDEX, FIRST_TO_CHECK) __attribute__ ((format (printf, STRING_INDEX, FIRST_TO_CHECK))) -# endif // __MINGW_PRINTF_FORMAT -#else -// TODO: implement NOB_PRINTF_FORMAT for MSVC -# define NOB_PRINTF_FORMAT(STRING_INDEX, FIRST_TO_CHECK) -#endif - -#define NOB_UNUSED(value) (void)(value) -#define NOB_TODO(message) do { fprintf(stderr, "%s:%d: TODO: %s\n", __FILE__, __LINE__, message); abort(); } while(0) -#define NOB_UNREACHABLE(message) do { fprintf(stderr, "%s:%d: UNREACHABLE: %s\n", __FILE__, __LINE__, message); abort(); } while(0) - -#define NOB_ARRAY_LEN(array) (sizeof(array)/sizeof(array[0])) -#define NOB_ARRAY_GET(array, index) \ - (NOB_ASSERT((size_t)index < NOB_ARRAY_LEN(array)), array[(size_t)index]) - -typedef enum { - NOB_INFO, - NOB_WARNING, - NOB_ERROR, - NOB_NO_LOGS, -} Nob_Log_Level; - -// Any messages with the level below nob_minimal_log_level are going to be suppressed by the nob_default_log_handler. -extern Nob_Log_Level nob_minimal_log_level; - -typedef void (Nob_Log_Handler)(Nob_Log_Level level, const char *fmt, va_list args); -NOB_DEPRECATED("Uncapitalized nob_log_handler type is deprecated. Use Nob_Log_Handler instead. It's just when we were releasing the log handler feature we forgot that we had a convention that all the types must be capitalized like that. Sorry about it!") -typedef Nob_Log_Handler nob_log_handler; - -NOBDEF void nob_set_log_handler(Nob_Log_Handler *handler); -NOBDEF Nob_Log_Handler *nob_get_log_handler(void); - -NOBDEF Nob_Log_Handler nob_default_log_handler; -NOBDEF Nob_Log_Handler nob_cancer_log_handler; -NOBDEF Nob_Log_Handler nob_null_log_handler; - -NOBDEF void nob_log(Nob_Log_Level level, const char *fmt, ...) NOB_PRINTF_FORMAT(2, 3); - -// It is an equivalent of shift command from bash (do `help shift` in bash). It basically -// pops an element from the beginning of a sized array. -#define nob_shift(xs, xs_sz) (NOB_ASSERT((xs_sz) > 0), (xs_sz)--, *(xs)++) -// NOTE: nob_shift_args() is an alias for an old variant of nob_shift that only worked with -// the command line arguments passed to the main() function. nob_shift() is more generic. -// So nob_shift_args() is semi-deprecated, but I don't see much reason to urgently -// remove it. This alias does not hurt anybody. -#define nob_shift_args(argc, argv) nob_shift(*argv, *argc) - -typedef struct { - const char **items; - size_t count; - size_t capacity; -} Nob_File_Paths; - -typedef enum { - NOB_FILE_REGULAR = 0, - NOB_FILE_DIRECTORY, - NOB_FILE_SYMLINK, - NOB_FILE_OTHER, -} Nob_File_Type; - -NOBDEF bool nob_mkdir_if_not_exists(const char *path); -NOBDEF bool nob_copy_file(const char *src_path, const char *dst_path); -NOBDEF bool nob_copy_directory_recursively(const char *src_path, const char *dst_path); -NOBDEF bool nob_read_entire_dir(const char *parent, Nob_File_Paths *children); -NOBDEF bool nob_write_entire_file(const char *path, const void *data, size_t size); -NOBDEF Nob_File_Type nob_get_file_type(const char *path); -NOBDEF bool nob_delete_file(const char *path); - -typedef enum { - // If the current file is a directory go inside of it. - NOB_WALK_CONT, - // If the current file is a directory do not go inside of it. - NOB_WALK_SKIP, - // Stop the recursive traversal process entirely. - NOB_WALK_STOP, -} Nob_Walk_Action; - -typedef struct { - // The path to the visited file. The lifetime of the path string is very short. - // As soon as the execution exits the Nob_Walk_Func it's dead. Dup it somewhere - // if you want to preserve it for longer periods of time. - const char *path; - // The type of the visited file. - Nob_File_Type type; - // How nested we currently are in the directory tree. - size_t level; - // User data supplied in Nob_Walk_Dir_Opt.data. - void *data; - // The action nob_walk_dir_opt() must perform after the Nob_Walk_Func has returned. - // Default is NOB_WALK_CONT. - Nob_Walk_Action *action; -} Nob_Walk_Entry; - -// A function that is called by nob_walk_dir_opt() on each visited file. -// Nob_Walk_Entry provides the details about the visited file and also -// expects you to modify the `action` in case you want to alter the -// usual behavior of the recursive walking algorithm. -// -// If the function returns `false`, an error is assumed which causes the entire -// recursive walking process to exit and nob_walk_dir_opt() return `false`. -typedef bool (*Nob_Walk_Func)(Nob_Walk_Entry entry); - -typedef struct { - // User data passed to Nob_Walk_Entry.data - void *data; - // Walk the directory in post-order visiting the leaf files first. - bool post_order; -} Nob_Walk_Dir_Opt; - -NOBDEF bool nob_walk_dir_opt(const char *root, Nob_Walk_Func func, Nob_Walk_Dir_Opt); - -#define nob_walk_dir(root, func, ...) nob_walk_dir_opt((root), (func), NOB_CLIT(Nob_Walk_Dir_Opt){__VA_ARGS__}) - -typedef struct { - char *name; - bool error; - - struct { -#ifdef _WIN32 - WIN32_FIND_DATA win32_data; - HANDLE win32_hFind; - bool win32_init; -#else - DIR *posix_dir; - struct dirent *posix_ent; -#endif // _WIN32 - } nob__private; // TODO: we don't have solid conventions regarding private struct fields -} Nob_Dir_Entry; - -// nob_dir_entry_open() - open the directory entry for iteration. -// RETURN: -// true - Sucess. -// false - Error. I will be logged automatically with nob_log(). -NOBDEF bool nob_dir_entry_open(const char *dir_path, Nob_Dir_Entry *dir); -// nob_dir_entry_next() - acquire the next file in the directory. -// RETURN: -// true - Successfully acquired the next file. -// false - Either failure or no more files to iterate. In case of failure dir->error is set to true. -NOBDEF bool nob_dir_entry_next(Nob_Dir_Entry *dir); -NOBDEF void nob_dir_entry_close(Nob_Dir_Entry dir); - -#define nob_return_defer(value) do { result = (value); goto defer; } while(0) - -// Initial capacity of a dynamic array -#ifndef NOB_DA_INIT_CAP -#define NOB_DA_INIT_CAP 256 -#endif - -#ifdef __cplusplus -#define NOB_DECLTYPE_CAST(T) (decltype(T)) -#else -#define NOB_DECLTYPE_CAST(T) -#endif // __cplusplus - -#define nob_da_reserve(da, expected_capacity) \ - do { \ - if ((expected_capacity) > (da)->capacity) { \ - if ((da)->capacity == 0) { \ - (da)->capacity = NOB_DA_INIT_CAP; \ - } \ - while ((expected_capacity) > (da)->capacity) { \ - (da)->capacity *= 2; \ - } \ - (da)->items = NOB_DECLTYPE_CAST((da)->items)NOB_REALLOC((da)->items, (da)->capacity * sizeof(*(da)->items)); \ - NOB_ASSERT((da)->items != NULL && "Buy more RAM lol"); \ - } \ - } while (0) - -// Append an item to a dynamic array -#define nob_da_append(da, item) \ - do { \ - nob_da_reserve((da), (da)->count + 1); \ - (da)->items[(da)->count++] = (item); \ - } while (0) - -#define nob_da_free(da) NOB_FREE((da).items) - -// Append several items to a dynamic array -#define nob_da_append_many(da, new_items, new_items_count) \ - do { \ - nob_da_reserve((da), (da)->count + (new_items_count)); \ - memcpy((da)->items + (da)->count, (new_items), (new_items_count)*sizeof(*(da)->items)); \ - (da)->count += (new_items_count); \ - } while (0) - -#define nob_da_resize(da, new_size) \ - do { \ - nob_da_reserve((da), new_size); \ - (da)->count = (new_size); \ - } while (0) - -#define nob_da_pop(da) (da)->items[(NOB_ASSERT((da)->count > 0), --(da)->count)] -#define nob_da_first(da) (da)->items[(NOB_ASSERT((da)->count > 0), 0)] -#define nob_da_last(da) (da)->items[(NOB_ASSERT((da)->count > 0), (da)->count-1)] -#define nob_da_remove_unordered(da, i) \ - do { \ - size_t j = (i); \ - NOB_ASSERT(j < (da)->count); \ - (da)->items[j] = (da)->items[--(da)->count]; \ - } while(0) - -// Foreach over Dynamic Arrays. Example: -// ```c -// typedef struct { -// int *items; -// size_t count; -// size_t capacity; -// } Numbers; -// -// Numbers xs = {0}; -// -// nob_da_append(&xs, 69); -// nob_da_append(&xs, 420); -// nob_da_append(&xs, 1337); -// -// nob_da_foreach(int, x, &xs) { -// // `x` here is a pointer to the current element. You can get its index by taking a difference -// // between `x` and the start of the array which is `x.items`. -// size_t index = x - xs.items; -// nob_log(INFO, "%zu: %d", index, *x); -// } -// ``` -#define nob_da_foreach(Type, it, da) for (Type *it = (da)->items; it < (da)->items + (da)->count; ++it) - -// The Fixed Array append. `items` fields must be a fixed size array. Its size determines the capacity. -#define nob_fa_append(fa, item) \ - (NOB_ASSERT((fa)->count < NOB_ARRAY_LEN((fa)->items)), \ - (fa)->items[(fa)->count++] = (item)) - -typedef struct { - char *items; - size_t count; - size_t capacity; -} Nob_String_Builder; - -#define nob_swap(T, a, b) do { T t = a; a = b; b = t; } while (0) - -NOBDEF bool nob_read_entire_file(const char *path, Nob_String_Builder *sb); -NOBDEF int nob_sb_appendf(Nob_String_Builder *sb, const char *fmt, ...) NOB_PRINTF_FORMAT(2, 3); -// Pads the String_Builder (sb) to the desired word size boundary with 0s. -// Imagine we have sb that contains 5 `a`-s: -// -// aaaa|a -// -// If we pad align it by size 4 it will look like this: -// -// aaaa|a000| <- padded with 0s to the next size 4 boundary -// -// Useful when you are building some sort of binary format using String_Builder. -NOBDEF void nob_sb_pad_align(Nob_String_Builder *sb, size_t size); - -// Append a sized buffer to a string builder -#define nob_sb_append_buf(sb, buf, size) nob_da_append_many(sb, buf, size) - -// Append a string view to a string builder -#define nob_sb_append_sv(sb, sv) nob_sb_append_buf((sb), (sv).data, (sv).count) - -// Append a NULL-terminated string to a string builder -#define nob_sb_append_cstr(sb, cstr) \ - do { \ - const char *s = (cstr); \ - size_t n = strlen(s); \ - nob_da_append_many(sb, s, n); \ - } while (0) - -// Append a single NULL character at the end of a string builder. So then you can -// use it a NULL-terminated C string -#define nob_sb_append_null(sb) nob_da_append_many(sb, "", 1) - -#define nob_sb_append nob_da_append - -// Free the memory allocated by a string builder -#define nob_sb_free(sb) NOB_FREE((sb).items) - -// Process handle -#ifdef _WIN32 -typedef HANDLE Nob_Proc; -#define NOB_INVALID_PROC INVALID_HANDLE_VALUE -typedef HANDLE Nob_Fd; -#define NOB_INVALID_FD INVALID_HANDLE_VALUE -#else -typedef int Nob_Proc; -#define NOB_INVALID_PROC (-1) -typedef int Nob_Fd; -#define NOB_INVALID_FD (-1) -#endif // _WIN32 - -NOBDEF Nob_Fd nob_fd_open_for_read(const char *path); -NOBDEF Nob_Fd nob_fd_open_for_write(const char *path); -NOBDEF void nob_fd_close(Nob_Fd fd); - -typedef struct { - Nob_Fd read; - Nob_Fd write; -} Nob_Pipe; - -NOBDEF bool nob_pipe_create(Nob_Pipe *pp); - -typedef struct { - Nob_Proc *items; - size_t count; - size_t capacity; -} Nob_Procs; - -// Wait until the process has finished -NOBDEF bool nob_proc_wait(Nob_Proc proc); - -// Wait until all the processes have finished -NOBDEF bool nob_procs_wait(Nob_Procs procs); - -// Wait until all the processes have finished and empty the procs array. -NOBDEF bool nob_procs_flush(Nob_Procs *procs); - -// Alias to nob_procs_flush -NOB_DEPRECATED("Use `nob_procs_flush(&procs)` instead.") -NOBDEF bool nob_procs_wait_and_reset(Nob_Procs *procs); - -// Append a new process to procs array and if procs.count reaches max_procs_count call nob_procs_wait_and_reset() on it -NOB_DEPRECATED("Use `nob_cmd_run(&cmd, .async = &procs, .max_procs = )` instead") -NOBDEF bool nob_procs_append_with_flush(Nob_Procs *procs, Nob_Proc proc, size_t max_procs_count); - -// A command - the main workhorse of Nob. Nob is all about building commands and running them -typedef struct { - const char **items; - size_t count; - size_t capacity; -} Nob_Cmd; - -// Options for nob_cmd_run_opt() function. -typedef struct { - // Run the command asynchronously appending its Nob_Proc to the provided Nob_Procs array - Nob_Procs *async; - // Maximum processes allowed in the .async list. Zero implies nob_nprocs(). - size_t max_procs; - // Do not reset the command after execution. - bool dont_reset; - // Redirect stdin to file - const char *stdin_path; - // Redirect stdout to file - const char *stdout_path; - // Redirect stderr to file - const char *stderr_path; -} Nob_Cmd_Opt; - -// Run the command with options. -NOBDEF bool nob_cmd_run_opt(Nob_Cmd *cmd, Nob_Cmd_Opt opt); - -// Command Chains (in Shell Scripting they are know as Pipes) -// -// Usage: -// ```c -// Nob_Cmd cmd = {0}; -// Nob_Chain chain = {0}; -// if (!nob_chain_begin(&chain)) return 1; -// { -// nob_cmd_append(&cmd, "echo", "Hello, World"); -// if (!nob_chain_cmd(&chain, &cmd)) return 1; -// -// nob_cmd_append(&cmd, "rev"); -// if (!nob_chain_cmd(&chain, &cmd)) return 1; -// -// nob_cmd_append(&cmd, "xxd"); -// if (!nob_chain_cmd(&chain, &cmd)) return 1; -// } -// if (!nob_chain_end(&chain)) return 1; -// ``` -// -// The above is equivalent to a shell command: -// -// ```sh -// echo "Hello, World" | rev | xxd -// ``` -// -// After nob_chain_end() the Nob_Chain struct can be reused again. -// -// The fields of the Nob_Chain struct contain the intermediate state of the Command -// Chain that is being built with the nob_chain_cmd() calls and generally have no -// particular use for the user. -// -// The only memory dynamically allocated within Nob_Chain belongs to the .cmd field. -// So if you want to clean it all up you can just do free(chain.cmd.items). -typedef struct { - // The file descriptor of the output of the previous command. Will be used as the input for the next command. - Nob_Fd fdin; - // The command from the last nob_chain_cmd() call. - Nob_Cmd cmd; - // The value of the optional .err2out parameter from the last nob_chain_cmd() call. - bool err2out; -} Nob_Chain; - -typedef struct { - const char *stdin_path; -} Nob_Chain_Begin_Opt; -#define nob_chain_begin(chain, ...) nob_chain_begin_opt((chain), NOB_CLIT(Nob_Chain_Begin_Opt) { __VA_ARGS__ }) -NOBDEF bool nob_chain_begin_opt(Nob_Chain *chain, Nob_Chain_Begin_Opt opt); - -typedef struct { - bool err2out; - bool dont_reset; -} Nob_Chain_Cmd_Opt; -#define nob_chain_cmd(chain, cmd, ...) nob_chain_cmd_opt((chain), (cmd), NOB_CLIT(Nob_Chain_Cmd_Opt) { __VA_ARGS__ }) -NOBDEF bool nob_chain_cmd_opt(Nob_Chain *chain, Nob_Cmd *cmd, Nob_Chain_Cmd_Opt opt); - -typedef struct { - Nob_Procs *async; - size_t max_procs; - const char *stdout_path; - const char *stderr_path; -} Nob_Chain_End_Opt; -#define nob_chain_end(chain, ...) nob_chain_end_opt((chain), NOB_CLIT(Nob_Chain_End_Opt) { __VA_ARGS__ }) -NOBDEF bool nob_chain_end_opt(Nob_Chain *chain, Nob_Chain_End_Opt opt); - -// Get amount of processors on the machine. -NOBDEF int nob_nprocs(void); - -#define NOB_NANOS_PER_SEC (1000*1000*1000) - -// The maximum time span representable is 584 years. -NOBDEF uint64_t nob_nanos_since_unspecified_epoch(void); - -// Same as nob_cmd_run_opt but using cool variadic macro to set the default options. -// See https://x.com/vkrajacic/status/1749816169736073295 for more info on how to use such macros. -#define nob_cmd_run(cmd, ...) nob_cmd_run_opt((cmd), NOB_CLIT(Nob_Cmd_Opt){__VA_ARGS__}) - -// DEPRECATED: -// -// You were suppose to use this structure like this: -// -// ```c -// Nob_Fd fdin = nob_fd_open_for_read("input.txt"); -// if (fdin == NOB_INVALID_FD) fail(); -// Nob_Fd fdout = nob_fd_open_for_write("output.txt"); -// if (fdout == NOB_INVALID_FD) fail(); -// Nob_Cmd cmd = {0}; -// nob_cmd_append(&cmd, "cat"); -// if (!nob_cmd_run_sync_redirect_and_reset(&cmd, (Nob_Cmd_Redirect) { -// .fdin = &fdin, -// .fdout = &fdout -// })) fail(); -// ``` -// -// But these days you should do: -// -// ```c -// Nob_Cmd cmd = {0}; -// nob_cmd_append(&cmd, "cat"); -// if (!nob_cmd_run(&cmd, .stdin_path = "input.txt", .stdout_path = "output.txt")) fail(); -// ``` -typedef struct { - Nob_Fd *fdin; - Nob_Fd *fdout; - Nob_Fd *fderr; -} Nob_Cmd_Redirect; - -// Render a string representation of a command into a string builder. Keep in mind the the -// string builder is not NULL-terminated by default. Use nob_sb_append_null if you plan to -// use it as a C string. -NOBDEF void nob_cmd_render(Nob_Cmd cmd, Nob_String_Builder *render); - -// Compound Literal -#if defined(__cplusplus) - #define NOB_CLIT(type) type -#else - #define NOB_CLIT(type) (type) -#endif - -NOBDEF void nob__cmd_append(Nob_Cmd *cmd, size_t n, const char **args); -#if defined(__cplusplus) - template - static inline void nob__cpp_cmd_append_wrapper(Nob_Cmd *cmd, Args... strs) - { - const char* args[] = { strs... }; - nob__cmd_append(cmd, sizeof(args)/sizeof(args[0]), args); - } - #define nob_cmd_append(cmd, ...) nob__cpp_cmd_append_wrapper(cmd, __VA_ARGS__) -#else - #define nob_cmd_append(cmd, ...) \ - nob__cmd_append(cmd, sizeof((const char*[]){__VA_ARGS__})/sizeof(const char*), (const char*[]){__VA_ARGS__}) -#endif // __cplusplus - -// TODO: nob_cmd_extend() evaluates other_cmd twice -// It can be fixed by turning nob_cmd_extend() call into a statement. -// But that may break backward compatibility of the API. -#define nob_cmd_extend(cmd, other_cmd) \ - nob_da_append_many(cmd, (other_cmd)->items, (other_cmd)->count) - -// Free all the memory allocated by command arguments -#define nob_cmd_free(cmd) NOB_FREE(cmd.items) - -// Run command asynchronously -NOB_DEPRECATED("Use `nob_cmd_run(&cmd, .async = &procs, .dont_reset = true)`.") -NOBDEF Nob_Proc nob_cmd_run_async(Nob_Cmd cmd); - -// nob_cmd_run_async_and_reset() is just like nob_cmd_run_async() except it also resets cmd.count to 0 -// so the Nob_Cmd instance can be seamlessly used several times in a row -NOB_DEPRECATED("Use `nob_cmd_run(&cmd, .async = &procs)` intead.") -NOBDEF Nob_Proc nob_cmd_run_async_and_reset(Nob_Cmd *cmd); - -// Run redirected command asynchronously -NOB_DEPRECATED("Use `nob_cmd_run(&cmd, " - ".async = &procs, " - ".stdin_path = \"path/to/stdin\", " - ".stdout_path = \"path/to/stdout\", " - ".stderr_path = \"path/to/stderr\", " - ".dont_reset = true" - ")` instead.") -NOBDEF Nob_Proc nob_cmd_run_async_redirect(Nob_Cmd cmd, Nob_Cmd_Redirect redirect); - -// Run redirected command asynchronously and set cmd.count to 0 and close all the opened files -NOB_DEPRECATED("Use `nob_cmd_run(&cmd, " - ".async = &procs, " - ".stdin_path = \"path/to/stdin\", " - ".stdout_path = \"path/to/stdout\", " - ".stderr_path = \"path/to/stderr\")` instead.") -NOBDEF Nob_Proc nob_cmd_run_async_redirect_and_reset(Nob_Cmd *cmd, Nob_Cmd_Redirect redirect); - -// Run command synchronously -NOB_DEPRECATED("Use `nob_cmd_run(&cmd, .dont_reset = true)` instead.") -NOBDEF bool nob_cmd_run_sync(Nob_Cmd cmd); - -// NOTE: nob_cmd_run_sync_and_reset() is just like nob_cmd_run_sync() except it also resets cmd.count to 0 -// so the Nob_Cmd instance can be seamlessly used several times in a row -NOB_DEPRECATED("Use `nob_cmd_run(&cmd)` instead.") -NOBDEF bool nob_cmd_run_sync_and_reset(Nob_Cmd *cmd); - -// Run redirected command synchronously -NOB_DEPRECATED("Use `nob_cmd_run(&cmd, " - ".stdin_path = \"path/to/stdin\", " - ".stdout_path = \"path/to/stdout\", " - ".stderr_path = \"path/to/stderr\", " - ".dont_reset = true" - ")` instead.") -NOBDEF bool nob_cmd_run_sync_redirect(Nob_Cmd cmd, Nob_Cmd_Redirect redirect); - -// Run redirected command synchronously and set cmd.count to 0 and close all the opened files -NOB_DEPRECATED("Use `nob_cmd_run(&cmd, " - ".stdin_path = \"path/to/stdin\", " - ".stdout_path = \"path/to/stdout\", " - ".stderr_path = \"path/to/stderr\")` instead.") -NOBDEF bool nob_cmd_run_sync_redirect_and_reset(Nob_Cmd *cmd, Nob_Cmd_Redirect redirect); - -#ifndef NOB_TEMP_CAPACITY -#define NOB_TEMP_CAPACITY (8*1024*1024) -#endif // NOB_TEMP_CAPACITY -NOBDEF char *nob_temp_strdup(const char *cstr); -NOBDEF char *nob_temp_strndup(const char *cstr, size_t size); -NOBDEF void *nob_temp_alloc(size_t size); -NOBDEF char *nob_temp_sprintf(const char *format, ...) NOB_PRINTF_FORMAT(1, 2); -NOBDEF char *nob_temp_vsprintf(const char *format, va_list ap); -// nob_temp_reset() - Resets the entire temporary storage to 0. -// -// It is generally not recommended to call this function ever. What you usually want to do is let's say you have a loop, -// that allocates some temporary objects and cleans them up at the end of each iteration. You should use -// nob_temp_save() and nob_temp_rewind() to organize such loop like this: -// -// ```c -// char *message = nob_temp_sprintf("This message is still valid after the loop below"); -// while (!quit) { -// size_t mark = nob_temp_save(); -// nob_temp_alloc(69); -// nob_temp_alloc(420); -// nob_temp_alloc(1337); -// nob_temp_rewind(mark); -// } -// printf("%s\n", message); -// ``` -// -// That way all the temporary allocations created before the loop are still valid even after the loop. -// Such save/rewind blocks define lifetime boundaries of the temporary objects which also could be nested. -// This turns the temporary storage into kind of a second stack with a more manual management. -NOBDEF void nob_temp_reset(void); -NOBDEF size_t nob_temp_save(void); -NOBDEF void nob_temp_rewind(size_t checkpoint); - -// Given any path returns the last part of that path. -// "/path/to/a/file.c" -> "file.c"; "/path/to/a/directory" -> "directory" -NOBDEF const char *nob_path_name(const char *path); -NOBDEF bool nob_rename(const char *old_path, const char *new_path); -NOBDEF int nob_needs_rebuild(const char *output_path, const char **input_paths, size_t input_paths_count); -NOBDEF int nob_needs_rebuild1(const char *output_path, const char *input_path); -NOBDEF int nob_file_exists(const char *file_path); -NOBDEF const char *nob_get_current_dir_temp(void); -NOBDEF bool nob_set_current_dir(const char *path); -// Returns you the directory part of the path allocated on the temporary storage. -NOBDEF char *nob_temp_dir_name(const char *path); -NOBDEF char *nob_temp_file_name(const char *path); -NOBDEF char *nob_temp_file_ext(const char *path); -NOBDEF char *nob_temp_running_executable_path(void); - -// TODO: we should probably document somewhere all the compilers we support - -// The nob_cc_* macros try to abstract away the specific compiler. -// They are verify basic and not particularly flexible, but you can redefine them if you need to -// or not use them at all and create your own abstraction on top of Nob_Cmd. - -#ifndef nob_cc -# if _WIN32 -# if defined(__GNUC__) -# define nob_cc(cmd) nob_cmd_append(cmd, "cc") -# elif defined(__clang__) -# define nob_cc(cmd) nob_cmd_append(cmd, "clang") -# elif defined(_MSC_VER) -# define nob_cc(cmd) nob_cmd_append(cmd, "cl.exe") -# elif defined(__TINYC__) -# define nob_cc(cmd) nob_cmd_append(cmd, "tcc") -# endif -# else -# define nob_cc(cmd) nob_cmd_append(cmd, "cc") -# endif -#endif // nob_cc - -#ifndef nob_cc_flags -# if defined(_MSC_VER) && !defined(__clang__) -# define nob_cc_flags(cmd) nob_cmd_append(cmd, "/W4", "/nologo", "/D_CRT_SECURE_NO_WARNINGS") -# else -# define nob_cc_flags(cmd) nob_cmd_append(cmd, "-Wall", "-Wextra") -# endif -#endif // nob_cc_flags - -#ifndef nob_cc_output -# if defined(_MSC_VER) && !defined(__clang__) -# define nob_cc_output(cmd, output_path) nob_cmd_append(cmd, nob_temp_sprintf("/Fe:%s", (output_path)), nob_temp_sprintf("/Fo:%s", (output_path))) -# else -# define nob_cc_output(cmd, output_path) nob_cmd_append(cmd, "-o", (output_path)) -# endif -#endif // nob_cc_output - -#ifndef nob_cc_inputs -# define nob_cc_inputs(cmd, ...) nob_cmd_append(cmd, __VA_ARGS__) -#endif // nob_cc_inputs - -// TODO: add MinGW support for Go Rebuild Urself™ Technology and all the nob_cc_* macros above -// Musializer contributors came up with a pretty interesting idea of an optional prefix macro which could be useful for -// MinGW support: -// https://github.com/tsoding/musializer/blob/b7578cc76b9ecb573d239acc9ccf5a04d3aba2c9/src_build/nob_win64_mingw.c#L3-L9 -// TODO: Maybe instead NOB_REBUILD_URSELF macro, the Go Rebuild Urself™ Technology should use the -// user defined nob_cc_* macros instead? -#ifndef NOB_REBUILD_URSELF -# if defined(_WIN32) -# if defined(__clang__) -# if defined(__cplusplus) -# define NOB_REBUILD_URSELF(binary_path, source_path) "clang", "-x", "c++", "-o", binary_path, source_path -# else -# define NOB_REBUILD_URSELF(binary_path, source_path) "clang", "-x", "c", "-o", binary_path, source_path -# endif -# elif defined(__GNUC__) -# if defined(__cplusplus) -# define NOB_REBUILD_URSELF(binary_path, source_path) "gcc", "-x", "c++", "-o", binary_path, source_path -# else -# define NOB_REBUILD_URSELF(binary_path, source_path) "gcc", "-x", "c", "-o", binary_path, source_path -# endif -# elif defined(_MSC_VER) -# define NOB_REBUILD_URSELF(binary_path, source_path) "cl.exe", nob_temp_sprintf("/Fe:%s", (binary_path)), source_path -# elif defined(__TINYC__) -# define NOB_REBUILD_URSELF(binary_path, source_path) "tcc", "-o", binary_path, source_path -# endif -# else -# if defined(__cplusplus) -# define NOB_REBUILD_URSELF(binary_path, source_path) "cc", "-x", "c++", "-o", binary_path, source_path -# else -# define NOB_REBUILD_URSELF(binary_path, source_path) "cc", "-x", "c", "-o", binary_path, source_path -# endif -# endif -#endif - -// Go Rebuild Urself™ Technology -// -// How to use it: -// int main(int argc, char** argv) { -// NOB_GO_REBUILD_URSELF(argc, argv); -// // actual work -// return 0; -// } -// -// After you added this macro every time you run ./nob it will detect -// that you modified its original source code and will try to rebuild itself -// before doing any actual work. So you only need to bootstrap your build system -// once. -// -// The modification is detected by comparing the last modified times of the executable -// and its source code. The same way the make utility usually does it. -// -// The rebuilding is done by using the NOB_REBUILD_URSELF macro which you can redefine -// if you need a special way of bootstraping your build system. (which I personally -// do not recommend since the whole idea of NoBuild is to keep the process of bootstrapping -// as simple as possible and doing all of the actual work inside of ./nob) -// -NOBDEF void nob__go_rebuild_urself(int argc, char **argv, const char *source_path, ...); -#define NOB_GO_REBUILD_URSELF(argc, argv) nob__go_rebuild_urself(argc, argv, __FILE__, NULL) -// Sometimes your nob.c includes additional files, so you want the Go Rebuild Urself™ Technology to check -// if they also were modified and rebuild nob.c accordingly. For that we have NOB_GO_REBUILD_URSELF_PLUS(): -// ```c -// #define NOB_IMPLEMENTATION -// #include "nob.h" -// -// #include "foo.c" -// #include "bar.c" -// -// int main(int argc, char **argv) -// { -// NOB_GO_REBUILD_URSELF_PLUS(argc, argv, "foo.c", "bar.c"); -// // ... -// return 0; -// } -#define NOB_GO_REBUILD_URSELF_PLUS(argc, argv, ...) nob__go_rebuild_urself(argc, argv, __FILE__, __VA_ARGS__, NULL); - -typedef struct { - size_t count; - const char *data; -} Nob_String_View; - -NOBDEF const char *nob_temp_sv_to_cstr(Nob_String_View sv); - -NOBDEF Nob_String_View nob_sv_chop_while(Nob_String_View *sv, int (*p)(int x)); -NOBDEF Nob_String_View nob_sv_chop_by_delim(Nob_String_View *sv, char delim); -NOBDEF Nob_String_View nob_sv_chop_left(Nob_String_View *sv, size_t n); -NOBDEF Nob_String_View nob_sv_chop_right(Nob_String_View *sv, size_t n); -// If `sv` starts with `prefix` chops off the prefix and returns true. -// Otherwise, leaves `sv` unmodified and returns false. -NOBDEF bool nob_sv_chop_prefix(Nob_String_View *sv, Nob_String_View prefix); -// If `sv` ends with `suffix` chops off the suffix and returns true. -// Otherwise, leaves `sv` unmodified and returns false. -NOBDEF bool nob_sv_chop_suffix(Nob_String_View *sv, Nob_String_View suffix); -NOBDEF Nob_String_View nob_sv_trim(Nob_String_View sv); -NOBDEF Nob_String_View nob_sv_trim_left(Nob_String_View sv); -NOBDEF Nob_String_View nob_sv_trim_right(Nob_String_View sv); -NOBDEF bool nob_sv_eq(Nob_String_View a, Nob_String_View b); -NOB_DEPRECATED("Use nob_sv_ends_with_cstr(sv, suffix) instead. " - "Pay attention to the `s` at the end of the `end`. " - "The reason this function was deprecated is because " - "of the typo in the name, of course, but also " - "because the second argument was a NULL-terminated string " - "while nob_sv_starts_with() accepted Nob_String_View as the " - "prefix which created an inconsistency in the API.") -NOBDEF bool nob_sv_end_with(Nob_String_View sv, const char *cstr); -NOBDEF bool nob_sv_ends_with_cstr(Nob_String_View sv, const char *cstr); -NOBDEF bool nob_sv_ends_with(Nob_String_View sv, Nob_String_View suffix); -NOBDEF bool nob_sv_starts_with(Nob_String_View sv, Nob_String_View prefix); -NOBDEF Nob_String_View nob_sv_from_cstr(const char *cstr); -NOBDEF Nob_String_View nob_sv_from_parts(const char *data, size_t count); -// nob_sb_to_sv() enables you to just view Nob_String_Builder as Nob_String_View -#define nob_sb_to_sv(sb) nob_sv_from_parts((sb).items, (sb).count) - -// printf macros for String_View -#ifndef SV_Fmt -#define SV_Fmt "%.*s" -#endif // SV_Fmt -#ifndef SV_Arg -#define SV_Arg(sv) (int) (sv).count, (sv).data -#endif // SV_Arg -// USAGE: -// String_View name = ...; -// printf("Name: "SV_Fmt"\n", SV_Arg(name)); - -#ifdef _WIN32 - -NOBDEF char *nob_win32_error_message(DWORD err); - -#endif // _WIN32 - -#endif // NOB_H_ - -#ifdef NOB_IMPLEMENTATION - -// This is like nob_proc_wait() but waits asynchronously. Depending on the platform ms means different thing. -// On Windows it means timeout. On POSIX it means for how long to sleep after checking if the process exited, -// so to not peg the core too much. Since this API is kinda of weird, the function is private for now. -static int nob__proc_wait_async(Nob_Proc proc, int ms); - -// Starts the process for the command. Its main purpose is to be the base for nob_cmd_run() and nob_cmd_run_opt(). -static Nob_Proc nob__cmd_start_process(Nob_Cmd cmd, Nob_Fd *fdin, Nob_Fd *fdout, Nob_Fd *fderr); - -// Any messages with the level below nob_minimal_log_level are going to be suppressed. -Nob_Log_Level nob_minimal_log_level = NOB_INFO; - -NOBDEF void nob__cmd_append(Nob_Cmd *cmd, size_t n, const char **args) -{ - for (size_t i = 0; i < n; ++i) { - nob_da_append(cmd, args[i]); - } -} - -#ifdef _WIN32 - -// Base on https://stackoverflow.com/a/75644008 -// > .NET Core uses 4096 * sizeof(WCHAR) buffer on stack for FormatMessageW call. And...thats it. -// > -// > https://github.com/dotnet/runtime/blob/3b63eb1346f1ddbc921374a5108d025662fb5ffd/src/coreclr/utilcode/posterror.cpp#L264-L265 -#ifndef NOB_WIN32_ERR_MSG_SIZE -#define NOB_WIN32_ERR_MSG_SIZE (4 * 1024) -#endif // NOB_WIN32_ERR_MSG_SIZE - -NOBDEF char *nob_win32_error_message(DWORD err) { - static char win32ErrMsg[NOB_WIN32_ERR_MSG_SIZE] = {0}; - DWORD errMsgSize = FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, err, LANG_USER_DEFAULT, win32ErrMsg, - NOB_WIN32_ERR_MSG_SIZE, NULL); - - if (errMsgSize == 0) { - if (GetLastError() != ERROR_MR_MID_NOT_FOUND) { - if (sprintf(win32ErrMsg, "Could not get error message for 0x%lX", err) > 0) { - return (char *)&win32ErrMsg; - } else { - return NULL; - } - } else { - if (sprintf(win32ErrMsg, "Invalid Windows Error code (0x%lX)", err) > 0) { - return (char *)&win32ErrMsg; - } else { - return NULL; - } - } - } - - while (errMsgSize > 1 && isspace(win32ErrMsg[errMsgSize - 1])) { - win32ErrMsg[--errMsgSize] = '\0'; - } - - return win32ErrMsg; -} - -#endif // _WIN32 - -// The implementation idea is stolen from https://github.com/zhiayang/nabs -NOBDEF void nob__go_rebuild_urself(int argc, char **argv, const char *source_path, ...) -{ - const char *binary_path = nob_shift(argv, argc); -#ifdef _WIN32 - // On Windows executables almost always invoked without extension, so - // it's ./nob, not ./nob.exe. For renaming the extension is a must. - if (!nob_sv_ends_with_cstr(nob_sv_from_cstr(binary_path), ".exe")) { - binary_path = nob_temp_sprintf("%s.exe", binary_path); - } -#endif - - Nob_File_Paths source_paths = {0}; - nob_da_append(&source_paths, source_path); - va_list args; - va_start(args, source_path); - for (;;) { - const char *path = va_arg(args, const char*); - if (path == NULL) break; - nob_da_append(&source_paths, path); - } - va_end(args); - - int rebuild_is_needed = nob_needs_rebuild(binary_path, source_paths.items, source_paths.count); - if (rebuild_is_needed < 0) exit(1); // error - if (!rebuild_is_needed) { // no rebuild is needed - NOB_FREE(source_paths.items); - return; - } - - Nob_Cmd cmd = {0}; - - const char *old_binary_path = nob_temp_sprintf("%s.old", binary_path); - - if (!nob_rename(binary_path, old_binary_path)) exit(1); - nob_cmd_append(&cmd, NOB_REBUILD_URSELF(binary_path, source_path)); - Nob_Cmd_Opt opt = {0}; - if (!nob_cmd_run_opt(&cmd, opt)) { - nob_rename(old_binary_path, binary_path); - exit(1); - } -#ifdef NOB_EXPERIMENTAL_DELETE_OLD - // TODO: this is an experimental behavior behind a compilation flag. - // Once it is confirmed that it does not cause much problems on both POSIX and Windows - // we may turn it on by default. - nob_delete_file(old_binary_path); -#endif // NOB_EXPERIMENTAL_DELETE_OLD - - nob_cmd_append(&cmd, binary_path); - nob_da_append_many(&cmd, argv, argc); - if (!nob_cmd_run_opt(&cmd, opt)) exit(1); - exit(0); -} - -static size_t nob_temp_size = 0; -static char nob_temp[NOB_TEMP_CAPACITY] = {0}; - -NOBDEF bool nob_mkdir_if_not_exists(const char *path) -{ -#ifdef _WIN32 - int result = _mkdir(path); -#else - int result = mkdir(path, 0755); -#endif - if (result < 0) { - if (errno == EEXIST) { -#ifndef NOB_NO_ECHO - nob_log(NOB_INFO, "directory `%s` already exists", path); -#endif // NOB_NO_ECHO - return true; - } - nob_log(NOB_ERROR, "could not create directory `%s`: %s", path, strerror(errno)); - return false; - } - -#ifndef NOB_NO_ECHO - nob_log(NOB_INFO, "created directory `%s`", path); -#endif // NOB_NO_ECHO - return true; -} - -NOBDEF bool nob_copy_file(const char *src_path, const char *dst_path) -{ -#ifndef NOB_NO_ECHO - nob_log(NOB_INFO, "copying %s -> %s", src_path, dst_path); -#endif // NOB_NO_ECHO -#ifdef _WIN32 - if (!CopyFile(src_path, dst_path, FALSE)) { - nob_log(NOB_ERROR, "Could not copy file: %s", nob_win32_error_message(GetLastError())); - return false; - } - return true; -#else - int src_fd = -1; - int dst_fd = -1; - size_t buf_size = 32*1024; - char *buf = (char*)NOB_REALLOC(NULL, buf_size); - NOB_ASSERT(buf != NULL && "Buy more RAM lol!!"); - bool result = true; - - src_fd = open(src_path, O_RDONLY); - if (src_fd < 0) { - nob_log(NOB_ERROR, "Could not open file %s: %s", src_path, strerror(errno)); - nob_return_defer(false); - } - - struct stat src_stat; - if (fstat(src_fd, &src_stat) < 0) { - nob_log(NOB_ERROR, "Could not get mode of file %s: %s", src_path, strerror(errno)); - nob_return_defer(false); - } - - dst_fd = open(dst_path, O_CREAT | O_TRUNC | O_WRONLY, src_stat.st_mode); - if (dst_fd < 0) { - nob_log(NOB_ERROR, "Could not create file %s: %s", dst_path, strerror(errno)); - nob_return_defer(false); - } - - for (;;) { - ssize_t n = read(src_fd, buf, buf_size); - if (n == 0) break; - if (n < 0) { - nob_log(NOB_ERROR, "Could not read from file %s: %s", src_path, strerror(errno)); - nob_return_defer(false); - } - char *buf2 = buf; - while (n > 0) { - ssize_t m = write(dst_fd, buf2, n); - if (m < 0) { - nob_log(NOB_ERROR, "Could not write to file %s: %s", dst_path, strerror(errno)); - nob_return_defer(false); - } - n -= m; - buf2 += m; - } - } - -defer: - NOB_FREE(buf); - close(src_fd); - close(dst_fd); - return result; -#endif -} - -NOBDEF void nob_cmd_render(Nob_Cmd cmd, Nob_String_Builder *render) -{ - for (size_t i = 0; i < cmd.count; ++i) { - const char *arg = cmd.items[i]; - if (arg == NULL) break; - if (i > 0) nob_sb_append_cstr(render, " "); - if (!strchr(arg, ' ')) { - nob_sb_append_cstr(render, arg); - } else { - nob_da_append(render, '\''); - nob_sb_append_cstr(render, arg); - nob_da_append(render, '\''); - } - } -} - -#ifdef _WIN32 -// https://learn.microsoft.com/en-gb/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way -static void nob__win32_cmd_quote(Nob_Cmd cmd, Nob_String_Builder *quoted) -{ - for (size_t i = 0; i < cmd.count; ++i) { - const char *arg = cmd.items[i]; - if (arg == NULL) break; - size_t len = strlen(arg); - if (i > 0) nob_da_append(quoted, ' '); - if (len != 0 && NULL == strpbrk(arg, " \t\n\v\"")) { - // no need to quote - nob_da_append_many(quoted, arg, len); - } else { - // we need to escape: - // 1. double quotes in the original arg - // 2. consequent backslashes before a double quote - size_t backslashes = 0; - nob_da_append(quoted, '\"'); - for (size_t j = 0; j < len; ++j) { - char x = arg[j]; - if (x == '\\') { - backslashes += 1; - } else { - if (x == '\"') { - // escape backslashes (if any) and the double quote - for (size_t k = 0; k < 1+backslashes; ++k) { - nob_da_append(quoted, '\\'); - } - } - backslashes = 0; - } - nob_da_append(quoted, x); - } - // escape backslashes (if any) - for (size_t k = 0; k < backslashes; ++k) { - nob_da_append(quoted, '\\'); - } - nob_da_append(quoted, '\"'); - } - } -} -#endif - -NOBDEF int nob_nprocs(void) -{ -#ifdef _WIN32 - SYSTEM_INFO siSysInfo; - GetSystemInfo(&siSysInfo); - return siSysInfo.dwNumberOfProcessors; -#else - return sysconf(_SC_NPROCESSORS_ONLN); -#endif -} - -NOBDEF bool nob_cmd_run_opt(Nob_Cmd *cmd, Nob_Cmd_Opt opt) -{ - bool result = true; - Nob_Fd fdin = NOB_INVALID_FD; - Nob_Fd fdout = NOB_INVALID_FD; - Nob_Fd fderr = NOB_INVALID_FD; - Nob_Fd *opt_fdin = NULL; - Nob_Fd *opt_fdout = NULL; - Nob_Fd *opt_fderr = NULL; - Nob_Proc proc = NOB_INVALID_PROC; - - size_t max_procs = opt.max_procs > 0 ? opt.max_procs : (size_t) nob_nprocs() + 1; - - if (opt.async && max_procs > 0) { - while (opt.async->count >= max_procs) { - for (size_t i = 0; i < opt.async->count; ++i) { - int ret = nob__proc_wait_async(opt.async->items[i], 1); - if (ret < 0) nob_return_defer(false); - if (ret) { - nob_da_remove_unordered(opt.async, i); - break; - } - } - } - } - - if (opt.stdin_path) { - fdin = nob_fd_open_for_read(opt.stdin_path); - if (fdin == NOB_INVALID_FD) nob_return_defer(false); - opt_fdin = &fdin; - } - if (opt.stdout_path) { - fdout = nob_fd_open_for_write(opt.stdout_path); - if (fdout == NOB_INVALID_FD) nob_return_defer(false); - opt_fdout = &fdout; - } - if (opt.stderr_path) { - fderr = nob_fd_open_for_write(opt.stderr_path); - if (fderr == NOB_INVALID_FD) nob_return_defer(false); - opt_fderr = &fderr; - } - proc = nob__cmd_start_process(*cmd, opt_fdin, opt_fdout, opt_fderr); - - if (opt.async) { - if (proc == NOB_INVALID_PROC) nob_return_defer(false); - nob_da_append(opt.async, proc); - } else { - if (!nob_proc_wait(proc)) nob_return_defer(false); - } - -defer: - if (opt_fdin) nob_fd_close(*opt_fdin); - if (opt_fdout) nob_fd_close(*opt_fdout); - if (opt_fderr) nob_fd_close(*opt_fderr); - if (!opt.dont_reset) cmd->count = 0; - return result; -} - -NOBDEF bool nob_chain_begin_opt(Nob_Chain *chain, Nob_Chain_Begin_Opt opt) -{ - chain->cmd.count = 0; - chain->err2out = false; - chain->fdin = NOB_INVALID_FD; - if (opt.stdin_path) { - chain->fdin = nob_fd_open_for_read(opt.stdin_path); - if (chain->fdin == NOB_INVALID_FD) return false; - } - return true; -} - -NOBDEF bool nob_chain_cmd_opt(Nob_Chain *chain, Nob_Cmd *cmd, Nob_Chain_Cmd_Opt opt) -{ - bool result = true; - Nob_Pipe pp = {0}; - struct { - size_t count; - Nob_Fd items[5]; // should be no more than 3, but we allocate 5 just in case - } fds = {0}; - - NOB_ASSERT(cmd->count > 0); - - if (chain->cmd.count != 0) { // not first cmd in the chain - Nob_Fd *pfdin = NULL; - if (chain->fdin != NOB_INVALID_FD) { - nob_fa_append(&fds, chain->fdin); - pfdin = &chain->fdin; - } - if (!nob_pipe_create(&pp)) nob_return_defer(false); - nob_fa_append(&fds, pp.write); - Nob_Fd *pfdout = &pp.write; - Nob_Fd *pfderr = chain->err2out ? pfdout : NULL; - - Nob_Proc proc = nob__cmd_start_process(chain->cmd, pfdin, pfdout, pfderr); - chain->cmd.count = 0; - if (proc == NOB_INVALID_PROC) { - nob_fa_append(&fds, pp.read); - nob_return_defer(false); - } - chain->fdin = pp.read; - } - - nob_da_append_many(&chain->cmd, cmd->items, cmd->count); - chain->err2out = opt.err2out; - -defer: - for (size_t i = 0; i < fds.count; ++i) { - nob_fd_close(fds.items[i]); - } - if (!opt.dont_reset) cmd->count = 0; - return result; -} - -static Nob_Fd nob__fd_stdout(void) -{ -#ifdef _WIN32 - return GetStdHandle(STD_OUTPUT_HANDLE); -#else - return STDOUT_FILENO; -#endif // _WIN32 -} - -NOBDEF bool nob_chain_end_opt(Nob_Chain *chain, Nob_Chain_End_Opt opt) -{ - bool result = true; - - Nob_Fd *pfdin = NULL; - struct { - size_t count; - Nob_Fd items[5]; // should be no more than 3, but we allocate 5 just in case - } fds = {0}; - - if (chain->fdin != NOB_INVALID_FD) { - nob_fa_append(&fds, chain->fdin); - pfdin = &chain->fdin; - } - - if (chain->cmd.count != 0) { // Non-empty chain case - size_t max_procs = opt.max_procs > 0 ? opt.max_procs : (size_t) nob_nprocs() + 1; - - if (opt.async && max_procs > 0) { - while (opt.async->count >= max_procs) { - for (size_t i = 0; i < opt.async->count; ++i) { - int ret = nob__proc_wait_async(opt.async->items[i], 1); - if (ret < 0) nob_return_defer(false); - if (ret) { - nob_da_remove_unordered(opt.async, i); - break; - } - } - } - } - - Nob_Fd fdout = nob__fd_stdout(); - if (opt.stdout_path) { - fdout = nob_fd_open_for_write(opt.stdout_path); - if (fdout == NOB_INVALID_FD) nob_return_defer(false); - nob_fa_append(&fds, fdout); - } - - Nob_Fd fderr = 0; - Nob_Fd *pfderr = NULL; - if (chain->err2out) pfderr = &fdout; - if (opt.stderr_path) { - if (pfderr == NULL) { - fderr = nob_fd_open_for_write(opt.stderr_path); - if (fderr == NOB_INVALID_FD) nob_return_defer(false); - nob_fa_append(&fds, fderr); - pfderr = &fderr; - } else { - // There was err2out set for the last command. - // All the stderr will go to stdout. - // So the stderr file is going to be empty. - NOB_ASSERT(chain->err2out); - if (!nob_write_entire_file(opt.stderr_path, NULL, 0)) nob_return_defer(false); - } - } - - Nob_Proc proc = nob__cmd_start_process(chain->cmd, pfdin, &fdout, pfderr); - chain->cmd.count = 0; - - if (opt.async) { - if (proc == NOB_INVALID_PROC) nob_return_defer(false); - nob_da_append(opt.async, proc); - } else { - if (!nob_proc_wait(proc)) nob_return_defer(false); - } - } - -defer: - for (size_t i = 0; i < fds.count; ++i) { - nob_fd_close(fds.items[i]); - } - return result; -} - -// The maximum time span representable is 584 years. -NOBDEF uint64_t nob_nanos_since_unspecified_epoch(void) -{ -#ifdef _WIN32 - LARGE_INTEGER Time; - QueryPerformanceCounter(&Time); - - static LARGE_INTEGER Frequency = {0}; - if (Frequency.QuadPart == 0) { - QueryPerformanceFrequency(&Frequency); - } - - uint64_t Secs = Time.QuadPart / Frequency.QuadPart; - uint64_t Nanos = Time.QuadPart % Frequency.QuadPart * NOB_NANOS_PER_SEC / Frequency.QuadPart; - return NOB_NANOS_PER_SEC * Secs + Nanos; -#else - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - - return NOB_NANOS_PER_SEC * ts.tv_sec + ts.tv_nsec; -#endif // _WIN32 -} - -NOBDEF Nob_Proc nob_cmd_run_async_redirect(Nob_Cmd cmd, Nob_Cmd_Redirect redirect) -{ - return nob__cmd_start_process(cmd, redirect.fdin, redirect.fdout, redirect.fderr); -} - -static Nob_Proc nob__cmd_start_process(Nob_Cmd cmd, Nob_Fd *fdin, Nob_Fd *fdout, Nob_Fd *fderr) -{ - if (cmd.count < 1) { - nob_log(NOB_ERROR, "Could not run empty command"); - return NOB_INVALID_PROC; - } - -#ifndef NOB_NO_ECHO - Nob_String_Builder sb = {0}; - nob_cmd_render(cmd, &sb); - nob_sb_append_null(&sb); - nob_log(NOB_INFO, "CMD: %s", sb.items); - nob_sb_free(sb); - memset(&sb, 0, sizeof(sb)); -#endif // NOB_NO_ECHO - -#ifdef _WIN32 - // https://docs.microsoft.com/en-us/windows/win32/procthread/creating-a-child-process-with-redirected-input-and-output - - STARTUPINFO siStartInfo; - ZeroMemory(&siStartInfo, sizeof(siStartInfo)); - siStartInfo.cb = sizeof(STARTUPINFO); - // NOTE: theoretically setting NULL to std handles should not be a problem - // https://docs.microsoft.com/en-us/windows/console/getstdhandle?redirectedfrom=MSDN#attachdetach-behavior - // TODO: check for errors in GetStdHandle - siStartInfo.hStdError = fderr ? *fderr : GetStdHandle(STD_ERROR_HANDLE); - siStartInfo.hStdOutput = fdout ? *fdout : GetStdHandle(STD_OUTPUT_HANDLE); - siStartInfo.hStdInput = fdin ? *fdin : GetStdHandle(STD_INPUT_HANDLE); - siStartInfo.dwFlags |= STARTF_USESTDHANDLES; - - PROCESS_INFORMATION piProcInfo; - ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION)); - - Nob_String_Builder quoted = {0}; - nob__win32_cmd_quote(cmd, "ed); - nob_sb_append_null("ed); - BOOL bSuccess = CreateProcessA(NULL, quoted.items, NULL, NULL, TRUE, 0, NULL, NULL, &siStartInfo, &piProcInfo); - nob_sb_free(quoted); - - if (!bSuccess) { - nob_log(NOB_ERROR, "Could not create child process for %s: %s", cmd.items[0], nob_win32_error_message(GetLastError())); - return NOB_INVALID_PROC; - } - - CloseHandle(piProcInfo.hThread); - - return piProcInfo.hProcess; -#else - pid_t cpid = fork(); - if (cpid < 0) { - nob_log(NOB_ERROR, "Could not fork child process: %s", strerror(errno)); - return NOB_INVALID_PROC; - } - - if (cpid == 0) { - if (fdin) { - if (dup2(*fdin, STDIN_FILENO) < 0) { - nob_log(NOB_ERROR, "Could not setup stdin for child process: %s", strerror(errno)); - exit(1); - } - } - - if (fdout) { - if (dup2(*fdout, STDOUT_FILENO) < 0) { - nob_log(NOB_ERROR, "Could not setup stdout for child process: %s", strerror(errno)); - exit(1); - } - } - - if (fderr) { - if (dup2(*fderr, STDERR_FILENO) < 0) { - nob_log(NOB_ERROR, "Could not setup stderr for child process: %s", strerror(errno)); - exit(1); - } - } - - // NOTE: This leaks a bit of memory in the child process. - // But do we actually care? It's a one off leak anyway... - Nob_Cmd cmd_null = {0}; - nob_da_append_many(&cmd_null, cmd.items, cmd.count); - nob_cmd_append(&cmd_null, (const char*)NULL); - - if (execvp(cmd.items[0], (char * const*) cmd_null.items) < 0) { - nob_log(NOB_ERROR, "Could not exec child process for %s: %s", cmd.items[0], strerror(errno)); - exit(1); - } - NOB_UNREACHABLE("nob_cmd_run_async_redirect"); - } - - return cpid; -#endif -} - -NOBDEF Nob_Proc nob_cmd_run_async(Nob_Cmd cmd) -{ - return nob__cmd_start_process(cmd, NULL, NULL, NULL); -} - -NOBDEF Nob_Proc nob_cmd_run_async_and_reset(Nob_Cmd *cmd) -{ - Nob_Proc proc = nob__cmd_start_process(*cmd, NULL, NULL, NULL); - cmd->count = 0; - return proc; -} - -NOBDEF Nob_Proc nob_cmd_run_async_redirect_and_reset(Nob_Cmd *cmd, Nob_Cmd_Redirect redirect) -{ - Nob_Proc proc = nob__cmd_start_process(*cmd, redirect.fdin, redirect.fdout, redirect.fderr); - cmd->count = 0; - if (redirect.fdin) { - nob_fd_close(*redirect.fdin); - *redirect.fdin = NOB_INVALID_FD; - } - if (redirect.fdout) { - nob_fd_close(*redirect.fdout); - *redirect.fdout = NOB_INVALID_FD; - } - if (redirect.fderr) { - nob_fd_close(*redirect.fderr); - *redirect.fderr = NOB_INVALID_FD; - } - return proc; -} - -NOBDEF Nob_Fd nob_fd_open_for_read(const char *path) -{ -#ifndef _WIN32 - Nob_Fd result = open(path, O_RDONLY); - if (result < 0) { - nob_log(NOB_ERROR, "Could not open file %s: %s", path, strerror(errno)); - return NOB_INVALID_FD; - } - return result; -#else - // https://docs.microsoft.com/en-us/windows/win32/fileio/opening-a-file-for-reading-or-writing - SECURITY_ATTRIBUTES saAttr = {0}; - saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); - saAttr.bInheritHandle = TRUE; - - Nob_Fd result = CreateFile( - path, - GENERIC_READ, - 0, - &saAttr, - OPEN_EXISTING, - FILE_ATTRIBUTE_READONLY, - NULL); - - if (result == INVALID_HANDLE_VALUE) { - nob_log(NOB_ERROR, "Could not open file %s: %s", path, nob_win32_error_message(GetLastError())); - return NOB_INVALID_FD; - } - - return result; -#endif // _WIN32 -} - -NOBDEF Nob_Fd nob_fd_open_for_write(const char *path) -{ -#ifndef _WIN32 - Nob_Fd result = open(path, - O_WRONLY | O_CREAT | O_TRUNC, - S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); - if (result < 0) { - nob_log(NOB_ERROR, "could not open file %s: %s", path, strerror(errno)); - return NOB_INVALID_FD; - } - return result; -#else - SECURITY_ATTRIBUTES saAttr = {0}; - saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); - saAttr.bInheritHandle = TRUE; - - Nob_Fd result = CreateFile( - path, // name of the write - GENERIC_WRITE, // open for writing - 0, // do not share - &saAttr, // default security - CREATE_ALWAYS, // create always - FILE_ATTRIBUTE_NORMAL, // normal file - NULL // no attr. template - ); - - if (result == INVALID_HANDLE_VALUE) { - nob_log(NOB_ERROR, "Could not open file %s: %s", path, nob_win32_error_message(GetLastError())); - return NOB_INVALID_FD; - } - - return result; -#endif // _WIN32 -} - -NOBDEF void nob_fd_close(Nob_Fd fd) -{ -#ifdef _WIN32 - CloseHandle(fd); -#else - close(fd); -#endif // _WIN32 -} - -NOBDEF bool nob_pipe_create(Nob_Pipe *pp) -{ -#ifdef _WIN32 - // https://docs.microsoft.com/en-us/windows/win32/ProcThread/creating-a-child-process-with-redirected-input-and-output - - SECURITY_ATTRIBUTES saAttr = {0}; - saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); - saAttr.bInheritHandle = TRUE; - - if (!CreatePipe(&pp->read, &pp->write, &saAttr, 0)) { - nob_log(NOB_ERROR, "Could not create pipe: %s", nob_win32_error_message(GetLastError())); - return false; - } - - return true; -#else - int pipefd[2]; - if (pipe(pipefd) < 0) { - nob_log(NOB_ERROR, "Could not create pipe: %s\n", strerror(errno)); - return false; - } - - pp->read = pipefd[0]; - pp->write = pipefd[1]; - - return true; -#endif // _WIN32 -} - -NOBDEF bool nob_procs_wait(Nob_Procs procs) -{ - bool success = true; - for (size_t i = 0; i < procs.count; ++i) { - success = nob_proc_wait(procs.items[i]) && success; - } - return success; -} - -NOBDEF bool nob_procs_flush(Nob_Procs *procs) -{ - bool success = nob_procs_wait(*procs); - procs->count = 0; - return success; -} - -NOBDEF bool nob_procs_wait_and_reset(Nob_Procs *procs) -{ - return nob_procs_flush(procs); -} - -NOBDEF bool nob_proc_wait(Nob_Proc proc) -{ - if (proc == NOB_INVALID_PROC) return false; - -#ifdef _WIN32 - DWORD result = WaitForSingleObject( - proc, // HANDLE hHandle, - INFINITE // DWORD dwMilliseconds - ); - - if (result == WAIT_FAILED) { - nob_log(NOB_ERROR, "could not wait on child process: %s", nob_win32_error_message(GetLastError())); - return false; - } - - DWORD exit_status; - if (!GetExitCodeProcess(proc, &exit_status)) { - nob_log(NOB_ERROR, "could not get process exit code: %s", nob_win32_error_message(GetLastError())); - return false; - } - - if (exit_status != 0) { - nob_log(NOB_ERROR, "command exited with exit code %lu", exit_status); - return false; - } - - CloseHandle(proc); - - return true; -#else - for (;;) { - int wstatus = 0; - if (waitpid(proc, &wstatus, 0) < 0) { - nob_log(NOB_ERROR, "could not wait on command (pid %d): %s", proc, strerror(errno)); - return false; - } - - if (WIFEXITED(wstatus)) { - int exit_status = WEXITSTATUS(wstatus); - if (exit_status != 0) { - nob_log(NOB_ERROR, "command exited with exit code %d", exit_status); - return false; - } - - break; - } - - if (WIFSIGNALED(wstatus)) { - nob_log(NOB_ERROR, "command process was terminated by signal %d", WTERMSIG(wstatus)); - return false; - } - } - - return true; -#endif -} - -static int nob__proc_wait_async(Nob_Proc proc, int ms) -{ - if (proc == NOB_INVALID_PROC) return false; - -#ifdef _WIN32 - DWORD result = WaitForSingleObject( - proc, // HANDLE hHandle, - ms // DWORD dwMilliseconds - ); - - if (result == WAIT_TIMEOUT) { - return 0; - } - - if (result == WAIT_FAILED) { - nob_log(NOB_ERROR, "could not wait on child process: %s", nob_win32_error_message(GetLastError())); - return -1; - } - - DWORD exit_status; - if (!GetExitCodeProcess(proc, &exit_status)) { - nob_log(NOB_ERROR, "could not get process exit code: %s", nob_win32_error_message(GetLastError())); - return -1; - } - - if (exit_status != 0) { - nob_log(NOB_ERROR, "command exited with exit code %lu", exit_status); - return -1; - } - - CloseHandle(proc); - - return 1; -#else - long ns = ms*1000*1000; - struct timespec duration = { - .tv_sec = ns/(1000*1000*1000), - .tv_nsec = ns%(1000*1000*1000), - }; - - int wstatus = 0; - pid_t pid = waitpid(proc, &wstatus, WNOHANG); - if (pid < 0) { - nob_log(NOB_ERROR, "could not wait on command (pid %d): %s", proc, strerror(errno)); - return -1; - } - - if (pid == 0) { - nanosleep(&duration, NULL); - return 0; - } - - if (WIFEXITED(wstatus)) { - int exit_status = WEXITSTATUS(wstatus); - if (exit_status != 0) { - nob_log(NOB_ERROR, "command exited with exit code %d", exit_status); - return -1; - } - - return 1; - } - - if (WIFSIGNALED(wstatus)) { - nob_log(NOB_ERROR, "command process was terminated by signal %d", WTERMSIG(wstatus)); - return -1; - } - - nanosleep(&duration, NULL); - return 0; -#endif -} - -NOBDEF bool nob_procs_append_with_flush(Nob_Procs *procs, Nob_Proc proc, size_t max_procs_count) -{ - nob_da_append(procs, proc); - - if (procs->count >= max_procs_count) { - if (!nob_procs_flush(procs)) return false; - } - - return true; -} - -NOBDEF bool nob_cmd_run_sync_redirect(Nob_Cmd cmd, Nob_Cmd_Redirect redirect) -{ - Nob_Proc p = nob__cmd_start_process(cmd, redirect.fdin, redirect.fdout, redirect.fderr); - return nob_proc_wait(p); -} - -NOBDEF bool nob_cmd_run_sync(Nob_Cmd cmd) -{ - Nob_Proc p = nob__cmd_start_process(cmd, NULL, NULL, NULL); - return nob_proc_wait(p); -} - -NOBDEF bool nob_cmd_run_sync_and_reset(Nob_Cmd *cmd) -{ - Nob_Proc p = nob__cmd_start_process(*cmd, NULL, NULL, NULL); - cmd->count = 0; - return nob_proc_wait(p); -} - -NOBDEF bool nob_cmd_run_sync_redirect_and_reset(Nob_Cmd *cmd, Nob_Cmd_Redirect redirect) -{ - Nob_Proc p = nob__cmd_start_process(*cmd, redirect.fdin, redirect.fdout, redirect.fderr); - cmd->count = 0; - if (redirect.fdin) { - nob_fd_close(*redirect.fdin); - *redirect.fdin = NOB_INVALID_FD; - } - if (redirect.fdout) { - nob_fd_close(*redirect.fdout); - *redirect.fdout = NOB_INVALID_FD; - } - if (redirect.fderr) { - nob_fd_close(*redirect.fderr); - *redirect.fderr = NOB_INVALID_FD; - } - return nob_proc_wait(p); -} - -static Nob_Log_Handler *nob__log_handler = &nob_default_log_handler; - -NOBDEF void nob_set_log_handler(Nob_Log_Handler *handler) -{ - nob__log_handler = handler; -} - -NOBDEF Nob_Log_Handler *nob_get_log_handler(void) -{ - return nob__log_handler; -} - -NOBDEF void nob_default_log_handler(Nob_Log_Level level, const char *fmt, va_list args) -{ - if (level < nob_minimal_log_level) return; - - switch (level) { - case NOB_INFO: - fprintf(stderr, "[INFO] "); - break; - case NOB_WARNING: - fprintf(stderr, "[WARNING] "); - break; - case NOB_ERROR: - fprintf(stderr, "[ERROR] "); - break; - case NOB_NO_LOGS: return; - default: - NOB_UNREACHABLE("Nob_Log_Level"); - } - - vfprintf(stderr, fmt, args); - fprintf(stderr, "\n"); -} - -NOBDEF void nob_null_log_handler(Nob_Log_Level level, const char *fmt, va_list args) -{ - NOB_UNUSED(level); - NOB_UNUSED(fmt); - NOB_UNUSED(args); -} - -NOBDEF void nob_cancer_log_handler(Nob_Log_Level level, const char *fmt, va_list args) -{ - switch (level) { - case NOB_INFO: - fprintf(stderr, "ℹ️ \x1b[36m[INFO]\x1b[0m "); - break; - case NOB_WARNING: - fprintf(stderr, "⚠️ \x1b[33m[WARNING]\x1b[0m "); - break; - case NOB_ERROR: - fprintf(stderr, "🚨 \x1b[31m[ERROR]\x1b[0m "); - break; - case NOB_NO_LOGS: return; - default: - NOB_UNREACHABLE("Nob_Log_Level"); - } - - vfprintf(stderr, fmt, args); - fprintf(stderr, "\n"); -} - -NOBDEF void nob_log(Nob_Log_Level level, const char *fmt, ...) -{ - va_list args; - va_start(args, fmt); - nob__log_handler(level, fmt, args); - va_end(args); -} - -NOBDEF bool nob_dir_entry_open(const char *dir_path, Nob_Dir_Entry *dir) -{ - memset(dir, 0, sizeof(*dir)); -#ifdef _WIN32 - size_t temp_mark = nob_temp_save(); - char *buffer = nob_temp_sprintf("%s\\*", dir_path); - dir->nob__private.win32_hFind = FindFirstFile(buffer, &dir->nob__private.win32_data); - nob_temp_rewind(temp_mark); - - if (dir->nob__private.win32_hFind == INVALID_HANDLE_VALUE) { - nob_log(NOB_ERROR, "Could not open directory %s: %s", dir_path, nob_win32_error_message(GetLastError())); - dir->error = true; - return false; - } -#else - dir->nob__private.posix_dir = opendir(dir_path); - if (dir->nob__private.posix_dir == NULL) { - nob_log(NOB_ERROR, "Could not open directory %s: %s", dir_path, strerror(errno)); - dir->error = true; - return false; - } -#endif // _WIN32 - return true; -} - -NOBDEF bool nob_dir_entry_next(Nob_Dir_Entry *dir) -{ -#ifdef _WIN32 - if (!dir->nob__private.win32_init) { - dir->nob__private.win32_init = true; - dir->name = dir->nob__private.win32_data.cFileName; - return true; - } - - if (!FindNextFile(dir->nob__private.win32_hFind, &dir->nob__private.win32_data)) { - if (GetLastError() == ERROR_NO_MORE_FILES) return false; - nob_log(NOB_ERROR, "Could not read next directory entry: %s", nob_win32_error_message(GetLastError())); - dir->error = true; - return false; - } - dir->name = dir->nob__private.win32_data.cFileName; -#else - errno = 0; - dir->nob__private.posix_ent = readdir(dir->nob__private.posix_dir); - if (dir->nob__private.posix_ent == NULL) { - if (errno == 0) return false; - nob_log(NOB_ERROR, "Could not read next directory entry: %s", strerror(errno)); - dir->error = true; - return false; - } - dir->name = dir->nob__private.posix_ent->d_name; -#endif // _WIN32 - return true; -} - -NOBDEF void nob_dir_entry_close(Nob_Dir_Entry dir) -{ -#ifdef _WIN32 - FindClose(dir.nob__private.win32_hFind); -#else - if (dir.nob__private.posix_dir) closedir(dir.nob__private.posix_dir); -#endif -} - -// On the moment of entering `nob__walk_dir_opt_impl()`, the `file_path` Nob_String_Builder is expected to be NULL-terminated. -// So you can freely pass `file_path->items` to functions that expect NULL-terminated file path. -// On existing `nob__walk_dir_opt_impl()` is expected to restore the original content of `file_path` -bool nob__walk_dir_opt_impl(Nob_String_Builder *file_path, Nob_Walk_Func func, size_t level, bool *stop, Nob_Walk_Dir_Opt opt) -{ - NOB_ASSERT(file_path->count > 0 && "file_path was probably not properly NULL-terminated"); - bool result = true; - - Nob_Dir_Entry dir = {0}; - size_t saved_file_path_count = file_path->count; - Nob_Walk_Action action = NOB_WALK_CONT; - - Nob_File_Type file_type = nob_get_file_type(file_path->items); - if (file_type < 0) nob_return_defer(false); - - // Pre-order walking - if (!opt.post_order) { - if (!func(NOB_CLIT(Nob_Walk_Entry) { - .path = file_path->items, - .type = file_type, - .level = level, - .data = opt.data, - .action = &action, - })) nob_return_defer(false); - switch (action) { - case NOB_WALK_CONT: break; - case NOB_WALK_STOP: *stop = true; // fallthrough - case NOB_WALK_SKIP: nob_return_defer(true); - default: NOB_UNREACHABLE("Nob_Walk_Action"); - } - } - - if (file_type == NOB_FILE_DIRECTORY) { - if (!nob_dir_entry_open(file_path->items, &dir)) nob_return_defer(false); - for (;;) { - // Next entry - if (!nob_dir_entry_next(&dir)) { - if (!dir.error) break; - nob_return_defer(false); - } - - // Ignore . and .. - if (strcmp(dir.name, ".") == 0) continue; - if (strcmp(dir.name, "..") == 0) continue; - - // Prepare the new file_path - file_path->count = saved_file_path_count - 1; -#ifdef _WIN32 - nob_sb_appendf(file_path, "\\%s", dir.name); -#else - nob_sb_appendf(file_path, "/%s", dir.name); -#endif // _WIN32 - nob_sb_append_null(file_path); - - // Recurse - if (!nob__walk_dir_opt_impl(file_path, func, level+1, stop, opt)) nob_return_defer(false); - if (*stop) nob_return_defer(true); - } - file_path->count = saved_file_path_count; - nob_da_last(file_path) = '\0'; - } - - // Post-order walking - if (opt.post_order) { - if (!func(NOB_CLIT(Nob_Walk_Entry) { - .path = file_path->items, - .type = file_type, - .level = level, - .data = opt.data, - .action = &action, - })) nob_return_defer(false); - switch (action) { - case NOB_WALK_CONT: break; - case NOB_WALK_STOP: *stop = true; // fallthrough - case NOB_WALK_SKIP: nob_return_defer(true); - default: NOB_UNREACHABLE("Nob_Walk_Action"); - } - } - -defer: - // Always reset the file_path back to what it was - file_path->count = saved_file_path_count; - nob_da_last(file_path) = '\0'; - - nob_dir_entry_close(dir); - return result; -} - -NOBDEF bool nob_walk_dir_opt(const char *root, Nob_Walk_Func func, Nob_Walk_Dir_Opt opt) -{ - Nob_String_Builder file_path = {0}; - - nob_sb_appendf(&file_path, "%s", root); - nob_sb_append_null(&file_path); - - bool stop = false; - bool ok = nob__walk_dir_opt_impl(&file_path, func, 0, &stop, opt); - free(file_path.items); - return ok; -} - -NOBDEF bool nob_read_entire_dir(const char *parent, Nob_File_Paths *children) -{ - if (strlen(parent) == 0) { - nob_log(NOB_ERROR, "Cannot read empty path"); - return false; - } - bool result = true; - Nob_Dir_Entry dir = {0}; - if (!nob_dir_entry_open(parent, &dir)) nob_return_defer(false); - while (nob_dir_entry_next(&dir)) nob_da_append(children, nob_temp_strdup(dir.name)); - if (dir.error) nob_return_defer(false); -defer: - nob_dir_entry_close(dir); - return result; -} - -NOBDEF bool nob_write_entire_file(const char *path, const void *data, size_t size) -{ - bool result = true; - - const char *buf = NULL; - FILE *f = fopen(path, "wb"); - if (f == NULL) { - nob_log(NOB_ERROR, "Could not open file %s for writing: %s\n", path, strerror(errno)); - nob_return_defer(false); - } - - // len - // v - // aaaaaaaaaa - // ^ - // data - - buf = (const char*)data; - while (size > 0) { - size_t n = fwrite(buf, 1, size, f); - if (ferror(f)) { - nob_log(NOB_ERROR, "Could not write into file %s: %s\n", path, strerror(errno)); - nob_return_defer(false); - } - size -= n; - buf += n; - } - -defer: - if (f) fclose(f); - return result; -} - -NOBDEF Nob_File_Type nob_get_file_type(const char *path) -{ -#ifdef _WIN32 - DWORD attr = GetFileAttributesA(path); - if (attr == INVALID_FILE_ATTRIBUTES) { - nob_log(NOB_ERROR, "Could not get file attributes of %s: %s", path, nob_win32_error_message(GetLastError())); - return (Nob_File_Type)-1; - } - - if (attr & FILE_ATTRIBUTE_DIRECTORY) return NOB_FILE_DIRECTORY; - // TODO: detect symlinks on Windows (whatever that means on Windows anyway) - return NOB_FILE_REGULAR; -#else // _WIN32 - struct stat statbuf; - if (lstat(path, &statbuf) < 0) { - nob_log(NOB_ERROR, "Could not get stat of %s: %s", path, strerror(errno)); - return (Nob_File_Type)(-1); - } - - if (S_ISREG(statbuf.st_mode)) return NOB_FILE_REGULAR; - if (S_ISDIR(statbuf.st_mode)) return NOB_FILE_DIRECTORY; - if (S_ISLNK(statbuf.st_mode)) return NOB_FILE_SYMLINK; - return NOB_FILE_OTHER; -#endif // _WIN32 -} - -NOBDEF bool nob_delete_file(const char *path) -{ -#ifndef NOB_NO_ECHO - nob_log(NOB_INFO, "deleting %s", path); -#endif // NOB_NO_ECHO -#ifdef _WIN32 - Nob_File_Type type = nob_get_file_type(path); - switch (type) { - case NOB_FILE_DIRECTORY: - if (!RemoveDirectoryA(path)) { - nob_log(NOB_ERROR, "Could not delete directory %s: %s", path, nob_win32_error_message(GetLastError())); - return false; - } - break; - case NOB_FILE_REGULAR: - case NOB_FILE_SYMLINK: - case NOB_FILE_OTHER: - if (!DeleteFileA(path)) { - nob_log(NOB_ERROR, "Could not delete file %s: %s", path, nob_win32_error_message(GetLastError())); - return false; - } - break; - default: NOB_UNREACHABLE("Nob_File_Type"); - } - return true; -#else - if (remove(path) < 0) { - nob_log(NOB_ERROR, "Could not delete file %s: %s", path, strerror(errno)); - return false; - } - return true; -#endif // _WIN32 -} - -NOBDEF bool nob_copy_directory_recursively(const char *src_path, const char *dst_path) -{ - bool result = true; - Nob_File_Paths children = {0}; - Nob_String_Builder src_sb = {0}; - Nob_String_Builder dst_sb = {0}; - size_t temp_checkpoint = nob_temp_save(); - - Nob_File_Type type = nob_get_file_type(src_path); - if (type < 0) return false; - - switch (type) { - case NOB_FILE_DIRECTORY: { - if (!nob_mkdir_if_not_exists(dst_path)) nob_return_defer(false); - if (!nob_read_entire_dir(src_path, &children)) nob_return_defer(false); - - for (size_t i = 0; i < children.count; ++i) { - if (strcmp(children.items[i], ".") == 0) continue; - if (strcmp(children.items[i], "..") == 0) continue; - - src_sb.count = 0; - nob_sb_append_cstr(&src_sb, src_path); - nob_sb_append_cstr(&src_sb, "/"); - nob_sb_append_cstr(&src_sb, children.items[i]); - nob_sb_append_null(&src_sb); - - dst_sb.count = 0; - nob_sb_append_cstr(&dst_sb, dst_path); - nob_sb_append_cstr(&dst_sb, "/"); - nob_sb_append_cstr(&dst_sb, children.items[i]); - nob_sb_append_null(&dst_sb); - - if (!nob_copy_directory_recursively(src_sb.items, dst_sb.items)) { - nob_return_defer(false); - } - } - } break; - - case NOB_FILE_REGULAR: { - if (!nob_copy_file(src_path, dst_path)) { - nob_return_defer(false); - } - } break; - - case NOB_FILE_SYMLINK: { - nob_log(NOB_WARNING, "TODO: Copying symlinks is not supported yet"); - } break; - - case NOB_FILE_OTHER: { - nob_log(NOB_ERROR, "Unsupported type of file %s", src_path); - nob_return_defer(false); - } break; - - default: NOB_UNREACHABLE("nob_copy_directory_recursively"); - } - -defer: - nob_temp_rewind(temp_checkpoint); - nob_da_free(src_sb); - nob_da_free(dst_sb); - nob_da_free(children); - return result; -} - -NOBDEF char *nob_temp_strdup(const char *cstr) -{ - size_t n = strlen(cstr); - char *result = (char*)nob_temp_alloc(n + 1); - NOB_ASSERT(result != NULL && "Increase NOB_TEMP_CAPACITY"); - memcpy(result, cstr, n); - result[n] = '\0'; - return result; -} - -NOBDEF char *nob_temp_strndup(const char *s, size_t n) -{ - char *r = (char*)nob_temp_alloc(n + 1); - NOB_ASSERT(r != NULL && "Extend the size of the temporary allocator"); - memcpy(r, s, n); - r[n] = '\0'; - return r; -} - -NOBDEF void *nob_temp_alloc(size_t requested_size) -{ - size_t word_size = sizeof(uintptr_t); - size_t size = (requested_size + word_size - 1)/word_size*word_size; - if (nob_temp_size + size > NOB_TEMP_CAPACITY) return NULL; - void *result = &nob_temp[nob_temp_size]; - nob_temp_size += size; - return result; -} - -NOBDEF char *nob_temp_vsprintf(const char *format, va_list ap) -{ - va_list args; - va_copy(args, ap); - int n = vsnprintf(NULL, 0, format, args); - va_end(args); - - NOB_ASSERT(n >= 0); - char *result = (char*)nob_temp_alloc(n + 1); - NOB_ASSERT(result != NULL && "Extend the size of the temporary allocator"); - // TODO: use proper arenas for the temporary allocator; - va_copy(args, ap); - vsnprintf(result, n + 1, format, args); - va_end(args); - - return result; -} - -NOBDEF char *nob_temp_sprintf(const char *format, ...) -{ - va_list args; - va_start(args, format); - char *result = nob_temp_vsprintf(format, args); - va_end(args); - return result; -} - -NOBDEF void nob_temp_reset(void) -{ - nob_temp_size = 0; -} - -NOBDEF size_t nob_temp_save(void) -{ - return nob_temp_size; -} - -NOBDEF void nob_temp_rewind(size_t checkpoint) -{ - nob_temp_size = checkpoint; -} - -NOBDEF const char *nob_temp_sv_to_cstr(Nob_String_View sv) -{ - return nob_temp_strndup(sv.data, sv.count); -} - -NOBDEF int nob_needs_rebuild(const char *output_path, const char **input_paths, size_t input_paths_count) -{ -#ifdef _WIN32 - BOOL bSuccess; - - HANDLE output_path_fd = CreateFile(output_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); - if (output_path_fd == INVALID_HANDLE_VALUE) { - // NOTE: if output does not exist it 100% must be rebuilt - if (GetLastError() == ERROR_FILE_NOT_FOUND) return 1; - nob_log(NOB_ERROR, "Could not open file %s: %s", output_path, nob_win32_error_message(GetLastError())); - return -1; - } - FILETIME output_path_time; - bSuccess = GetFileTime(output_path_fd, NULL, NULL, &output_path_time); - CloseHandle(output_path_fd); - if (!bSuccess) { - nob_log(NOB_ERROR, "Could not get time of %s: %s", output_path, nob_win32_error_message(GetLastError())); - return -1; - } - - for (size_t i = 0; i < input_paths_count; ++i) { - const char *input_path = input_paths[i]; - HANDLE input_path_fd = CreateFile(input_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL); - if (input_path_fd == INVALID_HANDLE_VALUE) { - // NOTE: non-existing input is an error cause it is needed for building in the first place - nob_log(NOB_ERROR, "Could not open file %s: %s", input_path, nob_win32_error_message(GetLastError())); - return -1; - } - FILETIME input_path_time; - bSuccess = GetFileTime(input_path_fd, NULL, NULL, &input_path_time); - CloseHandle(input_path_fd); - if (!bSuccess) { - nob_log(NOB_ERROR, "Could not get time of %s: %s", input_path, nob_win32_error_message(GetLastError())); - return -1; - } - - // NOTE: if even a single input_path is fresher than output_path that's 100% rebuild - if (CompareFileTime(&input_path_time, &output_path_time) == 1) return 1; - } - - return 0; -#else - struct stat statbuf = {0}; - - if (stat(output_path, &statbuf) < 0) { - // NOTE: if output does not exist it 100% must be rebuilt - if (errno == ENOENT) return 1; - nob_log(NOB_ERROR, "could not stat %s: %s", output_path, strerror(errno)); - return -1; - } - time_t output_path_time = statbuf.st_mtime; - - for (size_t i = 0; i < input_paths_count; ++i) { - const char *input_path = input_paths[i]; - if (stat(input_path, &statbuf) < 0) { - // NOTE: non-existing input is an error cause it is needed for building in the first place - nob_log(NOB_ERROR, "could not stat %s: %s", input_path, strerror(errno)); - return -1; - } - time_t input_path_time = statbuf.st_mtime; - // NOTE: if even a single input_path is fresher than output_path that's 100% rebuild - if (input_path_time > output_path_time) return 1; - } - - return 0; -#endif -} - -NOBDEF int nob_needs_rebuild1(const char *output_path, const char *input_path) -{ - return nob_needs_rebuild(output_path, &input_path, 1); -} - -NOBDEF const char *nob_path_name(const char *path) -{ -#ifdef _WIN32 - const char *p1 = strrchr(path, '/'); - const char *p2 = strrchr(path, '\\'); - const char *p = (p1 > p2)? p1 : p2; // NULL is ignored if the other search is successful - return p ? p + 1 : path; -#else - const char *p = strrchr(path, '/'); - return p ? p + 1 : path; -#endif // _WIN32 -} - -NOBDEF bool nob_rename(const char *old_path, const char *new_path) -{ -#ifndef NOB_NO_ECHO - nob_log(NOB_INFO, "renaming %s -> %s", old_path, new_path); -#endif // NOB_NO_ECHO -#ifdef _WIN32 - if (!MoveFileEx(old_path, new_path, MOVEFILE_REPLACE_EXISTING)) { - nob_log(NOB_ERROR, "could not rename %s to %s: %s", old_path, new_path, nob_win32_error_message(GetLastError())); - return false; - } -#else - if (rename(old_path, new_path) < 0) { - nob_log(NOB_ERROR, "could not rename %s to %s: %s", old_path, new_path, strerror(errno)); - return false; - } -#endif // _WIN32 - return true; -} - -NOBDEF bool nob_read_entire_file(const char *path, Nob_String_Builder *sb) -{ - bool result = true; - - FILE *f = fopen(path, "rb"); - size_t new_count = 0; - long long m = 0; - if (f == NULL) nob_return_defer(false); - if (fseek(f, 0, SEEK_END) < 0) nob_return_defer(false); -#ifndef _WIN32 - m = ftell(f); -#else - m = _telli64(_fileno(f)); -#endif - if (m < 0) nob_return_defer(false); - if (fseek(f, 0, SEEK_SET) < 0) nob_return_defer(false); - - new_count = sb->count + m; - if (new_count > sb->capacity) { - sb->items = NOB_DECLTYPE_CAST(sb->items)NOB_REALLOC(sb->items, new_count); - NOB_ASSERT(sb->items != NULL && "Buy more RAM lool!!"); - sb->capacity = new_count; - } - - fread(sb->items + sb->count, m, 1, f); - if (ferror(f)) { - // TODO: Afaik, ferror does not set errno. So the error reporting in defer is not correct in this case. - nob_return_defer(false); - } - sb->count = new_count; - -defer: - if (!result) nob_log(NOB_ERROR, "Could not read file %s: %s", path, strerror(errno)); - if (f) fclose(f); - return result; -} - -NOBDEF int nob_sb_appendf(Nob_String_Builder *sb, const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - int n = vsnprintf(NULL, 0, fmt, args); - va_end(args); - - // NOTE: the new_capacity needs to be +1 because of the null terminator. - // However, further below we increase sb->count by n, not n + 1. - // This is because we don't want the sb to include the null terminator. The user can always sb_append_null() if they want it - nob_da_reserve(sb, sb->count + n + 1); - char *dest = sb->items + sb->count; - va_start(args, fmt); - vsnprintf(dest, n+1, fmt, args); - va_end(args); - - sb->count += n; - - return n; -} - -NOBDEF void nob_sb_pad_align(Nob_String_Builder *sb, size_t size) -{ - size_t rem = sb->count%size; - if (rem == 0) return; - for (size_t i = 0; i < size - rem; ++i) { - nob_da_append(sb, 0); - } -} - -NOBDEF Nob_String_View nob_sv_chop_while(Nob_String_View *sv, int (*p)(int x)) -{ - size_t i = 0; - while (i < sv->count && p(sv->data[i])) { - i += 1; - } - - Nob_String_View result = nob_sv_from_parts(sv->data, i); - sv->count -= i; - sv->data += i; - - return result; -} - -NOBDEF Nob_String_View nob_sv_chop_by_delim(Nob_String_View *sv, char delim) -{ - size_t i = 0; - while (i < sv->count && sv->data[i] != delim) { - i += 1; - } - - Nob_String_View result = nob_sv_from_parts(sv->data, i); - - if (i < sv->count) { - sv->count -= i + 1; - sv->data += i + 1; - } else { - sv->count -= i; - sv->data += i; - } - - return result; -} - -NOBDEF bool nob_sv_chop_prefix(Nob_String_View *sv, Nob_String_View prefix) -{ - if (nob_sv_starts_with(*sv, prefix)) { - nob_sv_chop_left(sv, prefix.count); - return true; - } - return false; -} - -NOBDEF bool nob_sv_chop_suffix(Nob_String_View *sv, Nob_String_View suffix) -{ - if (nob_sv_ends_with(*sv, suffix)) { - nob_sv_chop_right(sv, suffix.count); - return true; - } - return false; -} - -NOBDEF Nob_String_View nob_sv_chop_left(Nob_String_View *sv, size_t n) -{ - if (n > sv->count) { - n = sv->count; - } - - Nob_String_View result = nob_sv_from_parts(sv->data, n); - - sv->data += n; - sv->count -= n; - - return result; -} - -NOBDEF Nob_String_View nob_sv_chop_right(Nob_String_View *sv, size_t n) -{ - if (n > sv->count) { - n = sv->count; - } - - Nob_String_View result = nob_sv_from_parts(sv->data + sv->count - n, n); - - sv->count -= n; - - return result; -} - -NOBDEF Nob_String_View nob_sv_from_parts(const char *data, size_t count) -{ - Nob_String_View sv; - sv.count = count; - sv.data = data; - return sv; -} - -NOBDEF Nob_String_View nob_sv_trim_left(Nob_String_View sv) -{ - size_t i = 0; - while (i < sv.count && isspace(sv.data[i])) { - i += 1; - } - - return nob_sv_from_parts(sv.data + i, sv.count - i); -} - -NOBDEF Nob_String_View nob_sv_trim_right(Nob_String_View sv) -{ - size_t i = 0; - while (i < sv.count && isspace(sv.data[sv.count - 1 - i])) { - i += 1; - } - - return nob_sv_from_parts(sv.data, sv.count - i); -} - -NOBDEF Nob_String_View nob_sv_trim(Nob_String_View sv) -{ - return nob_sv_trim_right(nob_sv_trim_left(sv)); -} - -NOBDEF Nob_String_View nob_sv_from_cstr(const char *cstr) -{ - return nob_sv_from_parts(cstr, strlen(cstr)); -} - -NOBDEF bool nob_sv_eq(Nob_String_View a, Nob_String_View b) -{ - if (a.count != b.count) { - return false; - } else { - return memcmp(a.data, b.data, a.count) == 0; - } -} - -NOBDEF bool nob_sv_end_with(Nob_String_View sv, const char *cstr) -{ - return nob_sv_ends_with_cstr(sv, cstr); -} - -NOBDEF bool nob_sv_ends_with_cstr(Nob_String_View sv, const char *cstr) -{ - return nob_sv_ends_with(sv, nob_sv_from_cstr(cstr)); -} - -NOBDEF bool nob_sv_ends_with(Nob_String_View sv, Nob_String_View suffix) -{ - if (sv.count >= suffix.count) { - Nob_String_View sv_tail = { - .count = suffix.count, - .data = sv.data + sv.count - suffix.count, - }; - return nob_sv_eq(sv_tail, suffix); - } - return false; -} - -NOBDEF bool nob_sv_starts_with(Nob_String_View sv, Nob_String_View expected_prefix) -{ - if (expected_prefix.count <= sv.count) { - Nob_String_View actual_prefix = nob_sv_from_parts(sv.data, expected_prefix.count); - return nob_sv_eq(expected_prefix, actual_prefix); - } - - return false; -} - -// RETURNS: -// 0 - file does not exists -// 1 - file exists -NOBDEF int nob_file_exists(const char *file_path) -{ -#if _WIN32 - return GetFileAttributesA(file_path) != INVALID_FILE_ATTRIBUTES; -#else - return access(file_path, F_OK) == 0; -#endif -} - -NOBDEF const char *nob_get_current_dir_temp(void) -{ -#ifdef _WIN32 - DWORD nBufferLength = GetCurrentDirectory(0, NULL); - if (nBufferLength == 0) { - nob_log(NOB_ERROR, "could not get current directory: %s", nob_win32_error_message(GetLastError())); - return NULL; - } - - char *buffer = (char*) nob_temp_alloc(nBufferLength); - if (GetCurrentDirectory(nBufferLength, buffer) == 0) { - nob_log(NOB_ERROR, "could not get current directory: %s", nob_win32_error_message(GetLastError())); - return NULL; - } - - return buffer; -#else - char *buffer = (char*) nob_temp_alloc(PATH_MAX); - if (getcwd(buffer, PATH_MAX) == NULL) { - nob_log(NOB_ERROR, "could not get current directory: %s", strerror(errno)); - return NULL; - } - - return buffer; -#endif // _WIN32 -} - -NOBDEF bool nob_set_current_dir(const char *path) -{ -#ifdef _WIN32 - if (!SetCurrentDirectory(path)) { - nob_log(NOB_ERROR, "could not set current directory to %s: %s", path, nob_win32_error_message(GetLastError())); - return false; - } - return true; -#else - if (chdir(path) < 0) { - nob_log(NOB_ERROR, "could not set current directory to %s: %s", path, strerror(errno)); - return false; - } - return true; -#endif // _WIN32 -} - -NOBDEF char *nob_temp_dir_name(const char *path) -{ -#ifndef _WIN32 - // Stolen from the musl's implementation of dirname. - // We are implementing our own one because libc vendors cannot agree on whether dirname(3) - // modifies the path or not. - if (!path || !*path) return nob_temp_strdup("."); - size_t i = strlen(path) - 1; - for (; path[i] == '/'; i--) if (!i) return nob_temp_strdup("/"); - for (; path[i] != '/'; i--) if (!i) return nob_temp_strdup("."); - for (; path[i] == '/'; i--) if (!i) return nob_temp_strdup("/"); - return nob_temp_strndup(path, i + 1); -#else - if (!path) path = ""; // Treating NULL as empty. - char *drive = (char*) nob_temp_alloc(_MAX_DRIVE); - char *dir = (char*) nob_temp_alloc(_MAX_DIR); - // https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/8e46eyt7(v=vs.100) - errno_t ret = _splitpath_s(path, drive, _MAX_DRIVE, dir, _MAX_DIR, NULL, 0, NULL, 0); - NOB_ASSERT(ret == 0); - return nob_temp_sprintf("%s%s", drive, dir); -#endif // _WIN32 -} - -NOBDEF char *nob_temp_file_name(const char *path) -{ -#ifndef _WIN32 - // Stolen from the musl's implementation of dirname. - // We are implementing our own one because libc vendors cannot agree on whether basename(3) - // modifies the path or not. - if (!path || !*path) return nob_temp_strdup("."); - char *s = nob_temp_strdup(path); - size_t i = strlen(s)-1; - for (; i&&s[i]=='/'; i--) s[i] = 0; - for (; i&&s[i-1]!='/'; i--); - return s+i; -#else - if (!path) path = ""; // Treating NULL as empty. - char *fname = (char*)nob_temp_alloc(_MAX_FNAME); - char *ext = (char*)nob_temp_alloc(_MAX_EXT); - // https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/8e46eyt7(v=vs.100) - errno_t ret = _splitpath_s(path, NULL, 0, NULL, 0, fname, _MAX_FNAME, ext, _MAX_EXT); - NOB_ASSERT(ret == 0); - return nob_temp_sprintf("%s%s", fname, ext); -#endif // _WIN32 -} - -NOBDEF char *nob_temp_file_ext(const char *path) -{ -#ifndef _WIN32 - return strrchr(nob_temp_file_name(path), '.'); -#else - if (!path) path = ""; // Treating NULL as empty. - char *ext = (char*)nob_temp_alloc(_MAX_EXT); - // https://learn.microsoft.com/en-us/previous-versions/visualstudio/visual-studio-2010/8e46eyt7(v=vs.100) - errno_t ret = _splitpath_s(path, NULL, 0, NULL, 0, NULL, 0, ext, _MAX_EXT); - NOB_ASSERT(ret == 0); - return ext; -#endif // _WIN32 -} - -NOBDEF char *nob_temp_running_executable_path(void) -{ -#if defined(__linux__) - char buf[4096]; - int length = readlink("/proc/self/exe", buf, NOB_ARRAY_LEN(buf)); - if (length < 0) return nob_temp_strdup(""); - return nob_temp_strndup(buf, length); -#elif defined(_WIN32) - char buf[MAX_PATH]; - int length = GetModuleFileNameA(NULL, buf, MAX_PATH); - return nob_temp_strndup(buf, length); -#elif defined(__APPLE__) - char buf[4096]; - uint32_t size = NOB_ARRAY_LEN(buf); - if (_NSGetExecutablePath(buf, &size) != 0) return nob_temp_strdup(""); - int length = strlen(buf); - return nob_temp_strndup(buf, length); -#elif defined(__FreeBSD__) - char buf[4096]; - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; - size_t length = sizeof(buf); - if (sysctl(mib, 4, buf, &length, NULL, 0) < 0) return nob_temp_strdup(""); - return nob_temp_strndup(buf, length); -#elif defined(__HAIKU__) - int cookie = 0; - image_info info; - while (get_next_image_info(B_CURRENT_TEAM, &cookie, &info) == B_OK) - if (info.type == B_APP_IMAGE) - break; - return nob_temp_strndup(info.name, strlen(info.name)); -#else - fprintf(stderr, "%s:%d: TODO: nob_temp_running_executable_path is not implemented for this platform\n", __FILE__, __LINE__); - return nob_temp_strdup(""); -#endif -} - -#endif // NOB_IMPLEMENTATION - -#ifndef NOB_STRIP_PREFIX_GUARD_ -#define NOB_STRIP_PREFIX_GUARD_ - // NOTE: The name stripping should be part of the header so it's not accidentally included - // several times. At the same time, it should be at the end of the file so to not create any - // potential conflicts in the NOB_IMPLEMENTATION. The header obviously cannot be at the end - // of the file because NOB_IMPLEMENTATION needs the forward declarations from there. So the - // solution is to split the header into two parts where the name stripping part is at the - // end of the file after the NOB_IMPLEMENTATION. - #ifndef NOB_UNSTRIP_PREFIX - #define TODO NOB_TODO - #define UNREACHABLE NOB_UNREACHABLE - #define UNUSED NOB_UNUSED - #define ARRAY_LEN NOB_ARRAY_LEN - #define ARRAY_GET NOB_ARRAY_GET - #define INFO NOB_INFO - #define WARNING NOB_WARNING - #define ERROR NOB_ERROR - #define NO_LOGS NOB_NO_LOGS - #define Log_Level Nob_Log_Level - #define minimal_log_level nob_minimal_log_level - #define log_handler nob_log_handler - #define Log_Handler Nob_Log_Handler - #define set_log_handler nob_set_log_handler - #define get_log_handler nob_get_log_handler - #define null_log_handler nob_null_log_handler - #define default_log_handler nob_default_log_handler - #define cancer_log_handler nob_cancer_log_handler - // NOTE: Name log is already defined in math.h and historically always was the natural logarithmic function. - // So there should be no reason to strip the `nob_` prefix in this specific case. - // #define log nob_log - #define shift nob_shift - #define shift_args nob_shift_args - #define GO_REBUILD_URSELF NOB_GO_REBUILD_URSELF - #define GO_REBUILD_URSELF_PLUS NOB_GO_REBUILD_URSELF_PLUS - #define File_Paths Nob_File_Paths - #define FILE_REGULAR NOB_FILE_REGULAR - #define FILE_DIRECTORY NOB_FILE_DIRECTORY - #define FILE_SYMLINK NOB_FILE_SYMLINK - #define FILE_OTHER NOB_FILE_OTHER - #define File_Type Nob_File_Type - #define mkdir_if_not_exists nob_mkdir_if_not_exists - #define copy_file nob_copy_file - #define copy_directory_recursively nob_copy_directory_recursively - #define read_entire_dir nob_read_entire_dir - #define WALK_CONT NOB_WALK_CONT - #define WALK_SKIP NOB_WALK_SKIP - #define WALK_STOP NOB_WALK_STOP - #define Walk_Action Nob_Walk_Action - #define Walk_Entry Nob_Walk_Entry - #define Walk_Func Nob_Walk_Func - #define Walk_Dir_Opt Nob_Walk_Dir_Opt - #define walk_dir nob_walk_dir - #define walk_dir_opt nob_walk_dir_opt - #define write_entire_file nob_write_entire_file - #define get_file_type nob_get_file_type - #define delete_file nob_delete_file - #define Dir_Entry Nob_Dir_Entry - #define dir_entry_open nob_dir_entry_open - #define dir_entry_next nob_dir_entry_next - #define dir_entry_close nob_dir_entry_close - #define return_defer nob_return_defer - #define da_append nob_da_append - #define da_free nob_da_free - #define da_append_many nob_da_append_many - #define da_resize nob_da_resize - #define da_reserve nob_da_reserve - #define da_last nob_da_last - #define da_first nob_da_first - #define da_pop nob_da_pop - #define da_remove_unordered nob_da_remove_unordered - #define da_foreach nob_da_foreach - #define fa_append nob_fa_append - #define swap nob_swap - #define String_Builder Nob_String_Builder - #define read_entire_file nob_read_entire_file - #define sb_appendf nob_sb_appendf - #define sb_append_buf nob_sb_append_buf - #define sb_append_sv nob_sb_append_sv - #define sb_append_cstr nob_sb_append_cstr - #define sb_append_null nob_sb_append_null - #define sb_append nob_sb_append - #define sb_pad_align nob_sb_pad_align - #define sb_free nob_sb_free - #define Proc Nob_Proc - #define INVALID_PROC NOB_INVALID_PROC - #define Fd Nob_Fd - #define Pipe Nob_Pipe - #define pipe_create nob_pipe_create - #define Chain Nob_Chain - #define Chain_Begin_Opt Nob_Chain_Begin_Opt - #define chain_begin nob_chain_begin - #define chain_begin_opt nob_chain_begin_opt - #define Chain_Cmd_Opt Nob_Chain_Cmd_Opt - #define chain_cmd nob_chain_cmd - #define chain_cmd_opt nob_chain_cmd_opt - #define Chain_End_Opt Nob_Chain_End_Opt - #define chain_end nob_chain_end - #define chain_end_opt nob_chain_end_opt - #define INVALID_FD NOB_INVALID_FD - #define fd_open_for_read nob_fd_open_for_read - #define fd_open_for_write nob_fd_open_for_write - #define fd_close nob_fd_close - #define Procs Nob_Procs - #define proc_wait nob_proc_wait - #define procs_wait nob_procs_wait - #define procs_wait_and_reset nob_procs_wait_and_reset - #define procs_append_with_flush nob_procs_append_with_flush - #define procs_flush nob_procs_flush - #define CLIT NOB_CLIT - #define Cmd Nob_Cmd - #define Cmd_Redirect Nob_Cmd_Redirect - #define Cmd_Opt Nob_Cmd_Opt - #define cmd_run_opt nob_cmd_run_opt - #define cmd_run nob_cmd_run - #define cmd_render nob_cmd_render - #define cmd_append nob_cmd_append - #define cmd_extend nob_cmd_extend - #define cmd_free nob_cmd_free - #define cmd_run_async nob_cmd_run_async - #define cmd_run_async_and_reset nob_cmd_run_async_and_reset - #define cmd_run_async_redirect nob_cmd_run_async_redirect - #define cmd_run_async_redirect_and_reset nob_cmd_run_async_redirect_and_reset - #define cmd_run_sync nob_cmd_run_sync - #define cmd_run_sync_and_reset nob_cmd_run_sync_and_reset - #define cmd_run_sync_redirect nob_cmd_run_sync_redirect - #define cmd_run_sync_redirect_and_reset nob_cmd_run_sync_redirect_and_reset - #define temp_strdup nob_temp_strdup - #define temp_strndup nob_temp_strndup - #define temp_alloc nob_temp_alloc - #define temp_sprintf nob_temp_sprintf - #define temp_vsprintf nob_temp_vsprintf - #define temp_reset nob_temp_reset - #define temp_save nob_temp_save - #define temp_rewind nob_temp_rewind - #define path_name nob_path_name - // NOTE: rename(2) is widely known POSIX function. We never wanna collide with it. - // #define rename nob_rename - #define needs_rebuild nob_needs_rebuild - #define needs_rebuild1 nob_needs_rebuild1 - #define file_exists nob_file_exists - #define get_current_dir_temp nob_get_current_dir_temp - #define set_current_dir nob_set_current_dir - #define temp_dir_name nob_temp_dir_name - #define temp_file_name nob_temp_file_name - #define temp_file_ext nob_temp_file_ext - #define temp_running_executable_path nob_temp_running_executable_path - #define String_View Nob_String_View - #define temp_sv_to_cstr nob_temp_sv_to_cstr - #define sv_chop_by_delim nob_sv_chop_by_delim - #define sv_chop_while nob_sv_chop_while - #define sv_chop_prefix nob_sv_chop_prefix - #define sv_chop_suffix nob_sv_chop_suffix - #define sv_chop_left nob_sv_chop_left - #define sv_chop_right nob_sv_chop_right - #define sv_trim nob_sv_trim - #define sv_trim_left nob_sv_trim_left - #define sv_trim_right nob_sv_trim_right - #define sv_eq nob_sv_eq - #define sv_starts_with nob_sv_starts_with - #define sv_end_with nob_sv_end_with - #define sv_ends_with nob_sv_ends_with - #define sv_ends_with_cstr nob_sv_ends_with_cstr - #define sv_from_cstr nob_sv_from_cstr - #define sv_from_parts nob_sv_from_parts - #define sb_to_sv nob_sb_to_sv - #define win32_error_message nob_win32_error_message - #define nprocs nob_nprocs - #define nanos_since_unspecified_epoch nob_nanos_since_unspecified_epoch - #define NANOS_PER_SEC NOB_NANOS_PER_SEC - #endif // NOB_STRIP_PREFIX -#endif // NOB_STRIP_PREFIX_GUARD_ - -/* - Revision history: - - 3.8.2 (2026-04-01) Fix the broken type safety of nob_cmd_append() (by @aalmkainzi) - 3.8.1 (2026-04-01) Fix annoying clang warning - 3.8.0 (2026-03-24) Add NOB_CLIT() - Fix compliation on MSVC with /TP - 3.7.0 (2026-03-20) Add nob_sb_append_sv() - 3.6.0 (2026-03-16) Add nob_sv_chop_suffix() - Deprecate nob_sv_end_with() - Add nob_sv_ends_with_cstr() instead of nob_sv_end_with() - Add nob_sv_ends_with() - Add nob_sv_chop_right() - 3.5.0 (2026-03-13) Add nob_null_log_handler() (by @rexim) - Rename nob_log_handler to Nob_Log_Handler (by @rexim) - 3.4.0 (2026-03-12) Add nob_da_first() (by @rexim) - Add nob_da_pop() (by @rexim) - Add nob_sv_chop_while() (by @rexim) - 3.3.0 (2026-03-07) Add nob_sv_chop_prefix() (by @rexim) - 3.2.2 (2026-02-06) Fix read_entire_dir crash on empty path (by @ysoftware) - 3.2.1 (2026-01-29) Fix the implicit declaration error when nob is included as a header (by @ysoftware) - 3.2.0 (2026-01-28) Introduce Chain API - - Nob_Chain - - Nob_Chain_Begin_Opt - - nob_chain_begin() - - nob_chain_begin_opt() - - Nob_Chain_Cmd_Opt - - nob_chain_cmd() - - nob_chain_cmd_opt() - - Nob_Chain_End_Opt - - nob_chain_end() - - nob_chain_end_opt() - Introduce some auxiliary things that were used in Chain API implementation, but might be useful outside of it: - - Nob_Pipe - - nob_pipe_create() - - nob_fa_append() - 3.1.0 (2026-01-22) Make nob_delete_file() be able to delete empty dir on Windows (by @rexim) - Introduce Directory Entry API - similar to POSIX dirent but with names that don't collide - - Nob_Dir_Entry - - nob_dir_entry_open() - - nob_dir_entry_next() - - nob_dir_entry_close() - Rewrite Directory Walking API using Directory Entry API - Introduce .post_order parameter to Nob_Walk_Dir_Opt which walks the directories in post order starting from leaf files - Rewrite nob_read_entire_dir() using Directory Entry API - 3.0.0 (2026-01-13) Improve C++ support (by @rexim) - - Fix various C++ compilers warnings and complains throughout the code. - - Reimplement nob_cmd_append() without taking a pointer to temporary array (some C++ compilers don't like that) - - Make default NOB_REBUILD_URSELF() try to recompile with C++ if __cplusplus macro is defined - Strip prefixes by default (by @rexim) - - Ignore NOB_STRIP_PREFIX macro - - Introduce NOB_UNSTRIP_PREFIX macro - BACKWARD INCOMPATIBLE CHANGE!!! If you had code that intentionally didn't enable NOB_STRIP_PREFIX - because all the names from nob.h were causing too many collisions for you, upgrading to 3.0.0 may break it. - In that case you should go and explicitly enable NOB_UNSTRIP_PREFIX where needed after upgrading. - Add nob_sb_append alias to nob_da_append (by @rexim) - 2.0.1 (2026-01-07) Fix Walk_Entry naming (by @Sinha-Ujjawal) - Using single String Builder in nob__walk_dir_opt_impl (by @Sinha-Ujjawal) - Add tcc to nob_cc_*() and NOB_REBUILD_URSELF() macros (by @vylsaz) - Fix building nob_read_entire_file() with tcc on windows (by @vylsaz) - Fix Y2038 in nob_needs_rebuild() (by @lnvitesace) - 2.0.0 (2026-01-06) Remove minirent.h (by @rexim) - BACKWARD INCOMPATIBLE CHANGE!!! If you were using minirent.h from this library - just use it directly from https://github.com/tsoding/minirent - or consider using the New Directory Walking API. - Introduce New Directory Walking API (by @rexim) - - NOB_WALK_CONT - - NOB_WALK_SKIP - - NOB_WALK_STOP - - Nob_Walk_Action - - Nob_Walk_Entry - - Nob_Walk_Func - - Nob_Walk_Dir_Opt - - nob_walk_dir() - - nob_walk_dir_opt() - Add support for Haiku to nob_temp_running_executable_path() (By @Cephon) - Make nob_file_exists() unfailable (By @rexim) - 1.27.0 (2025-12-30) Add .dont_reset option to cmd_run (by @Israel77) - Fix support for FreeBSD (by @cqundefine) - Strip prefixes from NOB_GO_REBUILD_URSELF and NOB_GO_REBUILD_URSELF_PLUS (by @huwwa) - Add /Fo flag to MSVC version of nob_cc_output() (by @ratchetfreak) - 1.26.0 (2025-12-28) Introduce customizable log handlers (by @rexim) - - Add nob_log_handler - - Add nob_set_log_handler - - Add nob_get_log_handler - - Add nob_default_log_handler - - Add nob_cancer_log_handler - Introduce nob_temp_vsprintf (by @rexim) - Fix compilation error on Windows when NOB_NO_ECHO is enabled (by @mlorenc227) - Do not redefine _CRT_SECURE_NO_WARNINGS if it's already defined (by @vylsaz) - 1.25.1 (2025-11-06) Fix forward declaration of _NSGetExecutablePath on MacOS (by @agss0) - 1.25.0 (2025-10-25) - Add nob_sb_pad_align() - - Add nob_swap() - - Add nob_temp_strndup() - - Add nob_temp_dir_name() - - Add nob_temp_file_name() - - Add nob_temp_file_ext() - - Add nob_temp_running_executable_path() - 1.24.0 (2025-10-23) Introduce NOB_NO_ECHO macro flag (@rexim) - 1.23.0 (2025-08-22) Introduce new API for running commands (by @rexim, @programmerlexi, @0x152a) - - Add nob_cmd_run() - - Add nob_cmd_run_opt() - - Add struct Nob_Cmd_Opt - - Add nob_procs_flush() - - Add nob_nprocs() - Deprecate old API for running commands. (by @rexim) - We do not plan to delete this API any time, but we believe that the new one is more convenient. - - Deprecate struct Nob_Cmd_Redirect{} (it's not explicitly marked with NOB_DEPRECATED, but functions that use it are) - - Turn nob_cmd_run_async() into a function (otherwise it's not deprecatable with NOB_DEPRECATED) - - Deprecate nob_cmd_run_async() - - Deprecate nob_cmd_run_async_and_reset() - - Deprecate nob_cmd_run_async_redirect() - - Deprecate nob_cmd_run_async_redirect_and_reset() - - Deprecate nob_cmd_run_sync() - - Deprecate nob_cmd_run_sync_and_reset() - - Deprecate nob_cmd_run_sync_redirect() - - Deprecate nob_cmd_run_sync_redirect_and_reset() - - Deprecate nob_procs_append_with_flush() - - Deprecate nob_procs_wait_and_reset() - Introduce deprecation mechanism (by @yuI4140, @rexim) - By default, deprecation warnings are not reported. You have to #define NOB_WARN_DEPRECATED to enable them. - - Add NOB_DEPRECATED() - - Add NOB_WARN_DEPRECATED - Add NOB_DECLTYPE_CAST() for C++-compatible casting of allocation results (by @rexim) - Introduce basic performance measuring mechanism (By @mikmart) - - Add nob_nanos_since_unspecified_epoch() - - Add NOB_NANOS_PER_SEC - 1.22.0 (2025-08-12) Add NOBDEF macro to the beginning of function declarations (by @minefreak19) - Add more flags to MSVC nob_cc_flags() (by @PieVieRo) - 1.21.0 (2025-08-11) Add NOB_NO_MINIRENT guard for "minirent.h" (by @fietec) - 1.20.9 (2025-08-11) Fix warnings on Windows: Define _CRT_SECURE_NO_WARNINGS, Rename mkdir to _mkdir (by @OetkenPurveyorOfCode) - 1.20.8 (2025-08-11) Fix the bug with nob_get_file_type() not identifying symlinks correctly on POSIX (By @samuellieberman) - 1.20.7 (2025-07-29) Align nob_temp_alloc() allocations by the word size (By @rexim) - 1.20.6 (2025-05-16) Never strip nob_* suffix from nob_rename (By @rexim) - 1.20.5 (2025-05-16) NOB_PRINTF_FORMAT() support for MinGW (By @KillerxDBr) - 1.20.4 (2025-05-16) More reliable rendering of the Windows command (By @vylsaz) - 1.20.3 (2025-05-16) Add check for __clang__ along with _MSC_VER checks (By @nashiora) - 1.20.2 (2025-04-24) Report the program name that failed to start up in nob_cmd_run_async_redirect() (By @rexim) - 1.20.1 (2025-04-16) Use vsnprintf() in nob_sb_appendf() instead of vsprintf() (By @LainLayer) - 1.20.0 (2025-04-16) Introduce nob_cc(), nob_cc_flags(), nob_cc_inputs(), nob_cc_output() macros (By @rexim) - 1.19.0 (2025-03-25) Add nob_procs_append_with_flush() (By @rexim and @anion155) - 1.18.0 (2025-03-24) Add nob_da_foreach() (By @rexim) - Allow file sizes greater than 2GB to be read on windows (By @satchelfrost and @KillerxDBr) - Fix nob_fd_open_for_write behaviour on windows so it truncates the opened files (By @twixuss) - 1.17.0 (2025-03-16) Factor out nob_da_reserve() (By @rexim) - Add nob_sb_appendf() (By @angelcaru) - 1.16.1 (2025-03-16) Make nob_da_resize() exponentially grow capacity similar to no_da_append_many() - 1.16.0 (2025-03-16) Introduce NOB_PRINTF_FORMAT - 1.15.1 (2025-03-16) Make nob.h compilable in gcc/clang with -std=c99 on POSIX. This includes: - not using strsignal() - using S_IS* stat macros instead of S_IF* flags - 1.15.0 (2025-03-03) Add nob_sv_chop_left() - 1.14.1 (2025-03-02) Add NOB_EXPERIMENTAL_DELETE_OLD flag that enables deletion of nob.old in Go Rebuild Urself™ Technology - 1.14.0 (2025-02-17) Add nob_da_last() - Add nob_da_remove_unordered() - 1.13.1 (2025-02-17) Fix segfault in nob_delete_file() (By @SileNce5k) - 1.13.0 (2025-02-11) Add nob_da_resize() (By @satchelfrost) - 1.12.0 (2025-02-04) Add nob_delete_file() - Add nob_sv_start_with() - 1.11.0 (2025-02-04) Add NOB_GO_REBUILD_URSELF_PLUS() (By @rexim) - 1.10.0 (2025-02-04) Make NOB_ASSERT, NOB_REALLOC, and NOB_FREE redefinable (By @OleksiiBulba) - 1.9.1 (2025-02-04) Fix signature of nob_get_current_dir_temp() (By @julianstoerig) - 1.9.0 (2024-11-06) Add Nob_Cmd_Redirect mechanism (By @rexim) - Add nob_path_name() (By @0dminnimda) - 1.8.0 (2024-11-03) Add nob_cmd_extend() (By @0dminnimda) - 1.7.0 (2024-11-03) Add nob_win32_error_message and NOB_WIN32_ERR_MSG_SIZE (By @KillerxDBr) - 1.6.0 (2024-10-27) Add nob_cmd_run_sync_and_reset() - Add nob_sb_to_sv() - Add nob_procs_wait_and_reset() - 1.5.1 (2024-10-25) Include limits.h for Linux musl libc (by @pgalkin) - 1.5.0 (2024-10-23) Add nob_get_current_dir_temp() - Add nob_set_current_dir() - 1.4.0 (2024-10-21) Fix UX issues with NOB_GO_REBUILD_URSELF on Windows when you call nob without the .exe extension (By @pgalkin) - Add nob_sv_end_with (By @pgalkin) - 1.3.2 (2024-10-21) Fix unreachable error in nob_log on passing NOB_NO_LOGS - 1.3.1 (2024-10-21) Fix redeclaration error for minimal_log_level (By @KillerxDBr) - 1.3.0 (2024-10-17) Add NOB_UNREACHABLE - 1.2.2 (2024-10-16) Fix compilation of nob_cmd_run_sync_and_reset on Windows (By @KillerxDBr) - 1.2.1 (2024-10-16) Add a separate include guard for NOB_STRIP_PREFIX. - 1.2.0 (2024-10-15) Make NOB_DA_INIT_CAP redefinable - Add NOB_STRIP_PREFIX which strips off nob_* prefix from all the user facing names - Add NOB_UNUSED macro - Add NOB_TODO macro - Add nob_sv_trim_left and nob_sv_trim_right declarations to the header part - 1.1.1 (2024-10-15) Remove forward declaration for is_path1_modified_after_path2 - 1.1.0 (2024-10-15) nob_minimal_log_level - nob_cmd_run_sync_and_reset - 1.0.0 (2024-10-15) first release based on https://github.com/tsoding/musializer/blob/4ac7cce9874bc19e02d8c160c8c6229de8919401/nob.h -*/ - -/* - Version Conventions: - - We are following https://semver.org/ so the version has a format MAJOR.MINOR.PATCH: - - Modifying comments does not update the version. - - PATCH is incremented in case of a bug fix or refactoring without touching the API. - - MINOR is incremented when new functions and/or types are added in a way that does - not break any existing user code. We want to do this in the majority of the situation. - If we want to delete a certain function or type in favor of another one we should - just add the new function/type and deprecate the old one in a backward compatible way - and let them co-exist for a while. - - MAJOR update should be just a periodic cleanup of the DEPRECATED functions and types - without really modifying any existing functionality. - - Breaking backward compatibility in a MINOR release should be considered a bug and - should be promptly fixed in the next PATCH release. - - API conventions: - - - All the user facing names should be prefixed with `nob_`, `NOB_`, or `Nob_` depending on the case. - - The prefixes of non-redefinable names should be stripped in NOB_STRIP_PREFIX_GUARD_ section, - unless explicitly stated otherwise like in case of nob_log() or nob_rename(). - - Internal (private) names should be prefixed with `nob__` (double underscore). The user code is discouraged - from using such names since they are allowed to be broken in a backward incompatible way even in PATCH - releases. (This is why they are internal) - - If a public macro uses an private function internally such function must be forward declared in the NOB_H_ - section. -*/ - -/* - ------------------------------------------------------------------------------ - This software is available under 2 licenses -- choose whichever you prefer. - ------------------------------------------------------------------------------ - ALTERNATIVE A - MIT License - Copyright (c) 2024 Alexey Kutepov - Permission is hereby granted, free of charge, to any person obtaining a copy of - this software and associated documentation files (the "Software"), to deal in - the Software without restriction, including without limitation the rights to - use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies - of the Software, and to permit persons to whom the Software is furnished to do - so, subject to the following conditions: - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - ------------------------------------------------------------------------------ - ALTERNATIVE B - Public Domain (www.unlicense.org) - This is free and unencumbered software released into the public domain. - Anyone is free to copy, modify, publish, use, compile, sell, or distribute this - software, either in source code form or as a compiled binary, for any purpose, - commercial or non-commercial, and by any means. - In jurisdictions that recognize copyright laws, the author or authors of this - software dedicate any and all copyright interest in the software to the public - domain. We make this dedication for the benefit of the public at large and to - the detriment of our heirs and successors. We intend this dedication to be an - overt act of relinquishment in perpetuity of all present and future rights to - this software under copyright law. - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION - WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - ------------------------------------------------------------------------------ -*/ diff --git a/code/common/dirs b/code/common/dirs new file mode 100644 index 0000000..a8b8a4f --- /dev/null +++ b/code/common/dirs @@ -0,0 +1 @@ +DIRS=libc printf diff --git a/code/common/libc.c b/code/common/libc.c index 6a02b59..4ced8e3 100644 --- a/code/common/libc.c +++ b/code/common/libc.c @@ -4,7 +4,6 @@ #include #include -// Implements the strcpy operation. char* strcpy(char* dest, const char* src) { char* d = dest; while (*src) *d++ = *src++; @@ -12,7 +11,6 @@ char* strcpy(char* dest, const char* src) { return dest; } -// Implements the strncpy operation. char* strncpy(char* dest, const char* src, size_t n) { size_t i; for (i = 0; i < n && src[i]; i++) dest[i] = src[i]; @@ -45,7 +43,6 @@ char* strstr(const char* haystack, const char* needle) { return NULL; } -// Implements the strcat operation. char* strcat(char* dest, const char* src) { char* ptr = dest; while (*ptr != '\0') { @@ -60,7 +57,6 @@ char* strcat(char* dest, const char* src) { return dest; } -// Implements the strncat operation. char* strncat(char* dest, const char* src, size_t n) { char* ptr = dest; while (*ptr != '\0') { @@ -76,13 +72,11 @@ char* strncat(char* dest, const char* src, size_t n) { return dest; } -// Implements the strcmp operation. int strcmp(const char* s1, const char* s2) { while (*s1 && *s1 == *s2) s1++, s2++; return (unsigned char)*s1 - (unsigned char)*s2; } -// Implements the strncmp operation. int strncmp(const char* s1, const char* s2, size_t n) { while (n && *s1 && (*s1 == *s2)) { s1++; @@ -92,7 +86,6 @@ int strncmp(const char* s1, const char* s2, size_t n) { return n == 0 ? 0 : *(unsigned char*)s1 - *(unsigned char*)s2; } -// Implements the stricmp operation. int _stricmp(const char* s1, const char* s2) { // ASCII case folding works here because bit 0x20 distinguishes 'A' from 'a'. while (*s1 && ((*s1 | 0x20) == (*s2 | 0x20))) { @@ -101,14 +94,12 @@ int _stricmp(const char* s1, const char* s2) { return (unsigned char)(*s1 | 0x20) - (unsigned char)(*s2 | 0x20); } -// Implements the strlen operation. size_t strlen(const char* s) { size_t n = 0; while (*s++) n++; return n; } -// Implements the strnlen operation. size_t strnlen(const char* s, size_t maxlen) { size_t len; for (len = 0; len < maxlen; len++) { @@ -119,7 +110,6 @@ size_t strnlen(const char* s, size_t maxlen) { return len; } -// Implements the strchr operation. char* strchr(const char* s, int c) { while (*s) { if (*s == (char)c) return (char*)s; @@ -128,7 +118,6 @@ char* strchr(const char* s, int c) { return NULL; } -// Implements the strrchr operation. char* strrchr(const char* s, int c) { char ch = (char)c; const char* last = NULL; @@ -150,7 +139,6 @@ void *memchr(const void *s, int c, size_t n) { return NULL; } -// Implements the memset operation. void* memset(void* dest, int c, size_t n) { unsigned char* d = (unsigned char*)dest; size_t qwords = n / 8; @@ -172,7 +160,6 @@ void* memset(void* dest, int c, size_t n) { return dest; } -// Implements the memcpy operation. void* memcpy(void* dest, const void* src, size_t n) { unsigned char* d = (unsigned char*)dest; const unsigned char* s = (const unsigned char*)src; @@ -192,7 +179,6 @@ void* memcpy(void* dest, const void* src, size_t n) { return dest; } -// Implements the memmove operation. void* memmove(void* dest, const void* src, size_t n) { unsigned char* d = (unsigned char*)dest; const unsigned char* s = (const unsigned char*)src; @@ -233,7 +219,6 @@ void* memmove(void* dest, const void* src, size_t n) { return dest; } -// Implements the memcmp operation. int memcmp(const void* s1, const void* s2, size_t n) { const unsigned __int64* a64 = (const unsigned __int64*)s1; const unsigned __int64* b64 = (const unsigned __int64*)s2; diff --git a/code/common/libc/makefile b/code/common/libc/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/common/libc/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/common/libc/sources b/code/common/libc/sources new file mode 100644 index 0000000..ace31db --- /dev/null +++ b/code/common/libc/sources @@ -0,0 +1,5 @@ +TARGETNAME=libc +TARGETPATH=obj +TARGETTYPE=LIBRARY +FLAVOR=LIBC +SOURCES=@/code/common/libc.c diff --git a/code/common/printf/makefile b/code/common/printf/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/common/printf/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/common/printf/sources b/code/common/printf/sources new file mode 100644 index 0000000..a09072f --- /dev/null +++ b/code/common/printf/sources @@ -0,0 +1,5 @@ +TARGETNAME=printf +TARGETPATH=obj +TARGETTYPE=LIBRARY +FLAVOR=COMMON +SOURCES=@/code/common/printf.c diff --git a/code/ddk/makefile b/code/ddk/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/ddk/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/ddk/sources b/code/ddk/sources new file mode 100644 index 0000000..22ef839 --- /dev/null +++ b/code/ddk/sources @@ -0,0 +1,5 @@ +TARGETNAME=ntlddk +TARGETPATH=obj +TARGETTYPE=LIBRARY +FLAVOR=DRIVER +SOURCES=@/code/ddk/pci_caps.c diff --git a/code/dirs b/code/dirs new file mode 100644 index 0000000..514f292 --- /dev/null +++ b/code/dirs @@ -0,0 +1 @@ +DIRS=common ddk kernel boot drivers user diff --git a/code/drivers/drivers.ini b/code/drivers.ini similarity index 77% rename from code/drivers/drivers.ini rename to code/drivers.ini index 6916492..adab7f8 100644 --- a/code/drivers/drivers.ini +++ b/code/drivers.ini @@ -1,4 +1,7 @@ -; drivers.ini +; Driver dependency graph. +; [class.id] declares a provider class; [driver.id] declares a driver. +; requires= Providers that must succeed; after= providers that must settle. +; start=boot loads during bootstrap; start=runtime loads after boot. [class.bus] @@ -88,3 +91,9 @@ class=network-adapter image=rtl816x.sys start=runtime class=network-adapter + +[driver.acpi] +image=acpi.sys +start=boot +critical=false + diff --git a/code/drivers/audio/dirs b/code/drivers/audio/dirs new file mode 100644 index 0000000..7ebf264 --- /dev/null +++ b/code/drivers/audio/dirs @@ -0,0 +1 @@ +DIRS=hda diff --git a/code/drivers/audio/hda/hda.c b/code/drivers/audio/hda/hda.c index 8c4955d..ef2f494 100644 --- a/code/drivers/audio/hda/hda.c +++ b/code/drivers/audio/hda/hda.c @@ -6,10 +6,6 @@ #include static DRIVER_OBJECT gHdaDriver; -static HDA_CONTROLLER* gHdaControllers[HDA_MAX_CONTROLLERS]; -static uint32_t gHdaControllerCount; -static SPINLOCK gHdaRegistryLock = SPINLOCK_INIT; - static const IO_DEVICE_ID gHdaIds[] = { { IoBusPci, { "PCI\\VEN_8086&DEV_2668", sizeof("PCI\\VEN_8086&DEV_2668") - 1u } }, { IoBusPci, { "PCI\\VEN_15AD&DEV_1977", sizeof("PCI\\VEN_15AD&DEV_1977") - 1u } }, @@ -21,79 +17,14 @@ static const IO_DRIVER_ID_TABLE gHdaIdTable = { sizeof(gHdaIds) / sizeof(gHdaIds[0]), }; -// Registers a controller in the shared interrupt scan set. -static KSTATUS HdaRegisterController(HDA_CONTROLLER* controller) { - if (!controller) - return NTLSTATUS_INVALID_PARAMETER; - - uintptr_t flags = KeAcquireSpinlock(&gHdaRegistryLock); - for (uint32_t index = 0; index < gHdaControllerCount; index++) { - if (gHdaControllers[index] == controller) { - KeReleaseSpinlock(&gHdaRegistryLock, flags); - return NTLSTATUS_SUCCESS; - } - } - if (gHdaControllerCount == HDA_MAX_CONTROLLERS) { - KeReleaseSpinlock(&gHdaRegistryLock, flags); - return NTLSTATUS_NO_MEMORY; - } - gHdaControllers[gHdaControllerCount++] = controller; - KeReleaseSpinlock(&gHdaRegistryLock, flags); - return NTLSTATUS_SUCCESS; +// Handles the interrupt for its owning HDA controller. +static void HdaIsr(void* context) { + HDA_CONTROLLER* controller = (HDA_CONTROLLER*)context; + if (controller && controller->Magic == HDA_CONTROLLER_MAGIC) + HdaHandleInterrupt(controller); } -// Removes a controller from the shared interrupt scan set. -static void HdaUnregisterController(HDA_CONTROLLER* controller) { - if (!controller) - return; - uintptr_t flags = KeAcquireSpinlock(&gHdaRegistryLock); - for (uint32_t index = 0; index < gHdaControllerCount; index++) { - if (gHdaControllers[index] != controller) - continue; - gHdaControllers[index] = gHdaControllers[gHdaControllerCount - 1u]; - gHdaControllers[gHdaControllerCount - 1u] = (HDA_CONTROLLER*)0; - gHdaControllerCount--; - break; - } - KeReleaseSpinlock(&gHdaRegistryLock, flags); -} - -// Dispatches a hardware interrupt to every live HDA controller. -static void HdaIsr(void) { - DEVICE_OBJECT* devices[HDA_MAX_CONTROLLERS]; - uint32_t count = 0; - - uintptr_t flags = KeAcquireSpinlock(&gHdaRegistryLock); - count = gHdaControllerCount; - if (count > HDA_MAX_CONTROLLERS) - count = HDA_MAX_CONTROLLERS; - for (uint32_t index = 0; index < count; index++) { - HDA_CONTROLLER* controller = gHdaControllers[index]; - devices[index] = controller ? controller->Fdo : (DEVICE_OBJECT*)0; - if (devices[index]) - IoReferenceDeviceObject(devices[index]); - } - KeReleaseSpinlock(&gHdaRegistryLock, flags); - - for (uint32_t index = 0; index < count; index++) { - DEVICE_OBJECT* device = devices[index]; - if (!device) - continue; - HDA_CONTROLLER* controller = (HDA_CONTROLLER*)device->DeviceExtension; - if (controller && controller->Magic == HDA_CONTROLLER_MAGIC) - HdaHandleInterrupt(controller); - IoDereferenceDeviceObject(device); - } -} - -// Registers the global ISR once for each kernel IRQ slot used by HDA. -static KSTATUS HdaRegisterIrq(uint8_t irq) { - if (irq >= 24u) - return NTLSTATUS_NOT_SUPPORTED; - KeIrqRegister(irq, HdaIsr); - return NTLSTATUS_SUCCESS; -} // Maps BAR0 and validates the stream-descriptor aperture described by GCAP. static KSTATUS HdaMapRegisters(HDA_CONTROLLER* controller) { @@ -149,29 +80,14 @@ static KSTATUS HdaMapRegisters(HDA_CONTROLLER* controller) { return NTLSTATUS_SUCCESS; } -// Configures MSI first and enables INTx only after MSI setup reports failure. +// Connects the controller interrupt using the PCI bus routing policy. static KSTATUS HdaConfigureInterrupt(HDA_CONTROLLER* controller) { - KSTATUS status = PciEnableMsiAuto(controller->Pdo, &controller->Irq); - if (KSUCCESS(status)) { - controller->UsingMsi = true; - return NTLSTATUS_SUCCESS; - } - - DbgPrint( - "HDA: MSI setup failed status=0x%x; attempting explicit INTx fallback\n", - status); - controller->UsingMsi = false; - status = PciGetInterrupt(controller->Pdo, &controller->Irq); - if (!KSUCCESS(status)) - return status; - if (controller->Irq == 0xFFu || controller->Irq >= 24u) - return NTLSTATUS_NOT_SUPPORTED; - - status = PciEnableDevice(controller->Pdo, - PCI_ENABLE_MEMORY | - PCI_ENABLE_BUSMASTER | - PCI_ENABLE_INTX); - return status; + controller->InterruptRequest.Routine = HdaIsr; + controller->InterruptRequest.Context = controller; + controller->InterruptRequest.Affinity = 0; + controller->InterruptRequest.Interrupt = (KE_INTERRUPT*)0; + return PciConnectInterrupts(controller->Pdo, &controller->InterruptRequest, + 1u, &controller->UsingMsi); } // Waits until queued or active interrupt work no longer references the controller. @@ -214,9 +130,6 @@ static KSTATUS HdaStartDevice(HDA_CONTROLLER* controller) { if (!KSUCCESS(status)) return status; - status = HdaConfigureInterrupt(controller); - if (!KSUCCESS(status)) - return status; status = HdaAllocateDma(controller); if (!KSUCCESS(status)) @@ -237,21 +150,13 @@ static KSTATUS HdaStartDevice(HDA_CONTROLLER* controller) { return status; } - status = HdaRegisterController(controller); + status = HdaConfigureInterrupt(controller); if (!KSUCCESS(status)) { HdaStopRecoveryWorker(controller); HdaQuiesceController(controller); HdaReleaseDma(controller); return status; } - status = HdaRegisterIrq(controller->Irq); - if (!KSUCCESS(status)) { - HdaUnregisterController(controller); - HdaStopRecoveryWorker(controller); - HdaQuiesceController(controller); - HdaReleaseDma(controller); - return status; - } controller->Started = true; controller->Fdo->PnpState = DevicePnpStarted; @@ -261,7 +166,8 @@ static KSTATUS HdaStartDevice(HDA_CONTROLLER* controller) { status != NTLSTATUS_NOT_FOUND) { controller->Started = false; controller->Fdo->PnpState = DevicePnpNotStarted; - HdaUnregisterController(controller); + if (controller->InterruptRequest.Interrupt) + PciDisconnectInterrupts(controller->Pdo, &controller->InterruptRequest, 1u); HdaStopRecoveryWorker(controller); HdaQuiesceController(controller); HdaReleaseDma(controller); @@ -302,7 +208,8 @@ static KSTATUS HdaDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { case IRP_MN_SURPRISE_REMOVAL: controller->Started = false; controller->SurpriseRemoved = true; - HdaUnregisterController(controller); + if (controller->InterruptRequest.Interrupt) + PciDisconnectInterrupts(controller->Pdo, &controller->InterruptRequest, 1u); HdaStopRecoveryWorker(controller); KSTATUS surpriseDpcStatus = HdaWaitForControllerInterruptWorkIdle(controller); @@ -320,7 +227,8 @@ static KSTATUS HdaDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { if (!controller->SurpriseRemoved && controller->Registers) HdaWrite32(controller, HDA_REG_INTCTL, 0); controller->Started = false; - HdaUnregisterController(controller); + if (controller->InterruptRequest.Interrupt) + PciDisconnectInterrupts(controller->Pdo, &controller->InterruptRequest, 1u); HdaStopRecoveryWorker(controller); KSTATUS dpcStatus = HdaWaitForControllerInterruptWorkIdle(controller); if (!KSUCCESS(dpcStatus)) { @@ -366,7 +274,6 @@ static KSTATUS HdaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDevice controller->Magic = HDA_CONTROLLER_MAGIC; controller->Fdo = fdo; controller->Pdo = physicalDeviceObject; - controller->Irq = 0xFFu; controller->StateLock = (SPINLOCK)SPINLOCK_INIT; controller->Output.StreamTag = HDA_OUTPUT_STREAM_TAG; @@ -382,8 +289,6 @@ static KSTATUS HdaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDevice static KSTATUS DriverInitialize(NTL_MODULE* module) { (void)module; - gHdaControllerCount = 0; - memset(gHdaControllers, 0, sizeof(gHdaControllers)); memset(&gHdaDriver, 0, sizeof(gHdaDriver)); IoInitializeDriverObject(&gHdaDriver, SYS_SV_LITERAL("hda")); diff --git a/code/drivers/audio/hda/hda.h b/code/drivers/audio/hda/hda.h index 796e2f4..7add264 100644 --- a/code/drivers/audio/hda/hda.h +++ b/code/drivers/audio/hda/hda.h @@ -242,7 +242,7 @@ struct HDA_CONTROLLER { uint8_t BidirectionalStreamCount; uint8_t TotalStreamCount; uint16_t CodecMask; - uint8_t Irq; + PCI_INTERRUPT_REQUEST InterruptRequest; bool UsingMsi; bool Started; bool Removed; diff --git a/code/drivers/audio/hda/makefile b/code/drivers/audio/hda/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/drivers/audio/hda/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/drivers/audio/hda/sources b/code/drivers/audio/hda/sources new file mode 100644 index 0000000..88e05cb --- /dev/null +++ b/code/drivers/audio/hda/sources @@ -0,0 +1,7 @@ +TARGETNAME=hda +TARGETPATH=obj +TARGETTYPE=DRIVER +FLAVOR=DRIVER +TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\pci.lib" +EXTRA_LFLAGS=/NOENTRY +SOURCES=@/code/drivers/audio/hda/hda.c @/code/drivers/audio/hda/hda_transport.c @/code/drivers/audio/hda/hda_codec.c diff --git a/code/drivers/bus/dirs b/code/drivers/bus/dirs new file mode 100644 index 0000000..5445459 --- /dev/null +++ b/code/drivers/bus/dirs @@ -0,0 +1 @@ +DIRS=pci usb diff --git a/code/drivers/bus/pci/makefile b/code/drivers/bus/pci/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/drivers/bus/pci/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/drivers/bus/pci/pci.c b/code/drivers/bus/pci/pci.c index 217578c..7c061bc 100644 --- a/code/drivers/bus/pci/pci.c +++ b/code/drivers/bus/pci/pci.c @@ -26,13 +26,12 @@ static uint32_t gPciDeviceCount; #define PCI_MMIO_VA_LIMIT 0xFFFF980000000000ULL static uintptr_t gPciMmioNext = PCI_MMIO_VA_BASE; +static SPINLOCK gPciMmioLock = SPINLOCK_INIT; -// Implements the align Up64 operation. static uint64_t PciAlignUp64(uint64_t value, uint64_t alignment) { return (value + alignment - 1u) & ~(alignment - 1u); } -// Implements the default Mmio Flags operation. static uint64_t PciDefaultMmioFlags(void) { return NTL_DDK_PAGE_PRESENT | NTL_DDK_PAGE_WRITE | NTL_DDK_PAGE_CACHE_UC | NTL_DDK_PAGE_NX; } @@ -43,13 +42,15 @@ static KSTATUS PciAllocateMmioVa(uint64_t length, uintptr_t* outVa) { return NTLSTATUS_INVALID_PARAMETER; uint64_t alignedLength = PciAlignUp64(length, NTL_DDK_PAGE_SIZE); + uintptr_t cookie = KeAcquireSpinlock(&gPciMmioLock); uintptr_t va = (uintptr_t)PciAlignUp64((uint64_t)gPciMmioNext, NTL_DDK_PAGE_SIZE); - if (va < PCI_MMIO_VA_BASE || va >= PCI_MMIO_VA_LIMIT) + if (va < PCI_MMIO_VA_BASE || va >= PCI_MMIO_VA_LIMIT || + alignedLength > (uint64_t)(PCI_MMIO_VA_LIMIT - va)) { + KeReleaseSpinlock(&gPciMmioLock, cookie); return NTLSTATUS_NO_MEMORY; - if (alignedLength > (uint64_t)(PCI_MMIO_VA_LIMIT - va)) - return NTLSTATUS_NO_MEMORY; - + } gPciMmioNext = va + (uintptr_t)alignedLength; + KeReleaseSpinlock(&gPciMmioLock, cookie); *outVa = va; return NTLSTATUS_SUCCESS; } @@ -64,31 +65,26 @@ static bool PciIsPdo(DEVICE_OBJECT* pdo, PCI_PDO_EXTENSION** outExt) { return true; } -// Implements the raw Read32 operation. static uint32_t PciRawRead32(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset) { if (offset > 0xFCu) return 0xFFFFFFFFu; return KePciReadConfig32(0, bus, dev, fn, offset & 0xFCu); } -// Implements the raw Write32 operation. static void PciRawWrite32(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, uint32_t value) { if (offset > 0xFCu) return; KePciWriteConfig32(0, bus, dev, fn, offset & 0xFCu, value); } -// Implements the raw Read8 operation. static uint8_t PciRawRead8(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset) { uint32_t v = PciRawRead32(bus, dev, fn, offset); return (uint8_t)(v >> ((offset & 3u) * 8u)); } -// Implements the raw Read16 operation. static uint16_t PciRawRead16(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset) { uint32_t v = PciRawRead32(bus, dev, fn, offset); return (uint16_t)(v >> ((offset & 2u) * 8u)); } -// Implements the raw Write8 operation. static void PciRawWrite8(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, uint8_t value) { uint16_t aligned = offset & ~3u; uint32_t shift = (offset & 3u) * 8u; @@ -98,7 +94,6 @@ static void PciRawWrite8(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, PciRawWrite32(bus, dev, fn, aligned, old); } -// Implements the raw Write16 operation. static void PciRawWrite16(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, uint16_t value) { uint16_t aligned = offset & ~3u; uint32_t shift = (offset & 2u) * 8u; @@ -108,7 +103,6 @@ static void PciRawWrite16(uint8_t bus, uint8_t dev, uint8_t fn, uint16_t offset, PciRawWrite32(bus, dev, fn, aligned, old); } -// Implements the bar Size From Mask operation. static uint64_t PciBarSizeFromMask(uint64_t mask, uint64_t baseMask) { uint64_t sizeMask = mask & baseMask; if (!sizeMask || sizeMask == baseMask) @@ -116,7 +110,6 @@ static uint64_t PciBarSizeFromMask(uint64_t mask, uint64_t baseMask) { return (~sizeMask + 1u) & baseMask; } -// Implements the header Bar Count operation. static uint8_t PciHeaderBarCount(uint8_t headerType) { switch (headerType & PCI_HEADER_TYPE_MASK) { case 0x00: return 6; @@ -126,7 +119,6 @@ static uint8_t PciHeaderBarCount(uint8_t headerType) { } } -// Implements the decode Bars operation. static void PciDecodeBars(PCI_PDO_EXTENSION* ext) { uint8_t barCount = PciHeaderBarCount(ext->Info.HeaderType); for (uint8_t i = 0; i < PCI_MAX_BARS; i++) { @@ -398,7 +390,6 @@ static KSTATUS PciCreatePdo(uint8_t bus, uint8_t dev, uint8_t fn) { return NTLSTATUS_SUCCESS; } -// Implements the enumerate Bus operation. static void PciEnumerateBus(void) { for (uint32_t bus = 0; bus < 256u; bus++) { for (uint32_t dev = 0; dev < 32u; dev++) { @@ -440,7 +431,6 @@ static KSTATUS PciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { } } -// Implements the driver Abi Version operation. __declspec(dllexport) uint32_t PciDriverAbiVersion(void) { return 1u; } @@ -601,77 +591,306 @@ static uint8_t PciFindCapability(PCI_PDO_EXTENSION* ext, uint8_t capId) { return offset; } -// Enables msi. -__declspec(dllexport) KSTATUS PciEnableMsi(DEVICE_OBJECT* pdo, uint8_t irqSlot) { +// PCI owns message programming, while the kernel owns CPU/vector placement. +typedef struct PCI_MESSAGE_CONTEXT { + DEVICE_OBJECT* Pdo; + uint32_t TableOffset; + uint16_t Capability; + uint8_t Msix; + uint8_t Reserved; +} PCI_MESSAGE_CONTEXT; + +static KSTATUS PciUpdateMessageRoute(void* opaque, + KE_INTERRUPT_MESSAGE_OPERATION operation, const NTL_DDK_MSI_MESSAGE* message) { + PCI_MESSAGE_CONTEXT* ctx = (PCI_MESSAGE_CONTEXT*)opaque; PCI_PDO_EXTENSION* ext; - if (!PciIsPdo(pdo, &ext)) - return NTLSTATUS_INVALID_PARAMETER; - if (irqSlot >= 24u) - return NTLSTATUS_INVALID_PARAMETER; - - uint8_t cap = PciFindCapability(ext, PCI_CAP_ID_MSI); - if (!cap) - return NTLSTATUS_NOT_SUPPORTED; - - uint8_t bus = ext->Info.Address.Bus; - uint8_t dev = ext->Info.Address.Device; + if (!ctx || !PciIsPdo(ctx->Pdo, &ext)) return NTLSTATUS_INVALID_PARAMETER; + uint8_t bus = ext->Info.Address.Bus, dev = ext->Info.Address.Device; uint8_t fn = ext->Info.Address.Function; - - uint16_t control = PciRawRead16(bus, dev, fn, (uint16_t)(cap + 2u)); - bool is64 = (control & PCI_MSI_CTRL_64BIT) != 0; - bool pvm = (control & PCI_MSI_CTRL_PVM) != 0; - NTL_DDK_MSI_MESSAGE message; - KSTATUS messageStatus = KeIrqComposeMsiMessage(irqSlot, &message); - if (!KSUCCESS(messageStatus)) - return messageStatus; - - PciRawWrite32(bus, dev, fn, (uint16_t)(cap + 4u), (uint32_t)message.Address); - if (is64) { - PciRawWrite32(bus, dev, fn, (uint16_t)(cap + 8u), (uint32_t)(message.Address >> 32)); - PciRawWrite16(bus, dev, fn, (uint16_t)(cap + 12u), (uint16_t)message.Data); - if (pvm) - PciRawWrite32(bus, dev, fn, (uint16_t)(cap + 16u), 0); - } else { - PciRawWrite16(bus, dev, fn, (uint16_t)(cap + 8u), (uint16_t)message.Data); - if (pvm) - PciRawWrite32(bus, dev, fn, (uint16_t)(cap + 12u), 0); + if (ctx->Msix) { + if (!ext->MsixTable || ctx->TableOffset > ext->MsixMappedLength || + ext->MsixMappedLength - ctx->TableOffset < 16u) + return NTLSTATUS_DEVICE_ERROR; + volatile uint32_t* entry = (volatile uint32_t*)(ext->MsixTable + ctx->TableOffset); + if (operation == KeInterruptMessageQuiesce) { + entry[3] = 1u; + } else if (operation == KeInterruptMessageProgram && message) { + entry[0] = (uint32_t)message->Address; + entry[1] = (uint32_t)(message->Address >> 32); + entry[2] = message->Data; + } else if (operation == KeInterruptMessageResume) { + entry[3] = 0u; + } else return NTLSTATUS_INVALID_PARAMETER; + (void)entry[3]; + return NTLSTATUS_SUCCESS; } - - control &= (uint16_t)~PCI_MSI_CTRL_MME_MASK; - control |= PCI_MSI_CTRL_ENABLE; - PciRawWrite16(bus, dev, fn, (uint16_t)(cap + 2u), control); - - uint16_t cmd = PciRawRead16(bus, dev, fn, PCI_REG_COMMAND_STATUS); - cmd |= PCI_COMMAND_INTX_DISABLE; - PciRawWrite16(bus, dev, fn, PCI_REG_COMMAND_STATUS, cmd); - - DbgPrint("pci: MSI enabled %02x:%02x.%u cap=0x%02x vector=0x%02x irqslot=%u %s\n", - bus, dev, fn, cap, (unsigned)(message.Data & 0xFFu), irqSlot, is64 ? "64-bit" : "32-bit"); + uint16_t control = PciRawRead16(bus, dev, fn, ctx->Capability + 2u); + bool is64 = (control & PCI_MSI_CTRL_64BIT) != 0; + // MSI per-vector masking preserves pending messages during retargeting. + // Devices without PVM retain their initial affinity until disconnect. + if (!(control & PCI_MSI_CTRL_PVM)) return NTLSTATUS_NOT_SUPPORTED; + uint16_t maskOffset = ctx->Capability + (is64 ? 16u : 12u); + if (operation == KeInterruptMessageQuiesce) { + uint32_t mask = PciRawRead32(bus, dev, fn, maskOffset); + PciRawWrite32(bus, dev, fn, maskOffset, mask | 1u); + (void)PciRawRead32(bus, dev, fn, maskOffset); + } else if (operation == KeInterruptMessageProgram && message) { + PciRawWrite32(bus, dev, fn, ctx->Capability + 4u, (uint32_t)message->Address); + if (is64) { + PciRawWrite32(bus, dev, fn, ctx->Capability + 8u, + (uint32_t)(message->Address >> 32)); + PciRawWrite16(bus, dev, fn, ctx->Capability + 12u, (uint16_t)message->Data); + } else PciRawWrite16(bus, dev, fn, ctx->Capability + 8u, (uint16_t)message->Data); + } else if (operation == KeInterruptMessageResume) { + uint32_t mask = PciRawRead32(bus, dev, fn, maskOffset); + PciRawWrite32(bus, dev, fn, maskOffset, mask & ~1u); + (void)PciRawRead32(bus, dev, fn, maskOffset); + } else return NTLSTATUS_INVALID_PARAMETER; + (void)PciRawRead16(bus, dev, fn, ctx->Capability + 2u); return NTLSTATUS_SUCCESS; } -// Enables a single MSI vector, allocating the nt-lite IRQ slot internally. -__declspec(dllexport) KSTATUS PciEnableMsiAuto(DEVICE_OBJECT* pdo, uint8_t* outIrqSlot) { - PCI_PDO_EXTENSION* ext; - if (!outIrqSlot || !PciIsPdo(pdo, &ext)) - return NTLSTATUS_INVALID_PARAMETER; - - if (!PciFindCapability(ext, PCI_CAP_ID_MSI)) - return NTLSTATUS_NOT_SUPPORTED; - - uint8_t irq = 0xFFu; - KSTATUS st = KeIrqAllocateMsiVector(&irq); - if (!KSUCCESS(st)) +static KSTATUS PciBindMessage(DEVICE_OBJECT* pdo, PCI_INTERRUPT_REQUEST* request, + uint8_t msix, uint16_t capability, uint32_t tableOffset) { + PCI_MESSAGE_CONTEXT* ctx = (PCI_MESSAGE_CONTEXT*)MmAllocatePool(sizeof(*ctx)); + if (!ctx) return NTLSTATUS_NO_MEMORY; + ctx->Pdo = pdo; + ctx->Msix = msix; + ctx->Capability = capability; + ctx->TableOffset = tableOffset; + ctx->Reserved = 0; + KSTATUS st = KeInterruptBindMessageSource(request->Interrupt, PciUpdateMessageRoute, ctx); + if (!KSUCCESS(st)) { + MmFreePool(ctx); return st; - - st = PciEnableMsi(pdo, irq); - if (!KSUCCESS(st)) - return st; - - *outIrqSlot = irq; + } + request->BusContext = ctx; return NTLSTATUS_SUCCESS; } +// Programs a pre-allocated interrupt group. All routes exist before device delivery begins. +static KSTATUS PciConnectMsix(DEVICE_OBJECT* pdo, PCI_PDO_EXTENSION* ext, + PCI_INTERRUPT_REQUEST* requests, uint32_t count) { + uint8_t cap = PciFindCapability(ext, PCI_CAP_ID_MSIX); + if (!cap) return NTLSTATUS_NOT_SUPPORTED; + uint8_t bus = ext->Info.Address.Bus, dev = ext->Info.Address.Device; + uint8_t fn = ext->Info.Address.Function; + uint16_t control = PciRawRead16(bus, dev, fn, cap + 2u); + uint32_t size = (control & 0x7FFu) + 1u; + if (count > size) return NTLSTATUS_NOT_SUPPORTED; + uint32_t table = PciRawRead32(bus, dev, fn, cap + 4u); + uint32_t bir = table & 7u, offset = table & ~7u; + if (bir >= PCI_MAX_BARS) return NTLSTATUS_DEVICE_ERROR; + PCI_BAR bar; + KSTATUS st = PciGetBar(pdo, (uint8_t)bir, &bar); + if (!KSUCCESS(st) || (bar.Type != PciBarMemory32 && bar.Type != PciBarMemory64) || + bar.Length < offset || count > (bar.Length - offset) / 16u) + return NTLSTATUS_NOT_SUPPORTED; + uint16_t command = PciRawRead16(bus, dev, fn, PCI_REG_COMMAND_STATUS); + if (!(command & PCI_COMMAND_MEMORY_SPACE)) { + DbgPrint("pci: MSI-X requires enabled memory decoding at %02x:%02x.%u\n", + bus, dev, fn); + return NTLSTATUS_DEVICE_ERROR; + } + + if (!ext->MsixTable) { + volatile uint8_t* mapped = (volatile uint8_t*)0; + uint64_t mappedLength = 0; + st = PciMapBar(pdo, (uint8_t)bir, + NTL_DDK_PAGE_PRESENT | NTL_DDK_PAGE_WRITE | NTL_DDK_PAGE_CACHE_UC | NTL_DDK_PAGE_NX, + (void**)&mapped, &mappedLength); + if (!KSUCCESS(st)) return st; + ext->MsixTable = mapped; + ext->MsixMappedLength = mappedLength; + ext->MsixBarIndex = (uint8_t)bir; + } + // A persistent per-PDO mapping prevents repeated BAR allocations on reconnect. + if (ext->MsixBarIndex != bir || ext->MsixMappedLength < offset || + count > (ext->MsixMappedLength - offset) / 16u) + return NTLSTATUS_DEVICE_ERROR; + volatile uint8_t* mapped = ext->MsixTable; + + // Mask the function and turn off stale firmware MSI before programming MSI-X. + PciRawWrite16(bus, dev, fn, cap + 2u, (control | 0x4000u) & ~0x8000u); + uint8_t msiCap = PciFindCapability(ext, PCI_CAP_ID_MSI); + if (msiCap) { + uint16_t msiControl = PciRawRead16(bus, dev, fn, msiCap + 2u); + PciRawWrite16(bus, dev, fn, msiCap + 2u, + msiControl & (uint16_t)~PCI_MSI_CTRL_ENABLE); + } + for (uint32_t i = 0; i < count; i++) { + st = KeInterruptReserveMessage(requests[i].Affinity, requests[i].Routine, + requests[i].Context, &requests[i].Interrupt); + if (!KSUCCESS(st)) goto failed; + NTL_DDK_MSI_MESSAGE msg; + st = KeInterruptComposeMessage(requests[i].Interrupt, &msg); + if (!KSUCCESS(st)) goto failed; + st = PciBindMessage(pdo, &requests[i], 1u, cap, offset + 16u * i); + if (!KSUCCESS(st)) goto failed; + volatile uint32_t* entry = (volatile uint32_t*)(mapped + offset + 16u * i); + entry[3] = 1u; + entry[0] = (uint32_t)msg.Address; + entry[1] = (uint32_t)(msg.Address >> 32); + entry[2] = msg.Data; + entry[3] = 0u; + // Read back the entry to drain posted MMIO writes before enabling MSI-X. + (void)entry[3]; + } + PciRawWrite16(bus, dev, fn, cap + 2u, (control | 0x8000u) & ~0x4000u); + (void)PciRawRead16(bus, dev, fn, cap + 2u); + PciRawWrite16(bus, dev, fn, PCI_REG_COMMAND_STATUS, command | PCI_COMMAND_INTX_DISABLE); + for (uint32_t i = 0; i < count; i++) { + st = KeInterruptActivateMessage(requests[i].Interrupt); + if (!KSUCCESS(st)) goto failed; + } + return NTLSTATUS_SUCCESS; +failed: + PciRawWrite16(bus, dev, fn, cap + 2u, control & ~0x8000u); + for (uint32_t i = 0; i < count; i++) { + if (requests[i].Interrupt) { + KeInterruptDisconnect(requests[i].Interrupt); + requests[i].Interrupt = (KE_INTERRUPT*)0; + } + if (requests[i].BusContext) { + MmFreePool(requests[i].BusContext); + requests[i].BusContext = 0; + } + } + return st; +} + +static KSTATUS PciConnectMsi(DEVICE_OBJECT* pdo, PCI_PDO_EXTENSION* ext, + PCI_INTERRUPT_REQUEST* request) { + uint8_t cap = PciFindCapability(ext, PCI_CAP_ID_MSI); + if (!cap) return NTLSTATUS_NOT_SUPPORTED; + uint8_t bus = ext->Info.Address.Bus, dev = ext->Info.Address.Device; + uint8_t fn = ext->Info.Address.Function; + KSTATUS st = KeInterruptReserveMessage(request->Affinity, request->Routine, + request->Context, &request->Interrupt); + if (!KSUCCESS(st)) return st; + NTL_DDK_MSI_MESSAGE msg; + st = KeInterruptComposeMessage(request->Interrupt, &msg); + if (!KSUCCESS(st)) goto failed; + st = PciBindMessage(pdo, request, 0u, cap, 0); + if (!KSUCCESS(st)) goto failed; + uint8_t msixCap = PciFindCapability(ext, PCI_CAP_ID_MSIX); + if (msixCap) { + uint16_t msixControl = PciRawRead16(bus, dev, fn, msixCap + 2u); + PciRawWrite16(bus, dev, fn, msixCap + 2u, + (msixControl | 0x4000u) & (uint16_t)~0x8000u); + } + uint16_t control = PciRawRead16(bus, dev, fn, cap + 2u); + bool is64 = (control & PCI_MSI_CTRL_64BIT) != 0; + bool pvm = (control & PCI_MSI_CTRL_PVM) != 0; + PciRawWrite32(bus, dev, fn, cap + 4u, (uint32_t)msg.Address); + if (is64) { + PciRawWrite32(bus, dev, fn, cap + 8u, (uint32_t)(msg.Address >> 32)); + PciRawWrite16(bus, dev, fn, cap + 12u, (uint16_t)msg.Data); + if (pvm) PciRawWrite32(bus, dev, fn, cap + 16u, 0); + } else { + PciRawWrite16(bus, dev, fn, cap + 8u, (uint16_t)msg.Data); + if (pvm) PciRawWrite32(bus, dev, fn, cap + 12u, 0); + } + control = (control & ~(uint16_t)PCI_MSI_CTRL_MME_MASK) | PCI_MSI_CTRL_ENABLE; + PciRawWrite16(bus, dev, fn, cap + 2u, control); + uint16_t command = PciRawRead16(bus, dev, fn, PCI_REG_COMMAND_STATUS); + PciRawWrite16(bus, dev, fn, PCI_REG_COMMAND_STATUS, command | PCI_COMMAND_INTX_DISABLE); + st = KeInterruptActivateMessage(request->Interrupt); + if (!KSUCCESS(st)) goto failed; + return NTLSTATUS_SUCCESS; +failed: + { + uint16_t previous = PciRawRead16(bus, dev, fn, cap + 2u); + PciRawWrite16(bus, dev, fn, cap + 2u, + previous & (uint16_t)~PCI_MSI_CTRL_ENABLE); + } + KeInterruptDisconnect(request->Interrupt); + request->Interrupt = (KE_INTERRUPT*)0; + if (request->BusContext) { + MmFreePool(request->BusContext); + request->BusContext = 0; + } + return st; +} + +__declspec(dllexport) KSTATUS PciConnectInterrupts(DEVICE_OBJECT* pdo, + PCI_INTERRUPT_REQUEST* requests, uint32_t count, bool* usingMessages) { + PCI_PDO_EXTENSION* ext; + if (!PciIsPdo(pdo, &ext) || !requests || !count || !usingMessages) + return NTLSTATUS_INVALID_PARAMETER; + *usingMessages = false; + for (uint32_t i = 0; i < count; i++) { + if (!requests[i].Routine) return NTLSTATUS_INVALID_PARAMETER; + requests[i].Interrupt = (KE_INTERRUPT*)0; + requests[i].BusContext = 0; + } + KSTATUS st = PciConnectMsix(pdo, ext, requests, count); + if (KSUCCESS(st)) { *usingMessages = true; return st; } + if (count > 1u) return st; + st = PciConnectMsi(pdo, ext, requests); + if (KSUCCESS(st)) { *usingMessages = true; return st; } + uint8_t line = ext->Info.InterruptLine; + uint8_t pin = ext->Info.InterruptPin; + if (pin < 1u || pin > 4u || line == 0u || line == 0xFFu) { + DbgPrint("pci: INTx resource unavailable for %02x:%02x.%u pin=%u line=%u\n", + ext->Info.Address.Bus, ext->Info.Address.Device, + ext->Info.Address.Function, pin, line); + return NTLSTATUS_NOT_FOUND; + } + // The Interrupt Line register is a firmware hint until PCI _PRT routing is available. + DbgPrint("pci: INTx legacy route %02x:%02x.%u pin=%u line=%u\n", + ext->Info.Address.Bus, ext->Info.Address.Device, + ext->Info.Address.Function, pin, line); + if (line < 16u) + st = KeInterruptConnectIsa(line, 0x0Fu, requests[0].Affinity, + requests[0].Routine, requests[0].Context, &requests[0].Interrupt); + else + st = KeInterruptConnectGsi(line, 0x0Fu, requests[0].Affinity, + requests[0].Routine, requests[0].Context, &requests[0].Interrupt); + if (KSUCCESS(st)) { + uint16_t command = PciRawRead16(ext->Info.Address.Bus, + ext->Info.Address.Device, ext->Info.Address.Function, PCI_REG_COMMAND_STATUS); + PciRawWrite16(ext->Info.Address.Bus, ext->Info.Address.Device, + ext->Info.Address.Function, PCI_REG_COMMAND_STATUS, + command & (uint16_t)~PCI_COMMAND_INTX_DISABLE); + } + return st; +} + +__declspec(dllexport) void PciDisconnectInterrupts(DEVICE_OBJECT* pdo, + PCI_INTERRUPT_REQUEST* requests, uint32_t count) { + PCI_PDO_EXTENSION* ext; + if (!PciIsPdo(pdo, &ext) || !requests) return; + // Close every route before disabling PCI delivery so an affinity update + // cannot resume the device after its disconnect has begun. + for (uint32_t i = 0; i < count; i++) + if (requests[i].Interrupt) KeInterruptBeginDisconnect(requests[i].Interrupt); + uint8_t bus = ext->Info.Address.Bus, dev = ext->Info.Address.Device; + uint8_t fn = ext->Info.Address.Function; + uint8_t msi = PciFindCapability(ext, PCI_CAP_ID_MSI); + uint8_t msix = PciFindCapability(ext, PCI_CAP_ID_MSIX); + if (msi) { + uint16_t control = PciRawRead16(bus, dev, fn, msi + 2u); + PciRawWrite16(bus, dev, fn, msi + 2u, control & ~PCI_MSI_CTRL_ENABLE); + } + if (msix) { + uint16_t control = PciRawRead16(bus, dev, fn, msix + 2u); + PciRawWrite16(bus, dev, fn, msix + 2u, (control | 0x4000u) & ~0x8000u); + } + uint16_t command = PciRawRead16(bus, dev, fn, PCI_REG_COMMAND_STATUS); + PciRawWrite16(bus, dev, fn, PCI_REG_COMMAND_STATUS, command | PCI_COMMAND_INTX_DISABLE); + for (uint32_t i = 0; i < count; i++) { + if (requests[i].Interrupt) { + KeInterruptDisconnect(requests[i].Interrupt); + requests[i].Interrupt = (KE_INTERRUPT*)0; + } + if (requests[i].BusContext) { + MmFreePool(requests[i].BusContext); + requests[i].BusContext = 0; + } + } +} + static KSTATUS DriverInitialize(NTL_MODULE* module) { (void)module; diff --git a/code/drivers/bus/pci/pci.h b/code/drivers/bus/pci/pci.h index d6a6796..3b91855 100644 --- a/code/drivers/bus/pci/pci.h +++ b/code/drivers/bus/pci/pci.h @@ -37,10 +37,13 @@ #define PCI_MSI_CTRL_64BIT 0x0080u #define PCI_MSI_CTRL_PVM 0x0100u -#define PCI_IRQ_VECTOR_BASE 0x20u typedef struct PCI_PDO_EXTENSION { PCI_DEVICE_INFO Info; PCI_BAR Bars[PCI_MAX_BARS]; uint8_t CapabilityOffset; + // The MSI-X table is mapped once for the lifetime of its PCI PDO. + volatile uint8_t* MsixTable; + uint64_t MsixMappedLength; + uint8_t MsixBarIndex; } PCI_PDO_EXTENSION; diff --git a/code/drivers/bus/pci/sources b/code/drivers/bus/pci/sources new file mode 100644 index 0000000..8780a02 --- /dev/null +++ b/code/drivers/bus/pci/sources @@ -0,0 +1,8 @@ +TARGETNAME=pci +TARGETPATH=obj +TARGETTYPE=DRIVER +FLAVOR=DRIVER +EXTRA_CFLAGS=/DPCI_SYS_BUILD +TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\ntlddk.lib" "$(BASEDIR)\bin\printf.lib" +EXTRA_LFLAGS=/NOENTRY /IMPLIB:"$(BASEDIR)\bin\pci.lib" +SOURCES=@/code/drivers/bus/pci/pci.c diff --git a/code/drivers/bus/usb/makefile b/code/drivers/bus/usb/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/drivers/bus/usb/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/drivers/bus/usb/sources b/code/drivers/bus/usb/sources new file mode 100644 index 0000000..cf42072 --- /dev/null +++ b/code/drivers/bus/usb/sources @@ -0,0 +1,8 @@ +TARGETNAME=usb +TARGETPATH=obj +TARGETTYPE=DRIVER +FLAVOR=DRIVER +TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\pci.lib" +EXTRA_LFLAGS=/NOENTRY +SOURCES=@/code/drivers/bus/usb/usb.c @/code/drivers/bus/usb/usb_bus.c @/code/drivers/bus/usb/usb_composite.c @/code/drivers/bus/usb/usb_core.c @/code/drivers/bus/usb/usb_xhci.c @/code/drivers/bus/usb/usb_hid.c \ + @/code/drivers/bus/usb/usb_storage.c @/code/drivers/bus/usb/usb_hub.c diff --git a/code/drivers/bus/usb/usb.h b/code/drivers/bus/usb/usb.h index fcf5169..15a9679 100644 --- a/code/drivers/bus/usb/usb.h +++ b/code/drivers/bus/usb/usb.h @@ -29,7 +29,6 @@ #if USB_DEBUG_VERBOSE #define UsbTrace DbgPrint #else -// Implements the trace operation. static __inline void UsbTrace(const char* fmt, ...) { (void)fmt; } #endif @@ -802,7 +801,7 @@ typedef struct XHCI_CONTROLLER { uint8_t Bus; uint8_t Dev; uint8_t Fn; - uint8_t Irq; + PCI_INTERRUPT_REQUEST InterruptRequest; bool UsingMsi; uint64_t MmioPhys; @@ -962,7 +961,7 @@ void XhciUnregisterWaitTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target); KSTATUS XhciWaitForArmedTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target, uint32_t timeoutUs); KSTATUS XhciWaitForTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target, uint32_t timeoutUs); void XhciEventDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2); -void XhciIsr(void); +void XhciIsr(void* context); KSTATUS XhciBiosHandoff(XHCI_CONTROLLER* xhci); KSTATUS XhciStopAndReset(XHCI_CONTROLLER* xhci); KSTATUS XhciAllocateScratchpads(XHCI_CONTROLLER* xhci); diff --git a/code/drivers/bus/usb/usb_bus.c b/code/drivers/bus/usb/usb_bus.c index bfb69a3..03882b5 100644 --- a/code/drivers/bus/usb/usb_bus.c +++ b/code/drivers/bus/usb/usb_bus.c @@ -11,7 +11,6 @@ DRIVER_OBJECT gUsbBusDriver; static bool gUsbBusModelReady; static uint8_t gUsbNextControllerIndex; -// Implements the device Destroy operation. static void UsbDeviceDestroy(OBJECT* object) { USB_DEVICE* dev = (USB_DEVICE*)object; if (dev->RemoveLockReady) { @@ -36,22 +35,18 @@ static void UsbPipeDestroy(OBJECT* object) { } } -// Implements the reference Device operation. void UsbReferenceDevice(USB_DEVICE* dev) { if (dev) ObReferenceObject(&dev->Header); } -// Implements the dereference Device operation. void UsbDereferenceDevice(USB_DEVICE* dev) { if (dev) ObDereferenceObject(&dev->Header); } -// Implements the reference Pipe operation. void UsbReferencePipe(USB_PIPE* pipe) { if (pipe) ObReferenceObject(&pipe->Header); } -// Implements the dereference Pipe operation. void UsbDereferencePipe(USB_PIPE* pipe) { if (pipe) ObDereferenceObject(&pipe->Header); } @@ -111,12 +106,10 @@ KSTATUS UsbCreatePipe(USB_DEVICE* dev, return NTLSTATUS_SUCCESS; } -// Implements the id From Buffer operation. static SYS_STRING_VIEW UsbIdFromBuffer(char* buf) { return SysSvFromCstr(buf); } -// Implements the id Put Char operation. static void UsbIdPutChar(char* buf, size_t cap, size_t* pos, char ch) { if (!buf || !pos || cap == 0) return; @@ -129,7 +122,6 @@ static void UsbIdPutChar(char* buf, size_t cap, size_t* pos, char ch) { buf[cap - 1] = '\0'; } -// Implements the id Append Literal operation. static void UsbIdAppendLiteral(char* buf, size_t cap, size_t* pos, const char* text) { if (!text) return; @@ -137,7 +129,6 @@ static void UsbIdAppendLiteral(char* buf, size_t cap, size_t* pos, const char* t UsbIdPutChar(buf, cap, pos, *text++); } -// Implements the id Append Hex operation. static void UsbIdAppendHex(char* buf, size_t cap, size_t* pos, uint32_t value, uint8_t digits) { static const char kHex[] = "0123456789ABCDEF"; while (digits) { @@ -146,7 +137,6 @@ static void UsbIdAppendHex(char* buf, size_t cap, size_t* pos, uint32_t value, u } } -// Implements the format Vid Pid Rev operation. static void UsbFormatVidPidRev(char* buf, size_t cap, uint16_t vid, uint16_t pid, uint16_t rev) { size_t pos = 0; if (cap) buf[0] = '\0'; @@ -158,7 +148,6 @@ static void UsbFormatVidPidRev(char* buf, size_t cap, uint16_t vid, uint16_t pid UsbIdAppendHex(buf, cap, &pos, rev, 4); } -// Implements the format Vid Pid operation. static void UsbFormatVidPid(char* buf, size_t cap, uint16_t vid, uint16_t pid) { size_t pos = 0; if (cap) buf[0] = '\0'; @@ -168,7 +157,6 @@ static void UsbFormatVidPid(char* buf, size_t cap, uint16_t vid, uint16_t pid) { UsbIdAppendHex(buf, cap, &pos, pid, 4); } -// Implements the format Vid Pid Mi operation. static void UsbFormatVidPidMi(char* buf, size_t cap, uint16_t vid, uint16_t pid, uint8_t mi) { size_t pos = 0; if (cap) buf[0] = '\0'; @@ -180,7 +168,6 @@ static void UsbFormatVidPidMi(char* buf, size_t cap, uint16_t vid, uint16_t pid, UsbIdAppendHex(buf, cap, &pos, mi, 2); } -// Implements the format Class Sub Prot operation. static void UsbFormatClassSubProt(char* buf, size_t cap, uint8_t cls, uint8_t sub, uint8_t proto) { size_t pos = 0; if (cap) buf[0] = '\0'; @@ -192,7 +179,6 @@ static void UsbFormatClassSubProt(char* buf, size_t cap, uint8_t cls, uint8_t su UsbIdAppendHex(buf, cap, &pos, proto, 2); } -// Implements the format Class operation. static void UsbFormatClass(char* buf, size_t cap, uint8_t cls) { size_t pos = 0; if (cap) buf[0] = '\0'; @@ -200,14 +186,12 @@ static void UsbFormatClass(char* buf, size_t cap, uint8_t cls) { UsbIdAppendHex(buf, cap, &pos, cls, 2); } -// Implements the format Composite operation. static void UsbFormatComposite(char* buf, size_t cap) { size_t pos = 0; if (cap) buf[0] = '\0'; UsbIdAppendLiteral(buf, cap, &pos, "USB\\COMPOSITE"); } -// Implements the format Root Hub operation. static void UsbFormatRootHub(char* buf, size_t cap) { size_t pos = 0; if (cap) buf[0] = '\0'; @@ -452,7 +436,6 @@ KSTATUS UsbCreateInterfacePdos(USB_HCD* hcd, XHCI_DEVICE* xdev, DEVICE_OBJECT* p return NTLSTATUS_SUCCESS; } -// Implements the reference First Child operation. static DEVICE_OBJECT* UsbReferenceFirstChild(DEVICE_OBJECT* parent) { if (!parent) return (DEVICE_OBJECT*)0; uintptr_t flags = KeAcquireSpinlock(&parent->Lock); @@ -463,7 +446,6 @@ static DEVICE_OBJECT* UsbReferenceFirstChild(DEVICE_OBJECT* parent) { return child; } -// Implements the send Pnp If Alive operation. static void UsbSendPnpIfAlive(DEVICE_OBJECT* pdo, IO_PNP_MINOR_FUNCTION minor) { if (!pdo || pdo->DeletePending) return; @@ -550,7 +532,6 @@ KSTATUS UsbSubmitUrbSync(DEVICE_OBJECT* target, USB_URB* urb) { return KSUCCESS(st) ? urb->Status : st; } -// Implements the async Urb Irp Complete operation. static void UsbAsyncUrbIrpComplete(IRP* irp, void* context) { (void)context; IoFreeIrp(irp); diff --git a/code/drivers/bus/usb/usb_composite.c b/code/drivers/bus/usb/usb_composite.c index 3cfdc63..c27ae37 100644 --- a/code/drivers/bus/usb/usb_composite.c +++ b/code/drivers/bus/usb/usb_composite.c @@ -13,7 +13,6 @@ static const IO_DRIVER_ID_TABLE gUsbCompositeIdTable = { sizeof(gUsbCompositeIds) / sizeof(gUsbCompositeIds[0]), }; -// Implements the composite Create Interfaces operation. static KSTATUS UsbCompositeCreateInterfaces(USB_COMPOSITE_EXTENSION* ext) { if (!ext || !ext->Device || ext->InterfacesCreated) return NTLSTATUS_SUCCESS; @@ -28,7 +27,6 @@ static KSTATUS UsbCompositeCreateInterfaces(USB_COMPOSITE_EXTENSION* ext) { return st; } -// Implements the composite Forward Pnp operation. static KSTATUS UsbCompositeForwardPnp(DEVICE_OBJECT* device, IRP* irp, KSTATUS localStatus) { if (!KSUCCESS(localStatus)) { IoCompleteRequest(irp, localStatus, 0); @@ -37,7 +35,6 @@ static KSTATUS UsbCompositeForwardPnp(DEVICE_OBJECT* device, IRP* irp, KSTATUS l return IoForwardIrpToLower(device, irp); } -// Implements the composite Dispatch Pnp operation. KSTATUS UsbCompositeDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp) return NTLSTATUS_INVALID_PARAMETER; @@ -114,7 +111,6 @@ KSTATUS UsbCompositeDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { } } -// Implements the composite Add Device operation. KSTATUS UsbCompositeAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return NTLSTATUS_INVALID_PARAMETER; diff --git a/code/drivers/bus/usb/usb_core.c b/code/drivers/bus/usb/usb_core.c index dde48a5..5253e9e 100644 --- a/code/drivers/bus/usb/usb_core.c +++ b/code/drivers/bus/usb/usb_core.c @@ -260,7 +260,6 @@ KSTATUS XhciDiscoverAndSetConfiguration(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, return NTLSTATUS_SUCCESS; } -// Implements the rollback Enumerated Slot operation. static void XhciRollbackEnumeratedSlot(XHCI_CONTROLLER* xhci, uint8_t slotId) { if (!xhci || slotId == 0 || slotId > XHCI_MAX_TRACKED_SLOTS) return; @@ -399,7 +398,6 @@ static KSTATUS XhciEnumeratePathEx(XHCI_CONTROLLER* xhci, return NTLSTATUS_SUCCESS; } -// Implements the enumerate Port Ex operation. KSTATUS XhciEnumeratePortEx(XHCI_CONTROLLER* xhci, uint8_t port, uint8_t* outSlotId) { if (outSlotId) *outSlotId = 0; @@ -449,12 +447,10 @@ KSTATUS XhciEnumerateHubPortEx(XHCI_CONTROLLER* xhci, return XhciEnumeratePathEx(xhci, hubPort, speed, &path, hub->Self, outSlotId); } -// Implements the enumerate Port operation. KSTATUS XhciEnumeratePort(XHCI_CONTROLLER* xhci, uint8_t port) { return XhciEnumeratePortEx(xhci, port, (uint8_t*)0); } -// Implements the enumerate Root Ports operation. void XhciEnumerateRootPorts(XHCI_CONTROLLER* xhci) { uint32_t attempted = 0; uint32_t configured = 0; diff --git a/code/drivers/bus/usb/usb_hid.c b/code/drivers/bus/usb/usb_hid.c index 1005d4d..a9bade8 100644 --- a/code/drivers/bus/usb/usb_hid.c +++ b/code/drivers/bus/usb/usb_hid.c @@ -12,7 +12,6 @@ static void UsbHidReleaseDma(USB_HID_EXTENSION* ext) { ext->ReportBufferDeviceAddress = 0; } -// Implements the hid Key In Report operation. bool XhciHidKeyInReport(const uint8_t* keys, uint8_t key) { if (key == 0 || key == 1) return false; for (uint8_t i = 0; i < 6; i++) { @@ -94,7 +93,6 @@ void XhciProcessBootMouseReport(XHCI_DEVICE* dev, const uint8_t* report, uint16_ dev->HidLastButtons = buttons; } -// Implements the arm Hid Interrupt In operation. KSTATUS XhciArmHidInterruptIn(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { if (!dev->HidActive || dev->HidArmed || !dev->HidRing || !dev->HidBuffer) return NTLSTATUS_SUCCESS; @@ -122,7 +120,6 @@ KSTATUS XhciArmHidInterruptIn(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { return NTLSTATUS_SUCCESS; } -// Implements the arm All Hid operation. void XhciArmAllHid(XHCI_CONTROLLER* xhci) { for (uint8_t slot = 1; slot <= XHCI_MAX_TRACKED_SLOTS; slot++) { XHCI_DEVICE* dev = &xhci->Devices[slot]; @@ -241,7 +238,6 @@ KSTATUS XhciAllocateHidMemory(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { return NTLSTATUS_SUCCESS; } -// Implements the configure Hid Endpoint operation. KSTATUS XhciConfigureHidEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { if (!dev->HidCandidate) return NTLSTATUS_SUCCESS; @@ -328,7 +324,6 @@ static const IO_DRIVER_ID_TABLE gUsbHidIdTable = { sizeof(gUsbHidIds) / sizeof(gUsbHidIds[0]), }; -// Implements the hid Is Qemu Absolute Tablet Pdo operation. static bool UsbHidIsQemuAbsoluteTabletPdo(const USB_PDO_EXTENSION* pdoExt, const USB_ENDPOINT_DESCRIPTOR* ep) { if (!pdoExt || !pdoExt->Device || !ep) return false; @@ -347,7 +342,6 @@ static bool UsbHidIsQemuAbsoluteTabletPdo(const USB_PDO_EXTENSION* pdoExt, const return (ep->wMaxPacketSize & 0x07FFu) >= 6u; } -// Implements the hid Find Interrupt In Pdo operation. static const USB_ENDPOINT_DESCRIPTOR* UsbHidFindInterruptInPdo(const USB_PDO_EXTENSION* ext) { if (!ext) return (const USB_ENDPOINT_DESCRIPTOR*)0; @@ -361,7 +355,6 @@ static const USB_ENDPOINT_DESCRIPTOR* UsbHidFindInterruptInPdo(const USB_PDO_EXT return (const USB_ENDPOINT_DESCRIPTOR*)0; } -// Implements the hid Process Boot Keyboard Report operation. static void UsbHidProcessBootKeyboardReport(USB_HID_EXTENSION* ext, const uint8_t* report, uint16_t len) { if (!ext || len < 8) return; @@ -390,7 +383,6 @@ static void UsbHidProcessBootKeyboardReport(USB_HID_EXTENSION* ext, const uint8_ memcpy(ext->LastKeys, keys, sizeof(ext->LastKeys)); } -// Implements the hid Process Boot Mouse Report operation. static void UsbHidProcessBootMouseReport(USB_HID_EXTENSION* ext, const uint8_t* report, uint16_t len) { if (!ext || len < 3) return; @@ -411,7 +403,6 @@ static void UsbHidProcessBootMouseReport(USB_HID_EXTENSION* ext, const uint8_t* ext->LastButtons = buttons; } -// Implements the hid Process Qemu Tablet Report operation. static void UsbHidProcessQemuTabletReport(USB_HID_EXTENSION* ext, const uint8_t* report, uint16_t len) { if (!ext || len < 5) return; @@ -432,7 +423,6 @@ static void UsbHidProcessQemuTabletReport(USB_HID_EXTENSION* ext, const uint8_t* static KSTATUS UsbHidArmInterrupt(USB_HID_EXTENSION* ext); -// Implements the hid Interrupt Complete operation. static void UsbHidInterruptComplete(USB_URB* urb, void* context) { USB_HID_EXTENSION* ext = (USB_HID_EXTENSION*)context; if (!ext || urb != &ext->InterruptUrb) @@ -470,7 +460,6 @@ static void UsbHidInterruptComplete(USB_URB* urb, void* context) { IoReleaseRemoveLock(&ext->RemoveLock, (IRP*)0); } -// Implements the hid Send Boot Protocol operation. static KSTATUS UsbHidSendBootProtocol(USB_HID_EXTENSION* ext) { if (!ext || !ext->LowerDevice || !ext->Device) return NTLSTATUS_INVALID_PARAMETER; @@ -514,7 +503,6 @@ static KSTATUS UsbHidSendBootProtocol(USB_HID_EXTENSION* ext) { return NTLSTATUS_SUCCESS; } -// Implements the hid Arm Interrupt operation. static KSTATUS UsbHidArmInterrupt(USB_HID_EXTENSION* ext) { if (!ext || !ext->Started || ext->SurpriseRemoved || ext->Removed) return NTLSTATUS_OBJECT_DEAD; @@ -551,7 +539,6 @@ static KSTATUS UsbHidArmInterrupt(USB_HID_EXTENSION* ext) { return NTLSTATUS_SUCCESS; } -// Implements the hid Start Device operation. static KSTATUS UsbHidStartDevice(DEVICE_OBJECT* device, USB_HID_EXTENSION* ext) { if (!device || !ext || !ext->Device || !ext->InterfacePdo) return NTLSTATUS_INVALID_PARAMETER; @@ -660,7 +647,6 @@ static KSTATUS UsbHidStartDevice(DEVICE_OBJECT* device, USB_HID_EXTENSION* ext) return NTLSTATUS_SUCCESS; } -// Implements the hid Dispatch Pnp operation. KSTATUS UsbHidDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp) return NTLSTATUS_INVALID_PARAMETER; @@ -758,7 +744,6 @@ KSTATUS UsbHidDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { } } -// Implements the hid Add Device operation. KSTATUS UsbHidAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return NTLSTATUS_INVALID_PARAMETER; diff --git a/code/drivers/bus/usb/usb_hub.c b/code/drivers/bus/usb/usb_hub.c index e27046b..458fd44 100644 --- a/code/drivers/bus/usb/usb_hub.c +++ b/code/drivers/bus/usb/usb_hub.c @@ -31,19 +31,16 @@ static const IO_DRIVER_ID_TABLE gUsbHubIdTable = { #define USB_HUB_PORT_ENUMERATING 0xffu #define USB_HUB_PORT_FAILED 0xfeu -// Implements the hub Slot Busy operation. static bool UsbHubSlotBusy(uint8_t slot) { return slot != 0 && slot != USB_HUB_PORT_ENUMERATING && slot != USB_HUB_PORT_FAILED; } -// Implements the hub Root Port Connected operation. static bool UsbHubRootPortConnected(XHCI_CONTROLLER* xhci, uint8_t port) { if (!xhci || !xhci->Op || port == 0) return false; uint32_t portsc = XhciRead32(xhci->Op, XhciPortReg(port)); return (portsc & XHCI_PORTSC_CCS) != 0; } -// Implements the hub Clear Root Port Failure operation. static void UsbHubClearRootPortFailure(USB_HUB_EXTENSION* hub, uint8_t port) { if (!hub || port == 0 || port > USB_ROOT_HUB_MAX_PORTS) return; hub->RootPortFailCount[port] = 0; @@ -51,7 +48,6 @@ static void UsbHubClearRootPortFailure(USB_HUB_EXTENSION* hub, uint8_t port) { hub->RootPortSlot[port] = 0; } -// Implements the hub Mark Root Port Failed operation. static void UsbHubMarkRootPortFailed(USB_HUB_EXTENSION* hub, uint8_t port) { if (!hub || port == 0 || port > USB_ROOT_HUB_MAX_PORTS) return; hub->RootPortSlot[port] = USB_HUB_PORT_FAILED; @@ -146,7 +142,6 @@ static KSTATUS UsbHubEnumerateConnectedRootPort(USB_HUB_EXTENSION* hub, return status; } -// Implements the hub Pop Pending Root Port operation. static bool UsbHubPopPendingRootPort(USB_HUB_EXTENSION* hub, uint8_t* outPort) { if (!hub || !outPort) return false; @@ -168,7 +163,6 @@ static bool UsbHubPopPendingRootPort(USB_HUB_EXTENSION* hub, uint8_t* outPort) { return false; } -// Implements the hub Pop Pending External Port operation. static bool UsbHubPopPendingExternalPort(USB_HUB_EXTENSION* hub, uint8_t* outPort) { if (!hub || !outPort) return false; @@ -193,7 +187,6 @@ static bool UsbHubPopPendingExternalPort(USB_HUB_EXTENSION* hub, uint8_t* outPor return false; } -// Implements the hub Record Root Port Change operation. static void UsbHubRecordRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) { if (!hub || port == 0 || port > hub->PortCount) return; @@ -206,7 +199,6 @@ static void UsbHubRecordRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) { KeSignalSemaphore(hub->WorkerSemaphore); } -// Implements the hub Queue External Port Change operation. void UsbHubQueueExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port) { if (!hub || port == 0 || port > hub->PortCount || port > USB_EXTERNAL_HUB_MAX_PORTS) return; @@ -217,7 +209,6 @@ void UsbHubQueueExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port) { KeSignalSemaphore(hub->WorkerSemaphore); } -// Implements the hub Remove Slot Child operation. static void UsbHubRemoveSlotChild(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t slot) { if (!hub || !hub->Hcd || slot == 0) return; @@ -253,7 +244,6 @@ static void UsbHubRemoveSlotChild(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t } } -// Implements the hub Remove Root Child operation. static void UsbHubRemoveRootChild(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t slot) { UsbHubRemoveSlotChild(hub, port, slot); } @@ -306,7 +296,6 @@ static KSTATUS UsbHubControlNoData(USB_HUB_EXTENSION* hub, return UsbSubmitUrbSync(hub->LowerDevice, &urb); } -// Implements the hub Read Descriptor operation. static KSTATUS UsbHubReadDescriptor(USB_HUB_EXTENSION* hub, USB_HUB_DESCRIPTOR* outDesc) { if (!hub || !outDesc || !hub->ChangeBitmap || !hub->ChangeBitmapDeviceAddress) return NTLSTATUS_INVALID_PARAMETER; @@ -329,7 +318,6 @@ static KSTATUS UsbHubReadDescriptor(USB_HUB_EXTENSION* hub, USB_HUB_DESCRIPTOR* return NTLSTATUS_SUCCESS; } -// Implements the hub Get Port Status operation. static KSTATUS UsbHubGetPortStatus(USB_HUB_EXTENSION* hub, uint8_t port, USB_HUB_PORT_STATUS* outStatus) { if (!hub || !outStatus || port == 0) return NTLSTATUS_INVALID_PARAMETER; @@ -350,7 +338,6 @@ static KSTATUS UsbHubGetPortStatus(USB_HUB_EXTENSION* hub, uint8_t port, USB_HUB return NTLSTATUS_SUCCESS; } -// Implements the hub Set Port Feature operation. static KSTATUS UsbHubSetPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint16_t feature) { return UsbHubControlNoData(hub, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER, @@ -359,7 +346,6 @@ static KSTATUS UsbHubSetPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint16 port); } -// Implements the hub Clear Port Feature operation. static KSTATUS UsbHubClearPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint16_t feature) { return UsbHubControlNoData(hub, USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_OTHER, @@ -368,7 +354,6 @@ static KSTATUS UsbHubClearPortFeature(USB_HUB_EXTENSION* hub, uint8_t port, uint port); } -// Implements the hub Speed From Port Status operation. static uint8_t UsbHubSpeedFromPortStatus(uint16_t status) { if (status & USB_HUB_PORT_STATUS_LOW_SPEED) return 2u; @@ -377,7 +362,6 @@ static uint8_t UsbHubSpeedFromPortStatus(uint16_t status) { return 1u; } -// Implements the hub Reset External Port operation. static KSTATUS UsbHubResetExternalPort(USB_HUB_EXTENSION* hub, uint8_t port, uint8_t* outSpeed) { if (outSpeed) *outSpeed = 0; if (!hub || port == 0) @@ -426,7 +410,6 @@ static KSTATUS UsbHubResetExternalPort(USB_HUB_EXTENSION* hub, uint8_t port, uin return NTLSTATUS_SUCCESS; } -// Implements the hub Handle External Port Change operation. static void UsbHubHandleExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port) { if (!hub || hub->Kind != UsbHubKindExternal || port == 0 || port > hub->PortCount || port > USB_EXTERNAL_HUB_MAX_PORTS) return; @@ -509,7 +492,6 @@ static void UsbHubHandleExternalPortChange(USB_HUB_EXTENSION* hub, uint8_t port) } } -// Implements the hub Handle Root Port Change operation. static void UsbHubHandleRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) { if (!hub || !hub->Hcd || port == 0 || port > hub->PortCount || port > USB_ROOT_HUB_MAX_PORTS) return; @@ -575,7 +557,6 @@ static void UsbHubHandleRootPortChange(USB_HUB_EXTENSION* hub, uint8_t port) { static void UsbHubArmExternalInterrupt(USB_HUB_EXTENSION* hub); static KSTATUS UsbHubDoRootPortScan(USB_HCD* hcd); -// Implements the hub Take Initial Root Scan operation. static bool UsbHubTakeInitialRootScan(USB_HUB_EXTENSION* hub) { if (!hub || hub->Kind != UsbHubKindRoot) return false; @@ -589,7 +570,6 @@ static bool UsbHubTakeInitialRootScan(USB_HUB_EXTENSION* hub) { return take; } -// Implements the hub Worker operation. static void UsbHubWorker(void* arg) { USB_HUB_EXTENSION* hub = (USB_HUB_EXTENSION*)arg; if (hub && hub->Kind == UsbHubKindRoot && hub->Hcd) { @@ -687,7 +667,6 @@ static KSTATUS UsbHubStartWorker(USB_HUB_EXTENSION* hub) { return NTLSTATUS_SUCCESS; } -// Implements the hub Do Root Port Scan operation. static KSTATUS UsbHubDoRootPortScan(USB_HCD* hcd) { if (!hcd || !hcd->RootHubContext) return NTLSTATUS_INVALID_PARAMETER; @@ -774,7 +753,6 @@ KSTATUS UsbHubScheduleRootScan(USB_HCD* hcd) { return NTLSTATUS_SUCCESS; } -// Implements the hub Queue Root Port Change operation. void UsbHubQueueRootPortChange(USB_HCD* hcd, uint8_t port) { if (!hcd || !hcd->RootHubContext) return; @@ -782,7 +760,6 @@ void UsbHubQueueRootPortChange(USB_HCD* hcd, uint8_t port) { UsbHubRecordRootPortChange(hub, port); } -// Implements the hub Scan External Ports operation. static KSTATUS UsbHubScanExternalPorts(USB_HUB_EXTENSION* hub) { if (!hub || hub->Kind != UsbHubKindExternal) return NTLSTATUS_INVALID_PARAMETER; @@ -810,7 +787,6 @@ static KSTATUS UsbHubScanExternalPorts(USB_HUB_EXTENSION* hub) { return NTLSTATUS_SUCCESS; } -// Implements the hub Find Interrupt In operation. static const USB_ENDPOINT_DESCRIPTOR* UsbHubFindInterruptIn(USB_PDO_EXTENSION* pdoExt) { if (!pdoExt) return (const USB_ENDPOINT_DESCRIPTOR*)0; @@ -844,7 +820,6 @@ static const USB_ENDPOINT_DESCRIPTOR* UsbHubFindInterruptIn(USB_PDO_EXTENSION* p return (const USB_ENDPOINT_DESCRIPTOR*)0; } -// Implements the hub External Change Complete operation. static void UsbHubExternalChangeComplete(USB_URB* urb, void* context) { USB_HUB_EXTENSION* hub = (USB_HUB_EXTENSION*)context; if (!hub || urb != &hub->ChangeUrb) @@ -869,7 +844,6 @@ static void UsbHubExternalChangeComplete(USB_URB* urb, void* context) { IoReleaseRemoveLock(&hub->RemoveLock, (IRP*)0); } -// Implements the hub Arm External Interrupt operation. static void UsbHubArmExternalInterrupt(USB_HUB_EXTENSION* hub) { if (!hub || !hub->InterruptPipe || !hub->ChangeBitmap || hub->ChangeUrbPending) return; @@ -902,7 +876,6 @@ static void UsbHubArmExternalInterrupt(USB_HUB_EXTENSION* hub) { } } -// Implements the hub Start Root Device operation. static KSTATUS UsbHubStartRootDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub) { hub->PortCount = hub->Hcd ? hub->Hcd->MaxRootPorts : 0; if (hub->PortCount > USB_ROOT_HUB_MAX_PORTS) @@ -939,7 +912,6 @@ static KSTATUS UsbHubStartRootDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* h return NTLSTATUS_SUCCESS; } -// Implements the hub Start External Device operation. static KSTATUS UsbHubStartExternalDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub) { if (!hub || !hub->Device) return NTLSTATUS_INVALID_PARAMETER; @@ -1019,7 +991,6 @@ static KSTATUS UsbHubStartExternalDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSIO return NTLSTATUS_SUCCESS; } -// Implements the hub Start Device operation. static KSTATUS UsbHubStartDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub) { if (!device || !hub || hub->Started) return NTLSTATUS_SUCCESS; @@ -1029,7 +1000,6 @@ static KSTATUS UsbHubStartDevice(DEVICE_OBJECT* device, USB_HUB_EXTENSION* hub) return UsbHubStartExternalDevice(device, hub); } -// Implements the hub Dispatch Pnp operation. KSTATUS UsbHubDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp) return NTLSTATUS_INVALID_PARAMETER; @@ -1154,7 +1124,6 @@ KSTATUS UsbHubDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { } } -// Implements the hub Add Device operation. KSTATUS UsbHubAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return NTLSTATUS_INVALID_PARAMETER; diff --git a/code/drivers/bus/usb/usb_storage.c b/code/drivers/bus/usb/usb_storage.c index ac03df4..8162d09 100644 --- a/code/drivers/bus/usb/usb_storage.c +++ b/code/drivers/bus/usb/usb_storage.c @@ -21,7 +21,6 @@ static const IO_DRIVER_ID_TABLE gUsbStorageIdTable = { sizeof(gUsbStorageIds) / sizeof(gUsbStorageIds[0]), }; -// Implements the storage From Disk Device operation. static USB_STORAGE_EXTENSION* UsbStorageFromDiskDevice(DEVICE_OBJECT* device) { if (!device || !device->DeviceExtension) return (USB_STORAGE_EXTENSION*)0; @@ -32,7 +31,6 @@ static USB_STORAGE_EXTENSION* UsbStorageFromDiskDevice(DEVICE_OBJECT* device) { return diskExt->Storage; } -// Implements the storage From Interface Device operation. static USB_STORAGE_EXTENSION* UsbStorageFromInterfaceDevice(DEVICE_OBJECT* device) { if (!device || !device->DeviceExtension) return (USB_STORAGE_EXTENSION*)0; @@ -43,7 +41,6 @@ static USB_STORAGE_EXTENSION* UsbStorageFromInterfaceDevice(DEVICE_OBJECT* devic return ext; } -// Implements the storage Find Bulk Endpoint operation. static const USB_ENDPOINT_DESCRIPTOR* UsbStorageFindBulkEndpoint(const USB_PDO_EXTENSION* pdoExt, bool wantIn) { if (!pdoExt) return (const USB_ENDPOINT_DESCRIPTOR*)0; @@ -290,7 +287,6 @@ KSTATUS UsbStorageBotCommand(USB_STORAGE_EXTENSION* storage, (USB_STORAGE_SENSE_DATA*)0); } -// Implements the be32 operation. uint32_t UsbBe32(const uint8_t* p) { return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3]; @@ -310,7 +306,6 @@ void UsbStoreBe16(uint8_t* p, uint16_t v) { p[1] = (uint8_t)v; } -// Implements the storage Inquiry operation. KSTATUS UsbStorageInquiry(USB_STORAGE_EXTENSION* storage) { if (!storage || !storage->XhciDevice) return NTLSTATUS_INVALID_PARAMETER; @@ -332,7 +327,6 @@ KSTATUS UsbStorageInquiry(USB_STORAGE_EXTENSION* storage) { return NTLSTATUS_SUCCESS; } -// Implements the storage Test Unit Ready operation. KSTATUS UsbStorageTestUnitReady(USB_STORAGE_EXTENSION* storage) { if (!storage || !storage->XhciDevice) return NTLSTATUS_INVALID_PARAMETER; @@ -353,7 +347,6 @@ KSTATUS UsbStorageTestUnitReady(USB_STORAGE_EXTENSION* storage) { return last; } -// Implements the storage Read Capacity operation. KSTATUS UsbStorageReadCapacity(USB_STORAGE_EXTENSION* storage) { if (!storage || !storage->XhciDevice) return NTLSTATUS_INVALID_PARAMETER; @@ -463,7 +456,6 @@ static KSTATUS UsbStorageSynchronizeCache(USB_STORAGE_EXTENSION* storage) { return NTLSTATUS_DEVICE_ERROR; } -// Implements the storage Acquire Io operation. void UsbStorageAcquireIo(USB_STORAGE_EXTENSION* storage) { if (!storage) return; XHCI_CONTROLLER* xhci = storage->Device ? (XHCI_CONTROLLER*)storage->Device->Hcd->ControllerContext : (XHCI_CONTROLLER*)0; @@ -472,12 +464,10 @@ void UsbStorageAcquireIo(USB_STORAGE_EXTENSION* storage) { } } -// Implements the storage Release Io operation. void UsbStorageReleaseIo(USB_STORAGE_EXTENSION* storage) { if (storage) NtlAtomicExchange32(&storage->IoBusy, 0); } -// Implements the storage Dispatch Read Write operation. KSTATUS UsbStorageDispatchReadWrite(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp) return NTLSTATUS_INVALID_PARAMETER; @@ -608,7 +598,6 @@ KSTATUS XhciAllocateMassStorageMemory(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { return NTLSTATUS_SUCCESS; } -// Implements the configure Mass Storage Endpoints operation. KSTATUS XhciConfigureMassStorageEndpoints(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { if (!dev->MassCandidate) return NTLSTATUS_SUCCESS; @@ -687,7 +676,6 @@ uint8_t UsbFindFreeDiskIndex(void) { return 0xFFu; } -// Implements the storage Register Disk operation. KSTATUS UsbStorageRegisterDisk(USB_STORAGE_EXTENSION* storage) { if (!storage || storage->BlockSize != USB_STORAGE_SECTOR_SIZE || storage->BlockCount == 0) return NTLSTATUS_NOT_SUPPORTED; @@ -731,7 +719,6 @@ KSTATUS UsbStorageRegisterDisk(USB_STORAGE_EXTENSION* storage) { return NTLSTATUS_SUCCESS; } -// Implements the storage Start Device operation. static KSTATUS UsbStorageStartDevice(DEVICE_OBJECT* device, USB_STORAGE_EXTENSION* storage) { if (!device || !storage || !storage->InterfacePdo || !storage->Device) return NTLSTATUS_INVALID_PARAMETER; @@ -849,7 +836,6 @@ fail: return st; } -// Implements the storage Disk Pnp operation. static KSTATUS UsbStorageDiskPnp(DEVICE_OBJECT* device, IRP* irp, USB_STORAGE_EXTENSION* storage, IO_PNP_MINOR_FUNCTION minor) { if (!device || !irp || !storage) return NTLSTATUS_INVALID_PARAMETER; @@ -900,7 +886,6 @@ static KSTATUS UsbStorageDiskPnp(DEVICE_OBJECT* device, IRP* irp, USB_STORAGE_EX } } -// Implements the storage Interface Pnp operation. static KSTATUS UsbStorageInterfacePnp(DEVICE_OBJECT* device, IRP* irp, USB_STORAGE_EXTENSION* storage, IO_PNP_MINOR_FUNCTION minor) { if (!device || !irp || !storage) return NTLSTATUS_INVALID_PARAMETER; @@ -978,7 +963,6 @@ static KSTATUS UsbStorageInterfacePnp(DEVICE_OBJECT* device, IRP* irp, USB_STORA } } -// Implements the storage Dispatch Pnp operation. KSTATUS UsbStorageDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp) return NTLSTATUS_INVALID_PARAMETER; @@ -998,7 +982,6 @@ KSTATUS UsbStorageDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { return NTLSTATUS_INVALID_PARAMETER; } -// Implements the storage Add Device operation. KSTATUS UsbStorageAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return NTLSTATUS_INVALID_PARAMETER; diff --git a/code/drivers/bus/usb/usb_xhci.c b/code/drivers/bus/usb/usb_xhci.c index f5aa3cd..9c17c78 100644 --- a/code/drivers/bus/usb/usb_xhci.c +++ b/code/drivers/bus/usb/usb_xhci.c @@ -2,52 +2,43 @@ #include "usb.h" -// Implements the align Up32 operation. uint32_t UsbAlignUp32(uint32_t value, uint32_t align) { return (value + align - 1u) & ~(align - 1u); } -// Implements the barrier operation. void XhciBarrier(void) { _ReadWriteBarrier(); _mm_mfence(); _ReadWriteBarrier(); } -// Implements the read8 operation. uint8_t XhciRead8(volatile uint8_t* base, uint32_t reg) { return *(volatile uint8_t*)(base + reg); } -// Implements the read16 operation. uint16_t XhciRead16(volatile uint8_t* base, uint32_t reg) { return *(volatile uint16_t*)(base + reg); } -// Implements the read32 operation. uint32_t XhciRead32(volatile uint8_t* base, uint32_t reg) { return *(volatile uint32_t*)(base + reg); } -// Implements the write32 operation. void XhciWrite32(volatile uint8_t* base, uint32_t reg, uint32_t value) { *(volatile uint32_t*)(base + reg) = value; } -// Implements the read64 operation. uint64_t XhciRead64(volatile uint8_t* base, uint32_t reg) { uint32_t lo = XhciRead32(base, reg); uint32_t hi = XhciRead32(base, reg + 4u); return ((uint64_t)hi << 32) | lo; } -// Implements the write64 operation. void XhciWrite64(volatile uint8_t* base, uint32_t reg, uint64_t value) { XhciWrite32(base, reg, (uint32_t)value); XhciWrite32(base, reg + 4u, (uint32_t)(value >> 32)); } -// Implements the delay Us operation. void UsbDelayUs(uint32_t us) { KeStallExecution(us); } @@ -169,43 +160,35 @@ static void XhciReleaseControllerDma(XHCI_CONTROLLER* xhci) { xhci->DmaAdapter = (IO_DMA_ADAPTER*)0; } -// Implements the scratchpad Count operation. uint16_t XhciScratchpadCount(uint32_t hcs2) { return (uint16_t)((((hcs2 >> 16) & 0x3E0u) | ((hcs2 >> 27) & 0x1Fu)) & 0x3FFu); } -// Implements the trb Type operation. uint32_t XhciTrbType(const XHCI_TRB* trb) { return (trb->Control >> XHCI_TRB_TYPE_SHIFT) & XHCI_TRB_TYPE_MASK; } -// Implements the completion Code operation. uint32_t XhciCompletionCode(const XHCI_TRB* trb) { return (trb->Status >> 24) & 0xFFu; } -// Implements the event Slot Id operation. uint8_t XhciEventSlotId(const XHCI_TRB* trb) { return (uint8_t)(trb->Control >> 24); } -// Implements the event Endpoint Id operation. uint8_t XhciEventEndpointId(const XHCI_TRB* trb) { return (uint8_t)((trb->Control >> 16) & 0x1Fu); } -// Implements the transfer Residue operation. uint32_t XhciTransferResidue(const XHCI_TRB* trb) { return trb->Status & 0xFFFFFFu; } -// Implements the input Control Context operation. uint32_t* XhciInputControlContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { (void)xhci; return (uint32_t*)dev->InputContext; } -// Implements the input Slot Context operation. uint32_t* XhciInputSlotContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { return (uint32_t*)(dev->InputContext + xhci->ContextBytes); } @@ -285,7 +268,6 @@ KSTATUS XhciConfigureHubContext(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, return NTLSTATUS_SUCCESS; } -// Implements the ep Max Packet operation. uint32_t XhciEpMaxPacket(uint8_t speed) { switch (speed) { case 2: return 8; // low-speed @@ -297,7 +279,6 @@ uint32_t XhciEpMaxPacket(uint8_t speed) { } } -// Implements the setup Packet To U64 operation. uint64_t UsbSetupPacketToU64(const USB_SETUP_PACKET* setup) { uint64_t v = 0; v |= (uint64_t)setup->bmRequestType; @@ -385,7 +366,6 @@ void XhciParseSupportedProtocols(XHCI_CONTROLLER* xhci) { (uint32_t)xhci->MaxPorts - usb2Ports - usb3Ports); } -// Implements the port Protocol Major operation. uint8_t XhciPortProtocolMajor(XHCI_CONTROLLER* xhci, uint8_t port, uint32_t portsc) { if (port <= XHCI_MAX_ROOT_PORTS && xhci->PortProtocolMajor[port]) return xhci->PortProtocolMajor[port]; @@ -426,7 +406,6 @@ const char* UsbInterfaceClassName(uint8_t klass, uint8_t subclass, uint8_t proto return "class"; } -// Implements the log Port Status operation. void XhciLogPortStatus(XHCI_CONTROLLER* xhci) { for (uint8_t port = 1; port <= xhci->MaxPorts; port++) { uint32_t off = XHCI_OP_PORT_BASE + ((uint32_t)port - 1u) * XHCI_OP_PORT_STRIDE; @@ -448,7 +427,6 @@ void XhciLogPortStatus(XHCI_CONTROLLER* xhci) { } } -// Implements the power Root Ports operation. void XhciPowerRootPorts(XHCI_CONTROLLER* xhci) { if (!xhci || !xhci->Op) return; @@ -474,7 +452,6 @@ void XhciPowerRootPorts(XHCI_CONTROLLER* xhci) { } } -// Implements the ack Interrupter0 operation. void XhciAckInterrupter0(XHCI_CONTROLLER* xhci) { if (!xhci->Runtime) return; volatile uint8_t* ir0 = xhci->Runtime + 0x20u; @@ -680,7 +657,6 @@ void XhciRegisterWaitTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target) { KeReleaseSpinlock(&xhci->WaitLock, flags); } -// Implements the unregister Wait Target operation. void XhciUnregisterWaitTarget(XHCI_CONTROLLER* xhci, XHCI_WAIT_TARGET* target) { if (!xhci || !target || !target->Registered) return; @@ -761,58 +737,18 @@ void XhciEventDpcRoutine(KDPC* dpc, void* context, } #define XHCI_CONTROLLER_MAGIC 0x58484349u // XHCI -#define XHCI_MAX_CONTROLLERS 8u - -static XHCI_CONTROLLER* gXhciControllers[XHCI_MAX_CONTROLLERS]; -static uint32_t gXhciControllerCount; - -// Registers controller. -static KSTATUS XhciRegisterController(XHCI_CONTROLLER* xhci) { - if (!xhci) return NTLSTATUS_INVALID_PARAMETER; - for (uint32_t i = 0; i < gXhciControllerCount; i++) { - if (gXhciControllers[i] == xhci) - return NTLSTATUS_SUCCESS; - } - if (gXhciControllerCount >= XHCI_MAX_CONTROLLERS) - return NTLSTATUS_NO_MEMORY; - gXhciControllers[gXhciControllerCount++] = xhci; - return NTLSTATUS_SUCCESS; -} - -// Removes a controller from the interrupt-dispatch registry. -static void XhciUnregisterController(XHCI_CONTROLLER* xhci) { - if (!xhci) +void XhciIsr(void* context) { + XHCI_CONTROLLER* xhci = (XHCI_CONTROLLER*)context; + if (!xhci || !xhci->Running || !xhci->Op || !xhci->Runtime) return; + uint32_t status = XhciRead32(xhci->Op, XHCI_OP_USBSTS); + if (!(status & (XHCI_USBSTS_EINT | XHCI_USBSTS_PCD | XHCI_USBSTS_HSE | XHCI_USBSTS_HCE))) return; - for (uint32_t i = 0; i < gXhciControllerCount; i++) { - if (gXhciControllers[i] != xhci) - continue; - for (uint32_t next = i + 1; next < gXhciControllerCount; next++) - gXhciControllers[next - 1] = gXhciControllers[next]; - gXhciControllerCount--; - gXhciControllers[gXhciControllerCount] = (XHCI_CONTROLLER*)0; - return; - } + xhci->InterruptCount++; + XhciWrite32(xhci->Op, XHCI_OP_USBSTS, status & XHCI_USBSTS_CLEAR_MASK); + XhciAckInterrupter0(xhci); + KeInsertQueueDpc(&xhci->EventDpc, (void*)0, (void*)0); } -// Implements the isr operation. -void XhciIsr(void) { - for (uint32_t i = 0; i < gXhciControllerCount; i++) { - XHCI_CONTROLLER* xhci = gXhciControllers[i]; - if (!xhci || !xhci->Running || !xhci->Op || !xhci->Runtime) - continue; - - uint32_t status = XhciRead32(xhci->Op, XHCI_OP_USBSTS); - if (!(status & (XHCI_USBSTS_EINT | XHCI_USBSTS_PCD | XHCI_USBSTS_HSE | XHCI_USBSTS_HCE))) - continue; - - xhci->InterruptCount++; - XhciWrite32(xhci->Op, XHCI_OP_USBSTS, status & XHCI_USBSTS_CLEAR_MASK); - XhciAckInterrupter0(xhci); - KeInsertQueueDpc(&xhci->EventDpc, (void*)0, (void*)0); - } -} - -// Implements the bios Handoff operation. KSTATUS XhciBiosHandoff(XHCI_CONTROLLER* xhci) { uint32_t xecp = (xhci->Hcc1 >> 16) & 0xFFFFu; if (!xecp) return NTLSTATUS_SUCCESS; @@ -856,7 +792,6 @@ KSTATUS XhciBiosHandoff(XHCI_CONTROLLER* xhci) { return NTLSTATUS_SUCCESS; } -// Implements the stop And Reset operation. KSTATUS XhciStopAndReset(XHCI_CONTROLLER* xhci) { uint32_t cmd = XhciRead32(xhci->Op, XHCI_OP_USBCMD); if (cmd & XHCI_USBCMD_RS) { @@ -991,7 +926,6 @@ KSTATUS XhciAllocateRuntimeMemory(XHCI_CONTROLLER* xhci) { return NTLSTATUS_SUCCESS; } -// Implements the program Runtime operation. KSTATUS XhciProgramRuntime(XHCI_CONTROLLER* xhci) { uint8_t slots = xhci->MaxSlots; if (slots == 0) return NTLSTATUS_DEVICE_ERROR; @@ -1159,7 +1093,6 @@ KSTATUS XhciDisableSlot(XHCI_CONTROLLER* xhci, uint8_t slotId) { return NTLSTATUS_SUCCESS; } -// Implements the address Device operation. KSTATUS XhciAddressDevice(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev) { XHCI_COMMAND_RESULT result; memset(&result, 0, sizeof(result)); @@ -1206,7 +1139,6 @@ void XhciEnableInterrupts(XHCI_CONTROLLER* xhci) { XhciWrite32(xhci->Op, XHCI_OP_USBCMD, cmd | XHCI_USBCMD_INTE | XHCI_USBCMD_HSEE); } -// Implements the port Reg operation. uint32_t XhciPortReg(uint8_t port) { return XHCI_OP_PORT_BASE + ((uint32_t)port - 1u) * XHCI_OP_PORT_STRIDE; } @@ -1227,7 +1159,6 @@ void XhciClearPortChanges(XHCI_CONTROLLER* xhci, uint8_t port) { } } -// Implements the reset Port operation. KSTATUS XhciResetPort(XHCI_CONTROLLER* xhci, uint8_t port, uint8_t* outSpeed) { uint32_t off = XhciPortReg(port); uint32_t portsc = XhciRead32(xhci->Op, off); @@ -1647,14 +1578,12 @@ KSTATUS XhciGetConfigurationDescriptor(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, return NTLSTATUS_SUCCESS; } -// Implements the endpoint Id From Address operation. uint8_t XhciEndpointIdFromAddress(uint8_t endpointAddress) { uint8_t number = endpointAddress & USB_ENDPOINT_NUMBER_MASK; if (number == 0) return 1; return (uint8_t)(number * 2u + ((endpointAddress & USB_ENDPOINT_DIR_IN) ? 1u : 0u)); } -// Implements the interrupt Interval operation. uint8_t XhciInterruptInterval(uint8_t speed, uint8_t usbInterval) { if (usbInterval == 0) usbInterval = 1; @@ -1781,7 +1710,6 @@ KSTATUS XhciBulkTransfer(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, return NTLSTATUS_SUCCESS; } -// Implements the configure Pipe Endpoint operation. KSTATUS XhciConfigurePipeEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_PIPE* pipe) { if (!xhci || !dev || !pipe || !pipe->Open) return NTLSTATUS_INVALID_PARAMETER; @@ -1868,7 +1796,6 @@ KSTATUS XhciConfigurePipeEndpoint(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_P return NTLSTATUS_SUCCESS; } -// Implements the hcd Submit Interrupt Urb operation. static KSTATUS XhciHcdSubmitInterruptUrb(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_URB* urb) { if (!xhci || !dev || !urb || !urb->Pipe || !urb->BufferDeviceAddress || urb->Length == 0) return NTLSTATUS_INVALID_PARAMETER; @@ -1966,7 +1893,6 @@ static bool XhciClaimAsyncCompletion(XHCI_CONTROLLER* xhci, uint64_t trbDeviceAd return true; } -// Implements the hcd Submit Bulk Urb operation. static KSTATUS XhciHcdSubmitBulkUrb(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB_URB* urb) { if (!xhci || !dev || !urb || !urb->Pipe || !urb->BufferDeviceAddress || urb->Length == 0) return NTLSTATUS_INVALID_PARAMETER; @@ -2006,7 +1932,6 @@ static KSTATUS XhciHcdSubmitBulkUrb(XHCI_CONTROLLER* xhci, XHCI_DEVICE* dev, USB return st; } -// Implements the hcd Submit Urb operation. static KSTATUS XhciHcdSubmitUrb(USB_HCD* hcd, USB_URB* urb) { if (!hcd || !urb || !urb->Device) return NTLSTATUS_INVALID_PARAMETER; @@ -2105,7 +2030,6 @@ static KSTATUS XhciHcdCancelUrb(USB_HCD* hcd, USB_URB* urb) { return NTLSTATUS_SUCCESS; } -// Implements the hcd Allocate Dma operation. static void* XhciHcdAllocateDma(USB_HCD* hcd, size_t pages, uint64_t* outDeviceAddress, @@ -2130,13 +2054,11 @@ static void XhciHcdDestroyPipe(USB_HCD* hcd, USB_PIPE* pipe) { MmFreePool(ctx); } -// Implements the hcd Reset Root Port operation. static KSTATUS XhciHcdResetRootPort(USB_HCD* hcd, uint8_t port, uint8_t* outSpeed) { if (!hcd) return NTLSTATUS_INVALID_PARAMETER; return XhciResetPort((XHCI_CONTROLLER*)hcd->ControllerContext, port, outSpeed); } -// Implements the hcd Clear Root Port Changes operation. static KSTATUS XhciHcdClearRootPortChanges(USB_HCD* hcd, uint8_t port) { if (!hcd) return NTLSTATUS_INVALID_PARAMETER; XhciClearPortChanges((XHCI_CONTROLLER*)hcd->ControllerContext, port); @@ -2181,35 +2103,13 @@ KSTATUS XhciStartController(XHCI_CONTROLLER* xhci) { return NTLSTATUS_DEVICE_ERROR; } - xhci->Irq = 0xFFu; + xhci->InterruptRequest.Routine = XhciIsr; + xhci->InterruptRequest.Context = xhci; + xhci->InterruptRequest.Affinity = 0; + xhci->InterruptRequest.Interrupt = (KE_INTERRUPT*)0; xhci->UsingMsi = false; - - st = PciEnableMsiAuto(xhci->Pdo, &xhci->Irq); - if (KSUCCESS(st)) { - xhci->UsingMsi = true; - DbgPrint("usb: xHCI using MSI IRQ slot %u\n", xhci->Irq); - } else { - KSTATUS intxStatus = PciGetInterrupt(xhci->Pdo, &xhci->Irq); - if (KSUCCESS(intxStatus) && xhci->Irq != 0xFFu) { - DbgPrint("usb: xHCI using legacy INTx IRQ %u\n", xhci->Irq); - } else { - xhci->Irq = 0xFFu; - DbgPrint("usb: xHCI no MSI/INTx interrupt available; using polled event-ring mode (msi=0x%x intx=0x%x)\n", - st, intxStatus); - } - } - - uint32_t enableFlags = PCI_ENABLE_MEMORY | PCI_ENABLE_BUSMASTER; - if (xhci->UsingMsi || xhci->Irq == 0xFFu) - enableFlags |= PCI_DISABLE_INTX; - else - enableFlags |= PCI_ENABLE_INTX; - - st = PciEnableDevice(xhci->Pdo, enableFlags); - if (!KSUCCESS(st)) { - DbgPrint("usb: xHCI PciEnableDevice failed st=0x%x\n", st); - return st; - } + st = PciEnableDevice(xhci->Pdo, PCI_ENABLE_MEMORY | PCI_ENABLE_BUSMASTER | PCI_DISABLE_INTX); + if (!KSUCCESS(st)) return st; xhci->MmioPhys = xhci->MmioBar.Base; @@ -2266,12 +2166,11 @@ KSTATUS XhciStartController(XHCI_CONTROLLER* xhci) { UsbInitializeHcd(&xhci->Hcd, &gXhciHcdOperations, xhci, 0, xhci->MaxPorts); xhci->Hcd.ControllerDevice = xhci->Fdo; - DbgPrint("usb: xHCI init %02x:%02x.%x vendor=%04x device=%04x irq=%u mmio=0x%016llX caplen=%u version=%04x\n", + UsbTrace("usb: xHCI init %02x:%02x.%x vendor=%04x device=%04x mmio=0x%016llX caplen=%u version=%04x\n", xhci->Bus, xhci->Dev, xhci->Fn, xhci->PciInfo.VendorId, xhci->PciInfo.DeviceId, - xhci->Irq, (unsigned long long)xhci->MmioPhys, xhci->CapLength, xhci->Version); - DbgPrint("usb: xHCI caps slots=%u intrs=%u ports=%u ctx=%u scratchpads=%u hcs2=%08x hcc1=%08x dboff=0x%x rtsoff=0x%x pagesize=%08x\n", + UsbTrace("usb: xHCI caps slots=%u intrs=%u ports=%u ctx=%u scratchpads=%u hcs2=%08x hcc1=%08x dboff=0x%x rtsoff=0x%x pagesize=%08x\n", xhci->MaxSlots, xhci->MaxIntrs, xhci->MaxPorts, xhci->ContextBytes, xhci->ScratchpadCount, xhci->Hcs2, xhci->Hcc1, xhci->DbOff, xhci->RtsOff, XhciRead32(xhci->Op, XHCI_OP_PAGESIZE)); @@ -2331,22 +2230,18 @@ KSTATUS XhciStartController(XHCI_CONTROLLER* xhci) { goto failDma; } - st = XhciRegisterController(xhci); - if (!KSUCCESS(st)) { - DbgPrint("usb: xHCI controller registry full st=0x%x\n", st); - goto failDma; - } - - if (xhci->Irq != 0xFFu) { - KeIrqRegister(xhci->Irq, XhciIsr); + st = PciConnectInterrupts(xhci->Pdo, &xhci->InterruptRequest, 1u, &xhci->UsingMsi); + if (KSUCCESS(st)) { XhciEnableInterrupts(xhci); xhci->InterruptsEnabled = true; KeInsertQueueDpc(&xhci->EventDpc, (void*)0, (void*)0); - DbgPrint("usb: xHCI ISR registered on IRQ %u (%s); event ring handled by DPC\n", - xhci->Irq, xhci->UsingMsi ? "MSI" : "INTx"); + KE_INTERRUPT_INFO info; + if (KSUCCESS(KeInterruptQuery(xhci->InterruptRequest.Interrupt, &info))) + DbgPrint("usb: xHCI interrupt cpu=%u vector=0x%02x mode=%s\n", + info.CpuIndex, info.Vector, xhci->UsingMsi ? "MSI/MSI-X" : "INTx"); } else { xhci->InterruptsEnabled = false; - DbgPrint("usb: xHCI started in polling mode; synchronous waits drain event ring\n"); + DbgPrint("usb: xHCI polling fallback status=0x%x\n", st); } xhci->Fdo->PnpState = DevicePnpStarted; @@ -2354,15 +2249,16 @@ KSTATUS XhciStartController(XHCI_CONTROLLER* xhci) { if (!KSUCCESS(st)) DbgPrint("usb: root hub async scan scheduling failed st=0x%x\n", st); else - DbgPrint("usb: root hub initial scan requested\n"); + UsbTrace("usb: root hub scan scheduled\n"); - DbgPrint("usb: xHCI host controller initialised; HID boot input active=%u mass-storage will arrive through hotplug\n", - xhci->HidDeviceCount); + DbgPrint("usb: xHCI ready pci=%02x:%02x.%u ports=%u\n", + xhci->Bus, xhci->Dev, xhci->Fn, xhci->MaxPorts); return NTLSTATUS_SUCCESS; failDma: XhciHaltForDmaRelease(xhci); - XhciUnregisterController(xhci); + if (xhci->InterruptRequest.Interrupt) + PciDisconnectInterrupts(xhci->Pdo, &xhci->InterruptRequest, 1u); if (xhci->Hcd.RootHubPdo) { (void)UsbRemovePdoSubtree(xhci->Hcd.RootHubPdo, true); xhci->Hcd.RootHubPdo = (DEVICE_OBJECT*)0; @@ -2400,6 +2296,8 @@ KSTATUS XhciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { xhci->SurpriseRemoved = true; xhci->Running = false; xhci->InterruptsEnabled = false; + if (xhci->InterruptRequest.Interrupt) + PciDisconnectInterrupts(xhci->Pdo, &xhci->InterruptRequest, 1u); if (xhci->Hcd.RootHubPdo) (void)UsbRemovePdoSubtree(xhci->Hcd.RootHubPdo, true); return NTLSTATUS_SUCCESS; @@ -2407,11 +2305,12 @@ KSTATUS XhciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { case IRP_MN_REMOVE_DEVICE: device->PnpState = DevicePnpDeleted; XhciHaltForDmaRelease(xhci); + if (xhci->InterruptRequest.Interrupt) + PciDisconnectInterrupts(xhci->Pdo, &xhci->InterruptRequest, 1u); if (xhci->Hcd.RootHubPdo) { (void)UsbRemovePdoSubtree(xhci->Hcd.RootHubPdo, true); xhci->Hcd.RootHubPdo = (DEVICE_OBJECT*)0; } - XhciUnregisterController(xhci); XhciReleaseControllerDma(xhci); IoDetachDevice(device); IoDeleteDevice(device); @@ -2422,7 +2321,6 @@ KSTATUS XhciDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { } } -// Implements the add Device operation. KSTATUS XhciAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return NTLSTATUS_INVALID_PARAMETER; @@ -2439,7 +2337,6 @@ KSTATUS XhciAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject xhci->Fdo = fdo; xhci->Pdo = physicalDeviceObject; - xhci->Irq = 0xFFu; KeInitializeDpc(&xhci->EventDpc, XhciEventDpcRoutine, xhci); xhci->LowerDevice = IoAttachDeviceToDeviceStack(fdo, physicalDeviceObject); diff --git a/code/drivers/dirs b/code/drivers/dirs new file mode 100644 index 0000000..fb6fbb7 --- /dev/null +++ b/code/drivers/dirs @@ -0,0 +1 @@ +DIRS=bus input storage audio fs display net platform diff --git a/code/drivers/display/dirs b/code/drivers/display/dirs new file mode 100644 index 0000000..c8b197f --- /dev/null +++ b/code/drivers/display/dirs @@ -0,0 +1 @@ +DIRS=vmwaresvga diff --git a/code/drivers/display/vmwaresvga/makefile b/code/drivers/display/vmwaresvga/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/drivers/display/vmwaresvga/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/drivers/display/vmwaresvga/sources b/code/drivers/display/vmwaresvga/sources new file mode 100644 index 0000000..6259220 --- /dev/null +++ b/code/drivers/display/vmwaresvga/sources @@ -0,0 +1,7 @@ +TARGETNAME=vmwaresvga +TARGETPATH=obj +TARGETTYPE=DRIVER +FLAVOR=DRIVER +TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\pci.lib" +EXTRA_LFLAGS=/NOENTRY +SOURCES=@/code/drivers/display/vmwaresvga/vmwaresvga.c diff --git a/code/drivers/display/vmwaresvga/vmwaresvga.c b/code/drivers/display/vmwaresvga/vmwaresvga.c index 1080c6a..e93eeea 100644 --- a/code/drivers/display/vmwaresvga/vmwaresvga.c +++ b/code/drivers/display/vmwaresvga/vmwaresvga.c @@ -213,7 +213,6 @@ static void VmwSvgaWakeFifo(VMWSVGA_DEVICE* v) { static KSTATUS VmwSvgaUploadCursorImage(VMWSVGA_DEVICE* v, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels); -// Implements the premultiply Argb For Bgra operation. static uint32_t VmwSvgaPremultiplyArgbForBgra(uint32_t argb) { uint32_t a = argb >> 24; if (a == 0) @@ -231,7 +230,6 @@ static uint32_t VmwSvgaPremultiplyArgbForBgra(uint32_t argb) { return (a << 24) | (r << 16) | (g << 8) | b; } -// Implements the cursor Commit operation. static void VmwSvgaCursorCommit(VMWSVGA_DEVICE* v) { if (!v || !v->HardwareCursor || !v->CursorImageDefined) return; @@ -266,7 +264,6 @@ static void VmwSvgaCursorCommit(VMWSVGA_DEVICE* v) { VmwSvgaWriteReg(v, SVGA_REG_CURSOR_ON, v->CursorVisible ? SVGA_CURSOR_ON_SHOW : SVGA_CURSOR_ON_HIDE); } -// Implements the cursor Set Visible operation. static void VmwSvgaCursorSetVisible(VMWSVGA_DEVICE* v, bool visible) { if (!v || !v->HardwareCursor) return; @@ -274,7 +271,6 @@ static void VmwSvgaCursorSetVisible(VMWSVGA_DEVICE* v, bool visible) { VmwSvgaCursorCommit(v); } -// Implements the cursor Set Position operation. static void VmwSvgaCursorSetPosition(VMWSVGA_DEVICE* v, int32_t x, int32_t y) { if (!v || !v->HardwareCursor) return; @@ -283,7 +279,6 @@ static void VmwSvgaCursorSetPosition(VMWSVGA_DEVICE* v, int32_t x, int32_t y) { VmwSvgaCursorCommit(v); } -// Implements the define Alpha Cursor operation. static KSTATUS VmwSvgaDefineAlphaCursor(VMWSVGA_DEVICE* v, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels) { KSTATUS st = VmwSvgaFifoWrite(v, SVGA_CMD_DEFINE_ALPHA_CURSOR); if (!KSUCCESS(st)) return st; @@ -342,7 +337,6 @@ static uint32_t VmwSvgaPackMonoCursorDword(const uint8_t* bits, ((uint32_t)bytes[3] << 24); } -// Implements the classic Cursor Width operation. static int32_t VmwSvgaClassicCursorWidth(int32_t width) { // QEMU's VMware SVGA implementation reads classic cursor masks as @@ -399,7 +393,6 @@ static void VmwSvgaBuildMonoCursorBits(const uint32_t* argbPixels, } } -// Implements the define Classic Cursor operation. static KSTATUS VmwSvgaDefineClassicCursor(VMWSVGA_DEVICE* v, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels) { int32_t encodedWidth = VmwSvgaClassicCursorWidth(width); uint32_t dwordsPerRow = ((uint32_t)encodedWidth + 31u) / 32u; @@ -460,7 +453,6 @@ done: return st; } -// Implements the upload Cursor Image operation. static KSTATUS VmwSvgaUploadCursorImage(VMWSVGA_DEVICE* v, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels) { if (!v || !v->HardwareCursor || !argbPixels || width <= 0 || height <= 0) return NTLSTATUS_INVALID_PARAMETER; @@ -478,7 +470,6 @@ static KSTATUS VmwSvgaUploadCursorImage(VMWSVGA_DEVICE* v, int32_t width, int32_ return st; } -// Implements the define Cursor Image operation. static KSTATUS VmwSvgaDefineCursorImage(VMWSVGA_DEVICE* v, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels) { if (!v || !v->HardwareCursor || !argbPixels || width <= 0 || height <= 0) return NTLSTATUS_INVALID_PARAMETER; @@ -509,12 +500,10 @@ static KSTATUS VmwSvgaDefineCursorImage(VMWSVGA_DEVICE* v, int32_t width, int32_ return NTLSTATUS_SUCCESS; } -// Implements the align Up32 operation. static uint32_t VmwSvgaAlignUp32(uint32_t value, uint32_t alignment) { return (value + alignment - 1u) & ~(alignment - 1u); } -// Implements the define Screen Object operation. static KSTATUS VmwSvgaDefineScreenObject(VMWSVGA_DEVICE* v) { if (!v || !v->FifoReady || !v->UseScreenObject) return NTLSTATUS_INVALID_PARAMETER; @@ -549,7 +538,6 @@ static KSTATUS VmwSvgaDefineScreenObject(VMWSVGA_DEVICE* v) { return VmwSvgaSyncDevice(v); } -// Implements the define Gmrfb operation. static KSTATUS VmwSvgaDefineGmrfb(VMWSVGA_DEVICE* v) { if (!v || !v->FifoReady || !v->UseScreenObject) return NTLSTATUS_INVALID_PARAMETER; @@ -658,7 +646,6 @@ static KSTATUS VmwSvgaInitializeScreenObject(VMWSVGA_DEVICE* v) { return NTLSTATUS_SUCCESS; } -// Implements the legacy Update operation. static KSTATUS VmwSvgaLegacyUpdate(VMWSVGA_DEVICE* v, int32_t x, int32_t y, int32_t w, int32_t h) { DISPLAY_RECT r = { x, y, w, h }; if (!VmwSvgaClipRect(v, &r)) @@ -712,7 +699,6 @@ static KSTATUS VmwSvgaSyncDevice(VMWSVGA_DEVICE* v) { return NTLSTATUS_TIMEOUT; } -// Implements the blend Pixel operation. static uint32_t VmwSvgaBlendPixel(uint32_t dst, uint32_t src) { uint8_t a = (uint8_t)(src >> 24); if (a == 0) return dst; @@ -731,12 +717,10 @@ static uint32_t VmwSvgaBlendPixel(uint32_t dst, uint32_t src) { return ((uint32_t)rr << 16) | ((uint32_t)gg << 8) | bb; } -// Implements the from Display operation. static VMWSVGA_DEVICE* VmwSvgaFromDisplay(DISPLAY_DEVICE* device) { return device ? (VMWSVGA_DEVICE*)device->DriverContext : NULL; } -// Implements the display Get Mode operation. static KSTATUS VmwSvgaDisplayGetMode(DISPLAY_DEVICE* device, DISPLAY_MODE* outMode) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v || !outMode || !v->Framebuffer) @@ -840,7 +824,6 @@ static void VmwSvgaCopyToShadowAndFramebuffer(uint32_t* shadow, } } -// Implements the display pitched blit operation. static KSTATUS VmwSvgaDisplayBlit(DISPLAY_DEVICE* device, int32_t x, int32_t y, int32_t w, int32_t h, const uint32_t* pixels, uint32_t pitchBytes) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v || !v->Backbuffer || !pixels || w <= 0 || h <= 0 || @@ -913,7 +896,6 @@ static KSTATUS VmwSvgaDisplayPresentPitched(DISPLAY_DEVICE* device, return VmwSvgaSyncDevice(v); } -// Implements the display Fill Rect operation. static KSTATUS VmwSvgaDisplayFillRect(DISPLAY_DEVICE* device, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v || !v->Backbuffer || w <= 0 || h <= 0) @@ -934,7 +916,6 @@ static KSTATUS VmwSvgaDisplayFillRect(DISPLAY_DEVICE* device, int32_t x, int32_t return NTLSTATUS_SUCCESS; } -// Implements the display Copy Rect operation. static KSTATUS VmwSvgaDisplayCopyRect(DISPLAY_DEVICE* device, int32_t dstX, int32_t dstY, int32_t srcX, int32_t srcY, int32_t w, int32_t h) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v || !v->Backbuffer || w <= 0 || h <= 0) @@ -971,7 +952,6 @@ static KSTATUS VmwSvgaDisplayCopyRect(DISPLAY_DEVICE* device, int32_t dstX, int3 return NTLSTATUS_SUCCESS; } -// Implements the display Read Rect operation. static KSTATUS VmwSvgaDisplayReadRect(DISPLAY_DEVICE* device, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t* outPixels, uint32_t outStride) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v || !v->Backbuffer || !outPixels || outStride == 0 || w <= 0 || h <= 0) @@ -994,7 +974,6 @@ static KSTATUS VmwSvgaDisplayReadRect(DISPLAY_DEVICE* device, int32_t x, int32_t return NTLSTATUS_SUCCESS; } -// Implements the display Present operation. static KSTATUS VmwSvgaDisplayPresent(DISPLAY_DEVICE* device, const DISPLAY_RECT* rects, size_t rectCount) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v || !v->Framebuffer || !v->Backbuffer) @@ -1039,13 +1018,11 @@ static KSTATUS VmwSvgaDisplayPresent(DISPLAY_DEVICE* device, const DISPLAY_RECT* return result; } -// Implements the display Sync operation. static KSTATUS VmwSvgaDisplaySync(DISPLAY_DEVICE* device) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); return VmwSvgaSyncDevice(v); } -// Implements the display Set Cursor Image operation. static KSTATUS VmwSvgaDisplaySetCursorImage(DISPLAY_DEVICE* device, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v || !v->HardwareCursor) @@ -1053,7 +1030,6 @@ static KSTATUS VmwSvgaDisplaySetCursorImage(DISPLAY_DEVICE* device, int32_t widt return VmwSvgaDefineCursorImage(v, width, height, hotX, hotY, argbPixels); } -// Implements the display Set Cursor Position operation. static KSTATUS VmwSvgaDisplaySetCursorPosition(DISPLAY_DEVICE* device, int32_t x, int32_t y) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v) @@ -1066,7 +1042,6 @@ static KSTATUS VmwSvgaDisplaySetCursorPosition(DISPLAY_DEVICE* device, int32_t x return NTLSTATUS_SUCCESS; } -// Implements the restore Cursor operation. static void VmwSvgaRestoreCursor(VMWSVGA_DEVICE* v) { if (!v || !v->CursorDrawn || !v->Backbuffer || !v->Framebuffer) return; @@ -1119,7 +1094,6 @@ static void VmwSvgaDrawCursor(VMWSVGA_DEVICE* v) { (void)VmwSvgaUpdate(v, dirty.X, dirty.Y, dirty.W, dirty.H); } -// Implements the display Show Cursor operation. static KSTATUS VmwSvgaDisplayShowCursor(DISPLAY_DEVICE* device, bool show) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v) @@ -1154,7 +1128,6 @@ static KSTATUS VmwSvgaDisplayShowCursor(DISPLAY_DEVICE* device, bool show) { return NTLSTATUS_SUCCESS; } -// Implements the display Query Stats operation. static KSTATUS VmwSvgaDisplayQueryStats(DISPLAY_DEVICE* device, DISPLAY_STATS* outStats) { VMWSVGA_DEVICE* v = VmwSvgaFromDisplay(device); if (!v || !outStats) @@ -1178,7 +1151,6 @@ static const DISPLAY_DEVICE_OPS gVmwSvgaDisplayOps = { .QueryStats = VmwSvgaDisplayQueryStats, }; -// Implements the select Bars operation. static KSTATUS VmwSvgaSelectBars(VMWSVGA_DEVICE* v) { PCI_BAR bar; memset(&bar, 0, sizeof(bar)); @@ -1564,7 +1536,6 @@ KSTATUS VmwSvgaDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { } } -// Implements the add Device operation. KSTATUS VmwSvgaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return NTLSTATUS_INVALID_PARAMETER; @@ -1589,14 +1560,12 @@ KSTATUS VmwSvgaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObj return NTLSTATUS_FAILURE; } - DbgPrint("VMWSVGA: FDO attached to %v\n", physicalDeviceObject->Name); return NTLSTATUS_SUCCESS; } static KSTATUS DriverInitialize(NTL_MODULE* module) { (void)module; - DbgPrint("VMWSVGA: driver loading...\n"); memset(&gVmwSvgaDriver, 0, sizeof(gVmwSvgaDriver)); IoInitializeDriverObject(&gVmwSvgaDriver, SYS_SV_LITERAL("vmwaresvga")); diff --git a/code/drivers/fs/dirs b/code/drivers/fs/dirs new file mode 100644 index 0000000..a929210 --- /dev/null +++ b/code/drivers/fs/dirs @@ -0,0 +1 @@ +DIRS=ext4 fat ntfs diff --git a/code/drivers/fs/ext4/ext4_driver.c b/code/drivers/fs/ext4/ext4_driver.c index 1acc36b..cd3ebf1 100644 --- a/code/drivers/fs/ext4/ext4_driver.c +++ b/code/drivers/fs/ext4/ext4_driver.c @@ -1130,7 +1130,8 @@ static void Ext4UnmountPartition(const IO_PARTITION_INFO* partition, IO_PARTITIO uint32_t count = gExt4MountedCount; KeReleaseMutex(&gExt4MountMutex); - (void)IoRemoveVolume(ioVolume, IoVolumeBackingRemoved); + (void)IoRemoveVolume(ioVolume, change == IoPartitionSurpriseRemoved + ? IoVolumeBackingRemoved : IoVolumeUnmounted); IoReleaseVolume(ioVolume); DbgPrint("EXT4: disk=%u lba=%llu %s; unmounted volume=%u; total=%u\n", partition->DiskIndex, (unsigned long long)partition->StartLba, @@ -1157,7 +1158,6 @@ static void Ext4PartitionChange(const IO_PARTITION_INFO* partition, static KSTATUS DriverInitialize(NTL_MODULE* module) { (void)module; - DbgPrint("EXT4: Init\n"); Ext4ListInit(&gExt4Mounts); gExt4MountedCount = 0; @@ -1170,9 +1170,7 @@ static KSTATUS DriverInitialize(NTL_MODULE* module) { return status; } - if (!gExt4MountedCount) - DbgPrint("EXT4: no mountable ext partitions found; driver resident for partition changes.\n"); - DbgPrint("EXT4: Init complete; mounted %u volume(s).\n", gExt4MountedCount); + DbgPrint("fs: ext4 volumes=%u\n", gExt4MountedCount); return NTLSTATUS_SUCCESS; } diff --git a/code/drivers/fs/ext4/makefile b/code/drivers/fs/ext4/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/drivers/fs/ext4/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/drivers/fs/ext4/sources b/code/drivers/fs/ext4/sources new file mode 100644 index 0000000..ef94314 --- /dev/null +++ b/code/drivers/fs/ext4/sources @@ -0,0 +1,11 @@ +TARGETNAME=ext4 +TARGETPATH=obj +TARGETTYPE=DRIVER +FLAVOR=EXT4 +TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" +EXTRA_LFLAGS=/NOENTRY +INCLUDES=$(BASEDIR)\code\drivers\fs\ext4\include;$(BASEDIR)\code\drivers\fs\ext4\third_party\lwext4\include +SOURCES=@/code/drivers/fs/ext4/ext4_port.c @/code/drivers/fs/ext4/ext4_driver.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_balloc.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_bcache.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_bitmap.c \ + @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_block_group.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_blockdev.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_crc32.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_debug.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_dir.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_dir_idx.c \ + @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_extent.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_fs.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_hash.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_ialloc.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_inode.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_journal.c \ + @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_super.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_trans.c @/code/drivers/fs/ext4/third_party/lwext4/src/ext4_xattr.c diff --git a/code/drivers/fs/fat/fat.c b/code/drivers/fs/fat/fat.c index 60d834d..3c73a31 100644 --- a/code/drivers/fs/fat/fat.c +++ b/code/drivers/fs/fat/fat.c @@ -98,7 +98,6 @@ static KSTATUS FatCacheRead(FAT_VOL* v, uint64_t lba, uint8_t** out) { return NTLSTATUS_SUCCESS; } -// Implements the fat Cache Mark Dirty operation. static void FatCacheMarkDirty(FAT_VOL* v, uint64_t lba) { uint32_t slot = (uint32_t)(lba % FAT_CACHE_SLOTS); if (gFatCache[slot].valid && gFatCache[slot].vol == v && gFatCache[slot].lba == lba) @@ -231,7 +230,6 @@ bool FatDirectoryNextSegment(FAT_VOL* v, uint32_t dirCluster, return true; } -// Implements the cluster To Lba operation. uint64_t FatClusterToLba(FAT_VOL* v, uint32_t cluster) { return v->DataStart + (uint64_t)(cluster - 2) * v->SectorsPerCluster; } @@ -390,12 +388,10 @@ void FatFreeClusterChain(FAT_VOL* v, uint32_t start) { // FAT timestamp and DIRENT metadata helpers. -// Implements the fat Is Leap Year operation. static bool FatIsLeapYear(uint32_t year) { return ((year % 4u) == 0u && (year % 100u) != 0u) || ((year % 400u) == 0u); } -// Implements the fat Days In Month operation. static uint32_t FatDaysInMonth(uint32_t year, uint32_t month) { static const uint8_t days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; if (month < 1u || month > 12u) return 31u; @@ -414,13 +410,11 @@ static uint64_t FatCalendarToEpochSeconds(uint32_t year, uint32_t month, uint32_ return (((days * 24u) + hour) * 60u + minute) * 60u + second; } -// Implements the fat Day Of Week operation. static uint8_t FatDayOfWeek(uint32_t year, uint32_t month, uint32_t day) { uint64_t epoch = FatCalendarToEpochSeconds(year, month, day, 0, 0, 0); return (uint8_t)(((epoch / 86400u) + 4u) % 7u); } -// Implements the fat Encode Date operation. static uint16_t FatEncodeDate(const SYS_SYSTEM_TIME* t) { uint32_t year = t && t->Year ? t->Year : 1980u; uint32_t month = t && t->Month ? t->Month : 1u; @@ -435,7 +429,6 @@ static uint16_t FatEncodeDate(const SYS_SYSTEM_TIME* t) { return (uint16_t)(((year - 1980u) << 9) | (month << 5) | day); } -// Implements the fat Encode Time operation. static uint16_t FatEncodeTime(const SYS_SYSTEM_TIME* t) { uint32_t hour = t ? t->Hour : 0u; uint32_t minute = t ? t->Minute : 0u; @@ -446,7 +439,6 @@ static uint16_t FatEncodeTime(const SYS_SYSTEM_TIME* t) { return (uint16_t)((hour << 11) | (minute << 5) | (second / 2u)); } -// Implements the fat Encode Create Time Tenth operation. static uint8_t FatEncodeCreateTimeTenth(const SYS_SYSTEM_TIME* t) { uint32_t second = t ? t->Second : 0u; uint32_t ms = t ? t->Millisecond : 0u; @@ -457,7 +449,6 @@ static uint8_t FatEncodeCreateTimeTenth(const SYS_SYSTEM_TIME* t) { return (uint8_t)v; } -// Implements the fat Query Encoded Time operation. void FatQueryEncodedTime(FAT_ENCODED_TIME* out) { SYS_SYSTEM_TIME now; memset(&now, 0, sizeof(now)); @@ -502,7 +493,6 @@ void FatDecodeDateTime(uint16_t date, uint16_t time, uint8_t createTenth, out->EpochSeconds = FatCalendarToEpochSeconds(year, month, day, hour, minute, second); } -// Implements the fat Decode Access Date operation. void FatDecodeAccessDate(uint16_t date, SYS_SYSTEM_TIME* out) { FatDecodeDateTime(date, 0, 0, out); } diff --git a/code/drivers/fs/fat/fat_async.c b/code/drivers/fs/fat/fat_async.c index e40a07d..3baeff9 100644 --- a/code/drivers/fs/fat/fat_async.c +++ b/code/drivers/fs/fat/fat_async.c @@ -46,7 +46,6 @@ static volatile int gFatAsyncInitState; static void FatAsyncReadSubmitNext(FAT_ASYNC_RW* ctx); static void FatAsyncWriteSubmitNext(FAT_ASYNC_RW* ctx); -// Implements the async Worker operation. static void FatAsyncWorker(void* arg) { (void)arg; @@ -70,7 +69,6 @@ static void FatAsyncWorker(void* arg) { } } -// Implements the ensure Async Worker Started operation. static KSTATUS FatEnsureAsyncWorkerStarted(void) { uintptr_t flags = KeAcquireSpinlock(&gFatAsyncLock); if (gFatAsyncInitState == 2) { @@ -104,7 +102,6 @@ static KSTATUS FatEnsureAsyncWorkerStarted(void) { return s; } -// Implements the async Queue Continuation operation. static void FatAsyncQueueContinuation(FAT_ASYNC_RW* ctx) { if (!ctx) return; @@ -114,7 +111,6 @@ static void FatAsyncQueueContinuation(FAT_ASYNC_RW* ctx) { KeSignalSemaphore(gFatAsyncSemaphore); } -// Implements the async Finish operation. static void FatAsyncFinish(FAT_ASYNC_RW* ctx, KSTATUS status, size_t information) { if (!ctx) return; if (ctx->CurrentDevice) { @@ -128,7 +124,6 @@ static void FatAsyncFinish(FAT_ASYNC_RW* ctx, KSTATUS status, size_t information if (complete) complete(completeContext, status, information); } -// Implements the async Read Irp Complete operation. static void FatAsyncReadIrpComplete(IRP* irp, void* completeCtx) { FAT_ASYNC_RW* ctx = (FAT_ASYNC_RW*)completeCtx; if (!ctx) return; @@ -158,7 +153,6 @@ static void FatAsyncReadIrpComplete(IRP* irp, void* completeCtx) { FatAsyncQueueContinuation(ctx); } -// Implements the async Read Submit Next operation. static void FatAsyncReadSubmitNext(FAT_ASYNC_RW* ctx) { if (ctx->Remaining == 0) { FatAsyncFinish(ctx, NTLSTATUS_SUCCESS, ctx->Done); @@ -271,7 +265,6 @@ KSTATUS FatReadAsync(IO_VOLUME_PROVIDER* fs, void* fileCtx, return NTLSTATUS_PENDING; } -// Implements the async Write Irp Complete operation. static void FatAsyncWriteIrpComplete(IRP* irp, void* completeCtx) { FAT_ASYNC_RW* ctx = (FAT_ASYNC_RW*)completeCtx; if (!ctx) return; @@ -294,7 +287,6 @@ static void FatAsyncWriteIrpComplete(IRP* irp, void* completeCtx) { FatAsyncQueueContinuation(ctx); } -// Implements the async Write Submit Next operation. static void FatAsyncWriteSubmitNext(FAT_ASYNC_RW* ctx) { if (ctx->Remaining == 0) { uint64_t newEnd = ctx->Offset + ctx->Done; diff --git a/code/drivers/fs/fat/fat_directory.c b/code/drivers/fs/fat/fat_directory.c index 9c07a78..43462b8 100644 --- a/code/drivers/fs/fat/fat_directory.c +++ b/code/drivers/fs/fat/fat_directory.c @@ -15,7 +15,6 @@ static char FatUpperChar(char c); static bool FatIsLowerChar(char c); static bool FatIsValidShortChar(char c); -// Implements the make83 Name V operation. static void Make83NameV(SYS_STRING_VIEW src, char name8[8], char ext3[3]) { memset(name8, ' ', 8); memset(ext3, ' ', 3); @@ -48,17 +47,14 @@ static void Make83NameV(SYS_STRING_VIEW src, char name8[8], char ext3[3]) { // LFN assembly / matching. -// Implements the fat Upper Char operation. static char FatUpperChar(char c) { return (c >= 'a' && c <= 'z') ? (char)(c - 32) : c; } -// Implements the fat Is Lower Char operation. static bool FatIsLowerChar(char c) { return c >= 'a' && c <= 'z'; } -// Implements the fat Is Valid Short Char operation. static bool FatIsValidShortChar(char c) { c = FatUpperChar(c); if (c >= 'A' && c <= 'Z') return true; @@ -96,14 +92,12 @@ static bool FatNameIsStructurallyShort83V(SYS_STRING_VIEW name) { return baseLen >= 1 && baseLen <= 8 && extLen <= 3; } -// Implements the fat Component Has Lower V operation. static bool FatComponentHasLowerV(SYS_STRING_VIEW name, size_t start, size_t end) { for (size_t i = start; i < end; i++) if (FatIsLowerChar(name.Data[i])) return true; return false; } -// Implements the fat Component Has Upper V operation. static bool FatComponentHasUpperV(SYS_STRING_VIEW name, size_t start, size_t end) { for (size_t i = start; i < end; i++) if (name.Data[i] >= 'A' && name.Data[i] <= 'Z') return true; @@ -144,7 +138,6 @@ static bool FatNameNeedsLfnForCreateV(SYS_STRING_VIEW name) { return false; } -// Implements the fat Short Name Case Flags V operation. static uint8_t FatShortNameCaseFlagsV(SYS_STRING_VIEW name) { if (!FatNameIsStructurallyShort83V(name)) return 0; size_t baseEnd, extStart, extEnd; @@ -160,7 +153,6 @@ static uint8_t FatShortNameCaseFlagsV(SYS_STRING_VIEW name) { return flags; } -// Implements the lfn Checksum operation. static uint8_t LfnChecksum(const char name8[8], const char ext3[3]) { uint8_t sum = 0; for (int i = 0; i < 11; i++) { @@ -170,7 +162,6 @@ static uint8_t LfnChecksum(const char name8[8], const char ext3[3]) { return sum; } -// Implements the lfn Set Char operation. static void LfnSetChar(LFN_ENTRY* e, int idx, uint16_t value) { if (idx < 5) e->Name1[idx] = value; else if (idx < 11) e->Name2[idx - 5] = value; @@ -242,7 +233,6 @@ static bool ShortNameExistsRaw(FAT_VOL* v, uint32_t dirCluster, return false; } -// Implements the fat Alias Append Char operation. static void FatAliasAppendChar(char* dst, int* len, int maxLen, char c) { c = FatUpperChar(c); if (!FatIsValidShortChar(c)) return; @@ -384,7 +374,6 @@ static KSTATUS DeleteLegacyBrokenDotAliasV(FAT_VOL* v, uint32_t dirCluster, return NTLSTATUS_SUCCESS; } -// Implements the lfn Append operation. void FatLfnAppend(char* lfn, const LFN_ENTRY* e) { int seq = (e->Order & 0x3F) - 1; if (seq < 0 || seq >= (FAT_MAX_LFN / 13)) return; @@ -413,7 +402,6 @@ static bool FatStringViewDataIsPlausible(SYS_STRING_VIEW view) { return data >= 0x10000u; } -// Implements the name View Is Valid operation. static bool FatNameViewIsValid(SYS_STRING_VIEW name) { if (!FatStringViewDataIsPlausible(name)) return false; if (name.Length == 0 || name.Length >= FAT_MAX_LFN) return false; @@ -424,7 +412,6 @@ static bool FatNameViewIsValid(SYS_STRING_VIEW name) { return true; } -// Implements the lfn Match V operation. static bool LfnMatchV(const char* lfn, SYS_STRING_VIEW want) { if (!lfn || !SysSvIsValid(want)) return false; size_t i = 0; diff --git a/code/drivers/fs/fat/fat_driver.c b/code/drivers/fs/fat/fat_driver.c index cb88112..c36277c 100644 --- a/code/drivers/fs/fat/fat_driver.c +++ b/code/drivers/fs/fat/fat_driver.c @@ -249,7 +249,8 @@ static void FatUnmountPartition(const IO_PARTITION_INFO* partition, IO_PARTITION uint32_t mountedCount = gMountedCount; KeReleaseMutex(&gFatMountMutex); - (void)IoRemoveVolume(volume, IoVolumeBackingRemoved); + (void)IoRemoveVolume(volume, change == IoPartitionSurpriseRemoved + ? IoVolumeBackingRemoved : IoVolumeUnmounted); IoReleaseVolume(volume); // Drop the active mount-list reference. DbgPrint("FAT: disk=%u lba=%llu %s; unmounted volume=%u; total=%u\n", partition->DiskIndex, (unsigned long long)partition->StartLba, @@ -278,7 +279,6 @@ static void FatPartitionChange(const IO_PARTITION_INFO* partition, // Initializes FAT and subscribes to the authoritative kernel partition stream. static KSTATUS DriverInitialize(NTL_MODULE* module) { (void)module; - DbgPrint("FAT: Init\n"); FatCacheInvalidate(); @@ -292,9 +292,7 @@ static KSTATUS DriverInitialize(NTL_MODULE* module) { return status; } - if (!gMountedCount) - DbgPrint("FAT: no mountable FAT partitions found; driver resident for partition changes.\n"); - DbgPrint("FAT: Init complete; mounted %u volume(s).\n", gMountedCount); + DbgPrint("fs: fat volumes=%u\n", gMountedCount); return NTLSTATUS_SUCCESS; } diff --git a/code/drivers/fs/fat/makefile b/code/drivers/fs/fat/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/drivers/fs/fat/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/drivers/fs/fat/sources b/code/drivers/fs/fat/sources new file mode 100644 index 0000000..e221951 --- /dev/null +++ b/code/drivers/fs/fat/sources @@ -0,0 +1,7 @@ +TARGETNAME=fat +TARGETPATH=obj +TARGETTYPE=DRIVER +FLAVOR=DRIVER +TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" +EXTRA_LFLAGS=/NOENTRY +SOURCES=@/code/drivers/fs/fat/fat.c @/code/drivers/fs/fat/fat_directory.c @/code/drivers/fs/fat/fat_file.c @/code/drivers/fs/fat/fat_async.c @/code/drivers/fs/fat/fat_driver.c @/code/drivers/fs/fat/fat_mount.c diff --git a/code/drivers/fs/ntfs/dirs b/code/drivers/fs/ntfs/dirs new file mode 100644 index 0000000..95b75ba --- /dev/null +++ b/code/drivers/fs/ntfs/dirs @@ -0,0 +1 @@ +DIRS=ntfs3g diff --git a/code/drivers/fs/ntfs/ntfs.c b/code/drivers/fs/ntfs/ntfs.c index 91d57da..acce176 100644 --- a/code/drivers/fs/ntfs/ntfs.c +++ b/code/drivers/fs/ntfs/ntfs.c @@ -1571,7 +1571,8 @@ static void NtfsUnmountPartition(const IO_PARTITION_INFO* partition, IO_PARTITIO uint32_t mountedCount = gMountedCount; KeReleaseMutex(&gNtfsMountMutex); - (void)IoRemoveVolume(volume, IoVolumeBackingRemoved); + (void)IoRemoveVolume(volume, change == IoPartitionSurpriseRemoved + ? IoVolumeBackingRemoved : IoVolumeUnmounted); IoReleaseVolume(volume); // Drop the active mount-list reference. DbgPrint("NTFS: disk=%u lba=%llu %s; unmounted volume=%u; total=%u\n", partition->DiskIndex, (unsigned long long)partition->StartLba, @@ -1600,7 +1601,6 @@ static void NtfsPartitionChange(const IO_PARTITION_INFO* partition, // Initializes NTFS and subscribes to the authoritative kernel partition stream. static KSTATUS DriverInitialize(NTL_MODULE* module) { (void)module; - DbgPrint("NTFS: Init\n"); LIST_INIT(&gNtfsMounts); @@ -1613,9 +1613,7 @@ static KSTATUS DriverInitialize(NTL_MODULE* module) { return status; } - if (!gMountedCount) - DbgPrint("NTFS: no mountable NTFS partitions found; driver resident for partition changes.\n"); - DbgPrint("NTFS: Init complete; mounted %u volume(s).\n", gMountedCount); + DbgPrint("fs: ntfs volumes=%u\n", gMountedCount); return NTLSTATUS_SUCCESS; } diff --git a/code/drivers/fs/ntfs/ntfs3g/makefile b/code/drivers/fs/ntfs/ntfs3g/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/drivers/fs/ntfs/ntfs3g/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/drivers/fs/ntfs/ntfs3g/ntfs3g_driver.c b/code/drivers/fs/ntfs/ntfs3g/ntfs3g_driver.c index f6c29af..d537e1d 100644 --- a/code/drivers/fs/ntfs/ntfs3g/ntfs3g_driver.c +++ b/code/drivers/fs/ntfs/ntfs3g/ntfs3g_driver.c @@ -1114,7 +1114,8 @@ static void Ntfs3gUnmountPartition(const IO_PARTITION_INFO* partition, IO_PARTIT uint32_t count = gNtfs3gMountedCount; KeReleaseMutex(&gNtfs3gMountMutex); - (void)IoRemoveVolume(ioVolume, IoVolumeBackingRemoved); + (void)IoRemoveVolume(ioVolume, change == IoPartitionSurpriseRemoved + ? IoVolumeBackingRemoved : IoVolumeUnmounted); IoReleaseVolume(ioVolume); DbgPrint("NTFS3G: disk=%u lba=%llu %s; unmounted volume=%u; total=%u\n", partition->DiskIndex, (unsigned long long)partition->StartLba, @@ -1140,14 +1141,13 @@ static void Ntfs3gPartitionChange(const IO_PARTITION_INFO* partition, static KSTATUS DriverInitialize(NTL_MODULE* module) { (void)module; - DbgPrint("NTFS3G: Init (libntfs-3g replacement driver)\n"); Ntfs3gListInit(&gNtfs3gMounts); gNtfs3gMountedCount = 0; Ntfs3gEnsureMutexes(); KSTATUS status = IoRegisterPartitionChangeCallback(Ntfs3gPartitionChange, (void*)0); if (!KSUCCESS(status)) return status; - DbgPrint("NTFS3G: Init complete; mounted %u volume(s).\n", gNtfs3gMountedCount); + DbgPrint("fs: ntfs3g volumes=%u\n", gNtfs3gMountedCount); return NTLSTATUS_SUCCESS; } diff --git a/code/drivers/fs/ntfs/ntfs3g/sources b/code/drivers/fs/ntfs/ntfs3g/sources new file mode 100644 index 0000000..42796f7 --- /dev/null +++ b/code/drivers/fs/ntfs/ntfs3g/sources @@ -0,0 +1,13 @@ +TARGETNAME=ntfs +TARGETPATH=obj +TARGETTYPE=DRIVER +FLAVOR=NTFS +TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\printf.lib" +EXTRA_LFLAGS=/NOENTRY +INCLUDES=$(BASEDIR)\code\drivers\fs\ntfs\ntfs3g\include;$(BASEDIR)\code\drivers\fs\ntfs\ntfs3g\third_party\ntfs-3g\include;$(BASEDIR)\code\drivers\fs\ntfs\ntfs3g\third_party\ntfs-3g\include\ntfs-3g +SOURCES=@/code/drivers/fs/ntfs/ntfs3g/ntfs3g_port.c @/code/drivers/fs/ntfs/ntfs3g/ntfs3g_device.c @/code/drivers/fs/ntfs/ntfs3g/ntfs3g_driver.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/acls.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/attrib.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/attrlist.c \ + @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/bitmap.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/bootsect.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/cache.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/collate.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/compat.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/compress.c \ + @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/debug.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/device.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/dir.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/ea.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/efs.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/index.c \ + @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/inode.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/ioctl.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/lcnalloc.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/logfile.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/logging.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/mft.c \ + @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/misc.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/mst.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/object_id.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/realpath.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/reparse.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/runlist.c \ + @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/security.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/unistr.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/volume.c @/code/drivers/fs/ntfs/ntfs3g/third_party/ntfs-3g/libntfs-3g/xattrs.c diff --git a/code/drivers/input/dirs b/code/drivers/input/dirs new file mode 100644 index 0000000..e77b842 --- /dev/null +++ b/code/drivers/input/dirs @@ -0,0 +1 @@ +DIRS=ps2 serial diff --git a/code/drivers/input/ps2/makefile b/code/drivers/input/ps2/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/drivers/input/ps2/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/drivers/input/ps2/ps2.c b/code/drivers/input/ps2/ps2.c index 8973a89..3f729d9 100644 --- a/code/drivers/input/ps2/ps2.c +++ b/code/drivers/input/ps2/ps2.c @@ -4,6 +4,8 @@ #include "ps2.h" static KDPC gKeyboardDpc; +static KE_INTERRUPT* gKeyboardInterrupt; +static KE_INTERRUPT* gMouseInterrupt; static KDPC gMouseDpc; static volatile bool gKeyboardNextExtended; static INPUT_KEY_EVENT gKeyboardDpcQueue[KEYBOARD_DPC_QUEUE_SIZE]; @@ -24,7 +26,6 @@ static volatile uint32_t gMousePacketCount; static volatile uint32_t gKeyboardForeignIrqCount; static volatile uint32_t gMouseForeignIrqCount; -// Implements the ps2 Set1 To Key operation. static INPUT_KEY Ps2Set1ToKey(uint8_t make, bool extended) { if (extended) { switch (make) { @@ -135,7 +136,6 @@ static INPUT_KEY Ps2Set1ToKey(uint8_t make, bool extended) { } } -// Implements the ps2 Keyboard Dpc Routine operation. static void Ps2KeyboardDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2) { (void)dpc; (void)context; @@ -147,13 +147,12 @@ static void Ps2KeyboardDpcRoutine(KDPC* dpc, void* context, void* systemArgument gKeyboardDpcHead = (gKeyboardDpcHead + 1) & (int)KEYBOARD_DPC_QUEUE_MASK; KeInputSubmitKey(&event); uint32_t n = ++gKeyboardEventCount; - if ((n & (n - 1u)) == 0u) - DbgPrint("ps2: keyboard progress irq=%u raw=%u events=%u foreign=%u\n", - gKeyboardIrqCount, gKeyboardByteCount, n, gKeyboardForeignIrqCount); + // if ((n & (n - 1u)) == 0u) + // DbgPrint("ps2: keyboard progress irq=%u raw=%u events=%u foreign=%u\n", + // gKeyboardIrqCount, gKeyboardByteCount, n, gKeyboardForeignIrqCount); } } -// Implements the ps2 Queue Keyboard Event operation. static void Ps2QueueKeyboardEvent(INPUT_KEY key, bool pressed) { if (key >= sizeof(gKeyboardDown)) return; @@ -173,8 +172,8 @@ static void Ps2QueueKeyboardEvent(INPUT_KEY key, bool pressed) { KeInsertQueueDpc(&gKeyboardDpc, 0, 0); } -// Implements the ps2 Keyboard Isr operation. -static void Ps2KeyboardIsr(void) { +static void Ps2KeyboardIsr(void* context) { + (void)context; ++gKeyboardIrqCount; uint8_t status = __inbyte(PS2_STAT); // The 8042 output buffer is shared; never consume AUX bytes as scancodes. @@ -200,7 +199,6 @@ static void Ps2KeyboardIsr(void) { Ps2QueueKeyboardEvent(key, !released); } -// Implements the ps2 Mouse Dpc Routine operation. static void Ps2MouseDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2) { (void)dpc; (void)context; @@ -219,14 +217,14 @@ static void Ps2MouseDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, }; KeInputSubmitMouse(&event); uint32_t n = ++gMousePacketCount; - if ((n & (n - 1u)) == 0u) - DbgPrint("ps2: mouse progress irq=%u raw=%u packets=%u foreign=%u\n", - gMouseIrqCount, gMouseByteCount, n, gMouseForeignIrqCount); + // if ((n & (n - 1u)) == 0u) + // DbgPrint("ps2: mouse progress irq=%u raw=%u packets=%u foreign=%u\n", + // gMouseIrqCount, gMouseByteCount, n, gMouseForeignIrqCount); } } -// Implements the ps2 Mouse Isr operation. -static void Ps2MouseIsr(void) { +static void Ps2MouseIsr(void* context) { + (void)context; ++gMouseIrqCount; uint8_t status = __inbyte(PS2_STAT); if (!(status & PS2_STAT_OUT_FULL) || !(status & PS2_STAT_AUX_DATA)) { @@ -262,7 +260,6 @@ static void Ps2MouseIsr(void) { } } -// Implements the ps2 Controller Prepare operation. static void Ps2ControllerPrepare(void) { Ps2WriteCommand(0xADu); // disable keyboard port Ps2WriteCommand(0xA7u); // disable aux port @@ -281,7 +278,6 @@ static void Ps2ControllerPrepare(void) { Ps2FlushOutput(); } -// Implements the ps2 Controller Enable Interrupts operation. static void Ps2ControllerEnableInterrupts(void) { uint8_t commandByte = Ps2ReadCommandByte(); commandByte |= 0x01u; @@ -289,7 +285,6 @@ static void Ps2ControllerEnableInterrupts(void) { Ps2WriteCommandByte(commandByte); } -// Implements the ps2 Keyboard Initialize operation. static void Ps2KeyboardInitialize(void) { // Enable scanning. If the keyboard is absent, the timeout/ACK failure is // non-fatal; the IRQ path simply never produces events. @@ -297,7 +292,6 @@ static void Ps2KeyboardInitialize(void) { DbgPrint("ps2: keyboard enable did not ACK\n"); } -// Implements the ps2 Mouse Initialize operation. static void Ps2MouseInitialize(void) { if (!Ps2SendMouse(0xFFu)) { DbgPrint("ps2: mouse reset did not ACK\n"); @@ -318,8 +312,10 @@ static KSTATUS DriverInitialize(NTL_MODULE* module) { uint32_t keyboardId = 0, mouseId = 0; - KeInputRegisterDevice("ps2-keyboard", 0, &keyboardId); - KeInputRegisterDevice("ps2-mouse", 0, &mouseId); + KSTATUS status = KeInputRegisterDevice("ps2-keyboard", 0, &keyboardId); + if (!KSUCCESS(status)) return status; + status = KeInputRegisterDevice("ps2-mouse", 0, &mouseId); + if (!KSUCCESS(status)) return status; KeInitializeDpc(&gKeyboardDpc, Ps2KeyboardDpcRoutine, 0); KeInitializeDpc(&gMouseDpc, Ps2MouseDpcRoutine, 0); @@ -332,12 +328,32 @@ static KSTATUS DriverInitialize(NTL_MODULE* module) { Ps2KeyboardInitialize(); Ps2MouseInitialize(); - KeIrqRegister(PS2_IRQ_KEYBOARD, Ps2KeyboardIsr); - KeIrqRegister(PS2_IRQ_MOUSE, Ps2MouseIsr); - Ps2ControllerEnableInterrupts(); + KSTATUS irqStatus = KeInterruptConnectIsa(PS2_IRQ_KEYBOARD, 0, 0, + Ps2KeyboardIsr, 0, &gKeyboardInterrupt); + if (!KSUCCESS(irqStatus)) return irqStatus; + irqStatus = KeInterruptConnectIsa(PS2_IRQ_MOUSE, 0, 0, + Ps2MouseIsr, 0, &gMouseInterrupt); + if (!KSUCCESS(irqStatus)) return irqStatus; - DbgPrint("ps2: initialized keyboard=%u mouse=%u\n", keyboardId, mouseId); + DbgPrint("ps2: prepared keyboard=%u mouse=%u\n", keyboardId, mouseId); return NTLSTATUS_SUCCESS; } -NTL_DECLARE_MODULE(DriverInitialize); +static void Ps2CommitStart(NTL_MODULE* module) { + (void)module; + Ps2ControllerEnableInterrupts(); +} + +static void Ps2AbortStart(NTL_MODULE* module) { + (void)module; + if (gMouseInterrupt) { + KeInterruptDisconnect(gMouseInterrupt); + gMouseInterrupt = (KE_INTERRUPT*)0; + } + if (gKeyboardInterrupt) { + KeInterruptDisconnect(gKeyboardInterrupt); + gKeyboardInterrupt = (KE_INTERRUPT*)0; + } +} + +NTL_DECLARE_STAGED_MODULE(DriverInitialize, Ps2CommitStart, Ps2AbortStart); diff --git a/code/drivers/input/ps2/ps2_i8042.c b/code/drivers/input/ps2/ps2_i8042.c index 18af070..61dbfdf 100644 --- a/code/drivers/input/ps2/ps2_i8042.c +++ b/code/drivers/input/ps2/ps2_i8042.c @@ -2,12 +2,10 @@ #include "ps2.h" -// Implements the ps2 Pause operation. void Ps2Pause(void) { _mm_pause(); } -// Implements the ps2 Wait Input operation. void Ps2WaitInput(void) { int timeout = 100000; while ((__inbyte(PS2_STAT) & PS2_STAT_IN_FULL) && --timeout) { @@ -15,7 +13,6 @@ void Ps2WaitInput(void) { } } -// Implements the ps2 Wait Output operation. bool Ps2WaitOutput(void) { int timeout = 5000000; while (!(__inbyte(PS2_STAT) & PS2_STAT_OUT_FULL) && --timeout) { @@ -24,7 +21,6 @@ bool Ps2WaitOutput(void) { return timeout != 0; } -// Implements the ps2 Flush Output operation. void Ps2FlushOutput(void) { int timeout = 100000; while ((__inbyte(PS2_STAT) & PS2_STAT_OUT_FULL) && --timeout) { @@ -32,43 +28,36 @@ void Ps2FlushOutput(void) { } } -// Implements the ps2 Read Data operation. uint8_t Ps2ReadData(void) { if (!Ps2WaitOutput()) return 0xFFu; return __inbyte(PS2_DATA); } -// Implements the ps2 Write Command operation. void Ps2WriteCommand(uint8_t command) { Ps2WaitInput(); __outbyte(PS2_CMD, command); } -// Implements the ps2 Write Data operation. void Ps2WriteData(uint8_t data) { Ps2WaitInput(); __outbyte(PS2_DATA, data); } -// Implements the ps2 Read Command Byte operation. uint8_t Ps2ReadCommandByte(void) { Ps2WriteCommand(0x20u); return Ps2ReadData(); } -// Implements the ps2 Write Command Byte operation. void Ps2WriteCommandByte(uint8_t commandByte) { Ps2WriteCommand(0x60u); Ps2WriteData(commandByte); } -// Implements the ps2 Send Keyboard operation. bool Ps2SendKeyboard(uint8_t byte) { Ps2WriteData(byte); return Ps2ReadData() == 0xFAu; } -// Implements the ps2 Send Mouse operation. bool Ps2SendMouse(uint8_t byte) { Ps2WriteCommand(0xD4u); Ps2WriteData(byte); diff --git a/code/drivers/input/ps2/sources b/code/drivers/input/ps2/sources new file mode 100644 index 0000000..75f1cf3 --- /dev/null +++ b/code/drivers/input/ps2/sources @@ -0,0 +1,7 @@ +TARGETNAME=ps2 +TARGETPATH=obj +TARGETTYPE=DRIVER +FLAVOR=DRIVER +TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" +EXTRA_LFLAGS=/NOENTRY +SOURCES=@/code/drivers/input/ps2/ps2.c @/code/drivers/input/ps2/ps2_i8042.c diff --git a/code/drivers/input/serial/makefile b/code/drivers/input/serial/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/drivers/input/serial/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/drivers/input/serial/serial.c b/code/drivers/input/serial/serial.c index 5c55c29..b12cfb1 100644 --- a/code/drivers/input/serial/serial.c +++ b/code/drivers/input/serial/serial.c @@ -49,6 +49,7 @@ typedef enum SERIAL_ESCAPE_STATE { } SERIAL_ESCAPE_STATE; static KDPC gSerialRxDpc; +static KE_INTERRUPT* gSerialInterrupt; static volatile SERIAL_ESCAPE_STATE gSerialEscapeState; static volatile uint8_t gSerialCsiNumber; static volatile bool gSerialDropNextLf; @@ -308,7 +309,8 @@ static void SerialQueueRxByte(uint8_t ch) { } // Handles receive interrupts for COM1. -static void SerialIsr(void) { +static void SerialIsr(void* context) { + (void)context; for (uint32_t i = 0; i < 256u; i++) { if ((SerialRead(SERIAL_REG_LSR) & SERIAL_LSR_DATA_READY) == 0) break; @@ -367,11 +369,25 @@ static KSTATUS SerialInitialize(NTL_MODULE* module) { gSerialRxTail = 0; gSerialRxDropped = 0; - KeIrqRegister(SERIAL_COM1_IRQ, SerialIsr); - SerialWrite(SERIAL_REG_IER, SERIAL_IER_RX_READY); + KSTATUS irqStatus = KeInterruptConnectIsa(SERIAL_COM1_IRQ, 0, 0, + SerialIsr, 0, &gSerialInterrupt); + if (!KSUCCESS(irqStatus)) return irqStatus; - DbgPrint("serial: initialized COM1 input device=%u irq=%u\n", deviceId, SERIAL_COM1_IRQ); + DbgPrint("serial: prepared COM1 input device=%u irq=%u\n", deviceId, SERIAL_COM1_IRQ); return NTLSTATUS_SUCCESS; } -NTL_DECLARE_MODULE(SerialInitialize); +static void SerialCommitStart(NTL_MODULE* module) { + (void)module; + SerialWrite(SERIAL_REG_IER, SERIAL_IER_RX_READY); +} + +static void SerialAbortStart(NTL_MODULE* module) { + (void)module; + if (!gSerialInterrupt) return; + SerialWrite(SERIAL_REG_IER, 0); + KeInterruptDisconnect(gSerialInterrupt); + gSerialInterrupt = (KE_INTERRUPT*)0; +} + +NTL_DECLARE_STAGED_MODULE(SerialInitialize, SerialCommitStart, SerialAbortStart); diff --git a/code/drivers/input/serial/sources b/code/drivers/input/serial/sources new file mode 100644 index 0000000..881a958 --- /dev/null +++ b/code/drivers/input/serial/sources @@ -0,0 +1,7 @@ +TARGETNAME=serial +TARGETPATH=obj +TARGETTYPE=DRIVER +FLAVOR=DRIVER +TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" +EXTRA_LFLAGS=/NOENTRY +SOURCES=@/code/drivers/input/serial/serial.c diff --git a/code/drivers/net/dirs b/code/drivers/net/dirs new file mode 100644 index 0000000..15a1c91 --- /dev/null +++ b/code/drivers/net/dirs @@ -0,0 +1 @@ +DIRS=lwip rtl8139 rtl816x diff --git a/code/drivers/net/lwip/lwip_stack.c b/code/drivers/net/lwip/lwip_stack.c index 13910e9..a467a77 100644 --- a/code/drivers/net/lwip/lwip_stack.c +++ b/code/drivers/net/lwip/lwip_stack.c @@ -146,7 +146,6 @@ static NET_STACK_PROVIDER gLwipProvider = { LwipProviderReceiveFrame, }; -// Implements the err To Status operation. static KSTATUS LwipErrToStatus(err_t err) { switch (err) { case ERR_OK: return NTLSTATUS_SUCCESS; @@ -167,7 +166,6 @@ static KSTATUS LwipErrToStatus(err_t err) { } } -// Implements the ascii Is Digit operation. static bool LwipAsciiIsDigit(char c) { return c >= '0' && c <= '9'; } @@ -365,20 +363,17 @@ static KSTATUS LwipLoadNetifConfig(const NET_DEVICE* device, LWIP_NETIF_CONFIG* return NTLSTATUS_SUCCESS; } -// Implements the socket Lock operation. static KSTATUS LwipSocketLock(LWIP_PROVIDER_SOCKET* s) { if (!s || !s->Lock) return NTLSTATUS_INVALID_PARAMETER; return KeWaitSemaphore(s->Lock, KE_WAIT_INFINITE); } -// Implements the socket Unlock operation. static void LwipSocketUnlock(LWIP_PROVIDER_SOCKET* s) { if (s && s->Lock) KeSignalSemaphore(s->Lock); } -// Implements the socket Callback operation. static void LwipSocketCallback(struct netconn* conn, enum netconn_evt evt, u16_t len) { (void)len; if (!conn) @@ -571,7 +566,6 @@ static bool LwipSocketFamilyMatches(const LWIP_PROVIDER_SOCKET* s, const SYS_SOC return false; } -// Implements the socket Make Ip operation. static KSTATUS LwipSocketMakeIp(const SYS_SOCKET_ADDRESS_K* address, ip_addr_t* out) { if (!address || !out) return NTLSTATUS_INVALID_PARAMETER; @@ -595,7 +589,6 @@ static KSTATUS LwipSocketMakeIp(const SYS_SOCKET_ADDRESS_K* address, ip_addr_t* return NTLSTATUS_NOT_SUPPORTED; } -// Implements the socket Fill Address operation. static void LwipSocketFillAddress(SYS_SOCKET_ADDRESS_K* out, const ip_addr_t* ip, u16_t port) { if (!out) return; @@ -624,7 +617,6 @@ static void LwipSocketFillAddress(SYS_SOCKET_ADDRESS_K* out, const ip_addr_t* ip out->Address[3] = (uint8_t)ip4_addr4(ip_2_ip4(ip)); } -// Implements the low Level Output operation. static err_t LwipLowLevelOutput(struct netif* netif, struct pbuf* p) { LWIP_BINDING* b = (LWIP_BINDING*)netif->state; if (!b || !b->Device || !p || p->tot_len < NET_ETHERNET_HEADER_LENGTH) @@ -652,7 +644,6 @@ static err_t LwipLowLevelOutput(struct netif* netif, struct pbuf* p) { return KSUCCESS(st) ? ERR_OK : ERR_IF; } -// Implements the netif Init operation. static err_t LwipNetifInit(struct netif* netif) { LWIP_BINDING* b = (LWIP_BINDING*)netif->state; if (!b || !b->Device) @@ -773,7 +764,6 @@ static KSTATUS LwipDelayThread(uint64_t milliseconds) { return KeDelayThread(milliseconds); } -// Implements the stack Initialize operation. static KSTATUS LwipStackInitialize(void) { if (gLwipInitialized) return NTLSTATUS_SUCCESS; @@ -796,7 +786,6 @@ static KSTATUS LwipStackInitialize(void) { return NTLSTATUS_SUCCESS; } -// Implements the provider Attach Device operation. static KSTATUS LwipProviderAttachDevice(NET_DEVICE* device) { if (!gLwipInitialized) return NTLSTATUS_NOT_SUPPORTED; @@ -855,7 +844,6 @@ static KSTATUS LwipProviderAttachDevice(NET_DEVICE* device) { return NTLSTATUS_SUCCESS; } -// Implements the provider Receive Frame operation. static KSTATUS LwipProviderReceiveFrame(NET_DEVICE* device, const void* frame, size_t length) { if (!gLwipInitialized) return NTLSTATUS_NOT_SUPPORTED; @@ -889,7 +877,6 @@ static KSTATUS LwipProviderReceiveFrame(NET_DEVICE* device, const void* frame, s return NTLSTATUS_SUCCESS; } -// Implements the provider Socket Create operation. static KSTATUS LwipProviderSocketCreate(uint32_t domain, uint32_t type, uint32_t protocol, void** outSocket) { if (!outSocket) return NTLSTATUS_INVALID_PARAMETER; @@ -937,7 +924,6 @@ static KSTATUS LwipProviderSocketCreate(uint32_t domain, uint32_t type, uint32_t return NTLSTATUS_SUCCESS; } -// Implements the provider Socket Close operation. static void LwipProviderSocketClose(void* socket) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (!s) @@ -964,7 +950,6 @@ static void LwipProviderSocketClose(void* socket) { MmFreePool(s); } -// Implements the provider Bind operation. static KSTATUS LwipProviderBind(void* socket, const SYS_SOCKET_ADDRESS_K* address, size_t addressSize) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (!s || !address) @@ -999,7 +984,6 @@ static KSTATUS LwipProviderBind(void* socket, const SYS_SOCKET_ADDRESS_K* addres return LwipErrToStatus(err); } -// Implements the provider Listen operation. static KSTATUS LwipProviderListen(void* socket, uint32_t backlog) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (!s) @@ -1028,7 +1012,6 @@ static KSTATUS LwipProviderListen(void* socket, uint32_t backlog) { return LwipErrToStatus(err); } -// Implements the provider Accept operation. static KSTATUS LwipProviderAccept(void* socket, void** acceptedOut, SYS_SOCKET_ADDRESS_K* remoteOut, volatile uint8_t* cancelRequested) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (!s || !acceptedOut) @@ -1087,7 +1070,6 @@ static KSTATUS LwipProviderAccept(void* socket, void** acceptedOut, SYS_SOCKET_A return NTLSTATUS_SUCCESS; } -// Implements the provider Connect operation. static KSTATUS LwipProviderConnect(void* socket, const SYS_SOCKET_ADDRESS_K* address, size_t addressSize, volatile uint8_t* cancelRequested) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (!s || !address) @@ -1173,7 +1155,6 @@ static KSTATUS LwipProviderConnect(void* socket, const SYS_SOCKET_ADDRESS_K* add } } -// Implements the provider Send operation. static KSTATUS LwipProviderSend(void* socket, const void* buffer, size_t length, uint32_t flags, size_t* sentOut) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (sentOut) @@ -1257,7 +1238,6 @@ static KSTATUS LwipReceiveFromBuffered(LWIP_PROVIDER_SOCKET* s, uint8_t* out, return NTLSTATUS_SUCCESS; } -// Implements the provider Receive operation. static KSTATUS LwipProviderReceive(void* socket, void* buffer, size_t length, uint32_t flags, size_t* receivedOut, volatile uint8_t* cancelRequested) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (receivedOut) @@ -1462,7 +1442,6 @@ static KSTATUS LwipProviderReceiveFrom(void* socket, void* buffer, size_t length return LwipErrToStatus(err); } -// Implements the provider Set Option operation. static KSTATUS LwipProviderSetOption(void* socket, uint32_t option, const void* value, size_t valueSize) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (!s || !value) @@ -1501,7 +1480,6 @@ static KSTATUS LwipProviderSetOption(void* socket, uint32_t option, const void* return NTLSTATUS_SUCCESS; } -// Implements the provider Get Option operation. static KSTATUS LwipProviderGetOption(void* socket, uint32_t option, void* value, size_t valueSize, size_t* actualSizeOut) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (actualSizeOut) @@ -1538,7 +1516,6 @@ static KSTATUS LwipProviderGetOption(void* socket, uint32_t option, void* value, return NTLSTATUS_SUCCESS; } -// Implements the provider Poll operation. static KSTATUS LwipProviderPoll(void* socket, uint32_t events, uint32_t* returnedEventsOut) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (!s || !returnedEventsOut) @@ -1577,7 +1554,6 @@ static KSTATUS LwipProviderPoll(void* socket, uint32_t events, uint32_t* returne return NTLSTATUS_SUCCESS; } -// Implements the provider Shutdown operation. static KSTATUS LwipProviderShutdown(void* socket, uint32_t how) { LWIP_PROVIDER_SOCKET* s = (LWIP_PROVIDER_SOCKET*)socket; if (!s) @@ -1648,7 +1624,6 @@ static void LwipResolveStartCallback(void* argument) { LwipResolveRelease(context); } -// Implements the provider Resolve Host operation. static KSTATUS LwipProviderResolveHost(const char* name, uint32_t family, SYS_SOCKET_ADDRESS_K* addressOut) { if (!name || !addressOut) return NTLSTATUS_INVALID_PARAMETER; @@ -1819,7 +1794,6 @@ static KSTATUS LwipDispatchInternalDeviceControl(DEVICE_OBJECT* device, IRP* irp static KSTATUS DriverInitialize(NTL_MODULE* module) { (void)module; - DbgPrint("lwIP: driver loading...\n"); LWIP_NETIF_CONFIG defaultConfig; KSTATUS st = LwipLoadConfigFromSection(LWIP_SETTINGS_DEFAULT_SECTION, &defaultConfig); @@ -1852,7 +1826,6 @@ static KSTATUS DriverInitialize(NTL_MODULE* module) { return st; } - DbgPrint("lwIP: driver initialized\n"); return NTLSTATUS_SUCCESS; } diff --git a/code/drivers/net/lwip/lwip_sys_arch.c b/code/drivers/net/lwip/lwip_sys_arch.c index ec7c7f2..cfee74c 100644 --- a/code/drivers/net/lwip/lwip_sys_arch.c +++ b/code/drivers/net/lwip/lwip_sys_arch.c @@ -43,7 +43,6 @@ struct sys_mbox { static uint64_t (*gLwipQueryTicksUs)(void) = 0; static uint32_t gRandState = 0x4b4e4554u; // 'KNET' -// Implements the port Set Timer Query operation. void LwipPortSetTimerQuery(uint64_t (*query_ticks_us)(void)) { gLwipQueryTicksUs = query_ticks_us; } @@ -54,7 +53,6 @@ unsigned int lwip_port_rand(void) { return gRandState; } -// Implements the sys init operation. void sys_init(void) { } @@ -81,7 +79,6 @@ u32_t sys_jiffies(void) { #undef errno #endif int errno; -// Implements the errno operation. int* __cdecl _errno(void) { return &errno; } err_t sys_sem_new(sys_sem_t* sem, u8_t count) { @@ -104,7 +101,6 @@ err_t sys_sem_new(sys_sem_t* sem, u8_t count) { return ERR_OK; } -// Implements the sys sem signal operation. void sys_sem_signal(sys_sem_t* sem) { if (sem && *sem && (*sem)->Sem) KeSignalSemaphore((*sem)->Sem); @@ -127,7 +123,6 @@ u32_t sys_arch_sem_wait(sys_sem_t* sem, u32_t timeout) { : SYS_ARCH_TIMEOUT; } -// Implements the sys sem free operation. void sys_sem_free(sys_sem_t* sem) { if (!sem || !*sem) return; @@ -157,19 +152,16 @@ err_t sys_mutex_new(sys_mutex_t* mutex) { return ERR_OK; } -// Implements the sys mutex lock operation. void sys_mutex_lock(sys_mutex_t* mutex) { if (mutex && *mutex && (*mutex)->Sem) (void)KeWaitSemaphore((*mutex)->Sem, KE_WAIT_INFINITE); } -// Implements the sys mutex unlock operation. void sys_mutex_unlock(sys_mutex_t* mutex) { if (mutex && *mutex && (*mutex)->Sem) KeSignalSemaphore((*mutex)->Sem); } -// Implements the sys mutex free operation. void sys_mutex_free(sys_mutex_t* mutex) { if (!mutex || !*mutex) return; @@ -179,7 +171,6 @@ void sys_mutex_free(sys_mutex_t* mutex) { *mutex = 0; } -// Implements the mbox Try Post operation. static err_t LwipMboxTryPost(sys_mbox_t* mbox, void* msg) { if (!mbox || !*mbox || !(*mbox)->Valid) return ERR_ARG; @@ -232,7 +223,6 @@ err_t sys_mbox_new(sys_mbox_t* mbox, int size) { return ERR_OK; } -// Implements the sys mbox post operation. void sys_mbox_post(sys_mbox_t* mbox, void* msg) { // lwIP promises this is not called from ISR context. while (LwipMboxTryPost(mbox, msg) != ERR_OK) @@ -247,7 +237,6 @@ err_t sys_mbox_trypost_fromisr(sys_mbox_t* mbox, void* msg) { return LwipMboxTryPost(mbox, msg); } -// Implements the mbox Pop After Item operation. static u32_t LwipMboxPopAfterItem(sys_mbox_t* mbox, void** msg, u32_t waited) { struct sys_mbox* m = *mbox; uintptr_t flags = KeAcquireSpinlock(&m->Lock); @@ -296,7 +285,6 @@ u32_t sys_arch_mbox_tryfetch(sys_mbox_t* mbox, void** msg) { return LwipMboxPopAfterItem(mbox, msg, 0); } -// Implements the sys mbox free operation. void sys_mbox_free(sys_mbox_t* mbox) { if (!mbox || !*mbox) return; diff --git a/code/drivers/net/lwip/makefile b/code/drivers/net/lwip/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/drivers/net/lwip/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/drivers/net/lwip/sources b/code/drivers/net/lwip/sources new file mode 100644 index 0000000..b8562f0 --- /dev/null +++ b/code/drivers/net/lwip/sources @@ -0,0 +1,15 @@ +TARGETNAME=lwip +TARGETPATH=obj +TARGETTYPE=DRIVER +FLAVOR=LWIP +TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" +EXTRA_LFLAGS=/NOENTRY +INCLUDES=$(BASEDIR)\code\drivers\net\lwip\include;$(BASEDIR)\code\drivers\net\lwip\third_party\lwip\src\include +SOURCES=@/code/drivers/net/lwip/lwip_sys_arch.c @/code/drivers/net/lwip/lwip_stack.c @/code/drivers/net/lwip/third_party/lwip/src/core/init.c @/code/drivers/net/lwip/third_party/lwip/src/core/def.c @/code/drivers/net/lwip/third_party/lwip/src/core/dns.c @/code/drivers/net/lwip/third_party/lwip/src/core/inet_chksum.c \ + @/code/drivers/net/lwip/third_party/lwip/src/core/ip.c @/code/drivers/net/lwip/third_party/lwip/src/core/mem.c @/code/drivers/net/lwip/third_party/lwip/src/core/memp.c @/code/drivers/net/lwip/third_party/lwip/src/core/netif.c @/code/drivers/net/lwip/third_party/lwip/src/core/pbuf.c @/code/drivers/net/lwip/third_party/lwip/src/core/raw.c \ + @/code/drivers/net/lwip/third_party/lwip/src/core/stats.c @/code/drivers/net/lwip/third_party/lwip/src/core/sys.c @/code/drivers/net/lwip/third_party/lwip/src/core/altcp.c @/code/drivers/net/lwip/third_party/lwip/src/core/altcp_alloc.c @/code/drivers/net/lwip/third_party/lwip/src/core/altcp_tcp.c @/code/drivers/net/lwip/third_party/lwip/src/core/tcp.c \ + @/code/drivers/net/lwip/third_party/lwip/src/core/tcp_in.c @/code/drivers/net/lwip/third_party/lwip/src/core/tcp_out.c @/code/drivers/net/lwip/third_party/lwip/src/core/timeouts.c @/code/drivers/net/lwip/third_party/lwip/src/core/udp.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/acd.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/autoip.c \ + @/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/dhcp.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/etharp.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/icmp.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/igmp.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/ip4_frag.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/ip4.c \ + @/code/drivers/net/lwip/third_party/lwip/src/core/ipv4/ip4_addr.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/dhcp6.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/ethip6.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/icmp6.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/inet6.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/ip6_frag.c \ + @/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/ip6.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/ip6_addr.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/mld6.c @/code/drivers/net/lwip/third_party/lwip/src/core/ipv6/nd6.c @/code/drivers/net/lwip/third_party/lwip/src/api/api_lib.c @/code/drivers/net/lwip/third_party/lwip/src/api/api_msg.c \ + @/code/drivers/net/lwip/third_party/lwip/src/api/err.c @/code/drivers/net/lwip/third_party/lwip/src/api/netbuf.c @/code/drivers/net/lwip/third_party/lwip/src/api/tcpip.c @/code/drivers/net/lwip/third_party/lwip/src/netif/ethernet.c diff --git a/code/drivers/net/rtl8139/makefile b/code/drivers/net/rtl8139/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/drivers/net/rtl8139/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/drivers/net/rtl8139/rtl8139.c b/code/drivers/net/rtl8139/rtl8139.c index d107380..8944c02 100644 --- a/code/drivers/net/rtl8139/rtl8139.c +++ b/code/drivers/net/rtl8139/rtl8139.c @@ -4,9 +4,6 @@ #include "rtl8139.h" static DRIVER_OBJECT gRtl8139Driver; -static RTL8139_DEVICE* gRtl8139Devices[RTL8139_MAX_DEVICES]; -static uint32_t gRtl8139DeviceCount; -static SPINLOCK gRtl8139RegistryLock = SPINLOCK_INIT; static const IO_DEVICE_ID gRtl8139Ids[] = { { IoBusPci, { "PCI\\VEN_10EC&DEV_8139", sizeof("PCI\\VEN_10EC&DEV_8139") - 1 } }, @@ -17,53 +14,45 @@ static const IO_DRIVER_ID_TABLE gRtl8139IdTable = { sizeof(gRtl8139Ids) / sizeof(gRtl8139Ids[0]), }; -// Implements the memory Barrier operation. static __forceinline void Rtl8139MemoryBarrier(void) { _ReadWriteBarrier(); _mm_mfence(); _ReadWriteBarrier(); } -// Implements the read8 operation. static uint8_t Rtl8139Read8(RTL8139_DEVICE* r, uint32_t reg) { if (r->UseMmio) return *(volatile uint8_t*)(r->Mmio + reg); return __inbyte((unsigned short)(r->IoBase + reg)); } -// Implements the read16 operation. static uint16_t Rtl8139Read16(RTL8139_DEVICE* r, uint32_t reg) { if (r->UseMmio) return *(volatile uint16_t*)(r->Mmio + reg); return __inword((unsigned short)(r->IoBase + reg)); } -// Implements the read32 operation. static uint32_t Rtl8139Read32(RTL8139_DEVICE* r, uint32_t reg) { if (r->UseMmio) return *(volatile uint32_t*)(r->Mmio + reg); return __indword((unsigned short)(r->IoBase + reg)); } -// Implements the write8 operation. static void Rtl8139Write8(RTL8139_DEVICE* r, uint32_t reg, uint8_t value) { if (r->UseMmio) *(volatile uint8_t*)(r->Mmio + reg) = value; else __outbyte((unsigned short)(r->IoBase + reg), value); } -// Implements the write16 operation. static void Rtl8139Write16(RTL8139_DEVICE* r, uint32_t reg, uint16_t value) { if (r->UseMmio) *(volatile uint16_t*)(r->Mmio + reg) = value; else __outword((unsigned short)(r->IoBase + reg), value); } -// Implements the write32 operation. static void Rtl8139Write32(RTL8139_DEVICE* r, uint32_t reg, uint32_t value) { if (r->UseMmio) *(volatile uint32_t*)(r->Mmio + reg) = value; else __outdword((unsigned short)(r->IoBase + reg), value); } -// Implements the reset operation. static KSTATUS Rtl8139Reset(RTL8139_DEVICE* r) { Rtl8139Write8(r, RTL8139_REG_CMD, RTL8139_CMD_RST); for (uint32_t i = 0; i < 1000; i++) { @@ -157,7 +146,6 @@ static KSTATUS Rtl8139AllocateDma(RTL8139_DEVICE* r) { return NTLSTATUS_SUCCESS; } -// Implements the rx Read16 operation. static uint16_t Rtl8139RxRead16(RTL8139_DEVICE* r, uint32_t offset) { offset %= RTL8139_RX_RING_SIZE; uint16_t lo = r->RxBuffer[offset]; @@ -165,7 +153,6 @@ static uint16_t Rtl8139RxRead16(RTL8139_DEVICE* r, uint32_t offset) { return (uint16_t)(lo | (hi << 8)); } -// Implements the rx Copy operation. static void Rtl8139RxCopy(RTL8139_DEVICE* r, uint32_t offset, void* dst, uint32_t length) { uint8_t* out = (uint8_t*)dst; offset %= RTL8139_RX_RING_SIZE; @@ -178,7 +165,6 @@ static void Rtl8139RxCopy(RTL8139_DEVICE* r, uint32_t offset, void* dst, uint32_ memcpy(out + first, r->RxBuffer, length - first); } -// Implements the program Hardware operation. static void Rtl8139ProgramHardware(RTL8139_DEVICE* r) { // Wake the device and clear stale interrupts before installing buffers. Rtl8139Write8(r, RTL8139_REG_CONFIG1, 0x00); @@ -252,7 +238,6 @@ static void Rtl8139HandleRx(RTL8139_DEVICE* r) { } } -// Implements the dpc Routine operation. static void Rtl8139DpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2) { (void)dpc; (void)systemArgument1; @@ -273,74 +258,19 @@ static void Rtl8139DpcRoutine(KDPC* dpc, void* context, void* systemArgument1, v DbgPrint("RTL8139: interrupt error bits=0x%04x\n", status); } -// Registers device. -static KSTATUS Rtl8139RegisterDevice(RTL8139_DEVICE* r) { - if (!r) return NTLSTATUS_INVALID_PARAMETER; +static void Rtl8139Isr(void* context) { + RTL8139_DEVICE* r = (RTL8139_DEVICE*)context; + if (!r || !r->Started || r->Removed || r->SurpriseRemoved) return; + uint16_t status = Rtl8139Read16(r, RTL8139_REG_ISR); + status &= RTL8139_INTR_ENABLES; + if (!status || status == 0xFFFFu) + return; - uintptr_t flags = KeAcquireSpinlock(&gRtl8139RegistryLock); - for (uint32_t i = 0; i < gRtl8139DeviceCount; i++) { - if (gRtl8139Devices[i] == r) { - KeReleaseSpinlock(&gRtl8139RegistryLock, flags); - return NTLSTATUS_SUCCESS; - } - } - - if (gRtl8139DeviceCount >= RTL8139_MAX_DEVICES) { - KeReleaseSpinlock(&gRtl8139RegistryLock, flags); - return NTLSTATUS_NO_MEMORY; - } - - gRtl8139Devices[gRtl8139DeviceCount++] = r; - KeReleaseSpinlock(&gRtl8139RegistryLock, flags); - return NTLSTATUS_SUCCESS; + Rtl8139Write16(r, RTL8139_REG_ISR, status); + r->PendingIsr |= status; + KeInsertQueueDpc(&r->Dpc, (void*)0, (void*)0); } -// Implements the unregister Device operation. -static void Rtl8139UnregisterDevice(RTL8139_DEVICE* r) { - if (!r) return; - - uintptr_t flags = KeAcquireSpinlock(&gRtl8139RegistryLock); - for (uint32_t i = 0; i < gRtl8139DeviceCount; i++) { - if (gRtl8139Devices[i] == r) { - gRtl8139Devices[i] = gRtl8139Devices[gRtl8139DeviceCount - 1u]; - gRtl8139Devices[gRtl8139DeviceCount - 1u] = (RTL8139_DEVICE*)0; - gRtl8139DeviceCount--; - break; - } - } - KeReleaseSpinlock(&gRtl8139RegistryLock, flags); -} - -// Implements the isr operation. -static void Rtl8139Isr(void) { - RTL8139_DEVICE* snapshot[RTL8139_MAX_DEVICES]; - uint32_t count = 0; - - uintptr_t flags = KeAcquireSpinlock(&gRtl8139RegistryLock); - count = gRtl8139DeviceCount; - if (count > RTL8139_MAX_DEVICES) - count = RTL8139_MAX_DEVICES; - for (uint32_t i = 0; i < count; i++) - snapshot[i] = gRtl8139Devices[i]; - KeReleaseSpinlock(&gRtl8139RegistryLock, flags); - - for (uint32_t i = 0; i < count; i++) { - RTL8139_DEVICE* r = snapshot[i]; - if (!r || !r->Started || r->Removed || r->SurpriseRemoved) - continue; - - uint16_t status = Rtl8139Read16(r, RTL8139_REG_ISR); - status &= RTL8139_INTR_ENABLES; - if (!status || status == 0xFFFFu) - continue; - - Rtl8139Write16(r, RTL8139_REG_ISR, status); - r->PendingIsr |= status; - KeInsertQueueDpc(&r->Dpc, (void*)0, (void*)0); - } -} - -// Implements the send Frame operation. static KSTATUS Rtl8139SendFrame(NET_DEVICE* device, const void* frame, size_t length) { if (!device || !frame) return NTLSTATUS_INVALID_PARAMETER; @@ -377,7 +307,6 @@ static KSTATUS Rtl8139SendFrame(NET_DEVICE* device, const void* frame, size_t le return NTLSTATUS_SUCCESS; } -// Implements the select Register Bar operation. static KSTATUS Rtl8139SelectRegisterBar(RTL8139_DEVICE* r) { if (!r || !r->Pdo) return NTLSTATUS_INVALID_PARAMETER; @@ -478,12 +407,10 @@ static KSTATUS Rtl8139StartDevice(RTL8139_DEVICE* r) { return st; } - st = PciGetInterrupt(r->Pdo, &r->Irq); - if (!KSUCCESS(st) || r->Irq == 0xFFu) { - DbgPrint("RTL8139: no legacy PCI IRQ line wired\n"); - return KSUCCESS(st) ? NTLSTATUS_NOT_SUPPORTED : st; - } - + r->InterruptRequest.Routine = Rtl8139Isr; + r->InterruptRequest.Context = r; + r->InterruptRequest.Affinity = 0; + r->InterruptRequest.Interrupt = (KE_INTERRUPT*)0; Rtl8139Write8(r, RTL8139_REG_CONFIG1, 0x00); st = Rtl8139Reset(r); if (!KSUCCESS(st)) { @@ -492,11 +419,10 @@ static KSTATUS Rtl8139StartDevice(RTL8139_DEVICE* r) { } Rtl8139ReadMac(r); - DbgPrint("RTL8139: MAC %02x:%02x:%02x:%02x:%02x:%02x irq=%u\n", + DbgPrint("RTL8139: MAC %02x:%02x:%02x:%02x:%02x:%02x\n", r->NetDevice.HardwareAddress[0], r->NetDevice.HardwareAddress[1], r->NetDevice.HardwareAddress[2], r->NetDevice.HardwareAddress[3], - r->NetDevice.HardwareAddress[4], r->NetDevice.HardwareAddress[5], - r->Irq); + r->NetDevice.HardwareAddress[4], r->NetDevice.HardwareAddress[5]); st = Rtl8139AllocateDma(r); if (!KSUCCESS(st)) @@ -508,13 +434,16 @@ static KSTATUS Rtl8139StartDevice(RTL8139_DEVICE* r) { r->NetDevice.DriverContext = r; r->NetDevice.SendFrame = Rtl8139SendFrame; - st = Rtl8139RegisterDevice(r); + bool message; + st = PciConnectInterrupts(r->Pdo, &r->InterruptRequest, 1u, &message); if (!KSUCCESS(st)) { Rtl8139ReleaseDma(r); return st; } - - KeIrqRegister(r->Irq, Rtl8139Isr); + KE_INTERRUPT_INFO route; + if (KSUCCESS(KeInterruptQuery(r->InterruptRequest.Interrupt, &route))) + DbgPrint("RTL8139: cpu=%u vector=0x%02x mode=%s\n", + route.CpuIndex, route.Vector, message ? "MSI/MSI-X" : "INTx"); r->Started = true; Rtl8139ProgramHardware(r); r->Fdo->PnpState = DevicePnpStarted; @@ -522,12 +451,13 @@ static KSTATUS Rtl8139StartDevice(RTL8139_DEVICE* r) { st = NetRegisterDevice(&r->NetDevice); if (!KSUCCESS(st)) { Rtl8139StopDma(r); - Rtl8139UnregisterDevice(r); + if (r->InterruptRequest.Interrupt) + PciDisconnectInterrupts(r->Pdo, &r->InterruptRequest, 1u); Rtl8139ReleaseDma(r); return st; } - DbgPrint("RTL8139: initialized; RX/TX enabled on IRQ %u\n", r->Irq); + DbgPrint("RTL8139: initialized; RX/TX interrupt connected\n"); return NTLSTATUS_SUCCESS; } @@ -562,7 +492,8 @@ KSTATUS Rtl8139DispatchPnp(DEVICE_OBJECT* device, IRP* irp) { r->Removed = true; device->PnpState = DevicePnpDeleted; Rtl8139StopDma(r); - Rtl8139UnregisterDevice(r); + if (r->InterruptRequest.Interrupt) + PciDisconnectInterrupts(r->Pdo, &r->InterruptRequest, 1u); Rtl8139ReleaseDma(r); IoDetachDevice(device); IoDeleteDevice(device); @@ -573,7 +504,6 @@ KSTATUS Rtl8139DispatchPnp(DEVICE_OBJECT* device, IRP* irp) { } } -// Implements the add Device operation. KSTATUS Rtl8139AddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return NTLSTATUS_INVALID_PARAMETER; @@ -589,7 +519,7 @@ KSTATUS Rtl8139AddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObj r->Magic = RTL8139_DEVICE_MAGIC; r->Fdo = fdo; r->Pdo = physicalDeviceObject; - r->Irq = 0xFFu; + r->PciInfo.InterruptLine = 0xFFu; r->TxLock = (SPINLOCK)SPINLOCK_INIT; r->LowerDevice = IoAttachDeviceToDeviceStack(fdo, physicalDeviceObject); @@ -605,9 +535,7 @@ KSTATUS Rtl8139AddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObj static KSTATUS DriverInitialize(NTL_MODULE* module) { (void)module; - DbgPrint("RTL8139: driver loading...\n"); - gRtl8139DeviceCount = 0; memset(&gRtl8139Driver, 0, sizeof(gRtl8139Driver)); IoInitializeDriverObject(&gRtl8139Driver, SYS_SV_LITERAL("rtl8139")); diff --git a/code/drivers/net/rtl8139/rtl8139.h b/code/drivers/net/rtl8139/rtl8139.h index fd5f1c6..d185f16 100644 --- a/code/drivers/net/rtl8139/rtl8139.h +++ b/code/drivers/net/rtl8139/rtl8139.h @@ -105,7 +105,7 @@ typedef struct RTL8139_DEVICE { PCI_DEVICE_INFO PciInfo; PCI_BAR RegisterBar; uint64_t RegisterBytes; - uint8_t Irq; + PCI_INTERRUPT_REQUEST InterruptRequest; bool Started; bool Removed; diff --git a/code/drivers/net/rtl8139/sources b/code/drivers/net/rtl8139/sources new file mode 100644 index 0000000..604bc15 --- /dev/null +++ b/code/drivers/net/rtl8139/sources @@ -0,0 +1,7 @@ +TARGETNAME=rtl8139 +TARGETPATH=obj +TARGETTYPE=DRIVER +FLAVOR=DRIVER +TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\pci.lib" +EXTRA_LFLAGS=/NOENTRY +SOURCES=@/code/drivers/net/rtl8139/rtl8139.c diff --git a/code/drivers/net/rtl816x/makefile b/code/drivers/net/rtl816x/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/drivers/net/rtl816x/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/drivers/net/rtl816x/rtl816x.c b/code/drivers/net/rtl816x/rtl816x.c index cd075a0..892eefb 100644 --- a/code/drivers/net/rtl816x/rtl816x.c +++ b/code/drivers/net/rtl816x/rtl816x.c @@ -4,9 +4,6 @@ #include "rtl816x.h" static DRIVER_OBJECT gRtl816xDriver; -static RTL816X_DEVICE* gRtl816xDevices[RTL816X_MAX_DEVICES]; -static uint32_t gRtl816xDeviceCount; -static SPINLOCK gRtl816xRegistryLock = SPINLOCK_INIT; static const IO_DEVICE_ID gRtl816xIds[] = { { IoBusPci, { "PCI\\VEN_10EC&DEV_8168", sizeof("PCI\\VEN_10EC&DEV_8168") - 1 } }, @@ -18,53 +15,45 @@ static const IO_DRIVER_ID_TABLE gRtl816xIdTable = { sizeof(gRtl816xIds) / sizeof(gRtl816xIds[0]), }; -// Implements the rtl Memory Barrier operation. static __forceinline void RtlMemoryBarrier(void) { _ReadWriteBarrier(); _mm_mfence(); _ReadWriteBarrier(); } -// Implements the rtl Read8 operation. static uint8_t RtlRead8(RTL816X_DEVICE* r, uint32_t reg) { if (r->UseMmio) return *(volatile uint8_t*)(r->Mmio + reg); return __inbyte((unsigned short)(r->IoBase + reg)); } -// Implements the rtl Read16 operation. static uint16_t RtlRead16(RTL816X_DEVICE* r, uint32_t reg) { if (r->UseMmio) return *(volatile uint16_t*)(r->Mmio + reg); return __inword((unsigned short)(r->IoBase + reg)); } -// Implements the rtl Read32 operation. static uint32_t RtlRead32(RTL816X_DEVICE* r, uint32_t reg) { if (r->UseMmio) return *(volatile uint32_t*)(r->Mmio + reg); return __indword((unsigned short)(r->IoBase + reg)); } -// Implements the rtl Write8 operation. static void RtlWrite8(RTL816X_DEVICE* r, uint32_t reg, uint8_t value) { if (r->UseMmio) *(volatile uint8_t*)(r->Mmio + reg) = value; else __outbyte((unsigned short)(r->IoBase + reg), value); } -// Implements the rtl Write16 operation. static void RtlWrite16(RTL816X_DEVICE* r, uint32_t reg, uint16_t value) { if (r->UseMmio) *(volatile uint16_t*)(r->Mmio + reg) = value; else __outword((unsigned short)(r->IoBase + reg), value); } -// Implements the rtl Write32 operation. static void RtlWrite32(RTL816X_DEVICE* r, uint32_t reg, uint32_t value) { if (r->UseMmio) *(volatile uint32_t*)(r->Mmio + reg) = value; else __outdword((unsigned short)(r->IoBase + reg), value); } -// Implements the rtl Reset operation. static KSTATUS RtlReset(RTL816X_DEVICE* r) { RtlWrite8(r, RTL_REG_CHIP_CMD, RTL_CMD_RESET); for (uint32_t i = 0; i < 1000; i++) { @@ -75,7 +64,6 @@ static KSTATUS RtlReset(RTL816X_DEVICE* r) { return NTLSTATUS_TIMEOUT; } -// Implements the rtl Read Mac operation. static void RtlReadMac(RTL816X_DEVICE* r) { for (uint32_t i = 0; i < 6; i++) r->NetDevice.HardwareAddress[i] = RtlRead8(r, RTL_REG_MAC0 + i); @@ -179,7 +167,6 @@ fail: return status; } -// Implements the rtl Init Descriptors operation. static void RtlInitDescriptors(RTL816X_DEVICE* r) { for (uint32_t i = 0; i < RTL_RX_COUNT; i++) { uint64_t address = r->RxBuffersDeviceAddress + (uint64_t)i * RTL_BUF_SIZE; @@ -202,7 +189,6 @@ static void RtlInitDescriptors(RTL816X_DEVICE* r) { RtlMemoryBarrier(); } -// Implements the rtl Program Hardware operation. static void RtlProgramHardware(RTL816X_DEVICE* r) { RtlWrite8(r, RTL_REG_CFG9346, 0xC0); @@ -232,7 +218,6 @@ static void RtlProgramHardware(RTL816X_DEVICE* r) { RtlWrite16(r, RTL_REG_INTR_MASK, RTL_INTR_ENABLES); } -// Implements the rtl Handle Rx operation. static void RtlHandleRx(RTL816X_DEVICE* r) { for (uint32_t budget = 0; budget < RTL_RX_COUNT; budget++) { RTL_DESC* d = &r->RxRing[r->RxIndex]; @@ -270,7 +255,6 @@ static void RtlHandleRx(RTL816X_DEVICE* r) { } } -// Implements the rtl Dpc Routine operation. static void RtlDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* systemArgument2) { (void)dpc; (void)systemArgument1; @@ -295,74 +279,19 @@ static void RtlDpcRoutine(KDPC* dpc, void* context, void* systemArgument1, void* DbgPrint("RTL816X: interrupt status error bits=0x%04x\n", status); } -// Implements the rtl Register Device operation. -static KSTATUS RtlRegisterDevice(RTL816X_DEVICE* r) { - if (!r) return NTLSTATUS_INVALID_PARAMETER; +static void RtlIsr(void* context) { + RTL816X_DEVICE* r = (RTL816X_DEVICE*)context; + if (!r || !r->Started || r->Removed || r->SurpriseRemoved) return; + uint16_t status = RtlRead16(r, RTL_REG_INTR_STAT); + status &= RTL_INTR_ENABLES; + if (!status || status == 0xFFFFu) + return; - uintptr_t flags = KeAcquireSpinlock(&gRtl816xRegistryLock); - for (uint32_t i = 0; i < gRtl816xDeviceCount; i++) { - if (gRtl816xDevices[i] == r) { - KeReleaseSpinlock(&gRtl816xRegistryLock, flags); - return NTLSTATUS_SUCCESS; - } - } - - if (gRtl816xDeviceCount >= RTL816X_MAX_DEVICES) { - KeReleaseSpinlock(&gRtl816xRegistryLock, flags); - return NTLSTATUS_NO_MEMORY; - } - - gRtl816xDevices[gRtl816xDeviceCount++] = r; - KeReleaseSpinlock(&gRtl816xRegistryLock, flags); - return NTLSTATUS_SUCCESS; + RtlWrite16(r, RTL_REG_INTR_STAT, status); + r->PendingIsr |= status; + KeInsertQueueDpc(&r->Dpc, (void*)0, (void*)0); } -// Implements the rtl Unregister Device operation. -static void RtlUnregisterDevice(RTL816X_DEVICE* r) { - if (!r) return; - - uintptr_t flags = KeAcquireSpinlock(&gRtl816xRegistryLock); - for (uint32_t i = 0; i < gRtl816xDeviceCount; i++) { - if (gRtl816xDevices[i] == r) { - gRtl816xDevices[i] = gRtl816xDevices[gRtl816xDeviceCount - 1u]; - gRtl816xDevices[gRtl816xDeviceCount - 1u] = (RTL816X_DEVICE*)0; - gRtl816xDeviceCount--; - break; - } - } - KeReleaseSpinlock(&gRtl816xRegistryLock, flags); -} - -// Implements the rtl Isr operation. -static void RtlIsr(void) { - RTL816X_DEVICE* snapshot[RTL816X_MAX_DEVICES]; - uint32_t count = 0; - - uintptr_t flags = KeAcquireSpinlock(&gRtl816xRegistryLock); - count = gRtl816xDeviceCount; - if (count > RTL816X_MAX_DEVICES) - count = RTL816X_MAX_DEVICES; - for (uint32_t i = 0; i < count; i++) - snapshot[i] = gRtl816xDevices[i]; - KeReleaseSpinlock(&gRtl816xRegistryLock, flags); - - for (uint32_t i = 0; i < count; i++) { - RTL816X_DEVICE* r = snapshot[i]; - if (!r || !r->Started || r->Removed || r->SurpriseRemoved) - continue; - - uint16_t status = RtlRead16(r, RTL_REG_INTR_STAT); - status &= RTL_INTR_ENABLES; - if (!status || status == 0xFFFFu) - continue; - - RtlWrite16(r, RTL_REG_INTR_STAT, status); - r->PendingIsr |= status; - KeInsertQueueDpc(&r->Dpc, (void*)0, (void*)0); - } -} - -// Implements the rtl Send Frame operation. static KSTATUS RtlSendFrame(NET_DEVICE* device, const void* frame, size_t length) { if (!device || !frame) return NTLSTATUS_INVALID_PARAMETER; @@ -402,7 +331,6 @@ static KSTATUS RtlSendFrame(NET_DEVICE* device, const void* frame, size_t length return NTLSTATUS_SUCCESS; } -// Implements the rtl Select Register Bar operation. static KSTATUS RtlSelectRegisterBar(RTL816X_DEVICE* r) { if (!r || !r->Pdo) return NTLSTATUS_INVALID_PARAMETER; @@ -468,42 +396,15 @@ static KSTATUS RtlSelectRegisterBar(RTL816X_DEVICE* r) { return NTLSTATUS_NOT_FOUND; } -// Configures a dedicated MSI vector and falls back to a routed INTx line. +// Connects a PCI message interrupt or a routed INTx source. static KSTATUS RtlConfigureInterrupt(RTL816X_DEVICE* r) { - if (!r || !r->Pdo) - return NTLSTATUS_INVALID_PARAMETER; - - r->Irq = 0xFFu; - r->UsingMsi = false; - - KSTATUS msiStatus = PciEnableMsiAuto(r->Pdo, &r->Irq); - if (KSUCCESS(msiStatus)) { - r->UsingMsi = true; - DbgPrint("RTL816X: using MSI IRQ slot %u\n", r->Irq); - return NTLSTATUS_SUCCESS; - } - - DbgPrint("RTL816X: MSI setup failed status=0x%x; attempting explicit INTx fallback\n", - msiStatus); - - KSTATUS intxStatus = PciGetInterrupt(r->Pdo, &r->Irq); - if (!KSUCCESS(intxStatus)) - return intxStatus; - if (r->Irq == 0xFFu || r->Irq >= 24u) - return NTLSTATUS_NOT_SUPPORTED; - - intxStatus = PciEnableDevice(r->Pdo, - PCI_ENABLE_BUSMASTER | - PCI_ENABLE_INTX | - (r->UseMmio ? PCI_ENABLE_MEMORY : PCI_ENABLE_IO)); - if (!KSUCCESS(intxStatus)) - return intxStatus; - - DbgPrint("RTL816X: using legacy INTx IRQ %u\n", r->Irq); - return NTLSTATUS_SUCCESS; + r->InterruptRequest.Routine = RtlIsr; + r->InterruptRequest.Context = r; + r->InterruptRequest.Affinity = 0; + r->InterruptRequest.Interrupt = (KE_INTERRUPT*)0; + return PciConnectInterrupts(r->Pdo, &r->InterruptRequest, 1u, &r->UsingMsi); } -// Implements the rtl Start Device operation. static KSTATUS RtlStartDevice(RTL816X_DEVICE* r) { if (!r || r->Magic != RTL816X_DEVICE_MAGIC || !r->Pdo || !r->Fdo) return NTLSTATUS_INVALID_PARAMETER; @@ -547,18 +448,7 @@ static KSTATUS RtlStartDevice(RTL816X_DEVICE* r) { return st; } - st = RtlConfigureInterrupt(r); - if (!KSUCCESS(st)) { - DbgPrint("RTL816X: no usable MSI or INTx interrupt status=0x%x\n", st); - return st; - } - RtlReadMac(r); - DbgPrint("RTL816X: MAC %02x:%02x:%02x:%02x:%02x:%02x irq=%u mode=%s\n", - r->NetDevice.HardwareAddress[0], r->NetDevice.HardwareAddress[1], - r->NetDevice.HardwareAddress[2], r->NetDevice.HardwareAddress[3], - r->NetDevice.HardwareAddress[4], r->NetDevice.HardwareAddress[5], - r->Irq, r->UsingMsi ? "MSI" : "INTx"); st = RtlAllocateDma(r); if (!KSUCCESS(st)) @@ -571,13 +461,21 @@ static KSTATUS RtlStartDevice(RTL816X_DEVICE* r) { r->NetDevice.DriverContext = r; r->NetDevice.SendFrame = RtlSendFrame; - st = RtlRegisterDevice(r); + st = RtlConfigureInterrupt(r); if (!KSUCCESS(st)) { + DbgPrint("RTL816X: no usable MSI or INTx interrupt status=0x%x\n", st); RtlReleaseDma(r); return st; } - KeIrqRegister(r->Irq, RtlIsr); + KE_INTERRUPT_INFO route; + if (KSUCCESS(KeInterruptQuery(r->InterruptRequest.Interrupt, &route))) + DbgPrint("RTL816X: MAC %02x:%02x:%02x:%02x:%02x:%02x cpu=%u vector=0x%02x mode=%s\n", + r->NetDevice.HardwareAddress[0], r->NetDevice.HardwareAddress[1], + r->NetDevice.HardwareAddress[2], r->NetDevice.HardwareAddress[3], + r->NetDevice.HardwareAddress[4], r->NetDevice.HardwareAddress[5], + route.CpuIndex, route.Vector, r->UsingMsi ? "MSI/MSI-X" : "INTx"); + r->Started = true; RtlProgramHardware(r); r->Fdo->PnpState = DevicePnpStarted; @@ -585,13 +483,14 @@ static KSTATUS RtlStartDevice(RTL816X_DEVICE* r) { st = NetRegisterDevice(&r->NetDevice); if (!KSUCCESS(st)) { RtlStopDma(r); - RtlUnregisterDevice(r); + if (r->InterruptRequest.Interrupt) + PciDisconnectInterrupts(r->Pdo, &r->InterruptRequest, 1u); RtlReleaseDma(r); return st; } - DbgPrint("RTL816X: initialized; RX/TX enabled on %s IRQ %u\n", - r->UsingMsi ? "MSI" : "INTx", r->Irq); + DbgPrint("RTL816X: initialized; RX/TX enabled via %s\n", + r->UsingMsi ? "MSI/MSI-X" : "INTx"); return NTLSTATUS_SUCCESS; } @@ -626,7 +525,8 @@ KSTATUS Rtl816xDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { r->Removed = true; device->PnpState = DevicePnpDeleted; RtlStopDma(r); - RtlUnregisterDevice(r); + if (r->InterruptRequest.Interrupt) + PciDisconnectInterrupts(r->Pdo, &r->InterruptRequest, 1u); RtlReleaseDma(r); IoDetachDevice(device); IoDeleteDevice(device); @@ -637,7 +537,6 @@ KSTATUS Rtl816xDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { } } -// Implements the add Device operation. KSTATUS Rtl816xAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return NTLSTATUS_INVALID_PARAMETER; @@ -653,7 +552,7 @@ KSTATUS Rtl816xAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObj r->Magic = RTL816X_DEVICE_MAGIC; r->Fdo = fdo; r->Pdo = physicalDeviceObject; - r->Irq = 0xFFu; + r->PciInfo.InterruptLine = 0xFFu; r->TxLock = (SPINLOCK)SPINLOCK_INIT; r->LowerDevice = IoAttachDeviceToDeviceStack(fdo, physicalDeviceObject); @@ -671,8 +570,6 @@ static KSTATUS DriverInitialize(NTL_MODULE* module) { DbgPrint("RTL816X: driver loading...\n"); - gRtl816xDeviceCount = 0; - memset(&gRtl816xDriver, 0, sizeof(gRtl816xDriver)); IoInitializeDriverObject(&gRtl816xDriver, SYS_SV_LITERAL("rtl816x")); gRtl816xDriver.IdTable = &gRtl816xIdTable; diff --git a/code/drivers/net/rtl816x/rtl816x.h b/code/drivers/net/rtl816x/rtl816x.h index 945d149..165095e 100644 --- a/code/drivers/net/rtl816x/rtl816x.h +++ b/code/drivers/net/rtl816x/rtl816x.h @@ -116,7 +116,7 @@ typedef struct RTL816X_DEVICE { PCI_DEVICE_INFO PciInfo; PCI_BAR RegisterBar; uint64_t RegisterBytes; - uint8_t Irq; + PCI_INTERRUPT_REQUEST InterruptRequest; bool UsingMsi; bool Started; diff --git a/code/drivers/net/rtl816x/sources b/code/drivers/net/rtl816x/sources new file mode 100644 index 0000000..afc3dd1 --- /dev/null +++ b/code/drivers/net/rtl816x/sources @@ -0,0 +1,7 @@ +TARGETNAME=rtl816x +TARGETPATH=obj +TARGETTYPE=DRIVER +FLAVOR=DRIVER +TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\pci.lib" +EXTRA_LFLAGS=/NOENTRY +SOURCES=@/code/drivers/net/rtl816x/rtl816x.c diff --git a/code/drivers/platform/acpi/acpi.c b/code/drivers/platform/acpi/acpi.c new file mode 100644 index 0000000..7e0ecfe --- /dev/null +++ b/code/drivers/platform/acpi/acpi.c @@ -0,0 +1,157 @@ +// Optional firmware-event driver using the resident ACPICA namespace. +#include +#include +#include +#include +#include +#include "third_party/acpica/include/acpi.h" +#include "third_party/acpica/include/aclocal.h" +#include "third_party/acpica/include/acobject.h" +#include "third_party/acpica/include/acglobal.h" +#include "acpi_local.h" +#include +#include + +// Firmware callbacks remain resident until the final ACPI S5 transition. +static KSTATUS AcpiNtlPreparePower(void* context, uint32_t action) { + (void)context; + if (action != SYS_POWER_ACTION_SHUTDOWN) return NTLSTATUS_NOT_SUPPORTED; + ACPI_STATUS status = AcpiEnterSleepStatePrep(ACPI_STATE_S5); + if (ACPI_FAILURE(status)) { + DbgPrint("acpi: S5 preparation failed status=0x%x\n", (unsigned)status); + return NTLSTATUS_NOT_SUPPORTED; + } + return NTLSTATUS_SUCCESS; +} + +static KSTATUS AcpiNtlEnterPower(void* context, uint32_t action) { + (void)context; + if (action != SYS_POWER_ACTION_SHUTDOWN) return NTLSTATUS_NOT_SUPPORTED; + // ACPICA requires interrupts disabled for the final sleep-control writes. + uintptr_t flags = KeDisableInterrupts(); + ACPI_STATUS status = AcpiEnterSleepState(ACPI_STATE_S5); + KeRestoreInterrupts(flags); + DbgPrint("acpi: S5 transition returned status=0x%x\n", (unsigned)status); + return NTLSTATUS_NOT_SUPPORTED; +} + +static volatile int32_t gFixedButtonPending; +static uint32_t gFixedButtonEvents; +static uint32_t gMethodButtonEvents; +static uint32_t gMethodButtons; + +static void AcpiNtlDeliverButton(void* context) { + (void)context; + KSTATUS result = KeNotifyPowerButton(); + if (!KSUCCESS(result)) DbgPrint("acpi: power button delivery failed status=0x%x\n", result); +} + +static void AcpiNtlDeliverFixedButton(void* context) { + AcpiNtlDeliverButton(context); + NtlAtomicExchange32(&gFixedButtonPending, 0); +} + +bool AcpiNtlFixedButtonHasDeferred(void) { + return NtlAtomicLoad32(&gFixedButtonPending) == 2; +} + +void AcpiNtlFixedButtonDrainDeferred(void) { + if (NtlAtomicCompareExchange32(&gFixedButtonPending, 1, 2) == 2) + AcpiNtlDeliverFixedButton(NULL); +} + +// Fixed-event handlers run in the SCI and delegate delivery to passive work. +static UINT32 AcpiNtlFixedButton(void* context) { + (void)context; + gFixedButtonEvents++; + if (NtlAtomicCompareExchange32(&gFixedButtonPending, 1, 0) == 0 && + ACPI_FAILURE(AcpiOsExecute(OSL_NOTIFY_HANDLER, AcpiNtlDeliverFixedButton, NULL))) { + NtlAtomicExchange32(&gFixedButtonPending, 2); + AcpiNtlWakeExecutor(); + } + return ACPI_INTERRUPT_HANDLED; +} + +// 0x80 is the normal S0 press event; 0x02 is a wake notification. +static void AcpiNtlButtonNotify(ACPI_HANDLE handle, UINT32 event, void* context) { + (void)handle; (void)context; + if (event == 0x80u) { + gMethodButtonEvents++; + AcpiNtlDeliverButton(NULL); + } +} + +static ACPI_STATUS AcpiNtlFindButton(ACPI_HANDLE handle, UINT32 depth, + void* context, void** returnValue) { + (void)depth; (void)context; (void)returnValue; + ACPI_STATUS result = AcpiInstallNotifyHandler(handle, ACPI_DEVICE_NOTIFY, + AcpiNtlButtonNotify, NULL); + if (ACPI_SUCCESS(result)) gMethodButtons++; + return AE_OK; +} + +static KSTATUS AcpiDriverInitialize(NTL_MODULE* module) { + (void)module; + uint64_t root = 0; + KSTATUS status = KeFirmwareQueryAcpiRsdp(&root); + if (!KSUCCESS(status)) { + DbgPrint("acpi: RSDP query failed status=0x%x\n", status); + return status; + } + ACPI_STATUS result = AcpiInitializeSubsystem(); + if (ACPI_FAILURE(result)) goto fail; + result = AcpiInitializeTables(NULL, 32, TRUE); + if (ACPI_FAILURE(result)) goto fail; + result = AcpiLoadTables(); + if (ACPI_FAILURE(result)) goto fail; + AcpiNtlRestrictRuntimeMappings(); + status = AcpiNtlPrepareMmioRegisters(); + if (!KSUCCESS(status)) { + DbgPrint("acpi: MMIO register mappings unavailable st=0x%x\n", status); + result = AE_NO_MEMORY; + goto fail; + } + status = AcpiNtlStartExecutor(); + if (!KSUCCESS(status)) { + DbgPrint("acpi: event worker unavailable st=0x%x\n", status); + result = AE_NO_MEMORY; + goto fail; + } + result = AcpiEnableSubsystem(0); + if (ACPI_FAILURE(result)) goto fail; + ACPI_STATUS ecStatus = AcpiNtlEcInitialize(); + if (ACPI_FAILURE(ecStatus)) + DbgPrint("acpi: EC enumeration failed status=0x%x\n", (unsigned)ecStatus); + result = AcpiInitializeObjects(0); + if (ACPI_FAILURE(result)) goto fail; + AcpiNtlEcActivate(); + + ACPI_STATUS fixedStatus = AE_SUPPORT; + if (!(AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON)) { + fixedStatus = AcpiInstallFixedEventHandler( + ACPI_EVENT_POWER_BUTTON, AcpiNtlFixedButton, NULL); + } + ACPI_STATUS methodStatus = AcpiGetDevices("PNP0C0C", AcpiNtlFindButton, NULL, NULL); + DbgPrint("acpi: ready rsdp=0x%016llX fixed=0x%x method=0x%x buttons=%u ec=%u\n", + (unsigned long long)root, (unsigned)fixedStatus, + (unsigned)methodStatus, gMethodButtons, AcpiNtlEcCount()); + const NTL_FIRMWARE_POWER_PROVIDER provider = { + .Size = sizeof(NTL_FIRMWARE_POWER_PROVIDER), + .Context = NULL, + .Prepare = AcpiNtlPreparePower, + .Enter = AcpiNtlEnterPower, + }; + status = KeRegisterFirmwarePowerProvider(&provider); + if (!KSUCCESS(status)) DbgPrint("acpi: power provider registration failed status=0x%x\n", status); + return NTLSTATUS_SUCCESS; +fail: + DbgPrint("acpi: namespace initialization failed status=0x%x\n", + (unsigned)result); + AcpiNtlEcTerminate(); + (void)AcpiTerminate(); + AcpiNtlStopExecutor(); + AcpiNtlReleaseMmioRegisters(); + return NTLSTATUS_NOT_SUPPORTED; +} + +NTL_DECLARE_MODULE(AcpiDriverInitialize); diff --git a/code/drivers/platform/acpi/acpi_ec.c b/code/drivers/platform/acpi/acpi_ec.c new file mode 100644 index 0000000..3f19651 --- /dev/null +++ b/code/drivers/platform/acpi/acpi_ec.c @@ -0,0 +1,249 @@ +// ACPI embedded-controller SystemIO transport and passive GPE query handling. +#include "third_party/acpica/include/acpi.h" +#include +#include +#include +#include +#include +#include +#include "acpi_local.h" + +#define ACPI_NTL_EC_COUNT 4u +#define EC_STATUS_OBF 0x01u +#define EC_STATUS_IBF 0x02u +#define EC_STATUS_SCI 0x20u +#define EC_CMD_READ 0x80u +#define EC_CMD_WRITE 0x81u +#define EC_CMD_QUERY 0x84u +#define EC_POLL_COUNT 10000u + +typedef struct ACPI_NTL_EC { + ACPI_HANDLE Handle; + SEMAPHORE* Mutex; + uint16_t DataPort; + uint16_t CommandPort; + ACPI_HANDLE GpeDevice; + uint32_t Gpe; + volatile long Pending; + uint8_t PortCount; + bool HaveGpe; + bool HandlerInstalled; + bool GpeInstalled; +} ACPI_NTL_EC; + +static ACPI_NTL_EC gEc[ACPI_NTL_EC_COUNT]; +static uint32_t gEcCount; + +static bool AcpiNtlEcWait(ACPI_NTL_EC* ec, uint8_t mask, bool asserted) { + for (uint32_t i = 0; i < EC_POLL_COUNT; i++) { + bool set = (__inbyte(ec->CommandPort) & mask) != 0; + if (set == asserted) return true; + KeStallExecution(10); + } + return false; +} + +static bool AcpiNtlEcReadByte(ACPI_NTL_EC* ec, uint8_t offset, uint8_t* result) { + if (!AcpiNtlEcWait(ec, EC_STATUS_IBF, false)) return false; + __outbyte(ec->CommandPort, EC_CMD_READ); + if (!AcpiNtlEcWait(ec, EC_STATUS_IBF, false)) return false; + __outbyte(ec->DataPort, offset); + if (!AcpiNtlEcWait(ec, EC_STATUS_OBF, true)) return false; + *result = __inbyte(ec->DataPort); + return true; +} + +static bool AcpiNtlEcWriteByte(ACPI_NTL_EC* ec, uint8_t offset, uint8_t value) { + if (!AcpiNtlEcWait(ec, EC_STATUS_IBF, false)) return false; + __outbyte(ec->CommandPort, EC_CMD_WRITE); + if (!AcpiNtlEcWait(ec, EC_STATUS_IBF, false)) return false; + __outbyte(ec->DataPort, offset); + if (!AcpiNtlEcWait(ec, EC_STATUS_IBF, false)) return false; + __outbyte(ec->DataPort, value); + return AcpiNtlEcWait(ec, EC_STATUS_IBF, false); +} + +static ACPI_STATUS AcpiNtlEcRegion(UINT32 function, ACPI_PHYSICAL_ADDRESS address, + UINT32 width, UINT64* value, void* context, + void* regionContext) { + (void)regionContext; + ACPI_NTL_EC* ec = (ACPI_NTL_EC*)context; + if (!ec || !value || !width || width > 64u || (width % 8u) || + address > 0xFFu || width / 8u > 256u - address || + (function != ACPI_READ && function != ACPI_WRITE)) return AE_BAD_PARAMETER; + if (KeWaitSemaphore(ec->Mutex, KE_WAIT_INFINITE) != NTLSTATUS_SUCCESS) return AE_ERROR; + UINT64 data = function == ACPI_WRITE ? *value : 0; + bool success = true; + for (uint32_t i = 0; i < width / 8u; i++) { + if (function == ACPI_READ) { + uint8_t byte = 0; + success = AcpiNtlEcReadByte(ec, (uint8_t)(address + i), &byte); + data |= (UINT64)byte << (8u * i); + } else { + success = AcpiNtlEcWriteByte(ec, (uint8_t)(address + i), (uint8_t)(data >> (8u * i))); + } + if (!success) break; + } + KeSignalSemaphore(ec->Mutex); + if (!success) return AE_TIME; + if (function == ACPI_READ) *value = data; + return AE_OK; +} + +// A disabled GPE remains masked until its passive query callback completes. +static void AcpiNtlEcQuery(void* context) { + ACPI_NTL_EC* ec = (ACPI_NTL_EC*)context; + for (unsigned count = 0; count < 32u; count++) { + if (KeWaitSemaphore(ec->Mutex, KE_WAIT_INFINITE) != NTLSTATUS_SUCCESS) break; + uint8_t status = __inbyte(ec->CommandPort); + bool ready = (status & EC_STATUS_SCI) != 0; + bool success = false; + uint8_t query = 0; + if (ready && AcpiNtlEcWait(ec, EC_STATUS_IBF, false)) { + __outbyte(ec->CommandPort, EC_CMD_QUERY); + if (AcpiNtlEcWait(ec, EC_STATUS_OBF, true)) { + query = __inbyte(ec->DataPort); + success = true; + } + } + KeSignalSemaphore(ec->Mutex); + if (!ready || !success) break; + if (query) { + static const char digits[] = "0123456789ABCDEF"; + char method[5] = { '_', 'Q', digits[query >> 4], digits[query & 15], 0 }; + (void)AcpiEvaluateObject(ec->Handle, method, NULL, NULL); + } + } + _InterlockedExchange(&ec->Pending, 0); + if (ec->GpeInstalled) (void)AcpiFinishGpe(ec->GpeDevice, ec->Gpe); +} + +static UINT32 AcpiNtlEcGpe(ACPI_HANDLE device, UINT32 number, void* context) { + (void)device; (void)number; + ACPI_NTL_EC* ec = (ACPI_NTL_EC*)context; + if (_InterlockedCompareExchange(&ec->Pending, 1, 0) == 0) { + if (ACPI_FAILURE(AcpiOsExecute(OSL_GPE_HANDLER, AcpiNtlEcQuery, ec))) { + _InterlockedExchange(&ec->Pending, 2); + AcpiNtlWakeExecutor(); + } + } + // ACPICA leaves this GPE masked until the query worker calls FinishGpe. + return ACPI_INTERRUPT_HANDLED; +} + +// The ACPI executor drains deferred EC queries after queued work completes. +bool AcpiNtlEcDrainDeferred(void) { + bool drained = false; + for (uint32_t i = 0; i < gEcCount; ++i) { + ACPI_NTL_EC* ec = &gEc[i]; + if (_InterlockedCompareExchange(&ec->Pending, 1, 2) != 2) continue; + AcpiNtlEcQuery(ec); + drained = true; + } + return drained; +} + +bool AcpiNtlEcHasDeferred(void) { + for (uint32_t i = 0; i < gEcCount; ++i) + if (_InterlockedCompareExchange(&gEc[i].Pending, 2, 2) == 2) return true; + return false; +} + +static ACPI_STATUS AcpiNtlEcResource(ACPI_RESOURCE* resource, void* context) { + ACPI_NTL_EC* ec = (ACPI_NTL_EC*)context; + uint16_t port; + if (resource->Type == ACPI_RESOURCE_TYPE_IO) port = resource->Data.Io.Minimum; + else if (resource->Type == ACPI_RESOURCE_TYPE_FIXED_IO) port = resource->Data.FixedIo.Address; + else return AE_OK; + if (ec->PortCount == 0) ec->DataPort = port; + else if (ec->PortCount == 1) ec->CommandPort = port; + ec->PortCount++; + return AE_OK; +} + +static ACPI_STATUS AcpiNtlEcDiscover(ACPI_HANDLE handle, UINT32 depth, void* context, + void** returnValue) { + (void)depth; (void)context; (void)returnValue; + if (gEcCount >= ACPI_NTL_EC_COUNT) return AE_OK; + ACPI_NTL_EC* ec = &gEc[gEcCount]; + ec->Handle = handle; + ACPI_STATUS status = AcpiWalkResources(handle, "_CRS", AcpiNtlEcResource, ec); + if (ACPI_FAILURE(status) || ec->PortCount != 2 || !ec->DataPort || !ec->CommandPort || + ec->DataPort == ec->CommandPort) { + DbgPrint("acpi: EC has unsupported _CRS resources st=0x%x\n", (unsigned)status); + ec->PortCount = 0; + return AE_OK; + } + if (KeSemaphoreCreate(1, 1, &ec->Mutex) != NTLSTATUS_SUCCESS) return AE_NO_MEMORY; + status = AcpiInstallAddressSpaceHandler(handle, ACPI_ADR_SPACE_EC, AcpiNtlEcRegion, + NULL, ec); + if (ACPI_FAILURE(status)) { + ObDereferenceObject((OBJECT*)ec->Mutex); + ec->Mutex = NULL; + return AE_OK; + } + ec->HandlerInstalled = true; + ACPI_BUFFER result = { ACPI_ALLOCATE_BUFFER, NULL }; + status = AcpiEvaluateObject(handle, "_GPE", NULL, &result); + if (ACPI_SUCCESS(status) && result.Pointer) { + ACPI_OBJECT* gpe = (ACPI_OBJECT*)result.Pointer; + if (gpe->Type == ACPI_TYPE_INTEGER && gpe->Integer.Value <= UINT32_MAX) { + ec->Gpe = (uint32_t)gpe->Integer.Value; + ec->GpeDevice = NULL; + ec->HaveGpe = true; + } else if (gpe->Type == ACPI_TYPE_PACKAGE && gpe->Package.Count == 2 && + gpe->Package.Elements && + gpe->Package.Elements[0].Type == ACPI_TYPE_LOCAL_REFERENCE && + gpe->Package.Elements[1].Type == ACPI_TYPE_INTEGER && + gpe->Package.Elements[1].Integer.Value <= UINT32_MAX) { + ec->GpeDevice = gpe->Package.Elements[0].Reference.Handle; + ec->Gpe = (uint32_t)gpe->Package.Elements[1].Integer.Value; + ec->HaveGpe = ec->GpeDevice != NULL; + } + AcpiOsFree(result.Pointer); + } + gEcCount++; + return AE_OK; +} + +ACPI_STATUS AcpiNtlEcInitialize(void) { + // Region handlers are established before ACPICA executes _REG methods. + return AcpiGetDevices("PNP0C09", AcpiNtlEcDiscover, NULL, NULL); +} + +void AcpiNtlEcActivate(void) { + for (uint32_t i = 0; i < gEcCount; i++) { + ACPI_NTL_EC* ec = &gEc[i]; + if (!ec->HaveGpe) continue; + ACPI_STATUS status = AcpiInstallGpeHandler(ec->GpeDevice, ec->Gpe, + ACPI_GPE_LEVEL_TRIGGERED, AcpiNtlEcGpe, ec); + if (ACPI_SUCCESS(status)) { + ec->GpeInstalled = true; + status = AcpiEnableGpe(ec->GpeDevice, ec->Gpe); + } + if (ACPI_FAILURE(status)) + DbgPrint("acpi: EC GPE enable failed gpe=%u status=0x%x\n", ec->Gpe, (unsigned)status); + } +} + +void AcpiNtlEcTerminate(void) { + for (uint32_t i = 0; i < gEcCount; i++) { + ACPI_NTL_EC* ec = &gEc[i]; + if (ec->GpeInstalled) { + (void)AcpiDisableGpe(ec->GpeDevice, ec->Gpe); + (void)AcpiRemoveGpeHandler(ec->GpeDevice, ec->Gpe, AcpiNtlEcGpe); + ec->GpeInstalled = false; + } + } + AcpiOsWaitEventsComplete(); + for (uint32_t i = 0; i < gEcCount; i++) { + ACPI_NTL_EC* ec = &gEc[i]; + if (ec->HandlerInstalled) + (void)AcpiRemoveAddressSpaceHandler(ec->Handle, ACPI_ADR_SPACE_EC, AcpiNtlEcRegion); + if (ec->Mutex) ObDereferenceObject((OBJECT*)ec->Mutex); + ec->Mutex = NULL; + } + gEcCount = 0; +} + +uint32_t AcpiNtlEcCount(void) { return gEcCount; } diff --git a/code/drivers/platform/acpi/acpi_local.h b/code/drivers/platform/acpi/acpi_local.h new file mode 100644 index 0000000..f9f1029 --- /dev/null +++ b/code/drivers/platform/acpi/acpi_local.h @@ -0,0 +1,26 @@ +// Local runtime lifecycle for the resident firmware interpreter. +#pragma once + +#include +#include +#include "third_party/acpica/include/acpi.h" + +KSTATUS AcpiNtlStartExecutor(void); +void AcpiNtlStopExecutor(void); +void AcpiNtlRestrictRuntimeMappings(void); + +// Preallocated FADT register mappings remain valid throughout SCI dispatch. +KSTATUS AcpiNtlPrepareMmioRegisters(void); +void AcpiNtlReleaseMmioRegisters(void); + +ACPI_STATUS AcpiNtlEcInitialize(void); +void AcpiNtlEcActivate(void); +void AcpiNtlEcTerminate(void); +uint32_t AcpiNtlEcCount(void); + +// The executor handles EC queries that arrive while its callback queue is full. +bool AcpiNtlEcHasDeferred(void); +bool AcpiNtlEcDrainDeferred(void); +void AcpiNtlWakeExecutor(void); +bool AcpiNtlFixedButtonHasDeferred(void); +void AcpiNtlFixedButtonDrainDeferred(void); diff --git a/code/drivers/platform/acpi/acpi_osl.c b/code/drivers/platform/acpi/acpi_osl.c new file mode 100644 index 0000000..c868683 --- /dev/null +++ b/code/drivers/platform/acpi/acpi_osl.c @@ -0,0 +1,473 @@ +// nt-lite OS Services Layer for the ACPICA table and namespace loader. +#include "third_party/acpica/include/acpi.h" +#include "third_party/acpica/include/aclocal.h" +#include "third_party/acpica/include/acobject.h" +#include "third_party/acpica/include/acglobal.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "acpi_local.h" +#include + +// The freestanding formatted-output routine comes from ACPICA utprint.c. +int vsnprintf(char* destination, size_t size, const char* format, va_list args); + +static bool gRuntimeMemoryRestricted; +ACPI_STATUS AcpiOsInitialize(void) { gRuntimeMemoryRestricted = false; return AE_OK; } +ACPI_STATUS AcpiOsTerminate(void) { gRuntimeMemoryRestricted = false; return AE_OK; } +ACPI_PHYSICAL_ADDRESS AcpiOsGetRootPointer(void) { + uint64_t root = 0; + return KSUCCESS(KeFirmwareQueryAcpiRsdp(&root)) ? root : 0; +} +ACPI_STATUS AcpiOsPredefinedOverride(const ACPI_PREDEFINED_NAMES* entry, ACPI_STRING* value) { + (void)entry; + if (!value) return AE_BAD_PARAMETER; + *value = NULL; + return AE_OK; +} +ACPI_STATUS AcpiOsTableOverride(ACPI_TABLE_HEADER* original, ACPI_TABLE_HEADER** replacement) { + (void)original; + if (!replacement) return AE_BAD_PARAMETER; + *replacement = NULL; + return AE_OK; +} +ACPI_STATUS AcpiOsPhysicalTableOverride(ACPI_TABLE_HEADER* original, ACPI_PHYSICAL_ADDRESS* address, UINT32* length) { + (void)original; + if (!address || !length) return AE_BAD_PARAMETER; + *address = 0; + *length = 0; + return AE_OK; +} +ACPI_STATUS AcpiOsCreateLock(ACPI_SPINLOCK* handle) { + if (!handle) return AE_BAD_PARAMETER; + SPINLOCK* lock = (SPINLOCK*)MmAllocatePool(sizeof(*lock)); + if (!lock) return AE_NO_MEMORY; + memset(lock, 0, sizeof(*lock)); + *handle = (ACPI_SPINLOCK)lock; + return AE_OK; +} +void AcpiOsDeleteLock(ACPI_SPINLOCK handle) { MmFreePool(handle); } +ACPI_CPU_FLAGS AcpiOsAcquireLock(ACPI_SPINLOCK handle) { + return (ACPI_CPU_FLAGS)KeAcquireSpinlock((SPINLOCK*)handle); +} +void AcpiOsReleaseLock(ACPI_SPINLOCK handle, ACPI_CPU_FLAGS flags) { + KeReleaseSpinlock((SPINLOCK*)handle, (uintptr_t)flags); +} +ACPI_STATUS AcpiOsCreateSemaphore(UINT32 max, UINT32 initial, ACPI_SEMAPHORE* handle) { + if (!handle || !max || initial > max || initial > INT32_MAX) return AE_BAD_PARAMETER; + int32_t nativeMax = max > INT32_MAX ? INT32_MAX : (int32_t)max; + SEMAPHORE* sem = NULL; + KSTATUS status = KeSemaphoreCreate((int32_t)initial, nativeMax, &sem); + if (!KSUCCESS(status)) return AE_NO_MEMORY; + *handle = (ACPI_SEMAPHORE)sem; + return AE_OK; +} +ACPI_STATUS AcpiOsDeleteSemaphore(ACPI_SEMAPHORE handle) { + if (!handle) return AE_BAD_PARAMETER; + ObDereferenceObject((OBJECT*)handle); + return AE_OK; +} +ACPI_STATUS AcpiOsWaitSemaphore(ACPI_SEMAPHORE handle, UINT32 units, UINT16 timeout) { + if (!handle || !units) return AE_BAD_PARAMETER; + uint64_t ms = timeout == ACPI_WAIT_FOREVER ? KE_WAIT_INFINITE : timeout; + for (UINT32 i = 0; i < units; i++) { + KSTATUS result = KeWaitSemaphore((SEMAPHORE*)handle, ms); + if (result != NTLSTATUS_SUCCESS) { + while (i--) KeSignalSemaphore((SEMAPHORE*)handle); + return result == NTLSTATUS_TIMEOUT ? AE_TIME : AE_ERROR; + } + } + return AE_OK; +} +ACPI_STATUS AcpiOsSignalSemaphore(ACPI_SEMAPHORE handle, UINT32 units) { + if (!handle || !units) return AE_BAD_PARAMETER; + for (UINT32 i = 0; i < units; i++) KeSignalSemaphore((SEMAPHORE*)handle); + return AE_OK; +} +void* AcpiOsAllocate(ACPI_SIZE size) { return MmAllocatePool((size_t)size); } +void AcpiOsFree(void* memory) { MmFreePool(memory); } + +// Firmware tables remain on the firmware RAM mapping. Device OperationRegions +// receive distinct UC mappings with explicit lifetimes. +void AcpiNtlRestrictRuntimeMappings(void) { gRuntimeMemoryRestricted = true; } + +static bool AcpiNtlIsFirmwareTableSpan(uint64_t physical, uint64_t length) { + const ACPI_TABLE_LIST* list = &AcpiGbl_RootTableList; + for (UINT32 i = 0; i < list->CurrentTableCount; i++) { + const ACPI_TABLE_DESC* table = &list->Tables[i]; + if (table->Length && physical >= table->Address && + physical - table->Address < table->Length && + length <= table->Length - (physical - table->Address)) return true; + } + return false; +} + +void* AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS physical, ACPI_SIZE length) { + if (!length || physical > UINT64_MAX - (uint64_t)length) return NULL; + if (!gRuntimeMemoryRestricted || + AcpiNtlIsFirmwareTableSpan((uint64_t)physical, (uint64_t)length) || + (AcpiGbl_FADT.XFacs && physical >= AcpiGbl_FADT.XFacs && + physical - AcpiGbl_FADT.XFacs < sizeof(ACPI_TABLE_FACS) && + length <= sizeof(ACPI_TABLE_FACS) - (physical - AcpiGbl_FADT.XFacs))) + return MmDdkPhysToVirt((uint64_t)physical); + void* mapped = NULL; + return KSUCCESS(MmDdkMapIoMemory((uint64_t)physical, (size_t)length, &mapped)) ? mapped : NULL; +} +void AcpiOsUnmapMemory(void* address, ACPI_SIZE length) { + if (!address || !length) return; + (void)MmDdkUnmapIoMemory(address, (size_t)length); +} +ACPI_STATUS AcpiOsGetPhysicalAddress(void* address, ACPI_PHYSICAL_ADDRESS* physical) { + (void)address; (void)physical; + return AE_SUPPORT; +} + +// ACPICA's SCI handler owns the PM1 and GPE acknowledgement protocol. +// The interrupt manager owns routing, affinity, vector and handler lifetime. +static KE_INTERRUPT* gSciInterrupt; +static ACPI_OSD_HANDLER gSciRoutine; +static void* gSciContext; +static UINT32 gSciGsi; + +static void AcpiNtlSciInterrupt(void* unused) { + (void)unused; + if (gSciRoutine) (void)gSciRoutine(gSciContext); +} + +ACPI_STATUS AcpiOsInstallInterruptHandler(UINT32 irq, ACPI_OSD_HANDLER routine, void* context) { + if (!routine || gSciInterrupt) return AE_BAD_PARAMETER; + gSciRoutine = routine; + gSciContext = context; + gSciGsi = irq; + KSTATUS status = irq < 16u + ? KeInterruptConnectIsa((uint8_t)irq, 0x0Fu, 0, AcpiNtlSciInterrupt, NULL, &gSciInterrupt) + : KeInterruptConnectGsi(irq, 0x0Fu, 0, AcpiNtlSciInterrupt, NULL, &gSciInterrupt); + if (!KSUCCESS(status)) { + gSciRoutine = NULL; + gSciContext = NULL; + return AE_ERROR; + } + return AE_OK; +} + +ACPI_STATUS AcpiOsRemoveInterruptHandler(UINT32 irq, ACPI_OSD_HANDLER routine) { + if (!gSciInterrupt || irq != gSciGsi || routine != gSciRoutine) return AE_BAD_PARAMETER; + KE_INTERRUPT* interrupt = gSciInterrupt; + KeInterruptDisconnect(interrupt); + gSciInterrupt = NULL; + gSciRoutine = NULL; + gSciContext = NULL; + return AE_OK; +} + +// AML callbacks run on a passive worker, including GPE and notify handlers. +// Queue nodes are preallocated because AcpiOsExecute may run in the SCI ISR. +#define ACPI_EXECUTOR_CAPACITY 256u +typedef struct ACPI_WORK_ITEM { + ACPI_OSD_EXEC_CALLBACK Callback; + void* Context; +} ACPI_WORK_ITEM; +static ACPI_WORK_ITEM gWorkItems[ACPI_EXECUTOR_CAPACITY]; +static uint32_t gWorkHead, gWorkTail, gWorkCount; +static bool gWorkerRunning, gWorkActive; +static SPINLOCK gWorkLock = SPINLOCK_INIT; +static SEMAPHORE* gWorkSemaphore; +static EVENT* gWorkerFinished; +static THREAD* gWorkerThread; +static KDPC gWakeDpc; + +void AcpiNtlWakeExecutor(void) { + (void)KeInsertQueueDpc(&gWakeDpc, NULL, NULL); +} + +static void AcpiNtlWakeDpc(KDPC* dpc, void* context, void* arg1, void* arg2) { + (void)dpc; (void)context; (void)arg1; (void)arg2; + if (gWorkSemaphore) KeSignalSemaphore(gWorkSemaphore); +} + +static void AcpiNtlWorker(uintptr_t context) { + (void)context; + for (;;) { + (void)KeWaitSemaphore(gWorkSemaphore, KE_WAIT_INFINITE); + for (;;) { + ACPI_WORK_ITEM item = { 0 }; + uintptr_t flags = KeAcquireSpinlock(&gWorkLock); + if (gWorkCount) { + item = gWorkItems[gWorkHead]; + gWorkHead = (gWorkHead + 1u) % ACPI_EXECUTOR_CAPACITY; + gWorkCount--; + } + bool deferred = AcpiNtlEcHasDeferred() || AcpiNtlFixedButtonHasDeferred(); + gWorkActive = item.Callback != NULL || deferred; + bool running = gWorkerRunning; + KeReleaseSpinlock(&gWorkLock, flags); + if (!item.Callback && !deferred) { + if (!running) goto done; + break; + } + // Service deferred firmware events on the existing worker. + if (deferred) { + (void)AcpiNtlEcDrainDeferred(); + AcpiNtlFixedButtonDrainDeferred(); + } + if (item.Callback) item.Callback(item.Context); + flags = KeAcquireSpinlock(&gWorkLock); + gWorkActive = false; + KeReleaseSpinlock(&gWorkLock, flags); + } + } +done: + KeSignalEvent(gWorkerFinished); +} + +KSTATUS AcpiNtlStartExecutor(void) { + KSTATUS status = KeSemaphoreCreate(0, INT32_MAX, &gWorkSemaphore); + if (!KSUCCESS(status)) return status; + status = KeEventCreate(EventManualReset, false, &gWorkerFinished); + if (!KSUCCESS(status)) { + ObDereferenceObject((OBJECT*)gWorkSemaphore); + gWorkSemaphore = NULL; + return status; + } + KeInitializeDpc(&gWakeDpc, AcpiNtlWakeDpc, NULL); + gWorkHead = gWorkTail = gWorkCount = 0; + gWorkActive = false; + gWorkerRunning = true; + const KE_THREAD_CREATE_PARAMETERS params = KE_THREAD_CREATE_NAMED_NORMAL(PriorityHigh, "acpi.events"); + status = KeCreateKernelThread((uintptr_t)AcpiNtlWorker, 0, ¶ms, &gWorkerThread); + if (!KSUCCESS(status)) { + gWorkerRunning = false; + ObDereferenceObject((OBJECT*)gWorkerFinished); + ObDereferenceObject((OBJECT*)gWorkSemaphore); + gWorkerFinished = NULL; + gWorkSemaphore = NULL; + } + return status; +} + +void AcpiNtlStopExecutor(void) { + if (!gWorkerThread) return; + AcpiOsWaitEventsComplete(); + uintptr_t flags = KeAcquireSpinlock(&gWorkLock); + gWorkerRunning = false; + KeReleaseSpinlock(&gWorkLock, flags); + KeSignalSemaphore(gWorkSemaphore); + (void)KeWaitForEvent(gWorkerFinished, false); + ObDereferenceObject((OBJECT*)gWorkerThread); + ObDereferenceObject((OBJECT*)gWorkerFinished); + ObDereferenceObject((OBJECT*)gWorkSemaphore); + gWorkerThread = NULL; + gWorkerFinished = NULL; + gWorkSemaphore = NULL; +} + +ACPI_THREAD_ID AcpiOsGetThreadId(void) { return (ACPI_THREAD_ID)KeCurrentThreadIdentity(); } +ACPI_STATUS AcpiOsExecute(ACPI_EXECUTE_TYPE type, ACPI_OSD_EXEC_CALLBACK routine, void* context) { + (void)type; + if (!routine) return AE_BAD_PARAMETER; + uintptr_t flags = KeAcquireSpinlock(&gWorkLock); + if (!gWorkerRunning || gWorkCount == ACPI_EXECUTOR_CAPACITY) { + KeReleaseSpinlock(&gWorkLock, flags); + return AE_NO_MEMORY; + } + gWorkItems[gWorkTail].Callback = routine; + gWorkItems[gWorkTail].Context = context; + gWorkTail = (gWorkTail + 1u) % ACPI_EXECUTOR_CAPACITY; + gWorkCount++; + KeReleaseSpinlock(&gWorkLock, flags); + (void)KeInsertQueueDpc(&gWakeDpc, NULL, NULL); + return AE_OK; +} +void AcpiOsWaitEventsComplete(void) { + if (!gWorkerThread) return; + for (;;) { + uintptr_t flags = KeAcquireSpinlock(&gWorkLock); + bool busy = gWorkCount != 0 || gWorkActive || AcpiNtlEcHasDeferred() || + AcpiNtlFixedButtonHasDeferred(); + KeReleaseSpinlock(&gWorkLock, flags); + if (!busy) break; + (void)KeDelayThread(1); + } +} +void AcpiOsSleep(UINT64 milliseconds) { + if (milliseconds) (void)KeDelayThread(milliseconds); +} +void AcpiOsStall(UINT32 microseconds) { KeStallExecution(microseconds); } +ACPI_STATUS AcpiOsReadPort(ACPI_IO_ADDRESS address, UINT32* value, UINT32 width) { + if (!value || address > UINT16_MAX || (width != 8u && width != 16u && width != 32u)) + return AE_BAD_PARAMETER; + if (width == 8u) *value = __inbyte((unsigned short)address); + else if (width == 16u) *value = __inword((unsigned short)address); + else *value = __indword((unsigned short)address); + return AE_OK; +} +ACPI_STATUS AcpiOsWritePort(ACPI_IO_ADDRESS address, UINT32 value, UINT32 width) { + if (address > UINT16_MAX || (width != 8u && width != 16u && width != 32u)) + return AE_BAD_PARAMETER; + if (width == 8u) __outbyte((unsigned short)address, (unsigned char)value); + else if (width == 16u) __outword((unsigned short)address, (unsigned short)value); + else __outdword((unsigned short)address, value); + return AE_OK; +} +// FADT GAS registers can be touched in the SCI. Establish these UC mappings +// before enabling the SCI, so interrupt handlers never allocate page tables. +#define ACPI_GAS_WINDOW_COUNT 12u +typedef struct ACPI_GAS_WINDOW { + uint64_t Physical; + uint32_t Length; + volatile uint8_t* Virtual; +} ACPI_GAS_WINDOW; +static ACPI_GAS_WINDOW gGasWindows[ACPI_GAS_WINDOW_COUNT]; +static uint32_t gGasWindowCount; + +static KSTATUS AcpiNtlMapGas(const ACPI_GENERIC_ADDRESS* gas, uint32_t bytes) { + if (!gas || !gas->Address || gas->SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) + return NTLSTATUS_SUCCESS; + if (!bytes) bytes = (gas->BitWidth + 7u) / 8u; + if (!bytes || gGasWindowCount == ACPI_GAS_WINDOW_COUNT) return NTLSTATUS_INVALID_PARAMETER; + void* virtualAddress = NULL; + KSTATUS status = MmDdkMapIoMemory(gas->Address, bytes, &virtualAddress); + if (!KSUCCESS(status)) return status; + ACPI_GAS_WINDOW* window = &gGasWindows[gGasWindowCount++]; + window->Physical = gas->Address; + window->Length = bytes; + window->Virtual = (volatile uint8_t*)virtualAddress; + return NTLSTATUS_SUCCESS; +} + +KSTATUS AcpiNtlPrepareMmioRegisters(void) { + // ACPICA's normalized FADT contains the active PM and GPE register blocks. + const struct { const ACPI_GENERIC_ADDRESS* Gas; uint32_t Length; } regions[] = { + { &AcpiGbl_FADT.XPm1aEventBlock, AcpiGbl_FADT.Pm1EventLength }, + { &AcpiGbl_FADT.XPm1bEventBlock, AcpiGbl_FADT.Pm1EventLength }, + { &AcpiGbl_FADT.XPm1aControlBlock, AcpiGbl_FADT.Pm1ControlLength }, + { &AcpiGbl_FADT.XPm1bControlBlock, AcpiGbl_FADT.Pm1ControlLength }, + { &AcpiGbl_FADT.XPm2ControlBlock, AcpiGbl_FADT.Pm2ControlLength }, + { &AcpiGbl_FADT.XPmTimerBlock, AcpiGbl_FADT.PmTimerLength }, + { &AcpiGbl_FADT.XGpe0Block, AcpiGbl_FADT.Gpe0BlockLength }, + { &AcpiGbl_FADT.XGpe1Block, AcpiGbl_FADT.Gpe1BlockLength }, + { &AcpiGbl_FADT.SleepControl, 1 }, + { &AcpiGbl_FADT.SleepStatus, 1 }, + { &AcpiGbl_FADT.ResetRegister, 1 }, + }; + for (uint32_t i = 0; i < sizeof(regions) / sizeof(regions[0]); i++) { + KSTATUS status = AcpiNtlMapGas(regions[i].Gas, regions[i].Length); + if (!KSUCCESS(status)) return status; + } + return NTLSTATUS_SUCCESS; +} + +void AcpiNtlReleaseMmioRegisters(void) { + while (gGasWindowCount) { + ACPI_GAS_WINDOW* window = &gGasWindows[--gGasWindowCount]; + (void)MmDdkUnmapIoMemory((void*)window->Virtual, window->Length); + window->Virtual = NULL; + } +} + +static volatile uint8_t* AcpiNtlFindGas(uint64_t address, uint32_t bytes) { + if (!bytes || address > UINT64_MAX - bytes) return NULL; + for (uint32_t i = 0; i < gGasWindowCount; i++) { + const ACPI_GAS_WINDOW* region = &gGasWindows[i]; + if (address >= region->Physical && address - region->Physical < region->Length && + bytes <= region->Length - (address - region->Physical)) + return region->Virtual + (size_t)(address - region->Physical); + } + return NULL; +} + +ACPI_STATUS AcpiOsReadMemory(ACPI_PHYSICAL_ADDRESS address, UINT64* value, UINT32 width) { + if (!value || (width != 8u && width != 16u && width != 32u && width != 64u)) + return AE_BAD_PARAMETER; + volatile uint8_t* mapped = AcpiNtlFindGas(address, width / 8u); + if (!mapped || (address & ((width / 8u) - 1u))) return AE_SUPPORT; + switch (width) { + case 8: *value = *mapped; break; + case 16: *value = *(volatile uint16_t*)mapped; break; + case 32: *value = *(volatile uint32_t*)mapped; break; + default: *value = *(volatile uint64_t*)mapped; break; + } + return AE_OK; +} +ACPI_STATUS AcpiOsWriteMemory(ACPI_PHYSICAL_ADDRESS address, UINT64 value, UINT32 width) { + if (width != 8u && width != 16u && width != 32u && width != 64u) + return AE_BAD_PARAMETER; + volatile uint8_t* mapped = AcpiNtlFindGas(address, width / 8u); + if (!mapped || (address & ((width / 8u) - 1u))) return AE_SUPPORT; + switch (width) { + case 8: *mapped = (uint8_t)value; break; + case 16: *(volatile uint16_t*)mapped = (uint16_t)value; break; + case 32: *(volatile uint32_t*)mapped = (uint32_t)value; break; + default: *(volatile uint64_t*)mapped = value; break; + } + return AE_OK; +} +ACPI_STATUS AcpiOsReadPciConfiguration(ACPI_PCI_ID* id, UINT32 reg, UINT64* value, UINT32 width) { + if (!id || !value || reg > 0xFFu || (width != 8u && width != 16u && width != 32u)) + return AE_BAD_PARAMETER; + UINT32 raw = KePciReadConfig32(id->Segment, (uint8_t)id->Bus, + (uint8_t)id->Device, (uint8_t)id->Function, (uint16_t)(reg & ~3u)); + if (width == 32u && (reg & 3u)) return AE_BAD_PARAMETER; + if (width == 16u && (reg & 1u)) return AE_BAD_PARAMETER; + if ((reg & 3u) + (width / 8u) > 4u) return AE_BAD_PARAMETER; + *value = ((UINT64)raw >> ((reg & 3u) * 8u)) & ((1ull << width) - 1u); + return AE_OK; +} +ACPI_STATUS AcpiOsWritePciConfiguration(ACPI_PCI_ID* id, UINT32 reg, UINT64 value, UINT32 width) { + if (!id || reg > 0xFCu || width != 32u || (reg & 3u)) return AE_SUPPORT; + KePciWriteConfig32(id->Segment, (uint8_t)id->Bus, (uint8_t)id->Device, + (uint8_t)id->Function, (uint16_t)reg, (uint32_t)value); + return AE_OK; +} +BOOLEAN AcpiOsReadable(void* address, ACPI_SIZE length) { return address && length ? TRUE : FALSE; } +BOOLEAN AcpiOsWritable(void* address, ACPI_SIZE length) { return address && length ? TRUE : FALSE; } +// KeQueryTicks returns microseconds; ACPICA expects 100-nanosecond units. +UINT64 AcpiOsGetTimer(void) { return KeQueryTicks() * 10u; } +ACPI_STATUS AcpiOsSignal(UINT32 function, void* info) { + (void)function; (void)info; + return AE_SUPPORT; +} +ACPI_STATUS AcpiOsEnterSleep(UINT8 state, UINT32 a, UINT32 b) { + (void)a; (void)b; + // ACPICA owns PM1 or extended sleep-control register programming. + return state == ACPI_STATE_S5 ? AE_OK : AE_SUPPORT; +} +void ACPI_INTERNAL_VAR_XFACE AcpiOsPrintf(const char* format, ...) { + va_list arguments; + va_start(arguments, format); + AcpiOsVprintf(format, arguments); + va_end(arguments); +} +static SPINLOCK gOutputLock = SPINLOCK_INIT; +static char gOutputLine[768]; +static uint32_t gOutputLength; +void AcpiOsVprintf(const char* format, va_list args) { + char message[512]; + vsnprintf(message, sizeof(message), format, args); + for (uint32_t i = 0; i < sizeof(message) && message[i]; i++) { + char complete[sizeof(gOutputLine)]; + bool flush = false; + uintptr_t flags = KeAcquireSpinlock(&gOutputLock); + if (message[i] == '\n' || gOutputLength + 1 >= sizeof(gOutputLine)) { + memcpy(complete, gOutputLine, gOutputLength); + complete[gOutputLength] = 0; + gOutputLength = 0; + flush = true; + } + if (message[i] != '\n') gOutputLine[gOutputLength++] = message[i]; + KeReleaseSpinlock(&gOutputLock, flags); + if (flush && complete[0] && + ((KeGetDebugFlags() & KE_DEBUG_ACPI_INFO) || strncmp(complete, "ACPI: ", 6) != 0)) + DbgPrint("acpi: %s\n", complete); + } +} +void AcpiOsRedirectOutput(void* destination) { (void)destination; } diff --git a/code/drivers/platform/acpi/acpica_sources.txt b/code/drivers/platform/acpi/acpica_sources.txt new file mode 100644 index 0000000..c2c37f1 --- /dev/null +++ b/code/drivers/platform/acpi/acpica_sources.txt @@ -0,0 +1,164 @@ +# ACPICA 20260930 interpreter source units, relative to code/. +drivers/platform/acpi/third_party/acpica/components/dispatcher/dsargs.c +drivers/platform/acpi/third_party/acpica/components/dispatcher/dscontrol.c +drivers/platform/acpi/third_party/acpica/components/dispatcher/dsdebug.c +drivers/platform/acpi/third_party/acpica/components/dispatcher/dsfield.c +drivers/platform/acpi/third_party/acpica/components/dispatcher/dsinit.c +drivers/platform/acpi/third_party/acpica/components/dispatcher/dsmethod.c +drivers/platform/acpi/third_party/acpica/components/dispatcher/dsmthdat.c +drivers/platform/acpi/third_party/acpica/components/dispatcher/dsobject.c +drivers/platform/acpi/third_party/acpica/components/dispatcher/dsopcode.c +drivers/platform/acpi/third_party/acpica/components/dispatcher/dspkginit.c +drivers/platform/acpi/third_party/acpica/components/dispatcher/dsutils.c +drivers/platform/acpi/third_party/acpica/components/dispatcher/dswexec.c +drivers/platform/acpi/third_party/acpica/components/dispatcher/dswload.c +drivers/platform/acpi/third_party/acpica/components/dispatcher/dswload2.c +drivers/platform/acpi/third_party/acpica/components/dispatcher/dswscope.c +drivers/platform/acpi/third_party/acpica/components/dispatcher/dswstate.c +drivers/platform/acpi/third_party/acpica/components/events/evevent.c +drivers/platform/acpi/third_party/acpica/components/events/evglock.c +drivers/platform/acpi/third_party/acpica/components/events/evgpe.c +drivers/platform/acpi/third_party/acpica/components/events/evgpeblk.c +drivers/platform/acpi/third_party/acpica/components/events/evgpeinit.c +drivers/platform/acpi/third_party/acpica/components/events/evgpeutil.c +drivers/platform/acpi/third_party/acpica/components/events/evhandler.c +drivers/platform/acpi/third_party/acpica/components/events/evmisc.c +drivers/platform/acpi/third_party/acpica/components/events/evregion.c +drivers/platform/acpi/third_party/acpica/components/events/evrgnini.c +drivers/platform/acpi/third_party/acpica/components/events/evsci.c +drivers/platform/acpi/third_party/acpica/components/events/evxface.c +drivers/platform/acpi/third_party/acpica/components/events/evxfevnt.c +drivers/platform/acpi/third_party/acpica/components/events/evxfgpe.c +drivers/platform/acpi/third_party/acpica/components/events/evxfregn.c +drivers/platform/acpi/third_party/acpica/components/executer/exconcat.c +drivers/platform/acpi/third_party/acpica/components/executer/exconfig.c +drivers/platform/acpi/third_party/acpica/components/executer/exconvrt.c +drivers/platform/acpi/third_party/acpica/components/executer/excreate.c +drivers/platform/acpi/third_party/acpica/components/executer/exdebug.c +drivers/platform/acpi/third_party/acpica/components/executer/exdump.c +drivers/platform/acpi/third_party/acpica/components/executer/exfield.c +drivers/platform/acpi/third_party/acpica/components/executer/exfldio.c +drivers/platform/acpi/third_party/acpica/components/executer/exmisc.c +drivers/platform/acpi/third_party/acpica/components/executer/exmutex.c +drivers/platform/acpi/third_party/acpica/components/executer/exnames.c +drivers/platform/acpi/third_party/acpica/components/executer/exoparg1.c +drivers/platform/acpi/third_party/acpica/components/executer/exoparg2.c +drivers/platform/acpi/third_party/acpica/components/executer/exoparg3.c +drivers/platform/acpi/third_party/acpica/components/executer/exoparg6.c +drivers/platform/acpi/third_party/acpica/components/executer/exprep.c +drivers/platform/acpi/third_party/acpica/components/executer/exregion.c +drivers/platform/acpi/third_party/acpica/components/executer/exresnte.c +drivers/platform/acpi/third_party/acpica/components/executer/exresolv.c +drivers/platform/acpi/third_party/acpica/components/executer/exresop.c +drivers/platform/acpi/third_party/acpica/components/executer/exserial.c +drivers/platform/acpi/third_party/acpica/components/executer/exstore.c +drivers/platform/acpi/third_party/acpica/components/executer/exstoren.c +drivers/platform/acpi/third_party/acpica/components/executer/exstorob.c +drivers/platform/acpi/third_party/acpica/components/executer/exsystem.c +drivers/platform/acpi/third_party/acpica/components/executer/extrace.c +drivers/platform/acpi/third_party/acpica/components/executer/exutils.c +drivers/platform/acpi/third_party/acpica/components/hardware/hwacpi.c +drivers/platform/acpi/third_party/acpica/components/hardware/hwesleep.c +drivers/platform/acpi/third_party/acpica/components/hardware/hwgpe.c +drivers/platform/acpi/third_party/acpica/components/hardware/hwpci.c +drivers/platform/acpi/third_party/acpica/components/hardware/hwregs.c +drivers/platform/acpi/third_party/acpica/components/hardware/hwsleep.c +drivers/platform/acpi/third_party/acpica/components/hardware/hwtimer.c +drivers/platform/acpi/third_party/acpica/components/hardware/hwvalid.c +drivers/platform/acpi/third_party/acpica/components/hardware/hwxface.c +drivers/platform/acpi/third_party/acpica/components/hardware/hwxfsleep.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsaccess.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsalloc.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsarguments.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsconvert.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsdump.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsdumpdv.c +drivers/platform/acpi/third_party/acpica/components/namespace/nseval.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsinit.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsload.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsnames.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsobject.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsparse.c +drivers/platform/acpi/third_party/acpica/components/namespace/nspredef.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsprepkg.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsrepair.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsrepair2.c +drivers/platform/acpi/third_party/acpica/components/namespace/nssearch.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsutils.c +drivers/platform/acpi/third_party/acpica/components/namespace/nswalk.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsxfeval.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsxfname.c +drivers/platform/acpi/third_party/acpica/components/namespace/nsxfobj.c +drivers/platform/acpi/third_party/acpica/components/parser/psargs.c +drivers/platform/acpi/third_party/acpica/components/parser/psloop.c +drivers/platform/acpi/third_party/acpica/components/parser/psobject.c +drivers/platform/acpi/third_party/acpica/components/parser/psopcode.c +drivers/platform/acpi/third_party/acpica/components/parser/psopinfo.c +drivers/platform/acpi/third_party/acpica/components/parser/psparse.c +drivers/platform/acpi/third_party/acpica/components/parser/psscope.c +drivers/platform/acpi/third_party/acpica/components/parser/pstree.c +drivers/platform/acpi/third_party/acpica/components/parser/psutils.c +drivers/platform/acpi/third_party/acpica/components/parser/pswalk.c +drivers/platform/acpi/third_party/acpica/components/parser/psxface.c +drivers/platform/acpi/third_party/acpica/components/resources/rsaddr.c +drivers/platform/acpi/third_party/acpica/components/resources/rscalc.c +drivers/platform/acpi/third_party/acpica/components/resources/rscreate.c +drivers/platform/acpi/third_party/acpica/components/resources/rsdumpinfo.c +drivers/platform/acpi/third_party/acpica/components/resources/rsinfo.c +drivers/platform/acpi/third_party/acpica/components/resources/rsio.c +drivers/platform/acpi/third_party/acpica/components/resources/rsirq.c +drivers/platform/acpi/third_party/acpica/components/resources/rslist.c +drivers/platform/acpi/third_party/acpica/components/resources/rsmemory.c +drivers/platform/acpi/third_party/acpica/components/resources/rsmisc.c +drivers/platform/acpi/third_party/acpica/components/resources/rsserial.c +drivers/platform/acpi/third_party/acpica/components/resources/rsutils.c +drivers/platform/acpi/third_party/acpica/components/resources/rsxface.c +drivers/platform/acpi/third_party/acpica/components/tables/tbdata.c +drivers/platform/acpi/third_party/acpica/components/tables/tbfadt.c +drivers/platform/acpi/third_party/acpica/components/tables/tbfind.c +drivers/platform/acpi/third_party/acpica/components/tables/tbinstal.c +drivers/platform/acpi/third_party/acpica/components/tables/tbprint.c +drivers/platform/acpi/third_party/acpica/components/tables/tbutils.c +drivers/platform/acpi/third_party/acpica/components/tables/tbxface.c +drivers/platform/acpi/third_party/acpica/components/tables/tbxfload.c +drivers/platform/acpi/third_party/acpica/components/tables/tbxfroot.c +drivers/platform/acpi/third_party/acpica/components/utilities/utaddress.c +drivers/platform/acpi/third_party/acpica/components/utilities/utalloc.c +drivers/platform/acpi/third_party/acpica/components/utilities/utascii.c +drivers/platform/acpi/third_party/acpica/components/utilities/utbuffer.c +drivers/platform/acpi/third_party/acpica/components/utilities/utcache.c +drivers/platform/acpi/third_party/acpica/components/utilities/utcksum.c +drivers/platform/acpi/third_party/acpica/components/utilities/utclib.c +drivers/platform/acpi/third_party/acpica/components/utilities/utcopy.c +drivers/platform/acpi/third_party/acpica/components/utilities/utdebug.c +drivers/platform/acpi/third_party/acpica/components/utilities/utdecode.c +drivers/platform/acpi/third_party/acpica/components/utilities/utdelete.c +drivers/platform/acpi/third_party/acpica/components/utilities/uterror.c +drivers/platform/acpi/third_party/acpica/components/utilities/uteval.c +drivers/platform/acpi/third_party/acpica/components/utilities/utexcep.c +drivers/platform/acpi/third_party/acpica/components/utilities/utglobal.c +drivers/platform/acpi/third_party/acpica/components/utilities/uthex.c +drivers/platform/acpi/third_party/acpica/components/utilities/utids.c +drivers/platform/acpi/third_party/acpica/components/utilities/utinit.c +drivers/platform/acpi/third_party/acpica/components/utilities/utlock.c +drivers/platform/acpi/third_party/acpica/components/utilities/utmath.c +drivers/platform/acpi/third_party/acpica/components/utilities/utmisc.c +drivers/platform/acpi/third_party/acpica/components/utilities/utmutex.c +drivers/platform/acpi/third_party/acpica/components/utilities/utnonansi.c +drivers/platform/acpi/third_party/acpica/components/utilities/utobject.c +drivers/platform/acpi/third_party/acpica/components/utilities/utosi.c +drivers/platform/acpi/third_party/acpica/components/utilities/utownerid.c +drivers/platform/acpi/third_party/acpica/components/utilities/utpredef.c +drivers/platform/acpi/third_party/acpica/components/utilities/utprint.c +drivers/platform/acpi/third_party/acpica/components/utilities/utresdecode.c +drivers/platform/acpi/third_party/acpica/components/utilities/utresrc.c +drivers/platform/acpi/third_party/acpica/components/utilities/utstate.c +drivers/platform/acpi/third_party/acpica/components/utilities/utstring.c +drivers/platform/acpi/third_party/acpica/components/utilities/utstrsuppt.c +drivers/platform/acpi/third_party/acpica/components/utilities/utstrtoul64.c +drivers/platform/acpi/third_party/acpica/components/utilities/uttrack.c +drivers/platform/acpi/third_party/acpica/components/utilities/utuuid.c +drivers/platform/acpi/third_party/acpica/components/utilities/utxface.c +drivers/platform/acpi/third_party/acpica/components/utilities/utxferror.c +drivers/platform/acpi/third_party/acpica/components/utilities/utxfinit.c +drivers/platform/acpi/third_party/acpica/components/utilities/utxfmutex.c diff --git a/code/drivers/platform/acpi/makefile b/code/drivers/platform/acpi/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/drivers/platform/acpi/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/drivers/platform/acpi/sources b/code/drivers/platform/acpi/sources new file mode 100644 index 0000000..bac4ce4 --- /dev/null +++ b/code/drivers/platform/acpi/sources @@ -0,0 +1,35 @@ +TARGETNAME=acpi +TARGETPATH=obj +TARGETTYPE=DRIVER +FLAVOR=ACPICA +TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" +EXTRA_LFLAGS=/NOENTRY +INCLUDES=$(BASEDIR)\code\drivers\platform\acpi\third_party\acpica\include +SOURCES=@/code/drivers/platform/acpi/acpi.c @/code/drivers/platform/acpi/acpi_osl.c @/code/drivers/platform/acpi/acpi_ec.c @/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsargs.c @/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dscontrol.c @/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsdebug.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsfield.c @/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsinit.c @/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsmethod.c @/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsmthdat.c @/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsobject.c @/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsopcode.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dspkginit.c @/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsutils.c @/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswexec.c @/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswload.c @/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswload2.c @/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswscope.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswstate.c @/code/drivers/platform/acpi/third_party/acpica/components/events/evevent.c @/code/drivers/platform/acpi/third_party/acpica/components/events/evglock.c @/code/drivers/platform/acpi/third_party/acpica/components/events/evgpe.c @/code/drivers/platform/acpi/third_party/acpica/components/events/evgpeblk.c @/code/drivers/platform/acpi/third_party/acpica/components/events/evgpeinit.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/events/evgpeutil.c @/code/drivers/platform/acpi/third_party/acpica/components/events/evhandler.c @/code/drivers/platform/acpi/third_party/acpica/components/events/evmisc.c @/code/drivers/platform/acpi/third_party/acpica/components/events/evregion.c @/code/drivers/platform/acpi/third_party/acpica/components/events/evrgnini.c @/code/drivers/platform/acpi/third_party/acpica/components/events/evsci.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/events/evxface.c @/code/drivers/platform/acpi/third_party/acpica/components/events/evxfevnt.c @/code/drivers/platform/acpi/third_party/acpica/components/events/evxfgpe.c @/code/drivers/platform/acpi/third_party/acpica/components/events/evxfregn.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exconcat.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exconfig.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/executer/exconvrt.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/excreate.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exdebug.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exdump.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exfield.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exfldio.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/executer/exmisc.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exmutex.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exnames.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg1.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg2.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg3.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg6.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exprep.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exregion.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exresnte.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exresolv.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exresop.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/executer/exserial.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exstore.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exstoren.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exstorob.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/exsystem.c @/code/drivers/platform/acpi/third_party/acpica/components/executer/extrace.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/executer/exutils.c @/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwacpi.c @/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwesleep.c @/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwgpe.c @/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwpci.c @/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwregs.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwsleep.c @/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwtimer.c @/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwvalid.c @/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwxface.c @/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwxfsleep.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsaccess.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsalloc.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsarguments.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsconvert.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsdump.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsdumpdv.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nseval.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsinit.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsload.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsnames.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsobject.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsparse.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nspredef.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsprepkg.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsrepair.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsrepair2.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nssearch.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsutils.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nswalk.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsxfeval.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsxfname.c @/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsxfobj.c @/code/drivers/platform/acpi/third_party/acpica/components/parser/psargs.c @/code/drivers/platform/acpi/third_party/acpica/components/parser/psloop.c @/code/drivers/platform/acpi/third_party/acpica/components/parser/psobject.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/parser/psopcode.c @/code/drivers/platform/acpi/third_party/acpica/components/parser/psopinfo.c @/code/drivers/platform/acpi/third_party/acpica/components/parser/psparse.c @/code/drivers/platform/acpi/third_party/acpica/components/parser/psscope.c @/code/drivers/platform/acpi/third_party/acpica/components/parser/pstree.c @/code/drivers/platform/acpi/third_party/acpica/components/parser/psutils.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/parser/pswalk.c @/code/drivers/platform/acpi/third_party/acpica/components/parser/psxface.c @/code/drivers/platform/acpi/third_party/acpica/components/resources/rsaddr.c @/code/drivers/platform/acpi/third_party/acpica/components/resources/rscalc.c @/code/drivers/platform/acpi/third_party/acpica/components/resources/rscreate.c @/code/drivers/platform/acpi/third_party/acpica/components/resources/rsdumpinfo.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/resources/rsinfo.c @/code/drivers/platform/acpi/third_party/acpica/components/resources/rsio.c @/code/drivers/platform/acpi/third_party/acpica/components/resources/rsirq.c @/code/drivers/platform/acpi/third_party/acpica/components/resources/rslist.c @/code/drivers/platform/acpi/third_party/acpica/components/resources/rsmemory.c @/code/drivers/platform/acpi/third_party/acpica/components/resources/rsmisc.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/resources/rsserial.c @/code/drivers/platform/acpi/third_party/acpica/components/resources/rsutils.c @/code/drivers/platform/acpi/third_party/acpica/components/resources/rsxface.c @/code/drivers/platform/acpi/third_party/acpica/components/tables/tbdata.c @/code/drivers/platform/acpi/third_party/acpica/components/tables/tbfadt.c @/code/drivers/platform/acpi/third_party/acpica/components/tables/tbfind.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/tables/tbinstal.c @/code/drivers/platform/acpi/third_party/acpica/components/tables/tbprint.c @/code/drivers/platform/acpi/third_party/acpica/components/tables/tbutils.c @/code/drivers/platform/acpi/third_party/acpica/components/tables/tbxface.c @/code/drivers/platform/acpi/third_party/acpica/components/tables/tbxfload.c @/code/drivers/platform/acpi/third_party/acpica/components/tables/tbxfroot.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utaddress.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utalloc.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utascii.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utbuffer.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utcache.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utcksum.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utclib.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utcopy.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utdebug.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utdecode.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utdelete.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/uterror.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/utilities/uteval.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utexcep.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utglobal.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/uthex.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utids.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utinit.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utlock.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utmath.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utmisc.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utmutex.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utnonansi.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utobject.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utosi.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utownerid.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utpredef.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utprint.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utresdecode.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utresrc.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utstate.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utstring.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utstrsuppt.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utstrtoul64.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/uttrack.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utuuid.c \ + @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utxface.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utxferror.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utxfinit.c @/code/drivers/platform/acpi/third_party/acpica/components/utilities/utxfmutex.c diff --git a/code/drivers/platform/acpi/third_party/acpica/LICENSE.BSD-3-Clause b/code/drivers/platform/acpi/third_party/acpica/LICENSE.BSD-3-Clause new file mode 100644 index 0000000..566d871 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/LICENSE.BSD-3-Clause @@ -0,0 +1,28 @@ +Copyright (c) 1999-2026, Intel Corporation + +SPDX-License-Identifier: BSD-3-Clause + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this +list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, +this list of conditions and the following disclaimer in the documentation and/or +other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/code/drivers/platform/acpi/third_party/acpica/LICENSE.GPL-2.0-only b/code/drivers/platform/acpi/third_party/acpica/LICENSE.GPL-2.0-only new file mode 100644 index 0000000..9efa6fb --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/LICENSE.GPL-2.0-only @@ -0,0 +1,338 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, see . + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Moe Ghoul, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsargs.c b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsargs.c new file mode 100644 index 0000000..c50e089 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsargs.c @@ -0,0 +1,410 @@ +/****************************************************************************** + * + * Module Name: dsargs - Support for execution of dynamic arguments for static + * objects (regions, fields, buffer fields, etc.) + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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_PTR (DsExecuteArguments, AmlStart); + + + /* Allocate a new parser op to be the root of the parsed tree */ + + Op = AcpiPsAllocOp (AML_INT_EVAL_SUBTREE_OP, AmlStart); + 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, AmlStart); + 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 Argument Init, AML Ptr: %p\n", + ObjDesc->Package.AmlStart)); + + /* 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/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dscontrol.c b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dscontrol.c new file mode 100644 index 0000000..7675780 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dscontrol.c @@ -0,0 +1,388 @@ +/****************************************************************************** + * + * Module Name: dscontrol - Support for execution control opcodes - + * if/else/while/return + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acdebug.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; + } + } + + ACPI_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; + ControlState->Control.LoopTimeout = AcpiOsGetTimer () + + ((UINT64) AcpiGbl_MaxLoopIterations * ACPI_100NSEC_PER_SEC); + + /* 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 infinite loop detection 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. + */ + if (ACPI_TIME_AFTER (AcpiOsGetTimer (), + ControlState->Control.LoopTimeout)) + { + Status = AE_AML_LOOP_TIMEOUT; + 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_BREAKPOINT_OP: + + AcpiDbSignalBreakPoint (WalkState); + + /* 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/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsdebug.c b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsdebug.c new file mode 100644 index 0000000..2932e6e --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsdebug.c @@ -0,0 +1,227 @@ +/****************************************************************************** + * + * Module Name: dsdebug - Parser/Interpreter interface - debugging + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acdispat.h" +#include "acnamesp.h" +#include "acdisasm.h" +#include "acinterp.h" + + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dsdebug") + + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +/* Local prototypes */ + +static void +AcpiDsPrintNodePathname ( + ACPI_NAMESPACE_NODE *Node, + const char *Message); + + +/******************************************************************************* + * + * FUNCTION: AcpiDsPrintNodePathname + * + * PARAMETERS: Node - Object + * Message - Prefix message + * + * DESCRIPTION: Print an object's full namespace pathname + * Manages allocation/freeing of a pathname buffer + * + ******************************************************************************/ + +static void +AcpiDsPrintNodePathname ( + ACPI_NAMESPACE_NODE *Node, + const char *Message) +{ + ACPI_BUFFER Buffer; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (DsPrintNodePathname); + + if (!Node) + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "[NULL NAME]")); + return_VOID; + } + + /* Convert handle to full pathname and print it (with supplied message) */ + + Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + + Status = AcpiNsHandleToPathname (Node, &Buffer, TRUE); + if (ACPI_SUCCESS (Status)) + { + if (Message) + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "%s ", Message)); + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "[%s] (Node %p)", + (char *) Buffer.Pointer, Node)); + ACPI_FREE (Buffer.Pointer); + } + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsDumpMethodStack + * + * 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. + * + ******************************************************************************/ + +void +AcpiDsDumpMethodStack ( + 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; + ACPI_OPERAND_OBJECT *MethodDesc; + + + ACPI_FUNCTION_TRACE (DsDumpMethodStack); + + + /* Ignore control codes, they are not errors */ + + if (ACPI_CNTL_EXCEPTION (Status)) + { + return_VOID; + } + + /* We may be executing a deferred opcode */ + + if (WalkState->DeferredNode) + { + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Executing subtree for Buffer/Package/Region\n")); + return_VOID; + } + + /* + * 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_VOID; + } + + /* Display exception and method name */ + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "\n**** Exception %s during execution of method ", + AcpiFormatException (Status))); + + AcpiDsPrintNodePathname (WalkState->MethodNode, NULL); + + /* Display stack of executing methods */ + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, + "\n\nMethod Execution Stack:\n")); + NextWalkState = Thread->WalkStateList; + + /* Walk list of linked walk states */ + + while (NextWalkState) + { + MethodDesc = NextWalkState->MethodDesc; + if (MethodDesc) + { + AcpiExStopTraceMethod ( + (ACPI_NAMESPACE_NODE *) MethodDesc->Method.Node, + MethodDesc, WalkState); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + " 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; + +#ifdef ACPI_DISASSEMBLER + if (WalkState->MethodNode != AcpiGbl_RootNode) + { + /* More verbose if not module-level code */ + + AcpiOsPrintf ("Failed at "); + AcpiDmDisassemble (NextWalkState, Op, ACPI_UINT32_MAX); + } +#endif + 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. + */ + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "Call to method ")); + AcpiDsPrintNodePathname (PreviousMethod, NULL); + } + + PreviousMethod = NextWalkState->MethodNode; + NextWalkState = NextWalkState->Next; + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_DISPATCH, "\n")); + } + + return_VOID; +} + +#else + +void +AcpiDsDumpMethodStack ( + ACPI_STATUS Status, + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op) +{ + return; +} + +#endif diff --git a/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsfield.c b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsfield.c new file mode 100644 index 0000000..dae5977 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsfield.c @@ -0,0 +1,878 @@ +/****************************************************************************** + * + * Module Name: dsfield - Dispatcher field routines + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acparser.h" + +#ifdef ACPI_EXEC_APP +#include "aecommon.h" +#endif + + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dsfield") + +/* Local prototypes */ + +#ifdef ACPI_ASL_COMPILER +#include "acdisasm.h" + +static ACPI_STATUS +AcpiDsCreateExternalRegion ( + ACPI_STATUS LookupStatus, + ACPI_PARSE_OBJECT *Op, + char *Path, + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE **Node); +#endif + +static ACPI_STATUS +AcpiDsGetFieldNames ( + ACPI_CREATE_FIELD_INFO *Info, + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Arg); + + +#ifdef ACPI_ASL_COMPILER +/******************************************************************************* + * + * FUNCTION: AcpiDsCreateExternalRegion (iASL Disassembler only) + * + * PARAMETERS: LookupStatus - Status from NsLookup operation + * Op - Op containing the Field definition and args + * Path - Pathname of the region + * ` WalkState - Current method state + * Node - Where the new region node is returned + * + * RETURN: Status + * + * DESCRIPTION: Add region to the external list if NOT_FOUND. Create a new + * region node/object. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDsCreateExternalRegion ( + ACPI_STATUS LookupStatus, + ACPI_PARSE_OBJECT *Op, + char *Path, + ACPI_WALK_STATE *WalkState, + ACPI_NAMESPACE_NODE **Node) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *ObjDesc; + + + if (LookupStatus != AE_NOT_FOUND) + { + return (LookupStatus); + } + + /* + * Table disassembly: + * OperationRegion not found. Generate an External for it, and + * insert the name into the namespace. + */ + AcpiDmAddOpToExternalList (Op, Path, ACPI_TYPE_REGION, 0, 0); + + Status = AcpiNsLookup (WalkState->ScopeInfo, Path, ACPI_TYPE_REGION, + ACPI_IMODE_LOAD_PASS1, ACPI_NS_SEARCH_PARENT, WalkState, Node); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Must create and install a region object for the new node */ + + ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION); + if (!ObjDesc) + { + return (AE_NO_MEMORY); + } + + ObjDesc->Region.Node = *Node; + Status = AcpiNsAttachObject (*Node, ObjDesc, ACPI_TYPE_REGION); + return (Status); +} +#endif + + +/******************************************************************************* + * + * 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; + } + else + { + /* Execute flag should always be set when this function is entered */ + + if (!(WalkState->ParseFlags & ACPI_PARSE_EXECUTE)) + { + ACPI_ERROR ((AE_INFO, + "Parse execute mode is not set")); + 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 ((WalkState->ParseFlags & ACPI_PARSE_DISASSEMBLE) && + Status == AE_ALREADY_EXISTS) + { + Status = AE_OK; + } + else if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo, + 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; + +#ifdef ACPI_EXEC_APP + ACPI_OPERAND_OBJECT *ResultDesc; + ACPI_OPERAND_OBJECT *ObjDesc; + char *NamePath; +#endif + + + 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; + Info->PinNumberIndex = 0; + + /* + * 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 (WalkState->ScopeInfo, + Child->Common.Value.Name, Status); + return_ACPI_STATUS (Status); + } + } + break; + + case AML_INT_NAMEDFIELD_OP: + + /* Validate the 4-char name to prevent OOB read in AcpiNsLookup */ + + if (!AcpiUtValidNameseg ((char *) &Arg->Named.Name)) + { + return_ACPI_STATUS (AE_BAD_CHARACTER); + } + + /* 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 (WalkState->ScopeInfo, + (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); + } +#ifdef ACPI_EXEC_APP + NamePath = AcpiNsGetExternalPathname (Info->FieldNode); + if (ACPI_SUCCESS (AeLookupInitFileEntry (NamePath, &ObjDesc))) + { + AcpiExWriteDataToField (ObjDesc, + AcpiNsGetAttachedObject (Info->FieldNode), + &ResultDesc); + AcpiUtRemoveReference (ObjDesc); + } + ACPI_FREE (NamePath); +#endif + } + } + + /* 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; + Info->PinNumberIndex++; /* Index relative to previous Connection() */ + 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); +#ifdef ACPI_ASL_COMPILER + Status = AcpiDsCreateExternalRegion (Status, Arg, + Arg->Common.Value.Name, WalkState, &RegionNode); +#endif + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo, + Arg->Common.Value.Name, Status); + return_ACPI_STATUS (Status); + } + } + + 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); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (Info.RegionNode->Object->Region.SpaceId == ACPI_ADR_SPACE_PLATFORM_COMM && + !RegionNode->Object->Field.InternalPccBuffer) + { + RegionNode->Object->Field.InternalPccBuffer = + ACPI_ALLOCATE_ZEROED(Info.RegionNode->Object->Region.Length); + if (!RegionNode->Object->Field.InternalPccBuffer) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + } + + 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); + } + + ACPI_ERROR ((AE_INFO, + "Parse deferred mode is not set")); + 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; + } + +#ifdef ACPI_EXEC_APP + Flags |= ACPI_NS_OVERRIDE_IF_FOUND; +#endif + /* + * 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) + { + /* Validate the 4-char name to prevent OOB read in AcpiNsLookup */ + + if (!AcpiUtValidNameseg ((char *) &Arg->Named.Name)) + { + return_ACPI_STATUS (AE_BAD_CHARACTER); + } + + Status = AcpiNsLookup (WalkState->ScopeInfo, + (char *) &Arg->Named.Name, Type, ACPI_IMODE_LOAD_PASS1, + Flags, WalkState, &Node); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo, + (char *) &Arg->Named.Name, Status); + if (Status != AE_ALREADY_EXISTS) + { + return_ACPI_STATUS (Status); + } + + /* Name already exists, just ignore this error */ + } + + 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); +#ifdef ACPI_ASL_COMPILER + Status = AcpiDsCreateExternalRegion (Status, Arg, + Arg->Common.Value.Name, WalkState, &RegionNode); +#endif + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo, + 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 (WalkState->ScopeInfo, + 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 (WalkState->ScopeInfo, + 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 (WalkState->ScopeInfo, + 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/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsinit.c b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsinit.c new file mode 100644 index 0000000..707d1f5 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsinit.c @@ -0,0 +1,244 @@ +/****************************************************************************** + * + * Module Name: dsinit - Object initialization namespace walk + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acdispat.h" +#include "acnamesp.h" +#include "actables.h" +#include "acinterp.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_STATUS Status; + ACPI_OPERAND_OBJECT *ObjDesc; + + + 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 */ + + switch (AcpiNsGetType (ObjHandle)) + { + 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: + /* + * Auto-serialization support. We will examine each method that is + * NotSerialized to determine if it creates any Named objects. If + * it does, it will be marked serialized to prevent problems if + * the method is entered by two or more threads and an attempt is + * made to create the same named object twice -- which results in + * an AE_ALREADY_EXISTS exception and method abort. + */ + Info->MethodCount++; + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc) + { + break; + } + + /* Ignore if already serialized */ + + if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED) + { + Info->SerialMethodCount++; + break; + } + + if (AcpiGbl_AutoSerializeMethods) + { + /* Parse/scan method and serialize it if necessary */ + + AcpiDsAutoSerializeMethod (Node, ObjDesc); + if (ObjDesc->Method.InfoFlags & ACPI_METHOD_SERIALIZED) + { + /* Method was just converted to Serialized */ + + Info->SerialMethodCount++; + Info->SerializedMethodCount++; + break; + } + } + + Info->NonSerialMethodCount++; + 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")); + + /* Set all init info to zero */ + + memset (&Info, 0, sizeof (ACPI_INIT_WALK_INFO)); + + Info.OwnerId = OwnerId; + Info.TableIndex = TableIndex; + + /* Walk entire namespace from the supplied root */ + + /* + * 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_NO_UNLOCK, AcpiDsInitOneObject, NULL, &Info, NULL); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "During WalkNamespace")); + } + + Status = AcpiGetTableByIndex (TableIndex, &Table); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* DSDT is always the first AML table */ + + if (ACPI_COMPARE_NAMESEG (Table->Signature, ACPI_SIG_DSDT)) + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, + "\nACPI table initialization:\n")); + } + + /* Summary of objects initialized */ + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, + "Table [%4.4s: %-8.8s] (id %.2X) - %4u Objects with %3u Devices, " + "%3u Regions, %4u Methods (%u/%u/%u Serial/Non/Cvt)\n", + Table->Signature, Table->OemTableId, OwnerId, Info.ObjectCount, + Info.DeviceCount,Info.OpRegionCount, Info.MethodCount, + Info.SerialMethodCount, Info.NonSerialMethodCount, + Info.SerializedMethodCount)); + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "%u Methods, %u Regions\n", + Info.MethodCount, Info.OpRegionCount)); + + return_ACPI_STATUS (AE_OK); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsmethod.c b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsmethod.c new file mode 100644 index 0000000..caad115 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsmethod.c @@ -0,0 +1,958 @@ +/****************************************************************************** + * + * Module Name: dsmethod - Parser/Interpreter interface - control method parsing + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdebug.h" + + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dsmethod") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiDsDetectNamedOpcodes ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT **OutOp); + +static ACPI_STATUS +AcpiDsCreateMethodMutex ( + ACPI_OPERAND_OBJECT *MethodDesc); + + +/******************************************************************************* + * + * FUNCTION: AcpiDsAutoSerializeMethod + * + * PARAMETERS: Node - Namespace Node of the method + * ObjDesc - Method object attached to node + * + * RETURN: Status + * + * DESCRIPTION: Parse a control method AML to scan for control methods that + * need serialization due to the creation of named objects. + * + * NOTE: It is a bit of overkill to mark all such methods serialized, since + * there is only a problem if the method actually blocks during execution. + * A blocking operation is, for example, a Sleep() operation, or any access + * to an operation region. However, it is probably not possible to easily + * detect whether a method will block or not, so we simply mark all suspicious + * methods as serialized. + * + * NOTE2: This code is essentially a generic routine for parsing a single + * control method. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsAutoSerializeMethod ( + ACPI_NAMESPACE_NODE *Node, + ACPI_OPERAND_OBJECT *ObjDesc) +{ + ACPI_STATUS Status; + ACPI_PARSE_OBJECT *Op = NULL; + ACPI_WALK_STATE *WalkState; + + + ACPI_FUNCTION_TRACE_PTR (DsAutoSerializeMethod, Node); + + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Method auto-serialization parse [%4.4s] %p\n", + AcpiUtGetNodeName (Node), Node)); + + /* Create/Init a root op for the method parse tree */ + + Op = AcpiPsAllocOp (AML_METHOD_OP, ObjDesc->Method.AmlStart); + if (!Op) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + AcpiPsSetName (Op, Node->Name.Integer); + Op->Common.Node = Node; + + /* Create and initialize a new walk state */ + + WalkState = AcpiDsCreateWalkState (Node->OwnerId, NULL, NULL, NULL); + if (!WalkState) + { + AcpiPsFreeOp (Op); + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Status = AcpiDsInitAmlWalk (WalkState, Op, Node, + ObjDesc->Method.AmlStart, ObjDesc->Method.AmlLength, NULL, 0); + if (ACPI_FAILURE (Status)) + { + AcpiDsDeleteWalkState (WalkState); + AcpiPsFreeOp (Op); + return_ACPI_STATUS (Status); + } + + WalkState->DescendingCallback = AcpiDsDetectNamedOpcodes; + + /* Parse the method, scan for creation of named objects */ + + Status = AcpiPsParseAml (WalkState); + + AcpiPsDeleteParseTree (Op); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsDetectNamedOpcodes + * + * PARAMETERS: WalkState - Current state of the parse tree walk + * OutOp - Unused, required for parser interface + * + * RETURN: Status + * + * DESCRIPTION: Descending callback used during the loading of ACPI tables. + * Currently used to detect methods that must be marked serialized + * in order to avoid problems with the creation of named objects. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiDsDetectNamedOpcodes ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT **OutOp) +{ + + ACPI_FUNCTION_NAME (AcpiDsDetectNamedOpcodes); + + + /* We are only interested in opcodes that create a new name */ + + if (!(WalkState->OpInfo->Flags & (AML_NAMED | AML_CREATE | AML_FIELD))) + { + return (AE_OK); + } + + /* + * At this point, we know we have a Named object opcode. + * Mark the method as serialized. Later code will create a mutex for + * this method to enforce serialization. + * + * Note, ACPI_METHOD_IGNORE_SYNC_LEVEL flag means that we will ignore the + * Sync Level mechanism for this method, even though it is now serialized. + * Otherwise, there can be conflicts with existing ASL code that actually + * uses sync levels. + */ + WalkState->MethodDesc->Method.SyncLevel = 0; + WalkState->MethodDesc->Method.InfoFlags |= + (ACPI_METHOD_SERIALIZED | ACPI_METHOD_IGNORE_SYNC_LEVEL); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Method serialized [%4.4s] %p - [%s] (%4.4X)\n", + WalkState->MethodNode->Name.Ascii, WalkState->MethodNode, + WalkState->OpInfo->Name, WalkState->Opcode)); + + /* Abort the parse, no need to examine this method any further */ + + return (AE_CTRL_TERMINATE); +} + + +/******************************************************************************* + * + * 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 debugger is configured + * + * Note: Allows the exception handler to change the status code + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsMethodError ( + ACPI_STATUS Status, + ACPI_WALK_STATE *WalkState) +{ + UINT32 AmlOffset; + ACPI_NAME Name = 0; + + + 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. + */ + AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->Aml, + WalkState->ParserState.AmlStart); + + if (WalkState->MethodNode) + { + Name = WalkState->MethodNode->Name.Integer; + } + else if (WalkState->DeferredNode) + { + Name = WalkState->DeferredNode->Name.Integer; + } + + Status = AcpiGbl_ExceptionHandler (Status, Name, + WalkState->Opcode, AmlOffset, NULL); + AcpiExEnterInterpreter (); + } + + AcpiDsClearImplicitReturn (WalkState); + + if (ACPI_FAILURE (Status)) + { + AcpiDsDumpMethodStack (Status, WalkState, WalkState->Op); + + /* Display method locals/args if debugger is present */ + +#ifdef ACPI_DEBUGGER + AcpiDbDumpMethodInfo (Status, WalkState); +#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)) + { + AcpiUtDeleteObjectDesc (MutexDesc); + 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); + } + + AcpiExStartTraceMethod (MethodNode, ObjDesc, WalkState); + + /* 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. + * + * If the method was auto-serialized, we just ignore the sync level + * mechanism, because auto-serialization of methods can interfere + * with ASL code that actually uses sync levels. + * + * Top-level method invocation has no walk state at this point + */ + if (WalkState && + (!(ObjDesc->Method.InfoFlags & ACPI_METHOD_IGNORE_SYNC_LEVEL)) && + (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; + + /* + * Update the current SyncLevel only if this is not an auto- + * serialized method. In the auto case, we have to ignore + * the sync level for the method mutex (created for the + * auto-serialization) because we have no idea of what the + * sync level should be. Therefore, just ignore it. + */ + if (!(ObjDesc->Method.InfoFlags & + ACPI_METHOD_IGNORE_SYNC_LEVEL)) + { + WalkState->Thread->CurrentSyncLevel = + ObjDesc->Method.SyncLevel; + } + } + else + { + ObjDesc->Method.Mutex->Mutex.OriginalSyncLevel = + ObjDesc->Method.Mutex->Mutex.SyncLevel; + + ObjDesc->Method.Mutex->Mutex.ThreadId = + AcpiOsGetThreadId (); + } + } + + /* 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; + + 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); + } + + if (ThisWalkState->NumOperands < ObjDesc->Method.ParamCount) + { + ACPI_ERROR ((AE_INFO, "Missing argument(s) for method [%4.4s]", + AcpiUtGetNodeName (MethodNode))); + + return_ACPI_STATUS (AE_AML_TOO_FEW_ARGUMENTS); + } + + else if (ThisWalkState->NumOperands > ObjDesc->Method.ParamCount) + { + ACPI_ERROR ((AE_INFO, "Too many arguments for method [%4.4s]", + AcpiUtGetNodeName (MethodNode))); + + return_ACPI_STATUS (AE_AML_TOO_MANY_ARGUMENTS); + } + + + /* 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) + { + Status = AE_NO_MEMORY; + goto PopWalkState; + } + + 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 PopWalkState; + } + + NextWalkState->MethodNestingDepth = ThisWalkState->MethodNestingDepth + 1; + + /* + * Delete the operands on the previous walkstate operand stack + * (they were copied to new objects) + */ + AcpiDsClearOperands (ThisWalkState); + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "**** Begin nested execution of [%4.4s] **** WalkState=%p\n", + MethodNode->Name.Ascii, NextWalkState)); + + ThisWalkState->MethodPathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE); + ThisWalkState->MethodIsNested = TRUE; + + /* Optional object evaluation log */ + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EVALUATION, + "%-26s: %*s%s\n", " Nested method call", + NextWalkState->MethodNestingDepth * 3, " ", + &ThisWalkState->MethodPathname[1])); + + /* 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); + + +PopWalkState: + + /* On error, pop the walk state to be deleted from thread */ + + AcpiDsPopWalkState(Thread); + +Cleanup: + + /* On error, we must terminate the method properly */ + + AcpiDsTerminateControlMethod (ObjDesc, 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) +{ + UINT32 i; + ACPI_NAMESPACE_NODE *RefNode; + + ACPI_FUNCTION_TRACE_PTR (DsTerminateControlMethod, WalkState); + + + /* MethodDesc is required, WalkState is optional */ + + if (!MethodDesc) + { + return_VOID; + } + + if (WalkState) + { + /* + * Check if the return value is a RefOf reference to a method local + * or argument. If so, clear the reference to avoid use-after-free + * when the walk state is deleted. + */ + if (WalkState->ReturnDesc && + (WalkState->ReturnDesc->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) && + (WalkState->ReturnDesc->Reference.Class == ACPI_REFCLASS_REFOF)) + { + RefNode = WalkState->ReturnDesc->Reference.Object; + if (RefNode) + { + /* Check against method locals */ + for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) + { + if (RefNode == &WalkState->LocalVariables[i]) + { + AcpiUtRemoveReference (WalkState->ReturnDesc); + WalkState->ReturnDesc = NULL; + break; + } + } + + /* Check against method arguments if not already cleared */ + if (WalkState->ReturnDesc) + { + for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) + { + if (RefNode == &WalkState->Arguments[i]) + { + AcpiUtRemoveReference (WalkState->ReturnDesc); + WalkState->ReturnDesc = NULL; + break; + } + } + } + } + } + + /* Delete all arguments and locals */ + + AcpiDsMethodDataDeleteAll (WalkState); + + /* + * 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 */ + + (void) AcpiExExitInterpreter (); + AcpiNsDeleteNamespaceSubtree (WalkState->MethodNode); + (void) AcpiExEnterInterpreter (); + + /* + * 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) + { + (void) AcpiExExitInterpreter (); + AcpiNsDeleteNamespaceByOwner (MethodDesc->Method.OwnerId); + (void) AcpiExEnterInterpreter (); + MethodDesc->Method.InfoFlags &= + ~ACPI_METHOD_MODIFIED_NAMESPACE; + } + } + + /* + * 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; + } + } + } + + /* 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 (( + "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 | ACPI_METHOD_IGNORE_SYNC_LEVEL); + MethodDesc->Method.SyncLevel = 0; + } + + /* No more threads, we can free the OwnerId */ + + if (!(MethodDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL)) + { + AcpiUtReleaseOwnerId (&MethodDesc->Method.OwnerId); + } + } + + AcpiExStopTraceMethod ((ACPI_NAMESPACE_NODE *) MethodDesc->Method.Node, + MethodDesc, WalkState); + + return_VOID; +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsmthdat.c b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsmthdat.c new file mode 100644 index 0000000..26afeab --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsmthdat.c @@ -0,0 +1,749 @@ +/******************************************************************************* + * + * Module Name: dsmthdat - control method arguments and local variables + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 parameter 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++; + } + AcpiExTraceArgs(Params, 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_FIRST LOCAL_OP or + * AML_FIRST_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/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsobject.c b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsobject.c new file mode 100644 index 0000000..a4a2bfe --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsobject.c @@ -0,0 +1,560 @@ +/****************************************************************************** + * + * Module Name: dsobject - Dispatcher object management routines + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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") + + +/******************************************************************************* + * + * 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! + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsBuildInternalObject ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + ACPI_OPERAND_OBJECT **ObjDescPtr) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + + + 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) + { + /* Check if we are resolving a named reference within a package */ + + if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)) + { + /* + * We won't resolve package elements here, we will do this + * after all ACPI tables are loaded into the namespace. This + * behavior supports both forward references to named objects + * and external references to objects in other tables. + */ + goto CreateNewObject; + } + else + { + 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)) + { + ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo, + Op->Common.Value.String, Status); + return_ACPI_STATUS (Status); + } + } + } + } + +CreateNewObject: + + /* 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); + } + + /* + * Handling for unresolved package reference elements. + * These are elements that are namepaths. + */ + if ((Op->Common.Parent->Common.AmlOpcode == AML_PACKAGE_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)) + { + ObjDesc->Reference.Resolved = TRUE; + + if ((Op->Common.AmlOpcode == AML_INT_NAMEPATH_OP) && + !ObjDesc->Reference.Node) + { + /* + * Name was unresolved above. + * Get the prefix node for later lookup + */ + ObjDesc->Reference.Node = WalkState->ScopeInfo->Scope.Node; + ObjDesc->Reference.Aml = Op->Common.Aml; + ObjDesc->Reference.Resolved = FALSE; + } + } + + *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) + { + 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: 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); +} + + +/******************************************************************************* + * + * 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 and all + * package elements. (01/2017): We defer the element + * resolution to allow forward references from the package + * in order to provide compatibility with other ACPI + * implementations. + */ + ObjDesc->Package.Node = ACPI_CAST_PTR ( + ACPI_NAMESPACE_NODE, WalkState->Operands[0]); + + if (!Op->Named.Data) + { + return_ACPI_STATUS (AE_OK); + } + + 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 */ + + (void) AcpiExTruncateFor32bitTable (ObjDesc); + 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; + + if (AcpiExTruncateFor32bitTable (ObjDesc)) + { + /* Warn if we found a 64-bit constant in a 32-bit table */ + + ACPI_WARNING ((AE_INFO, + "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X", + ACPI_FORMAT_UINT64 (Op->Common.Value.Integer), + (UINT32) ObjDesc->Integer.Value)); + } + 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) 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_FIRST_LOCAL_OP) */ + + ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_FIRST_LOCAL_OP; + ObjDesc->Reference.Class = ACPI_REFCLASS_LOCAL; + + Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_LOCAL, + ObjDesc->Reference.Value, WalkState, + ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, + &ObjDesc->Reference.Object)); + break; + + case AML_TYPE_METHOD_ARGUMENT: + + /* Arg ID (0-6) is (AML opcode - base AML_FIRST_ARG_OP) */ + + ObjDesc->Reference.Value = ((UINT32) Opcode) - AML_FIRST_ARG_OP; + ObjDesc->Reference.Class = ACPI_REFCLASS_ARG; + + Status = AcpiDsMethodDataGetNode (ACPI_REFCLASS_ARG, + ObjDesc->Reference.Value, WalkState, + ACPI_CAST_INDIRECT_PTR (ACPI_NAMESPACE_NODE, + &ObjDesc->Reference.Object)); + 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.Class = ACPI_REFCLASS_NAME; + if (Op->Common.Node) + { + ObjDesc->Reference.Object = Op->Common.Node->Object; + } + 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/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsopcode.c b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsopcode.c new file mode 100644 index 0000000..e5cf938 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsopcode.c @@ -0,0 +1,812 @@ +/****************************************************************************** + * + * Module Name: dsopcode - Dispatcher support for regions and fields + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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); + 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_BIOS_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)) + { + Status = AE_AML_BUFFER_LIMIT; + ACPI_BIOS_EXCEPTION ((AE_INFO, Status, + "Field [%4.4s] at bit offset/length %u/%u " + "exceeds size of target Buffer (%u bits)", + AcpiUtGetNodeName (ResultDesc), BitOffset, BitCount, + 8 * (UINT32) BufferDesc->Buffer.Length)); + 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; + ObjDesc->BufferField.IsCreateField = AmlOpcode == AML_CREATE_FIELD_OP; + + /* 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_ADR_SPACE_TYPE SpaceId; + + + 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; + SpaceId = (ACPI_ADR_SPACE_TYPE) NextOp->Common.Value.Integer; + + /* 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); + + /* A zero-length operation region is unusable. Just warn */ + + if (!ObjDesc->Region.Length && (SpaceId < ACPI_NUM_PREDEFINED_REGIONS)) + { + ACPI_WARNING ((AE_INFO, + "Operation Region [%4.4s] has zero length (SpaceId %X)", + Node->Name.Ascii, SpaceId)); + } + + /* + * 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_UINT64 (ObjDesc->Region.Address), + ObjDesc->Region.Length)); + + Status = AcpiUtAddAddressRange (ObjDesc->Region.SpaceId, + ObjDesc->Region.Address, ObjDesc->Region.Length, Node); + + /* 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; + ACPI_TABLE_HEADER *Table; + UINT32 TableIndex; + + + ACPI_FUNCTION_TRACE_PTR (DsEvalTableRegionOperands, Op); + + + /* + * This is where we evaluate the Signature string, OemId string, + * and OemTableId string of the Data Table Region declaration + */ + Node = Op->Common.Node; + + /* NextOp points to Signature string op */ + + NextOp = Op->Common.Value.Arg; + + /* + * Evaluate/create the Signature string, OemId string, + * and OemTableId string operands + */ + Status = AcpiDsCreateOperands (WalkState, NextOp); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Operand = &WalkState->Operands[0]; + + /* + * Resolve the Signature string, OemId string, + * and OemTableId string operands + */ + Status = AcpiExResolveOperands ( + Op->Common.AmlOpcode, ACPI_WALK_OPERANDS, WalkState); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + /* Find the ACPI table */ + + Status = AcpiTbFindTable ( + Operand[0]->String.Pointer, + Operand[1]->String.Pointer, + Operand[2]->String.Pointer, &TableIndex); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_NOT_FOUND) + { + ACPI_ERROR ((AE_INFO, + "ACPI Table [%4.4s] OEM:(%s, %s) not found in RSDT/XSDT", + Operand[0]->String.Pointer, + Operand[1]->String.Pointer, + Operand[2]->String.Pointer)); + } + goto Cleanup; + } + + Status = AcpiGetTableByIndex (TableIndex, &Table); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc) + { + Status = AE_NOT_EXIST; + goto Cleanup; + } + + ObjDesc->Region.Address = ACPI_PTR_TO_PHYSADDR (Table); + ObjDesc->Region.Length = Table->Length; + ObjDesc->Region.Pointer = Table; + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", + ObjDesc, ACPI_FORMAT_UINT64 (ObjDesc->Region.Address), + ObjDesc->Region.Length)); + + /* Now the address and length are valid for this opregion */ + + ObjDesc->Region.Flags |= AOPOBJ_DATA_VALID; + +Cleanup: + AcpiUtRemoveReference (Operand[0]); + AcpiUtRemoveReference (Operand[1]); + AcpiUtRemoveReference (Operand[2]); + + 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; + + /* Ignore if child is not valid */ + + if (!Op->Common.Value.Arg) + { + ACPI_ERROR ((AE_INFO, + "Missing child while evaluating opcode %4.4X, Op %p", + Op->Common.AmlOpcode, Op)); + return_ACPI_STATUS (AE_OK); + } + + 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_VARIABLE_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_VARIABLE_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/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dspkginit.c b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dspkginit.c new file mode 100644 index 0000000..a5052f1 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dspkginit.c @@ -0,0 +1,564 @@ +/****************************************************************************** + * + * Module Name: dspkginit - Completion of deferred package initialization + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acparser.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("dspkginit") + + +/* Local prototypes */ + +static void +AcpiDsResolvePackageElement ( + ACPI_OPERAND_OBJECT **Element); + + +/******************************************************************************* + * + * 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; + BOOLEAN ModuleLevelCode = FALSE; + UINT16 ReferenceCount; + UINT32 Index; + UINT32 i; + + + ACPI_FUNCTION_TRACE (DsBuildInternalPackageObj); + + + /* Check if we are executing module level code */ + + if (WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL) + { + ModuleLevelCode = TRUE; + } + + /* Find the parent of a possibly nested package */ + + Parent = Op->Common.Parent; + while ((Parent->Common.AmlOpcode == AML_PACKAGE_OP) || + (Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_OP)) + { + Parent = Parent->Common.Parent; + } + + /* + * If we are evaluating a Named package object of the form: + * 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; + } + + if (ObjDesc->Package.Flags & AOPOBJ_DATA_VALID) /* Just in case */ + { + return_ACPI_STATUS (AE_OK); + } + + /* + * Allocate the element array (array of pointers to the individual + * objects) if necessary. the count is based on the NumElements + * parameter. Add an extra pointer slot so that the list is always + * null terminated. + */ + if (!ObjDesc->Package.Elements) + { + 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; + } + + /* First arg is element count. Second arg begins the initializer list */ + + Arg = Op->Common.Value.Arg; + Arg = Arg->Common.Next; + + /* + * If we are executing module-level code, we will defer the + * full resolution of the package elements in order to support + * forward references from the elements. This provides + * compatibility with other ACPI implementations. + */ + if (ModuleLevelCode) + { + ObjDesc->Package.AmlStart = WalkState->Aml; + ObjDesc->Package.AmlLength = 0; + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE, + "%s: Deferring resolution of Package elements\n", + ACPI_GET_FUNCTION_NAME)); + } + + /* + * 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. + */ + for (i = 0; Arg && (i < ElementCount); i++) + { + if (Arg->Common.AmlOpcode == AML_INT_RETURN_VALUE_OP) + { + if (!Arg->Common.Node) + { + /* + * This is the case where an expression has returned a value. + * The use of expressions (TermArgs) within individual + * package elements is not supported by the AML interpreter, + * even though the ASL grammar supports it. Example: + * + * Name (INT1, 0x1234) + * + * Name (PKG3, Package () { + * Add (INT1, 0xAAAA0000) + * }) + * + * 1) No known AML interpreter supports this type of construct + * 2) This fixes a fault if the construct is encountered + */ + ACPI_EXCEPTION ((AE_INFO, AE_SUPPORT, + "Expressions within package elements are not supported")); + + /* Cleanup the return object, it is not needed */ + + AcpiUtRemoveReference (WalkState->Results->Results.ObjDesc[0]); + return_ACPI_STATUS (AE_SUPPORT); + } + + 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 (Status == AE_NOT_FOUND) + { + ACPI_ERROR ((AE_INFO, "%-48s", "****DS namepath not found")); + } + + if (!ModuleLevelCode) + { + /* + * Initialize this package element. This function handles the + * resolution of named references within the package. + * Forward references from module-level code are deferred + * until all ACPI tables are loaded. + */ + AcpiDsInitPackageElement (0, ObjDesc->Package.Elements[i], + NULL, &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 */ + /* TBD: Probably need an AcpiUtAddReferences function */ + + for (Index = 0; Index < ((UINT32) 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 compatibility with other + * ACPI implementations. Some firmware implementations will alter + * the NumElements on the fly, possibly 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 (( + "Actual Package length (%u) is larger than " + "NumElements field (%u), truncated", + 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 as per the ACPI specification. + */ + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, + "%s: Package List length (%u) smaller than NumElements " + "count (%u), padded with null elements\n", + ACPI_GET_FUNCTION_NAME, i, ElementCount)); + } + + /* Module-level packages will be resolved later */ + + if (!ModuleLevelCode) + { + ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID; + } + + Op->Common.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsInitPackageElement + * + * PARAMETERS: ACPI_PKG_CALLBACK + * + * RETURN: Status + * + * DESCRIPTION: Resolve a named reference element within a package object + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDsInitPackageElement ( + UINT8 ObjectType, + ACPI_OPERAND_OBJECT *SourceObject, + ACPI_GENERIC_STATE *State, + void *Context) +{ + ACPI_OPERAND_OBJECT **ElementPtr; + + + ACPI_FUNCTION_TRACE (DsInitPackageElement); + + + if (!SourceObject) + { + return_ACPI_STATUS (AE_OK); + } + + /* + * The following code is a bit of a hack to workaround a (current) + * limitation of the ACPI_PKG_CALLBACK interface. We need a pointer + * to the location within the element array because a new object + * may be created and stored there. + */ + if (Context) + { + /* A direct call was made to this function */ + + ElementPtr = (ACPI_OPERAND_OBJECT **) Context; + } + else + { + /* Call came from AcpiUtWalkPackageTree */ + + ElementPtr = State->Pkg.ThisTargetObj; + } + + /* We are only interested in reference objects/elements */ + + if (SourceObject->Common.Type == ACPI_TYPE_LOCAL_REFERENCE) + { + /* Attempt to resolve the (named) reference to a namespace node */ + + AcpiDsResolvePackageElement (ElementPtr); + } + else if (SourceObject->Common.Type == ACPI_TYPE_PACKAGE) + { + SourceObject->Package.Flags |= AOPOBJ_DATA_VALID; + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiDsResolvePackageElement + * + * PARAMETERS: ElementPtr - Pointer to a reference object + * + * RETURN: Possible new element is stored to the indirect ElementPtr + * + * DESCRIPTION: Resolve a package element that is a reference to a named + * object. + * + ******************************************************************************/ + +static void +AcpiDsResolvePackageElement ( + ACPI_OPERAND_OBJECT **ElementPtr) +{ + ACPI_STATUS Status; + ACPI_STATUS Status2; + ACPI_GENERIC_STATE ScopeInfo; + ACPI_OPERAND_OBJECT *Element = *ElementPtr; + ACPI_NAMESPACE_NODE *ResolvedNode; + ACPI_NAMESPACE_NODE *OriginalNode; + char *ExternalPath = ""; + ACPI_OBJECT_TYPE Type; + + + ACPI_FUNCTION_TRACE (DsResolvePackageElement); + + + /* Check if reference element is already resolved */ + + if (Element->Reference.Resolved) + { + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE, + "%s: Package element is already resolved\n", + ACPI_GET_FUNCTION_NAME)); + + return_VOID; + } + + /* Element must be a reference object of correct type */ + + ScopeInfo.Scope.Node = Element->Reference.Node; /* Prefix node */ + + Status = AcpiNsLookup (&ScopeInfo, (char *) Element->Reference.Aml, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, + NULL, &ResolvedNode); + if (ACPI_FAILURE (Status)) + { + if ((Status == AE_NOT_FOUND) && AcpiGbl_IgnorePackageResolutionErrors) + { + /* + * Optionally be silent about the NOT_FOUND case for the referenced + * name. Although this is potentially a serious problem, + * it can generate a lot of noise/errors on platforms whose + * firmware carries around a bunch of unused Package objects. + * To disable these errors, set this global to TRUE: + * AcpiGbl_IgnorePackageResolutionErrors + * + * If the AML actually tries to use such a package, the unresolved + * element(s) will be replaced with NULL elements. + */ + + /* Referenced name not found, set the element to NULL */ + + AcpiUtRemoveReference (*ElementPtr); + *ElementPtr = NULL; + return_VOID; + } + + Status2 = AcpiNsExternalizeName (ACPI_UINT32_MAX, + (char *) Element->Reference.Aml, NULL, &ExternalPath); + + ACPI_EXCEPTION ((AE_INFO, Status, + "While resolving a named reference package element - %s", + ExternalPath)); + if (ACPI_SUCCESS (Status2)) + { + ACPI_FREE (ExternalPath); + } + + /* Could not resolve name, set the element to NULL */ + + AcpiUtRemoveReference (*ElementPtr); + *ElementPtr = NULL; + return_VOID; + } + else if (ResolvedNode->Type == ACPI_TYPE_ANY) + { + /* Named reference not resolved, return a NULL package element */ + + ACPI_ERROR ((AE_INFO, + "Could not resolve named package element [%4.4s] in [%4.4s]", + ResolvedNode->Name.Ascii, ScopeInfo.Scope.Node->Name.Ascii)); + *ElementPtr = NULL; + return_VOID; + } + + /* + * Special handling for Alias objects. We need ResolvedNode to point + * to the Alias target. This effectively "resolves" the alias. + */ + if (ResolvedNode->Type == ACPI_TYPE_LOCAL_ALIAS) + { + ResolvedNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, + ResolvedNode->Object); + } + + /* Update the reference object */ + + Element->Reference.Resolved = TRUE; + Element->Reference.Node = ResolvedNode; + Type = Element->Reference.Node->Type; + + /* + * 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. + */ + OriginalNode = ResolvedNode; + Status = AcpiExResolveNodeToValue (&ResolvedNode, NULL); + if (ACPI_FAILURE (Status)) + { + return_VOID; + } + + switch (Type) + { + /* + * These object types are a result of named references, so we will + * leave them as reference objects. In other words, these types + * have no intrinsic "value". + */ + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_METHOD: + break; + + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_REGION: + + /* AcpiExResolveNodeToValue gave these an extra reference */ + + AcpiUtRemoveReference (OriginalNode->Object); + break; + + default: + /* + * For all other types - the node was resolved to an actual + * operand object with a value, return the object. Remove + * a reference on the existing object. + */ + AcpiUtRemoveReference (Element); + *ElementPtr = (ACPI_OPERAND_OBJECT *) ResolvedNode; + break; + } + + return_VOID; +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsutils.c b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsutils.c new file mode 100644 index 0000000..93b84d5 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dsutils.c @@ -0,0 +1,917 @@ +/******************************************************************************* + * + * Module Name: dsutils - Dispatcher utilities + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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; + } +} + + +/******************************************************************************* + * + * 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_BUFFER_OP) || + (Op->Common.Parent->Common.AmlOpcode == AML_VARIABLE_PACKAGE_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; +} + + +/******************************************************************************* + * + * 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_CONDITIONAL_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 if (ParentOp->Common.AmlOpcode == AML_EXTERNAL_OP) + { + /* + * This opcode should never appear here. It is used only + * by AML disassemblers and is surrounded by an If(0) + * by the ASL compiler. + * + * Therefore, if we see it here, it is a serious error. + */ + Status = AE_AML_BAD_OPCODE; + } + 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 (WalkState->ScopeInfo, + 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); + } + + 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)) + { + /* + * 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); + } + + 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 PrevNumOperands = WalkState->NumOperands; + UINT32 NewNumOperands; + 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++; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "NumOperands %d, ArgCount %d, Index %d\n", + WalkState->NumOperands, ArgCount, Index)); + + /* Create the interpreter arguments, in reverse order */ + + NewNumOperands = Index; + Index--; + for (i = 0; i < ArgCount; i++) + { + Arg = Arguments[Index]; + WalkState->OperandIndex = (UINT8) Index; + + Status = AcpiDsCreateOperand (WalkState, Arg, Index); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "Created Arg #%u (%p) %u args total\n", + Index, Arg, ArgCount)); + Index--; + } + + 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 + */ + WalkState->NumOperands = (UINT8) (i); + AcpiDsObjStackPopAndDelete (NewNumOperands, WalkState); + + /* Restore operand count */ + WalkState->NumOperands = (UINT8) (PrevNumOperands); + + 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_VARIABLE_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/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswexec.c b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswexec.c new file mode 100644 index 0000000..8098d35 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswexec.c @@ -0,0 +1,790 @@ +/****************************************************************************** + * + * Module Name: dswexec - Dispatcher method execution callbacks; + * dispatch to interpreter. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acdebug.h" +#ifdef ACPI_EXEC_APP +#include "aecommon.h" +#endif + +#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, + NULL, /* Was: AcpiExOpcode_1A_0T_0R (Was for Load operator) */ + 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, + ACPI_IMPLICIT_CONVERSION); + 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 */ + + (void) 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 */ + + 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; +#ifdef ACPI_EXEC_APP + char *Namepath; + ACPI_OPERAND_OBJECT *ObjDesc; +#endif + + 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) */ + + Status = AcpiDbSingleStep (WalkState, Op, OpClass); + 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 as well as opcodes that + * take no arguments. + */ + if (!(WalkState->OpInfo->Flags & AML_NO_OPERAND_RESOLVE) && + (WalkState->OpInfo->Flags & AML_HAS_ARGS)) + { + /* 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_VARIABLE_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); + if (ACPI_FAILURE (Status)) + { + break; + } + +#ifdef ACPI_EXEC_APP + /* + * AcpiExec support for namespace initialization file (initialize + * BufferFields in this code.) + */ + Namepath = AcpiNsGetExternalPathname (Op->Common.Node); + Status = AeLookupInitFileEntry (Namepath, &ObjDesc); + if (ACPI_SUCCESS (Status)) + { + Status = AcpiExWriteDataToField (ObjDesc, Op->Common.Node->Object, NULL); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "While writing to buffer field")); + } + } + ACPI_FREE (Namepath); + Status = AE_OK; +#endif + break; + + + case AML_TYPE_CREATE_OBJECT: + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Executing CreateObject (Buffer/Package) Op=%p Child=%p ParentOpcode=%4.4X\n", + Op, Op->Named.Value.Arg, Op->Common.Parent->Common.AmlOpcode)); + + 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; + } + + ACPI_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 + */ + (void) 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 */ + + 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/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswload.c b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswload.c new file mode 100644 index 0000000..6b88587 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswload.c @@ -0,0 +1,615 @@ +/****************************************************************************** + * + * Module Name: dswload - Dispatcher first pass namespace load callbacks + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 0: + + /* Parse only - caller will setup callbacks */ + + WalkState->ParseFlags = ACPI_PARSE_LOAD_PASS1 | + ACPI_PARSE_DELETE_TREE | + ACPI_PARSE_DISASSEMBLE; + WalkState->DescendingCallback = NULL; + WalkState->AscendingCallback = NULL; + break; + + case 1: + + /* Load pass 1 */ + + WalkState->ParseFlags = ACPI_PARSE_LOAD_PASS1 | + ACPI_PARSE_DELETE_TREE; + WalkState->DescendingCallback = AcpiDsLoad1BeginOp; + WalkState->AscendingCallback = AcpiDsLoad1EndOp; + break; + + case 2: + + /* Load pass 2 */ + + WalkState->ParseFlags = ACPI_PARSE_LOAD_PASS1 | + ACPI_PARSE_DELETE_TREE; + WalkState->DescendingCallback = AcpiDsLoad2BeginOp; + WalkState->AscendingCallback = AcpiDsLoad2EndOp; + break; + + case 3: + + /* Execution pass */ + + WalkState->ParseFlags |= ACPI_PARSE_EXECUTE | + ACPI_PARSE_DELETE_TREE; + WalkState->DescendingCallback = AcpiDsExecBeginOp; + WalkState->AscendingCallback = AcpiDsExecEndOp; + 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_PTR (DsLoad1BeginOp, WalkState->Op); + + + 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. + */ + AcpiDmAddOpToExternalList (Op, Path, ACPI_TYPE_DEVICE, 0, 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 (WalkState->ScopeInfo, 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; + + case ACPI_TYPE_METHOD: + /* + * Allow scope change to root during execution of module-level + * code. Root is typed METHOD during this time. + */ + if ((Node == AcpiGbl_RootNode) && + (WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)) + { + break; + } + + ACPI_FALLTHROUGH; + + 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))) + { + if (WalkState->NamespaceOverride) + { + Flags |= ACPI_NS_OVERRIDE_IF_FOUND; + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[%s] Override allowed\n", + AcpiUtGetTypeName (ObjectType))); + } + else + { + 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 (WalkState->ScopeInfo, Path, Status); + return_ACPI_STATUS (Status); + } + } + break; + } + + /* Common exit */ + + if (!Op) + { + /* Create a new op */ + + Op = AcpiPsAllocOp (WalkState->Opcode, WalkState->Aml); + if (!Op) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + } + + /* Initialize the op */ + +#ifdef ACPI_CONSTANT_EVAL_ONLY + Op->Named.Path = 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; +#ifdef ACPI_ASL_COMPILER + UINT8 ParamCount; +#endif + + + ACPI_FUNCTION_TRACE (DsLoad1EndOp); + + + Op = WalkState->Op; + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p State=%p\n", Op, WalkState)); + + /* + * Disassembler: handle create field operators here. + * + * CreateBufferField is a deferred op that is typically processed in load + * pass 2. However, disassembly of control method contents walk the parse + * tree with ACPI_PARSE_LOAD_PASS1 and AML_CREATE operators are processed + * in a later walk. This is a problem when there is a control method that + * has the same name as the AML_CREATE object. In this case, any use of the + * name segment will be detected as a method call rather than a reference + * to a buffer field. + * + * This earlier creation during disassembly solves this issue by inserting + * the named object in the ACPI namespace so that references to this name + * would be a name string rather than a method call. + */ + if ((WalkState->ParseFlags & ACPI_PARSE_DISASSEMBLE) && + (WalkState->OpInfo->Flags & AML_CREATE)) + { + Status = AcpiDsCreateBufferField (Op, WalkState); + return_ACPI_STATUS (Status); + } + + /* 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; + + 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); + } + } + } + + 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; + } + } + } + +#ifdef ACPI_ASL_COMPILER + /* + * For external opcode, get the object type from the argument and + * get the parameter count from the argument's next. + */ + if (AcpiGbl_DisasmFlag && + Op->Common.Node && + Op->Common.AmlOpcode == AML_EXTERNAL_OP) + { + /* + * Note, if this external is not a method + * Op->Common.Value.Arg->Common.Next->Common.Value.Integer == 0 + * Therefore, ParamCount will be 0. + */ + ParamCount = (UINT8) Op->Common.Value.Arg->Common.Next->Common.Value.Integer; + ObjectType = (UINT8) Op->Common.Value.Arg->Common.Value.Integer; + Op->Common.Node->Flags |= ANOBJ_IS_EXTERNAL; + Op->Common.Node->Type = (UINT8) ObjectType; + + AcpiDmCreateSubobjectForExternal ((UINT8)ObjectType, + &Op->Common.Node, ParamCount); + + /* + * Add the external to the external list because we may be + * emitting code based off of the items within the external list. + */ + AcpiDmAddOpToExternalList (Op, Op->Named.Path, (UINT8)ObjectType, ParamCount, + ACPI_EXT_ORIGIN_FROM_OPCODE | ACPI_EXT_RESOLVED_REFERENCE); + } +#endif + + /* + * 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 && + Op->Common.AmlOpcode != AML_EXTERNAL_OP && + 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/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswload2.c b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswload2.c new file mode 100644 index 0000000..e1738c7 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswload2.c @@ -0,0 +1,770 @@ +/****************************************************************************** + * + * Module Name: dswload2 - Dispatcher second pass namespace load callbacks + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "acevents.h" +#ifdef ACPI_EXEC_APP +#include "aecommon.h" +#endif + +#define _COMPONENT ACPI_DISPATCHER + ACPI_MODULE_NAME ("dswload2") + + +/******************************************************************************* + * + * FUNCTION: AcpiDsLoad2BeginOp + * + * 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 +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 (WalkState->ScopeInfo, + BufferPtr, Status); + } +#else + ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo, + 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", + AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type))); + + Node->Type = ACPI_TYPE_ANY; + WalkState->ScopeInfo->Common.Value = ACPI_TYPE_ANY; + break; + + case ACPI_TYPE_METHOD: + + /* + * Allow scope change to root during execution of module-level + * code. Root is typed METHOD during this time. + */ + if ((Node == AcpiGbl_RootNode) && + (WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)) + { + break; + } + + ACPI_FALLTHROUGH; + + 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: + + /* 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; + } + } + +#ifdef ACPI_ASL_COMPILER + + /* + * Do not open a scope for AML_EXTERNAL_OP + * AcpiNsLookup can open a new scope based on the object type + * of this op. AML_EXTERNAL_OP is a declaration rather than a + * definition. In the case that this external is a method object, + * AcpiNsLookup will open a new scope. However, an AML_EXTERNAL_OP + * associated with the ACPI_TYPE_METHOD is a declaration, rather than + * a definition. Flags is set to avoid opening a scope for any + * AML_EXTERNAL_OP. + */ + if (WalkState->Opcode == AML_EXTERNAL_OP) + { + Flags |= ACPI_NS_DONT_OPEN_SCOPE; + } +#endif + + /* + * For name creation opcodes, the full namepath prefix must + * exist, except for the final (new) nameseg. + */ + if (WalkState->OpInfo->Flags & AML_NAMED) + { + Flags |= ACPI_NS_PREFIX_MUST_EXIST; + } + + /* 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 (WalkState->ScopeInfo, + BufferPtr, Status); + return_ACPI_STATUS (Status); + } + + if (!Op) + { + /* Create a new op */ + + Op = AcpiPsAllocOp (WalkState->Opcode, WalkState->Aml); + 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; + UINT32 i; + UINT8 RegionSpace; +#ifdef ACPI_EXEC_APP + ACPI_OPERAND_OBJECT *ObjDesc; + char *Namepath; +#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) + { + + 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); + if ACPI_FAILURE (Status) + { + ACPI_EXCEPTION ((AE_INFO, Status, "CreateBufferField failure")); + goto Cleanup; + } + 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_RESOURCE_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; + + case AML_TYPE_NAMED_COMPLEX: + + switch (Op->Common.AmlOpcode) + { + 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_ACPI_STATUS (Status); + } + } + + Status = AcpiEvInitializeRegion ( + AcpiNsGetAttachedObject (Node)); + break; + + case AML_NAME_OP: + + Status = AcpiDsCreateNode (WalkState, Node, Op); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + +#ifdef ACPI_EXEC_APP + /* + * AcpiExec support for namespace initialization file (initialize + * Name opcodes in this code.) + */ + Namepath = AcpiNsGetExternalPathname (Node); + Status = AeLookupInitFileEntry (Namepath, &ObjDesc); + if (ACPI_SUCCESS (Status)) + { + /* Detach any existing object, attach new object */ + + if (Node->Object) + { + AcpiNsDetachObject (Node); + } + AcpiNsAttachObject (Node, ObjDesc, ObjDesc->Common.Type); + } + ACPI_FREE (Namepath); + Status = AE_OK; +#endif + 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; + + + 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 (WalkState->ScopeInfo, + 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/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswscope.c b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswscope.c new file mode 100644 index 0000000..9dd6d7b --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswscope.c @@ -0,0 +1,203 @@ +/****************************************************************************** + * + * Module Name: dswscope - Scope stack manipulation + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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, ACPI_NAMESPACE_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, "%s\n", ACPI_NAMESPACE_ROOT)); + } + + AcpiUtDeleteGenericState (ScopeInfo); + return_ACPI_STATUS (AE_OK); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswstate.c b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswstate.c new file mode 100644 index 0000000..9cfa434 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/dispatcher/dswstate.c @@ -0,0 +1,817 @@ +/****************************************************************************** + * + * Module Name: dswstate - Dispatcher parse tree walk management routines + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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! State=%p Num=%u", + 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 */ + +#ifndef 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 = + WalkState->ParserState.AmlEnd = + WalkState->ParserState.PkgEnd = AmlStart; + /* Avoid undefined behavior: applying zero offset to null pointer */ + if (AmlLength != 0) { + WalkState->ParserState.AmlEnd += AmlLength; + WalkState->ParserState.PkgEnd += 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_VOID; + } + + if (WalkState->DescriptorType != ACPI_DESC_TYPE_WALK) + { + ACPI_ERROR ((AE_INFO, "%p is not a valid walk state", + WalkState)); + return_VOID; + } + + /* 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/code/drivers/platform/acpi/third_party/acpica/components/events/evevent.c b/code/drivers/platform/acpi/third_party/acpica/components/events/evevent.c new file mode 100644 index 0000000..b42bc78 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/events/evevent.c @@ -0,0 +1,311 @@ +/****************************************************************************** + * + * Module Name: evevent - Fixed Event handling and dispatch + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 + * disable all of 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_STATUS Status; + + + ACPI_FUNCTION_NAME (EvFixedEventDetect); + + + /* + * Read the fixed feature status and enable registers, as all the cases + * depend on their values. Ignore errors here. + */ + Status = AcpiHwRegisterRead (ACPI_REGISTER_PM1_STATUS, &FixedStatus); + Status |= AcpiHwRegisterRead (ACPI_REGISTER_PM1_ENABLE, &FixedEnable); + if (ACPI_FAILURE (Status)) + { + return (IntStatus); + } + + 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. + * NOTE: If there is no handler for the event, the event is + * disabled to prevent further interrupts. + * + ******************************************************************************/ + +static UINT32 +AcpiEvFixedEventDispatch ( + UINT32 Event) +{ + + ACPI_FUNCTION_ENTRY (); + + + /* Clear the status bit */ + + (void) AcpiWriteBitRegister ( + AcpiGbl_FixedEventInfo[Event].StatusRegisterId, + ACPI_CLEAR_STATUS); + + /* + * Make sure that a handler exists. If not, report an error + * and disable the event to prevent further interrupts. + */ + if (!AcpiGbl_FixedEventHandlers[Event].Handler) + { + (void) AcpiWriteBitRegister ( + AcpiGbl_FixedEventInfo[Event].EnableRegisterId, + ACPI_DISABLE_EVENT); + + ACPI_ERROR ((AE_INFO, + "No installed handler for fixed event - %s (%u), disabling", + AcpiUtGetEventName (Event), 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/code/drivers/platform/acpi/third_party/acpica/components/events/evglock.c b/code/drivers/platform/acpi/third_party/acpica/components/events/evglock.c new file mode 100644 index 0000000..8db3d3b --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/events/evglock.c @@ -0,0 +1,354 @@ +/****************************************************************************** + * + * Module Name: evglock - Global Lock support + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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); + } + + if (!AcpiGbl_UseGlobalLock) + { + 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); + + AcpiOsDeleteLock (AcpiGbl_GlobalLockPendingLock); + 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/code/drivers/platform/acpi/third_party/acpica/components/events/evgpe.c b/code/drivers/platform/acpi/third_party/acpica/components/events/evgpe.c new file mode 100644 index 0000000..f64bc02 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/events/evgpe.c @@ -0,0 +1,1034 @@ +/****************************************************************************** + * + * Module Name: evgpe - General Purpose Event handling and dispatch + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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); + + /* 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); + } + + GpeRegisterInfo->EnableMask = GpeRegisterInfo->EnableForRun; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvEnableGpe + * + * PARAMETERS: GpeEventInfo - GPE to enable + * + * RETURN: Status + * + * DESCRIPTION: Enable a GPE. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvEnableGpe ( + ACPI_GPE_EVENT_INFO *GpeEventInfo) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvEnableGpe); + + + /* Enable the requested GPE */ + + Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvMaskGpe + * + * PARAMETERS: GpeEventInfo - GPE to be blocked/unblocked + * IsMasked - Whether the GPE is masked or not + * + * RETURN: Status + * + * DESCRIPTION: Unconditionally mask/unmask a GPE during runtime. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvMaskGpe ( + ACPI_GPE_EVENT_INFO *GpeEventInfo, + BOOLEAN IsMasked) +{ + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; + UINT32 RegisterBit; + + + ACPI_FUNCTION_TRACE (EvMaskGpe); + + + GpeRegisterInfo = GpeEventInfo->RegisterInfo; + if (!GpeRegisterInfo) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); + + /* Perform the action */ + + if (IsMasked) + { + if (RegisterBit & GpeRegisterInfo->MaskForRun) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); + ACPI_SET_BIT (GpeRegisterInfo->MaskForRun, (UINT8) RegisterBit); + } + else + { + if (!(RegisterBit & GpeRegisterInfo->MaskForRun)) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + ACPI_CLEAR_BIT (GpeRegisterInfo->MaskForRun, (UINT8) RegisterBit); + if (GpeEventInfo->RuntimeCount && + !GpeEventInfo->DisableForDispatch) + { + (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE); + } + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvAddGpeReference + * + * PARAMETERS: GpeEventInfo - Add a reference to this GPE + * ClearOnEnable - Clear GPE status before enabling it + * + * 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, + BOOLEAN ClearOnEnable) +{ + 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 */ + + if (ClearOnEnable) + { + (void) AcpiHwClearGpe (GpeEventInfo); + } + + 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_GPE_BLOCK_INFO *GpeBlock; + ACPI_NAMESPACE_NODE *GpeDevice; + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; + ACPI_GPE_EVENT_INFO *GpeEventInfo; + UINT32 GpeNumber; + UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; + 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) + { + GpeDevice = GpeBlock->Node; + + /* + * 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)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, + "Ignore disabled registers for GPE %02X-%02X: " + "RunEnable=%02X, WakeEnable=%02X\n", + GpeRegisterInfo->BaseGpeNumber, + GpeRegisterInfo->BaseGpeNumber + (ACPI_GPE_REGISTER_WIDTH - 1), + GpeRegisterInfo->EnableForRun, + GpeRegisterInfo->EnableForWake)); + continue; + } + + /* Now look at the individual GPEs in this byte register */ + + for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) + { + /* Detect and dispatch one GPE bit */ + + GpeEventInfo = &GpeBlock->EventInfo[((ACPI_SIZE) i * + ACPI_GPE_REGISTER_WIDTH) + j]; + GpeNumber = j + GpeRegisterInfo->BaseGpeNumber; + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + IntStatus |= AcpiEvDetectGpe ( + GpeDevice, GpeEventInfo, GpeNumber); + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + } + } + + GpeBlock = GpeBlock->Next; + } + + 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 = AE_OK; + ACPI_EVALUATE_INFO *Info; + ACPI_GPE_NOTIFY_INFO *Notify; + + + ACPI_FUNCTION_TRACE (EvAsynchExecuteGpeMethod); + + + /* Do the correct dispatch - normal method or implicit notify */ + + switch (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags)) + { + 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. + * + * June 2012: Expand implicit notify mechanism to support + * notifies on multiple device objects. + */ + Notify = GpeEventInfo->Dispatch.NotifyList; + while (ACPI_SUCCESS (Status) && Notify) + { + Status = AcpiEvQueueNotifyRequest ( + Notify->DeviceNode, ACPI_NOTIFY_DEVICE_WAKE); + + Notify = Notify->Next; + } + break; + + case ACPI_GPE_DISPATCH_METHOD: + + /* + * Re-check dispatch type. The table may have been unloaded + * and its GPE dispatch cleared while we were waiting. + */ + if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != + ACPI_GPE_DISPATCH_METHOD) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EVENTS, + "GPE method dispatch cleared during wait\n")); + goto ErrorExit; + } + + /* 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 = GpeEventInfo->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 (GpeEventInfo->Dispatch.MethodNode))); + } + break; + + default: + + goto ErrorExit; /* Should never happen */ + } + + /* Defer enabling of GPE until all notify handlers are done */ + + Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, + AcpiEvAsynchEnableGpe, GpeEventInfo); + if (ACPI_SUCCESS (Status)) + { + return_VOID; + } + +ErrorExit: + AcpiEvAsynchEnableGpe (GpeEventInfo); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvClearGpeDispatchByOwner + * + * PARAMETERS: OwnerId - Table OwnerId being unloaded + * + * RETURN: Status + * + * DESCRIPTION: Clear GPE dispatch info for methods belonging to the table + * being unloaded. If any matching GPE is currently dispatching, + * it is not cleared and AE_ABORT_METHOD is returned. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvClearGpeDispatchByOwner ( + ACPI_OWNER_ID OwnerId) +{ + ACPI_GPE_XRUPT_INFO *GpeXruptInfo; + ACPI_GPE_BLOCK_INFO *GpeBlock; + ACPI_GPE_EVENT_INFO *GpeEventInfo; + UINT32 GpeNumber; + ACPI_CPU_FLAGS Flags; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE_U32 (EvClearGpeDispatchByOwner, OwnerId); + + + if (OwnerId == 0) + { + return_ACPI_STATUS (AE_OK); + } + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* Walk all GPE interrupt blocks */ + + GpeXruptInfo = AcpiGbl_GpeXruptListHead; + while (GpeXruptInfo) + { + GpeBlock = GpeXruptInfo->GpeBlockListHead; + while (GpeBlock) + { + /* Walk all GPEs in this block */ + + for (GpeNumber = 0; GpeNumber < GpeBlock->GpeCount; GpeNumber++) + { + GpeEventInfo = &GpeBlock->EventInfo[GpeNumber]; + + if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == + ACPI_GPE_DISPATCH_METHOD) && + (GpeEventInfo->Dispatch.MethodNode) && + (GpeEventInfo->Dispatch.MethodNode->OwnerId == OwnerId)) + { + /* GPE method belongs to table being unloaded */ + + if (GpeEventInfo->DisableForDispatch) + { + /* Handler is executing, cannot clear */ + Status = AE_ABORT_METHOD; + } + else + { + /* Clear only the dispatch type, preserve other flags */ + GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK; + GpeEventInfo->Dispatch.MethodNode = NULL; + + /* + * Hardware-disable the GPE so a late interrupt + * cannot fire and land in the "no handler" default + * branch with DisableForDispatch stuck at TRUE. + */ + (void) AcpiHwLowSetGpe ( + GpeEventInfo, ACPI_GPE_DISABLE); + } + } + } + + GpeBlock = GpeBlock->Next; + } + + GpeXruptInfo = GpeXruptInfo->Next; + } + + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * 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; + ACPI_CPU_FLAGS Flags; + + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + (void) AcpiEvFinishGpe (GpeEventInfo); + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + + 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 EnableMask bit is set + * in the EventInfo. + */ + (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE); + GpeEventInfo->DisableForDispatch = FALSE; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvDetectGpe + * + * 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: Detect and dispatch a General Purpose Event to either a function + * (e.g. EC) or method (e.g. _Lxx/_Exx) handler. + * NOTE: GPE is W1C, so it is possible to handle a single GPE from both + * task and irq context in parallel as long as the process to + * detect and mask the GPE is atomic. + * However the atomicity of ACPI_GPE_DISPATCH_RAW_HANDLER is + * dependent on the raw handler itself. + * + ******************************************************************************/ + +UINT32 +AcpiEvDetectGpe ( + ACPI_NAMESPACE_NODE *GpeDevice, + ACPI_GPE_EVENT_INFO *GpeEventInfo, + UINT32 GpeNumber) +{ + UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; + UINT8 EnabledStatusByte; + UINT64 StatusReg; + UINT64 EnableReg; + UINT32 RegisterBit; + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; + ACPI_GPE_HANDLER_INFO *GpeHandlerInfo; + ACPI_CPU_FLAGS Flags; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvGpeDetect); + + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + if (!GpeEventInfo) + { + GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); + if (!GpeEventInfo) + { + goto ErrorExit; + } + } + + /* Get the info block for the entire GPE register */ + + GpeRegisterInfo = GpeEventInfo->RegisterInfo; + + /* Get the register bitmask for this GPE */ + + RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); + + /* GPE currently enabled (enable bit == 1)? */ + + Status = AcpiHwRead (&EnableReg, &GpeRegisterInfo->EnableAddress); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + + /* GPE currently active (status bit == 1)? */ + + Status = AcpiHwRead (&StatusReg, &GpeRegisterInfo->StatusAddress); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + + /* Check if there is anything active at all in this GPE */ + + ACPI_DEBUG_PRINT ((ACPI_DB_INTERRUPTS, + "Read registers for GPE %02X: Status=%02X, Enable=%02X, " + "RunEnable=%02X, WakeEnable=%02X\n", + GpeNumber, + (UINT32) (StatusReg & RegisterBit), + (UINT32) (EnableReg & RegisterBit), + GpeRegisterInfo->EnableForRun, + GpeRegisterInfo->EnableForWake)); + + EnabledStatusByte = (UINT8) (StatusReg & EnableReg); + if (!(EnabledStatusByte & RegisterBit)) + { + goto ErrorExit; + } + + /* Invoke global event handler if present */ + + AcpiGpeCount++; + if (AcpiGbl_GlobalEventHandler) + { + AcpiGbl_GlobalEventHandler (ACPI_EVENT_TYPE_GPE, + GpeDevice, GpeNumber, + AcpiGbl_GlobalEventHandlerContext); + } + + /* Found an active GPE */ + + if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == + ACPI_GPE_DISPATCH_RAW_HANDLER) + { + /* Dispatch the event to a raw handler */ + + GpeHandlerInfo = GpeEventInfo->Dispatch.Handler; + + /* + * There is no protection around the namespace node + * and the GPE handler to ensure a safe destruction + * because: + * 1. The namespace node is expected to always + * exist after loading a table. + * 2. The GPE handler is expected to be flushed by + * AcpiOsWaitEventsComplete() before the + * destruction. + */ + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + IntStatus |= GpeHandlerInfo->Address ( + GpeDevice, GpeNumber, GpeHandlerInfo->Context); + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + } + else + { + /* Dispatch the event to a standard handler or method. */ + + IntStatus |= AcpiEvGpeDispatch (GpeDevice, + GpeEventInfo, GpeNumber); + } + +ErrorExit: + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return (IntStatus); +} + + +/******************************************************************************* + * + * 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. + * + ******************************************************************************/ + +UINT32 +AcpiEvGpeDispatch ( + ACPI_NAMESPACE_NODE *GpeDevice, + ACPI_GPE_EVENT_INFO *GpeEventInfo, + UINT32 GpeNumber) +{ + ACPI_STATUS Status; + UINT32 ReturnValue; + + + ACPI_FUNCTION_TRACE (EvGpeDispatch); + + + /* + * 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); + } + + /* + * 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)); + (void) AcpiHwLowSetGpe ( + GpeEventInfo, ACPI_GPE_CONDITIONAL_ENABLE); + return_UINT32 (ACPI_INTERRUPT_NOT_HANDLED); + } + } + + GpeEventInfo->DisableForDispatch = TRUE; + + /* + * 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 (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags)) + { + 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 re-enable 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/code/drivers/platform/acpi/third_party/acpica/components/events/evgpeblk.c b/code/drivers/platform/acpi/third_party/acpica/components/events/evgpeblk.c new file mode 100644 index 0000000..f78ffc8 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/events/evgpeblk.c @@ -0,0 +1,539 @@ +/****************************************************************************** + * + * Module Name: evgpeblk - GPE block creation and initialization. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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); + } + + Status = AcpiEvGetGpeXruptBlock (InterruptNumber, &GpeXruptBlock); + if (ACPI_FAILURE (Status)) + { + 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: + (void) 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 (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + 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 = (UINT16) + (GpeBlock->BlockBaseNumber + (i * ACPI_GPE_REGISTER_WIDTH)); + + ThisRegister->StatusAddress.Address = + GpeBlock->Address + i; + + ThisRegister->EnableAddress.Address = + GpeBlock->Address + i + GpeBlock->RegisterCount; + + ThisRegister->StatusAddress.SpaceId = GpeBlock->SpaceId; + ThisRegister->EnableAddress.SpaceId = GpeBlock->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, + UINT64 Address, + UINT8 SpaceId, + UINT32 RegisterCount, + UINT16 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->Address = Address; + GpeBlock->SpaceId = SpaceId; + GpeBlock->Node = GpeDevice; + GpeBlock->GpeCount = (UINT16) (RegisterCount * ACPI_GPE_REGISTER_WIDTH); + GpeBlock->Initialized = FALSE; + GpeBlock->RegisterCount = RegisterCount; + GpeBlock->BlockBaseNumber = GpeBlockBaseNumber; + + /* + * 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->RegisterInfo); + ACPI_FREE (GpeBlock->EventInfo); + 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; + + (void) 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_RAW ((ACPI_DB_INIT, + " Initialized GPE %02X to %02X [%4.4s] %u regs on interrupt 0x%X%s\n", + (UINT32) GpeBlock->BlockBaseNumber, + (UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1)), + GpeDevice->Name.Ascii, GpeBlock->RegisterCount, InterruptNumber, + InterruptNumber == AcpiGbl_FADT.SciInterrupt ? " (SCI)" : "")); + + /* 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 *Context) +{ + ACPI_STATUS Status; + ACPI_GPE_EVENT_INFO *GpeEventInfo; + UINT32 GpeEnabledCount; + UINT32 GpeIndex; + UINT32 i; + UINT32 j; + BOOLEAN *IsPollingNeeded = Context; + ACPI_ERROR_ONLY (UINT32 GpeNumber); + + + 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]; + ACPI_ERROR_ONLY(GpeNumber = GpeBlock->BlockBaseNumber + GpeIndex); + GpeEventInfo->Flags |= ACPI_GPE_INITIALIZED; + + /* + * Ignore GPEs that have no corresponding _Lxx/_Exx method + * and GPEs that are used to wake the system + */ + if ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != ACPI_GPE_DISPATCH_METHOD) || + (GpeEventInfo->Flags & ACPI_GPE_CAN_WAKE)) + { + continue; + } + + Status = AcpiEvAddGpeReference (GpeEventInfo, FALSE); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not enable GPE 0x%02X", + GpeNumber)); + continue; + } + + GpeEventInfo->Flags |= ACPI_GPE_AUTO_ENABLED; + + if (IsPollingNeeded && + ACPI_GPE_IS_POLLING_NEEDED (GpeEventInfo)) + { + *IsPollingNeeded = TRUE; + } + + GpeEnabledCount++; + } + } + + if (GpeEnabledCount) + { + ACPI_INFO (( + "Enabled %u GPEs in block %02X to %02X", GpeEnabledCount, + (UINT32) GpeBlock->BlockBaseNumber, + (UINT32) (GpeBlock->BlockBaseNumber + (GpeBlock->GpeCount - 1)))); + } + + GpeBlock->Initialized = TRUE; + return_ACPI_STATUS (AE_OK); +} + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/code/drivers/platform/acpi/third_party/acpica/components/events/evgpeinit.c b/code/drivers/platform/acpi/third_party/acpica/components/events/evgpeinit.c new file mode 100644 index 0000000..e722501 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/events/evgpeinit.c @@ -0,0 +1,437 @@ +/****************************************************************************** + * + * Module Name: evgpeinit - System GPE initialization and update + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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); + + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, + "Initializing General Purpose Events (GPEs):\n")); + + 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.Address, + AcpiGbl_FADT.XGpe0Block.SpaceId, + 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.Address, + AcpiGbl_FADT.XGpe1Block.SpaceId, + 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. + */ + } + } + + /* 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")); + 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 (("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; + ACPI_STATUS Status; + UINT32 GpeNumber; + UINT8 TempGpeNumber; + char Name[ACPI_NAMESEG_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_NAMESEG_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 */ + + Status = AcpiUtAsciiToHexByte (&Name[2], &TempGpeNumber); + if (ACPI_FAILURE (Status)) + { + /* 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 */ + + GpeNumber = (UINT32) TempGpeNumber; + 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 ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == + ACPI_GPE_DISPATCH_HANDLER) || + (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == + ACPI_GPE_DISPATCH_RAW_HANDLER)) + { + /* If there is already a handler, ignore this GPE method */ + + return_ACPI_STATUS (AE_OK); + } + + if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == + 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); + } + + /* Disable the GPE in case it's been enabled already. */ + + (void) AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); + + /* + * 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; + WalkInfo->Count++; + + 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/code/drivers/platform/acpi/third_party/acpica/components/events/evgpeutil.c b/code/drivers/platform/acpi/third_party/acpica/components/events/evgpeutil.c new file mode 100644 index 0000000..fc28a91 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/events/evgpeutil.c @@ -0,0 +1,368 @@ +/****************************************************************************** + * + * Module Name: evgpeutil - GPE utilities + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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: 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 + * GpeXruptBlock - Where the block is returned + * + * RETURN: Status + * + * 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_STATUS +AcpiEvGetGpeXruptBlock ( + UINT32 InterruptNumber, + ACPI_GPE_XRUPT_INFO **GpeXruptBlock) +{ + 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) + { + *GpeXruptBlock = NextGpeXrupt; + return_ACPI_STATUS (AE_OK); + } + + NextGpeXrupt = NextGpeXrupt->Next; + } + + /* Not found, must allocate a new xrupt descriptor */ + + GpeXrupt = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_XRUPT_INFO)); + if (!GpeXrupt) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + 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_EXCEPTION ((AE_INFO, Status, + "Could not install GPE interrupt handler at level 0x%X", + InterruptNumber)); + return_ACPI_STATUS (Status); + } + } + + *GpeXruptBlock = GpeXrupt; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * 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; + ACPI_GPE_NOTIFY_INFO *Notify; + ACPI_GPE_NOTIFY_INFO *Next; + 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 ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == + ACPI_GPE_DISPATCH_HANDLER) || + (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == + ACPI_GPE_DISPATCH_RAW_HANDLER)) + { + /* Delete an installed handler block */ + + ACPI_FREE (GpeEventInfo->Dispatch.Handler); + GpeEventInfo->Dispatch.Handler = NULL; + GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK; + } + else if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == + ACPI_GPE_DISPATCH_NOTIFY) + { + /* Delete the implicit notification device list */ + + Notify = GpeEventInfo->Dispatch.NotifyList; + while (Notify) + { + Next = Notify->Next; + ACPI_FREE (Notify); + Notify = Next; + } + + GpeEventInfo->Dispatch.NotifyList = NULL; + GpeEventInfo->Flags &= ~ACPI_GPE_DISPATCH_MASK; + } + } + } + + return_ACPI_STATUS (AE_OK); +} + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/code/drivers/platform/acpi/third_party/acpica/components/events/evhandler.c b/code/drivers/platform/acpi/third_party/acpica/components/events/evhandler.c new file mode 100644 index 0000000..37629f1 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/events/evhandler.c @@ -0,0 +1,595 @@ +/****************************************************************************** + * + * Module Name: evhandler - Support for Address Space handlers + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" +#include "acnamesp.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evhandler") + + +/* Local prototypes */ + +static ACPI_STATUS +AcpiEvInstallHandler ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + + +/* These are the address spaces that will get default handlers */ + +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. + * + ******************************************************************************/ + +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->CommonNotify.Handler; + + /* Walk the linked list of handlers for this object */ + + while (HandlerObj) + { + /* Validate handler object type before accessing fields */ + + if (HandlerObj->Common.Type != ACPI_TYPE_LOCAL_ADDRESS_HANDLER) + { + break; + } + + if (HandlerObj->AddressSpace.SpaceId == SpaceId) + { + if (HandlerObj->AddressSpace.HandlerFlags & + ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) + { + return (TRUE); + } + } + + HandlerObj = HandlerObj->AddressSpace.Next; + } + } + + return (FALSE); +} + + +/******************************************************************************* + * + * 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 = AcpiEvFindRegionHandler ( + HandlerObj->AddressSpace.SpaceId, ObjDesc->CommonNotify.Handler); + if (NextHandlerObj) + { + /* Found a handler, is it for the same address space? */ + + 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); + } + + /* + * 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: AcpiEvFindRegionHandler + * + * PARAMETERS: SpaceId - The address space ID + * HandlerObj - Head of the handler object list + * + * RETURN: Matching handler object. NULL if space ID not matched + * + * DESCRIPTION: Search a handler object list for a match on the address + * space ID. + * + ******************************************************************************/ + +ACPI_OPERAND_OBJECT * +AcpiEvFindRegionHandler ( + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_OPERAND_OBJECT *HandlerObj) +{ + + /* Walk the handler list for this device */ + + while (HandlerObj) + { + if (HandlerObj->Common.Type != ACPI_TYPE_LOCAL_ADDRESS_HANDLER) + { + break; + } + + /* Same SpaceId indicates a handler is installed */ + + if (HandlerObj->AddressSpace.SpaceId == SpaceId) + { + return (HandlerObj); + } + + /* Next handler object */ + + HandlerObj = HandlerObj->AddressSpace.Next; + } + + return (NULL); +} + + +/******************************************************************************* + * + * 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 = AE_OK; + ACPI_OBJECT_TYPE Type; + UINT8 Flags = 0; + + + ACPI_FUNCTION_TRACE (EvInstallSpaceHandler); + + + /* + * This registration is valid for only the types below and the root. + * The root node is where the default handlers get installed. + */ + 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 = AcpiEvDataTableRegionSetup; + 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. Now make sure + * the handler is not already installed. + */ + HandlerObj = AcpiEvFindRegionHandler (SpaceId, + ObjDesc->CommonNotify.Handler); + + if (HandlerObj) + { + 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; + } + } + 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 */ + + Status = AcpiOsCreateMutex (&HandlerObj->AddressSpace.ContextMutex); + if (ACPI_FAILURE (Status)) + { + AcpiUtRemoveReference (HandlerObj); + goto UnlockAndExit; + } + + 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->CommonNotify.Handler; + + /* + * The Device object is the first reference on the HandlerObj. + * Each region that uses the handler adds a reference. + */ + ObjDesc->CommonNotify.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); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/events/evmisc.c b/code/drivers/platform/acpi/third_party/acpica/components/events/evmisc.c new file mode 100644 index 0000000..d96558a --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/events/evmisc.c @@ -0,0 +1,346 @@ +/****************************************************************************** + * + * Module Name: evmisc - Miscellaneous event manager support functions + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 *HandlerListHead = NULL; + ACPI_GENERIC_STATE *Info; + UINT8 HandlerListId = 0; + ACPI_STATUS Status = AE_OK; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_NAME (EvQueueNotifyRequest); + + + /* Are Notifies allowed on this object? */ + + if (!AcpiEvIsNotifyObject (Node)) + { + return (AE_TYPE); + } + + /* Get the correct notify list type (System or Device) */ + + if (NotifyValue <= ACPI_MAX_SYS_NOTIFY) + { + HandlerListId = ACPI_SYSTEM_HANDLER_LIST; + } + else + { + HandlerListId = ACPI_DEVICE_HANDLER_LIST; + } + + /* Get the notify object attached to the namespace Node */ + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (ObjDesc) + { + /* We have an attached object, Get the correct handler list */ + + HandlerListHead = ObjDesc->CommonNotify.NotifyList[HandlerListId]; + } + + /* + * If there is no notify handler (Global or Local) + * for this object, just ignore the notify + */ + if (!AcpiGbl_GlobalNotify[HandlerListId].Handler && !HandlerListHead) + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "No notify handler for Notify, ignoring (%4.4s, %X) node %p\n", + AcpiUtGetNodeName (Node), NotifyValue, Node)); + + return (AE_OK); + } + + /* Setup notify info and schedule the notify dispatcher */ + + Info = AcpiUtCreateGenericState (); + if (!Info) + { + return (AE_NO_MEMORY); + } + + Info->Common.DescriptorType = ACPI_DESC_TYPE_STATE_NOTIFY; + + Info->Notify.Node = Node; + Info->Notify.Value = (UINT16) NotifyValue; + Info->Notify.HandlerListId = HandlerListId; + Info->Notify.HandlerListHead = HandlerListHead; + Info->Notify.Global = &AcpiGbl_GlobalNotify[HandlerListId]; + Info->Notify.OwnerId = Node->OwnerId; + + 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, ACPI_TYPE_ANY), Node)); + + if (Node->OwnerId > 0 && Node->OwnerId < ACPI_NOTIFY_COUNT_MAX_OWNER) + { + Flags = AcpiOsAcquireLock (AcpiGbl_NotifyLock); + + /* Reject if table is being unloaded — avoid use-after-free of Node */ + + if (AcpiGbl_NotifyUnloading[Node->OwnerId]) + { + AcpiOsReleaseLock (AcpiGbl_NotifyLock, Flags); + AcpiUtDeleteGenericState (Info); + return (AE_OK); + } + + AcpiGbl_NotifyExecuteCount[Node->OwnerId]++; + AcpiOsReleaseLock (AcpiGbl_NotifyLock, Flags); + } + + Status = AcpiOsExecute (OSL_NOTIFY_HANDLER, + AcpiEvNotifyDispatch, Info); + if (ACPI_FAILURE (Status)) + { + if (Node->OwnerId > 0 && Node->OwnerId < ACPI_NOTIFY_COUNT_MAX_OWNER) + { + Flags = AcpiOsAcquireLock (AcpiGbl_NotifyLock); + AcpiGbl_NotifyExecuteCount[Node->OwnerId]--; + AcpiOsReleaseLock (AcpiGbl_NotifyLock, Flags); + } + AcpiUtDeleteGenericState (Info); + } + + 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 *Info = (ACPI_GENERIC_STATE *) Context; + ACPI_OPERAND_OBJECT *HandlerObj; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_ENTRY (); + + + /* Invoke a global notify handler if installed */ + + if (Info->Notify.Global->Handler) + { + Info->Notify.Global->Handler (Info->Notify.Node, + Info->Notify.Value, + Info->Notify.Global->Context); + } + + /* Now invoke the local notify handler(s) if any are installed */ + + HandlerObj = Info->Notify.HandlerListHead; + while (HandlerObj) + { + HandlerObj->Notify.Handler (Info->Notify.Node, + Info->Notify.Value, + HandlerObj->Notify.Context); + + HandlerObj = HandlerObj->Notify.Next[Info->Notify.HandlerListId]; + } + + /* All done with the info object */ + + if (Info->Notify.OwnerId > 0 && Info->Notify.OwnerId < ACPI_NOTIFY_COUNT_MAX_OWNER) + { + Flags = AcpiOsAcquireLock (AcpiGbl_NotifyLock); + AcpiGbl_NotifyExecuteCount[Info->Notify.OwnerId]--; + AcpiOsReleaseLock (AcpiGbl_NotifyLock, Flags); + } + + AcpiUtDeleteGenericState (Info); +} + + +#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); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not disable GPEs in GPE block")); + } + + Status = AcpiEvRemoveGlobalLockHandler (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not remove Global Lock handler")); + } + + AcpiGbl_EventsInitialized = FALSE; + } + + /* Remove SCI handlers */ + + Status = AcpiEvRemoveAllSciHandlers (); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, + "Could not remove SCI handler")); + } + + /* Deallocate all handler objects installed within GPE info structs */ + + Status = AcpiEvWalkGpeList (AcpiEvDeleteGpeHandlers, NULL); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not delete GPE handlers")); + } + + + /* 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/code/drivers/platform/acpi/third_party/acpica/components/events/evregion.c b/code/drivers/platform/acpi/third_party/acpica/components/events/evregion.c new file mode 100644 index 0000000..a08ff6d --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/events/evregion.c @@ -0,0 +1,946 @@ +/****************************************************************************** + * + * Module Name: evregion - Operation Region support + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" +#include "acnamesp.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evregion") + + +extern UINT8 AcpiGbl_DefaultAddressSpaces[]; + +/* Local prototypes */ + +static void +AcpiEvExecuteOrphanRegMethod ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_ADR_SPACE_TYPE SpaceId); + + +static ACPI_STATUS +AcpiEvRegRun ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + + +/******************************************************************************* + * + * 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])) + { + AcpiEvExecuteRegMethods (AcpiGbl_RootNode, + AcpiGbl_DefaultAddressSpaces[i], ACPI_REG_CONNECT); + } + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + 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. + * + * NOTE: During early initialization, we always install the default region + * handlers for Memory, I/O and PCI_Config. This ensures that these operation + * region address spaces are always available as per the ACPI specification. + * This is especially needed in order to support the execution of + * module-level AML code during loading of the ACPI tables. + * + ******************************************************************************/ + +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_MUTEX ContextMutex; + BOOLEAN ContextLocked; + ACPI_PHYSICAL_ADDRESS Address; + + + 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; + ContextMutex = HandlerDesc->AddressSpace.ContextMutex; + ContextLocked = FALSE; + + /* + * 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); + } + + if (FieldObj && RegionObj->Region.SpaceId == ACPI_ADR_SPACE_PLATFORM_COMM) + { + ACPI_PCC_INFO *Ctx = HandlerDesc->AddressSpace.Context; + + Ctx->InternalBuffer = FieldObj->Field.InternalPccBuffer; + Ctx->Length = (UINT16) RegionObj->Region.Length; + Ctx->SubspaceId = (UINT8) RegionObj->Region.Address; + } + + if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_FIXED_HARDWARE) + { + ACPI_FFH_INFO *Ctx = HandlerDesc->AddressSpace.Context; + + Ctx->Length = RegionObj->Region.Length; + Ctx->Offset = RegionObj->Region.Address; + } + + /* + * 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; + + /* + * Save the returned context for use in all accesses to + * the handler for this particular region + */ + if (!(RegionObj2->Extra.RegionContext)) + { + RegionObj2->Extra.RegionContext = RegionContext; + } + } + } + + /* We have everything we need, we can invoke the address space handler */ + + Handler = HandlerDesc->AddressSpace.Handler; + Address = (RegionObj->Region.Address + RegionOffset); + + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", + &RegionObj->Region.Handler->AddressSpace, Handler, + ACPI_FORMAT_UINT64 (Address), + AcpiUtGetRegionName (RegionObj->Region.SpaceId))); + + 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 interpreter. + */ + AcpiExExitInterpreter(); + } + + /* + * 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 + * + * Since we pass these extra parameters via the context, which is + * shared between threads, we must lock the context to avoid these + * parameters being changed from another thread before the handler + * has completed running. + * + * In addition, for GeneralPurposeIo, the Address and BitWidth fields + * are defined as follows: + * 1) Address is the pin number index of the field (bit offset from + * the previous Connection) + * 2) BitWidth is the actual bit length of the field (number of pins) + */ + if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || + RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO) && + Context && + FieldObj) + { + + Status = AcpiOsAcquireMutex (ContextMutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE (Status)) + { + goto ReEnterInterpreter; + } + + ContextLocked = TRUE; + + /* Get the Connection (ResourceTemplate) buffer */ + + Context->Connection = FieldObj->Field.ResourceBuffer; + Context->Length = FieldObj->Field.ResourceLength; + Context->AccessLength = FieldObj->Field.AccessLength; + + if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO) + { + Address = FieldObj->Field.PinNumberIndex; + BitWidth = FieldObj->Field.BitLength; + } + } + + /* Call the handler */ + + Status = Handler (Function, Address, BitWidth, Value, Context, + RegionObj2->Extra.RegionContext); + + if (ContextLocked) + { + AcpiOsReleaseMutex (ContextMutex); + } + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]", + AcpiUtGetRegionName (RegionObj->Region.SpaceId))); + + /* + * Special case for an EC timeout. These are seen so frequently + * that an additional error message is helpful + */ + if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_EC) && + (Status == AE_TIME)) + { + ACPI_ERROR ((AE_INFO, + "Timeout from EC hardware or EC device driver")); + } + } + +ReEnterInterpreter: + 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 *StartDesc; + 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; + StartDesc = ObjDesc; + 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); + + /* + * RegionContext should have been released by the deactivate + * operation. We don't need access to it anymore here. + */ + if (RegionContext) + { + *RegionContext = NULL; + } + + /* 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; + + /* Prevent infinite loop if list is corrupted */ + + if (ObjDesc == StartDesc) + { + ACPI_ERROR ((AE_INFO, + "Circular handler list in region object %p", + RegionObj)); + return_VOID; + } + } + + /* 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); + + + /* Install the region's handler */ + + if (RegionObj->Region.Handler) + { + return_ACPI_STATUS (AE_ALREADY_EXISTS); + } + + 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; + RegionObj->Region.Handler = HandlerObj; + AcpiUtAddReference (HandlerObj); + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * 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; + const ACPI_NAME *RegNamePtr = ACPI_CAST_PTR (ACPI_NAME, METHOD_NAME__REG); + ACPI_NAMESPACE_NODE *MethodNode; + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvExecuteRegMethod); + + + if (!AcpiGbl_NamespaceInitialized || + RegionObj->Region.Handler == NULL) + { + return_ACPI_STATUS (AE_OK); + } + + RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); + if (!RegionObj2) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + /* + * Find any "_REG" method associated with this region definition. + * The method should always be updated as this function may be + * invoked after a namespace change. + */ + Node = RegionObj->Region.Node->Parent; + 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; + } + if (RegionObj2->Extra.Method_REG == NULL) + { + return_ACPI_STATUS (AE_OK); + } + + /* _REG(DISCONNECT) should be paired with _REG(CONNECT) */ + + if ((Function == ACPI_REG_CONNECT && + RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED) || + (Function == ACPI_REG_DISCONNECT && + !(RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED))) + { + 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->RelativePathname = 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]); + + if (ACPI_FAILURE (Status)) + { + goto Cleanup2; + } + + if (Function == ACPI_REG_CONNECT) + { + RegionObj->Common.Flags |= AOPOBJ_REG_CONNECTED; + } + else + { + RegionObj->Common.Flags &= ~AOPOBJ_REG_CONNECTED; + } + +Cleanup2: + AcpiUtRemoveReference (Args[0]); + +Cleanup1: + ACPI_FREE (Info); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvExecuteRegMethods + * + * PARAMETERS: Node - Namespace node for the device + * SpaceId - The address space ID + * Function - Passed to _REG: On (1) or Off (0) + * + * RETURN: None + * + * DESCRIPTION: Run all _REG methods for the input Space ID; + * Note: assumes namespace is locked, or system init time. + * + ******************************************************************************/ + +void +AcpiEvExecuteRegMethods ( + ACPI_NAMESPACE_NODE *Node, + ACPI_ADR_SPACE_TYPE SpaceId, + UINT32 Function) +{ + ACPI_REG_WALK_INFO Info; + + + ACPI_FUNCTION_TRACE (EvExecuteRegMethods); + + /* + * These address spaces do not need a call to _REG, since the ACPI + * specification defines them as: "must always be accessible". Since + * they never change state (never become unavailable), no need to ever + * call _REG on them. Also, a DataTable is not a "real" address space, + * so do not call _REG. September 2018. + */ + if ((SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) || + (SpaceId == ACPI_ADR_SPACE_SYSTEM_IO) || + (SpaceId == ACPI_ADR_SPACE_DATA_TABLE)) + { + return_VOID; + } + + Info.SpaceId = SpaceId; + Info.Function = Function; + Info.RegRunCount = 0; + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES, + " Running _REG methods for SpaceId %s\n", + AcpiUtGetRegionName (Info.SpaceId))); + + /* + * 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) + */ + (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, + ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, &Info, NULL); + + /* + * Special case for EC and GPIO: handle "orphan" _REG methods with + * no region. + */ + if (SpaceId == ACPI_ADR_SPACE_EC || SpaceId == ACPI_ADR_SPACE_GPIO) + { + AcpiEvExecuteOrphanRegMethod (Node, SpaceId); + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES, + " Executed %u _REG methods for SpaceId %s\n", + Info.RegRunCount, AcpiUtGetRegionName (Info.SpaceId))); + + return_VOID; +} + + +/******************************************************************************* + * + * 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_STATUS Status; + ACPI_REG_WALK_INFO *Info; + + + Info = ACPI_CAST_PTR (ACPI_REG_WALK_INFO, 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 != Info->SpaceId) + { + /* This region is for a different address space, just ignore it */ + + return (AE_OK); + } + + Info->RegRunCount++; + Status = AcpiEvExecuteRegMethod (ObjDesc, Info->Function); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiEvExecuteOrphanRegMethod + * + * PARAMETERS: DeviceNode - Namespace node for an ACPI device + * SpaceId - The address space ID + * + * RETURN: None + * + * DESCRIPTION: Execute an "orphan" _REG method that appears under an ACPI + * device. This is a _REG method that has no corresponding region + * within the device's scope. ACPI tables depending on these + * "orphan" _REG methods have been seen for both EC and GPIO + * Operation Regions. Presumably the Windows ACPI implementation + * always calls the _REG method independent of the presence of + * an actual Operation Region with the correct address space ID. + * + * MUTEX: Assumes the namespace is locked + * + ******************************************************************************/ + +static void +AcpiEvExecuteOrphanRegMethod ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_ADR_SPACE_TYPE SpaceId) +{ + ACPI_HANDLE RegMethod; + ACPI_NAMESPACE_NODE *NextNode; + ACPI_STATUS Status; + ACPI_OBJECT_LIST Args; + ACPI_OBJECT Objects[2]; + + + ACPI_FUNCTION_TRACE (EvExecuteOrphanRegMethod); + + + if (!DeviceNode) + { + return_VOID; + } + + /* Namespace is currently locked, must release */ + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + + /* Get a handle to a _REG method immediately under the EC device */ + + Status = AcpiGetHandle (DeviceNode, METHOD_NAME__REG, &RegMethod); + if (ACPI_FAILURE (Status)) + { + goto Exit; /* There is no _REG method present */ + } + + /* + * 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 EmbeddedControl SpaceID argument. + */ + NextNode = AcpiNsGetNextNode (DeviceNode, NULL); + while (NextNode) + { + if ((NextNode->Type == ACPI_TYPE_REGION) && + (NextNode->Object) && + (NextNode->Object->Region.SpaceId == SpaceId)) + { + goto Exit; /* Do not execute the _REG */ + } + + NextNode = AcpiNsGetNextNode (DeviceNode, NextNode); + } + + /* Evaluate the _REG(SpaceId,Connect) method */ + + Args.Count = 2; + Args.Pointer = Objects; + Objects[0].Type = ACPI_TYPE_INTEGER; + Objects[0].Integer.Value = SpaceId; + Objects[1].Type = ACPI_TYPE_INTEGER; + Objects[1].Integer.Value = ACPI_REG_CONNECT; + + (void) AcpiEvaluateObject (RegMethod, NULL, &Args, NULL); + +Exit: + /* We ignore all errors from above, don't care */ + + (void) AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + return_VOID; +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/events/evrgnini.c b/code/drivers/platform/acpi/third_party/acpica/components/events/evrgnini.c new file mode 100644 index 0000000..9ebdad1 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/events/evrgnini.c @@ -0,0 +1,693 @@ +/****************************************************************************** + * + * Module Name: evrgnini- ACPI AddressSpace (OpRegion) init + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" +#include "acnamesp.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evrgnini") + + +/******************************************************************************* + * + * 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_MEM_MAPPING *Mm; + + + ACPI_FUNCTION_TRACE (EvSystemMemoryRegionSetup); + + + if (Function == ACPI_REGION_DEACTIVATE) + { + if (*RegionContext) + { + LocalRegionContext = (ACPI_MEM_SPACE_CONTEXT *) *RegionContext; + + /* Delete memory mappings if present */ + + while (LocalRegionContext->FirstMm) + { + Mm = LocalRegionContext->FirstMm; + LocalRegionContext->FirstMm = Mm->NextMm; + AcpiOsUnmapMemory(Mm->LogicalAddress, Mm->Length); + ACPI_FREE(Mm); + } + 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. + */ + } + 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. + * + ******************************************************************************/ + +BOOLEAN +AcpiEvIsPciRootBridge ( + ACPI_NAMESPACE_NODE *Node) +{ + ACPI_STATUS Status; + ACPI_PNP_DEVICE_ID *Hid; + ACPI_PNP_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: AcpiEvDataTableRegionSetup + * + * 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 DataTableRegion + * + * MUTEX: Assumes namespace is not locked + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvDataTableRegionSetup ( + ACPI_HANDLE Handle, + UINT32 Function, + void *HandlerContext, + void **RegionContext) +{ + ACPI_OPERAND_OBJECT *RegionDesc = (ACPI_OPERAND_OBJECT *) Handle; + ACPI_DATA_TABLE_MAPPING *LocalRegionContext; + + + ACPI_FUNCTION_TRACE (EvDataTableRegionSetup); + + + if (Function == ACPI_REGION_DEACTIVATE) + { + if (*RegionContext) + { + ACPI_FREE (*RegionContext); + *RegionContext = NULL; + } + return_ACPI_STATUS (AE_OK); + } + + /* Create a new context */ + + LocalRegionContext = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_DATA_TABLE_MAPPING)); + if (!(LocalRegionContext)) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Save the data table pointer for use in the handler */ + + LocalRegionContext->Pointer = RegionDesc->Region.Pointer; + + *RegionContext = LocalRegionContext; + 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 + * + * 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. + * + * NOTE: Possible incompliance: + * There is a behavior conflict in automatic _REG execution: + * 1. When the interpreter is evaluating a method, we can only + * automatically run _REG for the following case: + * Method(_REG, 2) {} + * OperationRegion (OPR1, 0x80, 0x1000010, 0x4) + * 2. When the interpreter is loading a table, we can also + * automatically run _REG for the following case: + * OperationRegion (OPR1, 0x80, 0x1000010, 0x4) + * Method(_REG, 2) {} + * Though this may not be compliant to the de-facto standard, the + * logic is kept in order not to trigger regressions. And keeping + * this logic should be taken care by the caller of this function. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEvInitializeRegion ( + ACPI_OPERAND_OBJECT *RegionObj) +{ + ACPI_OPERAND_OBJECT *HandlerObj; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_ADR_SPACE_TYPE SpaceId; + ACPI_NAMESPACE_NODE *Node; + + + ACPI_FUNCTION_TRACE (EvInitializeRegion); + + + if (!RegionObj) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (RegionObj->Common.Flags & AOPOBJ_OBJECT_INITIALIZED) + { + return_ACPI_STATUS (AE_OK); + } + + RegionObj->Common.Flags |= AOPOBJ_OBJECT_INITIALIZED; + + Node = RegionObj->Region.Node->Parent; + SpaceId = RegionObj->Region.SpaceId; + + /* + * The following loop depends upon the root Node having no parent + * ie: AcpiGbl_RootNode->Parent 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: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + + HandlerObj = ObjDesc->CommonNotify.Handler; + break; + + default: + + /* Ignore other objects */ + + break; + } + + HandlerObj = AcpiEvFindRegionHandler (SpaceId, HandlerObj); + if (HandlerObj) + { + /* Found correct handler */ + + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "Found handler %p for region %p in obj %p\n", + HandlerObj, RegionObj, ObjDesc)); + + (void) AcpiEvAttachRegion (HandlerObj, RegionObj, FALSE); + + /* + * Tell all users that this region is usable by + * running the _REG method + */ + AcpiExExitInterpreter (); + (void) AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_CONNECT); + AcpiExEnterInterpreter (); + return_ACPI_STATUS (AE_OK); + } + } + + /* 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. This is not + * fatal because many regions get created before a handler is installed + * for said region. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, + "No handler for RegionType %s(%X) (RegionObj %p)\n", + AcpiUtGetRegionName (SpaceId), SpaceId, RegionObj)); + + return_ACPI_STATUS (AE_OK); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/events/evsci.c b/code/drivers/platform/acpi/third_party/acpica/components/events/evsci.c new file mode 100644 index 0000000..709c817 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/events/evsci.c @@ -0,0 +1,391 @@ +/******************************************************************************* + * + * Module Name: evsci - System Control Interrupt configuration and + * legacy to ACPI mode state transition functions + * + ******************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + ***************************************************************************** + * + * Alternatively, you may choose to be licensed under the terms of the + * following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, you may choose to be licensed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + *****************************************************************************/ + +#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: AcpiEvSciDispatch + * + * PARAMETERS: None + * + * RETURN: Status code indicates whether interrupt was handled. + * + * DESCRIPTION: Dispatch the SCI to all host-installed SCI handlers. + * + ******************************************************************************/ + +UINT32 +AcpiEvSciDispatch ( + void) +{ + ACPI_SCI_HANDLER_INFO *SciHandler; + ACPI_CPU_FLAGS Flags; + UINT32 IntStatus = ACPI_INTERRUPT_NOT_HANDLED; + + + ACPI_FUNCTION_NAME (EvSciDispatch); + + + /* Are there any host-installed SCI handlers? */ + + if (!AcpiGbl_SciHandlerList) + { + return (IntStatus); + } + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* Invoke all host-installed SCI handlers */ + + SciHandler = AcpiGbl_SciHandlerList; + while (SciHandler) + { + /* Invoke the installed handler (at interrupt level) */ + + IntStatus |= SciHandler->Address ( + SciHandler->Context); + + SciHandler = SciHandler->Next; + } + + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return (IntStatus); +} + + +/******************************************************************************* + * + * 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 ACPICA 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); + + /* Invoke all host-installed SCI handlers */ + + InterruptHandled |= AcpiEvSciDispatch (); + + 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 ACPICA 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: AcpiEvRemoveAllSciHandlers + * + * PARAMETERS: none + * + * RETURN: AE_OK if handler uninstalled, AE_ERROR if handler was not + * installed to begin with + * + * DESCRIPTION: Remove the SCI interrupt handler. No further SCIs will be + * taken. Remove all host-installed SCI handlers. + * + * 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 +AcpiEvRemoveAllSciHandlers ( + void) +{ + ACPI_SCI_HANDLER_INFO *SciHandler; + ACPI_CPU_FLAGS Flags; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (EvRemoveAllSciHandlers); + + + /* Just let the OS remove the handler and disable the level */ + + Status = AcpiOsRemoveInterruptHandler ((UINT32) AcpiGbl_FADT.SciInterrupt, + AcpiEvSciXruptHandler); + + if (!AcpiGbl_SciHandlerList) + { + return (Status); + } + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* Free all host-installed SCI handlers */ + + while (AcpiGbl_SciHandlerList) + { + SciHandler = AcpiGbl_SciHandlerList; + AcpiGbl_SciHandlerList = SciHandler->Next; + ACPI_FREE (SciHandler); + } + + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return_ACPI_STATUS (Status); +} + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/code/drivers/platform/acpi/third_party/acpica/components/events/evxface.c b/code/drivers/platform/acpi/third_party/acpica/components/events/evxface.c new file mode 100644 index 0000000..b8e7fcc --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/events/evxface.c @@ -0,0 +1,1238 @@ +/****************************************************************************** + * + * Module Name: evxface - External interfaces for ACPI events + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acevents.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evxface") + +#if (!ACPI_REDUCED_HARDWARE) + +/* Local prototypes */ + +static ACPI_STATUS +AcpiEvInstallGpeHandler ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + UINT32 Type, + BOOLEAN IsRawHandler, + ACPI_GPE_HANDLER Address, + void *Context); + +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiInstallNotifyHandler + * + * PARAMETERS: Device - The device for which notifies will be handled + * HandlerType - The type of handler: + * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) + * ACPI_DEVICE_NOTIFY: Device Handler (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 notifications on an ACPI Device, + * ThermalZone, or Processor object. + * + * NOTES: The Root namespace object may have only one handler for each + * type of notify (System/Device). Device/Thermal/Processor objects + * may have one device notify handler, and multiple system notify + * handlers. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInstallNotifyHandler ( + ACPI_HANDLE Device, + UINT32 HandlerType, + ACPI_NOTIFY_HANDLER Handler, + void *Context) +{ + ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device); + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *HandlerObj; + ACPI_STATUS Status; + UINT32 i; + + + ACPI_FUNCTION_TRACE (AcpiInstallNotifyHandler); + + + /* Parameter validation */ + + if ((!Device) || (!Handler) || (!HandlerType) || + (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); + } + + /* + * 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 registered per notify type. + * Ensure that a handler is not already installed. + */ + if (Device == ACPI_ROOT_OBJECT) + { + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) + { + if (HandlerType & (i+1)) + { + if (AcpiGbl_GlobalNotify[i].Handler) + { + Status = AE_ALREADY_EXISTS; + goto UnlockAndExit; + } + + AcpiGbl_GlobalNotify[i].Handler = Handler; + AcpiGbl_GlobalNotify[i].Context = Context; + } + } + + goto UnlockAndExit; /* Global notify handler installed, all done */ + } + + /* + * All Other Objects: + * Caller will only receive notifications specific to the target + * object. Note that only certain object types are allowed to + * receive notifications. + */ + + /* Are Notifies allowed on this object? */ + + if (!AcpiEvIsNotifyObject (Node)) + { + Status = AE_TYPE; + goto UnlockAndExit; + } + + /* Check for an existing internal object, might not exist */ + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc) + { + /* Create a new object */ + + ObjDesc = AcpiUtCreateInternalObject (Node->Type); + if (!ObjDesc) + { + Status = AE_NO_MEMORY; + goto UnlockAndExit; + } + + /* Attach new object to the Node, remove local reference */ + + Status = AcpiNsAttachObject (Device, ObjDesc, Node->Type); + AcpiUtRemoveReference (ObjDesc); + if (ACPI_FAILURE (Status)) + { + goto UnlockAndExit; + } + } + + /* Ensure that the handler is not already installed in the lists */ + + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) + { + if (HandlerType & (i+1)) + { + HandlerObj = ObjDesc->CommonNotify.NotifyList[i]; + while (HandlerObj) + { + if (HandlerObj->Notify.Handler == Handler) + { + Status = AE_ALREADY_EXISTS; + goto UnlockAndExit; + } + + HandlerObj = HandlerObj->Notify.Next[i]; + } + } + } + + /* Create and populate a new notify handler object */ + + HandlerObj = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_NOTIFY); + if (!HandlerObj) + { + Status = AE_NO_MEMORY; + goto UnlockAndExit; + } + + HandlerObj->Notify.Node = Node; + HandlerObj->Notify.HandlerType = HandlerType; + HandlerObj->Notify.Handler = Handler; + HandlerObj->Notify.Context = Context; + + /* Install the handler at the list head(s) */ + + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) + { + if (HandlerType & (i+1)) + { + HandlerObj->Notify.Next[i] = + ObjDesc->CommonNotify.NotifyList[i]; + + ObjDesc->CommonNotify.NotifyList[i] = HandlerObj; + } + } + + /* Add an extra reference if handler was installed in both lists */ + + if (HandlerType == ACPI_ALL_NOTIFY) + { + AcpiUtAddReference (HandlerObj); + } + + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallNotifyHandler) + + +/******************************************************************************* + * + * FUNCTION: AcpiRemoveNotifyHandler + * + * PARAMETERS: Device - The device for which the handler is installed + * HandlerType - The type of handler: + * ACPI_SYSTEM_NOTIFY: System Handler (00-7F) + * ACPI_DEVICE_NOTIFY: Device Handler (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_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Device); + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *HandlerObj; + ACPI_OPERAND_OBJECT *PreviousHandlerObj; + ACPI_STATUS Status = AE_OK; + UINT32 i; + + + ACPI_FUNCTION_TRACE (AcpiRemoveNotifyHandler); + + + /* Parameter validation */ + + if ((!Device) || (!Handler) || (!HandlerType) || + (HandlerType > ACPI_MAX_NOTIFY_HANDLER_TYPE)) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Root Object. Global handlers are removed here */ + + if (Device == ACPI_ROOT_OBJECT) + { + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) + { + if (HandlerType & (i+1)) + { + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (!AcpiGbl_GlobalNotify[i].Handler || + (AcpiGbl_GlobalNotify[i].Handler != Handler)) + { + Status = AE_NOT_EXIST; + goto UnlockAndExit; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Removing global notify handler\n")); + + AcpiGbl_GlobalNotify[i].Handler = NULL; + AcpiGbl_GlobalNotify[i].Context = NULL; + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + + /* Make sure all deferred notify tasks are completed */ + + AcpiOsWaitEventsComplete (); + } + } + + return_ACPI_STATUS (AE_OK); + } + + /* All other objects: Are Notifies allowed on this object? */ + + if (!AcpiEvIsNotifyObject (Node)) + { + return_ACPI_STATUS (AE_TYPE); + } + + /* Must have an existing internal object */ + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + /* Internal object exists. Find the handler and remove it */ + + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) + { + if (HandlerType & (i+1)) + { + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + HandlerObj = ObjDesc->CommonNotify.NotifyList[i]; + PreviousHandlerObj = NULL; + + /* Attempt to find the handler in the handler list */ + + while (HandlerObj && + (HandlerObj->Notify.Handler != Handler)) + { + PreviousHandlerObj = HandlerObj; + HandlerObj = HandlerObj->Notify.Next[i]; + } + + if (!HandlerObj) + { + Status = AE_NOT_EXIST; + goto UnlockAndExit; + } + + /* Remove the handler object from the list */ + + if (PreviousHandlerObj) /* Handler is not at the list head */ + { + PreviousHandlerObj->Notify.Next[i] = + HandlerObj->Notify.Next[i]; + } + else /* Handler is at the list head */ + { + ObjDesc->CommonNotify.NotifyList[i] = + HandlerObj->Notify.Next[i]; + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + + /* Make sure all deferred notify tasks are completed */ + + AcpiOsWaitEventsComplete (); + AcpiUtRemoveReference (HandlerObj); + } + } + + return_ACPI_STATUS (Status); + + +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: AcpiInstallSciHandler + * + * PARAMETERS: Address - Address of the handler + * Context - Value passed to the handler on each SCI + * + * RETURN: Status + * + * DESCRIPTION: Install a handler for a System Control Interrupt. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiInstallSciHandler ( + ACPI_SCI_HANDLER Address, + void *Context) +{ + ACPI_SCI_HANDLER_INFO *NewSciHandler; + ACPI_SCI_HANDLER_INFO *SciHandler; + ACPI_CPU_FLAGS Flags; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiInstallSciHandler); + + + if (!Address) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Allocate and init a handler object */ + + NewSciHandler = ACPI_ALLOCATE (sizeof (ACPI_SCI_HANDLER_INFO)); + if (!NewSciHandler) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + NewSciHandler->Address = Address; + NewSciHandler->Context = Context; + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + + /* Lock list during installation */ + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + SciHandler = AcpiGbl_SciHandlerList; + + /* Ensure handler does not already exist */ + + while (SciHandler) + { + if (Address == SciHandler->Address) + { + Status = AE_ALREADY_EXISTS; + goto UnlockAndExit; + } + + SciHandler = SciHandler->Next; + } + + /* Install the new handler into the global list (at head) */ + + NewSciHandler->Next = AcpiGbl_SciHandlerList; + AcpiGbl_SciHandlerList = NewSciHandler; + + +UnlockAndExit: + + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + +Exit: + if (ACPI_FAILURE (Status)) + { + ACPI_FREE (NewSciHandler); + } + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallSciHandler) + + +/******************************************************************************* + * + * FUNCTION: AcpiRemoveSciHandler + * + * PARAMETERS: Address - Address of the handler + * + * RETURN: Status + * + * DESCRIPTION: Remove a handler for a System Control Interrupt. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRemoveSciHandler ( + ACPI_SCI_HANDLER Address) +{ + ACPI_SCI_HANDLER_INFO *PrevSciHandler; + ACPI_SCI_HANDLER_INFO *NextSciHandler; + ACPI_CPU_FLAGS Flags; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiRemoveSciHandler); + + + if (!Address) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Remove the SCI handler with lock */ + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + PrevSciHandler = NULL; + NextSciHandler = AcpiGbl_SciHandlerList; + while (NextSciHandler) + { + if (NextSciHandler->Address == Address) + { + /* Unlink and free the SCI handler info block */ + + if (PrevSciHandler) + { + PrevSciHandler->Next = NextSciHandler->Next; + } + else + { + AcpiGbl_SciHandlerList = NextSciHandler->Next; + } + + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + ACPI_FREE (NextSciHandler); + goto UnlockAndExit; + } + + PrevSciHandler = NextSciHandler; + NextSciHandler = NextSciHandler->Next; + } + + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + Status = AE_NOT_EXIST; + + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiRemoveSciHandler) + + +/******************************************************************************* + * + * 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); + } + + /* Do not allow multiple handlers */ + + if (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 - %s (%u)", + AcpiUtGetEventName (Event), Event)); + + /* Remove the handler */ + + AcpiGbl_FixedEventHandlers[Event].Handler = NULL; + AcpiGbl_FixedEventHandlers[Event].Context = NULL; + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Enabled fixed event %s (%X), Handler=%p\n", + AcpiUtGetEventName (Event), 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 disable fixed event - %s (%u)", + AcpiUtGetEventName (Event), Event)); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Disabled fixed event - %s (%X)\n", + AcpiUtGetEventName (Event), Event)); + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiRemoveFixedEventHandler) + + +/******************************************************************************* + * + * FUNCTION: AcpiEvInstallGpeHandler + * + * 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. + * IsRawHandler - Whether this GPE should be handled using + * the special GPE handler mode. + * Address - Address of the handler + * Context - Value passed to the handler on each GPE + * + * RETURN: Status + * + * DESCRIPTION: Internal function to install a handler for a General Purpose + * Event. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiEvInstallGpeHandler ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + UINT32 Type, + BOOLEAN IsRawHandler, + 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 (EvInstallGpeHandler); + + + /* 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 ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == + ACPI_GPE_DISPATCH_HANDLER) || + (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == + ACPI_GPE_DISPATCH_RAW_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 (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) == + ACPI_GPE_DISPATCH_METHOD) || + (ACPI_GPE_DISPATCH_TYPE (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 | (IsRawHandler ? + ACPI_GPE_DISPATCH_RAW_HANDLER : 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; +} + + +/******************************************************************************* + * + * 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_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiInstallGpeHandler); + + + Status = AcpiEvInstallGpeHandler (GpeDevice, GpeNumber, Type, + FALSE, Address, Context); + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallGpeHandler) + + +/******************************************************************************* + * + * FUNCTION: AcpiInstallGpeRawHandler + * + * 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 +AcpiInstallGpeRawHandler ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + UINT32 Type, + ACPI_GPE_HANDLER Address, + void *Context) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiInstallGpeRawHandler); + + + Status = AcpiEvInstallGpeHandler (GpeDevice, GpeNumber, Type, + TRUE, Address, Context); + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallGpeRawHandler) + + +/******************************************************************************* + * + * 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 ((ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != + ACPI_GPE_DISPATCH_HANDLER) && + (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != + ACPI_GPE_DISPATCH_RAW_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; + GpeEventInfo->Dispatch.Handler = NULL; + + /* 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 (((ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) == + ACPI_GPE_DISPATCH_METHOD) || + (ACPI_GPE_DISPATCH_TYPE (Handler->OriginalFlags) == + ACPI_GPE_DISPATCH_NOTIFY)) && + Handler->OriginallyEnabled) + { + (void) AcpiEvAddGpeReference (GpeEventInfo, FALSE); + if (ACPI_GPE_IS_POLLING_NEEDED (GpeEventInfo)) + { + /* Poll edge triggered GPEs to handle existing events */ + + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + (void) AcpiEvDetectGpe ( + GpeDevice, GpeEventInfo, GpeNumber); + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + } + } + + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + + /* Make sure all deferred GPE tasks are completed */ + + AcpiOsWaitEventsComplete (); + + /* Now we can free the handler object */ + + ACPI_FREE (Handler); + return_ACPI_STATUS (Status); + +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/code/drivers/platform/acpi/third_party/acpica/components/events/evxfevnt.c b/code/drivers/platform/acpi/third_party/acpica/components/events/evxfevnt.c new file mode 100644 index 0000000..f0ecc5e --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/events/evxfevnt.c @@ -0,0 +1,421 @@ +/****************************************************************************** + * + * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#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 (AcpiGbl_FadtIndex == ACPI_INVALID_TABLE_INDEX) + { + return_ACPI_STATUS (AE_NO_ACPI_TABLES); + } + + /* If the Hardware Reduced flag is set, machine is always in acpi mode */ + + if (AcpiGbl_ReducedHardware) + { + return_ACPI_STATUS (AE_OK); + } + + /* 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 the Hardware Reduced flag is set, machine is always in acpi mode */ + + if (AcpiGbl_ReducedHardware) + { + return_ACPI_STATUS (AE_OK); + } + + 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); + + + /* If Hardware Reduced flag is set, there are no fixed events */ + + if (AcpiGbl_ReducedHardware) + { + return_ACPI_STATUS (AE_OK); + } + + /* 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); + + + /* If Hardware Reduced flag is set, there are no fixed events */ + + if (AcpiGbl_ReducedHardware) + { + return_ACPI_STATUS (AE_OK); + } + + /* 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); + + + /* If Hardware Reduced flag is set, there are no fixed events */ + + if (AcpiGbl_ReducedHardware) + { + return_ACPI_STATUS (AE_OK); + } + + /* 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; + ACPI_EVENT_STATUS LocalEventStatus = 0; + UINT32 InByte; + + + 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); + } + + /* Fixed event currently can be dispatched? */ + + if (AcpiGbl_FixedEventHandlers[Event].Handler) + { + LocalEventStatus |= ACPI_EVENT_FLAG_HAS_HANDLER; + } + + /* Fixed event currently enabled? */ + + Status = AcpiReadBitRegister ( + AcpiGbl_FixedEventInfo[Event].EnableRegisterId, &InByte); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (InByte) + { + LocalEventStatus |= + (ACPI_EVENT_FLAG_ENABLED | ACPI_EVENT_FLAG_ENABLE_SET); + } + + /* Fixed event currently active? */ + + Status = AcpiReadBitRegister ( + AcpiGbl_FixedEventInfo[Event].StatusRegisterId, &InByte); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (InByte) + { + LocalEventStatus |= ACPI_EVENT_FLAG_STATUS_SET; + } + + (*EventStatus) = LocalEventStatus; + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiGetEventStatus) + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/code/drivers/platform/acpi/third_party/acpica/components/events/evxfgpe.c b/code/drivers/platform/acpi/third_party/acpica/components/events/evxfgpe.c new file mode 100644 index 0000000..0c7e181 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/events/evxfgpe.c @@ -0,0 +1,1217 @@ +/****************************************************************************** + * + * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs) + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#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; + BOOLEAN IsPollingNeeded = FALSE; + + + ACPI_FUNCTION_TRACE (AcpiUpdateAllGpes); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (AcpiGbl_AllGpesInitialized) + { + goto UnlockAndExit; + } + + Status = AcpiEvWalkGpeList (AcpiEvInitializeGpeBlock, + &IsPollingNeeded); + if (ACPI_SUCCESS (Status)) + { + AcpiGbl_AllGpesInitialized = TRUE; + } + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + + if (IsPollingNeeded && AcpiGbl_AllGpesInitialized) + { + /* Poll GPEs to handle already triggered events */ + + AcpiEvGpeDetect (AcpiGbl_GpeXruptListHead); + } + 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 and that there is some way + * of handling the GPE (handler or a GPE method). In other words, we + * won't allow a valid GPE to be enabled if there is no way to handle it. + */ + GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); + if (GpeEventInfo) + { + if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != + ACPI_GPE_DISPATCH_NONE) + { + Status = AcpiEvAddGpeReference (GpeEventInfo, TRUE); + if (ACPI_SUCCESS (Status) && + ACPI_GPE_IS_POLLING_NEEDED (GpeEventInfo)) + { + /* Poll edge-triggered GPEs to handle existing events */ + + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + (void) AcpiEvDetectGpe ( + GpeDevice, GpeEventInfo, GpeNumber); + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + } + } + else + { + Status = AE_NO_HANDLER; + } + } + + 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(), + * AcpiDisableGpe() interfaces. + * This API is typically used by the GPE raw handler mode driver + * to switch between the polling mode and the interrupt mode after + * the driver has enabled the GPE. + * The APIs should be invoked in this order: + * AcpiEnableGpe() <- Ensure the reference count > 0 + * AcpiSetGpe(ACPI_GPE_DISABLE) <- Enter polling mode + * AcpiSetGpe(ACPI_GPE_ENABLE) <- Leave polling mode + * AcpiDisableGpe() <- Decrease the reference count + * + * Note: If a GPE is shared by 2 silicon components, then both the drivers + * should support GPE polling mode or disabling the GPE for long period + * for one driver may break the other. So use it with care since all + * firmware _Lxx/_Exx handlers currently rely on the GPE interrupt mode. + * + ******************************************************************************/ + +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 = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_ENABLE); + GpeEventInfo->DisableForDispatch = FALSE; + break; + + case ACPI_GPE_DISABLE: + + Status = AcpiHwLowSetGpe (GpeEventInfo, ACPI_GPE_DISABLE); + GpeEventInfo->DisableForDispatch = TRUE; + break; + + default: + + Status = AE_BAD_PARAMETER; + break; + } + +UnlockAndExit: + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiSetGpe) + + +/******************************************************************************* + * + * FUNCTION: AcpiMaskGpe + * + * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 + * GpeNumber - GPE level within the GPE block + * IsMasked - Whether the GPE is masked or not + * + * RETURN: Status + * + * DESCRIPTION: Unconditionally mask/unmask the an individual GPE, ex., to + * prevent a GPE flooding. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiMaskGpe ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + BOOLEAN IsMasked) +{ + ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_STATUS Status; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (AcpiMaskGpe); + + + 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 = AcpiEvMaskGpe (GpeEventInfo, IsMasked); + +UnlockAndExit: + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiMaskGpe) + + +/******************************************************************************* + * + * FUNCTION: AcpiMarkGpeForWake + * + * PARAMETERS: 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. Simply + * sets the ACPI_GPE_CAN_WAKE flag. + * + * Some potential callers of AcpiSetupGpeForWake may know in advance that + * there won't be any notify handlers installed for device wake notifications + * from the given GPE (one example is a button GPE in Linux). For these cases, + * AcpiMarkGpeForWake should be used instead of AcpiSetupGpeForWake. + * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to + * setup implicit wake notification for it (since there's no handler method). + * + ******************************************************************************/ + +ACPI_STATUS +AcpiMarkGpeForWake ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber) +{ + ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_STATUS Status = AE_BAD_PARAMETER; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (AcpiMarkGpeForWake); + + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* Ensure that we have a valid GPE number */ + + GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); + if (GpeEventInfo) + { + /* Mark the GPE as a possible wake event */ + + GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; + Status = AE_OK; + } + + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiMarkGpeForWake) + + +/******************************************************************************* + * + * 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; + ACPI_GPE_EVENT_INFO *GpeEventInfo; + ACPI_NAMESPACE_NODE *DeviceNode; + ACPI_GPE_NOTIFY_INFO *Notify; + ACPI_GPE_NOTIFY_INFO *NewNotify; + 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); + } + + /* + * Allocate a new notify object up front, in case it is needed. + * Memory allocation while holding a spinlock is a big no-no + * on some hosts. + */ + NewNotify = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_GPE_NOTIFY_INFO)); + if (!NewNotify) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Flags = AcpiOsAcquireLock (AcpiGbl_GpeLock); + + /* Ensure that we have a valid GPE number */ + + GpeEventInfo = AcpiEvGetGpeEventInfo (GpeDevice, GpeNumber); + if (!GpeEventInfo) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* + * If there is no method or handler for this GPE, then the + * WakeDevice will be notified whenever this GPE fires. This is + * known as an "implicit notify". Note: The GPE is assumed to be + * level-triggered (for windows compatibility). + */ + if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == + ACPI_GPE_DISPATCH_NONE) + { + /* + * This is the first device for implicit notify on this GPE. + * Just set the flags here, and enter the NOTIFY block below. + */ + GpeEventInfo->Flags = + (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED); + } + else if (GpeEventInfo->Flags & ACPI_GPE_AUTO_ENABLED) + { + /* + * A reference to this GPE has been added during the GPE block + * initialization, so drop it now to prevent the GPE from being + * permanently enabled and clear its ACPI_GPE_AUTO_ENABLED flag. + */ + (void) AcpiEvRemoveGpeReference (GpeEventInfo); + GpeEventInfo->Flags &= ~ACPI_GPE_AUTO_ENABLED; + } + + /* + * If we already have an implicit notify on this GPE, add + * this device to the notify list. + */ + if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) == + ACPI_GPE_DISPATCH_NOTIFY) + { + /* Ensure that the device is not already in the list */ + + Notify = GpeEventInfo->Dispatch.NotifyList; + while (Notify) + { + if (Notify->DeviceNode == DeviceNode) + { + Status = AE_ALREADY_EXISTS; + goto UnlockAndExit; + } + Notify = Notify->Next; + } + + /* Add this device to the notify list for this GPE */ + + NewNotify->DeviceNode = DeviceNode; + NewNotify->Next = GpeEventInfo->Dispatch.NotifyList; + GpeEventInfo->Dispatch.NotifyList = NewNotify; + NewNotify = NULL; + } + + /* Mark the GPE as a possible wake event */ + + GpeEventInfo->Flags |= ACPI_GPE_CAN_WAKE; + Status = AE_OK; + + +UnlockAndExit: + AcpiOsReleaseLock (AcpiGbl_GpeLock, Flags); + + /* Delete the notify object if it was not used above */ + + if (NewNotify) + { + ACPI_FREE (NewNotify); + } + 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); + + /* 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: AcpiDispatchGpe + * + * PARAMETERS: GpeDevice - Parent GPE Device. NULL for GPE0/GPE1 + * GpeNumber - GPE level within the GPE block + * + * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED + * + * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function + * (e.g. EC) or method (e.g. _Lxx/_Exx) handler. + * + ******************************************************************************/ + +UINT32 +AcpiDispatchGpe( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber) +{ + ACPI_FUNCTION_TRACE(acpi_dispatch_gpe); + + return (AcpiEvDetectGpe (GpeDevice, NULL, GpeNumber)); +} + +ACPI_EXPORT_SYMBOL (AcpiDispatchGpe) + + +/******************************************************************************* + * + * 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 re-enable a GPE. This completes the GPE + * processing. Intended for use by asynchronous host-installed + * GPE handlers. The GPE is only re-enabled 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: AcpiEnableAllWakeupGpes + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in + * all GPE blocks. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiEnableAllWakeupGpes ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiEnableAllWakeupGpes); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiHwEnableAllWakeupGpes (); + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiEnableAllWakeupGpes) + + +/****************************************************************************** + * + * FUNCTION: AcpiAnyGpeStatusSet + * + * PARAMETERS: None + * + * RETURN: Whether or not the status bit is set for any GPE + * + * DESCRIPTION: Check the status bits of all enabled GPEs and return TRUE if any + * of them is set or FALSE otherwise. + * + ******************************************************************************/ + +UINT32 +AcpiAnyGpeStatusSet ( + void) +{ + ACPI_STATUS Status; + UINT8 Ret; + + + ACPI_FUNCTION_TRACE (AcpiAnyGpeStatusSet); + + Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS); + if (ACPI_FAILURE (Status)) + { + return (FALSE); + } + + Ret = AcpiHwCheckAllGpes (); + (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS); + + return (Ret); +} + +ACPI_EXPORT_SYMBOL(AcpiAnyGpeStatusSet) + + +/******************************************************************************* + * + * 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_ACPI_STATUS (Status); + } + + Node = AcpiNsValidateHandle (GpeDevice); + if (!Node) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* Validate the parent device */ + + if (Node->Type != ACPI_TYPE_DEVICE) + { + Status = AE_TYPE; + goto UnlockAndExit; + } + + if (Node->Object) + { + Status = AE_ALREADY_EXISTS; + goto UnlockAndExit; + } + + /* + * For user-installed GPE Block Devices, the GpeBlockBaseNumber + * is always zero + */ + Status = AcpiEvCreateGpeBlock (Node, GpeBlockAddress->Address, + GpeBlockAddress->SpaceId, 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_ACPI_STATUS (Status); + } + + Node = AcpiNsValidateHandle (GpeDevice); + if (!Node) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + /* Validate the parent device */ + + if (Node->Type != ACPI_TYPE_DEVICE) + { + Status = AE_TYPE; + 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/code/drivers/platform/acpi/third_party/acpica/components/events/evxfregn.c b/code/drivers/platform/acpi/third_party/acpica/components/events/evxfregn.c new file mode 100644 index 0000000..f064c2f --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/events/evxfregn.c @@ -0,0 +1,339 @@ +/****************************************************************************** + * + * Module Name: evxfregn - External Interfaces, ACPI Operation Regions and + * Address Spaces. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acevents.h" + +#define _COMPONENT ACPI_EVENTS + ACPI_MODULE_NAME ("evxfregn") + + +/******************************************************************************* + * + * FUNCTION: AcpiInstallAddressSpaceHandlerInternal + * + * 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 + * Run_Reg - Run _REG methods for this address space? + * + * 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.) + * To avoid this problem pass FALSE for Run_Reg and later on call + * AcpiExecuteRegMethods() to execute _REG. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiInstallAddressSpaceHandlerInternal ( + ACPI_HANDLE Device, + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_ADR_SPACE_HANDLER Handler, + ACPI_ADR_SPACE_SETUP Setup, + void *Context, + BOOLEAN Run_Reg) +{ + 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; + } + + /* Run all _REG methods for this address space */ + + if (Run_Reg) + { + AcpiEvExecuteRegMethods (Node, SpaceId, ACPI_REG_CONNECT); + } + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (Status); +} + +ACPI_STATUS +AcpiInstallAddressSpaceHandler ( + ACPI_HANDLE Device, + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_ADR_SPACE_HANDLER Handler, + ACPI_ADR_SPACE_SETUP Setup, + void *Context) +{ + return AcpiInstallAddressSpaceHandlerInternal (Device, SpaceId, Handler, Setup, Context, TRUE); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallAddressSpaceHandler) + +ACPI_STATUS +AcpiInstallAddressSpaceHandlerNo_Reg ( + ACPI_HANDLE Device, + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_ADR_SPACE_HANDLER Handler, + ACPI_ADR_SPACE_SETUP Setup, + void *Context) +{ + return AcpiInstallAddressSpaceHandlerInternal (Device, SpaceId, Handler, Setup, Context, FALSE); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallAddressSpaceHandlerNo_Reg) + + +/******************************************************************************* + * + * 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->CommonNotify.Handler; + LastObjPtr = &ObjDesc->CommonNotify.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) + + +/******************************************************************************* + * + * FUNCTION: AcpiExecuteRegMethods + * + * PARAMETERS: Device - Handle for the device + * SpaceId - The address space ID + * + * RETURN: Status + * + * DESCRIPTION: Execute _REG for all OpRegions of a given SpaceId. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExecuteRegMethods ( + ACPI_HANDLE Device, + ACPI_ADR_SPACE_TYPE SpaceId) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiExecuteRegMethods); + + + /* 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) + { + /* Run all _REG methods for this address space */ + + AcpiEvExecuteRegMethods (Node, SpaceId, ACPI_REG_CONNECT); + } + else + { + Status = AE_BAD_PARAMETER; + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiExecuteRegMethods) diff --git a/code/drivers/platform/acpi/third_party/acpica/components/executer/exconcat.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exconcat.c new file mode 100644 index 0000000..93f114b --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exconcat.c @@ -0,0 +1,570 @@ +/****************************************************************************** + * + * Module Name: exconcat - Concatenate-type AML operators + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + ***************************************************************************** + * + * Alternatively, you may choose to be licensed under the terms of the + * following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, you may choose to be licensed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "amlresrc.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exconcat") + +/* Local Prototypes */ + +static ACPI_STATUS +AcpiExConvertToObjectTypeString ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ResultDesc); + + +/******************************************************************************* + * + * 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 with the ACPI-defined conversion + * rules as necessary. + * NOTE: + * Per the ACPI spec (up to 6.1), Concatenate only supports Integer, + * String, and Buffer objects. However, we support all objects here + * as an extension. This improves the usefulness of both Concatenate + * and the Printf/Fprintf macros. The extension returns a string + * describing the object type for the other objects. + * 02/2016. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExDoConcatenate ( + ACPI_OPERAND_OBJECT *Operand0, + ACPI_OPERAND_OBJECT *Operand1, + ACPI_OPERAND_OBJECT **ActualReturnDesc, + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT *LocalOperand0 = Operand0; + ACPI_OPERAND_OBJECT *LocalOperand1 = Operand1; + ACPI_OPERAND_OBJECT *TempOperand1 = NULL; + ACPI_OPERAND_OBJECT *ReturnDesc; + char *Buffer; + ACPI_OBJECT_TYPE Operand0Type; + ACPI_OBJECT_TYPE Operand1Type; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (ExDoConcatenate); + + + /* Operand 0 preprocessing */ + + switch (Operand0->Common.Type) + { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + Operand0Type = Operand0->Common.Type; + break; + + default: + + /* For all other types, get the "object type" string */ + + Status = AcpiExConvertToObjectTypeString ( + Operand0, &LocalOperand0); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + Operand0Type = ACPI_TYPE_STRING; + break; + } + + /* Operand 1 preprocessing */ + + switch (Operand1->Common.Type) + { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + Operand1Type = Operand1->Common.Type; + break; + + default: + + /* For all other types, get the "object type" string */ + + Status = AcpiExConvertToObjectTypeString ( + Operand1, &LocalOperand1); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + Operand1Type = ACPI_TYPE_STRING; + break; + } + + /* + * Convert the second operand if necessary. The first operand (0) + * determines the type of the second operand (1) (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 (Operand0Type) + { + case ACPI_TYPE_INTEGER: + + Status = AcpiExConvertToInteger (LocalOperand1, &TempOperand1, + ACPI_IMPLICIT_CONVERSION); + break; + + case ACPI_TYPE_BUFFER: + + Status = AcpiExConvertToBuffer (LocalOperand1, &TempOperand1); + break; + + case ACPI_TYPE_STRING: + + switch (Operand1Type) + { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + /* Other types have already been converted to string */ + + Status = AcpiExConvertToString ( + LocalOperand1, &TempOperand1, ACPI_IMPLICIT_CONVERT_HEX); + break; + + default: + + Status = AE_OK; + break; + } + break; + + default: + + ACPI_ERROR ((AE_INFO, "Invalid object type: 0x%X", + Operand0->Common.Type)); + Status = AE_AML_INTERNAL; + } + + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + /* Take care with any newly created operand objects */ + + if ((LocalOperand1 != Operand1) && + (LocalOperand1 != TempOperand1)) + { + AcpiUtRemoveReference (LocalOperand1); + } + + LocalOperand1 = TempOperand1; + + /* + * 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, as per the ACPI spec: + * + * 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 (Operand0Type) + { + 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; + } + + Buffer = (char *) ReturnDesc->Buffer.Pointer; + + /* Copy the first integer, LSB first */ + + memcpy (Buffer, &Operand0->Integer.Value, + AcpiGbl_IntegerByteWidth); + + /* Copy the second integer (LSB first) after the first */ + + memcpy (Buffer + AcpiGbl_IntegerByteWidth, + &LocalOperand1->Integer.Value, AcpiGbl_IntegerByteWidth); + break; + + case ACPI_TYPE_STRING: + + /* Result of two Strings is a String */ + + ReturnDesc = AcpiUtCreateStringObject ( + ((ACPI_SIZE) LocalOperand0->String.Length + + LocalOperand1->String.Length)); + if (!ReturnDesc) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + Buffer = ReturnDesc->String.Pointer; + + /* Concatenate the strings */ + + strcpy (Buffer, LocalOperand0->String.Pointer); + strcat (Buffer, 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; + } + + Buffer = (char *) ReturnDesc->Buffer.Pointer; + + /* Concatenate the buffers */ + + memcpy (Buffer, Operand0->Buffer.Pointer, + Operand0->Buffer.Length); + memcpy (Buffer + 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 (LocalOperand0 != Operand0) + { + AcpiUtRemoveReference (LocalOperand0); + } + + if (LocalOperand1 != Operand1) + { + AcpiUtRemoveReference (LocalOperand1); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExConvertToObjectTypeString + * + * PARAMETERS: ObjDesc - Object to be converted + * ReturnDesc - Where to place the return object + * + * RETURN: Status + * + * DESCRIPTION: Convert an object of arbitrary type to a string object that + * contains the namestring for the object. Used for the + * concatenate operator. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiExConvertToObjectTypeString ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ResultDesc) +{ + ACPI_OPERAND_OBJECT *ReturnDesc; + const char *TypeString; + + + TypeString = AcpiUtGetTypeName (ObjDesc->Common.Type); + + ReturnDesc = AcpiUtCreateStringObject ( + ((ACPI_SIZE) strlen (TypeString) + 9)); /* 9 For "[ Object]" */ + if (!ReturnDesc) + { + return (AE_NO_MEMORY); + } + + strcpy (ReturnDesc->String.Pointer, "["); + strcat (ReturnDesc->String.Pointer, TypeString); + strcat (ReturnDesc->String.Pointer, " Object]"); + + *ResultDesc = ReturnDesc; + return (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; + memcpy (NewBuf, Operand0->Buffer.Pointer, Length0); + 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); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/executer/exconfig.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exconfig.c new file mode 100644 index 0000000..278b562 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exconfig.c @@ -0,0 +1,769 @@ +/****************************************************************************** + * + * Module Name: exconfig - Namespace reconfiguration (Load/Unload opcodes) + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + ***************************************************************************** + * + * Alternatively, you may choose to be licensed under the terms of the + * following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, you may choose to be licensed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "acnamesp.h" +#include "actables.h" +#include "acdispat.h" +#include "acevents.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exconfig") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiExAddTable ( + UINT32 TableIndex, + 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_OPERAND_OBJECT **DdbHandle) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + + + 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; + ObjDesc->Reference.Value = TableIndex; + *DdbHandle = ObjDesc; + 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 *ReturnObj; + ACPI_OPERAND_OBJECT *DdbHandle; + UINT32 TableIndex; + char OemId[ACPI_OEM_ID_SIZE + 1]; + char OemTableId[ACPI_OEM_TABLE_ID_SIZE + 1]; + + + ACPI_FUNCTION_TRACE (ExLoadTableOp); + + + /* Create the return object */ + + ReturnObj = AcpiUtCreateIntegerObject ((UINT64) 0); + if (!ReturnObj) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + *ReturnDesc = ReturnObj; + + /* + * Validate OEM ID and OEM Table ID string lengths. + * AcpiTbFindTable expects strings that can safely read + * ACPI_OEM_ID_SIZE and ACPI_OEM_TABLE_ID_SIZE bytes. + */ + if ((Operand[1]->String.Length > ACPI_OEM_ID_SIZE) || + (Operand[2]->String.Length > ACPI_OEM_TABLE_ID_SIZE)) + { + return_ACPI_STATUS (AE_AML_STRING_LIMIT); + } + + /* + * Copy OEM strings to local buffers with guaranteed null-termination. + * This prevents heap-buffer-overflow when AcpiTbFindTable reads + * ACPI_OEM_ID_SIZE/ACPI_OEM_TABLE_ID_SIZE bytes. + */ + memcpy (OemId, Operand[1]->String.Pointer, Operand[1]->String.Length); + OemId[Operand[1]->String.Length] = 0; + memcpy (OemTableId, Operand[2]->String.Pointer, Operand[2]->String.Length); + OemTableId[Operand[2]->String.Length] = 0; + + /* Find the ACPI table in the RSDT/XSDT */ + + AcpiExExitInterpreter (); + Status = AcpiTbFindTable ( + Operand[0]->String.Pointer, + OemId, + OemTableId, &TableIndex); + AcpiExEnterInterpreter (); + if (ACPI_FAILURE (Status)) + { + if (Status != AE_NOT_FOUND) + { + return_ACPI_STATUS (Status); + } + + /* Table not found, return an Integer=0 and AE_OK */ + + 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 = AcpiNsGetNodeUnlocked (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] != AML_ROOT_PREFIX) && + (Operand[4]->String.Pointer[0] != AML_PARENT_PREFIX)) + { + /* + * 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 = AcpiNsGetNodeUnlocked (StartNode, + Operand[4]->String.Pointer, ACPI_NS_SEARCH_PARENT, + &ParameterNode); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + /* Load the table into the namespace */ + + ACPI_INFO (("Dynamic OEM Table Load:")); + AcpiExExitInterpreter (); + Status = AcpiTbLoadTable (TableIndex, ParentNode); + AcpiExEnterInterpreter (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiExAddTable (TableIndex, &DdbHandle); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Complete the initialization/resolution of new objects */ + + AcpiExExitInterpreter(); + AcpiNsInitializeObjects(); + AcpiExEnterInterpreter(); + + /* 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); + } + } + + /* Remove the reference to DdbHandle created by AcpiExAddTable above */ + + AcpiUtRemoveReference (DdbHandle); + + /* Return -1 (non-zero) indicates success */ + + ReturnObj->Integer.Value = 0xFFFFFFFFFFFFFFFF; + 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 the status of the load 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 *TableHeader; + ACPI_TABLE_HEADER *Table; + UINT32 TableIndex; + ACPI_STATUS Status; + UINT32 Length; + + + ACPI_FUNCTION_TRACE (ExLoadOp); + + + if (Target->Common.DescriptorType == ACPI_DESC_TYPE_NAMED) + { + Target = AcpiNsGetAttachedObject (ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Target)); + } + if (Target->Common.Type != ACPI_TYPE_INTEGER) + { + ACPI_ERROR ((AE_INFO, "Type not integer: %X", Target->Common.Type)); + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + Target->Integer.Value = 0; + + /* 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 */ + + TableHeader = ACPI_ALLOCATE (sizeof (ACPI_TABLE_HEADER)); + if (!TableHeader) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Status = AcpiExRegionRead (ObjDesc, sizeof (ACPI_TABLE_HEADER), + ACPI_CAST_PTR (UINT8, TableHeader)); + Length = TableHeader->Length; + ACPI_FREE (TableHeader); + + 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 */ + + Table = ACPI_ALLOCATE (Length); + if (!Table) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Read the entire table */ + + Status = AcpiExRegionRead (ObjDesc, Length, + ACPI_CAST_PTR (UINT8, Table)); + if (ACPI_FAILURE (Status)) + { + ACPI_FREE (Table); + return_ACPI_STATUS (Status); + } + 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 */ + + TableHeader = ACPI_CAST_PTR ( + ACPI_TABLE_HEADER, ObjDesc->Buffer.Pointer); + Length = TableHeader->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 + */ + Table = ACPI_ALLOCATE (Length); + if (!Table) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + memcpy (Table, TableHeader, Length); + break; + + default: + + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + /* Install the new table into the local data structures */ + + ACPI_INFO (("Dynamic OEM Table Load:")); + AcpiExExitInterpreter (); + Status = AcpiTbInstallAndLoadTable (ACPI_PTR_TO_PHYSADDR (Table), + ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, Table, TRUE, &TableIndex); + AcpiExEnterInterpreter (); + if (ACPI_FAILURE (Status)) + { + /* + * Table buffer is already freed by AcpiTbUninstallTable + * in AcpiTbInstallAndLoadTable if installation succeeded, + * or by AcpiTbUninstallTable in AcpiTbInstallStandardTable + * if verification failed after partial setup. + */ + 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, &DdbHandle); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Complete the initialization/resolution of new objects */ + + AcpiExExitInterpreter (); + AcpiNsInitializeObjects (); + AcpiExEnterInterpreter (); + + /* Remove the reference to DdbHandle created by AcpiExAddTable above */ + + AcpiUtRemoveReference (DdbHandle); + + /* Return -1 (non-zero) indicates success */ + + Target->Integer.Value = 0xFFFFFFFFFFFFFFFF; + 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_FUNCTION_TRACE (ExUnloadTable); + + + /* + * Temporarily emit a warning so that the ASL for the machine can be + * hopefully obtained. This is to say that the Unload() operator is + * extremely rare if not completely unused. + */ + ACPI_WARNING ((AE_INFO, + "Received request to unload an ACPI table")); + + /* + * May 2018: Unload is no longer supported for the following reasons: + * 1) A correct implementation on some hosts may not be possible. + * 2) Other ACPI implementations do not correctly/fully support it. + * 3) It requires host device driver support which does not exist. + * (To properly support namespace unload out from underneath.) + * 4) This AML operator has never been seen in the field. + */ + ACPI_EXCEPTION ((AE_INFO, AE_NOT_IMPLEMENTED, + "AML Unload operator is not supported")); + + /* + * 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_AML_OPERAND_TYPE); + } + + /* Get the table index from the DdbHandle */ + + TableIndex = TableDesc->Reference.Value; + + /* + * Release the interpreter lock so that the table lock won't have + * strict order requirement against it. + */ + AcpiExExitInterpreter (); + Status = AcpiTbUnloadTable (TableIndex); + AcpiExEnterInterpreter (); + + /* + * 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. + */ + if (ACPI_SUCCESS (Status)) + { + DdbHandle->Common.Flags &= ~AOPOBJ_DATA_VALID; + } + return_ACPI_STATUS (Status); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/executer/exconvrt.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exconvrt.c new file mode 100644 index 0000000..76eccce --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exconvrt.c @@ -0,0 +1,786 @@ +/****************************************************************************** + * + * Module Name: exconvrt - Object conversion routines + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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, + BOOLEAN LeadingZeros); + + +/******************************************************************************* + * + * FUNCTION: AcpiExConvertToInteger + * + * PARAMETERS: ObjDesc - Object to be converted. Must be an + * Integer, Buffer, or String + * ResultDesc - Where the new Integer object is returned + * ImplicitConversion - 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 ImplicitConversion) +{ + ACPI_OPERAND_OBJECT *ReturnDesc; + UINT8 *Pointer; + UINT64 Result; + UINT32 i; + UINT32 Count; + + + 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"). + * + * Explicit conversion is used only by ToInteger. + * All other string-to-integer conversions are implicit conversions. + */ + if (ImplicitConversion) + { + Result = AcpiUtImplicitStrtoul64 (ACPI_CAST_PTR (char, Pointer)); + } + else + { + Result = AcpiUtExplicitStrtoul64 (ACPI_CAST_PTR (char, Pointer)); + } + 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 */ + + (void) 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; + 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; + memcpy ((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 + * LeadingZeros - Allow leading zeros + * + * 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, + BOOLEAN LeadingZeros) +{ + UINT64 Digit; + UINT32 i; + UINT32 j; + UINT32 k = 0; + UINT32 HexLength; + UINT32 DecimalLength; + UINT32 Remainder; + BOOLEAN SupressZeros = !LeadingZeros; + UINT8 HexChar; + + + 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; + } + + 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 = (DataWidth * 2); + for (i = 0, j = (HexLength-1); i < HexLength; i++, j--) + { + /* Get one hex digit, most significant digits first */ + + HexChar = (UINT8) + AcpiUtHexToAsciiChar (Integer, ACPI_MUL_4 (j)); + + /* Suppress leading zeros until the first non-zero character */ + + if (HexChar == ACPI_ASCII_ZERO && SupressZeros) + { + continue; + } + + SupressZeros = FALSE; + String[k] = HexChar; + 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. Supports both implicit + * and explicit conversions and related rules. + * + ******************************************************************************/ + +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 = ','; + BOOLEAN LeadingZeros; + + + 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: + /* + * From ToDecimalString, integer source. + * + * Make room for the maximum decimal number size + */ + StringLength = ACPI_MAX_DECIMAL_DIGITS; + LeadingZeros = FALSE; + Base = 10; + break; + + case ACPI_EXPLICIT_CONVERT_HEX: + /* + * From ToHexString. + * + * Suppress leading zeros and append "0x" + */ + StringLength = ACPI_MUL_2 (AcpiGbl_IntegerByteWidth) + 2; + LeadingZeros = FALSE; + break; + default: + + /* Two hex string characters for each integer byte */ + + StringLength = ACPI_MUL_2 (AcpiGbl_IntegerByteWidth); + LeadingZeros = TRUE; + 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; + if (Type == ACPI_EXPLICIT_CONVERT_HEX) + { + /* Append "0x" prefix for explicit hex conversion */ + + *NewBuf++ = '0'; + *NewBuf++ = 'x'; + } + + /* Convert integer to string */ + + StringLength = AcpiExConvertToAscii ( + ObjDesc->Integer.Value, Base, NewBuf, AcpiGbl_IntegerByteWidth, LeadingZeros); + + /* Null terminate at the correct place */ + + ReturnDesc->String.Length = StringLength; + if (Type == ACPI_EXPLICIT_CONVERT_HEX) + { + /* Take "0x" prefix into account */ + + ReturnDesc->String.Length += 2; + } + + NewBuf [StringLength] = 0; + break; + + case ACPI_TYPE_BUFFER: + + /* Setup string length, base, and separator */ + + switch (Type) + { + case ACPI_EXPLICIT_CONVERT_DECIMAL: /* Used by ToDecimalString */ + /* + * Explicit conversion from the ToDecimalString ASL operator. + * + * From ACPI: "If the input is a buffer, it is converted to a + * a string of decimal values separated by commas." + */ + LeadingZeros = FALSE; + 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: + /* + * Implicit buffer-to-string conversion + * + * 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." + * + * Each hex number is prefixed with 0x (11/2018) + */ + LeadingZeros = TRUE; + Separator = ' '; + StringLength = (ObjDesc->Buffer.Length * 5); + break; + + case ACPI_EXPLICIT_CONVERT_HEX: + /* + * Explicit conversion from the ToHexString ASL operator. + * + * From ACPI: "If Data is a buffer, it is converted to a string of + * hexadecimal values separated by commas." + * + * Each hex number is prefixed with 0x (11/2018) + */ + LeadingZeros = TRUE; + Separator = ','; + StringLength = (ObjDesc->Buffer.Length * 5); + 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++) + { + if (Base == 16) + { + /* Emit 0x prefix for explicit/implicit hex conversion */ + + *NewBuf++ = '0'; + *NewBuf++ = 'x'; + } + + NewBuf += AcpiExConvertToAscii ( + (UINT64) ObjDesc->Buffer.Pointer[i], Base, NewBuf, 1, LeadingZeros); + + /* Each digit is separated by either a comma or space */ + + *NewBuf++ = Separator; + } + + /* + * 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: + case ARGI_STORE_TARGET: + + 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, + ACPI_IMPLICIT_CONVERSION); + 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/code/drivers/platform/acpi/third_party/acpica/components/executer/excreate.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/excreate.c new file mode 100644 index 0000000..f78c7e5 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/excreate.c @@ -0,0 +1,660 @@ +/****************************************************************************** + * + * Module Name: excreate - Named object creation + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + ***************************************************************************** + * + * Alternatively, you may choose to be licensed under the terms of the + * following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, you may choose to be licensed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "amlcode.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("excreate") + + +/******************************************************************************* + * + * 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); + } + + /* Ensure that the target node is valid */ + + if (!TargetNode) + { + return_ACPI_STATUS (AE_NULL_OBJECT); + } + + /* Construct the alias object (a namespace node) */ + + switch (TargetNode->Type) + { + case ACPI_TYPE_METHOD: + /* + * Control method aliases need to be differentiated with + * a special type + */ + AliasNode->Type = ACPI_TYPE_LOCAL_METHOD_ALIAS; + break; + + default: + /* + * All other object types. + * + * 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; + } + + /* Since both operands are Nodes, we don't need to delete them */ + + AliasNode->Object = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, TargetNode); + 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 = AcpiNsGetSecondaryObject (ObjDesc); + RegionObj2->Extra.AmlStart = AmlStart; + RegionObj2->Extra.AmlLength = AmlLength; + RegionObj2->Extra.Method_REG = NULL; + 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.Pointer = NULL; + ObjDesc->Region.Node = Node; + ObjDesc->Region.Handler = NULL; + ObjDesc->Common.Flags &= + ~(AOPOBJ_SETUP_COMPLETE | AOPOBJ_REG_CONNECTED | + AOPOBJ_OBJECT_INITIALIZED); + + /* 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); +} + + +/******************************************************************************* + * + * 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; + ObjDesc->Method.Node = Operand[0]; + + /* + * 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/code/drivers/platform/acpi/third_party/acpica/components/executer/exdebug.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exdebug.c new file mode 100644 index 0000000..80350f1 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exdebug.c @@ -0,0 +1,323 @@ +/****************************************************************************** + * + * Module Name: exdebug - Support for stores to the AML Debug Object + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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; + UINT32 Timer; + ACPI_OPERAND_OBJECT *ObjectDesc; + UINT32 Value; + + + 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; + } + + /* Newline -- don't emit the line header */ + + if (SourceDesc && + (ACPI_GET_DESCRIPTOR_TYPE (SourceDesc) == ACPI_DESC_TYPE_OPERAND) && + (SourceDesc->Common.Type == ACPI_TYPE_STRING)) + { + if ((SourceDesc->String.Length == 1) && + (*SourceDesc->String.Pointer == '\n')) + { + AcpiOsPrintf ("\n"); + return_VOID; + } + } + + /* + * Print line header as long as we are not in the middle of an + * object display + */ + if (!((Level > 0) && Index == 0)) + { + if (AcpiGbl_DisplayDebugTimer) + { + /* + * We will emit the current timer value (in microseconds) with each + * debug output. Only need the lower 26 bits. This allows for 67 + * million microseconds or 67 seconds before rollover. + * + * Convert 100 nanosecond units to microseconds + */ + Timer = ((UINT32) AcpiOsGetTimer () / 10); + Timer &= 0x03FFFFFF; + + AcpiOsPrintf ("ACPI Debug: T=0x%8.8X %*s", Timer, Level, " "); + } + else + { + 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) + { + /* No object type prefix needed for integers and strings */ + + if ((SourceDesc->Common.Type != ACPI_TYPE_INTEGER) && + (SourceDesc->Common.Type != ACPI_TYPE_STRING)) + { + 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 (Node %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); + AcpiUtDumpBuffer (SourceDesc->Buffer.Pointer, + (SourceDesc->Buffer.Length < 256) ? + SourceDesc->Buffer.Length : 256, DB_BYTE_DISPLAY, 0); + break; + + case ACPI_TYPE_STRING: + + AcpiOsPrintf ("\"%s\"\n", 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_VOID; + + 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) + { + /* Reference object is a namespace node */ + + AcpiExDoDebugObject (ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, + SourceDesc->Reference.Object), + Level + 4, 0); + } + else + { + ObjectDesc = SourceDesc->Reference.Object; + Value = SourceDesc->Reference.Value; + + switch (ObjectDesc->Common.Type) + { + case ACPI_TYPE_BUFFER: + + AcpiOsPrintf ("Buffer[%u] = 0x%2.2X\n", + Value, *SourceDesc->Reference.IndexPointer); + break; + + case ACPI_TYPE_STRING: + + AcpiOsPrintf ("String[%u] = \"%c\" (0x%2.2X)\n", + Value, *SourceDesc->Reference.IndexPointer, + *SourceDesc->Reference.IndexPointer); + break; + + case ACPI_TYPE_PACKAGE: + + AcpiOsPrintf ("Package[%u] = ", Value); + if (!(*SourceDesc->Reference.Where)) + { + AcpiOsPrintf ("[Uninitialized Package Element]\n"); + } + else + { + AcpiExDoDebugObject (*SourceDesc->Reference.Where, + Level+4, 0); + } + break; + + default: + + AcpiOsPrintf ("Unknown Reference object type %X\n", + ObjectDesc->Common.Type); + break; + } + } + } + break; + + default: + + AcpiOsPrintf ("(Descriptor %p)\n", SourceDesc); + break; + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, "\n")); + return_VOID; +} +#endif diff --git a/code/drivers/platform/acpi/third_party/acpica/components/executer/exdump.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exdump.c new file mode 100644 index 0000000..bfc5069 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exdump.c @@ -0,0 +1,1282 @@ +/****************************************************************************** + * + * Module Name: exdump - Interpreter debug output routines + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 ( + const char *Title, + const char *Value); + +static void +AcpiExOutPointer ( + const char *Title, + const 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_NODE, ACPI_EXD_OFFSET (Buffer.Node), "Parent Node"}, + {ACPI_EXD_BUFFER, 0, NULL} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpPackage[6] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpPackage), NULL}, + {ACPI_EXD_NODE, ACPI_EXD_OFFSET (Package.Node), "Parent Node"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Package.Flags), "Flags"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (Package.Count), "Element Count"}, + {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.NotifyList[0]), "System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Device.NotifyList[1]), "Device Notify"}, + {ACPI_EXD_HDLR_LIST,ACPI_EXD_OFFSET (Device.Handler), "Handler"} +}; + +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_UINT16, 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[6] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpMutex), NULL}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Mutex.SyncLevel), "Sync Level"}, + {ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Mutex.OriginalSyncLevel), "Original 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[8] = +{ + {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_NODE, ACPI_EXD_OFFSET (Region.Node), "Parent Node"}, + {ACPI_EXD_ADDRESS, ACPI_EXD_OFFSET (Region.Address), "Address"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (Region.Length), "Length"}, + {ACPI_EXD_HDLR_LIST,ACPI_EXD_OFFSET (Region.Handler), "Handler"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Region.Next), "Next"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpPower[6] = +{ + {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.NotifyList[0]), "System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (PowerResource.NotifyList[1]), "Device Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (PowerResource.Handler), "Handler"} +}; + +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.NotifyList[0]), "System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Processor.NotifyList[1]), "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.NotifyList[0]), "System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (ThermalZone.NotifyList[1]), "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[9] = +{ + {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_NODE, ACPI_EXD_OFFSET (Reference.Node), "Node"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Reference.Where), "Where"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Reference.IndexPointer), "Index Pointer"}, + {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_HDLR_LIST,ACPI_EXD_OFFSET (AddressSpace.Next), "Next"}, + {ACPI_EXD_RGN_LIST, ACPI_EXD_OFFSET (AddressSpace.RegionList), "Region List"}, + {ACPI_EXD_NODE, ACPI_EXD_OFFSET (AddressSpace.Node), "Node"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (AddressSpace.Context), "Context"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpNotify[7] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpNotify), NULL}, + {ACPI_EXD_NODE, ACPI_EXD_OFFSET (Notify.Node), "Node"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (Notify.HandlerType), "Handler Type"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Notify.Handler), "Handler"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Notify.Context), "Context"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Notify.Next[0]), "Next System Notify"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Notify.Next[1]), "Next Device Notify"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpExtra[6] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpExtra), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Extra.Method_REG), "_REG Method"}, + {ACPI_EXD_NODE, ACPI_EXD_OFFSET (Extra.ScopeNode), "Scope Node"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Extra.RegionContext), "Region Context"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Extra.AmlStart), "Aml Start"}, + {ACPI_EXD_UINT32, ACPI_EXD_OFFSET (Extra.AmlLength), "Aml Length"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpData[3] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpData), NULL}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Data.Handler), "Handler"}, + {ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Data.Pointer), "Raw Data"} +}; + +/* Miscellaneous tables */ + +static ACPI_EXDUMP_INFO AcpiExDumpCommon[5] = +{ + {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"}, + {ACPI_EXD_LIST, ACPI_EXD_OFFSET (Common.NextObject), "Object List"} +}; + +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_NODE, ACPI_EXD_OFFSET (CommonField.Node), "Parent Node"} +}; + +static ACPI_EXDUMP_INFO AcpiExDumpNode[7] = +{ + {ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpNode), NULL}, + {ACPI_EXD_UINT16, ACPI_EXD_NSOFFSET (Flags), "Flags"}, + {ACPI_EXD_UINT16, ACPI_EXD_NSOFFSET (OwnerId), "Owner Id"}, + {ACPI_EXD_LIST, ACPI_EXD_NSOFFSET (Object), "Object List"}, + {ACPI_EXD_NODE, ACPI_EXD_NSOFFSET (Parent), "Parent"}, + {ACPI_EXD_NODE, ACPI_EXD_NSOFFSET (Child), "Child"}, + {ACPI_EXD_NODE, ACPI_EXD_NSOFFSET (Peer), "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, + AcpiExDumpExtra, + AcpiExDumpData +}; + + +/******************************************************************************* + * + * 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; + const char *Name; + UINT8 Count; + ACPI_OPERAND_OBJECT *Start; + ACPI_OPERAND_OBJECT *Data = NULL; + ACPI_OPERAND_OBJECT *Next; + ACPI_NAMESPACE_NODE *Node; + + + 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) + { + if (!ObjDesc) + { + return; + } + + Target = ACPI_ADD_PTR (UINT8, ObjDesc, Info->Offset); + Name = Info->Name; + + switch (Info->Opcode) + { + case ACPI_EXD_INIT: + + break; + + case ACPI_EXD_TYPE: + + AcpiOsPrintf ("%20s : %2.2X [%s]\n", "Type", + ObjDesc->Common.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", AcpiUtGetReferenceName (ObjDesc)); + AcpiExDumpReferenceObj (ObjDesc); + break; + + case ACPI_EXD_LIST: + + Start = *ACPI_CAST_PTR (void *, Target); + Next = Start; + + AcpiOsPrintf ("%20s : %p ", Name, Next); + if (Next) + { + AcpiOsPrintf ("%s (Type %2.2X)", + AcpiUtGetObjectTypeName (Next), Next->Common.Type); + + while (Next->Common.NextObject) + { + if ((Next->Common.Type == ACPI_TYPE_LOCAL_DATA) && + !Data) + { + Data = Next; + } + + Next = Next->Common.NextObject; + AcpiOsPrintf ("->%p(%s %2.2X)", Next, + AcpiUtGetObjectTypeName (Next), Next->Common.Type); + + if ((Next == Start) || (Next == Data)) + { + AcpiOsPrintf ( + "\n**** Error: Object list appears to be circular linked"); + break; + } + } + } + else + { + AcpiOsPrintf ("- No attached objects"); + } + + AcpiOsPrintf ("\n"); + break; + + case ACPI_EXD_HDLR_LIST: + + Start = *ACPI_CAST_PTR (void *, Target); + Next = Start; + + AcpiOsPrintf ("%20s : %p", Name, Next); + if (Next) + { + AcpiOsPrintf ("(%s %2.2X)", + AcpiUtGetObjectTypeName (Next), + Next->AddressSpace.SpaceId); + + while (Next->AddressSpace.Next) + { + if ((Next->Common.Type == ACPI_TYPE_LOCAL_DATA) && + !Data) + { + Data = Next; + } + + Next = Next->AddressSpace.Next; + AcpiOsPrintf ("->%p(%s %2.2X)", Next, + AcpiUtGetObjectTypeName (Next), + Next->AddressSpace.SpaceId); + + if ((Next == Start) || (Next == Data)) + { + AcpiOsPrintf ( + "\n**** Error: Handler list appears to be circular linked"); + break; + } + } + } + + AcpiOsPrintf ("\n"); + break; + + case ACPI_EXD_RGN_LIST: + + Start = *ACPI_CAST_PTR (void *, Target); + Next = Start; + + AcpiOsPrintf ("%20s : %p", Name, Next); + if (Next) + { + AcpiOsPrintf ("(%s %2.2X)", + AcpiUtGetObjectTypeName (Next), Next->Common.Type); + + while (Next->Region.Next) + { + if ((Next->Common.Type == ACPI_TYPE_LOCAL_DATA) && + !Data) + { + Data = Next; + } + + Next = Next->Region.Next; + AcpiOsPrintf ("->%p(%s %2.2X)", Next, + AcpiUtGetObjectTypeName (Next), Next->Common.Type); + + if ((Next == Start) || (Next == Data)) + { + AcpiOsPrintf ( + "\n**** Error: Region list appears to be circular linked"); + break; + } + } + } + + AcpiOsPrintf ("\n"); + break; + + case ACPI_EXD_NODE: + + Node = *ACPI_CAST_PTR (ACPI_NAMESPACE_NODE *, Target); + + AcpiOsPrintf ("%20s : %p", Name, Node); + if (Node) + { + AcpiOsPrintf (" [%4.4s]", Node->Name.Ascii); + } + AcpiOsPrintf ("\n"); + 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); + + + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_EXEC, _COMPONENT)) + { + 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 Refs=%u ", + Depth, " ", Depth, ObjDesc, ObjDesc->Common.ReferenceCount)); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%p Refs=%u ", + ObjDesc, ObjDesc->Common.ReferenceCount)); + } + + /* 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: + + AcpiUtRepairName (ObjDesc->Reference.Node->Name.Ascii); + AcpiOsPrintf ("- [%4.4s] (Node %p)\n", + ObjDesc->Reference.Node->Name.Ascii, + ObjDesc->Reference.Node); + 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_UINT64 (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_TRACE (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_VOID; +} + + +/******************************************************************************* + * + * 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 ( + const char *Title, + const char *Value) +{ + AcpiOsPrintf ("%20s : %s\n", Title, Value); +} + +static void +AcpiExOutPointer ( + const char *Title, + const 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) + { + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_OBJECTS, _COMPONENT)) + { + return; + } + } + + AcpiOsPrintf ("%20s : %4.4s\n", "Name", AcpiUtGetNodeName (Node)); + AcpiOsPrintf ("%20s : %2.2X [%s]\n", "Type", + Node->Type, AcpiUtGetTypeName (Node->Type)); + + 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, TRUE); + if (ACPI_FAILURE (Status)) + { + AcpiOsPrintf (" Could not convert name to pathname: %s\n", + AcpiFormatException (Status)); + } + else + { + AcpiOsPrintf ("%s: %s\n", + AcpiUtGetTypeName (ObjDesc->Reference.Node->Type), + (char *) RetBuf.Pointer); + ACPI_FREE (RetBuf.Pointer); + } + } + else if (ObjDesc->Reference.Object) + { + if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND) + { + AcpiOsPrintf ("%22s %p", "Target :", + ObjDesc->Reference.Object); + if (ObjDesc->Reference.Class == ACPI_REFCLASS_TABLE) + { + AcpiOsPrintf (" Table Index: %X\n", + ObjDesc->Reference.Value); + } + else + { + AcpiOsPrintf (" [%s]\n", + 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: "); + AcpiUtPrintString (ObjDesc->String.Pointer, ACPI_UINT8_MAX); + AcpiOsPrintf ("\n"); + break; + + case ACPI_TYPE_BUFFER: + + AcpiOsPrintf ("[Buffer] Length %.2X = ", ObjDesc->Buffer.Length); + if (ObjDesc->Buffer.Length) + { + AcpiUtDebugDumpBuffer ( + 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] Class [%s]", + AcpiUtGetReferenceName (ObjDesc)); + AcpiExDumpReferenceObj (ObjDesc); + break; + + default: + + AcpiOsPrintf ("[%s] Type: %2.2X\n", + AcpiUtGetTypeName (ObjDesc->Common.Type), 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) + { + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_OBJECTS, _COMPONENT)) + { + return_VOID; + } + } + + if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_NAMED) + { + AcpiExDumpNamespaceNode ((ACPI_NAMESPACE_NODE *) ObjDesc, Flags); + + ObjDesc = ((ACPI_NAMESPACE_NODE *) ObjDesc)->Object; + if (!ObjDesc) + { + return_VOID; + } + + AcpiOsPrintf ("\nAttached Object %p", ObjDesc); + if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_NAMED) + { + AcpiOsPrintf (" - Namespace Node"); + } + + AcpiOsPrintf (":\n"); + goto DumpObject; + } + + if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) + { + AcpiOsPrintf ( + "%p is not an ACPI operand object: [%s]\n", + ObjDesc, AcpiUtGetDescriptorName (ObjDesc)); + return_VOID; + } + + /* Validate the object type */ + + if (ObjDesc->Common.Type > ACPI_TYPE_LOCAL_MAX) + { + AcpiOsPrintf ("Not a known object type: %2.2X\n", + ObjDesc->Common.Type); + return_VOID; + } + + +DumpObject: + + if (!ObjDesc) + { + return_VOID; + } + + /* Common Fields */ + + AcpiExDumpObject (ObjDesc, AcpiExDumpCommon); + + /* Object-specific fields */ + + AcpiExDumpObject (ObjDesc, AcpiExDumpInfo[ObjDesc->Common.Type]); + + if (ObjDesc->Common.Type == ACPI_TYPE_REGION) + { + ObjDesc = ObjDesc->Common.NextObject; + if (ObjDesc->Common.Type > ACPI_TYPE_LOCAL_MAX) + { + AcpiOsPrintf ( + "Secondary object is not a known object type: %2.2X\n", + ObjDesc->Common.Type); + + return_VOID; + } + + AcpiOsPrintf ("\nExtra attached Object (%p):\n", ObjDesc); + AcpiExDumpObject (ObjDesc, AcpiExDumpInfo[ObjDesc->Common.Type]); + } + + return_VOID; +} + +#endif diff --git a/code/drivers/platform/acpi/third_party/acpica/components/executer/exfield.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exfield.c new file mode 100644 index 0000000..25a5904 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exfield.c @@ -0,0 +1,465 @@ +/****************************************************************************** + * + * Module Name: exfield - AML execution - FieldUnit read/write + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exfield") + + +/* + * This table maps the various Attrib protocols to the byte transfer + * length. Used for the generic serial bus. + */ +#define ACPI_INVALID_PROTOCOL_ID 0x80 +#define ACPI_MAX_PROTOCOL_ID 0x0F + +static const UINT8 AcpiProtocolLengths[] = +{ + ACPI_INVALID_PROTOCOL_ID, /* 0 - reserved */ + ACPI_INVALID_PROTOCOL_ID, /* 1 - reserved */ + 0x00, /* 2 - ATTRIB_QUICK */ + ACPI_INVALID_PROTOCOL_ID, /* 3 - reserved */ + 0x01, /* 4 - ATTRIB_SEND_RECEIVE */ + ACPI_INVALID_PROTOCOL_ID, /* 5 - reserved */ + 0x01, /* 6 - ATTRIB_BYTE */ + ACPI_INVALID_PROTOCOL_ID, /* 7 - reserved */ + 0x02, /* 8 - ATTRIB_WORD */ + ACPI_INVALID_PROTOCOL_ID, /* 9 - reserved */ + 0xFF, /* A - ATTRIB_BLOCK */ + 0xFF, /* B - ATTRIB_BYTES */ + 0x02, /* C - ATTRIB_PROCESS_CALL */ + 0xFF, /* D - ATTRIB_BLOCK_PROCESS_CALL */ + 0xFF, /* E - ATTRIB_RAW_BYTES */ + 0xFF /* F - ATTRIB_RAW_PROCESS_BYTES */ +}; + +#define PCC_MASTER_SUBSPACE 3 + +/* + * The following macros determine a given offset is a COMD field. + * According to the specification, the PCC OperationRegion begins after + * the PCC signature. The raw shared memory COMD offsets of 4 for generic + * subspaces (types 0-2) and 12 for master subspaces (type 3) therefore + * appear at OperationRegion offsets 0 and 8. + */ +#define GENERIC_SUBSPACE_COMMAND(a) (0 == a || a == 1) +#define MASTER_SUBSPACE_COMMAND(a) (8 <= a && a <= 11) + +/******************************************************************************* + * + * FUNCTION: AcpiExGetProtocolBufferLength + * + * PARAMETERS: ProtocolId - The type of the protocol indicated by region + * field access attributes + * ReturnLength - Where the protocol byte transfer length is + * returned + * + * RETURN: Status and decoded byte transfer length + * + * DESCRIPTION: This routine returns the length of the GenericSerialBus + * protocol bytes + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExGetProtocolBufferLength ( + UINT32 ProtocolId, + UINT32 *ReturnLength) +{ + + if ((ProtocolId > ACPI_MAX_PROTOCOL_ID) || + (AcpiProtocolLengths[ProtocolId] == ACPI_INVALID_PROTOCOL_ID)) + { + ACPI_ERROR ((AE_INFO, + "Invalid Field/AccessAs protocol ID: 0x%4.4X", ProtocolId)); + + return (AE_AML_PROTOCOL); + } + + *ReturnLength = AcpiProtocolLengths[ProtocolId]; + return (AE_OK); +} + + +/******************************************************************************* + * + * 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 and whether if a + * field is created by the CreateField() operator. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExReadDataFromField ( + ACPI_WALK_STATE *WalkState, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **RetBufferDesc) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *BufferDesc; + void *Buffer; + UINT32 BufferLength; + + + 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 || + ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_PLATFORM_RT || + ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_FIXED_HARDWARE)) + { + /* SMBus, GSBus, IPMI serial */ + + Status = AcpiExReadSerialBus (ObjDesc, RetBufferDesc); + return_ACPI_STATUS (Status); + } + + /* + * 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. + * + * However, all buffer fields created by CreateField operator needs to + * remain as a buffer to match other AML interpreter implementations. + * + * Note: Field.length is in bits. + */ + BufferLength = (ACPI_SIZE) ACPI_ROUND_BITS_UP_TO_BYTES ( + ObjDesc->Field.BitLength); + + if (BufferLength > AcpiGbl_IntegerByteWidth || + (ObjDesc->Common.Type == ACPI_TYPE_BUFFER_FIELD && + ObjDesc->BufferField.IsCreateField)) + { + /* Field is too large for an Integer, create a Buffer instead */ + + BufferDesc = AcpiUtCreateBufferObject (BufferLength); + 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); + } + + BufferLength = AcpiGbl_IntegerByteWidth; + Buffer = &BufferDesc->Integer.Value; + } + + if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && + (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)) + { + /* General Purpose I/O */ + + Status = AcpiExReadGpio (ObjDesc, Buffer); + goto Exit; + } + else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && + (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_PLATFORM_COMM)) + { + /* + * Reading from a PCC field unit does not require the handler because + * it only requires reading from the InternalPccBuffer. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "PCC FieldRead bits %u\n", ObjDesc->Field.BitLength)); + + /* + * Ensure the field access does not exceed the bounds of the + * InternalPccBuffer. The buffer is allocated with the region length, + * so verify that BaseByteOffset + field byte length <= Region.Length. + */ + if (!ObjDesc->Field.RegionObj->Field.InternalPccBuffer) + { + Status = AE_AML_NO_OPERAND; + goto Exit; + } + + BufferLength = (ACPI_SIZE) ACPI_ROUND_BITS_UP_TO_BYTES ( + ObjDesc->Field.BitLength); + if (ObjDesc->Field.BaseByteOffset + BufferLength > + ObjDesc->Field.RegionObj->Region.Length) + { + ACPI_ERROR ((AE_INFO, + "PCC field at offset %u length %u exceeds region size %u", + ObjDesc->Field.BaseByteOffset, BufferLength, + ObjDesc->Field.RegionObj->Region.Length)); + Status = AE_AML_BUFFER_LIMIT; + goto Exit; + } + + memcpy (Buffer, ObjDesc->Field.RegionObj->Field.InternalPccBuffer + + ObjDesc->Field.BaseByteOffset, BufferLength); + + *RetBufferDesc = BufferDesc; + return AE_OK; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "FieldRead [TO]: Obj %p, Type %X, Buf %p, ByteLen %X\n", + ObjDesc, ObjDesc->Common.Type, Buffer, BufferLength)); + 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, BufferLength); + 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 BufferLength; + UINT32 DataLength; + void *Buffer; + + + 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_GPIO)) + { + /* General Purpose I/O */ + + Status = AcpiExWriteGpio (SourceDesc, ObjDesc, ResultDesc); + 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 || + ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_PLATFORM_RT || + ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_FIXED_HARDWARE)) + { + /* SMBus, GSBus, IPMI serial */ + + Status = AcpiExWriteSerialBus (SourceDesc, ObjDesc, ResultDesc); + return_ACPI_STATUS (Status); + } + else if ((ObjDesc->Common.Type == ACPI_TYPE_LOCAL_REGION_FIELD) && + (ObjDesc->Field.RegionObj->Region.SpaceId == ACPI_ADR_SPACE_PLATFORM_COMM)) + { + /* + * According to the spec a write to the COMD field will invoke the + * region handler. Otherwise, write to the PccInternal buffer. This + * implementation will use the offsets specified rather than the name + * of the field. This is considered safer because some firmware tools + * are known to obfiscate named objects. + * + * Ensure the field access does not exceed the bounds of the + * InternalPccBuffer. + */ + DataLength = (ACPI_SIZE) ACPI_ROUND_BITS_UP_TO_BYTES ( + ObjDesc->Field.BitLength); + + if (!ObjDesc->Field.RegionObj->Field.InternalPccBuffer) + { + return_ACPI_STATUS (AE_AML_NO_OPERAND); + } + + if (ObjDesc->Field.BaseByteOffset + DataLength > + ObjDesc->Field.RegionObj->Region.Length) + { + ACPI_ERROR ((AE_INFO, + "PCC field at offset %u length %u exceeds region size %u", + ObjDesc->Field.BaseByteOffset, DataLength, + ObjDesc->Field.RegionObj->Region.Length)); + return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); + } + + memcpy (ObjDesc->Field.RegionObj->Field.InternalPccBuffer + + ObjDesc->Field.BaseByteOffset, + SourceDesc->Buffer.Pointer, DataLength); + + if (MASTER_SUBSPACE_COMMAND (ObjDesc->Field.BaseByteOffset)) + { + /* Perform the write */ + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "PCC COMD field has been written. Invoking PCC handler now.\n")); + + Status = AcpiExAccessRegion ( + ObjDesc, 0, (UINT64 *) ObjDesc->Field.RegionObj->Field.InternalPccBuffer, + ACPI_WRITE); + return_ACPI_STATUS (Status); + } + return (AE_OK); + } + + + /* Get a pointer to the data to be written */ + + switch (SourceDesc->Common.Type) + { + case ACPI_TYPE_INTEGER: + + Buffer = &SourceDesc->Integer.Value; + BufferLength = sizeof (SourceDesc->Integer.Value); + break; + + case ACPI_TYPE_BUFFER: + + Buffer = SourceDesc->Buffer.Pointer; + BufferLength = SourceDesc->Buffer.Length; + break; + + case ACPI_TYPE_STRING: + + Buffer = SourceDesc->String.Pointer; + BufferLength = 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, BufferLength)); + + 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, BufferLength); + AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); + return_ACPI_STATUS (Status); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/executer/exfldio.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exfldio.c new file mode 100644 index 0000000..091e1be --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exfldio.c @@ -0,0 +1,1018 @@ +/****************************************************************************** + * + * Module Name: exfldio - Aml Field I/O + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 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 %8.8X%8.8X\n", + AcpiUtGetRegionName (RgnDesc->Region.SpaceId), + RgnDesc->Region.SpaceId, + ObjDesc->CommonField.AccessByteWidth, + ObjDesc->CommonField.BaseByteOffset, + FieldDatumByteOffset, + ACPI_FORMAT_UINT64 (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. + */ + 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. + */ + 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 + */ + + ACPI_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); + } + + 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)) + { + if (BufferLength >= sizeof (UINT64)) + { + Status = AcpiExFieldDatumIo (ObjDesc, 0, Buffer, ACPI_READ); + } + else + { + /* Use RawDatum (UINT64) to handle buffers < 64 bits */ + + Status = AcpiExFieldDatumIo (ObjDesc, 0, &RawDatum, ACPI_READ); + memcpy (Buffer, &RawDatum, BufferLength); + } + + 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 */ + + 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 */ + + 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. + */ + 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 */ + + WidthMask = ACPI_MASK_BITS_ABOVE_64 (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 */ + + 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; + 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/code/drivers/platform/acpi/third_party/acpica/components/executer/exmisc.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exmisc.c new file mode 100644 index 0000000..befd8a9 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exmisc.c @@ -0,0 +1,643 @@ +/****************************************************************************** + * + * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + ***************************************************************************** + * + * Alternatively, you may choose to be licensed under the terms of the + * following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, you may choose to be licensed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "amlcode.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, "Invalid Reference Class 0x%2.2X", + ObjDesc->Reference.Class)); + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + 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: 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_LOGICAL_AND_OP: /* LAnd (Integer0, Integer1) */ + + if (Integer0 && Integer1) + { + LocalResult = TRUE; + } + break; + + case AML_LOGICAL_OR_OP: /* LOr (Integer0, Integer1) */ + + if (Integer0 || Integer1) + { + LocalResult = TRUE; + } + break; + + default: + + ACPI_ERROR ((AE_INFO, + "Invalid numeric logical opcode: %X", Opcode)); + 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, + ACPI_IMPLICIT_CONVERSION); + 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 for logical operator: %X", + Operand0->Common.Type)); + 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_LOGICAL_EQUAL_OP: /* LEqual (Operand0, Operand1) */ + + if (Integer0 == Integer1) + { + LocalResult = TRUE; + } + break; + + case AML_LOGICAL_GREATER_OP: /* LGreater (Operand0, Operand1) */ + + if (Integer0 > Integer1) + { + LocalResult = TRUE; + } + break; + + case AML_LOGICAL_LESS_OP: /* LLess (Operand0, Operand1) */ + + if (Integer0 < Integer1) + { + LocalResult = TRUE; + } + break; + + default: + + ACPI_ERROR ((AE_INFO, + "Invalid comparison opcode: %X", Opcode)); + 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 = memcmp (Operand0->Buffer.Pointer, + LocalOperand1->Buffer.Pointer, + (Length0 > Length1) ? Length1 : Length0); + + switch (Opcode) + { + case AML_LOGICAL_EQUAL_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_LOGICAL_GREATER_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_LOGICAL_LESS_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: + + ACPI_ERROR ((AE_INFO, + "Invalid comparison opcode: %X", Opcode)); + 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/code/drivers/platform/acpi/third_party/acpica/components/executer/exmutex.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exmutex.c new file mode 100644 index 0000000..4c06df6 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exmutex.c @@ -0,0 +1,555 @@ +/****************************************************************************** + * + * Module Name: exmutex - ASL Mutex Acquire/Release functions + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Acquiring: Mutex SyncLevel %u, Thread SyncLevel %u, " + "Depth %u TID %p\n", + ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel, + ObjDesc->Mutex.AcquisitionDepth, WalkState->Thread)); + + 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); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Acquired: Mutex SyncLevel %u, Thread SyncLevel %u, Depth %u\n", + ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel, + ObjDesc->Mutex.AcquisitionDepth)); + + 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_ACPI_STATUS (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) +{ + UINT8 PreviousSyncLevel; + ACPI_THREAD_STATE *OwnerThread; + ACPI_STATUS Status = AE_OK; + + + 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; + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Releasing: Object SyncLevel %u, Thread SyncLevel %u, " + "Prev SyncLevel %u, Depth %u TID %p\n", + ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel, + PreviousSyncLevel, ObjDesc->Mutex.AcquisitionDepth, + WalkState->Thread)); + + Status = AcpiExReleaseMutexObject (ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (ObjDesc->Mutex.AcquisitionDepth == 0) + { + /* Restore the previous SyncLevel */ + + OwnerThread->CurrentSyncLevel = PreviousSyncLevel; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Released: Object SyncLevel %u, Thread SyncLevel, %u, " + "Prev SyncLevel %u, Depth %u\n", + ObjDesc->Mutex.SyncLevel, WalkState->Thread->CurrentSyncLevel, + PreviousSyncLevel, ObjDesc->Mutex.AcquisitionDepth)); + + 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_TRACE (ExReleaseAllMutexes); + + + /* Traverse the list of owned mutexes, releasing each one */ + + while (Next) + { + ObjDesc = Next; + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Mutex [%4.4s] force-release, SyncLevel %u Depth %u\n", + ObjDesc->Mutex.Node->Name.Ascii, ObjDesc->Mutex.SyncLevel, + ObjDesc->Mutex.AcquisitionDepth)); + + /* Release the mutex, special case for Global Lock */ + + if (ObjDesc == AcpiGbl_GlobalLockMutex) + { + /* Ignore errors */ + + (void) AcpiEvReleaseGlobalLock (); + } + else + { + AcpiOsReleaseMutex (ObjDesc->Mutex.OsMutex); + } + + /* Update Thread SyncLevel (Last mutex is the important one) */ + + Thread->CurrentSyncLevel = ObjDesc->Mutex.OriginalSyncLevel; + + /* Mark mutex unowned */ + + Next = ObjDesc->Mutex.Next; + + ObjDesc->Mutex.Prev = NULL; + ObjDesc->Mutex.Next = NULL; + ObjDesc->Mutex.AcquisitionDepth = 0; + ObjDesc->Mutex.OwnerThread = NULL; + ObjDesc->Mutex.ThreadId = 0; + } + + return_VOID; +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/executer/exnames.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exnames.c new file mode 100644 index 0000000..8ce650e --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exnames.c @@ -0,0 +1,447 @@ +/****************************************************************************** + * + * Module Name: exnames - interpreter/scanner name load/execute + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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_NAMESEG_SIZE * NumNameSegs) + 2 + 1; + } + else + { + SizeNeeded = PrefixCount + (ACPI_NAMESEG_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; + *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); + } + + for (Index = 0; + (Index < ACPI_NAMESEG_SIZE) && (AcpiUtValidNameChar (*AmlAddress, 0)); + Index++) + { + CharBuf[Index] = *AmlAddress++; + } + + + /* Valid name segment */ + + if (Index == 4) + { + /* Found 4 valid characters */ + + CharBuf[4] = '\0'; + + if (NameString) + { + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Appending NameSeg %s\n", CharBuf)); + strcat (NameString, CharBuf); + } + 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: + + 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/code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg1.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg1.c new file mode 100644 index 0000000..0de6b49 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg1.c @@ -0,0 +1,1131 @@ +/****************************************************************************** + * + * Module Name: exoparg1 - AML execution - opcodes with 1 argument + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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); +} + + +#ifdef _OBSOLETE_CODE /* Was originally used for Load() operator */ +/******************************************************************************* + * + * 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) + { +#ifdef _OBSOLETE_CODE + case AML_LOAD_OP: + + Status = AcpiExLoadOp (Operand[0], Operand[1], WalkState); + break; +#endif + + 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); +} +#endif + +/******************************************************************************* + * + * 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. + * January 2022: Added Load operator, with new ACPI 6.4 + * semantics. + * + ******************************************************************************/ + +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_LOAD_OP: + case AML_TO_BCD_OP: + case AML_CONDITIONAL_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_LOAD_OP: /* Result1 = Load (Operand[0], Result1) */ + + ReturnDesc->Integer.Value = 0; + Status = AcpiExLoadOp (Operand[0], ReturnDesc, WalkState); + if (ACPI_SUCCESS (Status)) + { + /* Return -1 (non-zero) indicates success */ + + ReturnDesc->Integer.Value = 0xFFFFFFFFFFFFFFFF; + } + 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_CONDITIONAL_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_OBJECT_OP: /* CopyObject (Source, Target) */ + + Status = AcpiUtCopyIobjectToIobject ( + Operand[0], &ReturnDesc, WalkState); + break; + + case AML_TO_DECIMAL_STRING_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_HEX_STRING_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) */ + + /* Perform "explicit" conversion */ + + Status = AcpiExConvertToInteger (Operand[0], &ReturnDesc, 0); + 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_LOGICAL_NOT_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_LOGICAL_NOT_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_OBJECT_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 = AcpiNsGetNodeUnlocked (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, or for references to device and + * thermal objects. + */ + switch (((ACPI_NAMESPACE_NODE *) Operand[0])->Type) + { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_THERMAL: + + /* These types have no node subobject, return the NS node */ + + ReturnDesc = Operand[0]; + break; + + default: + /* For most types, get the object attached to the node */ + + ReturnDesc = AcpiNsGetAttachedObject ( + (ACPI_NAMESPACE_NODE *) Operand[0]); + AcpiUtAddReference (ReturnDesc); + break; + } + } + 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) + { + /* + * Element is NULL, do not allow the dereference. + * This provides compatibility with other ACPI + * implementations. + */ + return_ACPI_STATUS (AE_AML_UNINITIALIZED_ELEMENT); + } + + 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); + if (!ReturnDesc) + { + break; + } + + /* + * June 2013: + * BufferFields/FieldUnits require additional resolution + */ + switch (ReturnDesc->Common.Type) + { + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + + Status = AcpiExReadDataFromField ( + WalkState, ReturnDesc, &TempDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ReturnDesc = TempDesc; + break; + + default: + + /* Add another reference to the object */ + + AcpiUtAddReference (ReturnDesc); + break; + } + } + 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/code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg2.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg2.c new file mode 100644 index 0000000..9f36ed0 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg2.c @@ -0,0 +1,612 @@ +/****************************************************************************** + * + * Module Name: exoparg2 - AML execution - opcodes with 2 arguments + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 = 0; + + + 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_CONCATENATE_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. + */ + while ((Length < Operand[0]->Buffer.Length) && /* Length of input buffer */ + (Length < Operand[1]->Integer.Value) && /* Length operand */ + (Operand[0]->Buffer.Pointer[Length])) /* Null terminator */ + { + 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) + */ + memcpy (ReturnDesc->String.Pointer, + Operand[0]->Buffer.Pointer, Length); + break; + + case AML_CONCATENATE_TEMPLATE_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) + { + Length = Operand[0]->String.Length; + Status = AE_AML_STRING_LIMIT; + } + + ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD; + ReturnDesc->Reference.IndexPointer = + &(Operand[0]->Buffer.Pointer [Index]); + break; + + case ACPI_TYPE_BUFFER: + + if (Index >= Operand[0]->Buffer.Length) + { + Length = Operand[0]->Buffer.Length; + Status = AE_AML_BUFFER_LIMIT; + } + + ReturnDesc->Reference.TargetType = ACPI_TYPE_BUFFER_FIELD; + ReturnDesc->Reference.IndexPointer = + &(Operand[0]->Buffer.Pointer [Index]); + break; + + case ACPI_TYPE_PACKAGE: + + if (Index >= Operand[0]->Package.Count) + { + Length = 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: + + ACPI_ERROR ((AE_INFO, + "Invalid object type: %X", (Operand[0])->Common.Type)); + Status = AE_AML_INTERNAL; + goto Cleanup; + } + + /* Failure means that the Index was beyond the end of the object */ + + if (ACPI_FAILURE (Status)) + { + ACPI_BIOS_EXCEPTION ((AE_INFO, Status, + "Index (0x%X%8.8X) is beyond end of object (length 0x%X)", + ACPI_FORMAT_UINT64 (Index), (UINT32) Length)); + 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/code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg3.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg3.c new file mode 100644 index 0000000..e42317a --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg3.c @@ -0,0 +1,417 @@ +/****************************************************************************** + * + * Module Name: exoparg3 - AML execution - opcodes with 3 arguments + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + ***************************************************************************** + * + * Alternatively, you may choose to be licensed under the terms of the + * following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, you may choose to be licensed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" +#include "acoutput.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_FUNCTION_TRACE_STR (ExOpcode_3A_0T_0R, + AcpiPsGetOpcodeName (WalkState->Opcode)); + + + switch (WalkState->Opcode) + { + case AML_FATAL_OP: /* Fatal (FatalType FatalCode FatalArg) */ + + Fatal.Type = (UINT32) Operand[0]->Integer.Value; + Fatal.Code = (UINT32) Operand[1]->Integer.Value; + Fatal.Argument = (UINT32) Operand[2]->Integer.Value; + + ACPI_BIOS_ERROR ((AE_INFO, + "Fatal ACPI BIOS error (Type 0x%X Code 0x%X Arg 0x%X)\n", + Fatal.Type, Fatal.Code, Fatal.Argument)); + + /* Always signal the OS! */ + + AcpiOsSignal (ACPI_SIGNAL_FATAL, &Fatal); + +#ifndef ACPI_CONTINUE_ON_FATAL + /* + * Might return while OS is shutting down, so abort the AML execution + * by returning an error. + */ + return_ACPI_STATUS (AE_ERROR); +#else + /* + * The alstests require that the Fatal() opcode does not return an error. + */ + return_ACPI_STATUS (AE_OK); +#endif + + case AML_EXTERNAL_OP: + /* + * If the interpreter sees this opcode, just ignore it. The External + * op is intended for use by disassemblers in order to properly + * disassemble control method invocations. The opcode or group of + * opcodes should be surrounded by an "if (0)" clause to ensure that + * AML interpreters never see the opcode. Thus, something is + * wrong if an external opcode ever gets here. + */ + ACPI_ERROR ((AE_INFO, "Executed External Op")); + + return_ACPI_STATUS (AE_OK); + + default: + + ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X", + WalkState->Opcode)); + + return_ACPI_STATUS (AE_AML_BAD_OPCODE); + } +} + + +/******************************************************************************* + * + * 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 || + (Index + Length) < Index) /* Check for overflow */ + { + 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 */ + + 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; + } + else + { + /* Set the return object and exit */ + + WalkState->ResultObj = ReturnDesc; + } + + return_ACPI_STATUS (Status); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg6.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg6.c new file mode 100644 index 0000000..85c1e2d --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exoparg6.c @@ -0,0 +1,465 @@ +/****************************************************************************** + * + * Module Name: exoparg6 - AML execution - opcodes with 6 arguments + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + ***************************************************************************** + * + * Alternatively, you may choose to be licensed under the terms of the + * following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, you may choose to be licensed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + *****************************************************************************/ + +#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_LOGICAL_EQUAL_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_LOGICAL_LESS_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_LOGICAL_GREATER_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_LOGICAL_GREATER_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_LOGICAL_LESS_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/code/drivers/platform/acpi/third_party/acpica/components/executer/exprep.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exprep.c new file mode 100644 index 0000000..e3d7714 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exprep.c @@ -0,0 +1,637 @@ +/****************************************************************************** + * + * Module Name: exprep - ACPI AML field prep utilities + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 object of type ACPI_OPERAND_OBJECT with a + * subtype of 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 == NULL) + { + break; + } + 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; + } + + ObjDesc->Field.PinNumberIndex = Info->PinNumberIndex; + + /* 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; + } + } + + 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/code/drivers/platform/acpi/third_party/acpica/components/executer/exregion.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exregion.c new file mode 100644 index 0000000..8a22f8e --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exregion.c @@ -0,0 +1,571 @@ +/****************************************************************************** + * + * Module Name: exregion - ACPI default OpRegion (address space) handlers + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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; + ACPI_MEM_MAPPING *Mm = MemInfo->CurMm; + UINT32 Length; + ACPI_SIZE MapLength; +#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 (!Mm || (Address < Mm->PhysicalAddress) || + ((UINT64) Address + Length > (UINT64) Mm->PhysicalAddress + Mm->Length)) + { + /* + * The request cannot be resolved by the current memory mapping. + * + * Look for an existing saved mapping covering the address range + * at hand. If found, save it as the current one and carry out + * the access. + */ + for (Mm = MemInfo->FirstMm; Mm; Mm = Mm->NextMm) + { + if (Mm == MemInfo->CurMm) + { + continue; + } + + if (Address < Mm->PhysicalAddress) + { + continue; + } + + if ((UINT64) Address + Length > (UINT64) Mm->PhysicalAddress + Mm->Length) + { + continue; + } + + MemInfo->CurMm = Mm; + goto access; + } + + /* Create a new mappings list entry */ + + Mm = ACPI_ALLOCATE_ZEROED(sizeof(*Mm)); + if (!Mm) + { + ACPI_ERROR((AE_INFO, + "Unable to save memory mapping at 0x%8.8X%8.8X, size %u", + ACPI_FORMAT_UINT64(Address), Length)); + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* + * 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 (MapLength > ACPI_DEFAULT_PAGE_SIZE) + { + MapLength = ACPI_DEFAULT_PAGE_SIZE; + } + + /* Create a new mapping starting at the address given */ + + LogicalAddrPtr = AcpiOsMapMemory(Address, MapLength); + if (!LogicalAddrPtr) + { + ACPI_ERROR ((AE_INFO, + "Could not map memory at 0x%8.8X%8.8X, size %u", + ACPI_FORMAT_UINT64 (Address), (UINT32) MapLength)); + ACPI_FREE(Mm); + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Save the physical address and mapping size */ + + Mm->LogicalAddress = LogicalAddrPtr; + Mm->PhysicalAddress = Address; + Mm->Length = MapLength; + + /* + * Add the new entry to the mappigs list and save it as the + * current mapping. + */ + Mm->NextMm = MemInfo->FirstMm; + MemInfo->FirstMm = Mm; + MemInfo->CurMm = Mm; + } + +access: + /* + * Generate a logical pointer corresponding to the address we want to + * access + */ + LogicalAddrPtr = Mm->LogicalAddress + + ((UINT64) Address - (UINT64) Mm->PhysicalAddress); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "System-Memory (width %u) R/W %u Address=%8.8X%8.8X\n", + BitWidth, Function, ACPI_FORMAT_UINT64 (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, *Value); + break; + + case 16: + + ACPI_SET16 (LogicalAddrPtr, *Value); + break; + + case 32: + + ACPI_SET32 (LogicalAddrPtr, *Value); + break; + + case 64: + + ACPI_SET64 (LogicalAddrPtr, *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_UINT64 (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_DATA_TABLE_MAPPING *Mapping; + char *Pointer; + + + ACPI_FUNCTION_TRACE (ExDataTableSpaceHandler); + + + Mapping = (ACPI_DATA_TABLE_MAPPING *) RegionContext; + Pointer = ACPI_CAST_PTR (char, Mapping->Pointer) + + (Address - ACPI_PTR_TO_PHYSADDR (Mapping->Pointer)); + + /* + * Perform the memory read or write. The BitWidth was already + * validated. + */ + switch (Function) + { + case ACPI_READ: + + memcpy (ACPI_CAST_PTR (char, Value), Pointer, ACPI_DIV_8 (BitWidth)); + break; + + case ACPI_WRITE: + + memcpy (Pointer, 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/code/drivers/platform/acpi/third_party/acpica/components/executer/exresnte.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exresnte.c new file mode 100644 index 0000000..0bb8b92 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exresnte.c @@ -0,0 +1,262 @@ +/****************************************************************************** + * + * Module Name: exresnte - AML Interpreter object resolution + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 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 [%4.4s] %p", + Node->Name.Ascii, Node)); + return_ACPI_STATUS (AE_AML_UNINITIALIZED_NODE); + } + + /* + * 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/code/drivers/platform/acpi/third_party/acpica/components/executer/exresolv.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exresolv.c new file mode 100644 index 0000000..d16cc61 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exresolv.c @@ -0,0 +1,563 @@ +/****************************************************************************** + * + * Module Name: exresolv - AML Interpreter object resolution + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 object of type 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_OBJECT_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 + */ + 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 = ACPI_CAST_PTR (void, Operand); + ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Operand); + 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 (Node); + + /* 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); + } + + switch (Type) + { + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_THERMAL: + + /* These types have no attached subobject */ + break; + + default: + + /* All other types require a subobject */ + + if (!ObjDesc) + { + ACPI_ERROR ((AE_INFO, + "[%4.4s] Node is unresolved or uninitialized", + AcpiUtGetNodeName (Node))); + return_ACPI_STATUS (AE_AML_UNINITIALIZED_NODE); + } + break; + } + 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/code/drivers/platform/acpi/third_party/acpica/components/executer/exresop.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exresop.c new file mode 100644 index 0000000..5780bb4 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exresop.c @@ -0,0 +1,702 @@ +/****************************************************************************** + * + * Module Name: exresop - AML Interpreter operand/object resolution + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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; + + ACPI_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 + */ + ACPI_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 */ + case ARGI_STORE_TARGET: + + /* + * 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. + * + * Known as "Implicit Source Operand Conversion" + */ + Status = AcpiExConvertToInteger (ObjDesc, StackPtr, + ACPI_IMPLICIT_CONVERSION); + 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/code/drivers/platform/acpi/third_party/acpica/components/executer/exserial.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exserial.c new file mode 100644 index 0000000..1b12b3b --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exserial.c @@ -0,0 +1,393 @@ +/****************************************************************************** + * + * Module Name: exserial - FieldUnit support for serial address spaces + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acdispat.h" +#include "acinterp.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("exserial") + + +/******************************************************************************* + * + * FUNCTION: AcpiExReadGpio + * + * PARAMETERS: ObjDesc - The named field to read + * Buffer - Where the return data is returned + * + * RETURN: Status + * + * DESCRIPTION: Read from a named field that references a Generic Serial Bus + * field + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExReadGpio ( + ACPI_OPERAND_OBJECT *ObjDesc, + void *Buffer) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE_PTR (ExReadGpio, ObjDesc); + + + /* + * For GPIO (GeneralPurposeIo), the Address will be the bit offset + * from the previous Connection() operator, making it effectively a + * pin number index. The BitLength is the length of the field, which + * is thus the number of pins. + */ + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "GPIO FieldRead [FROM]: Pin %u Bits %u\n", + ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength)); + + /* Lock entire transaction if requested */ + + AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); + + /* Perform the read */ + + Status = AcpiExAccessRegion ( + ObjDesc, 0, (UINT64 *) Buffer, ACPI_READ); + + AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExWriteGpio + * + * PARAMETERS: SourceDesc - Contains data to write. Expect to be + * an Integer object. + * ObjDesc - The named field + * ResultDesc - Where the return value is returned, if any + * + * RETURN: Status + * + * DESCRIPTION: Write to a named field that references a General Purpose I/O + * field. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExWriteGpio ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ReturnBuffer) +{ + ACPI_STATUS Status; + void *Buffer; + + + ACPI_FUNCTION_TRACE_PTR (ExWriteGpio, ObjDesc); + + + /* + * For GPIO (GeneralPurposeIo), we will bypass the entire field + * mechanism and handoff the bit address and bit width directly to + * the handler. The Address will be the bit offset + * from the previous Connection() operator, making it effectively a + * pin number index. The BitLength is the length of the field, which + * is thus the number of pins. + */ + if (SourceDesc->Common.Type != ACPI_TYPE_INTEGER) + { + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD, + "GPIO FieldWrite [FROM]: (%s:%X), Value %.8X [TO]: Pin %u Bits %u\n", + AcpiUtGetTypeName (SourceDesc->Common.Type), + SourceDesc->Common.Type, (UINT32) SourceDesc->Integer.Value, + ObjDesc->Field.PinNumberIndex, ObjDesc->Field.BitLength)); + + Buffer = &SourceDesc->Integer.Value; + + /* Lock entire transaction if requested */ + + AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); + + /* Perform the write */ + + Status = AcpiExAccessRegion ( + ObjDesc, 0, (UINT64 *) Buffer, ACPI_WRITE); + AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExReadSerialBus + * + * PARAMETERS: ObjDesc - The named field to read + * ReturnBuffer - Where the return value is returned, if any + * + * RETURN: Status + * + * DESCRIPTION: Read from a named field that references a serial bus + * (SMBus, IPMI, or GSBus). + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExReadSerialBus ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ReturnBuffer) +{ + ACPI_STATUS Status; + UINT32 BufferLength; + ACPI_OPERAND_OBJECT *BufferDesc; + UINT32 Function; + UINT16 AccessorType; + + + ACPI_FUNCTION_TRACE_PTR (ExReadSerialBus, ObjDesc); + + + /* + * 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 + * + * Common buffer format: + * Status; (Byte 0 of the data buffer) + * Length; (Byte 1 of the data buffer) + * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) + */ + switch (ObjDesc->Field.RegionObj->Region.SpaceId) + { + case ACPI_ADR_SPACE_SMBUS: + + BufferLength = ACPI_SMBUS_BUFFER_SIZE; + Function = ACPI_READ | (ObjDesc->Field.Attribute << 16); + break; + + case ACPI_ADR_SPACE_IPMI: + + BufferLength = ACPI_IPMI_BUFFER_SIZE; + Function = ACPI_READ; + break; + + case ACPI_ADR_SPACE_GSBUS: + + AccessorType = ObjDesc->Field.Attribute; + if (AccessorType == AML_FIELD_ATTRIB_RAW_PROCESS_BYTES) + { + ACPI_ERROR ((AE_INFO, + "Invalid direct read using bidirectional write-then-read protocol")); + + return_ACPI_STATUS (AE_AML_PROTOCOL); + } + + Status = AcpiExGetProtocolBufferLength (AccessorType, &BufferLength); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, + "Invalid protocol ID for GSBus: 0x%4.4X", AccessorType)); + + return_ACPI_STATUS (Status); + } + + /* Add header length to get the full size of the buffer */ + + BufferLength += ACPI_SERIAL_HEADER_SIZE; + Function = ACPI_READ | (AccessorType << 16); + break; + + case ACPI_ADR_SPACE_PLATFORM_RT: + + BufferLength = ACPI_PRM_INPUT_BUFFER_SIZE; + Function = ACPI_READ; + break; + + case ACPI_ADR_SPACE_FIXED_HARDWARE: + + BufferLength = ACPI_FFH_INPUT_BUFFER_SIZE; + Function = ACPI_READ; + break; + + default: + return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID); + } + + /* Create the local transfer buffer that is returned to the caller */ + + BufferDesc = AcpiUtCreateBufferObject (BufferLength); + if (!BufferDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Lock entire transaction if requested */ + + AcpiExAcquireGlobalLock (ObjDesc->CommonField.FieldFlags); + + /* Call the region handler for the write-then-read */ + + Status = AcpiExAccessRegion (ObjDesc, 0, + ACPI_CAST_PTR (UINT64, BufferDesc->Buffer.Pointer), Function); + AcpiExReleaseGlobalLock (ObjDesc->CommonField.FieldFlags); + + *ReturnBuffer = BufferDesc; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExWriteSerialBus + * + * PARAMETERS: SourceDesc - Contains data to write + * ObjDesc - The named field + * ReturnBuffer - Where the return value is returned, if any + * + * RETURN: Status + * + * DESCRIPTION: Write to a named field that references a serial bus + * (SMBus, IPMI, GSBus). + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExWriteSerialBus ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ReturnBuffer) +{ + ACPI_STATUS Status; + UINT32 BufferLength; + UINT32 DataLength; + void *Buffer; + ACPI_OPERAND_OBJECT *BufferDesc; + UINT32 Function; + UINT16 AccessorType; + + + ACPI_FUNCTION_TRACE_PTR (ExWriteSerialBus, ObjDesc); + + + /* + * 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 bidirectional; on a + * write, return data is returned in the same buffer. + * + * Source must be a buffer of sufficient size, these are fixed size: + * ACPI_SMBUS_BUFFER_SIZE, or ACPI_IPMI_BUFFER_SIZE. + * + * Note: SMBus and GSBus protocol type is passed in upper 16-bits + * of Function + * + * Common buffer format: + * Status; (Byte 0 of the data buffer) + * Length; (Byte 1 of the data buffer) + * Data[x-1]: (Bytes 2-x of the arbitrary length data buffer) + */ + 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); + } + + switch (ObjDesc->Field.RegionObj->Region.SpaceId) + { + case ACPI_ADR_SPACE_SMBUS: + + BufferLength = ACPI_SMBUS_BUFFER_SIZE; + Function = ACPI_WRITE | (ObjDesc->Field.Attribute << 16); + break; + + case ACPI_ADR_SPACE_IPMI: + + BufferLength = ACPI_IPMI_BUFFER_SIZE; + Function = ACPI_WRITE; + break; + + case ACPI_ADR_SPACE_GSBUS: + + AccessorType = ObjDesc->Field.Attribute; + Status = AcpiExGetProtocolBufferLength (AccessorType, &BufferLength); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, + "Invalid protocol ID for GSBus: 0x%4.4X", AccessorType)); + + return_ACPI_STATUS (Status); + } + + /* Add header length to get the full size of the buffer */ + + BufferLength += ACPI_SERIAL_HEADER_SIZE; + Function = ACPI_WRITE | (AccessorType << 16); + break; + + case ACPI_ADR_SPACE_PLATFORM_RT: + + BufferLength = ACPI_PRM_INPUT_BUFFER_SIZE; + Function = ACPI_WRITE; + break; + + case ACPI_ADR_SPACE_FIXED_HARDWARE: + + BufferLength = ACPI_FFH_INPUT_BUFFER_SIZE; + Function = ACPI_WRITE; + break; + + default: + return_ACPI_STATUS (AE_AML_INVALID_SPACE_ID); + } + + /* Create the transfer/bidirectional/return buffer */ + + BufferDesc = AcpiUtCreateBufferObject (BufferLength); + if (!BufferDesc) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Copy the input buffer data to the transfer buffer */ + + Buffer = BufferDesc->Buffer.Pointer; + DataLength = ACPI_MIN (BufferLength, SourceDesc->Buffer.Length); + memcpy (Buffer, SourceDesc->Buffer.Pointer, DataLength); + + /* 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); + + *ReturnBuffer = BufferDesc; + return_ACPI_STATUS (Status); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/executer/exstore.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exstore.c new file mode 100644 index 0000000..a005163 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exstore.c @@ -0,0 +1,630 @@ +/****************************************************************************** + * + * Module Name: exstore - AML Interpreter object store support + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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); + +static ACPI_STATUS +AcpiExStoreDirectToNode ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_NAMESPACE_NODE *Node, + ACPI_WALK_STATE *WalkState); + + +/******************************************************************************* + * + * FUNCTION: AcpiExStore + * + * PARAMETERS: *SourceDesc - Value to be stored + * *DestDesc - Where to store it. Must be an NS node + * or 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); + } + + ACPI_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: + + /* + * A zero-length buffer has no first element and a NULL + * Pointer (see AcpiUtCreateBufferObject). Reject it, as is + * done for the buffer-to-integer conversion. + */ + if (!SourceDesc->Buffer.Length) + { + ACPI_BIOS_EXCEPTION ((AE_INFO, AE_AML_BUFFER_LIMIT, + "Source is a zero-length buffer, no data to store")); + return_ACPI_STATUS (AE_AML_BUFFER_LIMIT); + } + + Value = SourceDesc->Buffer.Pointer[0]; + break; + + case ACPI_TYPE_STRING: + + /* A String always has a pointer; a null string stores a zero */ + + Value = (UINT8) SourceDesc->String.Pointer[0]; + break; + + default: + + /* All other types are invalid */ + + ACPI_ERROR ((AE_INFO, + "Source must be type [Integer/Buffer/String], found [%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 of type [Package/BufferField]")); + Status = AE_AML_TARGET_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. A CopyObject can change + * the target type, however. + * + * The ImplicitConversion flag is set to NO/FALSE only when + * storing to an ArgX -- as per the rules of the ACPI spec. + * + * 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] to node %p [%s]\n", + SourceDesc, AcpiUtGetObjectTypeName (SourceDesc), + Node, AcpiUtGetTypeName (TargetType))); + + /* Only limited target types possible for everything except CopyObject */ + + if (WalkState->Opcode != AML_COPY_OBJECT_OP) + { + /* + * Only CopyObject allows all object types to be overwritten. For + * TargetRef(s), there are restrictions on the object types that + * are allowed. + * + * Allowable operations/typing for Store: + * + * 1) Simple Store + * Integer --> Integer (Named/Local/Arg) + * String --> String (Named/Local/Arg) + * Buffer --> Buffer (Named/Local/Arg) + * Package --> Package (Named/Local/Arg) + * + * 2) Store with implicit conversion + * Integer --> String or Buffer (Named) + * String --> Integer or Buffer (Named) + * Buffer --> Integer or String (Named) + */ + switch (TargetType) + { + case ACPI_TYPE_PACKAGE: + /* + * Here, can only store a package to an existing package. + * Storing a package to a Local/Arg is OK, and handled + * elsewhere. + */ + if (WalkState->Opcode == AML_STORE_OP) + { + if (SourceDesc->Common.Type != ACPI_TYPE_PACKAGE) + { + ACPI_ERROR ((AE_INFO, + "Cannot assign type [%s] to [Package] " + "(source must be type Pkg)", + AcpiUtGetObjectTypeName (SourceDesc))); + + return_ACPI_STATUS (AE_AML_TARGET_TYPE); + } + break; + } + + ACPI_FALLTHROUGH; + + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_EVENT: + case ACPI_TYPE_MUTEX: + case ACPI_TYPE_REGION: + case ACPI_TYPE_POWER: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + + ACPI_ERROR ((AE_INFO, + "Target must be [Buffer/Integer/String/Reference]" + ", found [%s] (%4.4s)", + AcpiUtGetTypeName (Node->Type), Node->Name.Ascii)); + + return_ACPI_STATUS (AE_AML_TARGET_TYPE); + + default: + break; + } + } + + /* + * 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); + } + + /* Do the actual store operation */ + + switch (TargetType) + { + /* + * The simple data types all support implicit source operand + * conversion before the store. + */ + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + + if ((WalkState->Opcode == AML_COPY_OBJECT_OP) || + !ImplicitConversion) + { + /* + * However, CopyObject and Stores to ArgX do not perform + * an implicit conversion, as per the ACPI specification. + * A direct store is performed instead. + */ + Status = AcpiExStoreDirectToNode (SourceDesc, Node, WalkState); + break; + } + + /* Store with implicit source operand conversion support */ + + 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 type [%s] into [%s] via Convert/Attach\n", + AcpiUtGetObjectTypeName (SourceDesc), + AcpiUtGetObjectTypeName (NewDesc))); + } + break; + + case ACPI_TYPE_BUFFER_FIELD: + case ACPI_TYPE_LOCAL_REGION_FIELD: + case ACPI_TYPE_LOCAL_BANK_FIELD: + case ACPI_TYPE_LOCAL_INDEX_FIELD: + /* + * For all fields, always write the source data to the target + * field. Any required implicit source operand conversion is + * performed in the function below as necessary. Note, field + * objects must retain their original type permanently. + */ + Status = AcpiExWriteDataToField (SourceDesc, TargetDesc, + &WalkState->ResultObj); + break; + + default: + /* + * CopyObject operator: No conversions for all other types. + * Instead, directly store a copy of the source object. + * + * This is the ACPI spec-defined behavior for the CopyObject + * operator. (Note, for this default case, all normal + * Store/Target operations exited above with an error). + */ + Status = AcpiExStoreDirectToNode (SourceDesc, Node, WalkState); + break; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExStoreDirectToNode + * + * PARAMETERS: SourceDesc - Value to be stored + * Node - Named object to receive the value + * WalkState - Current walk state + * + * RETURN: Status + * + * DESCRIPTION: "Store" an object directly to a node. This involves a copy + * and an attach. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiExStoreDirectToNode ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_NAMESPACE_NODE *Node, + ACPI_WALK_STATE *WalkState) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *NewDesc; + + + ACPI_FUNCTION_TRACE (ExStoreDirectToNode); + + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Storing [%s] (%p) directly into node [%s] (%p)" + " with no implicit conversion\n", + AcpiUtGetObjectTypeName (SourceDesc), SourceDesc, + AcpiUtGetTypeName (Node->Type), Node)); + + /* Copy the source object to a new object */ + + Status = AcpiUtCopyIobjectToIobject (SourceDesc, &NewDesc, WalkState); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Attach the new object to the node */ + + Status = AcpiNsAttachObject (Node, NewDesc, NewDesc->Common.Type); + AcpiUtRemoveReference (NewDesc); + return_ACPI_STATUS (Status); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/executer/exstoren.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exstoren.c new file mode 100644 index 0000000..89dc04f --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exstoren.c @@ -0,0 +1,274 @@ +/****************************************************************************** + * + * Module Name: exstoren - AML Interpreter object store support, + * Store to Node (namespace object) + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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_OBJECT_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 */ + + (void) 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/code/drivers/platform/acpi/third_party/acpica/components/executer/exstorob.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exstorob.c new file mode 100644 index 0000000..746302f --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exstorob.c @@ -0,0 +1,210 @@ +/****************************************************************************** + * + * Module Name: exstorob - AML object store support, store to object + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 */ + + memset (TargetDesc->Buffer.Pointer, 0, TargetDesc->Buffer.Length); + 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 */ + + 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 + */ + memset (TargetDesc->String.Pointer, 0, + (ACPI_SIZE) TargetDesc->String.Length + 1); + 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; + memcpy (TargetDesc->String.Pointer, Buffer, Length); + } + + /* Set the new target length */ + + TargetDesc->String.Length = Length; + return_ACPI_STATUS (AE_OK); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/executer/exsystem.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exsystem.c new file mode 100644 index 0000000..2369b1b --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exsystem.c @@ -0,0 +1,324 @@ +/****************************************************************************** + * + * Module Name: exsystem - Interface to OS services + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 */ + + AcpiExExitInterpreter (); + Status = AcpiOsWaitSemaphore (Semaphore, 1, Timeout); + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "*** Thread awake after blocking, %s\n", + AcpiFormatException (Status))); + + /* Reacquire the interpreter */ + + AcpiExEnterInterpreter (); + } + + 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 */ + + AcpiExExitInterpreter (); + Status = AcpiOsAcquireMutex (Mutex, Timeout); + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "*** Thread awake after blocking, %s\n", + AcpiFormatException (Status))); + + /* Reacquire the interpreter */ + + AcpiExEnterInterpreter (); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExSystemDoStall + * + * PARAMETERS: HowLongUs - 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 HowLongUs) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_ENTRY (); + + + if (HowLongUs > 255) + { + /* + * Longer than 255 microseconds, this is an error + * + * (ACPI specifies 100 usec as max, but this gives some slack in + * order to support existing BIOSs) + */ + ACPI_ERROR_ONCE ((AE_INFO, + "Time parameter is too large (%u)", HowLongUs)); + Status = AE_AML_OPERAND_VALUE; + } + else + { + if (HowLongUs > 100) + { + ACPI_WARNING_ONCE ((AE_INFO, + "Time parameter %u us > 100 us violating ACPI spec, please fix the firmware.", HowLongUs)); + } + AcpiOsStall (HowLongUs); + } + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExSystemDoSleep + * + * PARAMETERS: HowLongMs - The amount of time to sleep, + * in milliseconds + * + * RETURN: None + * + * DESCRIPTION: Sleep the running thread for specified amount of time. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiExSystemDoSleep ( + UINT64 HowLongMs) +{ + ACPI_FUNCTION_ENTRY (); + + + /* Since this thread will sleep, we must release the interpreter */ + + AcpiExExitInterpreter (); + + /* + * For compatibility with other ACPI implementations and to prevent + * accidental deep sleeps, limit the sleep time to something reasonable. + */ + if (HowLongMs > ACPI_MAX_SLEEP) + { + HowLongMs = ACPI_MAX_SLEEP; + } + + AcpiOsSleep (HowLongMs); + + /* And now we must get the interpreter again */ + + AcpiExEnterInterpreter (); + 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/code/drivers/platform/acpi/third_party/acpica/components/executer/extrace.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/extrace.c new file mode 100644 index 0000000..7952ed8 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/extrace.c @@ -0,0 +1,431 @@ +/****************************************************************************** + * + * Module Name: extrace - Support for interpreter execution tracing + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acinterp.h" + + +#define _COMPONENT ACPI_EXECUTER + ACPI_MODULE_NAME ("extrace") + + +static ACPI_OPERAND_OBJECT *AcpiGbl_TraceMethodObject = NULL; + +/* Local prototypes */ + +#ifdef ACPI_DEBUG_OUTPUT +static const char * +AcpiExGetTraceEventName ( + ACPI_TRACE_EVENT_TYPE Type); +#endif + + +/******************************************************************************* + * + * FUNCTION: AcpiExInterpreterTraceEnabled + * + * PARAMETERS: Name - Whether method name should be matched, + * this should be checked before starting + * the tracer + * + * RETURN: TRUE if interpreter trace is enabled. + * + * DESCRIPTION: Check whether interpreter trace is enabled + * + ******************************************************************************/ + +static BOOLEAN +AcpiExInterpreterTraceEnabled ( + char *Name) +{ + + /* Check if tracing is enabled */ + + if (!(AcpiGbl_TraceFlags & ACPI_TRACE_ENABLED)) + { + return (FALSE); + } + + /* + * Check if tracing is filtered: + * + * 1. If the tracer is started, AcpiGbl_TraceMethodObject should have + * been filled by the trace starter + * 2. If the tracer is not started, AcpiGbl_TraceMethodName should be + * matched if it is specified + * 3. If the tracer is oneshot style, AcpiGbl_TraceMethodName should + * not be cleared by the trace stopper during the first match + */ + if (AcpiGbl_TraceMethodObject) + { + return (TRUE); + } + + if (Name && + (AcpiGbl_TraceMethodName && + strcmp (AcpiGbl_TraceMethodName, Name))) + { + return (FALSE); + } + + if ((AcpiGbl_TraceFlags & ACPI_TRACE_ONESHOT) && + !AcpiGbl_TraceMethodName) + { + return (FALSE); + } + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExGetTraceEventName + * + * PARAMETERS: Type - Trace event type + * + * RETURN: Trace event name. + * + * DESCRIPTION: Used to obtain the full trace event name. + * + ******************************************************************************/ + +#ifdef ACPI_DEBUG_OUTPUT + +static const char * +AcpiExGetTraceEventName ( + ACPI_TRACE_EVENT_TYPE Type) +{ + + switch (Type) + { + case ACPI_TRACE_AML_METHOD: + + return "Method"; + + case ACPI_TRACE_AML_OPCODE: + + return "Opcode"; + + case ACPI_TRACE_AML_REGION: + + return "Region"; + + default: + + return ""; + } +} + +#endif + +/******************************************************************************* + * + * FUNCTION: AcpiExTraceArgs + * + * PARAMETERS: Params - AML method arguments + * Count - number of method arguments + * + * RETURN: None + * + * DESCRIPTION: Trace any arguments + * + ******************************************************************************/ + +void +AcpiExTraceArgs(ACPI_OPERAND_OBJECT **Params, UINT32 Count) +{ + UINT32 i; + + ACPI_FUNCTION_NAME(ExTraceArgs); + + for (i = 0; i < Count; i++) + { + ACPI_OPERAND_OBJECT *obj_desc = Params[i]; + + if (!i) + { + ACPI_DEBUG_PRINT((ACPI_DB_TRACE_POINT, " ")); + } + + switch (obj_desc->Common.Type) + { + case ACPI_TYPE_INTEGER: + ACPI_DEBUG_PRINT_RAW((ACPI_DB_TRACE_POINT, "%lx", obj_desc->Integer.Value)); + break; + + case ACPI_TYPE_STRING: + if (!obj_desc->String.Length) + { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_TRACE_POINT, "NULL")); + break; + } + if (ACPI_IS_DEBUG_ENABLED(ACPI_LV_TRACE_POINT, _COMPONENT)) + { + AcpiUtPrintString(obj_desc->String.Pointer, ACPI_UINT8_MAX); + } + break; + + default: + ACPI_DEBUG_PRINT_RAW((ACPI_DB_TRACE_POINT, "Unknown")); + break; + } + + if ((i + 1) == Count) + { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_TRACE_POINT, "\n")); + } + else + { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_TRACE_POINT, ", ")); + } + } +} + +/******************************************************************************* + * + * FUNCTION: AcpiExTracePoint + * + * PARAMETERS: Type - Trace event type + * Begin - TRUE if before execution + * Aml - Executed AML address + * Pathname - Object path + * + * RETURN: None + * + * DESCRIPTION: Internal interpreter execution trace. + * + ******************************************************************************/ + +void +AcpiExTracePoint ( + ACPI_TRACE_EVENT_TYPE Type, + BOOLEAN Begin, + UINT8 *Aml, + char *Pathname) +{ + + ACPI_FUNCTION_NAME (ExTracePoint); + + + if (Pathname) + { + ACPI_DEBUG_PRINT ((ACPI_DB_TRACE_POINT, + "%s %s [%s] execution.\n", + AcpiExGetTraceEventName (Type), Begin ? "Begin" : "End", + Pathname)); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_TRACE_POINT, + "%s %s [0x%p] execution.\n", + AcpiExGetTraceEventName (Type), Begin ? "Begin" : "End", + Aml)); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExStartTraceMethod + * + * PARAMETERS: MethodNode - Node of the method + * ObjDesc - The method object + * WalkState - current state, NULL if not yet executing + * a method. + * + * RETURN: None + * + * DESCRIPTION: Start control method execution trace + * + ******************************************************************************/ + +void +AcpiExStartTraceMethod ( + ACPI_NAMESPACE_NODE *MethodNode, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState) +{ + char *Pathname = NULL; + BOOLEAN Enabled = FALSE; + + + ACPI_FUNCTION_NAME (ExStartTraceMethod); + + + if (MethodNode) + { + Pathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE); + } + + Enabled = AcpiExInterpreterTraceEnabled (Pathname); + if (Enabled && !AcpiGbl_TraceMethodObject) + { + AcpiGbl_TraceMethodObject = ObjDesc; + AcpiGbl_OriginalDbgLevel = AcpiDbgLevel; + AcpiGbl_OriginalDbgLayer = AcpiDbgLayer; + AcpiDbgLevel = ACPI_TRACE_LEVEL_ALL; + AcpiDbgLayer = ACPI_TRACE_LAYER_ALL; + + if (AcpiGbl_TraceDbgLevel) + { + AcpiDbgLevel = AcpiGbl_TraceDbgLevel; + } + + if (AcpiGbl_TraceDbgLayer) + { + AcpiDbgLayer = AcpiGbl_TraceDbgLayer; + } + } + + if (Enabled) + { + ACPI_TRACE_POINT (ACPI_TRACE_AML_METHOD, TRUE, + ObjDesc ? ObjDesc->Method.AmlStart : NULL, Pathname); + } + + if (Pathname) + { + ACPI_FREE (Pathname); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExStopTraceMethod + * + * PARAMETERS: MethodNode - Node of the method + * ObjDesc - The method object + * WalkState - current state, NULL if not yet executing + * a method. + * + * RETURN: None + * + * DESCRIPTION: Stop control method execution trace + * + ******************************************************************************/ + +void +AcpiExStopTraceMethod ( + ACPI_NAMESPACE_NODE *MethodNode, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState) +{ + char *Pathname = NULL; + BOOLEAN Enabled; + + + ACPI_FUNCTION_NAME (ExStopTraceMethod); + + + if (MethodNode) + { + Pathname = AcpiNsGetNormalizedPathname (MethodNode, TRUE); + } + + Enabled = AcpiExInterpreterTraceEnabled (NULL); + + if (Enabled) + { + ACPI_TRACE_POINT (ACPI_TRACE_AML_METHOD, FALSE, + ObjDesc ? ObjDesc->Method.AmlStart : NULL, Pathname); + } + + /* Check whether the tracer should be stopped */ + + if (AcpiGbl_TraceMethodObject == ObjDesc) + { + /* Disable further tracing if type is one-shot */ + + if (AcpiGbl_TraceFlags & ACPI_TRACE_ONESHOT) + { + AcpiGbl_TraceMethodName = NULL; + } + + AcpiDbgLevel = AcpiGbl_OriginalDbgLevel; + AcpiDbgLayer = AcpiGbl_OriginalDbgLayer; + AcpiGbl_TraceMethodObject = NULL; + } + + if (Pathname) + { + ACPI_FREE (Pathname); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExStartTraceOpcode + * + * PARAMETERS: Op - The parser opcode object + * WalkState - current state, NULL if not yet executing + * a method. + * + * RETURN: None + * + * DESCRIPTION: Start opcode execution trace + * + ******************************************************************************/ + +void +AcpiExStartTraceOpcode ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState) +{ + + ACPI_FUNCTION_NAME (ExStartTraceOpcode); + + + if (AcpiExInterpreterTraceEnabled (NULL) && + (AcpiGbl_TraceFlags & ACPI_TRACE_OPCODE)) + { + ACPI_TRACE_POINT (ACPI_TRACE_AML_OPCODE, TRUE, + Op->Common.Aml, Op->Common.AmlOpName); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExStopTraceOpcode + * + * PARAMETERS: Op - The parser opcode object + * WalkState - current state, NULL if not yet executing + * a method. + * + * RETURN: None + * + * DESCRIPTION: Stop opcode execution trace + * + ******************************************************************************/ + +void +AcpiExStopTraceOpcode ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState) +{ + + ACPI_FUNCTION_NAME (ExStopTraceOpcode); + + + if (AcpiExInterpreterTraceEnabled (NULL) && + (AcpiGbl_TraceFlags & ACPI_TRACE_OPCODE)) + { + ACPI_TRACE_POINT (ACPI_TRACE_AML_OPCODE, FALSE, + Op->Common.Aml, Op->Common.AmlOpName); + } +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/executer/exutils.c b/code/drivers/platform/acpi/third_party/acpica/components/executer/exutils.c new file mode 100644 index 0000000..bdb1a1a --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/executer/exutils.c @@ -0,0 +1,477 @@ +/****************************************************************************** + * + * Module Name: exutils - interpreter/scanner utilities + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +/* + * 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); + + +/******************************************************************************* + * + * 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")); + } + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, "Could not acquire AML Namespace mutex")); + } + + 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, or when the method blocks. + * + * Cases where the interpreter is unlocked internally: + * 1) Method will be blocked on a Sleep() AML opcode + * 2) Method will be blocked on an Acquire() AML opcode + * 3) Method will be blocked on a Wait() AML opcode + * 4) Method will be blocked to acquire the global lock + * 5) Method will be blocked waiting to execute a serialized control + * method that is currently executing + * 6) About to invoke a user-installed opregion handler + * + ******************************************************************************/ + +void +AcpiExExitInterpreter ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (ExExitInterpreter); + + + Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, "Could not release AML Namespace mutex")); + } + Status = AcpiUtReleaseMutex (ACPI_MTX_INTERPRETER); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, "Could not release AML Interpreter mutex")); + } + + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiExTruncateFor32bitTable + * + * PARAMETERS: ObjDesc - Object to be truncated + * + * RETURN: TRUE if a truncation was performed, FALSE otherwise. + * + * DESCRIPTION: Truncate an ACPI Integer to 32 bits if the execution mode is + * 32-bit, as determined by the revision of the DSDT. + * + ******************************************************************************/ + +BOOLEAN +AcpiExTruncateFor32bitTable ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + + ACPI_FUNCTION_ENTRY (); + + + /* + * Object must be a valid number and we must be executing + * a control method. Object could be NS node for AML_INT_NAMEPATH_OP. + */ + if ((!ObjDesc) || + (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) || + (ObjDesc->Common.Type != ACPI_TYPE_INTEGER)) + { + return (FALSE); + } + + if ((AcpiGbl_IntegerByteWidth == 4) && + (ObjDesc->Integer.Value > (UINT64) ACPI_UINT32_MAX)) + { + /* + * We are executing 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; + return (TRUE); + } + + return (FALSE); +} + + +/******************************************************************************* + * + * 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 specify 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: OutString - Where to put the converted string (8 bytes) + * CompressedId - EISAID to be converted + * + * 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: Converted string in OutString + * + * 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: AcpiExPciClsToString + * + * PARAMETERS: OutString - Where to put the converted string (7 bytes) + * ClassCode - PCI class code to be converted (3 bytes) + * + * RETURN: Converted string in OutString + * + * DESCRIPTION: Convert 3-bytes PCI class code to string representation. + * Return buffer must be large enough to hold the string. The + * string returned is always exactly of length + * ACPI_PCICLS_STRING_SIZE (includes null terminator). + * + ******************************************************************************/ + +void +AcpiExPciClsToString ( + char *OutString, + UINT8 ClassCode[3]) +{ + + ACPI_FUNCTION_ENTRY (); + + + /* All 3 bytes are hexadecimal */ + + OutString[0] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[0], 4); + OutString[1] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[0], 0); + OutString[2] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[1], 4); + OutString[3] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[1], 0); + OutString[4] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[2], 4); + OutString[5] = AcpiUtHexToAsciiChar ((UINT64) ClassCode[2], 0); + OutString[6] = 0; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiIsValidSpaceId + * + * PARAMETERS: SpaceId - ID to be validated + * + * RETURN: TRUE if SpaceId is a 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); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwacpi.c b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwacpi.c new file mode 100644 index 0000000..1b599e8 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwacpi.c @@ -0,0 +1,191 @@ +/****************************************************************************** + * + * Module Name: hwacpi - ACPI Hardware Initialization/Mode Interface + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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); + + + /* If the Hardware Reduced flag is set, machine is always in acpi mode */ + + if (AcpiGbl_ReducedHardware) + { + return_ACPI_STATUS (AE_OK); + } + + /* + * 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 (ACPI_USEC_PER_MSEC); + 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); + + + /* If the Hardware Reduced flag is set, machine is always in acpi mode */ + + if (AcpiGbl_ReducedHardware) + { + return_UINT32 (ACPI_SYS_MODE_ACPI); + } + + /* + * 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/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwesleep.c b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwesleep.c new file mode 100644 index 0000000..4d3df12 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwesleep.c @@ -0,0 +1,238 @@ +/****************************************************************************** + * + * Name: hwesleep.c - ACPI Hardware Sleep/Wake Support functions for the + * extended FADT-V5 sleep registers. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_HARDWARE + ACPI_MODULE_NAME ("hwesleep") + + +/******************************************************************************* + * + * FUNCTION: AcpiHwExecuteSleepMethod + * + * PARAMETERS: MethodPathname - 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 *MethodPathname, + 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, MethodPathname, &ArgList, NULL); + if (ACPI_FAILURE (Status) && Status != AE_NOT_FOUND) + { + ACPI_EXCEPTION ((AE_INFO, Status, "While executing method %s", + MethodPathname)); + } + + 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 SleepControl; + 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 ((UINT64) ACPI_X_WAKE_STATUS, + &AcpiGbl_FADT.SleepStatus); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + AcpiGbl_SystemAwakeAndRunning = FALSE; + + /* + * 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)); + + SleepControl = ((AcpiGbl_SleepTypeA << ACPI_X_SLEEP_TYPE_POSITION) & + ACPI_X_SLEEP_TYPE_MASK) | ACPI_X_SLEEP_ENABLE; + + /* Flush caches, as per ACPI specification */ + + if (SleepState < ACPI_STATE_S4) + { + ACPI_FLUSH_CPU_CACHE (); + } + + Status = AcpiOsEnterSleep (SleepState, SleepControl, 0); + if (Status == AE_CTRL_TERMINATE) + { + return_ACPI_STATUS (AE_OK); + } + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiWrite ((UINT64) SleepControl, &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) +{ + UINT8 SleepTypeValue; + + + ACPI_FUNCTION_TRACE (HwExtendedWakePrep); + + + if (AcpiGbl_SleepTypeAS0 != ACPI_SLEEP_TYPE_INVALID) + { + SleepTypeValue = ((AcpiGbl_SleepTypeAS0 << ACPI_X_SLEEP_TYPE_POSITION) & + ACPI_X_SLEEP_TYPE_MASK); + + (void) AcpiWrite ((UINT64) (SleepTypeValue | ACPI_X_SLEEP_ENABLE), + &AcpiGbl_FADT.SleepControl); + } + + 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_PATHNAME__SST, ACPI_SST_WAKING); + AcpiHwExecuteSleepMethod (METHOD_PATHNAME__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 ((UINT64) ACPI_X_WAKE_STATUS, &AcpiGbl_FADT.SleepStatus); + AcpiGbl_SystemAwakeAndRunning = TRUE; + + AcpiHwExecuteSleepMethod (METHOD_PATHNAME__SST, ACPI_SST_WORKING); + return_ACPI_STATUS (AE_OK); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwgpe.c b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwgpe.c new file mode 100644 index 0000000..b02139f --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwgpe.c @@ -0,0 +1,659 @@ +/****************************************************************************** + * + * Module Name: hwgpe - Low level GPE enable/disable/clear functions + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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); + +static ACPI_STATUS +AcpiHwGpeEnableWrite ( + UINT8 EnableMask, + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo); + + +/****************************************************************************** + * + * FUNCTION: AcpiHwGetGpeRegisterBit + * + * PARAMETERS: GpeEventInfo - Info block for the GPE + * + * 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) +{ + + return ((UINT32) 1 << + (GpeEventInfo->GpeNumber - GpeEventInfo->RegisterInfo->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. + * The EnableMask field of the involved GPE register must be + * updated by the caller if necessary. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwLowSetGpe ( + ACPI_GPE_EVENT_INFO *GpeEventInfo, + UINT32 Action) +{ + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; + ACPI_STATUS Status = AE_OK; + UINT64 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); + switch (Action) + { + case ACPI_GPE_CONDITIONAL_ENABLE: + + /* Only enable if the corresponding EnableMask bit is set */ + + if (!(RegisterBit & GpeRegisterInfo->EnableMask)) + { + return (AE_BAD_PARAMETER); + } + + ACPI_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", Action)); + return (AE_BAD_PARAMETER); + } + + if (!(RegisterBit & GpeRegisterInfo->MaskForRun)) + { + /* 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); + + 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) +{ + UINT64 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); + } + + /* GPE currently handled? */ + + if (ACPI_GPE_DISPATCH_TYPE (GpeEventInfo->Flags) != + ACPI_GPE_DISPATCH_NONE) + { + LocalEventStatus |= ACPI_EVENT_FLAG_HAS_HANDLER; + } + + /* Get the info block for the entire GPE register */ + + GpeRegisterInfo = GpeEventInfo->RegisterInfo; + + /* Get the register bitmask for this GPE */ + + RegisterBit = AcpiHwGetGpeRegisterBit (GpeEventInfo); + + /* GPE currently enabled? (enabled for runtime?) */ + + if (RegisterBit & GpeRegisterInfo->EnableForRun) + { + LocalEventStatus |= ACPI_EVENT_FLAG_ENABLED; + } + + /* GPE currently masked? (masked for runtime?) */ + + if (RegisterBit & GpeRegisterInfo->MaskForRun) + { + LocalEventStatus |= ACPI_EVENT_FLAG_MASKED; + } + + /* GPE enabled for wake? */ + + if (RegisterBit & GpeRegisterInfo->EnableForWake) + { + LocalEventStatus |= ACPI_EVENT_FLAG_WAKE_ENABLED; + } + + /* GPE currently enabled (enable bit == 1)? */ + + Status = AcpiHwRead (&InByte, &GpeRegisterInfo->EnableAddress); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + if (RegisterBit & InByte) + { + LocalEventStatus |= ACPI_EVENT_FLAG_ENABLE_SET; + } + + /* GPE currently active (status bit == 1)? */ + + Status = AcpiHwRead (&InByte, &GpeRegisterInfo->StatusAddress); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + if (RegisterBit & InByte) + { + LocalEventStatus |= ACPI_EVENT_FLAG_STATUS_SET; + } + + /* Set return value */ + + (*EventStatus) = LocalEventStatus; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwGpeEnableWrite + * + * PARAMETERS: EnableMask - Bit mask to write to the GPE register + * GpeRegisterInfo - Gpe Register info + * + * RETURN: Status + * + * DESCRIPTION: Write the enable mask byte to the given GPE register. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiHwGpeEnableWrite ( + UINT8 EnableMask, + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo) +{ + ACPI_STATUS Status; + + + GpeRegisterInfo->EnableMask = EnableMask; + + Status = AcpiHwWrite (EnableMask, &GpeRegisterInfo->EnableAddress); + return (Status); +} + + +/****************************************************************************** + * + * 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 = AcpiHwGpeEnableWrite (0x00, &GpeBlock->RegisterInfo[i]); + 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; + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; + UINT8 EnableMask; + + + /* NOTE: assumes that all GPEs are currently disabled */ + + /* Examine each GPE Register within the block */ + + for (i = 0; i < GpeBlock->RegisterCount; i++) + { + GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; + if (!GpeRegisterInfo->EnableForRun) + { + continue; + } + + /* Enable all "runtime" GPEs in this register */ + + EnableMask = GpeRegisterInfo->EnableForRun & + ~GpeRegisterInfo->MaskForRun; + Status = AcpiHwGpeEnableWrite (EnableMask, GpeRegisterInfo); + 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; + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; + + + /* Examine each GPE Register within the block */ + + for (i = 0; i < GpeBlock->RegisterCount; i++) + { + GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; + + /* + * Enable all "wake" GPEs in this register and disable the + * remaining ones. + */ + Status = AcpiHwGpeEnableWrite (GpeRegisterInfo->EnableForWake, + GpeRegisterInfo); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwGetGpeBlockStatus + * + * PARAMETERS: GpeXruptInfo - GPE Interrupt info + * GpeBlock - Gpe Block info + * + * RETURN: Success + * + * DESCRIPTION: Produce a combined GPE status bits mask for the given block. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiHwGetGpeBlockStatus( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *RetPtr) +{ + ACPI_GPE_REGISTER_INFO *GpeRegisterInfo; + UINT64 InEnable; + UINT64 InStatus; + ACPI_STATUS Status; + UINT8 *Ret = RetPtr; + UINT32 i; + + + /* Examine each GPE Register within the block */ + + for (i = 0; i < GpeBlock->RegisterCount; i++) + { + GpeRegisterInfo = &GpeBlock->RegisterInfo[i]; + + Status = AcpiHwRead (&InEnable, &GpeRegisterInfo->EnableAddress); + if (ACPI_FAILURE (Status)) + { + continue; + } + + Status = AcpiHwRead (&InStatus, &GpeRegisterInfo->StatusAddress); + if (ACPI_FAILURE (Status)) + { + continue; + } + + *Ret |= InEnable & InStatus; + } + + 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); + 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); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiHwCheckAllGpes + * + * PARAMETERS: None + * + * RETURN: Combined status of all GPEs + * + * DESCRIPTION: Check all enabled GPEs in all GPE blocks and return TRUE if the + * status bit is set for at least one of them of FALSE otherwise. + * + ******************************************************************************/ + +UINT8 +AcpiHwCheckAllGpes ( + void) +{ + UINT8 Ret = 0; + + + ACPI_FUNCTION_TRACE (AcpiHwCheckAllGpes); + + (void) AcpiEvWalkGpeList (AcpiHwGetGpeBlockStatus, &Ret); + return (Ret != 0); +} + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwpci.c b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwpci.c new file mode 100644 index 0000000..00c3c80 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwpci.c @@ -0,0 +1,433 @@ +/******************************************************************************* + * + * Module Name: hwpci - Obtain PCI bus, device, and function numbers + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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; + + + 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); + + /* 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; + + + /* + * 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. + */ + *ReturnListHead = NULL; + CurrentDevice = PciRegion; + while (1) + { + Status = AcpiGetParent (CurrentDevice, &ParentDevice); + if (ACPI_FAILURE (Status)) + { + /* Must delete the list before exit */ + + AcpiHwDeletePciList (*ReturnListHead); + return (Status); + } + + /* Finished when we reach the PCI root device (PNP0A03 or PNP0A08) */ + + if (ParentDevice == RootPciDevice) + { + return (AE_OK); + } + + ListElement = ACPI_ALLOCATE (sizeof (ACPI_PCI_DEVICE)); + if (!ListElement) + { + /* Must delete the list before exit */ + + AcpiHwDeletePciList (*ReturnListHead); + return (AE_NO_MEMORY); + } + + /* Put new element at the head of the list */ + + ListElement->Next = *ReturnListHead; + ListElement->Device = ParentDevice; + *ReturnListHead = 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 (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 (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/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwregs.c b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwregs.c new file mode 100644 index 0000000..8e6fa86 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwregs.c @@ -0,0 +1,874 @@ +/******************************************************************************* + * + * Module Name: hwregs - Read/write access functions for the various ACPI + * control and status registers. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acevents.h" + +#define _COMPONENT ACPI_HARDWARE + ACPI_MODULE_NAME ("hwregs") + + +#if (!ACPI_REDUCED_HARDWARE) + +/* Local Prototypes */ + +static UINT8 +AcpiHwGetAccessBitWidth ( + UINT64 Address, + ACPI_GENERIC_ADDRESS *Reg, + UINT8 MaxBitWidth); + +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: AcpiHwGetAccessBitWidth + * + * PARAMETERS: Address - GAS register address + * Reg - GAS register structure + * MaxBitWidth - Max BitWidth supported (32 or 64) + * + * RETURN: Status + * + * DESCRIPTION: Obtain optimal access bit width + * + ******************************************************************************/ + +static UINT8 +AcpiHwGetAccessBitWidth ( + UINT64 Address, + ACPI_GENERIC_ADDRESS *Reg, + UINT8 MaxBitWidth) +{ + UINT8 AccessBitWidth; + + + /* + * GAS format "register", used by FADT: + * 1. Detected if BitOffset is 0 and BitWidth is 8/16/32/64; + * 2. AccessSize field is ignored and BitWidth field is used for + * determining the boundary of the IO accesses. + * GAS format "region", used by APEI registers: + * 1. Detected if BitOffset is not 0 or BitWidth is not 8/16/32/64; + * 2. AccessSize field is used for determining the boundary of the + * IO accesses; + * 3. BitOffset/BitWidth fields are used to describe the "region". + * + * Note: This algorithm assumes that the "Address" fields should always + * contain aligned values. + */ + if (!Reg->BitOffset && Reg->BitWidth && + ACPI_IS_POWER_OF_TWO (Reg->BitWidth) && + ACPI_IS_ALIGNED (Reg->BitWidth, 8)) + { + AccessBitWidth = Reg->BitWidth; + } + else if (Reg->AccessWidth) + { + AccessBitWidth = ACPI_ACCESS_BIT_WIDTH (Reg->AccessWidth); + } + else + { + AccessBitWidth = ACPI_ROUND_UP_POWER_OF_TWO_8 ( + Reg->BitOffset + Reg->BitWidth); + if (AccessBitWidth <= 8) + { + AccessBitWidth = 8; + } + else + { + while (!ACPI_IS_ALIGNED (Address, AccessBitWidth >> 3)) + { + AccessBitWidth >>= 1; + } + } + } + + /* Maximum IO port access bit width is 32 */ + + if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_IO) + { + MaxBitWidth = 32; + } + + /* + * Return access width according to the requested maximum access bit width, + * as the caller should know the format of the register and may enforce + * a 32-bit accesses. + */ + if (AccessBitWidth < MaxBitWidth) + { + return (AccessBitWidth); + } + return (MaxBitWidth); +} + + +/****************************************************************************** + * + * 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) +{ + UINT8 BitWidth; + UINT8 AccessWidth; + + + /* 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 AccessWidth */ + + if (Reg->AccessWidth > 4) + { + ACPI_ERROR ((AE_INFO, + "Unsupported register access width: 0x%X", Reg->AccessWidth)); + return (AE_SUPPORT); + } + + /* Validate the BitWidth, convert AccessWidth into number of bits */ + + AccessWidth = AcpiHwGetAccessBitWidth (*Address, Reg, MaxBitWidth); + BitWidth = ACPI_ROUND_UP (Reg->BitOffset + Reg->BitWidth, AccessWidth); + if (MaxBitWidth < BitWidth) + { + ACPI_WARNING ((AE_INFO, + "Requested bit width 0x%X is smaller than register bit width 0x%X", + MaxBitWidth, BitWidth)); + return (AE_SUPPORT); + } + + 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 64-bit max + * version of AcpiRead. + * + * LIMITATIONS: + * SpaceID must be SystemMemory or SystemIO. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwRead ( + UINT64 *Value, + ACPI_GENERIC_ADDRESS *Reg) +{ + UINT64 Address; + UINT8 AccessWidth; + UINT32 BitWidth; + UINT8 BitOffset; + UINT64 Value64; + UINT32 Value32; + UINT8 Index; + ACPI_STATUS Status; + + + ACPI_FUNCTION_NAME (HwRead); + + + /* Validate contents of the GAS register */ + + Status = AcpiHwValidateRegister (Reg, 64, &Address); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* + * Initialize entire 64-bit return value to zero, convert AccessWidth + * into number of bits based + */ + *Value = 0; + AccessWidth = AcpiHwGetAccessBitWidth (Address, Reg, 64); + BitWidth = Reg->BitOffset + Reg->BitWidth; + BitOffset = Reg->BitOffset; + + /* + * Two address spaces supported: Memory or IO. PCI_Config is + * not supported here because the GAS structure is insufficient + */ + Index = 0; + while (BitWidth) + { + if (BitOffset >= AccessWidth) + { + Value64 = 0; + BitOffset -= AccessWidth; + } + else + { + if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) + { + Status = AcpiOsReadMemory ((ACPI_PHYSICAL_ADDRESS) + Address + Index * ACPI_DIV_8 (AccessWidth), + &Value64, AccessWidth); + } + else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ + { + Status = AcpiHwReadPort ((ACPI_IO_ADDRESS) + Address + Index * ACPI_DIV_8 (AccessWidth), + &Value32, AccessWidth); + Value64 = (UINT64) Value32; + } + } + + /* + * Use offset style bit writes because "Index * AccessWidth" is + * ensured to be less than 64-bits by AcpiHwValidateRegister(). + */ + ACPI_SET_BITS (Value, Index * AccessWidth, + ACPI_MASK_BITS_ABOVE_64 (AccessWidth), Value64); + + BitWidth -= BitWidth > AccessWidth ? AccessWidth : BitWidth; + Index++; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_IO, + "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n", + ACPI_FORMAT_UINT64 (*Value), AccessWidth, + 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 64-bit max + * version of AcpiWrite. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiHwWrite ( + UINT64 Value, + ACPI_GENERIC_ADDRESS *Reg) +{ + UINT64 Address; + UINT8 AccessWidth; + UINT32 BitWidth; + UINT8 BitOffset; + UINT64 Value64; + UINT8 Index; + ACPI_STATUS Status; + + + ACPI_FUNCTION_NAME (HwWrite); + + + /* Validate contents of the GAS register */ + + Status = AcpiHwValidateRegister (Reg, 64, &Address); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Convert AccessWidth into number of bits based */ + + AccessWidth = AcpiHwGetAccessBitWidth (Address, Reg, 64); + BitWidth = Reg->BitOffset + Reg->BitWidth; + BitOffset = Reg->BitOffset; + + /* + * Two address spaces supported: Memory or IO. PCI_Config is + * not supported here because the GAS structure is insufficient + */ + Index = 0; + while (BitWidth) + { + /* + * Use offset style bit reads because "Index * AccessWidth" is + * ensured to be less than 64-bits by AcpiHwValidateRegister(). + */ + Value64 = ACPI_GET_BITS (&Value, Index * AccessWidth, + ACPI_MASK_BITS_ABOVE_64 (AccessWidth)); + + if (BitOffset >= AccessWidth) + { + BitOffset -= AccessWidth; + } + else + { + if (Reg->SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) + { + Status = AcpiOsWriteMemory ((ACPI_PHYSICAL_ADDRESS) + Address + Index * ACPI_DIV_8 (AccessWidth), + Value64, AccessWidth); + } + else /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ + { + Status = AcpiHwWritePort ((ACPI_IO_ADDRESS) + Address + Index * ACPI_DIV_8 (AccessWidth), + (UINT32) Value64, AccessWidth); + } + } + + /* + * Index * AccessWidth is ensured to be less than 32-bits by + * AcpiHwValidateRegister(). + */ + BitWidth -= BitWidth > AccessWidth ? AccessWidth : BitWidth; + Index++; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_IO, + "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n", + ACPI_FORMAT_UINT64 (Value), AccessWidth, + 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); + + AcpiOsReleaseLock (AcpiGbl_HardwareLock, LockFlags); + + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + + /* Clear the GPE Bits in all GPE registers in all GPE blocks */ + + Status = AcpiEvWalkGpeList (AcpiHwClearGpeBlock, NULL); + +Exit: + 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 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; + UINT64 Value64; + 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 (&Value64, &AcpiGbl_FADT.XPm2ControlBlock); + if (ACPI_SUCCESS (Status)) + { + Value = (UINT32) Value64; + } + break; + + case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ + + Status = AcpiHwRead (&Value64, &AcpiGbl_FADT.XPmTimerBlock); + if (ACPI_SUCCESS (Status)) + { + Value = (UINT32) Value64; + } + + 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 = (UINT32) 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; + UINT64 ReadValue64; + + + 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 (&ReadValue64, &AcpiGbl_FADT.XPm2ControlBlock); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + ReadValue = (UINT32) ReadValue64; + + /* 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; + UINT64 Value64; + ACPI_STATUS Status; + + + /* The first register is always required */ + + Status = AcpiHwRead (&Value64, RegisterA); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + ValueA = (UINT32) Value64; + + /* Second register is optional */ + + if (RegisterB->Address) + { + Status = AcpiHwRead (&Value64, RegisterB); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + ValueB = (UINT32) Value64; + } + + /* + * 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/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwsleep.c b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwsleep.c new file mode 100644 index 0000000..4dd6697 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwsleep.c @@ -0,0 +1,344 @@ +/****************************************************************************** + * + * Name: hwsleep.c - ACPI Hardware Sleep/Wake Support functions for the + * original/legacy sleep/PM registers. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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); + } + + /* Disable all GPEs */ + + Status = AcpiHwDisableAllGpes (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + Status = AcpiHwClearAcpiStatus(); + if (ACPI_FAILURE(Status)) + { + return_ACPI_STATUS(Status); + } + AcpiGbl_SystemAwakeAndRunning = FALSE; + + /* Enable all wakeup GPEs */ + + Status = AcpiHwEnableAllWakeupGpes (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* 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 */ + + if (SleepState < ACPI_STATE_S4) + { + ACPI_FLUSH_CPU_CACHE (); + } + + Status = AcpiOsEnterSleep (SleepState, Pm1aControl, Pm1bControl); + if (Status == AE_CTRL_TERMINATE) + { + return_ACPI_STATUS (AE_OK); + } + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* 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 (10 * ACPI_USEC_PER_SEC); + + 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 = AE_OK; + 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. + */ + if (AcpiGbl_SleepTypeAS0 != ACPI_SLEEP_TYPE_INVALID) + { + 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_SleepTypeAS0 << + SleepTypeRegInfo->BitPosition); + Pm1bControl |= (AcpiGbl_SleepTypeBS0 << + SleepTypeRegInfo->BitPosition); + + /* Write the control registers and ignore any errors */ + + (void) AcpiHwWritePm1Control (Pm1aControl, Pm1bControl); + } + } + + 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_PATHNAME__SST, ACPI_SST_WAKING); + + /* + * GPEs must be enabled before _WAK is called as GPEs + * might get fired there + * + * Restore the GPEs: + * 1) Disable 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_PATHNAME__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 sleep button */ + + (void) AcpiWriteBitRegister ( + AcpiGbl_FixedEventInfo[ACPI_EVENT_SLEEP_BUTTON].EnableRegisterId, + ACPI_ENABLE_EVENT); + + (void) AcpiWriteBitRegister ( + AcpiGbl_FixedEventInfo[ACPI_EVENT_SLEEP_BUTTON].StatusRegisterId, + ACPI_CLEAR_STATUS); + + AcpiHwExecuteSleepMethod (METHOD_PATHNAME__SST, ACPI_SST_WORKING); + return_ACPI_STATUS (Status); +} + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwtimer.c b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwtimer.c new file mode 100644 index 0000000..29bec9e --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwtimer.c @@ -0,0 +1,210 @@ +/****************************************************************************** + * + * Name: hwtimer.c - ACPI Power Management Timer Interface + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#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; + UINT64 TimerValue; + + + ACPI_FUNCTION_TRACE (AcpiGetTimer); + + + if (!Ticks) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* ACPI 5.0A: PM Timer is optional */ + + if (!AcpiGbl_FADT.XPmTimerBlock.Address) + { + return_ACPI_STATUS (AE_SUPPORT); + } + + Status = AcpiHwRead (&TimerValue, &AcpiGbl_FADT.XPmTimerBlock); + if (ACPI_SUCCESS (Status)) + { + /* ACPI PM Timer is defined to be 32 bits (PM_TMR_LEN) */ + + *Ticks = (UINT32) TimerValue; + } + + 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; + UINT64 DeltaTicks; + UINT64 Quotient; + + + ACPI_FUNCTION_TRACE (AcpiGetTimerDuration); + + + if (!TimeElapsed) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* ACPI 5.0A: PM Timer is optional */ + + if (!AcpiGbl_FADT.XPmTimerBlock.Address) + { + return_ACPI_STATUS (AE_SUPPORT); + } + + if (StartTicks == EndTicks) + { + *TimeElapsed = 0; + return_ACPI_STATUS (AE_OK); + } + + /* + * Compute Tick Delta: + * Handle (max one) timer rollovers on 24-bit versus 32-bit timers. + */ + DeltaTicks = EndTicks; + if (StartTicks > EndTicks) + { + if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0) + { + /* 24-bit Timer */ + + DeltaTicks |= (UINT64) 1 << 24; + } + else + { + /* 32-bit Timer */ + + DeltaTicks |= (UINT64) 1 << 32; + } + } + DeltaTicks -= StartTicks; + + /* + * Compute Duration (Requires a 64-bit multiply and divide): + * + * TimeElapsed (microseconds) = + * (DeltaTicks * ACPI_USEC_PER_SEC) / ACPI_PM_TIMER_FREQUENCY; + */ + Status = AcpiUtShortDivide (DeltaTicks * ACPI_USEC_PER_SEC, + ACPI_PM_TIMER_FREQUENCY, &Quotient, NULL); + + *TimeElapsed = (UINT32) Quotient; + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetTimerDuration) + +#endif /* !ACPI_REDUCED_HARDWARE */ diff --git a/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwvalid.c b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwvalid.c new file mode 100644 index 0000000..70b800a --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwvalid.c @@ -0,0 +1,334 @@ +/****************************************************************************** + * + * Module Name: hwvalid - I/O request validation + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 nothing newer than + * the specific _OSI strings. + * + * 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_ACPI_STATUS (AE_BAD_PARAMETER); + } + + PortInfo = AcpiProtectedPorts; + ByteWidth = ACPI_DIV_8 (BitWidth); + LastAddress = Address + ByteWidth - 1; + + ACPI_DEBUG_PRINT ((ACPI_DB_IO, + "Address %8.8X%8.8X LastAddress %8.8X%8.8X Length %X", + ACPI_FORMAT_UINT64 (Address), ACPI_FORMAT_UINT64 (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: %8.8X%8.8X/0x%X", + ACPI_FORMAT_UINT64 (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. There are 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 (PortInfo->OsiDependency == ACPI_ALWAYS_ILLEGAL || + AcpiGbl_OsiData == PortInfo->OsiDependency) + { + ACPI_DEBUG_PRINT ((ACPI_DB_VALUES, + "Denied AML access to port 0x%8.8X%8.8X/%X (%s 0x%.4X-0x%.4X)\n", + ACPI_FORMAT_UINT64 (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 (data) is returned + * 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 compatibility with other ACPI implementations. + */ + 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 compatibility with other ACPI implementations. + */ + 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/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwxface.c b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwxface.c new file mode 100644 index 0000000..4797d62 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwxface.c @@ -0,0 +1,508 @@ +/****************************************************************************** + * + * Module Name: hwxface - Public ACPICA hardware interfaces + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#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. + * + * NOTE: + * The ACPI spec requires the reset register width to be 8, so we + * hardcode it here and ignore the FADT value. This maintains + * compatibility with other ACPI implementations that have allowed + * BIOS code with bad register width values to go unnoticed. + */ + Status = AcpiOsWritePort ((ACPI_IO_ADDRESS) ResetReg->Address, + AcpiGbl_FADT.ResetValue, ACPI_RESET_REGISTER_WIDTH); + } + 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) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_NAME (AcpiRead); + + + Status = AcpiHwRead (ReturnValue, Reg); + 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) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_NAME (AcpiWrite); + + + Status = AcpiHwWrite (Value, Reg); + 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 automatically + * 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 + * + * DESCRIPTION: Obtain the SLP_TYPa and SLP_TYPb values for the requested + * sleep state via the appropriate \_Sx object. + * + * The sleep state package returned from the corresponding \_Sx_ object + * must contain at least one integer. + * + * March 2005: + * Added support for a package that contains two integers. This + * goes against the ACPI specification which defines this object as a + * package with one encoded DWORD integer. However, existing practice + * by many BIOS vendors is to return a package with 2 or more integer + * elements, at least one per sleep type (A/B). + * + * January 2013: + * Therefore, we must be prepared to accept a package with either a + * single integer or multiple integers. + * + * The single integer DWORD format is as follows: + * BYTE 0 - Value for the PM1A SLP_TYP register + * BYTE 1 - Value for the PM1B SLP_TYP register + * BYTE 2-3 - Reserved + * + * The dual integer format is as follows: + * Integer 0 - Value for the PM1A SLP_TYP register + * Integer 1 - Value for the PM1A SLP_TYP register + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetSleepTypeData ( + UINT8 SleepState, + UINT8 *SleepTypeA, + UINT8 *SleepTypeB) +{ + ACPI_STATUS Status; + ACPI_EVALUATE_INFO *Info; + ACPI_OPERAND_OBJECT **Elements; + + + 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); + } + + /* + * Evaluate the \_Sx namespace object containing the register values + * for this state + */ + Info->RelativePathname = AcpiGbl_SleepStateNames[SleepState]; + + Status = AcpiNsEvaluate (Info); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_NOT_FOUND) + { + /* The _Sx states are optional, ignore NOT_FOUND */ + + goto FinalCleanup; + } + + goto WarningCleanup; + } + + /* Must have a return object */ + + if (!Info->ReturnObject) + { + ACPI_ERROR ((AE_INFO, "No Sleep State object returned from [%s]", + Info->RelativePathname)); + Status = AE_AML_NO_RETURN_VALUE; + goto WarningCleanup; + } + + /* Return object must be of type Package */ + + 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; + goto ReturnValueCleanup; + } + + /* + * Any warnings about the package length or the object types have + * already been issued by the predefined name module -- there is no + * need to repeat them here. + */ + Elements = Info->ReturnObject->Package.Elements; + switch (Info->ReturnObject->Package.Count) + { + case 0: + + Status = AE_AML_PACKAGE_LIMIT; + break; + + case 1: + + if (Elements[0]->Common.Type != ACPI_TYPE_INTEGER) + { + Status = AE_AML_OPERAND_TYPE; + break; + } + + /* A valid _Sx_ package with one integer */ + + *SleepTypeA = (UINT8) Elements[0]->Integer.Value; + *SleepTypeB = (UINT8) (Elements[0]->Integer.Value >> 8); + break; + + case 2: + default: + + if ((Elements[0]->Common.Type != ACPI_TYPE_INTEGER) || + (Elements[1]->Common.Type != ACPI_TYPE_INTEGER)) + { + Status = AE_AML_OPERAND_TYPE; + break; + } + + /* A valid _Sx_ package with two integers */ + + *SleepTypeA = (UINT8) Elements[0]->Integer.Value; + *SleepTypeB = (UINT8) Elements[1]->Integer.Value; + break; + } + +ReturnValueCleanup: + AcpiUtRemoveReference (Info->ReturnObject); + +WarningCleanup: + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "While evaluating Sleep State [%s]", + Info->RelativePathname)); + } + +FinalCleanup: + ACPI_FREE (Info); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetSleepTypeData) diff --git a/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwxfsleep.c b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwxfsleep.c new file mode 100644 index 0000000..16202d6 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/hardware/hwxfsleep.c @@ -0,0 +1,485 @@ +/****************************************************************************** + * + * Name: hwxfsleep.c - ACPI Hardware Sleep/Wake External Interfaces + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_HARDWARE + ACPI_MODULE_NAME ("hwxfsleep") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiHwSetFirmwareWakingVector ( + ACPI_TABLE_FACS *Facs, + ACPI_PHYSICAL_ADDRESS PhysicalAddress, + ACPI_PHYSICAL_ADDRESS PhysicalAddress64); + +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_STRUCT_INIT (LegacyFunction, + ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacySleep)), + ACPI_STRUCT_INIT (ExtendedFunction, + AcpiHwExtendedSleep) }, + {ACPI_STRUCT_INIT (LegacyFunction, + ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacyWakePrep)), + ACPI_STRUCT_INIT (ExtendedFunction, + AcpiHwExtendedWakePrep) }, + {ACPI_STRUCT_INIT (LegacyFunction, + ACPI_HW_OPTIONAL_FUNCTION (AcpiHwLegacyWake)), + ACPI_STRUCT_INIT (ExtendedFunction, + AcpiHwExtendedWake) } +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiHwSetFirmwareWakingVector + * + * PARAMETERS: Facs - Pointer to FACS table + * PhysicalAddress - 32-bit physical address of ACPI real mode + * entry point + * PhysicalAddress64 - 64-bit physical address of ACPI protected + * mode entry point + * + * RETURN: Status + * + * DESCRIPTION: Sets the FirmwareWakingVector fields of the FACS + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiHwSetFirmwareWakingVector ( + ACPI_TABLE_FACS *Facs, + ACPI_PHYSICAL_ADDRESS PhysicalAddress, + ACPI_PHYSICAL_ADDRESS PhysicalAddress64) +{ + ACPI_FUNCTION_TRACE (AcpiHwSetFirmwareWakingVector); + + + /* + * According to the ACPI specification 2.0c and later, the 64-bit + * waking vector should be cleared and the 32-bit waking vector should + * be used, unless we want the wake-up code to be called by the BIOS in + * Protected Mode. Some systems (for example HP dv5-1004nr) are known + * to fail to resume if the 64-bit vector is used. + */ + + /* Set the 32-bit vector */ + + Facs->FirmwareWakingVector = (UINT32) PhysicalAddress; + + if (Facs->Length > 32) + { + if (Facs->Version >= 1) + { + /* Set the 64-bit vector */ + + Facs->XFirmwareWakingVector = PhysicalAddress64; + } + else + { + /* Clear the 64-bit vector if it exists */ + + Facs->XFirmwareWakingVector = 0; + } + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiSetFirmwareWakingVector + * + * PARAMETERS: PhysicalAddress - 32-bit physical address of ACPI real mode + * entry point + * PhysicalAddress64 - 64-bit physical address of ACPI protected + * mode entry point + * + * RETURN: Status + * + * DESCRIPTION: Sets the FirmwareWakingVector fields of the FACS + * + ******************************************************************************/ + +ACPI_STATUS +AcpiSetFirmwareWakingVector ( + ACPI_PHYSICAL_ADDRESS PhysicalAddress, + ACPI_PHYSICAL_ADDRESS PhysicalAddress64) +{ + + ACPI_FUNCTION_TRACE (AcpiSetFirmwareWakingVector); + + if (AcpiGbl_FACS) + { + (void) AcpiHwSetFirmwareWakingVector (AcpiGbl_FACS, + PhysicalAddress, PhysicalAddress64); + } + + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiSetFirmwareWakingVector) + + +/* + * These functions are removed for the ACPI_REDUCED_HARDWARE case: + * AcpiEnterSleepStateS4bios + */ + +#if (!ACPI_REDUCED_HARDWARE) +/******************************************************************************* + * + * 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 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); + } + + Status = AcpiHwWritePort (AcpiGbl_FADT.SmiCommand, + (UINT32) AcpiGbl_FADT.S4BiosRequest, 8); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + do { + AcpiOsStall (ACPI_USEC_PER_MSEC); + 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 (FADT). Note: As per the ACPI + * specification, these extended registers are to be used for HW-reduced + * platforms only. They are not general-purpose replacements for the + * legacy PM register sleep support. + */ + if (AcpiGbl_ReducedHardware) + { + 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); + + + Status = AcpiGetSleepTypeData (SleepState, + &AcpiGbl_SleepTypeA, &AcpiGbl_SleepTypeB); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiGetSleepTypeData (ACPI_STATE_S0, + &AcpiGbl_SleepTypeAS0, &AcpiGbl_SleepTypeBS0); + if (ACPI_FAILURE (Status)) { + AcpiGbl_SleepTypeAS0 = ACPI_SLEEP_TYPE_INVALID; + } + + /* 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_PATHNAME__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_PATHNAME__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/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsaccess.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsaccess.c new file mode 100644 index 0000000..f0f881f --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsaccess.c @@ -0,0 +1,781 @@ +/******************************************************************************* + * + * Module Name: nsaccess - Top-level functions for accessing ACPI namespace + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acdispat.h" + +#ifdef ACPI_ASL_COMPILER + #include "acdisasm.h" +#endif + +#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_NAMESPACE_NODE *PrevNode = NULL; + 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 predefined names in the name table */ + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Entering predefined entries into namespace\n")); + + /* + * Create the initial (default) namespace. + * This namespace looks like something similar to this: + * + * ACPI Namespace (from Namespace Root): + * 0 _GPE Scope 00203160 00 + * 0 _PR_ Scope 002031D0 00 + * 0 _SB_ Device 00203240 00 Notify Object: 0020ADD8 + * 0 _SI_ Scope 002032B0 00 + * 0 _TZ_ Device 00203320 00 + * 0 _REV Integer 00203390 00 = 0000000000000002 + * 0 _OS_ String 00203488 00 Len 14 "Microsoft Windows NT" + * 0 _GL_ Mutex 00203580 00 Object 002035F0 + * 0 _OSI Method 00203678 00 Args 1 Len 0000 Aml 00000000 + */ + for (InitVal = AcpiGbl_PreDefinedNames; InitVal->Name; InitVal++) + { + Status = AE_OK; + + /* _OSI is optional for now, will be permanent later */ + + if (!strcmp (InitVal->Name, "_OSI") && !AcpiGbl_CreateOsiMethod) + { + continue; + } + + /* + * Create, init, and link the new predefined name + * Note: No need to use AcpiNsLookup here because all the + * predefined names are at the root level. It is much easier to + * just create and link the new node(s) here. + */ + NewNode = AcpiNsCreateNode (*ACPI_CAST_PTR (UINT32, InitVal->Name)); + if (!NewNode) + { + Status = AE_NO_MEMORY; + goto UnlockAndExit; + } + + NewNode->DescriptorType = ACPI_DESC_TYPE_NAMED; + NewNode->Type = InitVal->Type; + + if (!PrevNode) + { + AcpiGbl_RootNodeStruct.Child = NewNode; + } + else + { + PrevNode->Peer = NewNode; + } + + NewNode->Parent = &AcpiGbl_RootNodeStruct; + PrevNode = NewNode; + + /* + * 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 (_OSI) */ + + 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) 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 (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; + char *ExternalPath; + ACPI_NAMESPACE_NODE *PrefixNode; + ACPI_NAMESPACE_NODE *CurrentNode = NULL; + ACPI_NAMESPACE_NODE *ThisNode = NULL; + UINT32 NumSegments; + UINT32 ACPI_UNUSED_VAR NumCarats; + ACPI_NAME SimpleName; + ACPI_OBJECT_TYPE TypeToCheckFor; + ACPI_OBJECT_TYPE ThisSearchType; + UINT32 SearchParentFlag = ACPI_NS_SEARCH_PARENT; + UINT32 LocalFlags; + ACPI_INTERPRETER_MODE LocalInterpreterMode; + + + ACPI_FUNCTION_TRACE (NsLookup); + + + if (!ReturnNode) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + LocalFlags = Flags & + ~(ACPI_NS_ERROR_IF_FOUND | ACPI_NS_OVERRIDE_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. Externalize + * the internal path for error message. + */ + Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Pathname, + NULL, &ExternalPath); + if (ACPI_SUCCESS (Status)) + { + ACPI_ERROR ((AE_INFO, + "%s: Path has too many parent prefixes (^)", + ExternalPath)); + + ACPI_FREE (ExternalPath); + } + + 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: + + /* 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; + } + + /* Set override flag according to caller */ + + if (Flags & ACPI_NS_OVERRIDE_IF_FOUND) + { + LocalFlags |= ACPI_NS_OVERRIDE_IF_FOUND; + } + } + + /* Handle opcodes that create a new NameSeg via a full NamePath */ + + LocalInterpreterMode = InterpreterMode; + if ((Flags & ACPI_NS_PREFIX_MUST_EXIST) && (NumSegments > 0)) + { + /* Every element of the path must exist (except for the final NameSeg) */ + + LocalInterpreterMode = ACPI_IMODE_EXECUTE; + } + + /* 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, + LocalInterpreterMode, ThisSearchType, LocalFlags, &ThisNode); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_NOT_FOUND) + { +#if !defined ACPI_ASL_COMPILER /* Note: iASL reports this error by itself, not needed here */ + if (Flags & ACPI_NS_PREFIX_MUST_EXIST) + { + AcpiOsPrintf (ACPI_MSG_BIOS_ERROR + "Object does not exist: %4.4s\n", (char *) &SimpleName); + } +#endif + /* 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)); + } + +#ifdef ACPI_EXEC_APP + if ((Status == AE_ALREADY_EXISTS) && + (ThisNode->Flags & ANOBJ_NODE_EARLY_INIT)) + { + ThisNode->Flags &= ~ANOBJ_NODE_EARLY_INIT; + Status = AE_OK; + } +#endif + +#ifdef ACPI_ASL_COMPILER + /* + * If this ACPI name already exists within the namespace as an + * external declaration, then mark the external as a conflicting + * declaration and proceed to process the current node as if it did + * not exist in the namespace. If this node is not processed as + * normal, then it could cause improper namespace resolution + * by failing to open a new scope. + */ + if (AcpiGbl_DisasmFlag && + (Status == AE_ALREADY_EXISTS) && + ((ThisNode->Flags & ANOBJ_IS_EXTERNAL) || + (WalkState && WalkState->Opcode == AML_EXTERNAL_OP))) + { + ThisNode->Flags &= ~ANOBJ_IS_EXTERNAL; + ThisNode->Type = (UINT8)ThisSearchType; + if (WalkState->Opcode != AML_EXTERNAL_OP) + { + AcpiDmMarkExternalConflict (ThisNode); + } + break; + } +#endif + + *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_NAMESEG_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); + } + } + } + +#ifdef ACPI_EXEC_APP + if (Flags & ACPI_NS_EARLY_INIT) + { + ThisNode->Flags |= ANOBJ_NODE_EARLY_INIT; + } +#endif + + *ReturnNode = ThisNode; + return_ACPI_STATUS (AE_OK); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsalloc.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsalloc.c new file mode 100644 index 0000000..61a6c14 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsalloc.c @@ -0,0 +1,570 @@ +/******************************************************************************* + * + * Module Name: nsalloc - Namespace allocation and deletion utilities + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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_OPERAND_OBJECT *NextDesc; + + + ACPI_FUNCTION_NAME (NsDeleteNode); + + + if (!Node) + { + return_VOID; + } + + /* Detach an object if there is one */ + + AcpiNsDetachObject (Node); + + /* + * Delete an attached data object list if present (objects that were + * attached via AcpiAttachData). Note: After any normal object is + * detached above, the only possible remaining object(s) are data + * objects, in a linked list. + */ + ObjDesc = Node->Object; + while (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); + } + + NextDesc = ObjDesc->Common.NextObject; + AcpiUtRemoveReference (ObjDesc); + ObjDesc = NextDesc; + } + + /* Special case for the statically allocated root node */ + + if (Node == AcpiGbl_RootNode) + { + return; + } + + /* 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 %3.3X] 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/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsarguments.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsarguments.c new file mode 100644 index 0000000..6db9aa2 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsarguments.c @@ -0,0 +1,291 @@ +/****************************************************************************** + * + * Module Name: nsarguments - Validation of args for ACPI predefined methods + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acpredef.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsarguments") + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCheckArgumentTypes + * + * PARAMETERS: Info - Method execution information block + * + * RETURN: None + * + * DESCRIPTION: Check the incoming argument count and all argument types + * against the argument type list for a predefined name. + * + ******************************************************************************/ + +void +AcpiNsCheckArgumentTypes ( + ACPI_EVALUATE_INFO *Info) +{ + UINT16 ArgTypeList; + UINT8 ArgCount; + UINT8 ArgType; + UINT8 UserArgType; + UINT32 i; + + + /* + * If not a predefined name, cannot typecheck args, because + * we have no idea what argument types are expected. + * Also, ignore typecheck if warnings/errors if this method + * has already been evaluated at least once -- in order + * to suppress repetitive messages. + */ + if (!Info->Predefined || (Info->Node->Flags & ANOBJ_EVALUATED)) + { + return; + } + + ArgTypeList = Info->Predefined->Info.ArgumentList; + ArgCount = METHOD_GET_ARG_COUNT (ArgTypeList); + + /* Typecheck all arguments */ + + for (i = 0; ((i < ArgCount) && (i < Info->ParamCount)); i++) + { + ArgType = METHOD_GET_NEXT_TYPE (ArgTypeList); + UserArgType = Info->Parameters[i]->Common.Type; + + /* No typechecking for ACPI_TYPE_ANY */ + + if ((UserArgType != ArgType) && (ArgType != ACPI_TYPE_ANY)) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, ACPI_WARN_ALWAYS, + "Argument #%u type mismatch - " + "Found [%s], ACPI requires [%s]", (i + 1), + AcpiUtGetTypeName (UserArgType), + AcpiUtGetTypeName (ArgType))); + + /* Prevent any additional typechecking for this method */ + + Info->Node->Flags |= ANOBJ_EVALUATED; + } + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCheckAcpiCompliance + * + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * Node - Namespace node for the method/object + * Predefined - Pointer to entry in predefined name table + * + * RETURN: None + * + * DESCRIPTION: Check that the declared parameter count (in ASL/AML) for a + * predefined name is what is expected (matches what is defined in + * the ACPI specification for this predefined name.) + * + ******************************************************************************/ + +void +AcpiNsCheckAcpiCompliance ( + char *Pathname, + ACPI_NAMESPACE_NODE *Node, + const ACPI_PREDEFINED_INFO *Predefined) +{ + UINT32 AmlParamCount; + UINT32 RequiredParamCount; + + + if (!Predefined || (Node->Flags & ANOBJ_EVALUATED)) + { + return; + } + + /* Get the ACPI-required arg count from the predefined info table */ + + RequiredParamCount = + METHOD_GET_ARG_COUNT (Predefined->Info.ArgumentList); + + /* + * If this object is not a control method, we can check if the ACPI + * spec requires that it be a method. + */ + if (Node->Type != ACPI_TYPE_METHOD) + { + if (RequiredParamCount > 0) + { + /* Object requires args, must be implemented as a method */ + + ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, + "Object (%s) must be a control method with %u arguments", + AcpiUtGetTypeName (Node->Type), RequiredParamCount)); + } + else if (!RequiredParamCount && !Predefined->Info.ExpectedBtypes) + { + /* Object requires no args and no return value, must be a method */ + + ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, + "Object (%s) must be a control method " + "with no arguments and no return value", + AcpiUtGetTypeName (Node->Type))); + } + + return; + } + + /* + * This is a control method. + * Check that the ASL/AML-defined parameter count for this method + * matches the ACPI-required parameter count + * + * Some methods are allowed to have a "minimum" number of args (_SCP) + * because their definition in ACPI has changed over time. + * + * Note: These are BIOS errors in the declaration of the object + */ + AmlParamCount = Node->Object->Method.ParamCount; + + if (AmlParamCount < RequiredParamCount) + { + ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, + "Insufficient arguments - " + "ASL declared %u, ACPI requires %u", + AmlParamCount, RequiredParamCount)); + } + else if ((AmlParamCount > RequiredParamCount) && + !(Predefined->Info.ArgumentList & ARG_COUNT_IS_MINIMUM)) + { + ACPI_BIOS_ERROR_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, + "Excess arguments - " + "ASL declared %u, ACPI requires %u", + AmlParamCount, RequiredParamCount)); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCheckArgumentCount + * + * 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 incoming argument count matches the declared + * parameter count (in the ASL/AML) for an object. + * + ******************************************************************************/ + +void +AcpiNsCheckArgumentCount ( + char *Pathname, + ACPI_NAMESPACE_NODE *Node, + UINT32 UserParamCount, + const ACPI_PREDEFINED_INFO *Predefined) +{ + UINT32 AmlParamCount; + UINT32 RequiredParamCount; + + + if (Node->Flags & ANOBJ_EVALUATED) + { + return; + } + + if (!Predefined) + { + /* + * Not a predefined name. Check the incoming user argument count + * against the count that is specified in the method/object. + */ + if (Node->Type != ACPI_TYPE_METHOD) + { + if (UserParamCount) + { + ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, + "%u arguments were passed to a non-method ACPI object (%s)", + UserParamCount, AcpiUtGetTypeName (Node->Type))); + } + + return; + } + + /* + * This is a control method. Check the parameter count. + * We can only check the incoming argument count against the + * argument count declared for the method in the ASL/AML. + * + * Emit a message if too few or too many arguments have been passed + * by the caller. + * + * Note: Too many arguments will 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. + */ + AmlParamCount = Node->Object->Method.ParamCount; + + if (UserParamCount < AmlParamCount) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, + "Insufficient arguments - " + "Caller passed %u, method requires %u", + UserParamCount, AmlParamCount)); + } + else if (UserParamCount > AmlParamCount) + { + ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, + "Excess arguments - " + "Caller passed %u, method requires %u", + UserParamCount, AmlParamCount)); + } + + return; + } + + /* + * This is a predefined name. Validate the user-supplied parameter + * count against the ACPI specification. We don't validate against + * the method itself because what is important here is that the + * caller is in conformance with the spec. (The arg count for the + * method was checked against the ACPI spec earlier.) + * + * Some methods are allowed to have a "minimum" number of args (_SCP) + * because their definition in ACPI has changed over time. + */ + RequiredParamCount = + METHOD_GET_ARG_COUNT (Predefined->Info.ArgumentList); + + if (UserParamCount < RequiredParamCount) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, + "Insufficient arguments - " + "Caller passed %u, ACPI requires %u", + UserParamCount, RequiredParamCount)); + } + else if ((UserParamCount > RequiredParamCount) && + !(Predefined->Info.ArgumentList & ARG_COUNT_IS_MINIMUM)) + { + ACPI_INFO_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, + "Excess arguments - " + "Caller passed %u, ACPI requires %u", + UserParamCount, RequiredParamCount)); + } +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsconvert.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsconvert.c new file mode 100644 index 0000000..ce8a6a9 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsconvert.c @@ -0,0 +1,536 @@ +/****************************************************************************** + * + * Module Name: nsconvert - Object conversions for objects returned by + * predefined methods + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "acpredef.h" +#include "amlresrc.h" + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsconvert") + + +/******************************************************************************* + * + * 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. + * + ******************************************************************************/ + +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, &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. + * + ******************************************************************************/ + +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. + */ + 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. + * + ******************************************************************************/ + +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); + } + + 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: AcpiNsConvertToUnicode + * + * PARAMETERS: Scope - Namespace node for the method/object + * OriginalObject - ASCII String 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 object to a Unicode string Buffer. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsConvertToUnicode ( + ACPI_NAMESPACE_NODE *Scope, + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject) +{ + ACPI_OPERAND_OBJECT *NewObject; + char *AsciiString; + UINT16 *UnicodeBuffer; + UINT32 UnicodeLength; + UINT32 i; + + + if (!OriginalObject) + { + return (AE_OK); + } + + /* If a Buffer was returned, it must be at least two bytes long */ + + if (OriginalObject->Common.Type == ACPI_TYPE_BUFFER) + { + if (OriginalObject->Buffer.Length < 2) + { + return (AE_AML_OPERAND_VALUE); + } + + *ReturnObject = NULL; + return (AE_OK); + } + + /* + * The original object is an ASCII string. Convert this string to + * a unicode buffer. + */ + AsciiString = OriginalObject->String.Pointer; + UnicodeLength = (OriginalObject->String.Length * 2) + 2; + + /* Create a new buffer object for the Unicode data */ + + NewObject = AcpiUtCreateBufferObject (UnicodeLength); + if (!NewObject) + { + return (AE_NO_MEMORY); + } + + UnicodeBuffer = ACPI_CAST_PTR (UINT16, NewObject->Buffer.Pointer); + + /* Convert ASCII to Unicode */ + + for (i = 0; i < OriginalObject->String.Length; i++) + { + UnicodeBuffer[i] = (UINT16) AsciiString[i]; + } + + *ReturnObject = NewObject; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsConvertToResource + * + * PARAMETERS: Scope - Namespace node for the method/object + * 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 object to a ResourceTemplate + * Buffer. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsConvertToResource ( + ACPI_NAMESPACE_NODE *Scope, + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject) +{ + ACPI_OPERAND_OBJECT *NewObject; + UINT8 *Buffer; + + + /* + * We can fix the following cases for an expected resource template: + * 1. No return value (interpreter slack mode is disabled) + * 2. A "Return (Zero)" statement + * 3. A "Return empty buffer" statement + * + * We will return a buffer containing a single EndTag + * resource descriptor. + */ + if (OriginalObject) + { + switch (OriginalObject->Common.Type) + { + case ACPI_TYPE_INTEGER: + + /* We can only repair an Integer==0 */ + + if (OriginalObject->Integer.Value) + { + return (AE_AML_OPERAND_TYPE); + } + break; + + case ACPI_TYPE_BUFFER: + + if (OriginalObject->Buffer.Length) + { + /* Additional checks can be added in the future */ + + *ReturnObject = NULL; + return (AE_OK); + } + break; + + case ACPI_TYPE_STRING: + default: + + return (AE_AML_OPERAND_TYPE); + } + } + + /* Create the new buffer object for the resource descriptor */ + + NewObject = AcpiUtCreateBufferObject (2); + if (!NewObject) + { + return (AE_NO_MEMORY); + } + + Buffer = ACPI_CAST_PTR (UINT8, NewObject->Buffer.Pointer); + + /* Initialize the Buffer with a single EndTag descriptor */ + + Buffer[0] = (ACPI_RESOURCE_NAME_END_TAG | ASL_RDESC_END_TAG_SIZE); + Buffer[1] = 0x00; + + *ReturnObject = NewObject; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsConvertToReference + * + * PARAMETERS: Scope - Namespace node for the method/object + * 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 object to a ObjectReference. + * Buffer. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsConvertToReference ( + ACPI_NAMESPACE_NODE *Scope, + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject) +{ + ACPI_OPERAND_OBJECT *NewObject = NULL; + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + ACPI_GENERIC_STATE ScopeInfo; + char *Name; + + + ACPI_FUNCTION_NAME (NsConvertToReference); + + + /* Convert path into internal presentation */ + + Status = AcpiNsInternalizeName (OriginalObject->String.Pointer, &Name); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Find the namespace node */ + + ScopeInfo.Scope.Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Scope); + Status = AcpiNsLookup (&ScopeInfo, Name, + ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, + ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, &Node); + if (ACPI_FAILURE (Status)) + { + /* Check if we are resolving a named reference within a package */ + + ACPI_ERROR_NAMESPACE (&ScopeInfo, + OriginalObject->String.Pointer, Status); + goto ErrorExit; + } + + /* Create and init a new internal ACPI object */ + + NewObject = AcpiUtCreateInternalObject (ACPI_TYPE_LOCAL_REFERENCE); + if (!NewObject) + { + Status = AE_NO_MEMORY; + goto ErrorExit; + } + NewObject->Reference.Node = Node; + NewObject->Reference.Object = Node->Object; + NewObject->Reference.Class = ACPI_REFCLASS_NAME; + + /* + * Increase reference of the object if needed (the object is likely a + * null for device nodes). + */ + AcpiUtAddReference (Node->Object); + +ErrorExit: + ACPI_FREE (Name); + *ReturnObject = NewObject; + return (Status); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsdump.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsdump.c new file mode 100644 index 0000000..c44c9cc --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsdump.c @@ -0,0 +1,1058 @@ +/****************************************************************************** + * + * Module Name: nsdump - table dumping routines for debug + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + ***************************************************************************** + * + * Alternatively, you may choose to be licensed under the terms of the + * following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, you may choose to be licensed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acoutput.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) + +static ACPI_STATUS +AcpiNsDumpOneObjectPath ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + +static ACPI_STATUS +AcpiNsGetMaxDepth ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + + +/******************************************************************************* + * + * 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, + const char *Pathname) +{ + UINT32 i; + + + ACPI_FUNCTION_NAME (NsPrintPathname); + + + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_NAMES, ACPI_NAMESPACE)) + { + return; + } + + /* Print the entire name */ + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "[")); + + while (NumSegments) + { + for (i = 0; i < 4; i++) + { + isprint ((int) Pathname[i]) ? + AcpiOsPrintf ("%c", Pathname[i]) : + AcpiOsPrintf ("?"); + } + + Pathname += ACPI_NAMESEG_SIZE; + NumSegments--; + if (NumSegments) + { + AcpiOsPrintf ("."); + } + } + + AcpiOsPrintf ("]\n"); +} + + +#ifdef ACPI_OBSOLETE_FUNCTIONS +/* Not used at this time, perhaps later */ + +/******************************************************************************* + * + * 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, + const char *Msg, + UINT32 Level, + UINT32 Component) +{ + + ACPI_FUNCTION_TRACE (NsDumpPathname); + + + /* Do this only if the requested debug level and component are enabled */ + + if (!ACPI_IS_DEBUG_ENABLED (Level, Component)) + { + return_VOID; + } + + /* Convert handle to a full pathname and print it (with supplied message) */ + + AcpiNsPrintNodePathname (Handle, Msg); + AcpiOsPrintf ("\n"); + return_VOID; +} +#endif + + +/******************************************************************************* + * + * 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; + Info->Count++; + + /* 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 %3.3X ", + 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. Some types should always have an object */ + + switch (Type) + { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_PACKAGE: + case ACPI_TYPE_BUFFER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_METHOD: + + AcpiOsPrintf (""); + break; + + default: + + break; + } + + AcpiOsPrintf ("\n"); + return (AE_OK); + } + + switch (Type) + { + case ACPI_TYPE_PROCESSOR: + + AcpiOsPrintf ("ID %02X Len %02X Addr %8.8X%8.8X\n", + ObjDesc->Processor.ProcId, ObjDesc->Processor.Length, + ACPI_FORMAT_UINT64 (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 (" %2.2X", 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, 80); + 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_UINT64 (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 %.2X\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; + } + } + +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.Count = 0; + 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); + + AcpiOsPrintf ("\nNamespace node count: %u\n\n", Info.Count); + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsDumpOneObjectPath, AcpiNsGetMaxDepth + * + * PARAMETERS: ObjHandle - Node to be dumped + * Level - Nesting level of the handle + * Context - Passed into WalkNamespace + * ReturnValue - Not used + * + * RETURN: Status + * + * DESCRIPTION: Dump the full pathname to a namespace object. AcpNsGetMaxDepth + * computes the maximum nesting depth in the namespace tree, in + * order to simplify formatting in AcpiNsDumpOneObjectPath. + * These procedures are UserFunctions called by AcpiNsWalkNamespace. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsDumpOneObjectPath ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue) +{ + UINT32 MaxLevel = *((UINT32 *) Context); + char *Pathname; + ACPI_NAMESPACE_NODE *Node; + int PathIndent; + + + if (!ObjHandle) + { + return (AE_OK); + } + + Node = AcpiNsValidateHandle (ObjHandle); + if (!Node) + { + /* Ignore bad node during namespace walk */ + + return (AE_OK); + } + + Pathname = AcpiNsGetNormalizedPathname (Node, TRUE); + + PathIndent = 1; + if (Level <= MaxLevel) + { + PathIndent = MaxLevel - Level + 1; + } + + AcpiOsPrintf ("%2d%*s%-12s%*s", + Level, Level, " ", AcpiUtGetTypeName (Node->Type), + PathIndent, " "); + + AcpiOsPrintf ("%s\n", &Pathname[1]); + ACPI_FREE (Pathname); + return (AE_OK); +} + + +static ACPI_STATUS +AcpiNsGetMaxDepth ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue) +{ + UINT32 *MaxLevel = (UINT32 *) Context; + + + if (Level > *MaxLevel) + { + *MaxLevel = Level; + } + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsDumpObjectPaths + * + * 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 full object pathnames within the loaded namespace. Uses + * AcpiNsWalkNamespace in conjunction with AcpiNsDumpOneObjectPath. + * + ******************************************************************************/ + +void +AcpiNsDumpObjectPaths ( + ACPI_OBJECT_TYPE Type, + UINT8 DisplayType, + UINT32 MaxDepth, + ACPI_OWNER_ID OwnerId, + ACPI_HANDLE StartHandle) +{ + ACPI_STATUS Status; + UINT32 MaxLevel = 0; + + + 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; + } + + /* Get the max depth of the namespace tree, for formatting later */ + + (void) AcpiNsWalkNamespace (Type, StartHandle, MaxDepth, + ACPI_NS_WALK_NO_UNLOCK | ACPI_NS_WALK_TEMP_NODES, + AcpiNsGetMaxDepth, NULL, (void *) &MaxLevel, NULL); + + /* Now dump the entire namespace */ + + (void) AcpiNsWalkNamespace (Type, StartHandle, MaxDepth, + ACPI_NS_WALK_NO_UNLOCK | ACPI_NS_WALK_TEMP_NODES, + AcpiNsDumpOneObjectPath, NULL, (void *) &MaxLevel, 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/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsdumpdv.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsdumpdv.c new file mode 100644 index 0000000..a3d75f4 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsdumpdv.c @@ -0,0 +1,265 @@ +/****************************************************************************** + * + * Module Name: nsdump - table dumping routines for debug + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + ***************************************************************************** + * + * Alternatively, you may choose to be licensed under the terms of the + * following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, you may choose to be licensed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + *****************************************************************************/ + +#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\n", + Info->HardwareId.Value, ACPI_FORMAT_UINT64 (Info->Address))); + 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, METHOD_NAME__SB_, &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/code/drivers/platform/acpi/third_party/acpica/components/namespace/nseval.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nseval.c new file mode 100644 index 0000000..a46c6b9 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nseval.c @@ -0,0 +1,460 @@ +/******************************************************************************* + * + * Module Name: nseval - Object evaluation, includes control method execution + * + ******************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + ***************************************************************************** + * + * Alternatively, you may choose to be licensed under the terms of the + * following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, you may choose to be licensed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "acinterp.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nseval") + + +/******************************************************************************* + * + * FUNCTION: AcpiNsEvaluate + * + * PARAMETERS: Info - Evaluation info block, contains these fields + * and more: + * PrefixNode - Prefix or Method/Object Node to execute + * RelativePath - 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. + * 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_FUNCTION_TRACE (NsEvaluate); + + + if (!Info) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (!Info->Node) + { + /* + * Get the actual namespace node for the target object if we + * need to. Handles these cases: + * + * 1) Null node, valid pathname from root (absolute path) + * 2) Node and valid pathname (path relative to Node) + * 3) Node, Null pathname + */ + Status = AcpiNsGetNode (Info->PrefixNode, Info->RelativePathname, + ACPI_NS_NO_UPSEARCH, &Info->Node); + 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->Node) == ACPI_TYPE_LOCAL_METHOD_ALIAS) + { + Info->Node = ACPI_CAST_PTR ( + ACPI_NAMESPACE_NODE, Info->Node->Object); + } + + /* Complete the info block initialization */ + + Info->ReturnObject = NULL; + Info->NodeFlags = Info->Node->Flags; + Info->ObjDesc = AcpiNsGetAttachedObject (Info->Node); + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%s [%p] Value %p\n", + Info->RelativePathname, Info->Node, + AcpiNsGetAttachedObject (Info->Node))); + + /* Get info if we have a predefined name (_HID, etc.) */ + + Info->Predefined = AcpiUtMatchPredefinedMethod (Info->Node->Name.Ascii); + + /* Get the full pathname to the object, for use in warning messages */ + + Info->FullPathname = AcpiNsGetNormalizedPathname (Info->Node, TRUE); + if (!Info->FullPathname) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Optional object evaluation log */ + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EVALUATION, + "%-26s: %s (%s)\n", " Enter evaluation", + &Info->FullPathname[1], AcpiUtGetTypeName (Info->Node->Type))); + + /* Count the number of arguments being passed in */ + + Info->ParamCount = 0; + if (Info->Parameters) + { + while (Info->Parameters[Info->ParamCount]) + { + Info->ParamCount++; + } + + /* Warn on impossible argument count */ + + if (Info->ParamCount > ACPI_METHOD_NUM_ARGS) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, ACPI_WARN_ALWAYS, + "Excess arguments (%u) - using only %u", + Info->ParamCount, ACPI_METHOD_NUM_ARGS)); + + Info->ParamCount = ACPI_METHOD_NUM_ARGS; + } + } + + /* + * For predefined names: Check that the declared argument count + * matches the ACPI spec -- otherwise this is a BIOS error. + */ + AcpiNsCheckAcpiCompliance (Info->FullPathname, Info->Node, + Info->Predefined); + + /* + * For all names: Check that the incoming argument count for + * this method/object matches the actual ASL/AML definition. + */ + AcpiNsCheckArgumentCount (Info->FullPathname, Info->Node, + Info->ParamCount, Info->Predefined); + + /* For predefined names: Typecheck all incoming arguments */ + + AcpiNsCheckArgumentTypes (Info); + + /* + * Three major evaluation cases: + * + * 1) Object types that cannot be evaluated by definition + * 2) The object is a control method -- execute it + * 3) The object is not a method -- just return it's current value + */ + switch (AcpiNsGetType (Info->Node)) + { + case ACPI_TYPE_ANY: + 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: + /* + * 1) Disallow evaluation of these object types. For these, + * object evaluation is undefined. + */ + ACPI_ERROR ((AE_INFO, + "%s: This object type [%s] " + "never contains data and cannot be evaluated", + Info->FullPathname, AcpiUtGetTypeName (Info->Node->Type))); + + Status = AE_TYPE; + goto Cleanup; + + case ACPI_TYPE_METHOD: + /* + * 2) Object is a control method - execute it + */ + + /* Verify that there is a method object associated with this node */ + + if (!Info->ObjDesc) + { + ACPI_ERROR ((AE_INFO, "%s: Method has no attached sub-object", + Info->FullPathname)); + Status = AE_NULL_OBJECT; + goto Cleanup; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "**** Execute method [%s] at AML address %p length %X\n", + Info->FullPathname, + 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 (); + break; + + default: + /* + * 3) All other non-method objects -- get the current object value + */ + + /* + * Some 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 + * the Node 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 (); + + /* TBD: ResolveNodeToValue has a strange interface, fix */ + + Info->ReturnObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, Info->Node); + + Status = AcpiExResolveNodeToValue (ACPI_CAST_INDIRECT_PTR ( + ACPI_NAMESPACE_NODE, &Info->ReturnObject), NULL); + AcpiExExitInterpreter (); + + if (ACPI_FAILURE (Status)) + { + Info->ReturnObject = NULL; + goto Cleanup; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "Returned object %p [%s]\n", + Info->ReturnObject, + AcpiUtGetObjectTypeName (Info->ReturnObject))); + + Status = AE_CTRL_RETURN_VALUE; /* Always has a "return value" */ + break; + } + + /* + * For predefined names, check the return value against the ACPI + * specification. Some incorrect return value types are repaired. + */ + (void) AcpiNsCheckReturnValue (Info->Node, Info, 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; + } + else if (ACPI_FAILURE(Status)) + { + /* If ReturnObject exists, delete it */ + + if (Info->ReturnObject) + { + AcpiUtRemoveReference (Info->ReturnObject); + Info->ReturnObject = NULL; + } + } + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "*** Completed evaluation of object %s ***\n", + Info->RelativePathname)); + +Cleanup: + /* Optional object evaluation log */ + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EVALUATION, + "%-26s: %s\n", " Exit evaluation", + &Info->FullPathname[1])); + + /* + * Namespace was unlocked by the handling AcpiNs* function, so we + * just free the pathname and return + */ + ACPI_FREE (Info->FullPathname); + Info->FullPathname = NULL; + return_ACPI_STATUS (Status); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsinit.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsinit.c new file mode 100644 index 0000000..345a602 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsinit.c @@ -0,0 +1,739 @@ +/****************************************************************************** + * + * Module Name: nsinit - namespace initialization + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acdispat.h" +#include "acinterp.h" +#include "acevents.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_EXEC, + "[Init] Completing Initialization of ACPI Objects\n")); + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "**** Starting initialization of namespace objects ****\n")); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, + "Final data object initialization: ")); + + /* Clear the info block */ + + memset (&Info, 0, sizeof (ACPI_INIT_WALK_INFO)); + + /* Walk entire namespace from the supplied root */ + + /* + * TBD: will become ACPI_TYPE_PACKAGE as this type object + * is now the only one that supports deferred initialization + * (forward references). + */ + 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, + "Namespace contains %u (0x%X) objects\n", + Info.ObjectCount, + Info.ObjectCount)); + + ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, + "%u Control Methods found\n%u Op Regions found\n", + Info.MethodCount, 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 ( + UINT32 Flags) +{ + ACPI_STATUS Status = AE_OK; + ACPI_DEVICE_WALK_INFO Info; + ACPI_HANDLE Handle; + + + ACPI_FUNCTION_TRACE (NsInitializeDevices); + + + if (!(Flags & ACPI_NO_DEVICE_INIT)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "[Init] Initializing ACPI Devices\n")); + + /* 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 " + "and executing _INI/_STA methods:\n")); + + /* 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->RelativePathname = 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++; + } + + /* + * Execute \_SB._INI. + * There appears to be a strict order requirement for \_SB._INI, + * which should be evaluated before any _REG evaluations. + */ + Status = AcpiGetHandle (NULL, "\\_SB", &Handle); + if (ACPI_SUCCESS (Status)) + { + memset (Info.EvaluateInfo, 0, sizeof (ACPI_EVALUATE_INFO)); + Info.EvaluateInfo->PrefixNode = Handle; + Info.EvaluateInfo->RelativePathname = 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++; + } + } + } + + /* + * 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). + * + * Note: According to the ACPI specification, we actually needn't execute + * _REG for SystemMemory/SystemIo operation regions, but for PCI_Config + * operation regions, it is required to evaluate _REG for those on a PCI + * root bus that doesn't contain _BBN object. So this code is kept here + * in order not to break things. + */ + 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)) + { + goto ErrorExit; + } + } + + if (!(Flags & ACPI_NO_DEVICE_INIT)) + { + /* 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, + " Executed %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: AcpiNsInitOnePackage + * + * PARAMETERS: ObjHandle - Node + * Level - Current nesting level + * Context - Not used + * ReturnValue - Not used + * + * RETURN: Status + * + * DESCRIPTION: Callback from AcpiWalkNamespace. Invoked for every package + * within the namespace. Used during dynamic load of an SSDT. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsInitOnePackage ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; + + + ObjDesc = AcpiNsGetAttachedObject (Node); + if (!ObjDesc) + { + return (AE_OK); + } + + /* Exit if package is already initialized */ + + if (ObjDesc->Package.Flags & AOPOBJ_DATA_VALID) + { + return (AE_OK); + } + + Status = AcpiDsGetPackageArguments (ObjDesc); + if (ACPI_FAILURE (Status)) + { + return (AE_OK); + } + + Status = AcpiUtWalkPackageTree (ObjDesc, NULL, AcpiDsInitPackageElement, + NULL); + if (ACPI_FAILURE (Status)) + { + return (AE_OK); + } + + ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID; + return (AE_OK); +} + + +/******************************************************************************* + * + * 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 (); + + /* + * Only initialization of Package objects can be deferred, in order + * to support forward references. + */ + switch (Type) + { + case ACPI_TYPE_LOCAL_BANK_FIELD: + + /* TBD: BankFields do not require deferred init, remove this code */ + + Info->FieldInit++; + Status = AcpiDsGetBankFieldArguments (ObjDesc); + break; + + case ACPI_TYPE_PACKAGE: + + /* Complete the initialization/resolution of the package object */ + + Info->PackageInit++; + Status = AcpiNsInitOnePackage (ObjHandle, Level, NULL, NULL); + break; + + default: + + /* No other types should get here */ + + Status = AE_TYPE; + ACPI_EXCEPTION ((AE_INFO, Status, + "Opcode is not deferred [%4.4s] (%s)", + AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type))); + break; + } + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Could not execute arguments for [%4.4s] (%s)", + AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type))); + } + + /* + * 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_NAMESEG (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. + */ + if (!ACPI_COMPARE_NAMESEG (DeviceNode->Name.Ascii, "_SB_") || + DeviceNode->Parent != AcpiGbl_RootNode) + { + ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname ( + ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__INI)); + + memset (Info, 0, sizeof (ACPI_EVALUATE_INFO)); + Info->PrefixNode = DeviceNode; + Info->RelativePathname = METHOD_NAME__INI; + Info->Parameters = NULL; + Info->Flags = ACPI_IGNORE_RETURN_VALUE; + + Status = AcpiNsEvaluate (Info); + if (ACPI_SUCCESS (Status)) + { + WalkInfo->Num_INI++; + } + +#ifdef ACPI_DEBUG_OUTPUT + else if (Status != AE_NOT_FOUND) + { + /* Ignore error and move on to next device */ + + char *ScopeName = AcpiNsGetNormalizedPathname (DeviceNode, TRUE); + + 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/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsload.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsload.c new file mode 100644 index 0000000..3db532c --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsload.c @@ -0,0 +1,328 @@ +/****************************************************************************** + * + * Module Name: nsload - namespace loading/expanding/contracting procedures + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acdispat.h" +#include "actables.h" +#include "acinterp.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 + + +/******************************************************************************* + * + * 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); + + + /* 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; + } + + /* + * 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 = AcpiNsParseTable (TableIndex, Node); + if (ACPI_SUCCESS (Status)) + { + AcpiTbSetTableLoadedFlag (TableIndex, TRUE); + } + else + { + /* + * On error, delete any namespace objects created by this table. + * We cannot initialize these objects, so delete them. There are + * a couple of especially bad cases: + * AE_ALREADY_EXISTS - namespace collision. + * AE_NOT_FOUND - the target of a Scope operator does not + * exist. This target of Scope must already exist in the + * namespace, as per the ACPI specification. + */ + AcpiNsDeleteNamespaceByOwner ( + AcpiGbl_RootTableList.Tables[TableIndex].OwnerId); + + AcpiTbReleaseOwnerId (TableIndex); + return_ACPI_STATUS (Status); + } + +Unlock: + 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 Object Initialization\n")); + + AcpiExEnterInterpreter (); + Status = AcpiDsInitializeObjects (TableIndex, Node); + AcpiExExitInterpreter (); + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "**** Completed Table 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 diff --git a/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsnames.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsnames.c new file mode 100644 index 0000000..0f49151 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsnames.c @@ -0,0 +1,547 @@ +/******************************************************************************* + * + * Module Name: nsnames - Name manipulation and search + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "amlcode.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsnames") + + +/******************************************************************************* + * + * 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) +{ + char *NameBuffer; + + + ACPI_FUNCTION_TRACE_PTR (NsGetExternalPathname, Node); + + + NameBuffer = AcpiNsGetNormalizedPathname (Node, FALSE); + 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; + + + /* Validate the Node */ + + if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) + { + ACPI_ERROR ((AE_INFO, + "Invalid/cached reference target node: %p, descriptor type %d", + Node, ACPI_GET_DESCRIPTOR_TYPE (Node))); + return (0); + } + + Size = AcpiNsBuildNormalizedPath (Node, NULL, 0, FALSE); + return (Size); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsHandleToName + * + * PARAMETERS: TargetHandle - Handle of named object whose name is + * to be found + * Buffer - Where the name is returned + * + * RETURN: Status, Buffer is filled with name if status is AE_OK + * + * DESCRIPTION: Build and return a full namespace name + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsHandleToName ( + ACPI_HANDLE TargetHandle, + ACPI_BUFFER *Buffer) +{ + ACPI_STATUS Status; + ACPI_NAMESPACE_NODE *Node; + const char *NodeName; + + + ACPI_FUNCTION_TRACE_PTR (NsHandleToName, TargetHandle); + + + Node = AcpiNsValidateHandle (TargetHandle); + if (!Node) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Validate/Allocate/Clear caller buffer */ + + Status = AcpiUtInitializeBuffer (Buffer, ACPI_PATH_SEGMENT_LENGTH); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Just copy the ACPI name from the Node and zero terminate it */ + + NodeName = AcpiUtGetNodeName (Node); + ACPI_COPY_NAMESEG (Buffer->Pointer, NodeName); + ((char *) Buffer->Pointer) [ACPI_NAMESEG_SIZE] = 0; + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%4.4s\n", (char *) Buffer->Pointer)); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsHandleToPathname + * + * PARAMETERS: TargetHandle - Handle of named object whose name is + * to be found + * Buffer - Where the pathname is returned + * NoTrailing - Remove trailing '_' for each name + * segment + * + * 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, + BOOLEAN NoTrailing) +{ + 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 = AcpiNsBuildNormalizedPath (Node, NULL, 0, NoTrailing); + 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 */ + + (void) AcpiNsBuildNormalizedPath (Node, Buffer->Pointer, + (UINT32) RequiredSize, NoTrailing); + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "%s [%X]\n", + (char *) Buffer->Pointer, (UINT32) RequiredSize)); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsBuildNormalizedPath + * + * PARAMETERS: Node - Namespace node + * FullPath - Where the path name is returned + * PathSize - Size of returned path name buffer + * NoTrailing - Remove trailing '_' from each name segment + * + * RETURN: Return 1 if the AML path is empty, otherwise returning (length + * of pathname + 1) which means the 'FullPath' contains a trailing + * null. + * + * DESCRIPTION: Build and return a full namespace pathname. + * Note that if the size of 'FullPath' isn't large enough to + * contain the namespace node's path name, the actual required + * buffer length is returned, and it should be greater than + * 'PathSize'. So callers are able to check the returning value + * to determine the buffer size of 'FullPath'. + * + ******************************************************************************/ + +UINT32 +AcpiNsBuildNormalizedPath ( + ACPI_NAMESPACE_NODE *Node, + char *FullPath, + UINT32 PathSize, + BOOLEAN NoTrailing) +{ + UINT32 Length = 0, i; + char Name[ACPI_NAMESEG_SIZE] ACPI_NONSTRING; + BOOLEAN DoNoTrailing; + char c, *Left, *Right; + ACPI_NAMESPACE_NODE *NextNode; + + + ACPI_FUNCTION_TRACE_PTR (NsBuildNormalizedPath, Node); + + +#define ACPI_PATH_PUT8(Path, Size, Byte, Length) \ + do { \ + if ((Length) < (Size)) \ + { \ + (Path)[(Length)] = (Byte); \ + } \ + (Length)++; \ + } while (0) + + /* + * Make sure the PathSize is correct, so that we don't need to + * validate both FullPath and PathSize. + */ + if (!FullPath) + { + PathSize = 0; + } + + if (!Node) + { + goto BuildTrailingNull; + } + + /* Validate the Node to avoid use-after-free vulnerabilities */ + + if (ACPI_GET_DESCRIPTOR_TYPE (Node) != ACPI_DESC_TYPE_NAMED) + { + goto BuildTrailingNull; + } + + NextNode = Node; + while (NextNode && NextNode != AcpiGbl_RootNode) + { + if (NextNode != Node) + { + ACPI_PATH_PUT8(FullPath, PathSize, AML_DUAL_NAME_PREFIX, Length); + } + + ACPI_MOVE_32_TO_32 (Name, &NextNode->Name); + DoNoTrailing = NoTrailing; + for (i = 0; i < 4; i++) + { + c = Name[4-i-1]; + if (DoNoTrailing && c != '_') + { + DoNoTrailing = FALSE; + } + if (!DoNoTrailing) + { + ACPI_PATH_PUT8(FullPath, PathSize, c, Length); + } + } + + NextNode = NextNode->Parent; + } + + ACPI_PATH_PUT8(FullPath, PathSize, AML_ROOT_PREFIX, Length); + + /* Reverse the path string */ + + if (Length <= PathSize) + { + Left = FullPath; + Right = FullPath+Length - 1; + + while (Left < Right) + { + c = *Left; + *Left++ = *Right; + *Right-- = c; + } + } + + /* Append the trailing null */ + +BuildTrailingNull: + ACPI_PATH_PUT8 (FullPath, PathSize, '\0', Length); + +#undef ACPI_PATH_PUT8 + + return_UINT32 (Length); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsGetNormalizedPathname + * + * PARAMETERS: Node - Namespace node whose pathname is needed + * NoTrailing - Remove trailing '_' from each name segment + * + * 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. All trailing '_' will be + * removed from the full pathname if 'NoTrailing' is specified.. + * + ******************************************************************************/ + +char * +AcpiNsGetNormalizedPathname ( + ACPI_NAMESPACE_NODE *Node, + BOOLEAN NoTrailing) +{ + char *NameBuffer; + ACPI_SIZE Size; + + + ACPI_FUNCTION_TRACE_PTR (NsGetNormalizedPathname, Node); + + + /* Calculate required buffer size based on depth below root */ + + Size = AcpiNsBuildNormalizedPath (Node, NULL, 0, NoTrailing); + 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 */ + + (void) AcpiNsBuildNormalizedPath (Node, NameBuffer, (UINT32) Size, NoTrailing); + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES, "%s: Path \"%s\"\n", + ACPI_GET_FUNCTION_NAME, NameBuffer)); + + return_PTR (NameBuffer); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsBuildPrefixedPathname + * + * PARAMETERS: PrefixScope - Scope/Path that prefixes the internal path + * InternalPath - Name or path of the namespace node + * + * RETURN: None + * + * DESCRIPTION: Construct a fully qualified pathname from a concatenation of: + * 1) Path associated with the PrefixScope namespace node + * 2) External path representation of the Internal path + * + ******************************************************************************/ + +char * +AcpiNsBuildPrefixedPathname ( + ACPI_GENERIC_STATE *PrefixScope, + const char *InternalPath) +{ + ACPI_STATUS Status; + char *FullPath = NULL; + char *ExternalPath = NULL; + char *PrefixPath = NULL; + ACPI_SIZE PrefixPathLength = 0; + + + /* If there is a prefix, get the pathname to it */ + + if (PrefixScope && PrefixScope->Scope.Node) + { + PrefixPath = AcpiNsGetNormalizedPathname (PrefixScope->Scope.Node, TRUE); + if (PrefixPath) + { + PrefixPathLength = strlen (PrefixPath); + } + } + + Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, InternalPath, + NULL, &ExternalPath); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + /* Merge the prefix path and the path. 2 is for one dot and trailing null */ + + FullPath = ACPI_ALLOCATE_ZEROED ( + PrefixPathLength + strlen (ExternalPath) + 2); + if (!FullPath) + { + goto Cleanup; + } + + /* Don't merge if the External path is already fully qualified */ + + if (PrefixPath && + (*ExternalPath != '\\') && + (*ExternalPath != '^')) + { + strcat (FullPath, PrefixPath); + if (PrefixPath[1]) + { + strcat (FullPath, "."); + } + } + + AcpiNsNormalizePathname (ExternalPath); + strcat (FullPath, ExternalPath); + +Cleanup: + if (PrefixPath) + { + ACPI_FREE (PrefixPath); + } + if (ExternalPath) + { + ACPI_FREE (ExternalPath); + } + + return (FullPath); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsNormalizePathname + * + * PARAMETERS: OriginalPath - Path to be normalized, in External format + * + * RETURN: The original path is processed in-place + * + * DESCRIPTION: Remove trailing underscores from each element of a path. + * + * For example: \A___.B___.C___ becomes \A.B.C + * + ******************************************************************************/ + +void +AcpiNsNormalizePathname ( + char *OriginalPath) +{ + char *InputPath = OriginalPath; + char *NewPathBuffer; + char *NewPath; + UINT32 i; + + + /* Allocate a temp buffer in which to construct the new path */ + + NewPathBuffer = ACPI_ALLOCATE_ZEROED (strlen (InputPath) + 1); + NewPath = NewPathBuffer; + if (!NewPathBuffer) + { + return; + } + + /* Special characters may appear at the beginning of the path */ + + if (*InputPath == '\\') + { + *NewPath = *InputPath; + NewPath++; + InputPath++; + } + + while (*InputPath == '^') + { + *NewPath = *InputPath; + NewPath++; + InputPath++; + } + + /* Remainder of the path */ + + while (*InputPath) + { + /* Do one nameseg at a time */ + + for (i = 0; (i < ACPI_NAMESEG_SIZE) && *InputPath; i++) + { + if ((i == 0) || (*InputPath != '_')) /* First char is allowed to be underscore */ + { + *NewPath = *InputPath; + NewPath++; + } + + InputPath++; + } + + /* Dot means that there are more namesegs to come */ + + if (*InputPath == '.') + { + *NewPath = *InputPath; + NewPath++; + InputPath++; + } + } + + *NewPath = 0; + strcpy (OriginalPath, NewPathBuffer); + ACPI_FREE (NewPathBuffer); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsobject.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsobject.c new file mode 100644 index 0000000..b4dec85 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsobject.c @@ -0,0 +1,499 @@ +/******************************************************************************* + * + * Module Name: nsobject - Utilities for objects attached to namespace + * table entries + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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; + + /* Alias nodes point directly to other namespace nodes; skip teardown */ + if ((Node->Type == ACPI_TYPE_LOCAL_ALIAS) || + (Node->Type == ACPI_TYPE_LOCAL_METHOD_ALIAS) || + (Node->Flags & ANOBJ_IS_ALIAS)) + { + Node->Object = NULL; + return_VOID; + } + + 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); + } + } + + if (ObjDesc->Common.Type == ACPI_TYPE_REGION) + { + AcpiUtRemoveAddressRange(ObjDesc->Region.SpaceId, Node); + } + + /* Clear the Node entry in all cases */ + + Node->Object = NULL; + if (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) == ACPI_DESC_TYPE_OPERAND) + { + /* Unlink object from front of possible object list */ + + Node->Object = ObjDesc->Common.NextObject; + + /* Handle possible 2-descriptor object */ + + if (Node->Object && + (Node->Object->Common.Type != ACPI_TYPE_LOCAL_DATA)) + { + Node->Object = Node->Object->Common.NextObject; + } + + /* + * Detach the object from any data objects (which are still held by + * the namespace node) + */ + if (ObjDesc->Common.NextObject && + ((ObjDesc->Common.NextObject)->Common.Type == ACPI_TYPE_LOCAL_DATA)) + { + ObjDesc->Common.NextObject = NULL; + } + } + + /* 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/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsparse.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsparse.c new file mode 100644 index 0000000..ac68530 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsparse.c @@ -0,0 +1,301 @@ +/****************************************************************************** + * + * Module Name: nsparse - namespace interface to AML parser + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acparser.h" +#include "acdispat.h" +#include "actables.h" +#include "acinterp.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsparse") + + +/******************************************************************************* + * + * FUNCTION: NsExecuteTable + * + * PARAMETERS: TableDesc - An ACPI table descriptor for table to parse + * StartNode - Where to enter the table into the namespace + * + * RETURN: Status + * + * DESCRIPTION: Load ACPI/AML table by executing the entire table as a single + * large control method. + * + * NOTE: The point of this is to execute any module-level code in-place + * as the table is parsed. Some AML code depends on this behavior. + * + * It is a run-time option at this time, but will eventually become + * the default. + * + * Note: This causes the table to only have a single-pass parse. + * However, this is compatible with other ACPI implementations. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsExecuteTable ( + UINT32 TableIndex, + ACPI_NAMESPACE_NODE *StartNode) +{ + ACPI_STATUS Status; + ACPI_TABLE_HEADER *Table; + ACPI_OWNER_ID OwnerId; + ACPI_EVALUATE_INFO *Info = NULL; + UINT32 AmlLength; + UINT8 *AmlStart; + ACPI_OPERAND_OBJECT *MethodObj = NULL; + + + ACPI_FUNCTION_TRACE (NsExecuteTable); + + + Status = AcpiGetTableByIndex (TableIndex, &Table); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Table must consist of at least a complete header */ + + if (Table->Length < sizeof (ACPI_TABLE_HEADER)) + { + return_ACPI_STATUS (AE_BAD_HEADER); + } + + AmlStart = (UINT8 *) Table + sizeof (ACPI_TABLE_HEADER); + AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER); + + Status = AcpiTbGetOwnerId (TableIndex, &OwnerId); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Create, initialize, and link a new temporary method object */ + + MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD); + if (!MethodObj) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Allocate the evaluation information block */ + + Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); + if (!Info) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE, + "%s: Create table pseudo-method for [%4.4s] @%p, method %p\n", + ACPI_GET_FUNCTION_NAME, Table->Signature, Table, MethodObj)); + + MethodObj->Method.AmlStart = AmlStart; + MethodObj->Method.AmlLength = AmlLength; + MethodObj->Method.OwnerId = OwnerId; + MethodObj->Method.InfoFlags |= ACPI_METHOD_MODULE_LEVEL; + + Info->PassNumber = ACPI_IMODE_EXECUTE; + Info->Node = StartNode; + Info->ObjDesc = MethodObj; + Info->NodeFlags = Info->Node->Flags; + Info->FullPathname = AcpiNsGetNormalizedPathname (Info->Node, TRUE); + if (!Info->FullPathname) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Optional object evaluation log */ + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EVALUATION, + "%-26s: (Definition Block level)\n", "Module-level evaluation")); + + Status = AcpiPsExecuteTable (Info); + + /* Optional object evaluation log */ + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EVALUATION, + "%-26s: (Definition Block level)\n", "Module-level complete")); + +Cleanup: + if (Info) + { + ACPI_FREE (Info->FullPathname); + Info->FullPathname = NULL; + } + ACPI_FREE (Info); + AcpiUtRemoveReference (MethodObj); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * 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 = AcpiGetTableByIndex (TableIndex, &Table); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Table must consist of at least a complete header */ + + if (Table->Length < sizeof (ACPI_TABLE_HEADER)) + { + return_ACPI_STATUS (AE_BAD_HEADER); + } + + AmlStart = (UINT8 *) Table + sizeof (ACPI_TABLE_HEADER); + AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER); + + Status = AcpiTbGetOwnerId (TableIndex, &OwnerId); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Create and init a Root Node */ + + ParseRoot = AcpiPsCreateScopeOp (AmlStart); + 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 = AcpiDsInitAmlWalk (WalkState, ParseRoot, NULL, + AmlStart, AmlLength, NULL, (UINT8) PassNumber); + if (ACPI_FAILURE (Status)) + { + AcpiDsDeleteWalkState (WalkState); + goto Cleanup; + } + + /* Found OSDT table, enable the namespace override feature */ + + if (ACPI_COMPARE_NAMESEG (Table->Signature, ACPI_SIG_OSDT) && + PassNumber == ACPI_IMODE_LOAD_PASS1) + { + WalkState->NamespaceOverride = TRUE; + } + + /* 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)); + AcpiExEnterInterpreter (); + Status = AcpiPsParseAml (WalkState); + AcpiExExitInterpreter (); + +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); + + + /* + * Executes the AML table as one large control method. + * The point of this is to execute any module-level code in-place + * as the table is parsed. Some AML code depends on this behavior. + * + * Note: This causes the table to only have a single-pass parse. + * However, this is compatible with other ACPI implementations. + */ + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_PARSE, + "%s: **** Start table execution pass\n", ACPI_GET_FUNCTION_NAME)); + + Status = AcpiNsExecuteTable (TableIndex, StartNode); + + return_ACPI_STATUS (Status); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/namespace/nspredef.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nspredef.c new file mode 100644 index 0000000..644d5d9 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nspredef.c @@ -0,0 +1,406 @@ +/****************************************************************************** + * + * Module Name: nspredef - Validation of ACPI predefined methods and objects + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 +AcpiNsCheckReference ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT *ReturnObject); + +static UINT32 +AcpiNsGetBitmappedType ( + ACPI_OPERAND_OBJECT *ReturnObject); + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCheckReturnValue + * + * PARAMETERS: Node - Namespace node for the method/object + * Info - Method execution information block + * 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 the value returned from a predefined name. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsCheckReturnValue ( + ACPI_NAMESPACE_NODE *Node, + ACPI_EVALUATE_INFO *Info, + UINT32 UserParamCount, + ACPI_STATUS ReturnStatus, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_STATUS Status; + const ACPI_PREDEFINED_INFO *Predefined; + + ACPI_FUNCTION_TRACE (NsCheckReturnValue); + + /* If not a predefined name, we cannot validate the return object */ + + Predefined = Info->Predefined; + if (!Predefined) + { + return_ACPI_STATUS (AE_OK); + } + + /* + * 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)) + { + return_ACPI_STATUS (AE_OK); + } + + /* + * 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)) + { + return_ACPI_STATUS (AE_OK); + } + + /* + * Check that the type of the main return object is what is expected + * for this predefined name + */ + Status = AcpiNsCheckObjectType (Info, ReturnObjectPtr, + Predefined->Info.ExpectedBtypes, ACPI_NOT_PACKAGE_ELEMENT); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + + /* + * + * 4) If there is no return value and it is optional, just return + * AE_OK (_WAK). + */ + if (!(*ReturnObjectPtr)) + { + 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) + { + Info->ParentPackage = *ReturnObjectPtr; + Status = AcpiNsCheckPackage (Info, ReturnObjectPtr); + if (ACPI_FAILURE (Status)) + { + /* We might be able to fix some errors */ + + if ((Status != AE_AML_OPERAND_TYPE) && + (Status != AE_AML_OPERAND_VALUE)) + { + 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 (Info, 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) || + (Info->ReturnFlags & ACPI_OBJECT_REPAIRED)) + { + Node->Flags |= ANOBJ_EVALUATED; + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCheckObjectType + * + * PARAMETERS: Info - Method execution information block + * 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. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsCheckObjectType ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **ReturnObjectPtr, + UINT32 ExpectedBtypes, + UINT32 PackageIndex) +{ + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + ACPI_STATUS Status = AE_OK; + char TypeBuffer[96]; /* Room for 10 types */ + + + /* A Namespace node should not get here, but make sure */ + + if (ReturnObject && + ACPI_GET_DESCRIPTOR_TYPE (ReturnObject) == ACPI_DESC_TYPE_NAMED) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->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) + */ + Info->ReturnBtype = AcpiNsGetBitmappedType (ReturnObject); + if (Info->ReturnBtype == ACPI_RTYPE_ANY) + { + /* Not one of the supported objects, must be incorrect */ + goto TypeErrorExit; + } + + /* For reference objects, check that the reference type is correct */ + + if ((Info->ReturnBtype & ExpectedBtypes) == ACPI_RTYPE_REFERENCE) + { + Status = AcpiNsCheckReference (Info, ReturnObject); + return (Status); + } + + /* Attempt simple repair of the returned object if necessary */ + + Status = AcpiNsSimpleRepair (Info, ExpectedBtypes, + PackageIndex, ReturnObjectPtr); + if (ACPI_SUCCESS (Status)) + { + return (AE_OK); /* Successful repair */ + } + + +TypeErrorExit: + + /* Create a string with all expected types for this predefined object */ + + AcpiUtGetExpectedReturnTypes (TypeBuffer, ExpectedBtypes); + + if (!ReturnObject) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, + "Expected return object of type %s", + TypeBuffer)); + } + else if (PackageIndex == ACPI_NOT_PACKAGE_ELEMENT) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, + "Return type mismatch - found %s, expected %s", + AcpiUtGetObjectTypeName (ReturnObject), TypeBuffer)); + } + else + { + ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, + "Return Package type mismatch at index %u - " + "found %s, expected %s", PackageIndex, + AcpiUtGetObjectTypeName (ReturnObject), TypeBuffer)); + } + + return (AE_AML_OPERAND_TYPE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCheckReference + * + * PARAMETERS: Info - Method execution information block + * 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_EVALUATE_INFO *Info, + 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, Info->FullPathname, Info->NodeFlags, + "Return type mismatch - unexpected reference object type [%s] %2.2X", + AcpiUtGetReferenceName (ReturnObject), + ReturnObject->Reference.Class)); + + return (AE_AML_OPERAND_TYPE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsGetBitmappedType + * + * PARAMETERS: ReturnObject - Object returned from method/obj evaluation + * + * RETURN: Object return type. ACPI_RTYPE_ANY indicates that the object + * type is not supported. ACPI_RTYPE_NONE indicates that no + * object was returned (ReturnObject is NULL). + * + * DESCRIPTION: Convert object type into a bitmapped object return type. + * + ******************************************************************************/ + +static UINT32 +AcpiNsGetBitmappedType ( + ACPI_OPERAND_OBJECT *ReturnObject) +{ + UINT32 ReturnBtype; + + + if (!ReturnObject) + { + return (ACPI_RTYPE_NONE); + } + + /* Map ACPI_OBJECT_TYPE to internal bitmapped type */ + + 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 */ + + ReturnBtype = ACPI_RTYPE_ANY; + break; + } + + return (ReturnBtype); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsprepkg.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsprepkg.c new file mode 100644 index 0000000..15b7a96 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsprepkg.c @@ -0,0 +1,769 @@ +/****************************************************************************** + * + * Module Name: nsprepkg - Validation of package objects for predefined names + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acpredef.h" + + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsprepkg") + + +/* Local prototypes */ + +static ACPI_STATUS +AcpiNsCheckPackageList ( + ACPI_EVALUATE_INFO *Info, + const ACPI_PREDEFINED_INFO *Package, + ACPI_OPERAND_OBJECT **Elements, + UINT32 Count); + +static ACPI_STATUS +AcpiNsCheckPackageElements ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **Elements, + UINT8 Type1, + UINT32 Count1, + UINT8 Type2, + UINT32 Count2, + UINT32 StartIndex); + +static ACPI_STATUS +AcpiNsCustomPackage ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **Elements, + UINT32 Count); + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCheckPackage + * + * PARAMETERS: Info - Method execution information block + * 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. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsCheckPackage ( + ACPI_EVALUATE_INFO *Info, + 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_TRACE (NsCheckPackage); + + + /* The package info for this name is in the next table entry */ + + Package = Info->Predefined + 1; + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "%s Validating return Package of Type %X, Count %X\n", + Info->FullPathname, Package->RetInfo.Type, + ReturnObject->Package.Count)); + + /* + * For variable-length Packages, we can safely remove all embedded + * and trailing NULL package elements + */ + AcpiNsRemoveNullElements (Info, Package->RetInfo.Type, ReturnObject); + + /* Extract package count and elements array */ + + Elements = ReturnObject->Package.Elements; + Count = ReturnObject->Package.Count; + + /* + * Most packages must have at least one element. The only exception + * is the variable-length package (ACPI_PTYPE1_VAR). + */ + if (!Count) + { + if (Package->RetInfo.Type == ACPI_PTYPE1_VAR) + { + return_ACPI_STATUS (AE_OK); + } + + ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, + "Return Package has no elements (empty)")); + + return_ACPI_STATUS (AE_AML_OPERAND_VALUE); + } + + /* + * Decode the type of the expected package contents + * + * PTYPE1 packages contain no subpackages + * PTYPE2 packages contain subpackages + */ + switch (Package->RetInfo.Type) + { + case ACPI_PTYPE_CUSTOM: + + Status = AcpiNsCustomPackage (Info, Elements, Count); + break; + + case ACPI_PTYPE1_FIXED: + /* + * The package count is fixed and there are no subpackages + * + * 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", + Info->FullPathname, Count, ExpectedCount)); + } + + /* Validate all elements of the returned package */ + + Status = AcpiNsCheckPackageElements (Info, 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 subpackages, and all + * elements must be of the same type + */ + for (i = 0; i < Count; i++) + { + Status = AcpiNsCheckObjectType (Info, Elements, + Package->RetInfo.ObjectType1, i); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Elements++; + } + break; + + case ACPI_PTYPE1_OPTION: + /* + * The package count is variable, there are no subpackages. 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 (Info, Elements, + Package->RetInfo3.ObjectType[i], i); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + else + { + /* These are the optional package elements */ + + Status = AcpiNsCheckObjectType (Info, Elements, + Package->RetInfo3.TailObjectType, i); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + Elements++; + } + break; + + case ACPI_PTYPE2_REV_FIXED: + + /* First element is the (Integer) revision */ + + Status = AcpiNsCheckObjectType ( + Info, Elements, ACPI_RTYPE_INTEGER, 0); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Elements++; + Count--; + + /* Examine the subpackages */ + + Status = AcpiNsCheckPackageList (Info, Package, Elements, Count); + break; + + case ACPI_PTYPE2_PKG_COUNT: + + /* First element is the (Integer) count of subpackages to follow */ + + Status = AcpiNsCheckObjectType ( + Info, Elements, ACPI_RTYPE_INTEGER, 0); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (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 subpackages */ + + Status = AcpiNsCheckPackageList (Info, 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 subpackages. + * + * First, ensure that the first element is a subpackage. 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 = AcpiNsWrapWithPackage ( + Info, ReturnObject, ReturnObjectPtr); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Update locals to point to the new package (of 1 element) */ + + ReturnObject = *ReturnObjectPtr; + Elements = ReturnObject->Package.Elements; + Count = 1; + } + + /* Examine the subpackages */ + + Status = AcpiNsCheckPackageList (Info, Package, Elements, Count); + break; + + case ACPI_PTYPE2_VAR_VAR: + /* + * Returns a variable list of packages, each with a variable list + * of objects. + */ + break; + + case ACPI_PTYPE2_UUID_PAIR: + + /* The package must contain pairs of (UUID + type) */ + + if (Count & 1) + { + ExpectedCount = Count + 1; + goto PackageTooSmall; + } + + while (Count > 0) + { + Status = AcpiNsCheckObjectType(Info, Elements, + Package->RetInfo.ObjectType1, 0); + if (ACPI_FAILURE(Status)) + { + return_ACPI_STATUS (Status); + } + + /* Validate length of the UUID buffer */ + + if ((*Elements)->Buffer.Length != 16) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, + Info->NodeFlags, "Invalid length for UUID Buffer")); + return_ACPI_STATUS (AE_AML_OPERAND_VALUE); + } + + Status = AcpiNsCheckObjectType(Info, Elements + 1, + Package->RetInfo.ObjectType2, 0); + if (ACPI_FAILURE(Status)) + { + return_ACPI_STATUS (Status); + } + + Elements += 2; + Count -= 2; + } + break; + + default: + + /* Should not get here if predefined info table is correct */ + + ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, + "Invalid internal return type in table entry: %X", + Package->RetInfo.Type)); + + return_ACPI_STATUS (AE_AML_INTERNAL); + } + + return_ACPI_STATUS (Status); + + +PackageTooSmall: + + /* Error exit for the case with an incorrect package count */ + + ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, + "Return Package is too small - found %u elements, expected %u", + Count, ExpectedCount)); + + return_ACPI_STATUS (AE_AML_OPERAND_VALUE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCheckPackageList + * + * PARAMETERS: Info - Method execution information block + * 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_EVALUATE_INFO *Info, + 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 subpackage in the parent Package + * + * NOTE: assumes list of subpackages 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; + Info->ParentPackage = SubPackage; + + /* Each sub-object must be of type Package */ + + Status = AcpiNsCheckObjectType (Info, &SubPackage, + ACPI_RTYPE_PACKAGE, i); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Examine the different types of expected subpackages */ + + Info->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 (Info, 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 (Info, 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_VAR_VAR: + /* + * Each subpackage has a fixed or variable number of elements + */ + break; + + case ACPI_PTYPE2_FIXED: + + /* Each subpackage has a fixed length */ + + ExpectedCount = Package->RetInfo2.Count; + if (SubPackage->Package.Count < ExpectedCount) + { + goto PackageTooSmall; + } + + /* Check the type of each subpackage element */ + + for (j = 0; j < ExpectedCount; j++) + { + Status = AcpiNsCheckObjectType (Info, &SubElements[j], + Package->RetInfo2.ObjectType[j], j); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + } + break; + + case ACPI_PTYPE2_MIN: + + /* Each subpackage has a variable but minimum length */ + + ExpectedCount = Package->RetInfo.Count1; + if (SubPackage->Package.Count < ExpectedCount) + { + goto PackageTooSmall; + } + + /* Check the type of each subpackage element */ + + Status = AcpiNsCheckPackageElements (Info, 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 (Info, 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 subpackage element */ + + Status = AcpiNsCheckPackageElements (Info, (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 */ + + ACPI_ERROR ((AE_INFO, "Invalid Package type: %X", + Package->RetInfo.Type)); + return (AE_AML_INTERNAL); + } + + Elements++; + } + + return (AE_OK); + + +PackageTooSmall: + + /* The subpackage count was smaller than required */ + + ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, + "Return SubPackage[%u] is too small - found %u elements, expected %u", + i, SubPackage->Package.Count, ExpectedCount)); + + return (AE_AML_OPERAND_VALUE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCustomPackage + * + * PARAMETERS: Info - Method execution information block + * Elements - Pointer to the package elements array + * Count - Element count for the package + * + * RETURN: Status + * + * DESCRIPTION: Check a returned package object for the correct count and + * correct type of all sub-objects. + * + * NOTE: Currently used for the _BIX method only. When needed for two or more + * methods, probably a detect/dispatch mechanism will be required. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiNsCustomPackage ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **Elements, + UINT32 Count) +{ + UINT32 ExpectedCount; + UINT32 Version; + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_NAME (NsCustomPackage); + + + /* Get version number, must be Integer */ + + if (!(*Elements)) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, + "Return Package has a NULL version element")); + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + if ((*Elements)->Common.Type != ACPI_TYPE_INTEGER) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, + "Return Package has invalid object type for version number")); + return_ACPI_STATUS (AE_AML_OPERAND_TYPE); + } + + Version = (UINT32) (*Elements)->Integer.Value; + ExpectedCount = 21; /* Version 1 */ + + if (Version == 0) + { + ExpectedCount = 20; /* Version 0 */ + } + + if (Count < ExpectedCount) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, Info->NodeFlags, + "Return Package is too small - found %u elements, expected %u", + Count, ExpectedCount)); + return_ACPI_STATUS (AE_AML_OPERAND_VALUE); + } + else if (Count > ExpectedCount) + { + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Return Package is larger than needed - " + "found %u, expected %u\n", + Info->FullPathname, Count, ExpectedCount)); + } + + /* Validate all elements of the returned package */ + + Status = AcpiNsCheckPackageElements (Info, Elements, + ACPI_RTYPE_INTEGER, 16, + ACPI_RTYPE_STRING, 4, 0); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Version 1 has a single trailing integer */ + + if (Version > 0) + { + Status = AcpiNsCheckPackageElements (Info, Elements + 20, + ACPI_RTYPE_INTEGER, 1, 0, 0, 20); + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsCheckPackageElements + * + * PARAMETERS: Info - Method execution information block + * 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_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **Elements, + UINT8 Type1, + UINT32 Count1, + UINT8 Type2, + UINT32 Count2, + UINT32 StartIndex) +{ + ACPI_OPERAND_OBJECT **ThisElement = Elements; + ACPI_STATUS Status; + UINT32 i; + + + ACPI_FUNCTION_TRACE (NsCheckPackageElements); + + /* + * 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 (Info, ThisElement, + Type1, i + StartIndex); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ThisElement++; + } + + for (i = 0; i < Count2; i++) + { + Status = AcpiNsCheckObjectType (Info, ThisElement, + Type2, (i + Count1 + StartIndex)); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + ThisElement++; + } + + return_ACPI_STATUS (AE_OK); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsrepair.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsrepair.c new file mode 100644 index 0000000..6c22f38 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsrepair.c @@ -0,0 +1,601 @@ +/****************************************************************************** + * + * Module Name: nsrepair - Repair for objects returned by predefined methods + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "acinterp.h" +#include "acpredef.h" +#include "amlresrc.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 conversions that are available: + * Convert a null return or zero return value to an EndTag descriptor + * Convert an ASCII string to a Unicode buffer + * + * An incorrect standalone object is wrapped with required outer package + * + * Additional possible repairs: + * Required package elements that are NULL replaced by Integer/String/Buffer + * + ******************************************************************************/ + + +/* Local prototypes */ + +static const ACPI_SIMPLE_REPAIR_INFO * +AcpiNsMatchSimpleRepair ( + ACPI_NAMESPACE_NODE *Node, + UINT32 ReturnBtype, + UINT32 PackageIndex); + + +/* + * Special but simple repairs for some names. + * + * 2nd argument: Unexpected types that can be repaired + */ +static const ACPI_SIMPLE_REPAIR_INFO AcpiObjectRepairInfo[] = +{ + /* Resource descriptor conversions */ + + { "_CRS", ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | ACPI_RTYPE_NONE, + ACPI_NOT_PACKAGE_ELEMENT, + AcpiNsConvertToResource }, + { "_DMA", ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | ACPI_RTYPE_NONE, + ACPI_NOT_PACKAGE_ELEMENT, + AcpiNsConvertToResource }, + { "_PRS", ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER | ACPI_RTYPE_NONE, + ACPI_NOT_PACKAGE_ELEMENT, + AcpiNsConvertToResource }, + + /* Object reference conversions */ + + { "_DEP", ACPI_RTYPE_STRING, ACPI_ALL_PACKAGE_ELEMENTS, + AcpiNsConvertToReference }, + + /* Unicode conversions */ + + { "_MLS", ACPI_RTYPE_STRING, 1, + AcpiNsConvertToUnicode }, + { "_STR", ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER, + ACPI_NOT_PACKAGE_ELEMENT, + AcpiNsConvertToUnicode }, + { {0,0,0,0}, 0, 0, NULL } /* Table terminator */ +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiNsSimpleRepair + * + * PARAMETERS: Info - Method execution information block + * 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 +AcpiNsSimpleRepair ( + ACPI_EVALUATE_INFO *Info, + UINT32 ExpectedBtypes, + UINT32 PackageIndex, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + ACPI_OPERAND_OBJECT *NewObject = NULL; + ACPI_STATUS Status; + const ACPI_SIMPLE_REPAIR_INFO *Predefined; + + + ACPI_FUNCTION_NAME (NsSimpleRepair); + + + /* + * Special repairs for certain names that are in the repair table. + * Check if this name is in the list of repairable names. + */ + Predefined = AcpiNsMatchSimpleRepair (Info->Node, + Info->ReturnBtype, PackageIndex); + if (Predefined) + { + if (!ReturnObject) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, + ACPI_WARN_ALWAYS, "Missing expected return value")); + } + + Status = Predefined->ObjectConverter (Info->Node, ReturnObject, + &NewObject); + if (ACPI_FAILURE (Status)) + { + /* A fatal error occurred during a conversion */ + + ACPI_EXCEPTION ((AE_INFO, Status, + "During return object analysis")); + return (Status); + } + if (NewObject) + { + goto ObjectRepaired; + } + } + + /* + * Do not perform simple object repair unless the return type is not + * expected. + */ + if (Info->ReturnBtype & ExpectedBtypes) + { + return (AE_OK); + } + + /* + * 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 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. + * + * Try to fix if there was no return object. Warning if failed to fix. + */ + if (!ReturnObject) + { + if (ExpectedBtypes) + { + if (!(ExpectedBtypes & ACPI_RTYPE_NONE) && + PackageIndex != ACPI_NOT_PACKAGE_ELEMENT) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, + ACPI_WARN_ALWAYS, "Found unexpected NULL package element")); + + Status = AcpiNsRepairNullElement (Info, ExpectedBtypes, + PackageIndex, ReturnObjectPtr); + if (ACPI_SUCCESS (Status)) + { + return (AE_OK); /* Repair was successful */ + } + } + + if (ExpectedBtypes != ACPI_RTYPE_NONE) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Info->FullPathname, + ACPI_WARN_ALWAYS, + "Missing expected return value")); + return (AE_AML_NO_RETURN_VALUE); + } + } + } + + 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) + { + /* + * A package is expected. We will wrap the existing object with a + * new package object. It is often the case that if a variable-length + * package is required, but there is only a single object needed, the + * BIOS will return that object instead of wrapping it with a Package + * object. Note: after the wrapping, the package will be validated + * for correct contents (expected object type or types). + */ + Status = AcpiNsWrapWithPackage (Info, ReturnObject, &NewObject); + if (ACPI_SUCCESS (Status)) + { + /* + * The original object just had its reference count + * incremented for being inserted into the new package. + */ + *ReturnObjectPtr = NewObject; /* New Package object */ + Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; + return (AE_OK); + } + } + + /* We cannot repair this object */ + + return (AE_AML_OPERAND_TYPE); + + +ObjectRepaired: + + /* Object was successfully repaired */ + + if (PackageIndex != ACPI_NOT_PACKAGE_ELEMENT) + { + /* Update reference count of new object */ + + if (!(Info->ReturnFlags & ACPI_OBJECT_WRAPPED)) + { + NewObject->Common.ReferenceCount = + ReturnObject->Common.ReferenceCount; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Converted %s to expected %s at Package index %u\n", + Info->FullPathname, AcpiUtGetObjectTypeName (ReturnObject), + AcpiUtGetObjectTypeName (NewObject), PackageIndex)); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Converted %s to expected %s\n", + Info->FullPathname, AcpiUtGetObjectTypeName (ReturnObject), + AcpiUtGetObjectTypeName (NewObject))); + } + + /* Delete old object, install the new return object */ + + AcpiUtRemoveReference (ReturnObject); + *ReturnObjectPtr = NewObject; + Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsMatchSimpleRepair + * + * PARAMETERS: Node - Namespace node for the method/object + * ReturnBtype - Object type that was returned + * PackageIndex - Index of object within parent package (if + * applicable - ACPI_NOT_PACKAGE_ELEMENT + * otherwise) + * + * RETURN: Pointer to entry in repair table. NULL indicates not found. + * + * DESCRIPTION: Check an object name against the repairable object list. + * + *****************************************************************************/ + +static const ACPI_SIMPLE_REPAIR_INFO * +AcpiNsMatchSimpleRepair ( + ACPI_NAMESPACE_NODE *Node, + UINT32 ReturnBtype, + UINT32 PackageIndex) +{ + const ACPI_SIMPLE_REPAIR_INFO *ThisName; + + + /* Search info table for a repairable predefined method/object name */ + + ThisName = AcpiObjectRepairInfo; + while (ThisName->ObjectConverter) + { + if (ACPI_COMPARE_NAMESEG (Node->Name.Ascii, ThisName->Name)) + { + /* Check if we can actually repair this name/type combination */ + + if ((ReturnBtype & ThisName->UnexpectedBtypes) && + (ThisName->PackageIndex == ACPI_ALL_PACKAGE_ELEMENTS || + PackageIndex == ThisName->PackageIndex)) + { + return (ThisName); + } + + return (NULL); + } + + ThisName++; + } + + return (NULL); /* Name was not found in the repair table */ +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsRepairNullElement + * + * PARAMETERS: Info - Method execution information block + * 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_EVALUATE_INFO *Info, + 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 = + Info->ParentPackage->Common.ReferenceCount; + + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Converted NULL package element to expected %s at index %u\n", + Info->FullPathname, AcpiUtGetObjectTypeName (NewObject), + PackageIndex)); + + *ReturnObjectPtr = NewObject; + Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsRemoveNullElements + * + * PARAMETERS: Info - Method execution information block + * PackageType - An AcpiReturnPackageTypes value + * ObjDesc - A Package object + * + * RETURN: None. + * + * DESCRIPTION: Remove all NULL package elements from packages that contain + * a variable number of subpackages. For these types of + * packages, NULL elements can be safely removed. + * + *****************************************************************************/ + +void +AcpiNsRemoveNullElements ( + ACPI_EVALUATE_INFO *Info, + 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 subpackages. + */ + 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_PTYPE2_VAR_VAR: + 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", + Info->FullPathname, (Count - NewCount))); + + /* NULL terminate list and update the package count */ + + *Dest = NULL; + ObjDesc->Package.Count = NewCount; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsWrapWithPackage + * + * PARAMETERS: Info - Method execution information block + * OriginalObject - Pointer to the object to repair. + * ObjDescPtr - The new package object is returned here + * + * RETURN: Status, new object in *ObjDescPtr + * + * DESCRIPTION: Repair a common problem with objects that are defined to + * return a variable-length Package of sub-objects. If there is + * only one sub-object, some BIOS code mistakenly simply declares + * the single object instead of a Package with one sub-object. + * This function attempts to repair this error by wrapping a + * Package object around the original object, creating the + * correct and expected Package with one sub-object. + * + * Names that can be repaired in this manner include: + * _ALR, _CSD, _HPX, _MLS, _PLD, _PRT, _PSS, _TRT, _TSS, + * _BCL, _DOD, _FIX, _Sx + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsWrapWithPackage ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ObjDescPtr) +{ + ACPI_OPERAND_OBJECT *PkgObjDesc; + + + ACPI_FUNCTION_NAME (NsWrapWithPackage); + + + /* + * Create the new outer package and populate it. The new + * package will have a single element, the lone sub-object. + */ + PkgObjDesc = AcpiUtCreatePackageObject (1); + if (!PkgObjDesc) + { + return (AE_NO_MEMORY); + } + + PkgObjDesc->Package.Elements[0] = OriginalObject; + + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Wrapped %s with expected Package object\n", + Info->FullPathname, AcpiUtGetObjectTypeName (OriginalObject))); + + /* Return the new object in the object pointer */ + + *ObjDescPtr = PkgObjDesc; + Info->ReturnFlags |= ACPI_OBJECT_REPAIRED | ACPI_OBJECT_WRAPPED; + return (AE_OK); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsrepair2.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsrepair2.c new file mode 100644 index 0000000..526b8d1 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsrepair2.c @@ -0,0 +1,1052 @@ +/****************************************************************************** + * + * Module Name: nsrepair2 - Repair for objects returned by specific + * predefined methods + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +typedef struct acpi_repair_info +{ + char Name[ACPI_NAMESEG_SIZE] ACPI_NONSTRING; + ACPI_REPAIR_FUNCTION RepairFunction; + +} ACPI_REPAIR_INFO; + + +/* Local prototypes */ + +static const ACPI_REPAIR_INFO * +AcpiNsMatchComplexRepair ( + ACPI_NAMESPACE_NODE *Node); + +static ACPI_STATUS +AcpiNsRepair_ALR ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +static ACPI_STATUS +AcpiNsRepair_CID ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +static ACPI_STATUS +AcpiNsRepair_CST ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +static ACPI_STATUS +AcpiNsRepair_FDE ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +static ACPI_STATUS +AcpiNsRepair_HID ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +static ACPI_STATUS +AcpiNsRepair_PRT ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +static ACPI_STATUS +AcpiNsRepair_PSS ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +static ACPI_STATUS +AcpiNsRepair_TSS ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +static ACPI_STATUS +AcpiNsCheckSortedList ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT *ReturnObject, + UINT32 StartIndex, + UINT32 ExpectedCount, + UINT32 SortIndex, + UINT8 SortDirection, + char *SortKeyName); + +/* Values for SortDirection above */ + +#define ACPI_SORT_ASCENDING 0 +#define ACPI_SORT_DESCENDING 1 + +static void +AcpiNsRemoveElement ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 Index); + +static void +AcpiNsSortList ( + ACPI_OPERAND_OBJECT **Elements, + UINT32 Count, + UINT32 Index, + UINT8 SortDirection); + + +/* + * 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 + * _CST: Sort the list ascending by C state type + * _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 + * _PRT: Fix reversed SourceName and SourceIndex + * _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}, + {"_CST", AcpiNsRepair_CST}, + {"_FDE", AcpiNsRepair_FDE}, + {"_GTM", AcpiNsRepair_FDE}, /* _GTM has same repair as _FDE */ + {"_HID", AcpiNsRepair_HID}, + {"_PRT", AcpiNsRepair_PRT}, + {"_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 * (UINT32) sizeof (UINT32)) + + +/****************************************************************************** + * + * FUNCTION: AcpiNsComplexRepairs + * + * PARAMETERS: Info - Method execution information block + * 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_EVALUATE_INFO *Info, + ACPI_NAMESPACE_NODE *Node, + ACPI_STATUS ValidateStatus, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + const ACPI_REPAIR_INFO *Predefined; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (NsComplexRepairs); + + /* Check if this name is in the list of repairable names */ + + Predefined = AcpiNsMatchComplexRepair (Node); + if (!Predefined) + { + return_ACPI_STATUS (ValidateStatus); + } + + Status = Predefined->RepairFunction (Info, ReturnObjectPtr); + return_ACPI_STATUS (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsMatchComplexRepair + * + * 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 * +AcpiNsMatchComplexRepair ( + 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_NAMESEG (Node->Name.Ascii, ThisName->Name)) + { + return (ThisName); + } + + ThisName++; + } + + return (NULL); /* Not found */ +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsRepair_ALR + * + * PARAMETERS: Info - Method execution information block + * 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_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + ACPI_STATUS Status; + + + Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 2, 1, + ACPI_SORT_ASCENDING, "AmbientIlluminance"); + + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsRepair_FDE + * + * PARAMETERS: Info - Method execution information block + * 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_EVALUATE_INFO *Info, + 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, + Info->FullPathname, Info->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", + Info->FullPathname)); + break; + + default: + + return (AE_AML_OPERAND_TYPE); + } + + /* Delete the original return object, return the new buffer object */ + + AcpiUtRemoveReference (ReturnObject); + *ReturnObjectPtr = BufferObject; + + Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsRepair_CID + * + * PARAMETERS: Info - Method execution information block + * 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_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_STATUS Status; + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + ACPI_OPERAND_OBJECT **ElementPtr; + ACPI_OPERAND_OBJECT *OriginalElement; + UINT16 OriginalRefCount; + UINT32 i; + + ACPI_FUNCTION_TRACE (NsRepair_CID); + + /* Check for _CID as a simple string */ + + if (ReturnObject->Common.Type == ACPI_TYPE_STRING) + { + Status = AcpiNsRepair_HID (Info, ReturnObjectPtr); + return_ACPI_STATUS (Status); + } + + /* Exit if not a Package */ + + if (ReturnObject->Common.Type != ACPI_TYPE_PACKAGE) + { + return_ACPI_STATUS (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 (Info, ElementPtr); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (OriginalElement != *ElementPtr) + { + /* Update reference count of new object */ + + (*ElementPtr)->Common.ReferenceCount = + OriginalRefCount; + } + + ElementPtr++; + } + + return_ACPI_STATUS (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsRepair_CST + * + * PARAMETERS: Info - Method execution information block + * 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 _CST object: + * 1. Sort the list ascending by C state type + * 2. Ensure type cannot be zero + * 3. A subpackage count of zero means _CST is meaningless + * 4. Count must match the number of C state subpackages + * + *****************************************************************************/ + +static ACPI_STATUS +AcpiNsRepair_CST ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + ACPI_OPERAND_OBJECT **OuterElements; + UINT32 OuterElementCount; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_STATUS Status; + BOOLEAN Removing; + UINT32 i; + + + ACPI_FUNCTION_NAME (NsRepair_CST); + + + /* + * Check if the C-state type values are proportional. + */ + OuterElementCount = ReturnObject->Package.Count - 1; + i = 0; + while (i < OuterElementCount) + { + OuterElements = &ReturnObject->Package.Elements[i + 1]; + Removing = FALSE; + + if ((*OuterElements)->Package.Count == 0) + { + ACPI_WARN_PREDEFINED ((AE_INFO, + Info->FullPathname, Info->NodeFlags, + "SubPackage[%u] - removing entry due to zero count", i)); + Removing = TRUE; + goto RemoveElement; + } + + ObjDesc = (*OuterElements)->Package.Elements[1]; /* Index1 = Type */ + if ((UINT32) ObjDesc->Integer.Value == 0) + { + ACPI_WARN_PREDEFINED ((AE_INFO, + Info->FullPathname, Info->NodeFlags, + "SubPackage[%u] - removing entry due to invalid Type(0)", i)); + Removing = TRUE; + } + +RemoveElement: + if (Removing) + { + AcpiNsRemoveElement (ReturnObject, i + 1); + OuterElementCount--; + } + else + { + i++; + } + } + + /* Update top-level package count, Type "Integer" checked elsewhere */ + + ObjDesc = ReturnObject->Package.Elements[0]; + ObjDesc->Integer.Value = OuterElementCount; + + /* + * Entries (subpackages) in the _CST Package must be sorted by the + * C-state type, in ascending order. + */ + Status = AcpiNsCheckSortedList (Info, ReturnObject, 1, 4, 1, + ACPI_SORT_ASCENDING, "C-State Type"); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsRepair_HID + * + * PARAMETERS: Info - Method execution information block + * 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_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_OPERAND_OBJECT *ReturnObject = *ReturnObjectPtr; + ACPI_OPERAND_OBJECT *NewString; + char *Source; + char *Dest; + + + ACPI_FUNCTION_TRACE (NsRepair_HID); + + + /* We only care about string _HID objects (not integers) */ + + if (ReturnObject->Common.Type != ACPI_TYPE_STRING) + { + return_ACPI_STATUS (AE_OK); + } + + if (ReturnObject->String.Length == 0) + { + ACPI_WARN_PREDEFINED ((AE_INFO, + Info->FullPathname, Info->NodeFlags, + "Invalid zero-length _HID or _CID string")); + + /* Return AE_OK anyway, let driver handle it */ + + Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; + return_ACPI_STATUS (AE_OK); + } + + /* It is simplest to always create a new string object */ + + NewString = AcpiUtCreateStringObject (ReturnObject->String.Length); + if (!NewString) + { + return_ACPI_STATUS (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", Info->FullPathname)); + } + + /* + * 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) toupper ((int) *Source); + } + + AcpiUtRemoveReference (ReturnObject); + *ReturnObjectPtr = NewString; + return_ACPI_STATUS (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsRepair_PRT + * + * PARAMETERS: Info - Method execution information block + * 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 _PRT object. If necessary, fix reversed + * SourceName and SourceIndex field, a common BIOS bug. + * + *****************************************************************************/ + +static ACPI_STATUS +AcpiNsRepair_PRT ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **ReturnObjectPtr) +{ + ACPI_OPERAND_OBJECT *PackageObject = *ReturnObjectPtr; + ACPI_OPERAND_OBJECT **TopObjectList; + ACPI_OPERAND_OBJECT **SubObjectList; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT *SubPackage; + UINT32 ElementCount; + UINT32 Index; + + + /* Each element in the _PRT package is a subpackage */ + + TopObjectList = PackageObject->Package.Elements; + ElementCount = PackageObject->Package.Count; + + /* Examine each subpackage */ + + for (Index = 0; Index < ElementCount; Index++, TopObjectList++) + { + SubPackage = *TopObjectList; + SubObjectList = SubPackage->Package.Elements; + + /* Check for minimum required element count */ + + if (SubPackage->Package.Count < 4) + { + continue; + } + + /* + * 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; + Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; + + ACPI_WARN_PREDEFINED ((AE_INFO, + Info->FullPathname, Info->NodeFlags, + "PRT[%X]: Fixed reversed SourceName and SourceIndex", + Index)); + } + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsRepair_PSS + * + * PARAMETERS: Info - Method execution information block + * 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_EVALUATE_INFO *Info, + 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 (subpackages) 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 (Info, ReturnObject, 0, 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, + Info->FullPathname, Info->NodeFlags, + "SubPackage[%u,%u] - suspicious power dissipation values", + i-1, i)); + } + + PreviousValue = (UINT32) ObjDesc->Integer.Value; + OuterElements++; + } + + return (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsRepair_TSS + * + * PARAMETERS: Info - Method execution information block + * 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_EVALUATE_INFO *Info, + 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 (Info->Node, "^_PSS", + ACPI_NS_NO_UPSEARCH, &Node); + if (ACPI_SUCCESS (Status)) + { + return (AE_OK); + } + + Status = AcpiNsCheckSortedList (Info, ReturnObject, 0, 5, 1, + ACPI_SORT_DESCENDING, "PowerDissipation"); + + return (Status); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsCheckSortedList + * + * PARAMETERS: Info - Method execution information block + * ReturnObject - Pointer to the top-level returned object + * StartIndex - Index of the first subpackage + * ExpectedCount - Minimum length of each subpackage + * SortIndex - Subpackage 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_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT *ReturnObject, + UINT32 StartIndex, + 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 subpackages contains no NULL elements. + * Any NULL elements should have been removed by earlier call + * to AcpiNsRemoveNullElements. + */ + OuterElementCount = ReturnObject->Package.Count; + if (!OuterElementCount || StartIndex >= OuterElementCount) + { + return (AE_AML_PACKAGE_LIMIT); + } + + OuterElements = &ReturnObject->Package.Elements[StartIndex]; + OuterElementCount -= StartIndex; + + 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 subpackage 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[StartIndex], + OuterElementCount, SortIndex, SortDirection); + + Info->ReturnFlags |= ACPI_OBJECT_REPAIRED; + + ACPI_DEBUG_PRINT ((ACPI_DB_REPAIR, + "%s: Repaired unsorted list - now sorted by %s\n", + Info->FullPathname, 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; + } + } + } +} + + +/****************************************************************************** + * + * FUNCTION: AcpiNsRemoveElement + * + * PARAMETERS: ObjDesc - Package object element list + * Index - Index of element to remove + * + * RETURN: None + * + * DESCRIPTION: Remove the requested element of a package and delete it. + * + *****************************************************************************/ + +static void +AcpiNsRemoveElement ( + ACPI_OPERAND_OBJECT *ObjDesc, + UINT32 Index) +{ + ACPI_OPERAND_OBJECT **Source; + ACPI_OPERAND_OBJECT **Dest; + UINT32 Count; + UINT32 NewCount; + UINT32 i; + + + ACPI_FUNCTION_NAME (NsRemoveElement); + + + Count = ObjDesc->Package.Count; + NewCount = Count - 1; + + Source = ObjDesc->Package.Elements; + Dest = Source; + + /* Examine all elements of the package object, remove matched index */ + + for (i = 0; i < Count; i++) + { + if (i == Index) + { + AcpiUtRemoveReference (*Source); /* Remove one ref for being in pkg */ + AcpiUtRemoveReference (*Source); + } + else + { + *Dest = *Source; + Dest++; + } + + Source++; + } + + /* NULL terminate list and update the package count */ + + *Dest = NULL; + ObjDesc->Package.Count = NewCount; +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/namespace/nssearch.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nssearch.c new file mode 100644 index 0000000..c239586 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nssearch.c @@ -0,0 +1,423 @@ +/******************************************************************************* + * + * Module Name: nssearch - Namespace search + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 = AcpiNsGetNormalizedPathname (ParentNode, TRUE); + 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) + { + /* The node was found in the namespace */ + + /* + * If the namespace override feature is enabled for this node, + * delete any existing attached sub-object and make the node + * look like a new node that is owned by the override table. + */ + if (Flags & ACPI_NS_OVERRIDE_IF_FOUND) + { + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "Namespace override: %4.4s pass %u type %X Owner %X\n", + ACPI_CAST_PTR(char, &TargetName), InterpreterMode, + (*ReturnNode)->Type, WalkState->OwnerId)); + + AcpiNsDeleteChildren (*ReturnNode); + if (AcpiGbl_RuntimeNamespaceOverride) + { + AcpiUtRemoveReference ((*ReturnNode)->Object); + (*ReturnNode)->Object = NULL; + (*ReturnNode)->OwnerId = WalkState->OwnerId; + } + else + { + AcpiNsRemoveNode (*ReturnNode); + *ReturnNode = ACPI_ENTRY_NOT_FOUND; + } + } + + /* Return an error if we don't expect to find the object */ + + else if (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/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsutils.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsutils.c new file mode 100644 index 0000000..045b4ad --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsutils.c @@ -0,0 +1,856 @@ +/****************************************************************************** + * + * Module Name: nsutils - Utilities for accessing ACPI namespace, accessing + * parents and siblings and Scope manipulation + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_NAMESPACE + ACPI_MODULE_NAME ("nsutils") + +/* Local prototypes */ + +#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, TRUE); + if (ACPI_SUCCESS (Status)) + { + if (Message) + { + AcpiOsPrintf ("%s ", Message); + } + + AcpiOsPrintf ("%s", (char *) Buffer.Pointer); + ACPI_FREE (Buffer.Pointer); + } +} + + +/******************************************************************************* + * + * 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_UINT8 (ACPI_TYPE_ANY); + } + + return_UINT8 (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 (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 (ACPI_IS_ROOT_PREFIX (*NextExternalChar)) + { + Info->FullyQualified = TRUE; + NextExternalChar++; + + /* Skip redundant RootPrefix, like \\_SB.PCI0.SBRG.EC0 */ + + while (ACPI_IS_ROOT_PREFIX (*NextExternalChar)) + { + NextExternalChar++; + } + } + else + { + /* Handle Carat prefixes */ + + while (ACPI_IS_PARENT_PREFIX (*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 (ACPI_IS_PATH_SEPARATOR (NextExternalChar[i])) + { + Info->NumSegments++; + } + } + } + + Info->Length = (ACPI_NAMESEG_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] = AML_ROOT_PREFIX; + + 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; + 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] = AML_PARENT_PREFIX; + } + } + + 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; + 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_NAMESEG_SIZE; i++) + { + if (ACPI_IS_PATH_SEPARATOR (*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) toupper ((int) *ExternalName); + ExternalName++; + } + } + + /* Now we must have a path separator, or the pathname is bad */ + + if (!ACPI_IS_PATH_SEPARATOR (*ExternalName) && + (*ExternalName != 0)) + { + return_ACPI_STATUS (AE_BAD_PATHNAME); + } + + /* Move on the next segment */ + + ExternalName++; + Result += ACPI_NAMESEG_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 representation 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 - Length 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 AML_ROOT_PREFIX: + + PrefixLength = 1; + break; + + case AML_PARENT_PREFIX: + + for (i = 0; i < InternalNameLength; i++) + { + if (ACPI_IS_PARENT_PREFIX (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: + + /* 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++] = '.'; + } + + /* Copy and validate the 4-char name segment */ + + ACPI_COPY_NAMESEG (&(*ConvertedName)[j], + &InternalName[NamesIndex]); + AcpiUtRepairName (&(*ConvertedName)[j]); + + j += ACPI_NAMESEG_SIZE; + NamesIndex += ACPI_NAMESEG_SIZE; + } + } + + 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_STATUS Status; + + + ACPI_FUNCTION_TRACE (NsTerminate); + + + /* + * Free the entire namespace -- all nodes and all objects + * attached to the nodes + */ + AcpiNsDeleteNamespaceSubtree (AcpiGbl_RootNode); + + /* Delete any objects attached to the root node */ + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_VOID; + } + + AcpiNsDeleteNode (AcpiGbl_RootNode); + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + + 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_ENTRY (); + + + if (Type > ACPI_TYPE_LOCAL_MAX) + { + /* type code out of range */ + + ACPI_WARNING ((AE_INFO, "Invalid Object Type 0x%X", Type)); + return (ACPI_NS_NORMAL); + } + + return (((UINT32) AcpiGbl_NsProperties[Type]) & ACPI_NS_NEWSCOPE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiNsGetNodeUnlocked + * + * 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: Doesn't locks namespace + * + ******************************************************************************/ + +ACPI_STATUS +AcpiNsGetNodeUnlocked ( + 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 (NsGetNodeUnlocked, ACPI_CAST_PTR (char, Pathname)); + + + /* Simplest case is a null pathname */ + + if (!Pathname) + { + *ReturnNode = PrefixNode; + if (!PrefixNode) + { + *ReturnNode = AcpiGbl_RootNode; + } + + return_ACPI_STATUS (AE_OK); + } + + /* Quick check for a reference to the root */ + + if (ACPI_IS_ROOT_PREFIX (Pathname[0]) && (!Pathname[1])) + { + *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); + } + + /* 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))); + } + + ACPI_FREE (InternalPath); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * 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_STATUS Status; + + + ACPI_FUNCTION_TRACE_PTR (NsGetNode, ACPI_CAST_PTR (char, Pathname)); + + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiNsGetNodeUnlocked (PrefixNode, Pathname, + Flags, ReturnNode); + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return_ACPI_STATUS (Status); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/namespace/nswalk.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nswalk.c new file mode 100644 index 0000000..ddd0d15 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nswalk.c @@ -0,0 +1,358 @@ +/****************************************************************************** + * + * Module Name: nswalk - Functions for walking the ACPI namespace + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 + * DescendingCallback - Called during tree descent + * when an object of "Type" is found + * AscendingCallback - Called during tree ascent + * 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 DescendingCallback, + ACPI_WALK_CALLBACK AscendingCallback, + 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; + } + + /* Avoid walking the namespace if the StartNode is NULL */ + + if (!StartNode) + { + return_ACPI_STATUS (AE_NO_NAMESPACE); + } + + /* 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 descending, ascending, + * or both. + */ + if (!NodePreviouslyVisited) + { + if (DescendingCallback) + { + Status = DescendingCallback (ChildNode, Level, + Context, ReturnValue); + } + } + else + { + if (AscendingCallback) + { + Status = AscendingCallback (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/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsxfeval.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsxfeval.c new file mode 100644 index 0000000..e39b360 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsxfeval.c @@ -0,0 +1,1075 @@ +/******************************************************************************* + * + * Module Name: nsxfeval - Public interfaces to the ACPI subsystem + * ACPI Object evaluation interfaces + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#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 a method, + * terminated by NULL. May be NULL + * if no parameters are being passed. + * ReturnBuffer - Where to put the object return value (if + * any). Required. + * 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 FreeBufferOnError = FALSE; + ACPI_HANDLE TargetHandle; + char *FullPathname; + + + ACPI_FUNCTION_TRACE (AcpiEvaluateObjectTyped); + + + /* Return buffer must be valid */ + + if (!ReturnBuffer) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + if (ReturnBuffer->Length == ACPI_ALLOCATE_BUFFER) + { + FreeBufferOnError = TRUE; + } + + /* Get a handle here, in order to build an error message if needed */ + + TargetHandle = Handle; + if (Pathname) + { + Status = AcpiGetHandle (Handle, Pathname, &TargetHandle); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + FullPathname = AcpiNsGetExternalPathname (TargetHandle); + if (!FullPathname) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Evaluate the object */ + + Status = AcpiEvaluateObject (TargetHandle, NULL, ExternalParams, + ReturnBuffer); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + + /* Type ANY means "don't care about return value type" */ + + if (ReturnType == ACPI_TYPE_ANY) + { + goto Exit; + } + + if (ReturnBuffer->Length == 0) + { + /* Error because caller specifically asked for a return value */ + + ACPI_ERROR ((AE_INFO, "%s did not return any object", + FullPathname)); + Status = AE_NULL_OBJECT; + goto Exit; + } + + /* Examine the object type returned from EvaluateObject */ + + if (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type == ReturnType) + { + goto Exit; + } + + /* Return object type does not match requested type */ + + ACPI_ERROR ((AE_INFO, + "Incorrect return type from %s - received [%s], requested [%s]", + FullPathname, + AcpiUtGetTypeName (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type), + AcpiUtGetTypeName (ReturnType))); + + if (FreeBufferOnError) + { + /* + * Free a buffer created via ACPI_ALLOCATE_BUFFER. + * Note: We use AcpiOsFree here because AcpiOsAllocate was used + * to allocate the buffer. This purposefully bypasses the + * (optionally enabled) allocation tracking mechanism since we + * only want to track internal allocations. + */ + AcpiOsFree (ReturnBuffer->Pointer); + ReturnBuffer->Pointer = NULL; + } + + ReturnBuffer->Length = 0; + Status = AE_TYPE; + +Exit: + ACPI_FREE (FullPathname); + return_ACPI_STATUS (Status); +} + +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); + } + + /* Convert and validate the device handle */ + + Info->PrefixNode = AcpiNsValidateHandle (Handle); + if (!Info->PrefixNode) + { + Status = AE_BAD_PARAMETER; + goto Cleanup; + } + + /* + * Get the actual namespace node for the target object. + * Handles these cases: + * + * 1) Null node, valid pathname from root (absolute path) + * 2) Node and valid pathname (path relative to Node) + * 3) Node, Null pathname + */ + if ((Pathname) && + (ACPI_IS_ROOT_PREFIX (Pathname[0]))) + { + /* The path is fully qualified, just evaluate by name */ + + Info->PrefixNode = NULL; + } + 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; + goto Cleanup; + } + + Info->RelativePathname = Pathname; + + /* + * Convert all external objects passed as arguments to the + * internal version(s). + */ + if (ExternalParams && ExternalParams->Count) + { + Info->ParamCount = (UINT16) ExternalParams->Count; + + /* Warn on impossible argument count */ + + if (Info->ParamCount > ACPI_METHOD_NUM_ARGS) + { + ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS, + "Excess arguments (%u) - using only %u", + Info->ParamCount, ACPI_METHOD_NUM_ARGS)); + + Info->ParamCount = ACPI_METHOD_NUM_ARGS; + } + + /* + * 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) Info->ParamCount + 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 < Info->ParamCount; i++) + { + Status = AcpiUtCopyEobjectToIobject ( + &ExternalParams->Pointer[i], &Info->Parameters[i]); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + } + + Info->Parameters[Info->ParamCount] = NULL; + } + + +#ifdef _FUTURE_FEATURE + + /* + * Begin incoming argument count analysis. Check for too few args + * and too many args. + */ + switch (AcpiNsGetType (Info->Node)) + { + case ACPI_TYPE_METHOD: + + /* Check incoming argument count against the method definition */ + + if (Info->ObjDesc->Method.ParamCount > Info->ParamCount) + { + ACPI_ERROR ((AE_INFO, + "Insufficient arguments (%u) - %u are required", + Info->ParamCount, + Info->ObjDesc->Method.ParamCount)); + + Status = AE_MISSING_ARGUMENTS; + goto Cleanup; + } + + else if (Info->ObjDesc->Method.ParamCount < Info->ParamCount) + { + ACPI_WARNING ((AE_INFO, + "Excess arguments (%u) - only %u are required", + Info->ParamCount, + Info->ObjDesc->Method.ParamCount)); + + /* Just pass the required number of arguments */ + + Info->ParamCount = Info->ObjDesc->Method.ParamCount; + } + + /* + * Any incoming external objects to be passed as arguments to the + * method must be converted to internal objects + */ + if (Info->ParamCount) + { + /* + * 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) Info->ParamCount + 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 < Info->ParamCount; i++) + { + Status = AcpiUtCopyEobjectToIobject ( + &ExternalParams->Pointer[i], &Info->Parameters[i]); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + } + + Info->Parameters[Info->ParamCount] = NULL; + } + break; + + default: + + /* Warn if arguments passed to an object that is not a method */ + + if (Info->ParamCount) + { + ACPI_WARNING ((AE_INFO, + "%u arguments were passed to a non-method ACPI object", + Info->ParamCount)); + } + break; + } + +#endif + + + /* Now we can evaluate the object */ + + 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) + { + goto CleanupReturnObject; + } + + if (!Info->ReturnObject) + { + ReturnBuffer->Length = 0; + goto Cleanup; + } + + 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_FAILURE (Status)) + { + goto CleanupReturnObject; + } + + /* 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); + } + } + +CleanupReturnObject: + + 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 + * DescendingCallback - Called during tree descent + * when an object of "Type" is found + * AscendingCallback - Called during tree ascent + * 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 DescendingCallback, + ACPI_WALK_CALLBACK AscendingCallback, + void *Context, + void **ReturnValue) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiWalkNamespace); + + + /* Parameter validation */ + + if ((Type > ACPI_TYPE_LOCAL_MAX) || + (!MaxDepth) || + (!DescendingCallback && !AscendingCallback)) + { + 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_ACPI_STATUS (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; + } + + /* Now we can validate the starting node */ + + if (!AcpiNsValidateHandle (StartObject)) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit2; + } + + Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth, + ACPI_NS_WALK_UNLOCK, DescendingCallback, + AscendingCallback, Context, ReturnValue); + +UnlockAndExit2: + (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_PNP_DEVICE_ID *Hid; + ACPI_PNP_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 = 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 (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/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsxfname.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsxfname.c new file mode 100644 index 0000000..4c7c1a4 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsxfname.c @@ -0,0 +1,689 @@ +/****************************************************************************** + * + * Module Name: nsxfname - Public interfaces to the ACPI subsystem + * ACPI Namespace oriented interfaces + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#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_PNP_DEVICE_ID *Dest, + ACPI_PNP_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, + const char *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 (ACPI_IS_ROOT_PREFIX (Pathname[0])) + { + /* Pathname is fully qualified (starts with '\') */ + + /* Special case for root-only, since we can't search for it */ + + if (!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; + + + /* Parameter validation */ + + if (NameType > ACPI_NAME_TYPE_MAX) + { + return (AE_BAD_PARAMETER); + } + + Status = AcpiUtValidateBuffer (Buffer); + if (ACPI_FAILURE (Status)) + { + 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); + } + + if (NameType == ACPI_FULL_PATHNAME || + NameType == ACPI_FULL_PATHNAME_NO_TRAILING) + { + /* Get the full pathname (From the namespace root) */ + + Status = AcpiNsHandleToPathname (Handle, Buffer, + NameType == ACPI_FULL_PATHNAME ? FALSE : TRUE); + } + else + { + /* Get the single name */ + + Status = AcpiNsHandleToName (Handle, Buffer); + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetName) + + +/****************************************************************************** + * + * FUNCTION: AcpiNsCopyDeviceId + * + * PARAMETERS: Dest - Pointer to the destination PNP_DEVICE_ID + * Source - Pointer to the source PNP_DEVICE_ID + * StringArea - Pointer to where to copy the dest string + * + * RETURN: Pointer to the next string area + * + * DESCRIPTION: Copy a single PNP_DEVICE_ID, including the string data. + * + ******************************************************************************/ + +static char * +AcpiNsCopyDeviceId ( + ACPI_PNP_DEVICE_ID *Dest, + ACPI_PNP_DEVICE_ID *Source, + char *StringArea) +{ + /* Create the destination PNP_DEVICE_ID */ + + Dest->String = StringArea; + Dest->Length = Source->Length; + + /* Copy actual string and return a pointer to the next string area */ + + 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, + * _CLS, _ADR, _SxW, and _SxD methods. + * + * Note: Allocates the return buffer, must be freed by the caller. + * + * Note: This interface is intended to be used during the initial device + * discovery namespace traversal. Therefore, no complex methods can be + * executed, especially those that access operation regions. Therefore, do + * not add any additional methods that could cause problems in this area. + * Because of this reason support for the following methods has been removed: + * 1) _SUB method was removed (11/2015) + * 2) _STA method was removed (02/2018) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetObjectInfo ( + ACPI_HANDLE Handle, + ACPI_DEVICE_INFO **ReturnBuffer) +{ + ACPI_NAMESPACE_NODE *Node; + ACPI_DEVICE_INFO *Info; + ACPI_PNP_DEVICE_ID_LIST *CidList = NULL; + ACPI_PNP_DEVICE_ID *Hid = NULL; + ACPI_PNP_DEVICE_ID *Uid = NULL; + ACPI_PNP_DEVICE_ID *Cls = NULL; + char *NextIdString; + ACPI_OBJECT_TYPE Type; + ACPI_NAME Name; + UINT8 ParamCount= 0; + UINT16 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)) + { + return (Status); + } + + 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, _CLS, 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_PNP_DEVICE_ID_LIST)); + Valid |= ACPI_VALID_CID; + } + + /* Execute the Device._CLS method */ + + Status = AcpiUtExecute_CLS (Node, &Cls); + if (ACPI_SUCCESS (Status)) + { + InfoSize += Cls->Length; + Valid |= ACPI_VALID_CLS; + } + } + + /* + * 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 _ADR and, SxW, and _SxD methods. + * + * Notes: 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._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 PNP_DEVICE_ID array */ + + NextIdString += ((ACPI_SIZE) CidList->Count * sizeof (ACPI_PNP_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; + } + } + } + + if (Cls) + { + (void) AcpiNsCopyDeviceId (&Info->ClassCode, + Cls, NextIdString); + } + + /* 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); + } + if (Cls) + { + ACPI_FREE (Cls); + } + 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_NAMESEG (Table->Signature, ACPI_SIG_DSDT) && + !ACPI_COMPARE_NAMESEG (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); + ParserState.AmlEnd = Buffer + Table->Length; + 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); + if ((ParserState.PkgEnd > ParserState.AmlEnd) || + (ParserState.PkgEnd < ParserState.Aml)) + { + return (AE_AML_PACKAGE_LIMIT); + } + Path = AcpiPsGetNextNamestring (&ParserState); + + /* + * Path can be NULL, and Aml can be PkgEnd which combined with the Aml++ + * a few lines below will cause AmlLength to underflow. + */ + if (!Path || (ParserState.Aml >= ParserState.PkgEnd)) + { + return (AE_AML_PACKAGE_LIMIT); + } + + MethodFlags = *ParserState.Aml++; + AmlStart = ParserState.Aml; + AmlLength = (UINT32) 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 */ + + 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); + AcpiUtDeleteObjectDesc (MethodObj); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallMethod) diff --git a/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsxfobj.c b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsxfobj.c new file mode 100644 index 0000000..4b0f544 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/namespace/nsxfobj.c @@ -0,0 +1,251 @@ +/******************************************************************************* + * + * Module Name: nsxfobj - Public interfaces to the ACPI subsystem + * ACPI Object oriented interfaces + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#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 associated 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/code/drivers/platform/acpi/third_party/acpica/components/parser/psargs.c b/code/drivers/platform/acpi/third_party/acpica/components/parser/psargs.c new file mode 100644 index 0000000..8ef957d --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/parser/psargs.c @@ -0,0 +1,1161 @@ +/****************************************************************************** + * + * Module Name: psargs - Parse AML opcode arguments + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acnamesp.h" +#include "acdispat.h" +#include "acconvert.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); + +static void +AcpiPsFreeFieldList ( + ACPI_PARSE_OBJECT *Start); + + +/******************************************************************************* + * + * 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] */ + UINT32 Remaining; + + + 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 + */ + + /* Check if we have at least one byte to read */ + Remaining = (UINT32) ACPI_PTR_DIFF (ParserState->AmlEnd, Aml); + if (Remaining == 0) + { + return_UINT32 (0); + } + + ByteCount = (Aml[0] >> 6); + + /* Validate ByteCount and ensure we have enough bytes to read */ + if (ByteCount >= Remaining) + { + /* Clamp to available bytes and advance to end */ + ParserState->Aml = ParserState->AmlEnd; + return_UINT32 (0); + } + + 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 (End < ParserState->AmlEnd && + (ACPI_IS_ROOT_PREFIX (*End) || + ACPI_IS_PARENT_PREFIX (*End))) + { + End++; + } + + if (End >= ParserState->AmlEnd) + { + ParserState->Aml = ParserState->AmlEnd; + return_PTR (NULL); + } + + /* 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_NAMESEG_SIZE); + break; + + case AML_MULTI_NAME_PREFIX: + + /* Multiple name segments, 4 chars each, count in next byte */ + + if ((End + 1) >= ParserState->AmlEnd) + { + ParserState->Aml = ParserState->AmlEnd; + return_PTR (NULL); + } + + End += 2 + (*(End + 1) * ACPI_NAMESEG_SIZE); + break; + + default: + + /* Single name segment */ + + End += ACPI_NAMESEG_SIZE; + break; + } + + if (End > ParserState->AmlEnd) + { + ParserState->Aml = ParserState->AmlEnd; + return_PTR (NULL); + } + + 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 ((GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) == ARGP_SUPERNAME) || + (GET_CURRENT_ARG_TYPE (WalkState->ArgTypes) == ARGP_TARGET)) + { + /* + * AcpiPsGetNextNamestring has increased the AML pointer past + * the method invocation namestring, so we need to restore the + * saved AML pointer back to the original method invocation + * namestring. + */ + WalkState->ParserState.Aml = Start; + WalkState->ArgCount = 1; + AcpiPsInitOp (Arg, AML_INT_METHODCALL_OP); + } + + /* This name is actually a control method invocation */ + + MethodDesc = AcpiNsGetAttachedObject (Node); + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Control Method invocation %4.4s - %p Desc %p Path=%p\n", + Node->Name.Ascii, Node, MethodDesc, Path)); + + NameOp = AcpiPsAllocOp (AML_INT_NAMEPATH_OP, Start); + 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_CONDITIONAL_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_VARIABLE_PACKAGE_OP))) + { + Status = AE_OK; + } + } + + /* Final exception check (may have been changed from code above) */ + + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR_NAMESPACE (WalkState->ScopeInfo, 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; + UINT32 Remaining = (UINT32) ACPI_PTR_DIFF (ParserState->AmlEnd, Aml); + UINT64 PartialValue; + + + ACPI_FUNCTION_TRACE_U32 (PsGetNextSimpleArg, ArgType); + + + switch (ArgType) + { + case ARGP_BYTEDATA: + + /* Get 1 byte from the AML stream */ + + Opcode = AML_BYTE_OP; + if (Remaining >= 1) + { + Arg->Common.Value.Integer = (UINT64) *Aml; + Length = 1; + } + else + { + Arg->Common.Value.Integer = 0; + Length = 0; + } + break; + + case ARGP_WORDDATA: + + /* Get 2 bytes from the AML stream */ + + Opcode = AML_WORD_OP; + if (Remaining >= 2) + { + ACPI_MOVE_16_TO_64 (&Arg->Common.Value.Integer, Aml); + Length = 2; + } + else + { + Arg->Common.Value.Integer = 0; + Length = 0; + if (Remaining > 0) + { + PartialValue = 0; + memcpy (&PartialValue, Aml, Remaining); + Arg->Common.Value.Integer = PartialValue; + Length = Remaining; + } + } + break; + + case ARGP_DWORDDATA: + + /* Get 4 bytes from the AML stream */ + + Opcode = AML_DWORD_OP; + if (Remaining >= 4) + { + ACPI_MOVE_32_TO_64 (&Arg->Common.Value.Integer, Aml); + Length = 4; + } + else + { + Arg->Common.Value.Integer = 0; + Length = 0; + if (Remaining > 0) + { + PartialValue = 0; + memcpy (&PartialValue, Aml, Remaining); + Arg->Common.Value.Integer = PartialValue; + Length = Remaining; + } + } + break; + + case ARGP_QWORDDATA: + + /* Get 8 bytes from the AML stream */ + + Opcode = AML_QWORD_OP; + if (Remaining >= 8) + { + ACPI_MOVE_64_TO_64 (&Arg->Common.Value.Integer, Aml); + Length = 8; + } + else + { + Arg->Common.Value.Integer = 0; + Length = 0; + if (Remaining > 0) + { + PartialValue = 0; + memcpy (&PartialValue, Aml, Remaining); + Arg->Common.Value.Integer = PartialValue; + Length = Remaining; + } + } + 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 ((Length < Remaining) && Aml[Length]) + { + Length++; + } + if (Length < Remaining) + { + /* Account for the terminating null */ + Length++; + } + else + { + /* + * No terminator found - add null at buffer boundary + * and report a warning + */ + ACPI_WARNING ((AE_INFO, + "Invalid AML string: no null terminator, truncating at offset %u", + (UINT32) (Aml - ParserState->Aml))); + + /* Add null terminator at the boundary */ + if (Remaining > 0) + { + Aml[Remaining - 1] = 0; + Length = Remaining; + } + } + 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) +{ + UINT8 *Aml; + 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); + + + ASL_CV_CAPTURE_COMMENTS_ONLY (ParserState); + Aml = ParserState->Aml; + + if (Aml >= ParserState->AmlEnd) + { + return_PTR (NULL); + } + + /* 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, Aml); + if (!Field) + { + return_PTR (NULL); + } + + /* Decode the field type */ + + ASL_CV_CAPTURE_COMMENTS_ONLY (ParserState); + switch (Opcode) + { + case AML_INT_NAMEDFIELD_OP: + + /* Get the 4-character name */ + + if ((ParserState->Aml + ACPI_NAMESEG_SIZE) > ParserState->AmlEnd) + { + AcpiPsFreeOp (Field); + return_PTR (NULL); + } + ACPI_MOVE_32_TO_32 (&Name, ParserState->Aml); + AcpiPsSetName (Field, Name); + ParserState->Aml += ACPI_NAMESEG_SIZE; + + + ASL_CV_CAPTURE_COMMENTS_ONLY (ParserState); + +#ifdef ACPI_ASL_COMPILER + /* + * Because the package length isn't represented as a parse tree object, + * take comments surrounding this and add to the previously created + * parse node. + */ + if (Field->Common.InlineComment) + { + Field->Common.NameComment = Field->Common.InlineComment; + } + Field->Common.InlineComment = AcpiGbl_CurrentInlineComment; + AcpiGbl_CurrentInlineComment = NULL; +#endif + + /* 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) */ + + if ((ParserState->Aml + 2) > ParserState->AmlEnd) + { + AcpiPsFreeOp (Field); + return_PTR (NULL); + } + 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) + { + if (ParserState->Aml >= ParserState->AmlEnd) + { + AcpiPsFreeOp (Field); + return_PTR (NULL); + } + 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. + */ + Aml = ParserState->Aml; + if (ACPI_GET8 (ParserState->Aml) == AML_BUFFER_OP) + { + ParserState->Aml++; + + ASL_CV_CAPTURE_COMMENTS_ONLY (ParserState); + PkgEnd = ParserState->Aml; + PkgLength = AcpiPsGetNextPackageLength (ParserState); + PkgEnd += PkgLength; + + ASL_CV_CAPTURE_COMMENTS_ONLY (ParserState); + if (ParserState->Aml < PkgEnd) + { + /* Non-empty list */ + + Arg = AcpiPsAllocOp (AML_INT_BYTELIST_OP, Aml); + if (!Arg) + { + AcpiPsFreeOp (Field); + return_PTR (NULL); + } + + /* Get the actual buffer length argument */ + + Opcode = ACPI_GET8 (ParserState->Aml); + ParserState->Aml++; + + ASL_CV_CAPTURE_COMMENTS_ONLY (ParserState); + 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 */ + + ASL_CV_CAPTURE_COMMENTS_ONLY (ParserState); + Arg->Named.Value.Size = BufferLength; + Arg->Named.Length = (UINT32) + ACPI_PTR_DIFF (PkgEnd, ParserState->Aml); + Arg->Named.Data = ParserState->Aml; + } + + /* Skip to End of byte data */ + + ParserState->Aml = PkgEnd; + } + else + { + Arg = AcpiPsAllocOp (AML_INT_NAMEPATH_OP, Aml); + if (!Arg) + { + AcpiPsFreeOp (Field); + 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: AcpiPsFreeFieldList + * + * PARAMETERS: Start - First Op in field list + * + * RETURN: None. + * + * DESCRIPTION: Free all Op objects inside a field list. + * + ******************************************************************************/ + +static void +AcpiPsFreeFieldList ( + ACPI_PARSE_OBJECT *Start) +{ + ACPI_PARSE_OBJECT *Current = Start; + ACPI_PARSE_OBJECT *Next; + ACPI_PARSE_OBJECT *Arg; + + while (Current) + { + Next = Current->Common.Next; + + /* AML_INT_CONNECTION_OP can have a single argument */ + + Arg = AcpiPsGetArg (Current, 0); + if (Arg) + { + AcpiPsFreeOp (Arg); + } + + AcpiPsFreeOp(Current); + Current = Next; + } +} + + +/******************************************************************************* + * + * 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); + + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Expected argument type ARGP: %s (%2.2X)\n", + AcpiUtGetArgumentTypeName (ArgType), ArgType)); + + 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, ParserState->Aml); + if (!Arg) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + AcpiPsGetNextSimpleArg (ParserState, ArgType, Arg); + break; + + case ARGP_PKGLENGTH: + + /* Package length, nothing returned */ + + ParserState->PkgEnd = AcpiPsGetNextPackageEnd (ParserState); + if ((ParserState->PkgEnd > ParserState->AmlEnd) || + (ParserState->PkgEnd < ParserState->Aml)) + { + return_ACPI_STATUS (AE_AML_PACKAGE_LIMIT); + } + break; + + case ARGP_FIELDLIST: + + if (ParserState->Aml < ParserState->PkgEnd) + { + /* Non-empty list */ + + while (ParserState->Aml < ParserState->PkgEnd) + { + Field = AcpiPsGetNextField (ParserState); + if (!Field) + { + if (Arg) + { + AcpiPsFreeFieldList(Arg); + } + + 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, + ParserState->Aml); + if (!Arg) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Fill in bytelist data */ + + Arg->Common.Value.Size = Arg->Named.Length = (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_SIMPLENAME: + case ARGP_NAME_OR_REF: + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "**** SimpleName/NameOrRef: %s (%2.2X)\n", + AcpiUtGetArgumentTypeName (ArgType), ArgType)); + + Subop = AcpiPsPeekOpcode (ParserState); + if (Subop == 0 || + AcpiPsIsLeadingChar (Subop) || + ACPI_IS_ROOT_PREFIX (Subop) || + ACPI_IS_PARENT_PREFIX (Subop)) + { + /* NullName or NameString */ + + Arg = AcpiPsAllocOp (AML_INT_NAMEPATH_OP, ParserState->Aml); + if (!Arg) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Status = AcpiPsGetNextNamepath (WalkState, ParserState, + Arg, ACPI_NOT_METHOD_CALL); + if (ACPI_FAILURE(Status)) + { + AcpiPsFreeOp (Arg); + return_ACPI_STATUS (Status); + } + } + else + { + /* Single complex argument, nothing returned */ + + WalkState->ArgCount = 1; + } + break; + + case ARGP_TARGET: + case ARGP_SUPERNAME: + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "**** Target/Supername: %s (%2.2X)\n", + AcpiUtGetArgumentTypeName (ArgType), ArgType)); + + Subop = AcpiPsPeekOpcode (ParserState); + if (Subop == 0 || + AcpiPsIsLeadingChar (Subop) || + ACPI_IS_ROOT_PREFIX (Subop) || + ACPI_IS_PARENT_PREFIX (Subop)) + { + /* NULL target (zero). Convert to a NULL namepath */ + + Arg = AcpiPsAllocOp (AML_INT_NAMEPATH_OP, ParserState->Aml); + if (!Arg) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + Status = AcpiPsGetNextNamepath (WalkState, ParserState, + Arg, ACPI_POSSIBLE_METHOD_CALL); + if (ACPI_FAILURE(Status)) + { + AcpiPsFreeOp (Arg); + return_ACPI_STATUS (Status); + } + + if (Arg->Common.AmlOpcode == AML_INT_METHODCALL_OP) + { + /* Free method call op and corresponding namestring sub-ob */ + + AcpiPsFreeOp (Arg->Common.Value.Arg); + AcpiPsFreeOp (Arg); + Arg = NULL; + WalkState->ArgCount = 1; + } + } + else + { + /* Single complex argument, nothing returned */ + + WalkState->ArgCount = 1; + } + break; + + case ARGP_DATAOBJ: + case ARGP_TERMARG: + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "**** TermArg/DataObj: %s (%2.2X)\n", + AcpiUtGetArgumentTypeName (ArgType), ArgType)); + + /* 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/code/drivers/platform/acpi/third_party/acpica/components/parser/psloop.c b/code/drivers/platform/acpi/third_party/acpica/components/parser/psloop.c new file mode 100644 index 0000000..e27beb6 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/parser/psloop.c @@ -0,0 +1,574 @@ +/****************************************************************************** + * + * Module Name: psloop - Main AML parse loop + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +/* + * 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 "acinterp.h" +#include "acparser.h" +#include "acdispat.h" +#include "amlcode.h" +#include "acconvert.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_PARSER + ACPI_MODULE_NAME ("psloop") + + +/* Local prototypes */ + +static ACPI_STATUS +AcpiPsGetArguments ( + ACPI_WALK_STATE *WalkState, + UINT8 *AmlOpStart, + ACPI_PARSE_OBJECT *Op); + + +/******************************************************************************* + * + * 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; + + + ACPI_FUNCTION_TRACE_PTR (PsGetArguments, WalkState); + + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Get arguments for opcode [%s]\n", Op->Common.AmlOpName)); + + 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, ACPI_POSSIBLE_METHOD_CALL); + 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->Aml = WalkState->ParserState.Aml; + + switch (Op->Common.AmlOpcode) + { + case AML_METHOD_OP: + case AML_BUFFER_OP: + case AML_PACKAGE_OP: + case AML_VARIABLE_PACKAGE_OP: + case AML_WHILE_OP: + + break; + + default: + + ASL_CV_CAPTURE_COMMENTS (WalkState); + break; + } + + Status = AcpiPsGetNextArg (WalkState, &(WalkState->ParserState), + GET_CURRENT_ARG_TYPE (WalkState->ArgTypes), &Arg); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + if (Arg) + { + AcpiPsAppendArg (Op, Arg); + } + + INCREMENT_ARG_LIST (WalkState->ArgTypes); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Final argument count: %8.8X pass %u\n", + WalkState->ArgCount, WalkState->PassNumber)); + + /* 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_VARIABLE_PACKAGE_OP: + + if ((Op->Common.Parent) && + (Op->Common.Parent->Common.AmlOpcode == AML_NAME_OP) && + (WalkState->PassNumber <= ACPI_IMODE_LOAD_PASS2)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Setup Package/Buffer: Pass %u, AML Ptr: %p\n", + WalkState->PassNumber, AmlOpStart)); + + /* + * 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: 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; + UINT8 OpcodeLength; + + + ACPI_FUNCTION_TRACE_PTR (PsParseLoop, WalkState); + + + if (WalkState->DescendingCallback == NULL) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + ParserState = &WalkState->ParserState; + WalkState->ArgTypes = 0; + +#ifndef 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) && !ACPI_CNTL_EXCEPTION (Status)) + { + 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)) + { + ASL_CV_CAPTURE_COMMENTS (WalkState); + + AmlOpStart = ParserState->Aml; + if (!Op) + { + Status = AcpiPsCreateOp (WalkState, AmlOpStart, &Op); + if (ACPI_FAILURE (Status)) + { + /* + * ACPI_PARSE_MODULE_LEVEL means that we are loading a table by + * executing it as a control method. However, if we encounter + * an error while loading the table, we need to keep trying to + * load the table rather than aborting the table load. Set the + * status to AE_OK to proceed with the table load. + */ + if ((WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL) && + ((Status == AE_ALREADY_EXISTS) || (Status == AE_NOT_FOUND))) + { + Status = AE_OK; + } + if (Status == AE_CTRL_PARSE_CONTINUE) + { + continue; + } + + if (Status == AE_CTRL_PARSE_PENDING) + { + Status = AE_OK; + } + + if (Status == AE_CTRL_TERMINATE) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiPsCompleteOp (WalkState, &Op, Status); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + if (AcpiNsOpensScope ( + AcpiPsGetOpcodeInfo (WalkState->Opcode)->ObjectType)) + { + /* + * If the scope/device op fails to parse, skip the body of + * the scope op because the parse failure indicates that + * the device may not exist. + */ + ACPI_INFO (("Skipping parse of AML opcode: %s (0x%4.4X)", + AcpiPsGetOpcodeName (WalkState->Opcode), WalkState->Opcode)); + + /* + * Determine the opcode length before skipping the opcode. + * An opcode can be 1 byte or 2 bytes in length. + */ + OpcodeLength = 1; + if ((WalkState->Opcode & 0xFF00) == AML_EXTENDED_OPCODE) + { + OpcodeLength = 2; + } + WalkState->ParserState.Aml = WalkState->Aml + OpcodeLength; + + WalkState->ParserState.Aml = + AcpiPsGetNextPackageEnd(&WalkState->ParserState); + if ((WalkState->ParserState.Aml > WalkState->ParserState.AmlEnd) || + (WalkState->ParserState.Aml < WalkState->Aml)) + { + return_ACPI_STATUS (AE_AML_PACKAGE_LIMIT); + } + WalkState->Aml = WalkState->ParserState.Aml; + } + + continue; + } + + AcpiExStartTraceOpcode (Op, WalkState); + } + + /* + * Start ArgCount at zero because we don't know if there are + * any args yet + */ + WalkState->ArgCount = 0; + + switch (Op->Common.AmlOpcode) + { + case AML_BYTE_OP: + case AML_WORD_OP: + case AML_DWORD_OP: + case AML_QWORD_OP: + + break; + + default: + + ASL_CV_CAPTURE_COMMENTS (WalkState); + break; + } + + /* 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); + } + if ((WalkState->ControlState) && + ((WalkState->ControlState->Control.Opcode == AML_IF_OP) || + (WalkState->ControlState->Control.Opcode == AML_WHILE_OP))) + { + /* + * If the if/while op fails to parse, we will skip parsing + * the body of the op. + */ + ParserState->Aml = + WalkState->ControlState->Control.AmlPredicateStart + 1; + ParserState->Aml = + AcpiPsGetNextPackageEnd (ParserState); + if ((ParserState->Aml > ParserState->AmlEnd) || + (ParserState->Aml < WalkState->ControlState->Control.AmlPredicateStart)) + { + return_ACPI_STATUS (AE_AML_PACKAGE_LIMIT); + } + WalkState->Aml = ParserState->Aml; + + ACPI_ERROR ((AE_INFO, "Skipping While/If block")); + if ((WalkState->Aml < ParserState->AmlEnd) && + (*WalkState->Aml == AML_ELSE_OP)) + { + ACPI_ERROR ((AE_INFO, "Skipping Else block")); + WalkState->ParserState.Aml = WalkState->Aml + 1; + WalkState->ParserState.Aml = + AcpiPsGetNextPackageEnd (ParserState); + if ((WalkState->ParserState.Aml > WalkState->ParserState.AmlEnd) || + (WalkState->ParserState.Aml < WalkState->Aml)) + { + return_ACPI_STATUS (AE_AML_PACKAGE_LIMIT); + } + WalkState->Aml = ParserState->Aml; + } + ACPI_FREE(AcpiUtPopGenericState (&WalkState->ControlState)); + } + Op = NULL; + continue; + } + } + + /* Check for arguments that need to be processed */ + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "Parseloop: argument count: %8.8X\n", WalkState->ArgCount)); + + 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 (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; + } + else if ((WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL) && + (ACPI_AML_EXCEPTION(Status) || Status == AE_ALREADY_EXISTS || + Status == AE_NOT_FOUND)) + { + /* + * ACPI_PARSE_MODULE_LEVEL flag means that we are currently + * loading a table by executing it as a control method. + * However, if we encounter an error while loading the table, + * we need to keep trying to load the table rather than + * aborting the table load (setting the status to AE_OK + * continues the table load). If we get a failure at this + * point, it means that the dispatcher got an error while + * trying to execute the Op. + */ + 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/code/drivers/platform/acpi/third_party/acpica/components/parser/psobject.c b/code/drivers/platform/acpi/third_party/acpica/components/parser/psobject.c new file mode 100644 index 0000000..d1c7e4a --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/parser/psobject.c @@ -0,0 +1,748 @@ +/****************************************************************************** + * + * Module Name: psobject - Support for parse objects + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acconvert.h" +#include "acnamesp.h" + +#define _COMPONENT ACPI_PARSER + ACPI_MODULE_NAME ("psobject") + + +/* Local prototypes */ + +static ACPI_STATUS +AcpiPsGetAmlOpcode ( + ACPI_WALK_STATE *WalkState); + + +/******************************************************************************* + * + * 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_ERROR_ONLY (UINT32 AmlOffset); + + + ACPI_FUNCTION_TRACE_PTR (PsGetAmlOpcode, WalkState); + + + WalkState->Aml = WalkState->ParserState.Aml; + 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. Complain and skip unknown opcodes */ + + if (WalkState->PassNumber == 2) + { + ACPI_ERROR_ONLY(AmlOffset = (UINT32) ACPI_PTR_DIFF (WalkState->Aml, + WalkState->ParserState.AmlStart)); + + ACPI_ERROR ((AE_INFO, + "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring", + WalkState->Opcode, + (UINT32) (AmlOffset + sizeof (ACPI_TABLE_HEADER)))); + + ACPI_DUMP_BUFFER ((WalkState->ParserState.Aml - 16), 48); + +#ifdef ACPI_ASL_COMPILER + /* + * This is executed for the disassembler only. Output goes + * to the disassembled ASL output file. + */ + AcpiOsPrintf ( + "/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n", + WalkState->Opcode, + (UINT32) (AmlOffset + sizeof (ACPI_TABLE_HEADER))); + + ACPI_ERROR ((AE_INFO, + "Aborting disassembly, AML byte code is corrupt")); + + /* Dump the context surrounding the invalid opcode */ + + AcpiUtDumpBuffer (((UINT8 *) WalkState->ParserState.Aml - 16), + 48, DB_BYTE_DISPLAY, + (AmlOffset + sizeof (ACPI_TABLE_HEADER) - 16)); + AcpiOsPrintf (" */\n"); + + /* + * Just abort the disassembly, cannot continue because the + * parser is essentially lost. The disassembler can then + * randomly fail because an ill-constructed parse tree + * can result. + */ + return_ACPI_STATUS (AE_AML_BAD_OPCODE); +#endif + } + + /* Increment past one-byte or two-byte opcode */ + + WalkState->ParserState.Aml++; + if (WalkState->Opcode > 0xFF) /* Can only happen if first byte is 0x5B */ + { + 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 + * + ******************************************************************************/ + +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)) + { + ASL_CV_CAPTURE_COMMENTS (WalkState); + 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); + } + + /* are there any inline comments associated with the NameSeg?? If so, save this. */ + + ASL_CV_CAPTURE_COMMENTS (WalkState); + +#ifdef ACPI_ASL_COMPILER + if (AcpiGbl_CurrentInlineComment != NULL) + { + UnnamedOp->Common.NameComment = AcpiGbl_CurrentInlineComment; + AcpiGbl_CurrentInlineComment = NULL; + } +#endif + + /* + * 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)) + { + if (Status != AE_CTRL_TERMINATE) + { + 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) + { + Status = AE_CTRL_PARSE_PENDING; + } + return_ACPI_STATUS (Status); + } + + AcpiPsAppendArg (*Op, UnnamedOp->Common.Value.Arg); + +#ifdef ACPI_ASL_COMPILER + + /* save any comments that might be associated with UnnamedOp. */ + + (*Op)->Common.InlineComment = UnnamedOp->Common.InlineComment; + (*Op)->Common.EndNodeComment = UnnamedOp->Common.EndNodeComment; + (*Op)->Common.CloseBraceComment = UnnamedOp->Common.CloseBraceComment; + (*Op)->Common.NameComment = UnnamedOp->Common.NameComment; + (*Op)->Common.CommentList = UnnamedOp->Common.CommentList; + (*Op)->Common.EndBlkComment = UnnamedOp->Common.EndBlkComment; + (*Op)->Common.CvFilename = UnnamedOp->Common.CvFilename; + (*Op)->Common.CvParentFilename = UnnamedOp->Common.CvParentFilename; + (*Op)->Named.Aml = UnnamedOp->Common.Aml; + + UnnamedOp->Common.InlineComment = NULL; + UnnamedOp->Common.EndNodeComment = NULL; + UnnamedOp->Common.CloseBraceComment = NULL; + UnnamedOp->Common.NameComment = NULL; + UnnamedOp->Common.CommentList = NULL; + UnnamedOp->Common.EndBlkComment = NULL; +#endif + + 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 + * + ******************************************************************************/ + +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); + } + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Create Op structure and append to parent's argument list */ + + WalkState->OpInfo = AcpiPsGetOpcodeInfo (WalkState->Opcode); + Op = AcpiPsAllocOp (WalkState->Opcode, AmlOpStart); + if (!Op) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + if (WalkState->OpInfo->Flags & AML_NAMED) + { + Status = AcpiPsBuildNamedOp (WalkState, AmlOpStart, Op, &NamedOp); + AcpiPsFreeOp (Op); + +#ifdef ACPI_ASL_COMPILER + if (AcpiGbl_DisasmFlag && WalkState->Opcode == AML_EXTERNAL_OP && + Status == AE_NOT_FOUND) + { + /* + * If parsing of AML_EXTERNAL_OP's name path fails, then skip + * past this opcode and keep parsing. This is a much better + * alternative than to abort the entire disassembler. At this + * point, the ParserState is at the end of the namepath of the + * external declaration opcode. Setting WalkState->Aml to + * WalkState->ParserState.Aml + 2 moves increments the + * WalkState->Aml past the object type and the paramcount of the + * external opcode. + */ + WalkState->Aml = WalkState->ParserState.Aml + 2; + WalkState->ParserState.Aml = WalkState->Aml; + return_ACPI_STATUS (AE_CTRL_PARSE_CONTINUE); + } +#endif + 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; + } + } + + /* + * Special case for both Increment() and Decrement(), where + * the lone argument is both a source and a target. + */ + else if ((ParentScope->Common.AmlOpcode == AML_INCREMENT_OP) || + (ParentScope->Common.AmlOpcode == AML_DECREMENT_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: AcpiPsCompleteOp + * + * PARAMETERS: WalkState - Current state + * Op - Returned Op + * Status - Parse status before complete Op + * + * RETURN: Status + * + * DESCRIPTION: Complete Op + * + ******************************************************************************/ + +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); + (void) AcpiPsNextParseState (WalkState, *Op, Status); + + Status2 = AcpiPsCompleteThisOp (WalkState, *Op); + if (ACPI_FAILURE (Status2)) + { + return_ACPI_STATUS (Status2); + } + } + + 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); + (void) AcpiPsNextParseState (WalkState, *Op, Status); + + Status2 = AcpiPsCompleteThisOp (WalkState, *Op); + if (ACPI_FAILURE (Status2)) + { + return_ACPI_STATUS (Status2); + } + + 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) + { + /* + * These Opcodes need to be removed from the namespace because they + * get created even if these opcodes cannot be created due to + * errors. + */ + if (((*Op)->Common.AmlOpcode == AML_REGION_OP) || + ((*Op)->Common.AmlOpcode == AML_DATA_REGION_OP)) + { + AcpiNsDeleteChildren ((*Op)->Common.Node); + AcpiNsRemoveNode ((*Op)->Common.Node); + (*Op)->Common.Node = NULL; + AcpiPsDeleteParseTree (*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; + + if (WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL) + { + /* + * There was something that went wrong while executing code at the + * module-level. We need to skip parsing whatever caused the + * error and keep going. One runtime error during the table load + * should not cause the entire table to not be loaded. This is + * because there could be correct AML beyond the parts that caused + * the runtime error. + */ + ACPI_INFO (("Ignoring error and continuing table load")); + return_ACPI_STATUS (AE_OK); + } + 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. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiPsCompleteFinalOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + ACPI_STATUS Status) +{ + ACPI_STATUS ReturnStatus = Status; + BOOLEAN Ascending = TRUE; + + + 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 (Ascending && 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) + { + Ascending = FALSE; + ReturnStatus = AE_CTRL_TERMINATE; + } + + else if (ACPI_FAILURE (Status)) + { + /* First error is most important */ + + Ascending = FALSE; + ReturnStatus = Status; + } + } + + Status = AcpiPsCompleteThisOp (WalkState, Op); + if (ACPI_FAILURE (Status)) + { + Ascending = FALSE; + if (ACPI_SUCCESS (ReturnStatus) || + ReturnStatus == AE_CTRL_TERMINATE) + { + ReturnStatus = Status; + } + } + } + + AcpiPsPopScope (&(WalkState->ParserState), &Op, &WalkState->ArgTypes, + &WalkState->ArgCount); + + } while (Op); + + return_ACPI_STATUS (ReturnStatus); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/parser/psopcode.c b/code/drivers/platform/acpi/third_party/acpica/components/parser/psopcode.c new file mode 100644 index 0000000..997f857 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/parser/psopcode.c @@ -0,0 +1,314 @@ +/****************************************************************************** + * + * Module Name: psopcode - Parser/Interpreter opcode information table + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acopcode.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_PARSER + ACPI_MODULE_NAME ("psopcode") + + +/******************************************************************************* + * + * 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_RESOURCE_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_RESOURCE_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_RESOURCE_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_RESOURCE_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_VARIABLE_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_OBJECT_TYPE_OP, ARGI_OBJECT_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_1R, AML_FLAGS_EXEC_1A_1T_1R), +/* 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 | AML_NO_OPERAND_RESOLVE), + +/* 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), + +/* ACPI 6.0 opcodes */ + +/* 81 */ ACPI_OP ("External", ARGP_EXTERNAL_OP, ARGI_EXTERNAL_OP, ACPI_TYPE_ANY, AML_CLASS_NAMED_OBJECT, AML_TYPE_NAMED_SIMPLE, AML_HAS_ARGS | AML_NSOBJECT | AML_NSOPCODE | AML_NSNODE | AML_NAMED), +/* 82 */ ACPI_OP ("Comment", ARGP_COMMENT_OP, ARGI_COMMENT_OP, ACPI_TYPE_STRING, AML_CLASS_ARGUMENT, AML_TYPE_LITERAL, AML_CONSTANT) + +/*! [End] no source code translation !*/ +}; diff --git a/code/drivers/platform/acpi/third_party/acpica/components/parser/psopinfo.c b/code/drivers/platform/acpi/third_party/acpica/components/parser/psopinfo.c new file mode 100644 index 0000000..511d7d4 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/parser/psopinfo.c @@ -0,0 +1,254 @@ +/****************************************************************************** + * + * Module Name: psopinfo - AML opcode information functions and dispatch tables + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "acopcode.h" +#include "amlcode.h" + + +#define _COMPONENT ACPI_PARSER + ACPI_MODULE_NAME ("psopinfo") + + +static const UINT8 AcpiGbl_ArgumentCount[] = {0,1,1,1,1,2,2,2,2,3,3,6}; + + +/******************************************************************************* + * + * 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) +{ +#if defined ACPI_ASL_COMPILER && defined ACPI_DEBUG_OUTPUT + const char *OpcodeName = "Unknown AML opcode"; +#endif + + 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]]); + } + +#if defined ACPI_ASL_COMPILER && defined ACPI_DEBUG_OUTPUT +#include "asldefine.h" + + switch (Opcode) + { + case AML_RAW_DATA_BYTE: + OpcodeName = "-Raw Data Byte-"; + break; + + case AML_RAW_DATA_WORD: + OpcodeName = "-Raw Data Word-"; + break; + + case AML_RAW_DATA_DWORD: + OpcodeName = "-Raw Data Dword-"; + break; + + case AML_RAW_DATA_QWORD: + OpcodeName = "-Raw Data Qword-"; + break; + + case AML_RAW_DATA_BUFFER: + OpcodeName = "-Raw Data Buffer-"; + break; + + case AML_RAW_DATA_CHAIN: + OpcodeName = "-Raw Data Buffer Chain-"; + break; + + case AML_PACKAGE_LENGTH: + OpcodeName = "-Package Length-"; + break; + + case AML_UNASSIGNED_OPCODE: + OpcodeName = "-Unassigned Opcode-"; + break; + + case AML_DEFAULT_ARG_OP: + OpcodeName = "-Default Arg-"; + break; + + default: + break; + } + + /* Unknown AML opcode */ + + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "%s [%4.4X]\n", OpcodeName, Opcode)); +#endif + + 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 + * + ******************************************************************************/ + +const 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); +} + + +/* + * This table is directly indexed by the opcodes It returns + * an index into the opcode table (AcpiGbl_AmlOpInfo) + */ +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, 0x81, _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, 0x82, _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) + */ +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, +}; diff --git a/code/drivers/platform/acpi/third_party/acpica/components/parser/psparse.c b/code/drivers/platform/acpi/third_party/acpica/components/parser/psparse.c new file mode 100644 index 0000000..1aacc0c --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/parser/psparse.c @@ -0,0 +1,722 @@ +/****************************************************************************** + * + * Module Name: psparse - Parser top level AML parse routines + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +/* + * 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" +#include "acnamesp.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; + if (Aml >= ParserState->AmlEnd) + { + return (0xFFFF); + } + Opcode = (UINT16) ACPI_GET8 (Aml); + + if (Opcode == AML_EXTENDED_PREFIX) + { + /* Extended opcode, get the second opcode byte */ + + Aml++; + if (Aml >= ParserState->AmlEnd) + { + return (0xFFFF); + } + 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 */ + } + + AcpiExStopTraceOpcode (Op, WalkState); + + /* 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, Op->Common.Aml); + 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_VARIABLE_PACKAGE_OP)) + { + ReplacementOp = AcpiPsAllocOp ( + AML_INT_RETURN_VALUE_OP, Op->Common.Aml); + 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_VARIABLE_PACKAGE_OP)) + { + ReplacementOp = AcpiPsAllocOp (Op->Common.AmlOpcode, + Op->Common.Aml); + 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, Op->Common.Aml); + 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; + UINT8 *Aml; + + + 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 + */ + Aml = ParserState->Aml; + + ParserState->Aml = AcpiPsGetNextPackageEnd (ParserState); + if ((ParserState->Aml > ParserState->AmlEnd) || + (ParserState->Aml < Aml)) + { + Status = AE_AML_PACKAGE_LIMIT; + break; + } + 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 (ACPI_CNTL_EXCEPTION (CallbackStatus)) + { + 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_BAD_ADDRESS); + } + + /* 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 (WalkState->MethodPathname && WalkState->MethodIsNested) + { + /* Optional object evaluation log */ + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EVALUATION, "%-26s: %*s%s\n", + " Exit nested method", + (WalkState->MethodNestingDepth + 1) * 3, " ", + &WalkState->MethodPathname[1])); + + ACPI_FREE (WalkState->MethodPathname); + WalkState->MethodIsNested = FALSE; + } + 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 */ + + AcpiExExitInterpreter (); + if (Status == AE_ABORT_METHOD) + { + AcpiNsPrintNodePathname ( + WalkState->MethodNode, "Aborting method"); + AcpiOsPrintf ("\n"); + } + else + { + ACPI_ERROR_METHOD ("Aborting method", + WalkState->MethodNode, NULL, Status); + } + AcpiExEnterInterpreter (); + + /* 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 && + !(WalkState->ParseFlags & ACPI_PARSE_MODULE_LEVEL)) || + (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/code/drivers/platform/acpi/third_party/acpica/components/parser/psscope.c b/code/drivers/platform/acpi/third_party/acpica/components/parser/psscope.c new file mode 100644 index 0000000..bcab07f --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/parser/psscope.c @@ -0,0 +1,270 @@ +/****************************************************************************** + * + * Module Name: psscope - Parser scope stack management routines + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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/code/drivers/platform/acpi/third_party/acpica/components/parser/pstree.c b/code/drivers/platform/acpi/third_party/acpica/components/parser/pstree.c new file mode 100644 index 0000000..ca4a2e6 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/parser/pstree.c @@ -0,0 +1,333 @@ +/****************************************************************************** + * + * Module Name: pstree - Parser op tree manipulation/traversal/search + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acconvert.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_TRACE (PsAppendArg); + + + if (!Op) + { + return_VOID; + } + + /* 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_VOID; + } + + /* Check if this opcode requires argument sub-objects */ + + if (!(OpInfo->Flags & AML_HAS_ARGS)) + { + /* Has no linked argument objects */ + + return_VOID; + } + + /* 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++; + } + + return_VOID; +} + + +/******************************************************************************* + * + * 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) + { + ASL_CV_LABEL_FILENODE (Next); + return (Next); + } + + /* Look for a sibling */ + + Next = Op->Common.Next; + if (Next) + { + ASL_CV_LABEL_FILENODE (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)) + { + + ASL_CV_LABEL_FILENODE (Arg); + Arg = Arg->Common.Next; + } + + if (Arg == Origin) + { + /* Reached parent of origin, end search */ + + return (NULL); + } + + if (Parent->Common.Next) + { + /* Found sibling of parent */ + + ASL_CV_LABEL_FILENODE (Parent->Common.Next); + return (Parent->Common.Next); + } + + Op = Parent; + Parent = Parent->Common.Parent; + } + + ASL_CV_LABEL_FILENODE (Next); + 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_VARIABLE_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_RESOURCE_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/code/drivers/platform/acpi/third_party/acpica/components/parser/psutils.c b/code/drivers/platform/acpi/third_party/acpica/components/parser/psutils.c new file mode 100644 index 0000000..0ec46c4 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/parser/psutils.c @@ -0,0 +1,264 @@ +/****************************************************************************** + * + * Module Name: psutils - Parser miscellaneous utilities (Parser only) + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "amlcode.h" +#include "acconvert.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 ( + UINT8 *Aml) +{ + ACPI_PARSE_OBJECT *ScopeOp; + + + ScopeOp = AcpiPsAllocOp (AML_SCOPE_OP, Aml); + 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 (AcpiUtSafeStrncpy (Op->Common.AmlOpName, + (AcpiPsGetOpcodeInfo (Opcode))->Name, + sizeof (Op->Common.AmlOpName))); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiPsAllocOp + * + * PARAMETERS: Opcode - Opcode that will be stored in the new Op + * Aml - Address of the opcode + * + * 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, + UINT8 *Aml) +{ + 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_OBJECT; + } + 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.Aml = Aml; + Op->Common.Flags = Flags; + ASL_CV_CLEAR_OP_COMMENTS(Op); + + if (Opcode == AML_SCOPE_OP) + { + AcpiGbl_CurrentScope = Op; + } + + if (AcpiGbl_CaptureComments) + { + ASL_CV_TRANSFER_COMMENTS (Op); + } + } + + 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); + + + ASL_CV_CLEAR_OP_COMMENTS(Op); + 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'))); +} + + +/* + * 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/code/drivers/platform/acpi/third_party/acpica/components/parser/pswalk.c b/code/drivers/platform/acpi/third_party/acpica/components/parser/pswalk.c new file mode 100644 index 0000000..2ebcefa --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/parser/pswalk.c @@ -0,0 +1,116 @@ +/****************************************************************************** + * + * Module Name: pswalk - Parser routines to walk parsed op tree(s) + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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. + * + ******************************************************************************/ + +#include "amlcode.h" + +void +AcpiPsDeleteParseTree ( + ACPI_PARSE_OBJECT *SubtreeRoot) +{ + ACPI_PARSE_OBJECT *Op = SubtreeRoot; + ACPI_PARSE_OBJECT *Next = NULL; + ACPI_PARSE_OBJECT *Parent = NULL; + UINT32 Level = 0; + + + ACPI_FUNCTION_TRACE_PTR (PsDeleteParseTree, SubtreeRoot); + + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE_TREES, + " root %p\n", SubtreeRoot)); + + /* Visit all nodes in the subtree */ + + while (Op) + { + if (Op != Parent) + { + /* This is the descending case */ + + if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_PARSE_TREES, _COMPONENT)) + { + /* This debug option will print the entire parse tree */ + + AcpiOsPrintf (" %*s%s %p", (Level * 4), "", + AcpiPsGetOpcodeName (Op->Common.AmlOpcode), Op); + + if (Op->Named.AmlOpcode == AML_INT_NAMEPATH_OP) + { + AcpiOsPrintf (" %4.4s", Op->Common.Value.String); + } + if (Op->Named.AmlOpcode == AML_STRING_OP) + { + AcpiOsPrintf (" %s", Op->Common.Value.String); + } + AcpiOsPrintf ("\n"); + } + + /* 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; + Level++; + 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 + { + Level--; + Op = Parent; + } + } + + return_VOID; +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/parser/psxface.c b/code/drivers/platform/acpi/third_party/acpica/components/parser/psxface.c new file mode 100644 index 0000000..0fe6ddd --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/parser/psxface.c @@ -0,0 +1,380 @@ +/****************************************************************************** + * + * Module Name: psxface - Parser external interfaces + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acparser.h" +#include "acdispat.h" +#include "acinterp.h" +#include "actables.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_PARSER + ACPI_MODULE_NAME ("psxface") + +/* Local Prototypes */ + +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 ( + const char *Name, + UINT32 DebugLevel, + UINT32 DebugLayer, + UINT32 Flags) +{ + ACPI_STATUS Status; + + + Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + AcpiGbl_TraceMethodName = Name; + AcpiGbl_TraceFlags = Flags; + AcpiGbl_TraceDbgLevel = DebugLevel; + AcpiGbl_TraceDbgLayer = DebugLayer; + Status = AE_OK; + + (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); + return (Status); +} + + +/******************************************************************************* + * + * 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->Node) + { + return_ACPI_STATUS (AE_NULL_ENTRY); + } + + /* Init for new method, wait on concurrency semaphore */ + + Status = AcpiDsBeginMethodExecution (Info->Node, 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); + + /* + * Execute the method. Performs parse simultaneously + */ + ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, + "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n", + Info->Node->Name.Ascii, Info->Node, Info->ObjDesc)); + + /* Create and init a Root Node */ + + Op = AcpiPsCreateScopeOp (Info->ObjDesc->Method.AmlStart); + 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->Node, + Info->ObjDesc->Method.AmlStart, + Info->ObjDesc->Method.AmlLength, Info, Info->PassNumber); + if (ACPI_FAILURE (Status)) + { + AcpiDsDeleteWalkState (WalkState); + goto Cleanup; + } + + WalkState->MethodPathname = Info->FullPathname; + WalkState->MethodIsNested = FALSE; + + 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); + + /* 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: AcpiPsExecuteTable + * + * PARAMETERS: Info - Method info block, contains: + * Node - Node to where the is entered into the + * namespace + * ObjDesc - Pseudo method object describing the AML + * code of the entire table + * PassNumber - Parse or execute pass + * + * RETURN: Status + * + * DESCRIPTION: Execute a table + * + ******************************************************************************/ + +ACPI_STATUS +AcpiPsExecuteTable ( + ACPI_EVALUATE_INFO *Info) +{ + ACPI_STATUS Status; + ACPI_PARSE_OBJECT *Op = NULL; + ACPI_WALK_STATE *WalkState = NULL; + + + ACPI_FUNCTION_TRACE (PsExecuteTable); + + + /* Create and init a Root Node */ + + Op = AcpiPsCreateScopeOp (Info->ObjDesc->Method.AmlStart); + if (!Op) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Create and initialize a new walk state */ + + WalkState = AcpiDsCreateWalkState ( + Info->ObjDesc->Method.OwnerId, NULL, NULL, NULL); + if (!WalkState) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + Status = AcpiDsInitAmlWalk (WalkState, Op, Info->Node, + Info->ObjDesc->Method.AmlStart, + Info->ObjDesc->Method.AmlLength, Info, Info->PassNumber); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + + WalkState->MethodPathname = Info->FullPathname; + WalkState->MethodIsNested = FALSE; + + if (Info->ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL) + { + WalkState->ParseFlags |= ACPI_PARSE_MODULE_LEVEL; + } + + /* Info->Node is the default location to load the table */ + + if (Info->Node && Info->Node != AcpiGbl_RootNode) + { + Status = AcpiDsScopeStackPush ( + Info->Node, ACPI_TYPE_METHOD, WalkState); + if (ACPI_FAILURE (Status)) + { + goto Cleanup; + } + } + + /* + * Parse the AML, WalkState will be deleted by ParseAml + */ + AcpiExEnterInterpreter (); + Status = AcpiPsParseAml (WalkState); + AcpiExExitInterpreter (); + WalkState = NULL; + +Cleanup: + if (WalkState) + { + AcpiDsDeleteWalkState (WalkState); + } + if (Op) + { + AcpiPsDeleteParseTree (Op); + } + 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/code/drivers/platform/acpi/third_party/acpica/components/resources/rsaddr.c b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsaddr.c new file mode 100644 index 0000000..06f8d20 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsaddr.c @@ -0,0 +1,381 @@ +/******************************************************************************* + * + * Module Name: rsaddr - Address resource descriptors (16/32/64) + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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.Address.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.Address.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.Address.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.Address.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) && + (Aml->Address.ResourceType != 0x0A)) + { + 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/code/drivers/platform/acpi/third_party/acpica/components/resources/rscalc.c b/code/drivers/platform/acpi/third_party/acpica/components/resources/rscalc.c new file mode 100644 index 0000000..caf43d4 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/resources/rscalc.c @@ -0,0 +1,855 @@ +/******************************************************************************* + * + * Module Name: rscalc - Calculate stream and list lengths + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 + * ResourceListSize - Size of 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 ResourceListSize, + ACPI_SIZE *SizeNeeded) +{ + ACPI_SIZE AmlSizeNeeded = 0; + ACPI_RESOURCE *ResourceEnd; + ACPI_RS_LENGTH TotalSize; + + + ACPI_FUNCTION_TRACE (RsGetAmlLength); + + + /* Traverse entire list of internal resource descriptors */ + + ResourceEnd = ACPI_ADD_PTR (ACPI_RESOURCE, Resource, ResourceListSize); + while (Resource < ResourceEnd) + { + /* Validate the descriptor type */ + + if (Resource->Type > ACPI_RESOURCE_TYPE_MAX) + { + return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); + } + + /* Sanity check the length. It must not be zero, or we loop forever */ + + if (!Resource->Length) + { + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); + } + + /* 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_PIN_FUNCTION: + + TotalSize = (ACPI_RS_LENGTH) (TotalSize + + (Resource->Data.PinFunction.PinTableLength * 2) + + Resource->Data.PinFunction.ResourceSource.StringLength + + Resource->Data.PinFunction.VendorLength); + + break; + + case ACPI_RESOURCE_TYPE_CLOCK_INPUT: + + TotalSize = (ACPI_RS_LENGTH) (TotalSize + + Resource->Data.ClockInput.ResourceSource.StringLength); + + 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; + + case ACPI_RESOURCE_TYPE_PIN_CONFIG: + + TotalSize = (ACPI_RS_LENGTH) (TotalSize + + (Resource->Data.PinConfig.PinTableLength * 2) + + Resource->Data.PinConfig.ResourceSource.StringLength + + Resource->Data.PinConfig.VendorLength); + + break; + + case ACPI_RESOURCE_TYPE_PIN_GROUP: + + TotalSize = (ACPI_RS_LENGTH) (TotalSize + + (Resource->Data.PinGroup.PinTableLength * 2) + + Resource->Data.PinGroup.ResourceLabel.StringLength + + Resource->Data.PinGroup.VendorLength); + + break; + + case ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION: + + TotalSize = (ACPI_RS_LENGTH) (TotalSize + + Resource->Data.PinGroupFunction.ResourceSource.StringLength + + Resource->Data.PinGroupFunction.ResourceSourceLabel.StringLength + + Resource->Data.PinGroupFunction.VendorLength); + + break; + + case ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG: + + TotalSize = (ACPI_RS_LENGTH) (TotalSize + + Resource->Data.PinGroupConfig.ResourceSource.StringLength + + Resource->Data.PinGroupConfig.ResourceSourceLabel.StringLength + + Resource->Data.PinGroupConfig.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 (NULL, 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; + + /* + * There is already one byte included in the minimum + * descriptor size. If there are extra struct bytes, + * subtract one from the count. + */ + if (ExtraStructBytes) + { + ExtraStructBytes--; + } + 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_PIN_FUNCTION: + + /* Vendor data is optional */ + + if (AmlResource->PinFunction.VendorLength) + { + ExtraStructBytes += + AmlResource->PinFunction.VendorOffset - + AmlResource->PinFunction.PinTableOffset + + AmlResource->PinFunction.VendorLength; + } + else + { + ExtraStructBytes += + AmlResource->LargeHeader.ResourceLength + + sizeof (AML_RESOURCE_LARGE_HEADER) - + AmlResource->PinFunction.PinTableOffset; + } + break; + + case ACPI_RESOURCE_NAME_SERIAL_BUS: { + + MinimumAmlResourceLength = AcpiGbl_ResourceAmlSerialBusSizes[ + AmlResource->CommonSerialBus.Type]; + ExtraStructBytes += + AmlResource->CommonSerialBus.ResourceLength - + MinimumAmlResourceLength; + break; + } + + case ACPI_RESOURCE_NAME_PIN_CONFIG: + + /* Vendor data is optional */ + + if (AmlResource->PinConfig.VendorLength) + { + ExtraStructBytes += + AmlResource->PinConfig.VendorOffset - + AmlResource->PinConfig.PinTableOffset + + AmlResource->PinConfig.VendorLength; + } + else + { + ExtraStructBytes += + AmlResource->LargeHeader.ResourceLength + + sizeof (AML_RESOURCE_LARGE_HEADER) - + AmlResource->PinConfig.PinTableOffset; + } + break; + + case ACPI_RESOURCE_NAME_PIN_GROUP: + + ExtraStructBytes += + AmlResource->PinGroup.VendorOffset - + AmlResource->PinGroup.PinTableOffset + + AmlResource->PinGroup.VendorLength; + + break; + + case ACPI_RESOURCE_NAME_PIN_GROUP_FUNCTION: + + ExtraStructBytes += + AmlResource->PinGroupFunction.VendorOffset - + AmlResource->PinGroupFunction.ResSourceOffset + + AmlResource->PinGroupFunction.VendorLength; + + break; + + case ACPI_RESOURCE_NAME_PIN_GROUP_CONFIG: + + ExtraStructBytes += + AmlResource->PinGroupConfig.VendorOffset - + AmlResource->PinGroupConfig.ResSourceOffset + + AmlResource->PinGroupConfig.VendorLength; + + break; + + case ACPI_RESOURCE_NAME_CLOCK_INPUT: + ExtraStructBytes = AcpiRsStreamOptionLength ( + 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%8X\n", + AcpiUtGetResourceType (AmlBuffer), + AcpiUtGetDescriptorLength (AmlBuffer), ACPI_FORMAT_UINT64(*SizeNeeded))); + + /* + * 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 subpackage */ + + 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 < PackageElement->Package.Count && !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/code/drivers/platform/acpi/third_party/acpica/components/resources/rscreate.c b/code/drivers/platform/acpi/third_party/acpica/components/resources/rscreate.c new file mode 100644 index 0000000..2b59402 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/resources/rscreate.c @@ -0,0 +1,480 @@ +/******************************************************************************* + * + * Module Name: rscreate - Create resource lists/tables + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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; + + + ACPI_FUNCTION_TRACE (AcpiBufferToResource); + + + /* + * 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_ACPI_STATUS (Status); + } + + /* Allocate a buffer for the converted resource */ + + Resource = ACPI_ALLOCATE_ZEROED (ListSizeNeeded); + CurrentResourcePtr = Resource; + if (!Resource) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* Perform the AML-to-Resource conversion */ + + Status = AcpiUtWalkAmlResources (NULL, 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_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiBufferToResource) + + +/******************************************************************************* + * + * 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 (NULL, 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 a package containing one + * of more ACPI_OPERAND_OBJECTs + * 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 subpackage 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 subpackage. + * 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 || 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 || 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; + + /* + * 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, FALSE); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* +1 to include null terminator */ + + UserPrt->Length += (UINT32) strlen (UserPrt->Source) + 1; + break; + + case ACPI_TYPE_STRING: + + 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 || 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: ResourceList - Pointer to the resource list buffer + * OutputBuffer - Where the AML buffer is returned + * + * 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: Converts a list of device resources to an AML bytestream + * to be used as input for the _SRS control method. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiRsCreateAmlResources ( + ACPI_BUFFER *ResourceList, + ACPI_BUFFER *OutputBuffer) +{ + ACPI_STATUS Status; + ACPI_SIZE AmlSizeNeeded = 0; + + + ACPI_FUNCTION_TRACE (RsCreateAmlResources); + + + /* Params already validated, no need to re-validate here */ + + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, "ResourceList Buffer = %p\n", + ResourceList->Pointer)); + + /* Get the buffer size needed for the AML byte stream */ + + Status = AcpiRsGetAmlLength ( + ResourceList->Pointer, ResourceList->Length, &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 (ResourceList->Pointer, + 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/code/drivers/platform/acpi/third_party/acpica/components/resources/rsdump.c b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsdump.c new file mode 100644 index 0000000..bcf1a6b --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsdump.c @@ -0,0 +1,695 @@ +/******************************************************************************* + * + * Module Name: rsdump - AML debugger support for resource structures. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsdump") + +/* + * All functions in this module are used by the AML Debugger only + */ + +/* Local prototypes */ + +static void +AcpiRsOutString ( + const char *Title, + const char *Value); + +static void +AcpiRsOutInteger8 ( + const char *Title, + UINT8 Value); + +static void +AcpiRsOutInteger16 ( + const char *Title, + UINT16 Value); + +static void +AcpiRsOutInteger32 ( + const char *Title, + UINT32 Value); + +static void +AcpiRsOutInteger64 ( + const char *Title, + UINT64 Value); + +static void +AcpiRsOutTitle ( + const 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 +AcpiRsDumpResourceLabel ( + char *Title, + ACPI_RESOURCE_LABEL *ResourceLabel); + +static void +AcpiRsDumpAddressCommon ( + ACPI_RESOURCE_DATA *Resource); + +static void +AcpiRsDumpDescriptor ( + void *Resource, + ACPI_RSDUMP_INFO *Table); + + +#ifdef ACPI_DEBUGGER +/******************************************************************************* + * + * 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 (); + + + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_RESOURCES, _COMPONENT)) + { + 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; + } + else if (!ResourceList->Type) + { + ACPI_ERROR ((AE_INFO, "Invalid Zero Resource Type")); + return; + } + + /* Sanity check the length. It must not be zero, or we loop forever */ + + if (!ResourceList->Length) + { + AcpiOsPrintf ( + "Invalid zero length descriptor in resource list\n"); + 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 (); + + + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED (ACPI_LV_RESOURCES, _COMPONENT)) + { + 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); + } +} +#endif + +/******************************************************************************* + * + * FUNCTION: AcpiRsDumpDescriptor + * + * PARAMETERS: Resource - Buffer containing the resource + * Table - Table entry to decode the resource + * + * RETURN: None + * + * DESCRIPTION: Dump a resource descriptor based on a dump table entry. + * + ******************************************************************************/ + +static void +AcpiRsDumpDescriptor ( + void *Resource, + ACPI_RSDUMP_INFO *Table) +{ + UINT8 *Target = NULL; + UINT8 *PreviousTarget; + const 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, 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, Table->Pointer [*Target & 0x01]); + break; + + case ACPI_RSD_2BITFLAG: + + AcpiRsOutString (Name, Table->Pointer [*Target & 0x03]); + break; + + case ACPI_RSD_3BITFLAG: + + AcpiRsOutString (Name, Table->Pointer [*Target & 0x07]); + break; + + case ACPI_RSD_6BITFLAG: + + AcpiRsOutInteger8 (Name, (ACPI_GET8 (Target) & 0x3F)); + 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; + + case ACPI_RSD_LABEL: + /* + * ResourceLabel + */ + AcpiRsDumpResourceLabel ("Resource Label", ACPI_CAST_PTR ( + ACPI_RESOURCE_LABEL, Target)); + break; + + case ACPI_RSD_SOURCE_LABEL: + /* + * ResourceSourceLabel + */ + AcpiRsDumpResourceLabel ("Resource Source Label", ACPI_CAST_PTR ( + ACPI_RESOURCE_LABEL, 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: AcpiRsDumpResourceLabel + * + * PARAMETERS: Title - Title of the dumped resource field + * ResourceLabel - Pointer to a Resource Label struct + * + * RETURN: None + * + * DESCRIPTION: Common routine for dumping the ResourceLabel + * + ******************************************************************************/ + +static void +AcpiRsDumpResourceLabel ( + char *Title, + ACPI_RESOURCE_LABEL *ResourceLabel) +{ + ACPI_FUNCTION_ENTRY (); + + AcpiRsOutString (Title, + ResourceLabel->StringPtr ? + ResourceLabel->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: 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 ( + const char *Title, + const char *Value) +{ + + AcpiOsPrintf ("%27s : %s", Title, Value); + if (!*Value) + { + AcpiOsPrintf ("[NULL NAMESTRING]"); + } + AcpiOsPrintf ("\n"); +} + +static void +AcpiRsOutInteger8 ( + const char *Title, + UINT8 Value) +{ + AcpiOsPrintf ("%27s : %2.2X\n", Title, Value); +} + +static void +AcpiRsOutInteger16 ( + const char *Title, + UINT16 Value) +{ + + AcpiOsPrintf ("%27s : %4.4X\n", Title, Value); +} + +static void +AcpiRsOutInteger32 ( + const char *Title, + UINT32 Value) +{ + + AcpiOsPrintf ("%27s : %8.8X\n", Title, Value); +} + +static void +AcpiRsOutInteger64 ( + const char *Title, + UINT64 Value) +{ + + AcpiOsPrintf ("%27s : %8.8X%8.8X\n", Title, + ACPI_FORMAT_UINT64 (Value)); +} + +static void +AcpiRsOutTitle ( + const 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) +{ + UINT16 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]); + } +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/resources/rsdumpinfo.c b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsdumpinfo.c new file mode 100644 index 0000000..4184c7c --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsdumpinfo.c @@ -0,0 +1,424 @@ +/******************************************************************************* + * + * Module Name: rsdumpinfo - Tables used to display resource descriptors. + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsdumpinfo") + + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DISASSEMBLER) || defined(ACPI_DEBUGGER) + + +#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_2BITFLAG, ACPI_RSD_OFFSET (Irq.Shareable), "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.Address.Granularity), "Granularity", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Address.Minimum), "Address Minimum", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Address.Maximum), "Address Maximum", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Address.TranslationOffset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Address16.Address.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.Address.Granularity), "Granularity", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Address.Minimum), "Address Minimum", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Address.Maximum), "Address Maximum", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Address.TranslationOffset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (Address32.Address.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.Address.Granularity), "Granularity", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Address.Minimum), "Address Minimum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Address.Maximum), "Address Maximum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Address.TranslationOffset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (Address64.Address.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.Address.Granularity), "Granularity", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Address.Minimum), "Address Minimum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Address.Maximum), "Address Maximum", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Address.TranslationOffset), + "Translation Offset", NULL}, + {ACPI_RSD_UINT64, ACPI_RSD_OFFSET (ExtAddress64.Address.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_2BITFLAG, ACPI_RSD_OFFSET (ExtendedIrq.Shareable), "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.Shareable), "Sharing", 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 AcpiRsDumpPinFunction[10] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpPinFunction), "PinFunction", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (PinFunction.RevisionId), "RevisionId", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (PinFunction.PinConfig), "PinConfig", AcpiGbl_PpcDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (PinFunction.Shareable), "Sharing", AcpiGbl_ShrDecode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (PinFunction.FunctionNumber), "FunctionNumber", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (PinFunction.ResourceSource), "ResourceSource", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (PinFunction.PinTableLength), "PinTableLength", NULL}, + {ACPI_RSD_WORDLIST, ACPI_RSD_OFFSET (PinFunction.PinTable), "PinTable", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (PinFunction.VendorLength), "VendorLength", NULL}, + {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (PinFunction.VendorData), "VendorData", NULL}, +}; + +ACPI_RSDUMP_INFO AcpiRsDumpClockInput[7] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpClockInput), "ClockInput", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (ClockInput.RevisionId), "RevisionId", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (ClockInput.FrequencyNumerator), "FrequencyNumerator", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (ClockInput.FrequencyDivisor), "FrequencyDivisor", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ClockInput.Scale), "Scale", AcpiGbl_ClockInputScale}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (ClockInput.Mode), "Mode", AcpiGbl_ClockInputMode}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (ClockInput.ResourceSource), "ResourceSource", NULL}, +}; + +ACPI_RSDUMP_INFO AcpiRsDumpPinConfig[11] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpPinConfig), "PinConfig", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (PinConfig.RevisionId), "RevisionId", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (PinConfig.ProducerConsumer), "ProducerConsumer", AcpiGbl_ConsumeDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (PinConfig.Shareable), "Sharing", AcpiGbl_ShrDecode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (PinConfig.PinConfigType), "PinConfigType", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (PinConfig.PinConfigValue), "PinConfigValue", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (PinConfig.ResourceSource), "ResourceSource", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (PinConfig.PinTableLength), "PinTableLength", NULL}, + {ACPI_RSD_WORDLIST, ACPI_RSD_OFFSET (PinConfig.PinTable), "PinTable", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (PinConfig.VendorLength), "VendorLength", NULL}, + {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (PinConfig.VendorData), "VendorData", NULL}, +}; + +ACPI_RSDUMP_INFO AcpiRsDumpPinGroup[8] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpPinGroup), "PinGroup", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (PinGroup.RevisionId), "RevisionId", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (PinGroup.ProducerConsumer), "ProducerConsumer", AcpiGbl_ConsumeDecode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (PinGroup.PinTableLength), "PinTableLength", NULL}, + {ACPI_RSD_WORDLIST, ACPI_RSD_OFFSET (PinGroup.PinTable), "PinTable", NULL}, + {ACPI_RSD_LABEL, ACPI_RSD_OFFSET (PinGroup.ResourceLabel), "ResourceLabel", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (PinGroup.VendorLength), "VendorLength", NULL}, + {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (PinGroup.VendorData), "VendorData", NULL}, +}; + +ACPI_RSDUMP_INFO AcpiRsDumpPinGroupFunction[9] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpPinGroupFunction), "PinGroupFunction", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (PinGroupFunction.RevisionId), "RevisionId", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (PinGroupFunction.ProducerConsumer), "ProducerConsumer", AcpiGbl_ConsumeDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (PinGroupFunction.Shareable), "Sharing", AcpiGbl_ShrDecode}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (PinGroupFunction.FunctionNumber), "FunctionNumber", NULL}, + {ACPI_RSD_SOURCE_LABEL, ACPI_RSD_OFFSET (PinGroupFunction.ResourceSourceLabel), "ResourceSourceLabel", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (PinGroupFunction.ResourceSource), "ResourceSource", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (PinGroupFunction.VendorLength), "VendorLength", NULL}, + {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (PinGroupFunction.VendorData), "VendorData", NULL}, +}; + +ACPI_RSDUMP_INFO AcpiRsDumpPinGroupConfig[10] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpPinGroupConfig), "PinGroupConfig", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (PinGroupConfig.RevisionId), "RevisionId", NULL}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (PinGroupConfig.ProducerConsumer), "ProducerConsumer", AcpiGbl_ConsumeDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (PinGroupConfig.Shareable), "Sharing", AcpiGbl_ShrDecode}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (PinGroupConfig.PinConfigType), "PinConfigType", NULL}, + {ACPI_RSD_UINT32, ACPI_RSD_OFFSET (PinGroupConfig.PinConfigValue), "PinConfigValue", NULL}, + {ACPI_RSD_SOURCE_LABEL, ACPI_RSD_OFFSET (PinGroupConfig.ResourceSourceLabel), "ResourceSourceLabel", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (PinGroupConfig.ResourceSource), "ResourceSource", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (PinGroupConfig.VendorLength), "VendorLength", NULL}, + {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (PinGroupConfig.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_1BITFLAG, ACPI_RSD_OFFSET (CommonSerialBus.ConnectionSharing),"ConnectionSharing", AcpiGbl_ShrDecode}, \ + {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[11] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpCommonSerialBus), "Common Serial Bus", NULL}, + ACPI_RS_DUMP_COMMON_SERIAL_BUS +}; + +ACPI_RSDUMP_INFO AcpiRsDumpCsi2SerialBus[11] = +{ + {ACPI_RSD_TITLE, ACPI_RSD_TABLE_SIZE (AcpiRsDumpCsi2SerialBus), "Camera Serial Bus", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Csi2SerialBus.RevisionId), "RevisionId", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Csi2SerialBus.Type), "Type", AcpiGbl_SbtDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Csi2SerialBus.ProducerConsumer), "ProducerConsumer", AcpiGbl_ConsumeDecode}, + {ACPI_RSD_1BITFLAG, ACPI_RSD_OFFSET (Csi2SerialBus.SlaveMode), "SlaveMode", AcpiGbl_SmDecode}, + {ACPI_RSD_2BITFLAG, ACPI_RSD_OFFSET (Csi2SerialBus.PhyType), "PhyType", AcpiGbl_PhyDecode}, + {ACPI_RSD_6BITFLAG, ACPI_RSD_OFFSET (Csi2SerialBus.LocalPortInstance), "LocalPortInstance", NULL}, + {ACPI_RSD_UINT8, ACPI_RSD_OFFSET (Csi2SerialBus.TypeRevisionId), "TypeRevisionId", NULL}, + {ACPI_RSD_UINT16, ACPI_RSD_OFFSET (Csi2SerialBus.VendorLength), "VendorLength", NULL}, + {ACPI_RSD_SHORTLISTX,ACPI_RSD_OFFSET (Csi2SerialBus.VendorData), "VendorData", NULL}, + {ACPI_RSD_SOURCE, ACPI_RSD_OFFSET (Csi2SerialBus.ResourceSource), "ResourceSource", NULL}, +}; + +ACPI_RSDUMP_INFO AcpiRsDumpI2cSerialBus[14] = +{ + {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[18] = +{ + {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[20] = +{ + {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 + */ +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} +}; + +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} +}; + +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 + */ +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} +}; + +#endif diff --git a/code/drivers/platform/acpi/third_party/acpica/components/resources/rsinfo.c b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsinfo.c new file mode 100644 index 0000000..592f126 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsinfo.c @@ -0,0 +1,266 @@ +/******************************************************************************* + * + * Module Name: rsinfo - Dispatch and Info tables + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 */ + AcpiRsConvertPinFunction, /* 0x14, ACPI_RESOURCE_TYPE_PIN_FUNCTION */ + AcpiRsConvertPinConfig, /* 0x15, ACPI_RESOURCE_TYPE_PIN_CONFIG */ + AcpiRsConvertPinGroup, /* 0x16, ACPI_RESOURCE_TYPE_PIN_GROUP */ + AcpiRsConvertPinGroupFunction, /* 0x17, ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION */ + AcpiRsConvertPinGroupConfig, /* 0x18, ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG */ + AcpiRsConvertClockInput, /* 0x19, ACPI_RESOURCE_TYPE_CLOCK_INPUT */ +}; + +/* 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 */ + AcpiRsConvertPinFunction, /* 0x0D, ACPI_RESOURCE_NAME_PIN_FUNCTION */ + NULL, /* 0x0E, ACPI_RESOURCE_NAME_SERIAL_BUS - Use subtype table below */ + AcpiRsConvertPinConfig, /* 0x0F, ACPI_RESOURCE_NAME_PIN_CONFIG */ + AcpiRsConvertPinGroup, /* 0x10, ACPI_RESOURCE_NAME_PIN_GROUP */ + AcpiRsConvertPinGroupFunction, /* 0x11, ACPI_RESOURCE_NAME_PIN_GROUP_FUNCTION */ + AcpiRsConvertPinGroupConfig, /* 0x12, ACPI_RESOURCE_NAME_PIN_GROUP_CONFIG */ + AcpiRsConvertClockInput, /* 0x13, ACPI_RESOURCE_NAME_CLOCK_INPUT */ +}; + +/* Subtype table for SerialBus -- I2C, SPI, UART, and CSI2 */ + +ACPI_RSCONVERT_INFO *AcpiGbl_ConvertResourceSerialBusDispatch[] = +{ + NULL, + AcpiRsConvertI2cSerialBus, + AcpiRsConvertSpiSerialBus, + AcpiRsConvertUartSerialBus, + AcpiRsConvertCsi2SerialBus +}; + + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DISASSEMBLER) || 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 */ + AcpiRsDumpPinFunction, /* ACPI_RESOURCE_TYPE_PIN_FUNCTION */ + AcpiRsDumpPinConfig, /* ACPI_RESOURCE_TYPE_PIN_CONFIG */ + AcpiRsDumpPinGroup, /* ACPI_RESOURCE_TYPE_PIN_GROUP */ + AcpiRsDumpPinGroupFunction, /* ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION */ + AcpiRsDumpPinGroupConfig, /* ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG */ + AcpiRsDumpClockInput, /* ACPI_RESOURCE_TYPE_CLOCK_INPUT */ +}; + +ACPI_RSDUMP_INFO *AcpiGbl_DumpSerialBusDispatch[] = +{ + NULL, + AcpiRsDumpI2cSerialBus, /* AML_RESOURCE_I2C_BUS_TYPE */ + AcpiRsDumpSpiSerialBus, /* AML_RESOURCE_SPI_BUS_TYPE */ + AcpiRsDumpUartSerialBus, /* AML_RESOURCE_UART_BUS_TYPE */ + AcpiRsDumpCsi2SerialBus, /* AML_RESOURCE_CSI2_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 */ + sizeof (AML_RESOURCE_PIN_FUNCTION), /* ACPI_RESOURCE_TYPE_PIN_FUNCTION */ + sizeof (AML_RESOURCE_PIN_CONFIG), /* ACPI_RESOURCE_TYPE_PIN_CONFIG */ + sizeof (AML_RESOURCE_PIN_GROUP), /* ACPI_RESOURCE_TYPE_PIN_GROUP */ + sizeof (AML_RESOURCE_PIN_GROUP_FUNCTION), /* ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION */ + sizeof (AML_RESOURCE_PIN_GROUP_CONFIG), /* ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG */ + sizeof (AML_RESOURCE_CLOCK_INPUT), /* ACPI_RESOURCE_TYPE_CLOCK_INPUT */ +}; + + +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_PIN_FUNCTION), + ACPI_RS_SIZE (ACPI_RESOURCE_COMMON_SERIALBUS), + ACPI_RS_SIZE (ACPI_RESOURCE_PIN_CONFIG), + ACPI_RS_SIZE (ACPI_RESOURCE_PIN_GROUP), + ACPI_RS_SIZE (ACPI_RESOURCE_PIN_GROUP_FUNCTION), + ACPI_RS_SIZE (ACPI_RESOURCE_PIN_GROUP_CONFIG), + ACPI_RS_SIZE (ACPI_RESOURCE_CLOCK_INPUT), +}; + +const UINT8 AcpiGbl_AmlResourceSerialBusSizes[] = +{ + 0, + sizeof (AML_RESOURCE_I2C_SERIALBUS), + sizeof (AML_RESOURCE_SPI_SERIALBUS), + sizeof (AML_RESOURCE_UART_SERIALBUS), + sizeof (AML_RESOURCE_CSI2_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), + ACPI_RS_SIZE (ACPI_RESOURCE_CSI2_SERIALBUS), +}; diff --git a/code/drivers/platform/acpi/third_party/acpica/components/resources/rsio.c b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsio.c new file mode 100644 index 0000000..1a20ce0 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsio.c @@ -0,0 +1,270 @@ +/******************************************************************************* + * + * Module Name: rsio - IO and DMA resource descriptors + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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/code/drivers/platform/acpi/third_party/acpica/components/resources/rsirq.c b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsirq.c new file mode 100644 index 0000000..3508c7c --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsirq.c @@ -0,0 +1,288 @@ +/******************************************************************************* + * + * Module Name: rsirq - IRQ resource descriptors + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsirq") + + +/******************************************************************************* + * + * AcpiRsGetIrq + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsGetIrq[9] = +{ + {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], Wake[5] */ + + {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.Shareable), + AML_OFFSET (Irq.Flags), + 4}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.WakeCapable), + AML_OFFSET (Irq.Flags), + 5} +}; + + +/******************************************************************************* + * + * AcpiRsSetIrq + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsSetIrq[14] = +{ + /* 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 flags: Triggering[0], Polarity[3], Sharing[4], Wake[5] */ + + {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.Shareable), + AML_OFFSET (Irq.Flags), + 4}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Irq.WakeCapable), + AML_OFFSET (Irq.Flags), + 5}, + + /* + * 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.Shareable), + 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[10] = +{ + {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}, + + /* + * Flags: Producer/Consumer[0], Triggering[1], Polarity[2], + * Sharing[3], Wake[4] + */ + {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.Shareable), + AML_OFFSET (ExtendedIrq.Flags), + 3}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.ExtendedIrq.WakeCapable), + AML_OFFSET (ExtendedIrq.Flags), + 4}, + + /* 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/code/drivers/platform/acpi/third_party/acpica/components/resources/rslist.c b/code/drivers/platform/acpi/third_party/acpica/components/resources/rslist.c new file mode 100644 index 0000000..9f2456c --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/resources/rslist.c @@ -0,0 +1,258 @@ +/******************************************************************************* + * + * Module Name: rslist - Linked list utilities + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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, UART, or CSI2 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_ACPI_STATUS (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); + } + + if (!Resource->Length) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "Zero-length resource returned from RsConvertAmlToResource")); + } + + 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); + } + + /* Sanity check the length. It must not be zero, or we loop forever */ + + if (!Resource->Length) + { + ACPI_ERROR ((AE_INFO, + "Invalid zero length descriptor in resource list\n")); + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); + } + + /* 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, UART or CSI2 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_ACPI_STATUS (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 ( + NULL, 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/code/drivers/platform/acpi/third_party/acpica/components/resources/rsmemory.c b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsmemory.c new file mode 100644 index 0000000..d81e3eb --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsmemory.c @@ -0,0 +1,217 @@ +/******************************************************************************* + * + * Module Name: rsmem24 - Memory resource descriptors + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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/code/drivers/platform/acpi/third_party/acpica/components/resources/rsmisc.c b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsmisc.c new file mode 100644 index 0000000..6776f55 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsmisc.c @@ -0,0 +1,805 @@ +/******************************************************************************* + * + * Module Name: rsmisc - Miscellaneous resource descriptors + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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) + { + Target = NULL; + + /* + * 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 + */ + 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, + ((ACPI_GET8 (Source) >> Info->Value) & 0x01)); + break; + + case ACPI_RSC_2BITFLAG: + /* + * Mask and shift the flag bits + */ + ACPI_SET8 (Destination, + ((ACPI_GET8 (Source) >> Info->Value) & 0x03)); + break; + + case ACPI_RSC_3BITFLAG: + /* + * Mask and shift the flag bits + */ + ACPI_SET8 (Destination, + ((ACPI_GET8 (Source) >> Info->Value) & 0x07)); + break; + + case ACPI_RSC_6BITFLAG: + /* + * Mask and shift the flag bits + */ + ACPI_SET8 (Destination, + ((ACPI_GET8 (Source) >> Info->Value) & 0x3F)); + break; + + case ACPI_RSC_COUNT: + + ItemCount = ACPI_GET8 (Source); + ACPI_SET8 (Destination, 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, 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: + + ACPI_MOVE_16_TO_16(&Temp16, Source); + ItemCount = Temp16 - Info->Value; + + Resource->Length = Resource->Length + ItemCount; + ACPI_SET16 (Destination, ItemCount); + break; + + case ACPI_RSC_COUNT_SERIAL_RES: + + ACPI_MOVE_16_TO_16(&Temp16, Source); + ItemCount = (AmlResourceLength + + sizeof (AML_RESOURCE_LARGE_HEADER)) - + Temp16 - 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 */ + + ACPI_MOVE_16_TO_16 (&Temp16, Source); + Source = ACPI_ADD_PTR ( + void, Aml, (Temp16 + Info->Value)); + AcpiRsMoveData (Target, Source, ItemCount, Info->Opcode); + break; + + case ACPI_RSC_SET8: + + memset (Destination, Info->AmlOffset, Info->Value); + break; + + case ACPI_RSC_DATA8: + + Target = ACPI_ADD_PTR (char, Resource, Info->Value); + 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, 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, 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: + + 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_SET_BIT (*ACPI_CAST8 (Destination), (UINT8) + ((ACPI_GET8 (Source) & 0x01) << Info->Value)); + break; + + case ACPI_RSC_2BITFLAG: + /* + * Mask and shift the flag bits + */ + ACPI_SET_BIT (*ACPI_CAST8 (Destination), (UINT8) + ((ACPI_GET8 (Source) & 0x03) << Info->Value)); + break; + + case ACPI_RSC_3BITFLAG: + /* + * Mask and shift the flag bits + */ + ACPI_SET_BIT (*ACPI_CAST8 (Destination), (UINT8) + ((ACPI_GET8 (Source) & 0x07) << Info->Value)); + break; + + case ACPI_RSC_6BITFLAG: + /* + * Mask and shift the flag bits + */ + ACPI_SET_BIT (*ACPI_CAST8 (Destination), (UINT8) + ((ACPI_GET8 (Source) & 0x3F) << Info->Value)); + break; + + case ACPI_RSC_COUNT: + + ItemCount = ACPI_GET8 (Source); + ACPI_SET8 (Destination, 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, AmlLength); + + AmlLength = (UINT16) (AmlLength + ItemCount * 2); + Target = ACPI_ADD_PTR (void, Aml, Info->Value); + ACPI_SET16 (Target, AmlLength); + AcpiRsSetResourceLength (AmlLength, Aml); + break; + + case ACPI_RSC_COUNT_GPIO_VEN: + + ItemCount = ACPI_GET16 (Source); + ACPI_SET16 (Destination, 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, 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 */ + + ACPI_SET16 (Target, 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, + 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/code/drivers/platform/acpi/third_party/acpica/components/resources/rsserial.c b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsserial.c new file mode 100644 index 0000000..ea68372 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsserial.c @@ -0,0 +1,875 @@ +/******************************************************************************* + * + * Module Name: rsserial - GPIO/SerialBus resource descriptors + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" + +#define _COMPONENT ACPI_RESOURCES + ACPI_MODULE_NAME ("rsserial") + + +/******************************************************************************* + * + * AcpiRsConvertGpio + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertGpio[18] = +{ + {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_1BITFLAG, ACPI_RS_OFFSET (Data.Gpio.Shareable), + AML_OFFSET (Gpio.IntFlags), + 3}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Gpio.WakeCapable), + AML_OFFSET (Gpio.IntFlags), + 4}, + + {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}, +}; + +/******************************************************************************* + * + * AcpiRsConvertClockInput + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertClockInput[8] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_CLOCK_INPUT, + ACPI_RS_SIZE (ACPI_RESOURCE_CLOCK_INPUT), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertClockInput)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_CLOCK_INPUT, + sizeof (AML_RESOURCE_CLOCK_INPUT), + 0}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.ClockInput.RevisionId), + AML_OFFSET (ClockInput.RevisionId), + 1}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.ClockInput.Mode), + AML_OFFSET (ClockInput.Flags), + 0}, + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.ClockInput.Scale), + AML_OFFSET (ClockInput.Flags), + 1}, + + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.ClockInput.FrequencyDivisor), + AML_OFFSET (ClockInput.FrequencyDivisor), + 2}, + + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET (Data.ClockInput.FrequencyNumerator), + AML_OFFSET (ClockInput.FrequencyNumerator), + 4}, + + /* Resource Source */ + {ACPI_RSC_SOURCE, ACPI_RS_OFFSET (Data.ClockInput.ResourceSource), + 0, + sizeof(AML_RESOURCE_CLOCK_INPUT)}, + +}; + + +/******************************************************************************* + * + * AcpiRsConvertPinfunction + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertPinFunction[13] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_PIN_FUNCTION, + ACPI_RS_SIZE (ACPI_RESOURCE_PIN_FUNCTION), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertPinFunction)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_PIN_FUNCTION, + sizeof (AML_RESOURCE_PIN_FUNCTION), + 0}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.PinFunction.RevisionId), + AML_OFFSET (PinFunction.RevisionId), + 1}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.PinFunction.Shareable), + AML_OFFSET (PinFunction.Flags), + 0}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.PinFunction.PinConfig), + AML_OFFSET (PinFunction.PinConfig), + 1}, + + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.PinFunction.FunctionNumber), + AML_OFFSET (PinFunction.FunctionNumber), + 2}, + + /* Pin Table */ + + /* + * It is OK to use GPIO operations here because none of them refer GPIO + * structures directly but instead use offsets given here. + */ + + {ACPI_RSC_COUNT_GPIO_PIN, ACPI_RS_OFFSET (Data.PinFunction.PinTableLength), + AML_OFFSET (PinFunction.PinTableOffset), + AML_OFFSET (PinFunction.ResSourceOffset)}, + + {ACPI_RSC_MOVE_GPIO_PIN, ACPI_RS_OFFSET (Data.PinFunction.PinTable), + AML_OFFSET (PinFunction.PinTableOffset), + 0}, + + /* Resource Source */ + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.PinFunction.ResourceSource.Index), + AML_OFFSET (PinFunction.ResSourceIndex), + 1}, + + {ACPI_RSC_COUNT_GPIO_RES, ACPI_RS_OFFSET (Data.PinFunction.ResourceSource.StringLength), + AML_OFFSET (PinFunction.ResSourceOffset), + AML_OFFSET (PinFunction.VendorOffset)}, + + {ACPI_RSC_MOVE_GPIO_RES, ACPI_RS_OFFSET (Data.PinFunction.ResourceSource.StringPtr), + AML_OFFSET (PinFunction.ResSourceOffset), + 0}, + + /* Vendor Data */ + + {ACPI_RSC_COUNT_GPIO_VEN, ACPI_RS_OFFSET (Data.PinFunction.VendorLength), + AML_OFFSET (PinFunction.VendorLength), + 1}, + + {ACPI_RSC_MOVE_GPIO_RES, ACPI_RS_OFFSET (Data.PinFunction.VendorData), + AML_OFFSET (PinFunction.VendorOffset), + 0}, +}; + + +/******************************************************************************* + * + * AcpiRsConvertCsi2SerialBus + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertCsi2SerialBus[14] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_SERIAL_BUS, + ACPI_RS_SIZE (ACPI_RESOURCE_CSI2_SERIALBUS), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertCsi2SerialBus)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_SERIAL_BUS, + sizeof (AML_RESOURCE_CSI2_SERIALBUS), + 0}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.CommonSerialBus.RevisionId), + AML_OFFSET (CommonSerialBus.RevisionId), + 1}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.Csi2SerialBus.Type), + AML_OFFSET (Csi2SerialBus.Type), + 1}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Csi2SerialBus.ProducerConsumer), + AML_OFFSET (Csi2SerialBus.Flags), + 1}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.Csi2SerialBus.SlaveMode), + AML_OFFSET (Csi2SerialBus.Flags), + 0}, + + {ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET (Data.Csi2SerialBus.PhyType), + AML_OFFSET (Csi2SerialBus.TypeSpecificFlags), + 0}, + + {ACPI_RSC_6BITFLAG, ACPI_RS_OFFSET (Data.Csi2SerialBus.LocalPortInstance), + AML_OFFSET (Csi2SerialBus.TypeSpecificFlags), + 2}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.Csi2SerialBus.TypeRevisionId), + AML_OFFSET (Csi2SerialBus.TypeRevisionId), + 1}, + + /* Vendor data */ + + {ACPI_RSC_COUNT_SERIAL_VEN, ACPI_RS_OFFSET (Data.Csi2SerialBus.VendorLength), + AML_OFFSET (Csi2SerialBus.TypeDataLength), + AML_RESOURCE_CSI2_MIN_DATA_LEN}, + + {ACPI_RSC_MOVE_SERIAL_VEN, ACPI_RS_OFFSET (Data.Csi2SerialBus.VendorData), + 0, + sizeof (AML_RESOURCE_CSI2_SERIALBUS)}, + + /* Resource Source */ + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.Csi2SerialBus.ResourceSource.Index), + AML_OFFSET (Csi2SerialBus.ResSourceIndex), + 1}, + + {ACPI_RSC_COUNT_SERIAL_RES, ACPI_RS_OFFSET (Data.Csi2SerialBus.ResourceSource.StringLength), + AML_OFFSET (Csi2SerialBus.TypeDataLength), + sizeof (AML_RESOURCE_CSI2_SERIALBUS)}, + + {ACPI_RSC_MOVE_SERIAL_RES, ACPI_RS_OFFSET (Data.Csi2SerialBus.ResourceSource.StringPtr), + AML_OFFSET (Csi2SerialBus.TypeDataLength), + sizeof (AML_RESOURCE_CSI2_SERIALBUS)}, +}; + + +/******************************************************************************* + * + * AcpiRsConvertI2cSerialBus + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertI2cSerialBus[18] = +{ + {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_1BITFLAG, ACPI_RS_OFFSET (Data.CommonSerialBus.ConnectionSharing), + AML_OFFSET (CommonSerialBus.Flags), + 2}, + + {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}, + + /* Read LVR from Type Specific Flags, bits[15:8] */ + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.I2cSerialBus.Lvr), + AML_OFFSET (I2cSerialBus.TypeSpecificFlags) + 1, + 1}, + + {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[21] = +{ + {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_1BITFLAG, ACPI_RS_OFFSET (Data.CommonSerialBus.ConnectionSharing), + AML_OFFSET (CommonSerialBus.Flags), + 2}, + + {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[23] = +{ + {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_1BITFLAG, ACPI_RS_OFFSET (Data.CommonSerialBus.ConnectionSharing), + AML_OFFSET (CommonSerialBus.Flags), + 2}, + + {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}, +}; + + +/******************************************************************************* + * + * AcpiRsConvertPinConfig + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertPinConfig[14] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_PIN_CONFIG, + ACPI_RS_SIZE (ACPI_RESOURCE_PIN_CONFIG), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertPinConfig)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_PIN_CONFIG, + sizeof (AML_RESOURCE_PIN_CONFIG), + 0}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.PinConfig.RevisionId), + AML_OFFSET (PinConfig.RevisionId), + 1}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.PinConfig.Shareable), + AML_OFFSET (PinConfig.Flags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.PinConfig.ProducerConsumer), + AML_OFFSET (PinConfig.Flags), + 1}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.PinConfig.PinConfigType), + AML_OFFSET (PinConfig.PinConfigType), + 1}, + + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET (Data.PinConfig.PinConfigValue), + AML_OFFSET (PinConfig.PinConfigValue), + 1}, + + /* Pin Table */ + + /* + * It is OK to use GPIO operations here because none of them refer GPIO + * structures directly but instead use offsets given here. + */ + + {ACPI_RSC_COUNT_GPIO_PIN, ACPI_RS_OFFSET (Data.PinConfig.PinTableLength), + AML_OFFSET (PinConfig.PinTableOffset), + AML_OFFSET (PinConfig.ResSourceOffset)}, + + {ACPI_RSC_MOVE_GPIO_PIN, ACPI_RS_OFFSET (Data.PinConfig.PinTable), + AML_OFFSET (PinConfig.PinTableOffset), + 0}, + + /* Resource Source */ + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.PinConfig.ResourceSource.Index), + AML_OFFSET (PinConfig.ResSourceIndex), + 1}, + + {ACPI_RSC_COUNT_GPIO_RES, ACPI_RS_OFFSET (Data.PinConfig.ResourceSource.StringLength), + AML_OFFSET (PinConfig.ResSourceOffset), + AML_OFFSET (PinConfig.VendorOffset)}, + + {ACPI_RSC_MOVE_GPIO_RES, ACPI_RS_OFFSET (Data.PinConfig.ResourceSource.StringPtr), + AML_OFFSET (PinConfig.ResSourceOffset), + 0}, + + /* Vendor Data */ + + {ACPI_RSC_COUNT_GPIO_VEN, ACPI_RS_OFFSET (Data.PinConfig.VendorLength), + AML_OFFSET (PinConfig.VendorLength), + 1}, + + {ACPI_RSC_MOVE_GPIO_RES, ACPI_RS_OFFSET (Data.PinConfig.VendorData), + AML_OFFSET (PinConfig.VendorOffset), + 0}, +}; + +/******************************************************************************* + * + * AcpiRsConvertPinGroup + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertPinGroup[10] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_PIN_GROUP, + ACPI_RS_SIZE (ACPI_RESOURCE_PIN_GROUP), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertPinGroup)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_PIN_GROUP, + sizeof (AML_RESOURCE_PIN_GROUP), + 0}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.PinGroup.RevisionId), + AML_OFFSET (PinGroup.RevisionId), + 1}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.PinGroup.ProducerConsumer), + AML_OFFSET (PinGroup.Flags), + 0}, + + /* Pin Table */ + + /* + * It is OK to use GPIO operations here because none of them refer GPIO + * structures directly but instead use offsets given here. + */ + + {ACPI_RSC_COUNT_GPIO_PIN, ACPI_RS_OFFSET (Data.PinGroup.PinTableLength), + AML_OFFSET (PinGroup.PinTableOffset), + AML_OFFSET (PinGroup.LabelOffset)}, + + {ACPI_RSC_MOVE_GPIO_PIN, ACPI_RS_OFFSET (Data.PinGroup.PinTable), + AML_OFFSET (PinGroup.PinTableOffset), + 0}, + + /* Resource Label */ + + {ACPI_RSC_COUNT_GPIO_RES, ACPI_RS_OFFSET (Data.PinGroup.ResourceLabel.StringLength), + AML_OFFSET (PinGroup.LabelOffset), + AML_OFFSET (PinGroup.VendorOffset)}, + + {ACPI_RSC_MOVE_GPIO_RES, ACPI_RS_OFFSET (Data.PinGroup.ResourceLabel.StringPtr), + AML_OFFSET (PinGroup.LabelOffset), + 0}, + + /* Vendor Data */ + + {ACPI_RSC_COUNT_GPIO_VEN, ACPI_RS_OFFSET (Data.PinGroup.VendorLength), + AML_OFFSET (PinGroup.VendorLength), + 1}, + + {ACPI_RSC_MOVE_GPIO_RES, ACPI_RS_OFFSET (Data.PinGroup.VendorData), + AML_OFFSET (PinGroup.VendorOffset), + 0}, +}; + +/******************************************************************************* + * + * AcpiRsConvertPinGroupFunction + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertPinGroupFunction[13] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION, + ACPI_RS_SIZE (ACPI_RESOURCE_PIN_GROUP_FUNCTION), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertPinGroupFunction)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_PIN_GROUP_FUNCTION, + sizeof (AML_RESOURCE_PIN_GROUP_FUNCTION), + 0}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.PinGroupFunction.RevisionId), + AML_OFFSET (PinGroupFunction.RevisionId), + 1}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.PinGroupFunction.Shareable), + AML_OFFSET (PinGroupFunction.Flags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.PinGroupFunction.ProducerConsumer), + AML_OFFSET (PinGroupFunction.Flags), + 1}, + + {ACPI_RSC_MOVE16, ACPI_RS_OFFSET (Data.PinGroupFunction.FunctionNumber), + AML_OFFSET (PinGroupFunction.FunctionNumber), + 1}, + + /* Resource Source */ + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.PinGroupFunction.ResourceSource.Index), + AML_OFFSET (PinGroupFunction.ResSourceIndex), + 1}, + + {ACPI_RSC_COUNT_GPIO_RES, ACPI_RS_OFFSET (Data.PinGroupFunction.ResourceSource.StringLength), + AML_OFFSET (PinGroupFunction.ResSourceOffset), + AML_OFFSET (PinGroupFunction.ResSourceLabelOffset)}, + + {ACPI_RSC_MOVE_GPIO_RES, ACPI_RS_OFFSET (Data.PinGroupFunction.ResourceSource.StringPtr), + AML_OFFSET (PinGroupFunction.ResSourceOffset), + 0}, + + /* Resource Source Label */ + + {ACPI_RSC_COUNT_GPIO_RES, ACPI_RS_OFFSET (Data.PinGroupFunction.ResourceSourceLabel.StringLength), + AML_OFFSET (PinGroupFunction.ResSourceLabelOffset), + AML_OFFSET (PinGroupFunction.VendorOffset)}, + + {ACPI_RSC_MOVE_GPIO_RES, ACPI_RS_OFFSET (Data.PinGroupFunction.ResourceSourceLabel.StringPtr), + AML_OFFSET (PinGroupFunction.ResSourceLabelOffset), + 0}, + + /* Vendor Data */ + + {ACPI_RSC_COUNT_GPIO_VEN, ACPI_RS_OFFSET (Data.PinGroupFunction.VendorLength), + AML_OFFSET (PinGroupFunction.VendorLength), + 1}, + + {ACPI_RSC_MOVE_GPIO_RES, ACPI_RS_OFFSET (Data.PinGroupFunction.VendorData), + AML_OFFSET (PinGroupFunction.VendorOffset), + 0}, +}; + +/******************************************************************************* + * + * AcpiRsConvertPinGroupConfig + * + ******************************************************************************/ + +ACPI_RSCONVERT_INFO AcpiRsConvertPinGroupConfig[14] = +{ + {ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG, + ACPI_RS_SIZE (ACPI_RESOURCE_PIN_GROUP_CONFIG), + ACPI_RSC_TABLE_SIZE (AcpiRsConvertPinGroupConfig)}, + + {ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_PIN_GROUP_CONFIG, + sizeof (AML_RESOURCE_PIN_GROUP_CONFIG), + 0}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.PinGroupConfig.RevisionId), + AML_OFFSET (PinGroupConfig.RevisionId), + 1}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.PinGroupConfig.Shareable), + AML_OFFSET (PinGroupConfig.Flags), + 0}, + + {ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET (Data.PinGroupConfig.ProducerConsumer), + AML_OFFSET (PinGroupConfig.Flags), + 1}, + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.PinGroupConfig.PinConfigType), + AML_OFFSET (PinGroupConfig.PinConfigType), + 1}, + + {ACPI_RSC_MOVE32, ACPI_RS_OFFSET (Data.PinGroupConfig.PinConfigValue), + AML_OFFSET (PinGroupConfig.PinConfigValue), + 1}, + + /* Resource Source */ + + {ACPI_RSC_MOVE8, ACPI_RS_OFFSET (Data.PinGroupConfig.ResourceSource.Index), + AML_OFFSET (PinGroupConfig.ResSourceIndex), + 1}, + + {ACPI_RSC_COUNT_GPIO_RES, ACPI_RS_OFFSET (Data.PinGroupConfig.ResourceSource.StringLength), + AML_OFFSET (PinGroupConfig.ResSourceOffset), + AML_OFFSET (PinGroupConfig.ResSourceLabelOffset)}, + + {ACPI_RSC_MOVE_GPIO_RES, ACPI_RS_OFFSET (Data.PinGroupConfig.ResourceSource.StringPtr), + AML_OFFSET (PinGroupConfig.ResSourceOffset), + 0}, + + /* Resource Source Label */ + + {ACPI_RSC_COUNT_GPIO_RES, ACPI_RS_OFFSET (Data.PinGroupConfig.ResourceSourceLabel.StringLength), + AML_OFFSET (PinGroupConfig.ResSourceLabelOffset), + AML_OFFSET (PinGroupConfig.VendorOffset)}, + + {ACPI_RSC_MOVE_GPIO_RES, ACPI_RS_OFFSET (Data.PinGroupConfig.ResourceSourceLabel.StringPtr), + AML_OFFSET (PinGroupConfig.ResSourceLabelOffset), + 0}, + + /* Vendor Data */ + + {ACPI_RSC_COUNT_GPIO_VEN, ACPI_RS_OFFSET (Data.PinGroupConfig.VendorLength), + AML_OFFSET (PinGroupConfig.VendorLength), + 1}, + + {ACPI_RSC_MOVE_GPIO_RES, ACPI_RS_OFFSET (Data.PinGroupConfig.VendorData), + AML_OFFSET (PinGroupConfig.VendorOffset), + 0}, +}; diff --git a/code/drivers/platform/acpi/third_party/acpica/components/resources/rsutils.c b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsutils.c new file mode 100644 index 0000000..591e886 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsutils.c @@ -0,0 +1,840 @@ +/******************************************************************************* + * + * Module Name: rsutils - Utilities for the resource manager + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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: + + memcpy (Destination, Source, ItemCount); + return; + + /* + * 16-, 32-, and 64-bit cases must use the move macros that perform + * endian conversion and/or accommodate 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 + * Clear any existing length, preserving descriptor type bits + */ + Aml->SmallHeader.DescriptorType = (UINT8) + ((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) strlen ( + ACPI_CAST_PTR (char, &AmlResourceSource[1])) + 1; + + TotalLength = (UINT32) ACPI_ROUND_UP_TO_NATIVE_WORD (TotalLength); + + 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 */ + + 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, + const 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 ( + ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, 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->RelativePathname = 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, &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/code/drivers/platform/acpi/third_party/acpica/components/resources/rsxface.c b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsxface.c new file mode 100644 index 0000000..9ede619 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/resources/rsxface.c @@ -0,0 +1,714 @@ +/******************************************************************************* + * + * Module Name: rsxface - Public interfaces to the resource manager + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#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, Address.Granularity); \ + ACPI_COPY_FIELD(Out, In, Address.Minimum); \ + ACPI_COPY_FIELD(Out, In, Address.Maximum); \ + ACPI_COPY_FIELD(Out, In, Address.TranslationOffset); \ + ACPI_COPY_FIELD(Out, In, Address.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 */ + + 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 device 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) || + (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 */ + + 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: AcpiWalkResourceBuffer + * + * PARAMETERS: Buffer - Formatted buffer returned by one of the + * various Get*Resource functions + * UserFunction - Called for each resource + * Context - Passed to UserFunction + * + * RETURN: Status + * + * DESCRIPTION: Walks the input resource template. The UserFunction is called + * once for each resource in the list. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiWalkResourceBuffer ( + ACPI_BUFFER *Buffer, + ACPI_WALK_RESOURCE_CALLBACK UserFunction, + void *Context) +{ + ACPI_STATUS Status = AE_OK; + ACPI_RESOURCE *Resource; + ACPI_RESOURCE *ResourceEnd; + + + ACPI_FUNCTION_TRACE (AcpiWalkResourceBuffer); + + + /* Parameter validation */ + + if (!Buffer || !Buffer->Pointer || !UserFunction) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Buffer contains the resource list and length */ + + 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 type */ + + if (Resource->Type > ACPI_RESOURCE_TYPE_MAX) + { + Status = AE_AML_INVALID_RESOURCE_TYPE; + break; + } + + /* Sanity check the length. It must not be zero, or we loop forever */ + + if (!Resource->Length) + { + return_ACPI_STATUS (AE_AML_BAD_RESOURCE_LENGTH); + } + + /* 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_NEXT_RESOURCE (Resource); + } + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiWalkResourceBuffer) + + +/******************************************************************************* + * + * 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 or METHOD_NAME__DMA) + * 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_FUNCTION_TRACE (AcpiWalkResources); + + + /* Parameter validation */ + + if (!DeviceHandle || !UserFunction || !Name || + (!ACPI_COMPARE_NAMESEG (Name, METHOD_NAME__CRS) && + !ACPI_COMPARE_NAMESEG (Name, METHOD_NAME__PRS) && + !ACPI_COMPARE_NAMESEG (Name, METHOD_NAME__AEI) && + !ACPI_COMPARE_NAMESEG (Name, METHOD_NAME__DMA))) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Get the _CRS/_PRS/_AEI/_DMA resource list */ + + Buffer.Length = ACPI_ALLOCATE_LOCAL_BUFFER; + Status = AcpiRsGetMethodData (DeviceHandle, Name, &Buffer); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Walk the resource list and cleanup */ + + Status = AcpiWalkResourceBuffer (&Buffer, UserFunction, Context); + ACPI_FREE (Buffer.Pointer); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiWalkResources) diff --git a/code/drivers/platform/acpi/third_party/acpica/components/tables/tbdata.c b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbdata.c new file mode 100644 index 0000000..0d57f13 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbdata.c @@ -0,0 +1,1299 @@ +/****************************************************************************** + * + * Module Name: tbdata - Table manager data structure functions + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "actables.h" +#include "acevents.h" + +#define _COMPONENT ACPI_TABLES + ACPI_MODULE_NAME ("tbdata") + +/* Local prototypes */ + +static ACPI_STATUS +AcpiTbCheckDuplication ( + ACPI_TABLE_DESC *TableDesc, + UINT32 *TableIndex); + +static BOOLEAN +AcpiTbCompareTables ( + ACPI_TABLE_DESC *TableDesc, + UINT32 TableIndex); + + +/******************************************************************************* + * + * FUNCTION: AcpiTbCompareTables + * + * PARAMETERS: TableDesc - Table 1 descriptor to be compared + * TableIndex - Index of table 2 to be compared + * + * RETURN: TRUE if both tables are identical. + * + * DESCRIPTION: This function compares a table with another table that has + * already been installed in the root table list. + * + ******************************************************************************/ + +static BOOLEAN +AcpiTbCompareTables ( + ACPI_TABLE_DESC *TableDesc, + UINT32 TableIndex) +{ + ACPI_STATUS Status = AE_OK; + BOOLEAN IsIdentical; + ACPI_TABLE_HEADER *Table; + UINT32 TableLength; + UINT8 TableFlags; + + + Status = AcpiTbAcquireTable (&AcpiGbl_RootTableList.Tables[TableIndex], + &Table, &TableLength, &TableFlags); + if (ACPI_FAILURE (Status)) + { + return (FALSE); + } + + /* + * Check for a table match on the entire table length, + * not just the header. + */ + IsIdentical = (BOOLEAN)((TableDesc->Length != TableLength || + memcmp (TableDesc->Pointer, Table, TableLength)) ? + FALSE : TRUE); + + /* Release the acquired table */ + + AcpiTbReleaseTable (Table, TableLength, TableFlags); + return (IsIdentical); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbInitTableDescriptor + * + * PARAMETERS: TableDesc - Table descriptor + * Address - Physical address of the table + * Flags - Allocation flags of the table + * Table - Pointer to the table + * + * RETURN: None + * + * DESCRIPTION: Initialize a new table descriptor + * + ******************************************************************************/ + +void +AcpiTbInitTableDescriptor ( + ACPI_TABLE_DESC *TableDesc, + ACPI_PHYSICAL_ADDRESS Address, + UINT8 Flags, + ACPI_TABLE_HEADER *Table) +{ + + /* + * Initialize the table descriptor. Set the pointer to NULL for external + * tables, since the table is not fully mapped at this time. + */ + memset (TableDesc, 0, sizeof (ACPI_TABLE_DESC)); + TableDesc->Address = Address; + TableDesc->Length = Table->Length; + TableDesc->Flags = Flags; + ACPI_MOVE_32_TO_32 (TableDesc->Signature.Ascii, Table->Signature); + + switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) + { + case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: + case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: + + TableDesc->Pointer = Table; + break; + + case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: + default: + + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbAcquireTable + * + * PARAMETERS: TableDesc - Table descriptor + * TablePtr - Where table is returned + * TableLength - Where table length is returned + * TableFlags - Where table allocation flags are returned + * + * RETURN: Status + * + * DESCRIPTION: Acquire an ACPI table. It can be used for tables not + * maintained in the AcpiGbl_RootTableList. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbAcquireTable ( + ACPI_TABLE_DESC *TableDesc, + ACPI_TABLE_HEADER **TablePtr, + UINT32 *TableLength, + UINT8 *TableFlags) +{ + ACPI_TABLE_HEADER *Table = NULL; + + + switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) + { + case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: + + Table = AcpiOsMapMemory (TableDesc->Address, TableDesc->Length); + break; + + case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: + case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: + + Table = TableDesc->Pointer; + break; + + default: + + break; + } + + /* Table is not valid yet */ + + if (!Table) + { + return (AE_NO_MEMORY); + } + + /* Fill the return values */ + + *TablePtr = Table; + *TableLength = TableDesc->Length; + *TableFlags = TableDesc->Flags; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbReleaseTable + * + * PARAMETERS: Table - Pointer for the table + * TableLength - Length for the table + * TableFlags - Allocation flags for the table + * + * RETURN: None + * + * DESCRIPTION: Release a table. The inverse of AcpiTbAcquireTable(). + * + ******************************************************************************/ + +void +AcpiTbReleaseTable ( + ACPI_TABLE_HEADER *Table, + UINT32 TableLength, + UINT8 TableFlags) +{ + + switch (TableFlags & ACPI_TABLE_ORIGIN_MASK) + { + case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: + + AcpiOsUnmapMemory (Table, TableLength); + break; + + case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: + case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: + default: + + break; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbAcquireTempTable + * + * PARAMETERS: TableDesc - Table descriptor to be acquired + * Address - Address of the table + * Flags - Allocation flags of the table + * Table - Pointer to the table (required for virtual + * origins, optional for physical) + * + * RETURN: Status + * + * DESCRIPTION: This function validates the table header to obtain the length + * of a table and fills the table descriptor to make its state as + * "INSTALLED". Such a table descriptor is only used for verified + * installation. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbAcquireTempTable ( + ACPI_TABLE_DESC *TableDesc, + ACPI_PHYSICAL_ADDRESS Address, + UINT8 Flags, + ACPI_TABLE_HEADER *Table) +{ + BOOLEAN MappedTable = FALSE; + + + switch (Flags & ACPI_TABLE_ORIGIN_MASK) + { + case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: + + /* Get the length of the full table from the header */ + + if (!Table) + { + Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); + if (!Table) + { + return (AE_NO_MEMORY); + } + + MappedTable = TRUE; + } + + break; + + case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: + case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: + + if (!Table) + { + return (AE_BAD_PARAMETER); + } + + break; + + default: + + /* Table is not valid yet */ + + return (AE_NO_MEMORY); + } + + AcpiTbInitTableDescriptor (TableDesc, Address, Flags, Table); + if (MappedTable) + { + AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER)); + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbReleaseTempTable + * + * PARAMETERS: TableDesc - Table descriptor to be released + * + * RETURN: Status + * + * DESCRIPTION: The inverse of AcpiTbAcquireTempTable(). + * + *****************************************************************************/ + +void +AcpiTbReleaseTempTable ( + ACPI_TABLE_DESC *TableDesc) +{ + + /* + * Note that the .Address is maintained by the callers of + * AcpiTbAcquireTempTable(), thus do not invoke AcpiTbUninstallTable() + * where .Address will be freed. + */ + AcpiTbInvalidateTable (TableDesc); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiTbValidateTable + * + * PARAMETERS: TableDesc - Table descriptor + * + * RETURN: Status + * + * DESCRIPTION: This function is called to validate the table, the returned + * table descriptor is in "VALIDATED" state. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiTbValidateTable ( + ACPI_TABLE_DESC *TableDesc) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (TbValidateTable); + + + /* Validate the table if necessary */ + + if (!TableDesc->Pointer) + { + Status = AcpiTbAcquireTable (TableDesc, &TableDesc->Pointer, + &TableDesc->Length, &TableDesc->Flags); + if (!TableDesc->Pointer) + { + Status = AE_NO_MEMORY; + } + } + + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbInvalidateTable + * + * PARAMETERS: TableDesc - Table descriptor + * + * RETURN: None + * + * DESCRIPTION: Invalidate one internal ACPI table, this is the inverse of + * AcpiTbValidateTable(). + * + ******************************************************************************/ + +void +AcpiTbInvalidateTable ( + ACPI_TABLE_DESC *TableDesc) +{ + + ACPI_FUNCTION_TRACE (TbInvalidateTable); + + + /* Table must be validated */ + + if (!TableDesc->Pointer) + { + return_VOID; + } + + AcpiTbReleaseTable (TableDesc->Pointer, TableDesc->Length, + TableDesc->Flags); + + switch (TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) + { + case ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL: + + TableDesc->Pointer = NULL; + break; + + case ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL: + case ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL: + default: + + break; + } + + return_VOID; +} + + +/****************************************************************************** + * + * FUNCTION: AcpiTbValidateTempTable + * + * PARAMETERS: TableDesc - Table descriptor + * + * RETURN: Status + * + * DESCRIPTION: This function is called to validate the table, the returned + * table descriptor is in "VALIDATED" state. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiTbValidateTempTable ( + ACPI_TABLE_DESC *TableDesc) +{ + + if (!TableDesc->Pointer && !AcpiGbl_EnableTableValidation) + { + /* + * Only validates the header of the table. + * Note that Length contains the size of the mapping after invoking + * this work around, this value is required by + * AcpiTbReleaseTempTable(). + * We can do this because in AcpiInitTableDescriptor(), the Length + * field of the installed descriptor is filled with the actual + * table length obtaining from the table header. + */ + TableDesc->Length = sizeof (ACPI_TABLE_HEADER); + } + + return (AcpiTbValidateTable (TableDesc)); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbCheckDuplication + * + * PARAMETERS: TableDesc - Table descriptor + * TableIndex - Where the table index is returned + * + * RETURN: Status + * + * DESCRIPTION: Avoid installing duplicated tables. However table override and + * user aided dynamic table load is allowed, thus comparing the + * address of the table is not sufficient, and checking the entire + * table content is required. + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiTbCheckDuplication ( + ACPI_TABLE_DESC *TableDesc, + UINT32 *TableIndex) +{ + UINT32 i; + + + ACPI_FUNCTION_TRACE (TbCheckDuplication); + + + /* Check if table is already registered */ + + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) + { + /* Do not compare with unverified tables */ + + if (!(AcpiGbl_RootTableList.Tables[i].Flags & ACPI_TABLE_IS_VERIFIED)) + { + continue; + } + + /* + * Check for a table match on the entire table length, + * not just the header. + */ + if (!AcpiTbCompareTables (TableDesc, i)) + { + 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. + */ + if (AcpiGbl_RootTableList.Tables[i].Flags & + ACPI_TABLE_IS_LOADED) + { + /* Table is still loaded, this is an error */ + + return_ACPI_STATUS (AE_ALREADY_EXISTS); + } + else + { + *TableIndex = i; + return_ACPI_STATUS (AE_CTRL_TERMINATE); + } + } + + /* Indicate no duplication to the caller */ + + return_ACPI_STATUS (AE_OK); +} + + +/****************************************************************************** + * + * FUNCTION: AcpiTbVerifyTempTable + * + * PARAMETERS: TableDesc - Table descriptor + * Signature - Table signature to verify + * TableIndex - Where the table index is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to validate and verify the table, the + * returned table descriptor is in "VALIDATED" state. + * Note that 'TableIndex' is required to be set to !NULL to + * enable duplication check. + * + *****************************************************************************/ + +ACPI_STATUS +AcpiTbVerifyTempTable ( + ACPI_TABLE_DESC *TableDesc, + char *Signature, + UINT32 *TableIndex) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (TbVerifyTempTable); + + + /* Validate the table */ + + Status = AcpiTbValidateTempTable (TableDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (AE_NO_MEMORY); + } + + /* If a particular signature is expected (DSDT/FACS), it must match */ + + if (Signature && + !ACPI_COMPARE_NAMESEG (&TableDesc->Signature, Signature)) + { + ACPI_BIOS_ERROR ((AE_INFO, + "Invalid signature 0x%X for ACPI table, expected [%s]", + TableDesc->Signature.Integer, Signature)); + Status = AE_BAD_SIGNATURE; + goto InvalidateAndExit; + } + + if (AcpiGbl_EnableTableValidation) + { + /* Verify the checksum */ + + Status = AcpiUtVerifyChecksum (TableDesc->Pointer, TableDesc->Length); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, AE_NO_MEMORY, + "%4.4s 0x%8.8X%8.8X" + " Attempted table install failed", + AcpiUtValidNameseg (TableDesc->Signature.Ascii) ? + TableDesc->Signature.Ascii : "????", + ACPI_FORMAT_UINT64 (TableDesc->Address))); + + goto InvalidateAndExit; + } + + /* Avoid duplications */ + + if (TableIndex) + { + Status = AcpiTbCheckDuplication (TableDesc, TableIndex); + if (ACPI_FAILURE (Status)) + { + if (Status != AE_CTRL_TERMINATE) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "%4.4s 0x%8.8X%8.8X" + " Table is already loaded", + AcpiUtValidNameseg (TableDesc->Signature.Ascii) ? + TableDesc->Signature.Ascii : "????", + ACPI_FORMAT_UINT64 (TableDesc->Address))); + } + + goto InvalidateAndExit; + } + } + + TableDesc->Flags |= ACPI_TABLE_IS_VERIFIED; + } + + return_ACPI_STATUS (Status); + +InvalidateAndExit: + AcpiTbInvalidateTable (TableDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbResizeRootTableList + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Expand the size of global table array + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbResizeRootTableList ( + void) +{ + ACPI_TABLE_DESC *Tables; + UINT32 TableCount; + UINT32 CurrentTableCount, MaxTableCount; + UINT32 i; + + + 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 */ + + if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED) + { + TableCount = AcpiGbl_RootTableList.MaxTableCount; + } + else + { + TableCount = AcpiGbl_RootTableList.CurrentTableCount; + } + + MaxTableCount = TableCount + ACPI_ROOT_TABLE_SIZE_INCREMENT; + Tables = ACPI_ALLOCATE_ZEROED ( + ((ACPI_SIZE) MaxTableCount) * 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 */ + + CurrentTableCount = 0; + if (AcpiGbl_RootTableList.Tables) + { + for (i = 0; i < TableCount; i++) + { + if (AcpiGbl_RootTableList.Tables[i].Address) + { + memcpy (Tables + CurrentTableCount, + AcpiGbl_RootTableList.Tables + i, + sizeof (ACPI_TABLE_DESC)); + CurrentTableCount++; + } + } + + if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED) + { + ACPI_FREE (AcpiGbl_RootTableList.Tables); + } + } + + AcpiGbl_RootTableList.Tables = Tables; + AcpiGbl_RootTableList.MaxTableCount = MaxTableCount; + AcpiGbl_RootTableList.CurrentTableCount = CurrentTableCount; + AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ORIGIN_ALLOCATED; + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbGetNextTableDescriptor + * + * PARAMETERS: TableIndex - Where table index is returned + * TableDesc - Where table descriptor is returned + * + * RETURN: Status and table index/descriptor. + * + * DESCRIPTION: Allocate a new ACPI table entry to the global table list + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbGetNextTableDescriptor ( + UINT32 *TableIndex, + ACPI_TABLE_DESC **TableDesc) +{ + ACPI_STATUS Status; + UINT32 i; + + + /* 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); + } + } + + i = AcpiGbl_RootTableList.CurrentTableCount; + AcpiGbl_RootTableList.CurrentTableCount++; + + if (TableIndex) + { + *TableIndex = i; + } + if (TableDesc) + { + *TableDesc = &AcpiGbl_RootTableList.Tables[i]; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * 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++) + { + AcpiTbUninstallTable (&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); + return_VOID; +} + + +/******************************************************************************* + * + * 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. + */ + Status = AcpiUtAcquireWriteLock (&AcpiGbl_NamespaceRwLock); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + AcpiNsDeleteNamespaceByOwner (OwnerId); + AcpiUtReleaseWriteLock (&AcpiGbl_NamespaceRwLock); + 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 - Index into the root table + * + * 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); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbLoadTable + * + * PARAMETERS: TableIndex - Table index + * ParentNode - Where table index is returned + * + * RETURN: Status + * + * DESCRIPTION: Load an ACPI table + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbLoadTable ( + UINT32 TableIndex, + ACPI_NAMESPACE_NODE *ParentNode) +{ + ACPI_TABLE_HEADER *Table; + ACPI_STATUS Status; + ACPI_OWNER_ID OwnerId; + + + ACPI_FUNCTION_TRACE (TbLoadTable); + + + /* + * Note: Now table is "INSTALLED", it must be validated before + * using. + */ + Status = AcpiGetTableByIndex (TableIndex, &Table); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiNsLoadTable (TableIndex, ParentNode); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* + * 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); + } + + /* Invoke table handler */ + + AcpiTbNotifyTable (ACPI_TABLE_EVENT_LOAD, Table); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbInstallAndLoadTable + * + * PARAMETERS: Address - Physical address of the table + * Flags - Allocation flags of the table + * Table - Pointer to the table (required for + * virtual origins, optional for + * physical) + * Override - Whether override should be performed + * TableIndex - Where table index is returned + * + * RETURN: Status + * + * DESCRIPTION: Install and load an ACPI table + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbInstallAndLoadTable ( + ACPI_PHYSICAL_ADDRESS Address, + UINT8 Flags, + ACPI_TABLE_HEADER *Table, + BOOLEAN Override, + UINT32 *TableIndex) +{ + ACPI_STATUS Status; + UINT32 i; + + + ACPI_FUNCTION_TRACE (TbInstallAndLoadTable); + + + /* Install the table and load it into the namespace */ + + Status = AcpiTbInstallStandardTable (Address, Flags, Table, TRUE, + Override, &i); + if (ACPI_FAILURE (Status)) + { + goto Exit; + } + + Status = AcpiTbLoadTable (i, AcpiGbl_RootNode); + if (ACPI_FAILURE (Status)) + { + /* Table was installed but not loaded, uninstall to clean up */ + + AcpiTbUninstallTable (&AcpiGbl_RootTableList.Tables[i]); + goto Exit; + } + +Exit: + *TableIndex = i; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbUnloadTable + * + * PARAMETERS: TableIndex - Table index + * + * RETURN: Status + * + * DESCRIPTION: Unload an ACPI table + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbUnloadTable ( + UINT32 TableIndex) +{ + ACPI_STATUS Status = AE_OK; + ACPI_TABLE_HEADER *Table; + ACPI_OWNER_ID OwnerId; + ACPI_CPU_FLAGS Flags; + + + ACPI_FUNCTION_TRACE (TbUnloadTable); + + + /* Ensure the table is still loaded */ + + if (!AcpiTbIsTableLoaded (TableIndex)) + { + return_ACPI_STATUS (AE_NOT_EXIST); + } + + /* Invoke table handler */ + + Status = AcpiGetTableByIndex (TableIndex, &Table); + if (ACPI_SUCCESS (Status)) + { + AcpiTbNotifyTable (ACPI_TABLE_EVENT_UNLOAD, Table); + } + +#if (!ACPI_REDUCED_HARDWARE) + /* + * Clear GPE dispatch for methods owned by the table being unloaded. + * If any matching GPE is currently dispatching, AE_ABORT_METHOD is + * returned and the unload cannot proceed. + */ + Status = AcpiEvClearGpeDispatchByOwner ( + AcpiGbl_RootTableList.Tables[TableIndex].OwnerId); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } +#endif /* !ACPI_REDUCED_HARDWARE */ + + /* + * Gate notify dispatch for this table's OwnerId so no new notifies + * are queued against namespace nodes that are about to be freed. + * If any notify dispatch is in-flight, abort the unload — the caller + * must retry after the dispatch completes. + */ + OwnerId = AcpiGbl_RootTableList.Tables[TableIndex].OwnerId; + if (OwnerId > 0 && OwnerId < ACPI_NOTIFY_COUNT_MAX_OWNER) + { + Flags = AcpiOsAcquireLock (AcpiGbl_NotifyLock); + AcpiGbl_NotifyUnloading[OwnerId] = TRUE; + + if (AcpiGbl_NotifyExecuteCount[OwnerId] > 0) + { + AcpiGbl_NotifyUnloading[OwnerId] = FALSE; + AcpiOsReleaseLock (AcpiGbl_NotifyLock, Flags); + return_ACPI_STATUS (AE_ABORT_METHOD); + } + + AcpiOsReleaseLock (AcpiGbl_NotifyLock, Flags); + } + + /* Delete the portion of the namespace owned by this table */ + + Status = AcpiTbDeleteNamespaceByOwner (TableIndex); + + /* + * Clear the unloading gate. If namespace deletion failed the table + * remains loaded so notifies must be allowed again. If it succeeded + * the OwnerId is about to be released and may be reused — clear + * the gate before release to avoid a stale flag on the new owner. + */ + if (OwnerId > 0 && OwnerId < ACPI_NOTIFY_COUNT_MAX_OWNER) + { + Flags = AcpiOsAcquireLock (AcpiGbl_NotifyLock); + AcpiGbl_NotifyUnloading[OwnerId] = FALSE; + AcpiOsReleaseLock (AcpiGbl_NotifyLock, Flags); + } + + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + (void) AcpiTbReleaseOwnerId (TableIndex); + AcpiTbSetTableLoadedFlag (TableIndex, FALSE); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbNotifyTable + * + * PARAMETERS: Event - Table event + * Table - Validated table pointer + * + * RETURN: None + * + * DESCRIPTION: Notify a table event to the users. + * + ******************************************************************************/ + +void +AcpiTbNotifyTable ( + UINT32 Event, + void *Table) +{ + /* Invoke table handler if present */ + + if (AcpiGbl_TableHandler) + { + (void) AcpiGbl_TableHandler (Event, Table, + AcpiGbl_TableHandlerContext); + } +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/tables/tbfadt.c b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbfadt.c new file mode 100644 index 0000000..9f83077 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbfadt.c @@ -0,0 +1,758 @@ +/****************************************************************************** + * + * Module Name: tbfadt - FADT table utilities + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "actables.h" + +#define _COMPONENT ACPI_TABLES + ACPI_MODULE_NAME ("tbfadt") + +/* Local prototypes */ + +static void +AcpiTbInitGenericAddress ( + ACPI_GENERIC_ADDRESS *GenericAddress, + UINT8 SpaceId, + UINT8 ByteWidth, + UINT64 Address, + const char *RegisterName, + UINT8 Flags); + +static void +AcpiTbConvertFadt ( + void); + +static void +AcpiTbSetupFadtRegisters ( + void); + +static UINT64 +AcpiTbSelectAddress ( + char *RegisterName, + UINT32 Address32, + UINT64 Address64); + + +/* Table for conversion of FADT to common internal format and FADT validation */ + +typedef struct acpi_fadt_info +{ + const char *Name; + UINT16 Address64; + UINT16 Address32; + UINT16 Length; + UINT8 DefaultLength; + UINT8 Flags; + +} ACPI_FADT_INFO; + +#define ACPI_FADT_OPTIONAL 0 +#define ACPI_FADT_REQUIRED 1 +#define ACPI_FADT_SEPARATE_LENGTH 2 +#define ACPI_FADT_GPE_REGISTER 4 + +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_SEPARATE_LENGTH}, /* ACPI 5.0A: Timer is optional */ + + {"Gpe0Block", + ACPI_FADT_OFFSET (XGpe0Block), + ACPI_FADT_OFFSET (Gpe0Block), + ACPI_FADT_OFFSET (Gpe0BlockLength), + 0, + ACPI_FADT_SEPARATE_LENGTH | ACPI_FADT_GPE_REGISTER}, + + {"Gpe1Block", + ACPI_FADT_OFFSET (XGpe1Block), + ACPI_FADT_OFFSET (Gpe1Block), + ACPI_FADT_OFFSET (Gpe1BlockLength), + 0, + ACPI_FADT_SEPARATE_LENGTH | ACPI_FADT_GPE_REGISTER} +}; + +#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 + * Address - Address of the register + * RegisterName - ASCII name of the ACPI register + * + * RETURN: None + * + * DESCRIPTION: Initialize a Generic Address Structure (GAS) + * See the ACPI specification for a full description and + * definition of this structure. + * + ******************************************************************************/ + +static void +AcpiTbInitGenericAddress ( + ACPI_GENERIC_ADDRESS *GenericAddress, + UINT8 SpaceId, + UINT8 ByteWidth, + UINT64 Address, + const char *RegisterName, + UINT8 Flags) +{ + UINT8 BitWidth; + + + /* + * Bit width field in the GAS is only one byte long, 255 max. + * Check for BitWidth overflow in GAS. + */ + BitWidth = (UINT8) (ByteWidth * 8); + if (ByteWidth > 31) /* (31*8)=248, (32*8)=256 */ + { + /* + * No error for GPE blocks, because we do not use the BitWidth + * for GPEs, the legacy length (ByteWidth) is used instead to + * allow for a large number of GPEs. + */ + if (!(Flags & ACPI_FADT_GPE_REGISTER)) + { + ACPI_ERROR ((AE_INFO, + "%s - 32-bit FADT register is too long (%u bytes, %u bits) " + "to convert to GAS struct - 255 bits max, truncating", + RegisterName, ByteWidth, (ByteWidth * 8))); + } + + BitWidth = 255; + } + + /* + * 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 = BitWidth; + GenericAddress->BitOffset = 0; + GenericAddress->AccessWidth = 0; /* Access width ANY */ +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbSelectAddress + * + * PARAMETERS: RegisterName - ASCII name of the ACPI register + * Address32 - 32-bit address of the register + * Address64 - 64-bit address of the register + * + * RETURN: The resolved 64-bit address + * + * DESCRIPTION: Select between 32-bit and 64-bit versions of addresses within + * the FADT. Used for the FACS and DSDT addresses. + * + * NOTES: + * + * 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) could be a corrupted address field or it might indicate + * the presence of two FACS or two DSDT tables. + * + * November 2013: + * By default, as per the ACPICA specification, a valid 64-bit address is + * used regardless of the value of the 32-bit address. However, this + * behavior can be overridden via the AcpiGbl_Use32BitFadtAddresses flag. + * + ******************************************************************************/ + +static UINT64 +AcpiTbSelectAddress ( + char *RegisterName, + UINT32 Address32, + UINT64 Address64) +{ + + if (!Address64) + { + /* 64-bit address is zero, use 32-bit address */ + + return ((UINT64) Address32); + } + + if (Address32 && + (Address64 != (UINT64) Address32)) + { + /* Address mismatch between 32-bit and 64-bit versions */ + + ACPI_BIOS_WARNING ((AE_INFO, + "32/64X %s address mismatch in FADT: " + "0x%8.8X/0x%8.8X%8.8X, using %u-bit address", + RegisterName, Address32, ACPI_FORMAT_UINT64 (Address64), + AcpiGbl_Use32BitFadtAddresses ? 32 : 64)); + + /* 32-bit address override */ + + if (AcpiGbl_Use32BitFadtAddresses) + { + return ((UINT64) Address32); + } + } + + /* Default is to use the 64-bit address */ + + return (Address64); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbParseFadt + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Initialize the FADT, DSDT and FACS tables + * (FADT contains the addresses of the DSDT and FACS) + * + ******************************************************************************/ + +void +AcpiTbParseFadt ( + void) +{ + UINT32 Length; + ACPI_TABLE_HEADER *Table; + ACPI_TABLE_DESC *FadtDesc; + ACPI_STATUS Status; + + + /* + * 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. + */ + FadtDesc = &AcpiGbl_RootTableList.Tables[AcpiGbl_FadtIndex]; + Status = AcpiTbGetTable (FadtDesc, &Table); + if (ACPI_FAILURE (Status)) + { + return; + } + Length = FadtDesc->Length; + + /* + * Validate the FADT checksum before we copy the table. Ignore + * checksum error as we want to try to get the DSDT and FACS. + */ + (void) AcpiUtVerifyChecksum (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 */ + + AcpiTbPutTable (FadtDesc); + + /* Obtain the DSDT and FACS tables via their addresses within the FADT */ + + AcpiTbInstallStandardTable ( + (ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XDsdt, + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, NULL, FALSE, TRUE, + &AcpiGbl_DsdtIndex); + + if (AcpiGbl_FADT.Facs) + { + AcpiTbInstallStandardTable ( + (ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.Facs, + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, NULL, FALSE, TRUE, + &AcpiGbl_FacsIndex); + } + if (AcpiGbl_FADT.XFacs) + { + AcpiTbInstallStandardTable ( + (ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XFacs, + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, NULL, FALSE, TRUE, + &AcpiGbl_XFacsIndex); + } +} + + +/******************************************************************************* + * + * 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 + * (typically the current ACPI specification version). If so, truncate + * the table, and issue a warning. + */ + if (Length > sizeof (ACPI_TABLE_FADT)) + { + ACPI_BIOS_WARNING ((AE_INFO, + "FADT (revision %u) is longer than %s length, " + "truncating length %u to %u", + Table->Revision, ACPI_FADT_CONFORMANCE, Length, + (UINT32) sizeof (ACPI_TABLE_FADT))); + } + + /* Clear the entire local FADT */ + + memset (&AcpiGbl_FADT, 0, sizeof (ACPI_TABLE_FADT)); + + /* Copy the original FADT, up to sizeof (ACPI_TABLE_FADT) */ + + 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 (); + + /* Initialize the global ACPI register structures */ + + AcpiTbSetupFadtRegisters (); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbConvertFadt + * + * PARAMETERS: None - AcpiGbl_FADT is used. + * + * RETURN: None + * + * DESCRIPTION: Converts all versions of the FADT to a common internal format. + * Expand 32-bit addresses to 64-bit as necessary. Also validate + * important fields within the FADT. + * + * NOTE: AcpiGbl_FADT must be of size (ACPI_TABLE_FADT), and must + * contain a copy of the actual BIOS-provided 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 to the 64-bit X fields if the 64-bit X field is originally + * zero. + * + * For ACPI 1.0 FADTs (that contain no 64-bit addresses), all 32-bit address + * fields are expanded to the corresponding 64-bit X fields in the internal + * common FADT. + * + * For ACPI 2.0+ FADTs, all valid (non-zero) 32-bit address fields are expanded + * to the corresponding 64-bit X fields, if the 64-bit field is originally + * zero. Adhering to the ACPI specification, we completely ignore the 32-bit + * field if the 64-bit field is valid, regardless of whether the host OS is + * 32-bit or 64-bit. + * + * 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 +AcpiTbConvertFadt ( + void) +{ + const char *Name; + ACPI_GENERIC_ADDRESS *Address64; + UINT32 Address32; + UINT8 Length; + UINT8 Flags; + UINT32 i; + + + /* + * 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; + } + + /* + * Now we can update the local FADT length to the length of the + * current FADT version as defined by the ACPI specification. + * Thus, we will have a common FADT internally. + */ + AcpiGbl_FADT.Header.Length = sizeof (ACPI_TABLE_FADT); + + /* + * Expand the 32-bit DSDT addresses to 64-bit as necessary. + * Later ACPICA code will always use the X 64-bit field. + */ + AcpiGbl_FADT.XDsdt = AcpiTbSelectAddress ("DSDT", + AcpiGbl_FADT.Dsdt, AcpiGbl_FADT.XDsdt); + + /* 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++) + { + /* + * Get the 32-bit and 64-bit addresses, as well as the register + * length and register name. + */ + Address32 = *ACPI_ADD_PTR (UINT32, + &AcpiGbl_FADT, FadtInfoTable[i].Address32); + + 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; + Flags = FadtInfoTable[i].Flags; + + /* + * 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. + * + * November 2013: + * Now always use the 64-bit address if it is valid (non-zero), in + * accordance with the ACPI specification which states that a 64-bit + * address supersedes the 32-bit version. This behavior can be + * overridden by the AcpiGbl_Use32BitFadtAddresses flag. + * + * During 64-bit address construction and verification, + * these cases are handled: + * + * Address32 zero, Address64 [don't care] - Use Address64 + * + * No override: if AcpiGbl_Use32BitFadtAddresses is FALSE, and: + * Address32 non-zero, Address64 zero - Copy/use Address32 + * Address32 non-zero == Address64 non-zero - Use Address64 + * Address32 non-zero != Address64 non-zero - Warning, use Address64 + * + * Override: if AcpiGbl_Use32BitFadtAddresses is TRUE, and: + * Address32 non-zero, Address64 zero - Copy/use Address32 + * Address32 non-zero == Address64 non-zero - Copy/use Address32 + * Address32 non-zero != Address64 non-zero - Warning, copy/use Address32 + * + * Note: SpaceId is always I/O for 32-bit legacy address fields + */ + if (Address32) + { + if (Address64->Address) + { + if (Address64->Address != (UINT64) Address32) + { + /* Address mismatch */ + + ACPI_BIOS_WARNING ((AE_INFO, + "32/64X address mismatch in FADT/%s: " + "0x%8.8X/0x%8.8X%8.8X, using %u-bit address", + Name, Address32, + ACPI_FORMAT_UINT64 (Address64->Address), + AcpiGbl_Use32BitFadtAddresses ? 32 : 64)); + } + + /* + * For each extended field, check for length mismatch + * between the legacy length field and the corresponding + * 64-bit X length field. + * Note: If the legacy length field is > 0xFF bits, ignore + * this check. (GPE registers can be larger than the + * 64-bit GAS structure can accommodate, 0xFF bits). + * Also skip if BitWidth is 0, indicating the 64-bit field + * was not populated - legacy length will be used instead. + */ + if ((ACPI_MUL_8 (Length) <= ACPI_UINT8_MAX) && + (Address64->BitWidth != 0) && + (Address64->BitWidth != ACPI_MUL_8 (Length))) + { + ACPI_BIOS_WARNING ((AE_INFO, + "32/64X length mismatch in FADT/%s: %u/%u", + Name, ACPI_MUL_8 (Length), Address64->BitWidth)); + } + } + + /* + * Hardware register access code always uses the 64-bit fields. + * So if the 64-bit field is zero or is to be overridden, + * initialize it with the 32-bit fields. + * Note that when the 32-bit address favor is specified, the + * 64-bit fields are always re-initialized so that + * AccessSize/BitWidth/BitOffset fields can be correctly + * configured to the values to trigger a 32-bit compatible + * access mode in the hardware register access code. + */ + if (!Address64->Address || AcpiGbl_Use32BitFadtAddresses) + { + AcpiTbInitGenericAddress (Address64, + ACPI_ADR_SPACE_SYSTEM_IO, Length, + (UINT64) Address32, Name, Flags); + } + } + + if (FadtInfoTable[i].Flags & ACPI_FADT_REQUIRED) + { + /* + * Field is required (PM1aEvent, PM1aControl). + * Both the address and length must be non-zero. + */ + if (!Address64->Address || !Length) + { + ACPI_BIOS_ERROR ((AE_INFO, + "Required FADT 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].Flags & 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_BIOS_WARNING ((AE_INFO, + "Optional FADT field %s has valid %s but zero %s: " + "0x%8.8X%8.8X/0x%X", Name, + (Length ? "Length" : "Address"), + (Length ? "Address": "Length"), + 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_BIOS_WARNING ((AE_INFO, + "Invalid length for FADT/%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), + "PmRegisters", 0); + } + } +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/tables/tbfind.c b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbfind.c new file mode 100644 index 0000000..a8d644c --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbfind.c @@ -0,0 +1,147 @@ +/****************************************************************************** + * + * Module Name: tbfind - find table + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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) +{ + ACPI_STATUS Status = AE_OK; + ACPI_TABLE_HEADER Header; + UINT32 i; + + + ACPI_FUNCTION_TRACE (TbFindTable); + + + /* Validate the input table signature */ + + if (!AcpiUtValidNameseg (Signature)) + { + return_ACPI_STATUS (AE_BAD_SIGNATURE); + } + + /* Don't allow the OEM strings to be too long */ + + if ((strlen (OemId) > ACPI_OEM_ID_SIZE) || + (strlen (OemTableId) > ACPI_OEM_TABLE_ID_SIZE)) + { + return_ACPI_STATUS (AE_AML_STRING_LIMIT); + } + + /* Normalize the input strings */ + + memset (&Header, 0, sizeof (ACPI_TABLE_HEADER)); + ACPI_COPY_NAMESEG (Header.Signature, Signature); + if (strlen (OemId) >= ACPI_OEM_ID_SIZE) + { + memcpy (Header.OemId, OemId, ACPI_OEM_ID_SIZE); + } + else + { + memcpy (Header.OemId, OemId, strlen (OemId)); + /* Remainder is already zeroed by memset above */ + } + + if (strlen (OemTableId) >= ACPI_OEM_TABLE_ID_SIZE) + { + memcpy (Header.OemTableId, OemTableId, ACPI_OEM_TABLE_ID_SIZE); + } + else + { + memcpy (Header.OemTableId, OemTableId, strlen (OemTableId)); + /* Remainder is already zeroed by memset above */ + } + + /* Search for the table */ + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) + { + if (memcmp (&(AcpiGbl_RootTableList.Tables[i].Signature), + Header.Signature, ACPI_NAMESEG_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 = AcpiTbValidateTable (&AcpiGbl_RootTableList.Tables[i]); + if (ACPI_FAILURE (Status)) + { + goto UnlockAndExit; + } + + if (!AcpiGbl_RootTableList.Tables[i].Pointer) + { + continue; + } + } + + /* Check for table match on all IDs */ + + if (!memcmp (AcpiGbl_RootTableList.Tables[i].Pointer->Signature, + Header.Signature, ACPI_NAMESEG_SIZE) && + (!OemId[0] || + !memcmp (AcpiGbl_RootTableList.Tables[i].Pointer->OemId, + Header.OemId, ACPI_OEM_ID_SIZE)) && + (!OemTableId[0] || + !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)); + goto UnlockAndExit; + } + } + Status = AE_NOT_FOUND; + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return_ACPI_STATUS (Status); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/tables/tbinstal.c b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbinstal.c new file mode 100644 index 0000000..90c28fc --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbinstal.c @@ -0,0 +1,331 @@ +/****************************************************************************** + * + * Module Name: tbinstal - ACPI table installation and removal + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "actables.h" + +#define _COMPONENT ACPI_TABLES + ACPI_MODULE_NAME ("tbinstal") + + +/******************************************************************************* + * + * FUNCTION: AcpiTbInstallTableWithOverride + * + * PARAMETERS: NewTableDesc - New table descriptor to install + * Override - Whether override should be performed + * TableIndex - Where the table index is returned + * + * 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 +AcpiTbInstallTableWithOverride ( + ACPI_TABLE_DESC *NewTableDesc, + BOOLEAN Override, + UINT32 *TableIndex) +{ + UINT32 i; + ACPI_STATUS Status; + + + Status = AcpiTbGetNextTableDescriptor (&i, NULL); + if (ACPI_FAILURE (Status)) + { + return; + } + + /* + * 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. + */ + if (Override) + { + AcpiTbOverrideTable (NewTableDesc); + } + + AcpiTbInitTableDescriptor (&AcpiGbl_RootTableList.Tables[i], + NewTableDesc->Address, NewTableDesc->Flags, NewTableDesc->Pointer); + + AcpiTbPrintTableHeader (NewTableDesc->Address, NewTableDesc->Pointer); + + /* This synchronizes AcpiGbl_DsdtIndex */ + + *TableIndex = i; + + /* Set the global integer width (based upon revision of the DSDT) */ + + if (i == AcpiGbl_DsdtIndex) + { + AcpiUtSetIntegerWidth (NewTableDesc->Pointer->Revision); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbInstallStandardTable + * + * PARAMETERS: Address - Address of the table (might be a virtual + * address depending on the TableFlags) + * Flags - Flags for the table + * Table - Pointer to the table (required for virtual + * origins, optional for physical) + * Reload - Whether reload should be performed + * Override - Whether override should be performed + * TableIndex - Where the table index is returned + * + * RETURN: Status + * + * DESCRIPTION: This function is called to verify and install an ACPI table. + * When this function is called by "Load" or "LoadTable" opcodes, + * or by AcpiLoadTable() API, the "Reload" parameter is set. + * After successfully returning from this function, table is + * "INSTALLED" but not "VALIDATED". + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbInstallStandardTable ( + ACPI_PHYSICAL_ADDRESS Address, + UINT8 Flags, + ACPI_TABLE_HEADER *Table, + BOOLEAN Reload, + BOOLEAN Override, + UINT32 *TableIndex) +{ + UINT32 i; + ACPI_STATUS Status = AE_OK; + ACPI_TABLE_DESC NewTableDesc; + + + ACPI_FUNCTION_TRACE (TbInstallStandardTable); + + + /* Acquire a temporary table descriptor for validation */ + + Status = AcpiTbAcquireTempTable (&NewTableDesc, Address, Flags, Table); + if (ACPI_FAILURE (Status)) + { + ACPI_ERROR ((AE_INFO, + "Could not acquire table length at %8.8X%8.8X", + ACPI_FORMAT_UINT64 (Address))); + return_ACPI_STATUS (Status); + } + + /* + * Optionally do not load any SSDTs from the RSDT/XSDT. This can + * be useful for debugging ACPI problems on some machines. + */ + if (!Reload && + AcpiGbl_DisableSsdtTableInstall && + ACPI_COMPARE_NAMESEG (&NewTableDesc.Signature, ACPI_SIG_SSDT)) + { + ACPI_INFO (( + "Ignoring installation of %4.4s at %8.8X%8.8X", + NewTableDesc.Signature.Ascii, ACPI_FORMAT_UINT64 (Address))); + goto ReleaseAndExit; + } + + /* Acquire the table lock */ + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + + /* Validate and verify a table before installation */ + + Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL, &i); + if (ACPI_FAILURE (Status)) + { + if (Status == AE_CTRL_TERMINATE) + { + /* + * Table was unloaded, allow it to be reloaded. + * As we are going to return AE_OK to the caller, we should + * take the responsibility of freeing the input descriptor. + * Refill the input descriptor to ensure + * AcpiTbInstallTableWithOverride() can be called again to + * indicate the re-installation. + */ + AcpiTbUninstallTable (&NewTableDesc); + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + *TableIndex = i; + return_ACPI_STATUS (AE_OK); + } + goto UnlockAndExit; + } + + /* Add the table to the global root table list */ + + AcpiTbInstallTableWithOverride (&NewTableDesc, Override, TableIndex); + + /* Invoke table handler */ + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + AcpiTbNotifyTable (ACPI_TABLE_EVENT_INSTALL, NewTableDesc.Pointer); + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + +UnlockAndExit: + + /* Release the table lock */ + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + +ReleaseAndExit: + + /* Release the temporary table descriptor */ + + AcpiTbReleaseTempTable (&NewTableDesc); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbOverrideTable + * + * PARAMETERS: OldTableDesc - Validated table descriptor to be + * overridden + * + * RETURN: None + * + * DESCRIPTION: Attempt table override by calling the OSL override functions. + * Note: If the table is overridden, then the entire new table + * is acquired and returned by this function. + * Before/after invocation, the table descriptor is in a state + * that is "VALIDATED". + * + ******************************************************************************/ + +void +AcpiTbOverrideTable ( + ACPI_TABLE_DESC *OldTableDesc) +{ + ACPI_STATUS Status; + ACPI_TABLE_DESC NewTableDesc; + ACPI_TABLE_HEADER *Table; + ACPI_PHYSICAL_ADDRESS Address; + UINT32 Length; + ACPI_ERROR_ONLY (char *OverrideType); + + + /* (1) Attempt logical override (returns a logical address) */ + + Status = AcpiOsTableOverride (OldTableDesc->Pointer, &Table); + if (ACPI_SUCCESS (Status) && Table) + { + AcpiTbAcquireTempTable (&NewTableDesc, ACPI_PTR_TO_PHYSADDR (Table), + ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, Table); + ACPI_ERROR_ONLY (OverrideType = "Logical"); + goto FinishOverride; + } + + /* (2) Attempt physical override (returns a physical address) */ + + Status = AcpiOsPhysicalTableOverride (OldTableDesc->Pointer, + &Address, &Length); + if (ACPI_SUCCESS (Status) && Address && Length) + { + AcpiTbAcquireTempTable (&NewTableDesc, Address, + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, NULL); + ACPI_ERROR_ONLY (OverrideType = "Physical"); + goto FinishOverride; + } + + return; /* There was no override */ + + +FinishOverride: + + /* + * Validate and verify a table before overriding, no nested table + * duplication check as it's too complicated and unnecessary. + */ + Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL, NULL); + if (ACPI_FAILURE (Status)) + { + return; + } + + ACPI_INFO (("%4.4s 0x%8.8X%8.8X" + " %s table override, new table: 0x%8.8X%8.8X", + OldTableDesc->Signature.Ascii, + ACPI_FORMAT_UINT64 (OldTableDesc->Address), + OverrideType, ACPI_FORMAT_UINT64 (NewTableDesc.Address))); + + /* We can now uninstall the original table */ + + AcpiTbUninstallTable (OldTableDesc); + + /* + * Replace the original table descriptor and keep its state as + * "VALIDATED". + */ + AcpiTbInitTableDescriptor (OldTableDesc, NewTableDesc.Address, + NewTableDesc.Flags, NewTableDesc.Pointer); + AcpiTbValidateTempTable (OldTableDesc); + + /* Release the temporary table descriptor */ + + AcpiTbReleaseTempTable (&NewTableDesc); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbUninstallTable + * + * PARAMETERS: TableDesc - Table descriptor + * + * RETURN: None + * + * DESCRIPTION: Delete one internal ACPI table + * + ******************************************************************************/ + +void +AcpiTbUninstallTable ( + ACPI_TABLE_DESC *TableDesc) +{ + + ACPI_FUNCTION_TRACE (TbUninstallTable); + + + /* Table must be installed */ + + if (!TableDesc->Address) + { + return_VOID; + } + + AcpiTbInvalidateTable (TableDesc); + + if ((TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) == + ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) + { + ACPI_FREE (TableDesc->Pointer); + TableDesc->Pointer = NULL; + } + + TableDesc->Address = ACPI_PTR_TO_PHYSADDR (NULL); + return_VOID; +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/tables/tbprint.c b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbprint.c new file mode 100644 index 0000000..1ad2804 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbprint.c @@ -0,0 +1,171 @@ +/****************************************************************************** + * + * Module Name: tbprint - Table output utilities + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "actables.h" +#include "acdisasm.h" +#include "acutils.h" + +#define _COMPONENT ACPI_TABLES + ACPI_MODULE_NAME ("tbprint") + + +/* Local prototypes */ + +static void +AcpiTbFixString ( + char *String, + ACPI_SIZE Length); + +static void +AcpiTbCleanupTableHeader ( + ACPI_TABLE_HEADER *OutHeader, + ACPI_TABLE_HEADER *Header); + + +/******************************************************************************* + * + * 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 (!isprint ((int) (UINT8) *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) +{ + + memcpy (OutHeader, Header, sizeof (ACPI_TABLE_HEADER)); + + AcpiTbFixString (OutHeader->Signature, ACPI_NAMESEG_SIZE); + AcpiTbFixString (OutHeader->OemId, ACPI_OEM_ID_SIZE); + AcpiTbFixString (OutHeader->OemTableId, ACPI_OEM_TABLE_ID_SIZE); + AcpiTbFixString (OutHeader->AslCompilerId, ACPI_NAMESEG_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; + +#pragma GCC diagnostic push +#if defined(__GNUC__) && __GNUC__ >= 11 +#pragma GCC diagnostic ignored "-Wstringop-overread" +#endif + + if (ACPI_COMPARE_NAMESEG (Header->Signature, ACPI_SIG_FACS)) + { + /* FACS only has signature and length fields */ + + ACPI_INFO (("%-4.4s 0x%8.8X%8.8X %06X", + Header->Signature, ACPI_FORMAT_UINT64 (Address), + Header->Length)); + } + else if (ACPI_VALIDATE_RSDP_SIG (ACPI_CAST_PTR (ACPI_TABLE_RSDP, + Header)->Signature)) + { + /* RSDP has no common fields */ + + memcpy (LocalHeader.OemId, ACPI_CAST_PTR (ACPI_TABLE_RSDP, + Header)->OemId, ACPI_OEM_ID_SIZE); + AcpiTbFixString (LocalHeader.OemId, ACPI_OEM_ID_SIZE); + + ACPI_INFO (("RSDP 0x%8.8X%8.8X %06X (v%.2d %-6.6s)", + ACPI_FORMAT_UINT64 (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 if (AcpiGbl_CDAT && !AcpiUtValidNameseg (Header->Signature)) + { + /* CDAT does not use the common ACPI table header */ + + ACPI_INFO (("%-4.4s 0x%8.8X%8.8X %06X", + ACPI_SIG_CDAT, ACPI_FORMAT_UINT64 (Address), + ACPI_CAST_PTR (ACPI_TABLE_CDAT, Header)->Length)); + } + else + { + /* Standard ACPI table with full common header */ + + AcpiTbCleanupTableHeader (&LocalHeader, Header); + + ACPI_INFO (( + "%-4.4s 0x%8.8X%8.8X" + " %06X (v%.2d %-6.6s %-8.8s %08X %-4.4s %08X)", + LocalHeader.Signature, ACPI_FORMAT_UINT64 (Address), + LocalHeader.Length, LocalHeader.Revision, LocalHeader.OemId, + LocalHeader.OemTableId, LocalHeader.OemRevision, + LocalHeader.AslCompilerId, LocalHeader.AslCompilerRevision)); + } +#pragma GCC diagnostic pop +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/tables/tbutils.c b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbutils.c new file mode 100644 index 0000000..f4a81f9 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbutils.c @@ -0,0 +1,483 @@ +/****************************************************************************** + * + * Module Name: tbutils - ACPI Table utilities + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "actables.h" + +#define _COMPONENT ACPI_TABLES + ACPI_MODULE_NAME ("tbutils") + + +/* Local prototypes */ + +static ACPI_PHYSICAL_ADDRESS +AcpiTbGetRootTableEntry ( + UINT8 *TableEntry, + UINT32 TableEntrySize); + + +/******************************************************************************* + * + * 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_TABLE_FACS *Facs; + + if (AcpiGbl_FADT.XFacs && + (!AcpiGbl_FADT.Facs || !AcpiGbl_Use32BitFacsAddresses)) + { + (void) AcpiGetTableByIndex (AcpiGbl_XFacsIndex, + ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Facs)); + AcpiGbl_FACS = Facs; + } + else if (AcpiGbl_FADT.Facs) + { + (void) AcpiGetTableByIndex (AcpiGbl_FacsIndex, + ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &Facs)); + AcpiGbl_FACS = Facs; + } + + /* If there is no FACS, just continue. There was already an error msg */ + + return (AE_OK); +} + + +/******************************************************************************* + * + * 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_BIOS_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: TableIndex - Index of installed table to copy + * + * RETURN: The copied DSDT + * + * 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); + } + + memcpy (NewTable, TableDesc->Pointer, TableDesc->Length); + AcpiTbUninstallTable (TableDesc); + + AcpiTbInitTableDescriptor ( + &AcpiGbl_RootTableList.Tables[AcpiGbl_DsdtIndex], + ACPI_PTR_TO_PHYSADDR (NewTable), + ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, NewTable); + + ACPI_INFO (( + "Forced DSDT copy: length 0x%05X copied locally, original unmapped", + NewTable->Length)); + + return (NewTable); +} + + +/******************************************************************************* + * + * 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) +{ + UINT32 Address32; + 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 == ACPI_RSDT_ENTRY_SIZE) + { + /* + * 32-bit platform, RSDT: Return 32-bit table entry + * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return + */ + ACPI_MOVE_32_TO_32(&Address32, TableEntry); + return Address32; + } + 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_BIOS_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: RsdpAddress - 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 ACPI_INIT_FUNCTION +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; + UINT32 TableIndex; + + + 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)); + + /* Use XSDT if present and not overridden. Otherwise, use RSDT */ + + if ((Rsdp->Revision > 1) && + Rsdp->XsdtPhysicalAddress && + !AcpiGbl_DoNotUseXsdt) + { + /* + * RSDP contains 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 = ACPI_XSDT_ENTRY_SIZE; + } + else + { + /* Root table is an RSDT (32-bit physical addresses) */ + + Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress; + TableEntrySize = ACPI_RSDT_ENTRY_SIZE; + } + + /* + * 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); + + /* + * Validate length of the table, and map entire table. + * Minimum length table must contain at least one entry. + */ + Length = Table->Length; + AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER)); + + if (Length < (sizeof (ACPI_TABLE_HEADER) + TableEntrySize)) + { + ACPI_BIOS_ERROR ((AE_INFO, + "Invalid table 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 = AcpiUtVerifyChecksum (Table, Length); + if (ACPI_FAILURE (Status)) + { + AcpiOsUnmapMemory (Table, Length); + return_ACPI_STATUS (Status); + } + + /* Get the number of entries and pointer to first entry */ + + TableCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) / + TableEntrySize); + TableEntry = ACPI_ADD_PTR (UINT8, Table, sizeof (ACPI_TABLE_HEADER)); + + /* Initialize the root table array from the RSDT/XSDT */ + + for (i = 0; i < TableCount; i++) + { + /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ + + Address = AcpiTbGetRootTableEntry (TableEntry, TableEntrySize); + + /* Skip NULL entries in RSDT/XSDT */ + + if (!Address) + { + goto NextTable; + } + + Status = AcpiTbInstallStandardTable (Address, + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, NULL, FALSE, TRUE, + &TableIndex); + + if (ACPI_SUCCESS (Status) && + ACPI_COMPARE_NAMESEG ( + &AcpiGbl_RootTableList.Tables[TableIndex].Signature, + ACPI_SIG_FADT)) + { + AcpiGbl_FadtIndex = TableIndex; + AcpiTbParseFadt (); + } + +NextTable: + + TableEntry += TableEntrySize; + } + + AcpiOsUnmapMemory (Table, Length); + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbGetTable + * + * PARAMETERS: TableDesc - Table descriptor + * OutTable - Where the pointer to the table is returned + * + * RETURN: Status and pointer to the requested table + * + * DESCRIPTION: Increase a reference to a table descriptor and return the + * validated table pointer. + * If the table descriptor is an entry of the root table list, + * this API must be invoked with ACPI_MTX_TABLES acquired. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbGetTable ( + ACPI_TABLE_DESC *TableDesc, + ACPI_TABLE_HEADER **OutTable) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiTbGetTable); + + + if (TableDesc->ValidationCount == 0) + { + /* Table need to be "VALIDATED" */ + + Status = AcpiTbValidateTable (TableDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } + + if (TableDesc->ValidationCount < ACPI_MAX_TABLE_VALIDATIONS) + { + TableDesc->ValidationCount++; + + /* + * Detect ValidationCount overflows to ensure that the warning + * message will only be printed once. + */ + if (TableDesc->ValidationCount >= ACPI_MAX_TABLE_VALIDATIONS) + { + ACPI_WARNING((AE_INFO, + "Table %p, Validation count overflows\n", TableDesc)); + } + } + + *OutTable = TableDesc->Pointer; + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbPutTable + * + * PARAMETERS: TableDesc - Table descriptor + * + * RETURN: None + * + * DESCRIPTION: Decrease a reference to a table descriptor and release the + * validated table pointer if no references. + * If the table descriptor is an entry of the root table list, + * this API must be invoked with ACPI_MTX_TABLES acquired. + * + ******************************************************************************/ + +void +AcpiTbPutTable ( + ACPI_TABLE_DESC *TableDesc) +{ + + ACPI_FUNCTION_TRACE (AcpiTbPutTable); + + + if (TableDesc->ValidationCount < ACPI_MAX_TABLE_VALIDATIONS) + { + TableDesc->ValidationCount--; + + /* + * Detect ValidationCount underflows to ensure that the warning + * message will only be printed once. + */ + if (TableDesc->ValidationCount >= ACPI_MAX_TABLE_VALIDATIONS) + { + ACPI_WARNING ((AE_INFO, + "Table %p, Validation count underflows\n", TableDesc)); + return_VOID; + } + } + + if (TableDesc->ValidationCount == 0) + { + /* Table need to be "INVALIDATED" */ + + AcpiTbInvalidateTable (TableDesc); + } + + return_VOID; +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/tables/tbxface.c b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbxface.c new file mode 100644 index 0000000..e407d70 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbxface.c @@ -0,0 +1,609 @@ +/****************************************************************************** + * + * Module Name: tbxface - ACPI table-oriented external interfaces + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#include "acpi.h" +#include "accommon.h" +#include "actables.h" + +#define _COMPONENT ACPI_TABLES + ACPI_MODULE_NAME ("tbxface") + + +/******************************************************************************* + * + * 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 + * AllowResize - 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 ACPI_INIT_FUNCTION +AcpiInitializeTables ( + ACPI_TABLE_DESC *InitialTableArray, + UINT32 InitialTableCount, + BOOLEAN AllowResize) +{ + ACPI_PHYSICAL_ADDRESS RsdpAddress; + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiInitializeTables); + + + /* + * Setup the Root Table Array and 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 */ + + 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 usable format. + */ + Status = AcpiTbParseRootTable (RsdpAddress); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL_INIT (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 ACPI_INIT_FUNCTION +AcpiReallocateRootTable ( + void) +{ + ACPI_STATUS Status; + ACPI_TABLE_DESC *TableDesc; + UINT32 i, j; + + + ACPI_FUNCTION_TRACE (AcpiReallocateRootTable); + + + /* + * If there are tables unverified, it is required to reallocate the + * root table list to clean up invalid table entries. Otherwise only + * reallocate the root table list if the host provided a static buffer + * for the table array in the call to AcpiInitializeTables(). + */ + if ((AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED) && + AcpiGbl_EnableTableValidation) + { + return_ACPI_STATUS (AE_SUPPORT); + } + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + + /* + * Ensure OS early boot logic, which is required by some hosts. If the + * table state is reported to be wrong, developers should fix the + * issue by invoking AcpiPutTable() for the reported table during the + * early stage. + */ + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) + { + TableDesc = &AcpiGbl_RootTableList.Tables[i]; + if (TableDesc->Pointer) + { + ACPI_ERROR ((AE_INFO, + "Table [%4.4s] is not invalidated during early boot stage", + TableDesc->Signature.Ascii)); + } + } + + if (!AcpiGbl_EnableTableValidation) + { + /* + * Now it's safe to do full table validation. We can do deferred + * table initialization here once the flag is set. + */ + AcpiGbl_EnableTableValidation = TRUE; + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) + { + TableDesc = &AcpiGbl_RootTableList.Tables[i]; + if (!(TableDesc->Flags & ACPI_TABLE_IS_VERIFIED)) + { + Status = AcpiTbVerifyTempTable (TableDesc, NULL, &j); + if (ACPI_FAILURE (Status)) + { + AcpiTbUninstallTable (TableDesc); + } + } + } + } + + AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ALLOW_RESIZE; + Status = AcpiTbResizeRootTableList (); + AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ORIGIN_ALLOCATED; + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL_INIT (AcpiReallocateRootTable) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetTableHeader + * + * PARAMETERS: Signature - ACPI signature of needed table + * Instance - Which instance (for SSDTs) + * OutTableHeader - The pointer to the where the table header + * is returned + * + * RETURN: Status and a copy of the table header + * + * DESCRIPTION: Finds and returns an ACPI table header. Caller provides the + * memory where a copy of the header is to be returned + * (fixed length). + * + ******************************************************************************/ + +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_NAMESEG ( + &(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_INTERNAL_PHYSICAL) + { + Header = AcpiOsMapMemory ( + AcpiGbl_RootTableList.Tables[i].Address, + sizeof (ACPI_TABLE_HEADER)); + if (!Header) + { + return (AE_NO_MEMORY); + } + + memcpy (OutTableHeader, Header, sizeof (ACPI_TABLE_HEADER)); + AcpiOsUnmapMemory (Header, sizeof (ACPI_TABLE_HEADER)); + } + else + { + return (AE_NOT_FOUND); + } + } + else + { + 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 the requested table + * + * DESCRIPTION: Finds and verifies an ACPI table. Table must be in the + * RSDT/XSDT. + * Note that an early stage AcpiGetTable() call must be paired + * with an early stage AcpiPutTable() call. otherwise the table + * pointer mapped by the early stage mapping implementation may be + * erroneously unmapped by the late stage unmapping implementation + * in an AcpiPutTable() invoked during the late stage. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetTable ( + char *Signature, + UINT32 Instance, + ACPI_TABLE_HEADER **OutTable) +{ + UINT32 i; + UINT32 j; + ACPI_STATUS Status = AE_NOT_FOUND; + ACPI_TABLE_DESC *TableDesc; + + + /* Parameter validation */ + + if (!Signature || !OutTable) + { + return (AE_BAD_PARAMETER); + } + + /* + * Note that the following line is required by some OSPMs, they only + * check if the returned table is NULL instead of the returned status + * to determined if this function is succeeded. + */ + *OutTable = NULL; + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + + /* Walk the root table list */ + + for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) + { + TableDesc = &AcpiGbl_RootTableList.Tables[i]; + + if (!ACPI_COMPARE_NAMESEG (&TableDesc->Signature, Signature)) + { + continue; + } + + if (++j < Instance) + { + continue; + } + + Status = AcpiTbGetTable (TableDesc, OutTable); + break; + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetTable) + + +/******************************************************************************* + * + * FUNCTION: AcpiPutTable + * + * PARAMETERS: Table - The pointer to the table + * + * RETURN: None + * + * DESCRIPTION: Release a table returned by AcpiGetTable() and its clones. + * Note that it is not safe if this function was invoked after an + * uninstallation happened to the original table descriptor. + * Currently there is no OSPMs' requirement to handle such + * situations. + * + ******************************************************************************/ + +void +AcpiPutTable ( + ACPI_TABLE_HEADER *Table) +{ + UINT32 i; + ACPI_TABLE_DESC *TableDesc; + + + ACPI_FUNCTION_TRACE (AcpiPutTable); + + + if (!Table) + { + return_VOID; + } + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + + /* Walk the root table list */ + + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) + { + TableDesc = &AcpiGbl_RootTableList.Tables[i]; + + if (TableDesc->Pointer != Table) + { + continue; + } + + AcpiTbPutTable (TableDesc); + break; + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return_VOID; +} + +ACPI_EXPORT_SYMBOL (AcpiPutTable) + + +/******************************************************************************* + * + * FUNCTION: AcpiGetTableByIndex + * + * PARAMETERS: TableIndex - Table index + * OutTable - Where the pointer to the table is returned + * + * RETURN: Status and pointer to the requested table + * + * DESCRIPTION: Obtain a table by an index into the global table list. Used + * internally also. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiGetTableByIndex ( + UINT32 TableIndex, + ACPI_TABLE_HEADER **OutTable) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiGetTableByIndex); + + + /* Parameter validation */ + + if (!OutTable) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* + * Note that the following line is required by some OSPMs, they only + * check if the returned table is NULL instead of the returned status + * to determined if this function is succeeded. + */ + *OutTable = NULL; + + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + + /* Validate index */ + + if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount) + { + Status = AE_BAD_PARAMETER; + goto UnlockAndExit; + } + + Status = AcpiTbGetTable ( + &AcpiGbl_RootTableList.Tables[TableIndex], OutTable); + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiGetTableByIndex) + + +/******************************************************************************* + * + * FUNCTION: AcpiInstallTableHandler + * + * PARAMETERS: Handler - Table event handler + * Context - Value passed to the handler on each event + * + * RETURN: Status + * + * DESCRIPTION: Install a global 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 a 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/code/drivers/platform/acpi/third_party/acpica/components/tables/tbxfload.c b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbxfload.c new file mode 100644 index 0000000..b88643c --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbxfload.c @@ -0,0 +1,514 @@ +/****************************************************************************** + * + * Module Name: tbxfload - Table load/unload external interfaces + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "actables.h" +#include "acevents.h" + +#define _COMPONENT ACPI_TABLES + ACPI_MODULE_NAME ("tbxfload") + + +/******************************************************************************* + * + * FUNCTION: AcpiLoadTables + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Load the ACPI tables from the RSDT/XSDT + * + ******************************************************************************/ + +ACPI_STATUS ACPI_INIT_FUNCTION +AcpiLoadTables ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiLoadTables); + + + /* + * Install the default operation region handlers. These are the + * handlers that are defined by the ACPI specification to be + * "always accessible" -- namely, SystemMemory, SystemIO, and + * PCI_Config. This also means that no _REG methods need to be + * run for these address spaces. We need to have these handlers + * installed before any AML code can be executed, especially any + * module-level code (11/2015). + * Note that we allow OSPMs to install their own region handlers + * between AcpiInitializeSubsystem() and AcpiLoadTables() to use + * their customized default region handlers. + */ + Status = AcpiEvInstallRegionHandlers (); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "During Region initialization")); + return_ACPI_STATUS (Status); + } + + /* Load the namespace from the tables */ + + Status = AcpiTbLoadNamespace (); + + /* Don't let single failures abort the load */ + + if (Status == AE_CTRL_TERMINATE) + { + Status = AE_OK; + } + + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, + "While loading namespace from ACPI tables")); + } + + /* + * Initialize the objects in the namespace that remain uninitialized. + * This runs the executable AML that may be part of the declaration of + * these name objects: + * OperationRegions, BufferFields, Buffers, and Packages. + * + */ + Status = AcpiNsInitializeObjects (); + if (ACPI_SUCCESS (Status)) + { + AcpiGbl_NamespaceInitialized = TRUE; + } + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL_INIT (AcpiLoadTables) + + +/******************************************************************************* + * + * FUNCTION: AcpiTbLoadNamespace + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Load the namespace from the DSDT and all SSDTs/PSDTs found in + * the RSDT/XSDT. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbLoadNamespace ( + void) +{ + ACPI_STATUS Status; + UINT32 i; + ACPI_TABLE_HEADER *NewDsdt; + ACPI_TABLE_DESC *Table; + UINT32 TablesLoaded = 0; + UINT32 TablesFailed = 0; + + + 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. + */ + Table = &AcpiGbl_RootTableList.Tables[AcpiGbl_DsdtIndex]; + + if (!AcpiGbl_RootTableList.CurrentTableCount || + !ACPI_COMPARE_NAMESEG (Table->Signature.Ascii, ACPI_SIG_DSDT) || + ACPI_FAILURE (AcpiTbValidateTable (Table))) + { + 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 AcpiTbValidateTable. + */ + AcpiGbl_DSDT = Table->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 (AcpiGbl_DsdtIndex); + 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. + */ + memcpy (&AcpiGbl_OriginalDsdtHeader, AcpiGbl_DSDT, + sizeof (ACPI_TABLE_HEADER)); + + /* Load and parse tables */ + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + Status = AcpiNsLoadTable (AcpiGbl_DsdtIndex, AcpiGbl_RootNode); + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "[DSDT] table load failed")); + TablesFailed++; + } + else + { + TablesLoaded++; + } + + /* Load any SSDT or PSDT tables. Note: Loop leaves tables locked */ + + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i) + { + Table = &AcpiGbl_RootTableList.Tables[i]; + + if (!Table->Address || + (!ACPI_COMPARE_NAMESEG (Table->Signature.Ascii, ACPI_SIG_SSDT) && + !ACPI_COMPARE_NAMESEG (Table->Signature.Ascii, ACPI_SIG_PSDT) && + !ACPI_COMPARE_NAMESEG (Table->Signature.Ascii, ACPI_SIG_OSDT)) || + ACPI_FAILURE (AcpiTbValidateTable (Table))) + { + continue; + } + + /* Ignore errors while loading tables, get as many as possible */ + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + Status = AcpiNsLoadTable (i, AcpiGbl_RootNode); + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + if (ACPI_FAILURE (Status)) + { + ACPI_EXCEPTION ((AE_INFO, Status, "(%4.4s:%8.8s) while loading table", + Table->Signature.Ascii, Table->Pointer->OemTableId)); + + TablesFailed++; + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, + "Table [%4.4s:%8.8s] (id FF) - Table namespace load failed\n\n", + Table->Signature.Ascii, Table->Pointer->OemTableId)); + } + else + { + TablesLoaded++; + } + } + + if (!TablesFailed) + { + ACPI_INFO (( + "%u ACPI AML tables successfully acquired and loaded", + TablesLoaded)); + } + else + { + ACPI_ERROR ((AE_INFO, + "%u table load failures, %u successful", + TablesFailed, TablesLoaded)); + + /* Indicate at least one failure */ + + Status = AE_CTRL_TERMINATE; + } + +#ifdef ACPI_APPLICATION + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT, "\n")); +#endif + + +UnlockAndExit: + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiInstallTable + * + * PARAMETERS: Table - Pointer to the ACPI table to be installed. + * + * RETURN: Status + * + * DESCRIPTION: Dynamically install an ACPI table. + * Note: This function should only be invoked after + * AcpiInitializeTables() and before AcpiLoadTables(). + * + ******************************************************************************/ + +ACPI_STATUS ACPI_INIT_FUNCTION +AcpiInstallTable ( + ACPI_TABLE_HEADER *Table) +{ + ACPI_STATUS Status; + UINT32 TableIndex; + + + ACPI_FUNCTION_TRACE (AcpiInstallTable); + + + Status = AcpiTbInstallStandardTable (ACPI_PTR_TO_PHYSADDR (Table), + ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, Table, FALSE, FALSE, &TableIndex); + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL_INIT (AcpiInstallTable) + + +/******************************************************************************* + * + * FUNCTION: AcpiInstallPhysicalTable + * + * PARAMETERS: Address - Address of the ACPI table to be installed. + * + * RETURN: Status + * + * DESCRIPTION: Dynamically install an ACPI table. + * Note: This function should only be invoked after + * AcpiInitializeTables() and before AcpiLoadTables(). + * + ******************************************************************************/ + +ACPI_STATUS ACPI_INIT_FUNCTION +AcpiInstallPhysicalTable ( + ACPI_PHYSICAL_ADDRESS Address) +{ + ACPI_STATUS Status; + UINT32 TableIndex; + + + ACPI_FUNCTION_TRACE (AcpiInstallPhysicalTable); + + + Status = AcpiTbInstallStandardTable (Address, + ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, NULL, FALSE, FALSE, &TableIndex); + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL_INIT (AcpiInstallPhysicalTable) + + +/******************************************************************************* + * + * FUNCTION: AcpiLoadTable + * + * PARAMETERS: Table - Pointer to a buffer containing the ACPI + * table to be loaded. + * TableIdx - Pointer to a UINT32 for storing the table + * index, might be NULL + * + * RETURN: Status + * + * DESCRIPTION: Dynamically load an ACPI table from the caller's buffer. Must + * be a valid ACPI table with a valid ACPI table header. + * Note1: Mainly intended to support hotplug addition of SSDTs. + * Note2: Does not copy the incoming table. User is responsible + * to ensure that the table is not deleted or unmapped. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiLoadTable ( + ACPI_TABLE_HEADER *Table, + UINT32 *TableIdx) +{ + ACPI_STATUS Status; + UINT32 TableIndex; + + + ACPI_FUNCTION_TRACE (AcpiLoadTable); + + + /* Parameter validation */ + + if (!Table) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* Install the table and load it into the namespace */ + + ACPI_INFO (("Host-directed Dynamic ACPI Table Load:")); + Status = AcpiTbInstallAndLoadTable (ACPI_PTR_TO_PHYSADDR (Table), + ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, Table, FALSE, &TableIndex); + if (TableIdx) + { + *TableIdx = TableIndex; + } + + if (ACPI_SUCCESS (Status)) + { + /* Complete the initialization/resolution of new objects */ + + AcpiNsInitializeObjects (); + } + + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiLoadTable) + + +/******************************************************************************* + * + * FUNCTION: AcpiUnloadParentTable + * + * PARAMETERS: Object - Handle to any namespace object owned by + * the table to be unloaded + * + * RETURN: Status + * + * DESCRIPTION: Via any namespace object within an SSDT or OEMx table, unloads + * the table and deletes all namespace objects associated with + * that table. Unloading of the DSDT is not allowed. + * Note: Mainly intended to support hotplug removal of SSDTs. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUnloadParentTable ( + ACPI_HANDLE Object) +{ + ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Object); + ACPI_STATUS Status = AE_NOT_EXIST; + ACPI_OWNER_ID OwnerId; + UINT32 i; + + + ACPI_FUNCTION_TRACE (AcpiUnloadParentTable); + + + /* Parameter validation */ + + if (!Object) + { + return_ACPI_STATUS (AE_BAD_PARAMETER); + } + + /* + * The node OwnerId is currently the same as the parent table ID. + * However, this could change in the future. + */ + OwnerId = Node->OwnerId; + if (!OwnerId) + { + /* OwnerId==0 means DSDT is the owner. DSDT cannot be unloaded */ + + return_ACPI_STATUS (AE_TYPE); + } + + /* Must acquire the table lock during this operation */ + + Status = AcpiUtAcquireMutex (ACPI_MTX_TABLES); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Find the table in the global table list */ + + for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++) + { + if (OwnerId != AcpiGbl_RootTableList.Tables[i].OwnerId) + { + continue; + } + + /* + * Allow unload of SSDT and OEMx tables only. Do not allow unload + * of the DSDT. No other types of tables should get here, since + * only these types can contain AML and thus are the only types + * that can create namespace objects. + */ + if (ACPI_COMPARE_NAMESEG ( + AcpiGbl_RootTableList.Tables[i].Signature.Ascii, + ACPI_SIG_DSDT)) + { + Status = AE_TYPE; + break; + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + Status = AcpiTbUnloadTable (i); + (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); + break; + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiUnloadParentTable) + + +/******************************************************************************* + * + * FUNCTION: AcpiUnloadTable + * + * PARAMETERS: TableIndex - Index as returned by AcpiLoadTable + * + * RETURN: Status + * + * DESCRIPTION: Via the TableIndex representing an SSDT or OEMx table, unloads + * the table and deletes all namespace objects associated with + * that table. Unloading of the DSDT is not allowed. + * Note: Mainly intended to support hotplug removal of SSDTs. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUnloadTable ( + UINT32 TableIndex) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiUnloadTable); + + + if (TableIndex == 1) + { + /* TableIndex==1 means DSDT is the owner. DSDT cannot be unloaded */ + + return_ACPI_STATUS (AE_TYPE); + } + + Status = AcpiTbUnloadTable (TableIndex); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiUnloadTable) diff --git a/code/drivers/platform/acpi/third_party/acpica/components/tables/tbxfroot.c b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbxfroot.c new file mode 100644 index 0000000..89f9b77 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/tables/tbxfroot.c @@ -0,0 +1,307 @@ +/****************************************************************************** + * + * Module Name: tbxfroot - Find the root ACPI table (RSDT) + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "actables.h" + + +#define _COMPONENT ACPI_TABLES + ACPI_MODULE_NAME ("tbxfroot") + + +/******************************************************************************* + * + * FUNCTION: AcpiTbGetRsdpLength + * + * PARAMETERS: Rsdp - Pointer to RSDP + * + * RETURN: Table length + * + * DESCRIPTION: Get the length of the RSDP + * + ******************************************************************************/ + +UINT32 +AcpiTbGetRsdpLength ( + ACPI_TABLE_RSDP *Rsdp) +{ + + if (!ACPI_VALIDATE_RSDP_SIG (Rsdp->Signature)) + { + /* BAD Signature */ + + return (0); + } + + /* "Length" field is available if table version >= 2 */ + + if (Rsdp->Revision >= 2) + { + return (Rsdp->Length); + } + else + { + return (ACPI_RSDP_CHECKSUM_LENGTH); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTbValidateRsdp + * + * PARAMETERS: Rsdp - Pointer to unvalidated RSDP + * + * RETURN: Status + * + * DESCRIPTION: Validate the RSDP (ptr) + * + ******************************************************************************/ + +ACPI_STATUS +AcpiTbValidateRsdp ( + ACPI_TABLE_RSDP *Rsdp) +{ + + /* + * 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_VALIDATE_RSDP_SIG (Rsdp->Signature)) + { + /* Nope, BAD Signature */ + + return (AE_BAD_SIGNATURE); + } + + /* Check the standard checksum */ + + if (AcpiUtChecksum ((UINT8 *) Rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) + { + return (AE_BAD_CHECKSUM); + } + + /* Check extended checksum if table version >= 2 */ + + if ((Rsdp->Revision >= 2) && + (AcpiUtChecksum ((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 ACPI_INIT_FUNCTION +AcpiFindRootPointer ( + ACPI_PHYSICAL_ADDRESS *TableAddress) +{ + UINT8 *TablePtr; + UINT8 *MemRover; + UINT32 PhysicalAddress; + UINT32 EbdaWindowSize; + + + 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? */ + + /* + * Check that the EBDA pointer from memory is sane and does not point + * above valid low memory + */ + if (PhysicalAddress > 0x400 && + PhysicalAddress < 0xA0000) + { + /* + * Calculate the scan window size + * The EBDA is not guaranteed to be larger than a KiB and in case + * that it is smaller, the scanning function would leave the low + * memory and continue to the VGA range. + */ + EbdaWindowSize = ACPI_MIN(ACPI_EBDA_WINDOW_SIZE, + 0xA0000 - PhysicalAddress); + + /* + * 1b) Search EBDA paragraphs + */ + TablePtr = AcpiOsMapMemory ( + (ACPI_PHYSICAL_ADDRESS) PhysicalAddress, + EbdaWindowSize); + if (!TablePtr) + { + ACPI_ERROR ((AE_INFO, + "Could not map memory at 0x%8.8X for length %u", + PhysicalAddress, EbdaWindowSize)); + + return_ACPI_STATUS (AE_NO_MEMORY); + } + + MemRover = AcpiTbScanMemoryForRsdp ( + TablePtr, EbdaWindowSize); + AcpiOsUnmapMemory (TablePtr, EbdaWindowSize); + + if (MemRover) + { + /* Return the physical address */ + + PhysicalAddress += + (UINT32) ACPI_PTR_DIFF (MemRover, TablePtr); + + *TableAddress = (ACPI_PHYSICAL_ADDRESS) 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 = (ACPI_PHYSICAL_ADDRESS) PhysicalAddress; + return_ACPI_STATUS (AE_OK); + } + + /* A valid RSDP was not found */ + + ACPI_BIOS_ERROR ((AE_INFO, "A valid RSDP was not found")); + return_ACPI_STATUS (AE_NOT_FOUND); +} + +ACPI_EXPORT_SYMBOL_INIT (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 + * + ******************************************************************************/ + +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/code/drivers/platform/acpi/third_party/acpica/components/utilities/utaddress.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utaddress.c new file mode 100644 index 0000000..5f8cd2f --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utaddress.c @@ -0,0 +1,285 @@ +/****************************************************************************** + * + * Module Name: utaddress - OpRegion address range check + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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_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; + + RangeInfo->Next = AcpiGbl_AddressRangeList[SpaceId]; + AcpiGbl_AddressRangeList[SpaceId] = RangeInfo; + + ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, + "\nAdded [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n", + AcpiUtGetNodeName (RangeInfo->RegionNode), + ACPI_FORMAT_UINT64 (Address), + ACPI_FORMAT_UINT64 (RangeInfo->EndAddress))); + + 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%8.8X%8.8X-0x%8.8X%8.8X\n", + AcpiUtGetNodeName (RangeInfo->RegionNode), + ACPI_FORMAT_UINT64 (RangeInfo->StartAddress), + ACPI_FORMAT_UINT64 (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 + * address range. There are 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 = AcpiNsGetNormalizedPathname (RangeInfo->RegionNode, TRUE); + + ACPI_WARNING ((AE_INFO, + "%s range 0x%8.8X%8.8X-0x%8.8X%8.8X conflicts with OpRegion 0x%8.8X%8.8X-0x%8.8X%8.8X (%s)", + AcpiUtGetRegionName (SpaceId), + ACPI_FORMAT_UINT64 (Address), + ACPI_FORMAT_UINT64 (EndAddress), + ACPI_FORMAT_UINT64 (RangeInfo->StartAddress), + ACPI_FORMAT_UINT64 (RangeInfo->EndAddress), + Pathname)); + 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/code/drivers/platform/acpi/third_party/acpica/components/utilities/utalloc.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utalloc.c new file mode 100644 index 0000000..5ab3c3e --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utalloc.c @@ -0,0 +1,379 @@ +/****************************************************************************** + * + * Module Name: utalloc - local memory allocation routines + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acdebug.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utalloc") + + +#if !defined (USE_NATIVE_ALLOCATE_ZEROED) +/******************************************************************************* + * + * FUNCTION: AcpiOsAllocateZeroed + * + * PARAMETERS: Size - Size of the allocation + * + * RETURN: Address of the allocated memory on success, NULL on failure. + * + * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory. + * This is the default implementation. Can be overridden via the + * USE_NATIVE_ALLOCATE_ZEROED flag. + * + ******************************************************************************/ + +void * +AcpiOsAllocateZeroed ( + ACPI_SIZE Size) +{ + void *Allocation; + + + ACPI_FUNCTION_ENTRY (); + + + Allocation = AcpiOsAllocate (Size); + if (Allocation) + { + /* Clear the memory block */ + + memset (Allocation, 0, Size); + } + + return (Allocation); +} + +#endif /* !USE_NATIVE_ALLOCATE_ZEROED */ + + +/******************************************************************************* + * + * 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_ASL_COMPILER + /* + * For use with the ASL-/ASL+ option. This cache keeps track of regular + * 0xA9 0x01 comments. + */ + Status = AcpiOsCreateCache ("Acpi-Comment", sizeof (ACPI_COMMENT_NODE), + ACPI_MAX_COMMENT_CACHE_DEPTH, &AcpiGbl_RegCommentCache); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* + * This cache keeps track of the starting addresses of where the comments + * lie. This helps prevent duplication of comments. + */ + Status = AcpiOsCreateCache ("Acpi-Comment-Addr", sizeof (ACPI_COMMENT_ADDR_NODE), + ACPI_MAX_COMMENT_CACHE_DEPTH, &AcpiGbl_CommentAddrCache); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* + * This cache will be used for nodes that represent files. + */ + Status = AcpiOsCreateCache ("Acpi-File", sizeof (ACPI_FILE_NODE), + ACPI_MAX_COMMENT_CACHE_DEPTH, &AcpiGbl_FileCache); + if (ACPI_FAILURE (Status)) + { + return (Status); + } +#endif + + +#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) + { + 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_ASL_COMPILER + (void) AcpiOsDeleteCache (AcpiGbl_RegCommentCache); + AcpiGbl_RegCommentCache = NULL; + + (void) AcpiOsDeleteCache (AcpiGbl_CommentAddrCache); + AcpiGbl_CommentAddrCache = NULL; + + (void) AcpiOsDeleteCache (AcpiGbl_FileCache); + AcpiGbl_FileCache = NULL; +#endif + +#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. We directectly call AcpiOsAllocate here to + * purposefully bypass the (optionally enabled) internal allocation + * tracking mechanism since we only want to track internal + * allocations. Note: The caller should use AcpiOsFree to free this + * buffer created via ACPI_ALLOCATE_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 */ + + memset (Buffer->Pointer, 0, RequiredLength); + return (AE_OK); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utascii.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utascii.c new file mode 100644 index 0000000..8e60ba0 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utascii.c @@ -0,0 +1,131 @@ +/****************************************************************************** + * + * Module Name: utascii - Utility ascii functions + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValidNameseg + * + * PARAMETERS: Name - The name or table signature to be examined. + * Four characters, does not have to be a + * NULL terminated string. + * + * RETURN: TRUE if signature is has 4 valid ACPI characters + * + * DESCRIPTION: Validate an ACPI table signature. + * + ******************************************************************************/ + +BOOLEAN +AcpiUtValidNameseg ( + char *Name) +{ + UINT32 i; + + + /* Validate each character in the signature */ + + for (i = 0; i < ACPI_NAMESEG_SIZE; i++) + { + if (!AcpiUtValidNameChar (Name[i], i)) + { + return (FALSE); + } + } + + return (TRUE); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtValidNameChar + * + * 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 +AcpiUtValidNameChar ( + 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: AcpiUtCheckAndRepairAscii + * + * 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 . + * + ******************************************************************************/ + +void +AcpiUtCheckAndRepairAscii ( + 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/code/drivers/platform/acpi/third_party/acpica/components/utilities/utbuffer.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utbuffer.c new file mode 100644 index 0000000..03bb31d --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utbuffer.c @@ -0,0 +1,340 @@ +/****************************************************************************** + * + * Module Name: utbuffer - Buffer dump routines + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utbuffer") + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDumpBuffer + * + * PARAMETERS: Buffer - Buffer to dump + * Count - Amount to dump, in bytes + * Display - BYTE, WORD, DWORD, or QWORD display: + * DB_BYTE_DISPLAY + * DB_WORD_DISPLAY + * DB_DWORD_DISPLAY + * DB_QWORD_DISPLAY + * BaseOffset - Beginning buffer offset (display only) + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii. + * + ******************************************************************************/ + +void +AcpiUtDumpBuffer ( + UINT8 *Buffer, + UINT32 Count, + UINT32 Display, + UINT32 BaseOffset) +{ + UINT32 i = 0; + UINT32 j; + UINT32 Temp32; + UINT8 BufChar; + UINT32 DisplayDataOnly = Display & DB_DISPLAY_DATA_ONLY; + + + Display &= ~DB_DISPLAY_DATA_ONLY; + 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 */ + + if (!DisplayDataOnly) + { + AcpiOsPrintf ("%8.4X: ", (BaseOffset + 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) + */ + if (!DisplayDataOnly) + { + AcpiOsPrintf (" "); + for (j = 0; j < 16; j++) + { + if (i + j >= Count) + { + AcpiOsPrintf ("\n"); + return; + } + + /* + * Add comment characters so rest of line is ignored when + * compiled + */ + if (j == 0) + { + AcpiOsPrintf ("// "); + } + + BufChar = Buffer[(ACPI_SIZE) i + j]; + if (isprint (BufChar)) + { + AcpiOsPrintf ("%c", BufChar); + } + else + { + AcpiOsPrintf ("."); + } + } + + /* Done with that line. */ + + AcpiOsPrintf ("\n"); + } + i += 16; + } + + return; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDebugDumpBuffer + * + * PARAMETERS: Buffer - Buffer to dump + * Count - Amount to dump, in bytes + * Display - BYTE, WORD, DWORD, or QWORD display: + * DB_BYTE_DISPLAY + * DB_WORD_DISPLAY + * DB_DWORD_DISPLAY + * DB_QWORD_DISPLAY + * ComponentID - Caller's component ID + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii. + * + ******************************************************************************/ + +void +AcpiUtDebugDumpBuffer ( + UINT8 *Buffer, + UINT32 Count, + UINT32 Display, + UINT32 ComponentId) +{ + + /* Only dump the buffer if tracing is enabled */ + + if (!((ACPI_LV_TABLES & AcpiDbgLevel) && + (ComponentId & AcpiDbgLayer))) + { + return; + } + + AcpiUtDumpBuffer (Buffer, Count, Display, 0); +} + + +#ifdef ACPI_APPLICATION +/******************************************************************************* + * + * FUNCTION: AcpiUtDumpBufferToFile + * + * PARAMETERS: File - File descriptor + * Buffer - Buffer to dump + * Count - Amount to dump, in bytes + * Display - BYTE, WORD, DWORD, or QWORD display: + * DB_BYTE_DISPLAY + * DB_WORD_DISPLAY + * DB_DWORD_DISPLAY + * DB_QWORD_DISPLAY + * BaseOffset - Beginning buffer offset (display only) + * + * RETURN: None + * + * DESCRIPTION: Generic dump buffer in both hex and ascii to a file. + * + ******************************************************************************/ + +void +AcpiUtDumpBufferToFile ( + ACPI_FILE File, + UINT8 *Buffer, + UINT32 Count, + UINT32 Display, + UINT32 BaseOffset) +{ + UINT32 i = 0; + UINT32 j; + UINT32 Temp32; + UINT8 BufChar; + + + if (!Buffer) + { + fprintf (File, "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 */ + + fprintf (File, "%8.4X: ", (BaseOffset + i)); + + /* Print 16 hex chars */ + + for (j = 0; j < 16;) + { + if (i + j >= Count) + { + /* Dump fill spaces */ + + fprintf (File, "%*s", ((Display * 2) + 1), " "); + j += Display; + continue; + } + + switch (Display) + { + case DB_BYTE_DISPLAY: + default: /* Default is BYTE display */ + + fprintf (File, "%02X ", Buffer[(ACPI_SIZE) i + j]); + break; + + case DB_WORD_DISPLAY: + + ACPI_MOVE_16_TO_32 (&Temp32, &Buffer[(ACPI_SIZE) i + j]); + fprintf (File, "%04X ", Temp32); + break; + + case DB_DWORD_DISPLAY: + + ACPI_MOVE_32_TO_32 (&Temp32, &Buffer[(ACPI_SIZE) i + j]); + fprintf (File, "%08X ", Temp32); + break; + + case DB_QWORD_DISPLAY: + + ACPI_MOVE_32_TO_32 (&Temp32, &Buffer[(ACPI_SIZE) i + j]); + fprintf (File, "%08X", Temp32); + + ACPI_MOVE_32_TO_32 (&Temp32, &Buffer[(ACPI_SIZE) i + j + 4]); + fprintf (File, "%08X ", Temp32); + break; + } + + j += Display; + } + + /* + * Print the ASCII equivalent characters but watch out for the bad + * unprintable ones (printable chars are 0x20 through 0x7E) + */ + fprintf (File, " "); + for (j = 0; j < 16; j++) + { + if (i + j >= Count) + { + fprintf (File, "\n"); + return; + } + + BufChar = Buffer[(ACPI_SIZE) i + j]; + if (isprint (BufChar)) + { + fprintf (File, "%c", BufChar); + } + else + { + fprintf (File, "."); + } + } + + /* Done with that line. */ + + fprintf (File, "\n"); + i += 16; + } + + return; +} +#endif diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utcache.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utcache.c new file mode 100644 index 0000000..a10f705 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utcache.c @@ -0,0 +1,324 @@ +/****************************************************************************** + * + * Module Name: utcache - local cache allocation routines + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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) + { + 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 */ + + memset (Cache, 0, sizeof (ACPI_MEMORY_LIST)); + 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) +{ + void *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_GET_DESCRIPTOR_PTR (Cache->ListHead); + 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 */ + + 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_SET_DESCRIPTOR_PTR (Object, 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_TRACE (OsAcquireObject); + + + if (!Cache) + { + return_PTR (NULL); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (Status)) + { + return_PTR (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_GET_DESCRIPTOR_PTR (Object); + + Cache->CurrentDepth--; + + ACPI_MEM_TRACKING (Cache->Hits++); + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_EXEC, + "%s: Object %p from %s cache\n", + ACPI_GET_FUNCTION_NAME, Object, Cache->ListName)); + + Status = AcpiUtReleaseMutex (ACPI_MTX_CACHES); + if (ACPI_FAILURE (Status)) + { + return_PTR (NULL); + } + + /* Clear (zero) the previously used Object */ + + memset (Object, 0, Cache->ObjectSize); + } + else + { + /* The cache is empty, create a new object */ + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS + ACPI_MEM_TRACKING (Cache->TotalAllocated++); + + 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_PTR (NULL); + } + + Object = ACPI_ALLOCATE_ZEROED (Cache->ObjectSize); + if (!Object) + { + return_PTR (NULL); + } + } + + return_PTR (Object); +} +#endif /* ACPI_USE_LOCAL_CACHE */ diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utcksum.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utcksum.c new file mode 100644 index 0000000..ef8893f --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utcksum.c @@ -0,0 +1,197 @@ +/****************************************************************************** + * + * Module Name: utcksum - Support generating table checksums + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acdisasm.h" +#include "acutils.h" + + +/* This module used for application-level code only */ + +#define _COMPONENT ACPI_CA_DISASSEMBLER + ACPI_MODULE_NAME ("utcksum") + + +/******************************************************************************* + * + * FUNCTION: AcpiUtVerifyChecksum + * + * 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. + * Note: We don't have to check for a CDAT here, since CDAT is + * not in the RSDT/XSDT, and the CDAT table is never installed + * via ACPICA. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtVerifyChecksum ( + ACPI_TABLE_HEADER *Table, + UINT32 Length) +{ + UINT8 Checksum; + + + /* + * FACS/S3PT: + * They are the odd tables, have no standard ACPI header and no checksum + */ + if (ACPI_COMPARE_NAMESEG (Table->Signature, ACPI_SIG_S3PT) || + ACPI_COMPARE_NAMESEG (Table->Signature, ACPI_SIG_FACS)) + { + return (AE_OK); + } + + /* Compute the checksum on the table */ + + Length = Table->Length; + Checksum = AcpiUtGenerateChecksum (ACPI_CAST_PTR (UINT8, Table), Length, Table->Checksum); + + /* Computed checksum matches table? */ + + if (Checksum != Table->Checksum) + { + ACPI_BIOS_WARNING ((AE_INFO, + "Incorrect checksum in table [%4.4s] - 0x%2.2X, " + "should be 0x%2.2X", + Table->Signature, Table->Checksum, + Checksum)); + +#if (ACPI_CHECKSUM_ABORT) + return (AE_BAD_CHECKSUM); +#endif + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtVerifyCdatChecksum + * + * PARAMETERS: Table - CDAT ACPI table to verify + * Length - Length of entire table + * + * RETURN: Status + * + * DESCRIPTION: Verifies that the CDAT table checksums to zero. Optionally + * returns an exception on bad checksum. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtVerifyCdatChecksum ( + ACPI_TABLE_CDAT *CdatTable, + UINT32 Length) +{ + UINT8 Checksum; + + + /* Compute the checksum on the table */ + + Checksum = AcpiUtGenerateChecksum (ACPI_CAST_PTR (UINT8, CdatTable), + CdatTable->Length, CdatTable->Checksum); + + /* Computed checksum matches table? */ + + if (Checksum != CdatTable->Checksum) + { + ACPI_BIOS_WARNING ((AE_INFO, + "Incorrect checksum in table [%4.4s] - 0x%2.2X, " + "should be 0x%2.2X", + AcpiGbl_CDAT, CdatTable->Checksum, Checksum)); + +#if (ACPI_CHECKSUM_ABORT) + return (AE_BAD_CHECKSUM); +#endif + } + + CdatTable->Checksum = Checksum; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGenerateChecksum + * + * 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 +AcpiUtGenerateChecksum ( + void *Table, + UINT32 Length, + UINT8 OriginalChecksum) +{ + UINT8 Checksum; + + + /* Sum the entire table as-is */ + + Checksum = AcpiUtChecksum ((UINT8 *) Table, Length); + + /* Subtract off the existing checksum value in the table */ + + Checksum = (UINT8) (Checksum - OriginalChecksum); + + /* Compute and return the final checksum */ + + Checksum = (UINT8) (0 - Checksum); + return (Checksum); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtChecksum + * + * 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 +AcpiUtChecksum ( + UINT8 *Buffer, + UINT32 Length) +{ + UINT8 Sum = 0; + UINT8 *End = Buffer + Length; + + + while (Buffer < End) + { + Sum = (UINT8) (Sum + *(Buffer++)); + } + + return (Sum); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utclib.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utclib.c new file mode 100644 index 0000000..3566a72 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utclib.c @@ -0,0 +1,1030 @@ +/****************************************************************************** + * + * Module Name: utclib - ACPICA implementations of C library functions + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define ACPI_CLIBRARY +#include "acpi.h" +#include "accommon.h" + +/* + * This module contains implementations of the standard C library functions + * that are required by the ACPICA code at both application level and kernel + * level. + * + * The module is an optional feature that can be used if a local/system + * C library is not available. Some operating system kernels may not have + * an internal C library. + * + * In general, these functions are less efficient than an inline or assembly + * code implementation. + * + * These C functions and the associated prototypes are enabled by default + * unless the ACPI_USE_SYSTEM_CLIBRARY symbol is defined. This is usually + * automatically defined for the ACPICA applications such as iASL and + * AcpiExec, so that these user-level applications use the local C library + * instead of the functions in this module. + */ + +/******************************************************************************* + * + * Functions implemented in this module: + * + * FUNCTION: memcmp + * FUNCTION: memcpy + * FUNCTION: memset + * FUNCTION: strlen + * FUNCTION: strcpy + * FUNCTION: strncpy + * FUNCTION: strcmp + * FUNCTION: strchr + * FUNCTION: strncmp + * FUNCTION: strcat + * FUNCTION: strncat + * FUNCTION: strstr + * FUNCTION: strtoul + * FUNCTION: toupper + * FUNCTION: tolower + * FUNCTION: is* functions + * + ******************************************************************************/ + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utclib") + + +#ifndef ACPI_USE_SYSTEM_CLIBRARY /* Entire module */ + + +/******************************************************************************* + * + * FUNCTION: 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 +memcmp ( + void *VBuffer1, + void *VBuffer2, + ACPI_SIZE Count) +{ + char *Buffer1 = (char *) VBuffer1; + char *Buffer2 = (char *) VBuffer2; + + + for ( ; Count-- && (*Buffer1 == *Buffer2); Buffer1++, Buffer2++) + { + } + + return ((Count == ACPI_SIZE_MAX) ? 0 : ((unsigned char) *Buffer1 - + (unsigned char) *Buffer2)); +} + + +/******************************************************************************* + * + * FUNCTION: memmove + * + * 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 with respect to the overlapping + * + ******************************************************************************/ + +void * +memmove ( + void *Dest, + const void *Src, + ACPI_SIZE Count) +{ + char *New = (char *) Dest; + char *Old = (char *) Src; + + + if (Old > New) + { + /* Copy from the beginning */ + + while (Count) + { + *New = *Old; + New++; + Old++; + Count--; + } + } + else if (Old < New) + { + /* Copy from the end */ + + New = New + Count - 1; + Old = Old + Count - 1; + while (Count) + { + *New = *Old; + New--; + Old--; + Count--; + } + } + + return (Dest); +} + + +/******************************************************************************* + * + * FUNCTION: 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 * +memcpy ( + 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: 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 * +memset ( + void *Dest, + int Value, + ACPI_SIZE Count) +{ + char *New = (char *) Dest; + + + while (Count) + { + *New = (char) Value; + New++; + Count--; + } + + return (Dest); +} + + +/******************************************************************************* + * + * FUNCTION: strlen + * + * PARAMETERS: String - Null terminated string + * + * RETURN: Length + * + * DESCRIPTION: Returns the length of the input string + * + ******************************************************************************/ + + +ACPI_SIZE +strlen ( + const char *String) +{ + UINT32 Length = 0; + + + /* Count the string until a null is encountered */ + + while (*String) + { + Length++; + String++; + } + + return (Length); +} + + +/******************************************************************************* + * + * FUNCTION: strpbrk + * + * PARAMETERS: String - Null terminated string + * Delimiters - Delimiters to match + * + * RETURN: The first occurrence in the string of any of the bytes in the + * delimiters + * + * DESCRIPTION: Search a string for any of a set of the delimiters + * + ******************************************************************************/ + +char * +strpbrk ( + const char *String, + const char *Delimiters) +{ + const char *Delimiter; + + + for ( ; *String != '\0'; ++String) + { + for (Delimiter = Delimiters; *Delimiter != '\0'; Delimiter++) + { + if (*String == *Delimiter) + { + return (ACPI_CAST_PTR (char, String)); + } + } + } + + return (NULL); +} + + +/******************************************************************************* + * + * FUNCTION: strtok + * + * PARAMETERS: String - Null terminated string + * Delimiters - Delimiters to match + * + * RETURN: Pointer to the next token + * + * DESCRIPTION: Split string into tokens + * + ******************************************************************************/ + +char* +strtok ( + char *String, + const char *Delimiters) +{ + char *Begin = String; + static char *SavedPtr; + + + if (Begin == NULL) + { + if (SavedPtr == NULL) + { + return (NULL); + } + Begin = SavedPtr; + } + + SavedPtr = strpbrk (Begin, Delimiters); + while (SavedPtr == Begin) + { + *Begin++ = '\0'; + SavedPtr = strpbrk (Begin, Delimiters); + } + + if (SavedPtr) + { + *SavedPtr++ = '\0'; + return (Begin); + } + else + { + return (NULL); + } +} + + +/******************************************************************************* + * + * FUNCTION: strcpy + * + * PARAMETERS: DstString - Target of the copy + * SrcString - The source string to copy + * + * RETURN: DstString + * + * DESCRIPTION: Copy a null terminated string + * + ******************************************************************************/ + +char * +strcpy ( + 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: 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 * +strncpy ( + 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: 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 +strcmp ( + const char *String1, + const char *String2) +{ + + + for ( ; (*String1 == *String2); String2++) + { + if (!*String1++) + { + return (0); + } + } + + return ((unsigned char) *String1 - (unsigned char) *String2); +} + + +/******************************************************************************* + * + * FUNCTION: 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 * +strchr ( + const char *String, + int ch) +{ + + + for ( ; (*String); String++) + { + if ((*String) == (char) ch) + { + return ((char *) String); + } + } + + return (NULL); +} + + +/******************************************************************************* + * + * FUNCTION: 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 +strncmp ( + 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: 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 * +strcat ( + 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: 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 * +strncat ( + 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: 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 * +strstr ( + char *String1, + char *String2) +{ + ACPI_SIZE Length; + + + Length = strlen (String2); + if (!Length) + { + return (String1); + } + + while (strlen (String1) >= Length) + { + if (memcmp (String1, String2, Length) == 0) + { + return (String1); + } + String1++; + } + + return (NULL); +} + + +/******************************************************************************* + * + * FUNCTION: strtoul + * + * PARAMETERS: String - Null terminated string + * Terminator - 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 strtoul64 for 64-bit integers. + * + ******************************************************************************/ + +UINT32 +strtoul ( + 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 (isspace (*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 = ACPI_SIGN_NEGATIVE; + ++String; + } + else if (*String == '+') + { + ++String; + sign = ACPI_SIGN_POSITIVE; + } + else + { + sign = ACPI_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 (*(++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' && + tolower (*(++String)) == 'x') + { + String++; + } + + /* + * Main loop: convert the string to an unsigned long: + */ + while (*String) + { + if (isdigit (*String)) + { + index = (UINT32) ((UINT8) *String - '0'); + } + else + { + index = (UINT32) toupper (*String); + if (isupper (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 == ACPI_SIGN_NEGATIVE) + { + ReturnValue = (ACPI_UINT32_MAX - ReturnValue) + 1; + } + + return (ReturnValue); +} + + +/******************************************************************************* + * + * FUNCTION: toupper + * + * PARAMETERS: c - Character to convert + * + * RETURN: Converted character as an int + * + * DESCRIPTION: Convert character to uppercase + * + ******************************************************************************/ + +int +toupper ( + int c) +{ + + return (islower(c) ? ((c)-0x20) : (c)); +} + + +/******************************************************************************* + * + * FUNCTION: tolower + * + * PARAMETERS: c - Character to convert + * + * RETURN: Converted character as an int + * + * DESCRIPTION: Convert character to lowercase + * + ******************************************************************************/ + +int +tolower ( + int c) +{ + + return (isupper(c) ? ((c)+0x20) : (c)); +} + + +/******************************************************************************* + * + * FUNCTION: is* function array + * + * DESCRIPTION: is* functions use the ctype table below + * + ******************************************************************************/ + +const UINT8 AcpiGbl_Ctypes[257] = { + _ACPI_CN, /* 0x00 0 NUL */ + _ACPI_CN, /* 0x01 1 SOH */ + _ACPI_CN, /* 0x02 2 STX */ + _ACPI_CN, /* 0x03 3 ETX */ + _ACPI_CN, /* 0x04 4 EOT */ + _ACPI_CN, /* 0x05 5 ENQ */ + _ACPI_CN, /* 0x06 6 ACK */ + _ACPI_CN, /* 0x07 7 BEL */ + _ACPI_CN, /* 0x08 8 BS */ + _ACPI_CN|_ACPI_SP, /* 0x09 9 TAB */ + _ACPI_CN|_ACPI_SP, /* 0x0A 10 LF */ + _ACPI_CN|_ACPI_SP, /* 0x0B 11 VT */ + _ACPI_CN|_ACPI_SP, /* 0x0C 12 FF */ + _ACPI_CN|_ACPI_SP, /* 0x0D 13 CR */ + _ACPI_CN, /* 0x0E 14 SO */ + _ACPI_CN, /* 0x0F 15 SI */ + _ACPI_CN, /* 0x10 16 DLE */ + _ACPI_CN, /* 0x11 17 DC1 */ + _ACPI_CN, /* 0x12 18 DC2 */ + _ACPI_CN, /* 0x13 19 DC3 */ + _ACPI_CN, /* 0x14 20 DC4 */ + _ACPI_CN, /* 0x15 21 NAK */ + _ACPI_CN, /* 0x16 22 SYN */ + _ACPI_CN, /* 0x17 23 ETB */ + _ACPI_CN, /* 0x18 24 CAN */ + _ACPI_CN, /* 0x19 25 EM */ + _ACPI_CN, /* 0x1A 26 SUB */ + _ACPI_CN, /* 0x1B 27 ESC */ + _ACPI_CN, /* 0x1C 28 FS */ + _ACPI_CN, /* 0x1D 29 GS */ + _ACPI_CN, /* 0x1E 30 RS */ + _ACPI_CN, /* 0x1F 31 US */ + _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 DEL */ + + 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, /* 0xF0 to 0xFF */ + 0 /* 0x100 */ +}; + + +#endif /* ACPI_USE_SYSTEM_CLIBRARY */ diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utcopy.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utcopy.c new file mode 100644 index 0000000..49ca126 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utcopy.c @@ -0,0 +1,1055 @@ +/****************************************************************************** + * + * Module Name: utcopy - Internal to external object translation utilities + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 */ + + 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); + + 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); + + 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; + } + + 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; + } + + 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: + + /* An incoming reference is defined to be a namespace node */ + + InternalObject->Reference.Class = ACPI_REFCLASS_REFOF; + InternalObject->Reference.Object = 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); + } + + 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 */ + + 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 */ + + 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; + } + + /* + * Local/Arg/Debug references do not have a valid Object pointer + * that can be referenced + */ + if ((SourceDesc->Reference.Class != ACPI_REFCLASS_LOCAL) && + (SourceDesc->Reference.Class != ACPI_REFCLASS_ARG) && + (SourceDesc->Reference.Class != ACPI_REFCLASS_DEBUG)) + { + 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); + } + + /* Delete the allocated object if copy failed */ + + if (ACPI_FAILURE (Status)) + { + AcpiUtRemoveReference (*DestDesc); + } + + return_ACPI_STATUS (Status); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utdebug.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utdebug.c new file mode 100644 index 0000000..fc32792 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utdebug.c @@ -0,0 +1,705 @@ +/****************************************************************************** + * + * Module Name: utdebug - Debug print/trace routines + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#include "acpi.h" +#include "accommon.h" +#include "acinterp.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utdebug") + + +#ifdef ACPI_DEBUG_OUTPUT + +static ACPI_THREAD_ID AcpiGbl_PreviousThreadId = (ACPI_THREAD_ID) 0xFFFFFFFF; +static const char *AcpiGbl_FunctionEntryPrefix = "----Entry"; +static const char *AcpiGbl_FunctionExitPrefix = "----Exit-"; + + +/******************************************************************************* + * + * FUNCTION: AcpiUtInitStackPtrTrace + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Save the current CPU stack pointer at subsystem startup + * + ******************************************************************************/ + +void +AcpiUtInitStackPtrTrace ( + void) +{ + ACPI_SIZE CurrentSp; + + +#pragma GCC diagnostic push +#if defined(__GNUC__) && __GNUC__ >= 12 +#pragma GCC diagnostic ignored "-Wdangling-pointer=" +#endif + AcpiGbl_EntryStackPointer = &CurrentSp; +#pragma GCC diagnostic pop +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtTrackStackPtr + * + * PARAMETERS: None + * + * RETURN: None + * + * DESCRIPTION: Save the current CPU stack pointer + * + ******************************************************************************/ + +void +AcpiUtTrackStackPtr ( + void) +{ + ACPI_SIZE CurrentSp; + + + if (&CurrentSp < AcpiGbl_LowestStackPointer) + { +#pragma GCC diagnostic push +#if defined(__GNUC__) && __GNUC__ >= 12 +#pragma GCC diagnostic ignored "-Wdangling-pointer=" +#endif + AcpiGbl_LowestStackPointer = &CurrentSp; +#pragma GCC diagnostic pop + } + + 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; +#ifdef ACPI_APPLICATION + int FillCount; +#endif + + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED (RequestedDebugLevel, ComponentId)) + { + return; + } + + /* + * Thread tracking and context switch notification + */ + ThreadId = AcpiOsGetThreadId (); + if (ThreadId != AcpiGbl_PreviousThreadId) + { + if (ACPI_LV_THREADS & AcpiDbgLevel) + { + AcpiOsPrintf ( + ACPI_MSG_DEBUG + "\n**** Context Switch from TID %u to TID %u ****\n\n", + (UINT32) AcpiGbl_PreviousThreadId, (UINT32) ThreadId); + } + + AcpiGbl_PreviousThreadId = ThreadId; + AcpiGbl_NestingLevel = 0; + } + + /* + * Display the module name, current line number, thread ID (if requested), + * current procedure nesting level, and the current procedure name + */ + AcpiOsPrintf (ACPI_MSG_DEBUG "%9s-%04d ", ModuleName, LineNumber); + +#ifdef ACPI_APPLICATION + /* + * For AcpiExec/iASL only, emit the thread ID and nesting level. + * Note: nesting level is really only useful during a single-thread + * execution. Otherwise, multiple threads will keep resetting the + * level. + */ + if (ACPI_LV_THREADS & AcpiDbgLevel) + { + AcpiOsPrintf ("[%u] ", (UINT32) ThreadId); + } + + FillCount = 48 - AcpiGbl_NestingLevel - + strlen (AcpiUtTrimFunctionName (FunctionName)); + if (FillCount < 0) + { + FillCount = 0; + } + + AcpiOsPrintf ("[%02d] %*s", + AcpiGbl_NestingLevel, AcpiGbl_NestingLevel + 1, " "); + AcpiOsPrintf ("%s%*s: ", + AcpiUtTrimFunctionName (FunctionName), FillCount, " "); + +#else + AcpiOsPrintf ("%-22.22s: ", AcpiUtTrimFunctionName (FunctionName)); +#endif + + 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; + + + /* Check if debug output enabled */ + + if (!ACPI_IS_DEBUG_ENABLED (RequestedDebugLevel, ComponentId)) + { + 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 (); + + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId)) + { + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s\n", AcpiGbl_FunctionEntryPrefix); + } +} + +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, + const void *Pointer) +{ + + AcpiGbl_NestingLevel++; + AcpiUtTrackStackPtr (); + + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId)) + { + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %p\n", AcpiGbl_FunctionEntryPrefix, 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, + const char *String) +{ + + AcpiGbl_NestingLevel++; + AcpiUtTrackStackPtr (); + + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId)) + { + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %s\n", AcpiGbl_FunctionEntryPrefix, 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 (); + + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId)) + { + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %08X\n", AcpiGbl_FunctionEntryPrefix, 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) +{ + + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId)) + { + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s\n", AcpiGbl_FunctionExitPrefix); + } + + if (AcpiGbl_NestingLevel) + { + 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) +{ + + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId)) + { + if (ACPI_SUCCESS (Status)) + { + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %s\n", AcpiGbl_FunctionExitPrefix, + AcpiFormatException (Status)); + } + else + { + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s ****Exception****: %s\n", AcpiGbl_FunctionExitPrefix, + AcpiFormatException (Status)); + } + } + + if (AcpiGbl_NestingLevel) + { + 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) +{ + + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId)) + { + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %8.8X%8.8X\n", AcpiGbl_FunctionExitPrefix, + ACPI_FORMAT_UINT64 (Value)); + } + + if (AcpiGbl_NestingLevel) + { + 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) +{ + + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId)) + { + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %p\n", AcpiGbl_FunctionExitPrefix, Ptr); + } + + if (AcpiGbl_NestingLevel) + { + AcpiGbl_NestingLevel--; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrExit + * + * PARAMETERS: LineNumber - Caller's line number + * FunctionName - Caller's procedure name + * ModuleName - Caller's module name + * ComponentId - Caller's component ID + * String - String to display + * + * RETURN: None + * + * DESCRIPTION: Function exit trace. Prints only if TRACE_FUNCTIONS bit is + * set in DebugLevel. Prints exit value also. + * + ******************************************************************************/ + +void +AcpiUtStrExit ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + const char *String) +{ + + /* Check if enabled up-front for performance */ + + if (ACPI_IS_DEBUG_ENABLED (ACPI_LV_FUNCTIONS, ComponentId)) + { + AcpiDebugPrint (ACPI_LV_FUNCTIONS, + LineNumber, FunctionName, ModuleName, ComponentId, + "%s %s\n", AcpiGbl_FunctionExitPrefix, String); + } + + if (AcpiGbl_NestingLevel) + { + AcpiGbl_NestingLevel--; + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiTracePoint + * + * PARAMETERS: Type - Trace event type + * Begin - TRUE if before execution + * Aml - Executed AML address + * Pathname - Object path + * Pointer - Pointer to the related object + * + * RETURN: None + * + * DESCRIPTION: Interpreter execution trace. + * + ******************************************************************************/ + +void +AcpiTracePoint ( + ACPI_TRACE_EVENT_TYPE Type, + BOOLEAN Begin, + UINT8 *Aml, + char *Pathname) +{ + + ACPI_FUNCTION_ENTRY (); + + AcpiExTracePoint (Type, Begin, Aml, Pathname); + +#ifdef ACPI_USE_SYSTEM_TRACER + AcpiOsTracePoint (Type, Begin, Aml, Pathname); +#endif +} + +ACPI_EXPORT_SYMBOL (AcpiTracePoint) + + +#endif diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utdecode.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utdecode.c new file mode 100644 index 0000000..4767c24 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utdecode.c @@ -0,0 +1,663 @@ +/****************************************************************************** + * + * Module Name: utdecode - Utility decoding routines (value-to-string) + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" +#include "amlcode.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utdecode") + + +/* + * 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: 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", /* 0x00 */ + "SystemIO", /* 0x01 */ + "PCI_Config", /* 0x02 */ + "EmbeddedControl", /* 0x03 */ + "SMBus", /* 0x04 */ + "SystemCMOS", /* 0x05 */ + "PCIBARTarget", /* 0x06 */ + "IPMI", /* 0x07 */ + "GeneralPurposeIo", /* 0x08 */ + "GenericSerialBus", /* 0x09 */ + "PCC", /* 0x0A */ + "PlatformRtMechanism" /* 0x0B */ +}; + + +const 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 (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", +}; + + +const char * +AcpiUtGetEventName ( + UINT32 EventId) +{ + + if (EventId > ACPI_EVENT_MAX) + { + return ("InvalidEventID"); + } + + return (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" +}; + + +const char * +AcpiUtGetTypeName ( + ACPI_OBJECT_TYPE Type) +{ + + if (Type > ACPI_TYPE_INVALID) + { + return (AcpiGbl_BadType); + } + + return (AcpiGbl_NsTypeNames[Type]); +} + + +const char * +AcpiUtGetObjectTypeName ( + ACPI_OPERAND_OBJECT *ObjDesc) +{ + ACPI_FUNCTION_TRACE (UtGetObjectTypeName); + + + if (!ObjDesc) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Null Object Descriptor\n")); + return_STR ("[NULL Object Descriptor]"); + } + + /* These descriptor types share a common area */ + + if ((ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_OPERAND) && + (ACPI_GET_DESCRIPTOR_TYPE (ObjDesc) != ACPI_DESC_TYPE_NAMED)) + { + ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, + "Invalid object descriptor type: 0x%2.2X [%s] (%p)\n", + ACPI_GET_DESCRIPTOR_TYPE (ObjDesc), + AcpiUtGetDescriptorName (ObjDesc), ObjDesc)); + + return_STR ("Invalid object"); + } + + return_STR (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. + * + ******************************************************************************/ + +const char * +AcpiUtGetNodeName ( + void *Object) +{ + ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) Object; + + + /* Must return a string of exactly 4 characters == ACPI_NAMESEG_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 Object", + /* 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 */ "Tree Walk State", + /* 13 */ "Parse Tree Op", + /* 14 */ "Operand Object", + /* 15 */ "Namespace Node" +}; + + +const char * +AcpiUtGetDescriptorName ( + void *Object) +{ + + if (!Object) + { + return ("NULL OBJECT"); + } + + if (ACPI_GET_DESCRIPTOR_TYPE (Object) > ACPI_DESC_TYPE_MAX) + { + return ("Not a Descriptor"); + } + + return (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]); +} + + +/******************************************************************************* + * + * 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 const char *AcpiGbl_MutexNames[ACPI_NUM_MUTEX] = +{ + "ACPI_MTX_Interpreter", + "ACPI_MTX_Namespace", + "ACPI_MTX_Tables", + "ACPI_MTX_Events", + "ACPI_MTX_Caches", + "ACPI_MTX_Memory", +}; + +const char * +AcpiUtGetMutexName ( + UINT32 MutexId) +{ + + if (MutexId > ACPI_MAX_MUTEX) + { + return ("Invalid Mutex ID"); + } + + return (AcpiGbl_MutexNames[MutexId]); +} + + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +/* + * Strings and procedures used for debug only + */ + +/******************************************************************************* + * + * 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_GenericNotify[ACPI_GENERIC_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", + /* 0A */ "Reserved", + /* 0B */ "System Locality Update", + /* 0C */ "Reserved (was previously Shutdown Request)", /* Reserved in ACPI 6.0 */ + /* 0D */ "System Resource Affinity Update", + /* 0E */ "Heterogeneous Memory Attributes Update", /* ACPI 6.2 */ + /* 0F */ "Error Disconnect Recover" /* ACPI 6.3 */ +}; + +static const char *AcpiGbl_DeviceNotify[5] = +{ + /* 80 */ "Status Change", + /* 81 */ "Information Change", + /* 82 */ "Device-Specific Change", + /* 83 */ "Device-Specific Change", + /* 84 */ "Reserved" +}; + +static const char *AcpiGbl_ProcessorNotify[5] = +{ + /* 80 */ "Performance Capability Change", + /* 81 */ "C-State Change", + /* 82 */ "Throttling Capability Change", + /* 83 */ "Guaranteed Change", + /* 84 */ "Minimum Excursion" +}; + +static const char *AcpiGbl_ThermalNotify[5] = +{ + /* 80 */ "Thermal Status Change", + /* 81 */ "Thermal Trip Point Change", + /* 82 */ "Thermal Device List Change", + /* 83 */ "Thermal Relationship Change", + /* 84 */ "Reserved" +}; + + +const char * +AcpiUtGetNotifyName ( + UINT32 NotifyValue, + ACPI_OBJECT_TYPE Type) +{ + + /* 00 - 0F are "common to all object types" (from ACPI Spec) */ + + if (NotifyValue <= ACPI_GENERIC_NOTIFY_MAX) + { + return (AcpiGbl_GenericNotify[NotifyValue]); + } + + /* 10 - 7F are reserved */ + + if (NotifyValue <= ACPI_MAX_SYS_NOTIFY) + { + return ("Reserved"); + } + + /* 80 - 84 are per-object-type */ + + if (NotifyValue <= ACPI_SPECIFIC_NOTIFY_MAX) + { + switch (Type) + { + case ACPI_TYPE_ANY: + case ACPI_TYPE_DEVICE: + return (AcpiGbl_DeviceNotify [NotifyValue - 0x80]); + + case ACPI_TYPE_PROCESSOR: + return (AcpiGbl_ProcessorNotify [NotifyValue - 0x80]); + + case ACPI_TYPE_THERMAL: + return (AcpiGbl_ThermalNotify [NotifyValue - 0x80]); + + default: + return ("Target object type does not support notifies"); + } + } + + /* 84 - BF are device-specific */ + + if (NotifyValue <= ACPI_MAX_DEVICE_SPECIFIC_NOTIFY) + { + return ("Device-Specific"); + } + + /* C0 and above are hardware-specific */ + + return ("Hardware-Specific"); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetArgumentTypeName + * + * PARAMETERS: ArgType - an ARGP_* parser argument type + * + * RETURN: Decoded ARGP_* type + * + * DESCRIPTION: Decode an ARGP_* parser type, as defined in the amlcode.h file, + * and used in the acopcode.h file. For example, ARGP_TERMARG. + * Used for debug only. + * + ******************************************************************************/ + +static const char *AcpiGbl_ArgumentType[20] = +{ + /* 00 */ "Unknown ARGP", + /* 01 */ "ByteData", + /* 02 */ "ByteList", + /* 03 */ "CharList", + /* 04 */ "DataObject", + /* 05 */ "DataObjectList", + /* 06 */ "DWordData", + /* 07 */ "FieldList", + /* 08 */ "Name", + /* 09 */ "NameString", + /* 0A */ "ObjectList", + /* 0B */ "PackageLength", + /* 0C */ "SuperName", + /* 0D */ "Target", + /* 0E */ "TermArg", + /* 0F */ "TermList", + /* 10 */ "WordData", + /* 11 */ "QWordData", + /* 12 */ "SimpleName", + /* 13 */ "NameOrRef" +}; + +const char * +AcpiUtGetArgumentTypeName ( + UINT32 ArgType) +{ + + if (ArgType > ARGP_MAX) + { + return ("Unknown ARGP"); + } + + return (AcpiGbl_ArgumentType[ArgType]); +} + +#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/code/drivers/platform/acpi/third_party/acpica/components/utilities/utdelete.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utdelete.c new file mode 100644 index 0000000..243ee65 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utdelete.c @@ -0,0 +1,800 @@ +/******************************************************************************* + * + * Module Name: utdelete - object deletion and reference count utilities + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 *StartDesc; + 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); + } + + ACPI_FALLTHROUGH; + + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + + /* Walk the address 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 = ACPI_SEMAPHORE_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 = ACPI_SEMAPHORE_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; + } + + if (Object->Method.Node) + { + Object->Method.Node = 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; + StartDesc = NextDesc; + LastObjPtr = &HandlerDesc->AddressSpace.RegionList; + + /* Remove the region object from the handler list */ + + while (NextDesc) + { + if (NextDesc == Object) + { + *LastObjPtr = NextDesc->Region.Next; + break; + } + + /* Walk the linked list of handlers */ + + LastObjPtr = &NextDesc->Region.Next; + NextDesc = NextDesc->Region.Next; + + /* Prevent infinite loop if list is corrupted */ + + if (NextDesc == StartDesc) + { + ACPI_ERROR ((AE_INFO, + "Circular region list in address handler object %p", + HandlerDesc)); + return_VOID; + } + } + + 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); + } + if (Object->Field.InternalPccBuffer) + { + ACPI_FREE(Object->Field.InternalPccBuffer); + } + + 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; + + case ACPI_TYPE_LOCAL_ADDRESS_HANDLER: + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "***** Address handler %p\n", Object)); + + AcpiOsDeleteMutex (Object->AddressSpace.ContextMutex); + 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_RAW ((ACPI_DB_ALLOCATIONS, "%s: Deleting Object %p [%s]\n", + ACPI_GET_FUNCTION_NAME, 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_ENTRY (); + + + /* 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; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtUpdateRefCount + * + * PARAMETERS: Object - Object whose ref count is to be updated + * Action - What to do (REF_INCREMENT or REF_DECREMENT) + * + * RETURN: None. Sets new reference count within the object + * + * DESCRIPTION: Modify the reference count for an internal acpi object + * + ******************************************************************************/ + +static void +AcpiUtUpdateRefCount ( + ACPI_OPERAND_OBJECT *Object, + UINT32 Action) +{ + UINT16 OriginalCount; + UINT16 NewCount = 0; + ACPI_CPU_FLAGS LockFlags; + char *Message; + + + ACPI_FUNCTION_NAME (UtUpdateRefCount); + + + if (!Object) + { + return; + } + + /* + * Always get the reference count lock. Note: Interpreter and/or + * Namespace is not always locked when this function is called. + */ + LockFlags = AcpiOsAcquireLock (AcpiGbl_ReferenceCountLock); + OriginalCount = Object->Common.ReferenceCount; + + /* Perform the reference count action (increment, decrement) */ + + switch (Action) + { + case REF_INCREMENT: + + NewCount = OriginalCount + 1; + Object->Common.ReferenceCount = NewCount; + AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags); + + /* The current reference count should never be zero here */ + + if (!OriginalCount) + { + ACPI_WARNING ((AE_INFO, + "Obj %p, Reference Count was zero before increment\n", + Object)); + } + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, + "Obj %p Type %.2X [%s] Refs %.2X [Incremented]\n", + Object, Object->Common.Type, + AcpiUtGetObjectTypeName (Object), NewCount)); + Message = "Increment"; + break; + + case REF_DECREMENT: + + /* The current reference count must be non-zero */ + + if (OriginalCount) + { + NewCount = OriginalCount - 1; + Object->Common.ReferenceCount = NewCount; + } + + AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags); + + if (!OriginalCount) + { + ACPI_WARNING ((AE_INFO, + "Obj %p, Reference Count is already zero, cannot decrement\n", + Object)); + return; + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ALLOCATIONS, + "%s: Obj %p Type %.2X Refs %.2X [Decremented]\n", + ACPI_GET_FUNCTION_NAME, Object, Object->Common.Type, NewCount)); + + /* Actually delete the object on a reference count of zero */ + + if (NewCount == 0) + { + AcpiUtDeleteInternalObj (Object); + } + Message = "Decrement"; + break; + + default: + + AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags); + ACPI_ERROR ((AE_INFO, "Unknown Reference Count action (0x%X)", + Action)); + return; + } + + /* + * Sanity check the reference count, for debug purposes only. + * (A deleted object will have a huge reference count) + */ + if (NewCount > ACPI_MAX_REFERENCE_COUNT) + { + ACPI_WARNING ((AE_INFO, + "Large Reference Count (0x%X) in object %p, Type=0x%.2X Operation=%s", + NewCount, Object, Object->Common.Type, Message)); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtUpdateObjectReference + * + * PARAMETERS: Object - Increment or decrement the ref count for + * this object and all sub-objects + * Action - Either REF_INCREMENT or REF_DECREMENT + * + * RETURN: Status + * + * DESCRIPTION: Increment or decrement 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_OPERAND_OBJECT *PrevObject; + ACPI_GENERIC_STATE *State; + UINT32 i; + + + ACPI_FUNCTION_NAME (UtUpdateObjectReference); + + + 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 (AE_OK); + } + + /* + * All sub-objects must have their reference count updated + * 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) + * Two lists, system and device notify handlers. + */ + for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) + { + PrevObject = Object->CommonNotify.NotifyList[i]; + while (PrevObject) + { + if (PrevObject->Common.Type != ACPI_TYPE_LOCAL_NOTIFY) + { + break; + } + NextObject = PrevObject->Notify.Next[i]; + AcpiUtUpdateRefCount (PrevObject, Action); + PrevObject = NextObject; + } + } + 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++) + { + /* + * Null package elements are legal and can be simply + * ignored. + */ + NextObject = Object->Package.Elements[i]; + if (!NextObject) + { + continue; + } + + switch (NextObject->Common.Type) + { + case ACPI_TYPE_INTEGER: + case ACPI_TYPE_STRING: + case ACPI_TYPE_BUFFER: + /* + * For these very simple sub-objects, we can just + * update the reference count here and continue. + * Greatly increases performance of this operation. + */ + AcpiUtUpdateRefCount (NextObject, Action); + break; + + default: + /* + * For complex sub-objects, push them onto the stack + * for later processing (this eliminates recursion.) + */ + Status = AcpiUtCreateUpdateStateAndPush ( + NextObject, Action, &StateList); + if (ACPI_FAILURE (Status)) + { + goto ErrorExit; + } + break; + } + } + + NextObject = NULL; + break; + + case ACPI_TYPE_BUFFER_FIELD: + + NextObject = Object->BufferField.BufferObj; + 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_LOCAL_REGION_FIELD: + 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 (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 (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_NAME (UtAddReference); + + + /* Ensure that we have a valid object */ + + if (!AcpiUtValidInternalObject (Object)) + { + return; + } + + 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; +} + + +/******************************************************************************* + * + * 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_NAME (UtRemoveReference); + + + /* + * 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; + } + + /* Ensure that we have a valid object */ + + if (!AcpiUtValidInternalObject (Object)) + { + return; + } + + ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ALLOCATIONS, + "%s: Obj %p Current Refs=%X [To Be Decremented]\n", + ACPI_GET_FUNCTION_NAME, 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; +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/uterror.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/uterror.c new file mode 100644 index 0000000..bd12ef7 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/uterror.c @@ -0,0 +1,372 @@ +/******************************************************************************* + * + * Module Name: uterror - Various internal error/warning output functions + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("uterror") + + +/* + * This module contains internal error functions that may + * be configured out. + */ +#if !defined (ACPI_NO_ERROR_MESSAGES) + +/******************************************************************************* + * + * 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, + UINT16 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 "%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, + UINT16 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 "%s: ", Pathname); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + ACPI_MSG_SUFFIX; + va_end (ArgList); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtPredefinedBiosError + * + * 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: BIOS error message for predefined names. 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 +AcpiUtPredefinedBiosError ( + const char *ModuleName, + UINT32 LineNumber, + char *Pathname, + UINT16 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_BIOS_ERROR "%s: ", Pathname); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + ACPI_MSG_SUFFIX; + va_end (ArgList); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtPrefixedNamespaceError + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * PrefixScope - Scope/Path that prefixes the internal path + * InternalPath - Name or path of the namespace node + * LookupStatus - Exception code from NS lookup + * + * RETURN: None + * + * DESCRIPTION: Print error message with the full pathname constructed this way: + * + * PrefixScopeNodeFullPath.ExternalizedInternalPath + * + * NOTE: 10/2017: Treat the major NsLookup errors as firmware errors + * + ******************************************************************************/ + +void +AcpiUtPrefixedNamespaceError ( + const char *ModuleName, + UINT32 LineNumber, + ACPI_GENERIC_STATE *PrefixScope, + const char *InternalPath, + ACPI_STATUS LookupStatus) +{ + char *FullPath; + const char *Message; + + + /* + * Main cases: + * 1) Object creation, object must not already exist + * 2) Object lookup, object must exist + */ + switch (LookupStatus) + { + case AE_ALREADY_EXISTS: + + AcpiOsPrintf (ACPI_MSG_BIOS_ERROR); + Message = "Failure creating named object"; + break; + + case AE_NOT_FOUND: + + AcpiOsPrintf (ACPI_MSG_BIOS_ERROR); + Message = "Could not resolve symbol"; + break; + + default: + + AcpiOsPrintf (ACPI_MSG_ERROR); + Message = "Failure resolving symbol"; + break; + } + + /* Concatenate the prefix path and the internal path */ + + FullPath = AcpiNsBuildPrefixedPathname (PrefixScope, InternalPath); + + AcpiOsPrintf ("%s [%s], %s", Message, + FullPath ? FullPath : "Could not get pathname", + AcpiFormatException (LookupStatus)); + + if (FullPath) + { + ACPI_FREE (FullPath); + } + + ACPI_MSG_SUFFIX; +} + + +#ifdef __OBSOLETE_FUNCTION +/******************************************************************************* + * + * 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%.8X] (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; +} +#endif + +/******************************************************************************* + * + * 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 (" due to previous error (%s)", + AcpiFormatException (MethodStatus)); + + ACPI_MSG_SUFFIX; + ACPI_MSG_REDIRECT_END; +} + +#endif /* ACPI_NO_ERROR_MESSAGES */ diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/uteval.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/uteval.c new file mode 100644 index 0000000..8f5ad82 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/uteval.c @@ -0,0 +1,349 @@ +/****************************************************************************** + * + * Module Name: uteval - Object evaluation + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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, + const 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->RelativePathname = 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 ( + const 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. If _STA does not exist, then the device is assumed + * to be present/functional/enabled (as per the ACPI spec). + * + * 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) + { + /* + * if _STA does not exist, then (as per the ACPI specification), + * the returned flags will indicate that the device is present, + * functional, and enabled. + */ + 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/code/drivers/platform/acpi/third_party/acpica/components/utilities/utexcep.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utexcep.c new file mode 100644 index 0000000..092b76d --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utexcep.c @@ -0,0 +1,149 @@ +/******************************************************************************* + * + * Module Name: utexcep - Exception code support + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#define ACPI_DEFINE_EXCEPTION_TABLE +#include "acpi.h" +#include "accommon.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utexcep") + + +/******************************************************************************* + * + * 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. Returns "unknown status" string for invalid codes. + * + ******************************************************************************/ + +const char * +AcpiFormatException ( + ACPI_STATUS Status) +{ + const ACPI_EXCEPTION_INFO *Exception; + + + ACPI_FUNCTION_ENTRY (); + + + Exception = AcpiUtValidateException (Status); + if (!Exception) + { + /* Exception code was not recognized */ + + ACPI_ERROR ((AE_INFO, + "Unknown exception code: 0x%8.8X", Status)); + + return ("UNKNOWN_STATUS_CODE"); + } + + return (Exception->Name); +} + +ACPI_EXPORT_SYMBOL (AcpiFormatException) + + +/******************************************************************************* + * + * 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 ACPI_EXCEPTION_INFO * +AcpiUtValidateException ( + ACPI_STATUS Status) +{ + UINT32 SubStatus; + const ACPI_EXCEPTION_INFO *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; + } + + if (!Exception || !Exception->Name) + { + return (NULL); + } + + return (Exception); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utglobal.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utglobal.c new file mode 100644 index 0000000..bab3bff --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utglobal.c @@ -0,0 +1,210 @@ +/****************************************************************************** + * + * Module Name: utglobal - Global variables for the ACPI subsystem + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES +#define DEFINE_ACPI_GLOBALS + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utglobal") + + +/******************************************************************************* + * + * Static global variable initialization. + * + ******************************************************************************/ + +/* Various state name strings */ + +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" +}; + + +/* Hex-to-ascii */ + +const char AcpiGbl_LowerHexDigits[] = "0123456789abcdef"; +const char AcpiGbl_UpperHexDigits[] = "0123456789ABCDEF"; + + +/******************************************************************************* + * + * 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}, + /* + * March, 2015: + * The _REV object is in the process of being deprecated, because + * other ACPI implementations permanently return 2. Thus, it + * has little or no value. Return 2 for compatibility with + * other ACPI implementations. + */ + {"_REV", ACPI_TYPE_INTEGER, ACPI_CAST_PTR (char, 2)}, + {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, + {"_GL_", ACPI_TYPE_MUTEX, ACPI_CAST_PTR (char, 1)}, + {"_OSI", ACPI_TYPE_METHOD, ACPI_CAST_PTR (char, 1)}, + + /* 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 */ + + +#if defined (ACPI_DISASSEMBLER) || defined (ACPI_ASL_COMPILER) + +/* ToPld macro: compile/disassemble strings */ + +const char *AcpiGbl_PldPanelList[] = +{ + "TOP", + "BOTTOM", + "LEFT", + "RIGHT", + "FRONT", + "BACK", + "UNKNOWN", + NULL +}; + +const char *AcpiGbl_PldVerticalPositionList[] = +{ + "UPPER", + "CENTER", + "LOWER", + NULL +}; + +const char *AcpiGbl_PldHorizontalPositionList[] = +{ + "LEFT", + "CENTER", + "RIGHT", + NULL +}; + +const char *AcpiGbl_PldShapeList[] = +{ + "ROUND", + "OVAL", + "SQUARE", + "VERTICALRECTANGLE", + "HORIZONTALRECTANGLE", + "VERTICALTRAPEZOID", + "HORIZONTALTRAPEZOID", + "UNKNOWN", + "CHAMFERED", + NULL +}; +#endif + + +/* 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/code/drivers/platform/acpi/third_party/acpica/components/utilities/uthex.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/uthex.c new file mode 100644 index 0000000..d969043 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/uthex.c @@ -0,0 +1,126 @@ +/****************************************************************************** + * + * Module Name: uthex -- Hex/ASCII support functions + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("uthex") + + +/* 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' +}; + + +/******************************************************************************* + * + * 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 + * + ******************************************************************************/ + +char +AcpiUtHexToAsciiChar ( + UINT64 Integer, + UINT32 Position) +{ + UINT64 Index; + + AcpiUtShortShiftRight (Integer, Position, &Index); + return (AcpiGbl_HexToAscii[Index & 0xF]); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAsciiToHexByte + * + * PARAMETERS: TwoAsciiChars - Pointer to two ASCII characters + * ReturnByte - Where converted byte is returned + * + * RETURN: Status and converted hex byte + * + * DESCRIPTION: Perform ascii-to-hex translation, exactly two ASCII characters + * to a single converted byte value. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtAsciiToHexByte ( + char *TwoAsciiChars, + UINT8 *ReturnByte) +{ + + /* Both ASCII characters must be valid hex digits */ + + if (!isxdigit ((int) TwoAsciiChars[0]) || + !isxdigit ((int) TwoAsciiChars[1])) + { + return (AE_BAD_HEX_CONSTANT); + } + + *ReturnByte = + AcpiUtAsciiCharToHex (TwoAsciiChars[1]) | + (AcpiUtAsciiCharToHex (TwoAsciiChars[0]) << 4); + + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtAsciiCharToHex + * + * PARAMETERS: HexChar - Hex character in Ascii. Must be: + * 0-9 or A-F or a-f + * + * RETURN: The binary value of the ascii/hex character + * + * DESCRIPTION: Perform ascii-to-hex translation + * + ******************************************************************************/ + +UINT8 +AcpiUtAsciiCharToHex ( + int HexChar) +{ + + /* Values 0-9 */ + + if (HexChar <= '9') + { + return ((UINT8) (HexChar - '0')); + } + + /* Upper case A-F */ + + if (HexChar <= 'F') + { + return ((UINT8) (HexChar - 0x37)); + } + + /* Lower case a-f */ + + return ((UINT8) (HexChar - 0x57)); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utids.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utids.c new file mode 100644 index 0000000..3ad3624 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utids.c @@ -0,0 +1,448 @@ +/****************************************************************************** + * + * Module Name: utids - support for device IDs - HID, UID, CID, SUB, CLS + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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_PNP_DEVICE_ID **ReturnId) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_PNP_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_PNP_DEVICE_ID) + (ACPI_SIZE) Length); + if (!Hid) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Area for the string starts after PNP_DEVICE_ID struct */ + + Hid->String = ACPI_ADD_PTR (char, Hid, sizeof (ACPI_PNP_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 + { + 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_PNP_DEVICE_ID **ReturnId) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_PNP_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_PNP_DEVICE_ID) + (ACPI_SIZE) Length); + if (!Uid) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Area for the string starts after PNP_DEVICE_ID struct */ + + Uid->String = ACPI_ADD_PTR (char, Uid, sizeof (ACPI_PNP_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 + { + 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_PNP_DEVICE_ID_LIST **ReturnCidList) +{ + ACPI_OPERAND_OBJECT **CidObjects; + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_PNP_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 PNP_DEVICE_ID array + + * 3) Size of the actual CID strings + */ + CidListSize = sizeof (ACPI_PNP_DEVICE_ID_LIST) + + (Count * sizeof (ACPI_PNP_DEVICE_ID)) + + StringAreaSize; + + CidList = ACPI_ALLOCATE_ZEROED (CidListSize); + if (!CidList) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Area for CID strings starts after the CID PNP_DEVICE_ID array */ + + NextIdString = ACPI_CAST_PTR (char, CidList->Ids) + + ((ACPI_SIZE) Count * sizeof (ACPI_PNP_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 */ + + 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); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtExecute_CLS + * + * PARAMETERS: DeviceNode - Node for the device + * ReturnId - Where the _CLS is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _CLS control method that returns PCI-defined + * class code of the device. The _CLS value is always a package + * containing PCI class information as a list of integers. + * The returned string has format "BBSSPP", where: + * BB = Base-class code + * SS = Sub-class code + * PP = Programming Interface code + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtExecute_CLS ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_PNP_DEVICE_ID **ReturnId) +{ + ACPI_OPERAND_OBJECT *ObjDesc; + ACPI_OPERAND_OBJECT **ClsObjects; + UINT32 Count; + ACPI_PNP_DEVICE_ID *Cls; + UINT32 Length; + ACPI_STATUS Status; + UINT8 ClassCode[3] = {0, 0, 0}; + + + ACPI_FUNCTION_TRACE (UtExecute_CLS); + + + Status = AcpiUtEvaluateObject (DeviceNode, METHOD_NAME__CLS, + ACPI_BTYPE_PACKAGE, &ObjDesc); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + /* Get the size of the String to be returned, includes null terminator */ + + Length = ACPI_PCICLS_STRING_SIZE; + ClsObjects = ObjDesc->Package.Elements; + Count = ObjDesc->Package.Count; + + if (ObjDesc->Common.Type == ACPI_TYPE_PACKAGE) + { + if (Count > 0 && ClsObjects[0]->Common.Type == ACPI_TYPE_INTEGER) + { + ClassCode[0] = (UINT8) ClsObjects[0]->Integer.Value; + } + if (Count > 1 && ClsObjects[1]->Common.Type == ACPI_TYPE_INTEGER) + { + ClassCode[1] = (UINT8) ClsObjects[1]->Integer.Value; + } + if (Count > 2 && ClsObjects[2]->Common.Type == ACPI_TYPE_INTEGER) + { + ClassCode[2] = (UINT8) ClsObjects[2]->Integer.Value; + } + } + + /* Allocate a buffer for the CLS */ + + Cls = ACPI_ALLOCATE_ZEROED ( + sizeof (ACPI_PNP_DEVICE_ID) + (ACPI_SIZE) Length); + if (!Cls) + { + Status = AE_NO_MEMORY; + goto Cleanup; + } + + /* Area for the string starts after PNP_DEVICE_ID struct */ + + Cls->String = ACPI_ADD_PTR (char, Cls, sizeof (ACPI_PNP_DEVICE_ID)); + + /* Simply copy existing string */ + + AcpiExPciClsToString (Cls->String, ClassCode); + Cls->Length = Length; + *ReturnId = Cls; + + +Cleanup: + + /* On exit, we must delete the return object */ + + AcpiUtRemoveReference (ObjDesc); + return_ACPI_STATUS (Status); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utinit.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utinit.c new file mode 100644 index 0000000..2ce64c0 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utinit.c @@ -0,0 +1,321 @@ +/****************************************************************************** + * + * Module Name: utinit - Common ACPI subsystem initialization + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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: AcpiUtInitGlobals + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize ACPICA globals. All globals that require specific + * initialization should be initialized here. This allows for + * a warm restart. + * + ******************************************************************************/ + +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/SCI support */ + + AcpiGbl_AllGpesInitialized = FALSE; + AcpiGbl_GpeXruptListHead = NULL; + AcpiGbl_GpeFadtBlocks[0] = NULL; + AcpiGbl_GpeFadtBlocks[1] = NULL; + AcpiCurrentGpeCount = 0; + + AcpiGbl_GlobalEventHandler = NULL; + AcpiGbl_SciHandlerList = NULL; + +#endif /* !ACPI_REDUCED_HARDWARE */ + + /* Global handlers */ + + AcpiGbl_GlobalNotify[0].Handler = NULL; + AcpiGbl_GlobalNotify[1].Handler = NULL; + AcpiGbl_ExceptionHandler = NULL; + AcpiGbl_InitHandler = NULL; + AcpiGbl_TableHandler = NULL; + AcpiGbl_InterfaceHandler = NULL; + + /* Global Lock support */ + + AcpiGbl_GlobalLockSemaphore = ACPI_SEMAPHORE_NULL; + AcpiGbl_GlobalLockMutex = NULL; + AcpiGbl_GlobalLockAcquired = FALSE; + AcpiGbl_GlobalLockHandle = 0; + AcpiGbl_GlobalLockPresent = FALSE; + + /* Miscellaneous variables */ + + AcpiGbl_DSDT = NULL; + AcpiGbl_CmSingleStep = FALSE; + AcpiGbl_Shutdown = FALSE; + AcpiGbl_NsLookupCount = 0; + AcpiGbl_PsFindCount = 0; + AcpiGbl_AcpiHardwarePresent = TRUE; + AcpiGbl_LastOwnerIdIndex = 0; + AcpiGbl_NextOwnerIdOffset = 0; + AcpiGbl_DebuggerConfiguration = DEBUGGER_THREADING; + AcpiGbl_OsiMutex = NULL; + + /* Hardware oriented */ + + AcpiGbl_EventsInitialized = FALSE; + AcpiGbl_SystemAwakeAndRunning = TRUE; + + /* Namespace */ + + 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; + AcpiGbl_NumExternalMethods = 0; + AcpiGbl_ResolvedExternalMethods = 0; +#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); +} + + +/****************************************************************************** + * + * 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); + + + /* Just exit if subsystem is already shutdown */ + + if (AcpiGbl_Shutdown) + { + ACPI_ERROR ((AE_INFO, "ACPI Subsystem is already terminated")); + return_VOID; + } + + /* 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")); + +#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/code/drivers/platform/acpi/third_party/acpica/components/utilities/utlock.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utlock.c new file mode 100644 index 0000000..a438769 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utlock.c @@ -0,0 +1,172 @@ +/****************************************************************************** + * + * Module Name: utlock - Reader/Writer lock interfaces + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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/code/drivers/platform/acpi/third_party/acpica/components/utilities/utmath.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utmath.c new file mode 100644 index 0000000..ecd46df --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utmath.c @@ -0,0 +1,586 @@ +/******************************************************************************* + * + * Module Name: utmath - Integer math support routines + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utmath") + +/* 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; + +/* + * Optional support for 64-bit double-precision integer multiply and shift. + * 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. + */ +#ifndef ACPI_USE_NATIVE_MATH64 + +/******************************************************************************* + * + * FUNCTION: AcpiUtShortMultiply + * + * PARAMETERS: Multiplicand - 64-bit multiplicand + * Multiplier - 32-bit multiplier + * OutProduct - Pointer to where the product is returned + * + * DESCRIPTION: Perform a short multiply. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtShortMultiply ( + UINT64 Multiplicand, + UINT32 Multiplier, + UINT64 *OutProduct) +{ + UINT64_OVERLAY MultiplicandOvl; + UINT64_OVERLAY Product; + UINT32 Carry32; + + + ACPI_FUNCTION_TRACE (UtShortMultiply); + + + MultiplicandOvl.Full = Multiplicand; + + /* + * The Product is 64 bits, the carry is always 32 bits, + * and is generated by the second multiply. + */ + ACPI_MUL_64_BY_32 (0, MultiplicandOvl.Part.Hi, Multiplier, + Product.Part.Hi, Carry32); + + ACPI_MUL_64_BY_32 (0, MultiplicandOvl.Part.Lo, Multiplier, + Product.Part.Lo, Carry32); + + Product.Part.Hi += Carry32; + + /* Return only what was requested */ + + if (OutProduct) + { + *OutProduct = Product.Full; + } + + return_ACPI_STATUS (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtShortShiftLeft + * + * PARAMETERS: Operand - 64-bit shift operand + * Count - 32-bit shift count + * OutResult - Pointer to where the result is returned + * + * DESCRIPTION: Perform a short left shift. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtShortShiftLeft ( + UINT64 Operand, + UINT32 Count, + UINT64 *OutResult) +{ + UINT64_OVERLAY OperandOvl; + + + ACPI_FUNCTION_TRACE (UtShortShiftLeft); + + + OperandOvl.Full = Operand; + + if ((Count & 63) >= 32) + { + OperandOvl.Part.Hi = OperandOvl.Part.Lo; + OperandOvl.Part.Lo = 0; + Count = (Count & 63) - 32; + } + ACPI_SHIFT_LEFT_64_BY_32 (OperandOvl.Part.Hi, + OperandOvl.Part.Lo, Count); + + /* Return only what was requested */ + + if (OutResult) + { + *OutResult = OperandOvl.Full; + } + + return_ACPI_STATUS (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: AcpiUtShortShiftRight + * + * PARAMETERS: Operand - 64-bit shift operand + * Count - 32-bit shift count + * OutResult - Pointer to where the result is returned + * + * DESCRIPTION: Perform a short right shift. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtShortShiftRight ( + UINT64 Operand, + UINT32 Count, + UINT64 *OutResult) +{ + UINT64_OVERLAY OperandOvl; + + + ACPI_FUNCTION_TRACE (UtShortShiftRight); + + + OperandOvl.Full = Operand; + + if ((Count & 63) >= 32) + { + OperandOvl.Part.Lo = OperandOvl.Part.Hi; + OperandOvl.Part.Hi = 0; + Count = (Count & 63) - 32; + } + ACPI_SHIFT_RIGHT_64_BY_32 (OperandOvl.Part.Hi, + OperandOvl.Part.Lo, Count); + + /* Return only what was requested */ + + if (OutResult) + { + *OutResult = OperandOvl.Full; + } + + return_ACPI_STATUS (AE_OK); +} +#else + +/******************************************************************************* + * + * FUNCTION: AcpiUtShortMultiply + * + * PARAMETERS: See function headers above + * + * DESCRIPTION: Native version of the UtShortMultiply function. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtShortMultiply ( + UINT64 Multiplicand, + UINT32 Multiplier, + UINT64 *OutProduct) +{ + + ACPI_FUNCTION_TRACE (UtShortMultiply); + + + /* Return only what was requested */ + + if (OutProduct) + { + *OutProduct = Multiplicand * Multiplier; + } + + return_ACPI_STATUS (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: AcpiUtShortShiftLeft + * + * PARAMETERS: See function headers above + * + * DESCRIPTION: Native version of the UtShortShiftLeft function. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtShortShiftLeft ( + UINT64 Operand, + UINT32 Count, + UINT64 *OutResult) +{ + + ACPI_FUNCTION_TRACE (UtShortShiftLeft); + + + /* Return only what was requested */ + + if (OutResult) + { + *OutResult = Operand << Count; + } + + return_ACPI_STATUS (AE_OK); +} + +/******************************************************************************* + * + * FUNCTION: AcpiUtShortShiftRight + * + * PARAMETERS: See function headers above + * + * DESCRIPTION: Native version of the UtShortShiftRight function. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtShortShiftRight ( + UINT64 Operand, + UINT32 Count, + UINT64 *OutResult) +{ + + ACPI_FUNCTION_TRACE (UtShortShiftRight); + + + /* Return only what was requested */ + + if (OutResult) + { + *OutResult = Operand >> Count; + } + + return_ACPI_STATUS (AE_OK); +} +#endif + +/* + * 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 + + +/******************************************************************************* + * + * 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/code/drivers/platform/acpi/third_party/acpica/components/utilities/utmisc.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utmisc.c new file mode 100644 index 0000000..927b802 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utmisc.c @@ -0,0 +1,435 @@ +/******************************************************************************* + * + * Module Name: utmisc - common utility procedures + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utmisc") + + +/******************************************************************************* + * + * 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 (!(strcmp (Id, + PCI_ROOT_HID_STRING)) || + + !(strcmp (Id, + PCI_EXPRESS_ROOT_HID_STRING))) + { + return (TRUE); + } + + return (FALSE); +} + + +#if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP || defined ACPI_NAMES_APP) +/******************************************************************************* + * + * 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_NAMESEG (Table->Signature, ACPI_SIG_DSDT) || + ACPI_COMPARE_NAMESEG (Table->Signature, ACPI_SIG_PSDT) || + ACPI_COMPARE_NAMESEG (Table->Signature, ACPI_SIG_SSDT) || + ACPI_COMPARE_NAMESEG (Table->Signature, ACPI_SIG_OSDT) || + ACPI_IS_OEM_SIG (Table->Signature)) + { + return (TRUE); + } + + return (FALSE); +} +#endif + + +/******************************************************************************* + * + * 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; + } +} + + +/******************************************************************************* + * + * 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, including subpackages + * + ******************************************************************************/ + +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; + ACPI_OPERAND_OBJECT *ThisSourceObj; + UINT32 ThisIndex; + + + 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 = + State->Pkg.SourceObject->Package.Elements[ThisIndex]; + State->Pkg.ThisTargetObj = + &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 */ + + ACPI_ERROR ((AE_INFO, + "State list did not terminate correctly")); + + return_ACPI_STATUS (AE_AML_INTERNAL); +} + + +#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, + const 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, TRUE); + 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 diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utmutex.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utmutex.c new file mode 100644 index 0000000..b12a702 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utmutex.c @@ -0,0 +1,387 @@ +/******************************************************************************* + * + * Module Name: utmutex - local mutex support + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 or for speed */ + + Status = AcpiOsCreateLock (&AcpiGbl_GpeLock); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiOsCreateLock (&AcpiGbl_HardwareLock); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiOsCreateLock (&AcpiGbl_ReferenceCountLock); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + Status = AcpiOsCreateLock (&AcpiGbl_NotifyLock); + 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); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + + 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); + AcpiOsDeleteLock (AcpiGbl_ReferenceCountLock); + AcpiOsDeleteLock (AcpiGbl_NotifyLock); + + /* 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; + + return_VOID; +} + + +/******************************************************************************* + * + * 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 [%s] (0x%X)", + (UINT32) ThisThreadId, AcpiUtGetMutexName (MutexId), 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 [%s] (0x%X) is not acquired, cannot release", + AcpiUtGetMutexName (MutexId), 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/code/drivers/platform/acpi/third_party/acpica/components/utilities/utnonansi.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utnonansi.c new file mode 100644 index 0000000..3fc6b5b --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utnonansi.c @@ -0,0 +1,222 @@ +/******************************************************************************* + * + * Module Name: utnonansi - Non-ansi C library functions + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utnonansi") + +/* + * Non-ANSI C library functions - strlwr, strupr, stricmp, and "safe" + * string functions. + */ + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrlwr (strlwr) + * + * PARAMETERS: SrcString - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert a string to lowercase + * + ******************************************************************************/ + +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) tolower ((int) *String); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrupr (strupr) + * + * PARAMETERS: SrcString - The source string to convert + * + * RETURN: None + * + * DESCRIPTION: Convert a string to uppercase + * + ******************************************************************************/ + +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) toupper ((int) *String); + } +} + + +/****************************************************************************** + * + * FUNCTION: AcpiUtStricmp (stricmp) + * + * PARAMETERS: String1 - first string to compare + * String2 - second string to compare + * + * RETURN: int that signifies string relationship. Zero means strings + * are equal. + * + * DESCRIPTION: Case-insensitive string compare. Implementation of the + * non-ANSI stricmp function. + * + ******************************************************************************/ + +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); +} + + +#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION) || defined (ACPI_DEBUG_OUTPUT) +/******************************************************************************* + * + * FUNCTION: AcpiUtSafeStrcpy, AcpiUtSafeStrcat, AcpiUtSafeStrncat + * + * PARAMETERS: Adds a "DestSize" parameter to each of the standard string + * functions. This is the size of the Destination buffer. + * + * RETURN: TRUE if the operation would overflow the destination buffer. + * + * DESCRIPTION: Safe versions of standard Clib string functions. Ensure that + * the result of the operation will not overflow the output string + * buffer. + * + * NOTE: These functions are typically only helpful for processing + * user input and command lines. For most ACPICA code, the + * required buffer length is precisely calculated before buffer + * allocation, so the use of these functions is unnecessary. + * + ******************************************************************************/ + +BOOLEAN +AcpiUtSafeStrcpy ( + char *Dest, + ACPI_SIZE DestSize, + char *Source) +{ + + if (strlen (Source) >= DestSize) + { + return (TRUE); + } + + strcpy (Dest, Source); + return (FALSE); +} + +BOOLEAN +AcpiUtSafeStrcat ( + char *Dest, + ACPI_SIZE DestSize, + char *Source) +{ + + if ((strlen (Dest) + strlen (Source)) >= DestSize) + { + return (TRUE); + } + + strcat (Dest, Source); + return (FALSE); +} + +BOOLEAN +AcpiUtSafeStrncat ( + char *Dest, + ACPI_SIZE DestSize, + char *Source, + ACPI_SIZE MaxTransferLength) +{ + ACPI_SIZE ActualTransferLength; + + + ActualTransferLength = ACPI_MIN (MaxTransferLength, strlen (Source)); + + if ((strlen (Dest) + ActualTransferLength) >= DestSize) + { + return (TRUE); + } + + strncat (Dest, Source, MaxTransferLength); + return (FALSE); +} + +void +AcpiUtSafeStrncpy ( + char *Dest, + char *Source, + ACPI_SIZE DestSize) +{ + /* Always terminate destination string */ + + strncpy (Dest, Source, DestSize); + Dest[DestSize - 1] = 0; +} + +#endif diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utobject.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utobject.c new file mode 100644 index 0000000..d851a4d --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utobject.c @@ -0,0 +1,754 @@ +/****************************************************************************** + * + * Module Name: utobject - ACPI object create/delete/size/cache routines + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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-satisfies-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) + { + AcpiUtDeleteObjectDesc (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 of type 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 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 of type 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 */ + + ACPI_ERROR ((AE_INFO, + "Received a namespace node [%4.4s] " + "where an operand object is required", + ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, InternalObject)->Name.Ascii)); + 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/code/drivers/platform/acpi/third_party/acpica/components/utilities/utosi.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utosi.c new file mode 100644 index 0000000..e097586 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utosi.c @@ -0,0 +1,533 @@ +/****************************************************************************** + * + * Module Name: utosi - Support for the _OSI predefined control method + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utosi") + + +/****************************************************************************** + * + * ACPICA policy for new _OSI strings: + * + * It is the stated policy of ACPICA that new _OSI strings will be integrated + * into this module as soon as possible after they are defined. It is strongly + * recommended that all ACPICA hosts mirror this policy and integrate any + * changes to this module as soon as possible. There are several historical + * reasons behind this policy: + * + * 1) New BIOSs tend to test only the case where the host responds TRUE to + * the latest version of Windows, which would respond to the latest/newest + * _OSI string. Not responding TRUE to the latest version of Windows will + * risk executing untested code paths throughout the DSDT and SSDTs. + * + * 2) If a new _OSI string is recognized only after a significant delay, this + * has the potential to cause problems on existing working machines because + * of the possibility that a new and different path through the ASL code + * will be executed. + * + * 3) New _OSI strings are tending to come out about once per year. A delay + * in recognizing a new string for a significant amount of time risks the + * release of another string which only compounds the initial problem. + * + *****************************************************************************/ + + +/* + * 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 */ + {"Windows 2012", NULL, 0, ACPI_OSI_WIN_8}, /* Windows 8 and Server 2012 - Added 08/2012 */ + {"Windows 2013", NULL, 0, ACPI_OSI_WIN_8_1}, /* Windows 8.1 and Server 2012 R2 - Added 01/2014 */ + {"Windows 2015", NULL, 0, ACPI_OSI_WIN_10}, /* Windows 10 - Added 03/2015 */ + {"Windows 2016", NULL, 0, ACPI_OSI_WIN_10_RS1}, /* Windows 10 version 1607 - Added 12/2017 */ + {"Windows 2017", NULL, 0, ACPI_OSI_WIN_10_RS2}, /* Windows 10 version 1703 - Added 12/2017 */ + {"Windows 2017.2", NULL, 0, ACPI_OSI_WIN_10_RS3}, /* Windows 10 version 1709 - Added 02/2018 */ + {"Windows 2018", NULL, 0, ACPI_OSI_WIN_10_RS4}, /* Windows 10 version 1803 - Added 11/2018 */ + {"Windows 2018.2", NULL, 0, ACPI_OSI_WIN_10_RS5}, /* Windows 10 version 1809 - Added 11/2018 */ + {"Windows 2019", NULL, 0, ACPI_OSI_WIN_10_19H1}, /* Windows 10 version 1903 - Added 08/2019 */ + {"Windows 2020", NULL, 0, ACPI_OSI_WIN_10_20H1}, /* Windows 10 version 2004 - Added 08/2021 */ + {"Windows 2021", NULL, 0, ACPI_OSI_WIN_11}, /* Windows 11 - Added 01/2022 */ + {"Windows 2022", NULL, 0, ACPI_OSI_WIN_11_22H2}, /* Windows 11 version 22H2 - Added 04/2024 */ + + /* Feature Group Strings */ + + {"Extended Address Space Descriptor", NULL, ACPI_OSI_FEATURE, 0}, + + /* + * All "optional" feature group strings (features that are implemented + * by the host) should be dynamically modified to VALID by the host via + * AcpiInstallInterface or AcpiUpdateInterfaces. Such optional feature + * group strings are set as INVALID by default here. + */ + + {"Module Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, + {"Processor Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, + {"3.0 Thermal Model", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, + {"3.0 _SCP Extensions", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, + {"Processor Aggregator Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, + + /* See https://learn.microsoft.com/en-us/windows-hardware/drivers/display/automatic-display-switch */ + + {"DisplayMux", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0} +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiUtInitializeInterfaces + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Initialize the global _OSI supported interfaces list + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtInitializeInterfaces ( + void) +{ + ACPI_STATUS Status; + UINT32 i; + + + Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + 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: Status + * + * DESCRIPTION: Delete all interfaces in the global list. Sets + * AcpiGbl_SupportedInterfaces to NULL. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtInterfaceTerminate ( + void) +{ + ACPI_STATUS Status; + ACPI_INTERFACE_INFO *NextInterface; + + + Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + NextInterface = AcpiGbl_SupportedInterfaces; + while (NextInterface) + { + AcpiGbl_SupportedInterfaces = NextInterface->Next; + + if (NextInterface->Flags & ACPI_OSI_DYNAMIC) + { + /* Only interfaces added at runtime can be freed */ + + ACPI_FREE (NextInterface->Name); + ACPI_FREE (NextInterface); + } + else + { + /* Interface is in static list. Reset it to invalid or valid. */ + + if (NextInterface->Flags & ACPI_OSI_DEFAULT_INVALID) + { + NextInterface->Flags |= ACPI_OSI_INVALID; + } + else + { + NextInterface->Flags &= ~ACPI_OSI_INVALID; + } + } + + NextInterface = AcpiGbl_SupportedInterfaces; + } + + AcpiOsReleaseMutex (AcpiGbl_OsiMutex); + return (AE_OK); +} + + +/******************************************************************************* + * + * 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 (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 */ + + 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 (!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: AcpiUtUpdateInterfaces + * + * PARAMETERS: Action - Actions to be performed during the + * update + * + * RETURN: Status + * + * DESCRIPTION: Update _OSI interface strings, disabling or enabling OS vendor + * strings or/and feature group strings. + * Caller MUST hold AcpiGbl_OsiMutex + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtUpdateInterfaces ( + UINT8 Action) +{ + ACPI_INTERFACE_INFO *NextInterface; + + + NextInterface = AcpiGbl_SupportedInterfaces; + while (NextInterface) + { + if (((NextInterface->Flags & ACPI_OSI_FEATURE) && + (Action & ACPI_FEATURE_STRINGS)) || + (!(NextInterface->Flags & ACPI_OSI_FEATURE) && + (Action & ACPI_VENDOR_STRINGS))) + { + if (Action & ACPI_DISABLE_INTERFACES) + { + /* Mark the interfaces as invalid */ + + NextInterface->Flags |= ACPI_OSI_INVALID; + } + else + { + /* Mark the interfaces as valid */ + + NextInterface->Flags &= ~ACPI_OSI_INVALID; + } + } + + NextInterface = NextInterface->Next; + } + + return (AE_OK); +} + + +/******************************************************************************* + * + * 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 (!strcmp (InterfaceName, NextInterface->Name)) + { + return (NextInterface); + } + + NextInterface = NextInterface->Next; + } + + return (NULL); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtOsiImplementation + * + * PARAMETERS: WalkState - Current walk state + * + * RETURN: Status + * Integer: TRUE (0) if input string is matched + * FALSE (-1) if string is not matched + * + * 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. + * + * (August 2016) + * Note: _OSI is now defined to return "Ones" to indicate a match, for + * compatibility with other ACPI implementations. On a 32-bit DSDT, Ones + * is 0xFFFFFFFF. On a 64-bit DSDT, Ones is 0xFFFFFFFFFFFFFFFF + * (ACPI_UINT64_MAX). + * + * This function always returns ACPI_UINT64_MAX for TRUE, and later code + * will truncate this to 32 bits if necessary. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtOsiImplementation ( + ACPI_WALK_STATE *WalkState) +{ + ACPI_OPERAND_OBJECT *StringDesc; + ACPI_OPERAND_OBJECT *ReturnDesc; + ACPI_INTERFACE_INFO *InterfaceInfo; + ACPI_INTERFACE_HANDLER InterfaceHandler; + ACPI_STATUS Status; + UINT64 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; + Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE (Status)) + { + AcpiUtRemoveReference (ReturnDesc); + return_ACPI_STATUS (Status); + } + + /* 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_UINT64_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) + { + if (InterfaceHandler ( + StringDesc->String.Pointer, (UINT32) ReturnValue)) + { + ReturnValue = ACPI_UINT64_MAX; + } + } + + 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/code/drivers/platform/acpi/third_party/acpica/components/utilities/utownerid.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utownerid.c new file mode 100644 index 0000000..4d89668 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utownerid.c @@ -0,0 +1,215 @@ +/******************************************************************************* + * + * Module Name: utownerid - Support for Table/Method Owner IDs + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utownerid") + + +/******************************************************************************* + * + * 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%3.3X] 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; + } + + /* + * Note: the UINT32 cast ensures that 1 is stored as a unsigned + * integer. Omitting the cast may result in 1 being stored as an + * int. Some compilers or runtime error detection may flag this as + * an error. + */ + if (!(AcpiGbl_OwnerIdMask[j] & ((UINT32) 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] |= ((UINT32) 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 4095) 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: 0x%3.3X\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 (4095 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%3.3X", 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 = (UINT32) 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, + "Attempted release of non-allocated OwnerId: 0x%3.3X", OwnerId + 1)); + } + + (void) AcpiUtReleaseMutex (ACPI_MTX_CACHES); + return_VOID; +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utpredef.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utpredef.c new file mode 100644 index 0000000..c820305 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utpredef.c @@ -0,0 +1,420 @@ +/****************************************************************************** + * + * Module Name: utpredef - support functions for predefined names + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acpredef.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utpredef") + + +/* + * 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 *UtRtypeNames[] = +{ + "/Integer", + "/String", + "/Buffer", + "/Package", + "/Reference", +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetNextPredefinedMethod + * + * PARAMETERS: ThisName - Entry in the predefined method/name table + * + * RETURN: Pointer to next entry in predefined table. + * + * DESCRIPTION: Get the next entry in the predefine method table. Handles the + * cases where a package info entry follows a method name that + * returns a package. + * + ******************************************************************************/ + +const ACPI_PREDEFINED_INFO * +AcpiUtGetNextPredefinedMethod ( + const ACPI_PREDEFINED_INFO *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->Info.ExpectedBtypes != ACPI_RTYPE_ALL)) + { + ThisName++; + } + + ThisName++; + return (ThisName); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtMatchPredefinedMethod + * + * PARAMETERS: Name - Name to find + * + * 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 * +AcpiUtMatchPredefinedMethod ( + char *Name) +{ + const ACPI_PREDEFINED_INFO *ThisName; + + + /* Quick check for a predefined name, first character must be underscore */ + + if (Name[0] != '_') + { + return (NULL); + } + + /* Search info table for a predefined method/object name */ + + ThisName = AcpiGbl_PredefinedMethods; + while (ThisName->Info.Name[0]) + { + if (ACPI_COMPARE_NAMESEG (Name, ThisName->Info.Name)) + { + return (ThisName); + } + + ThisName = AcpiUtGetNextPredefinedMethod (ThisName); + } + + return (NULL); /* Not found */ +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetExpectedReturnTypes + * + * 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. + * + ******************************************************************************/ + +void +AcpiUtGetExpectedReturnTypes ( + char *Buffer, + UINT32 ExpectedBtypes) +{ + UINT32 ThisRtype; + UINT32 i; + UINT32 j; + + + if (!ExpectedBtypes) + { + strcpy (Buffer, "NONE"); + return; + } + + 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, &UtRtypeNames[i][j]); + j = 0; /* Use name separator from now on */ + } + + ThisRtype <<= 1; /* Next Rtype */ + } +} + + +/******************************************************************************* + * + * The remaining functions are used by iASL and AcpiHelp only + * + ******************************************************************************/ + +#if (defined ACPI_ASL_COMPILER || defined ACPI_HELP_APP) + +/* Local prototypes */ + +static UINT32 +AcpiUtGetArgumentTypes ( + char *Buffer, + UINT16 ArgumentTypes); + + +/* Types that can be returned externally by a predefined name */ + +static const char *UtExternalTypeNames[] = /* Indexed by ACPI_TYPE_* */ +{ + ", Type_ANY", + ", Integer", + ", String", + ", Buffer", + ", Package" +}; + +/* Bit widths for resource descriptor predefined names */ + +static const char *UtResourceTypeNames[] = +{ + "/1", + "/2", + "/3", + "/8", + "/16", + "/32", + "/64", + "/variable", +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiUtMatchResourceName + * + * PARAMETERS: Name - Name to find + * + * RETURN: Pointer to entry in the resource table. NULL indicates not + * found. + * + * DESCRIPTION: Check an object name against the predefined resource + * descriptor object list. + * + ******************************************************************************/ + +const ACPI_PREDEFINED_INFO * +AcpiUtMatchResourceName ( + char *Name) +{ + const ACPI_PREDEFINED_INFO *ThisName; + + + /* + * Quick check for a predefined name, first character must + * be underscore + */ + if (Name[0] != '_') + { + return (NULL); + } + + /* Search info table for a predefined method/object name */ + + ThisName = AcpiGbl_ResourceNames; + while (ThisName->Info.Name[0]) + { + if (ACPI_COMPARE_NAMESEG (Name, ThisName->Info.Name)) + { + return (ThisName); + } + + ThisName++; + } + + return (NULL); /* Not found */ +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDisplayPredefinedMethod + * + * PARAMETERS: Buffer - Scratch buffer for this function + * ThisName - Entry in the predefined method/name table + * MultiLine - TRUE if output should be on >1 line + * + * RETURN: None + * + * DESCRIPTION: Display information about a predefined method. Number and + * type of the input arguments, and expected type(s) for the + * return value, if any. + * + ******************************************************************************/ + +void +AcpiUtDisplayPredefinedMethod ( + char *Buffer, + const ACPI_PREDEFINED_INFO *ThisName, + BOOLEAN MultiLine) +{ + UINT32 ArgCount; + + /* + * Get the argument count and the string buffer + * containing all argument types + */ + ArgCount = AcpiUtGetArgumentTypes (Buffer, + ThisName->Info.ArgumentList); + + if (MultiLine) + { + printf (" "); + } + + printf ("%4.4s Requires %s%u argument%s", + ThisName->Info.Name, + (ThisName->Info.ArgumentList & ARG_COUNT_IS_MINIMUM) ? + "(at least) " : "", + ArgCount, ArgCount != 1 ? "s" : ""); + + /* Display the types for any arguments */ + + if (ArgCount > 0) + { + printf (" (%s)", Buffer); + } + + if (MultiLine) + { + printf ("\n "); + } + + /* Get the return value type(s) allowed */ + + if (ThisName->Info.ExpectedBtypes) + { + AcpiUtGetExpectedReturnTypes (Buffer, ThisName->Info.ExpectedBtypes); + printf (" Return value types: %s\n", Buffer); + } + else + { + printf (" No return value\n"); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetArgumentTypes + * + * PARAMETERS: Buffer - Where to return the formatted types + * ArgumentTypes - Types field for this method + * + * RETURN: Count - the number of arguments required for this method + * + * DESCRIPTION: Format the required data types for this method (Integer, + * String, Buffer, or Package) and return the required argument + * count. + * + ******************************************************************************/ + +static UINT32 +AcpiUtGetArgumentTypes ( + char *Buffer, + UINT16 ArgumentTypes) +{ + UINT16 ThisArgumentType; + UINT16 SubIndex; + UINT16 ArgCount; + UINT32 i; + + + *Buffer = 0; + SubIndex = 2; + + /* First field in the types list is the count of args to follow */ + + ArgCount = METHOD_GET_ARG_COUNT (ArgumentTypes); + if (ArgCount > METHOD_PREDEF_ARGS_MAX) + { + printf ("**** Invalid argument count (%u) " + "in predefined info structure\n", ArgCount); + return (ArgCount); + } + + /* Get each argument from the list, convert to ascii, store to buffer */ + + for (i = 0; i < ArgCount; i++) + { + ThisArgumentType = METHOD_GET_NEXT_TYPE (ArgumentTypes); + + if (ThisArgumentType > METHOD_MAX_ARG_TYPE) + { + printf ("**** Invalid argument type (%u) " + "in predefined info structure\n", ThisArgumentType); + return (ArgCount); + } + + strcat (Buffer, UtExternalTypeNames[ThisArgumentType] + SubIndex); + SubIndex = 0; + } + + return (ArgCount); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtGetResourceBitWidth + * + * PARAMETERS: Buffer - Where the formatted string is returned + * Types - Bitfield of expected data types + * + * RETURN: Count of return types. Formatted string in Buffer. + * + * DESCRIPTION: Format the resource bit widths into a printable string. + * + ******************************************************************************/ + +UINT32 +AcpiUtGetResourceBitWidth ( + char *Buffer, + UINT16 Types) +{ + UINT32 i; + UINT16 SubIndex; + UINT32 Found; + + + *Buffer = 0; + SubIndex = 1; + Found = 0; + + for (i = 0; i < NUM_RESOURCE_WIDTHS; i++) + { + if (Types & 1) + { + strcat (Buffer, &(UtResourceTypeNames[i][SubIndex])); + SubIndex = 0; + Found++; + } + + Types >>= 1; + } + + return (Found); +} +#endif diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utprint.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utprint.c new file mode 100644 index 0000000..3d26ab5 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utprint.c @@ -0,0 +1,1016 @@ +/****************************************************************************** + * + * Module Name: utprint - Formatted printing routines + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2023, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + ***************************************************************************** + * + * Alternatively, you may choose to be licensed under the terms of the + * following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, you may choose to be licensed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utprint") + + +#define ACPI_FORMAT_SIGN 0x01 +#define ACPI_FORMAT_SIGN_PLUS 0x02 +#define ACPI_FORMAT_SIGN_PLUS_SPACE 0x04 +#define ACPI_FORMAT_ZERO 0x08 +#define ACPI_FORMAT_LEFT 0x10 +#define ACPI_FORMAT_UPPER 0x20 +#define ACPI_FORMAT_PREFIX 0x40 + + +/* Local prototypes */ + +static ACPI_SIZE +AcpiUtBoundStringLength ( + const char *String, + ACPI_SIZE Count); + +static char * +AcpiUtBoundStringOutput ( + char *String, + const char *End, + char c); + +static char * +AcpiUtFormatNumber ( + char *String, + char *End, + UINT64 Number, + UINT8 Base, + INT32 Width, + INT32 Precision, + UINT8 Type); + +static char * +AcpiUtPutNumber ( + char *String, + UINT64 Number, + UINT8 Base, + BOOLEAN Upper); + + +/******************************************************************************* + * + * FUNCTION: AcpiUtBoundStringLength + * + * PARAMETERS: String - String with boundary + * Count - Boundary of the string + * + * RETURN: Length of the string. Less than or equal to Count. + * + * DESCRIPTION: Calculate the length of a string with boundary. + * + ******************************************************************************/ + +static ACPI_SIZE +AcpiUtBoundStringLength ( + const char *String, + ACPI_SIZE Count) +{ + UINT32 Length = 0; + + + while (*String && Count) + { + Length++; + String++; + Count--; + } + + return (Length); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtBoundStringOutput + * + * PARAMETERS: String - String with boundary + * End - Boundary of the string + * c - Character to be output to the string + * + * RETURN: Updated position for next valid character + * + * DESCRIPTION: Output a character into a string with boundary check. + * + ******************************************************************************/ + +static char * +AcpiUtBoundStringOutput ( + char *String, + const char *End, + char c) +{ + + if (String < End) + { + *String = c; + } + + ++String; + return (String); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtPutNumber + * + * PARAMETERS: String - Buffer to hold reverse-ordered string + * Number - Integer to be converted + * Base - Base of the integer + * Upper - Whether or not using upper cased digits + * + * RETURN: Updated position for next valid character + * + * DESCRIPTION: Convert an integer into a string, note that, the string holds a + * reversed ordered number without the trailing zero. + * + ******************************************************************************/ + +static char * +AcpiUtPutNumber ( + char *String, + UINT64 Number, + UINT8 Base, + BOOLEAN Upper) +{ + const char *Digits; + UINT64 DigitIndex; + char *Pos; + + + Pos = String; + Digits = Upper ? AcpiGbl_UpperHexDigits : AcpiGbl_LowerHexDigits; + + if (Number == 0) + { + *(Pos++) = '0'; + } + else + { + while (Number) + { + (void) AcpiUtDivide (Number, Base, &Number, &DigitIndex); + *(Pos++) = Digits[DigitIndex]; + } + } + + /* *(Pos++) = '0'; */ + return (Pos); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtScanNumber + * + * PARAMETERS: String - String buffer + * NumberPtr - Where the number is returned + * + * RETURN: Updated position for next valid character + * + * DESCRIPTION: Scan a string for a decimal integer. + * + ******************************************************************************/ + +const char * +AcpiUtScanNumber ( + const char *String, + UINT64 *NumberPtr) +{ + UINT64 Number = 0; + + + while (isdigit ((int) *String)) + { + AcpiUtShortMultiply (Number, 10, &Number); + Number += *(String++) - '0'; + } + + *NumberPtr = Number; + return (String); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtPrintNumber + * + * PARAMETERS: String - String buffer + * Number - The number to be converted + * + * RETURN: Updated position for next valid character + * + * DESCRIPTION: Print a decimal integer into a string. + * + ******************************************************************************/ + +const char * +AcpiUtPrintNumber ( + char *String, + UINT64 Number) +{ + char AsciiString[20]; + const char *Pos1; + char *Pos2; + + + Pos1 = AcpiUtPutNumber (AsciiString, Number, 10, FALSE); + Pos2 = String; + + while (Pos1 != AsciiString) + { + *(Pos2++) = *(--Pos1); + } + + *Pos2 = 0; + return (String); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtFormatNumber + * + * PARAMETERS: String - String buffer with boundary + * End - Boundary of the string + * Number - The number to be converted + * Base - Base of the integer + * Width - Field width + * Precision - Precision of the integer + * Type - Special printing flags + * + * RETURN: Updated position for next valid character + * + * DESCRIPTION: Print an integer into a string with any base and any precision. + * + ******************************************************************************/ + +static char * +AcpiUtFormatNumber ( + char *String, + char *End, + UINT64 Number, + UINT8 Base, + INT32 Width, + INT32 Precision, + UINT8 Type) +{ + char *Pos; + char Sign; + char Zero; + BOOLEAN NeedPrefix; + BOOLEAN Upper; + INT32 i; + char ReversedString[66]; + + + /* Parameter validation */ + + if (Base < 2 || Base > 16) + { + return (NULL); + } + + if (Type & ACPI_FORMAT_LEFT) + { + Type &= ~ACPI_FORMAT_ZERO; + } + + NeedPrefix = ((Type & ACPI_FORMAT_PREFIX) && Base != 10) ? TRUE : FALSE; + Upper = (Type & ACPI_FORMAT_UPPER) ? TRUE : FALSE; + Zero = (Type & ACPI_FORMAT_ZERO) ? '0' : ' '; + + /* Calculate size according to sign and prefix */ + + Sign = '\0'; + if (Type & ACPI_FORMAT_SIGN) + { + if ((INT64) Number < 0) + { + Sign = '-'; + Number = - (INT64) Number; + Width--; + } + else if (Type & ACPI_FORMAT_SIGN_PLUS) + { + Sign = '+'; + Width--; + } + else if (Type & ACPI_FORMAT_SIGN_PLUS_SPACE) + { + Sign = ' '; + Width--; + } + } + if (NeedPrefix) + { + Width--; + if (Base == 16) + { + Width--; + } + } + + /* Generate full string in reverse order */ + + Pos = AcpiUtPutNumber (ReversedString, Number, Base, Upper); + i = (INT32) ACPI_PTR_DIFF (Pos, ReversedString); + + /* Printing 100 using %2d gives "100", not "00" */ + + if (i > Precision) + { + Precision = i; + } + + Width -= Precision; + + /* Output the string */ + + if (!(Type & (ACPI_FORMAT_ZERO | ACPI_FORMAT_LEFT))) + { + while (--Width >= 0) + { + String = AcpiUtBoundStringOutput (String, End, ' '); + } + } + if (Sign) + { + String = AcpiUtBoundStringOutput (String, End, Sign); + } + if (NeedPrefix) + { + String = AcpiUtBoundStringOutput (String, End, '0'); + if (Base == 16) + { + String = AcpiUtBoundStringOutput ( + String, End, Upper ? 'X' : 'x'); + } + } + if (!(Type & ACPI_FORMAT_LEFT)) + { + while (--Width >= 0) + { + String = AcpiUtBoundStringOutput (String, End, Zero); + } + } + + while (i <= --Precision) + { + String = AcpiUtBoundStringOutput (String, End, '0'); + } + while (--i >= 0) + { + String = AcpiUtBoundStringOutput (String, End, + ReversedString[i]); + } + while (--Width >= 0) + { + String = AcpiUtBoundStringOutput (String, End, ' '); + } + + return (String); +} + + +/******************************************************************************* + * + * FUNCTION: vsnprintf + * + * PARAMETERS: String - String with boundary + * Size - Boundary of the string + * Format - Standard printf format + * Args - Argument list + * + * RETURN: Number of bytes actually written. + * + * DESCRIPTION: Formatted output to a string using argument list pointer. + * + ******************************************************************************/ + +int +vsnprintf ( + char *String, + ACPI_SIZE Size, + const char *Format, + va_list Args) +{ + UINT8 Base; + UINT8 Type; + INT32 Width; + INT32 Precision; + char Qualifier; + UINT64 Number; + char *Pos; + char *End; + char c; + const char *s; + const void *p; + INT32 Length; + int i; + + + Pos = String; + + Size = ACPI_MIN(Size, ACPI_PTR_DIFF(ACPI_MAX_PTR, String)); + End = String + Size; + + for (; *Format; ++Format) + { + if (*Format != '%') + { + Pos = AcpiUtBoundStringOutput (Pos, End, *Format); + continue; + } + + Type = 0; + Base = 10; + + /* Process sign */ + + do + { + ++Format; + if (*Format == '#') + { + Type |= ACPI_FORMAT_PREFIX; + } + else if (*Format == '0') + { + Type |= ACPI_FORMAT_ZERO; + } + else if (*Format == '+') + { + Type |= ACPI_FORMAT_SIGN_PLUS; + } + else if (*Format == ' ') + { + Type |= ACPI_FORMAT_SIGN_PLUS_SPACE; + } + else if (*Format == '-') + { + Type |= ACPI_FORMAT_LEFT; + } + else + { + break; + } + + } while (1); + + /* Process width */ + + Width = -1; + if (isdigit ((int) *Format)) + { + Format = AcpiUtScanNumber (Format, &Number); + Width = (INT32) Number; + } + else if (*Format == '*') + { + ++Format; + Width = va_arg (Args, int); + if (Width < 0) + { + Width = -Width; + Type |= ACPI_FORMAT_LEFT; + } + } + + /* Process precision */ + + Precision = -1; + if (*Format == '.') + { + ++Format; + if (isdigit ((int) *Format)) + { + Format = AcpiUtScanNumber (Format, &Number); + Precision = (INT32) Number; + } + else if (*Format == '*') + { + ++Format; + Precision = va_arg (Args, int); + } + + if (Precision < 0) + { + Precision = 0; + } + } + + /* Process qualifier */ + + Qualifier = -1; + if (*Format == 'h' || *Format == 'l' || *Format == 'L') + { + Qualifier = *Format; + ++Format; + + if (Qualifier == 'l' && *Format == 'l') + { + Qualifier = 'L'; + ++Format; + } + } + + switch (*Format) + { + case '%': + + Pos = AcpiUtBoundStringOutput (Pos, End, '%'); + continue; + + case 'c': + + if (!(Type & ACPI_FORMAT_LEFT)) + { + while (--Width > 0) + { + Pos = AcpiUtBoundStringOutput (Pos, End, ' '); + } + } + + c = (char) va_arg (Args, int); + Pos = AcpiUtBoundStringOutput (Pos, End, c); + + while (--Width > 0) + { + Pos = AcpiUtBoundStringOutput (Pos, End, ' '); + } + continue; + + case 's': + + s = va_arg (Args, char *); + if (!s) + { + s = ""; + } + Length = (INT32) AcpiUtBoundStringLength (s, Precision); + if (!(Type & ACPI_FORMAT_LEFT)) + { + while (Length < Width--) + { + Pos = AcpiUtBoundStringOutput (Pos, End, ' '); + } + } + + for (i = 0; i < Length; ++i) + { + Pos = AcpiUtBoundStringOutput (Pos, End, *s); + ++s; + } + + while (Length < Width--) + { + Pos = AcpiUtBoundStringOutput (Pos, End, ' '); + } + continue; + + case 'o': + + Base = 8; + break; + + case 'X': + + Type |= ACPI_FORMAT_UPPER; + ACPI_FALLTHROUGH; + + case 'x': + + Base = 16; + break; + + case 'd': + case 'i': + + Type |= ACPI_FORMAT_SIGN; + + case 'u': + + break; + + case 'p': + + if (Width == -1) + { + Width = 2 * sizeof (void *); + Type |= ACPI_FORMAT_ZERO; + } + + p = va_arg (Args, void *); + Pos = AcpiUtFormatNumber ( + Pos, End, ACPI_TO_INTEGER (p), 16, Width, Precision, Type); + continue; + + default: + + Pos = AcpiUtBoundStringOutput (Pos, End, '%'); + if (*Format) + { + Pos = AcpiUtBoundStringOutput (Pos, End, *Format); + } + else + { + --Format; + } + continue; + } + + if (Qualifier == 'L') + { + Number = va_arg (Args, UINT64); + if (Type & ACPI_FORMAT_SIGN) + { + Number = (INT64) Number; + } + } + else if (Qualifier == 'l') + { + Number = va_arg (Args, unsigned long); + if (Type & ACPI_FORMAT_SIGN) + { + Number = (INT32) Number; + } + } + else if (Qualifier == 'h') + { + Number = (UINT16) va_arg (Args, int); + if (Type & ACPI_FORMAT_SIGN) + { + Number = (INT16) Number; + } + } + else + { + Number = va_arg (Args, unsigned int); + if (Type & ACPI_FORMAT_SIGN) + { + Number = (signed int) Number; + } + } + + Pos = AcpiUtFormatNumber (Pos, End, Number, Base, + Width, Precision, Type); + } + + if (Size > 0) + { + if (Pos < End) + { + *Pos = '\0'; + } + else + { + End[-1] = '\0'; + } + } + + return ((int) ACPI_PTR_DIFF (Pos, String)); +} + + +/******************************************************************************* + * + * FUNCTION: snprintf + * + * PARAMETERS: String - String with boundary + * Size - Boundary of the string + * Format, ... - Standard printf format + * + * RETURN: Number of bytes actually written. + * + * DESCRIPTION: Formatted output to a string. + * + ******************************************************************************/ + +int +snprintf ( + char *String, + ACPI_SIZE Size, + const char *Format, + ...) +{ + va_list Args; + int Length; + + + va_start (Args, Format); + Length = vsnprintf (String, Size, Format, Args); + va_end (Args); + + return (Length); +} + + +/******************************************************************************* + * + * FUNCTION: sprintf + * + * PARAMETERS: String - String with boundary + * Format, ... - Standard printf format + * + * RETURN: Number of bytes actually written. + * + * DESCRIPTION: Formatted output to a string. + * + ******************************************************************************/ + +int +sprintf ( + char *String, + const char *Format, + ...) +{ + va_list Args; + int Length; + + + va_start (Args, Format); + Length = vsnprintf (String, ACPI_UINT32_MAX, Format, Args); + va_end (Args); + + return (Length); +} + + +#ifdef ACPI_APPLICATION +/******************************************************************************* + * + * FUNCTION: vprintf + * + * PARAMETERS: Format - Standard printf format + * Args - Argument list + * + * RETURN: Number of bytes actually written. + * + * DESCRIPTION: Formatted output to stdout using argument list pointer. + * + ******************************************************************************/ + +int +vprintf ( + const char *Format, + va_list Args) +{ + ACPI_CPU_FLAGS Flags; + int Length; + + + Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock); + Length = vsnprintf (AcpiGbl_PrintBuffer, + sizeof (AcpiGbl_PrintBuffer), Format, Args); + + (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, ACPI_FILE_OUT); + AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags); + + return (Length); +} + + +/******************************************************************************* + * + * FUNCTION: printf + * + * PARAMETERS: Format, ... - Standard printf format + * + * RETURN: Number of bytes actually written. + * + * DESCRIPTION: Formatted output to stdout. + * + ******************************************************************************/ + +int +printf ( + const char *Format, + ...) +{ + va_list Args; + int Length; + + + va_start (Args, Format); + Length = vprintf (Format, Args); + va_end (Args); + + return (Length); +} + + +/******************************************************************************* + * + * FUNCTION: vfprintf + * + * PARAMETERS: File - File descriptor + * Format - Standard printf format + * Args - Argument list + * + * RETURN: Number of bytes actually written. + * + * DESCRIPTION: Formatted output to a file using argument list pointer. + * + ******************************************************************************/ + +int +vfprintf ( + FILE *File, + const char *Format, + va_list Args) +{ + ACPI_CPU_FLAGS Flags; + int Length; + + + Flags = AcpiOsAcquireLock (AcpiGbl_PrintLock); + Length = vsnprintf (AcpiGbl_PrintBuffer, + sizeof (AcpiGbl_PrintBuffer), Format, Args); + + (void) fwrite (AcpiGbl_PrintBuffer, Length, 1, File); + AcpiOsReleaseLock (AcpiGbl_PrintLock, Flags); + + return (Length); +} + + +/******************************************************************************* + * + * FUNCTION: fprintf + * + * PARAMETERS: File - File descriptor + * Format, ... - Standard printf format + * + * RETURN: Number of bytes actually written. + * + * DESCRIPTION: Formatted output to a file. + * + ******************************************************************************/ + +int +fprintf ( + FILE *File, + const char *Format, + ...) +{ + va_list Args; + int Length; + + + va_start (Args, Format); + Length = vfprintf (File, Format, Args); + va_end (Args); + + return (Length); +} +#endif diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utresdecode.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utresdecode.c new file mode 100644 index 0000000..d4f9130 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utresdecode.c @@ -0,0 +1,345 @@ +/******************************************************************************* + * + * Module Name: utresdecode - Resource descriptor keyword strings + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utresdecode") + + +#if defined (ACPI_DEBUG_OUTPUT) || \ + defined (ACPI_DISASSEMBLER) || \ + defined (ACPI_DEBUGGER) + +/* + * Strings used to decode resource descriptors. + * Used by both the disassembler 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", + "ActiveBoth", + "Reserved" +}; + +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_PhyDecode[] = +{ + "Type C", + "Type D", + "Unknown Type", + "Unknown Type" +}; + +const char *AcpiGbl_RngDecode[] = +{ + "InvalidRanges", + "NonISAOnlyRanges", + "ISAOnlyRanges", + "EntireRange" +}; + +const char *AcpiGbl_RwDecode[] = +{ + "ReadOnly", + "ReadWrite" +}; + +const char *AcpiGbl_ShrDecode[] = +{ + "Exclusive", + "Shared", + "ExclusiveAndWake", /* ACPI 5.0 */ + "SharedAndWake" /* ACPI 5.0 */ +}; + +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", + "CSI2" +}; + +/* 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[] = +{ + "StopBitsZero", + "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 */" +}; + +/* PinConfig type */ + +const char *AcpiGbl_PtypDecode[] = +{ + "Default", + "Bias Pull-up", + "Bias Pull-down", + "Bias Default", + "Bias Disable", + "Bias High Impedance", + "Bias Bus Hold", + "Drive Open Drain", + "Drive Open Source", + "Drive Push Pull", + "Drive Strength", + "Slew Rate", + "Input Debounce", + "Input Schmitt Trigger", +}; + +const char *AcpiGbl_ClockInputMode[] = +{ + "Fixed", + "Variable", +}; + +const char *AcpiGbl_ClockInputScale[] = +{ + "Hz", + "KHz", + "MHz", +}; + +#endif diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utresrc.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utresrc.c new file mode 100644 index 0000000..46341ce --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utresrc.c @@ -0,0 +1,665 @@ +/******************************************************************************* + * + * Module Name: utresrc - Resource management utilities + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acresrc.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utresrc") + + +/* + * 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), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_PIN_FUNCTION), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_COMMON_SERIALBUS), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_PIN_CONFIG), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_PIN_GROUP), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_PIN_GROUP_FUNCTION), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_PIN_GROUP_CONFIG), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_CLOCK_INPUT), + +}; + +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), + ACPI_AML_SIZE_LARGE (AML_RESOURCE_CSI2_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* */ + ACPI_VARIABLE_LENGTH, /* 0D PinFunction */ + ACPI_VARIABLE_LENGTH, /* 0E *SerialBus */ + ACPI_VARIABLE_LENGTH, /* 0F PinConfig */ + ACPI_VARIABLE_LENGTH, /* 10 PinGroup */ + ACPI_VARIABLE_LENGTH, /* 11 PinGroupFunction */ + ACPI_VARIABLE_LENGTH, /* 12 PinGroupConfig */ + ACPI_VARIABLE_LENGTH, /* 13 ClockInput */ +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiUtWalkAmlResources + * + * PARAMETERS: WalkState - Current walk info + * 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 ( + ACPI_WALK_STATE *WalkState, + 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 that the remaining buffer space can hold enough + * bytes to safely access fields during validation. + * For large resource descriptors (bit 7 set), we need enough + * bytes to access the Type field in SerialBus resources. + * Small resource descriptors only need sizeof(AML_RESOURCE_END_TAG). + */ + if ((ACPI_SIZE) (EndAml - Aml) < sizeof (AML_RESOURCE_END_TAG)) + { + return_ACPI_STATUS (AE_AML_BUFFER_LENGTH); + } + + /* + * For large resource descriptors, ensure enough space for + * the header plus SerialBus Type field access. + */ + if ((ACPI_GET8 (Aml) & ACPI_RESOURCE_NAME_LARGE) && + ((ACPI_SIZE) (EndAml - Aml) < + ACPI_OFFSET (AML_RESOURCE_COMMON_SERIALBUS, Type) + 1)) + { + return_ACPI_STATUS (AE_AML_BUFFER_LENGTH); + } + + /* Validate the Resource Type and Resource Length */ + + Status = AcpiUtValidateResource (WalkState, 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); + + /* + * Validate that the descriptor length doesn't exceed the + * remaining buffer size to prevent reading beyond the end. + */ + if (Length > (ACPI_SIZE) (EndAml - Aml)) + { + return_ACPI_STATUS (AE_AML_BUFFER_LENGTH); + } + + /* 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); + } + + /* + * Don't attempt to perform any validation on the 2nd byte. + * Although all known ASL compilers insert a zero for the 2nd + * byte, it can also be a checksum (as per the ACPI spec), + * and this is occasionally seen in the field. July 2017. + */ + + /* Return the pointer to the EndTag if requested */ + + if (!UserFunction) + { + *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 (WalkState, 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: WalkState - Current walk info + * 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 ( + ACPI_WALK_STATE *WalkState, + 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)) + { + if (WalkState) + { + ACPI_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: + + if (WalkState) + { + ACPI_ERROR ((AE_INFO, + "Invalid/unsupported resource descriptor: Type 0x%2.2X", + ResourceType)); + } + return (AE_AML_INVALID_RESOURCE_TYPE); + +BadResourceLength: + + if (WalkState) + { + ACPI_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 (NULL, ObjDesc->Buffer.Pointer, + ObjDesc->Buffer.Length, NULL, (void **) EndTag); + + return_ACPI_STATUS (Status); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utstate.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utstate.c new file mode 100644 index 0000000..ebc05a4 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utstate.c @@ -0,0 +1,324 @@ +/******************************************************************************* + * + * Module Name: utstate - state object support procedures + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utstate") + + +/******************************************************************************* + * + * 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_ENTRY (); + + + /* Push the state object onto the front of the list (stack) */ + + State->Common.Next = *ListHead; + *ListHead = State; + return; +} + + +/******************************************************************************* + * + * 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_ENTRY (); + + + /* Remove the state object at the head of the list (stack) */ + + State = *ListHead; + if (State) + { + /* Update the list head */ + + *ListHead = State->Common.Next; + } + + return (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_ENTRY (); + + + /* Create the generic state object */ + + State = AcpiUtCreateGenericState (); + if (!State) + { + return (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 ((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_ENTRY (); + + + /* Create the generic state object */ + + State = AcpiUtCreateGenericState (); + if (!State) + { + return (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 (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, + UINT32 Index) +{ + ACPI_GENERIC_STATE *State; + + + ACPI_FUNCTION_ENTRY (); + + + /* Create the generic state object */ + + State = AcpiUtCreateGenericState (); + if (!State) + { + return (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 (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_ENTRY (); + + + /* Create the generic state object */ + + State = AcpiUtCreateGenericState (); + if (!State) + { + return (NULL); + } + + /* Init fields specific to the control struct */ + + State->Common.DescriptorType = ACPI_DESC_TYPE_STATE_CONTROL; + State->Common.State = ACPI_CONTROL_CONDITIONAL_EXECUTING; + + return (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_ENTRY (); + + + /* Ignore null state */ + + if (State) + { + (void) AcpiOsReleaseObject (AcpiGbl_StateCache, State); + } + + return; +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utstring.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utstring.c new file mode 100644 index 0000000..9831b3e --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utstring.c @@ -0,0 +1,247 @@ +/******************************************************************************* + * + * Module Name: utstring - Common functions for strings and characters + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" +#include "acnamesp.h" + + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utstring") + + +/******************************************************************************* + * + * FUNCTION: AcpiUtPrintString + * + * PARAMETERS: String - Null terminated ASCII string + * MaxLength - Maximum output length. Used to constrain the + * length of strings during debug output only. + * + * RETURN: None + * + * DESCRIPTION: Dump an ASCII string with support for ACPI-defined escape + * sequences. + * + ******************************************************************************/ + +void +AcpiUtPrintString ( + char *String, + UINT16 MaxLength) +{ + UINT32 i; + + + if (!String) + { + AcpiOsPrintf ("<\"NULL STRING PTR\">"); + return; + } + + AcpiOsPrintf ("\""); + for (i = 0; (i < MaxLength) && String[i]; 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 (isprint ((int) 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: 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; + UINT32 OriginalName; + + + ACPI_FUNCTION_NAME (UtRepairName); + + + /* + * Special case for the root node. This can happen if we get an + * error during the execution of module-level code. + */ + if (ACPI_COMPARE_NAMESEG (Name, ACPI_ROOT_PATHNAME)) + { + return; + } + + ACPI_COPY_NAMESEG (&OriginalName, &Name[0]); + + /* Check each character in the name */ + + for (i = 0; i < ACPI_NAMESEG_SIZE; i++) + { + if (AcpiUtValidNameChar (Name[i], i)) + { + continue; + } + + /* + * Replace a bad character with something printable, yet technically + * "odd". 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, + "Invalid character(s) in name (0x%.8X) %p, repaired: [%4.4s]", + OriginalName, Name, &Name[0])); + } + else + { + ACPI_DEBUG_PRINT ((ACPI_DB_INFO, + "Invalid character(s) in name (0x%.8X), repaired: [%4.4s]", + OriginalName, Name)); + } + } +} + + +#if defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP +/******************************************************************************* + * + * FUNCTION: UtConvertBackslashes + * + * PARAMETERS: Pathname - File pathname string to be converted + * + * RETURN: Modifies the input Pathname + * + * DESCRIPTION: Convert all backslashes (0x5C) to forward slashes (0x2F) within + * the entire input file pathname string. + * + ******************************************************************************/ + +void +UtConvertBackslashes ( + char *Pathname) +{ + + if (!Pathname) + { + return; + } + + while (*Pathname) + { + if (*Pathname == '\\') + { + *Pathname = '/'; + } + + Pathname++; + } +} +#endif diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utstrsuppt.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utstrsuppt.c new file mode 100644 index 0000000..79ce275 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utstrsuppt.c @@ -0,0 +1,525 @@ +/******************************************************************************* + * + * Module Name: utstrsuppt - Support functions for string-to-integer conversion + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utstrsuppt") + + +/* Local prototypes */ + +static ACPI_STATUS +AcpiUtInsertDigit ( + UINT64 *AccumulatedValue, + UINT32 Base, + int AsciiDigit); + +static ACPI_STATUS +AcpiUtStrtoulMultiply64 ( + UINT64 Multiplicand, + UINT32 Base, + UINT64 *OutProduct); + +static ACPI_STATUS +AcpiUtStrtoulAdd64 ( + UINT64 Addend1, + UINT32 Digit, + UINT64 *OutSum); + + +/******************************************************************************* + * + * FUNCTION: AcpiUtConvertOctalString + * + * PARAMETERS: String - Null terminated input string + * ReturnValuePtr - Where the converted value is returned + * + * RETURN: Status and 64-bit converted integer + * + * DESCRIPTION: Performs a base 8 conversion of the input string to an + * integer value, either 32 or 64 bits. + * + * NOTE: Maximum 64-bit unsigned octal value is 01777777777777777777777 + * Maximum 32-bit unsigned octal value is 037777777777 + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtConvertOctalString ( + char *String, + UINT64 *ReturnValuePtr) +{ + UINT64 AccumulatedValue = 0; + ACPI_STATUS Status = AE_OK; + + + /* Convert each ASCII byte in the input string */ + + while (*String) + { + /* + * Character must be ASCII 0-7, otherwise: + * 1) Runtime: terminate with no error, per the ACPI spec + * 2) Compiler: return an error + */ + if (!(ACPI_IS_OCTAL_DIGIT (*String))) + { +#ifdef ACPI_ASL_COMPILER + Status = AE_BAD_OCTAL_CONSTANT; +#endif + break; + } + + /* Convert and insert this octal digit into the accumulator */ + + Status = AcpiUtInsertDigit (&AccumulatedValue, 8, *String); + if (ACPI_FAILURE (Status)) + { + Status = AE_OCTAL_OVERFLOW; + break; + } + + String++; + } + + /* Always return the value that has been accumulated */ + + *ReturnValuePtr = AccumulatedValue; + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtConvertDecimalString + * + * PARAMETERS: String - Null terminated input string + * ReturnValuePtr - Where the converted value is returned + * + * RETURN: Status and 64-bit converted integer + * + * DESCRIPTION: Performs a base 10 conversion of the input string to an + * integer value, either 32 or 64 bits. + * + * NOTE: Maximum 64-bit unsigned decimal value is 18446744073709551615 + * Maximum 32-bit unsigned decimal value is 4294967295 + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtConvertDecimalString ( + char *String, + UINT64 *ReturnValuePtr) +{ + UINT64 AccumulatedValue = 0; + ACPI_STATUS Status = AE_OK; + + + /* Convert each ASCII byte in the input string */ + + while (*String) + { + /* + * Character must be ASCII 0-9, otherwise: + * 1) Runtime: terminate with no error, per the ACPI spec + * 2) Compiler: return an error + */ + if (!isdigit ((int) *String)) + { +#ifdef ACPI_ASL_COMPILER + Status = AE_BAD_DECIMAL_CONSTANT; +#endif + break; + } + + /* Convert and insert this decimal digit into the accumulator */ + + Status = AcpiUtInsertDigit (&AccumulatedValue, 10, *String); + if (ACPI_FAILURE (Status)) + { + Status = AE_DECIMAL_OVERFLOW; + break; + } + + String++; + } + + /* Always return the value that has been accumulated */ + + *ReturnValuePtr = AccumulatedValue; + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtConvertHexString + * + * PARAMETERS: String - Null terminated input string + * ReturnValuePtr - Where the converted value is returned + * + * RETURN: Status and 64-bit converted integer + * + * DESCRIPTION: Performs a base 16 conversion of the input string to an + * integer value, either 32 or 64 bits. + * + * NOTE: Maximum 64-bit unsigned hex value is 0xFFFFFFFFFFFFFFFF + * Maximum 32-bit unsigned hex value is 0xFFFFFFFF + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtConvertHexString ( + char *String, + UINT64 *ReturnValuePtr) +{ + UINT64 AccumulatedValue = 0; + ACPI_STATUS Status = AE_OK; + + + /* Convert each ASCII byte in the input string */ + + while (*String) + { + /* + * Character must be ASCII A-F, a-f, or 0-9, otherwise: + * 1) Runtime: terminate with no error, per the ACPI spec + * 2) Compiler: return an error + */ + if (!isxdigit ((int) *String)) + { +#ifdef ACPI_ASL_COMPILER + Status = AE_BAD_HEX_CONSTANT; +#endif + break; + } + + /* Convert and insert this hex digit into the accumulator */ + + Status = AcpiUtInsertDigit (&AccumulatedValue, 16, *String); + if (ACPI_FAILURE (Status)) + { + Status = AE_HEX_OVERFLOW; + break; + } + + String++; + } + + /* Always return the value that has been accumulated */ + + *ReturnValuePtr = AccumulatedValue; + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtRemoveLeadingZeros + * + * PARAMETERS: String - Pointer to input ASCII string + * + * RETURN: Next character after any leading zeros. This character may be + * used by the caller to detect end-of-string. + * + * DESCRIPTION: Remove any leading zeros in the input string. Return the + * next character after the final ASCII zero to enable the caller + * to check for the end of the string (NULL terminator). + * + ******************************************************************************/ + +char +AcpiUtRemoveLeadingZeros ( + char **String) +{ + + while (**String == ACPI_ASCII_ZERO) + { + *String += 1; + } + + return (**String); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtRemoveWhitespace + * + * PARAMETERS: String - Pointer to input ASCII string + * + * RETURN: Next character after any whitespace. This character may be + * used by the caller to detect end-of-string. + * + * DESCRIPTION: Remove any leading whitespace in the input string. Return the + * next character after the final ASCII zero to enable the caller + * to check for the end of the string (NULL terminator). + * + ******************************************************************************/ + +char +AcpiUtRemoveWhitespace ( + char **String) +{ + + while (isspace ((UINT8) **String)) + { + *String += 1; + } + + return (**String); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDetectHexPrefix + * + * PARAMETERS: String - Pointer to input ASCII string + * + * RETURN: TRUE if a "0x" prefix was found at the start of the string + * + * DESCRIPTION: Detect and remove a hex "0x" prefix + * + ******************************************************************************/ + +BOOLEAN +AcpiUtDetectHexPrefix ( + char **String) +{ + char *InitialPosition = *String; + + AcpiUtRemoveHexPrefix (String); + if (*String != InitialPosition) + { + return (TRUE); /* String is past leading 0x */ + } + + return (FALSE); /* Not a hex string */ +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtRemoveHexPrefix + * + * PARAMETERS: String - Pointer to input ASCII string + * + * RETURN: none + * + * DESCRIPTION: Remove a hex "0x" prefix + * + ******************************************************************************/ + +void +AcpiUtRemoveHexPrefix ( + char **String) +{ + if ((**String == ACPI_ASCII_ZERO) && + (tolower ((int) *(*String + 1)) == 'x')) + { + *String += 2; /* Go past the leading 0x */ + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDetectOctalPrefix + * + * PARAMETERS: String - Pointer to input ASCII string + * + * RETURN: True if an octal "0" prefix was found at the start of the + * string + * + * DESCRIPTION: Detect and remove an octal prefix (zero) + * + ******************************************************************************/ + +BOOLEAN +AcpiUtDetectOctalPrefix ( + char **String) +{ + + if (**String == ACPI_ASCII_ZERO) + { + *String += 1; /* Go past the leading 0 */ + return (TRUE); + } + + return (FALSE); /* Not an octal string */ +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtInsertDigit + * + * PARAMETERS: AccumulatedValue - Current value of the integer value + * accumulator. The new value is + * returned here. + * Base - Radix, either 8/10/16 + * AsciiDigit - ASCII single digit to be inserted + * + * RETURN: Status and result of the convert/insert operation. The only + * possible returned exception code is numeric overflow of + * either the multiply or add conversion operations. + * + * DESCRIPTION: Generic conversion and insertion function for all bases: + * + * 1) Multiply the current accumulated/converted value by the + * base in order to make room for the new character. + * + * 2) Convert the new character to binary and add it to the + * current accumulated value. + * + * Note: The only possible exception indicates an integer + * overflow (AE_NUMERIC_OVERFLOW) + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtInsertDigit ( + UINT64 *AccumulatedValue, + UINT32 Base, + int AsciiDigit) +{ + ACPI_STATUS Status; + UINT64 Product; + + + /* Make room in the accumulated value for the incoming digit */ + + Status = AcpiUtStrtoulMultiply64 (*AccumulatedValue, Base, &Product); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Add in the new digit, and store the sum to the accumulated value */ + + Status = AcpiUtStrtoulAdd64 (Product, AcpiUtAsciiCharToHex (AsciiDigit), + AccumulatedValue); + + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrtoulMultiply64 + * + * PARAMETERS: Multiplicand - Current accumulated converted integer + * Base - Base/Radix + * OutProduct - Where the product is returned + * + * RETURN: Status and 64-bit product + * + * DESCRIPTION: Multiply two 64-bit values, with checking for 64-bit overflow as + * well as 32-bit overflow if necessary (if the current global + * integer width is 32). + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtStrtoulMultiply64 ( + UINT64 Multiplicand, + UINT32 Base, + UINT64 *OutProduct) +{ + UINT64 Product; + UINT64 Quotient; + + + /* Exit if either operand is zero */ + + *OutProduct = 0; + if (!Multiplicand || !Base) + { + return (AE_OK); + } + + /* + * Check for 64-bit overflow before the actual multiplication. + * + * Notes: 64-bit division is often not supported on 32-bit platforms + * (it requires a library function), Therefore ACPICA has a local + * 64-bit divide function. Also, Multiplier is currently only used + * as the radix (8/10/16), to the 64/32 divide will always work. + */ + AcpiUtShortDivide (ACPI_UINT64_MAX, Base, &Quotient, NULL); + if (Multiplicand > Quotient) + { + return (AE_NUMERIC_OVERFLOW); + } + + Product = Multiplicand * Base; + + /* Check for 32-bit overflow if necessary */ + + if ((AcpiGbl_IntegerBitWidth == 32) && (Product > ACPI_UINT32_MAX)) + { + return (AE_NUMERIC_OVERFLOW); + } + + *OutProduct = Product; + return (AE_OK); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrtoulAdd64 + * + * PARAMETERS: Addend1 - Current accumulated converted integer + * Digit - New hex value/char + * OutSum - Where sum is returned (Accumulator) + * + * RETURN: Status and 64-bit sum + * + * DESCRIPTION: Add two 64-bit values, with checking for 64-bit overflow as + * well as 32-bit overflow if necessary (if the current global + * integer width is 32). + * + ******************************************************************************/ + +static ACPI_STATUS +AcpiUtStrtoulAdd64 ( + UINT64 Addend1, + UINT32 Digit, + UINT64 *OutSum) +{ + UINT64 Sum; + + + /* Check for 64-bit overflow before the actual addition */ + + if ((Addend1 > 0) && (Digit > (ACPI_UINT64_MAX - Addend1))) + { + return (AE_NUMERIC_OVERFLOW); + } + + Sum = Addend1 + Digit; + + /* Check for 32-bit overflow if necessary */ + + if ((AcpiGbl_IntegerBitWidth == 32) && (Sum > ACPI_UINT32_MAX)) + { + return (AE_NUMERIC_OVERFLOW); + } + + *OutSum = Sum; + return (AE_OK); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utstrtoul64.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utstrtoul64.c new file mode 100644 index 0000000..c9fb250 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utstrtoul64.c @@ -0,0 +1,364 @@ +/******************************************************************************* + * + * Module Name: utstrtoul64 - String-to-integer conversion support for both + * 64-bit and 32-bit integers + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utstrtoul64") + + +/******************************************************************************* + * + * This module contains the top-level string to 64/32-bit unsigned integer + * conversion functions: + * + * 1) A standard strtoul() function that supports 64-bit integers, base + * 8/10/16, with integer overflow support. This is used mainly by the + * iASL compiler, which implements tighter constraints on integer + * constants than the runtime (interpreter) integer-to-string conversions. + * 2) Runtime "Explicit conversion" as defined in the ACPI specification. + * 3) Runtime "Implicit conversion" as defined in the ACPI specification. + * + * Current users of this module: + * + * iASL - Preprocessor (constants and math expressions) + * iASL - Main parser, conversion of constants to integers + * iASL - Data Table Compiler parser (constants and math expressions) + * Interpreter - Implicit and explicit conversions, GPE method names + * Interpreter - Repair code for return values from predefined names + * Debugger - Command line input string conversion + * AcpiDump - ACPI table physical addresses + * AcpiExec - Support for namespace overrides + * + * Notes concerning users of these interfaces: + * + * AcpiGbl_IntegerByteWidth is used to set the 32/64 bit limit for explicit + * and implicit conversions. This global must be set to the proper width. + * For the core ACPICA code, the width depends on the DSDT version. For the + * AcpiUtStrtoul64 interface, all conversions are 64 bits. This interface is + * used primarily for iASL, where the default width is 64 bits for all parsers, + * but error checking is performed later to flag cases where a 64-bit constant + * is wrongly defined in a 32-bit DSDT/SSDT. + * + * In ACPI, the only place where octal numbers are supported is within + * the ASL language itself. This is implemented via the main AcpiUtStrtoul64 + * interface. According the ACPI specification, there is no ACPI runtime + * support (explicit/implicit) for octal string conversions. + * + ******************************************************************************/ + + +/******************************************************************************* + * + * FUNCTION: AcpiUtStrtoul64 + * + * PARAMETERS: String - Null terminated input string, + * must be a valid pointer + * ReturnValue - Where the converted integer is + * returned. Must be a valid pointer + * + * RETURN: Status and converted integer. Returns an exception on a + * 64-bit numeric overflow + * + * DESCRIPTION: Convert a string into an unsigned integer. Always performs a + * full 64-bit conversion, regardless of the current global + * integer width. Supports Decimal, Hex, and Octal strings. + * + * Current users of this function: + * + * iASL - Preprocessor (constants and math expressions) + * iASL - Main ASL parser, conversion of ASL constants to integers + * iASL - Data Table Compiler parser (constants and math expressions) + * Interpreter - Repair code for return values from predefined names + * AcpiDump - ACPI table physical addresses + * AcpiExec - Support for namespace overrides + * + ******************************************************************************/ + +ACPI_STATUS +AcpiUtStrtoul64 ( + char *String, + UINT64 *ReturnValue) +{ + ACPI_STATUS Status = AE_OK; + UINT8 OriginalBitWidth; + UINT32 Base = 10; /* Default is decimal */ + + + ACPI_FUNCTION_TRACE_STR (UtStrtoul64, String); + + + *ReturnValue = 0; + + /* A NULL return string returns a value of zero */ + + if (*String == 0) + { + return_ACPI_STATUS (AE_OK); + } + + if (!AcpiUtRemoveWhitespace (&String)) + { + return_ACPI_STATUS (AE_OK); + } + + /* + * 1) Check for a hex constant. A "0x" prefix indicates base 16. + */ + if (AcpiUtDetectHexPrefix (&String)) + { + Base = 16; + } + + /* + * 2) Check for an octal constant, defined to be a leading zero + * followed by sequence of octal digits (0-7) + */ + else if (AcpiUtDetectOctalPrefix (&String)) + { + Base = 8; + } + + if (!AcpiUtRemoveLeadingZeros (&String)) + { + return_ACPI_STATUS (AE_OK); /* Return value 0 */ + } + + /* + * Force a full 64-bit conversion. The caller (usually iASL) must + * check for a 32-bit overflow later as necessary (If current mode + * is 32-bit, meaning a 32-bit DSDT). + */ + OriginalBitWidth = AcpiGbl_IntegerBitWidth; + AcpiGbl_IntegerBitWidth = 64; + + /* + * Perform the base 8, 10, or 16 conversion. A 64-bit numeric overflow + * will return an exception (to allow iASL to flag the statement). + */ + switch (Base) + { + case 8: + Status = AcpiUtConvertOctalString (String, ReturnValue); + break; + + case 10: + Status = AcpiUtConvertDecimalString (String, ReturnValue); + break; + + case 16: + default: + Status = AcpiUtConvertHexString (String, ReturnValue); + break; + } + + /* Only possible exception from above is a 64-bit overflow */ + + AcpiGbl_IntegerBitWidth = OriginalBitWidth; + return_ACPI_STATUS (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtImplicitStrtoul64 + * + * PARAMETERS: String - Null terminated input string, + * must be a valid pointer + * + * RETURN: Converted integer + * + * DESCRIPTION: Perform a 64-bit conversion with restrictions placed upon + * an "implicit conversion" by the ACPI specification. Used by + * many ASL operators that require an integer operand, and support + * an automatic (implicit) conversion from a string operand + * to the final integer operand. The major restriction is that + * only hex strings are supported. + * + * ----------------------------------------------------------------------------- + * + * Base is always 16, either with or without the 0x prefix. Decimal and + * Octal strings are not supported, as per the ACPI specification. + * + * Examples (both are hex values): + * Add ("BA98", Arg0, Local0) + * Subtract ("0x12345678", Arg1, Local1) + * + * Conversion rules as extracted from the ACPI specification: + * + * The converted integer is initialized to the value zero. + * The ASCII string is always interpreted as a hexadecimal constant. + * + * 1) According to the ACPI specification, a "0x" prefix is not allowed. + * However, ACPICA allows this as an ACPI extension on general + * principle. (NO ERROR) + * + * 2) The conversion terminates when the size of an integer is reached + * (32 or 64 bits). There are no numeric overflow conditions. (NO ERROR) + * + * 3) The first non-hex character terminates the conversion and returns + * the current accumulated value of the converted integer (NO ERROR). + * + * 4) Conversion of a null (zero-length) string to an integer is + * technically not allowed. However, ACPICA allows this as an ACPI + * extension. The conversion returns the value 0. (NO ERROR) + * + * NOTE: There are no error conditions returned by this function. At + * the minimum, a value of zero is returned. + * + * Current users of this function: + * + * Interpreter - All runtime implicit conversions, as per ACPI specification + * iASL - Data Table Compiler parser (constants and math expressions) + * + ******************************************************************************/ + +UINT64 +AcpiUtImplicitStrtoul64 ( + char *String) +{ + UINT64 ConvertedInteger = 0; + + + ACPI_FUNCTION_TRACE_STR (UtImplicitStrtoul64, String); + + + if (!AcpiUtRemoveWhitespace (&String)) + { + return_VALUE (0); + } + + /* + * Per the ACPI specification, only hexadecimal is supported for + * implicit conversions, and the "0x" prefix is "not allowed". + * However, allow a "0x" prefix as an ACPI extension. + */ + AcpiUtRemoveHexPrefix (&String); + + if (!AcpiUtRemoveLeadingZeros (&String)) + { + return_VALUE (0); + } + + /* + * Ignore overflow as per the ACPI specification. This is implemented by + * ignoring the return status from the conversion function called below. + * On overflow, the input string is simply truncated. + */ + AcpiUtConvertHexString (String, &ConvertedInteger); + return_VALUE (ConvertedInteger); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtExplicitStrtoul64 + * + * PARAMETERS: String - Null terminated input string, + * must be a valid pointer + * + * RETURN: Converted integer + * + * DESCRIPTION: Perform a 64-bit conversion with the restrictions placed upon + * an "explicit conversion" by the ACPI specification. The + * main restriction is that only hex and decimal are supported. + * + * ----------------------------------------------------------------------------- + * + * Base is either 10 (default) or 16 (with 0x prefix). Octal (base 8) strings + * are not supported, as per the ACPI specification. + * + * Examples: + * ToInteger ("1000") Decimal + * ToInteger ("0xABCD") Hex + * + * Conversion rules as extracted from the ACPI specification: + * + * 1) The input string is either a decimal or hexadecimal numeric string. + * A hex value must be prefixed by "0x" or it is interpreted as decimal. + * + * 2) The value must not exceed the maximum of an integer value + * (32 or 64 bits). The ACPI specification states the behavior is + * "unpredictable", so ACPICA matches the behavior of the implicit + * conversion case. There are no numeric overflow conditions. (NO ERROR) + * + * 3) Behavior on the first non-hex character is not defined by the ACPI + * specification (for the ToInteger operator), so ACPICA matches the + * behavior of the implicit conversion case. It terminates the + * conversion and returns the current accumulated value of the converted + * integer. (NO ERROR) + * + * 4) Conversion of a null (zero-length) string to an integer is + * technically not allowed. However, ACPICA allows this as an ACPI + * extension. The conversion returns the value 0. (NO ERROR) + * + * NOTE: There are no error conditions returned by this function. At the + * minimum, a value of zero is returned. + * + * Current users of this function: + * + * Interpreter - Runtime ASL ToInteger operator, as per the ACPI specification + * + ******************************************************************************/ + +UINT64 +AcpiUtExplicitStrtoul64 ( + char *String) +{ + UINT64 ConvertedInteger = 0; + UINT32 Base = 10; /* Default is decimal */ + + + ACPI_FUNCTION_TRACE_STR (UtExplicitStrtoul64, String); + + + if (!AcpiUtRemoveWhitespace (&String)) + { + return_VALUE (0); + } + + /* + * Only Hex and Decimal are supported, as per the ACPI specification. + * A "0x" prefix indicates hex; otherwise decimal is assumed. + */ + if (AcpiUtDetectHexPrefix (&String)) + { + Base = 16; + } + + if (!AcpiUtRemoveLeadingZeros (&String)) + { + return_VALUE (0); + } + + /* + * Ignore overflow as per the ACPI specification. This is implemented by + * ignoring the return status from the conversion functions called below. + * On overflow, the input string is simply truncated. + */ + switch (Base) + { + case 10: + default: + AcpiUtConvertDecimalString (String, &ConvertedInteger); + break; + + case 16: + AcpiUtConvertHexString (String, &ConvertedInteger); + break; + } + + return_VALUE (ConvertedInteger); +} diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/uttrack.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/uttrack.c new file mode 100644 index 0000000..d5de827 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/uttrack.c @@ -0,0 +1,771 @@ +/****************************************************************************** + * + * Module Name: uttrack - Memory allocation tracking routines (debug only) + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +/* + * 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. + */ + +#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 ( + ACPI_DEBUG_MEM_BLOCK *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 ( + const char *ListName, + UINT16 ObjectSize, + ACPI_MEMORY_LIST **ReturnCache) +{ + ACPI_MEMORY_LIST *Cache; + + + Cache = AcpiOsAllocateZeroed (sizeof (ACPI_MEMORY_LIST)); + if (!Cache) + { + return (AE_NO_MEMORY); + } + + 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; + + + /* 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 + sizeof (ACPI_DEBUG_MEM_HEADER)); + if (!Allocation) + { + /* Report allocation error */ + + ACPI_WARNING ((Module, Line, + "Could not allocate size %u", (UINT32) Size)); + + 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; + + + /* 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 = AcpiOsAllocateZeroed ( + Size + sizeof (ACPI_DEBUG_MEM_HEADER)); + 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 (block %p)\n", + Allocation, DebugBlock)); + return_VOID; +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtFindAllocation + * + * PARAMETERS: Allocation - Address of allocated memory + * + * RETURN: Three cases: + * 1) List is empty, NULL is returned. + * 2) Element was found. Returns Allocation parameter. + * 3) Element was not found. Returns position where it should be + * inserted into the list. + * + * DESCRIPTION: Searches for an element in the global allocation tracking list. + * If the element is not found, returns the location within the + * list where the element should be inserted. + * + * Note: The list is ordered by larger-to-smaller addresses. + * + * This global list is used to detect memory leaks in ACPICA as + * well as other issues such as an attempt to release the same + * internal object more than once. Although expensive as far + * as cpu time, this list is much more helpful for finding these + * types of issues than using memory leak detectors outside of + * the ACPICA code. + * + ******************************************************************************/ + +static ACPI_DEBUG_MEM_BLOCK * +AcpiUtFindAllocation ( + ACPI_DEBUG_MEM_BLOCK *Allocation) +{ + ACPI_DEBUG_MEM_BLOCK *Element; + + + Element = AcpiGbl_GlobalList->ListHead; + if (!Element) + { + return (NULL); + } + + /* + * Search for the address. + * + * Note: List is ordered by larger-to-smaller addresses, on the + * assumption that a new allocation usually has a larger address + * than previous allocations. + */ + while (Element > Allocation) + { + /* Check for end-of-list */ + + if (!Element->Next) + { + return (Element); + } + + Element = Element->Next; + } + + if (Element == Allocation) + { + return (Element); + } + + return (Element->Previous); +} + + +/******************************************************************************* + * + * 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: Status + * + * 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 the global list for this address to make sure it is not + * already present. This will catch several kinds of problems. + */ + Element = AcpiUtFindAllocation (Allocation); + if (Element == Allocation) + { + ACPI_ERROR ((AE_INFO, + "UtTrackAllocation: Allocation (%p) already present in global list!", + Allocation)); + goto UnlockAndExit; + } + + /* Fill in the instance data */ + + Allocation->Size = (UINT32) Size; + Allocation->AllocType = AllocType; + Allocation->Component = Component; + Allocation->Line = Line; + + AcpiUtSafeStrncpy (Allocation->Module, (char *) Module, ACPI_MAX_MODULE_NAME); + + if (!Element) + { + /* 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; + } + else + { + /* Insert after element */ + + Allocation->Next = Element->Next; + Allocation->Previous = Element; + + if (Element->Next) + { + (Element->Next)->Previous = Allocation; + } + + Element->Next = 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: Status + * + * 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_NAME (UtRemoveAllocation); + + + if (AcpiGbl_DisableMemTracking) + { + return (AE_OK); + } + + MemList = AcpiGbl_GlobalList; + if (NULL == MemList->ListHead) + { + /* No allocations! */ + + ACPI_ERROR ((Module, Line, + "Empty allocation list, nothing to free!")); + + return (AE_OK); + } + + Status = AcpiUtAcquireMutex (ACPI_MTX_MEMORY); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* Unlink */ + + if (Allocation->Previous) + { + (Allocation->Previous)->Next = Allocation->Next; + } + else + { + MemList->ListHead = Allocation->Next; + } + + if (Allocation->Next) + { + (Allocation->Next)->Previous = Allocation->Previous; + } + + ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n", + &Allocation->UserSpace, Allocation->Size)); + + /* Mark the segment as deleted */ + + memset (&Allocation->UserSpace, 0xEA, Allocation->Size); + + Status = AcpiUtReleaseMutex (ACPI_MTX_MEMORY); + return (Status); +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtDumpAllocationInfo + * + * PARAMETERS: None + * + * 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_VOID; + } + + /* + * Walk the allocation list. + */ + if (ACPI_FAILURE (AcpiUtAcquireMutex (ACPI_MTX_MEMORY))) + { + return_VOID; + } + + if (!AcpiGbl_GlobalList) + { + goto Exit; + } + + Element = AcpiGbl_GlobalList->ListHead; + while (Element) + { + if ((Element->Component & Component) && + ((Module == NULL) || (0 == 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-%4.4u " + "[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-%4.4u [%s] ", + Descriptor, Element->Size, Element->Module, + Element->Line, AcpiUtGetDescriptorName (Descriptor)); + + /* Optional object hex dump */ + + if (AcpiGbl_VerboseLeakDump) + { + AcpiOsPrintf ("\n"); + AcpiUtDumpBuffer ((UINT8 *) Descriptor, Element->Size, + DB_BYTE_DISPLAY, 0); + } + + /* 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_OPERAND_OBJECT)) + { + DescriptorType = ACPI_DESC_TYPE_OPERAND; + } + break; + + case ACPI_DESC_TYPE_PARSER: + + if (Element->Size == sizeof (ACPI_PARSE_OBJECT)) + { + DescriptorType = ACPI_DESC_TYPE_PARSER; + } + break; + + case ACPI_DESC_TYPE_NAMED: + + if (Element->Size == sizeof (ACPI_NAMESPACE_NODE)) + { + 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%04X\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; + } + +Exit: + (void) AcpiUtReleaseMutex (ACPI_MTX_MEMORY); + + /* Print summary */ + + if (!NumOutstanding) + { + ACPI_INFO (("No outstanding allocations")); + } + else + { + ACPI_ERROR ((AE_INFO, "%u (0x%X) Outstanding cache allocations", + NumOutstanding, NumOutstanding)); + } + + return_VOID; +} + +#endif /* ACPI_DBG_TRACK_ALLOCATIONS */ diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utuuid.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utuuid.c new file mode 100644 index 0000000..44d9e02 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utuuid.c @@ -0,0 +1,121 @@ +/****************************************************************************** + * + * Module Name: utuuid -- UUID support functions + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#include "acpi.h" +#include "accommon.h" + +#define _COMPONENT ACPI_COMPILER + ACPI_MODULE_NAME ("utuuid") + + +#if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP || defined ACPI_HELP_APP) +/* + * 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. + */ +const UINT8 AcpiGbl_MapToUuidOffset[UUID_BUFFER_LENGTH] = +{ + 6,4,2,0,11,9,16,14,19,21,24,26,28,30,32,34 +}; + + +/******************************************************************************* + * + * FUNCTION: AcpiUtConvertStringToUuid + * + * PARAMETERS: InString - 36-byte formatted UUID string + * UuidBuffer - Where the 16-byte UUID buffer is returned + * + * RETURN: None. Output data is returned in the UuidBuffer + * + * DESCRIPTION: Convert a 36-byte formatted UUID string to 16-byte UUID buffer + * + ******************************************************************************/ + +void +AcpiUtConvertStringToUuid ( + char *InString, + UINT8 *UuidBuffer) +{ + UINT32 i; + + + for (i = 0; i < UUID_BUFFER_LENGTH; i++) + { + UuidBuffer[i] = (AcpiUtAsciiCharToHex ( + InString[AcpiGbl_MapToUuidOffset[i]]) << 4); + + UuidBuffer[i] |= AcpiUtAsciiCharToHex ( + InString[AcpiGbl_MapToUuidOffset[i] + 1]); + } +} + + +/******************************************************************************* + * + * FUNCTION: AcpiUtConvertUuidToString + * + * 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 +AcpiUtConvertUuidToString ( + char *UuidBuffer, + char *OutString) +{ + UINT32 i; + + + if (!UuidBuffer || !OutString) + { + return (AE_BAD_PARAMETER); + } + + for (i = 0; i < UUID_BUFFER_LENGTH; i++) + { + OutString[AcpiGbl_MapToUuidOffset[i]] = + AcpiUtHexToAsciiChar (UuidBuffer[i], 4); + + OutString[AcpiGbl_MapToUuidOffset[i] + 1] = + AcpiUtHexToAsciiChar (UuidBuffer[i], 0); + } + + /* 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); +} +#endif diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utxface.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utxface.c new file mode 100644 index 0000000..144c02b --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utxface.c @@ -0,0 +1,613 @@ +/****************************************************************************** + * + * Module Name: utxface - External interfaces, miscellaneous utility functions + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#include "acpi.h" +#include "accommon.h" +#include "acdebug.h" + +#define _COMPONENT ACPI_UTILITIES + ACPI_MODULE_NAME ("utxface") + + +/******************************************************************************* + * + * FUNCTION: AcpiTerminate + * + * PARAMETERS: None + * + * RETURN: Status + * + * DESCRIPTION: Shutdown the ACPICA subsystem and release all resources. + * + ******************************************************************************/ + +ACPI_STATUS ACPI_INIT_FUNCTION +AcpiTerminate ( + void) +{ + ACPI_STATUS Status; + + + ACPI_FUNCTION_TRACE (AcpiTerminate); + + + /* Shutdown and free all resources */ + + AcpiUtSubsystemShutdown (); + + /* Free the mutex objects */ + + AcpiUtMutexTerminate (); + + /* Now we can shutdown the OS-dependent layer */ + + Status = AcpiOsTerminate (); + return_ACPI_STATUS (Status); +} + +ACPI_EXPORT_SYMBOL_INIT (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; + + 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 || (strlen (InterfaceName) == 0)) + { + return (AE_BAD_PARAMETER); + } + + Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + /* 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 || (strlen (InterfaceName) == 0)) + { + return (AE_BAD_PARAMETER); + } + + Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + 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; + + + Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + if (Handler && AcpiGbl_InterfaceHandler) + { + Status = AE_ALREADY_EXISTS; + } + else + { + AcpiGbl_InterfaceHandler = Handler; + } + + AcpiOsReleaseMutex (AcpiGbl_OsiMutex); + return (Status); +} + +ACPI_EXPORT_SYMBOL (AcpiInstallInterfaceHandler) + + +/***************************************************************************** + * + * FUNCTION: AcpiUpdateInterfaces + * + * PARAMETERS: Action - Actions to be performed during the + * update + * + * RETURN: Status + * + * DESCRIPTION: Update _OSI interface strings, disabling or enabling OS vendor + * string or/and feature group strings. + * + ****************************************************************************/ + +ACPI_STATUS +AcpiUpdateInterfaces ( + UINT8 Action) +{ + ACPI_STATUS Status; + + + Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); + if (ACPI_FAILURE (Status)) + { + return (Status); + } + + Status = AcpiUtUpdateInterfaces (Action); + + AcpiOsReleaseMutex (AcpiGbl_OsiMutex); + return (Status); +} + + +/***************************************************************************** + * + * 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 */ + + +/******************************************************************************* + * + * FUNCTION: AcpiDecodePldBuffer + * + * PARAMETERS: InBuffer - Buffer returned by _PLD method + * Length - Length of the InBuffer + * ReturnBuffer - Where the decode buffer is returned + * + * RETURN: Status and the decoded _PLD buffer. User must deallocate + * the buffer via ACPI_FREE. + * + * DESCRIPTION: Decode the bit-packed buffer returned by the _PLD method into + * a local struct that is much more useful to an ACPI driver. + * + ******************************************************************************/ + +ACPI_STATUS +AcpiDecodePldBuffer ( + UINT8 *InBuffer, + ACPI_SIZE Length, + ACPI_PLD_INFO **ReturnBuffer) +{ + ACPI_PLD_INFO *PldInfo; + UINT32 *Buffer = ACPI_CAST_PTR (UINT32, InBuffer); + UINT32 Dword; + + + /* Parameter validation */ + + if (!InBuffer || !ReturnBuffer || (Length < ACPI_PLD_REV1_BUFFER_SIZE)) + { + return (AE_BAD_PARAMETER); + } + + PldInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_PLD_INFO)); + if (!PldInfo) + { + return (AE_NO_MEMORY); + } + + /* First 32-bit DWord */ + + ACPI_MOVE_32_TO_32 (&Dword, &Buffer[0]); + PldInfo->Revision = ACPI_PLD_GET_REVISION (&Dword); + PldInfo->IgnoreColor = ACPI_PLD_GET_IGNORE_COLOR (&Dword); + PldInfo->Red = ACPI_PLD_GET_RED (&Dword); + PldInfo->Green = ACPI_PLD_GET_GREEN (&Dword); + PldInfo->Blue = ACPI_PLD_GET_BLUE (&Dword); + + /* Second 32-bit DWord */ + + ACPI_MOVE_32_TO_32 (&Dword, &Buffer[1]); + PldInfo->Width = ACPI_PLD_GET_WIDTH (&Dword); + PldInfo->Height = ACPI_PLD_GET_HEIGHT(&Dword); + + /* Third 32-bit DWord */ + + ACPI_MOVE_32_TO_32 (&Dword, &Buffer[2]); + PldInfo->UserVisible = ACPI_PLD_GET_USER_VISIBLE (&Dword); + PldInfo->Dock = ACPI_PLD_GET_DOCK (&Dword); + PldInfo->Lid = ACPI_PLD_GET_LID (&Dword); + PldInfo->Panel = ACPI_PLD_GET_PANEL (&Dword); + PldInfo->VerticalPosition = ACPI_PLD_GET_VERTICAL (&Dword); + PldInfo->HorizontalPosition = ACPI_PLD_GET_HORIZONTAL (&Dword); + PldInfo->Shape = ACPI_PLD_GET_SHAPE (&Dword); + PldInfo->GroupOrientation = ACPI_PLD_GET_ORIENTATION (&Dword); + PldInfo->GroupToken = ACPI_PLD_GET_TOKEN (&Dword); + PldInfo->GroupPosition = ACPI_PLD_GET_POSITION (&Dword); + PldInfo->Bay = ACPI_PLD_GET_BAY (&Dword); + + /* Fourth 32-bit DWord */ + + ACPI_MOVE_32_TO_32 (&Dword, &Buffer[3]); + PldInfo->Ejectable = ACPI_PLD_GET_EJECTABLE (&Dword); + PldInfo->OspmEjectRequired = ACPI_PLD_GET_OSPM_EJECT (&Dword); + PldInfo->CabinetNumber = ACPI_PLD_GET_CABINET (&Dword); + PldInfo->CardCageNumber = ACPI_PLD_GET_CARD_CAGE (&Dword); + PldInfo->Reference = ACPI_PLD_GET_REFERENCE (&Dword); + PldInfo->Rotation = ACPI_PLD_GET_ROTATION (&Dword); + PldInfo->Order = ACPI_PLD_GET_ORDER (&Dword); + + if (Length >= ACPI_PLD_REV2_BUFFER_SIZE) + { + /* Fifth 32-bit DWord (Revision 2 of _PLD) */ + + ACPI_MOVE_32_TO_32 (&Dword, &Buffer[4]); + PldInfo->VerticalOffset = ACPI_PLD_GET_VERT_OFFSET (&Dword); + PldInfo->HorizontalOffset = ACPI_PLD_GET_HORIZ_OFFSET (&Dword); + } + + *ReturnBuffer = PldInfo; + return (AE_OK); +} + +ACPI_EXPORT_SYMBOL (AcpiDecodePldBuffer) diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utxferror.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utxferror.c new file mode 100644 index 0000000..40336db --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utxferror.c @@ -0,0 +1,324 @@ +/******************************************************************************* + * + * Module Name: utxferror - Various error/warning output functions + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#include "acpi.h" +#include "accommon.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. + */ + +#ifndef ACPI_NO_ERROR_MESSAGES /* Entire module */ + +/******************************************************************************* + * + * 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 value to be decoded/formatted + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Print an "ACPI Error" message with module/line/version + * info as well as 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; + + /* For AE_OK, just print the message */ + + if (ACPI_SUCCESS (Status)) + { + AcpiOsPrintf (ACPI_MSG_ERROR); + + } + else + { + AcpiOsPrintf (ACPI_MSG_ERROR "%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 warning output) + * LineNumber - Caller's line number (for warning 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: 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. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiInfo ( + 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) + + +/******************************************************************************* + * + * FUNCTION: AcpiBiosError + * + * 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 Firmware Error" message with module/line/version + * info + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiBiosError ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...) +{ + va_list ArgList; + + + ACPI_MSG_REDIRECT_BEGIN; + AcpiOsPrintf (ACPI_MSG_BIOS_ERROR); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + ACPI_MSG_SUFFIX; + va_end (ArgList); + + ACPI_MSG_REDIRECT_END; +} + +ACPI_EXPORT_SYMBOL (AcpiBiosError) + + +/******************************************************************************* + * + * FUNCTION: AcpiBiosException + * + * PARAMETERS: ModuleName - Caller's module name (for error output) + * LineNumber - Caller's line number (for error output) + * Status - Status value to be decoded/formatted + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Print an "ACPI Firmware Error" message with module/line/version + * info as well as decoded ACPI_STATUS. + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiBiosException ( + const char *ModuleName, + UINT32 LineNumber, + ACPI_STATUS Status, + const char *Format, + ...) +{ + va_list ArgList; + + + ACPI_MSG_REDIRECT_BEGIN; + + /* For AE_OK, just print the message */ + + if (ACPI_SUCCESS (Status)) + { + AcpiOsPrintf (ACPI_MSG_BIOS_ERROR); + + } + else + { + AcpiOsPrintf (ACPI_MSG_BIOS_ERROR "%s, ", + AcpiFormatException (Status)); + } + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + ACPI_MSG_SUFFIX; + va_end (ArgList); + + ACPI_MSG_REDIRECT_END; +} + +ACPI_EXPORT_SYMBOL (AcpiBiosException) + + +/******************************************************************************* + * + * FUNCTION: AcpiBiosWarning + * + * PARAMETERS: ModuleName - Caller's module name (for warning output) + * LineNumber - Caller's line number (for warning output) + * Format - Printf format string + additional args + * + * RETURN: None + * + * DESCRIPTION: Print "ACPI Firmware Warning" message with module/line/version + * info + * + ******************************************************************************/ + +void ACPI_INTERNAL_VAR_XFACE +AcpiBiosWarning ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...) +{ + va_list ArgList; + + + ACPI_MSG_REDIRECT_BEGIN; + AcpiOsPrintf (ACPI_MSG_BIOS_WARNING); + + va_start (ArgList, Format); + AcpiOsVprintf (Format, ArgList); + ACPI_MSG_SUFFIX; + va_end (ArgList); + + ACPI_MSG_REDIRECT_END; +} + +ACPI_EXPORT_SYMBOL (AcpiBiosWarning) + +#endif /* ACPI_NO_ERROR_MESSAGES */ diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utxfinit.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utxfinit.c new file mode 100644 index 0000000..20ee3d9 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utxfinit.c @@ -0,0 +1,292 @@ +/****************************************************************************** + * + * Module Name: utxfinit - External interfaces for ACPICA initialization + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#define EXPORT_ACPI_INTERFACES + +#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 ("utxfinit") + +/* For AcpiExec only */ +void +AeDoObjectOverrides ( + void); + + +/******************************************************************************* + * + * 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 ACPI_INIT_FUNCTION +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); + } + + return_ACPI_STATUS (AE_OK); +} + +ACPI_EXPORT_SYMBOL_INIT (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 ACPI_INIT_FUNCTION +AcpiEnableSubsystem ( + UINT32 Flags) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (AcpiEnableSubsystem); + + + /* + * The early initialization phase is complete. The namespace is loaded, + * and we can now support address spaces other than Memory, I/O, and + * PCI_Config. + */ + AcpiGbl_EarlyInitialization = FALSE; + + /* + * Obtain a permanent mapping for the FACS. This is required for the + * Global Lock and the Firmware Waking Vector + */ + if (!(Flags & ACPI_NO_FACS_INIT)) + { + Status = AcpiTbInitializeFacs (); + if (ACPI_FAILURE (Status)) + { + ACPI_WARNING ((AE_INFO, "Could not map the FACS table")); + return_ACPI_STATUS (Status); + } + } + +#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); + } + } + + /* + * 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_INIT (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 ACPI_INIT_FUNCTION +AcpiInitializeObjects ( + UINT32 Flags) +{ + ACPI_STATUS Status = AE_OK; + + + ACPI_FUNCTION_TRACE (AcpiInitializeObjects); + + +#ifdef ACPI_OBSOLETE_BEHAVIOR + /* + * 05/2019: Removed, initialization now happens at both object + * creation and table load time + */ + + /* + * Initialize the objects that remain uninitialized. This + * runs the executable AML that may be part of the + * declaration of these objects: OperationRegions, BufferFields, + * BankFields, Buffers, and Packages. + */ + if (!(Flags & ACPI_NO_OBJECT_INIT)) + { + Status = AcpiNsInitializeObjects (); + if (ACPI_FAILURE (Status)) + { + return_ACPI_STATUS (Status); + } + } +#endif + + /* + * Initialize all device/region objects in the namespace. This runs + * the device _STA and _INI methods and region _REG methods. + */ + if (!(Flags & (ACPI_NO_DEVICE_INIT | ACPI_NO_ADDRESS_SPACE_INIT))) + { + Status = AcpiNsInitializeDevices (Flags); + 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_INIT (AcpiInitializeObjects) diff --git a/code/drivers/platform/acpi/third_party/acpica/components/utilities/utxfmutex.c b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utxfmutex.c new file mode 100644 index 0000000..170a10e --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/components/utilities/utxfmutex.c @@ -0,0 +1,185 @@ +/******************************************************************************* + * + * Module Name: utxfmutex - external AML mutex access functions + * + ******************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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); +} + +ACPI_EXPORT_SYMBOL (AcpiAcquireMutex) + + +/******************************************************************************* + * + * 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); +} + +ACPI_EXPORT_SYMBOL (AcpiReleaseMutex) diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acapps.h b/code/drivers/platform/acpi/third_party/acpica/include/acapps.h new file mode 100644 index 0000000..394aa3f --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acapps.h @@ -0,0 +1,205 @@ +/****************************************************************************** + * + * Module Name: acapps - common include for ACPI applications/tools + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef _ACAPPS +#define _ACAPPS + +#ifdef ACPI_USE_STANDARD_HEADERS +#include +#endif /* ACPI_USE_STANDARD_HEADERS */ + +/* Common info for tool signons */ + +#define ACPICA_NAME "Intel ACPI Component Architecture" +#define ACPICA_COPYRIGHT "Copyright (c) 2000 - 2026 Intel Corporation" + +#if ACPI_MACHINE_WIDTH == 64 +#define ACPI_WIDTH " (64-bit version)" + +#elif ACPI_MACHINE_WIDTH == 32 +#define ACPI_WIDTH " (32-bit version)" + +#else +#error unknown ACPI_MACHINE_WIDTH +#define ACPI_WIDTH " (unknown bit width, not 32 or 64)" + +#endif + +/* Macros for signons and file headers */ + +#define ACPI_COMMON_SIGNON(UtilityName) \ + "\n%s\n%s version %8.8X\n%s\n\n", \ + ACPICA_NAME, \ + UtilityName, ((UINT32) ACPI_CA_VERSION), \ + ACPICA_COPYRIGHT + +#define ACPI_COMMON_HEADER(UtilityName, Prefix) \ + "%s%s\n%s%s version %8.8X%s\n%s%s\n%s\n", \ + Prefix, ACPICA_NAME, \ + Prefix, UtilityName, ((UINT32) ACPI_CA_VERSION), ACPI_WIDTH, \ + Prefix, ACPICA_COPYRIGHT, \ + Prefix + +#define ACPI_COMMON_BUILD_TIME \ + "Build date/time: %s %s\n", __DATE__, __TIME__ + +/* Macros for usage messages */ + +#define ACPI_USAGE_HEADER(Usage) \ + printf ("Usage: %s\nOptions:\n", Usage); + +#define ACPI_USAGE_TEXT(Description) \ + printf (Description); + +#define ACPI_OPTION(Name, Description) \ + printf (" %-20s%s\n", Name, Description); + + +/* Check for unexpected exceptions */ + +#define ACPI_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 ACPI_CHECK_OK(Name, Status) ACPI_CHECK_STATUS (Name, Status, AE_OK); + +#define FILE_SUFFIX_DISASSEMBLY "dsl" +#define FILE_SUFFIX_BINARY_TABLE ".dat" /* Needs the dot */ + + +/* acfileio */ + +ACPI_STATUS +AcGetAllTablesFromFile ( + char *Filename, + UINT8 GetOnlyAmlTables, + ACPI_NEW_TABLE_DESC **ReturnListHead); + +void +AcDeleteTableList ( + ACPI_NEW_TABLE_DESC *ListHead); + +BOOLEAN +AcIsFileBinary ( + FILE *File); + +ACPI_STATUS +AcValidateTableHeader ( + FILE *File, + long TableOffset); + + +/* Values for GetOnlyAmlTables */ + +#define ACPI_GET_ONLY_AML_TABLES TRUE +#define ACPI_GET_ALL_TABLES FALSE + + +/* + * getopt + */ +int +AcpiGetopt( + int argc, + char **argv, + char *opts); + +int +AcpiGetoptArgument ( + int argc, + char **argv); + +extern int AcpiGbl_Optind; +extern int AcpiGbl_Opterr; +extern int AcpiGbl_SubOptChar; +extern char *AcpiGbl_Optarg; + + +/* + * cmfsize - Common get file size function + */ +UINT32 +CmGetFileSize ( + ACPI_FILE File); + + +/* + * 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 +AcpiDmConvertParseObjects ( + 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 * +FlGetFileBasename ( + char *FilePathname); + +char * +AdGenerateFilename ( + char *Prefix, + char *TableId); + +void +AdWriteTable ( + ACPI_TABLE_HEADER *Table, + UINT32 Length, + char *TableName, + char *OemTableId); + +#endif /* _ACAPPS */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acbuffer.h b/code/drivers/platform/acpi/third_party/acpica/include/acbuffer.h new file mode 100644 index 0000000..a4df254 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acbuffer.h @@ -0,0 +1,234 @@ +/****************************************************************************** + * + * Name: acbuffer.h - Support for buffers returned by ACPI predefined names + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACBUFFER_H__ +#define __ACBUFFER_H__ + +/* + * Contains buffer structures for these predefined names: + * _FDE, _GRT, _GTM, _PLD, _SRT + */ + +/* + * Note: C bitfields are not used for this reason: + * + * "Bitfields are great and easy to read, but unfortunately the C language + * does not specify the layout of bitfields in memory, which means they are + * essentially useless for dealing with packed data in on-disk formats or + * binary wire protocols." (Or ACPI tables and buffers.) "If you ask me, + * this decision was a design error in C. Ritchie could have picked an order + * and stuck with it." Norman Ramsey. + * See http://stackoverflow.com/a/1053662/41661 + */ + + +/* _FDE return value */ + +typedef struct acpi_fde_info +{ + UINT32 Floppy0; + UINT32 Floppy1; + UINT32 Floppy2; + UINT32 Floppy3; + UINT32 Tape; + +} ACPI_FDE_INFO; + +/* + * _GRT return value + * _SRT input value + */ +typedef struct acpi_grt_info +{ + UINT16 Year; + UINT8 Month; + UINT8 Day; + UINT8 Hour; + UINT8 Minute; + UINT8 Second; + UINT8 Valid; + UINT16 Milliseconds; + UINT16 Timezone; + UINT8 Daylight; + UINT8 Reserved[3]; + +} ACPI_GRT_INFO; + +/* _GTM return value */ + +typedef struct acpi_gtm_info +{ + UINT32 PioSpeed0; + UINT32 DmaSpeed0; + UINT32 PioSpeed1; + UINT32 DmaSpeed1; + UINT32 Flags; + +} ACPI_GTM_INFO; + +/* + * Formatted _PLD return value. The minimum size is a package containing + * one buffer. + * Revision 1: Buffer is 16 bytes (128 bits) + * Revision 2: Buffer is 20 bytes (160 bits) + * + * Note: This structure is returned from the AcpiDecodePldBuffer + * interface. + */ +typedef struct acpi_pld_info +{ + UINT8 Revision; + UINT8 IgnoreColor; + UINT8 Red; + UINT8 Green; + UINT8 Blue; + UINT16 Width; + UINT16 Height; + UINT8 UserVisible; + UINT8 Dock; + UINT8 Lid; + UINT8 Panel; + UINT8 VerticalPosition; + UINT8 HorizontalPosition; + UINT8 Shape; + UINT8 GroupOrientation; + UINT8 GroupToken; + UINT8 GroupPosition; + UINT8 Bay; + UINT8 Ejectable; + UINT8 OspmEjectRequired; + UINT8 CabinetNumber; + UINT8 CardCageNumber; + UINT8 Reference; + UINT8 Rotation; + UINT8 Order; + UINT8 Reserved; + UINT16 VerticalOffset; + UINT16 HorizontalOffset; + +} ACPI_PLD_INFO; + + +/* + * Macros to: + * 1) Convert a _PLD buffer to internal ACPI_PLD_INFO format - ACPI_PLD_GET* + * (Used by AcpiDecodePldBuffer) + * 2) Construct a _PLD buffer - ACPI_PLD_SET* + * (Intended for BIOS use only) + */ +#define ACPI_PLD_REV1_BUFFER_SIZE 16 /* For Revision 1 of the buffer (From ACPI spec) */ +#define ACPI_PLD_REV2_BUFFER_SIZE 20 /* For Revision 2 of the buffer (From ACPI spec) */ +#define ACPI_PLD_BUFFER_SIZE 20 /* For Revision 2 of the buffer (From ACPI spec) */ + +/* First 32-bit dword, bits 0:32 */ + +#define ACPI_PLD_GET_REVISION(dword) ACPI_GET_BITS (dword, 0, ACPI_7BIT_MASK) +#define ACPI_PLD_SET_REVISION(dword,value) ACPI_SET_BITS (dword, 0, ACPI_7BIT_MASK, value) /* Offset 0, Len 7 */ + +#define ACPI_PLD_GET_IGNORE_COLOR(dword) ACPI_GET_BITS (dword, 7, ACPI_1BIT_MASK) +#define ACPI_PLD_SET_IGNORE_COLOR(dword,value) ACPI_SET_BITS (dword, 7, ACPI_1BIT_MASK, value) /* Offset 7, Len 1 */ + +#define ACPI_PLD_GET_RED(dword) ACPI_GET_BITS (dword, 8, ACPI_8BIT_MASK) +#define ACPI_PLD_SET_RED(dword,value) ACPI_SET_BITS (dword, 8, ACPI_8BIT_MASK, value) /* Offset 8, Len 8 */ + +#define ACPI_PLD_GET_GREEN(dword) ACPI_GET_BITS (dword, 16, ACPI_8BIT_MASK) +#define ACPI_PLD_SET_GREEN(dword,value) ACPI_SET_BITS (dword, 16, ACPI_8BIT_MASK, value) /* Offset 16, Len 8 */ + +#define ACPI_PLD_GET_BLUE(dword) ACPI_GET_BITS (dword, 24, ACPI_8BIT_MASK) +#define ACPI_PLD_SET_BLUE(dword,value) ACPI_SET_BITS (dword, 24, ACPI_8BIT_MASK, value) /* Offset 24, Len 8 */ + +/* Second 32-bit dword, bits 33:63 */ + +#define ACPI_PLD_GET_WIDTH(dword) ACPI_GET_BITS (dword, 0, ACPI_16BIT_MASK) +#define ACPI_PLD_SET_WIDTH(dword,value) ACPI_SET_BITS (dword, 0, ACPI_16BIT_MASK, value) /* Offset 32+0=32, Len 16 */ + +#define ACPI_PLD_GET_HEIGHT(dword) ACPI_GET_BITS (dword, 16, ACPI_16BIT_MASK) +#define ACPI_PLD_SET_HEIGHT(dword,value) ACPI_SET_BITS (dword, 16, ACPI_16BIT_MASK, value) /* Offset 32+16=48, Len 16 */ + +/* Third 32-bit dword, bits 64:95 */ + +#define ACPI_PLD_GET_USER_VISIBLE(dword) ACPI_GET_BITS (dword, 0, ACPI_1BIT_MASK) +#define ACPI_PLD_SET_USER_VISIBLE(dword,value) ACPI_SET_BITS (dword, 0, ACPI_1BIT_MASK, value) /* Offset 64+0=64, Len 1 */ + +#define ACPI_PLD_GET_DOCK(dword) ACPI_GET_BITS (dword, 1, ACPI_1BIT_MASK) +#define ACPI_PLD_SET_DOCK(dword,value) ACPI_SET_BITS (dword, 1, ACPI_1BIT_MASK, value) /* Offset 64+1=65, Len 1 */ + +#define ACPI_PLD_GET_LID(dword) ACPI_GET_BITS (dword, 2, ACPI_1BIT_MASK) +#define ACPI_PLD_SET_LID(dword,value) ACPI_SET_BITS (dword, 2, ACPI_1BIT_MASK, value) /* Offset 64+2=66, Len 1 */ + +#define ACPI_PLD_GET_PANEL(dword) ACPI_GET_BITS (dword, 3, ACPI_3BIT_MASK) +#define ACPI_PLD_SET_PANEL(dword,value) ACPI_SET_BITS (dword, 3, ACPI_3BIT_MASK, value) /* Offset 64+3=67, Len 3 */ + +#define ACPI_PLD_GET_VERTICAL(dword) ACPI_GET_BITS (dword, 6, ACPI_2BIT_MASK) +#define ACPI_PLD_SET_VERTICAL(dword,value) ACPI_SET_BITS (dword, 6, ACPI_2BIT_MASK, value) /* Offset 64+6=70, Len 2 */ + +#define ACPI_PLD_GET_HORIZONTAL(dword) ACPI_GET_BITS (dword, 8, ACPI_2BIT_MASK) +#define ACPI_PLD_SET_HORIZONTAL(dword,value) ACPI_SET_BITS (dword, 8, ACPI_2BIT_MASK, value) /* Offset 64+8=72, Len 2 */ + +#define ACPI_PLD_GET_SHAPE(dword) ACPI_GET_BITS (dword, 10, ACPI_4BIT_MASK) +#define ACPI_PLD_SET_SHAPE(dword,value) ACPI_SET_BITS (dword, 10, ACPI_4BIT_MASK, value) /* Offset 64+10=74, Len 4 */ + +#define ACPI_PLD_GET_ORIENTATION(dword) ACPI_GET_BITS (dword, 14, ACPI_1BIT_MASK) +#define ACPI_PLD_SET_ORIENTATION(dword,value) ACPI_SET_BITS (dword, 14, ACPI_1BIT_MASK, value) /* Offset 64+14=78, Len 1 */ + +#define ACPI_PLD_GET_TOKEN(dword) ACPI_GET_BITS (dword, 15, ACPI_8BIT_MASK) +#define ACPI_PLD_SET_TOKEN(dword,value) ACPI_SET_BITS (dword, 15, ACPI_8BIT_MASK, value) /* Offset 64+15=79, Len 8 */ + +#define ACPI_PLD_GET_POSITION(dword) ACPI_GET_BITS (dword, 23, ACPI_8BIT_MASK) +#define ACPI_PLD_SET_POSITION(dword,value) ACPI_SET_BITS (dword, 23, ACPI_8BIT_MASK, value) /* Offset 64+23=87, Len 8 */ + +#define ACPI_PLD_GET_BAY(dword) ACPI_GET_BITS (dword, 31, ACPI_1BIT_MASK) +#define ACPI_PLD_SET_BAY(dword,value) ACPI_SET_BITS (dword, 31, ACPI_1BIT_MASK, value) /* Offset 64+31=95, Len 1 */ + +/* Fourth 32-bit dword, bits 96:127 */ + +#define ACPI_PLD_GET_EJECTABLE(dword) ACPI_GET_BITS (dword, 0, ACPI_1BIT_MASK) +#define ACPI_PLD_SET_EJECTABLE(dword,value) ACPI_SET_BITS (dword, 0, ACPI_1BIT_MASK, value) /* Offset 96+0=96, Len 1 */ + +#define ACPI_PLD_GET_OSPM_EJECT(dword) ACPI_GET_BITS (dword, 1, ACPI_1BIT_MASK) +#define ACPI_PLD_SET_OSPM_EJECT(dword,value) ACPI_SET_BITS (dword, 1, ACPI_1BIT_MASK, value) /* Offset 96+1=97, Len 1 */ + +#define ACPI_PLD_GET_CABINET(dword) ACPI_GET_BITS (dword, 2, ACPI_8BIT_MASK) +#define ACPI_PLD_SET_CABINET(dword,value) ACPI_SET_BITS (dword, 2, ACPI_8BIT_MASK, value) /* Offset 96+2=98, Len 8 */ + +#define ACPI_PLD_GET_CARD_CAGE(dword) ACPI_GET_BITS (dword, 10, ACPI_8BIT_MASK) +#define ACPI_PLD_SET_CARD_CAGE(dword,value) ACPI_SET_BITS (dword, 10, ACPI_8BIT_MASK, value) /* Offset 96+10=106, Len 8 */ + +#define ACPI_PLD_GET_REFERENCE(dword) ACPI_GET_BITS (dword, 18, ACPI_1BIT_MASK) +#define ACPI_PLD_SET_REFERENCE(dword,value) ACPI_SET_BITS (dword, 18, ACPI_1BIT_MASK, value) /* Offset 96+18=114, Len 1 */ + +#define ACPI_PLD_GET_ROTATION(dword) ACPI_GET_BITS (dword, 19, ACPI_4BIT_MASK) +#define ACPI_PLD_SET_ROTATION(dword,value) ACPI_SET_BITS (dword, 19, ACPI_4BIT_MASK, value) /* Offset 96+19=115, Len 4 */ + +#define ACPI_PLD_GET_ORDER(dword) ACPI_GET_BITS (dword, 23, ACPI_5BIT_MASK) +#define ACPI_PLD_SET_ORDER(dword,value) ACPI_SET_BITS (dword, 23, ACPI_5BIT_MASK, value) /* Offset 96+23=119, Len 5 */ + +/* Fifth 32-bit dword, bits 128:159 (Revision 2 of _PLD only) */ + +#define ACPI_PLD_GET_VERT_OFFSET(dword) ACPI_GET_BITS (dword, 0, ACPI_16BIT_MASK) +#define ACPI_PLD_SET_VERT_OFFSET(dword,value) ACPI_SET_BITS (dword, 0, ACPI_16BIT_MASK, value) /* Offset 128+0=128, Len 16 */ + +#define ACPI_PLD_GET_HORIZ_OFFSET(dword) ACPI_GET_BITS (dword, 16, ACPI_16BIT_MASK) +#define ACPI_PLD_SET_HORIZ_OFFSET(dword,value) ACPI_SET_BITS (dword, 16, ACPI_16BIT_MASK, value) /* Offset 128+16=144, Len 16 */ + +/* Panel position defined in _PLD section of ACPI Specification 6.3 */ + +#define ACPI_PLD_PANEL_TOP 0 +#define ACPI_PLD_PANEL_BOTTOM 1 +#define ACPI_PLD_PANEL_LEFT 2 +#define ACPI_PLD_PANEL_RIGHT 3 +#define ACPI_PLD_PANEL_FRONT 4 +#define ACPI_PLD_PANEL_BACK 5 +#define ACPI_PLD_PANEL_UNKNOWN 6 + +#endif /* ACBUFFER_H */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acclib.h b/code/drivers/platform/acpi/third_party/acpica/include/acclib.h new file mode 100644 index 0000000..e14d746 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acclib.h @@ -0,0 +1,293 @@ +/****************************************************************************** + * + * Name: acclib.h -- C library support. Prototypes for the (optional) local + * implementations of required C library functions. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef _ACCLIB_H +#define _ACCLIB_H + + +/* + * Prototypes and macros for local implementations of C library functions + */ + +/* is* functions. The AcpiGbl_Ctypes array is defined in utclib.c */ + +extern const UINT8 AcpiGbl_Ctypes[]; + +#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, tab, CR, LF, VT, FF */ +#define _ACPI_UP 0x01 /* 'A'-'Z' */ +#define _ACPI_XD 0x80 /* '0'-'9', 'A'-'F', 'a'-'f' */ + +#define isdigit(c) (AcpiGbl_Ctypes[(unsigned char)(c)] & (_ACPI_DI)) +#define isspace(c) (AcpiGbl_Ctypes[(unsigned char)(c)] & (_ACPI_SP)) +#define isxdigit(c) (AcpiGbl_Ctypes[(unsigned char)(c)] & (_ACPI_XD)) +#define isupper(c) (AcpiGbl_Ctypes[(unsigned char)(c)] & (_ACPI_UP)) +#define islower(c) (AcpiGbl_Ctypes[(unsigned char)(c)] & (_ACPI_LO)) +#define isprint(c) (AcpiGbl_Ctypes[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP | _ACPI_DI | _ACPI_XS | _ACPI_PU)) +#define isalpha(c) (AcpiGbl_Ctypes[(unsigned char)(c)] & (_ACPI_LO | _ACPI_UP)) + +/* Error code */ + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* I/O error */ +#define EBADF 9 /* Bad file number */ +#define EAGAIN 11 /* Try again */ +#define ENOMEM 12 /* Out of memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define EBUSY 16 /* Device or resource busy */ +#define EEXIST 17 /* File exists */ +#define ENODEV 19 /* No such device */ +#define EINVAL 22 /* Invalid argument */ +#define EPIPE 32 /* Broken pipe */ +#define ERANGE 34 /* Math result not representable */ + +/* Strings */ + +char * +strcat ( + char *DstString, + const char *SrcString); + +char * +strchr ( + const char *String, + int ch); + +char * +strpbrk ( + const char *String, + const char *Delimiters); + +char * +strtok ( + char *String, + const char *Delimiters); + +char * +strcpy ( + char *DstString, + const char *SrcString); + +int +strcmp ( + const char *String1, + const char *String2); + +ACPI_SIZE +strlen ( + const char *String); + +char * +strncat ( + char *DstString, + const char *SrcString, + ACPI_SIZE Count); + +int +strncmp ( + const char *String1, + const char *String2, + ACPI_SIZE Count); + +char * +strncpy ( + char *DstString, + const char *SrcString, + ACPI_SIZE Count); + +char * +strstr ( + char *String1, + char *String2); + + +/* Conversion */ + +UINT32 +strtoul ( + const char *String, + char **Terminator, + UINT32 Base); + + +/* Memory */ + +int +memcmp ( + void *Buffer1, + void *Buffer2, + ACPI_SIZE Count); + +void * +memcpy ( + void *Dest, + const void *Src, + ACPI_SIZE Count); + +void * +memmove ( + void *Dest, + const void *Src, + ACPI_SIZE Count); + +void * +memset ( + void *Dest, + int Value, + ACPI_SIZE Count); + + +/* upper/lower case */ + +int +tolower ( + int c); + +int +toupper ( + int c); + +/* + * utprint - printf/vprintf output functions + */ +const char * +AcpiUtScanNumber ( + const char *String, + UINT64 *NumberPtr); + +const char * +AcpiUtPrintNumber ( + char *String, + UINT64 Number); + +int +vsnprintf ( + char *String, + ACPI_SIZE Size, + const char *Format, + va_list Args); + +int +snprintf ( + char *String, + ACPI_SIZE Size, + const char *Format, + ...); + +int +sprintf ( + char *String, + const char *Format, + ...); + +#ifdef ACPI_APPLICATION +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +/* + * NOTE: Currently we only need to update errno for file IOs. Other + * Clibrary invocations in ACPICA do not make decisions according to + * the errno. + */ +extern int errno; + +#ifndef EOF +#define EOF (-1) +#endif + +#define putchar(c) fputc(stdout, c) +#define getchar(c) fgetc(stdin) + +int +vprintf ( + const char *Format, + va_list Args); + +int +printf ( + const char *Format, + ...); + +int +vfprintf ( + FILE *File, + const char *Format, + va_list Args); + +int +fprintf ( + FILE *File, + const char *Format, + ...); + +FILE * +fopen ( + const char *Path, + const char *Modes); + +void +fclose ( + FILE *File); + +int +fread ( + void *Buffer, + ACPI_SIZE Size, + ACPI_SIZE Count, + FILE *File); + +int +fwrite ( + void *Buffer, + ACPI_SIZE Size, + ACPI_SIZE Count, + FILE *File); + +int +fseek ( + FILE *File, + long Offset, + int From); + +long +ftell ( + FILE *File); + +int +fgetc ( + FILE *File); + +int +fputc ( + FILE *File, + char c); + +char * +fgets ( + char *s, + ACPI_SIZE Size, + FILE *File); +#endif + +#endif /* _ACCLIB_H */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/accommon.h b/code/drivers/platform/acpi/third_party/acpica/include/accommon.h new file mode 100644 index 0000000..295ad84 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/accommon.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Name: accommon.h - Common include files for generation of ACPICA source + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 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 */ +#ifndef ACPI_USE_SYSTEM_CLIBRARY +#include "acclib.h" /* C library interfaces */ +#endif /* !ACPI_USE_SYSTEM_CLIBRARY */ + + +#endif /* __ACCOMMON_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acconfig.h b/code/drivers/platform/acpi/third_party/acpica/include/acconfig.h new file mode 100644 index 0000000..6d94a26 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acconfig.h @@ -0,0 +1,239 @@ +/****************************************************************************** + * + * Name: acconfig.h - Global configuration constants + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 */ +#define ACPI_MAX_COMMENT_CACHE_DEPTH 96 /* Comments for the -ca option */ + +/* + * Should the subsystem abort the loading of an ACPI table if the + * table checksum is incorrect? + */ +#ifndef ACPI_CHECKSUM_ABORT +#define ACPI_CHECKSUM_ABORT FALSE +#endif + +/* + * 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 + */ +#ifndef ACPI_REDUCED_HARDWARE +#define ACPI_REDUCED_HARDWARE FALSE +#endif + + +/****************************************************************************** + * + * 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 0x4000 + +/* Default page size for use in mapping memory for operation regions */ + +#define ACPI_DEFAULT_PAGE_SIZE 4096 /* Must be power of 2 */ + +/* OwnerId tracking. 128 entries allows for 4095 OwnerIds */ + +#define ACPI_NUM_OWNERID_MASKS 128 + +/* Size of the root table array is increased by this increment */ + +#define ACPI_ROOT_TABLE_SIZE_INCREMENT 4 + +/* 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 + +/* Maximum time (default 30s) of While() loops before abort */ + +#define ACPI_MAX_LOOP_TIMEOUT 30 + + +/****************************************************************************** + * + * ACPI Specification constants (Do not change unless the specification changes) + * + *****************************************************************************/ + +/* Method info (in WALK_STATE), containing local variables and arguments */ + +#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 arbitrary 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 +#define ACPI_NUM_DEFAULT_SPACES 4 + +/* 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 buffer sizes. All have a 2-byte header, + * containing both Status and Length. + */ +#define ACPI_SERIAL_HEADER_SIZE 2 /* Common for below. Status and Length fields */ + +#define ACPI_SMBUS_DATA_SIZE 32 +#define ACPI_SMBUS_BUFFER_SIZE ACPI_SERIAL_HEADER_SIZE + ACPI_SMBUS_DATA_SIZE + +#define ACPI_IPMI_DATA_SIZE 64 +#define ACPI_IPMI_BUFFER_SIZE ACPI_SERIAL_HEADER_SIZE + ACPI_IPMI_DATA_SIZE + +#define ACPI_MAX_GSBUS_DATA_SIZE 255 +#define ACPI_MAX_GSBUS_BUFFER_SIZE ACPI_SERIAL_HEADER_SIZE + ACPI_MAX_GSBUS_DATA_SIZE + +#define ACPI_PRM_INPUT_BUFFER_SIZE 26 + +#define ACPI_FFH_INPUT_BUFFER_SIZE 256 + +/* _SxD and _SxW control methods */ + +#define ACPI_NUM_SxD_METHODS 4 +#define ACPI_NUM_SxW_METHODS 5 + + +/****************************************************************************** + * + * Miscellaneous constants + * + *****************************************************************************/ + +/* UUID constants */ + +#define UUID_BUFFER_LENGTH 16 /* Length of UUID in memory */ +#define UUID_STRING_LENGTH 36 /* Total length of a UUID string */ + +/* 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 + + +/****************************************************************************** + * + * ACPI AML Debugger + * + *****************************************************************************/ + +#define ACPI_DEBUGGER_MAX_ARGS ACPI_METHOD_NUM_ARGS + 4 /* 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/code/drivers/platform/acpi/third_party/acpica/include/acconvert.h b/code/drivers/platform/acpi/third_party/acpica/include/acconvert.h new file mode 100644 index 0000000..4e5bc32 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acconvert.h @@ -0,0 +1,173 @@ +/****************************************************************************** + * + * Module Name: acapps - common include for ACPI applications/tools + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef _ACCONVERT +#define _ACCONVERT + +/* Definitions for comment state */ + +#define ASL_COMMENT_STANDARD 1 +#define ASLCOMMENT_INLINE 2 +#define ASL_COMMENT_OPEN_PAREN 3 +#define ASL_COMMENT_CLOSE_PAREN 4 +#define ASL_COMMENT_CLOSE_BRACE 5 + +/* Definitions for comment print function*/ + +#define AML_COMMENT_STANDARD 1 +#define AMLCOMMENT_INLINE 2 +#define AML_COMMENT_END_NODE 3 +#define AML_NAMECOMMENT 4 +#define AML_COMMENT_CLOSE_BRACE 5 +#define AML_COMMENT_ENDBLK 6 +#define AML_COMMENT_INCLUDE 7 + + +#ifdef ACPI_ASL_COMPILER +/* + * cvcompiler + */ +void +CvProcessComment ( + ASL_COMMENT_STATE CurrentState, + char *StringBuffer, + int c1); + +void +CvProcessCommentType2 ( + ASL_COMMENT_STATE CurrentState, + char *StringBuffer); + +UINT32 +CvCalculateCommentLengths( + ACPI_PARSE_OBJECT *Op); + +void +CvProcessCommentState ( + char input); + +char* +CvAppendInlineComment ( + char *InlineComment, + char *ToAdd); + +void +CvAddToCommentList ( + char* ToAdd); + +void +CvPlaceComment ( + UINT8 Type, + char *CommentString); + +UINT32 +CvParseOpBlockType ( + ACPI_PARSE_OBJECT *Op); + +ACPI_COMMENT_NODE* +CvCommentNodeCalloc ( + void); + +void +CgWriteAmlDefBlockComment ( + ACPI_PARSE_OBJECT *Op); + +void +CgWriteOneAmlComment ( + ACPI_PARSE_OBJECT *Op, + char* CommentToPrint, + UINT8 InputOption); + +void +CgWriteAmlComment ( + ACPI_PARSE_OBJECT *Op); + + +/* + * cvparser + */ +void +CvInitFileTree ( + ACPI_TABLE_HEADER *Table, + FILE *RootFile); + +void +CvClearOpComments ( + ACPI_PARSE_OBJECT *Op); + +ACPI_FILE_NODE* +CvFilenameExists ( + char *Filename, + ACPI_FILE_NODE *Head); + +void +CvLabelFileNode ( + ACPI_PARSE_OBJECT *Op); + +void +CvCaptureListComments ( + ACPI_PARSE_STATE *ParserState, + ACPI_COMMENT_NODE *ListHead, + ACPI_COMMENT_NODE *ListTail); + +void +CvCaptureCommentsOnly ( + ACPI_PARSE_STATE *ParserState); + +void +CvCaptureComments ( + ACPI_WALK_STATE *WalkState); + +void +CvTransferComments ( + ACPI_PARSE_OBJECT *Op); + +/* + * cvdisasm + */ +void +CvSwitchFiles ( + UINT32 level, + ACPI_PARSE_OBJECT *op); + +BOOLEAN +CvFileHasSwitched ( + ACPI_PARSE_OBJECT *Op); + + +void +CvCloseParenWriteComment ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level); + +void +CvCloseBraceWriteComment ( + ACPI_PARSE_OBJECT *Op, + UINT32 Level); + +void +CvPrintOneCommentList ( + ACPI_COMMENT_NODE *CommentList, + UINT32 Level); + +void +CvPrintOneCommentType ( + ACPI_PARSE_OBJECT *Op, + UINT8 CommentType, + char* EndStr, + UINT32 Level); + + +#endif + +#endif /* _ACCONVERT */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acdebug.h b/code/drivers/platform/acpi/third_party/acpica/include/acdebug.h new file mode 100644 index 0000000..eda60b6 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acdebug.h @@ -0,0 +1,488 @@ +/****************************************************************************** + * + * Name: acdebug.h - ACPI/AML debugger + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACDEBUG_H__ +#define __ACDEBUG_H__ + +/* The debugger is used in conjunction with the disassembler most of time */ + +#ifdef ACPI_DISASSEMBLER +#include "acdisasm.h" +#endif + + +#define ACPI_DEBUG_BUFFER_SIZE 0x4000 /* 16K buffer for return objects */ +#define ACPI_DEBUG_LENGTH_FORMAT " (%.4X bits, %.3X bytes)" + +typedef struct acpi_db_command_info +{ + const char *Name; /* Command Name */ + UINT8 MinArgs; /* Minimum arguments required */ + +} ACPI_DB_COMMAND_INFO; + +typedef struct acpi_db_command_help +{ + UINT8 LineCount; /* Number of help lines */ + char *Invocation; /* Command Invocation */ + char *Description; /* Command Description */ + +} ACPI_DB_COMMAND_HELP; + +typedef struct acpi_db_argument_info +{ + const char *Name; /* Argument Name */ + +} ACPI_DB_ARGUMENT_INFO; + +typedef struct acpi_db_execute_walk +{ + UINT32 Count; + UINT32 MaxCount; + char NameSeg[ACPI_NAMESEG_SIZE + 1]; + +} ACPI_DB_EXECUTE_WALK; + + +#define PARAM_LIST(pl) pl + +#define EX_NO_SINGLE_STEP 1 +#define EX_SINGLE_STEP 2 +#define EX_ALL 4 + + +/* + * dbxface - external debugger interfaces + */ +ACPI_DBR_DEPENDENT_RETURN_OK ( +ACPI_STATUS +AcpiDbSingleStep ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + UINT32 OpType)) + +ACPI_DBR_DEPENDENT_RETURN_VOID ( +void +AcpiDbSignalBreakPoint ( + ACPI_WALK_STATE *WalkState)) + + +/* + * dbcmds - debug commands and output routines + */ +ACPI_NAMESPACE_NODE * +AcpiDbConvertToNode ( + char *InString); + +void +AcpiDbDisplayTableInfo ( + char *TableArg); + +void +AcpiDbDisplayTemplate ( + char *BufferArg); + +void +AcpiDbUnloadAcpiTable ( + char *Name); + +void +AcpiDbSendNotify ( + char *Name, + UINT32 Value); + +void +AcpiDbDisplayInterfaces ( + char *ActionArg, + char *InterfaceNameArg); + +ACPI_STATUS +AcpiDbSleep ( + char *ObjectArg); + +void +AcpiDbTrace ( + char *EnableArg, + char *MethodArg, + char *OnceArg); + +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)) + +ACPI_HW_DEPENDENT_RETURN_VOID ( +void +AcpiDbGenerateSci ( + void)) + +void +AcpiDbExecuteTest ( + char *TypeArg); + + +/* + * dbconvert - miscellaneous conversion routines + */ +ACPI_STATUS +AcpiDbHexCharToValue ( + int HexChar, + UINT8 *ReturnValue); + +ACPI_STATUS +AcpiDbConvertToPackage ( + char *String, + ACPI_OBJECT *Object); + +ACPI_STATUS +AcpiDbConvertToObject ( + ACPI_OBJECT_TYPE Type, + char *String, + ACPI_OBJECT *Object); + +UINT8 * +AcpiDbEncodePldBuffer ( + ACPI_PLD_INFO *PldInfo); + +void +AcpiDbDumpPldBuffer ( + ACPI_OBJECT *ObjDesc); + + +/* + * 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 +AcpiDbEvaluatePredefinedNames ( + void); + +void +AcpiDbEvaluateAll ( + char *NameSeg); + + +/* + * dbnames - namespace commands + */ +void +AcpiDbSetScope ( + char *Name); + +void +AcpiDbDumpNamespace ( + char *StartArg, + char *DepthArg); + +void +AcpiDbDumpNamespacePaths ( + void); + +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); + +ACPI_STATUS +AcpiDbDisplayFields ( + UINT32 AddressSpaceId); + + +/* + * dbdisply - debug display commands + */ +void +AcpiDbDisplayMethodInfo ( + ACPI_PARSE_OBJECT *Op); + +void +AcpiDbDecodeAndDisplayObject ( + char *Target, + char *OutputType); + +ACPI_DBR_DEPENDENT_RETURN_VOID ( +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); + +ACPI_DBR_DEPENDENT_RETURN_VOID ( +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 +AcpiDbCreateExecutionThread ( + char *MethodNameArg, + char **Arguments, + ACPI_OBJECT_TYPE *Types); + +void +AcpiDbCreateExecutionThreads ( + char *NumThreadsArg, + char *NumLoopsArg, + char *MethodNameArg); + +void +AcpiDbDeleteObjects ( + UINT32 Count, + ACPI_OBJECT *Objects); + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS +UINT32 +AcpiDbGetCacheInfo ( + ACPI_MEMORY_LIST *Cache); +#endif + + +/* + * dbfileio - Debugger file I/O commands + */ +ACPI_OBJECT_TYPE +AcpiDbMatchArgument ( + char *UserArgument, + ACPI_DB_ARGUMENT_INFO *Arguments); + +void +AcpiDbCloseDebugFile ( + void); + +void +AcpiDbOpenDebugFile ( + char *Name); + +ACPI_STATUS +AcpiDbLoadAcpiTable ( + char *Filename); + +ACPI_STATUS +AcpiDbLoadTables ( + ACPI_NEW_TABLE_DESC *ListHead); + + +/* + * dbhistry - debugger HISTORY command + */ +void +AcpiDbAddToHistory ( + char *CommandLine); + +void +AcpiDbDisplayHistory ( + void); + +char * +AcpiDbGetFromHistory ( + char *CommandNumArg); + +char * +AcpiDbGetHistoryByIndex ( + UINT32 CommanddNum); + + +/* + * 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 ( + void); + +char * +AcpiDbGetNextToken ( + char *String, + char **Next, + ACPI_OBJECT_TYPE *ReturnType); + + +/* + * dbobject + */ +void +AcpiDbDecodeInternalObject ( + ACPI_OPERAND_OBJECT *ObjDesc); + +void +AcpiDbDisplayInternalObject ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState); + +void +AcpiDbDecodeArguments ( + ACPI_WALK_STATE *WalkState); + +void +AcpiDbDecodeLocals ( + ACPI_WALK_STATE *WalkState); + +void +AcpiDbDumpMethodInfo ( + ACPI_STATUS Status, + ACPI_WALK_STATE *WalkState); + + +/* + * 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); + +void +AcpiDbGenerateInterrupt ( + char *GsivArg); + +#endif /* __ACDEBUG_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acdisasm.h b/code/drivers/platform/acpi/third_party/acpica/include/acdisasm.h new file mode 100644 index 0000000..333d48c --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acdisasm.h @@ -0,0 +1,1507 @@ +/****************************************************************************** + * + * Name: acdisasm.h - AML disassembler + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 struct acpi_dmtable_info +{ + UINT8 Opcode; + UINT16 Offset; + char *Name; + UINT8 Flags; + +} ACPI_DMTABLE_INFO; + +/* Values for Flags field above */ + +#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 */ +#define DT_OPTIONAL 0x08 /* Field is optional */ +#define DT_DESCRIBES_OPTIONAL 0x10 /* Field describes an optional field (length, etc.) */ +#define DT_COUNT 0x20 /* Currently not used */ + +/* + * 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_FLAGS8_2, + ACPI_DMT_FLAGS4, + ACPI_DMT_FLAGS4_0, + ACPI_DMT_FLAGS4_4, + ACPI_DMT_FLAGS4_8, + ACPI_DMT_FLAGS4_12, + ACPI_DMT_FLAGS16_16, + 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_BUF10, + ACPI_DMT_BUF11, + ACPI_DMT_BUF12, + ACPI_DMT_BUF16, + ACPI_DMT_BUF18, + ACPI_DMT_BUF24, + ACPI_DMT_BUF26, + ACPI_DMT_BUF32, + ACPI_DMT_BUF112, + 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_RAW_BUFFER, /* Large, multiple line buffer */ + ACPI_DMT_DEVICE_PATH, + ACPI_DMT_LABEL, + ACPI_DMT_PCI_PATH, + + /* Types that are specific to particular ACPI tables */ + + ACPI_DMT_AEST, + ACPI_DMT_AEST_CACHE, + ACPI_DMT_AEST_GIC, + ACPI_DMT_AEST_RES, + ACPI_DMT_AEST_XFACE, + ACPI_DMT_AEST_XRUPT, + ACPI_DMT_AGDI, + ACPI_DMT_ASF, + ACPI_DMT_ASPT, + ACPI_DMT_CDAT, + ACPI_DMT_CEDT, + ACPI_DMT_DMAR, + ACPI_DMT_DMAR_SCOPE, + ACPI_DMT_EINJACT, + ACPI_DMT_EINJINST, + ACPI_DMT_ERDT, + ACPI_DMT_ERSTACT, + ACPI_DMT_ERSTINST, + ACPI_DMT_FADTPM, + ACPI_DMT_GTDT, + ACPI_DMT_HEST, + ACPI_DMT_HESTNTFY, + ACPI_DMT_HESTNTYP, + ACPI_DMT_HMAT, + ACPI_DMT_IORTMEM, + ACPI_DMT_IOVT, + ACPI_DMT_IOVTDEV, + ACPI_DMT_IVRS, + ACPI_DMT_IVRS_DE, + ACPI_DMT_IVRS_UNTERMINATED_STRING, + ACPI_DMT_KEYP, + ACPI_DMT_LPIT, + ACPI_DMT_MADT, + ACPI_DMT_MPAM_LOCATOR, + ACPI_DMT_NFIT, + ACPI_DMT_PCCT, + ACPI_DMT_PHAT, + ACPI_DMT_PMTT, + ACPI_DMT_PMTT_VENDOR, + ACPI_DMT_PPTT, + ACPI_DMT_RGRT, + ACPI_DMT_RHCT, + ACPI_DMT_RIMT, + ACPI_DMT_SDEI, + ACPI_DMT_SDEV, + ACPI_DMT_SLIC, + ACPI_DMT_SRAT, + ACPI_DMT_SWFT, + ACPI_DMT_TPM2, + ACPI_DMT_UBRT, + ACPI_DMT_VIOT, + ACPI_DMT_WPBT_UNICODE, + + /* 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; + +} ACPI_DMTABLE_DATA; + + +typedef struct acpi_op_walk_info +{ + ACPI_WALK_STATE *WalkState; + ACPI_PARSE_OBJECT *MappingOp; + UINT8 *PreviousAml; + UINT8 *StartAml; + UINT32 Level; + UINT32 LastLevel; + UINT32 Count; + UINT32 BitOffset; + UINT32 Flags; + UINT32 AmlOffset; + +} 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) ( + ACPI_OP_WALK_INFO *Info, + 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 AcpiDmTableInfoAestHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestProcError[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestCacheRsrc[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestTlbRsrc[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestGenRsrc[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestMemError[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestSmmuError[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestVendorError[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestVendorV2Error[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestGicError[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestPCIeError[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestProxyError[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestXface[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestXfaceHeader[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestXface4k[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestXface16k[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestXface64k[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestXrupt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAestXruptV2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAgdi[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoApmtNode[]; +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 AcpiDmTableInfoAspt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAsptHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAspt0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAspt1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoAspt2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoBdat[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoBoot[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoBert[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoBgrt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCcel[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCdatTableHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCdatHeader[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCdat0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCdat1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCdat2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCdat3[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCdat4[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCdat5[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCdatEntries[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCedtHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCedt0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCedt1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCedt1_te[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCedt2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCedt2_te[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCedt3[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCpep[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCpep0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCsrt0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCsrt1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCsrt2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoCsrt2a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDbg2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDbg2Device[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDbg2Addr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDbg2Size[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDbg2Name[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDbg2OemData[]; +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 AcpiDmTableInfoDmar4[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDmar5[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDmar6[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDrtm[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDrtm0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDrtm0a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDrtm1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDrtm1a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDrtm2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDtpr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDtprInstance[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDtprArr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDtprSerializeReq0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoDtprSerializeReq1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoEcdt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoEinj[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoEinj0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdtHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdtCacd[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdtCacdX2apic[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdtCarc[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdtCard[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdtCmrc[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdtCmrd[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdtDacd[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdtDacdPath[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdtDacdScope[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdtIbad[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdtIbrd[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdtIbrdCorrFactor[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdtMarc[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdtMmrc[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdtMmrcCorrFactor[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoErdtRmdd[]; +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 AcpiDmTableInfoFadt6[]; +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 AcpiDmTableInfoGtdtHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoGtdtEl2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoGtdt0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoGtdt0a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoGtdt1[]; +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 AcpiDmTableInfoHest10[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHest11[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHestNotify[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHestBank[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHpet[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoLpitHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoLpit0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoLpit1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHmat[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHmat0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHmat1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHmat1a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHmat1b[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHmat1c[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHmat2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHmat2a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoHmatHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIort[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIort0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIort0a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIort1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIort1a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIort2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIort3[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIort3a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIort3b[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIort3c[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIort4[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIort5[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIort6[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIort6a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIort7[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIortAcc[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIortHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIortHdr3[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIortMap[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIortPad[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIovt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIovt0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIovtdev[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrsHware1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrsHware23[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrsMemory[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs4[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs8a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs8b[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrs8c[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrsCidString[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrsCidInteger[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrsHid[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrsUidString[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrsUidInteger[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrsHidString[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoIvrsHidInteger[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoKeyp[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoKeypHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoKeyp0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoKeyp0a[]; +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 AcpiDmTableInfoMadt11a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt11b[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt12[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt13[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt14[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt14a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt15[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt15a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt16[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt17[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt18[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt19[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt20[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt21[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt22[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt23[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt24[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt25[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt26[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt27[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt28[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt29[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt30[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadt128[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMadtHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMcfg[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMcfg0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMchi[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMisc[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMisc0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMisc0Data[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpam0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpam1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpam1A[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpam1B[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpam1C[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpam1D[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpam1E[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpam1F[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpam1G[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpam1Deps[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMpam2[]; +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 AcpiDmTableInfoMrrm[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMrrm0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMsct[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoMsct0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoNfit[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoNfitHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoNfit0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoNfit1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoNfit2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoNfit2a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoNfit3[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoNfit3a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoNfit4[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoNfit5[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoNfit6[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoNfit6a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoNfit7[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPhatHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPhat0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPhat0a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPhat1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPhat1a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPhat1b[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPmtt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPmtt0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPmtt1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPmtt2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPmttVendor[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPmttHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPcct[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPcctHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPcct0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPcct1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPcct2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPcct3[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPcct4[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPcct5[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPdtt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPdtt0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPptt0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPptt0a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPptt1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPptt1a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPptt2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPpttHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPrmtHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPrmtModule[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoPrmtHandler[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRasf[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRas2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRas2PccDesc[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRgrt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRgrt0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRhct[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRhctNodeHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRhctIsa1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRhctIsaPad[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRhctCmo1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRhctMmu1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRhctHartInfo1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRhctHartInfo2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRimt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRimtNodeHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRimtIommu[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRimtIommuWire[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRimtPcieRc[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRimtIdMapping[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRimtPlatDev[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoRimtPlatDevPad[]; +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 AcpiDmTableInfoSdei[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSdev[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSdevHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSdev0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSdev0a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSdev0b[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSdevSecCompHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSdevSecCompId[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSdevSecCompMem[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSdev1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSdev1a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSdev1b[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSlic[]; +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 AcpiDmTableInfoSrat3[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSrat4[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSrat5[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSrat6[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSrat7[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoStao[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoStaoStr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSvkl[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSvkl0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSwft[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSwftFileHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoSwftFileData[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoTcpaHdr[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoTcpaClient[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoTcpaServer[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoTdel[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoTpm2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoTpm2a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoTpm211[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoTpm23[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoTpm23a[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoUbrt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoUbrtSubtable[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoUefi[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoViot[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoViotHeader[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoViot1[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoViot2[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoViot3[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoViot4[]; +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 AcpiDmTableInfoWpbt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoWpbt0[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoWsmt[]; +extern ACPI_DMTABLE_INFO AcpiDmTableInfoXenv[]; + +extern ACPI_DMTABLE_INFO AcpiDmTableInfoGeneric[][2]; + +/* + * dmtable and ahtable + */ +extern const ACPI_DMTABLE_DATA AcpiDmTableData[]; +extern const AH_TABLE AcpiGbl_SupportedTables[]; + +UINT8 +AcpiDmGenerateChecksum ( + void *Table, + UINT32 Length, + UINT8 OriginalChecksum); + +const 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 +AcpiDmDumpBuffer ( + void *Table, + UINT32 BufferOffset, + UINT32 Length, + UINT32 AbsoluteOffset, + char *Header); + +void +AcpiDmDumpUnicode ( + void *Table, + UINT32 BufferOffset, + UINT32 ByteLength); + +void +AcpiDmDumpAest ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpApmt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpAsf ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpAspt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpCcel ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpCdat ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpCedt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpCpep ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpCsrt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpDbg2 ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpDmar ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpDrtm ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpDtpr ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpEinj ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpErdt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpErst ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpFadt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpFpdt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpGtdt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpHest ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpHmat ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpIort ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpIovt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpIvrs ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpKeyp ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpLpit ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpMadt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpMcfg ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpMisc ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpMpam ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpMpst ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpMrrm ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpMsct ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpNfit ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpPcct ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpPdtt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpPhat ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpPmtt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpPptt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpPrmt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpRas2 ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpRgrt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpRhct ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpRimt ( + ACPI_TABLE_HEADER *Table); + +UINT32 +AcpiDmDumpRsdp ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpRsdt ( + ACPI_TABLE_HEADER *Table); + +UINT32 +AcpiDmDumpS3pt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpSdev ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpSlic ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpSlit ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpSrat ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpStao ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpSvkl ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpSwft ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpTcpa ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpTdel ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpTpm2 ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpUbrt ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpViot ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpWdat ( + ACPI_TABLE_HEADER *Table); + +void +AcpiDmDumpWpbt ( + 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); + +UINT32 +AcpiDmListType ( + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmMethodFlags ( + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmDisplayTargetPathname ( + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmNotifyDescription ( + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmPredefinedDescription ( + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmFieldPredefinedDescription ( + 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); + + +/* + * dmbuffer + */ +void +AcpiDmDisasmByteList ( + UINT32 Level, + UINT8 *ByteData, + UINT32 ByteCount); + +void +AcpiDmByteList ( + ACPI_OP_WALK_INFO *Info, + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmCheckForHardwareId ( + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmDecompressEisaId ( + UINT32 EncodedId); + +BOOLEAN +AcpiDmIsUuidBuffer ( + ACPI_PARSE_OBJECT *Op); + +BOOLEAN +AcpiDmIsUnicodeBuffer ( + ACPI_PARSE_OBJECT *Op); + +BOOLEAN +AcpiDmIsStringBuffer ( + ACPI_PARSE_OBJECT *Op); + +BOOLEAN +AcpiDmIsPldBuffer ( + ACPI_PARSE_OBJECT *Op); + + +/* + * dmdeferred + */ +ACPI_STATUS +AcpiDmParseDeferredOps ( + ACPI_PARSE_OBJECT *Root); + + +/* + * dmextern + */ +ACPI_STATUS +AcpiDmAddToExternalFileList ( + char *PathList); + +void +AcpiDmClearExternalFileList ( + void); + +void +AcpiDmAddOpToExternalList ( + ACPI_PARSE_OBJECT *Op, + char *Path, + UINT8 Type, + UINT32 Value, + UINT16 Flags); + +void +AcpiDmCreateSubobjectForExternal ( + UINT8 Type, + ACPI_NAMESPACE_NODE **Node, + UINT32 Value); + +void +AcpiDmAddNodeToExternalList ( + ACPI_NAMESPACE_NODE *Node, + UINT8 Type, + UINT32 Value, + UINT16 Flags); + +void +AcpiDmAddExternalListToNamespace ( + void); + +void +AcpiDmAddOneExternalToNamespace ( + char *Path, + UINT8 Type, + UINT32 Value); + +UINT32 +AcpiDmGetUnresolvedExternalMethodCount ( + void); + +void +AcpiDmClearExternalList ( + void); + +void +AcpiDmEmitExternals ( + void); + +void +AcpiDmEmitExternal ( + ACPI_PARSE_OBJECT *NameOp, + ACPI_PARSE_OBJECT *TypeOp); + +void +AcpiDmUnresolvedWarning ( + UINT8 Type); + +void +AcpiDmGetExternalsFromFile ( + void); + +void +AcpiDmMarkExternalConflict ( + ACPI_NAMESPACE_NODE *Node); + + +/* + * dmresrc + */ +void +AcpiDmDumpInteger8 ( + UINT8 Value, + const char *Name); + +void +AcpiDmDumpInteger16 ( + UINT16 Value, + const char *Name); + +void +AcpiDmDumpInteger32 ( + UINT32 Value, + const char *Name); + +void +AcpiDmDumpInteger64 ( + UINT64 Value, + const char *Name); + +void +AcpiDmResourceTemplate ( + ACPI_OP_WALK_INFO *Info, + ACPI_PARSE_OBJECT *Op, + UINT8 *ByteData, + UINT32 ByteCount); + +ACPI_STATUS +AcpiDmIsResourceTemplate ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmBitList ( + UINT16 Mask); + +void +AcpiDmDescriptorName ( + void); + + +/* + * dmresrcl + */ +void +AcpiDmWordDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmDwordDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmExtendedDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmQwordDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmMemory24Descriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmMemory32Descriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmFixedMemory32Descriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmGenericRegisterDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmInterruptDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmVendorLargeDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmGpioDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmPinFunctionDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmPinConfigDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmPinGroupDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmPinGroupFunctionDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmPinGroupConfigDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmSerialBusDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmVendorCommon ( + const char *Name, + UINT8 *ByteData, + UINT32 Length, + UINT32 Level); + +void +AcpiDmClockInputDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +/* + * dmresrcs + */ +void +AcpiDmIrqDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmDmaDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmFixedDmaDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmIoDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmFixedIoDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmStartDependentDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmEndDependentDescriptor ( + ACPI_OP_WALK_INFO *Info, + AML_RESOURCE *Resource, + UINT32 Length, + UINT32 Level); + +void +AcpiDmVendorSmallDescriptor ( + ACPI_OP_WALK_INFO *Info, + 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); + + +/* + * dmcstyle + */ +BOOLEAN +AcpiDmCheckForSymbolicOpcode ( + ACPI_PARSE_OBJECT *Op, + ACPI_OP_WALK_INFO *Info); + +void +AcpiDmCloseOperator ( + ACPI_PARSE_OBJECT *Op); + + +/* + * dmtables + */ +ACPI_STATUS +AcpiDmProcessSwitch ( + ACPI_PARSE_OBJECT *Op); + +void +AcpiDmClearTempList( + void); + +/* + * dmtables + */ +void +AdDisassemblerHeader ( + char *Filename, + UINT8 TableType); + +#define ACPI_IS_AML_TABLE 0 +#define ACPI_IS_DATA_TABLE 1 + + +/* + * adisasm + */ +ACPI_STATUS +AdAmlDisassemble ( + BOOLEAN OutToFile, + char *Filename, + char *Prefix, + char **OutFilename); + +ACPI_STATUS +AdGetLocalTables ( + void); + +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); + + +/* + * dmwalk + */ +UINT32 +AcpiDmBlockType ( + ACPI_PARSE_OBJECT *Op); + + +#endif /* __ACDISASM_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acdispat.h b/code/drivers/platform/acpi/third_party/acpica/include/acdispat.h new file mode 100644 index 0000000..c50874b --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acdispat.h @@ -0,0 +1,461 @@ +/****************************************************************************** + * + * Name: acdispat.h - dispatcher (parser to interpreter interface) + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 + */ +ACPI_STATUS +AcpiDsInitCallbacks ( + ACPI_WALK_STATE *WalkState, + UINT32 PassNumber); + +/* dsload - pass 1 namespace load callbacks */ + +ACPI_STATUS +AcpiDsLoad1BeginOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT **OutOp); + +ACPI_STATUS +AcpiDsLoad1EndOp ( + ACPI_WALK_STATE *WalkState); + + +/* dsload - 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 +AcpiDsAutoSerializeMethod ( + ACPI_NAMESPACE_NODE *Node, + ACPI_OPERAND_OBJECT *ObjDesc); + +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 +AcpiDsBuildInternalObject ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + ACPI_OPERAND_OBJECT **ObjDescPtr); + +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); + + +/* + * dspkginit - Package object initialization + */ +ACPI_STATUS +AcpiDsInitPackageElement ( + UINT8 ObjectType, + ACPI_OPERAND_OBJECT *SourceObject, + ACPI_GENERIC_STATE *State, + void *Context); + + +/* + * 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); + + +/* + * dsdebug - parser debugging routines + */ +void +AcpiDsDumpMethodStack ( + ACPI_STATUS Status, + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op); + +#endif /* _ACDISPAT_H_ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acevents.h b/code/drivers/platform/acpi/third_party/acpica/include/acevents.h new file mode 100644 index 0000000..ace3ca9 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acevents.h @@ -0,0 +1,374 @@ +/****************************************************************************** + * + * Name: acevents.h - Event subcomponent prototypes and defines + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACEVENTS_H__ +#define __ACEVENTS_H__ + + +/* + * Conditions to trigger post enabling GPE polling: + * It is not sufficient to trigger edge-triggered GPE with specific GPE + * chips, software need to poll once after enabling. + */ +#ifdef ACPI_USE_GPE_POLLING +#define ACPI_GPE_IS_POLLING_NEEDED(__gpe__) \ + ((__gpe__)->RuntimeCount == 1 && \ + (__gpe__)->Flags & ACPI_GPE_INITIALIZED && \ + ((__gpe__)->Flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_EDGE_TRIGGERED) +#else +#define ACPI_GPE_IS_POLLING_NEEDED(__gpe__) FALSE +#endif + + +/* + * 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 +AcpiEvMaskGpe ( + ACPI_GPE_EVENT_INFO *GpeEventInfo, + BOOLEAN IsMasked); + +ACPI_STATUS +AcpiEvAddGpeReference ( + ACPI_GPE_EVENT_INFO *GpeEventInfo, + BOOLEAN ClearOnEnable); + +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); + +UINT32 +AcpiEvDetectGpe ( + ACPI_NAMESPACE_NODE *GpeDevice, + ACPI_GPE_EVENT_INFO *GpeEventInfo, + UINT32 GpeNumber); + + +/* + * evgpeblk - Upper-level GPE block support + */ +ACPI_STATUS +AcpiEvCreateGpeBlock ( + ACPI_NAMESPACE_NODE *GpeDevice, + UINT64 Address, + UINT8 SpaceId, + UINT32 RegisterCount, + UINT16 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_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiEvClearGpeDispatchByOwner ( + ACPI_OWNER_ID OwnerId)) + +ACPI_STATUS +AcpiEvMatchGpeMethod ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + + +/* + * evgpeutil - GPE utilities + */ +ACPI_STATUS +AcpiEvWalkGpeList ( + ACPI_GPE_CALLBACK GpeWalkCallback, + void *Context); + +ACPI_STATUS +AcpiEvGetGpeDevice ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context); + +ACPI_STATUS +AcpiEvGetGpeXruptBlock ( + UINT32 InterruptNumber, + ACPI_GPE_XRUPT_INFO **GpeXruptBlock); + +ACPI_STATUS +AcpiEvDeleteGpeXrupt ( + ACPI_GPE_XRUPT_INFO *GpeXrupt); + +ACPI_STATUS +AcpiEvDeleteGpeHandlers ( + ACPI_GPE_XRUPT_INFO *GpeXruptInfo, + ACPI_GPE_BLOCK_INFO *GpeBlock, + void *Context); + + +/* + * evhandler - Address space handling + */ +ACPI_OPERAND_OBJECT * +AcpiEvFindRegionHandler ( + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_OPERAND_OBJECT *HandlerObj); + +BOOLEAN +AcpiEvHasDefaultHandler ( + ACPI_NAMESPACE_NODE *Node, + ACPI_ADR_SPACE_TYPE SpaceId); + +ACPI_STATUS +AcpiEvInstallRegionHandlers ( + void); + +ACPI_STATUS +AcpiEvInstallSpaceHandler ( + ACPI_NAMESPACE_NODE *Node, + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_ADR_SPACE_HANDLER Handler, + ACPI_ADR_SPACE_SETUP Setup, + void *Context); + + +/* + * evregion - Operation region support + */ +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); + +void +AcpiEvExecuteRegMethods ( + ACPI_NAMESPACE_NODE *Node, + ACPI_ADR_SPACE_TYPE SpaceId, + UINT32 Function); + +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 +AcpiEvDataTableRegionSetup ( + 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 +AcpiEvIsPciRootBridge ( + ACPI_NAMESPACE_NODE *Node); + + +/* + * evsci - SCI (System Control Interrupt) handling/dispatch + */ +UINT32 ACPI_SYSTEM_XFACE +AcpiEvGpeXruptHandler ( + void *Context); + +UINT32 +AcpiEvSciDispatch ( + void); + +UINT32 +AcpiEvInstallSciHandler ( + void); + +ACPI_STATUS +AcpiEvRemoveAllSciHandlers ( + void); + +ACPI_HW_DEPENDENT_RETURN_VOID ( +void +AcpiEvTerminate ( + void)) + +#endif /* __ACEVENTS_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acexcep.h b/code/drivers/platform/acpi/third_party/acpica/include/acexcep.h new file mode 100644 index 0000000..2d20618 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acexcep.h @@ -0,0 +1,348 @@ +/****************************************************************************** + * + * Name: acexcep.h - Exception codes returned by the ACPI subsystem + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACEXCEP_H__ +#define __ACEXCEP_H__ + + +/* This module contains all possible exception codes for ACPI_STATUS */ + +/* + * Exception code classes + */ +#define AE_CODE_ENVIRONMENTAL 0x0000 /* General ACPICA environment */ +#define AE_CODE_PROGRAMMER 0x1000 /* External ACPICA interface caller */ +#define AE_CODE_ACPI_TABLES 0x2000 /* ACPI tables */ +#define AE_CODE_AML 0x3000 /* From executing AML code */ +#define AE_CODE_CONTROL 0x4000 /* Internal control codes */ + +#define AE_CODE_MAX 0x4000 +#define AE_CODE_MASK 0xF000 + +/* + * Macros to insert the exception code classes + */ +#define EXCEP_ENV(code) ((ACPI_STATUS) (code | AE_CODE_ENVIRONMENTAL)) +#define EXCEP_PGM(code) ((ACPI_STATUS) (code | AE_CODE_PROGRAMMER)) +#define EXCEP_TBL(code) ((ACPI_STATUS) (code | AE_CODE_ACPI_TABLES)) +#define EXCEP_AML(code) ((ACPI_STATUS) (code | AE_CODE_AML)) +#define EXCEP_CTL(code) ((ACPI_STATUS) (code | AE_CODE_CONTROL)) + +/* + * Exception info table. The "Description" field is used only by the + * ACPICA help application (acpihelp). + */ +typedef struct acpi_exception_info +{ + char *Name; + +#if defined (ACPI_HELP_APP) || defined (ACPI_ASL_COMPILER) + char *Description; +#endif +} ACPI_EXCEPTION_INFO; + +#if defined (ACPI_HELP_APP) || defined (ACPI_ASL_COMPILER) +#define EXCEP_TXT(Name,Description) {Name, Description} +#else +#define EXCEP_TXT(Name,Description) {Name} +#endif + + +/* + * Success is always zero, failure is non-zero + */ +#define ACPI_SUCCESS(a) (!(a)) +#define ACPI_FAILURE(a) (a) + +#define AE_OK (ACPI_STATUS) 0x0000 + +#define ACPI_ENV_EXCEPTION(Status) (((Status) & AE_CODE_MASK) == AE_CODE_ENVIRONMENTAL) +#define ACPI_AML_EXCEPTION(Status) (((Status) & AE_CODE_MASK) == AE_CODE_AML) +#define ACPI_PROG_EXCEPTION(Status) (((Status) & AE_CODE_MASK) == AE_CODE_PROGRAMMER) +#define ACPI_TABLE_EXCEPTION(Status) (((Status) & AE_CODE_MASK) == AE_CODE_ACPI_TABLES) +#define ACPI_CNTL_EXCEPTION(Status) (((Status) & AE_CODE_MASK) == AE_CODE_CONTROL) + + +/* + * Environmental exceptions + */ +#define AE_ERROR EXCEP_ENV (0x0001) +#define AE_NO_ACPI_TABLES EXCEP_ENV (0x0002) +#define AE_NO_NAMESPACE EXCEP_ENV (0x0003) +#define AE_NO_MEMORY EXCEP_ENV (0x0004) +#define AE_NOT_FOUND EXCEP_ENV (0x0005) +#define AE_NOT_EXIST EXCEP_ENV (0x0006) +#define AE_ALREADY_EXISTS EXCEP_ENV (0x0007) +#define AE_TYPE EXCEP_ENV (0x0008) +#define AE_NULL_OBJECT EXCEP_ENV (0x0009) +#define AE_NULL_ENTRY EXCEP_ENV (0x000A) +#define AE_BUFFER_OVERFLOW EXCEP_ENV (0x000B) +#define AE_STACK_OVERFLOW EXCEP_ENV (0x000C) +#define AE_STACK_UNDERFLOW EXCEP_ENV (0x000D) +#define AE_NOT_IMPLEMENTED EXCEP_ENV (0x000E) +#define AE_SUPPORT EXCEP_ENV (0x000F) +#define AE_LIMIT EXCEP_ENV (0x0010) +#define AE_TIME EXCEP_ENV (0x0011) +#define AE_ACQUIRE_DEADLOCK EXCEP_ENV (0x0012) +#define AE_RELEASE_DEADLOCK EXCEP_ENV (0x0013) +#define AE_NOT_ACQUIRED EXCEP_ENV (0x0014) +#define AE_ALREADY_ACQUIRED EXCEP_ENV (0x0015) +#define AE_NO_HARDWARE_RESPONSE EXCEP_ENV (0x0016) +#define AE_NO_GLOBAL_LOCK EXCEP_ENV (0x0017) +#define AE_ABORT_METHOD EXCEP_ENV (0x0018) +#define AE_SAME_HANDLER EXCEP_ENV (0x0019) +#define AE_NO_HANDLER EXCEP_ENV (0x001A) +#define AE_OWNER_ID_LIMIT EXCEP_ENV (0x001B) +#define AE_NOT_CONFIGURED EXCEP_ENV (0x001C) +#define AE_ACCESS EXCEP_ENV (0x001D) +#define AE_IO_ERROR EXCEP_ENV (0x001E) +#define AE_NUMERIC_OVERFLOW EXCEP_ENV (0x001F) +#define AE_HEX_OVERFLOW EXCEP_ENV (0x0020) +#define AE_DECIMAL_OVERFLOW EXCEP_ENV (0x0021) +#define AE_OCTAL_OVERFLOW EXCEP_ENV (0x0022) +#define AE_END_OF_TABLE EXCEP_ENV (0x0023) + +#define AE_CODE_ENV_MAX 0x0023 + + +/* + * Programmer exceptions + */ +#define AE_BAD_PARAMETER EXCEP_PGM (0x0001) +#define AE_BAD_CHARACTER EXCEP_PGM (0x0002) +#define AE_BAD_PATHNAME EXCEP_PGM (0x0003) +#define AE_BAD_DATA EXCEP_PGM (0x0004) +#define AE_BAD_HEX_CONSTANT EXCEP_PGM (0x0005) +#define AE_BAD_OCTAL_CONSTANT EXCEP_PGM (0x0006) +#define AE_BAD_DECIMAL_CONSTANT EXCEP_PGM (0x0007) +#define AE_MISSING_ARGUMENTS EXCEP_PGM (0x0008) +#define AE_BAD_ADDRESS EXCEP_PGM (0x0009) + +#define AE_CODE_PGM_MAX 0x0009 + + +/* + * Acpi table exceptions + */ +#define AE_BAD_SIGNATURE EXCEP_TBL (0x0001) +#define AE_BAD_HEADER EXCEP_TBL (0x0002) +#define AE_BAD_CHECKSUM EXCEP_TBL (0x0003) +#define AE_BAD_VALUE EXCEP_TBL (0x0004) +#define AE_INVALID_TABLE_LENGTH EXCEP_TBL (0x0005) + +#define AE_CODE_TBL_MAX 0x0005 + + +/* + * AML exceptions. These are caused by problems with + * the actual AML byte stream + */ +#define AE_AML_BAD_OPCODE EXCEP_AML (0x0001) +#define AE_AML_NO_OPERAND EXCEP_AML (0x0002) +#define AE_AML_OPERAND_TYPE EXCEP_AML (0x0003) +#define AE_AML_OPERAND_VALUE EXCEP_AML (0x0004) +#define AE_AML_UNINITIALIZED_LOCAL EXCEP_AML (0x0005) +#define AE_AML_UNINITIALIZED_ARG EXCEP_AML (0x0006) +#define AE_AML_UNINITIALIZED_ELEMENT EXCEP_AML (0x0007) +#define AE_AML_NUMERIC_OVERFLOW EXCEP_AML (0x0008) +#define AE_AML_REGION_LIMIT EXCEP_AML (0x0009) +#define AE_AML_BUFFER_LIMIT EXCEP_AML (0x000A) +#define AE_AML_PACKAGE_LIMIT EXCEP_AML (0x000B) +#define AE_AML_DIVIDE_BY_ZERO EXCEP_AML (0x000C) +#define AE_AML_BAD_NAME EXCEP_AML (0x000D) +#define AE_AML_NAME_NOT_FOUND EXCEP_AML (0x000E) +#define AE_AML_INTERNAL EXCEP_AML (0x000F) +#define AE_AML_INVALID_SPACE_ID EXCEP_AML (0x0010) +#define AE_AML_STRING_LIMIT EXCEP_AML (0x0011) +#define AE_AML_NO_RETURN_VALUE EXCEP_AML (0x0012) +#define AE_AML_METHOD_LIMIT EXCEP_AML (0x0013) +#define AE_AML_NOT_OWNER EXCEP_AML (0x0014) +#define AE_AML_MUTEX_ORDER EXCEP_AML (0x0015) +#define AE_AML_MUTEX_NOT_ACQUIRED EXCEP_AML (0x0016) +#define AE_AML_INVALID_RESOURCE_TYPE EXCEP_AML (0x0017) +#define AE_AML_INVALID_INDEX EXCEP_AML (0x0018) +#define AE_AML_REGISTER_LIMIT EXCEP_AML (0x0019) +#define AE_AML_NO_WHILE EXCEP_AML (0x001A) +#define AE_AML_ALIGNMENT EXCEP_AML (0x001B) +#define AE_AML_NO_RESOURCE_END_TAG EXCEP_AML (0x001C) +#define AE_AML_BAD_RESOURCE_VALUE EXCEP_AML (0x001D) +#define AE_AML_CIRCULAR_REFERENCE EXCEP_AML (0x001E) +#define AE_AML_BAD_RESOURCE_LENGTH EXCEP_AML (0x001F) +#define AE_AML_ILLEGAL_ADDRESS EXCEP_AML (0x0020) +#define AE_AML_LOOP_TIMEOUT EXCEP_AML (0x0021) +#define AE_AML_UNINITIALIZED_NODE EXCEP_AML (0x0022) +#define AE_AML_TARGET_TYPE EXCEP_AML (0x0023) +#define AE_AML_PROTOCOL EXCEP_AML (0x0024) +#define AE_AML_BUFFER_LENGTH EXCEP_AML (0x0025) +#define AE_AML_TOO_FEW_ARGUMENTS EXCEP_AML (0x0026) +#define AE_AML_TOO_MANY_ARGUMENTS EXCEP_AML (0x0027) + + +#define AE_CODE_AML_MAX 0x0027 + + +/* + * Internal exceptions used for control + */ +#define AE_CTRL_RETURN_VALUE EXCEP_CTL (0x0001) +#define AE_CTRL_PENDING EXCEP_CTL (0x0002) +#define AE_CTRL_TERMINATE EXCEP_CTL (0x0003) +#define AE_CTRL_TRUE EXCEP_CTL (0x0004) +#define AE_CTRL_FALSE EXCEP_CTL (0x0005) +#define AE_CTRL_DEPTH EXCEP_CTL (0x0006) +#define AE_CTRL_END EXCEP_CTL (0x0007) +#define AE_CTRL_TRANSFER EXCEP_CTL (0x0008) +#define AE_CTRL_BREAK EXCEP_CTL (0x0009) +#define AE_CTRL_CONTINUE EXCEP_CTL (0x000A) +#define AE_CTRL_PARSE_CONTINUE EXCEP_CTL (0x000B) +#define AE_CTRL_PARSE_PENDING EXCEP_CTL (0x000C) + +#define AE_CODE_CTRL_MAX 0x000C + + +/* Exception strings for AcpiFormatException */ + +#ifdef ACPI_DEFINE_EXCEPTION_TABLE + +/* + * String versions of the exception codes above + * These strings must match the corresponding defines exactly + */ +static const ACPI_EXCEPTION_INFO AcpiGbl_ExceptionNames_Env[] = +{ + EXCEP_TXT ("AE_OK", "No error"), + EXCEP_TXT ("AE_ERROR", "Unspecified error"), + EXCEP_TXT ("AE_NO_ACPI_TABLES", "ACPI tables could not be found"), + EXCEP_TXT ("AE_NO_NAMESPACE", "A namespace has not been loaded"), + EXCEP_TXT ("AE_NO_MEMORY", "Insufficient dynamic memory"), + EXCEP_TXT ("AE_NOT_FOUND", "A requested entity is not found"), + EXCEP_TXT ("AE_NOT_EXIST", "A required entity does not exist"), + EXCEP_TXT ("AE_ALREADY_EXISTS", "An entity already exists"), + EXCEP_TXT ("AE_TYPE", "The object type is incorrect"), + EXCEP_TXT ("AE_NULL_OBJECT", "A required object was missing"), + EXCEP_TXT ("AE_NULL_ENTRY", "The requested object does not exist"), + EXCEP_TXT ("AE_BUFFER_OVERFLOW", "The buffer provided is too small"), + EXCEP_TXT ("AE_STACK_OVERFLOW", "An internal stack overflowed"), + EXCEP_TXT ("AE_STACK_UNDERFLOW", "An internal stack underflowed"), + EXCEP_TXT ("AE_NOT_IMPLEMENTED", "The feature is not implemented"), + EXCEP_TXT ("AE_SUPPORT", "The feature is not supported"), + EXCEP_TXT ("AE_LIMIT", "A predefined limit was exceeded"), + EXCEP_TXT ("AE_TIME", "A time limit or timeout expired"), + EXCEP_TXT ("AE_ACQUIRE_DEADLOCK", "Internal error, attempt was made to acquire a mutex in improper order"), + EXCEP_TXT ("AE_RELEASE_DEADLOCK", "Internal error, attempt was made to release a mutex in improper order"), + EXCEP_TXT ("AE_NOT_ACQUIRED", "An attempt to release a mutex or Global Lock without a previous acquire"), + EXCEP_TXT ("AE_ALREADY_ACQUIRED", "Internal error, attempt was made to acquire a mutex twice"), + EXCEP_TXT ("AE_NO_HARDWARE_RESPONSE", "Hardware did not respond after an I/O operation"), + EXCEP_TXT ("AE_NO_GLOBAL_LOCK", "There is no FACS Global Lock"), + EXCEP_TXT ("AE_ABORT_METHOD", "A control method was aborted"), + EXCEP_TXT ("AE_SAME_HANDLER", "Attempt was made to install the same handler that is already installed"), + EXCEP_TXT ("AE_NO_HANDLER", "A handler for the operation is not installed"), + EXCEP_TXT ("AE_OWNER_ID_LIMIT", "There are no more Owner IDs available for ACPI tables or control methods"), + EXCEP_TXT ("AE_NOT_CONFIGURED", "The interface is not part of the current subsystem configuration"), + EXCEP_TXT ("AE_ACCESS", "Permission denied for the requested operation"), + EXCEP_TXT ("AE_IO_ERROR", "An I/O error occurred"), + EXCEP_TXT ("AE_NUMERIC_OVERFLOW", "Overflow during string-to-integer conversion"), + EXCEP_TXT ("AE_HEX_OVERFLOW", "Overflow during ASCII hex-to-binary conversion"), + EXCEP_TXT ("AE_DECIMAL_OVERFLOW", "Overflow during ASCII decimal-to-binary conversion"), + EXCEP_TXT ("AE_OCTAL_OVERFLOW", "Overflow during ASCII octal-to-binary conversion"), + EXCEP_TXT ("AE_END_OF_TABLE", "Reached the end of table") +}; + +static const ACPI_EXCEPTION_INFO AcpiGbl_ExceptionNames_Pgm[] = +{ + EXCEP_TXT (NULL, NULL), + EXCEP_TXT ("AE_BAD_PARAMETER", "A parameter is out of range or invalid"), + EXCEP_TXT ("AE_BAD_CHARACTER", "An invalid character was found in a name"), + EXCEP_TXT ("AE_BAD_PATHNAME", "An invalid character was found in a pathname"), + EXCEP_TXT ("AE_BAD_DATA", "A package or buffer contained incorrect data"), + EXCEP_TXT ("AE_BAD_HEX_CONSTANT", "Invalid character in a Hex constant"), + EXCEP_TXT ("AE_BAD_OCTAL_CONSTANT", "Invalid character in an Octal constant"), + EXCEP_TXT ("AE_BAD_DECIMAL_CONSTANT", "Invalid character in a Decimal constant"), + EXCEP_TXT ("AE_MISSING_ARGUMENTS", "Too few arguments were passed to a control method"), + EXCEP_TXT ("AE_BAD_ADDRESS", "An illegal null I/O address") +}; + +static const ACPI_EXCEPTION_INFO AcpiGbl_ExceptionNames_Tbl[] = +{ + EXCEP_TXT (NULL, NULL), + EXCEP_TXT ("AE_BAD_SIGNATURE", "An ACPI table has an invalid signature"), + EXCEP_TXT ("AE_BAD_HEADER", "Invalid field in an ACPI table header"), + EXCEP_TXT ("AE_BAD_CHECKSUM", "An ACPI table checksum is not correct"), + EXCEP_TXT ("AE_BAD_VALUE", "An invalid value was found in a table"), + EXCEP_TXT ("AE_INVALID_TABLE_LENGTH", "The FADT or FACS has improper length") +}; + +static const ACPI_EXCEPTION_INFO AcpiGbl_ExceptionNames_Aml[] = +{ + EXCEP_TXT (NULL, NULL), + EXCEP_TXT ("AE_AML_BAD_OPCODE", "Invalid AML opcode encountered"), + EXCEP_TXT ("AE_AML_NO_OPERAND", "A required operand is missing"), + EXCEP_TXT ("AE_AML_OPERAND_TYPE", "An operand of an incorrect type was encountered"), + EXCEP_TXT ("AE_AML_OPERAND_VALUE", "The operand had an inappropriate or invalid value"), + EXCEP_TXT ("AE_AML_UNINITIALIZED_LOCAL", "Method tried to use an uninitialized local variable"), + EXCEP_TXT ("AE_AML_UNINITIALIZED_ARG", "Method tried to use an uninitialized argument"), + EXCEP_TXT ("AE_AML_UNINITIALIZED_ELEMENT", "Method tried to use an empty package element"), + EXCEP_TXT ("AE_AML_NUMERIC_OVERFLOW", "Overflow during BCD conversion or other"), + EXCEP_TXT ("AE_AML_REGION_LIMIT", "Tried to access beyond the end of an Operation Region"), + EXCEP_TXT ("AE_AML_BUFFER_LIMIT", "Tried to access beyond the end of a buffer"), + EXCEP_TXT ("AE_AML_PACKAGE_LIMIT", "Tried to access beyond the end of a package"), + EXCEP_TXT ("AE_AML_DIVIDE_BY_ZERO", "During execution of AML Divide operator"), + EXCEP_TXT ("AE_AML_BAD_NAME", "An ACPI name contains invalid character(s)"), + EXCEP_TXT ("AE_AML_NAME_NOT_FOUND", "Could not resolve a named reference"), + EXCEP_TXT ("AE_AML_INTERNAL", "An internal error within the interpreter"), + EXCEP_TXT ("AE_AML_INVALID_SPACE_ID", "An Operation Region SpaceID is invalid"), + EXCEP_TXT ("AE_AML_STRING_LIMIT", "String is longer than 200 characters"), + EXCEP_TXT ("AE_AML_NO_RETURN_VALUE", "A method did not return a required value"), + EXCEP_TXT ("AE_AML_METHOD_LIMIT", "A control method reached the maximum reentrancy limit of 255"), + EXCEP_TXT ("AE_AML_NOT_OWNER", "A thread tried to release a mutex that it does not own"), + EXCEP_TXT ("AE_AML_MUTEX_ORDER", "Mutex SyncLevel release mismatch"), + EXCEP_TXT ("AE_AML_MUTEX_NOT_ACQUIRED", "Attempt to release a mutex that was not previously acquired"), + EXCEP_TXT ("AE_AML_INVALID_RESOURCE_TYPE", "Invalid resource type in resource list"), + EXCEP_TXT ("AE_AML_INVALID_INDEX", "Invalid Argx or Localx (x too large)"), + EXCEP_TXT ("AE_AML_REGISTER_LIMIT", "Bank value or Index value beyond range of register"), + EXCEP_TXT ("AE_AML_NO_WHILE", "Break or Continue without a While"), + EXCEP_TXT ("AE_AML_ALIGNMENT", "Non-aligned memory transfer on platform that does not support this"), + EXCEP_TXT ("AE_AML_NO_RESOURCE_END_TAG", "No End Tag in a resource list"), + EXCEP_TXT ("AE_AML_BAD_RESOURCE_VALUE", "Invalid value of a resource element"), + EXCEP_TXT ("AE_AML_CIRCULAR_REFERENCE", "Two references refer to each other"), + EXCEP_TXT ("AE_AML_BAD_RESOURCE_LENGTH", "The length of a Resource Descriptor in the AML is incorrect"), + EXCEP_TXT ("AE_AML_ILLEGAL_ADDRESS", "A memory, I/O, or PCI configuration address is invalid"), + EXCEP_TXT ("AE_AML_LOOP_TIMEOUT", "An AML While loop exceeded the maximum execution time"), + EXCEP_TXT ("AE_AML_UNINITIALIZED_NODE", "A namespace node is uninitialized or unresolved"), + EXCEP_TXT ("AE_AML_TARGET_TYPE", "A target operand of an incorrect type was encountered"), + EXCEP_TXT ("AE_AML_PROTOCOL", "Violation of a fixed ACPI protocol"), + EXCEP_TXT ("AE_AML_BUFFER_LENGTH", "The length of the buffer is invalid/incorrect"), + EXCEP_TXT ("AE_AML_TOO_FEW_ARGUMENTS", "There are fewer than expected method arguments"), + EXCEP_TXT ("AE_AML_TOO_MANY_ARGUMENTS", "There are too many arguments for this method") +}; + +static const ACPI_EXCEPTION_INFO AcpiGbl_ExceptionNames_Ctrl[] = +{ + EXCEP_TXT (NULL, NULL), + EXCEP_TXT ("AE_CTRL_RETURN_VALUE", "A Method returned a value"), + EXCEP_TXT ("AE_CTRL_PENDING", "Method is calling another method"), + EXCEP_TXT ("AE_CTRL_TERMINATE", "Terminate the executing method"), + EXCEP_TXT ("AE_CTRL_TRUE", "An If or While predicate result"), + EXCEP_TXT ("AE_CTRL_FALSE", "An If or While predicate result"), + EXCEP_TXT ("AE_CTRL_DEPTH", "Maximum search depth has been reached"), + EXCEP_TXT ("AE_CTRL_END", "An If or While predicate is false"), + EXCEP_TXT ("AE_CTRL_TRANSFER", "Transfer control to called method"), + EXCEP_TXT ("AE_CTRL_BREAK", "A Break has been executed"), + EXCEP_TXT ("AE_CTRL_CONTINUE", "A Continue has been executed"), + EXCEP_TXT ("AE_CTRL_PARSE_CONTINUE", "Used to skip over bad opcodes"), + EXCEP_TXT ("AE_CTRL_PARSE_PENDING", "Used to implement AML While loops") +}; + +#endif /* EXCEPTION_TABLE */ + +#endif /* __ACEXCEP_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acglobal.h b/code/drivers/platform/acpi/third_party/acpica/include/acglobal.h new file mode 100644 index 0000000..333a338 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acglobal.h @@ -0,0 +1,399 @@ +/****************************************************************************** + * + * Name: acglobal.h - Declarations for global variables + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACGLOBAL_H__ +#define __ACGLOBAL_H__ + + +/***************************************************************************** + * + * Globals related to the incoming ACPI tables + * + ****************************************************************************/ + +/* Master list of all ACPI tables that were found in the RSDT/XSDT */ + +ACPI_GLOBAL (ACPI_TABLE_LIST, AcpiGbl_RootTableList); + +/* DSDT information. Used to check for DSDT corruption */ + +ACPI_GLOBAL (ACPI_TABLE_HEADER *, AcpiGbl_DSDT); +ACPI_GLOBAL (ACPI_TABLE_HEADER, AcpiGbl_OriginalDsdtHeader); +ACPI_INIT_GLOBAL (char *, AcpiGbl_CDAT, NULL); +ACPI_INIT_GLOBAL (UINT32, AcpiGbl_DsdtIndex, ACPI_INVALID_TABLE_INDEX); +ACPI_INIT_GLOBAL (UINT32, AcpiGbl_FacsIndex, ACPI_INVALID_TABLE_INDEX); +ACPI_INIT_GLOBAL (UINT32, AcpiGbl_XFacsIndex, ACPI_INVALID_TABLE_INDEX); +ACPI_INIT_GLOBAL (UINT32, AcpiGbl_FadtIndex, ACPI_INVALID_TABLE_INDEX); +ACPI_INIT_GLOBAL (ACPI_TABLE_FACS *, AcpiGbl_FACS, NULL); + +/* These addresses are calculated from the FADT Event Block addresses */ + +ACPI_GLOBAL (ACPI_GENERIC_ADDRESS, AcpiGbl_XPm1aStatus); +ACPI_GLOBAL (ACPI_GENERIC_ADDRESS, AcpiGbl_XPm1aEnable); + +ACPI_GLOBAL (ACPI_GENERIC_ADDRESS, AcpiGbl_XPm1bStatus); +ACPI_GLOBAL (ACPI_GENERIC_ADDRESS, AcpiGbl_XPm1bEnable); + +/* + * 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_GLOBAL (UINT8, AcpiGbl_IntegerBitWidth); +ACPI_GLOBAL (UINT8, AcpiGbl_IntegerByteWidth); +ACPI_GLOBAL (UINT8, AcpiGbl_IntegerNybbleWidth); + + +/***************************************************************************** + * + * Mutual exclusion within the 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_GLOBAL (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_GLOBAL (ACPI_OPERAND_OBJECT *, AcpiGbl_GlobalLockMutex); +ACPI_GLOBAL (ACPI_SEMAPHORE, AcpiGbl_GlobalLockSemaphore); +ACPI_GLOBAL (ACPI_SPINLOCK, AcpiGbl_GlobalLockPendingLock); +ACPI_GLOBAL (UINT16, AcpiGbl_GlobalLockHandle); +ACPI_GLOBAL (BOOLEAN, AcpiGbl_GlobalLockAcquired); +ACPI_GLOBAL (BOOLEAN, AcpiGbl_GlobalLockPresent); +ACPI_GLOBAL (BOOLEAN, AcpiGbl_GlobalLockPending); + +/* + * Spinlocks are used for interfaces that can be possibly called at + * interrupt level + */ +ACPI_GLOBAL (ACPI_SPINLOCK, AcpiGbl_GpeLock); /* For GPE data structs and registers */ +ACPI_GLOBAL (ACPI_SPINLOCK, AcpiGbl_HardwareLock); /* For ACPI H/W except GPE registers */ +ACPI_GLOBAL (ACPI_SPINLOCK, AcpiGbl_ReferenceCountLock); + +/* Mutex for _OSI support */ + +ACPI_GLOBAL (ACPI_MUTEX, AcpiGbl_OsiMutex); + +/* Reader/Writer lock is used for namespace walk and dynamic table unload */ + +ACPI_GLOBAL (ACPI_RW_LOCK, AcpiGbl_NamespaceRwLock); + + +/***************************************************************************** + * + * Miscellaneous globals + * + ****************************************************************************/ + +/* Object caches */ + +ACPI_GLOBAL (ACPI_CACHE_T *, AcpiGbl_NamespaceCache); +ACPI_GLOBAL (ACPI_CACHE_T *, AcpiGbl_StateCache); +ACPI_GLOBAL (ACPI_CACHE_T *, AcpiGbl_PsNodeCache); +ACPI_GLOBAL (ACPI_CACHE_T *, AcpiGbl_PsNodeExtCache); +ACPI_GLOBAL (ACPI_CACHE_T *, AcpiGbl_OperandCache); + +/* System */ + +ACPI_INIT_GLOBAL (UINT32, AcpiGbl_StartupFlags, 0); +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_Shutdown, TRUE); +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_EarlyInitialization, TRUE); + +/* Global handlers */ + +ACPI_GLOBAL (ACPI_GLOBAL_NOTIFY_HANDLER,AcpiGbl_GlobalNotify[2]); +ACPI_GLOBAL (ACPI_EXCEPTION_HANDLER, AcpiGbl_ExceptionHandler); +ACPI_GLOBAL (ACPI_INIT_HANDLER, AcpiGbl_InitHandler); +ACPI_GLOBAL (ACPI_TABLE_HANDLER, AcpiGbl_TableHandler); +ACPI_GLOBAL (void *, AcpiGbl_TableHandlerContext); +ACPI_GLOBAL (ACPI_INTERFACE_HANDLER, AcpiGbl_InterfaceHandler); +ACPI_GLOBAL (ACPI_SCI_HANDLER_INFO *, AcpiGbl_SciHandlerList); +ACPI_GLOBAL (ACPI_GED_HANDLER_INFO *, AcpiGbl_GedHandlerList); + +/* Notify dispatch tracking — per-OwnerId counters with spinlock */ + +#define ACPI_NOTIFY_COUNT_MAX_OWNER (ACPI_OWNER_ID_MAX + 1) /* 4096 */ +ACPI_GLOBAL (UINT16, AcpiGbl_NotifyExecuteCount[ACPI_NOTIFY_COUNT_MAX_OWNER]); +ACPI_GLOBAL (BOOLEAN, AcpiGbl_NotifyUnloading[ACPI_NOTIFY_COUNT_MAX_OWNER]); +ACPI_GLOBAL (ACPI_SPINLOCK, AcpiGbl_NotifyLock); + +/* Owner ID support */ + +ACPI_GLOBAL (UINT32, AcpiGbl_OwnerIdMask[ACPI_NUM_OWNERID_MASKS]); +ACPI_GLOBAL (UINT8, AcpiGbl_LastOwnerIdIndex); +ACPI_GLOBAL (UINT8, AcpiGbl_NextOwnerIdOffset); + +/* Initialization sequencing */ + +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_NamespaceInitialized, FALSE); + +/* Miscellaneous */ + +ACPI_GLOBAL (UINT32, AcpiGbl_OriginalMode); +ACPI_GLOBAL (UINT32, AcpiGbl_NsLookupCount); +ACPI_GLOBAL (UINT32, AcpiGbl_PsFindCount); +ACPI_GLOBAL (UINT16, AcpiGbl_Pm1EnableRegisterSave); +ACPI_GLOBAL (UINT8, AcpiGbl_DebuggerConfiguration); +ACPI_GLOBAL (BOOLEAN, AcpiGbl_StepToNextCall); +ACPI_GLOBAL (BOOLEAN, AcpiGbl_AcpiHardwarePresent); +ACPI_GLOBAL (BOOLEAN, AcpiGbl_EventsInitialized); +ACPI_GLOBAL (ACPI_INTERFACE_INFO *, AcpiGbl_SupportedInterfaces); +ACPI_GLOBAL (ACPI_ADDRESS_RANGE *, AcpiGbl_AddressRangeList[ACPI_ADDRESS_RANGE_MAX]); + +/* Other miscellaneous, declared and initialized in utglobal */ + +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 char *AcpiGbl_RegionTypes[ACPI_NUM_PREDEFINED_REGIONS]; +extern const char AcpiGbl_LowerHexDigits[]; +extern const char AcpiGbl_UpperHexDigits[]; +extern const ACPI_OPCODE_INFO AcpiGbl_AmlOpInfo[AML_NUM_OPCODES]; + +/* Lists for tracking memory allocations (debug only) */ + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS +ACPI_GLOBAL (ACPI_MEMORY_LIST *, AcpiGbl_GlobalList); +ACPI_GLOBAL (ACPI_MEMORY_LIST *, AcpiGbl_NsNodeList); +ACPI_GLOBAL (BOOLEAN, AcpiGbl_DisplayFinalMemStats); +ACPI_GLOBAL (BOOLEAN, AcpiGbl_DisableMemTracking); +ACPI_GLOBAL (BOOLEAN, AcpiGbl_VerboseLeakDump); +#endif + + +/***************************************************************************** + * + * ACPI Namespace + * + ****************************************************************************/ + +#define NUM_PREDEFINED_NAMES 10 + +ACPI_GLOBAL (ACPI_NAMESPACE_NODE, AcpiGbl_RootNodeStruct); +ACPI_GLOBAL (ACPI_NAMESPACE_NODE *, AcpiGbl_RootNode); +ACPI_GLOBAL (ACPI_NAMESPACE_NODE *, AcpiGbl_FadtGpeDevice); + +extern const UINT8 AcpiGbl_NsProperties [ACPI_NUM_NS_TYPES]; +extern const ACPI_PREDEFINED_NAMES AcpiGbl_PreDefinedNames [NUM_PREDEFINED_NAMES]; + +#ifdef ACPI_DEBUG_OUTPUT +ACPI_GLOBAL (UINT32, AcpiGbl_CurrentNodeCount); +ACPI_GLOBAL (UINT32, AcpiGbl_CurrentNodeSize); +ACPI_GLOBAL (UINT32, AcpiGbl_MaxConcurrentNodeCount); +ACPI_GLOBAL (ACPI_SIZE *, AcpiGbl_EntryStackPointer); +ACPI_GLOBAL (ACPI_SIZE *, AcpiGbl_LowestStackPointer); +ACPI_GLOBAL (UINT32, AcpiGbl_DeepestNesting); +ACPI_INIT_GLOBAL (UINT32, AcpiGbl_NestingLevel, 0); +#endif + + +/***************************************************************************** + * + * Interpreter/Parser globals + * + ****************************************************************************/ + +/* Control method single step flag */ + +ACPI_GLOBAL (UINT8, AcpiGbl_CmSingleStep); +ACPI_GLOBAL (ACPI_THREAD_STATE *, AcpiGbl_CurrentWalkList); +ACPI_INIT_GLOBAL (ACPI_PARSE_OBJECT, *AcpiGbl_CurrentScope, NULL); + +/* ASL/ASL+ converter */ + +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_CaptureComments, FALSE); +ACPI_INIT_GLOBAL (ACPI_COMMENT_NODE, *AcpiGbl_LastListHead, NULL); + + +/***************************************************************************** + * + * Hardware globals + * + ****************************************************************************/ + +extern ACPI_BIT_REGISTER_INFO AcpiGbl_BitRegisterInfo[ACPI_NUM_BITREG]; +ACPI_GLOBAL (UINT8, AcpiGbl_SleepTypeA); +ACPI_GLOBAL (UINT8, AcpiGbl_SleepTypeB); +ACPI_GLOBAL (UINT8, AcpiGbl_SleepTypeAS0); +ACPI_GLOBAL (UINT8, AcpiGbl_SleepTypeBS0); + + +/***************************************************************************** + * + * Event and GPE globals + * + ****************************************************************************/ + +#if (!ACPI_REDUCED_HARDWARE) +ACPI_GLOBAL (UINT8, AcpiGbl_AllGpesInitialized); +ACPI_GLOBAL (ACPI_GPE_XRUPT_INFO *, AcpiGbl_GpeXruptListHead); +ACPI_GLOBAL (ACPI_GPE_BLOCK_INFO *, AcpiGbl_GpeFadtBlocks[ACPI_MAX_GPE_BLOCKS]); +ACPI_GLOBAL (ACPI_GBL_EVENT_HANDLER, AcpiGbl_GlobalEventHandler); +ACPI_GLOBAL (void *, AcpiGbl_GlobalEventHandlerContext); +ACPI_GLOBAL (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 + * + ****************************************************************************/ + +/* Event counters */ + +ACPI_GLOBAL (UINT32, AcpiMethodCount); +ACPI_GLOBAL (UINT32, AcpiGpeCount); +ACPI_GLOBAL (UINT32, AcpiSciCount); +ACPI_GLOBAL (UINT32, AcpiFixedEventCount[ACPI_NUM_FIXED_EVENTS]); + +/* Dynamic control method tracing mechanism */ + +ACPI_GLOBAL (UINT32, AcpiGbl_OriginalDbgLevel); +ACPI_GLOBAL (UINT32, AcpiGbl_OriginalDbgLayer); + + +/***************************************************************************** + * + * Debugger and Disassembler + * + ****************************************************************************/ + +ACPI_INIT_GLOBAL (UINT8, AcpiGbl_DbOutputFlags, ACPI_DB_CONSOLE_OUTPUT); + + +#ifdef ACPI_DISASSEMBLER + +/* Do not disassemble buffers to resource descriptors */ + +ACPI_INIT_GLOBAL (UINT8, AcpiGbl_NoResourceDisassembly, FALSE); +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_IgnoreNoopOperator, FALSE); +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_CstyleDisassembly, TRUE); +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_ForceAmlDisassembly, FALSE); +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_DmOpt_Verbose, TRUE); +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_DmEmitExternalOpcodes, FALSE); +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_DoDisassemblerOptimizations, TRUE); +ACPI_INIT_GLOBAL (ACPI_PARSE_OBJECT_LIST, *AcpiGbl_TempListHead, NULL); + +ACPI_GLOBAL (BOOLEAN, AcpiGbl_DmOpt_Disasm); +ACPI_GLOBAL (BOOLEAN, AcpiGbl_DmOpt_Listing); +ACPI_GLOBAL (UINT32, AcpiGbl_NumExternalMethods); +ACPI_GLOBAL (UINT32, AcpiGbl_ResolvedExternalMethods); +ACPI_GLOBAL (ACPI_EXTERNAL_LIST *, AcpiGbl_ExternalList); +ACPI_GLOBAL (ACPI_EXTERNAL_FILE *, AcpiGbl_ExternalFileList); +#endif + +#ifdef ACPI_DEBUGGER +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_AbortMethod, FALSE); +ACPI_INIT_GLOBAL (ACPI_THREAD_ID, AcpiGbl_DbThreadId, ACPI_INVALID_THREAD_ID); +ACPI_INIT_GLOBAL (UINT32, AcpiGbl_NextCmdNum, 1); + +ACPI_GLOBAL (BOOLEAN, AcpiGbl_DbOpt_NoIniMethods); +ACPI_GLOBAL (BOOLEAN, AcpiGbl_DbOpt_NoRegionSupport); +ACPI_GLOBAL (BOOLEAN, AcpiGbl_DbOutputToFile); +ACPI_GLOBAL (char *, AcpiGbl_DbBuffer); +ACPI_GLOBAL (char *, AcpiGbl_DbFilename); +ACPI_GLOBAL (UINT32, AcpiGbl_DbDebugLevel); +ACPI_GLOBAL (UINT32, AcpiGbl_DbConsoleDebugLevel); +ACPI_GLOBAL (ACPI_NAMESPACE_NODE *, AcpiGbl_DbScopeNode); +ACPI_GLOBAL (BOOLEAN, AcpiGbl_DbTerminateLoop); +ACPI_GLOBAL (BOOLEAN, AcpiGbl_DbThreadsTerminated); +ACPI_GLOBAL (char *, AcpiGbl_DbArgs[ACPI_DEBUGGER_MAX_ARGS]); +ACPI_GLOBAL (ACPI_OBJECT_TYPE, AcpiGbl_DbArgTypes[ACPI_DEBUGGER_MAX_ARGS]); + +/* These buffers should all be the same size */ + +ACPI_GLOBAL (char, AcpiGbl_DbParsedBuf[ACPI_DB_LINE_BUFFER_SIZE]); +ACPI_GLOBAL (char, AcpiGbl_DbScopeBuf[ACPI_DB_LINE_BUFFER_SIZE]); +ACPI_GLOBAL (char, AcpiGbl_DbDebugFilename[ACPI_DB_LINE_BUFFER_SIZE]); + +/* Statistics globals */ + +ACPI_GLOBAL (UINT16, AcpiGbl_ObjTypeCount[ACPI_TOTAL_TYPES]); +ACPI_GLOBAL (UINT16, AcpiGbl_NodeTypeCount[ACPI_TOTAL_TYPES]); +ACPI_GLOBAL (UINT16, AcpiGbl_ObjTypeCountMisc); +ACPI_GLOBAL (UINT16, AcpiGbl_NodeTypeCountMisc); +ACPI_GLOBAL (UINT32, AcpiGbl_NumNodes); +ACPI_GLOBAL (UINT32, AcpiGbl_NumObjects); +#endif /* ACPI_DEBUGGER */ + +#if defined (ACPI_DISASSEMBLER) || defined (ACPI_ASL_COMPILER) +ACPI_GLOBAL (const char, *AcpiGbl_PldPanelList[]); +ACPI_GLOBAL (const char, *AcpiGbl_PldVerticalPositionList[]); +ACPI_GLOBAL (const char, *AcpiGbl_PldHorizontalPositionList[]); +ACPI_GLOBAL (const char, *AcpiGbl_PldShapeList[]); +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_DisasmFlag, FALSE); +#endif + + +/***************************************************************************** + * + * ACPICA application-specific globals + * + ****************************************************************************/ + +/* ASL-to-ASL+ conversion utility (implemented within the iASL compiler) */ + +#ifdef ACPI_ASL_COMPILER +ACPI_INIT_GLOBAL (char *, AcpiGbl_CurrentInlineComment, NULL); +ACPI_INIT_GLOBAL (char *, AcpiGbl_CurrentEndNodeComment, NULL); +ACPI_INIT_GLOBAL (char *, AcpiGbl_CurrentOpenBraceComment, NULL); +ACPI_INIT_GLOBAL (char *, AcpiGbl_CurrentCloseBraceComment, NULL); + +ACPI_INIT_GLOBAL (char *, AcpiGbl_RootFilename, NULL); +ACPI_INIT_GLOBAL (char *, AcpiGbl_CurrentFilename, NULL); +ACPI_INIT_GLOBAL (char *, AcpiGbl_CurrentParentFilename, NULL); +ACPI_INIT_GLOBAL (char *, AcpiGbl_CurrentIncludeFilename, NULL); + +ACPI_INIT_GLOBAL (ACPI_COMMENT_NODE, *AcpiGbl_DefBlkCommentListHead, NULL); +ACPI_INIT_GLOBAL (ACPI_COMMENT_NODE, *AcpiGbl_DefBlkCommentListTail, NULL); +ACPI_INIT_GLOBAL (ACPI_COMMENT_NODE, *AcpiGbl_RegCommentListHead, NULL); +ACPI_INIT_GLOBAL (ACPI_COMMENT_NODE, *AcpiGbl_RegCommentListTail, NULL); +ACPI_INIT_GLOBAL (ACPI_COMMENT_NODE, *AcpiGbl_IncCommentListHead, NULL); +ACPI_INIT_GLOBAL (ACPI_COMMENT_NODE, *AcpiGbl_IncCommentListTail, NULL); +ACPI_INIT_GLOBAL (ACPI_COMMENT_NODE, *AcpiGbl_EndBlkCommentListHead, NULL); +ACPI_INIT_GLOBAL (ACPI_COMMENT_NODE, *AcpiGbl_EndBlkCommentListTail, NULL); + +ACPI_INIT_GLOBAL (ACPI_COMMENT_ADDR_NODE, *AcpiGbl_CommentAddrListHead, NULL); +ACPI_INIT_GLOBAL (ACPI_FILE_NODE, *AcpiGbl_FileTreeRoot, NULL); + +ACPI_GLOBAL (ACPI_CACHE_T *, AcpiGbl_RegCommentCache); +ACPI_GLOBAL (ACPI_CACHE_T *, AcpiGbl_CommentAddrCache); +ACPI_GLOBAL (ACPI_CACHE_T *, AcpiGbl_FileCache); + +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_DebugAslConversion, FALSE); +ACPI_INIT_GLOBAL (ACPI_FILE, AcpiGbl_ConvDebugFile, NULL); +ACPI_GLOBAL (char, AcpiGbl_TableSig[4]); +#endif + +#ifdef ACPI_APPLICATION +ACPI_INIT_GLOBAL (ACPI_FILE, AcpiGbl_DebugFile, NULL); +ACPI_INIT_GLOBAL (ACPI_FILE, AcpiGbl_OutputFile, NULL); +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_DebugTimeout, FALSE); + +/* Print buffer */ + +ACPI_GLOBAL (ACPI_SPINLOCK, AcpiGbl_PrintLock); /* For print buffer */ +ACPI_GLOBAL (char, AcpiGbl_PrintBuffer[1024]); +#endif /* ACPI_APPLICATION */ + +#endif /* __ACGLOBAL_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/achware.h b/code/drivers/platform/acpi/third_party/acpica/include/achware.h new file mode 100644 index 0000000..561466d --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/achware.h @@ -0,0 +1,201 @@ +/****************************************************************************** + * + * Name: achware.h -- hardware specific interfaces + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 ( + UINT64 *Value, + ACPI_GENERIC_ADDRESS *Reg); + +ACPI_STATUS +AcpiHwWrite ( + UINT64 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_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); + +UINT8 +AcpiHwCheckAllGpes ( + 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/code/drivers/platform/acpi/third_party/acpica/include/acinterp.h b/code/drivers/platform/acpi/third_party/acpica/include/acinterp.h new file mode 100644 index 0000000..bd80c47 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acinterp.h @@ -0,0 +1,758 @@ +/****************************************************************************** + * + * Name: acinterp.h - Interpreter subcomponent prototypes and defines + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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; + const 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 +#define ACPI_EXD_LIST 14 /* Operand object list */ +#define ACPI_EXD_HDLR_LIST 15 /* Address Handler list */ +#define ACPI_EXD_RGN_LIST 16 /* Region list */ +#define ACPI_EXD_NODE 17 /* Namespace Node */ + +/* restore default alignment */ + +#pragma pack() + + +/* + * exconvrt - object conversion + */ +ACPI_STATUS +AcpiExConvertToInteger ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ResultDesc, + UINT32 ImplicitConversion); + +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); + +void +AcpiExStartTraceMethod ( + ACPI_NAMESPACE_NODE *MethodNode, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState); + +void +AcpiExStopTraceMethod ( + ACPI_NAMESPACE_NODE *MethodNode, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_WALK_STATE *WalkState); + +void +AcpiExStartTraceOpcode ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState); + +void +AcpiExStopTraceOpcode ( + ACPI_PARSE_OBJECT *Op, + ACPI_WALK_STATE *WalkState); + +void +AcpiExTracePoint ( + ACPI_TRACE_EVENT_TYPE Type, + BOOLEAN Begin, + UINT8 *Aml, + char *Pathname); + +void +AcpiExTraceArgs( + ACPI_OPERAND_OBJECT **Params, + UINT32 Count); + +/* + * exfield - ACPI AML (p-code) execution - field manipulation + */ +ACPI_STATUS +AcpiExGetProtocolBufferLength ( + UINT32 ProtocolId, + UINT32 *ReturnLength); + +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); + + +/* + * exserial - FieldUnit support for serial address spaces + */ +ACPI_STATUS +AcpiExReadSerialBus ( + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ReturnBuffer); + +ACPI_STATUS +AcpiExWriteSerialBus ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ReturnBuffer); + +ACPI_STATUS +AcpiExReadGpio ( + ACPI_OPERAND_OBJECT *ObjDesc, + void *Buffer); + +ACPI_STATUS +AcpiExWriteGpio ( + ACPI_OPERAND_OBJECT *SourceDesc, + ACPI_OPERAND_OBJECT *ObjDesc, + ACPI_OPERAND_OBJECT **ReturnBuffer); + + +/* + * 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); + + +/* + * 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); + +BOOLEAN +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); + +void +AcpiExPciClsToString ( + char *Dest, + UINT8 ClassCode[3]); + +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/code/drivers/platform/acpi/third_party/acpica/include/aclocal.h b/code/drivers/platform/acpi/third_party/acpica/include/aclocal.h new file mode 100644 index 0000000..d0e4b06 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/aclocal.h @@ -0,0 +1,1527 @@ +/****************************************************************************** + * + * Name: aclocal.h - Internal data types used across the ACPI subsystem + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 0x83 + + +/* 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_MAX_MUTEX 5 +#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) + +/* This Thread ID means an invalid thread ID */ + +#ifdef ACPI_OS_INVALID_THREAD_ID +#define ACPI_INVALID_THREAD_ID ACPI_OS_INVALID_THREAD_ID +#else +#define ACPI_INVALID_THREAD_ID ((ACPI_THREAD_ID) 0xFFFFFFFF) +#endif + +/* 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 */ + UINT16 Flags; /* Miscellaneous flags */ + 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 */ + ACPI_OWNER_ID OwnerId; /* Node creator */ + + /* + * The following fields are used by the ASL compiler and disassembler only + */ +#ifdef ACPI_LARGE_NAMESPACE_NODE + union acpi_parse_object *Op; + void *MethodLocals; + void *MethodArgs; + UINT32 Value; + UINT32 Length; + UINT8 ArgCount; + +#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_NODE_EARLY_INIT 0x80 /* AcpiExec only: Node was create via init file (-fi) */ + +#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_ALIAS 0x40 /* iASL only: Node is an alias to another node */ +#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) + + +/* List to manage incoming ACPI tables */ + +typedef struct acpi_new_table_desc +{ + ACPI_TABLE_HEADER *Table; + struct acpi_new_table_desc *Next; + +} ACPI_NEW_TABLE_DESC; + + +/* Predefined table indexes */ + +#define ACPI_INVALID_TABLE_INDEX (0xFFFFFFFF) + + +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; + UINT16 PinNumberIndex; + 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_OBJECT 0x00010000 /* From Index(), RefOf(), etc (Type6Opcodes) */ +#define ACPI_BTYPE_RESOURCE 0x00020000 +#define ACPI_BTYPE_NAMED_REFERENCE 0x00040000 /* Generic unresolved Name or Namepath */ + +#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) + + /* Used by Copy, DeRefOf, Store, Printf, Fprintf */ + +#define ACPI_BTYPE_DATA_REFERENCE (ACPI_BTYPE_DATA | ACPI_BTYPE_REFERENCE_OBJECT | 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 + +#pragma pack(1) + +/* + * 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_NAMESEG_SIZE] ACPI_NONSTRING; + UINT16 ArgumentList; + 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; + UINT16 Reserved; + +} ACPI_PACKAGE_INFO; + +/* Used for ACPI_PTYPE2_FIXED */ + +typedef struct acpi_package_info2 +{ + UINT8 Type; + UINT8 Count; + UINT8 ObjectType[4]; + UINT8 Reserved; + +} ACPI_PACKAGE_INFO2; + +/* Used for ACPI_PTYPE1_OPTION */ + +typedef struct acpi_package_info3 +{ + UINT8 Type; + UINT8 Count; + UINT8 ObjectType[2]; + UINT8 TailObjectType; + UINT16 Reserved; + +} ACPI_PACKAGE_INFO3; + +typedef struct acpi_package_info4 +{ + UINT8 Type; + UINT8 ObjectType1; + UINT8 Count1; + UINT8 SubObjectTypes; + UINT8 PkgCount; + UINT16 Reserved; + +} ACPI_PACKAGE_INFO4; + +typedef union acpi_predefined_info +{ + ACPI_NAME_INFO Info; + ACPI_PACKAGE_INFO RetInfo; + ACPI_PACKAGE_INFO2 RetInfo2; + ACPI_PACKAGE_INFO3 RetInfo3; + ACPI_PACKAGE_INFO4 RetInfo4; + +} ACPI_PREDEFINED_INFO; + +/* Reset to default packing */ + +#pragma pack() + + +/* Return object auto-repair info */ + +typedef ACPI_STATUS (*ACPI_OBJECT_CONVERTER) ( + struct acpi_namespace_node *Scope, + union acpi_operand_object *OriginalObject, + union acpi_operand_object **ConvertedObject); + +typedef struct acpi_simple_repair_info +{ + char Name[ACPI_NAMESEG_SIZE] ACPI_NONSTRING; + UINT32 UnexpectedBtypes; + UINT32 PackageIndex; + ACPI_OBJECT_CONVERTER ObjectConverter; + +} ACPI_SIMPLE_REPAIR_INFO; + + +/* + * 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 */ + + +/* Info for running the _REG methods */ + +typedef struct acpi_reg_walk_info +{ + UINT32 Function; + UINT32 RegRunCount; + ACPI_ADR_SPACE_TYPE SpaceId; + +} ACPI_REG_WALK_INFO; + + +/***************************************************************************** + * + * Event typedefs and structs + * + ****************************************************************************/ + +/* Dispatch info for each host-installed SCI handler */ + +typedef struct acpi_sci_handler_info +{ + struct acpi_sci_handler_info *Next; + ACPI_SCI_HANDLER Address; /* Address of handler */ + void *Context; /* Context to be passed to handler */ + +} ACPI_SCI_HANDLER_INFO; + +/* 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; + +/* Notify info for implicit notify, multiple device objects */ + +typedef struct acpi_gpe_notify_info +{ + ACPI_NAMESPACE_NODE *DeviceNode; /* Device to be notified */ + struct acpi_gpe_notify_info *Next; + +} ACPI_GPE_NOTIFY_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 */ + ACPI_GPE_HANDLER_INFO *Handler; /* Installed GPE handler */ + ACPI_GPE_NOTIFY_INFO *NotifyList; /* List of _PRW devices for implicit notifies */ + +} 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, Handler, or NotifyList */ + 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 */ + BOOLEAN DisableForDispatch; /* Masked during dispatching */ + +} 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 */ + UINT16 BaseGpeNumber; /* Base GPE number for this register */ + UINT8 EnableForWake; /* GPEs to keep enabled when sleeping */ + UINT8 EnableForRun; /* GPEs to keep enabled when running */ + UINT8 MaskForRun; /* GPEs to keep masked when running */ + UINT8 EnableMask; /* Current mask of enabled GPEs */ + +} 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 */ + UINT64 Address; /* Base address of the block */ + UINT32 RegisterCount; /* Number of register pairs in block */ + UINT16 GpeCount; /* Number of individual GPEs in block */ + UINT16 BlockBaseNumber;/* Base GPE number for this block */ + UINT8 SpaceId; + 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; + +/* Information about the interrupt ID and _EVT of a GED device */ + +typedef struct acpi_ged_handler_info +{ + struct acpi_ged_handler_info *Next; + UINT32 IntId; /* The interrupt ID that triggers the execution of the EvtMethod. */ + ACPI_NAMESPACE_NODE *EvtMethod; /* The _EVT method to be executed when an interrupt with ID = IntID is received */ + +} ACPI_GED_HANDLER_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; + UINT32 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 */ + UINT64 LoopTimeout; /* While() loop timeout */ + +} 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); + + +/* Global handlers for AML Notifies */ + +typedef struct acpi_global_notify_handler +{ + ACPI_NOTIFY_HANDLER Handler; + void *Context; + +} ACPI_GLOBAL_NOTIFY_HANDLER; + +/* + * Notify info - used to pass info to the deferred notify + * handler/dispatcher. + */ +typedef struct acpi_notify_info +{ + ACPI_STATE_COMMON; + UINT8 HandlerListId; + ACPI_NAMESPACE_NODE *Node; + union acpi_operand_object *HandlerListHead; + ACPI_GLOBAL_NOTIFY_HANDLER *Global; + ACPI_OWNER_ID OwnerId; + +} 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; + + +#if defined(ACPI_DISASSEMBLER) || defined(ACPI_DEBUG_OUTPUT) +#define ACPI_DISASM_ONLY_MEMBERS(a) a; +#else +#define ACPI_DISASM_ONLY_MEMBERS(a) +#endif + +#if defined(ACPI_ASL_COMPILER) +#define ACPI_CONVERTER_ONLY_MEMBERS(a) a; +#else +#define ACPI_CONVERTER_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 */\ + UINT8 *Aml; /* Address 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 (\ + UINT16 DisasmFlags; /* Used during AML disassembly */\ + UINT8 DisasmOpcode; /* Subtype used for disassembly */\ + char *OperatorSymbol; /* Used for C-style operator name strings */\ + char AmlOpName[16]) /* Op name (debug only) */\ + ACPI_CONVERTER_ONLY_MEMBERS (\ + char *InlineComment; /* Inline comment */\ + char *EndNodeComment; /* End of node comment */\ + char *NameComment; /* Comment associated with the first parameter of the name node */\ + char *CloseBraceComment; /* Comments that come after } on the same as } */\ + ACPI_COMMENT_NODE *CommentList; /* comments that appears before this node */\ + ACPI_COMMENT_NODE *EndBlkComment; /* comments that at the end of a block but before ) or } */\ + char *CvFilename; /* Filename associated with this node. Used for ASL/ASL+ converter */\ + char *CvParentFilename) /* Parent filename associated with this node. Used for ASL/ASL+ converter */ + + +/* categories of comments */ + +typedef enum +{ + STANDARD_COMMENT = 1, + INLINE_COMMENT, + ENDNODE_COMMENT, + OPENBRACE_COMMENT, + CLOSE_BRACE_COMMENT, + STD_DEFBLK_COMMENT, + END_DEFBLK_COMMENT, + FILENAME_COMMENT, + PARENTFILENAME_COMMENT, + ENDBLK_COMMENT, + INCLUDE_COMMENT + +} ASL_COMMENT_TYPES; + + +/* Internal opcodes for DisasmOpcode field above */ + +#define ACPI_DASM_BUFFER 0x00 /* Buffer is a simple data buffer */ +#define ACPI_DASM_RESOURCE 0x01 /* Buffer is a Resource Descriptor */ +#define ACPI_DASM_STRING 0x02 /* Buffer is a ASCII string */ +#define ACPI_DASM_UNICODE 0x03 /* Buffer is a Unicode string */ +#define ACPI_DASM_PLD_METHOD 0x04 /* Buffer is a _PLD method bit-packed buffer */ +#define ACPI_DASM_UUID 0x05 /* Buffer is a UUID/GUID */ +#define ACPI_DASM_EISAID 0x06 /* Integer is an EISAID */ +#define ACPI_DASM_MATCHOP 0x07 /* Parent opcode is a Match() operator */ +#define ACPI_DASM_LNOT_PREFIX 0x08 /* Start of a LNotEqual (etc.) pair of opcodes */ +#define ACPI_DASM_LNOT_SUFFIX 0x09 /* End of a LNotEqual (etc.) pair of opcodes */ +#define ACPI_DASM_HID_STRING 0x0A /* String is a _HID or _CID */ +#define ACPI_DASM_IGNORE_SINGLE 0x0B /* Ignore the opcode but not it's children */ +#define ACPI_DASM_SWITCH 0x0C /* While is a Switch */ +#define ACPI_DASM_SWITCH_PREDICATE 0x0D /* Object is a predicate for a Switch or Case block */ +#define ACPI_DASM_CASE 0x0E /* If/Else is a Case in a Switch/Case block */ +#define ACPI_DASM_DEFAULT 0x0F /* Else is a Default in a Switch/Case block */ + + +/* + * List struct used in the -ca option + */ +typedef struct acpi_comment_node +{ + char *Comment; + struct acpi_comment_node *Next; + +} ACPI_COMMENT_NODE; + + +typedef struct acpi_comment_addr_node +{ + UINT8 *Addr; + struct acpi_comment_addr_node *Next; +} ACPI_COMMENT_ADDR_NODE; + +/* + * File node - used for "Include" operator file stack and + * dependency tree for the -ca option + */ +typedef struct acpi_file_node +{ + void *File; + char *Filename; + char *FileStart; /* Points to AML and indicates when the AML for this particular file starts. */ + char *FileEnd; /* Points to AML and indicates when the AML for this particular file ends. */ + struct acpi_file_node *Next; + struct acpi_file_node *Parent; + BOOLEAN IncludeWritten; + ACPI_COMMENT_NODE *IncludeComment; + +} ACPI_FILE_NODE; + + +/* + * 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 + char *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; + BOOLEAN FileChanged; + char *ParentFilename; + 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; + +typedef struct asl_comment_state +{ + UINT8 CommentType; + UINT32 SpacesBefore; + ACPI_PARSE_OBJECT *LatestParseOp; + ACPI_PARSE_OBJECT *ParsingParenBraceNode; + BOOLEAN CaptureComments; + +} ASL_COMMENT_STATE; + + +/* + * 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_OBJECT 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 0x0001 +#define ACPI_PARSEOP_PARAMETER_LIST 0x0002 +#define ACPI_PARSEOP_EMPTY_TERMLIST 0x0004 +#define ACPI_PARSEOP_PREDEFINED_CHECKED 0x0008 +#define ACPI_PARSEOP_CLOSING_PAREN 0x0010 +#define ACPI_PARSEOP_COMPOUND_ASSIGNMENT 0x0020 +#define ACPI_PARSEOP_ASSIGNMENT 0x0040 +#define ACPI_PARSEOP_ELSEIF 0x0080 +#define ACPI_PARSEOP_LEGACY_ASL_ONLY 0x0100 + + +/***************************************************************************** + * + * 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_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 +#define ACPI_OSI_FEATURE 0x04 +#define ACPI_OSI_DEFAULT_INVALID 0x08 +#define ACPI_OSI_OPTIONAL_FEATURE (ACPI_OSI_FEATURE | ACPI_OSI_DEFAULT_INVALID | ACPI_OSI_INVALID) + +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 + +#define ACPI_ADDRESS_TYPE_PCC_NUMBER 0xA + +/* 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_PIN_FUNCTION 0x8D +#define ACPI_RESOURCE_NAME_SERIAL_BUS 0x8E +#define ACPI_RESOURCE_NAME_PIN_CONFIG 0x8F +#define ACPI_RESOURCE_NAME_PIN_GROUP 0x90 +#define ACPI_RESOURCE_NAME_PIN_GROUP_FUNCTION 0x91 +#define ACPI_RESOURCE_NAME_PIN_GROUP_CONFIG 0x92 +#define ACPI_RESOURCE_NAME_CLOCK_INPUT 0x93 +#define ACPI_RESOURCE_NAME_LARGE_MAX 0x93 + + +/***************************************************************************** + * + * 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; + UINT16 Flags; + UINT8 Type; + +} ACPI_EXTERNAL_LIST; + +/* Values for Flags field above */ + +#define ACPI_EXT_RESOLVED_REFERENCE 0x01 /* Object was resolved during cross ref */ +#define ACPI_EXT_ORIGIN_FROM_FILE 0x02 /* External came from a file */ +#define ACPI_EXT_INTERNAL_PATH_ALLOCATED 0x04 /* Deallocate internal path on completion */ +#define ACPI_EXT_EXTERNAL_EMITTED 0x08 /* External() statement has been emitted */ +#define ACPI_EXT_ORIGIN_FROM_OPCODE 0x10 /* External came from a External() opcode */ +#define ACPI_EXT_CONFLICTING_DECLARATION 0x20 /* External has a conflicting declaration within AML */ + + +typedef struct acpi_external_file +{ + char *Path; + struct acpi_external_file *Next; + +} ACPI_EXTERNAL_FILE; + + +typedef struct acpi_parse_object_list +{ + ACPI_PARSE_OBJECT *Op; + struct acpi_parse_object_list *Next; + +} ACPI_PARSE_OBJECT_LIST; + +/***************************************************************************** + * + * Debugger + * + ****************************************************************************/ + +typedef struct acpi_db_method_info +{ + ACPI_HANDLE Method; + 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[ACPI_DB_LINE_BUFFER_SIZE]; + char **Args; + ACPI_OBJECT_TYPE *Types; + + /* + * Arguments to be passed to method for the commands Threads and + * Background. Note, ACPI specifies a maximum of 7 arguments (0 - 6). + * + * For the Threads command, the Number of threads, ID of current + * thread and Index of current thread inside all them created. + */ + char InitArgs; +#ifdef ACPI_DEBUGGER + ACPI_OBJECT_TYPE ArgTypes[ACPI_METHOD_NUM_ARGS]; +#endif + char *Arguments[ACPI_METHOD_NUM_ARGS]; + 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_DISABLE_OUTPUT 0x00 +#define ACPI_DB_REDIRECTABLE_OUTPUT 0x01 +#define ACPI_DB_CONSOLE_OUTPUT 0x02 +#define ACPI_DB_DUPLICATE_OUTPUT 0x03 + + +typedef struct acpi_object_info +{ + UINT32 Types[ACPI_TOTAL_TYPES]; + +} ACPI_OBJECT_INFO; + + +/***************************************************************************** + * + * 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 + + +/***************************************************************************** + * + * Info/help support + * + ****************************************************************************/ + +typedef struct ah_predefined_name +{ + char *Name; + char *Description; +#ifndef ACPI_ASL_COMPILER + char *Action; +#endif + +} AH_PREDEFINED_NAME; + +typedef struct ah_device_id +{ + char *Name; + char *Description; + +} AH_DEVICE_ID; + +typedef struct ah_uuid +{ + char *Description; + char *String; + +} AH_UUID; + +typedef struct ah_table +{ + char *Signature; + char *Description; + +} AH_TABLE; + +#endif /* __ACLOCAL_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acmacros.h b/code/drivers/platform/acpi/third_party/acpica/include/acmacros.h new file mode 100644 index 0000000..6b98baf --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acmacros.h @@ -0,0 +1,509 @@ +/****************************************************************************** + * + * Name: acmacros.h - C macros for the entire subsystem. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACMACROS_H__ +#define __ACMACROS_H__ + + +/* + * Extract data using a pointer. Any more than a byte and we + * get into potential alignment issues -- see the STORE macros below. + * Use with care. + */ +#define ACPI_CAST8(ptr) ACPI_CAST_PTR (UINT8, (ptr)) +#define ACPI_CAST16(ptr) ACPI_CAST_PTR (UINT16, (ptr)) +#define ACPI_CAST32(ptr) ACPI_CAST_PTR (UINT32, (ptr)) +#define ACPI_CAST64(ptr) ACPI_CAST_PTR (UINT64, (ptr)) +#define ACPI_GET8(ptr) (*ACPI_CAST8 (ptr)) +#define ACPI_GET16(ptr) (*ACPI_CAST16 (ptr)) +#define ACPI_GET32(ptr) (*ACPI_CAST32 (ptr)) +#define ACPI_GET64(ptr) (*ACPI_CAST64 (ptr)) +#define ACPI_SET8(ptr, val) (*ACPI_CAST8 (ptr) = (UINT8) (val)) +#define ACPI_SET16(ptr, val) (*ACPI_CAST16 (ptr) = (UINT16) (val)) +#define ACPI_SET32(ptr, val) (*ACPI_CAST32 (ptr) = (UINT32) (val)) +#define ACPI_SET64(ptr, val) (*ACPI_CAST64 (ptr) = (UINT64) (val)) + +/* + * printf() format helper. This macro is a workaround for the difficulties + * with emitting 64-bit integers and 64-bit pointers with the same code + * for both 32-bit and 64-bit hosts. + */ +#define ACPI_FORMAT_UINT64(i) ACPI_HIDWORD(i), ACPI_LODWORD(i) + + +/* + * 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) + +/* Test for ASCII character */ + +#define ACPI_IS_ASCII(c) ((c) < 0x80) + +/* Signed integers */ + +#define ACPI_SIGN_POSITIVE 0 +#define ACPI_SIGN_NEGATIVE 1 + + +/* + * 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)) + +/* Generic bit manipulation */ + +#ifndef ACPI_USE_NATIVE_BIT_FINDER + +#define __ACPI_FIND_LAST_BIT_2(a, r) ((((UINT8) (a)) & 0x02) ? (r)+1 : (r)) +#define __ACPI_FIND_LAST_BIT_4(a, r) ((((UINT8) (a)) & 0x0C) ? \ + __ACPI_FIND_LAST_BIT_2 ((a)>>2, (r)+2) : \ + __ACPI_FIND_LAST_BIT_2 ((a), (r))) +#define __ACPI_FIND_LAST_BIT_8(a, r) ((((UINT8) (a)) & 0xF0) ? \ + __ACPI_FIND_LAST_BIT_4 ((a)>>4, (r)+4) : \ + __ACPI_FIND_LAST_BIT_4 ((a), (r))) +#define __ACPI_FIND_LAST_BIT_16(a, r) ((((UINT16) (a)) & 0xFF00) ? \ + __ACPI_FIND_LAST_BIT_8 ((a)>>8, (r)+8) : \ + __ACPI_FIND_LAST_BIT_8 ((a), (r))) +#define __ACPI_FIND_LAST_BIT_32(a, r) ((((UINT32) (a)) & 0xFFFF0000) ? \ + __ACPI_FIND_LAST_BIT_16 ((a)>>16, (r)+16) : \ + __ACPI_FIND_LAST_BIT_16 ((a), (r))) +#define __ACPI_FIND_LAST_BIT_64(a, r) ((((UINT64) (a)) & 0xFFFFFFFF00000000) ? \ + __ACPI_FIND_LAST_BIT_32 ((a)>>32, (r)+32) : \ + __ACPI_FIND_LAST_BIT_32 ((a), (r))) + +#define ACPI_FIND_LAST_BIT_8(a) ((a) ? __ACPI_FIND_LAST_BIT_8 (a, 1) : 0) +#define ACPI_FIND_LAST_BIT_16(a) ((a) ? __ACPI_FIND_LAST_BIT_16 (a, 1) : 0) +#define ACPI_FIND_LAST_BIT_32(a) ((a) ? __ACPI_FIND_LAST_BIT_32 (a, 1) : 0) +#define ACPI_FIND_LAST_BIT_64(a) ((a) ? __ACPI_FIND_LAST_BIT_64 (a, 1) : 0) + +#define __ACPI_FIND_FIRST_BIT_2(a, r) ((((UINT8) (a)) & 0x01) ? (r) : (r)+1) +#define __ACPI_FIND_FIRST_BIT_4(a, r) ((((UINT8) (a)) & 0x03) ? \ + __ACPI_FIND_FIRST_BIT_2 ((a), (r)) : \ + __ACPI_FIND_FIRST_BIT_2 ((a)>>2, (r)+2)) +#define __ACPI_FIND_FIRST_BIT_8(a, r) ((((UINT8) (a)) & 0x0F) ? \ + __ACPI_FIND_FIRST_BIT_4 ((a), (r)) : \ + __ACPI_FIND_FIRST_BIT_4 ((a)>>4, (r)+4)) +#define __ACPI_FIND_FIRST_BIT_16(a, r) ((((UINT16) (a)) & 0x00FF) ? \ + __ACPI_FIND_FIRST_BIT_8 ((a), (r)) : \ + __ACPI_FIND_FIRST_BIT_8 ((a)>>8, (r)+8)) +#define __ACPI_FIND_FIRST_BIT_32(a, r) ((((UINT32) (a)) & 0x0000FFFF) ? \ + __ACPI_FIND_FIRST_BIT_16 ((a), (r)) : \ + __ACPI_FIND_FIRST_BIT_16 ((a)>>16, (r)+16)) +#define __ACPI_FIND_FIRST_BIT_64(a, r) ((((UINT64) (a)) & 0x00000000FFFFFFFF) ? \ + __ACPI_FIND_FIRST_BIT_32 ((a), (r)) : \ + __ACPI_FIND_FIRST_BIT_32 ((a)>>32, (r)+32)) + +#define ACPI_FIND_FIRST_BIT_8(a) ((a) ? __ACPI_FIND_FIRST_BIT_8 (a, 1) : 0) +#define ACPI_FIND_FIRST_BIT_16(a) ((a) ? __ACPI_FIND_FIRST_BIT_16 (a, 1) : 0) +#define ACPI_FIND_FIRST_BIT_32(a) ((a) ? __ACPI_FIND_FIRST_BIT_32 (a, 1) : 0) +#define ACPI_FIND_FIRST_BIT_64(a) ((a) ? __ACPI_FIND_FIRST_BIT_64 (a, 1) : 0) + +#endif /* ACPI_USE_NATIVE_BIT_FINDER */ + +/* Generic (power-of-two) rounding */ + +#define ACPI_ROUND_UP_POWER_OF_TWO_8(a) ((UINT8) \ + (((UINT16) 1) << ACPI_FIND_LAST_BIT_8 ((a) - 1))) +#define ACPI_ROUND_DOWN_POWER_OF_TWO_8(a) ((UINT8) \ + (((UINT16) 1) << (ACPI_FIND_LAST_BIT_8 ((a)) - 1))) +#define ACPI_ROUND_UP_POWER_OF_TWO_16(a) ((UINT16) \ + (((UINT32) 1) << ACPI_FIND_LAST_BIT_16 ((a) - 1))) +#define ACPI_ROUND_DOWN_POWER_OF_TWO_16(a) ((UINT16) \ + (((UINT32) 1) << (ACPI_FIND_LAST_BIT_16 ((a)) - 1))) +#define ACPI_ROUND_UP_POWER_OF_TWO_32(a) ((UINT32) \ + (((UINT64) 1) << ACPI_FIND_LAST_BIT_32 ((a) - 1))) +#define ACPI_ROUND_DOWN_POWER_OF_TWO_32(a) ((UINT32) \ + (((UINT64) 1) << (ACPI_FIND_LAST_BIT_32 ((a)) - 1))) +#define ACPI_IS_ALIGNED(a, s) (((a) & ((s) - 1)) == 0) +#define ACPI_IS_POWER_OF_TWO(a) ACPI_IS_ALIGNED(a, a) + +/* + * 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 + * MASK_BITS_ABOVE/BELOW accepts a bit offset to create a mask + * MASK_BITS_ABOVE/BELOW_32/64 accepts a bit width to create a mask + * Note: The ACPI_INTEGER_BIT_SIZE check is used to bypass compiler + * differences with the shift operator + */ +#define ACPI_MASK_BITS_ABOVE(position) (~((ACPI_UINT64_MAX) << ((UINT32) (position)))) +#define ACPI_MASK_BITS_BELOW(position) ((ACPI_UINT64_MAX) << ((UINT32) (position))) +#define ACPI_MASK_BITS_ABOVE_32(width) ((UINT32) ACPI_MASK_BITS_ABOVE(width)) +#define ACPI_MASK_BITS_BELOW_32(width) ((UINT32) ACPI_MASK_BITS_BELOW(width)) +#define ACPI_MASK_BITS_ABOVE_64(width) ((width) == ACPI_INTEGER_BIT_SIZE ? \ + ACPI_UINT64_MAX : \ + ACPI_MASK_BITS_ABOVE(width)) +#define ACPI_MASK_BITS_BELOW_64(width) ((width) == ACPI_INTEGER_BIT_SIZE ? \ + (UINT64) 0 : \ + ACPI_MASK_BITS_BELOW(width)) + +/* 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)) + +/* Generic bitfield macros and masks */ + +#define ACPI_GET_BITS(SourcePtr, Position, Mask) \ + ((*(SourcePtr) >> (Position)) & (Mask)) + +#define ACPI_SET_BITS(TargetPtr, Position, Mask, Value) \ + (*(TargetPtr) |= (((Value) & (Mask)) << (Position))) + +#define ACPI_1BIT_MASK 0x00000001 +#define ACPI_2BIT_MASK 0x00000003 +#define ACPI_3BIT_MASK 0x00000007 +#define ACPI_4BIT_MASK 0x0000000F +#define ACPI_5BIT_MASK 0x0000001F +#define ACPI_6BIT_MASK 0x0000003F +#define ACPI_7BIT_MASK 0x0000007F +#define ACPI_8BIT_MASK 0x000000FF +#define ACPI_16BIT_MASK 0x0000FFFF +#define ACPI_24BIT_MASK 0x00FFFFFF + +/* Macros to extract flag bits from position zero */ + +#define ACPI_GET_1BIT_FLAG(Value) ((Value) & ACPI_1BIT_MASK) +#define ACPI_GET_2BIT_FLAG(Value) ((Value) & ACPI_2BIT_MASK) +#define ACPI_GET_3BIT_FLAG(Value) ((Value) & ACPI_3BIT_MASK) +#define ACPI_GET_4BIT_FLAG(Value) ((Value) & ACPI_4BIT_MASK) + +/* Macros to extract flag bits from position one and above */ + +#define ACPI_EXTRACT_1BIT_FLAG(Field, Position) (ACPI_GET_1BIT_FLAG ((Field) >> Position)) +#define ACPI_EXTRACT_2BIT_FLAG(Field, Position) (ACPI_GET_2BIT_FLAG ((Field) >> Position)) +#define ACPI_EXTRACT_3BIT_FLAG(Field, Position) (ACPI_GET_3BIT_FLAG ((Field) >> Position)) +#define ACPI_EXTRACT_4BIT_FLAG(Field, Position) (ACPI_GET_4BIT_FLAG ((Field) >> Position)) + +/* ACPI Pathname helpers */ + +#define ACPI_IS_ROOT_PREFIX(c) ((c) == (UINT8) 0x5C) /* Backslash */ +#define ACPI_IS_PARENT_PREFIX(c) ((c) == (UINT8) 0x5E) /* Carat */ +#define ACPI_IS_PATH_SEPARATOR(c) ((c) == (UINT8) 0x2E) /* Period (dot) */ + +/* + * An object of type ACPI_NAMESPACE_NODE can appear in some contexts + * where a pointer to an object of type ACPI_OPERAND_OBJECT can also + * appear. This macro is used to distinguish them. + * + * The "DescriptorType" field is the second field in both structures. + */ +#define ACPI_GET_DESCRIPTOR_PTR(d) (((ACPI_DESCRIPTOR *)(void *)(d))->Common.CommonPointer) +#define ACPI_SET_DESCRIPTOR_PTR(d, p) (((ACPI_DESCRIPTOR *)(void *)(d))->Common.CommonPointer = (p)) +#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. The 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, p, e) AcpiUtPrefixedNamespaceError (AE_INFO, s, p, 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 +#define ACPI_BIOS_ERROR_PREDEFINED(plist) AcpiUtPredefinedBiosError plist +#define ACPI_ERROR_ONLY(s) s + +#else + +/* No error messages */ + +#define ACPI_ERROR_NAMESPACE(s, p, e) +#define ACPI_ERROR_METHOD(s, n, p, e) +#define ACPI_WARN_PREDEFINED(plist) +#define ACPI_INFO_PREDEFINED(plist) +#define ACPI_BIOS_ERROR_PREDEFINED(plist) +#define ACPI_ERROR_ONLY(s) + +#endif /* ACPI_NO_ERROR_MESSAGES */ + +#if (!ACPI_REDUCED_HARDWARE) +#define ACPI_HW_OPTIONAL_FUNCTION(addr) addr +#else +#define ACPI_HW_OPTIONAL_FUNCTION(addr) NULL +#endif + + +/* + * 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')) + + +/* + * Macros used for the ASL-/ASL+ converter utility + */ +#ifdef ACPI_ASL_COMPILER + +#define ASL_CV_LABEL_FILENODE(a) CvLabelFileNode(a); +#define ASL_CV_CAPTURE_COMMENTS_ONLY(a) CvCaptureCommentsOnly (a); +#define ASL_CV_CAPTURE_COMMENTS(a) CvCaptureComments (a); +#define ASL_CV_TRANSFER_COMMENTS(a) CvTransferComments (a); +#define ASL_CV_CLOSE_PAREN(a,b) CvCloseParenWriteComment(a,b); +#define ASL_CV_CLOSE_BRACE(a,b) CvCloseBraceWriteComment(a,b); +#define ASL_CV_SWITCH_FILES(a,b) CvSwitchFiles(a,b); +#define ASL_CV_CLEAR_OP_COMMENTS(a) CvClearOpComments(a); +#define ASL_CV_PRINT_ONE_COMMENT(a,b,c,d) CvPrintOneCommentType (a,b,c,d); +#define ASL_CV_PRINT_ONE_COMMENT_LIST(a,b) CvPrintOneCommentList (a,b); +#define ASL_CV_FILE_HAS_SWITCHED(a) CvFileHasSwitched(a) +#define ASL_CV_INIT_FILETREE(a,b) CvInitFileTree(a,b); + +#else + +#define ASL_CV_LABEL_FILENODE(a) +#define ASL_CV_CAPTURE_COMMENTS_ONLY(a) +#define ASL_CV_CAPTURE_COMMENTS(a) +#define ASL_CV_TRANSFER_COMMENTS(a) +#define ASL_CV_CLOSE_PAREN(a,b) AcpiOsPrintf (")"); +#define ASL_CV_CLOSE_BRACE(a,b) AcpiOsPrintf ("}"); +#define ASL_CV_SWITCH_FILES(a,b) +#define ASL_CV_CLEAR_OP_COMMENTS(a) +#define ASL_CV_PRINT_ONE_COMMENT(a,b,c,d) +#define ASL_CV_PRINT_ONE_COMMENT_LIST(a,b) +#define ASL_CV_FILE_HAS_SWITCHED(a) 0 +#define ASL_CV_INIT_FILETREE(a,b) + +#endif + +#endif /* ACMACROS_H */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acnames.h b/code/drivers/platform/acpi/third_party/acpica/include/acnames.h new file mode 100644 index 0000000..51f4862 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acnames.h @@ -0,0 +1,68 @@ +/****************************************************************************** + * + * Name: acnames.h - Global names and strings + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACNAMES_H__ +#define __ACNAMES_H__ + +/* Method names - these methods can appear anywhere in the namespace */ + +#define METHOD_NAME__ADR "_ADR" +#define METHOD_NAME__AEI "_AEI" +#define METHOD_NAME__BBN "_BBN" +#define METHOD_NAME__CBA "_CBA" +#define METHOD_NAME__CID "_CID" +#define METHOD_NAME__CLS "_CLS" +#define METHOD_NAME__CRS "_CRS" +#define METHOD_NAME__DDN "_DDN" +#define METHOD_NAME__DIS "_DIS" +#define METHOD_NAME__DMA "_DMA" +#define METHOD_NAME__EVT "_EVT" +#define METHOD_NAME__HID "_HID" +#define METHOD_NAME__INI "_INI" +#define METHOD_NAME__PLD "_PLD" +#define METHOD_NAME__DSD "_DSD" +#define METHOD_NAME__PRS "_PRS" +#define METHOD_NAME__PRT "_PRT" +#define METHOD_NAME__PRW "_PRW" +#define METHOD_NAME__PS0 "_PS0" +#define METHOD_NAME__PS1 "_PS1" +#define METHOD_NAME__PS2 "_PS2" +#define METHOD_NAME__PS3 "_PS3" +#define METHOD_NAME__REG "_REG" +#define METHOD_NAME__SB_ "_SB_" +#define METHOD_NAME__SEG "_SEG" +#define METHOD_NAME__SRS "_SRS" +#define METHOD_NAME__STA "_STA" +#define METHOD_NAME__SUB "_SUB" +#define METHOD_NAME__UID "_UID" + +/* Method names - these methods must appear at the namespace root */ + +#define METHOD_PATHNAME__PTS "\\_PTS" +#define METHOD_PATHNAME__SST "\\_SI._SST" +#define METHOD_PATHNAME__WAK "\\_WAK" + +/* Definitions of the predefined namespace names */ + +#define ACPI_UNKNOWN_NAME (UINT32) 0x3F3F3F3F /* Unknown name is "????" */ +#define ACPI_PREFIX_MIXED (UINT32) 0x69706341 /* "Acpi" */ +#define ACPI_PREFIX_LOWER (UINT32) 0x69706361 /* "acpi" */ + +/* Root name stuff */ + +#define ACPI_ROOT_NAME (UINT32) 0x5F5F5F5C /* Root name is "\___" */ +#define ACPI_ROOT_PATHNAME "\\___" +#define ACPI_NAMESPACE_ROOT "Namespace Root" +#define ACPI_NS_ROOT_PATH "\\" + +#endif /* __ACNAMES_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acnamesp.h b/code/drivers/platform/acpi/third_party/acpica/include/acnamesp.h new file mode 100644 index 0000000..97c57ea --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acnamesp.h @@ -0,0 +1,555 @@ +/****************************************************************************** + * + * Name: acnamesp.h - Namespace subcomponent prototypes and defines + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 0x0001 +#define ACPI_NS_DONT_OPEN_SCOPE 0x0002 +#define ACPI_NS_NO_PEER_SEARCH 0x0004 +#define ACPI_NS_ERROR_IF_FOUND 0x0008 +#define ACPI_NS_PREFIX_IS_SCOPE 0x0010 +#define ACPI_NS_EXTERNAL 0x0020 +#define ACPI_NS_TEMPORARY 0x0040 +#define ACPI_NS_OVERRIDE_IF_FOUND 0x0080 +#define ACPI_NS_EARLY_INIT 0x0100 +#define ACPI_NS_PREFIX_MUST_EXIST 0x0200 + +/* 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 +#define ACPI_ALL_PACKAGE_ELEMENTS (ACPI_UINT32_MAX-1) + +/* Always emit warning message, not dependent on node flags */ + +#define ACPI_WARN_ALWAYS 0 + + +/* + * nsinit - Namespace initialization + */ +ACPI_STATUS +AcpiNsInitializeObjects ( + void); + +ACPI_STATUS +AcpiNsInitializeDevices ( + UINT32 Flags); + +ACPI_STATUS +AcpiNsInitOnePackage ( + ACPI_HANDLE ObjHandle, + UINT32 Level, + void *Context, + void **ReturnValue); + +/* + * 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 DescendingCallback, + ACPI_WALK_CALLBACK AscendingCallback, + 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 +AcpiNsExecuteTable ( + 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); + + +/* + * nsconvert - Dynamic object conversion routines + */ +ACPI_STATUS +AcpiNsConvertToInteger ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + +ACPI_STATUS +AcpiNsConvertToString ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + +ACPI_STATUS +AcpiNsConvertToBuffer ( + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + +ACPI_STATUS +AcpiNsConvertToUnicode ( + ACPI_NAMESPACE_NODE *Scope, + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + +ACPI_STATUS +AcpiNsConvertToResource ( + ACPI_NAMESPACE_NODE *Scope, + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + +ACPI_STATUS +AcpiNsConvertToReference ( + ACPI_NAMESPACE_NODE *Scope, + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ReturnObject); + + +/* + * nsdump - Namespace dump/print utilities + */ +void +AcpiNsDumpTables ( + ACPI_HANDLE SearchBase, + UINT32 MaxDepth); + +void +AcpiNsDumpEntry ( + ACPI_HANDLE Handle, + UINT32 DebugLevel); + +void +AcpiNsDumpPathname ( + ACPI_HANDLE Handle, + const char *Msg, + UINT32 Level, + UINT32 Component); + +void +AcpiNsPrintPathname ( + UINT32 NumSegments, + const 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); + +void +AcpiNsDumpObjectPaths ( + 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); + + +/* + * nsarguments - Argument count/type checking for predefined/reserved names + */ +void +AcpiNsCheckArgumentCount ( + char *Pathname, + ACPI_NAMESPACE_NODE *Node, + UINT32 UserParamCount, + const ACPI_PREDEFINED_INFO *Info); + +void +AcpiNsCheckAcpiCompliance ( + char *Pathname, + ACPI_NAMESPACE_NODE *Node, + const ACPI_PREDEFINED_INFO *Predefined); + +void +AcpiNsCheckArgumentTypes ( + ACPI_EVALUATE_INFO *Info); + + +/* + * nspredef - Return value checking for predefined/reserved names + */ +ACPI_STATUS +AcpiNsCheckReturnValue ( + ACPI_NAMESPACE_NODE *Node, + ACPI_EVALUATE_INFO *Info, + UINT32 UserParamCount, + ACPI_STATUS ReturnStatus, + ACPI_OPERAND_OBJECT **ReturnObject); + +ACPI_STATUS +AcpiNsCheckObjectType ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **ReturnObjectPtr, + UINT32 ExpectedBtypes, + UINT32 PackageIndex); + + +/* + * nsprepkg - Validation of predefined name packages + */ +ACPI_STATUS +AcpiNsCheckPackage ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + + +/* + * nsnames - Name and Scope manipulation + */ +UINT32 +AcpiNsOpensScope ( + ACPI_OBJECT_TYPE Type); + +char * +AcpiNsGetExternalPathname ( + ACPI_NAMESPACE_NODE *Node); + +UINT32 +AcpiNsBuildNormalizedPath ( + ACPI_NAMESPACE_NODE *Node, + char *FullPath, + UINT32 PathSize, + BOOLEAN NoTrailing); + +void +AcpiNsNormalizePathname ( + char *OriginalPath); + +char * +AcpiNsGetNormalizedPathname ( + ACPI_NAMESPACE_NODE *Node, + BOOLEAN NoTrailing); + +char * +AcpiNsBuildPrefixedPathname ( + ACPI_GENERIC_STATE *PrefixScope, + const char *InternalPath); + +char * +AcpiNsNameOfCurrentScope ( + ACPI_WALK_STATE *WalkState); + +ACPI_STATUS +AcpiNsHandleToName ( + ACPI_HANDLE TargetHandle, + ACPI_BUFFER *Buffer); + +ACPI_STATUS +AcpiNsHandleToPathname ( + ACPI_HANDLE TargetHandle, + ACPI_BUFFER *Buffer, + BOOLEAN NoTrailing); + +BOOLEAN +AcpiNsPatternMatch ( + ACPI_NAMESPACE_NODE *ObjNode, + char *SearchFor); + +ACPI_STATUS +AcpiNsGetNodeUnlocked ( + ACPI_NAMESPACE_NODE *PrefixNode, + const char *ExternalPathname, + UINT32 Flags, + ACPI_NAMESPACE_NODE **OutNode); + +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 +AcpiNsSimpleRepair ( + ACPI_EVALUATE_INFO *Info, + UINT32 ExpectedBtypes, + UINT32 PackageIndex, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +ACPI_STATUS +AcpiNsWrapWithPackage ( + ACPI_EVALUATE_INFO *Info, + ACPI_OPERAND_OBJECT *OriginalObject, + ACPI_OPERAND_OBJECT **ObjDescPtr); + +ACPI_STATUS +AcpiNsRepairNullElement ( + ACPI_EVALUATE_INFO *Info, + UINT32 ExpectedBtypes, + UINT32 PackageIndex, + ACPI_OPERAND_OBJECT **ReturnObjectPtr); + +void +AcpiNsRemoveNullElements ( + ACPI_EVALUATE_INFO *Info, + UINT8 PackageType, + ACPI_OPERAND_OBJECT *ObjDesc); + + +/* + * nsrepair2 - Return object repair for specific + * predefined methods/objects + */ +ACPI_STATUS +AcpiNsComplexRepairs ( + ACPI_EVALUATE_INFO *Info, + 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 + */ +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/code/drivers/platform/acpi/third_party/acpica/include/acobject.h b/code/drivers/platform/acpi/third_party/acpica/include/acobject.h new file mode 100644 index 0000000..7cba404 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acobject.h @@ -0,0 +1,569 @@ +/****************************************************************************** + * + * Name: acobject.h - Definition of ACPI_OPERAND_OBJECT (Internal object only) + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 initialized and data is valid */ +#define AOPOBJ_OBJECT_INITIALIZED 0x08 /* Region is initialized */ +#define AOPOBJ_REG_CONNECTED 0x10 /* _REG was run */ +#define AOPOBJ_SETUP_COMPLETE 0x20 /* Region setup is complete */ +#define AOPOBJ_INVALID 0x40 /* 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 + + +/* Null terminated, ASCII characters only */ + +typedef struct acpi_object_string +{ + 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; + void *Pointer; /* Only for data table regions */ + +} ACPI_OBJECT_REGION; + + +typedef struct acpi_object_method +{ + ACPI_OBJECT_COMMON_HEADER; + UINT8 InfoFlags; + UINT8 ParamCount; + UINT8 SyncLevel; + union acpi_operand_object *Mutex; + union acpi_operand_object *Node; + UINT8 *AmlStart; + union + { + ACPI_INTERNAL_METHOD Implementation; + union acpi_operand_object *Handler; + } Dispatch; + + UINT32 AmlLength; + ACPI_OWNER_ID OwnerId; + UINT8 ThreadCount; + +} 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_IGNORE_SYNC_LEVEL 0x10 /* Method was auto-serialized at table load time */ +#define ACPI_METHOD_MODIFIED_NAMESPACE 0x20 /* 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 *NotifyList[2]; /* Handlers for system/device notifies */\ + union acpi_operand_object *Handler /* Handler for Address space */ + +/* COMMON NOTIFY for POWER, PROCESSOR, DEVICE, and THERMAL */ + +typedef struct acpi_object_notify_common +{ + 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 */ + +/* COMMON FIELD (for BUFFER, REGION, BANK, and INDEX fields) */ + +typedef struct acpi_object_field_common +{ + 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 */ + UINT16 PinNumberIndex; /* Index relative to previous Connection/Template */ + UINT8 *InternalPccBuffer; /* Internal buffer for fields associated with PCC */ + +} 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; + BOOLEAN IsCreateField; /* Special case for objects created by CreateField() */ + 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 */ + UINT32 HandlerType; /* Type: Device/System/Both */ + ACPI_NOTIFY_HANDLER Handler; /* Handler address */ + void *Context; + union acpi_operand_object *Next[2]; /* Device and System handler lists */ + +} 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_MUTEX ContextMutex; + 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 Resolved; /* Reference has been resolved to a value */ + 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 */ + UINT8 *IndexPointer; /* Used for Buffers and Strings */ + UINT8 *Aml; /* Used for deferred resolution of the ref */ + 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/code/drivers/platform/acpi/third_party/acpica/include/acopcode.h b/code/drivers/platform/acpi/third_party/acpica/include/acopcode.h new file mode 100644 index 0000000..6633c9a --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acopcode.h @@ -0,0 +1,303 @@ +/****************************************************************************** + * + * Name: acopcode.h - AML opcode information for the AML parser and interpreter + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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_COMMENT_OP ARGP_LIST2 (ARGP_BYTEDATA, ARGP_COMMENT) +#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_SIMPLENAME, ARGP_TARGET) +#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_SUPERNAME) +#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_EXTERNAL_OP ARGP_LIST3 (ARGP_NAME, ARGP_BYTEDATA, ARGP_BYTEDATA) +#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_OBJECT_TYPE_OP ARGP_LIST1 (ARGP_SIMPLENAME) +#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_SIMPLENAME) +#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_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_LIST1 (ARGI_INTEGER) +#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_COMMENT_OP ARGI_INVALID_OPCODE +#define ARGI_CONCAT_OP ARGI_LIST3 (ARGI_ANYTYPE, ARGI_ANYTYPE, 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_EXTERNAL_OP ARGI_LIST3 (ARGI_STRING, ARGI_INTEGER, ARGI_INTEGER) +#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_OBJECT_TYPE_OP ARGI_LIST1 (ARGI_ANYTYPE) +#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_STORE_TARGET) +#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_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/code/drivers/platform/acpi/third_party/acpica/include/acoutput.h b/code/drivers/platform/acpi/third_party/acpica/include/acoutput.h new file mode 100644 index 0000000..ae58fd5 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acoutput.h @@ -0,0 +1,481 @@ +/****************************************************************************** + * + * Name: acoutput.h -- debug output + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 ASL_PREPROCESSOR 0x00020000 + +#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_TRACE_POINT 0x00000010 +#define ACPI_LV_ALL_EXCEPTIONS 0x0000001F + +/* 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_EVALUATION 0x00080000 +#define ACPI_LV_VERBOSITY1 0x000FFF40 | 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_PARSE_TREES 0x00800000 +#define ACPI_LV_VERBOSITY2 0x00F00000 | 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_TRACE_POINT ACPI_DEBUG_LEVEL (ACPI_LV_TRACE_POINT) +#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_PARSE_TREES ACPI_DEBUG_LEVEL (ACPI_LV_PARSE_TREES) +#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_EVALUATION ACPI_DEBUG_LEVEL (ACPI_LV_EVALUATION) +#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_EVALUATION | 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) + + +/* + * Global trace flags + */ +#define ACPI_TRACE_ENABLED ((UINT32) 4) +#define ACPI_TRACE_ONESHOT ((UINT32) 2) +#define ACPI_TRACE_OPCODE ((UINT32) 1) + +/* Defaults for trace debugging level/layer */ + +#define ACPI_TRACE_LEVEL_ALL ACPI_LV_ALL +#define ACPI_TRACE_LAYER_ALL 0x000001FF +#define ACPI_TRACE_LEVEL_DEFAULT ACPI_LV_TRACE_POINT +#define ACPI_TRACE_LAYER_DEFAULT ACPI_EXECUTER + + +#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__ +#define ACPI_ONCE(_fn, _plist) { static char _done; if (!_done) { _done = 1; _fn _plist; } } + +/* + * 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_WARNING_ONCE(plist) ACPI_ONCE(AcpiWarning, plist) +#define ACPI_EXCEPTION(plist) AcpiException plist +#define ACPI_ERROR(plist) AcpiError plist +#define ACPI_ERROR_ONCE(plist) ACPI_ONCE(AcpiError, plist) +#define ACPI_BIOS_WARNING(plist) AcpiBiosWarning plist +#define ACPI_BIOS_EXCEPTION(plist) AcpiBiosException plist +#define ACPI_BIOS_ERROR(plist) AcpiBiosError 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_WARNING_ONCE(plist) +#define ACPI_EXCEPTION(plist) +#define ACPI_ERROR(plist) +#define ACPI_ERROR_ONCE(plist) +#define ACPI_BIOS_WARNING(plist) +#define ACPI_BIOS_EXCEPTION(plist) +#define ACPI_BIOS_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 non-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 + +/* Check if debug output is currently dynamically enabled */ + +#define ACPI_IS_DEBUG_ENABLED(Level, Component) \ + ((Level & AcpiDbgLevel) && (Component & AcpiDbgLayer)) + +/* + * 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 + * + * November 2012: Moved the runtime check for whether to actually emit the + * debug message outside of the print function itself. This improves overall + * performance at a relatively small code cost. Implementation involves the + * use of variadic macros supported by C99. + * + * Note: the ACPI_DO_WHILE0 macro is used to prevent some compilers from + * complaining about these constructs. On other compilers the do...while + * adds some extra code, so this feature is optional. + */ +#ifdef ACPI_USE_DO_WHILE_0 +#define ACPI_DO_WHILE0(a) do a while(0) +#else +#define ACPI_DO_WHILE0(a) a +#endif + +/* DEBUG_PRINT functions */ + +#ifndef COMPILER_VA_MACRO + +#define ACPI_DEBUG_PRINT(plist) AcpiDebugPrint plist +#define ACPI_DEBUG_PRINT_RAW(plist) AcpiDebugPrintRaw plist + +#else + +/* Helper macros for DEBUG_PRINT */ + +#define ACPI_DO_DEBUG_PRINT(Function, Level, Line, Filename, Modulename, Component, ...) \ + ACPI_DO_WHILE0 ({ \ + if (ACPI_IS_DEBUG_ENABLED (Level, Component)) \ + { \ + Function (Level, Line, Filename, Modulename, Component, __VA_ARGS__); \ + } \ + }) + +#define ACPI_ACTUAL_DEBUG(Level, Line, Filename, Modulename, Component, ...) \ + ACPI_DO_DEBUG_PRINT (AcpiDebugPrint, Level, Line, \ + Filename, Modulename, Component, __VA_ARGS__) + +#define ACPI_ACTUAL_DEBUG_RAW(Level, Line, Filename, Modulename, Component, ...) \ + ACPI_DO_DEBUG_PRINT (AcpiDebugPrintRaw, Level, Line, \ + Filename, Modulename, Component, __VA_ARGS__) + +#define ACPI_DEBUG_PRINT(plist) ACPI_ACTUAL_DEBUG plist +#define ACPI_DEBUG_PRINT_RAW(plist) ACPI_ACTUAL_DEBUG_RAW plist + +#endif + + +/* + * Function entry tracing + * + * The name of the function is emitted as a local variable that is + * intended to be used by both the entry trace and the exit trace. + */ + +/* Helper macro */ + +#define ACPI_TRACE_ENTRY(Name, Function, Type, Param) \ + ACPI_FUNCTION_NAME (Name) \ + Function (ACPI_DEBUG_PARAMETERS, (Type) (Param)) + +/* The actual entry trace macros */ + +#define ACPI_FUNCTION_TRACE(Name) \ + ACPI_FUNCTION_NAME(Name) \ + AcpiUtTrace (ACPI_DEBUG_PARAMETERS) + +#define ACPI_FUNCTION_TRACE_PTR(Name, Pointer) \ + ACPI_TRACE_ENTRY (Name, AcpiUtTracePtr, void *, Pointer) + +#define ACPI_FUNCTION_TRACE_U32(Name, Value) \ + ACPI_TRACE_ENTRY (Name, AcpiUtTraceU32, UINT32, Value) + +#define ACPI_FUNCTION_TRACE_STR(Name, String) \ + ACPI_TRACE_ENTRY (Name, AcpiUtTraceStr, const char *, String) + +#define ACPI_FUNCTION_ENTRY() \ + AcpiUtTrackStackPtr() + + +/* + * Function exit tracing + * + * These macros include a return statement. This is usually considered + * bad form, but having a separate exit macro before the actual return + * 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. + * + * 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 optimization is disabled.) + */ + +/* Exit trace helper macro */ + +#ifndef ACPI_SIMPLE_RETURN_MACROS + +#define ACPI_TRACE_EXIT(Function, Type, Param) \ + ACPI_DO_WHILE0 ({ \ + register Type _Param = (Type) (Param); \ + Function (ACPI_DEBUG_PARAMETERS, _Param); \ + return (_Param); \ + }) + +#else /* Use original less-safe macros */ + +#define ACPI_TRACE_EXIT(Function, Type, Param) \ + ACPI_DO_WHILE0 ({ \ + Function (ACPI_DEBUG_PARAMETERS, (Type) (Param)); \ + return (Param); \ + }) + +#endif /* ACPI_SIMPLE_RETURN_MACROS */ + +/* The actual exit macros */ + +#define return_VOID \ + ACPI_DO_WHILE0 ({ \ + AcpiUtExit (ACPI_DEBUG_PARAMETERS); \ + return; \ + }) + +#define return_ACPI_STATUS(Status) \ + ACPI_TRACE_EXIT (AcpiUtStatusExit, ACPI_STATUS, Status) + +#define return_PTR(Pointer) \ + ACPI_TRACE_EXIT (AcpiUtPtrExit, void *, Pointer) + +#define return_STR(String) \ + ACPI_TRACE_EXIT (AcpiUtStrExit, const char *, String) + +#define return_VALUE(Value) \ + ACPI_TRACE_EXIT (AcpiUtValueExit, UINT64, Value) + +#define return_UINT32(Value) \ + ACPI_TRACE_EXIT (AcpiUtValueExit, UINT32, Value) + +#define return_UINT8(Value) \ + ACPI_TRACE_EXIT (AcpiUtValueExit, UINT8, Value) + +/* 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) AcpiUtDebugDumpBuffer((UINT8 *) a, b, DB_BYTE_DISPLAY, _COMPONENT) + +#define ACPI_TRACE_POINT(a, b, c, d) AcpiTracePoint (a, b, c, d) + +#else /* ACPI_DEBUG_OUTPUT */ +/* + * This is the non-debug case -- make everything go away, + * leaving no executable debug code! + */ +#define ACPI_DEBUG_PRINT(pl) +#define ACPI_DEBUG_PRINT_RAW(pl) +#define ACPI_DEBUG_EXEC(a) +#define ACPI_DEBUG_ONLY_MEMBERS(a) +#define ACPI_FUNCTION_NAME(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_ENTRY() +#define ACPI_DUMP_STACK_ENTRY(a) +#define ACPI_DUMP_OPERANDS(a, b, c) +#define ACPI_DUMP_ENTRY(a, b) +#define ACPI_DUMP_PATHNAME(a, b, c, d) +#define ACPI_DUMP_BUFFER(a, b) +#define ACPI_IS_DEBUG_ENABLED(Level, Component) 0 +#define ACPI_TRACE_POINT(a, b, c, d) + +/* Return macros must have a return statement at the minimum */ + +#define return_VOID return +#define return_ACPI_STATUS(s) return(s) +#define return_PTR(s) return(s) +#define return_STR(s) return(s) +#define return_VALUE(s) return(s) +#define return_UINT8(s) return(s) +#define return_UINT32(s) return(s) + +#endif /* ACPI_DEBUG_OUTPUT */ + + +#endif /* __ACOUTPUT_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acparser.h b/code/drivers/platform/acpi/third_party/acpica/include/acparser.h new file mode 100644 index 0000000..2d85b6f --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acparser.h @@ -0,0 +1,338 @@ +/****************************************************************************** + * + * Module Name: acparser.h - AML Parser subcomponent prototypes and defines + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 + * + *****************************************************************************/ + +extern const UINT8 AcpiGbl_ShortOpIndex[]; +extern const UINT8 AcpiGbl_LongOpIndex[]; + + +/* + * psxface - Parser external interfaces + */ +ACPI_STATUS +AcpiPsExecuteMethod ( + ACPI_EVALUATE_INFO *Info); + +ACPI_STATUS +AcpiPsExecuteTable ( + 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 PossibleMethodCall); + +/* Values for BOOLEAN above */ + +#define ACPI_NOT_METHOD_CALL FALSE +#define ACPI_POSSIBLE_METHOD_CALL TRUE + +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); + + +/* + * psobject - support for parse object processing + */ +ACPI_STATUS +AcpiPsBuildNamedOp ( + ACPI_WALK_STATE *WalkState, + UINT8 *AmlOpStart, + ACPI_PARSE_OBJECT *UnnamedOp, + ACPI_PARSE_OBJECT **Op); + +ACPI_STATUS +AcpiPsCreateOp ( + ACPI_WALK_STATE *WalkState, + UINT8 *AmlOpStart, + ACPI_PARSE_OBJECT **NewOp); + +ACPI_STATUS +AcpiPsCompleteOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT **Op, + ACPI_STATUS Status); + +ACPI_STATUS +AcpiPsCompleteFinalOp ( + ACPI_WALK_STATE *WalkState, + ACPI_PARSE_OBJECT *Op, + ACPI_STATUS Status); + + +/* + * psopinfo - AML Opcode information + */ +const ACPI_OPCODE_INFO * +AcpiPsGetOpcodeInfo ( + UINT16 Opcode); + +const 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 ( + UINT8 *Aml); + +void +AcpiPsInitOp ( + ACPI_PARSE_OBJECT *op, + UINT16 opcode); + +ACPI_PARSE_OBJECT * +AcpiPsAllocOp ( + UINT16 Opcode, + UINT8 *Aml); + +void +AcpiPsFreeOp ( + ACPI_PARSE_OBJECT *Op); + +BOOLEAN +AcpiPsIsLeadingChar ( + 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/code/drivers/platform/acpi/third_party/acpica/include/acpi.h b/code/drivers/platform/acpi/third_party/acpica/include/acpi.h new file mode 100644 index 0000000..3e72807 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acpi.h @@ -0,0 +1,37 @@ +/****************************************************************************** + * + * Name: acpi.h - Master public include file used to interface to ACPICA + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 "actypes.h" /* ACPICA data types and structures */ +#include "platform/acenvex.h" /* Extra environment-specific items */ +#include "acnames.h" /* Common ACPI names and strings */ +#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/code/drivers/platform/acpi/third_party/acpica/include/acpiosxf.h b/code/drivers/platform/acpi/third_party/acpica/include/acpiosxf.h new file mode 100644 index 0000000..8bb6343 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acpiosxf.h @@ -0,0 +1,567 @@ +/****************************************************************************** + * + * 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) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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_MAIN_THREAD, + OSL_DEBUGGER_EXEC_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 + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsInitialize +ACPI_STATUS +AcpiOsInitialize ( + void); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsTerminate +ACPI_STATUS +AcpiOsTerminate ( + void); +#endif + + +/* + * ACPI Table interfaces + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsGetRootPointer +ACPI_PHYSICAL_ADDRESS +AcpiOsGetRootPointer ( + void); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsPredefinedOverride +ACPI_STATUS +AcpiOsPredefinedOverride ( + const ACPI_PREDEFINED_NAMES *InitVal, + ACPI_STRING *NewVal); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsTableOverride +ACPI_STATUS +AcpiOsTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_TABLE_HEADER **NewTable); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsPhysicalTableOverride +ACPI_STATUS +AcpiOsPhysicalTableOverride ( + ACPI_TABLE_HEADER *ExistingTable, + ACPI_PHYSICAL_ADDRESS *NewAddress, + UINT32 *NewTableLength); +#endif + + +/* + * Spinlock primitives + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsCreateLock +ACPI_STATUS +AcpiOsCreateLock ( + ACPI_SPINLOCK *OutHandle); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsDeleteLock +void +AcpiOsDeleteLock ( + ACPI_SPINLOCK Handle); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsAcquireLock +ACPI_CPU_FLAGS +AcpiOsAcquireLock ( + ACPI_SPINLOCK Handle); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsReleaseLock +void +AcpiOsReleaseLock ( + ACPI_SPINLOCK Handle, + ACPI_CPU_FLAGS Flags); +#endif + + +/* + * Semaphore primitives + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsCreateSemaphore +ACPI_STATUS +AcpiOsCreateSemaphore ( + UINT32 MaxUnits, + UINT32 InitialUnits, + ACPI_SEMAPHORE *OutHandle); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsDeleteSemaphore +ACPI_STATUS +AcpiOsDeleteSemaphore ( + ACPI_SEMAPHORE Handle); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsWaitSemaphore +ACPI_STATUS +AcpiOsWaitSemaphore ( + ACPI_SEMAPHORE Handle, + UINT32 Units, + UINT16 Timeout); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsSignalSemaphore +ACPI_STATUS +AcpiOsSignalSemaphore ( + ACPI_SEMAPHORE Handle, + UINT32 Units); +#endif + + +/* + * Mutex primitives. May be configured to use semaphores instead via + * ACPI_MUTEX_TYPE (see platform/acenv.h) + */ +#if (ACPI_MUTEX_TYPE != ACPI_BINARY_SEMAPHORE) + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsCreateMutex +ACPI_STATUS +AcpiOsCreateMutex ( + ACPI_MUTEX *OutHandle); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsDeleteMutex +void +AcpiOsDeleteMutex ( + ACPI_MUTEX Handle); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsAcquireMutex +ACPI_STATUS +AcpiOsAcquireMutex ( + ACPI_MUTEX Handle, + UINT16 Timeout); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsReleaseMutex +void +AcpiOsReleaseMutex ( + ACPI_MUTEX Handle); +#endif + +#endif + + +/* + * Memory allocation and mapping + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsAllocate +void * +AcpiOsAllocate ( + ACPI_SIZE Size); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsAllocateZeroed +void * +AcpiOsAllocateZeroed ( + ACPI_SIZE Size); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsFree +void +AcpiOsFree ( + void * Memory); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsMapMemory +void * +AcpiOsMapMemory ( + ACPI_PHYSICAL_ADDRESS Where, + ACPI_SIZE Length); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsUnmapMemory +void +AcpiOsUnmapMemory ( + void *LogicalAddress, + ACPI_SIZE Size); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsGetPhysicalAddress +ACPI_STATUS +AcpiOsGetPhysicalAddress ( + void *LogicalAddress, + ACPI_PHYSICAL_ADDRESS *PhysicalAddress); +#endif + + +/* + * Memory/Object Cache + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsCreateCache +ACPI_STATUS +AcpiOsCreateCache ( + char *CacheName, + UINT16 ObjectSize, + UINT16 MaxDepth, + ACPI_CACHE_T **ReturnCache); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsDeleteCache +ACPI_STATUS +AcpiOsDeleteCache ( + ACPI_CACHE_T *Cache); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsPurgeCache +ACPI_STATUS +AcpiOsPurgeCache ( + ACPI_CACHE_T *Cache); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsAcquireObject +void * +AcpiOsAcquireObject ( + ACPI_CACHE_T *Cache); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsReleaseObject +ACPI_STATUS +AcpiOsReleaseObject ( + ACPI_CACHE_T *Cache, + void *Object); +#endif + + +/* + * Interrupt handlers + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsInstallInterruptHandler +ACPI_STATUS +AcpiOsInstallInterruptHandler ( + UINT32 InterruptNumber, + ACPI_OSD_HANDLER ServiceRoutine, + void *Context); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsRemoveInterruptHandler +ACPI_STATUS +AcpiOsRemoveInterruptHandler ( + UINT32 InterruptNumber, + ACPI_OSD_HANDLER ServiceRoutine); +#endif + + +/* + * Threads and Scheduling + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsGetThreadId +ACPI_THREAD_ID +AcpiOsGetThreadId ( + void); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsExecute +ACPI_STATUS +AcpiOsExecute ( + ACPI_EXECUTE_TYPE Type, + ACPI_OSD_EXEC_CALLBACK Function, + void *Context); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsWaitEventsComplete +void +AcpiOsWaitEventsComplete ( + void); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsSleep +void +AcpiOsSleep ( + UINT64 Milliseconds); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsStall +void +AcpiOsStall ( + UINT32 Microseconds); +#endif + + +/* + * Platform and hardware-independent I/O interfaces + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsReadPort +ACPI_STATUS +AcpiOsReadPort ( + ACPI_IO_ADDRESS Address, + UINT32 *Value, + UINT32 Width); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsWritePort +ACPI_STATUS +AcpiOsWritePort ( + ACPI_IO_ADDRESS Address, + UINT32 Value, + UINT32 Width); +#endif + + +/* + * Platform and hardware-independent physical memory interfaces + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsReadMemory +ACPI_STATUS +AcpiOsReadMemory ( + ACPI_PHYSICAL_ADDRESS Address, + UINT64 *Value, + UINT32 Width); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsWriteMemory +ACPI_STATUS +AcpiOsWriteMemory ( + ACPI_PHYSICAL_ADDRESS Address, + UINT64 Value, + UINT32 Width); +#endif + + +/* + * Platform and hardware-independent PCI configuration space access + * Note: Can't use "Register" as a parameter, changed to "Reg" -- + * certain compilers complain. + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsReadPciConfiguration +ACPI_STATUS +AcpiOsReadPciConfiguration ( + ACPI_PCI_ID *PciId, + UINT32 Reg, + UINT64 *Value, + UINT32 Width); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsWritePciConfiguration +ACPI_STATUS +AcpiOsWritePciConfiguration ( + ACPI_PCI_ID *PciId, + UINT32 Reg, + UINT64 Value, + UINT32 Width); +#endif + + +/* + * Miscellaneous + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsReadable +BOOLEAN +AcpiOsReadable ( + void *Pointer, + ACPI_SIZE Length); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsWritable +BOOLEAN +AcpiOsWritable ( + void *Pointer, + ACPI_SIZE Length); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsGetTimer +UINT64 +AcpiOsGetTimer ( + void); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsSignal +ACPI_STATUS +AcpiOsSignal ( + UINT32 Function, + void *Info); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsEnterSleep +ACPI_STATUS +AcpiOsEnterSleep ( + UINT8 SleepState, + UINT32 RegaValue, + UINT32 RegbValue); +#endif + + +/* + * Debug print routines + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsPrintf +ACPI_PRINTF_LIKE (1) +void ACPI_INTERNAL_VAR_XFACE +AcpiOsPrintf ( + const char *Format, + ...); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsVprintf +void +AcpiOsVprintf ( + const char *Format, + va_list Args); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsRedirectOutput +void +AcpiOsRedirectOutput ( + void *Destination); +#endif + + +/* + * Debug IO + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsGetLine +ACPI_STATUS +AcpiOsGetLine ( + char *Buffer, + UINT32 BufferLength, + UINT32 *BytesRead); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsInitializeDebugger +ACPI_STATUS +AcpiOsInitializeDebugger ( + void); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsTerminateDebugger +void +AcpiOsTerminateDebugger ( + void); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsWaitCommandReady +ACPI_STATUS +AcpiOsWaitCommandReady ( + void); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsNotifyCommandComplete +ACPI_STATUS +AcpiOsNotifyCommandComplete ( + void); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsTracePoint +void +AcpiOsTracePoint ( + ACPI_TRACE_EVENT_TYPE Type, + BOOLEAN Begin, + UINT8 *Aml, + char *Pathname); +#endif + + +/* + * Obtain ACPI table(s) + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsGetTableByName +ACPI_STATUS +AcpiOsGetTableByName ( + char *Signature, + UINT32 Instance, + ACPI_TABLE_HEADER **Table, + ACPI_PHYSICAL_ADDRESS *Address); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsGetTableByIndex +ACPI_STATUS +AcpiOsGetTableByIndex ( + UINT32 Index, + ACPI_TABLE_HEADER **Table, + UINT32 *Instance, + ACPI_PHYSICAL_ADDRESS *Address); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsGetTableByAddress +ACPI_STATUS +AcpiOsGetTableByAddress ( + ACPI_PHYSICAL_ADDRESS Address, + ACPI_TABLE_HEADER **Table); +#endif + + +/* + * Directory manipulation + */ +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsOpenDirectory +void * +AcpiOsOpenDirectory ( + char *Pathname, + char *WildcardSpec, + char RequestedFileType); +#endif + +/* RequesteFileType values */ + +#define REQUEST_FILE_ONLY 0 +#define REQUEST_DIR_ONLY 1 + + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsGetNextFilename +char * +AcpiOsGetNextFilename ( + void *DirHandle); +#endif + +#ifndef ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsCloseDirectory +void +AcpiOsCloseDirectory ( + void *DirHandle); +#endif + + +#endif /* __ACPIOSXF_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acpixf.h b/code/drivers/platform/acpi/third_party/acpica/include/acpixf.h new file mode 100644 index 0000000..028f94a --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acpixf.h @@ -0,0 +1,1312 @@ +/****************************************************************************** + * + * Name: acpixf.h - External interfaces to the ACPI subsystem + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACXFACE_H__ +#define __ACXFACE_H__ + +/* Current ACPICA subsystem version in YYYYMMDD format */ + +#define ACPI_CA_VERSION 0x20260930 + +#include "acconfig.h" +#include "actypes.h" +#include "actbl.h" +#include "acbuffer.h" + + +/***************************************************************************** + * + * Macros used for ACPICA globals and configuration + * + ****************************************************************************/ + +/* + * Ensure that global variables are defined and initialized only once. + * + * The use of these macros allows for a single list of globals (here) + * in order to simplify maintenance of the code. + */ +#ifdef DEFINE_ACPI_GLOBALS +#define ACPI_GLOBAL(type,name) \ + extern type name; \ + type name + +#define ACPI_INIT_GLOBAL(type,name,value) \ + type name=value + +#else +#ifndef ACPI_GLOBAL +#define ACPI_GLOBAL(type,name) \ + extern type name +#endif + +#ifndef ACPI_INIT_GLOBAL +#define ACPI_INIT_GLOBAL(type,name,value) \ + extern type name +#endif +#endif + +/* + * These macros configure the various ACPICA interfaces. They are + * useful for generating stub inline functions for features that are + * configured out of the current kernel or ACPICA application. + */ +#ifndef ACPI_EXTERNAL_RETURN_STATUS +#define ACPI_EXTERNAL_RETURN_STATUS(Prototype) \ + Prototype; +#endif + +#ifndef ACPI_EXTERNAL_RETURN_OK +#define ACPI_EXTERNAL_RETURN_OK(Prototype) \ + Prototype; +#endif + +#ifndef ACPI_EXTERNAL_RETURN_VOID +#define ACPI_EXTERNAL_RETURN_VOID(Prototype) \ + Prototype; +#endif + +#ifndef ACPI_EXTERNAL_RETURN_UINT32 +#define ACPI_EXTERNAL_RETURN_UINT32(Prototype) \ + Prototype; +#endif + +#ifndef ACPI_EXTERNAL_RETURN_PTR +#define ACPI_EXTERNAL_RETURN_PTR(Prototype) \ + Prototype; +#endif + + +/***************************************************************************** + * + * Public globals and runtime configuration options + * + ****************************************************************************/ + +/* + * Enable "slack mode" of 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 + */ +ACPI_INIT_GLOBAL (UINT8, AcpiGbl_EnableInterpreterSlack, FALSE); + +/* + * Automatically serialize all methods that create named objects? Default + * is TRUE, meaning that all NonSerialized methods are scanned once at + * table load time to determine those that create named objects. Methods + * that create named objects are marked Serialized in order to prevent + * possible run-time problems if they are entered by more than one thread. + */ +ACPI_INIT_GLOBAL (UINT8, AcpiGbl_AutoSerializeMethods, TRUE); + +/* + * Create the predefined _OSI method in the namespace? Default is TRUE + * because ACPICA is fully compatible with other ACPI implementations. + * Changing this will revert ACPICA (and machine ASL) to pre-OSI behavior. + */ +ACPI_INIT_GLOBAL (UINT8, 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. + */ +ACPI_INIT_GLOBAL (UINT8, AcpiGbl_UseDefaultRegisterWidths, TRUE); + +/* + * Whether or not to validate (map) an entire table to verify + * checksum/duplication in early stage before install. Set this to TRUE to + * allow early table validation before install it to the table manager. + * Note that enabling this option causes errors to happen in some OSPMs + * during early initialization stages. Default behavior is to allow such + * validation. + */ +ACPI_INIT_GLOBAL (UINT8, AcpiGbl_EnableTableValidation, TRUE); + +/* + * Optionally enable output from the AML Debug Object. + */ +ACPI_INIT_GLOBAL (UINT8, 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. + */ +ACPI_INIT_GLOBAL (UINT8, AcpiGbl_CopyDsdtLocally, FALSE); + +/* + * Optionally ignore an XSDT if present and use the RSDT instead. + * Although the ACPI specification requires that an XSDT be used instead + * of the RSDT, the XSDT has been found to be corrupt or ill-formed on + * some machines. Default behavior is to use the XSDT if present. + */ +ACPI_INIT_GLOBAL (UINT8, AcpiGbl_DoNotUseXsdt, FALSE); + +/* + * Optionally use 32-bit FADT addresses if and when there is a conflict + * (address mismatch) between the 32-bit and 64-bit versions of the + * address. Although ACPICA adheres to the ACPI specification which + * requires the use of the corresponding 64-bit address if it is non-zero, + * some machines have been found to have a corrupted non-zero 64-bit + * address. Default is FALSE, do not favor the 32-bit addresses. + */ +ACPI_INIT_GLOBAL (UINT8, AcpiGbl_Use32BitFadtAddresses, FALSE); + +/* + * Optionally use 32-bit FACS table addresses. + * It is reported that some platforms fail to resume from system suspending + * if 64-bit FACS table address is selected: + * https://bugzilla.kernel.org/show_bug.cgi?id=74021 + * Default is TRUE, favor the 32-bit addresses. + */ +ACPI_INIT_GLOBAL (UINT8, AcpiGbl_Use32BitFacsAddresses, TRUE); + +/* + * 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. + */ +ACPI_INIT_GLOBAL (UINT8, 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. + */ +ACPI_INIT_GLOBAL (UINT8, AcpiGbl_DisableAutoRepair, FALSE); + +/* + * Optionally do not install any SSDTs from the RSDT/XSDT during initialization. + * This can be useful for debugging ACPI problems on some machines. + */ +ACPI_INIT_GLOBAL (UINT8, AcpiGbl_DisableSsdtTableInstall, FALSE); + +/* + * Optionally enable runtime namespace override. + */ +ACPI_INIT_GLOBAL (UINT8, AcpiGbl_RuntimeNamespaceOverride, TRUE); + +/* + * We keep track of the latest version of Windows that has been requested by + * the BIOS. ACPI 5.0. + */ +ACPI_INIT_GLOBAL (UINT8, AcpiGbl_OsiData, 0); + +/* + * 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. + */ +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_ReducedHardware, FALSE); + +/* + * ACPI Global Lock is mainly used for systems with SMM, so no-SMM systems + * (such as LoongArch) may not have and not use Global Lock. + */ +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_UseGlobalLock, TRUE); + +/* + * Maximum timeout for While() loop iterations before forced method abort. + * This mechanism is intended to prevent infinite loops during interpreter + * execution within a host kernel. + */ +ACPI_INIT_GLOBAL (UINT32, AcpiGbl_MaxLoopIterations, ACPI_MAX_LOOP_TIMEOUT); + +/* + * Optionally ignore AE_NOT_FOUND errors from named reference package elements + * during DSDT/SSDT table loading. This reduces error "noise" in platforms + * whose firmware is carrying around a bunch of unused package objects that + * refer to non-existent named objects. However, If the AML actually tries to + * use such a package, the unresolved element(s) will be replaced with NULL + * elements. + */ +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_IgnorePackageResolutionErrors, FALSE); + +/* + * This mechanism is used to trace a specified AML method. The method is + * traced each time it is executed. + */ +ACPI_INIT_GLOBAL (UINT32, AcpiGbl_TraceFlags, 0); +ACPI_INIT_GLOBAL (const char *, AcpiGbl_TraceMethodName, NULL); +ACPI_INIT_GLOBAL (UINT32, AcpiGbl_TraceDbgLevel, ACPI_TRACE_LEVEL_DEFAULT); +ACPI_INIT_GLOBAL (UINT32, AcpiGbl_TraceDbgLayer, ACPI_TRACE_LAYER_DEFAULT); + +/* + * Runtime configuration of debug output control masks. We want the debug + * switches statically initialized so they are already set when the debugger + * is entered. + */ +#ifdef ACPI_DEBUG_OUTPUT +ACPI_INIT_GLOBAL (UINT32, AcpiDbgLevel, ACPI_DEBUG_DEFAULT); +#else +ACPI_INIT_GLOBAL (UINT32, AcpiDbgLevel, ACPI_NORMAL_DEFAULT); +#endif +ACPI_INIT_GLOBAL (UINT32, AcpiDbgLayer, ACPI_COMPONENT_DEFAULT); + +/* Optionally enable timer output with Debug Object output */ + +ACPI_INIT_GLOBAL (UINT8, AcpiGbl_DisplayDebugTimer, FALSE); + +/* + * Debugger command handshake globals. Host OSes need to access these + * variables to implement their own command handshake mechanism. + */ +#ifdef ACPI_DEBUGGER +ACPI_INIT_GLOBAL (BOOLEAN, AcpiGbl_MethodExecuting, FALSE); +ACPI_GLOBAL (char, AcpiGbl_DbLineBuf[ACPI_DB_LINE_BUFFER_SIZE]); +#endif + +/* + * Other miscellaneous globals + */ +ACPI_GLOBAL (ACPI_TABLE_FADT, AcpiGbl_FADT); +ACPI_GLOBAL (UINT32, AcpiCurrentGpeCount); +ACPI_GLOBAL (BOOLEAN, AcpiGbl_SystemAwakeAndRunning); + + +/***************************************************************************** + * + * ACPICA public interface configuration. + * + * Interfaces that are configured out of the ACPICA build are replaced + * by inlined stubs by default. + * + ****************************************************************************/ + +/* + * Hardware-reduced prototypes (default: Not hardware reduced). + * + * All ACPICA hardware-related interfaces that use these macros will be + * configured out of the ACPICA build if the ACPI_REDUCED_HARDWARE flag + * is set to TRUE. + * + * Note: This static build option for reduced hardware is intended to + * reduce ACPICA code size if desired or necessary. However, even if this + * option is not specified, the runtime behavior of ACPICA is dependent + * on the actual FADT reduced hardware flag (HW_REDUCED_ACPI). If set, + * the flag will enable similar behavior -- ACPICA will not attempt + * to access any ACPI-relate hardware (SCI, GPEs, Fixed Events, etc.) + */ +#if (!ACPI_REDUCED_HARDWARE) +#define ACPI_HW_DEPENDENT_RETURN_STATUS(Prototype) \ + ACPI_EXTERNAL_RETURN_STATUS(Prototype) + +#define ACPI_HW_DEPENDENT_RETURN_OK(Prototype) \ + ACPI_EXTERNAL_RETURN_OK(Prototype) + +#define ACPI_HW_DEPENDENT_RETURN_UINT32(prototype) \ + ACPI_EXTERNAL_RETURN_UINT32(prototype) + +#define ACPI_HW_DEPENDENT_RETURN_VOID(Prototype) \ + ACPI_EXTERNAL_RETURN_VOID(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_UINT32(prototype) \ + static ACPI_INLINE prototype {return(0);} + +#define ACPI_HW_DEPENDENT_RETURN_VOID(Prototype) \ + static ACPI_INLINE Prototype {return;} + +#endif /* !ACPI_REDUCED_HARDWARE */ + + +/* + * Error message prototypes (default: error messages enabled). + * + * All interfaces related to error and warning messages + * will be configured out of the ACPICA build if the + * ACPI_NO_ERROR_MESSAGE flag is defined. + */ +#ifndef ACPI_NO_ERROR_MESSAGES +#define ACPI_MSG_DEPENDENT_RETURN_VOID(Prototype) \ + Prototype; + +#else +#define ACPI_MSG_DEPENDENT_RETURN_VOID(Prototype) \ + static ACPI_INLINE Prototype {return;} + +#endif /* ACPI_NO_ERROR_MESSAGES */ + + +/* + * Debugging output prototypes (default: no debug output). + * + * All interfaces related to debug output messages + * will be configured out of the ACPICA build unless the + * ACPI_DEBUG_OUTPUT flag is defined. + */ +#ifdef ACPI_DEBUG_OUTPUT +#define ACPI_DBG_DEPENDENT_RETURN_VOID(Prototype) \ + Prototype; + +#else +#define ACPI_DBG_DEPENDENT_RETURN_VOID(Prototype) \ + static ACPI_INLINE Prototype {return;} + +#endif /* ACPI_DEBUG_OUTPUT */ + + +/* + * Application prototypes + * + * All interfaces used by application will be configured + * out of the ACPICA build unless the ACPI_APPLICATION + * flag is defined. + */ +#ifdef ACPI_APPLICATION +#define ACPI_APP_DEPENDENT_RETURN_VOID(Prototype) \ + Prototype; + +#else +#define ACPI_APP_DEPENDENT_RETURN_VOID(Prototype) \ + static ACPI_INLINE Prototype {return;} + +#endif /* ACPI_APPLICATION */ + + +/* + * Debugger prototypes + * + * All interfaces used by debugger will be configured + * out of the ACPICA build unless the ACPI_DEBUGGER + * flag is defined. + */ +#ifdef ACPI_DEBUGGER +#define ACPI_DBR_DEPENDENT_RETURN_OK(Prototype) \ + ACPI_EXTERNAL_RETURN_OK(Prototype) + +#define ACPI_DBR_DEPENDENT_RETURN_VOID(Prototype) \ + ACPI_EXTERNAL_RETURN_VOID(Prototype) + +#else +#define ACPI_DBR_DEPENDENT_RETURN_OK(Prototype) \ + static ACPI_INLINE Prototype {return(AE_OK);} + +#define ACPI_DBR_DEPENDENT_RETURN_VOID(Prototype) \ + static ACPI_INLINE Prototype {return;} + +#endif /* ACPI_DEBUGGER */ + + +/***************************************************************************** + * + * ACPICA public interface prototypes + * + ****************************************************************************/ + +/* + * Initialization + */ +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS ACPI_INIT_FUNCTION +AcpiInitializeTables ( + ACPI_TABLE_DESC *InitialStorage, + UINT32 InitialTableCount, + BOOLEAN AllowResize)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS ACPI_INIT_FUNCTION +AcpiInitializeSubsystem ( + void)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS ACPI_INIT_FUNCTION +AcpiEnableSubsystem ( + UINT32 Flags)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS ACPI_INIT_FUNCTION +AcpiInitializeObjects ( + UINT32 Flags)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS ACPI_INIT_FUNCTION +AcpiTerminate ( + void)) + + +/* + * Miscellaneous global interfaces + */ +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiEnable ( + void)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiDisable ( + void)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiSubsystemStatus ( + void)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetSystemInfo ( + ACPI_BUFFER *RetBuffer)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetStatistics ( + ACPI_STATISTICS *Stats)) + +ACPI_EXTERNAL_RETURN_PTR ( +const char * +AcpiFormatException ( + ACPI_STATUS Exception)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiPurgeCachedObjects ( + void)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiInstallInterface ( + ACPI_STRING InterfaceName)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiRemoveInterface ( + ACPI_STRING InterfaceName)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiUpdateInterfaces ( + UINT8 Action)) + +ACPI_EXTERNAL_RETURN_UINT32 ( +UINT32 +AcpiCheckAddressRange ( + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_PHYSICAL_ADDRESS Address, + ACPI_SIZE Length, + BOOLEAN Warn)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiDecodePldBuffer ( + UINT8 *InBuffer, + ACPI_SIZE Length, + ACPI_PLD_INFO **ReturnBuffer)) + + +/* + * ACPI table load/unload interfaces + */ +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS ACPI_INIT_FUNCTION +AcpiInstallTable ( + ACPI_TABLE_HEADER *Table)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS ACPI_INIT_FUNCTION +AcpiInstallPhysicalTable ( + ACPI_PHYSICAL_ADDRESS Address)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiLoadTable ( + ACPI_TABLE_HEADER *Table, + UINT32 *TableIdx)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiUnloadTable ( + UINT32 TableIndex)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiUnloadParentTable ( + ACPI_HANDLE Object)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS ACPI_INIT_FUNCTION +AcpiLoadTables ( + void)) + + +/* + * ACPI table manipulation interfaces + */ +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS ACPI_INIT_FUNCTION +AcpiReallocateRootTable ( + void)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS ACPI_INIT_FUNCTION +AcpiFindRootPointer ( + ACPI_PHYSICAL_ADDRESS *RsdpAddress)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetTableHeader ( + ACPI_STRING Signature, + UINT32 Instance, + ACPI_TABLE_HEADER *OutTableHeader)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetTable ( + ACPI_STRING Signature, + UINT32 Instance, + ACPI_TABLE_HEADER **OutTable)) + +ACPI_EXTERNAL_RETURN_VOID ( +void +AcpiPutTable ( + ACPI_TABLE_HEADER *Table)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetTableByIndex ( + UINT32 TableIndex, + ACPI_TABLE_HEADER **OutTable)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiInstallTableHandler ( + ACPI_TABLE_HANDLER Handler, + void *Context)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiRemoveTableHandler ( + ACPI_TABLE_HANDLER Handler)) + + +/* + * Namespace and name interfaces + */ +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiWalkNamespace ( + ACPI_OBJECT_TYPE Type, + ACPI_HANDLE StartObject, + UINT32 MaxDepth, + ACPI_WALK_CALLBACK DescendingCallback, + ACPI_WALK_CALLBACK AscendingCallback, + void *Context, + void **ReturnValue)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetDevices ( + char *HID, + ACPI_WALK_CALLBACK UserFunction, + void *Context, + void **ReturnValue)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetName ( + ACPI_HANDLE Object, + UINT32 NameType, + ACPI_BUFFER *RetPathPtr)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetHandle ( + ACPI_HANDLE Parent, + const char *Pathname, + ACPI_HANDLE *RetHandle)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiAttachData ( + ACPI_HANDLE Object, + ACPI_OBJECT_HANDLER Handler, + void *Data)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiDetachData ( + ACPI_HANDLE Object, + ACPI_OBJECT_HANDLER Handler)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetData ( + ACPI_HANDLE Object, + ACPI_OBJECT_HANDLER Handler, + void **Data)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiDebugTrace ( + const char *Name, + UINT32 DebugLevel, + UINT32 DebugLayer, + UINT32 Flags)) + + +/* + * Object manipulation and enumeration + */ +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiEvaluateObject ( + ACPI_HANDLE Object, + ACPI_STRING Pathname, + ACPI_OBJECT_LIST *ParameterObjects, + ACPI_BUFFER *ReturnObjectBuffer)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiEvaluateObjectTyped ( + ACPI_HANDLE Object, + ACPI_STRING Pathname, + ACPI_OBJECT_LIST *ExternalParams, + ACPI_BUFFER *ReturnBuffer, + ACPI_OBJECT_TYPE ReturnType)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetObjectInfo ( + ACPI_HANDLE Object, + ACPI_DEVICE_INFO **ReturnBuffer)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiInstallMethod ( + UINT8 *Buffer)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetNextObject ( + ACPI_OBJECT_TYPE Type, + ACPI_HANDLE Parent, + ACPI_HANDLE Child, + ACPI_HANDLE *OutHandle)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetType ( + ACPI_HANDLE Object, + ACPI_OBJECT_TYPE *OutType)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetParent ( + ACPI_HANDLE Object, + ACPI_HANDLE *OutHandle)) + + +/* + * Handler interfaces + */ +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiInstallInitializationHandler ( + ACPI_INIT_HANDLER Handler, + UINT32 Function)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiInstallSciHandler ( + ACPI_SCI_HANDLER Address, + void *Context)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiRemoveSciHandler ( + ACPI_SCI_HANDLER Address)) + +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 +AcpiInstallGpeRawHandler ( + 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_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiInstallNotifyHandler ( + ACPI_HANDLE Device, + UINT32 HandlerType, + ACPI_NOTIFY_HANDLER Handler, + void *Context)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiRemoveNotifyHandler ( + ACPI_HANDLE Device, + UINT32 HandlerType, + ACPI_NOTIFY_HANDLER Handler)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiInstallAddressSpaceHandler ( + ACPI_HANDLE Device, + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_ADR_SPACE_HANDLER Handler, + ACPI_ADR_SPACE_SETUP Setup, + void *Context)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiInstallAddressSpaceHandlerNo_Reg( + ACPI_HANDLE Device, + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_ADR_SPACE_HANDLER Handler, + ACPI_ADR_SPACE_SETUP Setup, + void *Context)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiExecuteRegMethods ( + ACPI_HANDLE Device, + ACPI_ADR_SPACE_TYPE SpaceId)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiRemoveAddressSpaceHandler ( + ACPI_HANDLE Device, + ACPI_ADR_SPACE_TYPE SpaceId, + ACPI_ADR_SPACE_HANDLER Handler)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiInstallExceptionHandler ( + ACPI_EXCEPTION_HANDLER Handler)) + +ACPI_EXTERNAL_RETURN_STATUS ( +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_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiAcquireMutex ( + ACPI_HANDLE Handle, + ACPI_STRING Pathname, + UINT16 Timeout)) + +ACPI_EXTERNAL_RETURN_STATUS ( +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 +AcpiMaskGpe ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber, + BOOLEAN IsMasked)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiMarkGpeForWake ( + 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_UINT32 ( +UINT32 +AcpiDispatchGpe ( + ACPI_HANDLE GpeDevice, + UINT32 GpeNumber)) + +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 +AcpiEnableAllWakeupGpes ( + void)) + +ACPI_HW_DEPENDENT_RETURN_UINT32 ( + UINT32 AcpiAnyGpeStatusSet ( + 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_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetVendorResource ( + ACPI_HANDLE Device, + char *Name, + ACPI_VENDOR_UUID *Uuid, + ACPI_BUFFER *RetBuffer)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetCurrentResources ( + ACPI_HANDLE Device, + ACPI_BUFFER *RetBuffer)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetPossibleResources ( + ACPI_HANDLE Device, + ACPI_BUFFER *RetBuffer)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetEventResources ( + ACPI_HANDLE DeviceHandle, + ACPI_BUFFER *RetBuffer)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiWalkResourceBuffer ( + ACPI_BUFFER *Buffer, + ACPI_WALK_RESOURCE_CALLBACK UserFunction, + void *Context)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiWalkResources ( + ACPI_HANDLE Device, + char *Name, + ACPI_WALK_RESOURCE_CALLBACK UserFunction, + void *Context)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiSetCurrentResources ( + ACPI_HANDLE Device, + ACPI_BUFFER *InBuffer)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetIrqRoutingTable ( + ACPI_HANDLE Device, + ACPI_BUFFER *RetBuffer)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiResourceToAddress64 ( + ACPI_RESOURCE *Resource, + ACPI_RESOURCE_ADDRESS64 *Out)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiBufferToResource ( + UINT8 *AmlBuffer, + UINT16 AmlBufferLength, + ACPI_RESOURCE **ResourcePtr)) + + +/* + * Hardware (ACPI device) interfaces + */ +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiReset ( + void)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiRead ( + UINT64 *Value, + ACPI_GENERIC_ADDRESS *Reg)) + +ACPI_EXTERNAL_RETURN_STATUS ( +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_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiGetSleepTypeData ( + UINT8 SleepState, + UINT8 *Slp_TypA, + UINT8 *Slp_TypB)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiEnterSleepStatePrep ( + UINT8 SleepState)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiEnterSleepState ( + UINT8 SleepState)) + +ACPI_HW_DEPENDENT_RETURN_STATUS ( +ACPI_STATUS +AcpiEnterSleepStateS4bios ( + void)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiLeaveSleepStatePrep ( + UINT8 SleepState)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiLeaveSleepState ( + UINT8 SleepState)) + +ACPI_EXTERNAL_RETURN_STATUS ( +ACPI_STATUS +AcpiSetFirmwareWakingVector ( + ACPI_PHYSICAL_ADDRESS PhysicalAddress, + ACPI_PHYSICAL_ADDRESS PhysicalAddress64)) + + +/* + * 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 + */ +ACPI_MSG_DEPENDENT_RETURN_VOID ( +ACPI_PRINTF_LIKE(3) +void ACPI_INTERNAL_VAR_XFACE +AcpiError ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...)) + +ACPI_MSG_DEPENDENT_RETURN_VOID ( +ACPI_PRINTF_LIKE(4) +void ACPI_INTERNAL_VAR_XFACE +AcpiException ( + const char *ModuleName, + UINT32 LineNumber, + ACPI_STATUS Status, + const char *Format, + ...)) + +ACPI_MSG_DEPENDENT_RETURN_VOID ( +ACPI_PRINTF_LIKE(3) +void ACPI_INTERNAL_VAR_XFACE +AcpiWarning ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...)) + +ACPI_MSG_DEPENDENT_RETURN_VOID ( +ACPI_PRINTF_LIKE(1) +void ACPI_INTERNAL_VAR_XFACE +AcpiInfo ( + const char *Format, + ...)) + +ACPI_MSG_DEPENDENT_RETURN_VOID ( +ACPI_PRINTF_LIKE(3) +void ACPI_INTERNAL_VAR_XFACE +AcpiBiosError ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...)) + +ACPI_MSG_DEPENDENT_RETURN_VOID ( +ACPI_PRINTF_LIKE(4) +void ACPI_INTERNAL_VAR_XFACE +AcpiBiosException ( + const char *ModuleName, + UINT32 LineNumber, + ACPI_STATUS Status, + const char *Format, + ...)) + +ACPI_MSG_DEPENDENT_RETURN_VOID ( +ACPI_PRINTF_LIKE(3) +void ACPI_INTERNAL_VAR_XFACE +AcpiBiosWarning ( + const char *ModuleName, + UINT32 LineNumber, + const char *Format, + ...)) + + +/* + * Debug output + */ +ACPI_DBG_DEPENDENT_RETURN_VOID ( +ACPI_PRINTF_LIKE(6) +void ACPI_INTERNAL_VAR_XFACE +AcpiDebugPrint ( + UINT32 RequestedDebugLevel, + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + const char *Format, + ...)) + +ACPI_DBG_DEPENDENT_RETURN_VOID ( +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_DBG_DEPENDENT_RETURN_VOID ( +void +AcpiTracePoint ( + ACPI_TRACE_EVENT_TYPE Type, + BOOLEAN Begin, + UINT8 *Aml, + char *Pathname)) + +ACPI_STATUS +AcpiInitializeDebugger ( + void); + +void +AcpiTerminateDebugger ( + void); + +void +AcpiRunDebugger ( + char *BatchBuffer); + +void +AcpiSetDebuggerThreadId ( + ACPI_THREAD_ID ThreadId); + +#endif /* __ACXFACE_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acpredef.h b/code/drivers/platform/acpi/third_party/acpica/include/acpredef.h new file mode 100644 index 0000000..26266e3 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acpredef.h @@ -0,0 +1,1171 @@ +/****************************************************************************** + * + * Name: acpredef - Information table for ACPI predefined methods and objects + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACPREDEF_H__ +#define __ACPREDEF_H__ + + +/****************************************************************************** + * + * Return Package types + * + * 1) PTYPE1 packages do not contain subpackages. + * + * ACPI_PTYPE1_FIXED: Fixed-length length, 1 or 2 object types: + * object type + * count + * object type + * count + * + * ACPI_PTYPE1_VAR: Variable-length length. Zero-length package is allowed: + * 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 subpackages. Each + * of the different types describe the contents of each of the subpackages. + * + * ACPI_PTYPE2: Each subpackage contains 1 or 2 object types. Zero-length + * parent package is allowed: + * object type + * count + * object type + * count + * (Used for _ALR,_MLS,_PSS,_TRT,_TSS) + * + * ACPI_PTYPE2_COUNT: Each subpackage has a count as first element. + * Zero-length parent package is allowed: + * 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. Zero-length + * parent package is allowed. + * (Used for _PRT) + * + * ACPI_PTYPE2_MIN: Each subpackage has a Variable-length but minimum length. + * Zero-length parent package is allowed: + * (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. Zero-length parent package is allowed. + * object type + * count + * object type + * count = 0 (optional) + * (Used for _DLM) + * + * ACPI_PTYPE2_VAR_VAR: Variable number of subpackages, each of either a + * constant or variable length. The subpackages are preceded by a + * constant number of objects. + * (Used for _LPI, _RDI) + * + * ACPI_PTYPE2_UUID_PAIR: Each subpackage is preceded by a UUID Buffer. The UUID + * defines the format of the package. Zero-length parent package is + * allowed. + * (Used for _DSD) + * + *****************************************************************************/ + +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, + ACPI_PTYPE2_VAR_VAR = 11, + ACPI_PTYPE2_UUID_PAIR = 12, + ACPI_PTYPE_CUSTOM = 13 +}; + + +/* Support macros for users of the predefined info table */ + +#define METHOD_PREDEF_ARGS_MAX 5 +#define METHOD_ARG_BIT_WIDTH 3 +#define METHOD_ARG_MASK 0x0007 +#define ARG_COUNT_IS_MINIMUM 0x8000 +#define METHOD_MAX_ARG_TYPE ACPI_TYPE_PACKAGE + +#define METHOD_GET_ARG_COUNT(ArgList) ((ArgList) & METHOD_ARG_MASK) +#define METHOD_GET_NEXT_TYPE(ArgList) (((ArgList) >>= METHOD_ARG_BIT_WIDTH) & METHOD_ARG_MASK) + +/* Macros used to build the predefined info table */ + +#define METHOD_0ARGS 0 +#define METHOD_1ARGS(a1) (1 | (a1 << 3)) +#define METHOD_2ARGS(a1,a2) (2 | (a1 << 3) | (a2 << 6)) +#define METHOD_3ARGS(a1,a2,a3) (3 | (a1 << 3) | (a2 << 6) | (a3 << 9)) +#define METHOD_4ARGS(a1,a2,a3,a4) (4 | (a1 << 3) | (a2 << 6) | (a3 << 9) | (a4 << 12)) +#define METHOD_5ARGS(a1,a2,a3,a4,a5) (5 | (a1 << 3) | (a2 << 6) | (a3 << 9) | (a4 << 12) | (a5 << 15)) + +#define METHOD_RETURNS(type) (type) +#define METHOD_NO_RETURN_VALUE 0 + +#define PACKAGE_INFO(a,b,c,d,e,f) {{{(a),(b),(c),(d)}, ((((UINT16)(f)) << 8) | (e)), 0}} + + +/* Support macros for the resource descriptor info table */ + +#define WIDTH_1 0x0001 +#define WIDTH_2 0x0002 +#define WIDTH_3 0x0004 +#define WIDTH_8 0x0008 +#define WIDTH_16 0x0010 +#define WIDTH_32 0x0020 +#define WIDTH_64 0x0040 +#define VARIABLE_DATA 0x0080 +#define NUM_RESOURCE_WIDTHS 8 + +#define WIDTH_ADDRESS WIDTH_16 | WIDTH_32 | WIDTH_64 + + +#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 not usually evaluated via + * AcpiEvaluateObject: + * _Lxx and _Exx GPE methods + * _Qxx EC methods + * _T_x compiler temporary variables + * _Wxx wake events + * _Ixx indicator for GPEs in low power S0 idle state + * + * 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 + * + * The main entries in the table each contain the following items: + * + * Name - The ACPI reserved name + * ArgumentList - Contains (in 16 bits), the number of required + * arguments to the method (3 bits), and a 3-bit type + * field for each argument (up to 4 arguments). The + * METHOD_?ARGS macros generate the correct packed data. + * 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. + * + * Note2: Table is used by the kernel-resident subsystem, the iASL compiler, + * and the AcpiHelp utility. + * + * TBD: _PRT - currently ignore reversed entries. Attempt to fix in nsrepair. + * Possibly fixing package elements like _BIF, etc. + * + *****************************************************************************/ + +const ACPI_PREDEFINED_INFO AcpiGbl_PredefinedMethods[] = +{ + {{"_AC0", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_AC1", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_AC2", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_AC3", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_AC4", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_AC5", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_AC6", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_AC7", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_AC8", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_AC9", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_ADR", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_AEI", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_AL0", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_AL1", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_AL2", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_AL3", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_AL4", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_AL5", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_AL6", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_AL7", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_AL8", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_AL9", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_ALC", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_ALI", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_ALP", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_ALR", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each 2 (Ints) */ + PACKAGE_INFO (ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 2,0,0,0), + + {{"_ALT", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_ART", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (1 Int(rev), n Pkg (2 Ref/11 Int) */ + PACKAGE_INFO (ACPI_PTYPE2_REV_FIXED, ACPI_RTYPE_REFERENCE, 2, ACPI_RTYPE_INTEGER, 11,0), + + {{"_BBN", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_BCL", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Ints) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0,0,0), + + {{"_BCM", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_BCT", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_BDN", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_BFS", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_BIF", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (9 Int),(4 Str) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 9, ACPI_RTYPE_STRING, 4,0), + + {{"_BIX", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (16 Int),(4 Str) */ + PACKAGE_INFO (ACPI_PTYPE_CUSTOM, ACPI_RTYPE_INTEGER, 16, ACPI_RTYPE_STRING, 4,0), + + {{"_BLT", METHOD_3ARGS (ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_BMA", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_BMC", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_BMD", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (5 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 5,0,0,0), + + {{"_BMS", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_BPC", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (4 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0,0,0), + + {{"_BPS", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (5 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 5,0,0,0), + + {{"_BPT", METHOD_1ARGS (ACPI_TYPE_PACKAGE), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_BQC", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_BST", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (4 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0,0,0), + + {{"_BTH", METHOD_1ARGS (ACPI_TYPE_INTEGER), /* ACPI 6.0 */ + METHOD_NO_RETURN_VALUE}}, + + {{"_BTM", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_BTP", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_CBA", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, /* See PCI firmware spec 3.0 */ + + {{"_CBR", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (3 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3,0,0,0), + + {{"_CCA", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, /* ACPI 5.1 */ + + {{"_CDM", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_CID", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Ints/Strs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING, 0,0,0,0), + + {{"_CLS", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (3 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3,0,0,0), + + {{"_CPC", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Ints/Bufs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER | ACPI_RTYPE_PACKAGE, 0,0,0,0), + + {{"_CR3", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_CRS", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_CRT", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_CSD", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (1 Int(n), n-1 Int) */ + PACKAGE_INFO (ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 0,0,0,0), + + {{"_CST", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (1 Int(n), n Pkg (1 Buf/3 Int) */ + PACKAGE_INFO (ACPI_PTYPE2_PKG_COUNT,ACPI_RTYPE_BUFFER, 1, ACPI_RTYPE_INTEGER, 3,0), + + {{"_CWS", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_DCK", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_DCS", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_DDC", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER)}}, + + {{"_DDN", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_STRING)}}, + + {{"_DEP", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_DGS", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_DIS", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_DLM", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each (1 Ref, 0/1 Optional Buf/Ref) */ + PACKAGE_INFO (ACPI_PTYPE2_FIX_VAR, ACPI_RTYPE_REFERENCE, 1, ACPI_RTYPE_REFERENCE | ACPI_RTYPE_BUFFER, 0,0), + + {{"_DMA", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_DOD", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Ints) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0,0,0), + + {{"_DOS", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + { {"_DSC", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_DSD", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each: 1 Buf, 1 Pkg */ + PACKAGE_INFO (ACPI_PTYPE2_UUID_PAIR, ACPI_RTYPE_BUFFER, 1, ACPI_RTYPE_PACKAGE, 1,0), + + {{"_DSM", METHOD_4ARGS (ACPI_TYPE_BUFFER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_PACKAGE | ACPI_TYPE_ANY) | ARG_COUNT_IS_MINIMUM, + METHOD_RETURNS (ACPI_RTYPE_ALL)}}, /* Must return a value, but it can be of any type */ + + {{"_DSS", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_DSW", METHOD_3ARGS (ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_DTI", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_EC_", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_EDL", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs)*/ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_EJ0", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_EJ1", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_EJ2", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_EJ3", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_EJ4", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_EJD", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_STRING)}}, + + {{"_ERR", METHOD_3ARGS (ACPI_TYPE_INTEGER, ACPI_TYPE_STRING, ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, /* Internal use only, used by ACPICA test suites */ + + {{"_EVT", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_FDE", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_FDI", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (16 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16,0,0,0), + + {{"_FDM", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_FIF", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (4 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0,0,0), + + {{"_FIT", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, /* ACPI 6.0 */ + + {{"_FIX", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Ints) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0,0,0), + + {{"_FPS", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (1 Int(rev), n Pkg (5 Int) */ + PACKAGE_INFO (ACPI_PTYPE2_REV_FIXED,ACPI_RTYPE_INTEGER, 5, 0,0,0), + + {{"_FSL", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_FST", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (3 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3,0,0,0), + + {{"_GAI", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_GCP", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_GHL", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_GLK", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_GPD", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_GPE", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, /* _GPE method, not _GPE scope */ + + {{"_GRT", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_GSB", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_GTF", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_GTM", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_GTS", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_GWS", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_HID", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING)}}, + + {{"_HMA", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_HOT", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_HPP", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (4 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0,0,0), + + /* + * For _HPX, a single package is returned, containing a variable-length number + * of subpackages. Each subpackage 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", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each (var Ints) */ + PACKAGE_INFO (ACPI_PTYPE2_MIN, ACPI_RTYPE_INTEGER, 5,0,0,0), + + {{"_VDM", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_HRV", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_IFT", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, /* See IPMI spec */ + + {{"_INI", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_IRC", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_LCK", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_LID", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_LPD", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (1 Int(rev), n Pkg (2 Int) */ + PACKAGE_INFO (ACPI_PTYPE2_REV_FIXED, ACPI_RTYPE_INTEGER, 2,0,0,0), + + {{"_LPI", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (3 Int, n Pkg (10 Int/Buf) */ + PACKAGE_INFO (ACPI_PTYPE2_VAR_VAR, ACPI_RTYPE_INTEGER, 3, + ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER | ACPI_RTYPE_STRING, 10,0), + + {{"_LSI", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3,0,0,0), + + {{"_LSR", METHOD_2ARGS (ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 1, ACPI_RTYPE_BUFFER, 1,0), + + {{"_LSW", METHOD_3ARGS (ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_BUFFER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_MAT", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_MBM", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (8 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 8,0,0,0), + + {{"_MLS", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each (1 Str/1 Buf) */ + PACKAGE_INFO (ACPI_PTYPE2, ACPI_RTYPE_STRING, 1, ACPI_RTYPE_BUFFER, 1,0), + + {{"_MSG", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_MSM", METHOD_4ARGS (ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_MTL", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_NBS", METHOD_0ARGS, /* ACPI 6.3 */ + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_NCH", METHOD_0ARGS, /* ACPI 6.3 */ + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_NIC", METHOD_0ARGS, /* ACPI 6.3 */ + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_NIG", METHOD_0ARGS, /* ACPI 6.3 */ + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_NIH", METHOD_1ARGS (ACPI_TYPE_BUFFER), /* ACPI 6.3 */ + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_NTT", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_OFF", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_ON_", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_OS_", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_STRING)}}, + + {{"_OSC", METHOD_4ARGS (ACPI_TYPE_BUFFER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_BUFFER), + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_OST", METHOD_3ARGS (ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_BUFFER), + METHOD_NO_RETURN_VALUE}}, + + {{"_PAI", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_PCL", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_PCT", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (2 Buf) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2,0,0,0), + + {{"_PDC", METHOD_1ARGS (ACPI_TYPE_BUFFER), + METHOD_NO_RETURN_VALUE}}, + + {{"_PDL", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_PIC", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_PIF", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (3 Int),(3 Str) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, ACPI_RTYPE_STRING, 3,0), + + {{"_PLD", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Bufs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_BUFFER, 0,0,0,0), + + {{"_PMC", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (11 Int),(3 Str) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 11, ACPI_RTYPE_STRING, 3,0), + + {{"_PMD", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_PMM", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_PPC", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_PPE", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, /* See dig64 spec */ + + {{"_PR0", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_PR1", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_PR2", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_PR3", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_PRE", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_PRL", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_PRR", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (1 Ref) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_REFERENCE, 1,0,0,0), + + {{"_PRS", METHOD_0ARGS, + METHOD_RETURNS (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", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each (4): Int,Int,Int/Ref,Int */ + PACKAGE_INFO (ACPI_PTYPE2_FIXED, 4, ACPI_RTYPE_INTEGER, ACPI_RTYPE_INTEGER, + ACPI_RTYPE_INTEGER | ACPI_RTYPE_REFERENCE, ACPI_RTYPE_INTEGER), + + {{"_PRW", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each: Pkg/Int,Int,[Variable-length Refs] (Pkg is Ref/Int) */ + PACKAGE_INFO (ACPI_PTYPE1_OPTION, 2, ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE, + ACPI_RTYPE_INTEGER, ACPI_RTYPE_REFERENCE, 0), + + {{"_PS0", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_PS1", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_PS2", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_PS3", METHOD_0ARGS, + METHOD_NO_RETURN_VALUE}}, + + {{"_PSC", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_PSD", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each (5 Int) with count */ + PACKAGE_INFO (ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 0,0,0,0), + + {{"_PSE", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_PSL", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_PSR", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_PSS", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each (6 Int) */ + PACKAGE_INFO (ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 6,0,0,0), + + {{"_PSV", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_PSW", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_PTC", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (2 Buf) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2,0,0,0), + + {{"_PTP", METHOD_2ARGS (ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_PTS", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_PUR", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (2 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2,0,0,0), + + {{"_PXM", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_RDI", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (1 Int, n Pkg (m Ref)) */ + PACKAGE_INFO (ACPI_PTYPE2_VAR_VAR, ACPI_RTYPE_INTEGER, 1, + ACPI_RTYPE_REFERENCE,0,0), + + {{"_REG", METHOD_2ARGS (ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_REV", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_RMV", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_ROM", METHOD_2ARGS (ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_RST", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_NO_RETURN_VALUE}}, + + {{"_RTV", METHOD_0ARGS, + METHOD_RETURNS (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_", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (1 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0,0,0), + + {{"_S1_", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (1 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0,0,0), + + {{"_S2_", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (1 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0,0,0), + + {{"_S3_", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (1 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0,0,0), + + {{"_S4_", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (1 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0,0,0), + + {{"_S5_", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (1 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0,0,0), + + {{"_S1D", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_S2D", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_S3D", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_S4D", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_S0W", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_S1W", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_S2W", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_S3W", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_S4W", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_SBA", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (4 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0,0,0), + + {{"_SBI", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (1 Int, 1 Buf) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 1, ACPI_RTYPE_BUFFER,1,0), + + {{"_SBR", METHOD_3ARGS (ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (2 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2, ACPI_RTYPE_BUFFER | ACPI_RTYPE_INTEGER, 1,0), + + {{"_SBS", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_SBT", METHOD_4ARGS (ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_ANY), + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (2 Int, 1 Buf | Int) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2, ACPI_RTYPE_BUFFER | ACPI_RTYPE_INTEGER, 1,0), + + {{"_SBW", METHOD_5ARGS (ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, ACPI_TYPE_ANY), + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER | ACPI_RTYPE_INTEGER, 1, 0,0,0), + + {{"_SCP", METHOD_1ARGS (ACPI_TYPE_INTEGER) | ARG_COUNT_IS_MINIMUM, + METHOD_NO_RETURN_VALUE}}, /* Acpi 1.0 allowed 1 integer arg. Acpi 3.0 expanded to 3 args. Allow both. */ + + {{"_SDD", METHOD_1ARGS (ACPI_TYPE_BUFFER), + METHOD_NO_RETURN_VALUE}}, + + {{"_SEG", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_SHL", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_SLI", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_SPD", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_SRS", METHOD_1ARGS (ACPI_TYPE_BUFFER), + METHOD_NO_RETURN_VALUE}}, + + {{"_SRT", METHOD_1ARGS (ACPI_TYPE_BUFFER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_SRV", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, /* See IPMI spec */ + + {{"_SST", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_STA", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_STM", METHOD_3ARGS (ACPI_TYPE_BUFFER, ACPI_TYPE_BUFFER, ACPI_TYPE_BUFFER), + METHOD_NO_RETURN_VALUE}}, + + {{"_STP", METHOD_2ARGS (ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_STR", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_STV", METHOD_2ARGS (ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_SUB", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_STRING)}}, + + {{"_SUN", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_SWS", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_TC1", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_TC2", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_TDL", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_TFP", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_TIP", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_TIV", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_TMP", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_TPC", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_TPT", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_TRT", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each 2 Ref/6 Int */ + PACKAGE_INFO (ACPI_PTYPE2, ACPI_RTYPE_REFERENCE, 2, ACPI_RTYPE_INTEGER, 6, 0), + + {{"_TSD", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each 5 Int with count */ + PACKAGE_INFO (ACPI_PTYPE2_COUNT,ACPI_RTYPE_INTEGER, 5,0,0,0), + + {{"_TSN", METHOD_0ARGS, /* ACPI 6.0 */ + METHOD_RETURNS (ACPI_RTYPE_REFERENCE)}}, + + {{"_TSP", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_TSS", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Pkgs) each 5 Int */ + PACKAGE_INFO (ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 5,0,0,0), + + {{"_TST", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_TTS", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_NO_RETURN_VALUE}}, + + {{"_TZD", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Variable-length (Refs) */ + PACKAGE_INFO (ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0,0,0), + + {{"_TZM", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_REFERENCE)}}, + + {{"_TZP", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_UID", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING)}}, + + {{"_UPC", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_PACKAGE)}}, /* Fixed-length (4 Int) */ + PACKAGE_INFO (ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0,0,0), + + {{"_UPD", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_UPP", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + {{"_VPO", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, + + /* Acpi 1.0 defined _WAK with no return value. Later, it was changed to return a package */ + + {{"_WAK", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE)}}, + PACKAGE_INFO (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", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_BUFFER)}}, + + {{"_WED", METHOD_1ARGS (ACPI_TYPE_INTEGER), + METHOD_RETURNS (ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER)}}, + + {{"_WPC", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, /* ACPI 6.1 */ + + {{"_WPP", METHOD_0ARGS, + METHOD_RETURNS (ACPI_RTYPE_INTEGER)}}, /* ACPI 6.1 */ + + PACKAGE_INFO (0,0,0,0,0,0) /* Table terminator */ +}; +#else +extern const ACPI_PREDEFINED_INFO AcpiGbl_PredefinedMethods[]; +#endif + + +#if (defined ACPI_CREATE_RESOURCE_TABLE && defined ACPI_APPLICATION) +/****************************************************************************** + * + * 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) + * + * Note: Used by iASL compiler and AcpiHelp utility only. + * + *****************************************************************************/ + +const ACPI_PREDEFINED_INFO AcpiGbl_ResourceNames[] = +{ + {{"_ADR", WIDTH_16 | WIDTH_64, 0}}, + {{"_ALN", WIDTH_8 | WIDTH_16 | WIDTH_32, 0}}, + {{"_ASI", WIDTH_8, 0}}, + {{"_ASZ", WIDTH_8, 0}}, + {{"_ATT", WIDTH_64, 0}}, + {{"_BAS", WIDTH_16 | WIDTH_32, 0}}, + {{"_BM_", WIDTH_1, 0}}, + {{"_DBT", WIDTH_16, 0}}, /* Acpi 5.0 */ + {{"_DEC", WIDTH_1, 0}}, + {{"_DMA", WIDTH_8, 0}}, + {{"_DPL", WIDTH_1, 0}}, /* Acpi 5.0 */ + {{"_DRS", WIDTH_16, 0}}, /* Acpi 5.0 */ + {{"_END", WIDTH_1, 0}}, /* Acpi 5.0 */ + {{"_FLC", WIDTH_2, 0}}, /* Acpi 5.0 */ + {{"_GRA", WIDTH_ADDRESS, 0}}, + {{"_HE_", WIDTH_1, 0}}, + {{"_INT", WIDTH_16 | WIDTH_32, 0}}, + {{"_IOR", WIDTH_2, 0}}, /* Acpi 5.0 */ + {{"_LEN", WIDTH_8 | WIDTH_ADDRESS, 0}}, + {{"_LIN", WIDTH_8, 0}}, /* Acpi 5.0 */ + {{"_LL_", WIDTH_1, 0}}, + {{"_MAF", WIDTH_1, 0}}, + {{"_MAX", WIDTH_ADDRESS, 0}}, + {{"_MEM", WIDTH_2, 0}}, + {{"_MIF", WIDTH_1, 0}}, + {{"_MIN", WIDTH_ADDRESS, 0}}, + {{"_MOD", WIDTH_1, 0}}, /* Acpi 5.0 */ + {{"_MTP", WIDTH_2, 0}}, + {{"_PAR", WIDTH_8, 0}}, /* Acpi 5.0 */ + {{"_PHA", WIDTH_1, 0}}, /* Acpi 5.0 */ + {{"_PIN", WIDTH_16, 0}}, /* Acpi 5.0 */ + {{"_PPI", WIDTH_8, 0}}, /* Acpi 5.0 */ + {{"_POL", WIDTH_1 | WIDTH_2, 0}}, /* Acpi 5.0 */ + {{"_RBO", WIDTH_8, 0}}, + {{"_RBW", WIDTH_8, 0}}, + {{"_RNG", WIDTH_1, 0}}, + {{"_RT_", WIDTH_8, 0}}, /* Acpi 3.0 */ + {{"_RW_", WIDTH_1, 0}}, + {{"_RXL", WIDTH_16, 0}}, /* Acpi 5.0 */ + {{"_SHR", WIDTH_2, 0}}, + {{"_SIZ", WIDTH_2, 0}}, + {{"_SLV", WIDTH_1, 0}}, /* Acpi 5.0 */ + {{"_SPE", WIDTH_32, 0}}, /* Acpi 5.0 */ + {{"_STB", WIDTH_2, 0}}, /* Acpi 5.0 */ + {{"_TRA", WIDTH_ADDRESS, 0}}, + {{"_TRS", WIDTH_1, 0}}, + {{"_TSF", WIDTH_8, 0}}, /* Acpi 3.0 */ + {{"_TTP", WIDTH_1, 0}}, + {{"_TXL", WIDTH_16, 0}}, /* Acpi 5.0 */ + {{"_TYP", WIDTH_2 | WIDTH_16, 0}}, + {{"_VEN", VARIABLE_DATA, 0}}, /* Acpi 5.0 */ + PACKAGE_INFO (0,0,0,0,0,0) /* Table terminator */ +}; + +const ACPI_PREDEFINED_INFO AcpiGbl_ScopeNames[] = { + {{"_GPE", 0, 0}}, + {{"_PR_", 0, 0}}, + {{"_SB_", 0, 0}}, + {{"_SI_", 0, 0}}, + {{"_TZ_", 0, 0}}, + PACKAGE_INFO (0,0,0,0,0,0) /* Table terminator */ +}; +#else +extern const ACPI_PREDEFINED_INFO AcpiGbl_ResourceNames[]; +#endif + +#endif diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acresrc.h b/code/drivers/platform/acpi/third_party/acpica/include/acresrc.h new file mode 100644 index 0000000..d648194 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acresrc.h @@ -0,0 +1,569 @@ +/****************************************************************************** + * + * Name: acresrc.h - Resource Manager function prototypes + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + ***************************************************************************** + * + * Alternatively, you may choose to be licensed under the terms of the + * following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, you may choose to be licensed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + *****************************************************************************/ + +#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_6BITFLAG, + 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; + const 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_6BITFLAG, + 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_RSD_LABEL, + ACPI_RSD_SOURCE_LABEL, + +} 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_BUFFER *ResourceList, + 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, + const 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 *ResourceList, + ACPI_SIZE ResourceListSize, + 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 - Debugger support + */ +#ifdef ACPI_DEBUGGER +void +AcpiRsDumpResourceList ( + ACPI_RESOURCE *Resource); + +void +AcpiRsDumpIrqList ( + UINT8 *RouteTable); +#endif + + +/* + * 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 AcpiRsConvertCsi2SerialBus[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertI2cSerialBus[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertSpiSerialBus[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertUartSerialBus[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertPinFunction[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertPinConfig[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertPinGroup[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertPinGroupFunction[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertPinGroupConfig[]; +extern ACPI_RSCONVERT_INFO AcpiRsConvertClockInput[]; + +/* 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[]; + +/* + * rsdumpinfo + */ +extern ACPI_RSDUMP_INFO AcpiRsDumpIrq[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpPrt[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpDma[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpStartDpf[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpEndDpf[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpIo[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpIoFlags[]; +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 AcpiRsDumpMemoryFlags[]; +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 AcpiRsDumpPinFunction[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpFixedDma[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpCommonSerialBus[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpCsi2SerialBus[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpI2cSerialBus[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpSpiSerialBus[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpUartSerialBus[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpGeneralFlags[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpPinConfig[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpPinGroup[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpPinGroupFunction[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpPinGroupConfig[]; +extern ACPI_RSDUMP_INFO AcpiRsDumpClockInput[]; +#endif + +#endif /* __ACRESRC_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acrestyp.h b/code/drivers/platform/acpi/third_party/acpica/include/acrestyp.h new file mode 100644 index 0000000..a6caba7 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acrestyp.h @@ -0,0 +1,820 @@ +/****************************************************************************** + * + * Name: acrestyp.h - Defines, types, and structures for resource descriptors + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 + +/* Wake */ + +#define ACPI_NOT_WAKE_CAPABLE (UINT8) 0x00 +#define ACPI_WAKE_CAPABLE (UINT8) 0x01 + +/* + * 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 Shareable; + UINT8 WakeCapable; + UINT8 InterruptCount; + union { + UINT8 Interrupt; + ACPI_FLEX_ARRAY(UINT8, Interrupts); + }; + +} ACPI_RESOURCE_IRQ; + +typedef struct acpi_resource_dma +{ + UINT8 Type; + UINT8 BusMaster; + UINT8 Transfer; + UINT8 ChannelCount; + union { + UINT8 Channel; + ACPI_FLEX_ARRAY(UINT8, Channels); + }; + +} 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[]; + +} 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[]; + +} 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_label +{ + UINT16 StringLength; + char *StringPtr; + +} ACPI_RESOURCE_LABEL; + +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_address16_attribute +{ + UINT16 Granularity; + UINT16 Minimum; + UINT16 Maximum; + UINT16 TranslationOffset; + UINT16 AddressLength; + +} ACPI_ADDRESS16_ATTRIBUTE; + +typedef struct acpi_address32_attribute +{ + UINT32 Granularity; + UINT32 Minimum; + UINT32 Maximum; + UINT32 TranslationOffset; + UINT32 AddressLength; + +} ACPI_ADDRESS32_ATTRIBUTE; + +typedef struct acpi_address64_attribute +{ + UINT64 Granularity; + UINT64 Minimum; + UINT64 Maximum; + UINT64 TranslationOffset; + UINT64 AddressLength; + +} ACPI_ADDRESS64_ATTRIBUTE; + +typedef struct acpi_resource_address +{ + ACPI_RESOURCE_ADDRESS_COMMON + +} ACPI_RESOURCE_ADDRESS; + +typedef struct acpi_resource_address16 +{ + ACPI_RESOURCE_ADDRESS_COMMON + ACPI_ADDRESS16_ATTRIBUTE Address; + ACPI_RESOURCE_SOURCE ResourceSource; + +} ACPI_RESOURCE_ADDRESS16; + +typedef struct acpi_resource_address32 +{ + ACPI_RESOURCE_ADDRESS_COMMON + ACPI_ADDRESS32_ATTRIBUTE Address; + ACPI_RESOURCE_SOURCE ResourceSource; + +} ACPI_RESOURCE_ADDRESS32; + +typedef struct acpi_resource_address64 +{ + ACPI_RESOURCE_ADDRESS_COMMON + ACPI_ADDRESS64_ATTRIBUTE Address; + ACPI_RESOURCE_SOURCE ResourceSource; + +} ACPI_RESOURCE_ADDRESS64; + +typedef struct acpi_resource_extended_address64 +{ + ACPI_RESOURCE_ADDRESS_COMMON + UINT8 RevisionID; + ACPI_ADDRESS64_ATTRIBUTE Address; + UINT64 TypeSpecific; + +} ACPI_RESOURCE_EXTENDED_ADDRESS64; + +typedef struct acpi_resource_extended_irq +{ + UINT8 ProducerConsumer; + UINT8 Triggering; + UINT8 Polarity; + UINT8 Shareable; + UINT8 WakeCapable; + UINT8 InterruptCount; + ACPI_RESOURCE_SOURCE ResourceSource; + union { + UINT32 Interrupt; + ACPI_FLEX_ARRAY(UINT32, Interrupts); + }; + +} 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 Shareable; /* For values, see Interrupt Attributes above */ + UINT8 WakeCapable; /* 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, UART, CSI2 serial descriptors */ + +#define ACPI_RESOURCE_SERIAL_COMMON \ + UINT8 RevisionId; \ + UINT8 Type; \ + UINT8 ProducerConsumer; /* For values, see Producer/Consumer above */\ + UINT8 SlaveMode; \ + UINT8 ConnectionSharing; \ + 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 +#define ACPI_RESOURCE_SERIAL_TYPE_CSI2 4 + +/* 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; + UINT8 Lvr; + +} 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) + +typedef struct acpi_resource_csi2_serialbus +{ + ACPI_RESOURCE_SERIAL_COMMON + UINT8 LocalPortInstance; + UINT8 PhyType; + +} ACPI_RESOURCE_CSI2_SERIALBUS; + +typedef struct acpi_resource_pin_function +{ + UINT8 RevisionId; + UINT8 PinConfig; + UINT8 Shareable; /* For values, see Interrupt Attributes above */ + UINT16 FunctionNumber; + UINT16 PinTableLength; + UINT16 VendorLength; + ACPI_RESOURCE_SOURCE ResourceSource; + UINT16 *PinTable; + UINT8 *VendorData; + +} ACPI_RESOURCE_PIN_FUNCTION; + +typedef struct acpi_resource_pin_config +{ + UINT8 RevisionId; + UINT8 ProducerConsumer; /* For values, see Producer/Consumer above */ + UINT8 Shareable; /* For values, see Interrupt Attributes above */ + UINT8 PinConfigType; + UINT32 PinConfigValue; + UINT16 PinTableLength; + UINT16 VendorLength; + ACPI_RESOURCE_SOURCE ResourceSource; + UINT16 *PinTable; + UINT8 *VendorData; + +} ACPI_RESOURCE_PIN_CONFIG; + +typedef struct acpi_resource_clock_input +{ + UINT8 RevisionId; + UINT8 Mode; + UINT8 Scale; + UINT16 FrequencyDivisor; + UINT32 FrequencyNumerator; + ACPI_RESOURCE_SOURCE ResourceSource; +} ACPI_RESOURCE_CLOCK_INPUT; + +/* Values for PinConfigType field above */ + +#define ACPI_PIN_CONFIG_DEFAULT 0 +#define ACPI_PIN_CONFIG_BIAS_PULL_UP 1 +#define ACPI_PIN_CONFIG_BIAS_PULL_DOWN 2 +#define ACPI_PIN_CONFIG_BIAS_DEFAULT 3 +#define ACPI_PIN_CONFIG_BIAS_DISABLE 4 +#define ACPI_PIN_CONFIG_BIAS_HIGH_IMPEDANCE 5 +#define ACPI_PIN_CONFIG_BIAS_BUS_HOLD 6 +#define ACPI_PIN_CONFIG_DRIVE_OPEN_DRAIN 7 +#define ACPI_PIN_CONFIG_DRIVE_OPEN_SOURCE 8 +#define ACPI_PIN_CONFIG_DRIVE_PUSH_PULL 9 +#define ACPI_PIN_CONFIG_DRIVE_STRENGTH 10 +#define ACPI_PIN_CONFIG_SLEW_RATE 11 +#define ACPI_PIN_CONFIG_INPUT_DEBOUNCE 12 +#define ACPI_PIN_CONFIG_INPUT_SCHMITT_TRIGGER 13 + +typedef struct acpi_resource_pin_group +{ + UINT8 RevisionId; + UINT8 ProducerConsumer; /* For values, see Producer/Consumer above */ + UINT16 PinTableLength; + UINT16 VendorLength; + UINT16 *PinTable; + ACPI_RESOURCE_LABEL ResourceLabel; + UINT8 *VendorData; + +} ACPI_RESOURCE_PIN_GROUP; + +typedef struct acpi_resource_pin_group_function +{ + UINT8 RevisionId; + UINT8 ProducerConsumer; /* For values, see Producer/Consumer above */ + UINT8 Shareable; /* For values, see Interrupt Attributes above */ + UINT16 FunctionNumber; + UINT16 VendorLength; + ACPI_RESOURCE_SOURCE ResourceSource; + ACPI_RESOURCE_LABEL ResourceSourceLabel; + UINT8 *VendorData; + +} ACPI_RESOURCE_PIN_GROUP_FUNCTION; + +typedef struct acpi_resource_pin_group_config +{ + UINT8 RevisionId; + UINT8 ProducerConsumer; /* For values, see Producer/Consumer above */ + UINT8 Shareable; /* For values, see Interrupt Attributes above */ + UINT8 PinConfigType; /* For values, see PinConfigType above */ + UINT32 PinConfigValue; + UINT16 VendorLength; + ACPI_RESOURCE_SOURCE ResourceSource; + ACPI_RESOURCE_LABEL ResourceSourceLabel; + UINT8 *VendorData; + +} ACPI_RESOURCE_PIN_GROUP_CONFIG; + +/* 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_PIN_FUNCTION 20 /* ACPI 6.2 */ +#define ACPI_RESOURCE_TYPE_PIN_CONFIG 21 /* ACPI 6.2 */ +#define ACPI_RESOURCE_TYPE_PIN_GROUP 22 /* ACPI 6.2 */ +#define ACPI_RESOURCE_TYPE_PIN_GROUP_FUNCTION 23 /* ACPI 6.2 */ +#define ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG 24 /* ACPI 6.2 */ +#define ACPI_RESOURCE_TYPE_CLOCK_INPUT 25 /* ACPI 6.5 */ +#define ACPI_RESOURCE_TYPE_MAX 25 + +/* 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_CSI2_SERIALBUS Csi2SerialBus; + ACPI_RESOURCE_COMMON_SERIALBUS CommonSerialBus; + ACPI_RESOURCE_PIN_FUNCTION PinFunction; + ACPI_RESOURCE_PIN_CONFIG PinConfig; + ACPI_RESOURCE_PIN_GROUP PinGroup; + ACPI_RESOURCE_PIN_GROUP_FUNCTION PinGroupFunction; + ACPI_RESOURCE_PIN_GROUP_CONFIG PinGroupConfig; + ACPI_RESOURCE_CLOCK_INPUT ClockInput; + + /* 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)) + +/* Macro for walking resource templates with multiple descriptors */ + +#define ACPI_NEXT_RESOURCE(Res) \ + ACPI_ADD_PTR (ACPI_RESOURCE, (Res), (Res)->Length) + + +typedef struct acpi_pci_routing_table +{ + UINT32 Length; + UINT32 Pin; + UINT64 Address; /* here for 64-bit alignment */ + UINT32 SourceIndex; + union { + char Pad[4]; /* pad to 64 bits so sizeof() works in all cases */ + ACPI_FLEX_ARRAY(char, Source); + }; +} ACPI_PCI_ROUTING_TABLE; + +#endif /* __ACRESTYP_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acstruct.h b/code/drivers/platform/acpi/third_party/acpica/include/acstruct.h new file mode 100644 index 0000000..3dc3f50 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acstruct.h @@ -0,0 +1,255 @@ +/****************************************************************************** + * + * Name: acstruct.h - Internal structs + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 + + +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 */ + BOOLEAN NamespaceOverride; /* Override existing objects */ + UINT8 ResultSize; /* Total elements for the result stack */ + UINT8 ResultCount; /* Current number of occupied elements of result stack */ + UINT8 *Aml; + 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 */ + UINT16 MethodNestingDepth; + UINT8 MethodIsNested; + + 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 */ + char *MethodPathname; /* Full pathname of running 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 SerialMethodCount; + UINT32 NonSerialMethodCount; + UINT32 SerializedMethodCount; + 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 information and parameters. + * Purpose is to reduce CPU stack use. + */ +typedef struct acpi_evaluate_info +{ + /* The first 3 elements are passed by the caller to AcpiNsEvaluate */ + + ACPI_NAMESPACE_NODE *PrefixNode; /* Input: starting node */ + const char *RelativePathname; /* Input: path relative to PrefixNode */ + ACPI_OPERAND_OBJECT **Parameters; /* Input: argument list */ + + ACPI_NAMESPACE_NODE *Node; /* Resolved node (PrefixNode:RelativePathname) */ + ACPI_OPERAND_OBJECT *ObjDesc; /* Object attached to the resolved node */ + char *FullPathname; /* Full pathname of the resolved node */ + + const ACPI_PREDEFINED_INFO *Predefined; /* Used if Node is a predefined name */ + ACPI_OPERAND_OBJECT *ReturnObject; /* Object returned from the evaluation */ + union acpi_operand_object *ParentPackage; /* Used if return object is a Package */ + + UINT32 ReturnFlags; /* Used for return value analysis */ + UINT32 ReturnBtype; /* Bitmapped type of the returned object */ + UINT16 ParamCount; /* Count of the input argument list */ + UINT16 NodeFlags; /* Same as Node->Flags */ + UINT8 PassNumber; /* Parser pass number */ + UINT8 ReturnObjectType; /* Object type of the returned object */ + UINT8 Flags; /* General flags */ + +} ACPI_EVALUATE_INFO; + +/* Values for Flags above */ + +#define ACPI_IGNORE_RETURN_VALUE 1 + +/* Defines for ReturnFlags field above */ + +#define ACPI_OBJECT_REPAIRED 1 +#define ACPI_OBJECT_WRAPPED 2 + + +/* 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; + + +/* Info used by Acpi AcpiDbDisplayFields */ + +typedef struct acpi_region_walk_info +{ + UINT32 DebugLevel; + UINT32 Count; + ACPI_OWNER_ID OwnerId; + UINT8 DisplayType; + UINT32 AddressSpaceId; + +} ACPI_REGION_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/code/drivers/platform/acpi/third_party/acpica/include/actables.h b/code/drivers/platform/acpi/third_party/acpica/include/actables.h new file mode 100644 index 0000000..98c8468 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/actables.h @@ -0,0 +1,245 @@ +/****************************************************************************** + * + * Name: actables.h - ACPI table management + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACTABLES_H__ +#define __ACTABLES_H__ + + +ACPI_STATUS +AcpiAllocateRootTable ( + UINT32 InitialTableCount); + +/* + * tbxfroot - Root pointer utilities + */ +UINT32 +AcpiTbGetRsdpLength ( + ACPI_TABLE_RSDP *Rsdp); + +ACPI_STATUS +AcpiTbValidateRsdp ( + ACPI_TABLE_RSDP *Rsdp); + +UINT8 * +AcpiTbScanMemoryForRsdp ( + UINT8 *StartAddress, + UINT32 Length); + + +/* + * tbdata - table data structure management + */ +ACPI_STATUS +AcpiTbGetNextTableDescriptor ( + UINT32 *TableIndex, + ACPI_TABLE_DESC **TableDesc); + +void +AcpiTbInitTableDescriptor ( + ACPI_TABLE_DESC *TableDesc, + ACPI_PHYSICAL_ADDRESS Address, + UINT8 Flags, + ACPI_TABLE_HEADER *Table); + +ACPI_STATUS +AcpiTbAcquireTempTable ( + ACPI_TABLE_DESC *TableDesc, + ACPI_PHYSICAL_ADDRESS Address, + UINT8 Flags, + ACPI_TABLE_HEADER *Table); + +void +AcpiTbReleaseTempTable ( + ACPI_TABLE_DESC *TableDesc); + +ACPI_STATUS +AcpiTbValidateTempTable ( + ACPI_TABLE_DESC *TableDesc); + +ACPI_STATUS +AcpiTbVerifyTempTable ( + ACPI_TABLE_DESC *TableDesc, + char *Signature, + UINT32 *TableIndex); + +BOOLEAN +AcpiTbIsTableLoaded ( + UINT32 TableIndex); + +void +AcpiTbSetTableLoadedFlag ( + UINT32 TableIndex, + BOOLEAN IsLoaded); + + +/* + * tbfadt - FADT parse/convert/validate + */ +void +AcpiTbParseFadt ( + void); + +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 +AcpiTbValidateTable ( + ACPI_TABLE_DESC *TableDesc); + +void +AcpiTbInvalidateTable ( + ACPI_TABLE_DESC *TableDesc); + +void +AcpiTbOverrideTable ( + ACPI_TABLE_DESC *OldTableDesc); + +ACPI_STATUS +AcpiTbAcquireTable ( + ACPI_TABLE_DESC *TableDesc, + ACPI_TABLE_HEADER **TablePtr, + UINT32 *TableLength, + UINT8 *TableFlags); + +void +AcpiTbReleaseTable ( + ACPI_TABLE_HEADER *Table, + UINT32 TableLength, + UINT8 TableFlags); + +ACPI_STATUS +AcpiTbInstallStandardTable ( + ACPI_PHYSICAL_ADDRESS Address, + UINT8 Flags, + ACPI_TABLE_HEADER *Table, + BOOLEAN Reload, + BOOLEAN Override, + UINT32 *TableIndex); + +void +AcpiTbUninstallTable ( + ACPI_TABLE_DESC *TableDesc); + +ACPI_STATUS +AcpiTbLoadTable ( + UINT32 TableIndex, + ACPI_NAMESPACE_NODE *ParentNode); + +ACPI_STATUS +AcpiTbInstallAndLoadTable ( + ACPI_PHYSICAL_ADDRESS Address, + UINT8 Flags, + ACPI_TABLE_HEADER *Table, + BOOLEAN Override, + UINT32 *TableIndex); + +ACPI_STATUS +AcpiTbUnloadTable ( + UINT32 TableIndex); + +void +AcpiTbNotifyTable ( + UINT32 Event, + void *Table); + +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); + + +/* + * tbutils - table manager utilities + */ +ACPI_STATUS +AcpiTbInitializeFacs ( + void); + +void +AcpiTbPrintTableHeader( + ACPI_PHYSICAL_ADDRESS Address, + ACPI_TABLE_HEADER *Header); + +void +AcpiTbCheckDsdtHeader ( + void); + +ACPI_TABLE_HEADER * +AcpiTbCopyDsdt ( + UINT32 TableIndex); + +void +AcpiTbInstallTableWithOverride ( + ACPI_TABLE_DESC *NewTableDesc, + BOOLEAN Override, + UINT32 *TableIndex); + +ACPI_STATUS +AcpiTbParseRootTable ( + ACPI_PHYSICAL_ADDRESS RsdpAddress); + +ACPI_STATUS +AcpiTbGetTable ( + ACPI_TABLE_DESC *TableDesc, + ACPI_TABLE_HEADER **OutTable); + +void +AcpiTbPutTable ( + ACPI_TABLE_DESC *TableDesc); + + +/* + * tbxfload + */ +ACPI_STATUS +AcpiTbLoadNamespace ( + void); + +#endif /* __ACTABLES_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/actbinfo.h b/code/drivers/platform/acpi/third_party/acpica/include/actbinfo.h new file mode 100644 index 0000000..6e2db40 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/actbinfo.h @@ -0,0 +1,449 @@ +/****************************************************************************** + * + * Module Name: actbinfo - Table disassembly info for non-AML tables + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +/* + * Macros used to generate offsets to specific table fields + */ +#define ACPI_AGDI_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_AGDI,f) +#define ACPI_ASPT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_ASPT,f) +#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_BDAT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_BDAT,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_CCEL_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_CCEL,f) +#define ACPI_CPEP_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_CPEP,f) +#define ACPI_DBG2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_DBG2,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_DTPR_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_DTPR,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_ERDT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_ERDT,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_HMAT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_HMAT,f) +#define ACPI_IORT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_IORT,f) +#define ACPI_IOVT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_IOVT,f) +#define ACPI_IVRS_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_IVRS,f) +#define ACPI_KEYP_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_KEYP,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_MISC_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_MISC,f) +#define ACPI_MPST_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_MPST,f) +#define ACPI_MRRM_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_MRRM,f) +#define ACPI_MSCT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_MSCT,f) +#define ACPI_NFIT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_NFIT,f) +#define ACPI_PCCT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_PCCT,f) +#define ACPI_PDTT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_PDTT,f) +#define ACPI_PMTT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_PMTT,f) +#define ACPI_RASF_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_RASF,f) +#define ACPI_RAS2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_RAS2,f) +#define ACPI_RGRT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_RGRT,f) +#define ACPI_RHCT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_RHCT,f) +#define ACPI_RIMT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_RIMT,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_SDEI_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_SDEI,f) +#define ACPI_SDEV_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_SDEV,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_STAO_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_STAO,f) +#define ACPI_SVKL_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_SVKL,f) +#define ACPI_TCPA_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TCPA_HDR,f) +#define ACPI_TDEL_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TDEL,f) +#define ACPI_TPM2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TPM2,f) +#define ACPI_TPM23_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TPM23,f) +#define ACPI_UBRT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_UBRT,f) +#define ACPI_UEFI_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_UEFI,f) +#define ACPI_VIOT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_VIOT,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) +#define ACPI_WPBT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_WPBT,f) +#define ACPI_WPBT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_WPBT_UNICODE,f) +#define ACPI_WSMT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_WSMT,f) +#define ACPI_XENV_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_XENV,f) + +/* Subtables */ + +#define ACPI_AESTH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_HEADER,f) +#define ACPI_AEST0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_PROCESSOR,f) +#define ACPI_AEST0A_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_PROCESSOR_CACHE,f) +#define ACPI_AEST0B_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_PROCESSOR_TLB,f) +#define ACPI_AEST0C_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_PROCESSOR_GENERIC,f) +#define ACPI_AEST1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_MEMORY,f) +#define ACPI_AEST2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_SMMU,f) +#define ACPI_AEST3_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_VENDOR,f) +#define ACPI_AEST3A_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_VENDOR_V2,f) +#define ACPI_AEST4_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_GIC,f) +#define ACPI_AEST5_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_PCIE,f) +#define ACPI_AEST6_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_PROXY,f) +#define ACPI_AEST0D_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_NODE_INTERFACE,f) +#define ACPI_AEST0DH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_NODE_INTERFACE_HEADER,f) +#define ACPI_AEST0D4_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_NODE_INTERFACE_4K,f) +#define ACPI_AEST0D16_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_NODE_INTERFACE_16K,f) +#define ACPI_AEST0D64_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_NODE_INTERFACE_64K,f) +#define ACPI_AEST0E_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_NODE_INTERRUPT,f) +#define ACPI_AEST0EA_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_AEST_NODE_INTERRUPT_V2,f) +#define ACPI_APMTN_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_APMT_NODE,f) +#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_ASPTH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ASPT_HEADER,f) +#define ACPI_ASPT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ASPT_GLOBAL_REGS,f) +#define ACPI_ASPT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ASPT_SEV_MBOX_REGS,f) +#define ACPI_ASPT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ASPT_ACPI_MBOX_REGS,f) +#define ACPI_CDAT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_CDAT,f) +#define ACPI_CDATH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CDAT_HEADER,f) +#define ACPI_CDAT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CDAT_DSMAS,f) +#define ACPI_CDAT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CDAT_DSLBIS,f) +#define ACPI_CDAT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CDAT_DSMSCIS,f) +#define ACPI_CDAT3_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CDAT_DSIS,f) +#define ACPI_CDAT4_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CDAT_DSEMTS,f) +#define ACPI_CDAT5_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CDAT_SSLBIS,f) +#define ACPI_CDATE_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CDAT_SSLBE,f) +#define ACPI_CEDT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CEDT_HEADER, f) +#define ACPI_CEDT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CEDT_CHBS, f) +#define ACPI_CEDT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CEDT_CFMWS, f) +#define ACPI_CEDT1_TE_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CEDT_CFMWS_TARGET_ELEMENT, f) +#define ACPI_CEDT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CEDT_CXIMS, f) +#define ACPI_CEDT2_TE_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CEDT_CXIMS_TARGET_ELEMENT, f) +#define ACPI_CEDT3_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CEDT_RDPAS, f) +#define ACPI_CPEP0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CPEP_POLLING,f) +#define ACPI_CSRT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CSRT_GROUP,f) +#define ACPI_CSRT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CSRT_SHARED_INFO,f) +#define ACPI_CSRT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_CSRT_DESCRIPTOR,f) +#define ACPI_DBG20_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DBG2_DEVICE,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_DMAR4_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DMAR_ANDD,f) +#define ACPI_DMAR5_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DMAR_SATC,f) +#define ACPI_DMAR6_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DMAR_SIDP,f) +#define ACPI_DRTM0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DRTM_VTABLE_LIST,f) +#define ACPI_DRTM1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DRTM_RESOURCE_LIST,f) +#define ACPI_DRTM1a_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DRTM_RESOURCE,f) +#define ACPI_DRTM2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_DRTM_DPS_ID,f) +#define ACPI_DTPR_INST_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TPR_INSTANCE,f) +#define ACPI_DTPR_ARR_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TPR_ARRAY,f) +#define ACPI_DTPR_AUX_SR_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TPR_AUX_SR,f) +#define ACPI_DTPR_SR_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TPR_SERIALIZE_REQUEST,f) +#define ACPI_EINJ0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_WHEA_HEADER,f) +#define ACPI_ERDT_HDR_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SUBTBL_HDR_16,f) +#define ACPI_ERDT_CACD_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ERDT_CACD,f) +#define ACPI_ERDT_CARC_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ERDT_CARC,f) +#define ACPI_ERDT_CARD_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ERDT_CARD,f) +#define ACPI_ERDT_CMRC_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ERDT_CMRC,f) +#define ACPI_ERDT_CMRD_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ERDT_CMRD,f) +#define ACPI_ERDT_DACD_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ERDT_DACD,f) +#define ACPI_ERDT_DACD_PATH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ERDT_DACD_PATHS,f) +#define ACPI_ERDT_IBAD_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ERDT_IBAD,f) +#define ACPI_ERDT_IBRD_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ERDT_IBRD,f) +#define ACPI_ERDT_MARC_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ERDT_MARC,f) +#define ACPI_ERDT_MMRC_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ERDT_MMRC,f) +#define ACPI_ERDT_RMDD_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_ERDT_RMDD,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_POINTER,f) +#define ACPI_FPDT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_FPDT_S3PT_POINTER,f) +#define ACPI_GTDT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_GTDT_TIMER_BLOCK,f) +#define ACPI_GTDT0a_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_GTDT_TIMER_ENTRY,f) +#define ACPI_GTDT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_GTDT_WATCHDOG,f) +#define ACPI_GTDTH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_GTDT_HEADER,f) +#define ACPI_GTDT_EL2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_GTDT_EL2,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_HEST10_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_HEST_GENERIC_V2,f) +#define ACPI_HEST11_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_HEST_IA_DEFERRED_CHECK,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_HMAT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_HMAT_PROXIMITY_DOMAIN,f) +#define ACPI_HMAT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_HMAT_LOCALITY,f) +#define ACPI_HMAT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_HMAT_CACHE,f) +#define ACPI_HMATH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_HMAT_STRUCTURE,f) +#define ACPI_IORT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IORT_ITS_GROUP,f) +#define ACPI_IORT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IORT_NAMED_COMPONENT,f) +#define ACPI_IORT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IORT_ROOT_COMPLEX,f) +#define ACPI_IORT3_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IORT_SMMU,f) +#define ACPI_IORT3A_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IORT_SMMU_GSI,f) +#define ACPI_IORT4_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IORT_SMMU_V3,f) +#define ACPI_IORT5_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IORT_PMCG,f) +#define ACPI_IORT6_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IORT_RMR,f) +#define ACPI_IORT6A_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IORT_RMR_DESC,f) +#define ACPI_IORT7_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IORT_IWB,f) +#define ACPI_IORTA_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IORT_MEMORY_ACCESS,f) +#define ACPI_IORTH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IORT_NODE,f) +#define ACPI_IORTM_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IORT_ID_MAPPING,f) +#define ACPI_IOVTH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IOVT_HEADER,f) +#define ACPI_IOVT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IOVT_IOMMU,f) +#define ACPI_IOVTDEV_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IOVT_DEVICE_ENTRY,f) +#define ACPI_IVRSH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IVRS_HEADER,f) +#define ACPI_IVRS0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IVRS_HARDWARE1,f) +#define ACPI_IVRS01_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IVRS_HARDWARE2,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_IVRSHID_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_IVRS_DEVICE_HID,f) +#define ACPI_KEYPH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_KEYP_COMMON_HEADER,f) +#define ACPI_KEYP0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_KEYP_CONFIG_UNIT,f) +#define ACPI_KEYP0A_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_KEYP_RP_INFO,f) +#define ACPI_LPITH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_LPIT_HEADER,f) +#define ACPI_LPIT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_LPIT_NATIVE,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_MADT13_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_GENERIC_MSI_FRAME,f) +#define ACPI_MADT14_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_GENERIC_REDISTRIBUTOR,f) +#define ACPI_MADT15_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_GENERIC_TRANSLATOR,f) +#define ACPI_MADT16_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_MULTIPROC_WAKEUP,f) +#define ACPI_MADT17_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_CORE_PIC,f) +#define ACPI_MADT18_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_LIO_PIC,f) +#define ACPI_MADT19_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_HT_PIC,f) +#define ACPI_MADT20_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_EIO_PIC,f) +#define ACPI_MADT21_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_MSI_PIC,f) +#define ACPI_MADT22_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_BIO_PIC,f) +#define ACPI_MADT23_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_LPC_PIC,f) +#define ACPI_MADT24_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_RINTC,f) +#define ACPI_MADT25_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_IMSIC,f) +#define ACPI_MADT26_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_APLIC,f) +#define ACPI_MADT27_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_PLIC,f) +#define ACPI_MADT28_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_GICV5_IRS,f) +#define ACPI_MADT29_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_GICv5_ITS,f) +#define ACPI_MADT30_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_GICv5_ITS_TRANSLATE,f) +#define ACPI_MADT128_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MADT_OEM_DATA,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_MISC0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MISC_GUID_ENTRY,f) +#define ACPI_MPAM0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MPAM_MSC_NODE,f) +#define ACPI_MPAM1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MPAM_RESOURCE_NODE,f) +#define ACPI_MPAM1A_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MPAM_RESOURCE_CACHE_LOCATOR,f) +#define ACPI_MPAM1B_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MPAM_RESOURCE_MEMORY_LOCATOR,f) +#define ACPI_MPAM1C_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MPAM_RESOURCE_SMMU_INTERFACE,f) +#define ACPI_MPAM1D_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MPAM_RESOURCE_MEMCACHE_INTERFACE,f) +#define ACPI_MPAM1E_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MPAM_RESOURCE_ACPI_INTERFACE,f) +#define ACPI_MPAM1F_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MPAM_RESOURCE_INTERCONNECT_INTERFACE,f) +#define ACPI_MPAM1G_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MPAM_RESOURCE_GENERIC_LOCATOR,f) +#define ACPI_MPAM2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MPAM_FUNC_DEPS,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_MRRM0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MRRM_MEM_RANGE_ENTRY,f) +#define ACPI_MSCT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_MSCT_PROXIMITY,f) +#define ACPI_NFITH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_NFIT_HEADER,f) +#define ACPI_NFIT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_NFIT_SYSTEM_ADDRESS,f) +#define ACPI_NFIT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_NFIT_MEMORY_MAP,f) +#define ACPI_NFIT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_NFIT_INTERLEAVE,f) +#define ACPI_NFIT3_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_NFIT_SMBIOS,f) +#define ACPI_NFIT4_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_NFIT_CONTROL_REGION,f) +#define ACPI_NFIT5_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_NFIT_DATA_REGION,f) +#define ACPI_NFIT6_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_NFIT_FLUSH_ADDRESS,f) +#define ACPI_NFIT7_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_NFIT_CAPABILITIES,f) +#define ACPI_PCCT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PCCT_SUBSPACE,f) +#define ACPI_PCCT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PCCT_HW_REDUCED,f) +#define ACPI_PCCT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PCCT_HW_REDUCED_TYPE2,f) +#define ACPI_PCCT3_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PCCT_EXT_PCC_MASTER,f) +#define ACPI_PCCT4_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PCCT_EXT_PCC_SLAVE,f) +#define ACPI_PCCT5_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PCCT_HW_REG,f) +#define ACPI_PDTT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PDTT_CHANNEL,f) +#define ACPI_PHATH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PHAT_HEADER,f) +#define ACPI_PHAT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PHAT_VERSION_DATA,f) +#define ACPI_PHAT0A_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PHAT_VERSION_ELEMENT,f) +#define ACPI_PHAT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PHAT_HEALTH_DATA,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_PMTT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PMTT_PHYSICAL_COMPONENT,f) +#define ACPI_PMTT_VENDOR_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PMTT_VENDOR_SPECIFIC,f) +#define ACPI_PMTTH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PMTT_HEADER,f) +#define ACPI_PPTTH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SUBTABLE_HEADER,f) +#define ACPI_PPTT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PPTT_PROCESSOR,f) +#define ACPI_PPTT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PPTT_CACHE,f) +#define ACPI_PPTT1A_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PPTT_CACHE_V1,f) +#define ACPI_PPTT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PPTT_ID,f) +#define ACPI_PRMTH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_PRMT_HEADER,f) +#define ACPI_PRMT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PRMT_MODULE_INFO,f) +#define ACPI_PRMT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_PRMT_HANDLER_INFO,f) +#define ACPI_RAS2_PCC_DESC_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_RAS2_PCC_DESC,f) +#define ACPI_RHCTH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_RHCT_NODE_HEADER,f) +#define ACPI_RHCT0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_RHCT_ISA_STRING,f) +#define ACPI_RHCT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_RHCT_CMO_NODE,f) +#define ACPI_RHCT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_RHCT_MMU_NODE,f) +#define ACPI_RHCTFFFF_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_RHCT_HART_INFO,f) +#define ACPI_RIMTH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_RIMT_NODE,f) +#define ACPI_RIMTI_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_RIMT_IOMMU,f) +#define ACPI_RIMTW_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_RIMT_IOMMU_WIRE_GSI,f) +#define ACPI_RIMTP_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_RIMT_PCIE_RC,f) +#define ACPI_RIMTM_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_RIMT_ID_MAPPING,f) +#define ACPI_RIMTN_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_RIMT_PLATFORM_DEVICE,f) +#define ACPI_S3PTH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_FPDT_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_SDEVH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SDEV_HEADER,f) +#define ACPI_SDEV0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SDEV_NAMESPACE,f) +#define ACPI_SDEV0B_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SDEV_SECURE_COMPONENT,f) +#define ACPI_SDEVCH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SDEV_HEADER,f) +#define ACPI_SDEVC0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SDEV_ID_COMPONENT, f) +#define ACPI_SDEVC1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SDEV_MEM_COMPONENT, f) +#define ACPI_SDEV1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SDEV_PCIE,f) +#define ACPI_SDEV1A_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SDEV_PCIE_PATH,f) +#define ACPI_SLIC_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_SLIC,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_SRAT3_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SRAT_GICC_AFFINITY,f) +#define ACPI_SRAT4_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SRAT_GIC_ITS_AFFINITY,f) +#define ACPI_SRAT5_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SRAT_GENERIC_AFFINITY,f) +#define ACPI_SRAT7_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SRAT_RINTC_AFFINITY,f) +#define ACPI_SVKL0_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SVKL_KEY,f) +#define ACPI_SWFT_FILE_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_SWFT_FILE,f) +#define ACPI_TCPA_CLIENT_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TCPA_CLIENT,f) +#define ACPI_TCPA_SERVER_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TABLE_TCPA_SERVER,f) +#define ACPI_TPM2A_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TPM2_TRAILER,f) +#define ACPI_TPM211_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TPM2_ARM_SMC,f) +#define ACPI_TPM23A_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_TPM23_TRAILER,f) +#define ACPI_UBRTS_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_UBRT_SUBTABLE,f) +#define ACPI_VIOTH_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_VIOT_HEADER,f) +#define ACPI_VIOT1_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_VIOT_PCI_RANGE,f) +#define ACPI_VIOT2_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_VIOT_MMIO,f) +#define ACPI_VIOT3_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_VIOT_VIRTIO_IOMMU_PCI,f) +#define ACPI_VIOT4_OFFSET(f) (UINT16) ACPI_OFFSET (ACPI_VIOT_VIRTIO_IOMMU_MMIO,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_AEST0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_AEST_PROCESSOR,f,o) +#define ACPI_AEST0D_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_AEST_NODE_INTERFACE,f,o) +#define ACPI_AEST0E_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_AEST_NODE_INTERRUPT,f,o) +#define ACPI_AEST0EA_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_AEST_NODE_INTERRUPT_V2,f,o) +#define ACPI_AGDI_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TABLE_AGDI,f,o) +#define ACPI_APMTN_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_APMT_NODE,f,o) +#define ACPI_BGRT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TABLE_BGRT,f,o) +#define ACPI_DMAR0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_DMAR_HARDWARE_UNIT,f,o) +#define ACPI_DRTM_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TABLE_DRTM,f,o) +#define ACPI_DRTM1a_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_DRTM_RESOURCE,f,o) +#define ACPI_DTPR_BASE_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TPRN_BASE_REG,f,o) +#define ACPI_DTPR_LIM_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TPRN_LIMIT_REG,f,o) +#define ACPI_DTPR_SR_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TPR_SERIALIZE_REQUEST,f,o) +#define ACPI_ERDT_RMDD_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_ERDT_RMDD,f,o) +#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_PPTT0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_PPTT_PROCESSOR,f,o) +#define ACPI_PPTT1_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_PPTT_CACHE,f,o) +#define ACPI_PPTT1A_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_PPTT_CACHE_V1,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_SRAT3_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_SRAT_GICC_AFFINITY,f,o) +#define ACPI_SRAT5_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_SRAT_GENERIC_AFFINITY,f,o) +#define ACPI_SRAT7_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_SRAT_RINTC_AFFINITY,f,o) +#define ACPI_GTDT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TABLE_GTDT,f,o) +#define ACPI_GTDT0a_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_GTDT_TIMER_ENTRY,f,o) +#define ACPI_GTDT1_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_GTDT_WATCHDOG,f,o) +#define ACPI_HMAT0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_HMAT_PROXIMITY_DOMAIN,f,o) +#define ACPI_HMAT1_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_HMAT_LOCALITY,f,o) +#define ACPI_HMAT2_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_HMAT_CACHE,f,o) +#define ACPI_IORT3_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_IORT_SMMU,f,o) +#define ACPI_IORT3a_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_IORT_SMMU_GSI,f,o) +#define ACPI_IORT4_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_IORT_SMMU_V3,f,o) +#define ACPI_IORT6_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_IORT_RMR,f,o) +#define ACPI_IORTA_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_IORT_MEMORY_ACCESS,f,o) +#define ACPI_IORTM_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_IORT_ID_MAPPING,f,o) +#define ACPI_IOVT0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_IOVT_IOMMU,f,o) +#define ACPI_IVRS_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_IVRS_HEADER,f,o) +#define ACPI_IVRSDE_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_IVRS_DE_HEADER,f,o) +#define ACPI_LPITH_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_LPIT_HEADER,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_MADT13_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_MADT_GENERIC_MSI_FRAME,f,o) +#define ACPI_MADT14_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_MADT_GENERIC_REDISTRIBUTOR,f,o) +#define ACPI_MADT15_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_MADT_GENERIC_TRANSLATOR,f,o) +#define ACPI_MADT28_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_MADT_GICV5_IRS,f,o) +#define ACPI_MADT29_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_MADT_GICv5_ITS,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_NFIT0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_NFIT_SYSTEM_ADDRESS,f,o) +#define ACPI_NFIT1_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_NFIT_MEMORY_MAP,f,o) +#define ACPI_NFIT4_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_NFIT_CONTROL_REGION,f,o) +#define ACPI_NFIT7_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_NFIT_CAPABILITIES,f,o) +#define ACPI_PCCT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TABLE_PCCT,f,o) +#define ACPI_PCCT1_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_PCCT_HW_REDUCED,f,o) +#define ACPI_PCCT2_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_PCCT_HW_REDUCED_TYPE2,f,o) +#define ACPI_PCCT3_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_PCCT_EXT_PCC_MASTER,f,o) +#define ACPI_PCCT4_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_PCCT_EXT_PCC_SLAVE,f,o) +#define ACPI_PDTT0_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_PDTT_CHANNEL,f,o) +#define ACPI_PMTTH_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_PMTT_HEADER,f,o) +#define ACPI_SDEVH_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_SDEV_HEADER,f,o) +#define ACPI_WDDT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TABLE_WDDT,f,o) +#define ACPI_WSMT_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_TABLE_WSMT,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) +#define ACPI_HEST11_FLAG_OFFSET(f,o) ACPI_FLAG_OFFSET (ACPI_HEST_IA_DEFERRED_CHECK,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} diff --git a/code/drivers/platform/acpi/third_party/acpica/include/actbl.h b/code/drivers/platform/acpi/third_party/acpica/include/actbl.h new file mode 100644 index 0000000..8eee178 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/actbl.h @@ -0,0 +1,441 @@ +/****************************************************************************** + * + * Name: actbl.h - Basic ACPI Table Definitions + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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_OSDT "OSDT" /* Override System Description Table */ +#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 */ +#define ACPI_OEM_NAME "OEM" /* Short name for OEM, 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: C bitfields are not used for this reason: + * + * "Bitfields are great and easy to read, but unfortunately the C language + * does not specify the layout of bitfields in memory, which means they are + * essentially useless for dealing with packed data in on-disk formats or + * binary wire protocols." (Or ACPI tables and buffers.) "If you ask me, + * this decision was a design error in C. Ritchie could have picked an order + * and stuck with it." Norman Ramsey. + * See http://stackoverflow.com/a/1053662/41661 + */ + + +/******************************************************************************* + * + * 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_NAMESEG_SIZE] ACPI_NONSTRING; /* ASCII table signature */ + UINT32 Length; /* Length of table in bytes, including this header */ + UINT8 Revision; /* ACPI Specification minor version number */ + UINT8 Checksum; /* To make sum of entire table == 0 */ + char OemId[ACPI_OEM_ID_SIZE] ACPI_NONSTRING; /* ASCII OEM identification */ + char OemTableId[ACPI_OEM_TABLE_ID_SIZE] ACPI_NONSTRING; /* ASCII OEM table identification */ + UINT32 OemRevision; /* OEM revision number */ + char AslCompilerId[ACPI_NAMESEG_SIZE] ACPI_NONSTRING; /* 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 misaligned 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; + +#define ACPI_RSDT_ENTRY_SIZE (sizeof (UINT32)) +#define ACPI_XSDT_ENTRY_SIZE (sizeof (UINT64)) + + +/******************************************************************************* + * + * 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 6 + * + ******************************************************************************/ + +/* 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 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 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 */ + UINT16 ArmBootFlags; /* ARM-Specific Boot Flags (see below for individual flags) (ACPI 5.1) */ + UINT8 MinorRevision; /* FADT Minor Revision (ACPI 5.1) */ + 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 5.0) */ + ACPI_GENERIC_ADDRESS SleepStatus; /* 64-bit Sleep Status register (ACPI 5.0) */ + UINT64 HypervisorId; /* Hypervisor Vendor ID (ACPI 6.0) */ + +} ACPI_TABLE_FADT; + + +/* Masks for FADT IA-PC Boot Architecture Flags (boot_flags) [Vx]=Introduced in this FADT revision */ + +#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 ARM Boot Architecture Flags (arm_boot_flags) ACPI 5.1 */ + +#define ACPI_FADT_PSCI_COMPLIANT (1) /* 00: [V5+] PSCI 0.2+ is implemented */ +#define ACPI_FADT_PSCI_USE_HVC (1<<1) /* 01: [V5+] HVC must be used instead of SMC as the PSCI conduit */ + +/* 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 is 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 (Preferred Power Management Profiles) */ + +enum AcpiPreferredPmProfiles +{ + 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 (fixed in table header) */ + ACPI_NAME_UNION Signature; + ACPI_OWNER_ID OwnerId; + UINT8 Flags; + UINT16 ValidationCount; + +} ACPI_TABLE_DESC; + +/* + * Maximum value of the ValidationCount field in ACPI_TABLE_DESC. + * When reached, ValidationCount cannot be changed any more and the table will + * be permanently regarded as validated. + * + * This is to prevent situations in which unbalanced table get/put operations + * may cause premature table unmapping in the OS to happen. + * + * The maximum validation count can be defined to any value, but should be + * greater than the maximum number of OS early stage mapping slots to avoid + * leaking early stage table mappings to the late stage. + */ +#define ACPI_MAX_TABLE_VALIDATIONS ACPI_UINT16_MAX + +/* Masks for Flags field above */ + +#define ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL (0) /* Virtual address, external maintained */ +#define ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL (1) /* Physical address, internally mapped */ +#define ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL (2) /* Virtual address, internallly allocated */ +#define ACPI_TABLE_ORIGIN_MASK (3) +#define ACPI_TABLE_IS_VERIFIED (4) +#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 + * FADT V6 size: 0x114 + */ +#define ACPI_FADT_V1_SIZE (UINT32) (ACPI_FADT_OFFSET (Flags) + 4) +#define ACPI_FADT_V2_SIZE (UINT32) (ACPI_FADT_OFFSET (MinorRevision) + 1) +#define ACPI_FADT_V3_SIZE (UINT32) (ACPI_FADT_OFFSET (SleepControl)) +#define ACPI_FADT_V5_SIZE (UINT32) (ACPI_FADT_OFFSET (HypervisorId)) +#define ACPI_FADT_V6_SIZE (UINT32) (sizeof (ACPI_TABLE_FADT)) + +#define ACPI_FADT_CONFORMANCE "ACPI 6.1 (FADT version 6)" + +#endif /* __ACTBL_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/actbl1.h b/code/drivers/platform/acpi/third_party/acpica/include/actbl1.h new file mode 100644 index 0000000..c49bbcc --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/actbl1.h @@ -0,0 +1,2637 @@ +/****************************************************************************** + * + * Name: actbl1.h - Additional ACPI table definitions + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACTBL1_H__ +#define __ACTBL1_H__ + + +/******************************************************************************* + * + * Additional ACPI Tables + * + * These tables are not consumed directly by the ACPICA subsystem, but are + * included here to support device drivers and the AML disassembler. + * + ******************************************************************************/ + + +/* + * 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_AEST "AEST" /* Arm Error Source Table */ +#define ACPI_SIG_ASF "ASF!" /* Alert Standard Format table */ +#define ACPI_SIG_ASPT "ASPT" /* AMD Secure Processor Table */ +#define ACPI_SIG_BERT "BERT" /* Boot Error Record Table */ +#define ACPI_SIG_BGRT "BGRT" /* Boot Graphics Resource Table */ +#define ACPI_SIG_BOOT "BOOT" /* Simple Boot Flag Table */ +#define ACPI_SIG_CEDT "CEDT" /* CXL Early Discovery Table */ +#define ACPI_SIG_CPEP "CPEP" /* Corrected Platform Error Polling table */ +#define ACPI_SIG_CSRT "CSRT" /* Core System Resource Table */ +#define ACPI_SIG_DBG2 "DBG2" /* Debug Port table type 2 */ +#define ACPI_SIG_DBGP "DBGP" /* Debug Port table */ +#define ACPI_SIG_DMAR "DMAR" /* DMA Remapping table */ +#define ACPI_SIG_DRTM "DRTM" /* Dynamic Root of Trust for Measurement table */ +#define ACPI_SIG_DTPR "DTPR" /* DMA TXT Protection Ranges 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_FPDT "FPDT" /* Firmware Performance Data Table */ +#define ACPI_SIG_GTDT "GTDT" /* Generic Timer Description Table */ +#define ACPI_SIG_HEST "HEST" /* Hardware Error Source Table */ +#define ACPI_SIG_HMAT "HMAT" /* Heterogeneous Memory Attributes Table */ +#define ACPI_SIG_HPET "HPET" /* High Precision Event Timer table */ +#define ACPI_SIG_IBFT "IBFT" /* iSCSI Boot Firmware Table */ +#define ACPI_SIG_MSCT "MSCT" /* Maximum System Characteristics 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_MATR "MATR" /* Memory Address Translation Table */ +#define ACPI_SIG_MSDM "MSDM" /* Microsoft Data Management Table */ + +/* + * These tables have been seen in the field, but no definition has been found + */ +#ifdef ACPI_UNDEFINED_TABLES +#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: C bitfields are not used for this reason: + * + * "Bitfields are great and easy to read, but unfortunately the C language + * does not specify the layout of bitfields in memory, which means they are + * essentially useless for dealing with packed data in on-disk formats or + * binary wire protocols." (Or ACPI tables and buffers.) "If you ask me, + * this decision was a design error in C. Ritchie could have picked an order + * and stuck with it." Norman Ramsey. + * See http://stackoverflow.com/a/1053662/41661 + */ + + +/******************************************************************************* + * + * 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; + + +/* Larger subtable header (when Length can exceed 255) */ + +typedef struct acpi_subtbl_hdr_16 +{ + UINT16 Type; + UINT16 Length; + +} ACPI_SUBTBL_HDR_16; + + +/******************************************************************************* + * + * 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; + +/******************************************************************************* + * + * ASPT - AMD Secure Processor Table (Signature "ASPT") + * Revision 0x1 + * + * Conforms to AMD Socket SP5/SP6 Platform ASPT Rev1 Specification, + * 12 September 2022 + * + ******************************************************************************/ + +typedef struct acpi_table_aspt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 NumEntries; + +} ACPI_TABLE_ASPT; + + +/* ASPT subtable header */ + +typedef struct acpi_aspt_header +{ + UINT16 Type; + UINT16 Length; + +} ACPI_ASPT_HEADER; + + +/* Values for Type field above */ + +enum AcpiAsptType +{ + ACPI_ASPT_TYPE_GLOBAL_REGS = 0, + ACPI_ASPT_TYPE_SEV_MBOX_REGS = 1, + ACPI_ASPT_TYPE_ACPI_MBOX_REGS = 2, + ACPI_ASPT_TYPE_UNKNOWN = 3, +}; + +/* + * ASPT subtables + */ + +/* 0: ASPT Global Registers */ + +typedef struct acpi_aspt_global_regs +{ + ACPI_ASPT_HEADER Header; + UINT32 Reserved; + UINT64 FeatureRegAddr; + UINT64 IrqEnRegAddr; + UINT64 IrqStRegAddr; + +} ACPI_ASPT_GLOBAL_REGS; + + +/* 1: ASPT SEV Mailbox Registers */ + +typedef struct acpi_aspt_sev_mbox_regs +{ + ACPI_ASPT_HEADER Header; + UINT8 MboxIrqId; + UINT8 Reserved[3]; + UINT64 CmdRespRegAddr; + UINT64 CmdBufLoRegAddr; + UINT64 CmdBufHiRegAddr; + +} ACPI_ASPT_SEV_MBOX_REGS; + + +/* 2: ASPT ACPI Mailbox Registers */ + +typedef struct acpi_aspt_acpi_mbox_regs +{ + ACPI_ASPT_HEADER Header; + UINT32 Reserved1; + UINT64 CmdRespRegAddr; + UINT64 Reserved2[2]; + +} ACPI_ASPT_ACPI_MBOX_REGS; + + +/******************************************************************************* + * + * 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 address 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 + */ + + +/******************************************************************************* + * + * 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; + +/* Flags for Status field above */ + +#define ACPI_BGRT_DISPLAYED (1) +#define ACPI_BGRT_ORIENTATION_OFFSET (3 << 1) + + +/******************************************************************************* + * + * 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; + + +/******************************************************************************* + * + * CDAT - Coherent Device Attribute Table + * Version 1 + * + * Conforms to the "Coherent Device Attribute Table (CDAT) Specification + " (Revision 1.01, October 2020.) + * + ******************************************************************************/ + +typedef struct acpi_table_cdat +{ + UINT32 Length; /* Length of table in bytes, including this header */ + UINT8 Revision; /* ACPI Specification minor version number */ + UINT8 Checksum; /* To make sum of entire table == 0 */ + UINT8 Reserved[6]; + UINT32 Sequence; /* Used to detect runtime CDAT table changes */ + +} ACPI_TABLE_CDAT; + + +/* CDAT common subtable header */ + +typedef struct acpi_cdat_header +{ + UINT8 Type; + UINT8 Reserved; + UINT16 Length; + +} ACPI_CDAT_HEADER; + +/* Values for Type field above */ + +enum AcpiCdatType +{ + ACPI_CDAT_TYPE_DSMAS = 0, + ACPI_CDAT_TYPE_DSLBIS = 1, + ACPI_CDAT_TYPE_DSMSCIS = 2, + ACPI_CDAT_TYPE_DSIS = 3, + ACPI_CDAT_TYPE_DSEMTS = 4, + ACPI_CDAT_TYPE_SSLBIS = 5, + ACPI_CDAT_TYPE_RESERVED = 6 /* 6 through 0xFF are reserved */ +}; + + +/* Subtable 0: Device Scoped Memory Affinity Structure (DSMAS) */ + +typedef struct acpi_cdat_dsmas +{ + UINT8 DsmadHandle; + UINT8 Flags; + UINT16 Reserved; + UINT64 DpaBaseAddress; + UINT64 DpaLength; + +} ACPI_CDAT_DSMAS; + +/* Flags for subtable above */ + +#define ACPI_CDAT_DSMAS_NON_VOLATILE (1 << 2) +#define ACPI_CDAT_DSMAS_SHAREABLE (1 << 3) +#define ACPI_CDAT_DSMAS_READ_ONLY (1 << 6) + + +/* Subtable 1: Device scoped Latency and Bandwidth Information Structure (DSLBIS) */ + +typedef struct acpi_cdat_dslbis +{ + UINT8 Handle; + UINT8 Flags; /* If Handle matches a DSMAS handle, the definition of this field matches + * Flags field in HMAT System Locality Latency */ + UINT8 DataType; + UINT8 Reserved; + UINT64 EntryBaseUnit; + UINT16 Entry[3]; + UINT16 Reserved2; + +} ACPI_CDAT_DSLBIS; + + +/* Subtable 2: Device Scoped Memory Side Cache Information Structure (DSMSCIS) */ + +typedef struct acpi_cdat_dsmscis +{ + UINT8 DsmasHandle; + UINT8 Reserved[3]; + UINT64 SideCacheSize; + UINT32 CacheAttributes; + +} ACPI_CDAT_DSMSCIS; + + +/* Subtable 3: Device Scoped Initiator Structure (DSIS) */ + +typedef struct acpi_cdat_dsis +{ + UINT8 Flags; + UINT8 Handle; + UINT16 Reserved; + +} ACPI_CDAT_DSIS; + +/* Flags for above subtable */ + +#define ACPI_CDAT_DSIS_MEM_ATTACHED (1 << 0) + + +/* Subtable 4: Device Scoped EFI Memory Type Structure (DSEMTS) */ + +typedef struct acpi_cdat_dsemts +{ + UINT8 DsmasHandle; + UINT8 MemoryType; + UINT16 Reserved; + UINT64 DpaOffset; + UINT64 RangeLength; + +} ACPI_CDAT_DSEMTS; + + +/* Subtable 5: Switch Scoped Latency and Bandwidth Information Structure (SSLBIS) */ + +typedef struct acpi_cdat_sslbis +{ + UINT8 DataType; + UINT8 Reserved[3]; + UINT64 EntryBaseUnit; + +} ACPI_CDAT_SSLBIS; + + +/* Sub-subtable for above, SslbeEntries field */ + +typedef struct acpi_cdat_sslbe +{ + UINT16 PortxId; + UINT16 PortyId; + UINT16 LatencyOrBandwidth; + UINT16 Reserved; + +} ACPI_CDAT_SSLBE; + +#define ACPI_CDAT_SSLBIS_US_PORT 0x0100 +#define ACPI_CDAT_SSLBIS_ANY_PORT 0xffff + +/******************************************************************************* + * + * CEDT - CXL Early Discovery Table + * Version 1 + * + * Conforms to the "CXL Early Discovery Table" (CXL 2.0, October 2020) + * + ******************************************************************************/ + +typedef struct acpi_table_cedt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + +} ACPI_TABLE_CEDT; + +/* CEDT subtable header (Performance Record Structure) */ + +typedef struct acpi_cedt_header +{ + UINT8 Type; + UINT8 Reserved; + UINT16 Length; + +} ACPI_CEDT_HEADER; + +/* Values for Type field above */ + +enum AcpiCedtType +{ + ACPI_CEDT_TYPE_CHBS = 0, + ACPI_CEDT_TYPE_CFMWS = 1, + ACPI_CEDT_TYPE_CXIMS = 2, + ACPI_CEDT_TYPE_RDPAS = 3, + ACPI_CEDT_TYPE_RESERVED = 4, +}; + +/* Values for version field above */ + +#define ACPI_CEDT_CHBS_VERSION_CXL11 (0) +#define ACPI_CEDT_CHBS_VERSION_CXL20 (1) + +/* Values for length field above */ + +#define ACPI_CEDT_CHBS_LENGTH_CXL11 (0x2000) +#define ACPI_CEDT_CHBS_LENGTH_CXL20 (0x10000) + +/* + * CEDT subtables + */ + +/* 0: CXL Host Bridge Structure */ + +typedef struct acpi_cedt_chbs +{ + ACPI_CEDT_HEADER Header; + UINT32 Uid; + UINT32 CxlVersion; + UINT32 Reserved; + UINT64 Base; + UINT64 Length; + +} ACPI_CEDT_CHBS; + + +/* 1: CXL Fixed Memory Window Structure */ + +typedef struct acpi_cedt_cfmws +{ + ACPI_CEDT_HEADER Header; + UINT32 Reserved1; + UINT64 BaseHpa; + UINT64 WindowSize; + UINT8 InterleaveWays; + UINT8 InterleaveArithmetic; + UINT16 Reserved2; + UINT32 Granularity; + UINT16 Restrictions; + UINT16 QtgId; + UINT32 InterleaveTargets[]; + +} ACPI_CEDT_CFMWS; + +typedef struct acpi_cedt_cfmws_target_element +{ + UINT32 InterleaveTarget; + +} ACPI_CEDT_CFMWS_TARGET_ELEMENT; + +/* Values for Interleave Arithmetic field above */ + +#define ACPI_CEDT_CFMWS_ARITHMETIC_MODULO (0) +#define ACPI_CEDT_CFMWS_ARITHMETIC_XOR (1) + +/* Values for Restrictions field above */ + +#define ACPI_CEDT_CFMWS_RESTRICT_DEVMEM (1) +#define ACPI_CEDT_CFMWS_RESTRICT_HOSTONLYMEM (1<<1) +#define ACPI_CEDT_CFMWS_RESTRICT_VOLATILE (1<<2) +#define ACPI_CEDT_CFMWS_RESTRICT_PMEM (1<<3) +#define ACPI_CEDT_CFMWS_RESTRICT_FIXED (1<<4) +#define ACPI_CEDT_CFMWS_RESTRICT_BI (1<<5) + +/* 2: CXL XOR Interleave Math Structure */ + +typedef struct acpi_cedt_cxims { + ACPI_CEDT_HEADER Header; + UINT16 Reserved1; + UINT8 Hbig; + UINT8 NrXormaps; + UINT64 XormapList[]; +} ACPI_CEDT_CXIMS; + +typedef struct acpi_cedt_cxims_target_element +{ + UINT64 Xormap; + +} ACPI_CEDT_CXIMS_TARGET_ELEMENT; + + +/* 3: CXL RCEC Downstream Port Association Structure */ + +typedef struct acpi_cedt_rdpas { + ACPI_CEDT_HEADER Header; + UINT16 Segment; + UINT16 Bdf; + UINT64 Address; + UINT8 Protocol; + UINT8 Reserved[3]; +} ACPI_CEDT_RDPAS; + +/* Masks for bdf field above */ +#define ACPI_CEDT_RDPAS_BUS_MASK 0xff00 +#define ACPI_CEDT_RDPAS_DEVICE_MASK 0x00f8 +#define ACPI_CEDT_RDPAS_FUNCTION_MASK 0x0007 + +#define ACPI_CEDT_RDPAS_PROTOCOL_IO (0) +#define ACPI_CEDT_RDPAS_PROTOCOL_CACHEMEM (1) + +/******************************************************************************* + * + * 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; + + +/******************************************************************************* + * + * CSRT - Core System Resource Table + * Version 0 + * + * Conforms to the "Core System Resource Table (CSRT)", November 14, 2011 + * + ******************************************************************************/ + +typedef struct acpi_table_csrt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + +} ACPI_TABLE_CSRT; + + +/* Resource Group subtable */ + +typedef struct acpi_csrt_group +{ + UINT32 Length; + UINT32 VendorId; + UINT32 SubvendorId; + UINT16 DeviceId; + UINT16 SubdeviceId; + UINT16 Revision; + UINT16 Reserved; + UINT32 SharedInfoLength; + + /* Shared data immediately follows (Length = SharedInfoLength) */ + +} ACPI_CSRT_GROUP; + +/* Shared Info subtable */ + +typedef struct acpi_csrt_shared_info +{ + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT32 MmioBaseLow; + UINT32 MmioBaseHigh; + UINT32 GsiInterrupt; + UINT8 InterruptPolarity; + UINT8 InterruptMode; + UINT8 NumChannels; + UINT8 DmaAddressWidth; + UINT16 BaseRequestLine; + UINT16 NumHandshakeSignals; + UINT32 MaxBlockSize; + + /* Resource descriptors immediately follow (Length = Group Length - SharedInfoLength) */ + +} ACPI_CSRT_SHARED_INFO; + +/* Resource Descriptor subtable */ + +typedef struct acpi_csrt_descriptor +{ + UINT32 Length; + UINT16 Type; + UINT16 Subtype; + UINT32 Uid; + + /* Resource-specific information immediately follows */ + +} ACPI_CSRT_DESCRIPTOR; + + +/* Resource Types */ + +#define ACPI_CSRT_TYPE_INTERRUPT 0x0001 +#define ACPI_CSRT_TYPE_TIMER 0x0002 +#define ACPI_CSRT_TYPE_DMA 0x0003 + +/* Resource Subtypes */ + +#define ACPI_CSRT_XRUPT_LINE 0x0000 +#define ACPI_CSRT_XRUPT_CONTROLLER 0x0001 +#define ACPI_CSRT_TIMER 0x0000 +#define ACPI_CSRT_DMA_CHANNEL 0x0000 +#define ACPI_CSRT_DMA_CONTROLLER 0x0001 + + +/******************************************************************************* + * + * DBG2 - Debug Port Table 2 + * Version 0 (Both main table and subtables) + * + * Conforms to "Microsoft Debug Port Table 2 (DBG2)", September 21, 2020 + * + ******************************************************************************/ + +typedef struct acpi_table_dbg2 +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 InfoOffset; + UINT32 InfoCount; + +} ACPI_TABLE_DBG2; + + +typedef struct acpi_dbg2_header +{ + UINT32 InfoOffset; + UINT32 InfoCount; + +} ACPI_DBG2_HEADER; + + +/* Debug Device Information Subtable */ + +typedef struct acpi_dbg2_device +{ + UINT8 Revision; + UINT16 Length; + UINT8 RegisterCount; /* Number of BaseAddress registers */ + UINT16 NamepathLength; + UINT16 NamepathOffset; + UINT16 OemDataLength; + UINT16 OemDataOffset; + UINT16 PortType; + UINT16 PortSubtype; + UINT16 Reserved; + UINT16 BaseAddressOffset; + UINT16 AddressSizeOffset; + /* + * Data that follows: + * BaseAddress (required) - Each in 12-byte Generic Address Structure format. + * AddressSize (required) - Array of UINT32 sizes corresponding to each BaseAddress register. + * Namepath (required) - Null terminated string. Single dot if not supported. + * OemData (optional) - Length is OemDataLength. + */ +} ACPI_DBG2_DEVICE; + +/* Types for PortType field above */ + +#define ACPI_DBG2_SERIAL_PORT 0x8000 +#define ACPI_DBG2_1394_PORT 0x8001 +#define ACPI_DBG2_USB_PORT 0x8002 +#define ACPI_DBG2_NET_PORT 0x8003 + +/* Subtypes for PortSubtype field above */ + +#define ACPI_DBG2_16550_COMPATIBLE 0x0000 +#define ACPI_DBG2_16550_SUBSET 0x0001 +#define ACPI_DBG2_MAX311XE_SPI 0x0002 +#define ACPI_DBG2_ARM_PL011 0x0003 +#define ACPI_DBG2_MSM8X60 0x0004 +#define ACPI_DBG2_16550_NVIDIA 0x0005 +#define ACPI_DBG2_TI_OMAP 0x0006 +#define ACPI_DBG2_APM88XXXX 0x0008 +#define ACPI_DBG2_MSM8974 0x0009 +#define ACPI_DBG2_SAM5250 0x000A +#define ACPI_DBG2_INTEL_USIF 0x000B +#define ACPI_DBG2_IMX6 0x000C +#define ACPI_DBG2_ARM_SBSA_32BIT 0x000D +#define ACPI_DBG2_ARM_SBSA_GENERIC 0x000E +#define ACPI_DBG2_ARM_DCC 0x000F +#define ACPI_DBG2_BCM2835 0x0010 +#define ACPI_DBG2_SDM845_1_8432MHZ 0x0011 +#define ACPI_DBG2_16550_WITH_GAS 0x0012 +#define ACPI_DBG2_SDM845_7_372MHZ 0x0013 +#define ACPI_DBG2_INTEL_LPSS 0x0014 +#define ACPI_DBG2_RISCV_SBI_CON 0x0015 + +#define ACPI_DBG2_1394_STANDARD 0x0000 + +#define ACPI_DBG2_USB_XHCI 0x0000 +#define ACPI_DBG2_USB_EHCI 0x0001 + + +/******************************************************************************* + * + * 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 2.3, October 2014 + * + ******************************************************************************/ + +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) +#define ACPI_DMAR_X2APIC_OPT_OUT (1<<1) +#define ACPI_DMAR_X2APIC_MODE (1<<2) + + +/* 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_ROOT_ATS = 2, + ACPI_DMAR_TYPE_HARDWARE_AFFINITY = 3, + ACPI_DMAR_TYPE_NAMESPACE = 4, + ACPI_DMAR_TYPE_SATC = 5, + ACPI_DMAR_TYPE_SIDP = 6, + ACPI_DMAR_TYPE_RESERVED = 7 /* 7 and greater are reserved */ +}; + + +/* DMAR Device Scope structure */ + +typedef struct acpi_dmar_device_scope +{ + UINT8 EntryType; + UINT8 Length; + UINT8 Flags; + UINT8 Reserved; + UINT8 EnumerationId; + UINT8 Bus; + +} ACPI_DMAR_DEVICE_SCOPE; + +/* Values for EntryType in ACPI_DMAR_DEVICE_SCOPE - device types */ + +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_NAMESPACE = 5, + ACPI_DMAR_SCOPE_TYPE_RESERVED = 6 /* 6 and greater are reserved */ +}; + +typedef struct acpi_dmar_pci_path +{ + UINT8 Device; + UINT8 Function; + +} ACPI_DMAR_PCI_PATH; + + +/* + * DMAR Subtables, correspond to Type in ACPI_DMAR_HEADER + */ + +/* 0: Hardware Unit Definition */ + +typedef struct acpi_dmar_hardware_unit +{ + ACPI_DMAR_HEADER Header; + UINT8 Flags; + UINT8 Size; + 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 Definition */ + +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; + + +/* 4: ACPI Namespace Device Declaration Structure */ + +typedef struct acpi_dmar_andd +{ + ACPI_DMAR_HEADER Header; + UINT8 Reserved[3]; + UINT8 DeviceNumber; + union { + char __pad; + ACPI_FLEX_ARRAY(char, DeviceName); + }; + +} ACPI_DMAR_ANDD; + + +/* 5: SoC Integrated Address Translation Cache (SATC) */ + +typedef struct acpi_dmar_satc +{ + ACPI_DMAR_HEADER Header; + UINT8 Flags; + UINT8 Reserved; + UINT16 Segment; + +} ACPI_DMAR_SATC; + + +/* 6: SoC Integrated Device Property Reporting Structure */ + +typedef struct acpi_dmar_sidp +{ + ACPI_DMAR_HEADER Header; + UINT16 Reserved; + UINT16 Segment; + +} ACPI_DMAR_SIDP; + + +/******************************************************************************* + * + * DRTM - Dynamic Root of Trust for Measurement table + * Conforms to "TCG D-RTM Architecture" June 17 2013, Version 1.0.0 + * Table version 1 + * + ******************************************************************************/ + +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; + +/* Flag Definitions for above */ + +#define ACPI_DRTM_ACCESS_ALLOWED (1) +#define ACPI_DRTM_ENABLE_GAP_CODE (1<<1) +#define ACPI_DRTM_INCOMPLETE_MEASUREMENTS (1<<2) +#define ACPI_DRTM_AUTHORITY_ORDER (1<<3) + + +/* 1) Validated Tables List (64-bit addresses) */ + +typedef struct acpi_drtm_vtable_list +{ + UINT32 ValidatedTableCount; + UINT64 ValidatedTables[]; + +} ACPI_DRTM_VTABLE_LIST; + +/* 2) Resources List (of Resource Descriptors) */ + +/* Resource Descriptor */ + +typedef struct acpi_drtm_resource +{ + UINT8 Size[7]; + UINT8 Type; + UINT64 Address; + +} ACPI_DRTM_RESOURCE; + +typedef struct acpi_drtm_resource_list +{ + UINT32 ResourceCount; + ACPI_DRTM_RESOURCE Resources[]; + +} ACPI_DRTM_RESOURCE_LIST; + +/* 3) Platform-specific Identifiers List */ + +typedef struct acpi_drtm_dps_id +{ + UINT32 DpsIdLength; + UINT8 DpsId[16]; + +} ACPI_DRTM_DPS_ID; + + +/******************************************************************************* + * + * DTPR - DMA TXT Protection Ranges Table + * Version 1 + * + * Conforms to "Intel® Trusted Execution Technology (Intel® TXT) DMA Protection + * Ranges", + * Revision 0.73, August 2021 + * + ******************************************************************************/ + +typedef struct acpi_table_dtpr { + ACPI_TABLE_HEADER header; + UINT32 Flags; /* 36 */ + UINT32 InsCnt; + +} ACPI_TABLE_DTPR; + +typedef struct acpi_tpr_array { + UINT64 Base; + +} ACPI_TPR_ARRAY; + +typedef struct acpi_tpr_instance { + UINT32 Flags; + UINT32 TprCnt; + +} ACPI_TPR_INSTANCE; + +typedef struct acpi_tpr_aux_sr { + UINT32 SrlCnt; + +} ACPI_TPR_AUX_SR; + + +/* + * TPRn_BASE (ACPI_TPRN_BASE_REG) + * + * Specifies the start address of TPRn region. TPR region address and size must + * be with 1MB resolution. These bits are compared with the result of the + * TPRn_LIMIT[63:20], which is applied to the incoming address, to + * determine if an access fall within the TPRn defined region. + * + * Minimal TPRn_Base resolution is 1MB. Applied to the incoming address, to + * determine if an access fall within the TPRn defined region. Width is + * determined by a bus width which can be obtained via CPUID + * function 0x80000008. + */ + +typedef UINT64 ACPI_TPRN_BASE_REG; + + +/* TPRn_BASE Register Bit Masks */ + +/* Bit 3 - RW: access: 1 == RO, 0 == RW register (for TPR must be RW) */ +#define ACPI_TPRN_BASE_RW_SHIFT 3 + + +#define ACPI_TPRN_BASE_RW_MASK ((UINT64) 1 << ACPI_TPRN_BASE_RW_SHIFT) + + +/* + * Bit 4 - Enable: 0 – TPRn address range enabled; + * 1 – TPRn address range disabled. + */ +#define ACPI_TPRN_BASE_ENABLE_SHIFT 4 + + +#define ACPI_TPRN_BASE_ENABLE_MASK ((UINT64) 1 << ACPI_TPRN_BASE_ENABLE_SHIFT) + + +/* Bits 63:20 - TprBaseRw */ +#define ACPI_TPRN_BASE_ADDR_SHIFT 20 + + +#define ACPI_TPRN_BASE_ADDR_MASK ((UINT64) 0xFFFFFFFFFFF << \ + ACPI_TPRN_BASE_ADDR_SHIFT) + + +/* TPRn_BASE Register Bit Handlers*/ + +/* + * GET_TPRN_BASE_RW: + * + * Read RW bit from TPRn Base Register - bit 3. + * + * Input: + * - reg (represents TPRn Base Register (ACPI_TPRN_BASE_REG)) + * + * Output: + * + * Returns RW bit value (UINT64). + */ +#define GET_TPRN_BASE_RW(reg) (((UINT64) reg & ACPI_TPRN_BASE_RW_MASK) >> \ + ACPI_TPRN_BASE_RW_SHIFT) + + +/* + * GET_TPRN_BASE_ENABLE: + * + * Read Enable bit from TPRn Base Register - bit 4. + * + * Input: + * - reg (represents TPRn Base Register (ACPI_TPRN_BASE_REG)) + * + * Output: + * + * Returns Enable bit value (UINT64). + */ +#define GET_TPRN_BASE_ENABLE(reg) (((UINT64) reg & ACPI_TPRN_BASE_ENABLE_MASK) \ + >> ACPI_TPRN_BASE_ENABLE_SHIFT) + + +/* + * GET_TPRN_BASE_ADDR: + * + * Read TPRn Base Register address from bits 63:20. + * + * Input: + * - reg (represents TPRn Base Register (ACPI_TPRN_BASE_REG)) + * + * Output: + * + * Returns TPRn Base Register address (UINT64). + */ +#define GET_TPRN_BASE_ADDR(reg) (((UINT64) reg & ACPI_TPRN_BASE_ADDR_MASK) \ + >> ACPI_TPRN_BASE_ADDR_SHIFT) + + +/* + * SET_TPRN_BASE_RW: + * + * Set RW bit in TPRn Base Register - bit 3. + * + * Input: + * - reg (represents TPRn Base Register (ACPI_TPRN_BASE_REG)) + * - val (represents RW value to be set (UINT64)) + */ +#define SET_TPRN_BASE_RW(reg, val) ACPI_REGISTER_INSERT_VALUE(reg, \ + ACPI_TPRN_BASE_RW_SHIFT, \ + ACPI_TPRN_BASE_RW_MASK, val); + + +/* + * SET_TPRN_BASE_ENABLE: + * + * Set Enable bit in TPRn Base Register - bit 4. + * + * Input: + * - reg (represents TPRn Base Register (ACPI_TPRN_BASE_REG)) + * - val (represents Enable value to be set (UINT64)) + */ +#define SET_TPRN_BASE_ENABLE(reg, val) ACPI_REGISTER_INSERT_VALUE(reg, \ + ACPI_TPRN_BASE_ENABLE_SHIFT, \ + ACPI_TPRN_BASE_ENABLE_MASK, val); + + +/* + * SET_TPRN_BASE_ADDR: + * + * Set TPRn Base Register address - bits 63:20 + * + * Input + * - reg (represents TPRn Base Register (ACPI_TPRN_BASE_REG)) + * - val (represents address value to be set (UINT64)) + */ +#define SET_TPRN_BASE_ADDR(reg, val) ACPI_REGISTER_INSERT_VALUE(reg, \ + ACPI_TPRN_BASE_ADDR_SHIFT, \ + ACPI_TPRN_BASE_ADDR_MASK, val); + + +/* + * TPRn_LIMIT + * + * This register defines an isolated region of memory that can be enabled + * to prohibit certain system agents from accessing memory. When an agent + * sends a request upstream, whether snooped or not, a TPR prevents that + * transaction from changing the state of memory. + * + * Minimal TPRn_Limit resolution is 1MB. Width is determined by a bus width. + */ + +typedef UINT64 ACPI_TPRN_LIMIT_REG; + + +/* TPRn_LIMIT Register Bit Masks */ + + +/* Bit 3 - RW: access: 1 == RO, 0 == RW register (for TPR must be RW) */ +#define ACPI_TPRN_LIMIT_RW_SHIFT 3 + + +#define ACPI_TPRN_LIMIT_RW_MASK ((UINT64) 1 << ACPI_TPRN_LIMIT_RW_SHIFT) + + +/* Bits 63:20 - TprLimitRw */ +#define ACPI_TPRN_LIMIT_ADDR_SHIFT 20 + + +#define ACPI_TPRN_LIMIT_ADDR_MASK ((UINT64) 0xFFFFFFFFFFF << \ + ACPI_TPRN_LIMIT_ADDR_SHIFT) + + +/* TPRn_LIMIT Register Bit Handlers*/ + +/* + * GET_TPRN_LIMIT_RW: + * + * Read RW bit from TPRn Limit Register - bit 3. + * + * Input: + * - reg (represents TPRn Limit Register (ACPI_TPRN_LIMIT_REG)) + * + * Output: + * + * Returns RW bit value (UINT64). + */ +#define GET_TPRN_LIMIT_RW(reg) (((UINT64) reg & ACPI_TPRN_LIMIT_RW_MASK) \ + >> ACPI_TPRN_LIMIT_RW_SHIFT) + + +/* + * GET_TPRN_LIMIT_ADDR: + * + * Read TPRn Limit Register address from bits 63:20. + * + * Input: + * - reg (represents TPRn Limit Register (ACPI_TPRN_LIMIT_REG)) + * + * Output: + * + * Returns TPRn Limit Register address (UINT64). + */ +#define GET_TPRN_LIMIT_ADDR(reg) (((UINT64) reg & ACPI_TPRN_LIMIT_ADDR_MASK) \ + >> ACPI_TPRN_LIMIT_ADDR_SHIFT) + + +/* + * SET_TPRN_LIMIT_RW: + * + * Set RW bit in TPRn Limit Register - bit 3. + * + * Input: + * - reg (represents TPRn Limit Register (ACPI_TPRN_LIMIT_REG)) + * - val (represents RW value to be set (UINT64)) + */ +#define SET_TPRN_LIMIT_RW(reg, val) ACPI_REGISTER_INSERT_VALUE(reg, \ + ACPI_TPRN_LIMIT_RW_SHIFT, \ + ACPI_TPRN_LIMIT_RW_MASK, val); + + +/* + * SET_TPRN_LIMIT_ADDR: + * + * Set TPRn Limit Register address - bits 63:20. + * + * Input: + * - reg (represents TPRn Limit Register (ACPI_TPRN_LIMIT_REG)) + * - val (represents address value to be set (UINT64)) + */ +#define SET_TPRN_LIMIT_ADDR(reg, val) ACPI_REGISTER_INSERT_VALUE(reg, \ + ACPI_TPRN_LIMIT_ADDR_SHIFT, \ + ACPI_TPRN_LIMIT_ADDR_MASK, val); + + +/* + * SERIALIZE_REQUEST + * + * This register is used to request serialization of non-coherent DMA + * transactions. OS shall issue it before changing of TPR settings + * (base / size). + */ + +typedef struct acpi_tpr_serialize_request { + UINT64 SrRegister; + /* + * BIT 1 - Status of serialization request (RO) + * 0 == register idle, 1 == serialization in progress + * BIT 2 - Control field to initiate serialization (RW) + * 0 == normal, 1 == initialize serialization + * (self-clear to allow multiple serialization requests) + */ +} ACPI_TPR_SERIALIZE_REQUEST; + + +/******************************************************************************* + * + * 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[]; /* 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 = 0x0, + ACPI_EINJ_GET_TRIGGER_TABLE = 0x1, + ACPI_EINJ_SET_ERROR_TYPE = 0x2, + ACPI_EINJ_GET_ERROR_TYPE = 0x3, + ACPI_EINJ_END_OPERATION = 0x4, + ACPI_EINJ_EXECUTE_OPERATION = 0x5, + ACPI_EINJ_CHECK_BUSY_STATUS = 0x6, + ACPI_EINJ_GET_COMMAND_STATUS = 0x7, + ACPI_EINJ_SET_ERROR_TYPE_WITH_ADDRESS = 0x8, + ACPI_EINJ_GET_EXECUTE_TIMINGS = 0x9, + ACPI_EINJV2_GET_ERROR_TYPE = 0x11, + ACPI_EINJ_ACTION_RESERVED = 0x12, /* 0x12 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_CXL_CACHE_CORRECTABLE (1<<12) +#define ACPI_EINJ_CXL_CACHE_UNCORRECTABLE (1<<13) +#define ACPI_EINJ_CXL_CACHE_FATAL (1<<14) +#define ACPI_EINJ_CXL_MEM_CORRECTABLE (1<<15) +#define ACPI_EINJ_CXL_MEM_UNCORRECTABLE (1<<16) +#define ACPI_EINJ_CXL_MEM_FATAL (1<<17) +#define ACPI_EINJ_VENDOR_DEFINED (1<<31) + + +/* EINJV2 error types from EINJV2_GET_ERROR_TYPE (ACPI 6.6) */ + +#define ACPI_EINJV2_PROCESSOR (1) +#define ACPI_EINJV2_MEMORY (1<<1) +#define ACPI_EINJV2_PCIE (1<<2) + + +/******************************************************************************* + * + * 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_EXECUTE_TIMINGS = 16, + ACPI_ERST_ACTION_RESERVED = 17 /* 17 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_SUCCESS = 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; + + +/******************************************************************************* + * + * 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 (Performance Record Structure) */ + +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_pointer +{ + ACPI_FPDT_HEADER Header; + UINT8 Reserved[4]; + UINT64 Address; + +} ACPI_FPDT_BOOT_POINTER; + + +/* 1: S3 Performance Table Pointer Record */ + +typedef struct acpi_fpdt_s3pt_pointer +{ + ACPI_FPDT_HEADER Header; + UINT8 Reserved[4]; + UINT64 Address; + +} ACPI_FPDT_S3PT_POINTER; + + +/* + * S3PT - S3 Performance Table. This table is pointed to by the + * S3 Pointer Record above. + */ +typedef struct acpi_table_s3pt +{ + UINT8 Signature[4]; /* "S3PT" */ + UINT32 Length; + +} ACPI_TABLE_S3PT; + + +/* + * S3PT Subtables (Not part of the actual FPDT) + */ + +/* Values for Type field in S3PT header */ + +enum AcpiS3ptType +{ + ACPI_S3PT_TYPE_RESUME = 0, + ACPI_S3PT_TYPE_SUSPEND = 1, + ACPI_FPDT_BOOT_PERFORMANCE = 2 +}; + +typedef struct acpi_s3pt_resume +{ + ACPI_FPDT_HEADER Header; + UINT32 ResumeCount; + UINT64 FullResume; + UINT64 AverageResume; + +} ACPI_S3PT_RESUME; + +typedef struct acpi_s3pt_suspend +{ + ACPI_FPDT_HEADER Header; + UINT64 SuspendStart; + UINT64 SuspendEnd; + +} ACPI_S3PT_SUSPEND; + + +/* + * FPDT Boot Performance Record (Not part of the actual FPDT) + */ +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; + + +/******************************************************************************* + * + * GTDT - Generic Timer Description Table (ACPI 5.1) + * Version 2 + * + ******************************************************************************/ + +typedef struct acpi_table_gtdt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT64 CounterBlockAddresss; + UINT32 Reserved; + UINT32 SecureEl1Interrupt; + UINT32 SecureEl1Flags; + UINT32 NonSecureEl1Interrupt; + UINT32 NonSecureEl1Flags; + UINT32 VirtualTimerInterrupt; + UINT32 VirtualTimerFlags; + UINT32 NonSecureEl2Interrupt; + UINT32 NonSecureEl2Flags; + UINT64 CounterReadBlockAddress; + UINT32 PlatformTimerCount; + UINT32 PlatformTimerOffset; + +} ACPI_TABLE_GTDT; + +/* Flag Definitions: Timer Block Physical Timers and Virtual timers */ + +#define ACPI_GTDT_INTERRUPT_MODE (1) +#define ACPI_GTDT_INTERRUPT_POLARITY (1<<1) +#define ACPI_GTDT_ALWAYS_ON (1<<2) + +typedef struct acpi_gtdt_el2 +{ + UINT32 VirtualEL2TimerGsiv; + UINT32 VirtualEL2TimerFlags; +} ACPI_GTDT_EL2; + + +/* Common GTDT subtable header */ + +typedef struct acpi_gtdt_header +{ + UINT8 Type; + UINT16 Length; + +} ACPI_GTDT_HEADER; + +/* Values for GTDT subtable type above */ + +enum AcpiGtdtType +{ + ACPI_GTDT_TYPE_TIMER_BLOCK = 0, + ACPI_GTDT_TYPE_WATCHDOG = 1, + ACPI_GTDT_TYPE_RESERVED = 2 /* 2 and greater are reserved */ +}; + + +/* GTDT Subtables, correspond to Type in acpi_gtdt_header */ + +/* 0: Generic Timer Block */ + +typedef struct acpi_gtdt_timer_block +{ + ACPI_GTDT_HEADER Header; + UINT8 Reserved; + UINT64 BlockAddress; + UINT32 TimerCount; + UINT32 TimerOffset; + +} ACPI_GTDT_TIMER_BLOCK; + +/* Timer Sub-Structure, one per timer */ + +typedef struct acpi_gtdt_timer_entry +{ + UINT8 FrameNumber; + UINT8 Reserved[3]; + UINT64 BaseAddress; + UINT64 El0BaseAddress; + UINT32 TimerInterrupt; + UINT32 TimerFlags; + UINT32 VirtualTimerInterrupt; + UINT32 VirtualTimerFlags; + UINT32 CommonFlags; + +} ACPI_GTDT_TIMER_ENTRY; + +/* Flag Definitions: TimerFlags and VirtualTimerFlags above */ + +#define ACPI_GTDT_GT_IRQ_MODE (1) +#define ACPI_GTDT_GT_IRQ_POLARITY (1<<1) + +/* Flag Definitions: CommonFlags above */ + +#define ACPI_GTDT_GT_IS_SECURE_TIMER (1) +#define ACPI_GTDT_GT_ALWAYS_ON (1<<1) + + +/* 1: SBSA Generic Watchdog Structure */ + +typedef struct acpi_gtdt_watchdog +{ + ACPI_GTDT_HEADER Header; + UINT8 Reserved; + UINT64 RefreshFrameAddress; + UINT64 ControlFrameAddress; + UINT32 TimerInterrupt; + UINT32 TimerFlags; + +} ACPI_GTDT_WATCHDOG; + +/* Flag Definitions: TimerFlags above */ + +#define ACPI_GTDT_WATCHDOG_IRQ_MODE (1) +#define ACPI_GTDT_WATCHDOG_IRQ_POLARITY (1<<1) +#define ACPI_GTDT_WATCHDOG_SECURE (1<<2) + + +/******************************************************************************* + * + * 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_GENERIC_ERROR_V2 = 10, + ACPI_HEST_TYPE_IA32_DEFERRED_CHECK = 11, + ACPI_HEST_TYPE_RESERVED = 12 /* 12 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; /* Bus and Segment numbers */ + 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) +#define ACPI_HEST_GHES_ASSIST (1<<2) + +/* + * Macros to access the bus/segment numbers in Bus field above: + * Bus number is encoded in bits 7:0 + * Segment number is encoded in bits 23:8 + */ +#define ACPI_HEST_BUS(Bus) ((Bus) & 0xFF) +#define ACPI_HEST_SEGMENT(Bus) (((Bus) >> 8) & 0xFFFF) + + +/* 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_CMCI = 5, /* ACPI 5.0 */ + ACPI_HEST_NOTIFY_MCE = 6, /* ACPI 5.0 */ + ACPI_HEST_NOTIFY_GPIO = 7, /* ACPI 6.0 */ + ACPI_HEST_NOTIFY_SEA = 8, /* ACPI 6.1 */ + ACPI_HEST_NOTIFY_SEI = 9, /* ACPI 6.1 */ + ACPI_HEST_NOTIFY_GSIV = 10, /* ACPI 6.1 */ + ACPI_HEST_NOTIFY_SOFTWARE_DELEGATED = 11, /* ACPI 6.2 */ + ACPI_HEST_NOTIFY_SSE = 12, /* RISC-V SSE */ + ACPI_HEST_NOTIFY_RESERVED = 13 /* 13 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; /* See flags ACPI_HEST_GLOBAL, etc. above */ + 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; /* See flags ACPI_HEST_GLOBAL, etc. above */ + 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; + + +/* 10: Generic Hardware Error Source, version 2 */ + +typedef struct acpi_hest_generic_v2 +{ + 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_GENERIC_ADDRESS ReadAckRegister; + UINT64 ReadAckPreserve; + UINT64 ReadAckWrite; + +} ACPI_HEST_GENERIC_V2; + + +/* 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; + +/* Extension for revision 0x0300 */ + +typedef struct acpi_hest_generic_data_v300 +{ + UINT8 SectionType[16]; + UINT32 ErrorSeverity; + UINT16 Revision; + UINT8 ValidationBits; + UINT8 Flags; + UINT32 ErrorDataLength; + UINT8 FruId[16]; + UINT8 FruText[20]; + UINT64 TimeStamp; + +} ACPI_HEST_GENERIC_DATA_V300; + +/* Values for ErrorSeverity above */ + +#define ACPI_HEST_GEN_ERROR_RECOVERABLE 0 +#define ACPI_HEST_GEN_ERROR_FATAL 1 +#define ACPI_HEST_GEN_ERROR_CORRECTED 2 +#define ACPI_HEST_GEN_ERROR_NONE 3 + +/* Flags for ValidationBits above */ + +#define ACPI_HEST_GEN_VALID_FRU_ID (1) +#define ACPI_HEST_GEN_VALID_FRU_STRING (1<<1) +#define ACPI_HEST_GEN_VALID_TIMESTAMP (1<<2) + + +/* 11: IA32 Deferred Machine Check Exception (ACPI 6.2) */ + +typedef struct acpi_hest_ia_deferred_check +{ + ACPI_HEST_HEADER Header; + UINT16 Reserved1; + UINT8 Flags; /* See flags ACPI_HEST_GLOBAL, etc. above */ + UINT8 Enabled; + UINT32 RecordsToPreallocate; + UINT32 MaxSectionsPerRecord; + ACPI_HEST_NOTIFY Notify; + UINT8 NumHardwareBanks; + UINT8 Reserved2[3]; + +} ACPI_HEST_IA_DEFERRED_CHECK; + + +/******************************************************************************* + * + * HMAT - Heterogeneous Memory Attributes Table (ACPI 6.3) + * + ******************************************************************************/ + +typedef struct acpi_table_hmat +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 Reserved; + +} ACPI_TABLE_HMAT; + + +/* Values for HMAT structure types */ + +enum AcpiHmatType +{ + ACPI_HMAT_TYPE_ADDRESS_RANGE = 0, /* Memory subsystem address range */ + ACPI_HMAT_TYPE_LOCALITY = 1, /* System locality latency and bandwidth information */ + ACPI_HMAT_TYPE_CACHE = 2, /* Memory side cache information */ + ACPI_HMAT_TYPE_RESERVED = 3 /* 3 and greater are reserved */ +}; + +typedef struct acpi_hmat_structure +{ + UINT16 Type; + UINT16 Reserved; + UINT32 Length; + +} ACPI_HMAT_STRUCTURE; + + +/* + * HMAT Structures, correspond to Type in ACPI_HMAT_STRUCTURE + */ + +/* 0: Memory proximity domain attributes */ + +typedef struct acpi_hmat_proximity_domain +{ + ACPI_HMAT_STRUCTURE Header; + UINT16 Flags; + UINT16 Reserved1; + UINT32 InitiatorPD; /* Attached Initiator proximity domain */ + UINT32 MemoryPD; /* Memory proximity domain */ + UINT32 Reserved2; + UINT64 Reserved3; + UINT64 Reserved4; + +} ACPI_HMAT_PROXIMITY_DOMAIN; + +/* Masks for Flags field above */ + +#define ACPI_HMAT_INITIATOR_PD_VALID (1) /* 1: InitiatorPD field is valid */ + + +/* 1: System locality latency and bandwidth information */ + +typedef struct acpi_hmat_locality +{ + ACPI_HMAT_STRUCTURE Header; + UINT8 Flags; + UINT8 DataType; + UINT8 MinTransferSize; + UINT8 Reserved1; + UINT32 NumberOfInitiatorPDs; + UINT32 NumberOfTargetPDs; + UINT32 Reserved2; + UINT64 EntryBaseUnit; + +} ACPI_HMAT_LOCALITY; + +/* Masks for Flags field above */ + +#define ACPI_HMAT_MEMORY_HIERARCHY (0x0F) /* Bits 0-3 */ + +/* Values for Memory Hierarchy flags */ + +#define ACPI_HMAT_MEMORY 0 +#define ACPI_HMAT_1ST_LEVEL_CACHE 1 +#define ACPI_HMAT_2ND_LEVEL_CACHE 2 +#define ACPI_HMAT_3RD_LEVEL_CACHE 3 +#define ACPI_HMAT_MINIMUM_XFER_SIZE 0x10 /* Bit 4: ACPI 6.4 */ +#define ACPI_HMAT_NON_SEQUENTIAL_XFERS 0x20 /* Bit 5: ACPI 6.4 */ + + +/* Values for DataType field above */ + +#define ACPI_HMAT_ACCESS_LATENCY 0 +#define ACPI_HMAT_READ_LATENCY 1 +#define ACPI_HMAT_WRITE_LATENCY 2 +#define ACPI_HMAT_ACCESS_BANDWIDTH 3 +#define ACPI_HMAT_READ_BANDWIDTH 4 +#define ACPI_HMAT_WRITE_BANDWIDTH 5 + + +/* 2: Memory side cache information */ + +typedef struct acpi_hmat_cache +{ + ACPI_HMAT_STRUCTURE Header; + UINT32 MemoryPD; + UINT32 Reserved1; + UINT64 CacheSize; + UINT32 CacheAttributes; + UINT16 AddressMode; + UINT16 NumberOfSMBIOSHandles; + +} ACPI_HMAT_CACHE; + +/* Masks for CacheAttributes field above */ + +#define ACPI_HMAT_TOTAL_CACHE_LEVEL (0x0000000F) +#define ACPI_HMAT_CACHE_LEVEL (0x000000F0) +#define ACPI_HMAT_CACHE_ASSOCIATIVITY (0x00000F00) +#define ACPI_HMAT_WRITE_POLICY (0x0000F000) +#define ACPI_HMAT_CACHE_LINE_SIZE (0xFFFF0000) + +#define ACPI_HMAT_CACHE_MODE_UNKNOWN (0) +#define ACPI_HMAT_CACHE_MODE_EXTENDED_LINEAR (1) + +/* Values for cache associativity flag */ + +#define ACPI_HMAT_CA_NONE (0) +#define ACPI_HMAT_CA_DIRECT_MAPPED (1) +#define ACPI_HMAT_CA_COMPLEX_CACHE_INDEXING (2) + +/* Values for write policy flag */ + +#define ACPI_HMAT_CP_NONE (0) +#define ACPI_HMAT_CP_WB (1) +#define ACPI_HMAT_CP_WT (2) + + +/******************************************************************************* + * + * 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; + +/* Reset to default packing */ + +#pragma pack() + +#endif /* __ACTBL1_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/actbl2.h b/code/drivers/platform/acpi/third_party/acpica/include/actbl2.h new file mode 100644 index 0000000..c585489 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/actbl2.h @@ -0,0 +1,4429 @@ +/****************************************************************************** + * + * Name: actbl2.h - ACPI Table Definitions + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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. + * + ******************************************************************************/ + + +/* + * 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_AGDI "AGDI" /* Arm Generic Diagnostic Dump and Reset Device Interface */ +#define ACPI_SIG_APMT "APMT" /* Arm Performance Monitoring Unit table */ +#define ACPI_SIG_BDAT "BDAT" /* BIOS Data ACPI Table */ +#define ACPI_SIG_CCEL "CCEL" /* CC Event Log Table */ +#define ACPI_SIG_CDAT "CDAT" /* Coherent Device Attribute Table */ +#define ACPI_SIG_ERDT "ERDT" /* Enhanced Resource Director Technology */ +#define ACPI_SIG_IORT "IORT" /* IO Remapping Table */ +#define ACPI_SIG_IOVT "IOVT" /* I/O Virtualization Table */ +#define ACPI_SIG_IVRS "IVRS" /* I/O Virtualization Reporting Structure */ +#define ACPI_SIG_KEYP "KEYP" /* Key Programming Interface for IDE */ +#define ACPI_SIG_LPIT "LPIT" /* Low Power Idle Table */ +#define ACPI_SIG_MADT "APIC" /* Multiple APIC Description Table */ +#define ACPI_SIG_MCFG "MCFG" /* PCI Memory Mapped Configuration table */ +#define ACPI_SIG_MCHI "MCHI" /* Management Controller Host Interface table */ +#define ACPI_SIG_MISC "MISC" /* Miscellaneous GUIDed Table */ +#define ACPI_SIG_MPAM "MPAM" /* Memory System Resource Partitioning and Monitoring Table */ +#define ACPI_SIG_MPST "MPST" /* Memory Power State Table */ +#define ACPI_SIG_MRRM "MRRM" /* Memory Range and Region Mapping table */ +#define ACPI_SIG_MSDM "MSDM" /* Microsoft Data Management Table */ +#define ACPI_SIG_NFIT "NFIT" /* NVDIMM Firmware Interface Table */ +#define ACPI_SIG_NHLT "NHLT" /* Non HD Audio Link Table */ +#define ACPI_SIG_PCCT "PCCT" /* Platform Communications Channel Table */ +#define ACPI_SIG_PDTT "PDTT" /* Platform Debug Trigger Table */ +#define ACPI_SIG_PHAT "PHAT" /* Platform Health Assessment Table */ +#define ACPI_SIG_PMTT "PMTT" /* Platform Memory Topology Table */ +#define ACPI_SIG_PPTT "PPTT" /* Processor Properties Topology Table */ +#define ACPI_SIG_PRMT "PRMT" /* Platform Runtime Mechanism Table */ +#define ACPI_SIG_RASF "RASF" /* RAS Feature table */ +#define ACPI_SIG_RAS2 "RAS2" /* RAS2 Feature table */ +#define ACPI_SIG_RGRT "RGRT" /* Regulatory Graphics Resource Table */ +#define ACPI_SIG_RHCT "RHCT" /* RISC-V Hart Capabilities Table */ +#define ACPI_SIG_RIMT "RIMT" /* RISC-V IO Mapping Table */ +#define ACPI_SIG_SBST "SBST" /* Smart Battery Specification Table */ +#define ACPI_SIG_SDEI "SDEI" /* Software Delegated Exception Interface Table */ +#define ACPI_SIG_SDEV "SDEV" /* Secure Devices table */ +#define ACPI_SIG_SVKL "SVKL" /* Storage Volume Key Location Table */ +#define ACPI_SIG_SWFT "SWFT" /* SoundWire File Table */ +#define ACPI_SIG_TDEL "TDEL" /* TD Event Log Table */ +#define ACPI_SIG_UBRT "UBRT" /* UnifiedBus Root 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: C bitfields are not used for this reason: + * + * "Bitfields are great and easy to read, but unfortunately the C language + * does not specify the layout of bitfields in memory, which means they are + * essentially useless for dealing with packed data in on-disk formats or + * binary wire protocols." (Or ACPI tables and buffers.) "If you ask me, + * this decision was a design error in C. Ritchie could have picked an order + * and stuck with it." Norman Ramsey. + * See http://stackoverflow.com/a/1053662/41661 + */ + + +/******************************************************************************* + * + * AEST - Arm Error Source Table + * + * Conforms to: ACPI for the Armv8 RAS Extensions 1.1 Platform Design Document + * September 2020. + * + ******************************************************************************/ + +typedef struct acpi_table_aest +{ + ACPI_TABLE_HEADER Header; + +} ACPI_TABLE_AEST; + +/* Common Subtable header - one per Node Structure (Subtable) */ + +typedef struct acpi_aest_hdr +{ + UINT8 Type; + UINT16 Length; + UINT8 Reserved; + UINT32 NodeSpecificOffset; + UINT32 NodeInterfaceOffset; + UINT32 NodeInterruptOffset; + UINT32 NodeInterruptCount; + UINT64 TimestampRate; + UINT64 Reserved1; + UINT64 ErrorInjectionRate; + +} ACPI_AEST_HEADER; + +/* Values for Type above */ + +#define ACPI_AEST_PROCESSOR_ERROR_NODE 0 +#define ACPI_AEST_MEMORY_ERROR_NODE 1 +#define ACPI_AEST_SMMU_ERROR_NODE 2 +#define ACPI_AEST_VENDOR_ERROR_NODE 3 +#define ACPI_AEST_GIC_ERROR_NODE 4 +#define ACPI_AEST_PCIE_ERROR_NODE 5 +#define ACPI_AEST_PROXY_ERROR_NODE 6 +#define ACPI_AEST_NODE_TYPE_RESERVED 7 /* 7 and above are reserved */ + + +/* + * AEST subtables (Error nodes) + */ + +/* 0: Processor Error */ + +typedef struct acpi_aest_processor +{ + UINT32 ProcessorId; + UINT8 ResourceType; + UINT8 Reserved; + UINT8 Flags; + UINT8 Revision; + UINT64 ProcessorAffinity; + +} ACPI_AEST_PROCESSOR; + +/* Values for ResourceType above, related structs below */ + +#define ACPI_AEST_CACHE_RESOURCE 0 +#define ACPI_AEST_TLB_RESOURCE 1 +#define ACPI_AEST_GENERIC_RESOURCE 2 +#define ACPI_AEST_RESOURCE_RESERVED 3 /* 3 and above are reserved */ + +/* 0R: Processor Cache Resource Substructure */ + +typedef struct acpi_aest_processor_cache +{ + UINT32 CacheReference; + UINT32 Reserved; + +} ACPI_AEST_PROCESSOR_CACHE; + +/* Values for CacheType above */ + +#define ACPI_AEST_CACHE_DATA 0 +#define ACPI_AEST_CACHE_INSTRUCTION 1 +#define ACPI_AEST_CACHE_UNIFIED 2 +#define ACPI_AEST_CACHE_RESERVED 3 /* 3 and above are reserved */ + +/* 1R: Processor TLB Resource Substructure */ + +typedef struct acpi_aest_processor_tlb +{ + UINT32 TlbLevel; + UINT32 Reserved; + +} ACPI_AEST_PROCESSOR_TLB; + +/* 2R: Processor Generic Resource Substructure */ + +typedef struct acpi_aest_processor_generic +{ + UINT32 Resource; + +} ACPI_AEST_PROCESSOR_GENERIC; + +/* 1: Memory Error */ + +typedef struct acpi_aest_memory +{ + UINT32 SratProximityDomain; + +} ACPI_AEST_MEMORY; + +/* 2: Smmu Error */ + +typedef struct acpi_aest_smmu +{ + UINT32 IortNodeReference; + UINT32 SubcomponentReference; + +} ACPI_AEST_SMMU; + +/* 3: Vendor Defined */ + +typedef struct acpi_aest_vendor +{ + UINT32 AcpiHid; + UINT32 AcpiUid; + UINT8 VendorSpecificData[16]; + +} ACPI_AEST_VENDOR; + +/* 3: Vendor Defined V2 */ + +typedef struct acpi_aest_vendor_v2 +{ + UINT64 AcpiHid; + UINT32 AcpiUid; + UINT8 VendorSpecificData[16]; + +} ACPI_AEST_VENDOR_V2; + +/* 4: Gic Error */ + +typedef struct acpi_aest_gic +{ + UINT32 InterfaceType; + UINT32 InstanceId; + +} ACPI_AEST_GIC; + +/* Values for InterfaceType above */ + +#define ACPI_AEST_GIC_CPU 0 +#define ACPI_AEST_GIC_DISTRIBUTOR 1 +#define ACPI_AEST_GIC_REDISTRIBUTOR 2 +#define ACPI_AEST_GIC_ITS 3 +#define ACPI_AEST_GIC_RESERVED 4 /* 4 and above are reserved */ + +/* 5: PCIe Error */ + +typedef struct acpi_aest_pcie +{ + UINT32 IortNodeReference; + +} ACPI_AEST_PCIE; + + +/* 6: Proxy Error */ + +typedef struct acpi_aest_proxy +{ + UINT64 NodeAddress; + +} ACPI_AEST_PROXY; + +/* Node Interface Structure */ + +typedef struct acpi_aest_node_interface +{ + UINT8 Type; + UINT8 Reserved[3]; + UINT32 Flags; + UINT64 Address; + UINT32 ErrorRecordIndex; + UINT32 ErrorRecordCount; + UINT64 ErrorRecordImplemented; + UINT64 ErrorStatusReporting; + UINT64 AddressingMode; + +} ACPI_AEST_NODE_INTERFACE; + +/* Node Interface Structure V2*/ + +typedef struct acpi_aest_node_interface_header +{ + UINT8 Type; + UINT8 GroupFormat; + UINT8 Reserved[2]; + UINT32 Flags; + UINT64 Address; + UINT32 ErrorRecordIndex; + UINT32 ErrorRecordCount; + +} ACPI_AEST_NODE_INTERFACE_HEADER; + +#define ACPI_AEST_NODE_GROUP_FORMAT_4K 0 +#define ACPI_AEST_NODE_GROUP_FORMAT_16K 1 +#define ACPI_AEST_NODE_GROUP_FORMAT_64K 2 + +typedef struct acpi_aest_node_interface_common +{ + UINT32 ErrorNodeDevice; + UINT32 ProcessorAffinity; + UINT64 ErrorGroupRegisterBase; + UINT64 FaultInjectRegisterBase; + UINT64 InterruptConfigRegisterBase; + +} ACPI_AEST_NODE_INTERFACE_COMMON; + +typedef struct acpi_aest_node_interface_4k +{ + UINT64 ErrorRecordImplemented; + UINT64 ErrorStatusReporting; + UINT64 AddressingMode; + ACPI_AEST_NODE_INTERFACE_COMMON Common; + +} ACPI_AEST_NODE_INTERFACE_4K; + +typedef struct acpi_aest_node_interface_16k +{ + UINT64 ErrorRecordImplemented[4]; + UINT64 ErrorStatusReporting[4]; + UINT64 AddressingMode[4]; + ACPI_AEST_NODE_INTERFACE_COMMON Common; + +} ACPI_AEST_NODE_INTERFACE_16K; + +typedef struct acpi_aest_node_interface_64k +{ + INT64 ErrorRecordImplemented[14]; + UINT64 ErrorStatusReporting[14]; + UINT64 AddressingMode[14]; + ACPI_AEST_NODE_INTERFACE_COMMON Common; + +} ACPI_AEST_NODE_INTERFACE_64K; + +/* Values for Type field above */ + +#define ACPI_AEST_NODE_SYSTEM_REGISTER 0 +#define ACPI_AEST_NODE_MEMORY_MAPPED 1 +#define ACPI_AEST_NODE_SINGLE_RECORD_MEMORY_MAPPED 2 +#define ACPI_AEST_XFACE_RESERVED 3 /* 2 and above are reserved */ + +/* Node Interrupt Structure */ + +typedef struct acpi_aest_node_interrupt +{ + UINT8 Type; + UINT8 Reserved[2]; + UINT8 Flags; + UINT32 Gsiv; + UINT8 IortId; + UINT8 Reserved1[3]; + +} ACPI_AEST_NODE_INTERRUPT; + +/* Node Interrupt Structure V2 */ + +typedef struct acpi_aest_node_interrupt_v2 +{ + UINT8 Type; + UINT8 Reserved[2]; + UINT8 Flags; + UINT32 Gsiv; + UINT8 Reserved1[4]; + +} ACPI_AEST_NODE_INTERRUPT_V2; + +/* Values for Type field above */ + +#define ACPI_AEST_NODE_FAULT_HANDLING 0 +#define ACPI_AEST_NODE_ERROR_RECOVERY 1 +#define ACPI_AEST_XRUPT_RESERVED 2 /* 2 and above are reserved */ + + +/******************************************************************************* + * AGDI - Arm Generic Diagnostic Dump and Reset Device Interface + * + * Conforms to "ACPI for Arm Components 1.1, Platform Design Document" + * ARM DEN0093 v1.1 + * + ******************************************************************************/ +typedef struct acpi_table_agdi +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT8 Flags; + UINT8 Reserved[3]; + UINT32 SdeiEvent; + UINT32 Gsiv; + +} ACPI_TABLE_AGDI; + +/* Mask for Flags field above */ + +#define ACPI_AGDI_SIGNALING_MODE (1) + + +/******************************************************************************* + * + * APMT - ARM Performance Monitoring Unit Table + * + * Conforms to: + * ARM Performance Monitoring Unit Architecture 1.0 Platform Design Document + * ARM DEN0117 v1.0 November 25, 2021 + * + ******************************************************************************/ + +typedef struct acpi_table_apmt { + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ +} ACPI_TABLE_APMT; + +#define ACPI_APMT_NODE_ID_LENGTH 4 + +/* + * APMT subtables + */ +typedef struct acpi_apmt_node { + UINT16 Length; + UINT8 Flags; + UINT8 Type; + UINT32 Id; + UINT64 InstPrimary; + UINT32 InstSecondary; + UINT64 BaseAddress0; + UINT64 BaseAddress1; + UINT32 OvflwIrq; + UINT32 Reserved; + UINT32 OvflwIrqFlags; + UINT32 ProcAffinity; + UINT32 ImplId; +} ACPI_APMT_NODE; + +/* Masks for Flags field above */ + +#define ACPI_APMT_FLAGS_DUAL_PAGE (1<<0) +#define ACPI_APMT_FLAGS_AFFINITY (1<<1) +#define ACPI_APMT_FLAGS_ATOMIC (1<<2) + +/* Values for Flags dual page field above */ + +#define ACPI_APMT_FLAGS_DUAL_PAGE_NSUPP (0<<0) +#define ACPI_APMT_FLAGS_DUAL_PAGE_SUPP (1<<0) + +/* Values for Flags processor affinity field above */ +#define ACPI_APMT_FLAGS_AFFINITY_PROC (0<<1) +#define ACPI_APMT_FLAGS_AFFINITY_PROC_CONTAINER (1<<1) + +/* Values for Flags 64-bit atomic field above */ +#define ACPI_APMT_FLAGS_ATOMIC_NSUPP (0<<2) +#define ACPI_APMT_FLAGS_ATOMIC_SUPP (1<<2) + +/* Values for Type field above */ + +enum acpi_apmt_node_type { + ACPI_APMT_NODE_TYPE_MC = 0x00, + ACPI_APMT_NODE_TYPE_SMMU = 0x01, + ACPI_APMT_NODE_TYPE_PCIE_ROOT = 0x02, + ACPI_APMT_NODE_TYPE_ACPI = 0x03, + ACPI_APMT_NODE_TYPE_CACHE = 0x04, + ACPI_APMT_NODE_TYPE_COUNT +}; + +/* Masks for ovflw_irq_flags field above */ + +#define ACPI_APMT_OVFLW_IRQ_FLAGS_MODE (1<<0) +#define ACPI_APMT_OVFLW_IRQ_FLAGS_TYPE (1<<1) + +/* Values for ovflw_irq_flags mode field above */ + +#define ACPI_APMT_OVFLW_IRQ_FLAGS_MODE_LEVEL (0<<0) +#define ACPI_APMT_OVFLW_IRQ_FLAGS_MODE_EDGE (1<<0) + +/* Values for ovflw_irq_flags type field above */ + +#define ACPI_APMT_OVFLW_IRQ_FLAGS_TYPE_WIRED (0<<1) + + +/******************************************************************************* + * + * BDAT - BIOS Data ACPI Table + * + * Conforms to "BIOS Data ACPI Table", Interface Specification v4.0 Draft 5 + * Nov 2020 + * + ******************************************************************************/ + +typedef struct acpi_table_bdat +{ + ACPI_TABLE_HEADER Header; + ACPI_GENERIC_ADDRESS Gas; + +} ACPI_TABLE_BDAT; + +/******************************************************************************* + * + * CCEL - CC-Event Log + * From: "Guest-Host-Communication Interface (GHCI) for Intel + * Trust Domain Extensions (Intel TDX)". Feb 2022 + * + ******************************************************************************/ + +typedef struct acpi_table_ccel +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT8 CCType; + UINT8 CCSubType; + UINT16 Reserved; + UINT64 LogAreaMinimumLength; + UINT64 LogAreaStartAddress; + +} ACPI_TABLE_CCEL; + +/******************************************************************************* + * + * ERDT - Enhanced Resource Director Technology (ERDT) table + * + * Conforms to "Intel Resource Director Technology Architecture Specification" + * Version 1.1, January 2025 + * + ******************************************************************************/ + +typedef struct acpi_table_erdt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 MaxClos; /* Maximum classes of service */ + UINT8 Reserved[24]; + UINT8 Erdt_Substructures[]; + +} ACPI_TABLE_ERDT; + + +/* Values for subtable type in ACPI_SUBTBL_HDR_16 */ + +enum AcpiErdtType +{ + ACPI_ERDT_TYPE_RMDD = 0, + ACPI_ERDT_TYPE_CACD = 1, + ACPI_ERDT_TYPE_DACD = 2, + ACPI_ERDT_TYPE_CMRC = 3, + ACPI_ERDT_TYPE_MMRC = 4, + ACPI_ERDT_TYPE_MARC = 5, + ACPI_ERDT_TYPE_CARC = 6, + ACPI_ERDT_TYPE_CMRD = 7, + ACPI_ERDT_TYPE_IBRD = 8, + ACPI_ERDT_TYPE_IBAD = 9, + ACPI_ERDT_TYPE_CARD = 10, + ACPI_ERDT_TYPE_RESERVED = 11 /* 11 and above are reserved */ + +}; + +/* + * ERDT Subtables, correspond to Type in ACPI_SUBTBL_HDR_16 + */ + +/* 0: RMDD - Resource Management Domain Description */ + +typedef struct acpi_erdt_rmdd +{ + ACPI_SUBTBL_HDR_16 Header; + UINT16 Flags; + UINT16 IO_l3_Slices; /* Number of slices in IO cache */ + UINT8 IO_l3_Sets; /* Number of sets in IO cache */ + UINT8 IO_l3_Ways; /* Number of ways in IO cache */ + UINT64 Reserved; + UINT16 DomainId; /* Unique domain ID */ + UINT32 MaxRmid; /* Maximun RMID supported */ + UINT64 CregBase; /* Control Register Base Address */ + UINT16 CregSize; /* Control Register Size (4K pages) */ + UINT8 RmddStructs[]; + +} ACPI_ERDT_RMDD; + + +/* 1: CACD - CPU Agent Collection Description */ + +typedef struct acpi_erdt_cacd +{ + ACPI_SUBTBL_HDR_16 Header; + UINT16 Reserved; + UINT16 DomainId; /* Unique domain ID */ + UINT32 X2APICIDS[]; + +} ACPI_ERDT_CACD; + + +/* 2: DACD - Device Agent Collection Description */ + +typedef struct acpi_erdt_dacd +{ + ACPI_SUBTBL_HDR_16 Header; + UINT16 Reserved; + UINT16 DomainId; /* Unique domain ID */ + UINT8 DevPaths[]; + +} ACPI_ERDT_DACD; + +typedef struct acpi_erdt_dacd_dev_paths +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 Segment; + UINT8 Reserved; + UINT8 StartBus; + UINT8 Path[]; + +} ACPI_ERDT_DACD_PATHS; + + +/* 3: CMRC - Cache Monitoring Registers for CPU Agents */ + +typedef struct acpi_erdt_cmrc +{ + ACPI_SUBTBL_HDR_16 Header; + UINT32 Reserved1; + UINT32 Flags; + UINT8 IndexFn; + UINT8 Reserved2[11]; + UINT64 CmtRegBase; + UINT32 CmtRegSize; + UINT16 ClumpSize; + UINT16 ClumpStride; + UINT64 UpScale; + +} ACPI_ERDT_CMRC; + + +/* 4: MMRC - Memory-bandwidth Monitoring Registers for CPU Agents */ + +typedef struct acpi_erdt_mmrc +{ + ACPI_SUBTBL_HDR_16 Header; + UINT32 Reserved1; + UINT32 Flags; + UINT8 IndexFn; + UINT8 Reserved2[11]; + UINT64 RegBase; + UINT32 RegSize; + UINT8 CounterWidth; + UINT64 UpScale; + UINT8 Reserved3[7]; + UINT32 CorrFactorListLen; + UINT32 CorrFactorList[]; + +} ACPI_ERDT_MMRC; + + +/* 5: MARC - Memory-bandwidth Allocation Registers for CPU Agents */ + +typedef struct acpi_erdt_marc +{ + ACPI_SUBTBL_HDR_16 Header; + UINT16 Reserved1; + UINT16 Flags; + UINT8 IndexFn; + UINT8 Reserved2[7]; + UINT64 RegBaseOpt; + UINT64 RegBaseMin; + UINT64 RegBaseMax; + UINT32 MbaRegSize; + UINT32 MbaCtrlRange; + +} ACPI_ERDT_MARC; + + +/* 6: CARC - Cache Allocation Registers for CPU Agents */ + +typedef struct acpi_erdt_carc +{ + ACPI_SUBTBL_HDR_16 Header; + +} ACPI_ERDT_CARC; + + +/* 7: CMRD - Cache Monitoring Registers for Device Agents */ + +typedef struct acpi_erdt_cmrd +{ + ACPI_SUBTBL_HDR_16 Header; + UINT32 Reserved1; + UINT32 Flags; + UINT8 IndexFn; + UINT8 Reserved2[11]; + UINT64 RegBase; + UINT32 RegSize; + UINT16 CmtRegOff; + UINT16 CmtClumpSize; + UINT64 UpScale; + +} ACPI_ERDT_CMRD; + + +/* 8: IBRD - Cache Monitoring Registers for Device Agents */ + +typedef struct acpi_erdt_ibrd +{ + ACPI_SUBTBL_HDR_16 Header; + UINT32 Reserved1; + UINT32 Flags; + UINT8 IndexFn; + UINT8 Reserved2[11]; + UINT64 RegBase; + UINT32 RegSize; + UINT16 TotalBwOffset; + UINT16 IOMissBwOffset; + UINT16 TotalBwClump; + UINT16 IOMissBwClump; + UINT8 Reserved3[7]; + UINT8 CounterWidth; + UINT64 UpScale; + UINT32 CorrFactorListLen; + UINT32 CorrFactorList[]; + +} ACPI_ERDT_IBRD; + + +/* 9: IBAD - IO bandwidth Allocation Registers for device agents */ + +typedef struct acpi_erdt_ibad +{ + ACPI_SUBTBL_HDR_16 Header; + +} ACPI_ERDT_IBAD; + + +/* 10: CARD - IO bandwidth Allocation Registers for Device Agents */ + +typedef struct acpi_erdt_card +{ + ACPI_SUBTBL_HDR_16 Header; + UINT32 Reserved1; + UINT32 Flags; + UINT32 ContentionMask; + UINT8 IndexFn; + UINT8 Reserved2[7]; + UINT64 RegBase; + UINT32 RegSize; + UINT16 CatRegOffset; + UINT16 CatRegBlockSize; + +} ACPI_ERDT_CARD; + + +/******************************************************************************* + * + * IORT - IO Remapping Table + * + * Conforms to "IO Remapping Table System Software on ARM Platforms", + * Document number: ARM DEN 0049E.f, Apr 2024 + * + ******************************************************************************/ + +typedef struct acpi_table_iort +{ + ACPI_TABLE_HEADER Header; + UINT32 NodeCount; + UINT32 NodeOffset; + UINT32 Reserved; + +} ACPI_TABLE_IORT; + + +/* + * IORT subtables + */ +typedef struct acpi_iort_node +{ + UINT8 Type; + UINT16 Length; + UINT8 Revision; + UINT32 Identifier; + UINT32 MappingCount; + UINT32 MappingOffset; + char NodeData[]; + +} ACPI_IORT_NODE; + +/* Values for subtable Type above */ + +enum AcpiIortNodeType +{ + ACPI_IORT_NODE_ITS_GROUP = 0x00, + ACPI_IORT_NODE_NAMED_COMPONENT = 0x01, + ACPI_IORT_NODE_PCI_ROOT_COMPLEX = 0x02, + ACPI_IORT_NODE_SMMU = 0x03, + ACPI_IORT_NODE_SMMU_V3 = 0x04, + ACPI_IORT_NODE_PMCG = 0x05, + ACPI_IORT_NODE_RMR = 0x06, + ACPI_IORT_NODE_IWB = 0x07, +}; + + +typedef struct acpi_iort_id_mapping +{ + UINT32 InputBase; /* Lowest value in input range */ + UINT32 IdCount; /* Number of IDs */ + UINT32 OutputBase; /* Lowest value in output range */ + UINT32 OutputReference; /* A reference to the output node */ + UINT32 Flags; + +} ACPI_IORT_ID_MAPPING; + +/* Masks for Flags field above for IORT subtable */ + +#define ACPI_IORT_ID_SINGLE_MAPPING (1) + + +typedef struct acpi_iort_memory_access +{ + UINT32 CacheCoherency; + UINT8 Hints; + UINT16 Reserved; + UINT8 MemoryFlags; + +} ACPI_IORT_MEMORY_ACCESS; + +/* Values for CacheCoherency field above */ + +#define ACPI_IORT_NODE_COHERENT 0x00000001 /* The device node is fully coherent */ +#define ACPI_IORT_NODE_NOT_COHERENT 0x00000000 /* The device node is not coherent */ + +/* Masks for Hints field above */ + +#define ACPI_IORT_HT_TRANSIENT (1) +#define ACPI_IORT_HT_WRITE (1<<1) +#define ACPI_IORT_HT_READ (1<<2) +#define ACPI_IORT_HT_OVERRIDE (1<<3) + +/* Masks for MemoryFlags field above */ + +#define ACPI_IORT_MF_COHERENCY (1) +#define ACPI_IORT_MF_ATTRIBUTES (1<<1) +#define ACPI_IORT_MF_CANWBS (1<<2) + + +/* + * IORT node specific subtables + */ +typedef struct acpi_iort_its_group +{ + UINT32 ItsCount; + UINT32 Identifiers[]; /* GIC ITS identifier array */ + +} ACPI_IORT_ITS_GROUP; + + +typedef struct acpi_iort_named_component +{ + UINT32 NodeFlags; + UINT64 MemoryProperties; /* Memory access properties */ + UINT8 MemoryAddressLimit; /* Memory address size limit */ + char DeviceName[]; /* Path of namespace object */ + +} ACPI_IORT_NAMED_COMPONENT; + +/* Masks for Flags field above */ + +#define ACPI_IORT_NC_STALL_SUPPORTED (1) +#define ACPI_IORT_NC_PASID_BITS (31<<1) + +typedef struct acpi_iort_root_complex +{ + UINT64 MemoryProperties; /* Memory access properties */ + UINT32 AtsAttribute; + UINT32 PciSegmentNumber; + UINT8 MemoryAddressLimit; /* Memory address size limit */ + UINT16 PasidCapabilities; /* PASID Capabilities */ + UINT8 Reserved[]; /* Reserved, must be zero */ + +} ACPI_IORT_ROOT_COMPLEX; + +/* Masks for AtsAttribute field above */ + +#define ACPI_IORT_ATS_SUPPORTED (1) /* The root complex ATS support */ +#define ACPI_IORT_PRI_SUPPORTED (1<<1) /* The root complex PRI support */ +#define ACPI_IORT_PASID_FWD_SUPPORTED (1<<2) /* The root complex PASID forward support */ + +/* Masks for PasidCapabilities field above */ +#define ACPI_IORT_PASID_MAX_WIDTH (0x1F) /* Bits 0-4 */ + +typedef struct acpi_iort_smmu +{ + UINT64 BaseAddress; /* SMMU base address */ + UINT64 Span; /* Length of memory range */ + UINT32 Model; + UINT32 Flags; + UINT32 GlobalInterruptOffset; + UINT32 ContextInterruptCount; + UINT32 ContextInterruptOffset; + UINT32 PmuInterruptCount; + UINT32 PmuInterruptOffset; + UINT64 Interrupts[]; /* Interrupt array */ + +} ACPI_IORT_SMMU; + +/* Values for Model field above */ + +#define ACPI_IORT_SMMU_V1 0x00000000 /* Generic SMMUv1 */ +#define ACPI_IORT_SMMU_V2 0x00000001 /* Generic SMMUv2 */ +#define ACPI_IORT_SMMU_CORELINK_MMU400 0x00000002 /* ARM Corelink MMU-400 */ +#define ACPI_IORT_SMMU_CORELINK_MMU500 0x00000003 /* ARM Corelink MMU-500 */ +#define ACPI_IORT_SMMU_CORELINK_MMU401 0x00000004 /* ARM Corelink MMU-401 */ +#define ACPI_IORT_SMMU_CAVIUM_THUNDERX 0x00000005 /* Cavium ThunderX SMMUv2 */ + +/* Masks for Flags field above */ + +#define ACPI_IORT_SMMU_DVM_SUPPORTED (1) +#define ACPI_IORT_SMMU_COHERENT_WALK (1<<1) + +/* Global interrupt format */ + +typedef struct acpi_iort_smmu_gsi +{ + UINT32 NSgIrpt; + UINT32 NSgIrptFlags; + UINT32 NSgCfgIrpt; + UINT32 NSgCfgIrptFlags; + +} ACPI_IORT_SMMU_GSI; + + +typedef struct acpi_iort_smmu_v3 +{ + UINT64 BaseAddress; /* SMMUv3 base address */ + UINT32 Flags; + UINT32 Reserved; + UINT64 VatosAddress; + UINT32 Model; + UINT32 EventGsiv; + UINT32 PriGsiv; + UINT32 GerrGsiv; + UINT32 SyncGsiv; + UINT32 Pxm; + UINT32 IdMappingIndex; + +} ACPI_IORT_SMMU_V3; + +/* Values for Model field above */ + +#define ACPI_IORT_SMMU_V3_GENERIC 0x00000000 /* Generic SMMUv3 */ +#define ACPI_IORT_SMMU_V3_HISILICON_HI161X 0x00000001 /* HiSilicon Hi161x SMMUv3 */ +#define ACPI_IORT_SMMU_V3_CAVIUM_CN99XX 0x00000002 /* Cavium CN99xx SMMUv3 */ + +/* Masks for Flags field above */ + +#define ACPI_IORT_SMMU_V3_COHACC_OVERRIDE (1) +#define ACPI_IORT_SMMU_V3_HTTU_OVERRIDE (3<<1) +#define ACPI_IORT_SMMU_V3_PXM_VALID (1<<3) +#define ACPI_IORT_SMMU_V3_DEVICEID_VALID (1<<4) + +typedef struct acpi_iort_pmcg +{ + UINT64 Page0BaseAddress; + UINT32 OverflowGsiv; + UINT32 NodeReference; + UINT64 Page1BaseAddress; + +} ACPI_IORT_PMCG; + +typedef struct acpi_iort_rmr { + UINT32 Flags; + UINT32 RmrCount; + UINT32 RmrOffset; + +} ACPI_IORT_RMR; + +/* Masks for Flags field above */ +#define ACPI_IORT_RMR_REMAP_PERMITTED (1) +#define ACPI_IORT_RMR_ACCESS_PRIVILEGE (1<<1) + +/* + * Macro to access the Access Attributes in flags field above: + * Access Attributes is encoded in bits 9:2 + */ +#define ACPI_IORT_RMR_ACCESS_ATTRIBUTES(flags) (((flags) >> 2) & 0xFF) + +/* Values for above Access Attributes */ + +#define ACPI_IORT_RMR_ATTR_DEVICE_NGNRNE 0x00 +#define ACPI_IORT_RMR_ATTR_DEVICE_NGNRE 0x01 +#define ACPI_IORT_RMR_ATTR_DEVICE_NGRE 0x02 +#define ACPI_IORT_RMR_ATTR_DEVICE_GRE 0x03 +#define ACPI_IORT_RMR_ATTR_NORMAL_NC 0x04 +#define ACPI_IORT_RMR_ATTR_NORMAL_IWB_OWB 0x05 + +typedef struct acpi_iort_rmr_desc { + UINT64 BaseAddress; + UINT64 Length; + UINT32 Reserved; + +} ACPI_IORT_RMR_DESC; + +typedef struct acpi_iort_iwb { + UINT64 BaseAddress; + UINT16 IwbIndex; /* Unique IWB identifier matching with the IWB GSI namespace. */ + char DeviceName[]; /* Path of the IWB namespace object */ + +} ACPI_IORT_IWB; + + +/******************************************************************************* + * + * IOVT - I/O Virtualization Table + * + * Conforms to "LoongArch I/O Virtualization Table", + * Version 0.1, October 2024 + * + ******************************************************************************/ + +typedef struct acpi_table_iovt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT16 IommuCount; + UINT16 IommuOffset; + UINT8 Reserved[8]; + +} ACPI_TABLE_IOVT; + +/* IOVT subtable header */ + +typedef struct acpi_iovt_header +{ + UINT16 Type; + UINT16 Length; + +} ACPI_IOVT_HEADER; + +/* Values for Type field above */ + +enum AcpiIovtIommuType +{ + ACPI_IOVT_IOMMU_V1 = 0x00, + ACPI_IOVT_IOMMU_RESERVED = 0x01 /* 1 and greater are reserved */ +}; + +/* IOVT subtables */ + +typedef struct acpi_iovt_iommu +{ + ACPI_IOVT_HEADER Header; + UINT32 Flags; + UINT16 Segment; + UINT16 PhyWidth; /* Physical Address Width */ + UINT16 VirtWidth; /* Virtual Address Width */ + UINT16 MaxPageLevel; + UINT64 PageSize; + UINT32 DeviceId; + UINT64 BaseAddress; + UINT32 AddressSpaceSize; + UINT8 InterruptType; + UINT8 Reserved[3]; + UINT32 GsiNumber; + UINT32 ProximityDomain; + UINT32 MaxDeviceNum; + UINT32 DeviceEntryNum; + UINT32 DeviceEntryOffset; + +} ACPI_IOVT_IOMMU; + +/* Masks for Flags field above */ + +#define ACPI_IOVT_IOMMU_PCI_DEVICE (1<<0) +#define ACPI_IOVT_IOMMU_PXM_VALID (1<<1) +#define ACPI_IOVT_IOMMU_MAGAGE_BY_SEGMENT (1<<2) +#define ACPI_IOVT_IOMMU_HW_CAP_SUPPORT (1<<3) +#define ACPI_IOVT_IOMMU_MSI_INT_BYPASS (1<<4) + +typedef struct acpi_iovt_device_entry +{ + UINT8 Type; + UINT8 Length; + UINT8 Flags; + UINT8 Reserved[3]; + UINT16 DeviceId; + +} ACPI_IOVT_DEVICE_ENTRY; + +enum AcpiIovtDeviceEntryType +{ + ACPI_IOVT_DEVICE_ENTRY_SINGLE = 0x00, + ACPI_IOVT_DEVICE_ENTRY_START = 0x01, + ACPI_IOVT_DEVICE_ENTRY_END = 0x02, + ACPI_IOVT_DEVICE_ENTRY_RESERVED = 0x03 /* 3 and greater are reserved */ +}; + + +/******************************************************************************* + * + * 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_HARDWARE1 = 0x10, + ACPI_IVRS_TYPE_HARDWARE2 = 0x11, + ACPI_IVRS_TYPE_HARDWARE3 = 0x40, + 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_10 +{ + 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 FeatureReporting; + +} ACPI_IVRS_HARDWARE1; + +/* 0x11: I/O Virtualization Hardware Definition Block (IVHD) */ + +typedef struct acpi_ivrs_hardware_11 +{ + 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 Attributes; + UINT64 EfrRegisterImage; + UINT64 Reserved; +} ACPI_IVRS_HARDWARE2; + +/* 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 */ + + /* Variable-length device entries */ + + ACPI_IVRS_TYPE_HID = 240 /* Uses ACPI_IVRS_DEVICE_HID */ +}; + +/* 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 + +/* Type 240: variable-length device entry */ + +typedef struct acpi_ivrs_device_hid +{ + ACPI_IVRS_DE_HEADER Header; + UINT64 AcpiHid; + UINT64 AcpiCid; + UINT8 UidType; + UINT8 UidLength; + +} ACPI_IVRS_DEVICE_HID; + +/* Values for UidType above */ + +#define ACPI_IVRS_UID_NOT_PRESENT 0 +#define ACPI_IVRS_UID_IS_INTEGER 1 +#define ACPI_IVRS_UID_IS_STRING 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; + +/******************************************************************************* + * + * KEYP - Key Programming Interface for Root Complex Integrity and Data + * Encryption (IDE) + * Version 1 + * + * Conforms to "Key Programming Interface for Root Complex Integrity and Data + * Encryption (IDE)" document. See under ACPI-Related Documents. + * + ******************************************************************************/ +typedef struct acpi_table_keyp { + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 Reserved; +} ACPI_TABLE_KEYP; + +/* KEYP common subtable header */ + +typedef struct acpi_keyp_common_header { + UINT8 Type; + UINT8 Reserved; + UINT16 Length; +} ACPI_KEYP_COMMON_HEADER; + +/* Values for Type field above */ + +enum AcpiKeypType +{ + ACPI_KEYP_TYPE_CONFIG_UNIT = 0, + ACPI_KEYP_TYPE_RESERVED = 1, +}; + +/* Root Port Information Structure */ + +typedef struct acpi_keyp_rp_info { + UINT16 Segment; + UINT8 Bus; + UINT8 Devfn; +} ACPI_KEYP_RP_INFO; + +/* Key Configuration Unit Structure */ + +typedef struct acpi_keyp_config_unit { + ACPI_KEYP_COMMON_HEADER Header; + UINT8 ProtocolType; + UINT8 Version; + UINT8 RootPortCount; + UINT8 Flags; + UINT64 RegisterBaseAddress; + ACPI_KEYP_RP_INFO RpInfo[]; +} ACPI_KEYP_CONFIG_UNIT; + +enum AcpiKeypProtocolType +{ + ACPI_KEYP_PROTO_TYPE_INVALID = 0, + ACPI_KEYP_PROTO_TYPE_PCIE, + ACPI_KEYP_PROTO_TYPE_CXL, + ACPI_KEYP_PROTO_TYPE_RESERVED +}; + +/* Only version 1 of the KCU Structure is currently defined in the spec*/ + +#define ACPI_KEYP_CONFIG_UNIT_VERSION 1 + +#define ACPI_KEYP_F_TVM_USABLE (1) + +/******************************************************************************* + * + * LPIT - Low Power Idle Table + * + * Conforms to "ACPI Low Power Idle Table (LPIT)" July 2014. + * + ******************************************************************************/ + +typedef struct acpi_table_lpit +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + +} ACPI_TABLE_LPIT; + + +/* LPIT subtable header */ + +typedef struct acpi_lpit_header +{ + UINT32 Type; /* Subtable type */ + UINT32 Length; /* Subtable length */ + UINT16 UniqueId; + UINT16 Reserved; + UINT32 Flags; + +} ACPI_LPIT_HEADER; + +/* Values for subtable Type above */ + +enum AcpiLpitType +{ + ACPI_LPIT_TYPE_NATIVE_CSTATE = 0x00, + ACPI_LPIT_TYPE_RESERVED = 0x01 /* 1 and above are reserved */ +}; + +/* Masks for Flags field above */ + +#define ACPI_LPIT_STATE_DISABLED (1) +#define ACPI_LPIT_NO_COUNTER (1<<1) + +/* + * LPIT subtables, correspond to Type in ACPI_LPIT_HEADER + */ + +/* 0x00: Native C-state instruction based LPI structure */ + +typedef struct acpi_lpit_native +{ + ACPI_LPIT_HEADER Header; + ACPI_GENERIC_ADDRESS EntryTrigger; + UINT32 Residency; + UINT32 Latency; + ACPI_GENERIC_ADDRESS ResidencyCounter; + UINT64 CounterFrequency; + +} ACPI_LPIT_NATIVE; + + +/******************************************************************************* + * + * 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 1 +#define ACPI_MADT_MULTIPLE_APIC 0 + + +/* 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_GENERIC_MSI_FRAME = 13, + ACPI_MADT_TYPE_GENERIC_REDISTRIBUTOR = 14, + ACPI_MADT_TYPE_GENERIC_TRANSLATOR = 15, + ACPI_MADT_TYPE_MULTIPROC_WAKEUP = 16, + ACPI_MADT_TYPE_CORE_PIC = 17, + ACPI_MADT_TYPE_LIO_PIC = 18, + ACPI_MADT_TYPE_HT_PIC = 19, + ACPI_MADT_TYPE_EIO_PIC = 20, + ACPI_MADT_TYPE_MSI_PIC = 21, + ACPI_MADT_TYPE_BIO_PIC = 22, + ACPI_MADT_TYPE_LPC_PIC = 23, + ACPI_MADT_TYPE_RINTC = 24, + ACPI_MADT_TYPE_IMSIC = 25, + ACPI_MADT_TYPE_APLIC = 26, + ACPI_MADT_TYPE_PLIC = 27, + ACPI_MADT_TYPE_GICV5_IRS = 28, + ACPI_MADT_TYPE_GICV5_ITS = 29, + ACPI_MADT_TYPE_GICV5_ITS_TRANSLATE = 30, + ACPI_MADT_TYPE_RESERVED = 31, /* 31 to 0x7F are reserved */ + ACPI_MADT_TYPE_OEM_RESERVED = 0x80 /* 0x80 to 0xFF are reserved for OEM use */ +}; + + +/* + * MADT Subtables, 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[]; /* 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 - GICC (ACPI 5.0 + ACPI 6.0 + ACPI 6.3 + ACPI 6.5 + ACPI 6.7 changes) */ + +typedef struct acpi_madt_generic_interrupt +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 Reserved; /* Reserved - must be zero */ + UINT32 CpuInterfaceNumber; + UINT32 Uid; + UINT32 Flags; + UINT32 ParkingVersion; + UINT32 PerformanceInterrupt; + UINT64 ParkedAddress; + UINT64 BaseAddress; + UINT64 GicvBaseAddress; + UINT64 GichBaseAddress; + UINT32 VgicInterrupt; + UINT64 GicrBaseAddress; + UINT64 ArmMpidr; + UINT8 EfficiencyClass; + UINT8 Reserved2[1]; + UINT16 SpeInterrupt; /* ACPI 6.3 */ + UINT16 TrbeInterrupt; /* ACPI 6.5 */ + UINT16 Iaffid; /* ACPI 6.7 */ + UINT32 IrsId; + +} ACPI_MADT_GENERIC_INTERRUPT; + +/* Masks for Flags field above */ + +/* ACPI_MADT_ENABLED (1) Processor is usable if set */ +#define ACPI_MADT_PERFORMANCE_IRQ_MODE (1<<1) /* 01: Performance Interrupt Mode */ +#define ACPI_MADT_VGIC_IRQ_MODE (1<<2) /* 02: VGIC Maintenance Interrupt mode */ +#define ACPI_MADT_GICC_ONLINE_CAPABLE (1<<3) /* 03: Processor is online capable */ +#define ACPI_MADT_GICC_NON_COHERENT (1<<4) /* 04: GIC redistributor is not coherent */ + +/* 12: Generic Distributor (ACPI 5.0 + ACPI 6.0 changes) */ + +typedef struct acpi_madt_generic_distributor +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 Reserved; /* Reserved - must be zero */ + UINT32 GicId; + UINT64 BaseAddress; + UINT32 GlobalIrqBase; + UINT8 Version; + UINT8 Reserved2[3]; /* Reserved - must be zero */ + +} ACPI_MADT_GENERIC_DISTRIBUTOR; + +/* Values for Version field above and Version field in acpi_madt_gicv5_irs */ + +enum AcpiMadtGicVersion +{ + ACPI_MADT_GIC_VERSION_NONE = 0, + ACPI_MADT_GIC_VERSION_V1 = 1, + ACPI_MADT_GIC_VERSION_V2 = 2, + ACPI_MADT_GIC_VERSION_V3 = 3, + ACPI_MADT_GIC_VERSION_V4 = 4, + ACPI_MADT_GIC_VERSION_V5 = 5, + ACPI_MADT_GIC_VERSION_RESERVED = 6 /* 6 and greater are reserved */ +}; + + +/* 13: Generic MSI Frame (ACPI 5.1) */ + +typedef struct acpi_madt_generic_msi_frame +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 Reserved; /* Reserved - must be zero */ + UINT32 MsiFrameId; + UINT64 BaseAddress; + UINT32 Flags; + UINT16 SpiCount; + UINT16 SpiBase; + +} ACPI_MADT_GENERIC_MSI_FRAME; + +/* Masks for Flags field above */ + +#define ACPI_MADT_OVERRIDE_SPI_VALUES (1) + + +/* 14: Generic Redistributor (ACPI 5.1) */ + +typedef struct acpi_madt_generic_redistributor +{ + ACPI_SUBTABLE_HEADER Header; + UINT8 Flags; + UINT8 Reserved; /* reserved - must be zero */ + UINT64 BaseAddress; + UINT32 Length; + +} ACPI_MADT_GENERIC_REDISTRIBUTOR; + +#define ACPI_MADT_GICR_NON_COHERENT (1) + +/* 15: Generic Translator (ACPI 6.0) */ + +typedef struct acpi_madt_generic_translator +{ + ACPI_SUBTABLE_HEADER Header; + UINT8 Flags; + UINT8 Reserved; /* reserved - must be zero */ + UINT32 TranslationId; + UINT64 BaseAddress; + UINT32 Reserved2; + +} ACPI_MADT_GENERIC_TRANSLATOR; + +#define ACPI_MADT_ITS_NON_COHERENT (1) + +/* 16: Multiprocessor wakeup (ACPI 6.6) */ + +typedef struct acpi_madt_multiproc_wakeup +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 MailboxVersion; + UINT32 Reserved; /* reserved - must be zero */ + UINT64 BaseAddress; + UINT64 ResetVector; + +} ACPI_MADT_MULTIPROC_WAKEUP; + +#define ACPI_MULTIPROC_WAKEUP_MB_OS_SIZE 2032 +#define ACPI_MULTIPROC_WAKEUP_MB_FIRMWARE_SIZE 2048 + +typedef struct acpi_madt_multiproc_wakeup_mailbox +{ + UINT16 Command; + UINT16 Reserved; /* reserved - must be zero */ + UINT32 ApicId; + UINT64 WakeupVector; + UINT8 ReservedOs[ACPI_MULTIPROC_WAKEUP_MB_OS_SIZE]; /* reserved for OS use */ + UINT8 ReservedFirmware[ACPI_MULTIPROC_WAKEUP_MB_FIRMWARE_SIZE]; /* reserved for firmware use */ + +} ACPI_MADT_MULTIPROC_WAKEUP_MAILBOX; + +#define ACPI_MP_WAKE_COMMAND_WAKEUP 1 +#define ACPI_MP_WAKE_COMMAND_TEST 2 + +/* 17: CPU Core Interrupt Controller (ACPI 6.5) */ + +typedef struct acpi_madt_core_pic { + ACPI_SUBTABLE_HEADER Header; + UINT8 Version; + UINT32 ProcessorId; + UINT32 CoreId; + UINT32 Flags; +} ACPI_MADT_CORE_PIC; + +/* Values for Version field above */ + +enum AcpiMadtCorePicVersion { + ACPI_MADT_CORE_PIC_VERSION_NONE = 0, + ACPI_MADT_CORE_PIC_VERSION_V1 = 1, + ACPI_MADT_CORE_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */ +}; + +/* 18: Legacy I/O Interrupt Controller (ACPI 6.5) */ + +typedef struct acpi_madt_lio_pic { + ACPI_SUBTABLE_HEADER Header; + UINT8 Version; + UINT64 Address; + UINT16 Size; + UINT8 Cascade[2]; + UINT32 CascadeMap[2]; +} ACPI_MADT_LIO_PIC; + +/* Values for Version field above */ + +enum AcpiMadtLioPicVersion { + ACPI_MADT_LIO_PIC_VERSION_NONE = 0, + ACPI_MADT_LIO_PIC_VERSION_V1 = 1, + ACPI_MADT_LIO_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */ +}; + +/* 19: HT Interrupt Controller (ACPI 6.5) */ + +typedef struct acpi_madt_ht_pic { + ACPI_SUBTABLE_HEADER Header; + UINT8 Version; + UINT64 Address; + UINT16 Size; + UINT8 Cascade[8]; +} ACPI_MADT_HT_PIC; + +/* Values for Version field above */ + +enum AcpiMadtHtPicVersion { + ACPI_MADT_HT_PIC_VERSION_NONE = 0, + ACPI_MADT_HT_PIC_VERSION_V1 = 1, + ACPI_MADT_HT_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */ +}; + +/* 20: Extend I/O Interrupt Controller (ACPI 6.5) */ + +typedef struct acpi_madt_eio_pic { + ACPI_SUBTABLE_HEADER Header; + UINT8 Version; + UINT8 Cascade; + UINT8 Node; + UINT64 NodeMap; +} ACPI_MADT_EIO_PIC; + +/* Values for Version field above */ + +enum AcpiMadtEioPicVersion { + ACPI_MADT_EIO_PIC_VERSION_NONE = 0, + ACPI_MADT_EIO_PIC_VERSION_V1 = 1, + ACPI_MADT_EIO_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */ +}; + +/* 21: MSI Interrupt Controller (ACPI 6.5) */ + +typedef struct acpi_madt_msi_pic { + ACPI_SUBTABLE_HEADER Header; + UINT8 Version; + UINT64 MsgAddress; + UINT32 Start; + UINT32 Count; +} ACPI_MADT_MSI_PIC; + +/* Values for Version field above */ + +enum AcpiMadtMsiPicVersion { + ACPI_MADT_MSI_PIC_VERSION_NONE = 0, + ACPI_MADT_MSI_PIC_VERSION_V1 = 1, + ACPI_MADT_MSI_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */ +}; + +/* 22: Bridge I/O Interrupt Controller (ACPI 6.5) */ + +typedef struct acpi_madt_bio_pic { + ACPI_SUBTABLE_HEADER Header; + UINT8 Version; + UINT64 Address; + UINT16 Size; + UINT16 Id; + UINT16 GsiBase; +} ACPI_MADT_BIO_PIC; + +/* Values for Version field above */ + +enum AcpiMadtBioPicVersion { + ACPI_MADT_BIO_PIC_VERSION_NONE = 0, + ACPI_MADT_BIO_PIC_VERSION_V1 = 1, + ACPI_MADT_BIO_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */ +}; + +/* 23: LPC Interrupt Controller (ACPI 6.5) */ + +typedef struct acpi_madt_lpc_pic { + ACPI_SUBTABLE_HEADER Header; + UINT8 Version; + UINT64 Address; + UINT16 Size; + UINT8 Cascade; +} ACPI_MADT_LPC_PIC; + +/* Values for Version field above */ + +enum AcpiMadtLpcPicVersion { + ACPI_MADT_LPC_PIC_VERSION_NONE = 0, + ACPI_MADT_LPC_PIC_VERSION_V1 = 1, + ACPI_MADT_LPC_PIC_VERSION_RESERVED = 2 /* 2 and greater are reserved */ +}; + +/* 24: RISC-V INTC */ +typedef struct acpi_madt_rintc { + ACPI_SUBTABLE_HEADER Header; + UINT8 Version; + UINT8 Reserved; + UINT32 Flags; + UINT64 HartId; + UINT32 Uid; /* ACPI processor UID */ + UINT32 ExtIntcId; /* External INTC Id */ + UINT64 ImsicAddr; /* IMSIC base address */ + UINT32 ImsicSize; /* IMSIC size */ +} ACPI_MADT_RINTC; + +/* Values for RISC-V INTC Version field above */ + +enum AcpiMadtRintcVersion { + ACPI_MADT_RINTC_VERSION_NONE = 0, + ACPI_MADT_RINTC_VERSION_V1 = 1, + ACPI_MADT_RINTC_VERSION_RESERVED = 2 /* 2 and greater are reserved */ +}; + +/* 25: RISC-V IMSIC */ +typedef struct acpi_madt_imsic { + ACPI_SUBTABLE_HEADER Header; + UINT8 Version; + UINT8 Reserved; + UINT32 Flags; + UINT16 NumIds; + UINT16 NumGuestIds; + UINT8 GuestIndexBits; + UINT8 HartIndexBits; + UINT8 GroupIndexBits; + UINT8 GroupIndexShift; +} ACPI_MADT_IMSIC; + +/* 26: RISC-V APLIC */ +typedef struct acpi_madt_aplic { + ACPI_SUBTABLE_HEADER Header; + UINT8 Version; + UINT8 Id; + UINT32 Flags; + UINT8 HwId[8]; + UINT16 NumIdcs; + UINT16 NumSources; + UINT32 GsiBase; + UINT64 BaseAddr; + UINT32 Size; +} ACPI_MADT_APLIC; + +/* 27: RISC-V PLIC */ +typedef struct acpi_madt_plic { + ACPI_SUBTABLE_HEADER Header; + UINT8 Version; + UINT8 Id; + UINT8 HwId[8]; + UINT16 NumIrqs; + UINT16 MaxPrio; + UINT32 Flags; + UINT32 Size; + UINT64 BaseAddr; + UINT32 GsiBase; +} ACPI_MADT_PLIC; + +/* 28: Arm GICv5 IRS (ACPI 6.7) */ +typedef struct acpi_madt_gicv5_irs { + ACPI_SUBTABLE_HEADER Header; + UINT8 Version; + UINT8 Reserved; + UINT32 IrsId; + UINT32 Flags; + UINT32 Reserved2; + UINT64 ConfigBaseAddress; + UINT64 SetlpiBaseAddress; +} ACPI_MADT_GICV5_IRS; + +#define ACPI_MADT_IRS_NON_COHERENT (1) + + +/* 29: Arm GICv5 ITS Config Frame (ACPI 6.7) */ +typedef struct acpi_madt_gicv5_translator +{ + ACPI_SUBTABLE_HEADER Header; + UINT8 Flags; + UINT8 Reserved; /* reserved - must be zero */ + UINT32 TranslatorId; + UINT64 BaseAddress; + +} ACPI_MADT_GICv5_ITS; + +#define ACPI_MADT_GICV5_ITS_NON_COHERENT (1) + +/* 30: Arm GICv5 ITS Translate Frame (ACPI 6.7) */ +typedef struct acpi_madt_gicv5_translate_frame +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 Reserved; /* reserved - must be zero */ + UINT32 LinkedTranslatorId; + UINT32 TranslateFrameId; + UINT32 Reserved2; + UINT64 BaseAddress; + +} ACPI_MADT_GICv5_ITS_TRANSLATE; + + +/* 80: OEM data */ + +typedef struct acpi_madt_oem_data +{ + ACPI_FLEX_ARRAY(UINT8, OemData); +} ACPI_MADT_OEM_DATA; + + +/* + * Common flags fields for MADT subtables + */ + +/* MADT Local APIC flags */ + +#define ACPI_MADT_ENABLED (1) /* 00: Processor is usable if set */ +#define ACPI_MADT_ONLINE_CAPABLE (2) /* 01: System HW supports enabling processor at runtime */ + +/* 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) + + +/******************************************************************************* + * + * MCFG - PCI Memory Mapped Configuration table and subtable + * 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; + + +/******************************************************************************* + * + * MISC - Miscellaneous GUIDed Table + * + * Conforms to section "Miscellaneous GUIDed Table Entries" of ACPI + * Specification v6.5 + * + ******************************************************************************/ + +typedef struct acpi_misc_guid_entry { + UINT8 EntryGuid[16]; + UINT32 EntryLength; + UINT32 Revision; + char ProducerId[ACPI_NAMESEG_SIZE] ACPI_NONSTRING; /* ACPI Vendor ID */ + UINT8 Data[]; +} ACPI_MISC_GUID_ENTRY; + +/* Minimum length of a MISC entry (the header fields, without any Data) */ + +#define ACPI_MISC_MIN_ENTRY_LENGTH 28 + + +typedef struct acpi_table_misc { + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + /* + * Immediately followed by one or more variable-length entries: + * ACPI_MISC_GUID_ENTRY Entries[]; + */ +} ACPI_TABLE_MISC; + +/******************************************************************************* + * + * MPAM - Memory System Resource Partitioning and Monitoring + * + * Conforms to "ACPI for Memory System Resource Partitioning and Monitoring 2.0" + * Document number: ARM DEN 0065, December, 2022. + * + ******************************************************************************/ + +/* MPAM RIS locator types. Table 11, Location types */ +enum AcpiMpamLocatorType { + ACPI_MPAM_LOCATION_TYPE_PROCESSOR_CACHE = 0, + ACPI_MPAM_LOCATION_TYPE_MEMORY = 1, + ACPI_MPAM_LOCATION_TYPE_SMMU = 2, + ACPI_MPAM_LOCATION_TYPE_MEMORY_CACHE = 3, + ACPI_MPAM_LOCATION_TYPE_ACPI_DEVICE = 4, + ACPI_MPAM_LOCATION_TYPE_INTERCONNECT = 5, + ACPI_MPAM_LOCATION_TYPE_UNKNOWN = 0xFF +}; + +/* MPAM Functional dependency descriptor. Table 10 */ +typedef struct acpi_mpam_func_deps +{ + UINT32 Producer; + UINT32 Reserved; +} ACPI_MPAM_FUNC_DEPS; + +/* MPAM Processor cache locator descriptor. Table 13 */ +typedef struct acpi_mpam_resource_cache_locator +{ + UINT64 CacheReference; + UINT32 Reserved; +} ACPI_MPAM_RESOURCE_CACHE_LOCATOR; + +/* MPAM Memory locator descriptor. Table 14 */ +typedef struct acpi_mpam_resource_memory_locator +{ + UINT64 ProximityDomain; + UINT32 Reserved; +} ACPI_MPAM_RESOURCE_MEMORY_LOCATOR; + +/* MPAM SMMU locator descriptor. Table 15 */ +typedef struct acpi_mpam_resource_smmu_locator +{ + UINT64 SmmuInterface; + UINT32 Reserved; +} ACPI_MPAM_RESOURCE_SMMU_INTERFACE; + +/* MPAM Memory-side cache locator descriptor. Table 16 */ +typedef struct acpi_mpam_resource_memcache_locator +{ + UINT8 Reserved[7]; + UINT8 Level; + UINT32 Reference; +} ACPI_MPAM_RESOURCE_MEMCACHE_INTERFACE; + +/* MPAM ACPI device locator descriptor. Table 17 */ +typedef struct acpi_mpam_resource_acpi_locator +{ + UINT64 AcpiHwId; + UINT32 AcpiUniqueId; +} ACPI_MPAM_RESOURCE_ACPI_INTERFACE; + +/* MPAM Interconnect locator descriptor. Table 18 */ +typedef struct acpi_mpam_resource_interconnect_locator +{ + UINT64 InterConnectDescTblOff; + UINT32 Reserved; +} ACPI_MPAM_RESOURCE_INTERCONNECT_INTERFACE; + +/* MPAM Locator structure. Table 12 */ +typedef struct acpi_mpam_resource_generic_locator +{ + UINT64 Descriptor1; + UINT32 Descriptor2; +} ACPI_MPAM_RESOURCE_GENERIC_LOCATOR; + +typedef union acpi_mpam_resource_locator +{ + ACPI_MPAM_RESOURCE_CACHE_LOCATOR CacheLocator; + ACPI_MPAM_RESOURCE_MEMORY_LOCATOR MemoryLocator; + ACPI_MPAM_RESOURCE_SMMU_INTERFACE SmmuLocator; + ACPI_MPAM_RESOURCE_MEMCACHE_INTERFACE MemCacheLocator; + ACPI_MPAM_RESOURCE_ACPI_INTERFACE AcpiLocator; + ACPI_MPAM_RESOURCE_INTERCONNECT_INTERFACE InterconnectIfcLocator; + ACPI_MPAM_RESOURCE_GENERIC_LOCATOR GenericLocator; +} ACPI_MPAM_RESOURCE_LOCATOR; + +/* Memory System Component Resource Node Structure Table 9 */ +typedef struct acpi_mpam_resource_node +{ + UINT32 Identifier; + UINT8 RISIndex; + UINT16 Reserved1; + UINT8 LocatorType; + ACPI_MPAM_RESOURCE_LOCATOR Locator; + UINT32 NumFunctionalDeps; +} ACPI_MPAM_RESOURCE_NODE; + +/* Memory System Component (MSC) Node Structure. Table 4 */ +typedef struct acpi_mpam_msc_node +{ + UINT16 Length; + UINT8 InterfaceType; + UINT8 Reserved; + UINT32 Identifier; + UINT64 BaseAddress; + UINT32 MMIOSize; + UINT32 OverflowInterrupt; + UINT32 OverflowInterruptFlags; + UINT32 Reserved1; + UINT32 OverflowInterruptAffinity; + UINT32 ErrorInterrupt; + UINT32 ErrorInterruptFlags; + UINT32 Reserved2; + UINT32 ErrorInterruptAffinity; + UINT32 MaxNrdyUsec; + UINT64 HardwareIdLinkedDevice; + UINT32 InstanceIdLinkedDevice; + UINT32 NumResourceNodes; +} ACPI_MPAM_MSC_NODE; + +typedef struct acpi_table_mpam +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ +} ACPI_TABLE_MPAM; + +/******************************************************************************* + * + * MPST - Memory Power State Table (ACPI 5.0) + * Version 1 + * + ******************************************************************************/ + +#define ACPI_MPST_CHANNEL_INFO \ + UINT8 ChannelId; \ + UINT8 Reserved1[3]; \ + UINT16 PowerNodeCount; \ + UINT16 Reserved2; + +/* 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; + UINT32 NumPowerStates; + UINT32 NumPhysicalComponents; + +} 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; + UINT16 Reserved; + +} ACPI_MPST_DATA_HDR; + +typedef struct acpi_mpst_power_data +{ + UINT8 StructureId; + 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; + UINT32 CommandRegister; + UINT32 StatusRegister; + UINT32 PowerStateId; + UINT32 PowerNodeId; + UINT64 EnergyConsumed; + UINT64 AveragePower; + +} ACPI_MPST_SHARED; + + +/******************************************************************************* + * + * 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; + + +/******************************************************************************* + * + * MRRM - Memory Range and Region Mapping (MRRM) table + * Conforms to "Intel Resource Director Technology Architecture Specification" + * Version 1.1, January 2025 + * + ******************************************************************************/ + +typedef struct acpi_table_mrrm +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT8 MaxMemRegion; /* Max Memory Regions supported */ + UINT8 Flags; /* Region assignment type */ + UINT8 Reserved[26]; + UINT8 Memory_Range_Entry[]; + +} ACPI_TABLE_MRRM; + +/* Flags */ +#define ACPI_MRRM_FLAGS_REGION_ASSIGNMENT_OS (1<<0) + +/******************************************************************************* + * + * Memory Range entry - Memory Range entry in MRRM table + * + ******************************************************************************/ + +typedef struct acpi_mrrm_mem_range_entry +{ + ACPI_SUBTBL_HDR_16 Header; + UINT32 Reserved0; /* Reserved */ + UINT64 AddrBase; /* Base addr of the mem range */ + UINT64 AddrLen; /* Length of the mem range */ + UINT16 RegionIdFlags; /* Valid local or remote Region-ID */ + UINT8 LocalRegionId; /* Platform-assigned static local Region-ID */ + UINT8 RemoteRegionId; /* Platform-assigned static remote Region-ID */ + UINT32 Reserved1; /* Reserved */ + /* Region-ID Programming Registers[] */ + +} ACPI_MRRM_MEM_RANGE_ENTRY; + +/* Values for RegionIdFlags above */ +#define ACPI_MRRM_VALID_REGION_ID_FLAGS_LOCAL (1<<0) +#define ACPI_MRRM_VALID_REGION_ID_FLAGS_REMOTE (1<<1) + + +/******************************************************************************* + * + * MSDM - Microsoft Data Management table + * + * Conforms to "Microsoft Software Licensing Tables (SLIC and MSDM)", + * November 29, 2011. Copyright 2011 Microsoft + * + ******************************************************************************/ + +/* Basic MSDM table is only the common ACPI header */ + +typedef struct acpi_table_msdm +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + +} ACPI_TABLE_MSDM; + + +/******************************************************************************* + * + * NFIT - NVDIMM Interface Table (ACPI 6.0+) + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_nfit +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 Reserved; /* Reserved, must be zero */ + +} ACPI_TABLE_NFIT; + +/* Subtable header for NFIT */ + +typedef struct acpi_nfit_header +{ + UINT16 Type; + UINT16 Length; + +} ACPI_NFIT_HEADER; + + +/* Values for subtable type in ACPI_NFIT_HEADER */ + +enum AcpiNfitType +{ + ACPI_NFIT_TYPE_SYSTEM_ADDRESS = 0, + ACPI_NFIT_TYPE_MEMORY_MAP = 1, + ACPI_NFIT_TYPE_INTERLEAVE = 2, + ACPI_NFIT_TYPE_SMBIOS = 3, + ACPI_NFIT_TYPE_CONTROL_REGION = 4, + ACPI_NFIT_TYPE_DATA_REGION = 5, + ACPI_NFIT_TYPE_FLUSH_ADDRESS = 6, + ACPI_NFIT_TYPE_CAPABILITIES = 7, + ACPI_NFIT_TYPE_RESERVED = 8 /* 8 and greater are reserved */ +}; + +/* + * NFIT Subtables + */ + +/* 0: System Physical Address Range Structure */ + +typedef struct acpi_nfit_system_address +{ + ACPI_NFIT_HEADER Header; + UINT16 RangeIndex; + UINT16 Flags; + UINT32 Reserved; /* Reserved, must be zero */ + UINT32 ProximityDomain; + UINT8 RangeGuid[16]; + UINT64 Address; + UINT64 Length; + UINT64 MemoryMapping; + UINT64 LocationCookie; /* ACPI 6.4 */ + +} ACPI_NFIT_SYSTEM_ADDRESS; + +/* Flags */ + +#define ACPI_NFIT_ADD_ONLINE_ONLY (1) /* 00: Add/Online Operation Only */ +#define ACPI_NFIT_PROXIMITY_VALID (1<<1) /* 01: Proximity Domain Valid */ +#define ACPI_NFIT_LOCATION_COOKIE_VALID (1<<2) /* 02: SPA location cookie valid (ACPI 6.4) */ + +/* Range Type GUIDs appear in the include/acuuid.h file */ + + +/* 1: Memory Device to System Address Range Map Structure */ + +typedef struct acpi_nfit_memory_map +{ + ACPI_NFIT_HEADER Header; + UINT32 DeviceHandle; + UINT16 PhysicalId; + UINT16 RegionId; + UINT16 RangeIndex; + UINT16 RegionIndex; + UINT64 RegionSize; + UINT64 RegionOffset; + UINT64 Address; + UINT16 InterleaveIndex; + UINT16 InterleaveWays; + UINT16 Flags; + UINT16 Reserved; /* Reserved, must be zero */ + +} ACPI_NFIT_MEMORY_MAP; + +/* Flags */ + +#define ACPI_NFIT_MEM_SAVE_FAILED (1) /* 00: Last SAVE to Memory Device failed */ +#define ACPI_NFIT_MEM_RESTORE_FAILED (1<<1) /* 01: Last RESTORE from Memory Device failed */ +#define ACPI_NFIT_MEM_FLUSH_FAILED (1<<2) /* 02: Platform flush failed */ +#define ACPI_NFIT_MEM_NOT_ARMED (1<<3) /* 03: Memory Device is not armed */ +#define ACPI_NFIT_MEM_HEALTH_OBSERVED (1<<4) /* 04: Memory Device observed SMART/health events */ +#define ACPI_NFIT_MEM_HEALTH_ENABLED (1<<5) /* 05: SMART/health events enabled */ +#define ACPI_NFIT_MEM_MAP_FAILED (1<<6) /* 06: Mapping to SPA failed */ + + +/* 2: Interleave Structure */ + +typedef struct acpi_nfit_interleave +{ + ACPI_NFIT_HEADER Header; + UINT16 InterleaveIndex; + UINT16 Reserved; /* Reserved, must be zero */ + UINT32 LineCount; + UINT32 LineSize; + UINT32 LineOffset[]; /* Variable length */ + +} ACPI_NFIT_INTERLEAVE; + + +/* 3: SMBIOS Management Information Structure */ + +typedef struct acpi_nfit_smbios +{ + ACPI_NFIT_HEADER Header; + UINT32 Reserved; /* Reserved, must be zero */ + UINT8 Data[]; /* Variable length */ + +} ACPI_NFIT_SMBIOS; + + +/* 4: NVDIMM Control Region Structure */ + +typedef struct acpi_nfit_control_region +{ + ACPI_NFIT_HEADER Header; + UINT16 RegionIndex; + UINT16 VendorId; + UINT16 DeviceId; + UINT16 RevisionId; + UINT16 SubsystemVendorId; + UINT16 SubsystemDeviceId; + UINT16 SubsystemRevisionId; + UINT8 ValidFields; + UINT8 ManufacturingLocation; + UINT16 ManufacturingDate; + UINT8 Reserved[2]; /* Reserved, must be zero */ + UINT32 SerialNumber; + UINT16 Code; + UINT16 Windows; + UINT64 WindowSize; + UINT64 CommandOffset; + UINT64 CommandSize; + UINT64 StatusOffset; + UINT64 StatusSize; + UINT16 Flags; + UINT8 Reserved1[6]; /* Reserved, must be zero */ + +} ACPI_NFIT_CONTROL_REGION; + +/* Flags */ + +#define ACPI_NFIT_CONTROL_BUFFERED (1) /* Block Data Windows implementation is buffered */ + +/* ValidFields bits */ + +#define ACPI_NFIT_CONTROL_MFG_INFO_VALID (1) /* Manufacturing fields are valid */ + + +/* 5: NVDIMM Block Data Window Region Structure */ + +typedef struct acpi_nfit_data_region +{ + ACPI_NFIT_HEADER Header; + UINT16 RegionIndex; + UINT16 Windows; + UINT64 Offset; + UINT64 Size; + UINT64 Capacity; + UINT64 StartAddress; + +} ACPI_NFIT_DATA_REGION; + + +/* 6: Flush Hint Address Structure */ + +typedef struct acpi_nfit_flush_address +{ + ACPI_NFIT_HEADER Header; + UINT32 DeviceHandle; + UINT16 HintCount; + UINT8 Reserved[6]; /* Reserved, must be zero */ + UINT64 HintAddress[]; /* Variable length */ + +} ACPI_NFIT_FLUSH_ADDRESS; + + +/* 7: Platform Capabilities Structure */ + +typedef struct acpi_nfit_capabilities +{ + ACPI_NFIT_HEADER Header; + UINT8 HighestCapability; + UINT8 Reserved[3]; /* Reserved, must be zero */ + UINT32 Capabilities; + UINT32 Reserved2; + +} ACPI_NFIT_CAPABILITIES; + +/* Capabilities Flags */ + +#define ACPI_NFIT_CAPABILITY_CACHE_FLUSH (1) /* 00: Cache Flush to NVDIMM capable */ +#define ACPI_NFIT_CAPABILITY_MEM_FLUSH (1<<1) /* 01: Memory Flush to NVDIMM capable */ +#define ACPI_NFIT_CAPABILITY_MEM_MIRRORING (1<<2) /* 02: Memory Mirroring capable */ + + +/* + * NFIT/DVDIMM device handle support - used as the _ADR for each NVDIMM + */ +typedef struct nfit_device_handle +{ + UINT32 Handle; + +} NFIT_DEVICE_HANDLE; + +/* Device handle construction and extraction macros */ + +#define ACPI_NFIT_DIMM_NUMBER_MASK 0x0000000F +#define ACPI_NFIT_CHANNEL_NUMBER_MASK 0x000000F0 +#define ACPI_NFIT_MEMORY_ID_MASK 0x00000F00 +#define ACPI_NFIT_SOCKET_ID_MASK 0x0000F000 +#define ACPI_NFIT_NODE_ID_MASK 0x0FFF0000 + +#define ACPI_NFIT_DIMM_NUMBER_OFFSET 0 +#define ACPI_NFIT_CHANNEL_NUMBER_OFFSET 4 +#define ACPI_NFIT_MEMORY_ID_OFFSET 8 +#define ACPI_NFIT_SOCKET_ID_OFFSET 12 +#define ACPI_NFIT_NODE_ID_OFFSET 16 + +/* Macro to construct a NFIT/NVDIMM device handle */ + +#define ACPI_NFIT_BUILD_DEVICE_HANDLE(dimm, channel, memory, socket, node) \ + ((dimm) | \ + ((channel) << ACPI_NFIT_CHANNEL_NUMBER_OFFSET) | \ + ((memory) << ACPI_NFIT_MEMORY_ID_OFFSET) | \ + ((socket) << ACPI_NFIT_SOCKET_ID_OFFSET) | \ + ((node) << ACPI_NFIT_NODE_ID_OFFSET)) + +/* Macros to extract individual fields from a NFIT/NVDIMM device handle */ + +#define ACPI_NFIT_GET_DIMM_NUMBER(handle) \ + ((handle) & ACPI_NFIT_DIMM_NUMBER_MASK) + +#define ACPI_NFIT_GET_CHANNEL_NUMBER(handle) \ + (((handle) & ACPI_NFIT_CHANNEL_NUMBER_MASK) >> ACPI_NFIT_CHANNEL_NUMBER_OFFSET) + +#define ACPI_NFIT_GET_MEMORY_ID(handle) \ + (((handle) & ACPI_NFIT_MEMORY_ID_MASK) >> ACPI_NFIT_MEMORY_ID_OFFSET) + +#define ACPI_NFIT_GET_SOCKET_ID(handle) \ + (((handle) & ACPI_NFIT_SOCKET_ID_MASK) >> ACPI_NFIT_SOCKET_ID_OFFSET) + +#define ACPI_NFIT_GET_NODE_ID(handle) \ + (((handle) & ACPI_NFIT_NODE_ID_MASK) >> ACPI_NFIT_NODE_ID_OFFSET) + + +/******************************************************************************* + * + * NHLT - Non HDAudio Link Table + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_nhlt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT8 EndpointsCount; + /* + * ACPI_NHLT_ENDPOINT Endpoints[]; + * ACPI_NHLT_CONFIG OEDConfig; + */ + +} ACPI_TABLE_NHLT; + +typedef struct acpi_nhlt_endpoint +{ + UINT32 Length; + UINT8 LinkType; + UINT8 InstanceId; + UINT16 VendorId; + UINT16 DeviceId; + UINT16 RevisionId; + UINT32 SubsystemId; + UINT8 DeviceType; + UINT8 Direction; + UINT8 VirtualBusId; + /* + * ACPI_NHLT_CONFIG DeviceConfig; + * ACPI_NHLT_FORMATS_CONFIG FormatsConfig; + * ACPI_NHLT_DEVICES_INFO DevicesInfo; + */ + +} ACPI_NHLT_ENDPOINT; + +/* Values for LinkType field above */ + +#define ACPI_NHLT_LINKTYPE_HDA 0 +#define ACPI_NHLT_LINKTYPE_DSP 1 +#define ACPI_NHLT_LINKTYPE_PDM 2 +#define ACPI_NHLT_LINKTYPE_SSP 3 +#define ACPI_NHLT_LINKTYPE_SLIMBUS 4 +#define ACPI_NHLT_LINKTYPE_SDW 5 +#define ACPI_NHLT_LINKTYPE_UAOL 6 + +/* Values for DeviceId field above */ + +#define ACPI_NHLT_DEVICEID_DMIC 0xAE20 +#define ACPI_NHLT_DEVICEID_BT 0xAE30 +#define ACPI_NHLT_DEVICEID_I2S 0xAE34 + +/* Values for DeviceType field above */ + +/* Device types unique to endpoint of LinkType=PDM */ +#define ACPI_NHLT_DEVICETYPE_PDM 0 +#define ACPI_NHLT_DEVICETYPE_PDM_SKL 1 +/* Device types unique to endpoint of LinkType=SSP */ +#define ACPI_NHLT_DEVICETYPE_BT 0 +#define ACPI_NHLT_DEVICETYPE_FM 1 +#define ACPI_NHLT_DEVICETYPE_MODEM 2 +#define ACPI_NHLT_DEVICETYPE_CODEC 4 + +/* Values for Direction field above */ + +#define ACPI_NHLT_DIR_RENDER 0 +#define ACPI_NHLT_DIR_CAPTURE 1 + +typedef struct acpi_nhlt_config +{ + UINT32 CapabilitiesSize; + UINT8 Capabilities[1]; + +} ACPI_NHLT_CONFIG; + +typedef struct acpi_nhlt_gendevice_config +{ + UINT8 VirtualSlot; + UINT8 ConfigType; + +} ACPI_NHLT_GENDEVICE_CONFIG; + +/* Values for ConfigType field above */ + +#define ACPI_NHLT_CONFIGTYPE_GENERIC 0 +#define ACPI_NHLT_CONFIGTYPE_MICARRAY 1 + +typedef struct acpi_nhlt_micdevice_config +{ + UINT8 VirtualSlot; + UINT8 ConfigType; + UINT8 ArrayType; + +} ACPI_NHLT_MICDEVICE_CONFIG; + +/* Values for ArrayType field above */ + +#define ACPI_NHLT_ARRAYTYPE_LINEAR2_SMALL 0xA +#define ACPI_NHLT_ARRAYTYPE_LINEAR2_BIG 0xB +#define ACPI_NHLT_ARRAYTYPE_LINEAR4_GEO1 0xC +#define ACPI_NHLT_ARRAYTYPE_PLANAR4_LSHAPED 0xD +#define ACPI_NHLT_ARRAYTYPE_LINEAR4_GEO2 0xE +#define ACPI_NHLT_ARRAYTYPE_VENDOR 0xF + +typedef struct acpi_nhlt_vendor_mic_config +{ + UINT8 Type; + UINT8 Panel; + UINT16 SpeakerPositionDistance; /* mm */ + UINT16 HorizontalOffset; /* mm */ + UINT16 VerticalOffset; /* mm */ + UINT8 FrequencyLowBand; /* 5*Hz */ + UINT8 FrequencyHighBand; /* 500*Hz */ + UINT16 DirectionAngle; /* -180 - +180 */ + UINT16 ElevationAngle; /* -180 - +180 */ + UINT16 WorkVerticalAngleBegin; /* -180 - +180 with 2 deg step */ + UINT16 WorkVerticalAngleEnd; /* -180 - +180 with 2 deg step */ + UINT16 WorkHorizontalAngleBegin; /* -180 - +180 with 2 deg step */ + UINT16 WorkHorizontalAngleEnd; /* -180 - +180 with 2 deg step */ + +} ACPI_NHLT_VENDOR_MIC_CONFIG; + +/* Values for Type field above */ + +#define ACPI_NHLT_MICTYPE_OMNIDIRECTIONAL 0 +#define ACPI_NHLT_MICTYPE_SUBCARDIOID 1 +#define ACPI_NHLT_MICTYPE_CARDIOID 2 +#define ACPI_NHLT_MICTYPE_SUPERCARDIOID 3 +#define ACPI_NHLT_MICTYPE_HYPERCARDIOID 4 +#define ACPI_NHLT_MICTYPE_8SHAPED 5 +#define ACPI_NHLT_MICTYPE_RESERVED 6 +#define ACPI_NHLT_MICTYPE_VENDORDEFINED 7 + +/* Values for Panel field above */ + +#define ACPI_NHLT_MICLOCATION_TOP 0 +#define ACPI_NHLT_MICLOCATION_BOTTOM 1 +#define ACPI_NHLT_MICLOCATION_LEFT 2 +#define ACPI_NHLT_MICLOCATION_RIGHT 3 +#define ACPI_NHLT_MICLOCATION_FRONT 4 +#define ACPI_NHLT_MICLOCATION_REAR 5 + +typedef struct acpi_nhlt_vendor_micdevice_config +{ + UINT8 VirtualSlot; + UINT8 ConfigType; + UINT8 ArrayType; + UINT8 MicsCount; + ACPI_NHLT_VENDOR_MIC_CONFIG Mics[]; + +} ACPI_NHLT_VENDOR_MICDEVICE_CONFIG; + +typedef union acpi_nhlt_device_config +{ + UINT8 VirtualSlot; + ACPI_NHLT_GENDEVICE_CONFIG Gen; + ACPI_NHLT_MICDEVICE_CONFIG Mic; + ACPI_NHLT_VENDOR_MICDEVICE_CONFIG VendorMic; + +} ACPI_NHLT_DEVICE_CONFIG; + +/* Inherited from Microsoft's WAVEFORMATEXTENSIBLE. */ +typedef struct acpi_nhlt_wave_formatext +{ + UINT16 FormatTag; + UINT16 ChannelCount; + UINT32 SamplesPerSec; + UINT32 AvgBytesPerSec; + UINT16 BlockAlign; + UINT16 BitsPerSample; + UINT16 ExtraFormatSize; + UINT16 ValidBitsPerSample; + UINT32 ChannelMask; + UINT8 Subformat[16]; + +} ACPI_NHLT_WAVE_FORMATEXT; + +typedef struct acpi_nhlt_format_config +{ + ACPI_NHLT_WAVE_FORMATEXT Format; + ACPI_NHLT_CONFIG Config; + +} ACPI_NHLT_FORMAT_CONFIG; + +typedef struct acpi_nhlt_formats_config +{ + UINT8 FormatsCount; + ACPI_NHLT_FORMAT_CONFIG Formats[]; + +} ACPI_NHLT_FORMATS_CONFIG; + +typedef struct acpi_nhlt_device_info +{ + UINT8 Id[16]; + UINT8 InstanceId; + UINT8 PortId; + +} ACPI_NHLT_DEVICE_INFO; + +typedef struct acpi_nhlt_devices_info +{ + UINT8 DevicesCount; + ACPI_NHLT_DEVICE_INFO Devices[]; + +} ACPI_NHLT_DEVICES_INFO; + + +/******************************************************************************* + * + * PCCT - Platform Communications Channel Table (ACPI 5.0) + * Version 2 (ACPI 6.2) + * + ******************************************************************************/ + +typedef struct acpi_table_pcct +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 Flags; + UINT64 Reserved; + +} ACPI_TABLE_PCCT; + +/* Values for Flags field above */ + +#define ACPI_PCCT_DOORBELL 1 + +/* Values for subtable type in ACPI_SUBTABLE_HEADER */ + +enum AcpiPcctType +{ + ACPI_PCCT_TYPE_GENERIC_SUBSPACE = 0, + ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE = 1, + ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE_TYPE2 = 2, /* ACPI 6.1 */ + ACPI_PCCT_TYPE_EXT_PCC_MASTER_SUBSPACE = 3, /* ACPI 6.2 */ + ACPI_PCCT_TYPE_EXT_PCC_SLAVE_SUBSPACE = 4, /* ACPI 6.2 */ + ACPI_PCCT_TYPE_HW_REG_COMM_SUBSPACE = 5, /* ACPI 6.4 */ + ACPI_PCCT_TYPE_RESERVED = 6 /* 6 and greater are reserved */ +}; + +/* + * PCCT Subtables, correspond to Type in ACPI_SUBTABLE_HEADER + */ + +/* 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; + UINT32 Latency; + UINT32 MaxAccessRate; + UINT16 MinTurnaroundTime; + +} ACPI_PCCT_SUBSPACE; + + +/* 1: HW-reduced Communications Subspace (ACPI 5.1) */ + +typedef struct acpi_pcct_hw_reduced +{ + ACPI_SUBTABLE_HEADER Header; + UINT32 PlatformInterrupt; + UINT8 Flags; + UINT8 Reserved; + UINT64 BaseAddress; + UINT64 Length; + ACPI_GENERIC_ADDRESS DoorbellRegister; + UINT64 PreserveMask; + UINT64 WriteMask; + UINT32 Latency; + UINT32 MaxAccessRate; + UINT16 MinTurnaroundTime; + +} ACPI_PCCT_HW_REDUCED; + + +/* 2: HW-reduced Communications Subspace Type 2 (ACPI 6.1) */ + +typedef struct acpi_pcct_hw_reduced_type2 +{ + ACPI_SUBTABLE_HEADER Header; + UINT32 PlatformInterrupt; + UINT8 Flags; + UINT8 Reserved; + UINT64 BaseAddress; + UINT64 Length; + ACPI_GENERIC_ADDRESS DoorbellRegister; + UINT64 PreserveMask; + UINT64 WriteMask; + UINT32 Latency; + UINT32 MaxAccessRate; + UINT16 MinTurnaroundTime; + ACPI_GENERIC_ADDRESS PlatformAckRegister; + UINT64 AckPreserveMask; + UINT64 AckWriteMask; + +} ACPI_PCCT_HW_REDUCED_TYPE2; + + +/* 3: Extended PCC Master Subspace Type 3 (ACPI 6.2) */ + +typedef struct acpi_pcct_ext_pcc_master +{ + ACPI_SUBTABLE_HEADER Header; + UINT32 PlatformInterrupt; + UINT8 Flags; + UINT8 Reserved1; + UINT64 BaseAddress; + UINT32 Length; + ACPI_GENERIC_ADDRESS DoorbellRegister; + UINT64 PreserveMask; + UINT64 WriteMask; + UINT32 Latency; + UINT32 MaxAccessRate; + UINT32 MinTurnaroundTime; + ACPI_GENERIC_ADDRESS PlatformAckRegister; + UINT64 AckPreserveMask; + UINT64 AckSetMask; + UINT64 Reserved2; + ACPI_GENERIC_ADDRESS CmdCompleteRegister; + UINT64 CmdCompleteMask; + ACPI_GENERIC_ADDRESS CmdUpdateRegister; + UINT64 CmdUpdatePreserveMask; + UINT64 CmdUpdateSetMask; + ACPI_GENERIC_ADDRESS ErrorStatusRegister; + UINT64 ErrorStatusMask; + +} ACPI_PCCT_EXT_PCC_MASTER; + + +/* 4: Extended PCC Slave Subspace Type 4 (ACPI 6.2) */ + +typedef struct acpi_pcct_ext_pcc_slave +{ + ACPI_SUBTABLE_HEADER Header; + UINT32 PlatformInterrupt; + UINT8 Flags; + UINT8 Reserved1; + UINT64 BaseAddress; + UINT32 Length; + ACPI_GENERIC_ADDRESS DoorbellRegister; + UINT64 PreserveMask; + UINT64 WriteMask; + UINT32 Latency; + UINT32 MaxAccessRate; + UINT32 MinTurnaroundTime; + ACPI_GENERIC_ADDRESS PlatformAckRegister; + UINT64 AckPreserveMask; + UINT64 AckSetMask; + UINT64 Reserved2; + ACPI_GENERIC_ADDRESS CmdCompleteRegister; + UINT64 CmdCompleteMask; + ACPI_GENERIC_ADDRESS CmdUpdateRegister; + UINT64 CmdUpdatePreserveMask; + UINT64 CmdUpdateSetMask; + ACPI_GENERIC_ADDRESS ErrorStatusRegister; + UINT64 ErrorStatusMask; + +} ACPI_PCCT_EXT_PCC_SLAVE; + +/* 5: HW Registers based Communications Subspace */ + +typedef struct acpi_pcct_hw_reg +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 Version; + UINT64 BaseAddress; + UINT64 Length; + ACPI_GENERIC_ADDRESS DoorbellRegister; + UINT64 DoorbellPreserve; + UINT64 DoorbellWrite; + ACPI_GENERIC_ADDRESS CmdCompleteRegister; + UINT64 CmdCompleteMask; + ACPI_GENERIC_ADDRESS ErrorStatusRegister; + UINT64 ErrorStatusMask; + UINT32 NominalLatency; + UINT32 MinTurnaroundTime; + +} ACPI_PCCT_HW_REG; + + +/* Values for doorbell flags above */ + +#define ACPI_PCCT_INTERRUPT_POLARITY (1) +#define ACPI_PCCT_INTERRUPT_MODE (1<<1) + + +/* + * 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; + + +/* Extended PCC Subspace Shared Memory Region (ACPI 6.2) */ + +typedef struct acpi_pcct_ext_pcc_shared_memory +{ + UINT32 Signature; + UINT32 Flags; + UINT32 Length; + UINT32 Command; + +} ACPI_PCCT_EXT_PCC_SHARED_MEMORY; + + +/******************************************************************************* + * + * PDTT - Platform Debug Trigger Table (ACPI 6.2) + * Version 0 + * + ******************************************************************************/ + +typedef struct acpi_table_pdtt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT8 TriggerCount; + UINT8 Reserved[3]; + UINT32 ArrayOffset; + +} ACPI_TABLE_PDTT; + + +/* + * PDTT Communication Channel Identifier Structure. + * The number of these structures is defined by TriggerCount above, + * starting at ArrayOffset. + */ +typedef struct acpi_pdtt_channel +{ + UINT8 SubchannelId; + UINT8 Flags; + +} ACPI_PDTT_CHANNEL; + +/* Flags for above */ + +#define ACPI_PDTT_RUNTIME_TRIGGER (1) +#define ACPI_PDTT_WAIT_COMPLETION (1<<1) +#define ACPI_PDTT_TRIGGER_ORDER (1<<2) + + +/******************************************************************************* + * + * PHAT - Platform Health Assessment Table (ACPI 6.4) + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_phat +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + +} ACPI_TABLE_PHAT; + +/* Common header for PHAT subtables that follow main table */ + +typedef struct acpi_phat_header +{ + UINT16 Type; + UINT16 Length; + UINT8 Revision; + +} ACPI_PHAT_HEADER; + + +/* Values for Type field above */ + +#define ACPI_PHAT_TYPE_FW_VERSION_DATA 0 +#define ACPI_PHAT_TYPE_FW_HEALTH_DATA 1 +#define ACPI_PHAT_TYPE_RESERVED 2 /* 0x02-0xFFFF are reserved */ + +/* + * PHAT subtables, correspond to Type in ACPI_PHAT_HEADER + */ + +/* 0: Firmware Version Data Record */ + +typedef struct acpi_phat_version_data +{ + ACPI_PHAT_HEADER Header; + UINT8 Reserved[3]; + UINT32 ElementCount; + +} ACPI_PHAT_VERSION_DATA; + +typedef struct acpi_phat_version_element +{ + UINT8 Guid[16]; + UINT64 VersionValue; + UINT32 ProducerId; + +} ACPI_PHAT_VERSION_ELEMENT; + + +/* 1: Firmware Health Data Record */ + +typedef struct acpi_phat_health_data +{ + ACPI_PHAT_HEADER Header; + UINT8 Reserved[2]; + UINT8 Health; + UINT8 DeviceGuid[16]; + UINT32 DeviceSpecificOffset; /* Zero if no Device-specific data */ + +} ACPI_PHAT_HEALTH_DATA; + +/* Values for Health field above */ + +#define ACPI_PHAT_ERRORS_FOUND 0 +#define ACPI_PHAT_NO_ERRORS 1 +#define ACPI_PHAT_UNKNOWN_ERRORS 2 +#define ACPI_PHAT_ADVISORY 3 + + +/******************************************************************************* + * + * PMTT - Platform Memory Topology Table (ACPI 5.0) + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_pmtt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 MemoryDeviceCount; + /* + * Immediately followed by: + * MEMORY_DEVICE MemoryDeviceStruct[MemoryDeviceCount]; + */ + +} 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; + UINT32 MemoryDeviceCount; /* Zero means no memory device structs follow */ + /* + * Immediately followed by: + * UINT8 TypeSpecificData[] + * MEMORY_DEVICE MemoryDeviceStruct[MemoryDeviceCount]; + */ + +} 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-0xFE are reserved */ +#define ACPI_PMTT_TYPE_VENDOR 0xFF + +/* 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; + /* + * Immediately followed by: + * MEMORY_DEVICE MemoryDeviceStruct[MemoryDeviceCount]; + */ + + +/* 1: Memory Controller subtable */ + +typedef struct acpi_pmtt_controller +{ + ACPI_PMTT_HEADER Header; + UINT16 ControllerId; + UINT16 Reserved; + +} ACPI_PMTT_CONTROLLER; + /* + * Immediately followed by: + * MEMORY_DEVICE MemoryDeviceStruct[MemoryDeviceCount]; + */ + + +/* 2: Physical Component Identifier (DIMM) */ + +typedef struct acpi_pmtt_physical_component +{ + ACPI_PMTT_HEADER Header; + UINT32 BiosHandle; + +} ACPI_PMTT_PHYSICAL_COMPONENT; + + +/* 0xFF: Vendor Specific Data */ + +typedef struct acpi_pmtt_vendor_specific +{ + ACPI_PMTT_HEADER Header; + UINT8 TypeUuid[16]; + UINT8 Specific[]; + /* + * Immediately followed by: + * UINT8 VendorSpecificData[]; + * MEMORY_DEVICE MemoryDeviceStruct[MemoryDeviceCount]; + */ + +} ACPI_PMTT_VENDOR_SPECIFIC; + + +/******************************************************************************* + * + * PPTT - Processor Properties Topology Table (ACPI 6.2) + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_pptt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + +} ACPI_TABLE_PPTT; + +/* Values for Type field above */ + +enum AcpiPpttType +{ + ACPI_PPTT_TYPE_PROCESSOR = 0, + ACPI_PPTT_TYPE_CACHE = 1, + ACPI_PPTT_TYPE_ID = 2, + ACPI_PPTT_TYPE_RESERVED = 3 +}; + + +/* 0: Processor Hierarchy Node Structure */ + +typedef struct acpi_pptt_processor +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 Reserved; + UINT32 Flags; + UINT32 Parent; + UINT32 AcpiProcessorId; + UINT32 NumberOfPrivResources; + +} ACPI_PPTT_PROCESSOR; + +/* Flags */ + +#define ACPI_PPTT_PHYSICAL_PACKAGE (1) +#define ACPI_PPTT_ACPI_PROCESSOR_ID_VALID (1<<1) +#define ACPI_PPTT_ACPI_PROCESSOR_IS_THREAD (1<<2) /* ACPI 6.3 */ +#define ACPI_PPTT_ACPI_LEAF_NODE (1<<3) /* ACPI 6.3 */ +#define ACPI_PPTT_ACPI_IDENTICAL (1<<4) /* ACPI 6.3 */ + + +/* 1: Cache Type Structure */ + +typedef struct acpi_pptt_cache +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 Reserved; + UINT32 Flags; + UINT32 NextLevelOfCache; + UINT32 Size; + UINT32 NumberOfSets; + UINT8 Associativity; + UINT8 Attributes; + UINT16 LineSize; + +} ACPI_PPTT_CACHE; + +/* 1: Cache Type Structure for PPTT version 3 */ + +typedef struct acpi_pptt_cache_v1 +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 Reserved; + UINT32 Flags; + UINT32 NextLevelOfCache; + UINT32 Size; + UINT32 NumberOfSets; + UINT8 Associativity; + UINT8 Attributes; + UINT16 LineSize; + UINT32 CacheId; + +} ACPI_PPTT_CACHE_V1; + + +/* Flags */ + +#define ACPI_PPTT_SIZE_PROPERTY_VALID (1) /* Physical property valid */ +#define ACPI_PPTT_NUMBER_OF_SETS_VALID (1<<1) /* Number of sets valid */ +#define ACPI_PPTT_ASSOCIATIVITY_VALID (1<<2) /* Associativity valid */ +#define ACPI_PPTT_ALLOCATION_TYPE_VALID (1<<3) /* Allocation type valid */ +#define ACPI_PPTT_CACHE_TYPE_VALID (1<<4) /* Cache type valid */ +#define ACPI_PPTT_WRITE_POLICY_VALID (1<<5) /* Write policy valid */ +#define ACPI_PPTT_LINE_SIZE_VALID (1<<6) /* Line size valid */ +#define ACPI_PPTT_CACHE_ID_VALID (1<<7) /* Cache ID valid */ + +/* Masks for Attributes */ + +#define ACPI_PPTT_MASK_ALLOCATION_TYPE (0x03) /* Allocation type */ +#define ACPI_PPTT_MASK_CACHE_TYPE (0x0C) /* Cache type */ +#define ACPI_PPTT_MASK_WRITE_POLICY (0x10) /* Write policy */ + +/* Attributes describing cache */ +#define ACPI_PPTT_CACHE_READ_ALLOCATE (0x0) /* Cache line is allocated on read */ +#define ACPI_PPTT_CACHE_WRITE_ALLOCATE (0x01) /* Cache line is allocated on write */ +#define ACPI_PPTT_CACHE_RW_ALLOCATE (0x02) /* Cache line is allocated on read and write */ +#define ACPI_PPTT_CACHE_RW_ALLOCATE_ALT (0x03) /* Alternate representation of above */ + +#define ACPI_PPTT_CACHE_TYPE_DATA (0x0) /* Data cache */ +#define ACPI_PPTT_CACHE_TYPE_INSTR (1<<2) /* Instruction cache */ +#define ACPI_PPTT_CACHE_TYPE_UNIFIED (2<<2) /* Unified I & D cache */ +#define ACPI_PPTT_CACHE_TYPE_UNIFIED_ALT (3<<2) /* Alternate representation of above */ + +#define ACPI_PPTT_CACHE_POLICY_WB (0x0) /* Cache is write back */ +#define ACPI_PPTT_CACHE_POLICY_WT (1<<4) /* Cache is write through */ + +/* 2: ID Structure */ + +typedef struct acpi_pptt_id +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 Reserved; + UINT32 VendorId; + UINT64 Level1Id; + UINT64 Level2Id; + UINT16 MajorRev; + UINT16 MinorRev; + UINT16 SpinRev; + +} ACPI_PPTT_ID; + + +/******************************************************************************* + * + * PRMT - Platform Runtime Mechanism Table + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_prmt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + +} ACPI_TABLE_PRMT; + +typedef struct acpi_table_prmt_header +{ + UINT8 PlatformGuid[16]; + UINT32 ModuleInfoOffset; + UINT32 ModuleInfoCount; + +} ACPI_TABLE_PRMT_HEADER; + +typedef struct acpi_prmt_module_header +{ + UINT16 Revision; + UINT16 Length; + +} ACPI_PRMT_MODULE_HEADER; + +typedef struct acpi_prmt_module_info +{ + UINT16 Revision; + UINT16 Length; + UINT8 ModuleGuid[16]; + UINT16 MajorRev; + UINT16 MinorRev; + UINT16 HandlerInfoCount; + UINT32 HandlerInfoOffset; + UINT64 MmioListPointer; + +} ACPI_PRMT_MODULE_INFO; + +typedef struct acpi_prmt_handler_info +{ + UINT16 Revision; + UINT16 Length; + UINT8 HandlerGuid[16]; + UINT64 HandlerAddress; + UINT64 StaticDataBufferAddress; + UINT64 AcpiParamBufferAddress; + +} ACPI_PRMT_HANDLER_INFO; + + +/******************************************************************************* + * + * 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; + UINT16 Version; + UINT8 Capabilities[16]; + UINT8 SetCapabilities[16]; + UINT16 NumParameterBlocks; + UINT32 SetCapabilitiesStatus; + +} ACPI_RASF_SHARED_MEMORY; + +/* RASF Parameter Block Structure Header */ + +typedef struct acpi_rasf_parameter_block +{ + UINT16 Type; + UINT16 Version; + UINT16 Length; + +} ACPI_RASF_PARAMETER_BLOCK; + +/* RASF Parameter Block Structure for PATROL_SCRUB */ + +typedef struct acpi_rasf_patrol_scrub_parameter +{ + ACPI_RASF_PARAMETER_BLOCK Header; + UINT16 PatrolScrubCommand; + UINT64 RequestedAddressRange[2]; + UINT64 ActualAddressRange[2]; + UINT16 Flags; + UINT8 RequestedSpeed; + +} ACPI_RASF_PATROL_SCRUB_PARAMETER; + +/* Masks for Flags and Speed fields above */ + +#define ACPI_RASF_SCRUBBER_RUNNING 1 +#define ACPI_RASF_SPEED (7<<1) +#define ACPI_RASF_SPEED_SLOW (0<<1) +#define ACPI_RASF_SPEED_MEDIUM (4<<1) +#define ACPI_RASF_SPEED_FAST (7<<1) + +/* Channel Commands */ + +enum AcpiRasfCommands +{ + ACPI_RASF_EXECUTE_RASF_COMMAND = 1 +}; + +/* Platform RAS Capabilities */ + +enum AcpiRasfCapabiliities +{ + ACPI_HW_PATROL_SCRUB_SUPPORTED = 0, + ACPI_SW_PATROL_SCRUB_EXPOSED = 1 +}; + +/* Patrol Scrub Commands */ + +enum AcpiRasfPatrolScrubCommands +{ + ACPI_RASF_GET_PATROL_PARAMETERS = 1, + ACPI_RASF_START_PATROL_SCRUBBER = 2, + ACPI_RASF_STOP_PATROL_SCRUBBER = 3 +}; + +/* 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) + + +/******************************************************************************* + * + * RAS2 - RAS2 Feature Table (ACPI 6.5) + * Version 1 + * + * + ******************************************************************************/ + +typedef struct acpi_table_ras2 { + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT16 Reserved; + UINT16 NumPccDescs; + +} ACPI_TABLE_RAS2; + +/* RAS2 Platform Communication Channel Descriptor */ + +typedef struct acpi_ras2_pcc_desc { + UINT8 ChannelId; + UINT16 Reserved; + UINT8 FeatureType; + UINT32 Instance; + +} ACPI_RAS2_PCC_DESC; + +/* RAS2 Platform Communication Channel Shared Memory Region */ + +typedef struct acpi_ras2_shmem { + UINT32 Signature; + UINT16 Command; + UINT16 Status; + UINT16 Version; + UINT8 Features[16]; + UINT8 SetCaps[16]; + UINT16 NumParamBlks; + UINT32 SetCapsStatus; + +} ACPI_RAS2_SHMEM; + +/* RAS2 Parameter Block Structure for PATROL_SCRUB */ + +typedef struct acpi_ras2_parameter_block +{ + UINT16 Type; + UINT16 Version; + UINT16 Length; + +} ACPI_RAS2_PARAMETER_BLOCK; + +/* RAS2 Parameter Block Structure for PATROL_SCRUB */ + +typedef struct acpi_ras2_patrol_scrub_param { + ACPI_RAS2_PARAMETER_BLOCK Header; + UINT16 Command; + UINT64 ReqAddrRange[2]; + UINT64 ActlAddrRange[2]; + UINT32 Flags; + UINT32 ScrubParamsOut; + UINT32 ScrubParamsIn; + UINT32 ExtScrubParams; + UINT8 ScrubRateDesc[256]; + +} ACPI_RAS2_PATROL_SCRUB_PARAM; + +/* Masks for Flags field above */ + +#define ACPI_RAS2_SCRUBBER_RUNNING 1 + +/* RAS2 Parameter Block Structure for LA2PA_TRANSLATION */ + +typedef struct acpi_ras2_la2pa_translation_parameter { + ACPI_RAS2_PARAMETER_BLOCK Header; + UINT16 AddrTranslationCommand; + UINT64 SubInstId; + UINT64 LogicalAddress; + UINT64 PhysicalAddress; + UINT32 Status; + +} ACPI_RAS2_LA2PA_TRANSLATION_PARAM; + +/* Channel Commands */ + +enum AcpiRas2Commands +{ + ACPI_RAS2_EXECUTE_RAS2_COMMAND = 1 +}; + +/* Platform RAS2 Features */ + +enum AcpiRas2Features +{ + ACPI_RAS2_PATROL_SCRUB_SUPPORTED = 0, + ACPI_RAS2_LA2PA_TRANSLATION = 1 +}; + +/* RAS2 Patrol Scrub Commands */ + +enum AcpiRas2PatrolScrubCommands +{ + ACPI_RAS2_GET_PATROL_PARAMETERS = 1, + ACPI_RAS2_START_PATROL_SCRUBBER = 2, + ACPI_RAS2_STOP_PATROL_SCRUBBER = 3 +}; + +/* RAS2 LA2PA Translation Commands */ + +enum AcpiRas2La2PaTranslationCommands +{ + ACPI_RAS2_GET_LA2PA_TRANSLATION = 1, +}; + +/* RAS2 LA2PA Translation Status values */ + +enum AcpiRas2La2PaTranslationStatus +{ + ACPI_RAS2_LA2PA_TRANSLATION_SUCCESS = 0, + ACPI_RAS2_LA2PA_TRANSLATION_FAIL = 1, +}; + +/* Channel Command flags */ + +#define ACPI_RAS2_GENERATE_SCI (1<<15) + +/* Status values */ + +enum AcpiRas2Status +{ + ACPI_RAS2_SUCCESS = 0, + ACPI_RAS2_NOT_VALID = 1, + ACPI_RAS2_NOT_SUPPORTED = 2, + ACPI_RAS2_BUSY = 3, + ACPI_RAS2_FAILED = 4, + ACPI_RAS2_ABORTED = 5, + ACPI_RAS2_INVALID_DATA = 6 +}; + +/* Status flags */ + +#define ACPI_RAS2_COMMAND_COMPLETE (1) +#define ACPI_RAS2_SCI_DOORBELL (1<<1) +#define ACPI_RAS2_ERROR (1<<2) +#define ACPI_RAS2_STATUS (0x1F<<3) + + +/******************************************************************************* + * + * RGRT - Regulatory Graphics Resource Table + * Version 1 + * + * Conforms to "ACPI RGRT" available at: + * https://microsoft.github.io/mu/dyn/mu_plus/MsCorePkg/AcpiRGRT/feature_acpi_rgrt/ + * + ******************************************************************************/ + +typedef struct acpi_table_rgrt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT16 Version; + UINT8 ImageType; + UINT8 Reserved; + UINT8 Image[]; + +} ACPI_TABLE_RGRT; + +/* ImageType values */ + +enum AcpiRgrtImageType +{ + ACPI_RGRT_TYPE_RESERVED0 = 0, + ACPI_RGRT_IMAGE_TYPE_PNG = 1, + ACPI_RGRT_TYPE_RESERVED = 2 /* 2 and greater are reserved */ +}; + + +/******************************************************************************* + * + * RHCT - RISC-V Hart Capabilities Table + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_rhct { + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 Flags; /* RHCT flags */ + UINT64 TimeBaseFreq; + UINT32 NodeCount; + UINT32 NodeOffset; +} ACPI_TABLE_RHCT; + +/* RHCT Flags */ + +#define ACPI_RHCT_TIMER_CANNOT_WAKEUP_CPU (1) +/* + * RHCT subtables + */ +typedef struct acpi_rhct_node_header { + UINT16 Type; + UINT16 Length; + UINT16 Revision; +} ACPI_RHCT_NODE_HEADER; + +/* Values for RHCT subtable Type above */ + +enum acpi_rhct_node_type { + ACPI_RHCT_NODE_TYPE_ISA_STRING = 0x0000, + ACPI_RHCT_NODE_TYPE_CMO = 0x0001, + ACPI_RHCT_NODE_TYPE_MMU = 0x0002, + ACPI_RHCT_NODE_TYPE_RESERVED = 0x0003, + ACPI_RHCT_NODE_TYPE_HART_INFO = 0xFFFF, +}; + +/* + * RHCT node specific subtables + */ + +/* ISA string node structure */ +typedef struct acpi_rhct_isa_string { + UINT16 IsaLength; + char Isa[]; +} ACPI_RHCT_ISA_STRING; + +typedef struct acpi_rhct_cmo_node { + UINT8 Reserved; /* Must be zero */ + UINT8 CbomSize; /* CBOM size in powerof 2 */ + UINT8 CbopSize; /* CBOP size in powerof 2 */ + UINT8 CbozSize; /* CBOZ size in powerof 2 */ +} ACPI_RHCT_CMO_NODE; + +typedef struct acpi_rhct_mmu_node { + UINT8 Reserved; /* Must be zero */ + UINT8 MmuType; /* Virtual Address Scheme */ +} ACPI_RHCT_MMU_NODE; + +enum acpi_rhct_mmu_type { + ACPI_RHCT_MMU_TYPE_SV39 = 0, + ACPI_RHCT_MMU_TYPE_SV48 = 1, + ACPI_RHCT_MMU_TYPE_SV57 = 2 +}; + +/* Hart Info node structure */ +typedef struct acpi_rhct_hart_info { + UINT16 NumOffsets; + UINT32 Uid; /* ACPI processor UID */ +} ACPI_RHCT_HART_INFO; + +/******************************************************************************* + * + * RIMT - RISC-V IO Remapping Table + * + * https://github.com/riscv-non-isa/riscv-acpi-rimt + * + ******************************************************************************/ + +typedef struct acpi_table_rimt { + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 NumNodes; /* Number of RIMT Nodes */ + UINT32 NodeOffset; /* Offset to RIMT Node Array */ + UINT32 Reserved; +} ACPI_TABLE_RIMT; + +typedef struct acpi_rimt_node { + UINT8 Type; + UINT8 Revision; + UINT16 Length; + UINT16 Reserved; + UINT16 Id; + char NodeData[]; +} ACPI_RIMT_NODE; + +enum acpi_rimt_node_type { + ACPI_RIMT_NODE_TYPE_IOMMU = 0x0, + ACPI_RIMT_NODE_TYPE_PCIE_ROOT_COMPLEX = 0x1, + ACPI_RIMT_NODE_TYPE_PLAT_DEVICE = 0x2, +}; + +typedef struct acpi_rimt_iommu { + UINT8 HardwareId[8]; /* Hardware ID */ + UINT64 BaseAddress; /* Base Address */ + UINT32 Flags; /* Flags */ + UINT32 ProximityDomain; /* Proximity Domain */ + UINT16 PcieSegmentNumber; /* PCIe Segment number */ + UINT16 PcieBdf; /* PCIe B/D/F */ + UINT16 NumInterruptWires; /* Number of interrupt wires */ + UINT16 InterruptWireOffset; /* Interrupt wire array offset */ + UINT64 InterruptWire[]; /* Interrupt wire array */ +} ACPI_RIMT_IOMMU; + +/* IOMMU Node Flags */ +#define ACPI_RIMT_IOMMU_FLAGS_PCIE (1) +#define ACPI_RIMT_IOMMU_FLAGS_PXM_VALID (1 << 1) + +/* Interrupt Wire Structure */ +typedef struct acpi_rimt_iommu_wire_gsi { + UINT32 IrqNum; /* Interrupt Number */ + UINT32 Flags; /* Flags */ +} ACPI_RIMT_IOMMU_WIRE_GSI; + +/* Interrupt Wire Flags */ +#define ACPI_RIMT_GSI_LEVEL_TRIGGERRED (1) +#define ACPI_RIMT_GSI_ACTIVE_HIGH (1 << 1) + +typedef struct acpi_rimt_id_mapping { + UINT32 SourceIdBase; /* Source ID Base */ + UINT32 NumIds; /* Number of IDs */ + UINT32 DestIdBase; /* Destination Device ID Base */ + UINT32 DestOffset; /* Destination IOMMU Offset */ + UINT32 Flags; /* Flags */ +} ACPI_RIMT_ID_MAPPING; + +typedef struct acpi_rimt_pcie_rc { + UINT32 Flags; /* Flags */ + UINT16 Reserved; /* Reserved */ + UINT16 PcieSegmentNumber; /* PCIe Segment number */ + UINT16 IdMappingOffset; /* ID mapping array offset */ + UINT16 NumIdMappings; /* Number of ID mappings */ +} ACPI_RIMT_PCIE_RC; + +/* PCIe Root Complex Node Flags */ +#define ACPI_RIMT_PCIE_ATS_SUPPORTED (1) +#define ACPI_RIMT_PCIE_PRI_SUPPORTED (1 << 1) + +typedef struct acpi_rimt_platform_device { + UINT16 IdMappingOffset; /* ID Mapping array offset */ + UINT16 NumIdMappings; /* Number of ID mappings */ + char DeviceName[]; /* Device Object Name */ +} ACPI_RIMT_PLATFORM_DEVICE; + + +/******************************************************************************* + * + * 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; + + +/******************************************************************************* + * + * SDEI - Software Delegated Exception Interface Descriptor Table + * + * Conforms to "Software Delegated Exception Interface (SDEI)" ARM DEN0054A, + * May 8th, 2017. Copyright 2017 ARM Ltd. + * + ******************************************************************************/ + +typedef struct acpi_table_sdei +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + +} ACPI_TABLE_SDEI; + + +/******************************************************************************* + * + * SDEV - Secure Devices Table (ACPI 6.2) + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_sdev +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + +} ACPI_TABLE_SDEV; + + +typedef struct acpi_sdev_header +{ + UINT8 Type; + UINT8 Flags; + UINT16 Length; + +} ACPI_SDEV_HEADER; + + +/* Values for subtable type above */ + +enum AcpiSdevType +{ + ACPI_SDEV_TYPE_NAMESPACE_DEVICE = 0, + ACPI_SDEV_TYPE_PCIE_ENDPOINT_DEVICE = 1, + ACPI_SDEV_TYPE_RESERVED = 2 /* 2 and greater are reserved */ +}; + +/* Values for flags above */ + +#define ACPI_SDEV_HANDOFF_TO_UNSECURE_OS (1) +#define ACPI_SDEV_SECURE_COMPONENTS_PRESENT (1<<1) + +/* + * SDEV subtables + */ + +/* 0: Namespace Device Based Secure Device Structure */ + +typedef struct acpi_sdev_namespace +{ + ACPI_SDEV_HEADER Header; + UINT16 DeviceIdOffset; + UINT16 DeviceIdLength; + UINT16 VendorDataOffset; + UINT16 VendorDataLength; + +} ACPI_SDEV_NAMESPACE; + +typedef struct acpi_sdev_secure_component +{ + UINT16 SecureComponentOffset; + UINT16 SecureComponentLength; + +} ACPI_SDEV_SECURE_COMPONENT; + + +/* + * SDEV sub-subtables ("Components") for above + */ +typedef struct acpi_sdev_component +{ + ACPI_SDEV_HEADER Header; + +} ACPI_SDEV_COMPONENT; + + +/* Values for sub-subtable type above */ + +enum AcpiSacType +{ + ACPI_SDEV_TYPE_ID_COMPONENT = 0, + ACPI_SDEV_TYPE_MEM_COMPONENT = 1 +}; + +typedef struct acpi_sdev_id_component +{ + ACPI_SDEV_HEADER Header; + UINT16 HardwareIdOffset; + UINT16 HardwareIdLength; + UINT16 SubsystemIdOffset; + UINT16 SubsystemIdLength; + UINT16 HardwareRevision; + UINT8 HardwareRevPresent; + UINT8 ClassCodePresent; + UINT8 PciBaseClass; + UINT8 PciSubClass; + UINT8 PciProgrammingXface; + +} ACPI_SDEV_ID_COMPONENT; + +typedef struct acpi_sdev_mem_component +{ + ACPI_SDEV_HEADER Header; + UINT32 Reserved; + UINT64 MemoryBaseAddress; + UINT64 MemoryLength; + +} ACPI_SDEV_MEM_COMPONENT; + + +/* 1: PCIe Endpoint Device Based Device Structure */ + +typedef struct acpi_sdev_pcie +{ + ACPI_SDEV_HEADER Header; + UINT16 Segment; + UINT16 StartBus; + UINT16 PathOffset; + UINT16 PathLength; + UINT16 VendorDataOffset; + UINT16 VendorDataLength; + +} ACPI_SDEV_PCIE; + +/* 1a: PCIe Endpoint path entry */ + +typedef struct acpi_sdev_pcie_path +{ + UINT8 Device; + UINT8 Function; + +} ACPI_SDEV_PCIE_PATH; + + +/******************************************************************************* + * + * SVKL - Storage Volume Key Location Table (ACPI 6.4) + * From: "Guest-Host-Communication Interface (GHCI) for Intel + * Trust Domain Extensions (Intel TDX)". + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_svkl +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 Count; + +} ACPI_TABLE_SVKL; + +typedef struct acpi_svkl_key +{ + UINT16 Type; + UINT16 Format; + UINT32 Size; + UINT64 Address; + +} ACPI_SVKL_KEY; + +enum acpi_svkl_type +{ + ACPI_SVKL_TYPE_MAIN_STORAGE = 0, + ACPI_SVKL_TYPE_RESERVED = 1 /* 1 and greater are reserved */ +}; + +enum acpi_svkl_format +{ + ACPI_SVKL_FORMAT_RAW_BINARY = 0, + ACPI_SVKL_FORMAT_RESERVED = 1 /* 1 and greater are reserved */ +}; + +/******************************************************************************* + * + * SWFT - SoundWire File Table + * as described in Discovery and Configuration (DisCo) Specification + * for SoundWire® + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_swft +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + +} ACPI_TABLE_SWFT; + +typedef struct acpi_swft_file +{ + UINT16 VendorID; + UINT32 FileID; + UINT16 FileVersion; + UINT32 FileLength; + UINT8 FileData[]; +} ACPI_SWFT_FILE; + +/******************************************************************************* + * + * TDEL - TD-Event Log + * From: "Guest-Host-Communication Interface (GHCI) for Intel + * Trust Domain Extensions (Intel TDX)". + * September 2020 + * + ******************************************************************************/ + +typedef struct acpi_table_tdel +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 Reserved; + UINT64 LogAreaMinimumLength; + UINT64 LogAreaStartAddress; + +} ACPI_TABLE_TDEL; + + +/******************************************************************************* + * + * UBRT - UnifiedBus Root Table + * Revision 1 + * + * Conforms to "UnifiedBus Root Table (UBRT) Specification" + * Revision 1.0, Release Date 2026-03-05 + * + ******************************************************************************/ + +typedef struct acpi_table_ubrt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 Count; /* Number of sub-tables */ + +} ACPI_TABLE_UBRT; + +/* UBRT sub-table entry (16 bytes) */ + +typedef struct acpi_ubrt_subtable +{ + UINT8 Type; /* Sub-table type (0=UBC, 1=UMMU, 2=ReservedMem) */ + UINT8 Reserved[7]; /* Reserved, must be zero */ + UINT64 Pointer; /* Physical address of the sub-table */ + +} ACPI_UBRT_SUBTABLE; + +/* Values for Type field above */ + +#define ACPI_UBRT_TYPE_UBC 0 /* UBC information sub-table */ +#define ACPI_UBRT_TYPE_UMMU 1 /* UMMU information sub-table */ +#define ACPI_UBRT_TYPE_RESERVED_MEM 2 /* UB reserved memory information sub-table */ + +/* + * UBRT Sub-tables, correspond to Type in ACPI_UBRT_SUBTABLE. + * These are accessed via the physical Pointer field - not contiguous with UBRT. + */ + +/* Common header for all UBRT sub-tables */ + +typedef struct acpi_ubrt_header +{ + char Name[16]; /* Table name, null-terminated */ + UINT32 TotalSize; /* Total size including header */ + UINT8 Version; /* Version number */ + UINT8 Reserved[3]; /* Reserved, must be zero */ + UINT32 RemainingSize; /* Remaining size of the sub-table */ + UINT32 Checksum; /* Entire table must sum to zero */ + +} ACPI_UBRT_HEADER; + +/* Type 0: UBC Information Table */ + +typedef struct acpi_ubrt_ubc +{ + ACPI_UBRT_HEADER Header; /* Common sub-table header */ + UINT32 LocalCnaStart; /* Start CNA available for local UBPU */ + UINT32 LocalCnaEnd; /* End CNA available for local UBPU (included) */ + UINT32 LocalEidStart; /* Start EID available for local UBPU */ + UINT32 LocalEidEnd; /* End EID available for local UBPU (included) */ + UINT8 FeatureSets; /* Features enabled for the UBC */ + UINT8 Reserved[3]; /* Reserved, must be zero */ + UINT16 ClusterMode; /* System operating mode */ + UINT16 UbcCount; /* Number of UBC structures */ + +} ACPI_UBRT_UBC; + +/* Values for FeatureSets field above */ + +#define ACPI_UBRT_UBC_FEAT_MMIO_TOKEN (1<<0) /* Bit 0: MMIO token value */ +#define ACPI_UBRT_UBC_FEAT_MCTP_UB (1<<1) /* Bit 1: MCTP over UB */ + +/* Values for ClusterMode field above */ + +#define ACPI_UBRT_CLUSTER_MODE_STANDALONE 0 +#define ACPI_UBRT_CLUSTER_MODE_SUPERPOD 1 + +/* UBC Structure entry (one per UbcCount) */ + +typedef struct acpi_ubrt_ubc_entry +{ + UINT32 InterruptIdStart; /* Start interrupt ID */ + UINT32 InterruptIdEnd; /* End interrupt ID (included) */ + UINT64 HpaBase; /* Base address of available HPA */ + UINT64 HpaSize; /* Size of available HPA */ + UINT8 MemorySizeLimit; /* Maximum address bit width */ + UINT8 DmaCca; /* DMA and cache coherent attribute */ + UINT16 UmmuMapping; /* Mapping between UBC and UMMU */ + UINT16 ProximityDomain; /* NUMA domain sequence number */ + UINT16 Reserved; /* Reserved, must be zero */ + UINT64 MsgQueueBase; /* MSG queue register base address */ + UINT64 MsgQueueSize; /* MSG queue register size */ + UINT16 MsgQueueDepth; /* MSG queue depth */ + UINT16 MsgQueueInterrupt; /* MSG queue interrupt ID */ + UINT8 MsgQueueInterruptAttr; /* MSG queue interrupt attribute */ + UINT8 Reserved1[59]; /* Reserved, must be zero */ + UINT8 Guid[16]; /* UBC GUID */ + UINT8 VendorInfo[256]; /* Vendor-defined information */ + +} ACPI_UBRT_UBC_ENTRY; + +/* Values for DmaCca field above */ + +#define ACPI_UBRT_UBC_DMA_ONLY 0 +#define ACPI_UBRT_UBC_DMA_CCA 1 + +/* Values for MsgQueueInterruptAttr field above */ + +#define ACPI_UBRT_UBC_MSG_INT_LEVEL (0<<0) /* Bit 0: level-triggered */ +#define ACPI_UBRT_UBC_MSG_INT_EDGE (1<<0) /* Bit 0: edge-triggered */ +#define ACPI_UBRT_UBC_MSG_INT_HIGH (0<<1) /* Bit 1: high level (rising edge) */ +#define ACPI_UBRT_UBC_MSG_INT_LOW (1<<1) /* Bit 1: low level (falling edge) */ + +/* Type 1: UMMU Information Table */ + +typedef struct acpi_ubrt_ummu +{ + ACPI_UBRT_HEADER Header; /* Common sub-table header */ + UINT16 UmmuCount; /* Number of UMMU structures */ + UINT8 Reserved[6]; /* Reserved, must be zero */ + +} ACPI_UBRT_UMMU; + +/* UMMU Structure entry (one per UmmuCount) */ + +typedef struct acpi_ubrt_ummu_entry +{ + UINT64 BaseAddress; /* Base address of UMMU register */ + UINT64 Size; /* Size of UMMU register */ + UINT32 Reserved; /* Reserved, must be zero */ + UINT16 ProximityDomain; /* NUMA domain sequence number */ + UINT16 Reserved1; /* Reserved, must be zero */ + UINT64 PmuBaseAddress; /* PMU register base address */ + UINT64 PmuSize; /* PMU register size */ + UINT32 Reserved2; /* Reserved, must be zero */ + UINT32 MinTokenId; /* Minimum TokenID */ + UINT32 MaxTokenId; /* Maximum TokenID */ + UINT8 Reserved3[26]; /* Reserved, must be zero */ + UINT16 VendorId; /* Vendor ID */ + UINT8 VendorInfo[80]; /* Vendor-defined information */ + +} ACPI_UBRT_UMMU_ENTRY; + +/* Type 2: UB Reserved Memory Information Table */ + +typedef struct acpi_ubrt_reserved_mem +{ + ACPI_UBRT_HEADER Header; /* Common sub-table header */ + UINT16 MemoryRangesCount; /* Number of memory ranges */ + UINT8 Reserved[6]; /* Reserved, must be zero */ + +} ACPI_UBRT_RESERVED_MEM; + +/* Memory Range entry (one per MemoryRangesCount) */ + +typedef struct acpi_ubrt_mem_range +{ + UINT8 Flags; /* Memory segment flags */ + UINT8 Reserved[7]; /* Reserved, must be zero */ + UINT64 MemoryBase; /* Base address of allocated UB memory (64KB aligned) */ + UINT64 MemorySize; /* Size of allocated UB memory (64KB aligned) */ + +} ACPI_UBRT_MEM_RANGE; + +/* Values for Flags field above */ + +#define ACPI_UBRT_MEM_FLAG_1_1_MAPPING (1<<0) /* Bit 0: 1:1 mapped mode */ + + +/* Reset to default packing */ + +#pragma pack() + +#endif /* __ACTBL2_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/actbl3.h b/code/drivers/platform/acpi/third_party/acpica/include/actbl3.h new file mode 100644 index 0000000..18209c1 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/actbl3.h @@ -0,0 +1,906 @@ +/****************************************************************************** + * + * Name: actbl3.h - ACPI Table Definitions + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACTBL3_H__ +#define __ACTBL3_H__ + + +/******************************************************************************* + * + * Additional ACPI Tables + * + * These tables are not consumed directly by the ACPICA subsystem, but are + * included here to support device drivers and the AML disassembler. + * + ******************************************************************************/ + + +/* + * 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_SLIC "SLIC" /* Software Licensing Description Table */ +#define ACPI_SIG_SLIT "SLIT" /* System Locality Distance Information Table */ +#define ACPI_SIG_SPCR "SPCR" /* Serial Port Console Redirection table */ +#define ACPI_SIG_SPMI "SPMI" /* Server Platform Management Interface table */ +#define ACPI_SIG_SRAT "SRAT" /* System Resource Affinity Table */ +#define ACPI_SIG_STAO "STAO" /* Status Override table */ +#define ACPI_SIG_TCPA "TCPA" /* Trusted Computing Platform Alliance table */ +#define ACPI_SIG_TPM2 "TPM2" /* Trusted Platform Module 2.0 H/W interface table */ +#define ACPI_SIG_UEFI "UEFI" /* Uefi Boot Optimization Table */ +#define ACPI_SIG_VIOT "VIOT" /* Virtual I/O Translation 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 */ +#define ACPI_SIG_WPBT "WPBT" /* Windows Platform Binary Table */ +#define ACPI_SIG_WSMT "WSMT" /* Windows SMM Security Mitigations Table */ +#define ACPI_SIG_XENV "XENV" /* Xen Environment table */ +#define ACPI_SIG_XXXX "XXXX" /* Intermediate AML header for ASL/ASL+ converter */ + +/* + * All tables must be byte-packed to match the ACPI specification, since + * the tables are provided by the system BIOS. + */ +#pragma pack(1) + +/* + * Note: C bitfields are not used for this reason: + * + * "Bitfields are great and easy to read, but unfortunately the C language + * does not specify the layout of bitfields in memory, which means they are + * essentially useless for dealing with packed data in on-disk formats or + * binary wire protocols." (Or ACPI tables and buffers.) "If you ask me, + * this decision was a design error in C. Ritchie could have picked an order + * and stuck with it." Norman Ramsey. + * See http://stackoverflow.com/a/1053662/41661 + */ + + +/******************************************************************************* + * + * SLIC - Software Licensing Description Table + * + * Conforms to "Microsoft Software Licensing Tables (SLIC and MSDM)", + * November 29, 2011. Copyright 2011 Microsoft + * + ******************************************************************************/ + +/* 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; + + +/******************************************************************************* + * + * 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; + + +/******************************************************************************* + * + * SPCR - Serial Port Console Redirection table + * Version 4 + * + * Conforms to "Serial Port Console Redirection Table", + * Version 1.10, Jan 5, 2023 + * + ******************************************************************************/ + +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 Language; + UINT16 PciDeviceId; + UINT16 PciVendorId; + UINT8 PciBus; + UINT8 PciDevice; + UINT8 PciFunction; + UINT32 PciFlags; + UINT8 PciSegment; + UINT32 UartClkFreq; + UINT32 PreciseBaudrate; + UINT16 NameSpaceStringLength; + UINT16 NameSpaceStringOffset; + char NameSpaceString[]; + +} ACPI_TABLE_SPCR; + +/* Masks for PciFlags field above */ + +#define ACPI_SPCR_DO_NOT_DISABLE (1) + +/* Values for Interface Type: See the definition of the DBG2 table */ + + +/******************************************************************************* + * + * 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 */ +}; + + +/******************************************************************************* + * + * 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_GICC_AFFINITY = 3, + ACPI_SRAT_TYPE_GIC_ITS_AFFINITY = 4, /* ACPI 6.2 */ + ACPI_SRAT_TYPE_GENERIC_AFFINITY = 5, /* ACPI 6.3 */ + ACPI_SRAT_TYPE_GENERIC_PORT_AFFINITY = 6, /* ACPI 6.4 */ + ACPI_SRAT_TYPE_RINTC_AFFINITY = 7, /* ACPI 6.6 */ + ACPI_SRAT_TYPE_RESERVED = 8 /* 8 and greater are reserved */ +}; + +/* + * SRAT Subtables, 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 ClockDomain; + +} 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 */ +#define ACPI_SRAT_MEM_SPEC_PURPOSE (1<<3) /* 03: Memory is intended for specific-purpose usage */ + + +/* 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 */ + + +/* 3: GICC Affinity (ACPI 5.1) */ + +typedef struct acpi_srat_gicc_affinity +{ + ACPI_SUBTABLE_HEADER Header; + UINT32 ProximityDomain; + UINT32 AcpiProcessorUid; + UINT32 Flags; + UINT32 ClockDomain; + +} ACPI_SRAT_GICC_AFFINITY; + +/* Flags for ACPI_SRAT_GICC_AFFINITY */ + +#define ACPI_SRAT_GICC_ENABLED (1) /* 00: Use affinity structure */ + + +/* 4: GIC ITS Affinity (ACPI 6.2) */ + +typedef struct acpi_srat_gic_its_affinity +{ + ACPI_SUBTABLE_HEADER Header; + UINT32 ProximityDomain; + UINT16 Reserved; + UINT32 ItsId; + +} ACPI_SRAT_GIC_ITS_AFFINITY; + +/* + * Common structure for SRAT subtable types: + * 5: ACPI_SRAT_TYPE_GENERIC_AFFINITY + * 6: ACPI_SRAT_TYPE_GENERIC_PORT_AFFINITY + */ + +#define ACPI_SRAT_DEVICE_HANDLE_SIZE 16 + +typedef struct acpi_srat_generic_affinity +{ + ACPI_SUBTABLE_HEADER Header; + UINT8 Reserved; + UINT8 DeviceHandleType; + UINT32 ProximityDomain; + UINT8 DeviceHandle[ACPI_SRAT_DEVICE_HANDLE_SIZE]; + UINT32 Flags; + UINT32 Reserved1; + +} ACPI_SRAT_GENERIC_AFFINITY; + +/* Flags for ACPI_SRAT_GENERIC_AFFINITY */ + +#define ACPI_SRAT_GENERIC_AFFINITY_ENABLED (1) /* 00: Use affinity structure */ +#define ACPI_SRAT_ARCHITECTURAL_TRANSACTIONS (1<<1) /* ACPI 6.4 */ + +/* 7: RINTC Affinity Structure(ACPI 6.6) */ + +typedef struct acpi_srat_rintc_affinity +{ + ACPI_SUBTABLE_HEADER Header; + UINT16 Reserved; + UINT32 ProximityDomain; + UINT32 AcpiProcessorUid; + UINT32 Flags; + UINT32 ClockDomain; + +} ACPI_SRAT_RINTC_AFFINITY; + +/* Flags for ACPI_SRAT_RINTC_AFFINITY */ + +#define ACPI_SRAT_RINTC_ENABLED (1) /* 00: Use affinity structure */ + +/******************************************************************************* + * + * STAO - Status Override Table (_STA override) - ACPI 6.0 + * Version 1 + * + * Conforms to "ACPI Specification for Status Override Table" + * 6 January 2015 + * + ******************************************************************************/ + +typedef struct acpi_table_stao +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT8 IgnoreUart; + +} ACPI_TABLE_STAO; + + +/******************************************************************************* + * + * TCPA - Trusted Computing Platform Alliance table + * Version 2 + * + * TCG Hardware Interface Table for TPM 1.2 Clients and Servers + * + * Conforms to "TCG ACPI Specification, Family 1.2 and 2.0", + * Version 1.2, Revision 8 + * February 27, 2017 + * + * NOTE: There are two versions of the table with the same signature -- + * the client version and the server version. The common PlatformClass + * field is used to differentiate the two types of tables. + * + ******************************************************************************/ + +typedef struct acpi_table_tcpa_hdr +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT16 PlatformClass; + +} ACPI_TABLE_TCPA_HDR; + +/* + * Values for PlatformClass above. + * This is how the client and server subtables are differentiated + */ +#define ACPI_TCPA_CLIENT_TABLE 0 +#define ACPI_TCPA_SERVER_TABLE 1 + + +typedef struct acpi_table_tcpa_client +{ + UINT32 MinimumLogLength; /* Minimum length for the event log area */ + UINT64 LogAddress; /* Address of the event log area */ + +} ACPI_TABLE_TCPA_CLIENT; + +typedef struct acpi_table_tcpa_server +{ + UINT16 Reserved; + UINT64 MinimumLogLength; /* Minimum length for the event log area */ + UINT64 LogAddress; /* Address of the event log area */ + UINT16 SpecRevision; + UINT8 DeviceFlags; + UINT8 InterruptFlags; + UINT8 GpeNumber; + UINT8 Reserved2[3]; + UINT32 GlobalInterrupt; + ACPI_GENERIC_ADDRESS Address; + UINT32 Reserved3; + ACPI_GENERIC_ADDRESS ConfigAddress; + UINT8 Group; + UINT8 Bus; /* PCI Bus/Segment/Function numbers */ + UINT8 Device; + UINT8 Function; + +} ACPI_TABLE_TCPA_SERVER; + +/* Values for DeviceFlags above */ + +#define ACPI_TCPA_PCI_DEVICE (1) +#define ACPI_TCPA_BUS_PNP (1<<1) +#define ACPI_TCPA_ADDRESS_VALID (1<<2) + +/* Values for InterruptFlags above */ + +#define ACPI_TCPA_INTERRUPT_MODE (1) +#define ACPI_TCPA_INTERRUPT_POLARITY (1<<1) +#define ACPI_TCPA_SCI_VIA_GPE (1<<2) +#define ACPI_TCPA_GLOBAL_INTERRUPT (1<<3) + + +/******************************************************************************* + * + * TPM2 - Trusted Platform Module (TPM) 2.0 Hardware Interface Table + * Version 4 + * + * TCG Hardware Interface Table for TPM 2.0 Clients and Servers + * + * Conforms to "TCG ACPI Specification, Family 1.2 and 2.0", + * Version 1.2, Revision 8 + * February 27, 2017 + * + ******************************************************************************/ + +/* Revision 3 */ + +typedef struct acpi_table_tpm23 +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 Reserved; + UINT64 ControlAddress; + UINT32 StartMethod; + +} ACPI_TABLE_TPM23; + +/* Value for StartMethod above */ + +#define ACPI_TPM23_ACPI_START_METHOD 2 + +/* + * Optional trailer for revision 3. If start method is 2, there is a 4 byte + * reserved area of all zeros. + */ +typedef struct acpi_tmp23_trailer +{ + UINT32 Reserved; + +} ACPI_TPM23_TRAILER; + + +/* Revision 4 */ + +typedef struct acpi_table_tpm2 +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT16 PlatformClass; + UINT16 Reserved; + UINT64 ControlAddress; + UINT32 StartMethod; + + /* Platform-specific data follows */ + +} ACPI_TABLE_TPM2; + +/* Values for StartMethod above */ + +#define ACPI_TPM2_NOT_ALLOWED 0 +#define ACPI_TPM2_RESERVED1 1 +#define ACPI_TPM2_START_METHOD 2 +#define ACPI_TPM2_RESERVED3 3 +#define ACPI_TPM2_RESERVED4 4 +#define ACPI_TPM2_RESERVED5 5 +#define ACPI_TPM2_MEMORY_MAPPED 6 +#define ACPI_TPM2_COMMAND_BUFFER 7 +#define ACPI_TPM2_COMMAND_BUFFER_WITH_START_METHOD 8 +#define ACPI_TPM2_RESERVED9 9 +#define ACPI_TPM2_RESERVED10 10 +#define ACPI_TPM2_COMMAND_BUFFER_WITH_ARM_SMC 11 /* V1.2 Rev 8 */ +#define ACPI_TPM2_RESERVED 12 +#define ACPI_TPM2_COMMAND_BUFFER_WITH_PLUTON 13 +#define ACPI_TPM2_CRB_WITH_ARM_FFA 15 + + +/* Optional trailer appears after any StartMethod subtables */ + +typedef struct acpi_tpm2_trailer +{ + UINT8 MethodParameters[12]; + UINT32 MinimumLogLength; /* Minimum length for the event log area */ + UINT64 LogAddress; /* Address of the event log area */ + +} ACPI_TPM2_TRAILER; + + +/* + * Subtables (StartMethod-specific) + */ + +/* 11: Start Method for ARM SMC (V1.2 Rev 8) */ + +typedef struct acpi_tpm2_arm_smc +{ + UINT32 GlobalInterrupt; + UINT8 InterruptFlags; + UINT8 OperationFlags; + UINT16 Reserved; + UINT32 FunctionId; + +} ACPI_TPM2_ARM_SMC; + +/* Values for InterruptFlags above */ + +#define ACPI_TPM2_INTERRUPT_SUPPORT (1) + +/* Values for OperationFlags above */ + +#define ACPI_TPM2_IDLE_SUPPORT (1) + + +/******************************************************************************* + * + * 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; + + +/******************************************************************************* + * + * VIOT - Virtual I/O Translation Table + * Version 1 + * + ******************************************************************************/ + +typedef struct acpi_table_viot +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT16 NodeCount; + UINT16 NodeOffset; + UINT8 Reserved[8]; + +} ACPI_TABLE_VIOT; + +/* VIOT subtable header */ + +typedef struct acpi_viot_header +{ + UINT8 Type; + UINT8 Reserved; + UINT16 Length; + +} ACPI_VIOT_HEADER; + +/* Values for Type field above */ + +enum AcpiViotNodeType +{ + ACPI_VIOT_NODE_PCI_RANGE = 0x01, + ACPI_VIOT_NODE_MMIO = 0x02, + ACPI_VIOT_NODE_VIRTIO_IOMMU_PCI = 0x03, + ACPI_VIOT_NODE_VIRTIO_IOMMU_MMIO = 0x04, + ACPI_VIOT_RESERVED = 0x05 +}; + +/* VIOT subtables */ + +typedef struct acpi_viot_pci_range +{ + ACPI_VIOT_HEADER Header; + UINT32 EndpointStart; + UINT16 SegmentStart; + UINT16 SegmentEnd; + UINT16 BdfStart; + UINT16 BdfEnd; + UINT16 OutputNode; + UINT8 Reserved[6]; + +} ACPI_VIOT_PCI_RANGE; + +typedef struct acpi_viot_mmio +{ + ACPI_VIOT_HEADER Header; + UINT32 Endpoint; + UINT64 BaseAddress; + UINT16 OutputNode; + UINT8 Reserved[6]; + +} ACPI_VIOT_MMIO; + +typedef struct acpi_viot_virtio_iommu_pci +{ + ACPI_VIOT_HEADER Header; + UINT16 Segment; + UINT16 Bdf; + UINT8 Reserved[8]; + +} ACPI_VIOT_VIRTIO_IOMMU_PCI; + +typedef struct acpi_viot_virtio_iommu_mmio +{ + ACPI_VIOT_HEADER Header; + UINT8 Reserved[4]; + UINT64 BaseAddress; + +} ACPI_VIOT_VIRTIO_IOMMU_MMIO; + + +/******************************************************************************* + * + * 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; + + +/******************************************************************************* + * + * WPBT - Windows Platform Environment Table (ACPI 6.0) + * Version 1 + * + * Conforms to "Windows Platform Binary Table (WPBT)" 29 November 2011 + * + ******************************************************************************/ + +typedef struct acpi_table_wpbt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 HandoffSize; + UINT64 HandoffAddress; + UINT8 Layout; + UINT8 Type; + UINT16 ArgumentsLength; + +} ACPI_TABLE_WPBT; + +typedef struct acpi_wpbt_unicode +{ + UINT16 *UnicodeString; + +} ACPI_WPBT_UNICODE; + + +/******************************************************************************* + * + * WSMT - Windows SMM Security Mitigations Table + * Version 1 + * + * Conforms to "Windows SMM Security Mitigations Table", + * Version 1.0, April 18, 2016 + * + ******************************************************************************/ + +typedef struct acpi_table_wsmt +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT32 ProtectionFlags; + +} ACPI_TABLE_WSMT; + +/* Flags for ProtectionFlags field above */ + +#define ACPI_WSMT_FIXED_COMM_BUFFERS (1) +#define ACPI_WSMT_COMM_BUFFER_NESTED_PTR_PROTECTION (2) +#define ACPI_WSMT_SYSTEM_RESOURCE_PROTECTION (4) + + +/******************************************************************************* + * + * XENV - Xen Environment Table (ACPI 6.0) + * Version 1 + * + * Conforms to "ACPI Specification for Xen Environment Table" 4 January 2015 + * + ******************************************************************************/ + +typedef struct acpi_table_xenv +{ + ACPI_TABLE_HEADER Header; /* Common ACPI table header */ + UINT64 GrantTableAddress; + UINT64 GrantTableSize; + UINT32 EventInterrupt; + UINT8 EventFlags; + +} ACPI_TABLE_XENV; + + +/* Reset to default packing */ + +#pragma pack() + +#endif /* __ACTBL3_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/actypes.h b/code/drivers/platform/acpi/third_party/acpica/include/actypes.h new file mode 100644 index 0000000..67c97b0 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/actypes.h @@ -0,0 +1,1449 @@ +/****************************************************************************** + * + * Name: actypes.h - Common data types for the entire ACPI subsystem + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 + +/* + * 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 + * + ******************************************************************************/ + +#ifndef ACPI_USE_SYSTEM_INTTYPES + +typedef unsigned char BOOLEAN; +typedef unsigned char UINT8; +typedef unsigned short UINT16; +typedef short INT16; +typedef COMPILER_DEPENDENT_UINT64 UINT64; +typedef COMPILER_DEPENDENT_INT64 INT64; + +#endif /* ACPI_USE_SYSTEM_INTTYPES */ + +/* + * 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 + +#ifndef ACPI_USE_SYSTEM_INTTYPES + +typedef unsigned int UINT32; +typedef int INT32; + +#endif /* ACPI_USE_SYSTEM_INTTYPES */ + + +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 */ +#define ACPI_USE_NATIVE_MATH64 /* 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 + +#ifndef ACPI_USE_SYSTEM_INTTYPES + +typedef unsigned int UINT32; +typedef int INT32; + +#endif /* ACPI_USE_SYSTEM_INTTYPES */ + + +typedef INT32 ACPI_NATIVE_INT; +typedef UINT32 ACPI_SIZE; + +#ifdef ACPI_32BIT_PHYSICAL_ADDRESS + +/* + * OSPMs can define this to shrink the size of the structures for 32-bit + * none PAE environment. ASL compiler may always define this to generate + * 32-bit OSPM compliant tables. + */ +typedef UINT32 ACPI_IO_ADDRESS; +typedef UINT32 ACPI_PHYSICAL_ADDRESS; + +#else /* ACPI_32BIT_PHYSICAL_ADDRESS */ + +/* + * It is reported that, after some calculations, the physical addresses can + * wrap over the 32-bit boundary on 32-bit PAE environment. + * https://bugzilla.kernel.org/show_bug.cgi?id=87971 + */ +typedef UINT64 ACPI_IO_ADDRESS; +typedef UINT64 ACPI_PHYSICAL_ADDRESS; + +#endif /* ACPI_32BIT_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 tell the compiler in a per-variable manner that a variable + * is unused + */ +#ifndef ACPI_UNUSED_VAR +#define ACPI_UNUSED_VAR +#endif + +/* + * All ACPICA external functions that are available to the rest of the + * kernel are tagged with these macros which can be defined as appropriate + * for the host. + * + * Notes: + * ACPI_EXPORT_SYMBOL_INIT is used for initialization and termination + * interfaces that may need special processing. + * ACPI_EXPORT_SYMBOL is used for all other public external functions. + */ +#ifndef ACPI_EXPORT_SYMBOL_INIT +#define ACPI_EXPORT_SYMBOL_INIT(Symbol) +#endif + +#ifndef ACPI_EXPORT_SYMBOL +#define ACPI_EXPORT_SYMBOL(Symbol) +#endif + +/* + * Compiler/Clibrary-dependent debug initialization. Used for ACPICA + * utilities only. + */ +#ifndef ACPI_DEBUG_INITIALIZE +#define ACPI_DEBUG_INITIALIZE() +#endif + + +/******************************************************************************* + * + * Configuration + * + ******************************************************************************/ + +#ifdef ACPI_NO_MEM_ALLOCATIONS + +#define ACPI_ALLOCATE(a) NULL +#define ACPI_ALLOCATE_ZEROED(a) NULL +#define ACPI_FREE(a) +#define ACPI_MEM_TRACKING(a) + +#else /* ACPI_NO_MEM_ALLOCATIONS */ + +#ifdef ACPI_DBG_TRACK_ALLOCATIONS +/* + * Memory allocation tracking (used by AcpiExec to detect memory leaks) + */ +#define ACPI_MEM_PARAMETERS _COMPONENT, _AcpiModuleName, __LINE__ +#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 + +#else +/* + * Normal memory allocation directly via the OS services layer + */ +#define ACPI_ALLOCATE(a) AcpiOsAllocate ((ACPI_SIZE) (a)) +#define ACPI_ALLOCATE_ZEROED(a) AcpiOsAllocateZeroed ((ACPI_SIZE) (a)) +#define ACPI_FREE(a) AcpiOsFree (a) +#define ACPI_MEM_TRACKING(a) + +#endif /* ACPI_DBG_TRACK_ALLOCATIONS */ + +#endif /* ACPI_NO_MEM_ALLOCATIONS */ + + +/****************************************************************************** + * + * 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 +#define ACPI_RESET_REGISTER_WIDTH 8 + +/* Names within the namespace are 4 bytes long */ + +#define ACPI_NAMESEG_SIZE 4 /* Fixed by ACPI spec */ +#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 ACPI_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 */ + + +/* Time constants for timer calculations */ + +#define ACPI_MSEC_PER_SEC 1000L + +#define ACPI_USEC_PER_MSEC 1000L +#define ACPI_USEC_PER_SEC 1000000L + +#define ACPI_100NSEC_PER_USEC 10L +#define ACPI_100NSEC_PER_MSEC 10000L +#define ACPI_100NSEC_PER_SEC 10000000L + +#define ACPI_NSEC_PER_USEC 1000L +#define ACPI_NSEC_PER_MSEC 1000000L +#define ACPI_NSEC_PER_SEC 1000000000L + +#define ACPI_TIME_AFTER(a, b) ((INT64)((b) - (a)) < 0) + + +/* Owner IDs are used to track namespace nodes for selective deletion */ + +typedef UINT16 ACPI_OWNER_ID; +#define ACPI_OWNER_ID_MAX 0xFFF /* 4095 possible owner IDs */ + + +#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_HANDLE) ACPI_TO_POINTER (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 max 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_SUB_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_CAST_PTR (void, (ACPI_SIZE) (i)) +#ifndef ACPI_TO_INTEGER +#define ACPI_TO_INTEGER(p) ACPI_PTR_DIFF (p, (void *) 0) +#endif +#ifndef ACPI_OFFSET +#define ACPI_OFFSET(d, f) ACPI_PTR_DIFF (&(((d *) 0)->f), (void *) 0) +#endif +#define ACPI_PTR_TO_PHYSADDR(i) ACPI_TO_INTEGER(i) + +/* Optimizations for 4-character (32-bit) ACPI_NAME manipulation */ + +#ifndef ACPI_MISALIGNMENT_NOT_SUPPORTED +#define ACPI_COMPARE_NAMESEG(a,b) (*ACPI_CAST_PTR (UINT32, (a)) == *ACPI_CAST_PTR (UINT32, (b))) +#define ACPI_COPY_NAMESEG(dest,src) (*ACPI_CAST_PTR (UINT32, (dest)) = *ACPI_CAST_PTR (UINT32, (src))) +#else +#define ACPI_COMPARE_NAMESEG(a,b) (!strncmp (ACPI_CAST_PTR (char, (a)), ACPI_CAST_PTR (char, (b)), ACPI_NAMESEG_SIZE)) +#define ACPI_COPY_NAMESEG(dest,src) (memcpy (ACPI_CAST_PTR (char, (dest)), ACPI_CAST_PTR (char, (src)), ACPI_NAMESEG_SIZE)) +#endif + +/* Support for the special RSDP signature (8 characters) */ + +#define ACPI_VALIDATE_RSDP_SIG(a) (!strncmp (ACPI_CAST_PTR (char, (a)), ACPI_SIG_RSDP, (sizeof(a) < 8) ? ACPI_NAMESEG_SIZE : 8)) +#define ACPI_MAKE_RSDP_SIG(dest) (memcpy (ACPI_CAST_PTR (char, (dest)), ACPI_SIG_RSDP, 8)) + +/* Support for OEMx signature (x can be any character) */ +#define ACPI_IS_OEM_SIG(a) (!strncmp (ACPI_CAST_PTR (char, (a)), ACPI_OEM_NAME, 3) &&\ + strnlen (a, ACPI_NAMESEG_SIZE) == ACPI_NAMESEG_SIZE) + +/* + * Algorithm to obtain access bit or byte width. + * Can be used with AccessSize field of ACPI_GENERIC_ADDRESS and + * ACPI_RESOURCE_GENERIC_REGISTER. + */ +#define ACPI_ACCESS_BIT_SHIFT 2 +#define ACPI_ACCESS_BYTE_SHIFT -1 +#define ACPI_ACCESS_BIT_MAX (31 - ACPI_ACCESS_BIT_SHIFT) +#define ACPI_ACCESS_BYTE_MAX (31 - ACPI_ACCESS_BYTE_SHIFT) +#define ACPI_ACCESS_BIT_DEFAULT (8 - ACPI_ACCESS_BIT_SHIFT) +#define ACPI_ACCESS_BYTE_DEFAULT (8 - ACPI_ACCESS_BYTE_SHIFT) +#define ACPI_ACCESS_BIT_WIDTH(size) (1 << ((size) + ACPI_ACCESS_BIT_SHIFT)) +#define ACPI_ACCESS_BYTE_WIDTH(size) (1 << ((size) + ACPI_ACCESS_BYTE_SHIFT)) + +/******************************************************************************* + * + * Miscellaneous constants + * + ******************************************************************************/ + +/* + * Initialization sequence options + */ +#define ACPI_FULL_INITIALIZATION 0x0000 +#define ACPI_NO_FACS_INIT 0x0001 +#define ACPI_NO_ACPI_ENABLE 0x0002 +#define ACPI_NO_HARDWARE_INIT 0x0004 +#define ACPI_NO_EVENT_INIT 0x0008 +#define ACPI_NO_HANDLER_INIT 0x0010 +#define ACPI_NO_OBJECT_INIT 0x0020 +#define ACPI_NO_DEVICE_INIT 0x0040 +#define ACPI_NO_ADDRESS_SPACE_INIT 0x0080 + +/* + * 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_HOT (UINT8) 3 +#define ACPI_STATE_D3_COLD (UINT8) 4 +#define ACPI_STATE_D3 ACPI_STATE_D3_COLD +#define ACPI_D_STATES_MAX ACPI_STATE_D3_COLD +#define ACPI_D_STATE_COUNT 5 + +#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_AFFINITY_UPDATE (UINT8) 0x0D +#define ACPI_NOTIFY_MEMORY_UPDATE (UINT8) 0x0E +#define ACPI_NOTIFY_DISCONNECT_RECOVER (UINT8) 0x0F + +#define ACPI_GENERIC_NOTIFY_MAX 0x0F +#define ACPI_SPECIFIC_NOTIFY_MAX 0x84 + +/* + * 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 +#define ACPI_NUM_TYPES (ACPI_TYPE_EXTERNAL_MAX + 1) + +/* + * 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 */ +#define ACPI_TOTAL_TYPES (ACPI_TYPE_NS_NODE_MAX + 1) + +/* + * These are special object types that never appear in + * a Namespace node, only in an object of 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:6 |5|4|3|2|1|0| + * +-------------+-+-+-+-+-+-+ + * | | | | | | | + * | | | | | | +- Enabled? + * | | | | | +--- Enabled for wake? + * | | | | +----- Status bit set? + * | | | +------- Enable bit set? + * | | +--------- Has a handler? + * | +----------- Masked? + * +----------------- + */ +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_STATUS_SET (ACPI_EVENT_STATUS) 0x04 +#define ACPI_EVENT_FLAG_ENABLE_SET (ACPI_EVENT_STATUS) 0x08 +#define ACPI_EVENT_FLAG_HAS_HANDLER (ACPI_EVENT_STATUS) 0x10 +#define ACPI_EVENT_FLAG_MASKED (ACPI_EVENT_STATUS) 0x20 +#define ACPI_EVENT_FLAG_SET ACPI_EVENT_FLAG_STATUS_SET + +/* 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:6|5|4|3|2:0| + * +---+-+-+-+---+ + * | | | | | + * | | | | +-- Type of dispatch:to method, handler, notify, or none + * | | | +----- Interrupt type: edge or level triggered + * | | +------- Is a Wake GPE + * | +--------- Has been enabled automatically at init time + * +------------ + */ +#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_RAW_HANDLER (UINT8) 0x04 +#define ACPI_GPE_DISPATCH_MASK (UINT8) 0x07 +#define ACPI_GPE_DISPATCH_TYPE(flags) ((UINT8) ((flags) & ACPI_GPE_DISPATCH_MASK)) + +#define ACPI_GPE_LEVEL_TRIGGERED (UINT8) 0x08 +#define ACPI_GPE_EDGE_TRIGGERED (UINT8) 0x00 +#define ACPI_GPE_XRUPT_TYPE_MASK (UINT8) 0x08 + +#define ACPI_GPE_CAN_WAKE (UINT8) 0x10 +#define ACPI_GPE_AUTO_ENABLED (UINT8) 0x20 +#define ACPI_GPE_INITIALIZED (UINT8) 0x40 + +/* + * 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_NUM_NOTIFY_TYPES 2 + +#define ACPI_MAX_SYS_NOTIFY 0x7F +#define ACPI_MAX_DEVICE_SPECIFIC_NOTIFY 0xBF + +#define ACPI_SYSTEM_HANDLER_LIST 0 /* Used as index, must be SYSTEM_NOTIFY -1 */ +#define ACPI_DEVICE_HANDLER_LIST 1 /* Used as index, must be DEVICE_NOTIFY -1 */ + + +/* 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_ADR_SPACE_PLATFORM_COMM (ACPI_ADR_SPACE_TYPE) 10 +#define ACPI_ADR_SPACE_PLATFORM_RT (ACPI_ADR_SPACE_TYPE) 11 + +#define ACPI_NUM_PREDEFINED_REGIONS 12 + +/* + * 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 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 + +#ifdef ACPI_NO_MEM_ALLOCATIONS + +#define ACPI_ALLOCATE_BUFFER (ACPI_SIZE) (0) +#define ACPI_ALLOCATE_LOCAL_BUFFER (ACPI_SIZE) (0) + +#else /* ACPI_NO_MEM_ALLOCATIONS */ + +#define ACPI_ALLOCATE_BUFFER (ACPI_SIZE) (-1) /* Let ACPICA allocate buffer */ +#define ACPI_ALLOCATE_LOCAL_BUFFER (ACPI_SIZE) (-2) /* For internal use only (enables tracking) */ + +#endif /* ACPI_NO_MEM_ALLOCATIONS */ + +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_FULL_PATHNAME_NO_TRAILING 2 +#define ACPI_NAME_TYPE_MAX 2 + + +/* + * Predefined Namespace items + */ +typedef struct acpi_predefined_names +{ + const 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; + + +/* + * 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 +UINT32 (*ACPI_SCI_HANDLER) ( + void *Context); + +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); + + +/* Table Event Types */ + +#define ACPI_TABLE_EVENT_LOAD 0x0 +#define ACPI_TABLE_EVENT_UNLOAD 0x1 +#define ACPI_TABLE_EVENT_INSTALL 0x2 +#define ACPI_TABLE_EVENT_UNINSTALL 0x3 +#define ACPI_NUM_TABLE_EVENTS 4 + + +/* 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; + +/* Special Context data for PCC Opregion (ACPI 6.3) */ + +typedef struct acpi_pcc_info { + UINT8 SubspaceId; + UINT16 Length; + UINT8 *InternalBuffer; +} ACPI_PCC_INFO; + +/* Special Context data for FFH Opregion (ACPI 6.5) */ + +typedef struct acpi_ffh_info { + UINT64 Offset; + UINT64 Length; +} ACPI_FFH_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 + +/* Length of 3-byte PCI class code values when converted back to a string */ + +#define ACPI_PCICLS_STRING_SIZE 7 /* Includes null terminator */ + + +/* Structures used for device/processor HID, UID, CID */ + +typedef struct acpi_pnp_device_id +{ + UINT32 Length; /* Length of string + null */ + char *String; + +} ACPI_PNP_DEVICE_ID; + +typedef struct acpi_pnp_device_id_list +{ + UINT32 Count; /* Number of IDs in Ids array */ + UINT32 ListSize; /* Size of list, including ID strings */ + ACPI_PNP_DEVICE_ID Ids[]; /* ID array */ + +} ACPI_PNP_DEVICE_ID_LIST; + +/* + * Structure returned from AcpiGetObjectInfo. + * Optimized for both 32-bit 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 */ + UINT16 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 */ + UINT64 Address; /* _ADR value */ + ACPI_PNP_DEVICE_ID HardwareId; /* _HID value */ + ACPI_PNP_DEVICE_ID UniqueId; /* _UID value */ + ACPI_PNP_DEVICE_ID ClassCode; /* _CLS value */ + ACPI_PNP_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_ADR 0x0002 +#define ACPI_VALID_HID 0x0004 +#define ACPI_VALID_UID 0x0008 +#define ACPI_VALID_CID 0x0020 +#define ACPI_VALID_CLS 0x0040 +#define ACPI_VALID_SXDS 0x0100 +#define ACPI_VALID_SXWS 0x0200 + +/* 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_mapping +{ + ACPI_PHYSICAL_ADDRESS PhysicalAddress; + UINT8 *LogicalAddress; + ACPI_SIZE Length; + struct acpi_mem_mapping *NextMm; + +} ACPI_MEM_MAPPING; + +typedef struct acpi_mem_space_context +{ + UINT32 Length; + ACPI_PHYSICAL_ADDRESS Address; + ACPI_MEM_MAPPING *CurMm; + ACPI_MEM_MAPPING *FirstMm; + +} ACPI_MEM_SPACE_CONTEXT; + +typedef struct acpi_data_table_mapping +{ + void *Pointer; + +} ACPI_DATA_TABLE_MAPPING; + + +/* + * ACPI_MEMORY_LIST is used only if the ACPICA local cache is enabled + */ +typedef struct acpi_memory_list +{ + const char *ListName; + void *ListHead; + UINT16 ObjectSize; + UINT16 MaxDepth; + UINT16 CurrentDepth; + +#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; + + +/* Definitions of trace event types */ + +typedef enum +{ + ACPI_TRACE_AML_METHOD, + ACPI_TRACE_AML_OPCODE, + ACPI_TRACE_AML_REGION + +} ACPI_TRACE_EVENT_TYPE; + + +/* Definitions of _OSI support */ + +#define ACPI_VENDOR_STRINGS 0x01 +#define ACPI_FEATURE_STRINGS 0x02 +#define ACPI_ENABLE_INTERFACES 0x00 +#define ACPI_DISABLE_INTERFACES 0x04 + +#define ACPI_DISABLE_ALL_VENDOR_STRINGS (ACPI_DISABLE_INTERFACES | ACPI_VENDOR_STRINGS) +#define ACPI_DISABLE_ALL_FEATURE_STRINGS (ACPI_DISABLE_INTERFACES | ACPI_FEATURE_STRINGS) +#define ACPI_DISABLE_ALL_STRINGS (ACPI_DISABLE_INTERFACES | ACPI_VENDOR_STRINGS | ACPI_FEATURE_STRINGS) +#define ACPI_ENABLE_ALL_VENDOR_STRINGS (ACPI_ENABLE_INTERFACES | ACPI_VENDOR_STRINGS) +#define ACPI_ENABLE_ALL_FEATURE_STRINGS (ACPI_ENABLE_INTERFACES | ACPI_FEATURE_STRINGS) +#define ACPI_ENABLE_ALL_STRINGS (ACPI_ENABLE_INTERFACES | ACPI_VENDOR_STRINGS | ACPI_FEATURE_STRINGS) + +#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_OSI_WIN_8 0x0C +#define ACPI_OSI_WIN_8_1 0x0D +#define ACPI_OSI_WIN_10 0x0E +#define ACPI_OSI_WIN_10_RS1 0x0F +#define ACPI_OSI_WIN_10_RS2 0x10 +#define ACPI_OSI_WIN_10_RS3 0x11 +#define ACPI_OSI_WIN_10_RS4 0x12 +#define ACPI_OSI_WIN_10_RS5 0x13 +#define ACPI_OSI_WIN_10_19H1 0x14 +#define ACPI_OSI_WIN_10_20H1 0x15 +#define ACPI_OSI_WIN_11 0x16 +#define ACPI_OSI_WIN_11_22H2 0x17 + + +/* Definitions of getopt */ + +#define ACPI_OPT_END -1 + +/* Definitions for explicit fallthrough */ + +#ifndef ACPI_FALLTHROUGH +#define ACPI_FALLTHROUGH do {} while(0) +#endif + +#ifndef ACPI_FLEX_ARRAY +#define ACPI_FLEX_ARRAY(TYPE, NAME) TYPE NAME[0] +#endif + +#ifndef ACPI_NONSTRING +#define ACPI_NONSTRING /* No terminating NUL character */ +#endif + +#endif /* __ACTYPES_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acutils.h b/code/drivers/platform/acpi/third_party/acpica/include/acutils.h new file mode 100644 index 0000000..74ca522 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acutils.h @@ -0,0 +1,1170 @@ +/****************************************************************************** + * + * Name: acutils.h -- prototypes for the common (subsystem-wide) procedures + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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_DEBUG_OUTPUT) || 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_PhyDecode[]; +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[]; +extern const char *AcpiGbl_PtypDecode[]; +extern const char *AcpiGbl_ClockInputMode[]; +extern const char *AcpiGbl_ClockInputScale[]; +#endif + +/* + * 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 + +#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 error message prefixes + */ +#ifndef ACPI_MSG_ERROR +#define ACPI_MSG_ERROR "ACPI Error: " +#endif +#ifndef ACPI_MSG_WARNING +#define ACPI_MSG_WARNING "ACPI Warning: " +#endif +#ifndef ACPI_MSG_INFO +#define ACPI_MSG_INFO "ACPI: " +#endif + +#ifndef ACPI_MSG_BIOS_ERROR +#define ACPI_MSG_BIOS_ERROR "Firmware Error (ACPI): " +#endif +#ifndef ACPI_MSG_BIOS_WARNING +#define ACPI_MSG_BIOS_WARNING "Firmware Warning (ACPI): " +#endif +#ifndef ACPI_MSG_DEBUG +#define ACPI_MSG_DEBUG "" +#endif + +/* + * Common message suffix + */ +#define ACPI_MSG_SUFFIX \ + AcpiOsPrintf (" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, ModuleName, LineNumber) + +/* Flags to indicate implicit or explicit string-to-integer conversion */ + +#define ACPI_IMPLICIT_CONVERSION TRUE +#define ACPI_NO_IMPLICIT_CONVERSION FALSE + +/* 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; + +/* Object reference counts */ + +#define REF_INCREMENT (UINT16) 0 +#define REF_DECREMENT (UINT16) 1 + +/* AcpiUtDumpBuffer */ + +#define DB_BYTE_DISPLAY 0x01 +#define DB_WORD_DISPLAY 0x02 +#define DB_DWORD_DISPLAY 0x04 +#define DB_QWORD_DISPLAY 0x08 +#define DB_DISPLAY_DATA_ONLY 0x10 + + +/* + * utascii - ASCII utilities + */ +BOOLEAN +AcpiUtValidNameseg ( + char *Signature); + +BOOLEAN +AcpiUtValidNameChar ( + char Character, + UINT32 Position); + +void +AcpiUtCheckAndRepairAscii ( + UINT8 *Name, + char *RepairedName, + UINT32 Count); + + +/* + * utcksum - Checksum utilities + */ +UINT8 +AcpiUtGenerateChecksum ( + void *Table, + UINT32 Length, + UINT8 OriginalChecksum); + +UINT8 +AcpiUtChecksum ( + UINT8 *Buffer, + UINT32 Length); + +ACPI_STATUS +AcpiUtVerifyCdatChecksum ( + ACPI_TABLE_CDAT *CdatTable, + UINT32 Length); + +ACPI_STATUS +AcpiUtVerifyChecksum ( + ACPI_TABLE_HEADER *Table, + UINT32 Length); + + +/* + * utnonansi - Non-ANSI C library functions + */ +void +AcpiUtStrupr ( + char *SrcString); + +void +AcpiUtStrlwr ( + char *SrcString); + +int +AcpiUtStricmp ( + char *String1, + char *String2); + + +/* + * utstrsuppt - string-to-integer conversion support functions + */ +ACPI_STATUS +AcpiUtConvertOctalString ( + char *String, + UINT64 *ReturnValue); + +ACPI_STATUS +AcpiUtConvertDecimalString ( + char *String, + UINT64 *ReturnValuePtr); + +ACPI_STATUS +AcpiUtConvertHexString ( + char *String, + UINT64 *ReturnValuePtr); + +char +AcpiUtRemoveWhitespace ( + char **String); + +char +AcpiUtRemoveLeadingZeros ( + char **String); + +BOOLEAN +AcpiUtDetectHexPrefix ( + char **String); + +void +AcpiUtRemoveHexPrefix ( + char **String); + +BOOLEAN +AcpiUtDetectOctalPrefix ( + char **String); + + +/* + * utstrtoul64 - string-to-integer conversion functions + */ +ACPI_STATUS +AcpiUtStrtoul64 ( + char *String, + UINT64 *RetInteger); + +UINT64 +AcpiUtExplicitStrtoul64 ( + char *String); + +UINT64 +AcpiUtImplicitStrtoul64 ( + char *String); + + +/* + * utglobal - Global data structures and procedures + */ +ACPI_STATUS +AcpiUtInitGlobals ( + void); + +const char * +AcpiUtGetMutexName ( + UINT32 MutexId); + +#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER) + +const char * +AcpiUtGetNotifyName ( + UINT32 NotifyValue, + ACPI_OBJECT_TYPE Type); +#endif + +const char * +AcpiUtGetTypeName ( + ACPI_OBJECT_TYPE Type); + +const char * +AcpiUtGetNodeName ( + void *Object); + +const char * +AcpiUtGetDescriptorName ( + void *Object); + +const char * +AcpiUtGetReferenceName ( + ACPI_OPERAND_OBJECT *Object); + +const char * +AcpiUtGetObjectTypeName ( + ACPI_OPERAND_OBJECT *ObjDesc); + +const char * +AcpiUtGetRegionName ( + UINT8 SpaceId); + +const char * +AcpiUtGetEventName ( + UINT32 EventId); + +const char * +AcpiUtGetArgumentTypeName ( + UINT32 ArgType); + +char +AcpiUtHexToAsciiChar ( + UINT64 Integer, + UINT32 Position); + +ACPI_STATUS +AcpiUtAsciiToHexByte ( + char *TwoAsciiChars, + UINT8 *ReturnByte); + +UINT8 +AcpiUtAsciiCharToHex ( + int HexChar); + +BOOLEAN +AcpiUtValidObjectType ( + ACPI_OBJECT_TYPE Type); + + +/* + * utinit - miscellaneous initialization and shutdown + */ +ACPI_STATUS +AcpiUtHardwareInitialize ( + void); + +void +AcpiUtSubsystemShutdown ( + void); + + +/* + * 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, + const 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, + const 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 +AcpiUtStrExit ( + UINT32 LineNumber, + const char *FunctionName, + const char *ModuleName, + UINT32 ComponentId, + const char *String); + +void +AcpiUtDebugDumpBuffer ( + UINT8 *Buffer, + UINT32 Count, + UINT32 Display, + UINT32 ComponentId); + +void +AcpiUtDumpBuffer ( + UINT8 *Buffer, + UINT32 Count, + UINT32 Display, + UINT32 Offset); + +#ifdef ACPI_APPLICATION +void +AcpiUtDumpBufferToFile ( + ACPI_FILE File, + UINT8 *Buffer, + UINT32 Count, + UINT32 Display, + UINT32 BaseOffset); +#endif + +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, + const char *Path, + UINT32 ExpectedReturnBtypes, + ACPI_OPERAND_OBJECT **ReturnDesc); + +ACPI_STATUS +AcpiUtEvaluateNumericObject ( + const 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_PNP_DEVICE_ID **ReturnId); + +ACPI_STATUS +AcpiUtExecute_UID ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_PNP_DEVICE_ID **ReturnId); + +ACPI_STATUS +AcpiUtExecute_CID ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_PNP_DEVICE_ID_LIST **ReturnCidList); + +ACPI_STATUS +AcpiUtExecute_CLS ( + ACPI_NAMESPACE_NODE *DeviceNode, + ACPI_PNP_DEVICE_ID **ReturnId); + + +/* + * 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); + +ACPI_STATUS +AcpiUtInterfaceTerminate ( + void); + +ACPI_STATUS +AcpiUtInstallInterface ( + ACPI_STRING InterfaceName); + +ACPI_STATUS +AcpiUtRemoveInterface ( + ACPI_STRING InterfaceName); + +ACPI_STATUS +AcpiUtUpdateInterfaces ( + UINT8 Action); + +ACPI_INTERFACE_INFO * +AcpiUtGetInterface ( + ACPI_STRING InterfaceName); + +ACPI_STATUS +AcpiUtOsiImplementation ( + ACPI_WALK_STATE *WalkState); + + +/* + * utpredef - support for predefined names + */ +const ACPI_PREDEFINED_INFO * +AcpiUtGetNextPredefinedMethod ( + const ACPI_PREDEFINED_INFO *ThisName); + +const ACPI_PREDEFINED_INFO * +AcpiUtMatchPredefinedMethod ( + char *Name); + +void +AcpiUtGetExpectedReturnTypes ( + char *Buffer, + UINT32 ExpectedBtypes); + +#if (defined ACPI_ASL_COMPILER || defined ACPI_HELP_APP) +const ACPI_PREDEFINED_INFO * +AcpiUtMatchResourceName ( + char *Name); + +void +AcpiUtDisplayPredefinedMethod ( + char *Buffer, + const ACPI_PREDEFINED_INFO *ThisName, + BOOLEAN MultiLine); + +UINT32 +AcpiUtGetResourceBitWidth ( + char *Buffer, + UINT16 Types); +#endif + + +/* + * 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, + UINT32 Index); + +ACPI_STATUS +AcpiUtCreateUpdateStateAndPush ( + ACPI_OPERAND_OBJECT *Object, + UINT16 Action, + 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); + +ACPI_STATUS +AcpiUtShortMultiply ( + UINT64 InMultiplicand, + UINT32 Multiplier, + UINT64 *Outproduct); + +ACPI_STATUS +AcpiUtShortShiftLeft ( + UINT64 Operand, + UINT32 Count, + UINT64 *OutResult); + +ACPI_STATUS +AcpiUtShortShiftRight ( + UINT64 Operand, + UINT32 Count, + UINT64 *OutResult); + + +/* + * utmisc + */ +const ACPI_EXCEPTION_INFO * +AcpiUtValidateException ( + ACPI_STATUS Status); + +BOOLEAN +AcpiUtIsPciRootBridge ( + char *Id); + +#if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP || defined ACPI_NAMES_APP) +BOOLEAN +AcpiUtIsAmlTable ( + ACPI_TABLE_HEADER *Table); +#endif + +ACPI_STATUS +AcpiUtWalkPackageTree ( + ACPI_OPERAND_OBJECT *SourceObject, + void *TargetObject, + ACPI_PKG_CALLBACK WalkCallback, + void *Context); + +/* 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, + const char *Path); +#endif + + +/* + * utownerid - Support for Table/Method Owner IDs + */ +ACPI_STATUS +AcpiUtAllocateOwnerId ( + ACPI_OWNER_ID *OwnerId); + +void +AcpiUtReleaseOwnerId ( + ACPI_OWNER_ID *OwnerId); + + +/* + * utresrc + */ +ACPI_STATUS +AcpiUtWalkAmlResources ( + ACPI_WALK_STATE *WalkState, + UINT8 *Aml, + ACPI_SIZE AmlLength, + ACPI_WALK_AML_CALLBACK UserFunction, + void **Context); + +ACPI_STATUS +AcpiUtValidateResource ( + ACPI_WALK_STATE *WalkState, + 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); + + +/* + * utstring - String and character utilities + */ +void +AcpiUtPrintString ( + char *String, + UINT16 MaxLength); + +#if defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP +void +UtConvertBackslashes ( + char *Pathname); +#endif + +void +AcpiUtRepairName ( + char *Name); + +#if defined (ACPI_DEBUGGER) || defined (ACPI_APPLICATION) || defined (ACPI_DEBUG_OUTPUT) +BOOLEAN +AcpiUtSafeStrcpy ( + char *Dest, + ACPI_SIZE DestSize, + char *Source); + +void +AcpiUtSafeStrncpy ( + char *Dest, + char *Source, + ACPI_SIZE DestSize); + +BOOLEAN +AcpiUtSafeStrcat ( + char *Dest, + ACPI_SIZE DestSize, + char *Source); + +BOOLEAN +AcpiUtSafeStrncat ( + char *Dest, + ACPI_SIZE DestSize, + char *Source, + ACPI_SIZE MaxTransferLength); +#endif + + +/* + * 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); + +#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 ( + const 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 + */ +ACPI_PRINTF_LIKE(5) +void ACPI_INTERNAL_VAR_XFACE +AcpiUtPredefinedWarning ( + const char *ModuleName, + UINT32 LineNumber, + char *Pathname, + UINT16 NodeFlags, + const char *Format, + ...); + +ACPI_PRINTF_LIKE(5) +void ACPI_INTERNAL_VAR_XFACE +AcpiUtPredefinedInfo ( + const char *ModuleName, + UINT32 LineNumber, + char *Pathname, + UINT16 NodeFlags, + const char *Format, + ...); + +ACPI_PRINTF_LIKE(5) +void ACPI_INTERNAL_VAR_XFACE +AcpiUtPredefinedBiosError ( + const char *ModuleName, + UINT32 LineNumber, + char *Pathname, + UINT16 NodeFlags, + const char *Format, + ...); + +void +AcpiUtPrefixedNamespaceError ( + const char *ModuleName, + UINT32 LineNumber, + ACPI_GENERIC_STATE *PrefixScope, + 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); + + +/* + * Utility functions for ACPI names and IDs + */ +const AH_PREDEFINED_NAME * +AcpiAhMatchPredefinedName ( + char *Nameseg); + +const AH_DEVICE_ID * +AcpiAhMatchHardwareId ( + char *Hid); + +const char * +AcpiAhMatchUuid ( + UINT8 *Data); + + +/* + * utuuid -- UUID support functions + */ +#if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP || defined ACPI_HELP_APP) +void +AcpiUtConvertStringToUuid ( + char *InString, + UINT8 *UuidBuffer); + +ACPI_STATUS +AcpiUtConvertUuidToString ( + char *UuidBuffer, + char *OutString); +#endif + +#endif /* _ACUTILS_H */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/acuuid.h b/code/drivers/platform/acpi/third_party/acpica/include/acuuid.h new file mode 100644 index 0000000..0906254 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/acuuid.h @@ -0,0 +1,89 @@ +/****************************************************************************** + * + * Name: acuuid.h - ACPI-related UUID/GUID definitions + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACUUID_H__ +#define __ACUUID_H__ + +/* + * Note1: UUIDs and GUIDs are defined to be identical in ACPI. + * + * Note2: This file is standalone and should remain that way. + */ + +/* Controllers */ + +#define UUID_GPIO_CONTROLLER "4f248f40-d5e2-499f-834c-27758ea1cd3f" +#define UUID_USB_CONTROLLER "ce2ee385-00e6-48cb-9f05-2edb927c4899" +#define UUID_SATA_CONTROLLER "e4db149b-fcfe-425b-a6d8-92357d78fc7f" + +/* Devices */ + +#define UUID_PCI_HOST_BRIDGE "33db4d5b-1ff7-401c-9657-7441c03dd766" +#define UUID_I2C_DEVICE "3cdff6f7-4267-4555-ad05-b30a3d8938de" +#define UUID_POWER_BUTTON "dfbcf3c5-e7a5-44e6-9c1f-29c76f6e059c" +#define UUID_MEMORY_DEVICE "03b19910-f473-11dd-87af-0800200c9a66" +#define UUID_GENERIC_BUTTONS_DEVICE "fa6bd625-9ce8-470d-a2c7-b3ca36c4282e" +#define UUID_NVDIMM_ROOT_DEVICE "2f10e7a4-9e91-11e4-89d3-123b93f75cba" +#define UUID_CONTROL_METHOD_BATTERY "f18fc78b-0f15-4978-b793-53f833a1d35b" + +/* Interfaces */ + +#define UUID_DEVICE_LABELING "e5c937d0-3553-4d7a-9117-ea4d19c3434d" +#define UUID_PHYSICAL_PRESENCE "3dddfaa6-361b-4eb4-a424-8d10089d1653" + +/* TPM */ +#define UUID_HARDWARE_INFORMATION "cf8e16a5-c1e8-4e25-b712-4f54a96702c8" +#define UUID_START_METHOD "6bbf6cab-5463-4714-b7cd-f0203c0368d4" +#define UUID_MEMORY_CLEAR "376054ed-cc13-4675-901c-4756d7f2d45d" + +/* NVDIMM - NFIT table */ + +#define UUID_NFIT_DIMM "4309ac30-0d11-11e4-9191-0800200c9a66" +#define UUID_VOLATILE_MEMORY "7305944f-fdda-44e3-b16c-3f22d252e5d0" +#define UUID_PERSISTENT_MEMORY "66f0d379-b4f3-4074-ac43-0d3318b78cdb" +#define UUID_CONTROL_REGION "92f701f6-13b4-405d-910b-299367e8234c" +#define UUID_DATA_REGION "91af0530-5d86-470e-a6b0-0a2db9408249" +#define UUID_VOLATILE_VIRTUAL_DISK "77ab535a-45fc-624b-5560-f7b281d1f96e" +#define UUID_VOLATILE_VIRTUAL_CD "3d5abd30-4175-87ce-6d64-d2ade523c4bb" +#define UUID_PERSISTENT_VIRTUAL_DISK "5cea02c9-4d07-69d3-269f-4496fbe096f9" +#define UUID_PERSISTENT_VIRTUAL_CD "08018188-42cd-bb48-100f-5387d53ded3d" +#define UUID_NFIT_DIMM_N_MSFT "1ee68b36-d4bd-4a1a-9a16-4f8e53d46e05" +#define UUID_NFIT_DIMM_N_HPE1 "9002c334-acf3-4c0e-9642-a235f0d53bc6" +#define UUID_NFIT_DIMM_N_HPE2 "5008664b-b758-41a0-a03c-27c2f2d04f7e" +#define UUID_NFIT_DIMM_N_HYPERV "5746c5f2-a9a2-4264-ad0e-e4ddc9e09e80" + +/* Processor Properties (ACPI 6.2) */ + +#define UUID_CACHE_PROPERTIES "6DC63E77-257E-4E78-A973-A21F2796898D" +#define UUID_PHYSICAL_PROPERTY "DDE4D59A-AA42-4349-B407-EA40F57D9FB7" + +/* Modern Standby */ +#define UUID_LPS0_MICROSOFT "11E00D56-CE64-47CE-837B-1F898F9AA461" +#define UUID_LPS0_INTEL "C4EB40A0-6CD2-11E2-BCFD-0800200C9A66" +#define UUID_LPS0_AMD "E3F32452-FEBC-43CE-9039-932122D37721" + +/* Miscellaneous */ + +#define UUID_PLATFORM_CAPABILITIES "0811b06e-4a27-44f9-8d60-3cbbc22e7b48" +#define UUID_DYNAMIC_ENUMERATION "d8c1a3a6-be9b-4c9b-91bf-c3cb81fc5daf" +#define UUID_BATTERY_THERMAL_LIMIT "4c2067e3-887d-475c-9720-4af1d3ed602e" +#define UUID_THERMAL_EXTENSIONS "14d399cd-7a27-4b18-8fb4-7cb7b9f4e500" +#define UUID_DEVICE_PROPERTIES "daffd814-6eba-4d8c-8a91-bc9bbf4aa301" +#define UUID_DEVICE_GRAPHS "ab02a46b-74c7-45a2-bd68-f7d344ef2153" +#define UUID_HIERARCHICAL_DATA_EXTENSION "dbb8e3e6-5886-4ba6-8795-1319f52a966b" +#define UUID_CORESIGHT_GRAPH "3ecbc8b6-1d0e-4fb3-8107-e627f805c6cd" +#define UUID_USB4_CAPABILITIES "23a0d13a-26ab-486c-9c5f-0ffa525a575a" +#define UUID_1ST_FUNCTION_ID "893f00a6-660c-494e-bcfd-3043f4fb67c0" +#define UUID_2ND_FUNCTION_ID "107ededd-d381-4fd7-8da9-08e9a6c79644" +#define UUID_FAN_TRIP_POINTS "a7611840-99fe-41ae-a488-35c75926c8eb" +#endif /* __ACUUID_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/amlcode.h b/code/drivers/platform/acpi/third_party/acpica/include/amlcode.h new file mode 100644 index 0000000..c1fde40 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/amlcode.h @@ -0,0 +1,480 @@ +/****************************************************************************** + * + * 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) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __AMLCODE_H__ +#define __AMLCODE_H__ + +/* primary opcodes */ + +#define AML_ZERO_OP (UINT16) 0x00 +#define AML_ONE_OP (UINT16) 0x01 +#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_VARIABLE_PACKAGE_OP (UINT16) 0x13 /* ACPI 2.0 */ +#define AML_METHOD_OP (UINT16) 0x14 +#define AML_EXTERNAL_OP (UINT16) 0x15 /* ACPI 6.0 */ +#define AML_DUAL_NAME_PREFIX (UINT16) 0x2e +#define AML_MULTI_NAME_PREFIX (UINT16) 0x2f +#define AML_EXTENDED_PREFIX (UINT16) 0x5b +#define AML_ROOT_PREFIX (UINT16) 0x5c +#define AML_PARENT_PREFIX (UINT16) 0x5e +#define AML_FIRST_LOCAL_OP (UINT16) 0x60 /* Used for Local op # calculations */ +#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_FIRST_ARG_OP (UINT16) 0x68 /* Used for Arg op # calculations */ +#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_CONCATENATE_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_CONCATENATE_TEMPLATE_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_OBJECT_TYPE_OP (UINT16) 0x8e +#define AML_CREATE_QWORD_FIELD_OP (UINT16) 0x8f /* ACPI 2.0 */ +#define AML_LOGICAL_AND_OP (UINT16) 0x90 +#define AML_LOGICAL_OR_OP (UINT16) 0x91 +#define AML_LOGICAL_NOT_OP (UINT16) 0x92 +#define AML_LOGICAL_EQUAL_OP (UINT16) 0x93 +#define AML_LOGICAL_GREATER_OP (UINT16) 0x94 +#define AML_LOGICAL_LESS_OP (UINT16) 0x95 +#define AML_TO_BUFFER_OP (UINT16) 0x96 /* ACPI 2.0 */ +#define AML_TO_DECIMAL_STRING_OP (UINT16) 0x97 /* ACPI 2.0 */ +#define AML_TO_HEX_STRING_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_OBJECT_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_COMMENT_OP (UINT16) 0xa9 +#define AML_BREAKPOINT_OP (UINT16) 0xcc +#define AML_ONES_OP (UINT16) 0xff + + +/* + * Combination opcodes (actually two one-byte opcodes) + * Used by the disassembler and iASL compiler + */ +#define AML_LOGICAL_GREATER_EQUAL_OP (UINT16) 0x9295 /* LNot (LLess) */ +#define AML_LOGICAL_LESS_EQUAL_OP (UINT16) 0x9294 /* LNot (LGreater) */ +#define AML_LOGICAL_NOT_EQUAL_OP (UINT16) 0x9293 /* LNot (LEqual) */ + + +/* Prefixed (2-byte) opcodes (with AML_EXTENDED_PREFIX) */ + +#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 /* Obsolete, not in ACPI spec */ +#define AML_SHIFT_LEFT_BIT_OP (UINT16) 0x5b11 /* Obsolete, not in ACPI spec */ +#define AML_CONDITIONAL_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_RESOURCE_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 */ + + +/* + * 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_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 /* NameString | LocalTerm | ArgTerm */ +#define ARGP_NAME_OR_REF 0x13 /* For ObjectType only */ +#define ARGP_MAX 0x13 +#define ARGP_COMMENT 0x14 + +/* + * 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 */ +#define ARGI_STORE_TARGET 0x12 /* Target for store is TARGETREF + package objects */ + +/* Multiple/complex types */ + +#define ARGI_DATAOBJECT 0x13 /* Buffer, String, package or reference to a Node - Used only by SizeOf operator*/ +#define ARGI_COMPLEXOBJ 0x14 /* Buffer, String, or package (Used by INDEX op only) */ +#define ARGI_REF_OR_STRING 0x15 /* Reference or String (Used by DEREFOF op only) */ +#define ARGI_REGION_OR_BUFFER 0x16 /* Used by LOAD op only */ +#define ARGI_DATAREFOBJ 0x17 + +/* Note: types above can expand to 0x1F maximum */ + +#define ARGI_INVALID_OPCODE 0xFFFFFFFF + + +/* + * Some of the flags and types below are of the form: + * + * AML_FLAGS_EXEC_#A_#T,#R, or + * AML_TYPE_EXEC_#A_#T,#R where: + * + * #A is the number of required arguments + * #T is the number of target operands + * #R indicates whether there is a return value + * + * These types are used for the top-level dispatch of the AML + * opcode. They group similar operators that can share common + * front-end code before dispatch to the final code that implements + * the operator. + */ + +/* + * Opcode information 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 of the flags above */ + +#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 + * or add anything new without updating the table. + */ +#define AML_TYPE_EXEC_0A_0T_1R 0x00 /* 0 Args, 0 Target, 1 RetVal */ +#define AML_TYPE_EXEC_1A_0T_0R 0x01 /* 1 Args, 0 Target, 0 RetVal */ +#define AML_TYPE_EXEC_1A_0T_1R 0x02 /* 1 Args, 0 Target, 1 RetVal */ +#define AML_TYPE_EXEC_1A_1T_0R 0x03 /* 1 Args, 1 Target, 0 RetVal */ +#define AML_TYPE_EXEC_1A_1T_1R 0x04 /* 1 Args, 1 Target, 1 RetVal */ +#define AML_TYPE_EXEC_2A_0T_0R 0x05 /* 2 Args, 0 Target, 0 RetVal */ +#define AML_TYPE_EXEC_2A_0T_1R 0x06 /* 2 Args, 0 Target, 1 RetVal */ +#define AML_TYPE_EXEC_2A_1T_1R 0x07 /* 2 Args, 1 Target, 1 RetVal */ +#define AML_TYPE_EXEC_2A_2T_1R 0x08 /* 2 Args, 2 Target, 1 RetVal */ +#define AML_TYPE_EXEC_3A_0T_0R 0x09 /* 3 Args, 0 Target, 0 RetVal */ +#define AML_TYPE_EXEC_3A_1T_1R 0x0A /* 3 Args, 1 Target, 1 RetVal */ +#define AML_TYPE_EXEC_6A_0T_1R 0x0B /* 6 Args, 0 Target, 1 RetVal */ +/* End of types used in dispatch table */ + +#define AML_TYPE_LITERAL 0x0C +#define AML_TYPE_CONSTANT 0x0D +#define AML_TYPE_METHOD_ARGUMENT 0x0E +#define AML_TYPE_LOCAL_VARIABLE 0x0F +#define AML_TYPE_DATA_TERM 0x10 + +/* Generic for an op that returns a value */ + +#define AML_TYPE_METHOD_CALL 0x11 + +/* Miscellaneous types */ + +#define AML_TYPE_CREATE_FIELD 0x12 +#define AML_TYPE_CREATE_OBJECT 0x13 +#define AML_TYPE_CONTROL 0x14 +#define AML_TYPE_NAMED_NO_OBJ 0x15 +#define AML_TYPE_NAMED_FIELD 0x16 +#define AML_TYPE_NAMED_SIMPLE 0x17 +#define AML_TYPE_NAMED_COMPLEX 0x18 +#define AML_TYPE_RETURN 0x19 +#define AML_TYPE_UNDEFINED 0x1A +#define AML_TYPE_BOGUS 0x1B + +/* 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_RECEIVE = 0x04, + AML_FIELD_ATTRIB_BYTE = 0x06, + AML_FIELD_ATTRIB_WORD = 0x08, + AML_FIELD_ATTRIB_BLOCK = 0x0A, + AML_FIELD_ATTRIB_BYTES = 0x0B, + AML_FIELD_ATTRIB_PROCESS_CALL = 0x0C, + AML_FIELD_ATTRIB_BLOCK_PROCESS_CALL = 0x0D, + AML_FIELD_ATTRIB_RAW_BYTES = 0x0E, + AML_FIELD_ATTRIB_RAW_PROCESS_BYTES = 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/code/drivers/platform/acpi/third_party/acpica/include/amlresrc.h b/code/drivers/platform/acpi/third_party/acpica/include/amlresrc.h new file mode 100644 index 0000000..4cbb50d --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/amlresrc.h @@ -0,0 +1,762 @@ +/****************************************************************************** + * + * Module Name: amlresrc.h - AML resource descriptors + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +/* 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_FUNCTION "_FUN" +#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_LOCALPORT "_PRT" +#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_PHYTYPE "_PHY" +#define ACPI_RESTAG_PIN "_PIN" +#define ACPI_RESTAG_PINCONFIG "_PPI" +#define ACPI_RESTAG_PINCONFIG_TYPE "_TYP" +#define ACPI_RESTAG_PINCONFIG_VALUE "_VAL" +#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" +#define ACPI_RESTAG_FQN "_FQN" +#define ACPI_RESTAG_FQD "_FQD" + + +/* 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; + +typedef struct asl_resource_info +{ + ACPI_PARSE_OBJECT *DescriptorTypeOp; /* Resource descriptor parse node */ + ACPI_PARSE_OBJECT *MappingOp; /* Used for mapfile support */ + UINT32 CurrentByteOffset; /* Offset in resource template */ + +} ASL_RESOURCE_INFO; + + +/* 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; + union { + UINT32 Interrupt; + ACPI_FLEX_ARRAY(UINT32, Interrupts); + }; + /* 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_CSI2_SERIALBUSTYPE 4 +#define AML_RESOURCE_MAX_SERIALBUSTYPE 4 +#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_csi2_serialbus +{ + AML_RESOURCE_LARGE_HEADER_COMMON + AML_RESOURCE_SERIAL_COMMON + + /* + * Optional fields follow immediately: + * 1) Vendor Data bytes + * 2) Resource Source String + */ + +} AML_RESOURCE_CSI2_SERIALBUS; + +#define AML_RESOURCE_CSI2_REVISION 1 /* ACPI 6.4 */ +#define AML_RESOURCE_CSI2_TYPE_REVISION 1 /* ACPI 6.4 */ +#define AML_RESOURCE_CSI2_MIN_DATA_LEN 0 /* ACPI 6.4 */ + +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 + +typedef struct aml_resource_pin_function +{ + AML_RESOURCE_LARGE_HEADER_COMMON + UINT8 RevisionId; + UINT16 Flags; + UINT8 PinConfig; + UINT16 FunctionNumber; + 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_PIN_FUNCTION; + +#define AML_RESOURCE_PIN_FUNCTION_REVISION 1 /* ACPI 6.2 */ + +typedef struct aml_resource_pin_config +{ + AML_RESOURCE_LARGE_HEADER_COMMON + UINT8 RevisionId; + UINT16 Flags; + UINT8 PinConfigType; + UINT32 PinConfigValue; + 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_PIN_CONFIG; + +#define AML_RESOURCE_CLOCK_INPUT_REVISION 1 /* ACPI 6.5 */ + +typedef struct aml_resource_clock_input +{ + AML_RESOURCE_LARGE_HEADER_COMMON + UINT8 RevisionId; + UINT16 Flags; + UINT16 FrequencyDivisor; + UINT32 FrequencyNumerator; + /* + * Optional fields follow immediately: + * 1) Resource Source index + * 2) Resource Source String + */ +} AML_RESOURCE_CLOCK_INPUT; + + +#define AML_RESOURCE_PIN_CONFIG_REVISION 1 /* ACPI 6.2 */ + +typedef struct aml_resource_pin_group +{ + AML_RESOURCE_LARGE_HEADER_COMMON + UINT8 RevisionId; + UINT16 Flags; + UINT16 PinTableOffset; + UINT16 LabelOffset; + UINT16 VendorOffset; + UINT16 VendorLength; + /* + * Optional fields follow immediately: + * 1) PIN list (Words) + * 2) Resource Label String + * 3) Vendor Data bytes + */ + +} AML_RESOURCE_PIN_GROUP; + +#define AML_RESOURCE_PIN_GROUP_REVISION 1 /* ACPI 6.2 */ + +typedef struct aml_resource_pin_group_function +{ + AML_RESOURCE_LARGE_HEADER_COMMON + UINT8 RevisionId; + UINT16 Flags; + UINT16 FunctionNumber; + UINT8 ResSourceIndex; + UINT16 ResSourceOffset; + UINT16 ResSourceLabelOffset; + UINT16 VendorOffset; + UINT16 VendorLength; + /* + * Optional fields follow immediately: + * 1) Resource Source String + * 2) Resource Source Label String + * 3) Vendor Data bytes + */ + +} AML_RESOURCE_PIN_GROUP_FUNCTION; + +#define AML_RESOURCE_PIN_GROUP_FUNCTION_REVISION 1 /* ACPI 6.2 */ + +typedef struct aml_resource_pin_group_config +{ + AML_RESOURCE_LARGE_HEADER_COMMON + UINT8 RevisionId; + UINT16 Flags; + UINT8 PinConfigType; + UINT32 PinConfigValue; + UINT8 ResSourceIndex; + UINT16 ResSourceOffset; + UINT16 ResSourceLabelOffset; + UINT16 VendorOffset; + UINT16 VendorLength; + /* + * Optional fields follow immediately: + * 1) Resource Source String + * 2) Resource Source Label String + * 3) Vendor Data bytes + */ + +} AML_RESOURCE_PIN_GROUP_CONFIG; + +#define AML_RESOURCE_PIN_GROUP_CONFIG_REVISION 1 /* ACPI 6.2 */ + +/* 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_CSI2_SERIALBUS Csi2SerialBus; + AML_RESOURCE_COMMON_SERIALBUS CommonSerialBus; + AML_RESOURCE_PIN_FUNCTION PinFunction; + AML_RESOURCE_PIN_CONFIG PinConfig; + AML_RESOURCE_PIN_GROUP PinGroup; + AML_RESOURCE_PIN_GROUP_FUNCTION PinGroupFunction; + AML_RESOURCE_PIN_GROUP_CONFIG PinGroupConfig; + AML_RESOURCE_CLOCK_INPUT ClockInput; + + /* Utility overlays */ + + AML_RESOURCE_ADDRESS Address; + UINT32 DwordItem; + UINT16 WordItem; + UINT8 ByteItem; + +} AML_RESOURCE; + +/* restore default alignment */ + +#pragma pack() + +/* Interfaces used by both the disassembler and compiler */ + +void +MpSaveGpioInfo ( + ACPI_PARSE_OBJECT *Op, + AML_RESOURCE *Resource, + UINT32 PinCount, + UINT16 *PinList, + char *DeviceName); + +void +MpSaveSerialInfo ( + ACPI_PARSE_OBJECT *Op, + AML_RESOURCE *Resource, + char *DeviceName); + +char * +MpGetHidFromParseTree ( + ACPI_NAMESPACE_NODE *HidNode); + +char * +MpGetHidViaNamestring ( + char *DeviceName); + +char * +MpGetConnectionInfo ( + ACPI_PARSE_OBJECT *Op, + UINT32 PinIndex, + ACPI_NAMESPACE_NODE **TargetNode, + char **TargetName); + +char * +MpGetParentDeviceHid ( + ACPI_PARSE_OBJECT *Op, + ACPI_NAMESPACE_NODE **TargetNode, + char **ParentDeviceName); + +char * +MpGetDdnValue ( + char *DeviceName); + +char * +MpGetHidValue ( + ACPI_NAMESPACE_NODE *DeviceNode); + +#endif diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/accygwin.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/accygwin.h new file mode 100644 index 0000000..a346150 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/accygwin.h @@ -0,0 +1,71 @@ +/****************************************************************************** + * + * Name: accygwin.h - OS specific defines, etc. for cygwin environment + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACCYGWIN_H__ +#define __ACCYGWIN_H__ + +/* + * ACPICA configuration + */ +#define ACPI_USE_STANDARD_HEADERS +#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 + + +#ifdef ACPI_USE_STANDARD_HEADERS +#include +#endif + +#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 +#define ACPI_USE_NATIVE_MATH64 +#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)) + + +/* + * The vsnprintf/snprintf functions are defined by c99, but cygwin/gcc + * does not enable this prototype when the -ansi flag is set. Also related + * to __STRICT_ANSI__. So, we just declare the prototype here. + */ +int +vsnprintf (char *s, size_t n, const char *format, va_list ap); + +int +snprintf (char *s, size_t n, const char *format, ...); + +#endif /* __ACCYGWIN_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/acdragonfly.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acdragonfly.h new file mode 100644 index 0000000..94d2808 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acdragonfly.h @@ -0,0 +1,236 @@ +/****************************************************************************** + * + * Name: acdragonfly.h - OS specific for DragonFly BSD + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + ***************************************************************************** + * + * Alternatively, you may choose to be licensed under the terms of the + * following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, you may choose to be licensed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + *****************************************************************************/ + +#ifndef __ACDRAGONFLY_H_ +#define __ACDRAGONFLY_H_ + +#include + +#ifdef __LP64__ +#define ACPI_MACHINE_WIDTH 64 +#else +#define ACPI_MACHINE_WIDTH 32 +#define ACPI_USE_NATIVE_DIVIDE +#define ACPI_USE_NATIVE_MATH64 +#endif + +#define ACPI_UINTPTR_T uintptr_t +#define COMPILER_DEPENDENT_INT64 int64_t +#define COMPILER_DEPENDENT_UINT64 uint64_t + +#define ACPI_USE_DO_WHILE_0 +#define ACPI_USE_SYSTEM_CLIBRARY + +#ifdef _KERNEL + +#include "opt_acpi.h" +#include +#include +#include +#include + +#ifdef ACPI_DEBUG +#define ACPI_DEBUG_OUTPUT /* enable debug output */ +#ifdef DEBUGGER_THREADING +#undef DEBUGGER_THREADING +#endif /* DEBUGGER_THREADING */ +#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED /* integrated with DDB */ +#include "opt_ddb.h" +#ifdef DDB +#define ACPI_DEBUGGER +#endif /* DDB */ +#define ACPI_DISASSEMBLER +#endif + +#ifdef ACPI_DEBUG_CACHE +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsReleaseObject +#define AcpiOsReleaseObject(Cache, Object) \ + _AcpiOsReleaseObject((Cache), (Object), __func__, __LINE__) +#endif + +#ifdef ACPI_DEBUG_LOCKS +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsAcquireLock +#define AcpiOsAcquireLock(Handle) \ + _AcpiOsAcquireLock((Handle), __func__, __LINE__) +#endif + +#ifdef ACPI_DEBUG_MEMMAP +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsMapMemory +#define AcpiOsMapMemory(Where, Length) \ + _AcpiOsMapMemory((Where), (Length), __func__, __LINE__) + +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsUnmapMemory +#define AcpiOsUnmapMemory(LogicalAddress, Size) \ + _AcpiOsUnmapMemory((LogicalAddress), (Size), __func__, __LINE__) +#endif + +/* XXX TBI */ +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsWaitEventsComplete +#define AcpiOsWaitEventsComplete() + +#define USE_NATIVE_ALLOCATE_ZEROED + +#define ACPI_SPINLOCK struct acpi_spinlock * +struct acpi_spinlock; + +#define ACPI_CACHE_T struct acpicache +struct acpicache; + +#else /* _KERNEL */ + +#define ACPI_USE_STANDARD_HEADERS + +#define ACPI_CAST_PTHREAD_T(pthread) ((ACPI_THREAD_ID) ACPI_TO_INTEGER (pthread)) +#define ACPI_FLUSH_CPU_CACHE() + +#endif /* _KERNEL */ + +#endif /* __ACDRAGONFLY_H_ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/acdragonflyex.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acdragonflyex.h new file mode 100644 index 0000000..ebd015c --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acdragonflyex.h @@ -0,0 +1,54 @@ +/****************************************************************************** + * + * Name: acdragonflyex.h - Extra OS specific defines, etc. for DragonFly BSD + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACDRAGONFLYEX_H__ +#define __ACDRAGONFLYEX_H__ + +#ifdef _KERNEL + +#ifdef ACPI_DEBUG_CACHE +ACPI_STATUS +_AcpiOsReleaseObject ( + ACPI_CACHE_T *Cache, + void *Object, + const char *func, + int line); +#endif + +#ifdef ACPI_DEBUG_LOCKS +ACPI_CPU_FLAGS +_AcpiOsAcquireLock ( + ACPI_SPINLOCK Spin, + const char *func, + int line); +#endif + +#ifdef ACPI_DEBUG_MEMMAP +void * +_AcpiOsMapMemory ( + ACPI_PHYSICAL_ADDRESS Where, + ACPI_SIZE Length, + const char *caller, + int line); + +void +_AcpiOsUnmapMemory ( + void *LogicalAddress, + ACPI_SIZE Length, + const char *caller, + int line); +#endif + +#endif /* _KERNEL */ + +#endif /* __ACDRAGONFLYEX_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/acefi.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acefi.h new file mode 100644 index 0000000..75e94db --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acefi.h @@ -0,0 +1,285 @@ +/****************************************************************************** + * + * Name: acefi.h - OS specific defines, etc. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACEFI_H__ +#define __ACEFI_H__ + +/* + * Single threaded environment where Mutex/Event/Sleep are fake. This model is + * sufficient for pre-boot AcpiExec. + */ +#ifndef DEBUGGER_THREADING +#define DEBUGGER_THREADING DEBUGGER_SINGLE_THREADED +#endif /* !DEBUGGER_THREADING */ + +/* EDK2 EFI environment */ + +#if defined(_EDK2_EFI) + +#ifdef USE_STDLIB +#define ACPI_USE_STANDARD_HEADERS +#define ACPI_USE_SYSTEM_CLIBRARY +#define ACPI_USE_NATIVE_DIVIDE +#define ACPI_USE_NATIVE_MATH64 +#endif + +#endif + +#if defined(__x86_64__) +#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) +#define USE_MS_ABI 1 +#endif +#endif + +#ifdef _MSC_EXTENSIONS +#define ACPI_EFI_API __cdecl +#elif USE_MS_ABI +#define ACPI_EFI_API __attribute__((ms_abi)) +#else +#define ACPI_EFI_API +#endif + +#define VOID void + +#if defined(__ia64__) || defined(__x86_64__) || __riscv_xlen == 64 + +#define ACPI_MACHINE_WIDTH 64 + +#if defined(__x86_64__) + +/* for x86_64, EFI_FUNCTION_WRAPPER must be defined */ + +#ifndef USE_MS_ABI +#define USE_EFI_FUNCTION_WRAPPER +#endif + +#ifdef _MSC_EXTENSIONS +#pragma warning ( disable : 4731 ) /* Suppress warnings about modification of EBP */ +#endif + +#endif + +#ifndef USE_STDLIB +#define UINTN uint64_t +#define INTN int64_t +#endif + +#define ACPI_EFI_ERR(a) (0x8000000000000000 | a) + +#else + +#define ACPI_MACHINE_WIDTH 32 + +#ifndef USE_STDLIB +#define UINTN uint32_t +#define INTN int32_t +#endif + +#define ACPI_EFI_ERR(a) (0x80000000 | a) + +#endif + +#define CHAR16 uint16_t + +#ifdef USE_EFI_FUNCTION_WRAPPER +#define __VA_NARG__(...) \ + __VA_NARG_(_0, ## __VA_ARGS__, __RSEQ_N()) +#define __VA_NARG_(...) \ + __VA_ARG_N(__VA_ARGS__) +#define __VA_ARG_N( \ + _0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,N,...) N +#define __RSEQ_N() \ + 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 + +#define __VA_ARG_NSUFFIX__(prefix,...) \ + __VA_ARG_NSUFFIX_N(prefix, __VA_NARG__(__VA_ARGS__)) +#define __VA_ARG_NSUFFIX_N(prefix,nargs) \ + __VA_ARG_NSUFFIX_N_(prefix, nargs) +#define __VA_ARG_NSUFFIX_N_(prefix,nargs) \ + prefix ## nargs + +/* Prototypes of EFI cdecl -> stdcall trampolines */ + +UINT64 efi_call0(void *func); +UINT64 efi_call1(void *func, UINT64 arg1); +UINT64 efi_call2(void *func, UINT64 arg1, UINT64 arg2); +UINT64 efi_call3(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3); +UINT64 efi_call4(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4); +UINT64 efi_call5(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5); +UINT64 efi_call6(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6); +UINT64 efi_call7(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7); +UINT64 efi_call8(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7, + UINT64 arg8); +UINT64 efi_call9(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7, + UINT64 arg8, UINT64 arg9); +UINT64 efi_call10(void *func, UINT64 arg1, UINT64 arg2, UINT64 arg3, + UINT64 arg4, UINT64 arg5, UINT64 arg6, UINT64 arg7, + UINT64 arg8, UINT64 arg9, UINT64 arg10); + +/* Front-ends to efi_callX to avoid compiler warnings */ + +#define _cast64_efi_call0(f) \ + efi_call0(f) +#define _cast64_efi_call1(f,a1) \ + efi_call1(f, (UINT64)(a1)) +#define _cast64_efi_call2(f,a1,a2) \ + efi_call2(f, (UINT64)(a1), (UINT64)(a2)) +#define _cast64_efi_call3(f,a1,a2,a3) \ + efi_call3(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3)) +#define _cast64_efi_call4(f,a1,a2,a3,a4) \ + efi_call4(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4)) +#define _cast64_efi_call5(f,a1,a2,a3,a4,a5) \ + efi_call5(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5)) +#define _cast64_efi_call6(f,a1,a2,a3,a4,a5,a6) \ + efi_call6(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6)) +#define _cast64_efi_call7(f,a1,a2,a3,a4,a5,a6,a7) \ + efi_call7(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6), (UINT64)(a7)) +#define _cast64_efi_call8(f,a1,a2,a3,a4,a5,a6,a7,a8) \ + efi_call8(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8)) +#define _cast64_efi_call9(f,a1,a2,a3,a4,a5,a6,a7,a8,a9) \ + efi_call9(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8), \ + (UINT64)(a9)) +#define _cast64_efi_call10(f,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10) \ + efi_call10(f, (UINT64)(a1), (UINT64)(a2), (UINT64)(a3), (UINT64)(a4), \ + (UINT64)(a5), (UINT64)(a6), (UINT64)(a7), (UINT64)(a8), \ + (UINT64)(a9), (UINT64)(a10)) + +/* main wrapper (va_num ignored) */ + +#define uefi_call_wrapper(func,va_num,...) \ + __VA_ARG_NSUFFIX__(_cast64_efi_call, __VA_ARGS__) (func , ##__VA_ARGS__) + +#else + +#define uefi_call_wrapper(func, va_num, ...) func(__VA_ARGS__) + +#endif + +/* AED EFI definitions */ + +#if defined(_AED_EFI) + +/* _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 + + +/* EFI math64 definitions */ + +#if defined(_GNU_EFI) || defined(_EDK2_EFI) +/* + * Math helpers, GNU EFI provided a platform independent 64-bit math + * support. + */ +#ifndef ACPI_DIV_64_BY_32 +#define ACPI_DIV_64_BY_32(n_hi, n_lo, d32, q32, r32) \ + do { \ + UINT64 __n = ((UINT64) n_hi) << 32 | (n_lo); \ + (q32) = (UINT32) DivU64x32 ((__n), (d32), &(r32)); \ + } while (0) +#endif + +#ifndef ACPI_MUL_64_BY_32 +#define ACPI_MUL_64_BY_32(n_hi, n_lo, m32, p32, c32) \ + do { \ + UINT64 __n = ((UINT64) n_hi) << 32 | (n_lo); \ + UINT64 __p = MultU64x32 (__n, (m32)); \ + (p32) = (UINT32) __p; \ + (c32) = (UINT32) (__p >> 32); \ + } while (0) +#endif + +#ifndef ACPI_SHIFT_LEFT_64_by_32 +#define ACPI_SHIFT_LEFT_64_BY_32(n_hi, n_lo, s32) \ + do { \ + UINT64 __n = ((UINT64) n_hi) << 32 | (n_lo); \ + UINT64 __r = LShiftU64 (__n, (s32)); \ + (n_lo) = (UINT32) __r; \ + (n_hi) = (UINT32) (__r >> 32); \ + } while (0) +#endif + +#ifndef ACPI_SHIFT_RIGHT_64_BY_32 +#define ACPI_SHIFT_RIGHT_64_BY_32(n_hi, n_lo, s32) \ + do { \ + UINT64 __n = ((UINT64) n_hi) << 32 | (n_lo); \ + UINT64 __r = RShiftU64 (__n, (s32)); \ + (n_lo) = (UINT32) __r; \ + (n_hi) = (UINT32) (__r >> 32); \ + } while (0) +#endif + +#ifndef ACPI_SHIFT_RIGHT_64 +#define ACPI_SHIFT_RIGHT_64(n_hi, n_lo) \ + do { \ + (n_lo) >>= 1; \ + (n_lo) |= (((n_hi) & 1) << 31); \ + (n_hi) >>= 1; \ + } while (0) +#endif +#endif + +struct _ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE; +struct _ACPI_SIMPLE_INPUT_INTERFACE; +struct _ACPI_EFI_FILE_IO_INTERFACE; +struct _ACPI_EFI_FILE_HANDLE; +struct _ACPI_EFI_BOOT_SERVICES; +struct _ACPI_EFI_RUNTIME_SERVICES; +struct _ACPI_EFI_SYSTEM_TABLE; +struct _ACPI_EFI_PCI_IO; + +extern struct _ACPI_EFI_SYSTEM_TABLE *ST; +extern struct _ACPI_EFI_BOOT_SERVICES *BS; +extern struct _ACPI_EFI_RUNTIME_SERVICES *RT; + +#ifndef USE_STDLIB +typedef union acpi_efi_file ACPI_EFI_FILE; +#define FILE ACPI_EFI_FILE + +extern FILE *stdin; +extern FILE *stdout; +extern FILE *stderr; +#endif + +#endif /* __ACEFI_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/acefiex.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acefiex.h new file mode 100644 index 0000000..c6c43f2 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acefiex.h @@ -0,0 +1,1034 @@ +/****************************************************************************** + * + * Name: acefiex.h - Extra OS specific defines, etc. for EFI + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACEFIEX_H__ +#define __ACEFIEX_H__ + + +#ifndef ACPI_USE_SYSTEM_CLIBRARY + +typedef signed char int8_t; +typedef short int int16_t; +typedef int int32_t; +typedef unsigned char uint8_t; +typedef unsigned short int uint16_t; +typedef unsigned int uint32_t; +typedef COMPILER_DEPENDENT_INT64 int64_t; +typedef COMPILER_DEPENDENT_UINT64 uint64_t; + +#endif /* ACPI_USE_SYSTEM_CLIBRARY */ + +#define ACPI_EFI_ERROR(a) (((INTN) a) < 0) +#define ACPI_EFI_SUCCESS 0 +#define ACPI_EFI_LOAD_ERROR ACPI_EFI_ERR(1) +#define ACPI_EFI_INVALID_PARAMETER ACPI_EFI_ERR(2) +#define ACPI_EFI_UNSUPPORTED ACPI_EFI_ERR(3) +#define ACPI_EFI_BAD_BUFFER_SIZE ACPI_EFI_ERR(4) +#define ACPI_EFI_BUFFER_TOO_SMALL ACPI_EFI_ERR(5) +#define ACPI_EFI_NOT_READY ACPI_EFI_ERR(6) +#define ACPI_EFI_DEVICE_ERROR ACPI_EFI_ERR(7) +#define ACPI_EFI_WRITE_PROTECTED ACPI_EFI_ERR(8) +#define ACPI_EFI_OUT_OF_RESOURCES ACPI_EFI_ERR(9) +#define ACPI_EFI_VOLUME_CORRUPTED ACPI_EFI_ERR(10) +#define ACPI_EFI_VOLUME_FULL ACPI_EFI_ERR(11) +#define ACPI_EFI_NO_MEDIA ACPI_EFI_ERR(12) +#define ACPI_EFI_MEDIA_CHANGED ACPI_EFI_ERR(13) +#define ACPI_EFI_NOT_FOUND ACPI_EFI_ERR(14) +#define ACPI_EFI_ACCESS_DENIED ACPI_EFI_ERR(15) +#define ACPI_EFI_NO_RESPONSE ACPI_EFI_ERR(16) +#define ACPI_EFI_NO_MAPPING ACPI_EFI_ERR(17) +#define ACPI_EFI_TIMEOUT ACPI_EFI_ERR(18) +#define ACPI_EFI_NOT_STARTED ACPI_EFI_ERR(19) +#define ACPI_EFI_ALREADY_STARTED ACPI_EFI_ERR(20) +#define ACPI_EFI_ABORTED ACPI_EFI_ERR(21) +#define ACPI_EFI_PROTOCOL_ERROR ACPI_EFI_ERR(24) + + +typedef UINTN ACPI_EFI_STATUS; +typedef VOID *ACPI_EFI_HANDLE; +typedef VOID *ACPI_EFI_EVENT; + +typedef struct { + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; +} ACPI_EFI_GUID; + +typedef struct { + UINT16 Year; /* 1998 - 20XX */ + UINT8 Month; /* 1 - 12 */ + UINT8 Day; /* 1 - 31 */ + UINT8 Hour; /* 0 - 23 */ + UINT8 Minute; /* 0 - 59 */ + UINT8 Second; /* 0 - 59 */ + UINT8 Pad1; + UINT32 Nanosecond; /* 0 - 999,999,999 */ + INT16 TimeZone; /* -1440 to 1440 or 2047 */ + UINT8 Daylight; + UINT8 Pad2; +} ACPI_EFI_TIME; + +typedef struct _ACPI_EFI_DEVICE_PATH { + UINT8 Type; + UINT8 SubType; + UINT8 Length[2]; +} ACPI_EFI_DEVICE_PATH; + +typedef UINT64 ACPI_EFI_PHYSICAL_ADDRESS; +typedef UINT64 ACPI_EFI_VIRTUAL_ADDRESS; + +typedef enum { + AcpiEfiAllocateAnyPages, + AcpiEfiAllocateMaxAddress, + AcpiEfiAllocateAddress, + AcpiEfiMaxAllocateType +} ACPI_EFI_ALLOCATE_TYPE; + +typedef enum { + AcpiEfiReservedMemoryType, + AcpiEfiLoaderCode, + AcpiEfiLoaderData, + AcpiEfiBootServicesCode, + AcpiEfiBootServicesData, + AcpiEfiRuntimeServicesCode, + AcpiEfiRuntimeServicesData, + AcpiEfiConventionalMemory, + AcpiEfiUnusableMemory, + AcpiEfiACPIReclaimMemory, + AcpiEfiACPIMemoryNVS, + AcpiEfiMemoryMappedIO, + AcpiEfiMemoryMappedIOPortSpace, + AcpiEfiPalCode, + AcpiEfiMaxMemoryType +} ACPI_EFI_MEMORY_TYPE; + +/* possible caching types for the memory range */ +#define ACPI_EFI_MEMORY_UC 0x0000000000000001 +#define ACPI_EFI_MEMORY_WC 0x0000000000000002 +#define ACPI_EFI_MEMORY_WT 0x0000000000000004 +#define ACPI_EFI_MEMORY_WB 0x0000000000000008 +#define ACPI_EFI_MEMORY_UCE 0x0000000000000010 + +/* physical memory protection on range */ +#define ACPI_EFI_MEMORY_WP 0x0000000000001000 +#define ACPI_EFI_MEMORY_RP 0x0000000000002000 +#define ACPI_EFI_MEMORY_XP 0x0000000000004000 + +/* range requires a runtime mapping */ +#define ACPI_EFI_MEMORY_RUNTIME 0x8000000000000000 + +#define ACPI_EFI_MEMORY_DESCRIPTOR_VERSION 1 +typedef struct { + UINT32 Type; + UINT32 Pad; + ACPI_EFI_PHYSICAL_ADDRESS PhysicalStart; + ACPI_EFI_VIRTUAL_ADDRESS VirtualStart; + UINT64 NumberOfPages; + UINT64 Attribute; +} ACPI_EFI_MEMORY_DESCRIPTOR; + +typedef struct _ACPI_EFI_TABLE_HEARDER { + UINT64 Signature; + UINT32 Revision; + UINT32 HeaderSize; + UINT32 CRC32; + UINT32 Reserved; +} ACPI_EFI_TABLE_HEADER; + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_UNKNOWN_INTERFACE) ( + void); + + +/* + * Text output protocol + */ +#define ACPI_SIMPLE_TEXT_OUTPUT_PROTOCOL \ + { 0x387477c2, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_TEXT_RESET) ( + struct _ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE *This, + BOOLEAN ExtendedVerification); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_TEXT_OUTPUT_STRING) ( + struct _ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE *This, + CHAR16 *String); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_TEXT_TEST_STRING) ( + struct _ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE *This, + CHAR16 *String); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_TEXT_QUERY_MODE) ( + struct _ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE *This, + UINTN ModeNumber, + UINTN *Columns, + UINTN *Rows); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_TEXT_SET_MODE) ( + struct _ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE *This, + UINTN ModeNumber); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_TEXT_SET_ATTRIBUTE) ( + struct _ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE *This, + UINTN Attribute); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_TEXT_CLEAR_SCREEN) ( + struct _ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE *This); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_TEXT_SET_CURSOR_POSITION) ( + struct _ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE *This, + UINTN Column, + UINTN Row); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_TEXT_ENABLE_CURSOR) ( + struct _ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE *This, + BOOLEAN Enable); + +typedef struct { + INT32 MaxMode; + INT32 Mode; + INT32 Attribute; + INT32 CursorColumn; + INT32 CursorRow; + BOOLEAN CursorVisible; +} ACPI_SIMPLE_TEXT_OUTPUT_MODE; + +typedef struct _ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE { + ACPI_EFI_TEXT_RESET Reset; + + ACPI_EFI_TEXT_OUTPUT_STRING OutputString; + ACPI_EFI_TEXT_TEST_STRING TestString; + + ACPI_EFI_TEXT_QUERY_MODE QueryMode; + ACPI_EFI_TEXT_SET_MODE SetMode; + ACPI_EFI_TEXT_SET_ATTRIBUTE SetAttribute; + + ACPI_EFI_TEXT_CLEAR_SCREEN ClearScreen; + ACPI_EFI_TEXT_SET_CURSOR_POSITION SetCursorPosition; + ACPI_EFI_TEXT_ENABLE_CURSOR EnableCursor; + + ACPI_SIMPLE_TEXT_OUTPUT_MODE *Mode; +} ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE; + +/* + * Text input protocol + */ +#define ACPI_SIMPLE_TEXT_INPUT_PROTOCOL \ + { 0x387477c1, 0x69c7, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +typedef struct { + UINT16 ScanCode; + CHAR16 UnicodeChar; +} ACPI_EFI_INPUT_KEY; + +/* + * Baseline unicode control chars + */ +#define CHAR_NULL 0x0000 +#define CHAR_BACKSPACE 0x0008 +#define CHAR_TAB 0x0009 +#define CHAR_LINEFEED 0x000A +#define CHAR_CARRIAGE_RETURN 0x000D + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_INPUT_RESET) ( + struct _ACPI_SIMPLE_INPUT_INTERFACE *This, + BOOLEAN ExtendedVerification); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_INPUT_READ_KEY) ( + struct _ACPI_SIMPLE_INPUT_INTERFACE *This, + ACPI_EFI_INPUT_KEY *Key); + +typedef struct _ACPI_SIMPLE_INPUT_INTERFACE { + ACPI_EFI_INPUT_RESET Reset; + ACPI_EFI_INPUT_READ_KEY ReadKeyStroke; + ACPI_EFI_EVENT WaitForKey; +} ACPI_SIMPLE_INPUT_INTERFACE; + + +/* + * Simple file system protocol + */ +#define ACPI_SIMPLE_FILE_SYSTEM_PROTOCOL \ + { 0x964e5b22, 0x6459, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_VOLUME_OPEN) ( + struct _ACPI_EFI_FILE_IO_INTERFACE *This, + struct _ACPI_EFI_FILE_HANDLE **Root); + +#define ACPI_EFI_FILE_IO_INTERFACE_REVISION 0x00010000 + +typedef struct _ACPI_EFI_FILE_IO_INTERFACE { + UINT64 Revision; + ACPI_EFI_VOLUME_OPEN OpenVolume; +} ACPI_EFI_FILE_IO_INTERFACE; + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_FILE_OPEN) ( + struct _ACPI_EFI_FILE_HANDLE *File, + struct _ACPI_EFI_FILE_HANDLE **NewHandle, + CHAR16 *FileName, + UINT64 OpenMode, + UINT64 Attributes); + +/* Values for OpenMode used above */ + +#define ACPI_EFI_FILE_MODE_READ 0x0000000000000001 +#define ACPI_EFI_FILE_MODE_WRITE 0x0000000000000002 +#define ACPI_EFI_FILE_MODE_CREATE 0x8000000000000000 + +/* Values for Attribute used above */ + +#define ACPI_EFI_FILE_READ_ONLY 0x0000000000000001 +#define ACPI_EFI_FILE_HIDDEN 0x0000000000000002 +#define ACPI_EFI_FILE_SYSTEM 0x0000000000000004 +#define ACPI_EFI_FILE_RESERVIED 0x0000000000000008 +#define ACPI_EFI_FILE_DIRECTORY 0x0000000000000010 +#define ACPI_EFI_FILE_ARCHIVE 0x0000000000000020 +#define ACPI_EFI_FILE_VALID_ATTR 0x0000000000000037 + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_FILE_CLOSE) ( + struct _ACPI_EFI_FILE_HANDLE *File); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_FILE_DELETE) ( + struct _ACPI_EFI_FILE_HANDLE *File); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_FILE_READ) ( + struct _ACPI_EFI_FILE_HANDLE *File, + UINTN *BufferSize, + VOID *Buffer); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_FILE_WRITE) ( + struct _ACPI_EFI_FILE_HANDLE *File, + UINTN *BufferSize, + VOID *Buffer); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_FILE_SET_POSITION) ( + struct _ACPI_EFI_FILE_HANDLE *File, + UINT64 Position); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_FILE_GET_POSITION) ( + struct _ACPI_EFI_FILE_HANDLE *File, + UINT64 *Position); + +#define ACPI_EFI_FILE_INFO_ID \ + { 0x9576e92, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} } + +typedef struct { + UINT64 Size; + UINT64 FileSize; + UINT64 PhysicalSize; + ACPI_EFI_TIME CreateTime; + ACPI_EFI_TIME LastAccessTime; + ACPI_EFI_TIME ModificationTime; + UINT64 Attribute; + CHAR16 FileName[]; +} ACPI_EFI_FILE_INFO; + +#define SIZE_OF_ACPI_EFI_FILE_INFO ACPI_OFFSET(ACPI_EFI_FILE_INFO, FileName) + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_FILE_GET_INFO) ( + struct _ACPI_EFI_FILE_HANDLE *File, + ACPI_EFI_GUID *InformationType, + UINTN *BufferSize, + VOID *Buffer); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_FILE_SET_INFO) ( + struct _ACPI_EFI_FILE_HANDLE *File, + ACPI_EFI_GUID *InformationType, + UINTN BufferSize, + VOID *Buffer); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_FILE_FLUSH) ( + struct _ACPI_EFI_FILE_HANDLE *File); + + +#define ACPI_EFI_FILE_HANDLE_REVISION 0x00010000 + +typedef struct _ACPI_EFI_FILE_HANDLE { + UINT64 Revision; + ACPI_EFI_FILE_OPEN Open; + ACPI_EFI_FILE_CLOSE Close; + ACPI_EFI_FILE_DELETE Delete; + ACPI_EFI_FILE_READ Read; + ACPI_EFI_FILE_WRITE Write; + ACPI_EFI_FILE_GET_POSITION GetPosition; + ACPI_EFI_FILE_SET_POSITION SetPosition; + ACPI_EFI_FILE_GET_INFO GetInfo; + ACPI_EFI_FILE_SET_INFO SetInfo; + ACPI_EFI_FILE_FLUSH Flush; +} ACPI_EFI_FILE_STRUCT, *ACPI_EFI_FILE_HANDLE; + + +/* + * Loaded image protocol + */ +#define ACPI_EFI_LOADED_IMAGE_PROTOCOL \ + { 0x5B1B31A1, 0x9562, 0x11d2, {0x8E, 0x3F, 0x00, 0xA0, 0xC9, 0x69, 0x72, 0x3B} } + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_IMAGE_ENTRY_POINT) ( + ACPI_EFI_HANDLE ImageHandle, + struct _ACPI_EFI_SYSTEM_TABLE *SystemTable); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_IMAGE_LOAD) ( + BOOLEAN BootPolicy, + ACPI_EFI_HANDLE ParentImageHandle, + ACPI_EFI_DEVICE_PATH *FilePath, + VOID *SourceBuffer, + UINTN SourceSize, + ACPI_EFI_HANDLE *ImageHandle); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_IMAGE_START) ( + ACPI_EFI_HANDLE ImageHandle, + UINTN *ExitDataSize, + CHAR16 **ExitData); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_EXIT) ( + ACPI_EFI_HANDLE ImageHandle, + ACPI_EFI_STATUS ExitStatus, + UINTN ExitDataSize, + CHAR16 *ExitData); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_IMAGE_UNLOAD) ( + ACPI_EFI_HANDLE ImageHandle); + + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_STALL) ( + UINTN Microseconds); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_SET_WATCHDOG_TIMER) ( + UINTN Timeout, + UINT64 WatchdogCode, + UINTN DataSize, + CHAR16 *WatchdogData); + + +#define EFI_IMAGE_INFORMATION_REVISION 0x1000 +typedef struct { + UINT32 Revision; + ACPI_EFI_HANDLE ParentHandle; + struct _ACPI_EFI_SYSTEM_TABLE *SystemTable; + ACPI_EFI_HANDLE DeviceHandle; + ACPI_EFI_DEVICE_PATH *FilePath; + VOID *Reserved; + UINT32 LoadOptionsSize; + VOID *LoadOptions; + VOID *ImageBase; + UINT64 ImageSize; + ACPI_EFI_MEMORY_TYPE ImageCodeType; + ACPI_EFI_MEMORY_TYPE ImageDataType; + ACPI_EFI_IMAGE_UNLOAD Unload; + +} ACPI_EFI_LOADED_IMAGE; + + +/* + * EFI Memory + */ +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_ALLOCATE_PAGES) ( + ACPI_EFI_ALLOCATE_TYPE Type, + ACPI_EFI_MEMORY_TYPE MemoryType, + UINTN NoPages, + ACPI_EFI_PHYSICAL_ADDRESS *Memory); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_FREE_PAGES) ( + ACPI_EFI_PHYSICAL_ADDRESS Memory, + UINTN NoPages); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_GET_MEMORY_MAP) ( + UINTN *MemoryMapSize, + ACPI_EFI_MEMORY_DESCRIPTOR *MemoryMap, + UINTN *MapKey, + UINTN *DescriptorSize, + UINT32 *DescriptorVersion); + +#define NextMemoryDescriptor(Ptr,Size) ((ACPI_EFI_MEMORY_DESCRIPTOR *) (((UINT8 *) Ptr) + Size)) + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_ALLOCATE_POOL) ( + ACPI_EFI_MEMORY_TYPE PoolType, + UINTN Size, + VOID **Buffer); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_FREE_POOL) ( + VOID *Buffer); + + +/* + * EFI Time + */ +typedef struct { + UINT32 Resolution; + UINT32 Accuracy; + BOOLEAN SetsToZero; +} ACPI_EFI_TIME_CAPABILITIES; + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_GET_TIME) ( + ACPI_EFI_TIME *Time, + ACPI_EFI_TIME_CAPABILITIES *Capabilities); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_SET_TIME) ( + ACPI_EFI_TIME *Time); + + +/* + * Protocol handler functions + */ +typedef enum { + ACPI_EFI_NATIVE_INTERFACE, + ACPI_EFI_PCODE_INTERFACE +} ACPI_EFI_INTERFACE_TYPE; + +typedef enum { + AcpiEfiAllHandles, + AcpiEfiByRegisterNotify, + AcpiEfiByProtocol +} ACPI_EFI_LOCATE_SEARCH_TYPE; + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_INSTALL_PROTOCOL_INTERFACE) ( + ACPI_EFI_HANDLE *Handle, + ACPI_EFI_GUID *Protocol, + ACPI_EFI_INTERFACE_TYPE InterfaceType, + VOID *Interface); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_REINSTALL_PROTOCOL_INTERFACE) ( + ACPI_EFI_HANDLE Handle, + ACPI_EFI_GUID *Protocol, + VOID *OldInterface, + VOID *NewInterface); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_UNINSTALL_PROTOCOL_INTERFACE) ( + ACPI_EFI_HANDLE Handle, + ACPI_EFI_GUID *Protocol, + VOID *Interface); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_HANDLE_PROTOCOL) ( + ACPI_EFI_HANDLE Handle, + ACPI_EFI_GUID *Protocol, + VOID **Interface); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_REGISTER_PROTOCOL_NOTIFY) ( + ACPI_EFI_GUID *Protocol, + ACPI_EFI_EVENT Event, + VOID **Registration); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_LOCATE_HANDLE) ( + ACPI_EFI_LOCATE_SEARCH_TYPE SearchType, + ACPI_EFI_GUID *Protocol, + VOID *SearchKey, + UINTN *BufferSize, + ACPI_EFI_HANDLE *Buffer); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_LOCATE_DEVICE_PATH) ( + ACPI_EFI_GUID *Protocol, + ACPI_EFI_DEVICE_PATH **DevicePath, + ACPI_EFI_HANDLE *Device); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_INSTALL_CONFIGURATION_TABLE) ( + ACPI_EFI_GUID *Guid, + VOID *Table); + +#define ACPI_EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL 0x00000001 +#define ACPI_EFI_OPEN_PROTOCOL_GET_PROTOCOL 0x00000002 +#define ACPI_EFI_OPEN_PROTOCOL_TEST_PROTOCOL 0x00000004 +#define ACPI_EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER 0x00000008 +#define ACPI_EFI_OPEN_PROTOCOL_BY_DRIVER 0x00000010 +#define ACPI_EFI_OPEN_PROTOCOL_EXCLUSIVE 0x00000020 + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_OPEN_PROTOCOL) ( + ACPI_EFI_HANDLE Handle, + ACPI_EFI_GUID *Protocol, + VOID **Interface, + ACPI_EFI_HANDLE AgentHandle, + ACPI_EFI_HANDLE ControllerHandle, + UINT32 Attributes); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_CLOSE_PROTOCOL) ( + ACPI_EFI_HANDLE Handle, + ACPI_EFI_GUID *Protocol, + ACPI_EFI_HANDLE AgentHandle, + ACPI_EFI_HANDLE ControllerHandle); + +typedef struct { + ACPI_EFI_HANDLE AgentHandle; + ACPI_EFI_HANDLE ControllerHandle; + UINT32 Attributes; + UINT32 OpenCount; +} ACPI_EFI_OPEN_PROTOCOL_INFORMATION_ENTRY; + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_OPEN_PROTOCOL_INFORMATION) ( + ACPI_EFI_HANDLE Handle, + ACPI_EFI_GUID *Protocol, + ACPI_EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer, + UINTN *EntryCount); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_PROTOCOLS_PER_HANDLE) ( + ACPI_EFI_HANDLE Handle, + ACPI_EFI_GUID ***ProtocolBuffer, + UINTN *ProtocolBufferCount); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_LOCATE_HANDLE_BUFFER) ( + ACPI_EFI_LOCATE_SEARCH_TYPE SearchType, + ACPI_EFI_GUID *Protocol, + VOID *SearchKey, + UINTN *NoHandles, + ACPI_EFI_HANDLE **Buffer); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_LOCATE_PROTOCOL) ( + ACPI_EFI_GUID *Protocol, + VOID *Registration, + VOID **Interface); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES) ( + ACPI_EFI_HANDLE *Handle, + ...); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES) ( + ACPI_EFI_HANDLE Handle, + ...); + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_CALCULATE_CRC32) ( + VOID *Data, + UINTN DataSize, + UINT32 *Crc32); + +typedef +VOID +(ACPI_EFI_API *ACPI_EFI_COPY_MEM) ( + VOID *Destination, + VOID *Source, + UINTN Length); + +typedef +VOID +(ACPI_EFI_API *ACPI_EFI_SET_MEM) ( + VOID *Buffer, + UINTN Size, + UINT8 Value); + +/* + * EFI Boot Services Table + */ +#define ACPI_EFI_BOOT_SERVICES_SIGNATURE 0x56524553544f4f42 +#define ACPI_EFI_BOOT_SERVICES_REVISION (ACPI_EFI_SPECIFICATION_MAJOR_REVISION<<16) | (ACPI_EFI_SPECIFICATION_MINOR_REVISION) + +typedef struct _ACPI_EFI_BOOT_SERVICES { + ACPI_EFI_TABLE_HEADER Hdr; + +#if 0 + ACPI_EFI_RAISE_TPL RaiseTPL; + ACPI_EFI_RESTORE_TPL RestoreTPL; +#else + ACPI_EFI_UNKNOWN_INTERFACE RaiseTPL; + ACPI_EFI_UNKNOWN_INTERFACE RestoreTPL; +#endif + + ACPI_EFI_ALLOCATE_PAGES AllocatePages; + ACPI_EFI_FREE_PAGES FreePages; + ACPI_EFI_GET_MEMORY_MAP GetMemoryMap; + ACPI_EFI_ALLOCATE_POOL AllocatePool; + ACPI_EFI_FREE_POOL FreePool; + +#if 0 + ACPI_EFI_CREATE_EVENT CreateEvent; + ACPI_EFI_SET_TIMER SetTimer; + ACPI_EFI_WAIT_FOR_EVENT WaitForEvent; + ACPI_EFI_SIGNAL_EVENT SignalEvent; + ACPI_EFI_CLOSE_EVENT CloseEvent; + ACPI_EFI_CHECK_EVENT CheckEvent; +#else + ACPI_EFI_UNKNOWN_INTERFACE CreateEvent; + ACPI_EFI_UNKNOWN_INTERFACE SetTimer; + ACPI_EFI_UNKNOWN_INTERFACE WaitForEvent; + ACPI_EFI_UNKNOWN_INTERFACE SignalEvent; + ACPI_EFI_UNKNOWN_INTERFACE CloseEvent; + ACPI_EFI_UNKNOWN_INTERFACE CheckEvent; +#endif + + ACPI_EFI_INSTALL_PROTOCOL_INTERFACE InstallProtocolInterface; + ACPI_EFI_REINSTALL_PROTOCOL_INTERFACE ReinstallProtocolInterface; + ACPI_EFI_UNINSTALL_PROTOCOL_INTERFACE UninstallProtocolInterface; + ACPI_EFI_HANDLE_PROTOCOL HandleProtocol; + ACPI_EFI_HANDLE_PROTOCOL PCHandleProtocol; + ACPI_EFI_REGISTER_PROTOCOL_NOTIFY RegisterProtocolNotify; + ACPI_EFI_LOCATE_HANDLE LocateHandle; + ACPI_EFI_LOCATE_DEVICE_PATH LocateDevicePath; + ACPI_EFI_INSTALL_CONFIGURATION_TABLE InstallConfigurationTable; + + ACPI_EFI_IMAGE_LOAD LoadImage; + ACPI_EFI_IMAGE_START StartImage; + ACPI_EFI_EXIT Exit; + ACPI_EFI_IMAGE_UNLOAD UnloadImage; + +#if 0 + ACPI_EFI_EXIT_BOOT_SERVICES ExitBootServices; + ACPI_EFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount; +#else + ACPI_EFI_UNKNOWN_INTERFACE ExitBootServices; + ACPI_EFI_UNKNOWN_INTERFACE GetNextMonotonicCount; +#endif + ACPI_EFI_STALL Stall; + ACPI_EFI_SET_WATCHDOG_TIMER SetWatchdogTimer; + +#if 0 + ACPI_EFI_CONNECT_CONTROLLER ConnectController; + ACPI_EFI_DISCONNECT_CONTROLLER DisconnectController; +#else + ACPI_EFI_UNKNOWN_INTERFACE ConnectController; + ACPI_EFI_UNKNOWN_INTERFACE DisconnectController; +#endif + + ACPI_EFI_OPEN_PROTOCOL OpenProtocol; + ACPI_EFI_CLOSE_PROTOCOL CloseProtocol; + ACPI_EFI_OPEN_PROTOCOL_INFORMATION OpenProtocolInformation; + ACPI_EFI_PROTOCOLS_PER_HANDLE ProtocolsPerHandle; + ACPI_EFI_LOCATE_HANDLE_BUFFER LocateHandleBuffer; + ACPI_EFI_LOCATE_PROTOCOL LocateProtocol; + ACPI_EFI_INSTALL_MULTIPLE_PROTOCOL_INTERFACES InstallMultipleProtocolInterfaces; + ACPI_EFI_UNINSTALL_MULTIPLE_PROTOCOL_INTERFACES UninstallMultipleProtocolInterfaces; + + ACPI_EFI_CALCULATE_CRC32 CalculateCrc32; + + ACPI_EFI_COPY_MEM CopyMem; + ACPI_EFI_SET_MEM SetMem; + +#if 0 + ACPI_EFI_CREATE_EVENT_EX CreateEventEx; +#else + ACPI_EFI_UNKNOWN_INTERFACE CreateEventEx; +#endif +} ACPI_EFI_BOOT_SERVICES; + + +/* + * EFI Runtime Services Table + */ +#define ACPI_EFI_RUNTIME_SERVICES_SIGNATURE 0x56524553544e5552 +#define ACPI_EFI_RUNTIME_SERVICES_REVISION (EFI_SPECIFICATION_MAJOR_REVISION<<16) | (EFI_SPECIFICATION_MINOR_REVISION) + +typedef struct _ACPI_EFI_RUNTIME_SERVICES { + ACPI_EFI_TABLE_HEADER Hdr; + + ACPI_EFI_GET_TIME GetTime; + ACPI_EFI_SET_TIME SetTime; +#if 0 + ACPI_EFI_GET_WAKEUP_TIME GetWakeupTime; + ACPI_EFI_SET_WAKEUP_TIME SetWakeupTime; +#else + ACPI_EFI_UNKNOWN_INTERFACE GetWakeupTime; + ACPI_EFI_UNKNOWN_INTERFACE SetWakeupTime; +#endif + +#if 0 + ACPI_EFI_SET_VIRTUAL_ADDRESS_MAP SetVirtualAddressMap; + ACPI_EFI_CONVERT_POINTER ConvertPointer; +#else + ACPI_EFI_UNKNOWN_INTERFACE SetVirtualAddressMap; + ACPI_EFI_UNKNOWN_INTERFACE ConvertPointer; +#endif + +#if 0 + ACPI_EFI_GET_VARIABLE GetVariable; + ACPI_EFI_GET_NEXT_VARIABLE_NAME GetNextVariableName; + ACPI_EFI_SET_VARIABLE SetVariable; +#else + ACPI_EFI_UNKNOWN_INTERFACE GetVariable; + ACPI_EFI_UNKNOWN_INTERFACE GetNextVariableName; + ACPI_EFI_UNKNOWN_INTERFACE SetVariable; +#endif + +#if 0 + ACPI_EFI_GET_NEXT_HIGH_MONO_COUNT GetNextHighMonotonicCount; + ACPI_EFI_RESET_SYSTEM ResetSystem; +#else + ACPI_EFI_UNKNOWN_INTERFACE GetNextHighMonotonicCount; + ACPI_EFI_UNKNOWN_INTERFACE ResetSystem; +#endif + +} ACPI_EFI_RUNTIME_SERVICES; + + +/* + * EFI System Table + */ + +/* + * EFI Configuration Table and GUID definitions + */ +#define ACPI_TABLE_GUID \ + { 0xeb9d2d30, 0x2d88, 0x11d3, {0x9a, 0x16, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d} } +#define ACPI_20_TABLE_GUID \ + { 0x8868e871, 0xe4f1, 0x11d3, {0xbc, 0x22, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81} } + +typedef struct _ACPI_EFI_CONFIGURATION_TABLE { + ACPI_EFI_GUID VendorGuid; + VOID *VendorTable; +} ACPI_EFI_CONFIGURATION_TABLE; + + +#define ACPI_EFI_SYSTEM_TABLE_SIGNATURE 0x5453595320494249 +#define ACPI_EFI_SYSTEM_TABLE_REVISION (ACPI_EFI_SPECIFICATION_MAJOR_REVISION<<16) | (ACPI_EFI_SPECIFICATION_MINOR_REVISION) + +typedef struct _ACPI_EFI_SYSTEM_TABLE { + ACPI_EFI_TABLE_HEADER Hdr; + + CHAR16 *FirmwareVendor; + UINT32 FirmwareRevision; + + ACPI_EFI_HANDLE ConsoleInHandle; + ACPI_SIMPLE_INPUT_INTERFACE *ConIn; + + ACPI_EFI_HANDLE ConsoleOutHandle; + ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE *ConOut; + + ACPI_EFI_HANDLE StandardErrorHandle; + ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE *StdErr; + + ACPI_EFI_RUNTIME_SERVICES *RuntimeServices; + ACPI_EFI_BOOT_SERVICES *BootServices; + + UINTN NumberOfTableEntries; + ACPI_EFI_CONFIGURATION_TABLE *ConfigurationTable; + +} ACPI_EFI_SYSTEM_TABLE; + + +/* + * EFI PCI I/O Protocol + */ +#define ACPI_EFI_PCI_IO_PROTOCOL \ + { 0x4cf5b200, 0x68b8, 0x4ca5, {0x9e, 0xec, 0xb2, 0x3e, 0x3f, 0x50, 0x2, 0x9a} } + +typedef enum { + AcpiEfiPciIoWidthUint8 = 0, + AcpiEfiPciIoWidthUint16, + AcpiEfiPciIoWidthUint32, + AcpiEfiPciIoWidthUint64, + AcpiEfiPciIoWidthFifoUint8, + AcpiEfiPciIoWidthFifoUint16, + AcpiEfiPciIoWidthFifoUint32, + AcpiEfiPciIoWidthFifoUint64, + AcpiEfiPciIoWidthFillUint8, + AcpiEfiPciIoWidthFillUint16, + AcpiEfiPciIoWidthFillUint32, + AcpiEfiPciIoWidthFillUint64, + AcpiEfiPciIoWidthMaximum +} ACPI_EFI_PCI_IO_PROTOCOL_WIDTH; + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_PCI_IO_PROTOCOL_CONFIG)( + struct _ACPI_EFI_PCI_IO *This, + ACPI_EFI_PCI_IO_PROTOCOL_WIDTH Width, + UINT32 Offset, + UINTN Count, + VOID *Buffer); + +typedef struct { + ACPI_EFI_PCI_IO_PROTOCOL_CONFIG Read; + ACPI_EFI_PCI_IO_PROTOCOL_CONFIG Write; +} ACPI_EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS; + +typedef +ACPI_EFI_STATUS +(ACPI_EFI_API *ACPI_EFI_PCI_IO_PROTOCOL_GET_LOCATION)( + struct _ACPI_EFI_PCI_IO *This, + UINTN *SegmentNumber, + UINTN *BusNumber, + UINTN *DeviceNumber, + UINTN *FunctionNumber); + +typedef struct _ACPI_EFI_PCI_IO { + ACPI_EFI_UNKNOWN_INTERFACE PollMem; + ACPI_EFI_UNKNOWN_INTERFACE PollIo; + ACPI_EFI_UNKNOWN_INTERFACE Mem; + ACPI_EFI_UNKNOWN_INTERFACE Io; + ACPI_EFI_PCI_IO_PROTOCOL_CONFIG_ACCESS Pci; + ACPI_EFI_UNKNOWN_INTERFACE CopyMem; + ACPI_EFI_UNKNOWN_INTERFACE Map; + ACPI_EFI_UNKNOWN_INTERFACE Unmap; + ACPI_EFI_UNKNOWN_INTERFACE AllocateBuffer; + ACPI_EFI_UNKNOWN_INTERFACE FreeBuffer; + ACPI_EFI_UNKNOWN_INTERFACE Flush; + ACPI_EFI_PCI_IO_PROTOCOL_GET_LOCATION GetLocation; + ACPI_EFI_UNKNOWN_INTERFACE Attributes; + ACPI_EFI_UNKNOWN_INTERFACE GetBarAttributes; + ACPI_EFI_UNKNOWN_INTERFACE SetBarAttributes; + UINT64 RomSize; + VOID *RomImage; +} ACPI_EFI_PCI_IO; + +/* FILE abstraction */ + +union acpi_efi_file { + struct _ACPI_EFI_FILE_HANDLE File; + struct _ACPI_SIMPLE_TEXT_OUTPUT_INTERFACE ConOut; + struct _ACPI_SIMPLE_INPUT_INTERFACE ConIn; +}; + + +/* EFI definitions */ + +#if defined(_GNU_EFI) || defined(_EDK2_EFI) + +/* + * This is needed to hide platform specific code from ACPICA + */ +UINT64 ACPI_EFI_API +DivU64x32 ( + UINT64 Dividend, + UINTN Divisor, + UINTN *Remainder); + +UINT64 ACPI_EFI_API +MultU64x32 ( + UINT64 Multiplicand, + UINTN Multiplier); + +UINT64 ACPI_EFI_API +LShiftU64 ( + UINT64 Operand, + UINTN Count); + +UINT64 ACPI_EFI_API +RShiftU64 ( + UINT64 Operand, + UINTN Count); + +/* + * EFI specific prototypes + */ +ACPI_EFI_STATUS +efi_main ( + ACPI_EFI_HANDLE Image, + ACPI_EFI_SYSTEM_TABLE *SystemTab); + +int +acpi_main ( + int argc, + char *argv[]); + +#endif + +extern ACPI_EFI_GUID AcpiGbl_LoadedImageProtocol; +extern ACPI_EFI_GUID AcpiGbl_TextInProtocol; +extern ACPI_EFI_GUID AcpiGbl_TextOutProtocol; +extern ACPI_EFI_GUID AcpiGbl_FileSystemProtocol; +extern ACPI_EFI_GUID AcpiGbl_GenericFileInfo; + +#endif /* __ACEFIEX_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/acenv.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acenv.h new file mode 100644 index 0000000..da405a9 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acenv.h @@ -0,0 +1,390 @@ +/****************************************************************************** + * + * Name: acenv.h - Host and compiler configuration + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#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 + * + *****************************************************************************/ + +/* Common application configuration. All single threaded except for AcpiExec. */ + +#if (defined ACPI_ASL_COMPILER) || \ + (defined ACPI_BIN_APP) || \ + (defined ACPI_DUMP_APP) || \ + (defined ACPI_HELP_APP) || \ + (defined ACPI_NAMES_APP) || \ + (defined ACPI_SRC_APP) || \ + (defined ACPI_XTRACT_APP) || \ + (defined ACPI_EXAMPLE_APP) || \ + (defined ACPI_EFI_HELLO) +#define ACPI_APPLICATION +#define ACPI_SINGLE_THREADED +#define USE_NATIVE_ALLOCATE_ZEROED +#endif + +/* iASL configuration */ + +#ifdef ACPI_ASL_COMPILER +#define ACPI_DEBUG_OUTPUT +#define ACPI_CONSTANT_EVAL_ONLY +#define ACPI_LARGE_NAMESPACE_NODE +#define ACPI_DATA_TABLE_DISASSEMBLY +#define ACPI_32BIT_PHYSICAL_ADDRESS +#define ACPI_DISASSEMBLER 1 +#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 + +/* AcpiHelp configuration. Error messages disabled. */ + +#ifdef ACPI_HELP_APP +#define ACPI_NO_ERROR_MESSAGES +#endif + +/* AcpiNames configuration. Debug output enabled. */ + +#ifdef ACPI_NAMES_APP +#define ACPI_DEBUG_OUTPUT +#endif + +/* AcpiExec/AcpiNames/Example configuration. Native RSDP used. */ + +#if (defined ACPI_EXEC_APP) || \ + (defined ACPI_EXAMPLE_APP) || \ + (defined ACPI_NAMES_APP) +#define ACPI_USE_NATIVE_RSDP_POINTER +#endif + +/* AcpiDump configuration. Native mapping used if provided by the host */ + +#ifdef ACPI_DUMP_APP +#define ACPI_USE_NATIVE_MEMORY_MAPPING +#endif + +/* AcpiNames/Example configuration. Hardware disabled */ + +#if (defined ACPI_EXAMPLE_APP) || \ + (defined ACPI_NAMES_APP) +#define ACPI_REDUCED_HARDWARE 1 +#endif + +/* Linkable ACPICA library. Two versions, one with full debug. */ + +#ifdef ACPI_LIBRARY +#define ACPI_USE_LOCAL_CACHE +#define ACPI_DEBUGGER 1 +#define ACPI_DISASSEMBLER 1 + +#ifdef _DEBUG +#define ACPI_DEBUG_OUTPUT +#endif +#endif + +/* Common for all ACPICA applications */ + +#ifdef ACPI_APPLICATION +#define ACPI_USE_LOCAL_CACHE +#endif + +/* Common debug/disassembler support */ + +#ifdef ACPI_FULL_DEBUG +#define ACPI_DEBUG_OUTPUT +#define ACPI_DEBUGGER 1 +#define ACPI_DISASSEMBLER 1 +#endif + +/* + * acpisrc CR\LF support + * Unix file line endings do not include the carriage return. + * If the acpisrc utility is being built using a microsoft compiler, it means + * that it will be running on a windows machine which means that the output is + * expected to have CR/LF newlines. If the acpisrc utility is built with + * anything else, it will likely run on a system with LF newlines. This flag + * tells the acpisrc utility that newlines will be in the LF format. + */ +#if defined(ACPI_SRC_APP) && !defined(_MSC_VER) +#define ACPI_SRC_OS_LF_ONLY 1 +#else +#define ACPI_SRC_OS_LF_ONLY 0 +#endif + +/*! [Begin] no source code translation */ + +/****************************************************************************** + * + * Host configuration files. The compiler configuration files are included + * first. + * + *****************************************************************************/ + +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) +#include "acgcc.h" + +#elif defined(_MSC_VER) +#include "acmsvc.h" + +#elif defined(__INTEL_COMPILER) +#include "acintel.h" + +#endif + +#if defined(ACPI_NTLITE) +#include "acntlite.h" + +#elif defined(_LINUX) || defined(__linux__) +#include "aclinux.h" + +#elif defined(_APPLE) || defined(__APPLE__) +#include "acmacosx.h" + +#elif defined(__DragonFly__) +#include "acdragonfly.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(__HAIKU__) +#include "achaiku.h" + +#elif defined(__QNX__) +#include "acqnx.h" + +/* + * EFI applications can be built with -nostdlib, in this case, it must be + * included after including all other host environmental definitions, in + * order to override the definitions. + */ +#elif defined(_AED_EFI) || defined(_GNU_EFI) || defined(_EDK2_EFI) +#include "acefi.h" + +#elif defined(__ZEPHYR__) +#include "aczephyr.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 + +/* NULL/invalid value to use for destroyed or not-yet-created semaphores. */ + +#ifndef ACPI_SEMAPHORE_NULL +#define ACPI_SEMAPHORE_NULL NULL +#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 + +/* Use ordered initialization if compiler doesn't support designated. */ +#ifndef ACPI_STRUCT_INIT +#define ACPI_STRUCT_INIT(field, value) value +#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 +#if !defined (ACPI_APPLICATION) || defined (ACPI_EXEC_APP) +#define DEBUGGER_THREADING DEBUGGER_MULTI_THREADED + +#else +#define DEBUGGER_THREADING DEBUGGER_SINGLE_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. Defining this implies that + * ACPI_USE_SYSTEM_CLIBRARY has been defined. + * + * 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. + */ + +/* 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 +#if defined (ACPI_APPLICATION) || defined(ACPI_LIBRARY) +#include +#include +#include +#include +#include +#endif + +#endif /* ACPI_USE_STANDARD_HEADERS */ + +#ifdef ACPI_APPLICATION +#define ACPI_FILE FILE * +#define ACPI_FILE_OUT stdout +#define ACPI_FILE_ERR stderr +#else +#define ACPI_FILE void * +#define ACPI_FILE_OUT NULL +#define ACPI_FILE_ERR NULL +#endif /* ACPI_APPLICATION */ + +#ifndef ACPI_INIT_FUNCTION +#define ACPI_INIT_FUNCTION +#endif + +#endif /* __ACENV_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/acenvex.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acenvex.h new file mode 100644 index 0000000..bf22950 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acenvex.h @@ -0,0 +1,52 @@ +/****************************************************************************** + * + * Name: acenvex.h - Extra host and compiler configuration + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACENVEX_H__ +#define __ACENVEX_H__ + +/*! [Begin] no source code translation */ + +/****************************************************************************** + * + * Extra host configuration files. All ACPICA headers are included before + * including these files. + * + *****************************************************************************/ + +#if defined(_LINUX) || defined(__linux__) +#include "aclinuxex.h" + +#elif defined(__DragonFly__) +#include "acdragonflyex.h" + +/* + * EFI applications can be built with -nostdlib, in this case, it must be + * included after including all other host environmental definitions, in + * order to override the definitions. + */ +#elif defined(_AED_EFI) || defined(_GNU_EFI) || defined(_EDK2_EFI) +#include "acefiex.h" + +#endif + +#if defined(__GNUC__) && !defined(__INTEL_COMPILER) +#include "acgccex.h" + +#elif defined(_MSC_VER) +#include "acmsvcex.h" + +#endif + +/*! [End] no source code translation !*/ + +#endif /* __ACENVEX_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/acfreebsd.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acfreebsd.h new file mode 100644 index 0000000..58b19c5 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acfreebsd.h @@ -0,0 +1,91 @@ +/****************************************************************************** + * + * Name: acfreebsd.h - OS specific defines, etc. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACFREEBSD_H__ +#define __ACFREEBSD_H__ + + +#include + +#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 + +#define ACPI_UINTPTR_T uintptr_t + +#define ACPI_TO_INTEGER(p) ((uintptr_t)(p)) +#define ACPI_OFFSET(d, f) __offsetof(d, f) + +#define ACPI_USE_DO_WHILE_0 +#define ACPI_USE_LOCAL_CACHE +#define ACPI_USE_NATIVE_DIVIDE +#define ACPI_USE_NATIVE_MATH64 +#define ACPI_USE_SYSTEM_CLIBRARY + +#ifdef _KERNEL + +#include +#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 */ + +#ifdef INVARIANTS +#define ACPI_MUTEX_DEBUG +#endif + +#else /* _KERNEL */ + +#if __STDC_HOSTED__ +#include +#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/code/drivers/platform/acpi/third_party/acpica/include/platform/acgcc.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acgcc.h new file mode 100644 index 0000000..bd10760 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acgcc.h @@ -0,0 +1,97 @@ +/****************************************************************************** + * + * Name: acgcc.h - GCC specific defines, etc. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACGCC_H__ +#define __ACGCC_H__ + +/* + * Use compiler specific is a good practice for even when + * -nostdinc is specified (i.e., ACPI_USE_STANDARD_HEADERS undefined. + */ +#ifndef va_arg +#ifdef ACPI_USE_BUILTIN_STDARG +typedef __builtin_va_list va_list; +#define va_start(v, l) __builtin_va_start(v, l) +#define va_end(v) __builtin_va_end(v) +#define va_arg(v, l) __builtin_va_arg(v, l) +#define va_copy(d, s) __builtin_va_copy(d, s) +#else +#include +#endif +#endif + +#define ACPI_INLINE __inline__ + +/* Function name is used for debug output. Non-ANSI, compiler-dependent */ + +#define ACPI_GET_FUNCTION_NAME __func__ + +/* + * 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 tell the compiler warning in a per-variable manner that a variable + * is unused. + */ +#define ACPI_UNUSED_VAR __attribute__ ((unused)) + +/* GCC supports __VA_ARGS__ in macros */ + +#define COMPILER_VA_MACRO 1 + +/* GCC supports native multiply/shift on 32-bit platforms */ + +#define ACPI_USE_NATIVE_MATH64 + +/* GCC did not support __has_attribute until 5.1. */ + +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif + +/* + * Explicitly mark intentional explicit fallthrough to silence + * -Wimplicit-fallthrough in GCC 7.1+. + */ + +#if __has_attribute(__fallthrough__) +#define ACPI_FALLTHROUGH __attribute__((__fallthrough__)) +#endif + +/* + * Flexible array members are not allowed to be part of a union under + * C99, but this is not for any technical reason. Work around the + * limitation. + */ +#ifndef __cplusplus +#define ACPI_FLEX_ARRAY(TYPE, NAME) \ + struct { \ + struct { } __Empty_ ## NAME; \ + TYPE NAME[]; \ + } +#endif + +/* + * Explicitly mark strings that lack a terminating NUL character so + * that ACPICA can be built with -Wunterminated-string-initialization. + */ +#if __has_attribute(__nonstring__) +#define ACPI_NONSTRING __attribute__((__nonstring__)) +#endif + +#endif /* __ACGCC_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/acgccex.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acgccex.h new file mode 100644 index 0000000..dde4c1a --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acgccex.h @@ -0,0 +1,28 @@ +/****************************************************************************** + * + * Name: acgccex.h - Extra GCC specific defines, etc. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACGCCEX_H__ +#define __ACGCCEX_H__ + +/* + * Some versions of gcc implement strchr() with a buggy macro. So, + * undef it here. Prevents error messages of this form (usually from the + * file getopt.c): + * + * error: logical '&&' with non-zero constant will always evaluate as true + */ +#ifdef strchr +#undef strchr +#endif + +#endif /* __ACGCCEX_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/achaiku.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/achaiku.h new file mode 100644 index 0000000..9541a3d --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/achaiku.h @@ -0,0 +1,81 @@ +/****************************************************************************** + * + * Name: achaiku.h - OS specific defines, etc. for Haiku (www.haiku-os.org) + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACHAIKU_H__ +#define __ACHAIKU_H__ + +#define ACPI_USE_STANDARD_HEADERS +#define ACPI_USE_SYSTEM_CLIBRARY + +#include + +struct mutex; + + +/* Host-dependent types and defines for user- and kernel-space ACPICA */ + +#define ACPI_MUTEX_TYPE ACPI_OSL_MUTEX +#define ACPI_MUTEX struct mutex * + +#define ACPI_USE_NATIVE_DIVIDE +#define ACPI_USE_NATIVE_MATH64 + +/* #define ACPI_THREAD_ID thread_id */ + +#define ACPI_SEMAPHORE sem_id +#define ACPI_SPINLOCK spinlock * +#define ACPI_CPU_FLAGS cpu_status + +#define COMPILER_DEPENDENT_INT64 int64 +#define COMPILER_DEPENDENT_UINT64 uint64 + + +#ifdef B_HAIKU_64_BIT +#define ACPI_MACHINE_WIDTH 64 +#else +#define ACPI_MACHINE_WIDTH 32 +#endif + + +#ifdef _KERNEL_MODE +/* Host-dependent types and defines for in-kernel ACPICA */ + +/* ACPICA cache implementation is adequate. */ +#define ACPI_USE_LOCAL_CACHE + +/* On other platform the default definition (do nothing) is fine. */ +#if defined(__i386__) || defined(__x86_64__) +#define ACPI_FLUSH_CPU_CACHE() __asm __volatile("wbinvd"); +#endif + +/* Based on FreeBSD's due to lack of documentation */ +extern int AcpiOsAcquireGlobalLock(volatile uint32_t *lock); +extern int AcpiOsReleaseGlobalLock(volatile uint32_t *lock); + +#define ACPI_ACQUIRE_GLOBAL_LOCK(GLptr, Acq) do { \ + (Acq) = AcpiOsAcquireGlobalLock(&((GLptr)->GlobalLock)); \ +} while (0) + +#define ACPI_RELEASE_GLOBAL_LOCK(GLptr, Acq) do { \ + (Acq) = AcpiOsReleaseGlobalLock(&((GLptr)->GlobalLock)); \ +} while (0) + +#define ACPI_SEMAPHORE_NULL -1 + +#else /* _KERNEL_MODE */ +/* Host-dependent types and defines for user-space ACPICA */ + +#error "We only support kernel mode ACPI atm." + +#endif /* _KERNEL_MODE */ +#endif /* __ACHAIKU_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/acintel.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acintel.h new file mode 100644 index 0000000..8cb853a --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acintel.h @@ -0,0 +1,60 @@ +/****************************************************************************** + * + * Name: acintel.h - VC specific defines, etc. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACINTEL_H__ +#define __ACINTEL_H__ + +/* + * Use compiler specific is a good practice for even when + * -nostdinc is specified (i.e., ACPI_USE_STANDARD_HEADERS undefined. + */ +#ifndef va_arg +#include +#endif + +/* 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/code/drivers/platform/acpi/third_party/acpica/include/platform/aclinux.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/aclinux.h new file mode 100644 index 0000000..b506f85 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/aclinux.h @@ -0,0 +1,218 @@ +/****************************************************************************** + * + * Name: aclinux.h - OS specific defines, etc. for Linux + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACLINUX_H__ +#define __ACLINUX_H__ + +#ifdef __KERNEL__ + +/* ACPICA external files should not include ACPICA headers directly. */ + +#if !defined(BUILDING_ACPICA) && !defined(_LINUX_ACPI_H) +#error "Please don't include directly, include instead." +#endif + +#endif + +/* Common (in-kernel/user-space) ACPICA configuration */ + +#define ACPI_USE_SYSTEM_CLIBRARY +#define ACPI_USE_DO_WHILE_0 +#define ACPI_IGNORE_PACKAGE_RESOLUTION_ERRORS + + +#ifdef __KERNEL__ + +#define ACPI_USE_SYSTEM_INTTYPES +#define ACPI_USE_GPE_POLLING + +/* Kernel specific ACPICA configuration */ + +#ifdef CONFIG_ACPI_REDUCED_HARDWARE_ONLY +#define ACPI_REDUCED_HARDWARE 1 +#endif + +#ifdef CONFIG_ACPI_DEBUGGER +#define ACPI_DEBUGGER +#endif + +#ifdef CONFIG_ACPI_DEBUG +#define ACPI_MUTEX_DEBUG +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef EXPORT_ACPI_INTERFACES +#include +#endif +#ifdef CONFIG_ACPI +#include +#endif + +#define ACPI_INIT_FUNCTION __init + +/* Use a specific bugging default separate from ACPICA */ + +#undef ACPI_DEBUG_DEFAULT +#define ACPI_DEBUG_DEFAULT (ACPI_LV_INFO | ACPI_LV_REPAIR) + +#ifndef CONFIG_ACPI + +/* External globals for __KERNEL__, stubs is needed */ + +#define ACPI_GLOBAL(t,a) +#define ACPI_INIT_GLOBAL(t,a,b) + +/* Generating stubs for configurable ACPICA macros */ + +#define ACPI_NO_MEM_ALLOCATIONS + +/* Generating stubs for configurable ACPICA functions */ + +#define ACPI_NO_ERROR_MESSAGES +#undef ACPI_DEBUG_OUTPUT + +/* External interface for __KERNEL__, stub is needed */ + +#define ACPI_EXTERNAL_RETURN_STATUS(Prototype) \ + static ACPI_INLINE Prototype {return(AE_NOT_CONFIGURED);} +#define ACPI_EXTERNAL_RETURN_OK(Prototype) \ + static ACPI_INLINE Prototype {return(AE_OK);} +#define ACPI_EXTERNAL_RETURN_VOID(Prototype) \ + static ACPI_INLINE Prototype {return;} +#define ACPI_EXTERNAL_RETURN_UINT32(Prototype) \ + static ACPI_INLINE Prototype {return(0);} +#define ACPI_EXTERNAL_RETURN_PTR(Prototype) \ + static ACPI_INLINE Prototype {return(NULL);} + +#endif /* CONFIG_ACPI */ + +/* Host-dependent types and defines for in-kernel ACPICA */ + +#define ACPI_MACHINE_WIDTH BITS_PER_LONG +#define ACPI_USE_NATIVE_MATH64 +#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 + +#define ACPI_UINTPTR_T uintptr_t + +#define ACPI_TO_INTEGER(p) ((uintptr_t)(p)) +#define ACPI_OFFSET(d, f) offsetof(d, f) + +/* Use native linux version of AcpiOsAllocateZeroed */ + +#define USE_NATIVE_ALLOCATE_ZEROED + +/* + * Overrides for in-kernel ACPICA + */ +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsInitialize +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsTerminate +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsAllocate +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsAllocateZeroed +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsFree +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsAcquireObject +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsGetThreadId +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsCreateLock + +/* + * OSL interfaces used by debugger/disassembler + */ +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsReadable +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsWritable +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsInitializeDebugger +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsTerminateDebugger + +/* + * OSL interfaces used by utilities + */ +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsRedirectOutput +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsGetTableByName +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsGetTableByIndex +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsGetTableByAddress +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsOpenDirectory +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsGetNextFilename +#define ACPI_USE_ALTERNATE_PROTOTYPE_AcpiOsCloseDirectory + +#define ACPI_MSG_ERROR KERN_ERR "ACPI Error: " +#define ACPI_MSG_EXCEPTION KERN_ERR "ACPI Exception: " +#define ACPI_MSG_WARNING KERN_WARNING "ACPI Warning: " +#define ACPI_MSG_INFO KERN_INFO "ACPI: " + +#define ACPI_MSG_BIOS_ERROR KERN_ERR "ACPI BIOS Error (bug): " +#define ACPI_MSG_BIOS_WARNING KERN_WARNING "ACPI BIOS Warning (bug): " +#define ACPI_MSG_DEBUG KERN_DEBUG + +/* + * Linux wants to use designated initializers for function pointer structs. + */ +#define ACPI_STRUCT_INIT(field, value) .field = value + +#else /* !__KERNEL__ */ + +#define ACPI_USE_STANDARD_HEADERS + +#ifdef ACPI_USE_STANDARD_HEADERS +#include +#include +#include + +#define ACPI_OFFSET(d, f) offsetof(d, f) +#endif + +/* Define/disable kernel-specific declarators */ + +#ifndef __init +#define __init +#endif +#ifndef __iomem +#define __iomem +#endif + +/* Host-dependent types and defines for user-space ACPICA */ + +#define ACPI_FLUSH_CPU_CACHE() +#define ACPI_CAST_PTHREAD_T(Pthread) ((ACPI_THREAD_ID) (Pthread)) + +#if defined(__ia64__) || (defined(__x86_64__) && !defined(__ILP32__)) ||\ + defined(__aarch64__) || defined(__PPC64__) ||\ + defined(__s390x__) || defined(__loongarch__) ||\ + (defined(__riscv) && (defined(__LP64__) || defined(_LP64))) +#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 +#define ACPI_USE_NATIVE_MATH64 +#endif + +#ifndef __cdecl +#define __cdecl +#endif + +#endif /* __KERNEL__ */ + +#endif /* __ACLINUX_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/aclinuxex.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/aclinuxex.h new file mode 100644 index 0000000..f1d10ee --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/aclinuxex.h @@ -0,0 +1,138 @@ +/****************************************************************************** + * + * Name: aclinuxex.h - Extra OS specific defines, etc. for Linux + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACLINUXEX_H__ +#define __ACLINUXEX_H__ + +#ifdef __KERNEL__ + +#ifndef ACPI_USE_NATIVE_DIVIDE + +#ifndef ACPI_DIV_64_BY_32 +#define ACPI_DIV_64_BY_32(n_hi, n_lo, d32, q32, r32) \ + do { \ + UINT64 (__n) = ((UINT64) n_hi) << 32 | (n_lo); \ + (r32) = do_div ((__n), (d32)); \ + (q32) = (UINT32) (__n); \ + } while (0) +#endif + +#ifndef ACPI_SHIFT_RIGHT_64 +#define ACPI_SHIFT_RIGHT_64(n_hi, n_lo) \ + do { \ + (n_lo) >>= 1; \ + (n_lo) |= (((n_hi) & 1) << 31); \ + (n_hi) >>= 1; \ + } while (0) +#endif + +#endif + +/* + * Overrides for in-kernel ACPICA + */ +ACPI_STATUS ACPI_INIT_FUNCTION AcpiOsInitialize ( + void); + +ACPI_STATUS AcpiOsTerminate ( + void); + +/* + * 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. + */ +static inline void * +AcpiOsAllocate ( + ACPI_SIZE Size) +{ + return kmalloc (Size, irqs_disabled () ? GFP_ATOMIC : GFP_KERNEL); +} + +static inline void * +AcpiOsAllocateZeroed ( + ACPI_SIZE Size) +{ + return kzalloc (Size, irqs_disabled () ? GFP_ATOMIC : GFP_KERNEL); +} + +static inline void +AcpiOsFree ( + void *Memory) +{ + kfree (Memory); +} + +static inline void * +AcpiOsAcquireObject ( + ACPI_CACHE_T *Cache) +{ + return kmem_cache_zalloc (Cache, + irqs_disabled () ? GFP_ATOMIC : GFP_KERNEL); +} + +static inline ACPI_THREAD_ID +AcpiOsGetThreadId ( + void) +{ + return (ACPI_THREAD_ID) (unsigned long) current; +} + +/* + * When lockdep is enabled, the spin_lock_init() macro stringifies it's + * argument and uses that as a name for the lock in debugging. + * By executing spin_lock_init() in a macro the key changes from "lock" for + * all locks to the name of the argument of acpi_os_create_lock(), which + * prevents lockdep from reporting false positives for ACPICA locks. + */ +#define AcpiOsCreateLock(__Handle) \ + ({ \ + spinlock_t *Lock = ACPI_ALLOCATE(sizeof(*Lock)); \ + if (Lock) { \ + *(__Handle) = Lock; \ + spin_lock_init(*(__Handle)); \ + } \ + Lock ? AE_OK : AE_NO_MEMORY; \ + }) + +static inline BOOLEAN +AcpiOsReadable ( + void *Pointer, + ACPI_SIZE Length) +{ + return TRUE; +} + +static inline ACPI_STATUS +AcpiOsInitializeDebugger ( + void) +{ + return AE_OK; +} + +static inline void +AcpiOsTerminateDebugger ( + void) +{ + return; +} + + +/* + * OSL interfaces added by Linux + */ + +#endif /* __KERNEL__ */ + +#endif /* __ACLINUXEX_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/acmacosx.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acmacosx.h new file mode 100644 index 0000000..fe0a603 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acmacosx.h @@ -0,0 +1,27 @@ +/****************************************************************************** + * + * Name: acmacosx.h - OS specific defines, etc. for Mac OS X + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACMACOSX_H__ +#define __ACMACOSX_H__ + +#include "aclinux.h" + +#ifdef __APPLE__ +#define ACPI_USE_ALTERNATE_TIMEOUT +#endif /* __APPLE__ */ + +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wformat-nonliteral" +#endif + +#endif /* __ACMACOSX_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/acmsvc.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acmsvc.h new file mode 100644 index 0000000..d5e5bed --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acmsvc.h @@ -0,0 +1,204 @@ +/****************************************************************************** + * + * Name: acmsvc.h - VC specific defines, etc. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACMSVC_H__ +#define __ACMSVC_H__ + +/* Note: do not include any C library headers here */ + +/* + * Note: MSVC project files should define ACPI_DEBUGGER and ACPI_DISASSEMBLER + * as appropriate to enable editor functions like "Find all references". + * The editor isn't smart enough to dig through the include files to find + * out if these are actually defined. + */ + +/* 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 + + +/* Do not maintain the architecture specific stuffs for the EFI ports */ + +#if defined(__i386__) && !defined(_GNU_EFI) && !defined(_EDK2_EFI) +/* + * Math helper functions + */ +#ifndef ACPI_DIV_64_BY_32 +#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 \ +} +#endif + +#ifndef ACPI_MUL_64_BY_32 +#define ACPI_MUL_64_BY_32(n_hi, n_lo, m32, p32, c32) \ +{ \ + __asm mov edx, n_hi \ + __asm mov eax, n_lo \ + __asm mul m32 \ + __asm mov p32, eax \ + __asm mov c32, edx \ +} +#endif + +#ifndef ACPI_SHIFT_LEFT_64_BY_32 +#define ACPI_SHIFT_LEFT_64_BY_32(n_hi, n_lo, s32) \ +{ \ + __asm mov edx, n_hi \ + __asm mov eax, n_lo \ + __asm mov ecx, s32 \ + __asm and ecx, 31 \ + __asm shld edx, eax, cl \ + __asm shl eax, cl \ + __asm mov n_hi, edx \ + __asm mov n_lo, eax \ +} +#endif + +#ifndef ACPI_SHIFT_RIGHT_64_BY_32 +#define ACPI_SHIFT_RIGHT_64_BY_32(n_hi, n_lo, s32) \ +{ \ + __asm mov edx, n_hi \ + __asm mov eax, n_lo \ + __asm mov ecx, s32 \ + __asm and ecx, 31 \ + __asm shrd eax, edx, cl \ + __asm shr edx, cl \ + __asm mov n_hi, edx \ + __asm mov n_lo, eax \ +} +#endif + +#ifndef ACPI_SHIFT_RIGHT_64 +#define ACPI_SHIFT_RIGHT_64(n_hi, n_lo) \ +{ \ + __asm shr n_hi, 1 \ + __asm rcr n_lo, 1 \ +} +#endif +#endif + +/* warn C4001: use of slash-slash comments */ +/* NOTE: MSVC 2015 headers use these extensively */ +#pragma warning(disable:4001) + +/* 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) + +/* warn C4131: uses old-style declarator (iASL compiler only) */ +#pragma warning(disable:4459) + +/* warn c4200: allow flexible arrays (of zero length) */ +#pragma warning(disable:4200) + +#if _MSC_VER > 1200 /* Versions above VC++ 6 */ +#pragma warning( disable : 4295 ) /* needed for acpredef.h array */ +#endif + +/* + * MSVC 2015+ + */ + + /* warn C4459: xxxx (identifier) hides global declaration */ +#pragma warning(disable:4459) + + +/* Debug support. */ + +#ifdef _DEBUG + +/* + * Debugging memory corruption issues with windows: + * Add #include to accommon.h if necessary. + * Add _ASSERTE(_CrtCheckMemory()); where needed to test memory integrity. + * This can quickly localize the memory corruption. + */ +#define ACPI_DEBUG_INITIALIZE() \ + _CrtSetDbgFlag (\ + _CRTDBG_CHECK_ALWAYS_DF | \ + _CRTDBG_ALLOC_MEM_DF | \ + _CRTDBG_DELAY_FREE_MEM_DF | \ + _CRTDBG_LEAK_CHECK_DF | \ + _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG)); + +#if 0 +/* + * _CrtSetBreakAlloc can be used to set a breakpoint at a particular + * memory leak, add to the macro above. + */ +Detected memory leaks! +Dumping objects -> +..\..\source\os_specific\service_layers\oswinxf.c(701) : {937} normal block at 0x002E9190, 40 bytes long. + Data: < > 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + +_CrtSetBreakAlloc (937); +#endif + +#endif + +#if _MSC_VER > 1200 /* Versions above VC++ 6 */ +#define COMPILER_VA_MACRO 1 +#else +#endif + +/* Begin standard headers */ + +/* + * warn C4001: nonstandard extension 'single line comment' was used + * + * We need to enable this for ACPICA internal files, but disable it for + * buggy MS runtime headers. + */ +#pragma warning(push) +#pragma warning(disable:4001) + +#endif /* __ACMSVC_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/acmsvcex.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acmsvcex.h new file mode 100644 index 0000000..c810262 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acmsvcex.h @@ -0,0 +1,67 @@ +/****************************************************************************** + * + * Name: acmsvcex.h - Extra VC specific defines, etc. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACMSVCEX_H__ +#define __ACMSVCEX_H__ + +/* va_arg implementation can be compiler specific */ + +#ifdef ACPI_USE_STANDARD_HEADERS + +#include + +#endif /* ACPI_USE_STANDARD_HEADERS */ + +/* Debug support. */ + +#ifdef _DEBUG +#define _CRTDBG_MAP_ALLOC /* Enables specific file/lineno for leaks */ +#include +#endif + +/* End standard headers */ + +#pragma warning(pop) + +#ifndef ACPI_USE_SYSTEM_CLIBRARY + +/****************************************************************************** + * + * Not using native C library, use local implementations + * + *****************************************************************************/ + +#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) (ap = (va_list) NULL) +#define va_start(ap, A) (void) ((ap) = (((char *) &(A)) + (_Bnd (A,_AUPBND)))) + +#endif /* va_arg */ + +#endif /* !ACPI_USE_SYSTEM_CLIBRARY */ + +#endif /* __ACMSVCEX_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/acnetbsd.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acnetbsd.h new file mode 100644 index 0000000..c30584b --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acnetbsd.h @@ -0,0 +1,83 @@ +/****************************************************************************** + * + * Name: acnetbsd.h - OS specific defines, etc. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACNETBSD_H__ +#define __ACNETBSD_H__ + +#define ACPI_UINTPTR_T uintptr_t +#define ACPI_USE_LOCAL_CACHE +#define ACPI_CAST_PTHREAD_T(x) ((ACPI_THREAD_ID) ACPI_TO_INTEGER (x)) + +#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 + +#if defined(_KERNEL) || defined(_STANDALONE) +#ifdef _KERNEL_OPT +#include "opt_acpi.h" /* collect build-time options here */ +#endif /* _KERNEL_OPT */ + +#include +#include +#include +#include + +#define asm __asm + +#define ACPI_USE_NATIVE_DIVIDE +#define ACPI_USE_NATIVE_MATH64 + +#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 */ + +#else /* defined(_KERNEL) || defined(_STANDALONE) */ + +#include +#include + +/* Not building kernel code, so use libc */ +#define ACPI_USE_STANDARD_HEADERS + +#define __cli() +#define __sti() +#define __cdecl + +#endif /* defined(_KERNEL) || defined(_STANDALONE) */ + +/* Always use NetBSD code over our local versions */ +#define ACPI_USE_SYSTEM_CLIBRARY +#define ACPI_USE_NATIVE_DIVIDE +#define ACPI_USE_NATIVE_MATH64 + +#endif /* __ACNETBSD_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/acntlite.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acntlite.h new file mode 100644 index 0000000..90bd5cc --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acntlite.h @@ -0,0 +1,7 @@ +// ACPICA platform configuration for the nt-lite freestanding kernel. +#ifndef ACNTLITE_H +#define ACNTLITE_H +#define ACPI_MACHINE_WIDTH 64 +#define ACPI_USE_LOCAL_CACHE +#define ACPI_USE_NATIVE_DIVIDE +#endif diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/acos2.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acos2.h new file mode 100644 index 0000000..a1eee92 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acos2.h @@ -0,0 +1,68 @@ +/****************************************************************************** + * + * Name: acos2.h - OS/2 specific defines, etc. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACOS2_H__ +#define __ACOS2_H__ + +#define ACPI_USE_STANDARD_HEADERS +#define ACPI_USE_SYSTEM_CLIBRARY + +#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_USE_NATIVE_MATH64 + +#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 + +#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/code/drivers/platform/acpi/third_party/acpica/include/platform/acqnx.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acqnx.h new file mode 100644 index 0000000..92c0599 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acqnx.h @@ -0,0 +1,41 @@ +/****************************************************************************** + * + * Name: acqnx.h - OS specific defines, etc. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACQNX_H__ +#define __ACQNX_H__ + +#define ACPI_USE_STANDARD_HEADERS +#define ACPI_USE_SYSTEM_CLIBRARY + +#define ACPI_UINTPTR_T uintptr_t +#define ACPI_USE_LOCAL_CACHE +#define ACPI_CAST_PTHREAD_T(x) ((ACPI_THREAD_ID) ACPI_TO_INTEGER (x)) + +/* At present time (QNX 6.6) all supported architectures are 32 bits. */ +#define ACPI_MACHINE_WIDTH 32 + +#define COMPILER_DEPENDENT_INT64 int64_t +#define COMPILER_DEPENDENT_UINT64 uint64_t + +#include +#include +#include + +#define __cli() InterruptDisable(); +#define __sti() InterruptEnable(); +#define __cdecl + +#define ACPI_USE_NATIVE_DIVIDE +#define ACPI_USE_NATIVE_MATH64 + +#endif /* __ACQNX_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/acwin.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acwin.h new file mode 100644 index 0000000..a7ecad7 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acwin.h @@ -0,0 +1,174 @@ +/****************************************************************************** + * + * Name: acwin.h - OS specific defines, etc. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACWIN_H__ +#define __ACWIN_H__ + +#include + +#define ACPI_USE_STANDARD_HEADERS +#define ACPI_USE_SYSTEM_CLIBRARY + + /* Note: do not include any C library headers here */ + + /* + * Note: MSVC project files should define ACPI_DEBUGGER and ACPI_DISASSEMBLER + * as appropriate to enable editor functions like "Find all references". + * The editor isn't smart enough to dig through the include files to find + * out if these are actually defined. + */ + + /* 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 + + /* Disable these warnings under Windows and MSVC since C4201: nameless + * structs/unions are needed as ACPI event-handling under Linux/GCC breaks + * with named and nested structs/unions while C4068: unknown pragma + * complains of GCC pragmas in use to disable dangling ptr warnings + */ + +#pragma warning( disable: 4201) +#pragma warning( disable: 4068) +#pragma warning( disable: 4214) +#pragma warning( push) + +#define ACPI_MACHINE_WIDTH 32 +#define ACPI_USE_NATIVE_DIVIDE +#define ACPI_USE_NATIVE_MATH64 + +#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 + +/* + * 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 fileno _fileno +#define isatty _isatty + +#if _MSC_VER <= 1200 /* Versions below VC++ 6 */ +#define vsnprintf _vsnprintf +#endif +#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 +#if _MSC_VER < 1900 +#define snprintf _snprintf +#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/code/drivers/platform/acpi/third_party/acpica/include/platform/acwin64.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/acwin64.h new file mode 100644 index 0000000..95957ba --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/acwin64.h @@ -0,0 +1,96 @@ +/****************************************************************************** + * + * Name: acwin64.h - OS specific defines, etc. + * + *****************************************************************************/ + +/****************************************************************************** + * + * Copyright (c) 1999 - 2026, Intel Corp. + * SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0-only + * + *****************************************************************************/ + +#ifndef __ACWIN64_H__ +#define __ACWIN64_H__ + +#define ACPI_USE_STANDARD_HEADERS +#define ACPI_USE_SYSTEM_CLIBRARY + + /* Note: do not include any C library headers here */ + + /* + * Note: MSVC project files should define ACPI_DEBUGGER and ACPI_DISASSEMBLER + * as appropriate to enable editor functions like "Find all references". + * The editor isn't smart enough to dig through the include files to find + * out if these are actually defined. + */ + + /* 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 ACPI_MACHINE_WIDTH 64 + +/* + * 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 snprintf _snprintf +#if _MSC_VER <= 1200 /* Versions below VC++ 6 */ +#define vsnprintf _vsnprintf +#endif +#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 + +/* + * 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 + +/*! [End] no source code translation !*/ + +#endif /* __ACWIN_H__ */ diff --git a/code/drivers/platform/acpi/third_party/acpica/include/platform/aczephyr.h b/code/drivers/platform/acpi/third_party/acpica/include/platform/aczephyr.h new file mode 100644 index 0000000..84f9b88 --- /dev/null +++ b/code/drivers/platform/acpi/third_party/acpica/include/platform/aczephyr.h @@ -0,0 +1,199 @@ +/****************************************************************************** + * + * Module Name: aczephyr.h - OS specific defines, etc. + * + *****************************************************************************/ + +/****************************************************************************** + * + * 1. Copyright Notice + * + * Some or all of this work - Copyright (c) 1999 - 2026, Intel Corp. + * All rights reserved. + * + * 2. License + * + * 2.1. This is your license from Intel Corp. under its intellectual property + * rights. You may have additional license terms from the party that provided + * you this software, covering your right to use that party's intellectual + * property rights. + * + * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a + * copy of the source code appearing in this file ("Covered Code") an + * irrevocable, perpetual, worldwide license under Intel's copyrights in the + * base code distributed originally by Intel ("Original Intel Code") to copy, + * make derivatives, distribute, use and display any portion of the Covered + * Code in any form, with the right to sublicense such rights; and + * + * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent + * license (with the right to sublicense), under only those claims of Intel + * patents that are infringed by the Original Intel Code, to make, use, sell, + * offer to sell, and import the Covered Code and derivative works thereof + * solely to the minimum extent necessary to exercise the above copyright + * license, and in no event shall the patent license extend to any additions + * to or modifications of the Original Intel Code. No other license or right + * is granted directly or by implication, estoppel or otherwise; + * + * The above copyright and patent license is granted only if the following + * conditions are met: + * + * 3. Conditions + * + * 3.1. Redistribution of Source with Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification with rights to further distribute source must include + * the above Copyright Notice, the above License, this list of Conditions, + * and the following Disclaimer and Export Compliance provision. In addition, + * Licensee must cause all Covered Code to which Licensee contributes to + * contain a file documenting the changes Licensee made to create that Covered + * Code and the date of any change. Licensee must include in that file the + * documentation of any changes made by any predecessor Licensee. Licensee + * must include a prominent statement that the modification is derived, + * directly or indirectly, from Original Intel Code. + * + * 3.2. Redistribution of Source with no Rights to Further Distribute Source. + * Redistribution of source code of any substantial portion of the Covered + * Code or modification without rights to further distribute source must + * include the following Disclaimer and Export Compliance provision in the + * documentation and/or other materials provided with distribution. In + * addition, Licensee may not authorize further sublicense of source of any + * portion of the Covered Code, and must include terms to the effect that the + * license from Licensee to its licensee is limited to the intellectual + * property embodied in the software Licensee provides to its licensee, and + * not to intellectual property embodied in modifications its licensee may + * make. + * + * 3.3. Redistribution of Executable. Redistribution in executable form of any + * substantial portion of the Covered Code or modification must reproduce the + * above Copyright Notice, and the following Disclaimer and Export Compliance + * provision in the documentation and/or other materials provided with the + * distribution. + * + * 3.4. Intel retains all right, title, and interest in and to the Original + * Intel Code. + * + * 3.5. Neither the name Intel nor any other trademark owned or controlled by + * Intel shall be used in advertising or otherwise to promote the sale, use or + * other dealings in products derived from or relating to the Covered Code + * without prior written authorization from Intel. + * + * 4. Disclaimer and Export Compliance + * + * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED + * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE + * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, + * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY + * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY + * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A + * PARTICULAR PURPOSE. + * + * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES + * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR + * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, + * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY + * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL + * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS + * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY + * LIMITED REMEDY. + * + * 4.3. Licensee shall not export, either directly or indirectly, any of this + * software or system incorporating such software without first obtaining any + * required license or other approval from the U. S. Department of Commerce or + * any other agency or department of the United States Government. In the + * event Licensee exports any such software from the United States or + * re-exports any such software from a foreign destination, Licensee shall + * ensure that the distribution and export/re-export of the software is in + * compliance with all laws, regulations, orders, or other restrictions of the + * U.S. Export Administration Regulations. Licensee agrees that neither it nor + * any of its subsidiaries will export/re-export any technical data, process, + * software, or service, directly or indirectly, to any country for which the + * United States government or any agency thereof requires an export license, + * other governmental approval, or letter of assurance, without first obtaining + * such license, approval or letter. + * + ***************************************************************************** + * + * Alternatively, you may choose to be licensed under the terms of the + * following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions, and the following disclaimer, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * substantially similar to the "NO WARRANTY" disclaimer below + * ("Disclaimer") and any redistribution must be conditioned upon + * including a substantially similar Disclaimer requirement for further + * binary redistribution. + * 3. Neither the names of the above-listed copyright holders nor the names + * of any contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Alternatively, you may choose to be licensed under the terms of the + * GNU General Public License ("GPL") version 2 as published by the Free + * Software Foundation. + * + *****************************************************************************/ + +#ifndef __ACZEPHYR_H__ +#define __ACZEPHYR_H__ + +#if defined(__x86_64__) +#define ACPI_MACHINE_WIDTH 64 +#else +#define ACPI_32BIT_PHYSICAL_ADDRESS +#define ACPI_MACHINE_WIDTH 32 +#define ACPI_USE_NATIVE_DIVIDE +#define ACPI_USE_NATIVE_MATH64 +#endif + +#define COMPILER_DEPENDENT_INT64 long long +#define COMPILER_DEPENDENT_UINT64 unsigned long long + +#define ACPI_NO_ERROR_MESSAGES +#undef ACPI_DEBUG_OUTPUT +#define ACPI_USE_SYSTEM_CLIBRARY +#undef ACPI_DBG_TRACK_ALLOCATIONS +#define ACPI_SINGLE_THREADED +#define ACPI_USE_NATIVE_RSDP_POINTER + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/****************************************************************************** + * + * FUNCTION: AcpiEnableDbgPrint + * + * PARAMETERS: Enable, - Enable/Disable debug print + * + * RETURN: None + * + * DESCRIPTION: Enable/disable debug print + * + *****************************************************************************/ + +void AcpiEnableDbgPrint ( + bool Enable); +#endif diff --git a/code/drivers/platform/dirs b/code/drivers/platform/dirs new file mode 100644 index 0000000..6b639a0 --- /dev/null +++ b/code/drivers/platform/dirs @@ -0,0 +1 @@ +DIRS=acpi diff --git a/code/drivers/storage/ahci/ahci.c b/code/drivers/storage/ahci/ahci.c index 0c9a920..e6c76a1 100644 --- a/code/drivers/storage/ahci/ahci.c +++ b/code/drivers/storage/ahci/ahci.c @@ -5,8 +5,6 @@ DRIVER_OBJECT g_driver; -static AHCI_CONTROLLER* g_controllers[MAX_AHCI_CONTROLLERS]; -static int g_controllerCount; static uint8_t g_nextDiskIndex; #define AHCI_COMMAND_TIMEOUT_MS 10000ull @@ -26,7 +24,6 @@ static const IO_DRIVER_ID_TABLE g_ahciIdTable = { // Helpers. static KSTATUS AhciStartController(AHCI_CONTROLLER* ctl); -static void AhciUnregisterController(AHCI_CONTROLLER* ctl); // Accessors for port structure memory at known CPU and device-address offsets. static inline HBA_CMD_HEADER* cmd_list(AHCI_DRIVE* drv) { @@ -255,42 +252,40 @@ static void AhciCompletionDpc(KDPC* dpc, void* context, // Walks all registered drives, checks if their port raised an interrupt, // captures IS, clears it, and queues the per-drive completion DPC. -static void AhciIsr(void) { - for (int c = 0; c < g_controllerCount; c++) { - AHCI_CONTROLLER* ctl = g_controllers[c]; - if (!ctl || !ctl->hba || ctl->removed) - continue; +static void AhciIsr(void* context) { + AHCI_CONTROLLER* ctl = (AHCI_CONTROLLER*)context; + if (!ctl || !ctl->hba || ctl->removed) return; + // GHC.IS tells us which ports are pending for this HBA. + uint32_t pending = ctl->hba->is; + if (!pending) + return; - // GHC.IS tells us which ports are pending for this HBA. - uint32_t pending = ctl->hba->is; - if (!pending) - continue; + for (uint32_t i = 0; i < ctl->driveCount; i++) { + AHCI_DRIVE* drv = &ctl->drives[i]; + uint32_t portBit = (1u << drv->portNo); + if (!(pending & portBit)) continue; - for (uint32_t i = 0; i < ctl->driveCount; i++) { - AHCI_DRIVE* drv = &ctl->drives[i]; - uint32_t portBit = (1u << drv->portNo); - if (!(pending & portBit)) continue; + // Capture and clear port IS before queueing the bottom half. The + // waiter reads lastIs to check for errors without racing the next + // command. OR in case hardware reports multiple causes before the + // DPC releases the worker. + uint32_t portIs = drv->port->is; + drv->port->is = portIs; // W1C - write back to clear + drv->lastIs |= portIs; - // Capture and clear port IS before queueing the bottom half. The - // waiter reads lastIs to check for errors without racing the next - // command. OR in case hardware reports multiple causes before the - // DPC releases the worker. - uint32_t portIs = drv->port->is; - drv->port->is = portIs; // W1C - write back to clear - drv->lastIs |= portIs; + // Clear the HBA-level bit. + ctl->hba->is = portBit; - // Clear the HBA-level bit. - ctl->hba->is = portBit; - - // DMA Setup, PIO Setup, and other progress interrupts are not - // command completion. Only wake the worker for D2H completion or - // an error that terminates the command. - if (portIs & AHCI_PORT_TERMINAL_MASK) - KeInsertQueueDpc(&drv->completionDpc, (void*)0, (void*)0); - } + // DMA Setup, PIO Setup, and other progress interrupts are not + // command completion. Only wake the worker for D2H completion or + // an error that terminates the command. + if (portIs & AHCI_PORT_TERMINAL_MASK) + KeInsertQueueDpc(&drv->completionDpc, (void*)0, (void*)0); } + } + // Issue a command - interrupt-driven (runtime path). // Caller has already built slot 0 via build_rw_cmd / port_identify. // Blocks the current thread until the ISR signals completionEvent. @@ -700,7 +695,8 @@ static KSTATUS AhciDispatchControllerPnp(DEVICE_OBJECT* device, IRP* irp) { AhciReleaseDriveDma(drv); } } - AhciUnregisterController(ctl); + if (ctl->InterruptRequest.Interrupt) + PciDisconnectInterrupts(ctl->pdo, &ctl->InterruptRequest, 1u); IoDmaPutAdapter(ctl->dmaAdapter); ctl->dmaAdapter = (IO_DMA_ADAPTER*)0; IoDetachDevice(device); @@ -818,33 +814,6 @@ static void AhciWorker(uintptr_t arg) { // Runtime commands are non-NCQ DMA commands. DHRS is their completion signal; // setup/progress FIS interrupts must not wake the serialized command waiter. -// Registers controller. -static KSTATUS AhciRegisterController(AHCI_CONTROLLER* ctl) { - if (!ctl) return NTLSTATUS_INVALID_PARAMETER; - for (int i = 0; i < g_controllerCount; i++) { - if (g_controllers[i] == ctl) - return NTLSTATUS_SUCCESS; - } - if (g_controllerCount >= MAX_AHCI_CONTROLLERS) - return NTLSTATUS_NO_MEMORY; - g_controllers[g_controllerCount++] = ctl; - return NTLSTATUS_SUCCESS; -} - -// Removes a controller from the interrupt registry. -static void AhciUnregisterController(AHCI_CONTROLLER* ctl) { - if (!ctl) - return; - for (int i = 0; i < g_controllerCount; i++) { - if (g_controllers[i] != ctl) - continue; - g_controllerCount--; - g_controllers[i] = g_controllers[g_controllerCount]; - g_controllers[g_controllerCount] = (AHCI_CONTROLLER*)0; - return; - } -} - // Starts controller. static KSTATUS AhciStartController(AHCI_CONTROLLER* ctl) { if (!ctl || ctl->magic != AHCI_CONTROLLER_MAGIC || !ctl->pdo || !ctl->fdo) @@ -866,25 +835,12 @@ static KSTATUS AhciStartController(AHCI_CONTROLLER* ctl) { ctl->pciInfo.VendorId, ctl->pciInfo.DeviceId); - ctl->irq = 0xFFu; ctl->usingMsi = false; ctl->pollingMode = false; - - st = PciEnableMsiAuto(ctl->pdo, &ctl->irq); - if (KSUCCESS(st)) { - ctl->usingMsi = true; - DbgPrint("AHCI: using MSI IRQ slot %u\n", (unsigned)ctl->irq); - } else { - KSTATUS intxStatus = PciGetInterrupt(ctl->pdo, &ctl->irq); - if (KSUCCESS(intxStatus) && ctl->irq != 0xFFu) { - DbgPrint("AHCI: using legacy INTx IRQ %u\n", (unsigned)ctl->irq); - } else { - ctl->irq = 0xFFu; - ctl->pollingMode = true; - DbgPrint("AHCI: no MSI/INTx interrupt available; using polled command completion (msi=0x%x intx=0x%x)\n", - st, intxStatus); - } - } + ctl->InterruptRequest.Routine = AhciIsr; + ctl->InterruptRequest.Context = ctl; + ctl->InterruptRequest.Affinity = 0; + ctl->InterruptRequest.Interrupt = (KE_INTERRUPT*)0; st = PciGetBar(ctl->pdo, AHCI_PCI_BAR_ABAR, &ctl->abar); if (!KSUCCESS(st)) { @@ -907,10 +863,7 @@ static KSTATUS AhciStartController(AHCI_CONTROLLER* ctl) { } uint32_t enableFlags = PCI_ENABLE_MEMORY | PCI_ENABLE_BUSMASTER; - if (ctl->usingMsi || ctl->pollingMode) - enableFlags |= PCI_DISABLE_INTX; - else - enableFlags |= PCI_ENABLE_INTX; + enableFlags |= PCI_DISABLE_INTX; st = PciEnableDevice(ctl->pdo, enableFlags); if (!KSUCCESS(st)) { @@ -946,19 +899,14 @@ static KSTATUS AhciStartController(AHCI_CONTROLLER* ctl) { return st; } - st = AhciRegisterController(ctl); - if (!KSUCCESS(st)) { - DbgPrint("AHCI: controller registry full (0x%x)\n", st); - IoDmaPutAdapter(ctl->dmaAdapter); - ctl->dmaAdapter = (IO_DMA_ADAPTER*)0; - return st; - } - // IoRegisterDiskDevice publishes arrival synchronously, and partition/filesystem // consumers may issue reads from that callback. Install the controller ISR before // any disk is published so an interrupt-driven drive can complete those reads. - if (!ctl->pollingMode) - KeIrqRegister(ctl->irq, AhciIsr); + st = PciConnectInterrupts(ctl->pdo, &ctl->InterruptRequest, 1u, &ctl->usingMsi); + if (!KSUCCESS(st)) { + ctl->pollingMode = true; + DbgPrint("AHCI: polling fallback status=0x%x\n", st); + } uint32_t pi = ctl->hba->pi; for (uint32_t portno = 0; portno < 32 && ctl->driveCount < MAX_AHCI_DRIVES; portno++) { @@ -1119,8 +1067,11 @@ static KSTATUS AhciStartController(AHCI_CONTROLLER* ctl) { ctl->pciInfo.Address.Function); if (!ctl->pollingMode) { - DbgPrint("AHCI: ISR registered on IRQ %u (%s); controller drives=%u\n", - (unsigned)ctl->irq, ctl->usingMsi ? "MSI" : "INTx", (unsigned)ctl->driveCount); + KE_INTERRUPT_INFO info; + if (KSUCCESS(KeInterruptQuery(ctl->InterruptRequest.Interrupt, &info))) + DbgPrint("AHCI: ISR cpu=%u vector=0x%02x mode=%s drives=%u\n", + info.CpuIndex, info.Vector, ctl->usingMsi ? "MSI/MSI-X" : "INTx", + (unsigned)ctl->driveCount); } else { DbgPrint("AHCI: controller started in polling mode; controller drives=%u\n", (unsigned)ctl->driveCount); @@ -1131,7 +1082,6 @@ static KSTATUS AhciStartController(AHCI_CONTROLLER* ctl) { return NTLSTATUS_SUCCESS; } -// Implements the add Device operation. static KSTATUS AhciAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return NTLSTATUS_INVALID_PARAMETER; @@ -1146,7 +1096,7 @@ static KSTATUS AhciAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDevic ctl->magic = AHCI_CONTROLLER_MAGIC; ctl->fdo = fdo; ctl->pdo = physicalDeviceObject; - ctl->irq = 0xFF; + ctl->pciInfo.InterruptLine = 0xFF; (void)IoSetDeviceName(fdo, SYS_SV_LITERAL("ahci-controller")); ctl->lowerDevice = IoAttachDeviceToDeviceStack(fdo, physicalDeviceObject); @@ -1164,7 +1114,6 @@ static KSTATUS DriverInitialize(NTL_MODULE* module) { DbgPrint("AHCI: driver loading...\n"); - g_controllerCount = 0; g_nextDiskIndex = 0; memset(&g_driver, 0, sizeof(g_driver)); diff --git a/code/drivers/storage/ahci/ahci.h b/code/drivers/storage/ahci/ahci.h index 08613c3..463d30b 100644 --- a/code/drivers/storage/ahci/ahci.h +++ b/code/drivers/storage/ahci/ahci.h @@ -373,7 +373,7 @@ struct AHCI_CONTROLLER { PCI_BAR abar; HBA_MEM* hba; uint64_t abarLength; - uint8_t irq; + PCI_INTERRUPT_REQUEST InterruptRequest; bool usingMsi; bool pollingMode; diff --git a/code/drivers/storage/ahci/ahci_port.c b/code/drivers/storage/ahci/ahci_port.c index b912bcf..704d573 100644 --- a/code/drivers/storage/ahci/ahci_port.c +++ b/code/drivers/storage/ahci/ahci_port.c @@ -2,7 +2,6 @@ #include "ahci.h" -// Implements the ahci map mmio operation. KSTATUS ahci_map_mmio(uint64_t physBase, uint64_t length) { if (length == 0) length = AHCI_MMIO_PAGES * 4096ull; @@ -25,7 +24,6 @@ KSTATUS ahci_map_mmio(uint64_t physBase, uint64_t length) { return NTLSTATUS_SUCCESS; } -// Implements the port stop operation. void port_stop(HBA_PORT* port) { // Clear ST (bit 0). port->cmd &= ~PORT_CMD_ST; @@ -41,7 +39,6 @@ void port_stop(HBA_PORT* port) { } } -// Implements the port start operation. void port_start(HBA_PORT* port) { // Wait until CR is clear before setting ST. for (int i = 0; i < POLL_TIMEOUT; i++) { @@ -51,7 +48,6 @@ void port_start(HBA_PORT* port) { port->cmd |= PORT_CMD_ST; } -// Implements the hba reset operation. KSTATUS hba_reset(HBA_MEM* hba) { // BIOS/OS handoff (spec §10.6.3). if (hba->cap2 & CAP2_BOH) { @@ -85,25 +81,21 @@ KSTATUS hba_reset(HBA_MEM* hba) { return NTLSTATUS_SUCCESS; } -// Implements the port link up operation. bool port_link_up(HBA_PORT* port) { uint32_t det = port->ssts & 0x0F; uint32_t ipm = (port->ssts >> 8) & 0x0F; return (det == PORT_DET_PRESENT && ipm == PORT_IPM_ACTIVE); } -// Implements the port is sata disk operation. bool port_is_sata_disk(HBA_PORT* port) { return port->sig == SATA_SIG_ATA; } -// Implements the ahci delay ms operation. void ahci_delay_ms(uint32_t ms) { for (uint32_t i = 0; i < ms * 1000; i++) __outbyte(0x80, 0); } -// Implements the port comreset operation. KSTATUS port_comreset(AHCI_DRIVE* drv) { HBA_PORT* port = drv->port; diff --git a/code/drivers/storage/ahci/makefile b/code/drivers/storage/ahci/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/drivers/storage/ahci/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/drivers/storage/ahci/sources b/code/drivers/storage/ahci/sources new file mode 100644 index 0000000..95ccd4e --- /dev/null +++ b/code/drivers/storage/ahci/sources @@ -0,0 +1,7 @@ +TARGETNAME=ahci +TARGETPATH=obj +TARGETTYPE=DRIVER +FLAVOR=DRIVER +TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\pci.lib" +EXTRA_LFLAGS=/NOENTRY +SOURCES=@/code/drivers/storage/ahci/ahci.c @/code/drivers/storage/ahci/ahci_port.c diff --git a/code/drivers/storage/ata/ata.c b/code/drivers/storage/ata/ata.c index ce52b6c..ccf368b 100644 --- a/code/drivers/storage/ata/ata.c +++ b/code/drivers/storage/ata/ata.c @@ -16,37 +16,30 @@ static const IO_DRIVER_ID_TABLE gAtaIdTable = { sizeof(gAtaIds) / sizeof(gAtaIds[0]), }; -// Implements the in8 operation. static uint8_t AtaIn8(ATA_CHANNEL* ch, uint8_t reg) { return __inbyte((unsigned short)(ch->CommandBase + reg)); } -// Implements the in16 operation. static uint16_t AtaIn16(ATA_CHANNEL* ch, uint8_t reg) { return __inword((unsigned short)(ch->CommandBase + reg)); } -// Implements the out8 operation. static void AtaOut8(ATA_CHANNEL* ch, uint8_t reg, uint8_t value) { __outbyte((unsigned short)(ch->CommandBase + reg), value); } -// Implements the out16 operation. static void AtaOut16(ATA_CHANNEL* ch, uint8_t reg, uint16_t value) { __outword((unsigned short)(ch->CommandBase + reg), value); } -// Implements the alt Status operation. static uint8_t AtaAltStatus(ATA_CHANNEL* ch) { return __inbyte((unsigned short)(ch->ControlBase + ATA_REG_ALT_STATUS)); } -// Implements the device Control operation. static void AtaDeviceControl(ATA_CHANNEL* ch, uint8_t value) { __outbyte((unsigned short)(ch->ControlBase + ATA_REG_DEVICE_CONTROL), value); } -// Implements the delay400ns operation. static void AtaDelay400ns(ATA_CHANNEL* ch) { (void)AtaAltStatus(ch); (void)AtaAltStatus(ch); @@ -142,7 +135,6 @@ static KSTATUS AtaResetChannel(ATA_CHANNEL* ch) { return status; } -// Implements the select Drive operation. static void AtaSelectDrive(ATA_DEVICE* dev) { ATA_CHANNEL* ch = dev->Channel; AtaOut8(ch, ATA_REG_DRIVE_HEAD, (uint8_t)(0xA0u | (dev->Drive ? 0x10u : 0u))); @@ -241,7 +233,6 @@ static KSTATUS AtaIdentify(ATA_DEVICE* dev) { return dev->SectorCount ? NTLSTATUS_SUCCESS : NTLSTATUS_NOT_FOUND; } -// Implements the program Lba operation. static KSTATUS AtaProgramLba(ATA_DEVICE* dev, uint64_t lba, uint16_t count, bool write) { ATA_CHANNEL* ch = dev->Channel; @@ -407,7 +398,6 @@ static KSTATUS AtaGetIrpReadWrite(IRP* irp, bool* outWrite, uint64_t* outLba, return NTLSTATUS_SUCCESS; } -// Implements the worker operation. static void AtaWorker(uintptr_t arg) { ATA_DEVICE* dev = (ATA_DEVICE*)arg; if (!dev) @@ -572,7 +562,6 @@ static uint8_t AtaFindFreeDiskIndex(void) { return 0xFFu; } -// Implements the bar Io Base operation. static uint16_t AtaBarIoBase(ATA_CONTROLLER* ctl, uint8_t barIndex, uint16_t fallback) { PCI_BAR bar; KSTATUS st = PciGetBar(ctl->Pdo, barIndex, &bar); @@ -709,7 +698,6 @@ static KSTATUS AtaProbeDrive(ATA_CONTROLLER* ctl, ATA_CHANNEL* ch, uint8_t drive return NTLSTATUS_SUCCESS; } -// Registers controller. static KSTATUS AtaRegisterController(ATA_CONTROLLER* ctl) { if (!ctl) return NTLSTATUS_INVALID_PARAMETER; for (uint32_t i = 0; i < gAtaControllerCount; i++) { @@ -895,7 +883,6 @@ KSTATUS AtaDispatchPnp(DEVICE_OBJECT* device, IRP* irp) { return NTLSTATUS_INVALID_PARAMETER; } -// Implements the add Device operation. KSTATUS AtaAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* physicalDeviceObject) { if (!driver || !physicalDeviceObject || physicalDeviceObject->Type != DeviceObjectPhysical) return NTLSTATUS_INVALID_PARAMETER; diff --git a/code/drivers/storage/ata/makefile b/code/drivers/storage/ata/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/drivers/storage/ata/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/drivers/storage/ata/sources b/code/drivers/storage/ata/sources new file mode 100644 index 0000000..ad8b6b0 --- /dev/null +++ b/code/drivers/storage/ata/sources @@ -0,0 +1,7 @@ +TARGETNAME=ata +TARGETPATH=obj +TARGETTYPE=DRIVER +FLAVOR=DRIVER +TARGETLIBS="$(BASEDIR)\bin\kernel.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\pci.lib" +EXTRA_LFLAGS=/NOENTRY +SOURCES=@/code/drivers/storage/ata/ata.c diff --git a/code/drivers/storage/dirs b/code/drivers/storage/dirs new file mode 100644 index 0000000..23e5739 --- /dev/null +++ b/code/drivers/storage/dirs @@ -0,0 +1 @@ +DIRS=ahci ata diff --git a/code/kernel/core/makefile b/code/kernel/core/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/kernel/core/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/kernel/core/sources b/code/kernel/core/sources new file mode 100644 index 0000000..cc73812 --- /dev/null +++ b/code/kernel/core/sources @@ -0,0 +1,21 @@ +TARGETNAME=kernel +TARGETPATH=obj +TARGETTYPE=PROGRAM +IMAGE_KIND=KERNEL +FLAVOR=KERNEL +EXTRA_CFLAGS=/DNTL_KERNEL_BUILD /DKE_DISPLAY_BUILD +TARGETLIBS="$(BASEDIR)\bin\hal.lib" "$(BASEDIR)\bin\printf.lib" "$(BASEDIR)\bin\libc.lib" +EXTRA_LFLAGS=/ENTRY:KernelMain /MAP:"$(BASEDIR)\bin\kernel.map" /FIXED /DYNAMICBASE:NO /HIGHENTROPYVA:NO /RELEASE /BASE:0xFFFF800000000000 +INCLUDES=$(BASEDIR)\code\kernel\include +SOURCES=@/code/kernel/dm_config.c @/code/kernel/driver_module.c @/code/kernel/io_async.c @/code/kernel/io_ddk.c @/code/kernel/io_device.c @/code/kernel/io_dma.c \ + @/code/kernel/io_file.c @/code/kernel/io_partition.c @/code/kernel/io_pipe.c @/code/kernel/io_pnp.c @/code/kernel/io_volume.c @/code/kernel/ke_apc.c \ + @/code/kernel/ke_audio.c @/code/kernel/ke_boot_config.c @/code/kernel/ke_cpu.c @/code/kernel/ke_debug.c @/code/kernel/ke_display.c @/code/kernel/ke_dpc.c \ + @/code/kernel/ke_event.c @/code/kernel/ke_exception.c @/code/kernel/ke_firmware.c @/code/kernel/ke_hal.c @/code/kernel/ke_handle.c @/code/kernel/ke_id.c \ + @/code/kernel/ke_idt.c @/code/kernel/ke_input.c @/code/kernel/ke_irp.c @/code/kernel/ke_irq.c @/code/kernel/ke_irql.c @/code/kernel/ke_list.c \ + @/code/kernel/ke_mutex.c @/code/kernel/ke_port.c @/code/kernel/ke_power.c @/code/kernel/ke_process.c @/code/kernel/ke_queue.c @/code/kernel/ke_sched.c \ + @/code/kernel/ke_selftest.c @/code/kernel/ke_semaphore.c @/code/kernel/ke_settings.c @/code/kernel/ke_smp.c @/code/kernel/ke_surface.c @/code/kernel/ke_syscall.c \ + @/code/kernel/ke_system_root.c @/code/kernel/ke_system_service.c @/code/kernel/ke_thread.c @/code/kernel/ke_time.c @/code/kernel/ke_timer.c @/code/kernel/ke_trap.c \ + @/code/kernel/ke_work.c @/code/kernel/kmain.c @/code/kernel/ldr_image.c @/code/kernel/ldr_section.c @/code/kernel/mm_file_cache.c @/code/kernel/mm_phys.c \ + @/code/kernel/mm_pool.c @/code/kernel/mm_pte.c @/code/kernel/mm_swap.c @/code/kernel/mm_virt.c @/code/kernel/net_device.c @/code/kernel/net_socket.c \ + @/code/kernel/net_stack.c @/code/kernel/ob_object.c @/code/kernel/se_security.c @/code/kernel/ke_gdt_reload.asm @/code/kernel/ke_switch.asm @/code/kernel/ke_syscall.asm \ + @/code/common/boot_volume_selector.c diff --git a/code/kernel/dirs b/code/kernel/dirs new file mode 100644 index 0000000..9c7f060 --- /dev/null +++ b/code/kernel/dirs @@ -0,0 +1 @@ +DIRS=hal core diff --git a/code/kernel/dm_config.c b/code/kernel/dm_config.c index 53e75b5..3200ae8 100644 --- a/code/kernel/dm_config.c +++ b/code/kernel/dm_config.c @@ -354,7 +354,7 @@ bool DmClassSettled(const DM_CONFIG* config, const char* classId) { const DM_DRIVER_CONFIG* driver = &config->Drivers[i]; if (!strcmp(driver->Class, classId) && (config->ActivePhase == DmStartRuntime || driver->Phase == DmStartBoot) && - driver->State == DmRunWaiting) return false; + (driver->State == DmRunWaiting || driver->State == DmRunStarting)) return false; } return true; } @@ -377,7 +377,8 @@ static bool DmEdgesReady(const DM_CONFIG* config, const DM_EDGES* edges, bool re int index = DmFindDriver(config, edge->Id); if (index < 0) return false; DM_RUN_STATE state = config->Drivers[index].State; - if (required ? state != DmRunStarted : state == DmRunWaiting) return false; + if (required ? state != DmRunStarted : + (state == DmRunWaiting || state == DmRunStarting)) return false; } } return true; diff --git a/code/kernel/driver_module.c b/code/kernel/driver_module.c index d1afd9e..c4d2570 100644 --- a/code/kernel/driver_module.c +++ b/code/kernel/driver_module.c @@ -10,11 +10,14 @@ #include #include #include +#include #define DM_NAME_MAX 64u typedef enum DM_MODULE_STATE { DmModuleStarting, + DmModulePrepared, + DmModuleCommitting, DmModuleStarted, DmModuleFailed, DmModuleStopping, @@ -26,11 +29,14 @@ struct NTL_MODULE { char Name[DM_NAME_MAX]; uintptr_t ImageBase; DM_MODULE_STATE State; + NTL_MODULE_COMMIT_START CommitStart; + NTL_MODULE_ABORT_START AbortStart; NTL_MODULE_PREPARE_SHUTDOWN PrepareShutdown; NTL_MODULE_COMMIT_SHUTDOWN CommitShutdown; }; static NTL_MODULE* gDriverModules; +static SPINLOCK gDriverModuleLock = SPINLOCK_INIT; static bool DmImageContains(uintptr_t base, size_t imageSize, uintptr_t ptr, size_t bytes) { return ptr >= base && ptr - base <= imageSize && bytes <= imageSize - (ptr - base); @@ -94,7 +100,9 @@ static bool DmValidIoDriver(uintptr_t imageBase, size_t imageSize, const DRIVER_ return true; } -KSTATUS DmStartLoadedDriver(const char* name, uintptr_t imageBase) { +KSTATUS DmPrepareLoadedDriver(const char* name, uintptr_t imageBase, bool* canReleaseImage) { + if (!canReleaseImage) return NTLSTATUS_INVALID_PARAMETER; + *canReleaseImage = true; if (!name || !*name || !imageBase) return NTLSTATUS_INVALID_PARAMETER; @@ -104,18 +112,13 @@ KSTATUS DmStartLoadedDriver(const char* name, uintptr_t imageBase) { if (!length || length == DM_NAME_MAX) return NTLSTATUS_INVALID_PARAMETER; - for (NTL_MODULE* it = gDriverModules; it; it = it->Next) { - if (strcmp(it->Name, name) == 0 || it->ImageBase == imageBase) - return NTLSTATUS_ALREADY_EXISTS; - } - size_t imageSize = LdrGetImageSize(imageBase); if (!imageSize) return NTLSTATUS_INVALID_IMAGE_FORMAT; const NTL_MODULE_EXPORT* manifest = (const NTL_MODULE_EXPORT*)LdrGetImageExport(imageBase, NTL_DDK_MODULE_EXPORT_NAME); - NTL_MODULE_INITIALIZE initialize = (NTL_MODULE_INITIALIZE)0; + NTL_MODULE_PREPARE_START prepareStart = (NTL_MODULE_PREPARE_START)0; if (!manifest) return NTLSTATUS_INVALID_IMAGE_FORMAT; { @@ -124,15 +127,19 @@ KSTATUS DmStartLoadedDriver(const char* name, uintptr_t imageBase) { manifest->Version != NTL_DDK_MODULE_ABI_VERSION || manifest->Size != sizeof(*manifest) || manifest->Flags != 0u || manifest->Reserved != 0u || manifest->Reserved2 != 0u || - (manifest->Initialize && !DmImageContains(imageBase, imageSize, - (uintptr_t)manifest->Initialize, 1u)) || + (manifest->PrepareStart && !DmImageContains(imageBase, imageSize, + (uintptr_t)manifest->PrepareStart, 1u)) || (manifest->PrepareShutdown && !DmImageContains(imageBase, imageSize, (uintptr_t)manifest->PrepareShutdown, 1u)) || (manifest->CommitShutdown && !DmImageContains(imageBase, imageSize, - (uintptr_t)manifest->CommitShutdown, 1u))) + (uintptr_t)manifest->CommitShutdown, 1u)) || + (manifest->CommitStart && !DmImageContains(imageBase, imageSize, + (uintptr_t)manifest->CommitStart, 1u)) || + (manifest->AbortStart && !DmImageContains(imageBase, imageSize, + (uintptr_t)manifest->AbortStart, 1u))) return NTLSTATUS_INVALID_IMAGE_FORMAT; if ((manifest->DeviceCount && !manifest->Devices) || - manifest->DeviceCount > 64u || + manifest->DeviceCount > imageSize / sizeof(NTL_DEVICE_DESC) || (manifest->DeviceCount && !DmImageContains(imageBase, imageSize, (uintptr_t)manifest->Devices, (size_t)manifest->DeviceCount * sizeof(NTL_DEVICE_DESC)))) @@ -157,7 +164,7 @@ KSTATUS DmStartLoadedDriver(const char* name, uintptr_t imageBase) { } } if ((manifest->IoDriverCount && !manifest->IoDrivers) || - manifest->IoDriverCount > 64u || + manifest->IoDriverCount > imageSize / sizeof(*manifest->IoDrivers) || (manifest->IoDriverCount && !DmImageContains(imageBase, imageSize, (uintptr_t)manifest->IoDrivers, (size_t)manifest->IoDriverCount * sizeof(*manifest->IoDrivers)))) @@ -167,7 +174,7 @@ KSTATUS DmStartLoadedDriver(const char* name, uintptr_t imageBase) { (uintptr_t)manifest->IoDrivers[i], sizeof(DRIVER_OBJECT))) return NTLSTATUS_INVALID_IMAGE_FORMAT; } - initialize = manifest->Initialize; + prepareStart = manifest->PrepareStart; } NTL_MODULE* module = (NTL_MODULE*)MmAllocatePool(sizeof(*module)); @@ -178,12 +185,30 @@ KSTATUS DmStartLoadedDriver(const char* name, uintptr_t imageBase) { memcpy(module->Name, name, length); module->ImageBase = imageBase; module->State = DmModuleStarting; + module->CommitStart = manifest->CommitStart; + module->AbortStart = manifest->AbortStart; module->PrepareShutdown = manifest->PrepareShutdown; module->CommitShutdown = manifest->CommitShutdown; - module->Next = gDriverModules; - gDriverModules = module; + KSTATUS status = NTLSTATUS_SUCCESS; + uintptr_t flags = KeAcquireSpinlock(&gDriverModuleLock); + for (NTL_MODULE* it = gDriverModules; it; it = it->Next) { + if (strcmp(it->Name, name) == 0 || it->ImageBase == imageBase) { + status = NTLSTATUS_ALREADY_EXISTS; + break; + } + } + if (KSUCCESS(status)) { + module->Next = gDriverModules; + gDriverModules = module; + } + KeReleaseSpinlock(&gDriverModuleLock, flags); + if (!KSUCCESS(status)) { + MmFreePool(module); + return status; + } - KSTATUS status = initialize ? initialize(module) : NTLSTATUS_SUCCESS; + if (prepareStart && !module->AbortStart) *canReleaseImage = false; + status = prepareStart ? prepareStart(module) : NTLSTATUS_SUCCESS; if (!KSUCCESS(status) && !KFAILED(status)) status = NTLSTATUS_INVALID_PARAMETER; @@ -196,10 +221,42 @@ KSTATUS DmStartLoadedDriver(const char* name, uintptr_t imageBase) { } } if (KSUCCESS(status)) - status = IoPnpPublishModule(module, manifest->Devices, manifest->DeviceCount, + status = IoPnpPrepareModule(module, manifest->Devices, manifest->DeviceCount, manifest->IoDrivers, manifest->IoDriverCount); - module->State = KSUCCESS(status) ? DmModuleStarted : DmModuleFailed; - return status; + if (!KSUCCESS(status)) { + if (module->AbortStart) module->AbortStart(module); + IoPnpAbortModule(module); + uintptr_t flags = KeAcquireSpinlock(&gDriverModuleLock); + NTL_MODULE** link = &gDriverModules; + while (*link && *link != module) link = &(*link)->Next; + if (*link) *link = module->Next; + KeReleaseSpinlock(&gDriverModuleLock, flags); + MmFreePool(module); + return status; + } + module->State = DmModulePrepared; + return NTLSTATUS_SUCCESS; +} + +// Commit activates the module, exports, and PnP registrations. +void DmCommitLoadedDriver(uintptr_t imageBase, LDR_KERNEL_MODULE* image) { + NTL_MODULE* module = (NTL_MODULE*)0; + uintptr_t flags = KeAcquireSpinlock(&gDriverModuleLock); + for (NTL_MODULE* it = gDriverModules; it; it = it->Next) { + if (it->ImageBase == imageBase && it->State == DmModulePrepared) { + module = it; + module->State = DmModuleCommitting; + break; + } + } + KeReleaseSpinlock(&gDriverModuleLock, flags); + if (!module) return; + if (module->CommitStart) module->CommitStart(module); + LdrPublishModule(image); + IoPnpCommitModule(module); + flags = KeAcquireSpinlock(&gDriverModuleLock); + module->State = DmModuleStarted; + KeReleaseSpinlock(&gDriverModuleLock, flags); } KSTATUS DmPrepareShutdown(void) { diff --git a/code/kernel/hal/hal_apic.c b/code/kernel/hal/hal_apic.c index de2ad68..8dc3d08 100644 --- a/code/kernel/hal/hal_apic.c +++ b/code/kernel/hal/hal_apic.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include #include @@ -14,6 +16,9 @@ static volatile uint32_t* gLapic = (volatile uint32_t*)0; #define LAPIC_REG(off) (*(volatile uint32_t*)((uint8_t*)gLapic + (off))) #define LAPIC_ID 0x020 #define LAPIC_EOI 0x0B0 +#define LAPIC_TPR 0x080 +#define LAPIC_ISR_BASE 0x100 +#define LAPIC_IRR_BASE 0x200 #define LAPIC_SPURIOUS 0x0F0 #define LAPIC_ICR_LO 0x300 #define LAPIC_ICR_HI 0x310 @@ -24,38 +29,70 @@ static volatile uint32_t* gLapic = (volatile uint32_t*)0; #define IA32_APIC_BASE_X2APIC (1ULL << 10) #define IA32_X2APIC_ID 0x00000802u #define IA32_X2APIC_EOI 0x0000080Bu +#define IA32_X2APIC_TPR 0x00000808u +#define IA32_X2APIC_ISR_BASE 0x00000810u +#define IA32_X2APIC_IRR_BASE 0x00000820u #define IA32_X2APIC_SVR 0x0000080Fu #define IA32_X2APIC_ICR 0x00000830u #define CPUID_FEATURE_ECX_X2APIC (1u << 21) -// ---- I/O APIC ----. -static volatile uint32_t* gIoapic = (volatile uint32_t*)0; -static uint32_t gBspLapicId = 0; -static uint8_t gX2ApicSupported = 0; -static uint8_t gX2ApicEnabled = 0; -static uint32_t gIoapicGsiBase = 0; -static uint32_t gIoapicRedirectionCount = 0; +// ---- I/O APIC interrupt domains ----. +#define HAL_IOAPIC_MAX 8u +#define IOAPIC_IDX 0x00u +#define IOAPIC_DATA 0x10u + +typedef struct HAL_IOAPIC { + volatile uint32_t* Registers; + uintptr_t Physical; + uint32_t GsiBase; + uint32_t Pins; + volatile long RegisterLock; +} HAL_IOAPIC; + +static HAL_IOAPIC gIoapics[HAL_IOAPIC_MAX]; +static uint32_t gIoapicCount; +static uint32_t gBspLapicId; +static uint8_t gX2ApicSupported; +static uint8_t gX2ApicEnabled; static uint32_t gIsaGsi[16]; static uint16_t gIsaFlags[16]; -static uint16_t gSciIrq = UINT16_MAX; -static bool gIsaOverridesInitialized = false; -#define IOAPIC_IDX 0x00 -#define IOAPIC_DATA 0x10 +static bool gIsaOverridesInitialized; -// Implements the ioapic Read operation. -static uint32_t IoapicRead(uint8_t reg) { - *(volatile uint32_t*)((uint8_t*)gIoapic + IOAPIC_IDX) = reg; - return *(volatile uint32_t*)((uint8_t*)gIoapic + IOAPIC_DATA); -} -// Implements the ioapic Write operation. -static void IoapicWrite(uint8_t reg, uint32_t val) { - *(volatile uint32_t*)((uint8_t*)gIoapic + IOAPIC_IDX) = reg; - *(volatile uint32_t*)((uint8_t*)gIoapic + IOAPIC_DATA) = val; +// I/O APIC register selectors are shared by every CPU accessing that APIC. +static uint32_t IoapicRead(HAL_IOAPIC* apic, uint8_t reg) { + uintptr_t interruptFlags = HalDisableInterrupts(); + while (_InterlockedCompareExchange(&apic->RegisterLock, 1, 0)) + _mm_pause(); + apic->Registers[IOAPIC_IDX / 4u] = reg; + uint32_t value = apic->Registers[IOAPIC_DATA / 4u]; + _InterlockedExchange(&apic->RegisterLock, 0); + HalRestoreInterrupts(interruptFlags); + return value; +} + +static void IoapicWrite(HAL_IOAPIC* apic, uint8_t reg, uint32_t value) { + uintptr_t interruptFlags = HalDisableInterrupts(); + while (_InterlockedCompareExchange(&apic->RegisterLock, 1, 0)) + _mm_pause(); + apic->Registers[IOAPIC_IDX / 4u] = reg; + apic->Registers[IOAPIC_DATA / 4u] = value; + _InterlockedExchange(&apic->RegisterLock, 0); + HalRestoreInterrupts(interruptFlags); +} + +static HAL_IOAPIC* HalApicFindGsi(uint32_t gsi, uint32_t* pinOut) { + for (uint32_t i = 0; i < gIoapicCount; i++) { + HAL_IOAPIC* apic = &gIoapics[i]; + if (gsi >= apic->GsiBase && gsi - apic->GsiBase < apic->Pins) { + *pinOut = gsi - apic->GsiBase; + return apic; + } + } + return (HAL_IOAPIC*)0; } -// Implements the apic Detect Mode operation. static void HalApicDetectMode(void) { int regs[4] = {0, 0, 0, 0}; __cpuid(regs, 1); @@ -70,7 +107,6 @@ static void HalApicStallUs(uint32_t us) { HalTimerStall(us); } -// Implements the apic Wait Icr Idle operation. static void HalApicWaitIcrIdle(void) { if (gX2ApicEnabled) return; @@ -82,7 +118,6 @@ static void HalApicWaitIcrIdle(void) { } } -// Implements the apic Send Ipi operation. static void HalApicSendIpi(uint32_t lapicId, uint32_t low) { if (gX2ApicEnabled) { __writemsr(IA32_X2APIC_ICR, ((uint64_t)lapicId << 32) | low); @@ -98,8 +133,6 @@ static void HalApicSendIpi(uint32_t lapicId, uint32_t low) { // IRQ n -> redirection table at register 0x10 + 2*n (low), 0x11 + 2*n (high). #define IOREDTBL_LO(n) (0x10 + 2*(n)) #define IOREDTBL_HI(n) (0x11 + 2*(n)) -// Interrupt vector base: IRQ 0 -> vector 0x20, IRQ 1 -> vector 0x21, ... -#define IRQ_VECTOR_BASE 0x20 // Returns the local interrupt-controller hardware ID of the boot processor. uint32_t HalApicGetBootProcessorId(void) { @@ -126,12 +159,46 @@ void HalApicInitializeCurrentProcessor(void) { apicBase |= IA32_APIC_BASE_X2APIC; __writemsr(IA32_APIC_BASE, apicBase); __writemsr(IA32_X2APIC_SVR, LAPIC_ENABLE | 0xFFu); + HalApicSetTaskPriority(0); return; } __writemsr(IA32_APIC_BASE, apicBase); if (gLapic) LAPIC_REG(LAPIC_SPURIOUS) = LAPIC_ENABLE | 0xFF; + HalApicSetTaskPriority(0); +} + +// Controls the current CPU's interrupt priority without changing its interrupt-enable flag. +void HalApicSetTaskPriority(uint8_t priority) { + if (gX2ApicEnabled) { + __writemsr(IA32_X2APIC_TPR, priority); + } else if (gLapic) { + LAPIC_REG(LAPIC_TPR) = priority; + } +} + +uint8_t HalApicQueryTaskPriority(void) { + if (gX2ApicEnabled) + return (uint8_t)__readmsr(IA32_X2APIC_TPR); + return gLapic ? (uint8_t)LAPIC_REG(LAPIC_TPR) : 0u; +} + +// Reads the current processor's local delivery state after a source is masked. +bool HalApicVectorPending(uint8_t vector) { + const uint32_t index = (uint32_t)vector >> 5u; + const uint32_t mask = 1u << (vector & 31u); + uint32_t irr, isr; + if (gX2ApicEnabled) { + irr = (uint32_t)__readmsr(IA32_X2APIC_IRR_BASE + index); + isr = (uint32_t)__readmsr(IA32_X2APIC_ISR_BASE + index); + } else if (gLapic) { + irr = LAPIC_REG(LAPIC_IRR_BASE + 0x10u * index); + isr = LAPIC_REG(LAPIC_ISR_BASE + 0x10u * index); + } else { + return true; + } + return ((irr | isr) & mask) != 0u; } // Broadcasts an NMI to every processor except the caller. @@ -182,102 +249,85 @@ KSTATUS HalApicStartProcessor(uint32_t hardwareId, uintptr_t startPhysical) { return NTLSTATUS_SUCCESS; } -// Composes an MSI message targeting the boot processor without exposing APIC mode. -KSTATUS HalApicComposeMsi(uint8_t vector, HAL_MSI_MESSAGE* messageOut) { - if (!messageOut || vector < 0x20u) +// MSI destination encoding without interrupt remapping supports an 8-bit APIC ID. +KSTATUS HalApicComposeMsi(uint32_t hardwareId, uint8_t vector, HAL_MSI_MESSAGE* out) { + if (!out || vector < KE_VECTOR_DEVICE_FIRST || vector > KE_VECTOR_DEVICE_LAST) return NTLSTATUS_INVALID_PARAMETER; - if (gBspLapicId >= 256u) + if (hardwareId > 255u) return NTLSTATUS_NOT_SUPPORTED; - - messageOut->Address = 0xFEE00000ull | ((uint64_t)(gBspLapicId & 0xFFu) << 12); - messageOut->Data = vector; - messageOut->Reserved = 0; + out->Address = 0xFEE00000ull | ((uint64_t)hardwareId << 12); + out->Data = vector; + out->Reserved = 0; return NTLSTATUS_SUCCESS; } -// Initializes the identity ISA map before processing MADT source overrides. static void HalApicInitializeIsaMap(void) { if (gIsaOverridesInitialized) return; - for (uint32_t irq = 0; irq < 16; ++irq) { + for (uint32_t irq = 0; irq < 16; irq++) { gIsaGsi[irq] = irq; gIsaFlags[irq] = 0; } gIsaOverridesInitialized = true; } -// Records the global-system-interrupt base of the currently supported IOAPIC. -void HalApicSetGsiBase(uint32_t gsiBase) { gIoapicGsiBase = gsiBase; } +void HalApicAddIoapic(uintptr_t physical, uint32_t gsiBase) { + if (!physical || gIoapicCount >= HAL_IOAPIC_MAX) + return; + for (uint32_t i = 0; i < gIoapicCount; i++) + if (gIoapics[i].Physical == physical) + return; + HAL_IOAPIC* apic = &gIoapics[gIoapicCount++]; + apic->Physical = physical; + apic->GsiBase = gsiBase; +} -// Preserves MADT interrupt-source overrides for legacy ISA devices. void HalApicSetIsaOverride(uint8_t irq, uint32_t gsi, uint16_t flags) { - if (irq >= 16) return; + if (irq >= 16u) return; HalApicInitializeIsaMap(); gIsaGsi[irq] = gsi; gIsaFlags[irq] = flags; } -// Marks the FADT SCI as a low-active, level-triggered interrupt by default. -void HalApicSetSciIrq(uint16_t irq) { gSciIrq = irq; } - -// Resolves one logical IRQ to a physical pin on the selected IOAPIC. -static bool HalApicResolveIrq(uint8_t irq, uint32_t* pinOut, uint32_t* flagsOut) { +KSTATUS HalApicResolveIsa(uint8_t irq, uint32_t* gsiOut, uint16_t* flagsOut) { + if (irq >= 16u || !gsiOut || !flagsOut) + return NTLSTATUS_INVALID_PARAMETER; HalApicInitializeIsaMap(); - uint32_t gsi = irq < 16 ? gIsaGsi[irq] : irq; - if (gsi < gIoapicGsiBase || gsi - gIoapicGsiBase >= gIoapicRedirectionCount) - return false; - uint32_t flags = 0; - if (irq == gSciIrq) flags = (1u << 13) | (1u << 15); - if (irq < 16) { - uint16_t override = gIsaFlags[irq]; - // MADT 00 is bus-conformant; 11 selects active low or level triggered. - if ((override & 3u) == 3u) flags |= (1u << 13); - else if ((override & 3u) == 1u) flags &= ~(1u << 13); - if (((override >> 2) & 3u) == 3u) flags |= (1u << 15); - else if (((override >> 2) & 3u) == 1u) flags &= ~(1u << 15); - } - *pinOut = gsi - gIoapicGsiBase; - *flagsOut = flags; - return true; + uint32_t pin; + if (!HalApicFindGsi(gIsaGsi[irq], &pin)) + return NTLSTATUS_NOT_SUPPORTED; + *gsiOut = gIsaGsi[irq]; + *flagsOut = gIsaFlags[irq]; + return NTLSTATUS_SUCCESS; } -// Reports whether a platform IRQ can be routed by the current IOAPIC. -bool HalApicCanRouteIrq(uint8_t irq) { - uint32_t pin, flags; - return irq < 24 && HalApicResolveIrq(irq, &pin, &flags); +// ACPI polarity bits 1:0 and trigger bits 3:2 encode bus-defined defaults. +KSTATUS HalApicRouteGsi(uint32_t gsi, uint8_t vector, uint32_t hardwareId, + uint16_t flags, bool masked) { + if (vector < KE_VECTOR_DEVICE_FIRST || vector > KE_VECTOR_DEVICE_LAST || hardwareId > 255u) + return NTLSTATUS_INVALID_PARAMETER; + uint32_t pin; + HAL_IOAPIC* apic = HalApicFindGsi(gsi, &pin); + if (!apic) return NTLSTATUS_NOT_SUPPORTED; + uint32_t mode = 0; + if ((flags & 3u) == 3u) mode |= (1u << 13); + if (((flags >> 2) & 3u) == 3u) mode |= (1u << 15); + IoapicWrite(apic, IOREDTBL_LO(pin), (1u << 16) | vector | mode); + IoapicWrite(apic, IOREDTBL_HI(pin), (hardwareId & 255u) << 24); + if (!masked) IoapicWrite(apic, IOREDTBL_LO(pin), vector | mode); + return NTLSTATUS_SUCCESS; } -// Implements the apic Route Irq operation. -void HalApicRouteIrq(uint8_t irq) { - // Full initial setup of the redirection entry. - // Sets the vector and clears the mask bit in one write. - uint32_t pin, flags; - if (!HalApicResolveIrq(irq, &pin, &flags)) return; - uint32_t vector = IRQ_VECTOR_BASE + irq; - IoapicWrite(IOREDTBL_HI(pin), (gBspLapicId & 0xFFu) << 24); - IoapicWrite(IOREDTBL_LO(pin), vector | flags); +KSTATUS HalApicMaskGsi(uint32_t gsi, bool masked) { + uint32_t pin; + HAL_IOAPIC* apic = HalApicFindGsi(gsi, &pin); + if (!apic) return NTLSTATUS_NOT_SUPPORTED; + uint32_t lo = IoapicRead(apic, IOREDTBL_LO(pin)); + if (masked) lo |= 1u << 16; + else lo &= ~(1u << 16); + IoapicWrite(apic, IOREDTBL_LO(pin), lo); + return NTLSTATUS_SUCCESS; } -// Implements the apic Mask Irq operation. -void HalApicMaskIrq(uint8_t irq) { - uint32_t pin, flags; - if (!HalApicResolveIrq(irq, &pin, &flags)) return; - uint32_t lo = IoapicRead(IOREDTBL_LO(pin)); - lo |= (1 << 16); - IoapicWrite(IOREDTBL_LO(pin), lo); -} - -// Implements the apic Unmask Irq operation. -void HalApicUnmaskIrq(uint8_t irq) { - uint32_t pin, flags; - if (!HalApicResolveIrq(irq, &pin, &flags)) return; - uint32_t lo = IoapicRead(IOREDTBL_LO(pin)); - lo = (lo & ~(0xFFu | (1u << 16) | (1u << 13) | (1u << 15))) | - (IRQ_VECTOR_BASE + irq) | flags; - IoapicWrite(IOREDTBL_HI(pin), (gBspLapicId & 0xFFu) << 24); - IoapicWrite(IOREDTBL_LO(pin), lo); -} - -// Implements the apic Send Eoi operation. void HalApicSendEoi(void) { if (gX2ApicEnabled) { __writemsr(IA32_X2APIC_EOI, 0); @@ -286,27 +336,29 @@ void HalApicSendEoi(void) { LAPIC_REG(LAPIC_EOI) = 0; } -// Implements the apic Initialize operation. -void HalApicInitialize(uintptr_t lapicPhys, uintptr_t ioapicPhys) { +void HalApicInitialize(uintptr_t lapicPhys) { + // The PIC remains masked: legacy input arrives through programmed I/O APICs. + __outbyte(0x21, 0xFF); + __outbyte(0xA1, 0xFF); HalApicDetectMode(); - gLapic = (volatile uint32_t*)(HalPhysicalToVirtual(lapicPhys)); - gIoapic = (volatile uint32_t*)(HalPhysicalToVirtual(ioapicPhys)); - - // The BSP is the CPU executing HAL init. Keep all external/device IRQs - // routed to this LAPIC; CPU-local IPIs use the local APIC directly. + gLapic = (volatile uint32_t*)HalPhysicalToVirtual(lapicPhys); if (gX2ApicEnabled) gBspLapicId = (uint32_t)__readmsr(IA32_X2APIC_ID); else - gBspLapicId = (LAPIC_REG(LAPIC_ID) >> 24) & 0xFF; - + gBspLapicId = (LAPIC_REG(LAPIC_ID) >> 24) & 0xFFu; HalApicInitializeCurrentProcessor(); + if (gIoapicCount == 0) + HalApicAddIoapic(0xFEC00000u, 0); - // Mask all IOAPIC lines initially. - uint32_t maxRedir = (IoapicRead(1) >> 16) & 0xFF; - gIoapicRedirectionCount = maxRedir + 1u; - for (uint32_t i = 0; i <= maxRedir; i++) { - IoapicWrite(IOREDTBL_LO(i), (1u << 16) | IRQ_VECTOR_BASE); - IoapicWrite(IOREDTBL_HI(i), (gBspLapicId & 0xFFu) << 24); + for (uint32_t index = 0; index < gIoapicCount; index++) { + HAL_IOAPIC* apic = &gIoapics[index]; + apic->Registers = (volatile uint32_t*)HalPhysicalToVirtual(apic->Physical); + uint32_t version = IoapicRead(apic, 1u); + apic->Pins = ((version >> 16) & 0xFFu) + 1u; + for (uint32_t pin = 0; pin < apic->Pins; pin++) { + IoapicWrite(apic, IOREDTBL_LO(pin), (1u << 16) | KE_VECTOR_DEVICE_FIRST); + IoapicWrite(apic, IOREDTBL_HI(pin), (gBspLapicId & 255u) << 24); + } } } diff --git a/code/kernel/hal/hal_main.c b/code/kernel/hal/hal_main.c index f6a8397..8d8acbb 100644 --- a/code/kernel/hal/hal_main.c +++ b/code/kernel/hal/hal_main.c @@ -39,10 +39,13 @@ static HAL_API gApi = { .Start = HalApicStartProcessor, }, .InterruptController = { - .RouteIrq = HalApicRouteIrq, - .MaskIrq = HalApicMaskIrq, - .UnmaskIrq = HalApicUnmaskIrq, + .RouteGsi = HalApicRouteGsi, + .MaskGsi = HalApicMaskGsi, + .ResolveIsa = HalApicResolveIsa, .SendEoi = HalApicSendEoi, + .SetTaskPriority = HalApicSetTaskPriority, + .QueryTaskPriority = HalApicQueryTaskPriority, + .VectorPending = HalApicVectorPending, .InitializeCurrentProcessor = HalApicInitializeCurrentProcessor, .SendProcessorInterrupt = HalApicSendProcessorInterrupt, .SendProcessorNmi = HalApicSendProcessorNmi, @@ -122,12 +125,7 @@ typedef struct ACPI_FIXED_REGISTER { static ACPI_FIXED_REGISTER gPm1aCnt; static ACPI_FIXED_REGISTER gPm1bCnt; -static ACPI_FIXED_REGISTER gPm1aStatus; -static ACPI_FIXED_REGISTER gPm1bStatus; -static ACPI_FIXED_REGISTER gPm1aEnable; -static ACPI_FIXED_REGISTER gPm1bEnable; static uint16_t gSciIrq = 0; -static bool gFixedPowerButtonArmed = false; static ACPI_FIXED_REGISTER gSleepControl; static uint32_t gLegacyPm1aPort = 0; static uint32_t gLegacyPm1bPort = 0; @@ -179,13 +177,6 @@ void* HalPhysicalToVirtual(uint64_t phys) { // systems may put the real DSDT and PM1 control registers in the extended // X_* fields, so do not rely only on the legacy 32-bit fields. #define FADT_SCI_INT_OFFSET 46u -#define FADT_PM1A_EVT_BLK_OFFSET 56u -#define FADT_PM1B_EVT_BLK_OFFSET 60u -#define FADT_PM1_EVT_LEN_OFFSET 88u -#define FADT_X_PM1A_EVT_BLK_OFFSET 148u -#define FADT_X_PM1B_EVT_BLK_OFFSET 160u -#define FADT_FLAG_POWER_BUTTON (1u << 4) -#define ACPI_PM1_POWER_BUTTON_BIT (1u << 8) #define FADT_DSDT_OFFSET 40u #define FADT_SMI_CMD_OFFSET 48u #define FADT_ACPI_ENABLE_OFFSET 52u @@ -217,7 +208,6 @@ typedef struct { static ACPI_FIXED_REGISTER gResetRegister; static uint8_t gResetValue; -// Implements the acpi Read U32 operation. static uint32_t AcpiReadU32(const void* table, uint32_t tableLen, uint32_t off) { uint32_t value = 0; if (off + sizeof(value) <= tableLen) @@ -225,7 +215,6 @@ static uint32_t AcpiReadU32(const void* table, uint32_t tableLen, uint32_t off) return value; } -// Implements the acpi Read U64 operation. static uint64_t AcpiReadU64(const void* table, uint32_t tableLen, uint32_t off) { uint64_t value = 0; if (off + sizeof(value) <= tableLen) @@ -310,77 +299,6 @@ static void AcpiWriteFixedRegister(const ACPI_FIXED_REGISTER* reg, uint32_t valu else *(volatile uint32_t*)address = value; } -// Selects a PM1 event block as two adjacent equal-width status and enable registers. -static void AcpiConfigurePm1EventBlock(const void* fadt, uint32_t len, - uint32_t legacyOffset, uint32_t gasOffset, - uint8_t halfLength, ACPI_FIXED_REGISTER* status, - ACPI_FIXED_REGISTER* enable) { - ACPI_FIXED_REGISTER block = {0}; - uint32_t legacy = AcpiReadU32(fadt, len, legacyOffset); - if (legacy && legacy <= 0xFFFFu) { - block.AddressSpaceId = 1; - block.Address = legacy; - } - ACPI_FIXED_REGISTER extended = {0}; - if (AcpiReadGasRegister(fadt, len, gasOffset, &extended)) block = extended; - if (!block.Address || (block.AddressSpaceId == 1 && - block.Address + halfLength * 2u - 1u > 0xFFFFu)) return; - block.WidthBytes = halfLength; - *status = block; - block.Address += halfLength; - *enable = block; -} - -// Reports the fixed-feature power-button interrupt supported by this HAL. -static KSTATUS AcpiQueryFixedButtonIrq(uint8_t* irqOut) { - if (!irqOut) return NTLSTATUS_INVALID_PARAMETER; - // A FADT control-method power button requires AML evaluation, not PM1 polling. - if (gHwReducedAcpi || (gFadtFlags & FADT_FLAG_POWER_BUTTON) || - !gSciIrq || gSciIrq >= 16u || !gPm1aStatus.Address || !gPm1aEnable.Address || - !HalApicCanRouteIrq((uint8_t)gSciIrq)) - return NTLSTATUS_NOT_SUPPORTED; - *irqOut = (uint8_t)gSciIrq; - return NTLSTATUS_SUCCESS; -} - -// Discards any stale press then enables the PM1 fixed power-button SCI. -static KSTATUS AcpiArmFixedButton(void) { - uint8_t irq; - KSTATUS status = AcpiQueryFixedButtonIrq(&irq); - if (!KSUCCESS(status)) return status; - // No SCI_EN means firmware still owns ACPI events. Never steal ownership - // through SMI_CMD just to install a power-button handler during boot. - if (!(AcpiReadFixedRegister(&gPm1aCnt) & 1u)) - return NTLSTATUS_NOT_SUPPORTED; - AcpiWriteFixedRegister(&gPm1aStatus, ACPI_PM1_POWER_BUTTON_BIT); - if (gPm1bStatus.Address) - AcpiWriteFixedRegister(&gPm1bStatus, ACPI_PM1_POWER_BUTTON_BIT); - uint32_t enabled = AcpiReadFixedRegister(&gPm1aEnable); - AcpiWriteFixedRegister(&gPm1aEnable, enabled | ACPI_PM1_POWER_BUTTON_BIT); - if (gPm1bEnable.Address) { - enabled = AcpiReadFixedRegister(&gPm1bEnable); - AcpiWriteFixedRegister(&gPm1bEnable, enabled | ACPI_PM1_POWER_BUTTON_BIT); - } - gFixedPowerButtonArmed = true; - return NTLSTATUS_SUCCESS; -} - -// Acknowledges the fixed-button source only; the SCI may carry unrelated events. -static bool AcpiConsumeFixedButton(void) { - if (!gFixedPowerButtonArmed) return false; - bool pressed = false; - if (AcpiReadFixedRegister(&gPm1aStatus) & ACPI_PM1_POWER_BUTTON_BIT) { - AcpiWriteFixedRegister(&gPm1aStatus, ACPI_PM1_POWER_BUTTON_BIT); - pressed = true; - } - if (gPm1bStatus.Address && - (AcpiReadFixedRegister(&gPm1bStatus) & ACPI_PM1_POWER_BUTTON_BIT)) { - AcpiWriteFixedRegister(&gPm1bStatus, ACPI_PM1_POWER_BUTTON_BIT); - pressed = true; - } - return pressed; -} - // Detects whether PM1 control is using the standard Intel PCH PMBASE layout. static void AcpiDetectIntelPchPmBase(void) { gIntelPchPmBase = 0; @@ -486,7 +404,6 @@ static const uint8_t* AmlParseNameString(const uint8_t* p, const uint8_t* end, return p; } -// Implements the aml Read Integer operation. static bool AmlReadInteger(const uint8_t** pp, const uint8_t* end, uint8_t* out) { const uint8_t* p = *pp; if (p >= end) return false; @@ -580,10 +497,6 @@ static void ParseFadt(const ACPISDTHeader* header) { memset(&gPm1aCnt, 0, sizeof(gPm1aCnt)); memset(&gPm1bCnt, 0, sizeof(gPm1bCnt)); - memset(&gPm1aStatus, 0, sizeof(gPm1aStatus)); - memset(&gPm1bStatus, 0, sizeof(gPm1bStatus)); - memset(&gPm1aEnable, 0, sizeof(gPm1aEnable)); - memset(&gPm1bEnable, 0, sizeof(gPm1bEnable)); gSciIrq = 0; if (len >= FADT_SCI_INT_OFFSET + sizeof(gSciIrq)) memcpy(&gSciIrq, (const uint8_t*)fadt + FADT_SCI_INT_OFFSET, sizeof(gSciIrq)); @@ -628,16 +541,6 @@ static void ParseFadt(const ACPISDTHeader* header) { if (gHwReducedAcpi) (void)AcpiReadByteGasRegister(fadt, len, FADT_SLEEP_CONTROL_OFFSET, &gSleepControl); - uint8_t eventLength = FADT_PM1_EVT_LEN_OFFSET < len ? - *((const uint8_t*)fadt + FADT_PM1_EVT_LEN_OFFSET) : 0u; - if (!gHwReducedAcpi && (eventLength == 4u || eventLength == 8u)) { - uint8_t half = eventLength / 2u; - AcpiConfigurePm1EventBlock(fadt, len, FADT_PM1A_EVT_BLK_OFFSET, - FADT_X_PM1A_EVT_BLK_OFFSET, half, &gPm1aStatus, &gPm1aEnable); - AcpiConfigurePm1EventBlock(fadt, len, FADT_PM1B_EVT_BLK_OFFSET, - FADT_X_PM1B_EVT_BLK_OFFSET, half, &gPm1bStatus, &gPm1bEnable); - } - gSmiCommandPort = AcpiReadU32(fadt, len, FADT_SMI_CMD_OFFSET); gAcpiEnableValue = FADT_ACPI_ENABLE_OFFSET < len ? *((const uint8_t*)fadt + FADT_ACPI_ENABLE_OFFSET) @@ -652,10 +555,12 @@ static void ParseFadt(const ACPISDTHeader* header) { centuryRegister = *((const uint8_t*)fadt + FADT_CENTURY_OFFSET); HalRtcSetCenturyRegister(centuryRegister); - HalDbgPrint("HAL: FADT flags=0x%08x hw_reduced=%u PM1a_CNT=%u:0x%016llx legacy=0x%04x " + HalDbgPrint("HAL: FADT flags=0x%08x sci_irq=%u power_button=%s hw_reduced=%u PM1a_CNT=%u:0x%016llx legacy=0x%04x " "PM1b_CNT=%u:0x%016llx legacy=0x%04x SLEEP_CTL=%u:0x%016llx " "SMI=0x%08x DSDT=0x%016llx RTC_CENTURY=0x%02x\n", - gFadtFlags, gHwReducedAcpi ? 1u : 0u, + gFadtFlags, (unsigned)gSciIrq, + (gFadtFlags & (1u << 4)) ? "control-method" : "fixed", + gHwReducedAcpi ? 1u : 0u, gPm1aCnt.AddressSpaceId, gPm1aCnt.Address, gLegacyPm1aPort, gPm1bCnt.AddressSpaceId, gPm1bCnt.Address, gLegacyPm1bPort, gSleepControl.AddressSpaceId, gSleepControl.Address, @@ -674,7 +579,6 @@ static void ParseFadt(const ACPISDTHeader* header) { } } -// Implements the add Cpu Record operation. static void HalAddCpuRecord(uint32_t uid, uint32_t lapicId, uint32_t flags) { if (gCpuTopology.Count >= HAL_MAX_PROCESSORS) return; @@ -711,7 +615,7 @@ static void ParseMadt(MADT* madt) { gIoapicPhys = *(uint32_t*)(p + 4); uint32_t base; memcpy(&base, p + 8, sizeof(base)); - HalApicSetGsiBase(base); + HalApicAddIoapic(*(uint32_t*)(p + 4), base); } else if (type == 2 && len >= 10 && p[2] == 0) { // ISA source override uint32_t gsi; uint16_t flags; @@ -732,7 +636,6 @@ static void ParseMadt(MADT* madt) { } } -// Implements the walk Acpi operation. static void WalkAcpi(uintptr_t rsdpPhys) { if (!rsdpPhys) return; @@ -995,8 +898,7 @@ HAL_ENTRY KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) { HalDbgPrint("HAL: LAPIC=%016llx IOAPIC=%016llx HPET=%016llx\n", gLapicPhys, gIoapicPhys, gHpetPhys); - HalApicSetSciIrq(gSciIrq); - HalApicInitialize(gLapicPhys, gIoapicPhys); + HalApicInitialize(gLapicPhys); HalDbgPrint("HAL: local APIC mode=%s BSP_ID=%u\n", HalApicUsingX2Apic() ? "x2APIC" : "xAPIC", HalApicGetBootProcessorId()); @@ -1008,9 +910,6 @@ HAL_ENTRY KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) { HalPciInitialize(&gApi.Pci); gApi.Power.Shutdown = HalShutdown; gApi.Power.Reset = HalReset; - gApi.Power.QueryFixedButtonIrq = AcpiQueryFixedButtonIrq; - gApi.Power.ArmFixedButton = AcpiArmFixedButton; - gApi.Power.ConsumeFixedButton = AcpiConsumeFixedButton; AcpiDetectIntelPchPmBase(); gInitialised = 1; @@ -1026,7 +925,6 @@ HAL_ENTRY KSTATUS HalInitialize(const HAL_INIT_PARAMS* initParams) { gApi.Timer.Stall(1); // Micro-stalls } - HalDbgPrint("HAL: initialisation complete.\n"); return NTLSTATUS_SUCCESS; } diff --git a/code/kernel/hal/hal_pci.c b/code/kernel/hal/hal_pci.c index 1e0ec66..dda89d0 100644 --- a/code/kernel/hal/hal_pci.c +++ b/code/kernel/hal/hal_pci.c @@ -41,7 +41,6 @@ static void PciWrite32(uint16_t segment, __outdword(PCI_CONFIG_DATA, value); } -// Implements the pci Initialize operation. void HalPciInitialize(HAL_PCI* out) { out->Read32 = PciRead32; out->Write32 = PciWrite32; diff --git a/code/kernel/hal/hal_rtc.c b/code/kernel/hal/hal_rtc.c index a8983dd..26259ef 100644 --- a/code/kernel/hal/hal_rtc.c +++ b/code/kernel/hal/hal_rtc.c @@ -23,23 +23,19 @@ static uint8_t gCenturyRegister; -// Implements the rtc Read operation. static uint8_t RtcRead(uint8_t reg) { __outbyte(CMOS_INDEX_PORT, (uint8_t)(reg | 0x80u)); // keep NMI masked while selecting. return __inbyte(CMOS_DATA_PORT); } -// Implements the rtc Update In Progress operation. static bool RtcUpdateInProgress(void) { return (RtcRead(RTC_REG_STATUS_A) & 0x80u) != 0; } -// Implements the rtc Bcd To Binary operation. static uint8_t RtcBcdToBinary(uint8_t value) { return (uint8_t)(((value >> 4) * 10u) + (value & 0x0Fu)); } -// Implements the rtc Read Stable operation. static bool RtcReadStable(HAL_RTC_TIME* out) { if (!out) return false; @@ -116,12 +112,10 @@ static bool RtcReadStable(HAL_RTC_TIME* out) { return true; } -// Implements the rtc Leap Year operation. static bool RtcLeapYear(uint16_t year) { return ((year % 4u) == 0u && (year % 100u) != 0u) || ((year % 400u) == 0u); } -// Implements the rtc Days In Month operation. static uint8_t RtcDaysInMonth(uint16_t year, uint8_t month) { static const uint8_t days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; if (month < 1u || month > 12u) return 0; @@ -129,7 +123,6 @@ static uint8_t RtcDaysInMonth(uint16_t year, uint8_t month) { return days[month - 1u]; } -// Implements the rtc Valid operation. static bool RtcValid(const HAL_RTC_TIME* t) { if (!t) return false; if (t->Year < 1970u || t->Year > 9999u) return false; @@ -140,7 +133,6 @@ static bool RtcValid(const HAL_RTC_TIME* t) { return true; } -// Implements the rtc Query Time operation. static KSTATUS HalRtcQueryTime(HAL_RTC_TIME* outTime) { if (!outTime) return NTLSTATUS_INVALID_PARAMETER; @@ -153,12 +145,10 @@ static KSTATUS HalRtcQueryTime(HAL_RTC_TIME* outTime) { return NTLSTATUS_SUCCESS; } -// Implements the rtc Set Century Register operation. void HalRtcSetCenturyRegister(uint8_t centuryRegister) { gCenturyRegister = centuryRegister; } -// Implements the rtc Initialize operation. void HalRtcInitialize(HAL_RTC* out) { if (!out) return; out->QueryTime = HalRtcQueryTime; diff --git a/code/kernel/hal/hal_screen.c b/code/kernel/hal/hal_screen.c index bed6038..9b11c43 100644 --- a/code/kernel/hal/hal_screen.c +++ b/code/kernel/hal/hal_screen.c @@ -39,7 +39,6 @@ static inline void PutPixelRaw(int32_t x, int32_t y, uint32_t color) { gFb[y * gStride + x] = color; } -// Implements the screen Flush Rows operation. static void ScreenFlushRows(int startY, int rows) { if (!gBackbuffer || rows <= 0) return; @@ -73,12 +72,10 @@ static void ScreenClear(uint32_t color) { gCursorX = 0; gCursorY = 0; } -// Implements the screen Put Pixel operation. static void ScreenPutPixel(int32_t x, int32_t y, uint32_t color) { PutPixelRaw(x, y, color); } -// Implements the screen Blit operation. static void ScreenBlit(int32_t x, int32_t y, int32_t w, int32_t h, const uint32_t* pixels) { // Calculate clipping bounds. int startX = (x < 0) ? 0 : x; @@ -111,10 +108,8 @@ static void ScreenBlit(int32_t x, int32_t y, int32_t w, int32_t h, const uint32_ } } -// Implements the screen Get Size operation. static void ScreenGetSize(int* w, int* h) { *w = gWidth; *h = gHeight; } -// Implements the screen Get Framebuffer operation. static KSTATUS ScreenGetFramebuffer(HAL_FRAMEBUFFER_INFO* outInfo) { if (!outInfo || !gFb || gWidth <= 0 || gHeight <= 0 || gStride <= 0) return NTLSTATUS_INVALID_PARAMETER; @@ -127,7 +122,6 @@ static KSTATUS ScreenGetFramebuffer(HAL_FRAMEBUFFER_INFO* outInfo) { return NTLSTATUS_SUCCESS; } -// Implements the screen Scroll operation. static void ScreenScroll(int32_t lines) { if (lines <= 0) return; @@ -153,7 +147,6 @@ static void ScreenScroll(int32_t lines) { ScreenFlushRows(0, gHeight); } -// Implements the screen Put Char operation. static void ScreenPutChar(char c, int32_t x, int32_t y, uint32_t fg, uint32_t bg) { const uint8_t* glyph = Font8x16 + ((uint8_t)c * 16); for (int32_t row = 0; row < 16; row++) { @@ -165,7 +158,6 @@ static void ScreenPutChar(char c, int32_t x, int32_t y, uint32_t fg, uint32_t bg } } -// Implements the screen Print Char operation. static void ScreenPrintChar(char c, uint32_t fg, uint32_t bg) { int cols = gWidth / FONT_W; int rows = gHeight / FONT_H; diff --git a/code/kernel/hal/hal_timer.c b/code/kernel/hal/hal_timer.c index 1d14186..7aa3513 100644 --- a/code/kernel/hal/hal_timer.c +++ b/code/kernel/hal/hal_timer.c @@ -6,13 +6,14 @@ #include #include #include +#include #define LAPIC_TIMER_LVT 0x320 #define LAPIC_TIMER_INIT 0x380 #define LAPIC_TIMER_CUR 0x390 #define LAPIC_TIMER_DIV 0x3E0 -#define TIMER_VECTOR 0x20 // vector 0x20 = IRQ 0 slot in IDT +#define TIMER_VECTOR KE_VECTOR_CPU_TIMER #define TIMER_PERIODIC (1 << 17) #define TIMER_MASKED (1 << 16) #define TIMER_DIV16 0x3 @@ -30,9 +31,7 @@ static volatile uint64_t* gHpet = NULL; static volatile uint64_t gTicks = 0; -// Implements the outb operation. static inline void outb(uint16_t port, uint8_t val) { __outbyte(port, val); } -// Implements the inb operation. static inline uint8_t inb(uint16_t port) { return __inbyte(port); } // Records one local timer interrupt for HAL timekeeping fallback. @@ -87,7 +86,6 @@ static uint64_t QueryTickFrequency(void) { return 1000000ull; } -// Implements the stall operation. void HalTimerStall(uint32_t us) { // Priority 1: Use HPET (Highest Precision). if (gHpet && gHpetTicksPerUs > 0) { @@ -187,7 +185,6 @@ static uint32_t CalibrateApicTimerViaHpet(uintptr_t hpetPhys) { return elapsed / 10; // APIC ticks per ms } -// Implements the timer Configure Current Cpu operation. void HalTimerConfigureCurrentProcessor(void) { if (!gLapic || !gApicTicksPerQuantum) return; LAPIC_REG(LAPIC_TIMER_DIV) = TIMER_DIV16; @@ -195,14 +192,12 @@ void HalTimerConfigureCurrentProcessor(void) { LAPIC_REG(LAPIC_TIMER_INIT) = gApicTicksPerQuantum; } -// Implements the timer Initialize operation. KSTATUS HalTimerInitialize(uintptr_t lapicPhys, uintptr_t hpetPhys, HAL_TIMER* out) { gLapic = (volatile uint32_t*)HalPhysicalToVirtual(lapicPhys); HalDbgPrint("HAL: lapicPhys=0x%016llX, lapicVirt=0x%016llX, hpetPhys=0x%016llX\n", lapicPhys, (uintptr_t)gLapic, hpetPhys); uint32_t ticksPerMs = 0; if (hpetPhys) { - HalDbgPrint("HAL: Attempting to calibrate APIC timer via HPET...\n"); ticksPerMs = CalibrateApicTimerViaHpet(hpetPhys); } if (!ticksPerMs) { @@ -210,7 +205,7 @@ KSTATUS HalTimerInitialize(uintptr_t lapicPhys, uintptr_t hpetPhys, HAL_TIMER* o ticksPerMs = CalibrateApicTimerViaPit(); } if (!ticksPerMs) { - HalDbgPrint("HAL: APIC calibration failed. How?\n"); + HalDbgPrint("hal: APIC timer calibration failed\n"); return NTLSTATUS_DEVICE_ERROR; } @@ -226,14 +221,13 @@ KSTATUS HalTimerInitialize(uintptr_t lapicPhys, uintptr_t hpetPhys, HAL_TIMER* o HalDbgPrint("HAL: APIC timer: %u ticks/ms\n", ticksPerMs); - // Leave the BSP timer masked until the kernel registers its scheduler - // callback and IRQ route. APs arm their local timer after per-CPU setup. + // Leave the BSP timer masked until the kernel installs its timer handlers. + // APs arm their local timer after per-CPU setup. out->QueryTicks = HalTimerQueryTicks; out->QueryTickFrequency = QueryTickFrequency; out->Stall = HalTimerStall; out->HandleInterrupt = TimerInterrupt; out->ConfigureCurrentProcessor = HalTimerConfigureCurrentProcessor; - out->IrqNumber = 0; return NTLSTATUS_SUCCESS; } diff --git a/code/kernel/hal/makefile b/code/kernel/hal/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/kernel/hal/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/kernel/hal/sources b/code/kernel/hal/sources new file mode 100644 index 0000000..93aaa85 --- /dev/null +++ b/code/kernel/hal/sources @@ -0,0 +1,11 @@ +TARGETNAME=hal +TARGETPATH=obj +TARGETTYPE=DYNLINK +IMAGE_KIND=DLL +FLAVOR=KERNEL +EXTRA_CFLAGS=/DNTL_HAL_BUILD +TARGETLIBS="$(BASEDIR)\bin\printf.lib" "$(BASEDIR)\bin\libc.lib" +EXTRA_LFLAGS=/NOENTRY /FIXED /DYNAMICBASE:NO /HIGHENTROPYVA:NO /RELEASE /BASE:0xFFFF800010000000 /IGNORE:4216 +INCLUDES=$(BASEDIR)\code\kernel\include +SOURCES=@/code/kernel/hal/hal_apic.c @/code/kernel/hal/hal_disk.c @/code/kernel/hal/hal_keyboard.c @/code/kernel/hal/hal_main.c @/code/kernel/hal/hal_mouse.c @/code/kernel/hal/hal_output.c \ + @/code/kernel/hal/hal_pci.c @/code/kernel/hal/hal_processor.c @/code/kernel/hal/hal_rtc.c @/code/kernel/hal/hal_screen.c @/code/kernel/hal/hal_serial.c @/code/kernel/hal/hal_timer.c diff --git a/code/kernel/include/kernel/dm_config.h b/code/kernel/include/kernel/dm_config.h index b9362a1..55a84fc 100644 --- a/code/kernel/include/kernel/dm_config.h +++ b/code/kernel/include/kernel/dm_config.h @@ -36,6 +36,7 @@ typedef struct DM_EDGES { typedef enum DM_RUN_STATE { DmRunWaiting, + DmRunStarting, DmRunStarted, DmRunFailed, DmRunBlocked, diff --git a/code/kernel/include/kernel/driver_module.h b/code/kernel/include/kernel/driver_module.h index 1a6fbb7..2a9a803 100644 --- a/code/kernel/include/kernel/driver_module.h +++ b/code/kernel/include/kernel/driver_module.h @@ -1,9 +1,12 @@ #pragma once #include +#include #include -KSTATUS DmStartLoadedDriver(const char* name, uintptr_t imageBase); +KSTATUS DmPrepareLoadedDriver(const char* name, uintptr_t imageBase, bool* canReleaseImage); +struct LDR_KERNEL_MODULE; +void DmCommitLoadedDriver(uintptr_t imageBase, struct LDR_KERNEL_MODULE* image); KSTATUS DmPrepareShutdown(void); void DmCommitShutdown(void); diff --git a/code/kernel/include/kernel/hal/hal_api.h b/code/kernel/include/kernel/hal/hal_api.h index 9688f14..88ac297 100644 --- a/code/kernel/include/kernel/hal/hal_api.h +++ b/code/kernel/include/kernel/hal/hal_api.h @@ -132,7 +132,6 @@ typedef struct HAL_TIMER { void (*Stall)(uint32_t us); void (*HandleInterrupt)(void); void (*ConfigureCurrentProcessor)(void); - uint8_t IrqNumber; } HAL_TIMER; #define HAL_RTC_TIME_FLAG_VALID 0x0001u @@ -173,24 +172,27 @@ typedef struct HAL_PCI { } HAL_PCI; typedef struct HAL_INTERRUPT_CONTROLLER { - void (*RouteIrq)(uint8_t irq); - void (*MaskIrq)(uint8_t irq); - void (*UnmaskIrq)(uint8_t irq); + KSTATUS (*RouteGsi)(uint32_t gsi, uint8_t vector, uint32_t hardwareId, + uint16_t flags, bool masked); + KSTATUS (*MaskGsi)(uint32_t gsi, bool masked); + KSTATUS (*ResolveIsa)(uint8_t isaIrq, uint32_t* gsiOut, uint16_t* flagsOut); void (*SendEoi)(void); + // The APIC task priority must follow the kernel's per-CPU IRQL. + void (*SetTaskPriority)(uint8_t priority); + uint8_t (*QueryTaskPriority)(void); + // Queries the current CPU's pending and in-service APIC bits for a vector. + bool (*VectorPending)(uint8_t vector); void (*InitializeCurrentProcessor)(void); void (*SendProcessorInterrupt)(uint32_t hardwareId, uint8_t vector); void (*SendProcessorNmi)(uint32_t hardwareId); void (*BroadcastNmi)(void); - KSTATUS (*ComposeMsi)(uint8_t vector, HAL_MSI_MESSAGE* messageOut); + KSTATUS (*ComposeMsi)(uint32_t hardwareId, uint8_t vector, + HAL_MSI_MESSAGE* messageOut); } HAL_INTERRUPT_CONTROLLER; typedef struct HAL_POWER { - // ACPI fixed-feature button events. Control-method devices require an AML owner. - KSTATUS (*QueryFixedButtonIrq)(uint8_t* irqOut); - KSTATUS (*ArmFixedButton)(void); - bool (*ConsumeFixedButton)(void); - // ACPI S5 soft-off. Disables interrupts, writes SLP_EN to PM1a/b_CNT, - // and halts if firmware doesn't respond. Does not return. + // Basic platform shutdown and reset, available without a firmware driver. + // The HAL halts if its final hardware transition returns. void (*Shutdown)(void); void (*Reset)(void); } HAL_POWER; @@ -231,7 +233,7 @@ typedef struct HAL_INIT_PARAMS { } HAL_INIT_PARAMS; // Increment whenever the kernel/HAL table ABI changes. -#define HAL_API_VERSION 4u +#define HAL_API_VERSION 8u // Returns the HAL table. Processor interrupt-state operations are valid before HalInitialize(). HAL_ENTRY const HAL_API* HalGetApi(void); diff --git a/code/kernel/include/kernel/hal/hal_apic.h b/code/kernel/include/kernel/hal/hal_apic.h index 70b5548..af627f3 100644 --- a/code/kernel/include/kernel/hal/hal_apic.h +++ b/code/kernel/include/kernel/hal/hal_apic.h @@ -6,15 +6,17 @@ #include #include -void HalApicRouteIrq(uint8_t irq); -void HalApicSetGsiBase(uint32_t gsiBase); +KSTATUS HalApicRouteGsi(uint32_t gsi, uint8_t vector, uint32_t hardwareId, + uint16_t flags, bool masked); +KSTATUS HalApicMaskGsi(uint32_t gsi, bool masked); +KSTATUS HalApicResolveIsa(uint8_t irq, uint32_t* gsiOut, uint16_t* flagsOut); +void HalApicAddIoapic(uintptr_t physical, uint32_t gsiBase); void HalApicSetIsaOverride(uint8_t irq, uint32_t gsi, uint16_t flags); -void HalApicSetSciIrq(uint16_t irq); -bool HalApicCanRouteIrq(uint8_t irq); -void HalApicMaskIrq(uint8_t irq); -void HalApicUnmaskIrq(uint8_t irq); void HalApicSendEoi(void); -void HalApicInitialize(uintptr_t lapicPhys, uintptr_t ioapicPhys); +void HalApicSetTaskPriority(uint8_t priority); +uint8_t HalApicQueryTaskPriority(void); +bool HalApicVectorPending(uint8_t vector); +void HalApicInitialize(uintptr_t lapicPhys); uint32_t HalApicGetBootProcessorId(void); uint8_t HalApicUsingX2Apic(void); uint8_t HalApicCanAddressId(uint32_t hardwareId); @@ -23,4 +25,4 @@ void HalApicBroadcastNmi(void); void HalApicSendProcessorInterrupt(uint32_t hardwareId, uint8_t vector); void HalApicSendProcessorNmi(uint32_t hardwareId); KSTATUS HalApicStartProcessor(uint32_t hardwareId, uintptr_t startPhysical); -KSTATUS HalApicComposeMsi(uint8_t vector, HAL_MSI_MESSAGE* messageOut); +KSTATUS HalApicComposeMsi(uint32_t hardwareId, uint8_t vector, HAL_MSI_MESSAGE* messageOut); diff --git a/code/kernel/include/kernel/io_pnp.h b/code/kernel/include/kernel/io_pnp.h index c9848b5..c206cfe 100644 --- a/code/kernel/include/kernel/io_pnp.h +++ b/code/kernel/include/kernel/io_pnp.h @@ -9,9 +9,11 @@ struct NTL_MODULE; struct DRIVER_OBJECT; KSTATUS IoPnpInitialize(void); -KSTATUS IoPnpPublishModule(struct NTL_MODULE* module, +KSTATUS IoPnpPrepareModule(struct NTL_MODULE* module, const NTL_DEVICE_DESC* descriptors, uint32_t count, struct DRIVER_OBJECT* const* ioDrivers, uint32_t ioCount); +void IoPnpCommitModule(struct NTL_MODULE* module); +void IoPnpAbortModule(struct NTL_MODULE* module); KSTATUS IoPnpPhysicalDeviceArrived(struct DEVICE_OBJECT* pdo); void IoPnpPhysicalDevicePublished(struct DEVICE_OBJECT* pdo); void IoPnpPhysicalDeviceRemoved(struct DEVICE_OBJECT* pdo); diff --git a/code/kernel/include/kernel/ke_boot_config.h b/code/kernel/include/kernel/ke_boot_config.h index 684b7a1..17c2379 100644 --- a/code/kernel/include/kernel/ke_boot_config.h +++ b/code/kernel/include/kernel/ke_boot_config.h @@ -6,14 +6,12 @@ #include #include -#define KE_BOOT_COMMAND_LINE_MAX 256u #define KE_BOOT_SYSTEM_VOLUME_MAX 128u typedef struct KE_BOOT_CONFIG { uint32_t Debug; // Opaque system-volume selector interpreted by storage policy, never as a legacy drive slot. char SystemVolume[KE_BOOT_SYSTEM_VOLUME_MAX]; - char CommandLine[KE_BOOT_COMMAND_LINE_MAX]; } KE_BOOT_CONFIG; // Parses the kernel-owned boot.ini settings from the raw bootloader string. diff --git a/code/kernel/include/kernel/ke_firmware.h b/code/kernel/include/kernel/ke_firmware.h new file mode 100644 index 0000000..d824da1 --- /dev/null +++ b/code/kernel/include/kernel/ke_firmware.h @@ -0,0 +1,8 @@ +// Firmware roots retained from the verified bootloader handoff. + +#pragma once + +#include + +void KeFirmwareInitialize(const BOOT_INFO* bootInfo); +void KeFirmwareLog(void); diff --git a/code/kernel/include/kernel/ke_idt.h b/code/kernel/include/kernel/ke_idt.h index 5a4ca92..6663082 100644 --- a/code/kernel/include/kernel/ke_idt.h +++ b/code/kernel/include/kernel/ke_idt.h @@ -51,6 +51,4 @@ extern void KeFaultPF(void); // #PF page fault extern void KeFaultUD(void); // #UD invalid opcode extern void KeNmiIpiStub(void); // returning NMI SMP-control stub -// CPU-local IPI vector. This uses the common interrupt entry machinery but is -// not an external/device IRQ and is never routed through the external interrupt controller. -#define KE_VECTOR_RESCHEDULE_IPI 0xF0u +#include diff --git a/code/kernel/include/kernel/ke_irq.h b/code/kernel/include/kernel/ke_irq.h index 51ca8a1..aa3dd50 100644 --- a/code/kernel/include/kernel/ke_irq.h +++ b/code/kernel/include/kernel/ke_irq.h @@ -1,18 +1,13 @@ -// Kernel ke irq declarations shared by implementation files and kernel clients. - +// Kernel interrupt-manager declarations. #pragma once -#include + +#include #include -#include void KeIrqInitialize(const HAL_API* hal); -__declspec(dllexport) KSTATUS KeIrqAllocateMsiVector(uint8_t* outIrq); -__declspec(dllexport) void KeIrqRegister(uint8_t irq, void (*handler)(void)); -void KeIrqDispatch(uint8_t irq); // called from ke_syscall.asm - -// Low-level interrupt entry/exit hooks. These are called by the common IRQ -// assembly stub around KeIrqDispatch. The exit hook is where deferred -// interrupt-time scheduling now happens, so IRQ handlers never switch away -// before KeIrqDispatch has returned and sent EOI. +void KeIrqRegisterLocalTimerHandler(void (*handler)(void)); +void KeIrqDispatch(uint8_t vector); void KiEnterInterrupt(void); void KiExitInterrupt(void); +// CPU offlining requires the interrupt manager to evacuate every route first. +KSTATUS KiInterruptPrepareCpuOffline(uint32_t cpuIndex); diff --git a/code/kernel/include/kernel/ke_irql.h b/code/kernel/include/kernel/ke_irql.h index ed5c4c2..b55ca29 100644 --- a/code/kernel/include/kernel/ke_irql.h +++ b/code/kernel/include/kernel/ke_irql.h @@ -2,9 +2,7 @@ #pragma once -// ke_irql.h - software IRQL skeleton. -// The level constants are DDK-visible because current synchronization and IRP -// layouts expose KIRQL. Kernel routines remain declared here. +// IRQL levels are DDK-visible; the kernel synchronizes them with APIC TPR. #include #include diff --git a/code/kernel/include/kernel/ke_power.h b/code/kernel/include/kernel/ke_power.h index c49da69..50f1b16 100644 --- a/code/kernel/include/kernel/ke_power.h +++ b/code/kernel/include/kernel/ke_power.h @@ -5,9 +5,10 @@ struct PROCESS; struct EVENT; -struct HAL_API; KSTATUS KePowerInitialize(void); -void KePowerInitializeButton(const struct HAL_API* hal); +void KePowerInitializePolicy(void); +KSTATUS KePowerPrepareFirmware(uint32_t action); +KSTATUS KePowerEnterFirmware(uint32_t action); void KePowerSetInitProcess(struct PROCESS* init); KSTATUS KePowerRequest(uint32_t action); KSTATUS KePowerRequestHardware(uint32_t action); diff --git a/code/kernel/include/kernel/ke_vectors.h b/code/kernel/include/kernel/ke_vectors.h new file mode 100644 index 0000000..b565638 --- /dev/null +++ b/code/kernel/include/kernel/ke_vectors.h @@ -0,0 +1,12 @@ +// x86-64 interrupt-vector assignments shared by the kernel and HAL. + +#pragma once + +// CPU exception gates occupy vectors 0x00 through 0x1f. +// Software gates occupy 0x20 through 0x2f; only the syscall gate is active. +#define KE_VECTOR_SYSCALL 0x2Fu +#define KE_VECTOR_DEVICE_FIRST 0x30u +#define KE_VECTOR_DEVICE_LAST 0xCFu +#define KE_VECTOR_CPU_TIMER 0xE0u +#define KE_VECTOR_RESCHEDULE_IPI 0xF0u +#define KE_VECTOR_SPURIOUS 0xFFu diff --git a/code/kernel/include/kernel/ldr_image.h b/code/kernel/include/kernel/ldr_image.h index 6bbebe9..cf5130a 100644 --- a/code/kernel/include/kernel/ldr_image.h +++ b/code/kernel/include/kernel/ldr_image.h @@ -42,6 +42,9 @@ KSTATUS LdrProtectImageForProcess(struct PROCESS* process, uintptr_t imageBase, // Called by KernelMain to register the fixed kernel/HAL bootstrap images so LdrGetExport can find them. struct BOOT_INFO; // forward declaration KSTATUS LdrRegisterModulesFromBootInfo(const struct BOOT_INFO* bootInfo); -KSTATUS LdrRegisterModule(const char* name, uintptr_t base); -KSTATUS LdrSetModuleExportsAvailable(const char* name, bool available); +typedef struct LDR_KERNEL_MODULE LDR_KERNEL_MODULE; +KSTATUS LdrRegisterModule(const char* name, uintptr_t base, LDR_KERNEL_MODULE** out); +void LdrPublishModule(LDR_KERNEL_MODULE* module); +void LdrDiscardModule(LDR_KERNEL_MODULE* module); +void LdrReleaseKernelImage(uintptr_t imageBase); const char* LdrFindKernelModuleByAddress(uintptr_t address, uintptr_t* baseOut, size_t* sizeOut); diff --git a/code/kernel/include/kernel/syscall_nr.h b/code/kernel/include/kernel/syscall_nr.h index 4585e23..fa4ef6d 100644 --- a/code/kernel/include/kernel/syscall_nr.h +++ b/code/kernel/include/kernel/syscall_nr.h @@ -2,7 +2,7 @@ #pragma once -// INT 0x40 calling convention, MS x64. +// INT 0x2F calling convention, MS x64. // RAX selects the syscall number. RCX, RDX, R8, and R9 carry args 0-3. // Syscalls use at most four register arguments; larger operations use request structures. // RAX carries the return value. diff --git a/code/kernel/io_ddk.c b/code/kernel/io_ddk.c index 33f7667..13aa54a 100644 --- a/code/kernel/io_ddk.c +++ b/code/kernel/io_ddk.c @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include #include static const HAL_API* gHal; @@ -14,6 +17,10 @@ void IoInitializeDdk(const HAL_API* hal, uintptr_t physicalWindowBase) { gPhysicalWindowBase = physicalWindowBase; } +__declspec(dllexport) uintptr_t KeCurrentThreadIdentity(void) { + return (uintptr_t)KeGetCurrentThread(); +} + __declspec(dllexport) uint64_t KeQueryTicks(void) { return gHal && gHal->Timer.QueryTicks ? gHal->Timer.QueryTicks() : 0; } @@ -30,18 +37,6 @@ __declspec(dllexport) void KePciWriteConfig32(uint16_t segment, uint8_t bus, uin if (gHal && gHal->Pci.Write32) gHal->Pci.Write32(segment, bus, device, function, offset, value); } -__declspec(dllexport) KSTATUS KeIrqComposeMsiMessage(uint8_t irq, NTL_DDK_MSI_MESSAGE* out) { - if (!gHal || !out || irq >= 24u || !gHal->InterruptController.ComposeMsi) - return NTLSTATUS_INVALID_PARAMETER; - HAL_MSI_MESSAGE message; - KSTATUS status = gHal->InterruptController.ComposeMsi((uint8_t)(0x20u + irq), &message); - if (!KSUCCESS(status)) return status; - out->Address = message.Address; - out->Data = message.Data; - out->Reserved = 0; - return NTLSTATUS_SUCCESS; -} - __declspec(dllexport) void* MmDdkPhysToVirt(uint64_t physicalAddress) { if (!gPhysicalWindowBase || physicalAddress > UINTPTR_MAX - gPhysicalWindowBase) return (void*)0; @@ -53,6 +48,118 @@ __declspec(dllexport) KSTATUS MmDdkMapPage(uintptr_t virtualAddress, uint64_t ph mode == NtlDdkMapReplaceExisting ? MmPteMapReplaceExisting : MmPteMapFailIfPresent); } +// Each slot is a recyclable 2 MiB VA reservation; no pool allocation is needed +// when reserving a device mapping. This aperture stays separate from PCI BARs. +#define DDK_IO_VA_BASE 0xFFFF980000000000ULL +#define DDK_IO_SLOT_SIZE (2ULL * 1024ULL * 1024ULL) +#define DDK_IO_SLOT_COUNT 256u + +typedef struct DDK_IO_MAPPING { + uint8_t State; + uint32_t Pages; + uintptr_t Offset; + size_t Length; +} DDK_IO_MAPPING; + +static SPINLOCK gDdkIoMapLock = SPINLOCK_INIT; +static DDK_IO_MAPPING gDdkIoMaps[DDK_IO_SLOT_COUNT]; + +// The caller owns the mapping until an exact-length unmap completes. +__declspec(dllexport) KSTATUS MmDdkMapIoMemory(uint64_t physicalAddress, size_t length, void** outVirtual) { + if (!outVirtual) return NTLSTATUS_INVALID_PARAMETER; + *outVirtual = NULL; + if (!KeCanWait()) return NTLSTATUS_NOT_SUPPORTED; + if (!length || physicalAddress > UINT64_MAX - length) return NTLSTATUS_INVALID_PARAMETER; + uintptr_t offset = (uintptr_t)(physicalAddress & (PAGE_SIZE - 1u)); + if (length > DDK_IO_SLOT_SIZE - offset) return NTLSTATUS_INVALID_PARAMETER; + uint32_t pages = (uint32_t)((offset + length + PAGE_SIZE - 1u) / PAGE_SIZE); + if (pages == 0 || pages > DDK_IO_SLOT_SIZE / PAGE_SIZE) return NTLSTATUS_INVALID_PARAMETER; + + // Reject a UC alias of RAM already covered by the firmware's WB/WC + // direct map. Real device registers have no direct mapping or an UC one. + for (uint32_t i = 0; i < pages; i++) { + uint64_t frame = (physicalAddress - offset) + (uint64_t)i * PAGE_SIZE; + if (gPhysicalWindowBase && frame <= UINTPTR_MAX - gPhysicalWindowBase) { + PHYSICAL_ADDRESS existing = 0; + uint64_t existingFlags = 0; + if (KSUCCESS(MmPteQueryPage(gPhysicalWindowBase + (uintptr_t)frame, + &existing, &existingFlags))) { + if ((existing & PAGE_MASK) != frame || + (existingFlags & PAGE_CACHE_MASK) != PAGE_CACHE_UC) + return NTLSTATUS_NOT_SUPPORTED; + } + } + } + + uintptr_t flags = KeAcquireSpinlock(&gDdkIoMapLock); + uint32_t slot; + for (slot = 0; slot < DDK_IO_SLOT_COUNT; slot++) { + if (!gDdkIoMaps[slot].State) { + gDdkIoMaps[slot].State = 1; + gDdkIoMaps[slot].Length = length; + gDdkIoMaps[slot].Offset = offset; + gDdkIoMaps[slot].Pages = pages; + break; + } + } + KeReleaseSpinlock(&gDdkIoMapLock, flags); + if (slot == DDK_IO_SLOT_COUNT) return NTLSTATUS_NO_MEMORY; + + uintptr_t base = (uintptr_t)(DDK_IO_VA_BASE + (uint64_t)slot * DDK_IO_SLOT_SIZE); + uint64_t physBase = physicalAddress - offset; + uint32_t mapped = 0; + KSTATUS status = NTLSTATUS_SUCCESS; + for (; mapped < pages; mapped++) { + status = MmPteMapPage(base + (uintptr_t)mapped * PAGE_SIZE, + physBase + (uint64_t)mapped * PAGE_SIZE, + PAGE_PRESENT | PAGE_WRITE | PAGE_CACHE_UC | PAGE_NX, + MmPteMapFailIfPresent); + if (!KSUCCESS(status)) break; + } + if (mapped != pages) { + while (mapped) (void)MmPteUnmapPage(base + (uintptr_t)(--mapped) * PAGE_SIZE); + flags = KeAcquireSpinlock(&gDdkIoMapLock); + gDdkIoMaps[slot].State = 0; + KeReleaseSpinlock(&gDdkIoMapLock, flags); + return status; + } + flags = KeAcquireSpinlock(&gDdkIoMapLock); + gDdkIoMaps[slot].State = 2; + KeReleaseSpinlock(&gDdkIoMapLock, flags); + *outVirtual = (void*)(base + offset); + return NTLSTATUS_SUCCESS; +} + +__declspec(dllexport) KSTATUS MmDdkUnmapIoMemory(void* virtualAddress, size_t length) { + if (!KeCanWait()) return NTLSTATUS_NOT_SUPPORTED; + if (!virtualAddress || !length) return NTLSTATUS_INVALID_PARAMETER; + uintptr_t address = (uintptr_t)virtualAddress; + if (address < DDK_IO_VA_BASE || + (uint64_t)(address - DDK_IO_VA_BASE) >= DDK_IO_SLOT_SIZE * DDK_IO_SLOT_COUNT) + return NTLSTATUS_INVALID_PARAMETER; + uint32_t slot = (uint32_t)((address - DDK_IO_VA_BASE) / DDK_IO_SLOT_SIZE); + uintptr_t base = (uintptr_t)(DDK_IO_VA_BASE + (uint64_t)slot * DDK_IO_SLOT_SIZE); + uintptr_t flags = KeAcquireSpinlock(&gDdkIoMapLock); + DDK_IO_MAPPING* map = &gDdkIoMaps[slot]; + if (map->State != 2 || map->Length != length || address != base + map->Offset) { + KeReleaseSpinlock(&gDdkIoMapLock, flags); + return NTLSTATUS_INVALID_PARAMETER; + } + map->State = 3; + uint32_t pages = map->Pages; + KeReleaseSpinlock(&gDdkIoMapLock, flags); + KSTATUS result = NTLSTATUS_SUCCESS; + for (uint32_t i = 0; i < pages; i++) { + KSTATUS status = MmPteUnmapPage(base + (uintptr_t)i * PAGE_SIZE); + if (!KSUCCESS(status)) result = status; + } + flags = KeAcquireSpinlock(&gDdkIoMapLock); + // Preserve the slot after a failed unmap to prevent stale PTE reuse. + if (KSUCCESS(result)) map->State = 0; + KeReleaseSpinlock(&gDdkIoMapLock, flags); + return result; +} + __declspec(dllexport) KSTATUS IoDmaGetAdapter(struct DEVICE_OBJECT* device, const IO_DMA_REQUIREMENTS* requirements, IO_DMA_ADAPTER** outAdapter) { return IoGetDmaDdk()->GetAdapter(device, requirements, outAdapter); } diff --git a/code/kernel/io_device.c b/code/kernel/io_device.c index 08e9d3f..18f2379 100644 --- a/code/kernel/io_device.c +++ b/code/kernel/io_device.c @@ -159,12 +159,10 @@ __declspec(dllexport) KSTATUS IoSetDeviceName(DEVICE_OBJECT* device, return NTLSTATUS_SUCCESS; } -// Implements the reference Device Object operation. __declspec(dllexport) void IoReferenceDeviceObject(DEVICE_OBJECT* device) { if (device) ObReferenceObject(&device->Header); } -// Implements the dereference Device Object operation. __declspec(dllexport) void IoDereferenceDeviceObject(DEVICE_OBJECT* device) { if (device) ObDereferenceObject(&device->Header); } @@ -228,7 +226,6 @@ __declspec(dllexport) DEVICE_OBJECT* IoAttachDeviceToDeviceStack(DEVICE_OBJECT* return top; } -// Implements the detach Device operation. __declspec(dllexport) void IoDetachDevice(DEVICE_OBJECT* source) { if (!source || !source->LowerDevice) return; @@ -258,7 +255,6 @@ __declspec(dllexport) uint8_t IoGetDeviceStackSize(DEVICE_OBJECT* device) { return count ? count : 1; } -// Implements the forward Irp To Lower operation. __declspec(dllexport) KSTATUS IoForwardIrpToLower(DEVICE_OBJECT* device, IRP* irp) { if (!device || !irp || !device->LowerDevice) return NTLSTATUS_NOT_SUPPORTED; @@ -373,7 +369,6 @@ static void IoDiskStatsNoteWrite(uint8_t driveIndex, uint32_t count) { KeReleaseSpinlock(&state->Lock, flags); } -// Implements the notify Disk Change operation. static void IoNotifyDiskChange(uint8_t driveIndex, DEVICE_OBJECT* device, IO_DEVICE_CHANGE change) { for (uint32_t i = 0; i < gDiskChangeCallbackCount; i++) { IO_DISK_CHANGE_CALLBACK_ENTRY* entry = &gDiskChangeCallbacks[i]; @@ -429,7 +424,7 @@ __declspec(dllexport) KSTATUS IoRegisterDiskDevice(uint8_t driveIndex, return NTLSTATUS_SUCCESS; } -// Implements the notify Disk Surprise Removed operation. +// Invalidates mounted partitions when a disk disappears unexpectedly. __declspec(dllexport) KSTATUS IoNotifyDiskSurpriseRemoved(uint8_t driveIndex) { if (driveIndex >= MAX_DISK_DEVICES) return NTLSTATUS_INVALID_PARAMETER; @@ -442,29 +437,32 @@ __declspec(dllexport) KSTATUS IoNotifyDiskSurpriseRemoved(uint8_t driveIndex) { return NTLSTATUS_SUCCESS; } -// Implements the unregister Disk Device operation. +// Releases volume consumers before the backing device completes orderly teardown. __declspec(dllexport) KSTATUS IoUnregisterDiskDevice(uint8_t driveIndex) { if (driveIndex >= MAX_DISK_DEVICES) return NTLSTATUS_INVALID_PARAMETER; DEVICE_OBJECT* dev = gDiskDevices[driveIndex]; if (!dev) return NTLSTATUS_NOT_FOUND; - if (dev->PnpState != DevicePnpSurpriseRemoved) { + bool surpriseRemoved = dev->PnpState == DevicePnpSurpriseRemoved; + if (!surpriseRemoved) { IoNotifyDiskChange(driveIndex, dev, IoDeviceQueryRemove); KSTATUS queryStatus = IoSendPnpIrpSync(dev, IRP_MN_QUERY_REMOVE_DEVICE); - if (!KSUCCESS(queryStatus) && queryStatus != NTLSTATUS_NOT_SUPPORTED) + if (!KSUCCESS(queryStatus) && queryStatus != NTLSTATUS_NOT_SUPPORTED) { + (void)IoSendPnpIrpSync(dev, IRP_MN_CANCEL_REMOVE_DEVICE); return queryStatus; + } - dev->PnpState = DevicePnpSurpriseRemoved; - IoNotifyDiskChange(driveIndex, dev, IoDeviceSurpriseRemoved); - (void)IoSendPnpIrpSync(dev, IRP_MN_SURPRISE_REMOVAL); + // Notify volume owners while the backing disk can still service teardown I/O. + IoNotifyDiskChange(driveIndex, dev, IoDeviceRemoved); } dev->PnpState = DevicePnpRemovePending; (void)IoSendPnpIrpSync(dev, IRP_MN_REMOVE_DEVICE); gDiskDevices[driveIndex] = (DEVICE_OBJECT*)0; - IoNotifyDiskChange(driveIndex, dev, IoDeviceRemoved); + if (surpriseRemoved) + IoNotifyDiskChange(driveIndex, dev, IoDeviceRemoved); IoDereferenceDeviceObject(dev); return NTLSTATUS_SUCCESS; } @@ -526,19 +524,16 @@ __declspec(dllexport) DEVICE_OBJECT* IoGetDiskDevice(uint8_t driveIndex) { return gDiskDevices[driveIndex]; } -// Implements the reference Disk Device operation. __declspec(dllexport) DEVICE_OBJECT* IoReferenceDiskDevice(uint8_t driveIndex) { DEVICE_OBJECT* dev = IoGetDiskDevice(driveIndex); if (dev) IoReferenceDeviceObject(dev); return dev; } -// Implements the disk Device Present operation. __declspec(dllexport) bool IoDiskDevicePresent(uint8_t driveIndex) { return IoGetDiskDevice(driveIndex) != (DEVICE_OBJECT*)0; } -// Implements the disk Sector Count operation. __declspec(dllexport) uint64_t IoDiskSectorCount(uint8_t driveIndex) { DEVICE_OBJECT* dev = IoGetDiskDevice(driveIndex); return dev ? dev->u.Disk.SectorCount : 0; diff --git a/code/kernel/io_file.c b/code/kernel/io_file.c index bd57314..1f0c91b 100644 --- a/code/kernel/io_file.c +++ b/code/kernel/io_file.c @@ -254,7 +254,6 @@ static KSTATUS KiIoCancelAsyncFileRequest(IO_ASYNC_REQUEST_OBJECT* async, void* return NTLSTATUS_OBJECT_DEAD; } -// Implements the io Async File Dequeue operation. static IO_ASYNC_FILE_REQUEST_OBJECT* KiIoAsyncFileDequeue(void) { uintptr_t flags = KeAcquireSpinlock(&gAsyncFileQueueLock); LIST_ENTRY* node = ListPopHead(&gAsyncFileQueue); @@ -275,7 +274,6 @@ static IO_ASYNC_FILE_REQUEST_OBJECT* KiIoAsyncFileDequeue(void) { return req; } -// Implements the io Async File Worker operation. static void KiIoAsyncFileWorker(void* arg) { (void)arg; @@ -317,7 +315,6 @@ static void KiIoAsyncFileWorker(void* arg) { } } -// Implements the io Ensure Async File Io Started operation. static KSTATUS KiIoEnsureAsyncFileIoStarted(void) { uintptr_t flags = KeAcquireSpinlock(&gAsyncFileInitLock); if (gAsyncFileInitState == 2) { @@ -517,7 +514,6 @@ __declspec(dllexport) KSTATUS IoWriteFileAsyncKernel(FILE_OBJECT* file, const vo lockedBuffer, lockedIosb, requestOut); } -// Implements the async File Request Object operation. __declspec(dllexport) OBJECT* IoAsyncFileRequestObject(IO_ASYNC_FILE_REQUEST_OBJECT* req) { return req ? &req->Async.Header : (OBJECT*)0; } diff --git a/code/kernel/io_pnp.c b/code/kernel/io_pnp.c index 02b85af..24a47bf 100644 --- a/code/kernel/io_pnp.c +++ b/code/kernel/io_pnp.c @@ -12,8 +12,6 @@ #include #include -#define PNP_MAX_DESCRIPTORS 64u -#define PNP_MAX_DEVICES 128u #define PNP_WORKERS 2u typedef enum PNP_BIND_STATE { @@ -29,12 +27,15 @@ typedef enum PNP_BIND_STATE { } PNP_BIND_STATE; typedef struct PNP_DRIVER { + struct PNP_DRIVER* Next; const NTL_DEVICE_DESC* Descriptor; DRIVER_OBJECT* IoDriver; struct NTL_MODULE* Module; + bool Committed; } PNP_DRIVER; typedef struct PNP_NODE { + struct PNP_NODE* Next; DEVICE_OBJECT* Pdo; DEVICE_OBJECT* ParentPdo; NTL_DEVICE* Binding; @@ -63,10 +64,11 @@ struct NTL_DEVICE { }; static SPINLOCK gPnpLock = SPINLOCK_INIT; -static PNP_DRIVER gPnpDrivers[PNP_MAX_DESCRIPTORS]; -static uint32_t gPnpDriverCount; -static PNP_NODE* gPnpNodes[PNP_MAX_DEVICES]; -static uint32_t gPnpNodeCount; +static PNP_DRIVER* gPnpDrivers; +static PNP_DRIVER* gPnpDriversTail; +static PNP_NODE* gPnpNodes; +static PNP_NODE* gPnpNodesTail; +static size_t gPnpNodeCount; static EVENT* gPnpReady; static EVENT* gPnpChanged; static bool gPnpStarted; @@ -113,18 +115,19 @@ static bool IoPnpMatchesIoDriver(const DRIVER_OBJECT* driver, const DEVICE_OBJEC } static const PNP_DRIVER* IoPnpFindDriver(const DEVICE_OBJECT* pdo) { - for (uint32_t i = 0; i < gPnpDriverCount; ++i) { - if ((gPnpDrivers[i].Descriptor && IoPnpMatches(gPnpDrivers[i].Descriptor, pdo)) || - (gPnpDrivers[i].IoDriver && IoPnpMatchesIoDriver(gPnpDrivers[i].IoDriver, pdo))) - return &gPnpDrivers[i]; + for (PNP_DRIVER* driver = gPnpDrivers; driver; driver = driver->Next) { + if (!driver->Committed) continue; + if ((driver->Descriptor && IoPnpMatches(driver->Descriptor, pdo)) || + (driver->IoDriver && IoPnpMatchesIoDriver(driver->IoDriver, pdo))) + return driver; } return (const PNP_DRIVER*)0; } static PNP_NODE* IoPnpFindNode(const DEVICE_OBJECT* pdo) { - for (uint32_t i = 0; i < gPnpNodeCount; ++i) - if (gPnpNodes[i]->Pdo == pdo) - return gPnpNodes[i]; + for (PNP_NODE* node = gPnpNodes; node; node = node->Next) + if (node->Pdo == pdo) + return node; return (PNP_NODE*)0; } @@ -139,9 +142,9 @@ static DEVICE_OBJECT* IoPnpParentPdo(const DEVICE_OBJECT* pdo) { } static bool IoPnpHasChildren(const DEVICE_OBJECT* parent) { - for (uint32_t i = 0; i < gPnpNodeCount; ++i) { - const DEVICE_OBJECT* ancestor = gPnpNodes[i]->ParentPdo; - for (uint32_t depth = 0; ancestor && depth < PNP_MAX_DEVICES; ++depth) { + for (PNP_NODE* candidate = gPnpNodes; candidate; candidate = candidate->Next) { + const DEVICE_OBJECT* ancestor = candidate->ParentPdo; + for (size_t depth = 0; ancestor && depth < gPnpNodeCount; ++depth) { if (ancestor == parent) return true; const PNP_NODE* node = IoPnpFindNode(ancestor); ancestor = node ? node->ParentPdo : (const DEVICE_OBJECT*)0; @@ -180,12 +183,15 @@ static void IoPnpDispose(PNP_NODE* node) { } uintptr_t flags = KeAcquireSpinlock(&gPnpLock); - for (uint32_t i = 0; i < gPnpNodeCount; ++i) { - if (gPnpNodes[i] == node) { - gPnpNodes[i] = gPnpNodes[--gPnpNodeCount]; - gPnpNodes[gPnpNodeCount] = (PNP_NODE*)0; - break; + PNP_NODE** link = &gPnpNodes; + while (*link && *link != node) link = &(*link)->Next; + if (*link) { + *link = node->Next; + if (gPnpNodesTail == node) { + gPnpNodesTail = (PNP_NODE*)0; + for (PNP_NODE* it = gPnpNodes; it; it = it->Next) gPnpNodesTail = it; } + --gPnpNodeCount; } KeReleaseSpinlock(&gPnpLock, flags); IoDereferenceDeviceObject(node->Pdo); @@ -247,8 +253,7 @@ static void IoPnpWorker(void* ignored) { bool cleanup = false; bool cancel = false; uintptr_t flags = KeAcquireSpinlock(&gPnpLock); - for (uint32_t i = 0; i < gPnpNodeCount; ++i) { - PNP_NODE* candidate = gPnpNodes[i]; + for (PNP_NODE* candidate = gPnpNodes; candidate; candidate = candidate->Next) { if (candidate->State == PnpPending && candidate->Removed && !candidate->CancelIssued && (candidate->Driver->Descriptor && candidate->Driver->Descriptor->CancelStart)) { candidate->CancelIssued = true; @@ -338,82 +343,105 @@ KSTATUS IoPnpInitialize(void) { return NTLSTATUS_SUCCESS; } -KSTATUS IoPnpPublishModule(struct NTL_MODULE* module, +// Reserve declarative and DRIVER_OBJECT names in one namespace. +KSTATUS IoPnpPrepareModule(struct NTL_MODULE* module, const NTL_DEVICE_DESC* descriptors, uint32_t count, DRIVER_OBJECT* const* ioDrivers, uint32_t ioCount) { if (!gPnpStarted || !module || (count && !descriptors) || (ioCount && !ioDrivers)) return NTLSTATUS_INVALID_PARAMETER; + if (count > UINT32_MAX - ioCount) return NTLSTATUS_INVALID_PARAMETER; + + PNP_DRIVER* first = (PNP_DRIVER*)0; + PNP_DRIVER* last = (PNP_DRIVER*)0; + for (uint32_t i = 0; i < count + ioCount; ++i) { + PNP_DRIVER* driver = (PNP_DRIVER*)MmAllocatePool(sizeof(*driver)); + if (!driver) { + while (first) { + PNP_DRIVER* next = first->Next; + MmFreePool(first); + first = next; + } + return NTLSTATUS_NO_MEMORY; + } + memset(driver, 0, sizeof(*driver)); + driver->Module = module; + if (i < count) driver->Descriptor = &descriptors[i]; + else driver->IoDriver = ioDrivers[i - count]; + if (last) last->Next = driver; + else first = driver; + last = driver; + } + + KSTATUS status = NTLSTATUS_SUCCESS; uintptr_t flags = KeAcquireSpinlock(&gPnpLock); - if (gPnpShutdown) { - KeReleaseSpinlock(&gPnpLock, flags); - return NTLSTATUS_DEVICE_REMOVED; - } - if (count > PNP_MAX_DESCRIPTORS - gPnpDriverCount || - ioCount > PNP_MAX_DESCRIPTORS - gPnpDriverCount - count) { - KeReleaseSpinlock(&gPnpLock, flags); - return NTLSTATUS_NO_MEMORY; - } - for (uint32_t i = 0; i < count; ++i) { - for (uint32_t j = 0; j < gPnpDriverCount; ++j) { - SYS_STRING_VIEW existing = gPnpDrivers[j].IoDriver ? - gPnpDrivers[j].IoDriver->Name : - SysSvFromParts(gPnpDrivers[j].Descriptor->Name, - strlen(gPnpDrivers[j].Descriptor->Name)); - SYS_STRING_VIEW incoming = SysSvFromParts(descriptors[i].Name, - strlen(descriptors[i].Name)); - if (SysSvEqual(existing, incoming)) { - KeReleaseSpinlock(&gPnpLock, flags); - return NTLSTATUS_ALREADY_EXISTS; + if (gPnpShutdown) status = NTLSTATUS_DEVICE_REMOVED; + for (PNP_DRIVER* proposed = first; KSUCCESS(status) && proposed; + proposed = proposed->Next) { + SYS_STRING_VIEW name = proposed->IoDriver ? proposed->IoDriver->Name : + SysSvFromCstr(proposed->Descriptor->Name); + for (PNP_DRIVER* existing = gPnpDrivers; existing; existing = existing->Next) { + SYS_STRING_VIEW oldName = existing->IoDriver ? existing->IoDriver->Name : + SysSvFromCstr(existing->Descriptor->Name); + if (SysSvEqual(name, oldName)) { + status = NTLSTATUS_ALREADY_EXISTS; + break; } } - for (uint32_t j = i + 1; j < count; ++j) { - if (!strcmp(descriptors[i].Name, descriptors[j].Name)) { - KeReleaseSpinlock(&gPnpLock, flags); - return NTLSTATUS_ALREADY_EXISTS; - } + for (PNP_DRIVER* other = proposed->Next; KSUCCESS(status) && other; + other = other->Next) { + SYS_STRING_VIEW otherName = other->IoDriver ? other->IoDriver->Name : + SysSvFromCstr(other->Descriptor->Name); + if (SysSvEqual(name, otherName)) status = NTLSTATUS_ALREADY_EXISTS; } } - for (uint32_t i = 0; i < ioCount; ++i) { - DRIVER_OBJECT* driver = ioDrivers[i]; - for (uint32_t j = 0; j < gPnpDriverCount; ++j) { - SYS_STRING_VIEW existing = gPnpDrivers[j].IoDriver ? - gPnpDrivers[j].IoDriver->Name : - SysSvFromParts(gPnpDrivers[j].Descriptor->Name, - strlen(gPnpDrivers[j].Descriptor->Name)); - if (SysSvEqual(driver->Name, existing)) { - KeReleaseSpinlock(&gPnpLock, flags); - return NTLSTATUS_ALREADY_EXISTS; - } - } - for (uint32_t j = i + 1; j < ioCount; ++j) { - if (SysSvEqual(driver->Name, ioDrivers[j]->Name)) { - KeReleaseSpinlock(&gPnpLock, flags); - return NTLSTATUS_ALREADY_EXISTS; - } - } - for (uint32_t j = 0; j < count; ++j) { - if (SysSvEqual(driver->Name, SysSvFromParts(descriptors[j].Name, - strlen(descriptors[j].Name)))) { - KeReleaseSpinlock(&gPnpLock, flags); - return NTLSTATUS_ALREADY_EXISTS; - } - } - } - for (uint32_t i = 0; i < count; ++i) { - gPnpDrivers[gPnpDriverCount].Descriptor = &descriptors[i]; - gPnpDrivers[gPnpDriverCount].IoDriver = (DRIVER_OBJECT*)0; - gPnpDrivers[gPnpDriverCount].Module = module; - ++gPnpDriverCount; - } - for (uint32_t i = 0; i < ioCount; ++i) { - gPnpDrivers[gPnpDriverCount].Descriptor = (const NTL_DEVICE_DESC*)0; - gPnpDrivers[gPnpDriverCount].IoDriver = ioDrivers[i]; - gPnpDrivers[gPnpDriverCount].Module = module; - ++gPnpDriverCount; + if (KSUCCESS(status) && first) { + if (gPnpDriversTail) gPnpDriversTail->Next = first; + else gPnpDrivers = first; + gPnpDriversTail = last; } KeReleaseSpinlock(&gPnpLock, flags); + if (!KSUCCESS(status)) { + while (first) { + PNP_DRIVER* next = first->Next; + MmFreePool(first); + first = next; + } + } + return status; +} + +// Reserved registrations become eligible for binding without allocation. +void IoPnpCommitModule(struct NTL_MODULE* module) { + uintptr_t flags = KeAcquireSpinlock(&gPnpLock); + for (PNP_DRIVER* driver = gPnpDrivers; driver; driver = driver->Next) + if (driver->Module == module) driver->Committed = true; + KeReleaseSpinlock(&gPnpLock, flags); IoPnpWake(); - return NTLSTATUS_SUCCESS; +} + +// Abort releases reservations before any binding can reference them. +void IoPnpAbortModule(struct NTL_MODULE* module) { + PNP_DRIVER* removed = (PNP_DRIVER*)0; + uintptr_t flags = KeAcquireSpinlock(&gPnpLock); + PNP_DRIVER** link = &gPnpDrivers; + while (*link) { + PNP_DRIVER* driver = *link; + if (driver->Module != module || driver->Committed) { + link = &driver->Next; + continue; + } + *link = driver->Next; + driver->Next = removed; + removed = driver; + } + gPnpDriversTail = (PNP_DRIVER*)0; + for (PNP_DRIVER* it = gPnpDrivers; it; it = it->Next) gPnpDriversTail = it; + KeReleaseSpinlock(&gPnpLock, flags); + while (removed) { + PNP_DRIVER* next = removed->Next; + MmFreePool(removed); + removed = next; + } } KSTATUS IoPnpPhysicalDeviceArrived(DEVICE_OBJECT* pdo) { @@ -432,21 +460,16 @@ KSTATUS IoPnpPhysicalDeviceArrived(DEVICE_OBJECT* pdo) { MmFreePool(node); return NTLSTATUS_DEVICE_REMOVED; } - for (uint32_t i = 0; i < gPnpNodeCount; ++i) { - if (gPnpNodes[i]->Pdo == pdo) { - KeReleaseSpinlock(&gPnpLock, flags); - IoDereferenceDeviceObject(pdo); - MmFreePool(node); - return NTLSTATUS_ALREADY_EXISTS; - } - } - if (gPnpNodeCount == PNP_MAX_DEVICES) { + if (IoPnpFindNode(pdo)) { KeReleaseSpinlock(&gPnpLock, flags); IoDereferenceDeviceObject(pdo); MmFreePool(node); - return NTLSTATUS_NO_MEMORY; + return NTLSTATUS_ALREADY_EXISTS; } - gPnpNodes[gPnpNodeCount++] = node; + if (gPnpNodesTail) gPnpNodesTail->Next = node; + else gPnpNodes = node; + gPnpNodesTail = node; + ++gPnpNodeCount; KeReleaseSpinlock(&gPnpLock, flags); return NTLSTATUS_SUCCESS; } @@ -454,12 +477,8 @@ KSTATUS IoPnpPhysicalDeviceArrived(DEVICE_OBJECT* pdo) { void IoPnpPhysicalDevicePublished(DEVICE_OBJECT* pdo) { if (!pdo || !gPnpStarted) return; uintptr_t flags = KeAcquireSpinlock(&gPnpLock); - for (uint32_t i = 0; i < gPnpNodeCount; ++i) { - if (gPnpNodes[i]->Pdo == pdo) { - gPnpNodes[i]->Published = true; - break; - } - } + PNP_NODE* node = IoPnpFindNode(pdo); + if (node) node->Published = true; KeReleaseSpinlock(&gPnpLock, flags); IoPnpWake(); } @@ -467,12 +486,8 @@ void IoPnpPhysicalDevicePublished(DEVICE_OBJECT* pdo) { void IoPnpPhysicalDeviceRemoved(DEVICE_OBJECT* pdo) { if (!pdo || !gPnpStarted) return; uintptr_t flags = KeAcquireSpinlock(&gPnpLock); - for (uint32_t i = 0; i < gPnpNodeCount; ++i) { - if (gPnpNodes[i]->Pdo == pdo) { - gPnpNodes[i]->Removed = true; - break; - } - } + PNP_NODE* node = IoPnpFindNode(pdo); + if (node) node->Removed = true; KeReleaseSpinlock(&gPnpLock, flags); IoPnpWake(); } @@ -483,8 +498,7 @@ KSTATUS IoPnpWaitForIdle(uint64_t timeoutMs) { for (;;) { bool idle = true; uintptr_t flags = KeAcquireSpinlock(&gPnpLock); - for (uint32_t i = 0; i < gPnpNodeCount; ++i) { - PNP_NODE* node = gPnpNodes[i]; + for (PNP_NODE* node = gPnpNodes; node; node = node->Next) { if (node->State == PnpReserved || node->State == PnpStarting || node->State == PnpPending || node->State == PnpCancelling || node->State == PnpCleaning || @@ -512,8 +526,8 @@ KSTATUS IoPnpShutdown(uint64_t timeoutMs) { if (!gPnpStarted) return NTLSTATUS_INVALID_PARAMETER; uintptr_t flags = KeAcquireSpinlock(&gPnpLock); gPnpShutdown = true; - for (uint32_t i = 0; i < gPnpNodeCount; ++i) - gPnpNodes[i]->Removed = true; + for (PNP_NODE* node = gPnpNodes; node; node = node->Next) + node->Removed = true; KeReleaseSpinlock(&gPnpLock, flags); IoPnpWake(); return IoPnpWaitForIdle(timeoutMs); diff --git a/code/kernel/io_volume.c b/code/kernel/io_volume.c index 9cc9e4d..af11926 100644 --- a/code/kernel/io_volume.c +++ b/code/kernel/io_volume.c @@ -379,7 +379,9 @@ __declspec(dllexport) KSTATUS IoRemoveVolume(IO_VOLUME* volume, IO_VOLUME_REMOVA KiIoVolumeAddStat(&gVolumeStats.MountedVolumes, -1); KiIoVolumeAddStat(&gVolumeStats.RemovedVolumes, 1); KiIoNotifyVolumeChange(); - DbgPrint("io: volume %u removed reason=%u\n", volume->InstanceId, (unsigned)reason); + const char* reasonName = reason == IoVolumeUnmounted ? "unmounted" : + reason == IoVolumeBackingRemoved ? "backing-removed" : "provider-dead"; + DbgPrint("io: volume %u removed reason=%s\n", volume->InstanceId, reasonName); if (dropRegistryReference) ObDereferenceObject(&volume->Header); return NTLSTATUS_SUCCESS; diff --git a/code/kernel/ke_apc.c b/code/kernel/ke_apc.c index e7bd74d..d75c50e 100644 --- a/code/kernel/ke_apc.c +++ b/code/kernel/ke_apc.c @@ -144,7 +144,6 @@ __declspec(dllexport) bool KeInsertQueueApc(KAPC* apc, return true; } -// Implements the enter Critical Region operation. __declspec(dllexport) void KeEnterCriticalRegion(void) { THREAD* thread = KeGetCurrentThread(); if (!thread) return; @@ -154,7 +153,6 @@ __declspec(dllexport) void KeEnterCriticalRegion(void) { KeReleaseSpinlock(&thread->ApcLock, flags); } -// Implements the leave Critical Region operation. __declspec(dllexport) void KeLeaveCriticalRegion(void) { THREAD* thread = KeGetCurrentThread(); if (!thread) return; @@ -169,14 +167,12 @@ __declspec(dllexport) void KeLeaveCriticalRegion(void) { KiDeliverKernelApcs(); } -// Implements the are Kernel Apcs Disabled operation. __declspec(dllexport) bool KeAreKernelApcsDisabled(void) { THREAD* thread = KeGetCurrentThread(); if (!thread) return true; return thread->KernelApcDisable != 0; } -// Implements the pop Kernel Apc operation. static KAPC* KiPopKernelApc(THREAD* thread) { uintptr_t flags = KeAcquireSpinlock(&thread->ApcLock); LIST_ENTRY* node = ListPopHead(&thread->ApcQueue); @@ -189,7 +185,6 @@ static KAPC* KiPopKernelApc(THREAD* thread) { return CONTAINING_RECORD(node, KAPC, Link); } -// Implements the deliver Kernel Apcs operation. void KiDeliverKernelApcs(void) { THREAD* thread = KeGetCurrentThread(); if (!thread) @@ -322,7 +317,6 @@ static KUSER_APC* KiPopUserApc(THREAD* thread, bool alertableDelivery) { return (KUSER_APC*)0; } -// Implements the check For User Apc Delivery operation. void KiCheckForUserApcDelivery(KTRAP_FRAME* frame) { if (!frame || !KeTrapFrameFromUser(frame)) return; @@ -394,7 +388,6 @@ void KiCheckForUserApcDelivery(KTRAP_FRAME* frame) { MmFreePool(apc); } -// Implements the rundown Apc State operation. void KiRundownApcState(THREAD* thread) { if (!thread) return; @@ -435,7 +428,6 @@ void KiRundownApcState(THREAD* thread) { thread->UserApcSavedRax = 0; } -// Implements the user Apc Return operation. __declspec(dllexport) uint64_t KeUserApcReturn(const SYS_USER_APC_FRAME_K* userFrame) { THREAD* thread = KeGetCurrentThread(); if (!thread) diff --git a/code/kernel/ke_audio.c b/code/kernel/ke_audio.c index 31e844d..fc9b054 100644 --- a/code/kernel/ke_audio.c +++ b/code/kernel/ke_audio.c @@ -1447,7 +1447,6 @@ static KSTATUS KiAudioRegisterEndpoint(const IO_AUDIO_ENDPOINT_REGISTRATION* reg return NTLSTATUS_SUCCESS; } -// Implements the provider-facing endpoint registration operation. static KSTATUS KiAudioDdkRegisterEndpoint(const IO_AUDIO_ENDPOINT_REGISTRATION* registration, IO_AUDIO_ENDPOINT** outEndpoint) { return KiAudioRegisterEndpoint(registration, outEndpoint); diff --git a/code/kernel/ke_boot_config.c b/code/kernel/ke_boot_config.c index 5055a65..d970d35 100644 --- a/code/kernel/ke_boot_config.c +++ b/code/kernel/ke_boot_config.c @@ -146,11 +146,6 @@ KSTATUS KeParseBootConfiguration(const char* text, size_t length, KE_BOOT_CONFIG return status; if (config.Debug & ~KE_DEBUG_VALID_MASK) return NTLSTATUS_INVALID_PARAMETER; - } else if (strcmp(section, "init") == 0 && KiBootConfigSpanEquals(keyBegin, keyEnd, "commandline")) { - KSTATUS status = KiBootConfigCopyString(valueBegin, valueEnd, - config.CommandLine, sizeof(config.CommandLine)); - if (!KSUCCESS(status)) - return status; } } diff --git a/code/kernel/ke_debug.c b/code/kernel/ke_debug.c index af942fb..938bf47 100644 --- a/code/kernel/ke_debug.c +++ b/code/kernel/ke_debug.c @@ -30,7 +30,6 @@ static const HAL_API* gDebugHal; #define KE_DEBUG_LOG_LINE_SIZE 1024u #define KE_FATAL_OUTPUT_LINE_SIZE 2048u #define KE_STACK_DUMP_SLOT_COUNT 12u -#define KE_RBP_CALL_STACK_DEPTH 16u static SPINLOCK gDebugPrintLock = SPINLOCK_INIT; static char* gDebugLogBuffer; @@ -458,7 +457,6 @@ static const char* KiResolveModuleEx(PROCESS* proc, uintptr_t addr, return "unknown"; } -// Implements the resolve Module operation. static const char* KiResolveModule(PROCESS* proc, uintptr_t addr) { return KiResolveModuleEx(proc, addr, (uintptr_t*)0, (size_t*)0); } @@ -639,28 +637,6 @@ static void KiDumpModules(PROCESS* proc) { } -#if 0 -// Returns whether a range is inside the current kernel stack. -static bool KiKernelStackContains(const THREAD* thread, uintptr_t addr, size_t size) { - if (!thread || !thread->KernelStackBase || !thread->KernelStackTop || !addr || size == 0) - return false; - if (size - 1u > (size_t)(UINTPTR_MAX - addr)) - return false; - - uintptr_t base = (uintptr_t)thread->KernelStackBase; - uintptr_t top = thread->KernelStackTop; - uintptr_t end = addr + size; - return addr >= base && end <= top; -} - -// Returns whether the fault frame is using the current kernel stack. -static bool KiFaultFrameOnKernelStack(const THREAD* thread, const KFAULT_FRAME* f) { - if (!f || !thread) - return false; - return KiKernelStackContains(thread, (uintptr_t)f->Rsp, sizeof(uint64_t)); -} - -#endif // Dumps stack words near RSP. static void KiDumpStack(PROCESS* proc, uintptr_t rsp) { KiFaultPrintf("Stack @ %016llx:\n", (unsigned long long)rsp); @@ -684,58 +660,8 @@ static void KiDumpStack(PROCESS* proc, uintptr_t rsp) { } } -#if 0 -// Dumps a best-effort frame-pointer call stack. -static void KiDumpRbpCallStack(PROCESS* proc, THREAD* thread, const KFAULT_FRAME* f) { - uintptr_t rbp = f ? (uintptr_t)f->Rbp : 0; - KiFaultPrintf("RBP call stack @ %016llx:\n", (unsigned long long)rbp); - if (!rbp) { - KiFaultPrintf(" \n"); - return; - } - - int kernelStack = KiFaultFrameOnKernelStack(thread, f); - for (uint32_t depth = 0; depth < KE_RBP_CALL_STACK_DEPTH; depth++) { - if (rbp & (sizeof(uint64_t) - 1u)) { - KiFaultPrintf(" stop: unaligned RBP %016llx\n", - (unsigned long long)rbp); - return; - } - if (kernelStack && !KiKernelStackContains(thread, rbp, sizeof(uint64_t) * 2u)) { - KiFaultPrintf(" stop: RBP outside kernel stack %016llx\n", - (unsigned long long)rbp); - return; - } - - uint64_t next = 0; - uint64_t ret = 0; - if (!KiUserReadU64(rbp, &next) || !KiUserReadU64(rbp + sizeof(uint64_t), &ret)) { - KiFaultPrintf(" stop: frame unreadable at %016llx\n", - (unsigned long long)rbp); - return; - } - - KiFaultPrintf(" #%02u rbp=%016llx ret=", - (unsigned)depth, - (unsigned long long)rbp); - KiPrintAddressValue(proc, (uintptr_t)ret); - KiFaultPrintf(" next=%016llx\n", (unsigned long long)next); - - if (!next) - return; - if ((uintptr_t)next <= rbp) { - KiFaultPrintf(" stop: non-forward RBP chain %016llx -> %016llx\n", - (unsigned long long)rbp, - (unsigned long long)next); - return; - } - rbp = (uintptr_t)next; - } -} - -#endif // Dumps a fault frame. -static void KiDumpFaultFrame(PROCESS* proc, THREAD* thread, const KFAULT_FRAME* f) { +static void KiDumpFaultFrame(PROCESS* proc, const KFAULT_FRAME* f) { if (!f) return; KiFaultPrintf("Regs:\n"); @@ -771,9 +697,6 @@ static void KiDumpFaultFrame(PROCESS* proc, THREAD* thread, const KFAULT_FRAME* } KiDumpStack(proc, (uintptr_t)f->Rsp); -#if 0 - KiDumpRbpCallStack(proc, thread, f); -#endif } static void KiPrintCrashHeader(PROCESS* proc, int vector, uintptr_t rip, @@ -804,7 +727,6 @@ static void KiPrintCrashHeader(PROCESS* proc, int vector, uintptr_t rip, (unsigned long long)errCode); } -// Implements the finish Faulted Process operation. static _Noreturn void KiFinishFaultedProcess(PROCESS* proc, THREAD* thread, KSTATUS exitStatus) { int exitCode = (int)exitStatus; if (proc) (void)KeTerminateProcess(proc, exitCode); @@ -849,7 +771,7 @@ static _Noreturn void KiPanicKernelFault(PROCESS* proc, THREAD* thread, const KF thread, proc ? proc->ProcessId : 0, proc ? proc->Name : ""); - KiDumpFaultFrame(proc, thread, frame); + KiDumpFaultFrame(proc, frame); if (vector == 14) { MmDebugDescribeAddress((uintptr_t)frame->Cr2); if (frame->Rip) MmDebugDescribeAddress((uintptr_t)frame->Rip); @@ -894,7 +816,7 @@ static _Noreturn void KiTerminateUserFault(PROCESS* proc, THREAD* thread, const (uintptr_t)frame->Rip, (uintptr_t)frame->ErrorCode, (uintptr_t)frame->Cr2); - KiDumpFaultFrame(proc, thread, frame); + KiDumpFaultFrame(proc, frame); KiDumpModules(proc); KiFinishFaultedProcess(proc, thread, KeExceptionProcessExitStatus((uint32_t)frame->Vector)); diff --git a/code/kernel/ke_display.c b/code/kernel/ke_display.c index 2ed754b..7b1fa58 100644 --- a/code/kernel/ke_display.c +++ b/code/kernel/ke_display.c @@ -837,14 +837,12 @@ static KSTATUS KiDisplayFinishProviderDraw(DISPLAY_DEVICE* device, return KSUCCESS(drawStatus) ? presentStatus : drawStatus; } -// Implements the display Dirty All operation. static void KiDisplayDirtyAll(void) { gDisplayStats.DirtyAllCount++; gDirtyAll = true; gDirtyRectCount = 0; } -// Implements the display Add Dirty operation. static void KiDisplayAddDirty(int32_t x, int32_t y, int32_t w, int32_t h) { if (!KiDisplayHasDevice() || gDirtyAll || w <= 0 || h <= 0) return; @@ -872,7 +870,6 @@ static void KiDisplayAddDirty(int32_t x, int32_t y, int32_t w, int32_t h) { gDirtyRects[gDirtyRectCount++] = rect; } -// Implements the display Flush Dirty operation. static KSTATUS KiDisplayFlushDirty(void) { if (!KiDisplayHasDevice() || !gPrimaryDisplay->Ops->Present) return NTLSTATUS_SUCCESS; @@ -906,7 +903,6 @@ static KSTATUS KiDisplayFlushDirty(void) { return s; } -// Implements the display Hide Cursor For Draw operation. static void KiDisplayHideCursorForDraw(void) { if (!gCursorDrawn || !KiDisplayUsesSoftwareCursor()) return; @@ -915,7 +911,6 @@ static void KiDisplayHideCursorForDraw(void) { gCursorDrawn = false; } -// Implements the display Restore Cursor After Draw operation. static void KiDisplayRestoreCursorAfterDraw(void) { if (!gCursorVisible || gCursorDrawn || !KiDisplayHasCursorOps()) return; @@ -927,13 +922,11 @@ static void KiDisplayRestoreCursorAfterDraw(void) { gCursorDrawn = true; } -// Implements the display Begin Draw operation. static void KiDisplayBeginDraw(void) { if (gDrawDepth++ == 0) KiDisplayHideCursorForDraw(); } -// Implements the display End Draw operation. static KSTATUS KiDisplayEndDraw(void) { KSTATUS s = NTLSTATUS_SUCCESS; if (gDrawDepth > 0) @@ -946,7 +939,6 @@ static KSTATUS KiDisplayEndDraw(void) { return s; } -// Implements the display Draw Blit No Cursor operation. static KSTATUS KiDisplayDrawBlitNoCursor(int32_t x, int32_t y, int32_t w, int32_t h, const uint32_t* pixels) { if (!pixels || w <= 0 || h <= 0) return NTLSTATUS_INVALID_PARAMETER; @@ -962,7 +954,6 @@ static KSTATUS KiDisplayDrawBlitNoCursor(int32_t x, int32_t y, int32_t w, int32_ return s; } -// Implements the display Fill Rect No Cursor operation. static KSTATUS KiDisplayFillRectNoCursor(int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) { if (w <= 0 || h <= 0) return NTLSTATUS_INVALID_PARAMETER; @@ -978,7 +969,6 @@ static KSTATUS KiDisplayFillRectNoCursor(int32_t x, int32_t y, int32_t w, int32_ return s; } -// Implements the display Copy Rect No Cursor operation. static KSTATUS KiDisplayCopyRectNoCursor(int32_t dstX, int32_t dstY, int32_t srcX, int32_t srcY, int32_t w, int32_t h) { if (w <= 0 || h <= 0) return NTLSTATUS_INVALID_PARAMETER; @@ -994,12 +984,10 @@ static KSTATUS KiDisplayCopyRectNoCursor(int32_t dstX, int32_t dstY, int32_t src return s; } -// Implements the display Console Index operation. static size_t KiDisplayConsoleIndex(int32_t col, int32_t row) { return (size_t)row * DISPLAY_CONSOLE_MAX_COLS + (size_t)col; } -// Implements the display Console Color operation. static uint32_t KiDisplayConsoleColor(uint8_t index) { static const uint32_t colors[16] = { 0x00000000u, 0x000000AAu, 0x0000AA00u, 0x0000AAAAu, @@ -1010,17 +998,14 @@ static uint32_t KiDisplayConsoleColor(uint8_t index) { return colors[index & 0x0Fu]; } -// Implements the display Console Fg operation. static uint32_t KiDisplayConsoleFg(uint16_t attr) { return KiDisplayConsoleColor((uint8_t)(attr & 0x0Fu)); } -// Implements the display Console Bg operation. static uint32_t KiDisplayConsoleBg(uint16_t attr) { return KiDisplayConsoleColor((uint8_t)((attr >> 4) & 0x0Fu)); } -// Implements the display Get Console Grid Locked operation. static bool KiDisplayGetConsoleGridLocked(int* outCols, int* outRows) { DISPLAY_MODE mode; if (!KiDisplayHasDevice() || !gPrimaryDisplay->Ops->GetMode) @@ -1040,7 +1025,6 @@ static bool KiDisplayGetConsoleGridLocked(int* outCols, int* outRows) { return true; } -// Implements the display Console Reset Cells Locked operation. static void KiDisplayConsoleResetCellsLocked(void) { for (size_t i = 0; i < DISPLAY_CONSOLE_MAX_CELLS; i++) { gConsoleCells[i] = ' '; @@ -1049,7 +1033,6 @@ static void KiDisplayConsoleResetCellsLocked(void) { gConsoleAttribute = DISPLAY_CONSOLE_DEFAULT_ATTR; } -// Implements the display Console Scroll Cells Locked operation. static void KiDisplayConsoleScrollCellsLocked(int cols, int rows, int cellLines) { if (cols <= 0 || rows <= 0 || cellLines <= 0) return; @@ -1083,7 +1066,6 @@ static void KiDisplayConsoleScrollCellsLocked(int cols, int rows, int cellLines) } } -// Implements the display Draw Char Pixels Locked operation. static KSTATUS KiDisplayDrawCharPixelsLocked(char c, int32_t x, int32_t y, uint32_t fg, uint32_t bg) { uint32_t glyphPixels[FONT_W * FONT_H]; const uint8_t* glyph = Font8x16 + ((uint8_t)c * 16u); @@ -1097,7 +1079,6 @@ static KSTATUS KiDisplayDrawCharPixelsLocked(char c, int32_t x, int32_t y, uint3 return KiDisplayDrawBlitNoCursor(x, y, FONT_W, FONT_H, glyphPixels); } -// Implements the display Draw Console Cell Locked operation. static KSTATUS KiDisplayDrawConsoleCellLocked(int32_t col, int32_t row, char c, uint16_t attr, bool updateCell) { if (updateCell) { size_t i = KiDisplayConsoleIndex(col, row); @@ -1555,7 +1536,6 @@ DISPLAY_API KSTATUS KeDisplayUnregisterDevice(DISPLAY_DEVICE* device) { return NTLSTATUS_SUCCESS; } -// Implements the display Seed New Primary operation. static KSTATUS KiDisplaySeedNewPrimary(DISPLAY_DEVICE* oldDevice, DISPLAY_DEVICE* newDevice) { if (!oldDevice || !newDevice || oldDevice == newDevice) return NTLSTATUS_SUCCESS; @@ -1598,7 +1578,6 @@ DISPLAY_API void KeDisplaySuspendConsole(bool suspend) { NtlAtomicExchange32(&gDisplayConsoleSuspended, suspend ? 1 : 0); } -// Implements the display Output Suspended operation. static bool KiDisplayOutputSuspended(void) { return NtlAtomicLoad32(&gDisplayConsoleSuspended) != 0; } @@ -2501,12 +2480,10 @@ DISPLAY_API KSTATUS KeDisplayShowCursor(bool show) { return NTLSTATUS_SUCCESS; } -// Implements the boot Fb Context operation. static BOOTFB_CONTEXT* BootFbContext(DISPLAY_DEVICE* device) { return device ? (BOOTFB_CONTEXT*)device->DriverContext : NULL; } -// Implements the boot Fb Get Mode operation. static KSTATUS BootFbGetMode(DISPLAY_DEVICE* device, DISPLAY_MODE* outMode) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (!fb || !fb->Framebuffer || !outMode) @@ -2622,7 +2599,6 @@ static void BootFbCopyToShadowAndScanout(uint32_t* shadow, } } -// Implements the boot framebuffer pitched blit operation. static KSTATUS BootFbBlit(DISPLAY_DEVICE* device, int32_t x, int32_t y, int32_t w, int32_t h, const uint32_t* pixels, uint32_t pitchBytes) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (!fb || !fb->Framebuffer || !pixels || w <= 0 || h <= 0 || @@ -2702,7 +2678,6 @@ static KSTATUS BootFbPresentPitched(DISPLAY_DEVICE* device, return NTLSTATUS_SUCCESS; } -// Implements the boot Fb Fill Rect operation. static KSTATUS BootFbFillRect(DISPLAY_DEVICE* device, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (!fb || !fb->Framebuffer || w <= 0 || h <= 0) @@ -2728,7 +2703,6 @@ static KSTATUS BootFbFillRect(DISPLAY_DEVICE* device, int32_t x, int32_t y, int3 return NTLSTATUS_SUCCESS; } -// Implements the boot Fb Copy Rect operation. static KSTATUS BootFbCopyRect(DISPLAY_DEVICE* device, int32_t dstX, int32_t dstY, int32_t srcX, int32_t srcY, int32_t w, int32_t h) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (!fb || !fb->Framebuffer || w <= 0 || h <= 0) @@ -2767,7 +2741,6 @@ static KSTATUS BootFbCopyRect(DISPLAY_DEVICE* device, int32_t dstX, int32_t dstY return NTLSTATUS_SUCCESS; } -// Implements the boot Fb Read Rect operation. static KSTATUS BootFbReadRect(DISPLAY_DEVICE* device, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t* outPixels, uint32_t outStride) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (!fb || !fb->Framebuffer || !outPixels || outStride == 0 || w <= 0 || h <= 0) @@ -2792,7 +2765,6 @@ static KSTATUS BootFbReadRect(DISPLAY_DEVICE* device, int32_t x, int32_t y, int3 return NTLSTATUS_SUCCESS; } -// Implements the boot Fb Present operation. static KSTATUS BootFbPresent(DISPLAY_DEVICE* device, const DISPLAY_RECT* rects, size_t rectCount) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (!fb || !fb->Framebuffer) @@ -2827,14 +2799,12 @@ static KSTATUS BootFbPresent(DISPLAY_DEVICE* device, const DISPLAY_RECT* rects, return NTLSTATUS_SUCCESS; } -// Implements the boot Fb Sync operation. static KSTATUS BootFbSync(DISPLAY_DEVICE* device) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (fb) fb->Stats.SyncCount++; return NTLSTATUS_SUCCESS; } -// Implements the boot Fb Set Cursor Image operation. static KSTATUS BootFbSetCursorImage(DISPLAY_DEVICE* device, int32_t width, int32_t height, int32_t hotX, int32_t hotY, const uint32_t* argbPixels) { (void)device; (void)width; @@ -2845,7 +2815,6 @@ static KSTATUS BootFbSetCursorImage(DISPLAY_DEVICE* device, int32_t width, int32 return NTLSTATUS_NOT_SUPPORTED; } -// Implements the boot Fb Set Cursor Position operation. static KSTATUS BootFbSetCursorPosition(DISPLAY_DEVICE* device, int32_t x, int32_t y) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (fb) fb->Stats.CursorMoveCount++; @@ -2854,7 +2823,6 @@ static KSTATUS BootFbSetCursorPosition(DISPLAY_DEVICE* device, int32_t x, int32_ return NTLSTATUS_SUCCESS; } -// Implements the display Blend Pixel operation. static inline uint32_t KiDisplayBlendPixel(uint32_t dst, uint32_t src) { uint8_t a = (uint8_t)(src >> 24); if (a == 0) return dst; @@ -2873,7 +2841,6 @@ static inline uint32_t KiDisplayBlendPixel(uint32_t dst, uint32_t src) { return ((uint32_t)rr << 16) | ((uint32_t)gg << 8) | bb; } -// Implements the boot Fb Restore Cursor operation. static void BootFbRestoreCursor(BOOTFB_CONTEXT* fb) { if (!fb || !fb->Framebuffer || !fb->Backbuffer || gCursorDrawX < 0) return; @@ -2893,7 +2860,6 @@ static void BootFbRestoreCursor(BOOTFB_CONTEXT* fb) { gCursorUpdatePending = false; } -// Implements the boot Fb Draw Cursor operation. static void BootFbDrawCursor(BOOTFB_CONTEXT* fb, int32_t x, int32_t y) { if (!fb || !fb->Framebuffer || !fb->Backbuffer) return; @@ -2918,7 +2884,6 @@ static void BootFbDrawCursor(BOOTFB_CONTEXT* fb, int32_t x, int32_t y) { } } -// Implements the boot Fb Show Cursor operation. static KSTATUS BootFbShowCursor(DISPLAY_DEVICE* device, bool show) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (!fb || !fb->Framebuffer || !fb->Backbuffer) @@ -2935,7 +2900,6 @@ static KSTATUS BootFbShowCursor(DISPLAY_DEVICE* device, bool show) { return NTLSTATUS_SUCCESS; } -// Implements the boot Fb Query Stats operation. static KSTATUS BootFbQueryStats(DISPLAY_DEVICE* device, DISPLAY_STATS* outStats) { BOOTFB_CONTEXT* fb = BootFbContext(device); if (!fb || !outStats) diff --git a/code/kernel/ke_dpc.c b/code/kernel/ke_dpc.c index 3e0c4c2..5f54c22 100644 --- a/code/kernel/ke_dpc.c +++ b/code/kernel/ke_dpc.c @@ -24,7 +24,6 @@ void KeInitializeDpcSystem(void) { gDpcInitialized = 1; } -// Implements the ensure Dpc Initialized operation. static void KiEnsureDpcInitialized(void) { if (gDpcInitialized) return; @@ -69,7 +68,6 @@ __declspec(dllexport) bool KeInsertQueueDpc(KDPC* dpc, return true; } -// Implements the drain Dpc Queue operation. void KiDrainDpcQueue(void) { if (!gDpcInitialized) return; diff --git a/code/kernel/ke_event.c b/code/kernel/ke_event.c index 5b6b4fc..7b49f5a 100644 --- a/code/kernel/ke_event.c +++ b/code/kernel/ke_event.c @@ -33,7 +33,6 @@ struct KE_EVENT_MULTI_WAIT_CONTEXT { uint32_t SelectedIndex; }; -// Implements the event Destroy operation. static void KiEventDestroy(OBJECT* obj) { (void)obj; } // Completes a multi-wait block while the source event lock is held. diff --git a/code/kernel/ke_firmware.c b/code/kernel/ke_firmware.c new file mode 100644 index 0000000..beba0ae --- /dev/null +++ b/code/kernel/ke_firmware.c @@ -0,0 +1,106 @@ +// Firmware root discovery for optional platform drivers. + +#include +#include +#include +#include +#include +#include +#include +#include + +#define KI_RSDP_V1_SIZE 20u +#define KI_RSDP_V2_SIZE 36u +#define KI_RSDP_MAX_SIZE 4096u + +static uint64_t gAcpiRsdpPhysical; +static const char* gAcpiRootDiagnostic = "absent"; +static uint8_t gAcpiRsdpRevision; + +// Firmware roots must remain in reserved memory after ExitBootServices. +static bool KiFirmwareReservedSpan(const MEMORY_MAP* map, uint64_t start, uint32_t length) { + if (!map || map->Magic != MEMORY_MAP_MAGIC || + map->RegionCount > MEMORY_MAX_REGIONS || !length || start > UINT64_MAX - length) + return false; + uint64_t end = start + length; + for (uint32_t i = 0; i < map->RegionCount; i++) { + const MEMORY_REGION* region = &map->Regions[i]; + if (region->Type != MemoryReserved || + region->Base > UINT64_MAX - region->Length) + continue; + if (start >= region->Base && end <= region->Base + region->Length) + return true; + } + return false; +} + +static bool KiFirmwareChecksumValid(const uint8_t* bytes, uint32_t length) { + uint8_t sum = 0; + for (uint32_t i = 0; i < length; i++) sum = (uint8_t)(sum + bytes[i]); + return sum == 0; +} + +void KeFirmwareInitialize(const BOOT_INFO* bootInfo) { + gAcpiRsdpPhysical = 0; + gAcpiRsdpRevision = 0; + gAcpiRootDiagnostic = "absent"; + if (!bootInfo || !bootInfo->RsdpPhysical) return; + if (!bootInfo->PhysicalMapBase || + !KiFirmwareReservedSpan(&bootInfo->MemoryMap, + bootInfo->RsdpPhysical, KI_RSDP_V1_SIZE) || + bootInfo->RsdpPhysical > UINTPTR_MAX - bootInfo->PhysicalMapBase) { + gAcpiRootDiagnostic = "invalid physical range"; + return; + } + + const uint8_t* rsdp = (const uint8_t*)(bootInfo->PhysicalMapBase + bootInfo->RsdpPhysical); + if (memcmp(rsdp, "RSD PTR ", 8) != 0) { + gAcpiRootDiagnostic = "invalid signature"; + return; + } + if (!KiFirmwareChecksumValid(rsdp, KI_RSDP_V1_SIZE)) { + gAcpiRootDiagnostic = "invalid legacy checksum"; + return; + } + + if (rsdp[15] >= 2u) { + if (!KiFirmwareReservedSpan(&bootInfo->MemoryMap, + bootInfo->RsdpPhysical, KI_RSDP_V2_SIZE)) { + gAcpiRootDiagnostic = "truncated extended root"; + return; + } + uint32_t length; + memcpy(&length, rsdp + 20, sizeof(length)); + if (length < KI_RSDP_V2_SIZE || length > KI_RSDP_MAX_SIZE || + !KiFirmwareReservedSpan(&bootInfo->MemoryMap, + bootInfo->RsdpPhysical, length)) { + gAcpiRootDiagnostic = "invalid extended length"; + return; + } + if (!KiFirmwareChecksumValid(rsdp, length)) { + gAcpiRootDiagnostic = "invalid extended checksum"; + return; + } + } + + gAcpiRsdpPhysical = (uint64_t)bootInfo->RsdpPhysical; + gAcpiRsdpRevision = rsdp[15]; + gAcpiRootDiagnostic = "valid"; +} + +// A driver chooses its own ACPI interpreter and maps tables through the DDK. +__declspec(dllexport) KSTATUS KeFirmwareQueryAcpiRsdp(uint64_t* physicalAddressOut) { + if (!physicalAddressOut) return NTLSTATUS_INVALID_PARAMETER; + *physicalAddressOut = 0; + if (!gAcpiRsdpPhysical) return NTLSTATUS_NOT_SUPPORTED; + *physicalAddressOut = gAcpiRsdpPhysical; + return NTLSTATUS_SUCCESS; +} + +// Reports the firmware handoff state through the normal kernel diagnostic stream. +void KeFirmwareLog(void) { + DbgPrint("firmware: ACPI RSDP %s phys=0x%016llX revision=%u\n", + gAcpiRootDiagnostic, + (unsigned long long)gAcpiRsdpPhysical, + (unsigned)gAcpiRsdpRevision); +} diff --git a/code/kernel/ke_hal.c b/code/kernel/ke_hal.c index 22c165c..574b3b4 100644 --- a/code/kernel/ke_hal.c +++ b/code/kernel/ke_hal.c @@ -30,8 +30,10 @@ static bool KiHalRuntimeTableValid(const HAL_API* hal) { hal->Timer.QueryTicks && hal->Timer.QueryTickFrequency && hal->Timer.Stall && hal->Timer.HandleInterrupt && hal->Timer.ConfigureCurrentProcessor && hal->Rtc.QueryTime && hal->Pci.Read32 && hal->Pci.Write32 && - hal->InterruptController.RouteIrq && hal->InterruptController.MaskIrq && - hal->InterruptController.UnmaskIrq && hal->InterruptController.SendEoi && + hal->InterruptController.RouteGsi && hal->InterruptController.MaskGsi && + hal->InterruptController.ResolveIsa && hal->InterruptController.SendEoi && + hal->InterruptController.SetTaskPriority && hal->InterruptController.QueryTaskPriority && + hal->InterruptController.VectorPending && hal->InterruptController.InitializeCurrentProcessor && hal->InterruptController.SendProcessorInterrupt && hal->InterruptController.SendProcessorNmi && hal->InterruptController.BroadcastNmi && diff --git a/code/kernel/ke_idt.c b/code/kernel/ke_idt.c index f47e07c..596e744 100644 --- a/code/kernel/ke_idt.c +++ b/code/kernel/ke_idt.c @@ -12,6 +12,7 @@ #include #include #include +#include // External assembly procedures. extern void KeFlushGdt(void* pGdtr, uint16_t codeSel, uint16_t dataSel, uint16_t tssSel); @@ -41,7 +42,145 @@ extern void KeIrqStub20(void); extern void KeIrqStub21(void); extern void KeIrqStub22(void); extern void KeIrqStub23(void); +extern void KeIrqStub24(void); +extern void KeIrqStub25(void); +extern void KeIrqStub26(void); +extern void KeIrqStub27(void); +extern void KeIrqStub28(void); +extern void KeIrqStub29(void); +extern void KeIrqStub30(void); +extern void KeIrqStub31(void); +extern void KeIrqStub32(void); +extern void KeIrqStub33(void); +extern void KeIrqStub34(void); +extern void KeIrqStub35(void); +extern void KeIrqStub36(void); +extern void KeIrqStub37(void); +extern void KeIrqStub38(void); +extern void KeIrqStub39(void); +extern void KeIrqStub40(void); +extern void KeIrqStub41(void); +extern void KeIrqStub42(void); +extern void KeIrqStub43(void); +extern void KeIrqStub44(void); +extern void KeIrqStub45(void); +extern void KeIrqStub46(void); +extern void KeIrqStub47(void); +extern void KeIrqStub48(void); +extern void KeIrqStub49(void); +extern void KeIrqStub50(void); +extern void KeIrqStub51(void); +extern void KeIrqStub52(void); +extern void KeIrqStub53(void); +extern void KeIrqStub54(void); +extern void KeIrqStub55(void); +extern void KeIrqStub56(void); +extern void KeIrqStub57(void); +extern void KeIrqStub58(void); +extern void KeIrqStub59(void); +extern void KeIrqStub60(void); +extern void KeIrqStub61(void); +extern void KeIrqStub62(void); +extern void KeIrqStub63(void); +extern void KeIrqStub64(void); +extern void KeIrqStub65(void); +extern void KeIrqStub66(void); +extern void KeIrqStub67(void); +extern void KeIrqStub68(void); +extern void KeIrqStub69(void); +extern void KeIrqStub70(void); +extern void KeIrqStub71(void); +extern void KeIrqStub72(void); +extern void KeIrqStub73(void); +extern void KeIrqStub74(void); +extern void KeIrqStub75(void); +extern void KeIrqStub76(void); +extern void KeIrqStub77(void); +extern void KeIrqStub78(void); +extern void KeIrqStub79(void); +extern void KeIrqStub80(void); +extern void KeIrqStub81(void); +extern void KeIrqStub82(void); +extern void KeIrqStub83(void); +extern void KeIrqStub84(void); +extern void KeIrqStub85(void); +extern void KeIrqStub86(void); +extern void KeIrqStub87(void); +extern void KeIrqStub88(void); +extern void KeIrqStub89(void); +extern void KeIrqStub90(void); +extern void KeIrqStub91(void); +extern void KeIrqStub92(void); +extern void KeIrqStub93(void); +extern void KeIrqStub94(void); +extern void KeIrqStub95(void); +extern void KeIrqStub96(void); +extern void KeIrqStub97(void); +extern void KeIrqStub98(void); +extern void KeIrqStub99(void); +extern void KeIrqStub100(void); +extern void KeIrqStub101(void); +extern void KeIrqStub102(void); +extern void KeIrqStub103(void); +extern void KeIrqStub104(void); +extern void KeIrqStub105(void); +extern void KeIrqStub106(void); +extern void KeIrqStub107(void); +extern void KeIrqStub108(void); +extern void KeIrqStub109(void); +extern void KeIrqStub110(void); +extern void KeIrqStub111(void); +extern void KeIrqStub112(void); +extern void KeIrqStub113(void); +extern void KeIrqStub114(void); +extern void KeIrqStub115(void); +extern void KeIrqStub116(void); +extern void KeIrqStub117(void); +extern void KeIrqStub118(void); +extern void KeIrqStub119(void); +extern void KeIrqStub120(void); +extern void KeIrqStub121(void); +extern void KeIrqStub122(void); +extern void KeIrqStub123(void); +extern void KeIrqStub124(void); +extern void KeIrqStub125(void); +extern void KeIrqStub126(void); +extern void KeIrqStub127(void); +extern void KeIrqStub128(void); +extern void KeIrqStub129(void); +extern void KeIrqStub130(void); +extern void KeIrqStub131(void); +extern void KeIrqStub132(void); +extern void KeIrqStub133(void); +extern void KeIrqStub134(void); +extern void KeIrqStub135(void); +extern void KeIrqStub136(void); +extern void KeIrqStub137(void); +extern void KeIrqStub138(void); +extern void KeIrqStub139(void); +extern void KeIrqStub140(void); +extern void KeIrqStub141(void); +extern void KeIrqStub142(void); +extern void KeIrqStub143(void); +extern void KeIrqStub144(void); +extern void KeIrqStub145(void); +extern void KeIrqStub146(void); +extern void KeIrqStub147(void); +extern void KeIrqStub148(void); +extern void KeIrqStub149(void); +extern void KeIrqStub150(void); +extern void KeIrqStub151(void); +extern void KeIrqStub152(void); +extern void KeIrqStub153(void); +extern void KeIrqStub154(void); +extern void KeIrqStub155(void); +extern void KeIrqStub156(void); +extern void KeIrqStub157(void); +extern void KeIrqStub158(void); +extern void KeIrqStub159(void); extern void KeRescheduleIpiStub(void); +extern void KeLocalTimerStub(void); +extern void KeSpuriousStub(void); extern void KeFaultDB(void); extern void KeFaultNMI(void); @@ -74,7 +213,7 @@ extern void KeFaultVC(void); extern void KeFaultSX(void); extern void KeFaultRSV31(void); -#define NUM_IRQS 24 +#define NUM_DEVICE_VECTORS (KE_VECTOR_DEVICE_LAST - KE_VECTOR_DEVICE_FIRST + 1u) // GDT. static void KiGdtSetEntry(uint64_t* gdt, int idx, uint32_t base, uint32_t limit, @@ -88,7 +227,6 @@ static void KiGdtSetEntry(uint64_t* gdt, int idx, uint32_t base, uint32_t limit, ((uint64_t)(base >> 24 & 0xFF)<< 56); } -// Implements the gdt Set Tss operation. static void KiGdtSetTss(uint64_t* gdt, int idx, uintptr_t base, uint32_t limit) { // TSS descriptor is 16 bytes (two GDT slots). gdt[idx] = 0; @@ -219,23 +357,180 @@ void KeInitializeIdt(void) { // User-mode INT3 must enter #BP, not fail the gate-DPL check and become #GP. KiIdtSetGate(3, (uintptr_t)KeFaultBP, KI_IDT_TYPE_USER_INTERRUPT_GATE, 0); - KiIdtSetGate(0x40, (uintptr_t)KeSyscallEntry, KI_IDT_TYPE_USER_INTERRUPT_GATE, 0); + KiIdtSetGate(KE_VECTOR_SYSCALL, (uintptr_t)KeSyscallEntry, KI_IDT_TYPE_USER_INTERRUPT_GATE, 0); - static void* irqStubs[NUM_IRQS] = { - (void*)KeIrqStub0, (void*)KeIrqStub1, (void*)KeIrqStub2, - (void*)KeIrqStub3, (void*)KeIrqStub4, (void*)KeIrqStub5, - (void*)KeIrqStub6, (void*)KeIrqStub7, (void*)KeIrqStub8, - (void*)KeIrqStub9, (void*)KeIrqStub10, (void*)KeIrqStub11, - (void*)KeIrqStub12, (void*)KeIrqStub13, (void*)KeIrqStub14, - (void*)KeIrqStub15, (void*)KeIrqStub16, (void*)KeIrqStub17, - (void*)KeIrqStub18, (void*)KeIrqStub19, (void*)KeIrqStub20, - (void*)KeIrqStub21, (void*)KeIrqStub22, (void*)KeIrqStub23, + static void* irqStubs[NUM_DEVICE_VECTORS] = { + (void*)KeIrqStub0, + (void*)KeIrqStub1, + (void*)KeIrqStub2, + (void*)KeIrqStub3, + (void*)KeIrqStub4, + (void*)KeIrqStub5, + (void*)KeIrqStub6, + (void*)KeIrqStub7, + (void*)KeIrqStub8, + (void*)KeIrqStub9, + (void*)KeIrqStub10, + (void*)KeIrqStub11, + (void*)KeIrqStub12, + (void*)KeIrqStub13, + (void*)KeIrqStub14, + (void*)KeIrqStub15, + (void*)KeIrqStub16, + (void*)KeIrqStub17, + (void*)KeIrqStub18, + (void*)KeIrqStub19, + (void*)KeIrqStub20, + (void*)KeIrqStub21, + (void*)KeIrqStub22, + (void*)KeIrqStub23, + (void*)KeIrqStub24, + (void*)KeIrqStub25, + (void*)KeIrqStub26, + (void*)KeIrqStub27, + (void*)KeIrqStub28, + (void*)KeIrqStub29, + (void*)KeIrqStub30, + (void*)KeIrqStub31, + (void*)KeIrqStub32, + (void*)KeIrqStub33, + (void*)KeIrqStub34, + (void*)KeIrqStub35, + (void*)KeIrqStub36, + (void*)KeIrqStub37, + (void*)KeIrqStub38, + (void*)KeIrqStub39, + (void*)KeIrqStub40, + (void*)KeIrqStub41, + (void*)KeIrqStub42, + (void*)KeIrqStub43, + (void*)KeIrqStub44, + (void*)KeIrqStub45, + (void*)KeIrqStub46, + (void*)KeIrqStub47, + (void*)KeIrqStub48, + (void*)KeIrqStub49, + (void*)KeIrqStub50, + (void*)KeIrqStub51, + (void*)KeIrqStub52, + (void*)KeIrqStub53, + (void*)KeIrqStub54, + (void*)KeIrqStub55, + (void*)KeIrqStub56, + (void*)KeIrqStub57, + (void*)KeIrqStub58, + (void*)KeIrqStub59, + (void*)KeIrqStub60, + (void*)KeIrqStub61, + (void*)KeIrqStub62, + (void*)KeIrqStub63, + (void*)KeIrqStub64, + (void*)KeIrqStub65, + (void*)KeIrqStub66, + (void*)KeIrqStub67, + (void*)KeIrqStub68, + (void*)KeIrqStub69, + (void*)KeIrqStub70, + (void*)KeIrqStub71, + (void*)KeIrqStub72, + (void*)KeIrqStub73, + (void*)KeIrqStub74, + (void*)KeIrqStub75, + (void*)KeIrqStub76, + (void*)KeIrqStub77, + (void*)KeIrqStub78, + (void*)KeIrqStub79, + (void*)KeIrqStub80, + (void*)KeIrqStub81, + (void*)KeIrqStub82, + (void*)KeIrqStub83, + (void*)KeIrqStub84, + (void*)KeIrqStub85, + (void*)KeIrqStub86, + (void*)KeIrqStub87, + (void*)KeIrqStub88, + (void*)KeIrqStub89, + (void*)KeIrqStub90, + (void*)KeIrqStub91, + (void*)KeIrqStub92, + (void*)KeIrqStub93, + (void*)KeIrqStub94, + (void*)KeIrqStub95, + (void*)KeIrqStub96, + (void*)KeIrqStub97, + (void*)KeIrqStub98, + (void*)KeIrqStub99, + (void*)KeIrqStub100, + (void*)KeIrqStub101, + (void*)KeIrqStub102, + (void*)KeIrqStub103, + (void*)KeIrqStub104, + (void*)KeIrqStub105, + (void*)KeIrqStub106, + (void*)KeIrqStub107, + (void*)KeIrqStub108, + (void*)KeIrqStub109, + (void*)KeIrqStub110, + (void*)KeIrqStub111, + (void*)KeIrqStub112, + (void*)KeIrqStub113, + (void*)KeIrqStub114, + (void*)KeIrqStub115, + (void*)KeIrqStub116, + (void*)KeIrqStub117, + (void*)KeIrqStub118, + (void*)KeIrqStub119, + (void*)KeIrqStub120, + (void*)KeIrqStub121, + (void*)KeIrqStub122, + (void*)KeIrqStub123, + (void*)KeIrqStub124, + (void*)KeIrqStub125, + (void*)KeIrqStub126, + (void*)KeIrqStub127, + (void*)KeIrqStub128, + (void*)KeIrqStub129, + (void*)KeIrqStub130, + (void*)KeIrqStub131, + (void*)KeIrqStub132, + (void*)KeIrqStub133, + (void*)KeIrqStub134, + (void*)KeIrqStub135, + (void*)KeIrqStub136, + (void*)KeIrqStub137, + (void*)KeIrqStub138, + (void*)KeIrqStub139, + (void*)KeIrqStub140, + (void*)KeIrqStub141, + (void*)KeIrqStub142, + (void*)KeIrqStub143, + (void*)KeIrqStub144, + (void*)KeIrqStub145, + (void*)KeIrqStub146, + (void*)KeIrqStub147, + (void*)KeIrqStub148, + (void*)KeIrqStub149, + (void*)KeIrqStub150, + (void*)KeIrqStub151, + (void*)KeIrqStub152, + (void*)KeIrqStub153, + (void*)KeIrqStub154, + (void*)KeIrqStub155, + (void*)KeIrqStub156, + (void*)KeIrqStub157, + (void*)KeIrqStub158, + (void*)KeIrqStub159, }; - for (int i = 0; i < NUM_IRQS; i++) - KiIdtSetGate(0x20 + i, (uintptr_t)irqStubs[i], KI_IDT_TYPE_INTERRUPT_GATE, 0); + for (uint32_t i = 0; i < NUM_DEVICE_VECTORS; i++) + KiIdtSetGate(KE_VECTOR_DEVICE_FIRST + i, (uintptr_t)irqStubs[i], + KI_IDT_TYPE_INTERRUPT_GATE, 0); + KiIdtSetGate(KE_VECTOR_CPU_TIMER, (uintptr_t)KeLocalTimerStub, + KI_IDT_TYPE_INTERRUPT_GATE, 0); KiIdtSetGate(KE_VECTOR_RESCHEDULE_IPI, (uintptr_t)KeRescheduleIpiStub, KI_IDT_TYPE_INTERRUPT_GATE, 0); + KiIdtSetGate(KE_VECTOR_SPURIOUS, (uintptr_t)KeSpuriousStub, + KI_IDT_TYPE_INTERRUPT_GATE, 0); KeLoadIdtForCurrentCpu(); } diff --git a/code/kernel/ke_input.c b/code/kernel/ke_input.c index a200349..f152e87 100644 --- a/code/kernel/ke_input.c +++ b/code/kernel/ke_input.c @@ -41,7 +41,6 @@ static void KiInputQueueManagerEvent(KE_INPUT_CONTEXT* context, const KE_INPUT_M KiInputRefreshManagerEvent(context); } -// Implements the input Initialize operation. void KeInputInitialize(const HAL_API* hal) { KE_INPUT_CONTEXT* context = &gDefaultInputContext; ObInitializeObjectHeader(&gInputManager.Header, ObjectTypeInputManager); @@ -114,7 +113,6 @@ KSTATUS KeInputManagerReadEvent(KE_INPUT_MANAGER* manager, uint64_t timeoutMs, S } } -// Implements the input Register Device operation. __declspec(dllexport) KSTATUS KeInputRegisterDevice(const char* name, uint32_t flags, uint32_t* outDeviceId) { (void)flags; uint32_t id = 0; @@ -125,7 +123,6 @@ __declspec(dllexport) KSTATUS KeInputRegisterDevice(const char* name, uint32_t f return NTLSTATUS_SUCCESS; } -// Implements the input Submit Key operation. __declspec(dllexport) void KeInputSubmitKey(const INPUT_KEY_EVENT* event) { KE_INPUT_CONTEXT* context = &gDefaultInputContext; if (!event) return; @@ -139,7 +136,6 @@ __declspec(dllexport) void KeInputSubmitKey(const INPUT_KEY_EVENT* event) { KiInputQueueManagerEvent(context, &managerEvent); } -// Implements the input Commit Mouse Position operation. static void KiInputCommitMousePosition(KE_INPUT_CONTEXT* context, int32_t nx, int32_t ny) { int32_t bw = context->MouseBoundsWidth; int32_t bh = context->MouseBoundsHeight; @@ -155,7 +151,6 @@ static void KiInputCommitMousePosition(KE_INPUT_CONTEXT* context, int32_t nx, in context->MouseY = ny; } -// Implements the input Submit Mouse operation. __declspec(dllexport) void KeInputSubmitMouse(const INPUT_MOUSE_EVENT* event) { KE_INPUT_CONTEXT* context = &gDefaultInputContext; if (!event) return; @@ -174,7 +169,6 @@ __declspec(dllexport) void KeInputSubmitMouse(const INPUT_MOUSE_EVENT* event) { KiInputCommitMousePosition(context, nx, ny); } -// Implements the input Submit Mouse Absolute operation. __declspec(dllexport) void KeInputSubmitMouseAbsolute(const INPUT_MOUSE_ABSOLUTE_EVENT* event) { KE_INPUT_CONTEXT* context = &gDefaultInputContext; if (!event) return; @@ -196,7 +190,6 @@ __declspec(dllexport) void KeInputSubmitMouseAbsolute(const INPUT_MOUSE_ABSOLUTE KiInputCommitMousePosition(context, event->x, event->y); } -// Implements the input Submit Mouse Absolute Scaled operation. __declspec(dllexport) void KeInputSubmitMouseAbsoluteScaled(uint32_t rawX, uint32_t rawY, uint32_t maxX, uint32_t maxY, int32_t wheel, uint8_t buttons) { KE_INPUT_CONTEXT* context = &gDefaultInputContext; int32_t bw = context->MouseBoundsWidth; @@ -212,7 +205,6 @@ __declspec(dllexport) void KeInputSubmitMouseAbsoluteScaled(uint32_t rawX, uint3 KeInputSubmitMouseAbsolute(&ev); } -// Implements the input Mouse Set Position operation. void KeInputMouseSetPosition(int32_t x, int32_t y) { KE_INPUT_CONTEXT* context = &gDefaultInputContext; int32_t bw = context->MouseBoundsWidth; @@ -227,7 +219,6 @@ void KeInputMouseSetPosition(int32_t x, int32_t y) { context->MouseY = y; } -// Implements the input Mouse Set Bounds operation. void KeInputMouseSetBounds(int32_t w, int32_t h) { KE_INPUT_CONTEXT* context = &gDefaultInputContext; if (w < 1) w = 1; diff --git a/code/kernel/ke_irp.c b/code/kernel/ke_irp.c index cc0053e..6462f22 100644 --- a/code/kernel/ke_irp.c +++ b/code/kernel/ke_irp.c @@ -21,7 +21,6 @@ __declspec(dllexport) void IrpQueueInit(IRP_QUEUE* q, struct SEMAPHORE* sem) { LIST_INIT(&q->Head); } -// Implements the irp Queue Enqueue operation. __declspec(dllexport) void IrpQueueEnqueue(IRP_QUEUE* q, IRP* irp) { uintptr_t flags = KeAcquireSpinlock(&q->Lock); if (irp->Flags & IRP_FLAG_PRIORITY) @@ -32,7 +31,6 @@ __declspec(dllexport) void IrpQueueEnqueue(IRP_QUEUE* q, IRP* irp) { KeSignalSemaphore((SEMAPHORE*)q->Semaphore); } -// Implements the irp Queue Dequeue operation. __declspec(dllexport) IRP* IrpQueueDequeue(IRP_QUEUE* q) { uintptr_t flags = KeAcquireSpinlock(&q->Lock); LIST_ENTRY* node = ListPopHead(&q->Head); @@ -62,7 +60,6 @@ __declspec(dllexport) void IrpQueueCancelAllWithCallback(IRP_QUEUE* q, } } -// Implements the irp Queue Cancel All operation. __declspec(dllexport) void IrpQueueCancelAll(IRP_QUEUE* q, KSTATUS status) { IrpQueueCancelAllWithCallback(q, status, (IRP_QUEUE_CANCEL_CALLBACK)0, (void*)0); } @@ -88,7 +85,6 @@ __declspec(dllexport) void IoDestroyRemoveLock(IO_REMOVE_LOCK* lock) { } } -// Implements the acquire Remove Lock operation. __declspec(dllexport) KSTATUS IoAcquireRemoveLock(IO_REMOVE_LOCK* lock, IRP* irp) { (void)irp; if (!lock) return NTLSTATUS_INVALID_PARAMETER; @@ -179,7 +175,6 @@ __declspec(dllexport) IO_STACK_LOCATION* IoGetNextIrpStackLocation(IRP* irp) { return &irp->Stack[irp->CurrentLocation + 1u]; } -// Implements the skip Current Irp Stack Location operation. __declspec(dllexport) void IoSkipCurrentIrpStackLocation(IRP* irp) { if (!irp) return; if (irp->CurrentLocation + 1u < irp->StackCount) diff --git a/code/kernel/ke_irq.c b/code/kernel/ke_irq.c index b5f8358..101ddcb 100644 --- a/code/kernel/ke_irq.c +++ b/code/kernel/ke_irq.c @@ -1,136 +1,643 @@ -// Interrupt manager. This file owns IRQ routing, handler dispatch, and post-interrupt scheduling hooks. +// Interrupt manager. Per-CPU vector ownership is independent of physical sources. #include #include #include -#include +#include #include #include #include #include -#include #include +#include +#include -#define MAX_IRQS 24 -#define MAX_IRQ_HANDLERS 8 -#define MSI_IRQ_FIRST 16u -#define MSI_IRQ_LAST 23u +#define KI_INTERRUPT_ROUTES 256u +#define KI_INTERRUPT_HANDLERS 512u -typedef struct IRQ_HANDLER_LIST { - void (*Handlers[MAX_IRQ_HANDLERS])(void); - uint8_t Count; -} IRQ_HANDLER_LIST; +typedef struct KI_INTERRUPT_ROUTE KI_INTERRUPT_ROUTE; +struct KE_INTERRUPT { + KE_INTERRUPT_ROUTINE Routine; + void* Context; + KI_INTERRUPT_ROUTE* Route; + KE_INTERRUPT_MESSAGE_PROGRAM Program; + void* ProgramContext; + uint64_t Affinity; + struct KE_INTERRUPT* Next; + bool Used; +}; -static IRQ_HANDLER_LIST gIrqHandlers[MAX_IRQS]; -static bool gIrqSoftwareVector[MAX_IRQS]; +struct KI_INTERRUPT_ROUTE { + KE_INTERRUPT* Handlers; + uint32_t Gsi; + uint32_t Cpu; + uint8_t Vector; + uint16_t Flags; + bool Used; + bool Message; + bool Draining; + bool Closing; + bool MessageActive; + volatile long Active; + volatile long Enabled; + volatile uint64_t Delivered; +}; + +static KI_INTERRUPT_ROUTE gRoutes[KI_INTERRUPT_ROUTES]; +static KE_INTERRUPT gHandlers[KI_INTERRUPT_HANDLERS]; +static KI_INTERRUPT_ROUTE* volatile gCpuVectors[KE_MAX_CPUS][256]; +// A reader is registered before it resolves the route pointer. A retired route +// waits for all readers on its former CPU/vector before releasing handler state. +static volatile long gCpuVectorReaders[KE_MAX_CPUS][256]; +// Vector reservations outlive publication while a route is draining. +static bool gCpuVectorReserved[KE_MAX_CPUS][256]; +static bool gCpuVectorRetired[KE_MAX_CPUS][256]; +static uint8_t gCpuVectorQuietTicks[KE_MAX_CPUS][256]; +static SPINLOCK gInterruptLock = SPINLOCK_INIT; static const HAL_API* gHal; +static void (*gLocalTimerHandlers[2])(void); +static uint8_t gLocalTimerHandlerCount; +static uint32_t gPlacementCursor; -// Implements the irq To Irql operation. -static KIRQL KiIrqToIrql(uint8_t irq) { - uint32_t level = (uint32_t)DIRQL_BASE + (uint32_t)irq; - if (level >= HIGH_LEVEL) - level = (uint32_t)(HIGH_LEVEL - 1); +static KIRQL KiVectorIrql(uint8_t vector) { + uint32_t level = (uint32_t)DIRQL_BASE + (uint32_t)((vector >> 4u) - 3u); + if (level >= HIGH_LEVEL) level = HIGH_LEVEL - 1u; return (KIRQL)level; } -// Implements the irq Initialize operation. void KeIrqInitialize(const HAL_API* hal) { - if (!hal || !hal->InterruptController.RouteIrq || !hal->InterruptController.SendEoi) - KePanic(KE_PANIC_CODE_INIT, "IRQ: invalid interrupt-controller API during initialization\n"); + if (!hal || !hal->InterruptController.SendEoi || + !hal->InterruptController.RouteGsi || !hal->InterruptController.ResolveIsa || + !hal->InterruptController.ComposeMsi) + KePanic(KE_PANIC_CODE_INIT, "IRQ: incomplete interrupt-controller API\n"); gHal = hal; } -// Implements the irq Allocate Msi Vector operation. -__declspec(dllexport) KSTATUS KeIrqAllocateMsiVector(uint8_t* outIrq) { - if (!outIrq) return NTLSTATUS_INVALID_PARAMETER; - - for (uint8_t irq = MSI_IRQ_FIRST; irq <= MSI_IRQ_LAST; irq++) { - IRQ_HANDLER_LIST* list = &gIrqHandlers[irq]; - if (!gIrqSoftwareVector[irq] && list->Count == 0) { - gIrqSoftwareVector[irq] = true; - *outIrq = irq; - DbgPrint("KeIrq: allocated MSI vector slot IRQ %u vector 0x%02x\n", - irq, 0x20u + irq); - return NTLSTATUS_SUCCESS; - } - } - - return NTLSTATUS_NO_MEMORY; +static bool KiCpuAvailable(uint32_t index, uint64_t affinity) { + if (index >= gCpuCount || index >= KE_MAX_CPUS || + (affinity && !(affinity & (1ull << index)))) return false; + KCPU* cpu = KeGetCpuByIndex(index); + return cpu && (cpu->IsBootProcessor || cpu->State >= KeCpuSchedulerActive) && + cpu->HardwareId <= 255u; } -// Implements the irq Register operation. -__declspec(dllexport) void KeIrqRegister(uint8_t irq, void (*handler)(void)) { - if (irq >= MAX_IRQS || !handler) return; - if (!gHal) - KePanic(KE_PANIC_CODE_INIT, "IRQ: registration before interrupt-manager initialization\n"); +static bool KiPickVector(uint64_t affinity, uint32_t* cpuOut, uint8_t* vectorOut) { + uint32_t count = gCpuCount; + if (!count || count > KE_MAX_CPUS) count = 1; + // Rotate the first candidate CPU, and allocate the least occupied vector. + uint32_t start = gPlacementCursor++ % count; + uint32_t bestLoad = UINT32_MAX; + bool found = false; + for (uint32_t i = 0; i < count; i++) { + uint32_t cpu = (start + i) % count; + if (!KiCpuAvailable(cpu, affinity)) continue; + uint32_t occupied = 0; + for (uint32_t v = KE_VECTOR_DEVICE_FIRST; v <= KE_VECTOR_DEVICE_LAST; v++) + if (gCpuVectorReserved[cpu][v]) occupied++; + if (occupied >= KE_VECTOR_DEVICE_LAST - KE_VECTOR_DEVICE_FIRST + 1u || occupied >= bestLoad) + continue; + for (uint32_t v = KE_VECTOR_DEVICE_FIRST; v <= KE_VECTOR_DEVICE_LAST; v++) { + if (!gCpuVectorReserved[cpu][v]) { + bestLoad = occupied; + *cpuOut = cpu; + *vectorOut = (uint8_t)v; + found = true; + break; + } + } + } + return found; +} - IRQ_HANDLER_LIST* list = &gIrqHandlers[irq]; - for (uint8_t i = 0; i < list->Count; i++) { - if (list->Handlers[i] == handler) - return; +static KSTATUS KiReserveInterrupt(bool message, uint32_t gsi, uint16_t flags, + uint64_t affinity, KE_INTERRUPT_ROUTINE routine, void* context, + KE_INTERRUPT** out) { + if (!out || !routine || !gHal) return NTLSTATUS_INVALID_PARAMETER; + *out = (KE_INTERRUPT*)0; + uintptr_t cookie = KeAcquireSpinlock(&gInterruptLock); + KI_INTERRUPT_ROUTE* route = (KI_INTERRUPT_ROUTE*)0; + if (!message) { + for (uint32_t i = 0; i < KI_INTERRUPT_ROUTES; i++) { + if (gRoutes[i].Used && !gRoutes[i].Message && gRoutes[i].Gsi == gsi) { + if (gRoutes[i].Draining || gRoutes[i].Closing) { + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_NOT_SUPPORTED; + } + if (gRoutes[i].Flags != flags || + (affinity && !(affinity & (1ull << gRoutes[i].Cpu)))) { + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_INVALID_PARAMETER; + } + route = &gRoutes[i]; + break; + } + } + } + bool newRoute = route == 0; + uint32_t cpu = 0; + uint8_t vector = 0; + if (newRoute) { + if (!KiPickVector(affinity, &cpu, &vector)) { + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_NO_MEMORY; + } + for (uint32_t i = 0; i < KI_INTERRUPT_ROUTES; i++) + if (!gRoutes[i].Used) { route = &gRoutes[i]; break; } + if (!route) { + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_NO_MEMORY; + } + } + KE_INTERRUPT* handler = 0; + for (uint32_t i = 0; i < KI_INTERRUPT_HANDLERS; i++) + if (!gHandlers[i].Used) { handler = &gHandlers[i]; break; } + if (!handler) { + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_NO_MEMORY; + } + if (newRoute) { + route->Used = true; + route->Message = message; + route->Draining = false; + route->Closing = false; + route->MessageActive = false; + route->Gsi = gsi; + route->Cpu = cpu; + route->Vector = vector; + route->Flags = flags; + route->Handlers = 0; + route->Active = 0; + route->Enabled = 0; + route->Delivered = 0; + gCpuVectorReserved[cpu][vector] = true; + gCpuVectorRetired[cpu][vector] = false; + gCpuVectorQuietTicks[cpu][vector] = 0; + _InterlockedExchangePointer((void* volatile*)&gCpuVectors[cpu][vector], route); + } + handler->Used = true; + handler->Routine = routine; + handler->Context = context; + handler->Route = route; + handler->Program = 0; + handler->ProgramContext = 0; + handler->Affinity = affinity; + handler->Next = route->Handlers; + route->Handlers = handler; + KeReleaseSpinlock(&gInterruptLock, cookie); + if (newRoute && !message) { + KCPU* target = KeGetCpuByIndex(cpu); + KSTATUS st = gHal->InterruptController.RouteGsi(gsi, vector, + target->HardwareId, flags, true); + if (!KSUCCESS(st)) { + KeInterruptDisconnect(handler); + return st; + } + _InterlockedExchange(&route->Enabled, 1); + (void)gHal->InterruptController.MaskGsi(gsi, false); + } else if (newRoute) { + _InterlockedExchange(&route->Enabled, 1); + } + *out = handler; + return NTLSTATUS_SUCCESS; +} + +__declspec(dllexport) KSTATUS KeInterruptConnectGsi(uint32_t gsi, uint16_t flags, + uint64_t affinity, KE_INTERRUPT_ROUTINE routine, void* context, KE_INTERRUPT** out) { + return KiReserveInterrupt(false, gsi, flags, affinity, routine, context, out); +} + +__declspec(dllexport) KSTATUS KeInterruptConnectIsa(uint8_t isaIrq, uint16_t sourceFlags, uint64_t affinity, + KE_INTERRUPT_ROUTINE routine, void* context, KE_INTERRUPT** out) { + uint32_t gsi; + uint16_t flags; + if (!gHal || !gHal->InterruptController.ResolveIsa) + return NTLSTATUS_INVALID_PARAMETER; + KSTATUS st = gHal->InterruptController.ResolveIsa(isaIrq, &gsi, &flags); + if (!KSUCCESS(st)) return st; + if (sourceFlags) flags = sourceFlags; + return KiReserveInterrupt(false, gsi, flags, affinity, routine, context, out); +} + +__declspec(dllexport) KSTATUS KeInterruptReserveMessage(uint64_t affinity, + KE_INTERRUPT_ROUTINE routine, void* context, KE_INTERRUPT** out) { + return KiReserveInterrupt(true, UINT32_MAX, 0, affinity, routine, context, out); +} + +__declspec(dllexport) KSTATUS KeInterruptComposeMessage(const KE_INTERRUPT* interrupt, + NTL_DDK_MSI_MESSAGE* out) { + if (!interrupt || !out || !gHal) return NTLSTATUS_INVALID_PARAMETER; + uintptr_t cookie = KeAcquireSpinlock(&gInterruptLock); + if (!interrupt->Used || !interrupt->Route || + !interrupt->Route->Message || interrupt->Route->Draining) { + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_INVALID_PARAMETER; + } + const KI_INTERRUPT_ROUTE* route = interrupt->Route; + const KCPU* cpu = KeGetCpuByIndex(route->Cpu); + HAL_MSI_MESSAGE message; + KSTATUS st = cpu ? gHal->InterruptController.ComposeMsi( + cpu->HardwareId, route->Vector, &message) : NTLSTATUS_INVALID_PARAMETER; + KeReleaseSpinlock(&gInterruptLock, cookie); + if (!KSUCCESS(st)) return st; + out->Address = message.Address; + out->Data = message.Data; + out->Reserved = 0; + return NTLSTATUS_SUCCESS; +} + +__declspec(dllexport) KSTATUS KeInterruptQuery(const KE_INTERRUPT* interrupt, + KE_INTERRUPT_INFO* out) { + if (!interrupt || !out) return NTLSTATUS_INVALID_PARAMETER; + uintptr_t cookie = KeAcquireSpinlock(&gInterruptLock); + if (!interrupt->Used || !interrupt->Route || interrupt->Route->Draining) { + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_INVALID_PARAMETER; + } + const KI_INTERRUPT_ROUTE* route = interrupt->Route; + const KCPU* cpu = KeGetCpuByIndex(route->Cpu); + out->CpuIndex = route->Cpu; + out->HardwareId = cpu ? cpu->HardwareId : UINT32_MAX; + out->Gsi = route->Gsi; + out->Flags = route->Flags; + out->Vector = route->Vector; + out->IsMessage = route->Message ? 1u : 0u; + out->Delivered = route->Delivered; + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_SUCCESS; +} + +// A message device registers its update operation once PCI has enabled the source. +__declspec(dllexport) KSTATUS KeInterruptBindMessageSource(KE_INTERRUPT* interrupt, + KE_INTERRUPT_MESSAGE_PROGRAM program, void* context) { + if (!interrupt || !program) return NTLSTATUS_INVALID_PARAMETER; + uintptr_t cookie = KeAcquireSpinlock(&gInterruptLock); + if (!interrupt->Used || !interrupt->Route || !interrupt->Route->Message || + (interrupt->Route->Draining || interrupt->Route->Closing) || interrupt->Program) { + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_INVALID_PARAMETER; + } + interrupt->Program = program; + interrupt->ProgramContext = context; + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_SUCCESS; +} + +// The bus owner enables migration only after the device source is programmed. +__declspec(dllexport) KSTATUS KeInterruptActivateMessage(KE_INTERRUPT* interrupt) { + if (!interrupt) return NTLSTATUS_INVALID_PARAMETER; + uintptr_t cookie = KeAcquireSpinlock(&gInterruptLock); + if (!interrupt->Used || !interrupt->Route || !interrupt->Route->Message || + (interrupt->Route->Draining || interrupt->Route->Closing) || !interrupt->Program) { + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_INVALID_PARAMETER; + } + interrupt->Route->MessageActive = true; + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_SUCCESS; +} + +// Moves the complete physical source to one new CPU/vector, including PCI +// message programming. The old vector remains quarantined through APIC drain. +__declspec(dllexport) KSTATUS KeInterruptSetAffinity(KE_INTERRUPT* interrupt, + uint64_t permittedCpuMask) { + if (!interrupt || !permittedCpuMask || !gHal || + KeGetCurrentIrql() != PASSIVE_LEVEL || KeGetCurrentCpu()->InterruptDepth) + return NTLSTATUS_INVALID_PARAMETER; + + uintptr_t cookie = KeAcquireSpinlock(&gInterruptLock); + if (!interrupt->Used || !interrupt->Route || + interrupt->Route->Draining || interrupt->Route->Closing) { + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_INVALID_PARAMETER; + } + KI_INTERRUPT_ROUTE* route = interrupt->Route; + if (route->Message && !route->MessageActive) { + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_NOT_SUPPORTED; + } + // One shared line must satisfy every handler's affinity constraint. + for (KE_INTERRUPT* h = route->Handlers; h; h = h->Next) { + if (h->Affinity && !(h->Affinity & permittedCpuMask)) { + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_NOT_SUPPORTED; + } + if (route->Message && (!h->Program || h != interrupt)) { + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_NOT_SUPPORTED; + } + } + for (KE_INTERRUPT* h = route->Handlers; h; h = h->Next) + if (h->Affinity) permittedCpuMask &= h->Affinity; + if (!permittedCpuMask) { + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_NOT_SUPPORTED; + } + if (permittedCpuMask & (1ull << route->Cpu)) { + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_SUCCESS; + } + uint32_t newCpu = 0; + uint8_t newVector = 0; + if (!KiPickVector(permittedCpuMask, &newCpu, &newVector)) { + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_NO_MEMORY; + } + const uint32_t oldCpu = route->Cpu; + const uint8_t oldVector = route->Vector; + gCpuVectorReserved[newCpu][newVector] = true; + route->Draining = true; + KeReleaseSpinlock(&gInterruptLock, cookie); + + NTL_DDK_MSI_MESSAGE updated = {0}; + if (route->Message) { + const KCPU* destination = KeGetCpuByIndex(newCpu); + HAL_MSI_MESSAGE message; + KSTATUS st = gHal->InterruptController.ComposeMsi(destination->HardwareId, + newVector, &message); + if (!KSUCCESS(st)) goto rollback_reservation; + updated.Address = message.Address; + updated.Data = message.Data; + st = interrupt->Program(interrupt->ProgramContext, KeInterruptMessageQuiesce, 0); + if (!KSUCCESS(st)) goto rollback_reservation; + } else { + KSTATUS st = gHal->InterruptController.MaskGsi(route->Gsi, true); + if (!KSUCCESS(st)) goto rollback_reservation; } - if (list->Count >= MAX_IRQ_HANDLERS) { - DbgPrint("KeIrqRegister: IRQ %u handler table full\n", irq); + _InterlockedExchange(&route->Enabled, 0); + _InterlockedExchangePointer((void* volatile*)&gCpuVectors[oldCpu][oldVector], 0); + uint32_t spins = 0; + while (route->Active || gCpuVectorReaders[oldCpu][oldVector]) { + if (++spins == 100000000u) + KePanic(KE_PANIC_CODE_DRIVER, "IRQ: affinity migration drain timeout\n"); + _mm_pause(); + } + + KSTATUS update = NTLSTATUS_SUCCESS; + if (route->Message) + update = interrupt->Program(interrupt->ProgramContext, + KeInterruptMessageProgram, &updated); + else { + const KCPU* destination = KeGetCpuByIndex(newCpu); + update = gHal->InterruptController.RouteGsi(route->Gsi, newVector, + destination->HardwareId, route->Flags, true); + } + if (!KSUCCESS(update)) { + // Restore the existing route and re-enable its original source. + if (route->Message) { + const KCPU* previous = KeGetCpuByIndex(oldCpu); + HAL_MSI_MESSAGE msg; + if (!KSUCCESS(gHal->InterruptController.ComposeMsi(previous->HardwareId, + oldVector, &msg))) + KePanic(KE_PANIC_CODE_DRIVER, "IRQ: cannot restore original MSI route\n"); + NTL_DDK_MSI_MESSAGE original = {msg.Address, msg.Data, 0}; + if (!KSUCCESS(interrupt->Program(interrupt->ProgramContext, + KeInterruptMessageProgram, &original))) + KePanic(KE_PANIC_CODE_DRIVER, "IRQ: cannot restore MSI message\n"); + } else { + const KCPU* previous = KeGetCpuByIndex(oldCpu); + if (!KSUCCESS(gHal->InterruptController.RouteGsi(route->Gsi, oldVector, + previous->HardwareId, route->Flags, true))) + KePanic(KE_PANIC_CODE_DRIVER, "IRQ: cannot restore original GSI route\n"); + } + _InterlockedExchangePointer((void* volatile*)&gCpuVectors[oldCpu][oldVector], route); + _InterlockedExchange(&route->Enabled, 1); + if (route->Message) { + if (!KSUCCESS(interrupt->Program(interrupt->ProgramContext, + KeInterruptMessageResume, 0))) + KePanic(KE_PANIC_CODE_DRIVER, "IRQ: MSI restore resume failed\n"); + } else (void)gHal->InterruptController.MaskGsi(route->Gsi, false); + cookie = KeAcquireSpinlock(&gInterruptLock); + route->Draining = false; + gCpuVectorReserved[newCpu][newVector] = false; + KeReleaseSpinlock(&gInterruptLock, cookie); + return update; + } + + cookie = KeAcquireSpinlock(&gInterruptLock); + route->Cpu = newCpu; + route->Vector = newVector; + gCpuVectorRetired[oldCpu][oldVector] = true; + gCpuVectorQuietTicks[oldCpu][oldVector] = 0; + _InterlockedExchangePointer((void* volatile*)&gCpuVectors[newCpu][newVector], route); + _InterlockedExchange(&route->Enabled, 1); + KeReleaseSpinlock(&gInterruptLock, cookie); + + if (route->Message) { + if (!KSUCCESS(interrupt->Program(interrupt->ProgramContext, + KeInterruptMessageResume, 0))) + KePanic(KE_PANIC_CODE_DRIVER, "IRQ: MSI migration resume failed\n"); + } else if (!KSUCCESS(gHal->InterruptController.MaskGsi(route->Gsi, false))) + KePanic(KE_PANIC_CODE_DRIVER, "IRQ: GSI migration unmask failed\n"); + cookie = KeAcquireSpinlock(&gInterruptLock); + route->Draining = false; + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_SUCCESS; + +rollback_reservation: + cookie = KeAcquireSpinlock(&gInterruptLock); + gCpuVectorReserved[newCpu][newVector] = false; + route->Draining = false; + KeReleaseSpinlock(&gInterruptLock, cookie); + return NTLSTATUS_NOT_SUPPORTED; +} + +// The scheduler must evacuate every device route before stopping a processor. +KSTATUS KiInterruptPrepareCpuOffline(uint32_t cpuIndex) { + if (cpuIndex >= gCpuCount || cpuIndex >= KE_MAX_CPUS || + KeGetCurrentIrql() != PASSIVE_LEVEL) return NTLSTATUS_INVALID_PARAMETER; + uint64_t allowed = 0; + for (uint32_t i = 0; i < gCpuCount && i < 64u; i++) + if (i != cpuIndex && KiCpuAvailable(i, 0)) allowed |= 1ull << i; + if (!allowed) return NTLSTATUS_NOT_SUPPORTED; + for (uint32_t i = 0; i < KI_INTERRUPT_ROUTES; i++) { + KI_INTERRUPT_ROUTE* route = &gRoutes[i]; + if (route->Used && route->Cpu == cpuIndex && route->Handlers) { + KSTATUS st = KeInterruptSetAffinity(route->Handlers, allowed); + if (!KSUCCESS(st)) return st; + } + } + return NTLSTATUS_SUCCESS; +} + +// Serializes device-source disable with affinity migration. A caller must +// close the route before masking the PCI source, preventing a racing resume. +__declspec(dllexport) void KeInterruptBeginDisconnect(KE_INTERRUPT* interrupt) { + if (!interrupt || KeGetCurrentIrql() != PASSIVE_LEVEL || + KeGetCurrentCpu()->InterruptDepth) + KePanic(KE_PANIC_CODE_DRIVER, "IRQ: invalid disconnect preparation context\n"); + for (uint32_t spins = 0;; spins++) { + uintptr_t cookie = KeAcquireSpinlock(&gInterruptLock); + if (!interrupt->Used || !interrupt->Route) { + KeReleaseSpinlock(&gInterruptLock, cookie); + return; + } + KI_INTERRUPT_ROUTE* route = interrupt->Route; + if (!route->Draining && !route->Closing) { + route->Closing = true; + KeReleaseSpinlock(&gInterruptLock, cookie); + return; + } + KeReleaseSpinlock(&gInterruptLock, cookie); + if (spins >= 100000000u) + KePanic(KE_PANIC_CODE_DRIVER, "IRQ: disconnect serialization timed out\n"); + _mm_pause(); + } +} + +// Disconnect runs in thread context after the device has stopped producing messages. +// The route is unpublished before draining readers, so a concurrent dispatcher +// either holds a counted reference or observes an empty vector. +__declspec(dllexport) void KeInterruptDisconnect(KE_INTERRUPT* interrupt) { + if (!interrupt) return; + if (KeGetCurrentCpu()->InterruptDepth || KeGetCurrentIrql() != PASSIVE_LEVEL) + KePanic(KE_PANIC_CODE_DRIVER, "IRQ: disconnect requires PASSIVE_LEVEL\n"); + + // PCI callers have already serialized source disable. A direct GSI + // caller prepares the route here before masking it inside this routine. + uintptr_t cookie = KeAcquireSpinlock(&gInterruptLock); + if (!interrupt->Used || !interrupt->Route) { + KeReleaseSpinlock(&gInterruptLock, cookie); return; } + KI_INTERRUPT_ROUTE* route = interrupt->Route; + if (!route->Closing) { + KeReleaseSpinlock(&gInterruptLock, cookie); + KeInterruptBeginDisconnect(interrupt); + cookie = KeAcquireSpinlock(&gInterruptLock); + route = interrupt->Route; + if (!route) { KeReleaseSpinlock(&gInterruptLock, cookie); return; } + } + if (route->Draining) { + KeReleaseSpinlock(&gInterruptLock, cookie); + KePanic(KE_PANIC_CODE_DRIVER, "IRQ: unexpected concurrent route drain\n"); + } + route->Draining = true; + _InterlockedExchange(&route->Enabled, 0); + if (!route->Message) + (void)gHal->InterruptController.MaskGsi(route->Gsi, true); + const uint32_t cpu = route->Cpu; + const uint8_t vector = route->Vector; + _InterlockedExchangePointer((void* volatile*)&gCpuVectors[cpu][vector], 0); + KeReleaseSpinlock(&gInterruptLock, cookie); - list->Handlers[list->Count++] = handler; - if (!gIrqSoftwareVector[irq]) - gHal->InterruptController.RouteIrq(irq); -} - -// Implements the irq Dispatch operation. -void KeIrqDispatch(uint8_t irq) { - if (!gHal) - KePanic(KE_PANIC_CODE_INIT, "IRQ: dispatch before interrupt-manager initialization, irq=%u\n", irq); - - KIRQL targetIrql = KiIrqToIrql(irq); - KIRQL currentIrql = KeGetCurrentIrql(); - - // Do not ever lower IRQL on interrupt entry. Nested IRQs are not expected - // while IF is clear, but preserving monotonic IRQL keeps nesting safe. - if (targetIrql < currentIrql) - targetIrql = currentIrql; - - KIRQL oldIrql = KeRaiseIrql(targetIrql); - - if (irq == KE_VECTOR_RESCHEDULE_IPI) { - // Nothing to do here. The sender has already set this CPU's - // ReschedulePending flag. KiExitInterrupt consumes it after EOI and - // after the interrupted frame unwinds to PASSIVE_LEVEL. - } else if (irq < MAX_IRQS) { - IRQ_HANDLER_LIST* list = &gIrqHandlers[irq]; - for (uint8_t i = 0; i < list->Count; i++) { - if (list->Handlers[i]) - list->Handlers[i](); - } + // Drain both ISRs already invoking callbacks and readers that fetched the + // route just before the unpublish. Reserved vectors remain unavailable. + uint32_t spins = 0; + while (route->Active || gCpuVectorReaders[cpu][vector]) { + if (++spins == 100000000u) + KePanic(KE_PANIC_CODE_DRIVER, "IRQ: route rundown timed out cpu=%u vector=%02x\n", + cpu, vector); + _mm_pause(); } - // Handlers are no longer allowed to context-switch directly. Timer IRQs - // only request rescheduling; KiExitInterrupt performs the switch after this - // function returns, so the EOI is guaranteed to be sent first. Keep the - // software level at DIRQL until after the controller has been acknowledged. - gHal->InterruptController.SendEoi(); + cookie = KeAcquireSpinlock(&gInterruptLock); + KE_INTERRUPT** link = &route->Handlers; + while (*link && *link != interrupt) link = &(*link)->Next; + if (*link != interrupt) + KePanic(KE_PANIC_CODE_DRIVER, "IRQ: missing handler during disconnect\n"); + *link = interrupt->Next; + interrupt->Used = false; + interrupt->Route = 0; + interrupt->Routine = 0; + interrupt->Context = 0; + interrupt->Program = 0; + interrupt->ProgramContext = 0; + interrupt->Affinity = 0; + interrupt->Next = 0; + if (!route->Handlers) { + route->Used = false; + // Retain the vector while the target APIC drains any pending delivery. + // Only its target CPU can inspect its IRR and ISR registers. + gCpuVectorRetired[cpu][vector] = true; + gCpuVectorQuietTicks[cpu][vector] = 0; + } else { + _InterlockedExchangePointer((void* volatile*)&gCpuVectors[cpu][vector], route); + _InterlockedExchange(&route->Enabled, 1); + if (!route->Message) + (void)gHal->InterruptController.MaskGsi(route->Gsi, false); + } + route->Draining = false; + route->Closing = false; + KeReleaseSpinlock(&gInterruptLock, cookie); +} +// The local timer gives a retiring vector a grace period on its owning CPU. +// Source drivers must disable message generation before disconnecting. A +// vector is reusable after consecutive timer checks find no APIC delivery. +static void KiReapRetiredVectors(void) { + const uint32_t cpu = KeGetCurrentCpuIndex(); + if (cpu >= KE_MAX_CPUS) return; + uintptr_t cookie = KeAcquireSpinlock(&gInterruptLock); + for (uint32_t v = KE_VECTOR_DEVICE_FIRST; v <= KE_VECTOR_DEVICE_LAST; v++) { + if (!gCpuVectorRetired[cpu][v]) continue; + if (gCpuVectorReaders[cpu][v] || + gHal->InterruptController.VectorPending((uint8_t)v)) { + gCpuVectorQuietTicks[cpu][v] = 0; + } else if (++gCpuVectorQuietTicks[cpu][v] >= 3u) { + gCpuVectorRetired[cpu][v] = false; + gCpuVectorReserved[cpu][v] = false; + gCpuVectorQuietTicks[cpu][v] = 0; + } + } + KeReleaseSpinlock(&gInterruptLock, cookie); +} + +void KeIrqRegisterLocalTimerHandler(void (*handler)(void)) { + if (!handler || !gHal) + KePanic(KE_PANIC_CODE_INIT, "IRQ: invalid local timer registration\n"); + for (uint8_t i = 0; i < gLocalTimerHandlerCount; i++) + if (gLocalTimerHandlers[i] == handler) return; + if (gLocalTimerHandlerCount >= 2u) + KePanic(KE_PANIC_CODE_INIT, "IRQ: local timer handler count exceeded\n"); + gLocalTimerHandlers[gLocalTimerHandlerCount++] = handler; +} + +void KeIrqDispatch(uint8_t vector) { + if (!gHal) KePanic(KE_PANIC_CODE_INIT, "IRQ: uninitialized dispatch\n"); + if (vector == KE_VECTOR_SPURIOUS) return; + KIRQL target = (vector >= KE_VECTOR_DEVICE_FIRST && vector <= KE_VECTOR_DEVICE_LAST) + ? KiVectorIrql(vector) : (vector == KE_VECTOR_CPU_TIMER ? (KIRQL)27 : (KIRQL)29); + if (target < KeGetCurrentIrql()) target = KeGetCurrentIrql(); + KIRQL oldIrql = KeRaiseIrql(target); + if (vector == KE_VECTOR_CPU_TIMER) { + KiReapRetiredVectors(); + for (uint8_t i = 0; i < gLocalTimerHandlerCount; i++) + gLocalTimerHandlers[i](); + } else if (vector >= KE_VECTOR_DEVICE_FIRST && vector <= KE_VECTOR_DEVICE_LAST) { + uint32_t cpu = KeGetCurrentCpuIndex(); + if (cpu < KE_MAX_CPUS) { + _InterlockedIncrement(&gCpuVectorReaders[cpu][vector]); + KI_INTERRUPT_ROUTE* route = (KI_INTERRUPT_ROUTE*) + _InterlockedCompareExchangePointer( + (void* volatile*)&gCpuVectors[cpu][vector], 0, 0); + if (route) { + _InterlockedIncrement(&route->Active); + if (route->Enabled) { + route->Delivered++; + for (KE_INTERRUPT* h = route->Handlers; h; h = h->Next) + if (h->Used && h->Routine) h->Routine(h->Context); + } + _InterlockedDecrement(&route->Active); + } + } + } + gHal->InterruptController.SendEoi(); + if (vector >= KE_VECTOR_DEVICE_FIRST && vector <= KE_VECTOR_DEVICE_LAST) { + uint32_t cpu = KeGetCurrentCpuIndex(); + if (cpu < KE_MAX_CPUS) + _InterlockedDecrement(&gCpuVectorReaders[cpu][vector]); + } KeLowerIrql(oldIrql); } -// Implements the enter Interrupt operation. void KiEnterInterrupt(void) { KeGetCurrentCpu()->InterruptDepth++; } -// Implements the exit Interrupt operation. void KiExitInterrupt(void) { KCPU* cpu = KeGetCurrentCpu(); - if (cpu->InterruptDepth) - cpu->InterruptDepth--; - - // A reschedule is only legal after the interrupt unwinds back to the - // interrupted thread's PASSIVE context. If an interrupt hit DISPATCH/DIRQL - // code, leave the request pending instead of switching out of a spinlock or - // high-IRQL region. + if (cpu->InterruptDepth) cpu->InterruptDepth--; if (cpu->InterruptDepth == 0 && KeGetCurrentIrql() == PASSIVE_LEVEL) { THREAD* current = cpu->CurrentThread; if (current && !current->IsIdleThread && current->Owner && @@ -140,13 +647,7 @@ void KiExitInterrupt(void) { KeExitThread(current, current->Owner->ExitCode); while (true) ; } - KiDrainDpcQueue(); - - // KeExitThread owns a terminal stack/rundown interval. A timer or IPI - // may interrupt it, but switching away here would abandon teardown - // before the process ExitEvent is necessarily published. The explicit - // KeYield at the end of KeExitThread performs the one terminal switch. current = cpu->CurrentThread; if (KeGetCurrentIrql() == PASSIVE_LEVEL && (!current || !KeThreadExitInProgress(current))) diff --git a/code/kernel/ke_irql.c b/code/kernel/ke_irql.c index 000dd55..f85c8fa 100644 --- a/code/kernel/ke_irql.c +++ b/code/kernel/ke_irql.c @@ -1,13 +1,13 @@ -// Kernel IRQL model. This file owns the software interrupt-priority state used by IRQ and scheduler code. +// Kernel IRQL model. This file synchronizes per-CPU IRQL with APIC task priority. #include #include #include +#include #include #include #include -// Implements the irql Name operation. __declspec(dllexport) const char* KeIrqlName(KIRQL irql) { switch (irql) { case PASSIVE_LEVEL: return "PASSIVE_LEVEL"; @@ -26,7 +26,27 @@ __declspec(dllexport) KIRQL KeGetCurrentIrql(void) { return KeGetCurrentCpu()->CurrentIrql; } -// Implements the raise Irql operation. +// IRQL classes 16-25 map to vectors 0x30-0xC0. The TPR masks the current +// class and all lower-priority external interrupts. HIGH_LEVEL masks all. +static uint8_t KiIrqlTaskPriority(KIRQL level) { + if (level == HIGH_LEVEL) return 0xFFu; + if (level >= 28u) return 0xF0u; + if (level >= DIRQL_BASE) return (uint8_t)((level - DIRQL_BASE + 3u) << 4u); + if (level >= DISPATCH_LEVEL) return 0x20u; + if (level >= APC_LEVEL) return 0x10u; + return 0u; +} + +// Applies the priority before publishing a raised IRQL and after a lowered IRQL. +static void KiSetIrql(KCPU* cpu, KIRQL level, bool raising) { + const HAL_API* hal = KeGetHal(); + if (raising && hal && hal->InterruptController.SetTaskPriority) + hal->InterruptController.SetTaskPriority(KiIrqlTaskPriority(level)); + cpu->CurrentIrql = level; + if (!raising && hal && hal->InterruptController.SetTaskPriority) + hal->InterruptController.SetTaskPriority(KiIrqlTaskPriority(level)); +} + __declspec(dllexport) KIRQL KeRaiseIrql(KIRQL newIrql) { KCPU* cpu = KeGetCurrentCpu(); KIRQL oldIrql = cpu->CurrentIrql; @@ -41,11 +61,10 @@ __declspec(dllexport) KIRQL KeRaiseIrql(KIRQL newIrql) { KeIrqlName(newIrql), (unsigned)newIrql); } - cpu->CurrentIrql = newIrql; + KiSetIrql(cpu, newIrql, true); return oldIrql; } -// Implements the lower Irql operation. __declspec(dllexport) void KeLowerIrql(KIRQL oldIrql) { KCPU* cpu = KeGetCurrentCpu(); KIRQL currentIrql = cpu->CurrentIrql; @@ -60,14 +79,13 @@ __declspec(dllexport) void KeLowerIrql(KIRQL oldIrql) { KeIrqlName(oldIrql), (unsigned)oldIrql); } - cpu->CurrentIrql = oldIrql; + KiSetIrql(cpu, oldIrql, false); if (oldIrql == PASSIVE_LEVEL && currentIrql != PASSIVE_LEVEL && (__readeflags() & 0x200u) != 0 && cpu->InterruptDepth == 0) KiDeliverKernelApcs(); } -// Implements the assert Irql operation. __declspec(dllexport) void KeAssertIrql(KIRQL expected) { KIRQL currentIrql = KeGetCurrentIrql(); if (currentIrql != expected) { @@ -77,7 +95,6 @@ __declspec(dllexport) void KeAssertIrql(KIRQL expected) { } } -// Implements the assert Irql At Or Below operation. __declspec(dllexport) void KeAssertIrqlAtOrBelow(KIRQL maxIrql) { KIRQL currentIrql = KeGetCurrentIrql(); if (currentIrql > maxIrql) { diff --git a/code/kernel/ke_power.c b/code/kernel/ke_power.c index ee4edb0..df98249 100644 --- a/code/kernel/ke_power.c +++ b/code/kernel/ke_power.c @@ -1,14 +1,14 @@ -#include +// Kernel power coordinator and optional firmware-provider binding. + #include +#include #include #include #include #include -#include -#include #include #include -#include +#include #include static SPINLOCK gPowerLock = SPINLOCK_INIT; @@ -17,70 +17,116 @@ static EVENT* gPowerComplete; static PROCESS* gInit; static uint32_t gAction; static bool gCommitted; -static const HAL_API* gButtonHal; +static bool gPolicyReady; +static bool gEarlyButtonPressed; static uint32_t gButtonAction; -static KDPC gPowerButtonDpc; +static NTL_FIRMWARE_POWER_PROVIDER gFirmwareProvider; +static bool gFirmwarePrepared; +static uint32_t gPreparedAction; KSTATUS KePowerInitialize(void) { if (gPowerRequest) return NTLSTATUS_ALREADY_EXISTS; - KSTATUS st = KeEventCreate(EventManualReset, false, &gPowerRequest); - if (!KSUCCESS(st)) return st; - st = KeEventCreate(EventManualReset, false, &gPowerComplete); - return st; + EVENT* request = NULL; + EVENT* complete = NULL; + KSTATUS status = KeEventCreate(EventManualReset, false, &request); + if (!KSUCCESS(status)) return status; + status = KeEventCreate(EventManualReset, false, &complete); + if (!KSUCCESS(status)) { + ObDereferenceObject((OBJECT*)request); + return status; + } + gPowerRequest = request; + gPowerComplete = complete; + return NTLSTATUS_SUCCESS; } -// Delivers the physical action after interrupt-exit processing. -static void KiPowerButtonDpc(KDPC* dpc, void* context, void* arg1, void* arg2) { - (void)dpc; - (void)context; - (void)arg1; - (void)arg2; - (void)KePowerRequestHardware(gButtonAction); +// The resident firmware owner may be ACPICA or another platform implementation. +__declspec(dllexport) KSTATUS KeRegisterFirmwarePowerProvider( + const NTL_FIRMWARE_POWER_PROVIDER* provider) { + if (!provider || provider->Size != sizeof(*provider) || + !provider->Prepare || !provider->Enter) + return NTLSTATUS_INVALID_PARAMETER; + uintptr_t flags = KeAcquireSpinlock(&gPowerLock); + KSTATUS status = gFirmwareProvider.Size ? NTLSTATUS_ALREADY_EXISTS : NTLSTATUS_SUCCESS; + if (KSUCCESS(status)) gFirmwareProvider = *provider; + KeReleaseSpinlock(&gPowerLock, flags); + if (KSUCCESS(status)) DbgPrint("power: firmware provider registered\n"); + return status; } -// The ACPI SCI handler only acknowledges the fixed event and queues normal work. -static void KiPowerButtonIsr(void) { - if (!gButtonHal || !gButtonHal->Power.ConsumeFixedButton || - !gButtonHal->Power.ConsumeFixedButton()) return; - (void)KeInsertQueueDpc(&gPowerButtonDpc, NULL, NULL); +// Events before system-root policy becomes available are retained once. +__declspec(dllexport) KSTATUS KeNotifyPowerButton(void) { + uintptr_t flags = KeAcquireSpinlock(&gPowerLock); + if (!gPowerRequest) { + KeReleaseSpinlock(&gPowerLock, flags); + return NTLSTATUS_NOT_SUPPORTED; + } + if (!gPolicyReady) { + gEarlyButtonPressed = true; + KeReleaseSpinlock(&gPowerLock, flags); + return NTLSTATUS_SUCCESS; + } + uint32_t action = gButtonAction; + KeReleaseSpinlock(&gPowerLock, flags); + return action ? KePowerRequestHardware(action) : NTLSTATUS_SUCCESS; } -// Reads immutable boot-time button policy and attaches it to the fixed ACPI SCI. -void KePowerInitializeButton(const HAL_API* hal) { +// System-root policy is loaded independently of the presence of a firmware driver. +void KePowerInitializePolicy(void) { char mode[24]; KSTATUS status = KeGetSettingString("power", "button", mode, sizeof(mode)); if (!KSUCCESS(status)) KePanic(KE_PANIC_CODE_INIT, "power: missing [power] button, status=0x%x\n", status); - if (strcmp(mode, "ignore") == 0) { - DbgPrint("power: ACPI power button ignored by policy\n"); - return; - } - if (strcmp(mode, "shutdown") == 0) gButtonAction = SYS_POWER_ACTION_SHUTDOWN; - else if (strcmp(mode, "restart") == 0) gButtonAction = SYS_POWER_ACTION_RESTART; - else KePanic(KE_PANIC_CODE_INIT, "power: invalid [power] button=%s\n", mode); + uint32_t action = 0; + if (strcmp(mode, "shutdown") == 0) action = SYS_POWER_ACTION_SHUTDOWN; + else if (strcmp(mode, "restart") == 0) action = SYS_POWER_ACTION_RESTART; + else if (strcmp(mode, "ignore") != 0) + KePanic(KE_PANIC_CODE_INIT, "power: invalid [power] button=%s\n", mode); - if (!hal || !hal->Power.QueryFixedButtonIrq || !hal->Power.ArmFixedButton || - !hal->Power.ConsumeFixedButton) { - DbgPrint("power: no ACPI fixed power button HAL support\n"); - return; + uintptr_t flags = KeAcquireSpinlock(&gPowerLock); + gButtonAction = action; + gPolicyReady = true; + bool pending = gEarlyButtonPressed; + bool providerPresent = gFirmwareProvider.Size != 0; + gEarlyButtonPressed = false; + KeReleaseSpinlock(&gPowerLock, flags); + DbgPrint("power: button policy=%s firmware provider=%s\n", + mode, providerPresent ? "present" : "absent"); + if (pending && action) (void)KePowerRequestHardware(action); +} + +// A provider prepares firmware while threads, device resources and AML can run. +KSTATUS KePowerPrepareFirmware(uint32_t action) { + if (action != SYS_POWER_ACTION_SHUTDOWN && action != SYS_POWER_ACTION_RESTART) + return NTLSTATUS_INVALID_PARAMETER; + NTL_FIRMWARE_POWER_PROVIDER provider; + uintptr_t flags = KeAcquireSpinlock(&gPowerLock); + provider = gFirmwareProvider; + KeReleaseSpinlock(&gPowerLock, flags); + if (!provider.Size) return NTLSTATUS_NOT_SUPPORTED; + flags = KeAcquireSpinlock(&gPowerLock); + gFirmwarePrepared = false; + gPreparedAction = 0; + KeReleaseSpinlock(&gPowerLock, flags); + KSTATUS status = provider.Prepare(provider.Context, action); + if (KSUCCESS(status)) { + flags = KeAcquireSpinlock(&gPowerLock); + gFirmwarePrepared = true; + gPreparedAction = action; + KeReleaseSpinlock(&gPowerLock, flags); } - uint8_t irq = 0; - status = hal->Power.QueryFixedButtonIrq(&irq); - if (!KSUCCESS(status)) { - DbgPrint("power: ACPI fixed button unavailable (0x%x); AML button not yet supported\n", status); - return; - } - // The IOAPIC is still masked for this IRQ. Arm the firmware source first, - // then install the kernel handler and finally unmask via KeIrqRegister. - status = hal->Power.ArmFixedButton(); - if (!KSUCCESS(status)) { - DbgPrint("power: cannot arm fixed button IRQ %u, status=0x%x\n", irq, status); - return; - } - KeInitializeDpc(&gPowerButtonDpc, KiPowerButtonDpc, NULL); - gButtonHal = hal; - KeIrqRegister(irq, KiPowerButtonIsr); - DbgPrint("power: ACPI fixed button armed on IRQ %u, action=%s\n", irq, mode); + return status; +} + +// Any returned transition leaves the HAL as the supported final fallback. +KSTATUS KePowerEnterFirmware(uint32_t action) { + NTL_FIRMWARE_POWER_PROVIDER provider; + uintptr_t flags = KeAcquireSpinlock(&gPowerLock); + bool prepared = gFirmwarePrepared && gPreparedAction == action; + provider = gFirmwareProvider; + KeReleaseSpinlock(&gPowerLock, flags); + if (!prepared || !provider.Size) return NTLSTATUS_NOT_SUPPORTED; + return provider.Enter(provider.Context, action); } void KePowerSetInitProcess(PROCESS* init) { diff --git a/code/kernel/ke_sched.c b/code/kernel/ke_sched.c index 5e2bd33..3acbd85 100644 --- a/code/kernel/ke_sched.c +++ b/code/kernel/ke_sched.c @@ -129,7 +129,6 @@ bool KiSchedulerRefreshMutexDonation(MUTEX* mutex) { return changed; } -// Implements the default Thread Affinity Mask operation. static uint64_t KiDefaultThreadAffinityMask(void) { // Normal kernel, user, and driver-created threads are boot-processor-affine by // default. Code that is explicitly audited for AP execution can widen its @@ -137,14 +136,12 @@ static uint64_t KiDefaultThreadAffinityMask(void) { return 1ULL; } -// Implements the thread Is Killed Locked operation. static bool KiThreadIsKilledLocked(const THREAD* thread) { return thread && !thread->IsIdleThread && thread->Owner && KeIsProcessTerminating(thread->Owner) && !KeThreadTerminationDeferred(thread); } -// Implements the thread Can Run On Cpu Locked operation. static bool KiThreadCanRunOnCpuLocked(const THREAD* thread, const KCPU* cpu) { if (!thread || !cpu) return false; if (thread->IsIdleThread) return thread == cpu->IdleThread; @@ -152,7 +149,6 @@ static bool KiThreadCanRunOnCpuLocked(const THREAD* thread, const KCPU* cpu) { return (thread->AffinityMask & (1ULL << cpu->CpuIndex)) != 0; } -// Implements the cpu Is Idle Locked operation. static bool KiCpuIsIdleLocked(const KCPU* cpu) { if (!cpu || cpu->State != KeCpuOnline) return false; @@ -160,7 +156,6 @@ static bool KiCpuIsIdleLocked(const KCPU* cpu) { return (!cur || cur == cpu->IdleThread || cur->State != ThreadRunning); } -// Implements the any Idle Primary For Thread Locked operation. static bool KiAnyIdlePrimaryForThreadLocked(const THREAD* thread) { if (!thread || thread->IsIdleThread) return false; @@ -193,7 +188,6 @@ static bool KiShouldDeferToIdlePrimaryLocked(KCPU* cpu, const THREAD* thread) { return KiAnyIdlePrimaryForThreadLocked(thread); } -// Implements the request Reschedule Cpu Locked operation. static void KiRequestRescheduleCpuLocked(KCPU* target) { if (!target || target->State != KeCpuOnline) return; @@ -206,7 +200,6 @@ static void KiRequestRescheduleCpuLocked(KCPU* target) { } } -// Implements the poke Runnable Cpus Locked operation. static void KiPokeRunnableCpusLocked(THREAD* thread) { if (!thread || thread->IsIdleThread) return; @@ -256,7 +249,6 @@ static void KiPokeRunnableCpusLocked(THREAD* thread) { } } -// Implements the base Quantum For Priority operation. static uint32_t KiBaseQuantumForPriority(uint32_t priority) { switch ((THREAD_PRIORITY)priority) { case PriorityHigh: return SCHED_HIGH_QUANTUM_TICKS; @@ -266,7 +258,6 @@ static uint32_t KiBaseQuantumForPriority(uint32_t priority) { } } -// Implements the compute Quantum Locked operation. static uint32_t KiComputeQuantumLocked(THREAD* thread) { if (!thread || thread == KeGetCurrentCpu()->IdleThread) return 1; @@ -288,7 +279,6 @@ static uint32_t KiComputeQuantumLocked(THREAD* thread) { return quantum ? quantum : 1; } -// Implements the refill Quantum Locked operation. static void KiRefillQuantumLocked(THREAD* thread) { if (!thread) return; thread->QuantumTicks = KiComputeQuantumLocked(thread); @@ -308,7 +298,6 @@ void KeGetSchedulerStats(KE_SCHED_STATS* out) { KeReleaseSpinlock(&gSchedLock, flags); } -// Implements the arm Post Switch Unlock operation. static void KiArmPostSwitchUnlock(THREAD* thread, uintptr_t cookie) { // The scheduler lock is intentionally held across KeSwitchContext(). The // unlock cookie belongs to the thread continuation that will resume after @@ -319,12 +308,10 @@ static void KiArmPostSwitchUnlock(THREAD* thread, uintptr_t cookie) { thread->SwitchLockCookie = cookie; } -// Implements the post Switch Unlock Cookie operation. static uintptr_t KiPostSwitchUnlockCookie(THREAD* thread) { return thread ? thread->SwitchLockCookie : 0x202ULL; } -// Implements the scheduler Bug operation. static void KiSchedulerBug(const char* where, THREAD* thread, const char* why) { KePanic(KE_PANIC_CODE_SCHEDULER, "scheduler invariant failed: %s: thread=0x%016llX tid=%u state=%u queued=%u runningCpu=%u idle=%u: %s\n", @@ -338,7 +325,6 @@ static void KiSchedulerBug(const char* where, THREAD* thread, const char* why) { why ? why : "?"); } -// Implements the assert Ready Queue Candidate Locked operation. static void KiAssertReadyQueueCandidateLocked(const char* where, THREAD* thread) { if (!thread) KiSchedulerBug(where, thread, "null thread"); @@ -352,7 +338,6 @@ static void KiAssertReadyQueueCandidateLocked(const char* where, THREAD* thread) KiSchedulerBug(where, thread, "thread still reserved/running on a CPU"); } -// Implements the assert Picked Thread Locked operation. static void KiAssertPickedThreadLocked(const char* where, THREAD* thread) { if (!thread) KiSchedulerBug(where, thread, "null picked thread"); @@ -694,7 +679,6 @@ KSTATUS KiSchedulerSetNormalPriority(THREAD* thread, THREAD_PRIORITY priority) { static bool KiAnyRunnableForCpuLocked(KCPU* cpu); -// Implements the any Runnable For Current Cpu operation. static int KiAnyRunnableForCurrentCpu(void) { KCPU* cpu = KeGetCurrentCpu(); uintptr_t flags = KeAcquireSpinlock(&gSchedLock); @@ -703,7 +687,6 @@ static int KiAnyRunnableForCurrentCpu(void) { return any; } -// Implements the idle Loop operation. static void KiIdleLoop(void) { while (true) { KCPU* cpu = KeGetCurrentCpu(); @@ -900,7 +883,6 @@ uint64_t KeGetDefaultThreadAffinityMask(void) { return KiDefaultThreadAffinityMask(); } -// Implements the ready Thread operation. void KeReadyThread(THREAD* thread) { if (!thread) return; @@ -968,7 +950,6 @@ KSTATUS KeCancelSuspendedThread(THREAD* thread) { return NTLSTATUS_SUCCESS; } -// Implements the unready Thread operation. void KeUnreadyThread(THREAD* thread) { if (!thread) return; uintptr_t flags = KeAcquireSpinlock(&gSchedLock); @@ -979,7 +960,6 @@ void KeUnreadyThread(THREAD* thread) { KeReleaseSpinlock(&gSchedLock, flags); } -// Implements the any Runnable For Cpu Locked operation. static bool KiAnyRunnableForCpuLocked(KCPU* cpu) { if (!cpu) cpu = KeGetCurrentCpu(); @@ -1028,7 +1008,6 @@ static THREAD* KiPickFromQueueLocked(KCPU* cpu, LIST_ENTRY* head) { return (THREAD*)0; } -// Implements the pick Next For Cpu operation. static THREAD* KiPickNextForCpu(KCPU* cpu) { if (!cpu) cpu = KeGetCurrentCpu(); @@ -1049,7 +1028,6 @@ static THREAD* KiPickNextForCpu(KCPU* cpu) { return cpu->IdleThread; } -// Implements the request Reschedule operation. void KiRequestReschedule(void) { KCPU* cpu = KeGetCurrentCpu(); if (cpu) @@ -1062,7 +1040,6 @@ bool KiIsReschedulePending(void) { return cpu && NtlAtomicLoad32(&cpu->ReschedulePending) != 0; } -// Implements the schedule operation. static void KiSchedule(void) { KCPU* cpu = KeGetCurrentCpu(); THREAD* cur = cpu->CurrentThread; @@ -1143,13 +1120,11 @@ static void KiSchedule(void) { KeSchedulerPostSwitch(); } -// Implements the schedule From Interrupt operation. void KiScheduleFromInterrupt(void) { if (!KiIsReschedulePending()) return; KiSchedule(); } -// Implements the scheduler Mark Thread Waiting operation. void KiSchedulerMarkThreadWaiting(THREAD* thread) { if (!thread) return; @@ -1196,7 +1171,6 @@ static void KiCancelThreadTimeoutLocked(THREAD* thread) { thread->TimeoutStatus = NTLSTATUS_SUCCESS; } -// Implements the scheduler Note Voluntary Block operation. void KiSchedulerNoteVoluntaryBlock(THREAD* thread) { if (!thread) return; uintptr_t flags = KeAcquireSpinlock(&gSchedLock); @@ -1263,7 +1237,6 @@ void KeUnblockThreadFromWaitListWithStatus(THREAD* thread, KSTATUS status) { KeReleaseSpinlock(&gSchedLock, flags); } -// Implements the scheduler Wake Thread operation. void KiSchedulerWakeThread(THREAD* thread, KSTATUS status) { uintptr_t flags = KeAcquireSpinlock(&gSchedLock); KiWakeThreadLocked(thread, status); @@ -1430,7 +1403,6 @@ static int KiRunLocalSchedulerTickLocked(KCPU* cpu, THREAD* cur, THREAD* idle) { return requestReschedule; } -// Implements the scheduler Tick operation. void KeSchedulerTick(void) { KCPU* cpu = KeGetCurrentCpu(); THREAD* cur = cpu->CurrentThread; @@ -1513,7 +1485,6 @@ KSTATUS KeArmCurrentThreadTimeout(uint64_t milliseconds, KSTATUS timeoutStatus) return NTLSTATUS_SUCCESS; } -// Implements the delay Thread operation. __declspec(dllexport) KSTATUS KeDelayThread(uint64_t milliseconds) { if (milliseconds == 0) { KeYield(); @@ -1554,7 +1525,6 @@ __declspec(dllexport) KSTATUS KeDelayThread(uint64_t milliseconds) { return KeCommitBlockThread(self, 0); } -// Implements the yield operation. __declspec(dllexport) void KeYield(void) { KeAssertIrql(PASSIVE_LEVEL); KiSchedule(); diff --git a/code/kernel/ke_semaphore.c b/code/kernel/ke_semaphore.c index 801dce1..722370c 100644 --- a/code/kernel/ke_semaphore.c +++ b/code/kernel/ke_semaphore.c @@ -8,10 +8,8 @@ #include #include -// Implements the semaphore Destroy operation. static void KiSemaphoreDestroy(OBJECT* obj) { (void)obj; } -// Implements the semaphore Create operation. __declspec(dllexport) KSTATUS KeSemaphoreCreate(int32_t initial, int32_t max, SEMAPHORE** out) { if (!out || initial < 0 || max < 1 || initial > max) return NTLSTATUS_INVALID_PARAMETER; diff --git a/code/kernel/ke_smp.c b/code/kernel/ke_smp.c index 813d52e..7aaca4a 100644 --- a/code/kernel/ke_smp.c +++ b/code/kernel/ke_smp.c @@ -108,23 +108,15 @@ static void KiSmpPoolCheckpoint(const char* phase, uint32_t cpuIndex) { (void)MmValidateKernelPool(phase ? phase : "smp"); } -// Implements the emit8 operation. static void KiEmit8(uint8_t** p, uint8_t v) { *(*p)++ = v; } -// Implements the emit16 operation. static void KiEmit16(uint8_t** p, uint16_t v) { memcpy(*p, &v, sizeof(v)); *p += sizeof(v); } -// Implements the emit32 operation. static void KiEmit32(uint8_t** p, uint32_t v) { memcpy(*p, &v, sizeof(v)); *p += sizeof(v); } -// Implements the emit64 operation. static void KiEmit64(uint8_t** p, uint64_t v) { memcpy(*p, &v, sizeof(v)); *p += sizeof(v); } -// Implements the patch16 operation. static void KiPatch16(uint8_t* base, size_t off, uint16_t v) { memcpy(base + off, &v, sizeof(v)); } -// Implements the patch32 operation. static void KiPatch32(uint8_t* base, size_t off, uint32_t v) { memcpy(base + off, &v, sizeof(v)); } -// Implements the patch64 operation. static void KiPatch64(uint8_t* base, size_t off, uint64_t v) { memcpy(base + off, &v, sizeof(v)); } -// Implements the gdt Descriptor operation. static uint64_t KiGdtDescriptor(uint32_t base, uint32_t limit, uint8_t access, uint8_t flags) { return ((uint64_t)(limit & 0xFFFF)) | ((uint64_t)(base & 0xFFFFFF) << 16) | @@ -394,7 +386,6 @@ static void KiPrepareCpuRecord(uint32_t cpuIndex, const HAL_PROCESSOR_INFO* info cpu->ReschedulePending = 0; } -// Implements the ceil Log2 U32 operation. static uint32_t KiCeilLog2U32(uint32_t value) { if (value <= 1u) return 0u; @@ -407,7 +398,6 @@ static uint32_t KiCeilLog2U32(uint32_t value) { return shift; } -// Implements the mask Width operation. static uint32_t KiMaskWidth(uint32_t shift) { if (shift >= 32u) return 0xFFFFFFFFu; @@ -451,7 +441,6 @@ static void KiReadCpuidTopologyLeaf(uint32_t leaf, KI_CPUID_TOPOLOGY_PARAMS* out } } -// Implements the detect Cpuid Topology Params operation. static KI_CPUID_TOPOLOGY_PARAMS KiDetectCpuidTopologyParams(void) { KI_CPUID_TOPOLOGY_PARAMS topo; memset(&topo, 0, sizeof(topo)); @@ -640,7 +629,6 @@ static KSTATUS KiAllocateApStack(KCPU* cpu) { return NTLSTATUS_SUCCESS; } -// Implements the ap Stage Name operation. static const char* KiApStageName(uint32_t stage) { switch (stage) { case AP_STAGE_NONE: return "none"; @@ -801,7 +789,6 @@ KSTATUS KeStartApplicationProcessors(void) { return NTLSTATUS_SUCCESS; } -// Implements the admit Application Processors To Scheduler operation. KSTATUS KeAdmitApplicationProcessorsToScheduler(void) { if (gCpuCount <= 1) { DbgPrint("SMP: no AP scheduler admission needed\n"); diff --git a/code/kernel/ke_syscall.asm b/code/kernel/ke_syscall.asm index 5ae59e1..3eb9b5a 100644 --- a/code/kernel/ke_syscall.asm +++ b/code/kernel/ke_syscall.asm @@ -1,4 +1,4 @@ -; ke_syscall.asm - INT 0x40, fault, and IRQ kernel entries (MASM64) +; ke_syscall.asm - INT 0x2F, fault, and IRQ kernel entries (MASM64) ; ; Syscall entry now builds an editable KTRAP_FRAME on the current kernel ; stack. KiExitTrapFrame commits Rip/Cs/Rflags/Rsp/Ss back to the CPU IRET @@ -64,7 +64,7 @@ KeSyscallEntry PROC mov rax, KTRAP_FRAME_MAGIC mov [rbx + TF_Magic], rax mov dword ptr [rbx + TF_Kind], KTRAP_KIND_SYSCALL - mov dword ptr [rbx + TF_Vector], 40h + mov dword ptr [rbx + TF_Vector], 02Fh mov dword ptr [rbx + TF_PreviousMode], KTRAP_MODE_USER mov [rbx + TF_Rcx], rcx @@ -781,7 +781,7 @@ IrqStub MACRO num PUBLIC KeIrqStub&num KeIrqStub&num PROC push rax - mov al, num + mov al, (030h + num) jmp KeIrqCommon KeIrqStub&num ENDP ENDM @@ -810,6 +810,156 @@ IrqStub 20 IrqStub 21 IrqStub 22 IrqStub 23 +IrqStub 24 +IrqStub 25 +IrqStub 26 +IrqStub 27 +IrqStub 28 +IrqStub 29 +IrqStub 30 +IrqStub 31 +IrqStub 32 +IrqStub 33 +IrqStub 34 +IrqStub 35 +IrqStub 36 +IrqStub 37 +IrqStub 38 +IrqStub 39 +IrqStub 40 +IrqStub 41 +IrqStub 42 +IrqStub 43 +IrqStub 44 +IrqStub 45 +IrqStub 46 +IrqStub 47 +IrqStub 48 +IrqStub 49 +IrqStub 50 +IrqStub 51 +IrqStub 52 +IrqStub 53 +IrqStub 54 +IrqStub 55 +IrqStub 56 +IrqStub 57 +IrqStub 58 +IrqStub 59 +IrqStub 60 +IrqStub 61 +IrqStub 62 +IrqStub 63 +IrqStub 64 +IrqStub 65 +IrqStub 66 +IrqStub 67 +IrqStub 68 +IrqStub 69 +IrqStub 70 +IrqStub 71 +IrqStub 72 +IrqStub 73 +IrqStub 74 +IrqStub 75 +IrqStub 76 +IrqStub 77 +IrqStub 78 +IrqStub 79 +IrqStub 80 +IrqStub 81 +IrqStub 82 +IrqStub 83 +IrqStub 84 +IrqStub 85 +IrqStub 86 +IrqStub 87 +IrqStub 88 +IrqStub 89 +IrqStub 90 +IrqStub 91 +IrqStub 92 +IrqStub 93 +IrqStub 94 +IrqStub 95 +IrqStub 96 +IrqStub 97 +IrqStub 98 +IrqStub 99 +IrqStub 100 +IrqStub 101 +IrqStub 102 +IrqStub 103 +IrqStub 104 +IrqStub 105 +IrqStub 106 +IrqStub 107 +IrqStub 108 +IrqStub 109 +IrqStub 110 +IrqStub 111 +IrqStub 112 +IrqStub 113 +IrqStub 114 +IrqStub 115 +IrqStub 116 +IrqStub 117 +IrqStub 118 +IrqStub 119 +IrqStub 120 +IrqStub 121 +IrqStub 122 +IrqStub 123 +IrqStub 124 +IrqStub 125 +IrqStub 126 +IrqStub 127 +IrqStub 128 +IrqStub 129 +IrqStub 130 +IrqStub 131 +IrqStub 132 +IrqStub 133 +IrqStub 134 +IrqStub 135 +IrqStub 136 +IrqStub 137 +IrqStub 138 +IrqStub 139 +IrqStub 140 +IrqStub 141 +IrqStub 142 +IrqStub 143 +IrqStub 144 +IrqStub 145 +IrqStub 146 +IrqStub 147 +IrqStub 148 +IrqStub 149 +IrqStub 150 +IrqStub 151 +IrqStub 152 +IrqStub 153 +IrqStub 154 +IrqStub 155 +IrqStub 156 +IrqStub 157 +IrqStub 158 +IrqStub 159 + +PUBLIC KeLocalTimerStub +KeLocalTimerStub PROC + push rax + mov al, 0E0h + jmp KeIrqCommon +KeLocalTimerStub ENDP + +PUBLIC KeSpuriousStub +KeSpuriousStub PROC + push rax + mov al, 0FFh + jmp KeIrqCommon +KeSpuriousStub ENDP PUBLIC KeRescheduleIpiStub KeRescheduleIpiStub PROC @@ -819,7 +969,7 @@ KeRescheduleIpiStub PROC KeRescheduleIpiStub ENDP KeIrqCommon PROC - ; al = irq number, original rax saved by the per-IRQ stub. + ; al = IDT vector, original rax saved by the vector stub. push rcx push rdx push r8 diff --git a/code/kernel/ke_syscall.c b/code/kernel/ke_syscall.c index ab7ffde..5394008 100644 --- a/code/kernel/ke_syscall.c +++ b/code/kernel/ke_syscall.c @@ -1,6 +1,6 @@ // Kernel syscall dispatcher. This file validates user requests and bridges user-mode ABI calls into kernel services. -// KeSyscallEntry (ke_syscall.asm) handles the INT 0x40 ring-3 -> ring-0 +// KeSyscallEntry (ke_syscall.asm) handles the INT 0x2F ring-3 -> ring-0 // transition, re-orders the arguments to match MS x64, and calls // KeSyscallDispatch with the syscall number plus at most four register arguments. // Compound operations use size-tagged request structures instead of extending @@ -135,7 +135,6 @@ static void KiFileMappingDestroy(OBJECT* obj) { } -// Implements the syscall Init operation. void KeSyscallInit(const HAL_API* hal) { gHal = hal; } @@ -301,7 +300,6 @@ static KSTATUS KiCopyInt32ToUser(int32_t* valueOut, int32_t value) { return CopyToUser(valueOut, &value, sizeof(value)); } -// Implements the mul Size operation. static bool KiMulSize(size_t a, size_t b, size_t* out) { if (!out) return false; if (a && b > ((size_t)-1) / a) return false; @@ -1044,7 +1042,6 @@ static KSTATUS KiVmProtectToPageFlags(uint32_t protect, uint64_t* flagsOut) { } } -// Implements the page Flags To Vm Protect operation. static uint32_t KiPageFlagsToVmProtect(uint64_t flags) { if (!(flags & PAGE_PRESENT)) return SYS_VM_NOACCESS; bool writable = (flags & PAGE_WRITE) != 0; @@ -2070,7 +2067,6 @@ static void SyscallUserAsyncKernelRoutine(KAPC* apc, KeGetCurrentIrql()); } -// Implements the user Async Apc Context Free operation. static void SyscallUserAsyncApcContextFree(SYS_USER_ASYNC_APC_CONTEXT* ctx) { if (!ctx) return; if (ctx->TargetThread) { @@ -2080,7 +2076,6 @@ static void SyscallUserAsyncApcContextFree(SYS_USER_ASYNC_APC_CONTEXT* ctx) { MmFreePool(ctx); } -// Implements the user Async Apc Rundown operation. static void SyscallUserAsyncApcRundown(KAPC* apc) { if (!apc) return; SYS_USER_ASYNC_APC_CONTEXT* ctx = CONTAINING_RECORD(apc, SYS_USER_ASYNC_APC_CONTEXT, KernelApc); @@ -2110,7 +2105,6 @@ static void SyscallUserAsyncNormalRoutine(void* normalContext, SyscallUserAsyncApcContextFree(ctx); } -// Implements the async File Common operation. static uint64_t SyscallAsyncFileCommon(const SYS_ASYNC_FILE_REQUEST* request, bool write) { if (!request) return NTLSTATUS_INVALID_PARAMETER; diff --git a/code/kernel/ke_thread.c b/code/kernel/ke_thread.c index d22e065..bbc6f16 100644 --- a/code/kernel/ke_thread.c +++ b/code/kernel/ke_thread.c @@ -136,7 +136,6 @@ void KeFinalizeThreadExit(THREAD* thread) { } } -// Implements the thread Destroy operation. static void KiThreadDestroy(OBJECT* obj) { THREAD* thread = CONTAINING_RECORD(obj, THREAD, Header); @@ -450,7 +449,6 @@ bool KeThreadExitInProgress(const THREAD* thread) { return thread && NtlAtomicLoad32(&thread->ExitInProgress) != 0; } -// Implements the exit Thread operation. __declspec(dllexport) void KeExitThread(THREAD* thread, int32_t code) { (void)code; if (!thread) return; @@ -601,6 +599,15 @@ static KSTATUS KiCreateKernelThread(uintptr_t fn, uintptr_t arg, ctx->Rip = (uint64_t)KeKernelThreadEntry; thread->SavedContext = ctx; + // Publish thread completion before the new kernel thread can run. + EVENT* exitEvent = (EVENT*)0; + KSTATUS eventStatus = KeEventCreate(EventManualReset, false, &exitEvent); + if (!KSUCCESS(eventStatus)) { + ObDereferenceObject(&thread->Header); + return eventStatus; + } + thread->ExitEvent = exitEvent; + // Register with the owning process. ObReferenceObject(&owner->Header); thread->Owner = owner; @@ -716,7 +723,6 @@ void KeRundownThreadWait(THREAD* thread, KSTATUS status) { routine(thread, context, status); } -// Implements the commit Block Thread operation. KSTATUS KeCommitBlockThread(THREAD* thread, uint8_t alertable) { KeAssertIrql(PASSIVE_LEVEL); if (!thread) return NTLSTATUS_INVALID_PARAMETER; @@ -766,13 +772,11 @@ KSTATUS KeCommitBlockThread(THREAD* thread, uint8_t alertable) { return thread->WaitStatus; } -// Implements the block Thread operation. KSTATUS KeBlockThread(THREAD* thread, OBJECT* waitObject, uint8_t alertable) { KePrepareBlockThread(thread, waitObject, alertable); return KeCommitBlockThread(thread, alertable); } -// Implements the unblock Thread With Status operation. void KeUnblockThreadWithStatus(THREAD* thread, KSTATUS status) { if (!thread) return; KiSchedulerWakeThread(thread, status); @@ -864,12 +868,10 @@ bool KeAbortThreadWait(THREAD* thread, KSTATUS status) { return true; } -// Implements the unblock Thread operation. void KeUnblockThread(THREAD* thread) { KeUnblockThreadWithStatus(thread, NTLSTATUS_SUCCESS); } -// Implements the alert Thread With Status operation. static KSTATUS KiAlertThreadWithStatus(THREAD* thread, KSTATUS status) { if (!thread) return NTLSTATUS_INVALID_PARAMETER; @@ -881,17 +883,14 @@ static KSTATUS KiAlertThreadWithStatus(THREAD* thread, KSTATUS status) { : NTLSTATUS_PENDING; } -// Implements the alert Thread operation. KSTATUS KeAlertThread(THREAD* thread) { return KiAlertThreadWithStatus(thread, NTLSTATUS_ALERTED); } -// Implements the wake Thread For Kernel Apc operation. void KiWakeThreadForKernelApc(THREAD* thread) { (void)KiAlertThreadWithStatus(thread, NTLSTATUS_KERNEL_APC); } -// Implements the wake Thread For User Apc operation. void KiWakeThreadForUserApc(THREAD* thread) { (void)KiAlertThreadWithStatus(thread, NTLSTATUS_USER_APC); } diff --git a/code/kernel/ke_time.c b/code/kernel/ke_time.c index bd03e9c..0b4fd86 100644 --- a/code/kernel/ke_time.c +++ b/code/kernel/ke_time.c @@ -56,7 +56,6 @@ static bool KiIsLeapYear(uint32_t year) { return ((year % 4u) == 0u && (year % 100u) != 0u) || ((year % 400u) == 0u); } -// Implements the days In Month operation. static uint32_t KiDaysInMonth(uint32_t year, uint32_t month) { static const uint8_t days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; if (month == 2u && KiIsLeapYear(year)) return 29u; @@ -76,7 +75,6 @@ static bool KiValidCalendar(uint32_t year, uint32_t month, uint32_t day, return true; } -// Implements the days Before Year operation. static uint64_t KiDaysBeforeYear(uint32_t year) { uint64_t days = 0; for (uint32_t y = 1970u; y < year; y++) @@ -93,7 +91,6 @@ static uint64_t KiCalendarToEpochSeconds(uint32_t year, uint32_t month, uint32_t return (((days * 24u) + hour) * 60u + minute) * 60u + second; } -// Implements the epoch Seconds To Calendar operation. static void KiEpochSecondsToCalendar(uint64_t epochSeconds, SYS_SYSTEM_TIME* out) { uint64_t days = epochSeconds / 86400u; uint32_t sod = (uint32_t)(epochSeconds % 86400u); @@ -124,20 +121,17 @@ static void KiEpochSecondsToCalendar(uint64_t epochSeconds, SYS_SYSTEM_TIME* out out->DayOfWeek = (uint8_t)((totalDays + 4u) % 7u); // 1970-01-01 was Thursday. } -// Implements the day Of Week operation. static uint32_t KiDayOfWeek(uint32_t year, uint32_t month, uint32_t day) { uint64_t epoch = KiCalendarToEpochSeconds(year, month, day, 0, 0, 0); return (uint32_t)(((epoch / 86400u) + 4u) % 7u); } -// Implements the last Sunday Of Month operation. static uint32_t KiLastSundayOfMonth(uint32_t year, uint32_t month) { uint32_t last = KiDaysInMonth(year, month); uint32_t dow = KiDayOfWeek(year, month, last); // Sunday == 0. return last - dow; } -// Implements the central Europe Dst Active Utc operation. static bool KiCentralEuropeDstActiveUtc(uint64_t utcEpochSeconds) { SYS_SYSTEM_TIME utc; memset(&utc, 0, sizeof(utc)); @@ -150,7 +144,6 @@ static bool KiCentralEuropeDstActiveUtc(uint64_t utcEpochSeconds) { return utcEpochSeconds >= startUtc && utcEpochSeconds < endUtc; } -// Implements the offset For Utc Epoch operation. static int16_t KiOffsetForUtcEpoch(uint64_t utcEpochSeconds, bool* daylight) { int32_t offset = gTimeZonePolicy.StandardOffsetMinutes; bool dst = false; @@ -166,7 +159,6 @@ static int16_t KiOffsetForUtcEpoch(uint64_t utcEpochSeconds, bool* daylight) { return (int16_t)offset; } -// Implements the local Epoch To Utc operation. static uint64_t KiLocalEpochToUtc(uint64_t localEpochSeconds, int16_t offsetMinutes) { uint64_t offsetSeconds = (uint64_t)((offsetMinutes < 0) ? -offsetMinutes : offsetMinutes) * 60u; if (offsetMinutes >= 0) @@ -174,7 +166,6 @@ static uint64_t KiLocalEpochToUtc(uint64_t localEpochSeconds, int16_t offsetMinu return localEpochSeconds + offsetSeconds; } -// Implements the rebase Utc From Source operation. static void KiRebaseUtcFromSource(void) { if (gSourceTimeZoneKnown) { gBaseUtcEpochSeconds = KiLocalEpochToUtc(gSourceRawEpochSeconds, gSourceTimeZoneMinutes); @@ -194,13 +185,11 @@ static void KiRebaseUtcFromSource(void) { gBaseTickMicroseconds = gSourceTickMicroseconds; } -// Implements the ascii Lower operation. static int KiAsciiLower(int c) { if (c >= 'A' && c <= 'Z') return c + ('a' - 'A'); return c; } -// Implements the string Equals No Case operation. static bool KiStringEqualsNoCase(const char* a, const char* b) { if (!a || !b) return false; while (*a && *b) { @@ -237,7 +226,6 @@ static bool KiParseInt32(const char* s, int32_t* out) { return true; } -// Implements the starts With No Case operation. static bool KiStartsWithNoCase(const char* s, const char* prefix) { if (!s || !prefix) return false; while (*prefix) { @@ -307,7 +295,6 @@ static bool KiParseUtcOffset(const char* s, int16_t* out) { return true; } -// Implements the apply Default Time Zone Policy operation. static void KiApplyDefaultTimeZonePolicy(void) { gTimeZonePolicy.StandardOffsetMinutes = KE_CE_STANDARD_OFFSET; gTimeZonePolicy.DstRule = KeDstRuleCentralEurope; @@ -315,7 +302,6 @@ static void KiApplyDefaultTimeZonePolicy(void) { gHardwareClockMode = KeHardwareClockUtc; } -// Implements the time Initialize operation. void KeTimeInitialize(const BOOT_INFO* bootInfo, const HAL_API* hal) { gTimeHal = hal; KiApplyDefaultTimeZonePolicy(); @@ -369,7 +355,6 @@ void KeTimeInitialize(const BOOT_INFO* bootInfo, const HAL_API* hal) { } } -// Implements the time Reload Settings operation. KSTATUS KeTimeReloadSettings(void) { KE_TIME_ZONE_POLICY policy = gTimeZonePolicy; char value[64]; diff --git a/code/kernel/ke_timer.c b/code/kernel/ke_timer.c index c3d6222..0d1f31f 100644 --- a/code/kernel/ke_timer.c +++ b/code/kernel/ke_timer.c @@ -52,7 +52,6 @@ static uint8_t KiTimerRemoveLocked(KTIMER* timer) { return 1; } -// Implements the timer Destroy operation. static void KiTimerDestroy(OBJECT* obj) { KTIMER* timer = (KTIMER*)obj; if (!timer) diff --git a/code/kernel/ke_trap.c b/code/kernel/ke_trap.c index ef93b16..5db3daa 100644 --- a/code/kernel/ke_trap.c +++ b/code/kernel/ke_trap.c @@ -45,7 +45,6 @@ STATIC_ASSERT_OFFSET(KTRAP_FRAME, SsSlot, 216); STATIC_ASSERT_OFFSET(KTRAP_FRAME, PreviousFrame, 224); _Static_assert(sizeof(KTRAP_FRAME) == 240, "KTRAP_FRAME size must match ke_syscall.asm"); -// Implements the trap Frame From User operation. bool KeTrapFrameFromUser(const KTRAP_FRAME* frame) { if (!frame || frame->Magic != KTRAP_FRAME_MAGIC) return false; return (frame->Cs & 3u) == 3u; @@ -58,7 +57,6 @@ KTRAP_FRAME* KeGetCurrentTrapFrame(void) { return t->TrapFrame; } -// Implements the enter Trap Frame operation. void KiEnterTrapFrame(KTRAP_FRAME* frame) { if (!frame || frame->Magic != KTRAP_FRAME_MAGIC) KePanic(KE_PANIC_CODE_TRAP, "KiEnterTrapFrame: invalid trap frame 0x%016llX\n", (uint64_t)frame); @@ -71,7 +69,6 @@ void KiEnterTrapFrame(KTRAP_FRAME* frame) { t->TrapFrame = frame; } -// Implements the exit Trap Frame operation. void KiExitTrapFrame(KTRAP_FRAME* frame) { if (!frame || frame->Magic != KTRAP_FRAME_MAGIC) KePanic(KE_PANIC_CODE_TRAP, "KiExitTrapFrame: invalid trap frame 0x%016llX\n", (uint64_t)frame); diff --git a/code/kernel/kmain.c b/code/kernel/kmain.c index 99d011a..a8ac665 100644 --- a/code/kernel/kmain.c +++ b/code/kernel/kmain.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -43,6 +44,8 @@ #include #include #include +#include +#include #include #include #include @@ -134,7 +137,6 @@ static void KiInitializeSwapFromSettings(void) { // HAL pointer cached at boot for subsystems that still need platform services. static const HAL_API* gKmainHal; -// Implements the page In Bootloader Region operation. static bool KiPageInBootloaderRegion(const BOOT_INFO* bootInfo, PHYSICAL_ADDRESS page) { for (uint32_t i = 0; i < bootInfo->MemoryMap.RegionCount; i++) { const MEMORY_REGION* r = &bootInfo->MemoryMap.Regions[i]; @@ -178,6 +180,24 @@ static void KiReclaimBootloaderMemory(const BOOT_INFO* bootInfo) { KiReclaimBootBlob(bootInfo, bootInfo->DriversIni.PhysicalBase, bootInfo->DriversIni.PageCount); } +// Runs the shared module prepare/publication sequence for both image sources. +static KSTATUS KiStartLoadedDriver(const DM_DRIVER_CONFIG* driver, uintptr_t base) { + KSTATUS status = LdrResolveImports(base); + LDR_KERNEL_MODULE* reservation = (LDR_KERNEL_MODULE*)0; + bool canReleaseImage = true; + if (KSUCCESS(status)) + status = LdrRegisterModule(driver->Image, base, &reservation); + if (KSUCCESS(status)) status = DmPrepareLoadedDriver(driver->Id, base, &canReleaseImage); + if (KSUCCESS(status)) { + DmCommitLoadedDriver(base, reservation); + return NTLSTATUS_SUCCESS; + } + LdrDiscardModule(reservation); + if (canReleaseImage) LdrReleaseKernelImage(base); + else DbgPrint("driver: failed image retained for callback lifetime %s\n", driver->Image); + return status; +} + // Loads a runtime image from the selected system root, keeping PE identity separate // from the configured module id used for lifecycle and dependency accounting. static KSTATUS KiLoadRuntimeDriver(const DM_DRIVER_CONFIG* driver) { @@ -210,14 +230,7 @@ static KSTATUS KiLoadRuntimeDriver(const DM_DRIVER_CONFIG* driver) { status = LdrLoadKernelImage(memory, (size_t)size, &base); MmFreePool(memory); if (!KSUCCESS(status)) return status; - status = LdrResolveImports(base); - if (!KSUCCESS(status)) return status; - status = LdrRegisterModule(driver->Image, base); - if (!KSUCCESS(status)) return status; - status = DmStartLoadedDriver(driver->Id, base); - if (KSUCCESS(status)) - status = LdrSetModuleExportsAvailable(driver->Image, true); - return status; + return KiStartLoadedDriver(driver, base); } // Starts a preloaded boot driver by its configuration identity, not array position. @@ -237,14 +250,7 @@ static KSTATUS KiLoadBootDriver(const BOOT_INFO* bootInfo, KSTATUS status = LdrLoadKernelImage( (const void*)(bootInfo->PhysicalMapBase + found->PhysicalBase), found->Length, &base); if (!KSUCCESS(status)) return status; - status = LdrResolveImports(base); - if (!KSUCCESS(status)) return status; - status = LdrRegisterModule(driver->Image, base); - if (!KSUCCESS(status)) return status; - status = DmStartLoadedDriver(driver->Id, base); - if (KSUCCESS(status)) - status = LdrSetModuleExportsAvailable(driver->Image, true); - return status; + return KiStartLoadedDriver(driver, base); } // Validates that the firmware preloaded exactly the configured boot modules. @@ -266,54 +272,195 @@ static bool KiCheckBootDriverHandoff(const BOOT_INFO* bootInfo, const DM_CONFIG* return expected == bootInfo->BootDrivers.Count; } -// Starts the lexicographically first eligible driver, independent of INI order. -// Failed providers block requires= dependents, while after= waits for settlement. +// Bounded workers execute independent driver starts while the coordinator owns graph state. +#define KI_DRIVER_START_WORKERS 4u + +typedef enum KI_DRIVER_WORK_STATE { + KiDriverWorkIdle, + KiDriverWorkQueued, + KiDriverWorkRunning, + KiDriverWorkFinished, + KiDriverWorkExit, + KiDriverWorkExited +} KI_DRIVER_WORK_STATE; + +typedef struct KI_DRIVER_START_WORKER { + EVENT* Wake; + EVENT* Completion; + THREAD* Thread; + const DM_CONFIG* Config; + const BOOT_INFO* BootInfo; + volatile int32_t State; + uint32_t Index; + KSTATUS Status; +} KI_DRIVER_START_WORKER; + +static void KiDriverStartWorker(void* argument) { + KI_DRIVER_START_WORKER* worker = (KI_DRIVER_START_WORKER*)argument; + for (;;) { + EVENT* wake = worker->Wake; + if (!wake) + KePanic(KE_PANIC_CODE_INIT, + "Driver worker: null wake worker=0x%016llx index=%u state=%d\n", + (uint64_t)(uintptr_t)worker, worker->Index, + NtlAtomicLoad32(&worker->State)); + KSTATUS status = KeWaitForEvent(wake, false); + if (!KSUCCESS(status)) { + THREAD* self = KeGetCurrentThread(); + KePanic(KE_PANIC_CODE_INIT, + "Driver worker wait status=0x%x worker=0x%016llx index=%u state=%d\n" + " wake=0x%016llx currentWake=0x%016llx thread=0x%016llx\n" + " waitStatus=0x%x threadState=%u waitObject=0x%016llx\n", + status, (uint64_t)(uintptr_t)worker, worker->Index, + NtlAtomicLoad32(&worker->State), + (uint64_t)(uintptr_t)wake, + (uint64_t)(uintptr_t)worker->Wake, + (uint64_t)(uintptr_t)self, + self ? self->WaitStatus : 0u, + self ? (unsigned)self->State : 0u, + self ? (uint64_t)(uintptr_t)self->WaitObject : 0ull); + } + // A wake alone does not claim work; stale signals may arrive after completion. + int32_t prior = NtlAtomicCompareExchange32(&worker->State, + KiDriverWorkRunning, KiDriverWorkQueued); + if (prior == KiDriverWorkExit) { + NtlAtomicExchange32(&worker->State, KiDriverWorkExited); + return; + } + if (prior != KiDriverWorkQueued) continue; + uint32_t index = worker->Index; + if (index >= worker->Config->DriverCount) + KePanic(KE_PANIC_CODE_INIT, "Driver worker: invalid assignment %u\n", index); + const DM_DRIVER_CONFIG* driver = &worker->Config->Drivers[index]; + DbgPrint("driver: start id=%s image=%s\n", driver->Id, driver->Image); + worker->Status = driver->Phase == DmStartBoot ? + KiLoadBootDriver(worker->BootInfo, driver) : KiLoadRuntimeDriver(driver); + NtlAtomicExchange32(&worker->State, KiDriverWorkFinished); + KeSignalEvent(worker->Completion); + } +} + +static int KiSelectEligibleDriver(const DM_CONFIG* config, DM_START_PHASE phase) { + int selected = -1; + for (uint32_t i = 0; i < config->DriverCount; ++i) { + const DM_DRIVER_CONFIG* d = &config->Drivers[i]; + if (d->Phase != phase || !DmDriverCanStart(config, i)) continue; + if (selected < 0 || strcmp(d->Id, config->Drivers[selected].Id) < 0) + selected = (int)i; + } + return selected; +} + static void KiRunDriverPhase(DM_CONFIG* config, const BOOT_INFO* bootInfo, DM_START_PHASE phase) { config->ActivePhase = phase; + EVENT* completion = (EVENT*)0; + KSTATUS status = KeEventCreate(EventAutoReset, false, &completion); + if (!KSUCCESS(status)) KePanic(KE_PANIC_CODE_INIT, "Driver scheduler: completion event failed\n"); + + // Worker threads retain these records until their exit has been acknowledged. + KI_DRIVER_START_WORKER* workers = (KI_DRIVER_START_WORKER*) + MmAllocatePoolTag(sizeof(KI_DRIVER_START_WORKER) * KI_DRIVER_START_WORKERS, + MM_POOL_TAG('d', 'r', 'w', 'k')); + if (!workers) + KePanic(KE_PANIC_CODE_INIT, "Driver scheduler: worker allocation failed\n"); + memset(workers, 0, sizeof(KI_DRIVER_START_WORKER) * KI_DRIVER_START_WORKERS); + for (uint32_t i = 0; i < KI_DRIVER_START_WORKERS; ++i) { + KI_DRIVER_START_WORKER* worker = &workers[i]; + worker->Index = UINT32_MAX; + worker->Config = config; + worker->BootInfo = bootInfo; + worker->Completion = completion; + status = KeEventCreate(EventAutoReset, false, &worker->Wake); + if (!KSUCCESS(status)) KePanic(KE_PANIC_CODE_INIT, "Driver scheduler: work event failed\n"); + const KE_THREAD_CREATE_PARAMETERS parameters = + KE_THREAD_CREATE_NAMED_NORMAL(PriorityNormal, "driver.start"); + status = KeCreateKernelThread((uintptr_t)KiDriverStartWorker, + (uintptr_t)worker, ¶meters, &worker->Thread); + if (!KSUCCESS(status)) KePanic(KE_PANIC_CODE_INIT, "Driver scheduler: worker failed\n"); + } + + uint32_t active = 0; for (;;) { - int selected = -1; - for (uint32_t i = 0; i < config->DriverCount; ++i) { - const DM_DRIVER_CONFIG* d = &config->Drivers[i]; - if (d->Phase != phase || !DmDriverCanStart(config, i)) continue; - if (selected < 0 || strcmp(d->Id, config->Drivers[selected].Id) < 0) - selected = (int)i; - } - if (selected >= 0) { - DM_DRIVER_CONFIG* d = &config->Drivers[selected]; - DbgPrint("Driver manager: starting %s (%s)\n", d->Id, d->Image); - KSTATUS status = phase == DmStartBoot - ? KiLoadBootDriver(bootInfo, d) : KiLoadRuntimeDriver(d); - d->State = KSUCCESS(status) ? DmRunStarted : DmRunFailed; - if (!KSUCCESS(status)) { - DbgPrint("Driver manager: failed %s, status=0x%x\n", d->Id, status); - if (d->Critical) - KePanic(KE_PANIC_CODE_INIT, - "Critical driver %s failed (0x%x)\n", d->Id, status); + for (uint32_t i = 0; i < KI_DRIVER_START_WORKERS; ++i) { + KI_DRIVER_START_WORKER* worker = &workers[i]; + if (NtlAtomicCompareExchange32(&worker->State, + KiDriverWorkIdle, KiDriverWorkFinished) != + KiDriverWorkFinished) continue; + uint32_t index = worker->Index; + if (index >= config->DriverCount) + KePanic(KE_PANIC_CODE_INIT, "Driver scheduler: invalid completion %u\n", index); + DM_DRIVER_CONFIG* driver = &config->Drivers[index]; + driver->State = KSUCCESS(worker->Status) ? DmRunStarted : DmRunFailed; + if (!KSUCCESS(worker->Status)) { + DbgPrint("driver: failed id=%s status=0x%x\n", driver->Id, worker->Status); + if (driver->Critical) + KePanic(KE_PANIC_CODE_INIT, "Critical driver %s failed (0x%x)\n", + driver->Id, worker->Status); } + worker->Index = UINT32_MAX; + --active; + } + + for (uint32_t i = 0; i < KI_DRIVER_START_WORKERS; ++i) { + KI_DRIVER_START_WORKER* worker = &workers[i]; + if (NtlAtomicLoad32(&worker->State) != KiDriverWorkIdle) continue; + int selected = KiSelectEligibleDriver(config, phase); + if (selected < 0) break; + DM_DRIVER_CONFIG* driver = &config->Drivers[selected]; + driver->State = DmRunStarting; + worker->Index = (uint32_t)selected; + NtlAtomicExchange32(&worker->State, KiDriverWorkQueued); + ++active; + KeSignalEvent(worker->Wake); + } + + if (active) { + status = KeWaitForEvent(completion, false); + if (!KSUCCESS(status)) KePanic(KE_PANIC_CODE_INIT, "Driver scheduler: wait failed\n"); continue; } bool changed = false; uint32_t waiting = 0; for (uint32_t i = 0; i < config->DriverCount; ++i) { - DM_DRIVER_CONFIG* d = &config->Drivers[i]; - if (d->Phase != phase || d->State != DmRunWaiting) continue; + DM_DRIVER_CONFIG* driver = &config->Drivers[i]; + if (driver->Phase != phase || driver->State != DmRunWaiting) continue; ++waiting; - if (DmDriverIsBlocked(config, i)) { - d->State = DmRunBlocked; - DbgPrint("Driver manager: blocked %s by unsatisfied dependency\n", d->Id); - if (d->Critical) - KePanic(KE_PANIC_CODE_INIT, "Critical driver %s blocked\n", d->Id); - changed = true; - } + if (!DmDriverIsBlocked(config, i)) continue; + driver->State = DmRunBlocked; + DbgPrint("driver: blocked id=%s dependency failed\n", driver->Id); + if (driver->Critical) + KePanic(KE_PANIC_CODE_INIT, "Critical driver %s blocked\n", driver->Id); + changed = true; } if (changed) continue; if (waiting) KePanic(KE_PANIC_CODE_INIT, - "Driver manager: no eligible drivers in phase %u (waiting=%u)\n", + "Driver manager: deadlocked phase=%u waiting=%u\n", (unsigned)phase, waiting); - return; + break; } + + for (uint32_t i = 0; i < KI_DRIVER_START_WORKERS; ++i) { + if (NtlAtomicCompareExchange32(&workers[i].State, + KiDriverWorkExit, KiDriverWorkIdle) != KiDriverWorkIdle) + KePanic(KE_PANIC_CODE_INIT, "Driver scheduler: worker still active at shutdown\n"); + KeSignalEvent(workers[i].Wake); + } + for (uint32_t i = 0; i < KI_DRIVER_START_WORKERS; ++i) { + status = KeWaitForEvent(workers[i].Thread->ExitEvent, false); + if (!KSUCCESS(status)) + KePanic(KE_PANIC_CODE_INIT, + "Driver scheduler: worker %u exit wait failed (0x%x)\n", i, status); + if (NtlAtomicLoad32(&workers[i].State) != KiDriverWorkExited) + KePanic(KE_PANIC_CODE_INIT, + "Driver scheduler: worker %u exited without acknowledgment (state=%d)\n", + i, NtlAtomicLoad32(&workers[i].State)); + ObDereferenceObject(&workers[i].Thread->Header); + ObDereferenceObject(&workers[i].Wake->Header); + } + ObDereferenceObject(&completion->Header); + MmFreePool(workers); } static DM_CONFIG* gDriverConfig; @@ -359,7 +506,7 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) { // Kernel-launched user images are rooted at the selected system volume. s = KeOpenSystemRootFile(filePath, &f); if (s != NTLSTATUS_SUCCESS) { - DbgPrint("Failed to load system file: \"%s\" (status %d)!\n", filePath, s); + DbgPrint("process: image load failed path=%s status=0x%x\n", filePath, s); return 0; } @@ -376,13 +523,13 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) { IoCloseFile(f); return 0; } - DbgPrint("Created process (PID %u) with command line: %s\n", proc->ProcessId, (args && args[0]) ? args : filePath); + DbgPrint("process: created pid=%u image=%s\n", proc->ProcessId, filePath); s = KeSetupUserProcessEnvironment(proc, SysSvFromCstr(filePath), SysSvFromCstr(args)); if (!KSUCCESS(s)) { - DbgPrint("KiLaunchUserProcess: Failed to build user process environment. Status: %d\n", s); + DbgPrint("process: environment failed status=0x%x\n", s); IoCloseFile(f); ObDereferenceObject(&proc->Header); return 0; @@ -461,7 +608,7 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) { } } if (!KSUCCESS(s)) { - DbgPrint("KiLaunchUserProcess: Failed to create bootstrap startup capabilities. Status: %d\n", s); + DbgPrint("process: bootstrap capabilities failed status=0x%x\n", s); IoCloseFile(f); ObDereferenceObject(&proc->Header); return 0; @@ -476,7 +623,7 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) { }; s = KeSetProcessStartupCapabilities(proc, startupCapabilities, 6); if (!KSUCCESS(s)) { - DbgPrint("KiLaunchUserProcess: Failed to install startup capabilities. Status: %d\n", s); + DbgPrint("process: capability install failed status=0x%x\n", s); IoCloseFile(f); ObDereferenceObject(&proc->Header); return 0; @@ -487,7 +634,7 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) { s = LdrLoadImageFileForProcess(proc, f, &imageBase); IoCloseFile(f); if (!KSUCCESS(s)) { - DbgPrint("KiLaunchUserProcess: LdrLoadImageFileForProcess failed with status: %d\n", s); + DbgPrint("process: image map failed status=0x%x\n", s); ObDereferenceObject(&proc->Header); return 0; } @@ -501,7 +648,7 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) { s = LdrProtectImageForProcess(proc, imageBase, true); if (!KSUCCESS(s)) { - DbgPrint("KiLaunchUserProcess: Failed to protect EXE image for %s (status %d)\n", filePath, s); + DbgPrint("process: image protect failed path=%s status=0x%x\n", filePath, s); ObDereferenceObject(&proc->Header); return 0; } @@ -520,14 +667,12 @@ static PROCESS* KiLaunchUserProcess(const char* filePath, const char* args) { s = KeCreateThread(proc, (uintptr_t)entryPoint, 0, &threadParameters, &thread); if (!KSUCCESS(s)) { KePowerSetInitProcess((PROCESS*)0); - DbgPrint("KiLaunchUserProcess: Failed to create thread. Status: %d\n", s); + DbgPrint("process: thread creation failed status=0x%x\n", s); proc->ImageBase = 0; proc->ImageSize = 0; ObDereferenceObject(&proc->Header); return 0; } - uint32_t tid = thread->ThreadId; - DbgPrint("KiLaunchUserProcess: Thread created and queued! TID=%u\n", tid); ObDereferenceObject(&thread->Header); // Caller owns the reference returned by KeCreateProcess. @@ -548,19 +693,15 @@ static void KiFlushRegisteredDisks(const char* phase) { DbgPrint("shutdown: %s disk enumeration failed 0x%x\n", phase, st); } -// Implements the system Init Thread operation. void SystemInitThread(void* arg) { SYSTEM_INIT_ARGS* args = (SYSTEM_INIT_ARGS*)arg; - DbgPrint("SystemInitThread: Thread started. Igniting the system...\n"); - - KiInitializeDrivers(args->BootInfo, args->Hal); - KSTATUS powerStatus = KePowerInitialize(); if (!KSUCCESS(powerStatus)) KePanic(KE_PANIC_CODE_INIT, "Power coordinator failed (0x%x)\n", powerStatus); - KePowerInitializeButton(args->Hal); + KiInitializeDrivers(args->BootInfo, args->Hal); + KePowerInitializePolicy(); KeTimeReloadSettings(); KiInitializeSwapFromSettings(); @@ -571,7 +712,7 @@ void SystemInitThread(void* arg) { KiRunKernelSelfTests(); // Launch the bootstrap service manager. Its allocated PID is not a system contract. - PROCESS* initProcess = KiLaunchUserProcess("system/init.exe", args->BootConfig.CommandLine); + PROCESS* initProcess = KiLaunchUserProcess("system/init.exe", ""); if (!initProcess) { DbgPrint("SystemInitThread: Failed to start system/init.exe.\n"); KePanic(KE_PANIC_CODE_INIT, "SystemInitThread: Failed to start system/init.exe.\n"); @@ -588,7 +729,7 @@ void SystemInitThread(void* arg) { if (exitCode != 0) { KePanic(KE_PANIC_CODE_INIT, "SystemInitThread: init.exe exited with code %d.\n", exitCode); } - DbgPrint("SystemInitThread: power commit accepted; init exited with code %d.\n", exitCode); + DbgPrint("shutdown: init exit=%d\n", exitCode); uint32_t action = KePowerCommittedAction(); if (!action) KePanic(KE_PANIC_CODE_INIT, "SystemInitThread: missing power action\n"); KSTATUS flush = MmFileCacheFlushAll(); @@ -604,12 +745,19 @@ void SystemInitThread(void* arg) { flush = MmFileCacheFlushAll(); if (!KSUCCESS(flush)) DbgPrint("shutdown: final cache flush status 0x%x\n", flush); KiFlushRegisteredDisks("final"); + // Firmware preparation runs while platform drivers can still execute methods. + KSTATUS firmwarePrepare = KePowerPrepareFirmware(action); + if (!KSUCCESS(firmwarePrepare) && firmwarePrepare != NTLSTATUS_NOT_SUPPORTED) + DbgPrint("shutdown: firmware prepare failed 0x%x; using HAL fallback\n", firmwarePrepare); KSTATUS prepare = DmPrepareShutdown(); if (!KSUCCESS(prepare)) DbgPrint("shutdown: prepare status 0x%x\n", prepare); KSTATUS pnpShutdown = IoPnpShutdown(10000u); if (!KSUCCESS(pnpShutdown)) DbgPrint("shutdown: device stop status 0x%x\n", pnpShutdown); DmCommitShutdown(); + KSTATUS firmwareEnter = KePowerEnterFirmware(action); + if (firmwareEnter != NTLSTATUS_NOT_SUPPORTED) + DbgPrint("shutdown: firmware transition returned 0x%x; using HAL fallback\n", firmwareEnter); if (action == SYS_POWER_ACTION_RESTART) { if (!gKmainHal->Power.Reset) KePanic(KE_PANIC_CODE_INIT, "shutdown: reset HAL callback unavailable\n"); @@ -741,9 +889,7 @@ extern void KernelMain(BOOT_INFO* bootInfo) { KeInitializeGdt(); KeInitializeIdt(); - // Register boot modules (Allows LdrGetExport to work for drivers and the HAL) - // Note: Kept to a single call here to avoid the duplicate in your original code. - + // Register boot exports before resolving driver imports. KSTATUS moduleRegistryStatus = LdrRegisterModulesFromBootInfo(bootInfo); if (!KSUCCESS(moduleRegistryStatus)) KeStopProcessor(); @@ -773,9 +919,11 @@ extern void KernelMain(BOOT_INFO* bootInfo) { KeStopProcessor(); IoInitializeDdk(hal, bootInfo->PhysicalMapBase); + KeFirmwareInitialize(bootInfo); gKmainHal = hal; KeInitDebug(hal, KSUCCESS(bootConfigStatus) ? bootConfig.Debug : 0); + KeFirmwareLog(); if (!KSUCCESS(bootConfigStatus)) { KePanic(KE_PANIC_CODE_INIT, "boot.ini: malformed or missing mandatory configuration, status=0x%x\n", @@ -786,7 +934,6 @@ extern void KernelMain(BOOT_INFO* bootInfo) { // Bind IRQ dispatch while IF remains clear. Interrupt sources are armed // later, after their kernel consumers have registered. KeIrqInitialize(hal); - DbgPrint("CPU: PAT owns WB/WC/UC policy; MTRR default=WB fixed=off variable=off.\n"); KeTimeInitialize(bootInfo, hal); KeDisplayInitialize(hal); @@ -805,7 +952,7 @@ extern void KernelMain(BOOT_INFO* bootInfo) { KeInputInitialize(hal); - KeIrqRegister(hal->Timer.IrqNumber, hal->Timer.HandleInterrupt); + KeIrqRegisterLocalTimerHandler(hal->Timer.HandleInterrupt); KeSyscallInit(hal); @@ -822,7 +969,7 @@ extern void KernelMain(BOOT_INFO* bootInfo) { // Scheduler Prep & Status Update. KeInitializeScheduler(); - KeIrqRegister(hal->Timer.IrqNumber, KeSchedulerTick); + KeIrqRegisterLocalTimerHandler(KeSchedulerTick); KeConfigureCurrentProcessorTimer(); KSTATUS volumeManagerStatus = IoInitializeVolumeManager(); @@ -873,7 +1020,6 @@ extern void KernelMain(BOOT_INFO* bootInfo) { if (!KSUCCESS(st)) { KePanic(KE_PANIC_CODE_INIT, "KernelMain: Failed to create SystemInitThread (status 0x%x)\n", st); } - DbgPrint("KernelMain: Handing over to scheduler...\n"); // The bootstrap CPU becomes the scheduler idle context once interrupts are enabled. while (true) diff --git a/code/kernel/ldr_image.c b/code/kernel/ldr_image.c index 85b8592..860bea2 100644 --- a/code/kernel/ldr_image.c +++ b/code/kernel/ldr_image.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #ifndef LDR_DEBUG_VERBOSE @@ -89,12 +90,10 @@ typedef struct { uint32_t Characteristics; } SECTION_HEADER; -// Implements the align Pe Size operation. static size_t KiAlignPeSize(size_t value) { return (value + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); } -// Implements the compute Required Image Size operation. static KSTATUS KiComputeRequiredImageSize(const PE_HEADER* pe, size_t fileSize, size_t* outSize) { if (!pe || !outSize) return NTLSTATUS_INVALID_PARAMETER; @@ -166,15 +165,16 @@ typedef struct { // Global kernel-module registry. Entries are allocated as modules arrive so boot-driver count is not an ABI limit. #define LDR_KERNEL_MODULE_NAME_MAX 64u -typedef struct MODULE_ENTRY { +typedef struct LDR_KERNEL_MODULE { char Name[LDR_KERNEL_MODULE_NAME_MAX]; uintptr_t Base; size_t Size; bool ExportsAvailable; - struct MODULE_ENTRY* Next; -} MODULE_ENTRY; + struct LDR_KERNEL_MODULE* Next; +} LDR_KERNEL_MODULE; -static MODULE_ENTRY* gModules; +static LDR_KERNEL_MODULE* gModules; +static SPINLOCK gModuleLock = SPINLOCK_INIT; // Ensures a user image page is privately writable before the kernel patches it. static KSTATUS KiEnsureUserImageWrite(PROCESS* process, bool user, uintptr_t address, size_t size) { @@ -182,66 +182,82 @@ static KSTATUS KiEnsureUserImageWrite(PROCESS* process, bool user, uintptr_t add return MmVadMakeImageRangePrivate(process, (void*)address, size); } -// Allocates and inserts one global kernel-module registry entry. +// Reserves an exact module identity before exposing its exports. static KSTATUS KiRegisterGlobalModule(const char* name, uintptr_t base, size_t size, - bool exportsAvailable) { + bool exportsAvailable, LDR_KERNEL_MODULE** out) { if (!name || !*name || !base || !size) return NTLSTATUS_INVALID_PARAMETER; + if (out) *out = (LDR_KERNEL_MODULE*)0; size_t nameLength = 0; - while (nameLength < LDR_KERNEL_MODULE_NAME_MAX && name[nameLength]) nameLength++; - if (nameLength == 0 || nameLength >= LDR_KERNEL_MODULE_NAME_MAX || + while (nameLength < LDR_KERNEL_MODULE_NAME_MAX && name[nameLength]) ++nameLength; + if (!nameLength || nameLength >= LDR_KERNEL_MODULE_NAME_MAX || !SysSvIsUtf8Text(SysSvFromParts(name, nameLength))) return NTLSTATUS_INVALID_PARAMETER; - MODULE_ENTRY* entry = (MODULE_ENTRY*)MmAllocatePool(sizeof(MODULE_ENTRY)); - if (!entry) - return NTLSTATUS_NO_MEMORY; - + LDR_KERNEL_MODULE* entry = (LDR_KERNEL_MODULE*)MmAllocatePool(sizeof(*entry)); + if (!entry) return NTLSTATUS_NO_MEMORY; memset(entry, 0, sizeof(*entry)); memcpy(entry->Name, name, nameLength); - entry->Name[nameLength] = '\0'; entry->Base = base; entry->Size = size; entry->ExportsAvailable = exportsAvailable; - entry->Next = gModules; - gModules = entry; - return NTLSTATUS_SUCCESS; -} -// Registers the two fixed bootstrap images described explicitly by BOOT_INFO. -KSTATUS LdrRegisterModulesFromBootInfo(const BOOT_INFO* bootInfo) { - if (!bootInfo) - return NTLSTATUS_INVALID_PARAMETER; - - KSTATUS status = KiRegisterGlobalModule("kernel.exe", - bootInfo->KernelImage.VirtualBase, - bootInfo->KernelImage.ImageSize, true); - if (!KSUCCESS(status)) - return status; - - return KiRegisterGlobalModule("hal.dll", - bootInfo->HalImage.VirtualBase, - bootInfo->HalImage.ImageSize, true); -} - -// Registers one loaded kernel module without imposing a fixed registry capacity. -KSTATUS LdrRegisterModule(const char* name, uintptr_t base) { - size_t size = base ? LdrGetImageSize(base) : 0; - return KiRegisterGlobalModule(name, base, size, false); -} - -// Makes an initialized module's exports visible to future import resolution. -// Failed images remain mapped for diagnostics but must not provide exports. -KSTATUS LdrSetModuleExportsAvailable(const char* name, bool available) { - if (!name) return NTLSTATUS_INVALID_PARAMETER; - for (MODULE_ENTRY* entry = gModules; entry; entry = entry->Next) { - if (_stricmp(entry->Name, name) == 0) { - entry->ExportsAvailable = available; - return NTLSTATUS_SUCCESS; + KSTATUS status = NTLSTATUS_SUCCESS; + uintptr_t flags = KeAcquireSpinlock(&gModuleLock); + for (LDR_KERNEL_MODULE* it = gModules; it; it = it->Next) { + if (_stricmp(it->Name, name) == 0 || it->Base == base) { + status = NTLSTATUS_ALREADY_EXISTS; + break; } } - return NTLSTATUS_NOT_FOUND; + if (KSUCCESS(status)) { + entry->Next = gModules; + gModules = entry; + if (out) *out = entry; + } + KeReleaseSpinlock(&gModuleLock, flags); + if (!KSUCCESS(status)) MmFreePool(entry); + return status; +} + +KSTATUS LdrRegisterModulesFromBootInfo(const BOOT_INFO* bootInfo) { + if (!bootInfo) return NTLSTATUS_INVALID_PARAMETER; + + KSTATUS status = KiRegisterGlobalModule("kernel.exe", + bootInfo->KernelImage.VirtualBase, + bootInfo->KernelImage.ImageSize, true, (LDR_KERNEL_MODULE**)0); + if (!KSUCCESS(status)) return status; + return KiRegisterGlobalModule("hal.dll", bootInfo->HalImage.VirtualBase, + bootInfo->HalImage.ImageSize, true, (LDR_KERNEL_MODULE**)0); +} + +KSTATUS LdrRegisterModule(const char* name, uintptr_t base, LDR_KERNEL_MODULE** out) { + size_t size = base ? LdrGetImageSize(base) : 0; + if (!out) return NTLSTATUS_INVALID_PARAMETER; + return KiRegisterGlobalModule(name, base, size, false, out); +} + +// Only the owner of the reservation can publish or discard it. +void LdrPublishModule(LDR_KERNEL_MODULE* module) { + uintptr_t flags = KeAcquireSpinlock(&gModuleLock); + module->ExportsAvailable = true; + KeReleaseSpinlock(&gModuleLock, flags); +} + +void LdrDiscardModule(LDR_KERNEL_MODULE* module) { + if (!module) return; + uintptr_t flags = KeAcquireSpinlock(&gModuleLock); + LDR_KERNEL_MODULE** link = &gModules; + while (*link && *link != module) link = &(*link)->Next; + if (*link && !module->ExportsAvailable) *link = module->Next; + else module = (LDR_KERNEL_MODULE*)0; + KeReleaseSpinlock(&gModuleLock, flags); + if (module) MmFreePool(module); +} + +void LdrReleaseKernelImage(uintptr_t imageBase) { + if (imageBase) MmFreePool((void*)imageBase); } // Finds the loaded kernel module that owns an address. @@ -249,7 +265,9 @@ const char* LdrFindKernelModuleByAddress(uintptr_t address, uintptr_t* baseOut, if (baseOut) *baseOut = 0; if (sizeOut) *sizeOut = 0; - for (MODULE_ENTRY* module = gModules; module; module = module->Next) { + uintptr_t flags = KeAcquireSpinlock(&gModuleLock); + for (LDR_KERNEL_MODULE* module = gModules; module; module = module->Next) { + if (!module->ExportsAvailable) continue; uintptr_t base = module->Base; size_t size = module->Size; if (!base || !size || base > UINTPTR_MAX - size) @@ -257,20 +275,28 @@ const char* LdrFindKernelModuleByAddress(uintptr_t address, uintptr_t* baseOut, if (address >= base && address < base + size) { if (baseOut) *baseOut = base; if (sizeOut) *sizeOut = size; - return module->Name; + const char* name = module->Name; + KeReleaseSpinlock(&gModuleLock, flags); + return name; } } + KeReleaseSpinlock(&gModuleLock, flags); return "unknown"; } // Returns the loaded global kernel module base for one exact module name. static uintptr_t KiFindGlobalModuleBase(const char* name) { if (!name) return 0; - for (MODULE_ENTRY* module = gModules; module; module = module->Next) { - if (module->ExportsAvailable && _stricmp(module->Name, name) == 0) - return module->Base; + uintptr_t base = 0; + uintptr_t flags = KeAcquireSpinlock(&gModuleLock); + for (LDR_KERNEL_MODULE* module = gModules; module; module = module->Next) { + if (module->ExportsAvailable && _stricmp(module->Name, name) == 0) { + base = module->Base; + break; + } } - return 0; + KeReleaseSpinlock(&gModuleLock, flags); + return base; } // Returns export At Base. @@ -313,7 +339,6 @@ void* LdrGetExport(const char* moduleName, const char* functionName) { return KiGetExportAtBase(base, functionName); } -// Implements the ldr Get Image Size operation. size_t LdrGetImageSize(uintptr_t base) { if (!base) return 0; uint32_t peOffset = *(uint32_t*)(base + 0x3C); @@ -322,7 +347,6 @@ size_t LdrGetImageSize(uintptr_t base) { return (size_t)pe->OptionalHeader.SizeOfImage; } -// Implements the ldr Get Mapped Image Size operation. size_t LdrGetMappedImageSize(PROCESS* process, uintptr_t base) { if (!base) return 0; if (process) { diff --git a/code/kernel/mm_pool.c b/code/kernel/mm_pool.c index 404dfc5..162a8b4 100644 --- a/code/kernel/mm_pool.c +++ b/code/kernel/mm_pool.c @@ -67,19 +67,15 @@ _Static_assert((sizeof(BLOCK_FTR) % POOL_ALIGNMENT) == 0, "pool footer must pres #define OVERHEAD (HDR_SIZE + FTR_SIZE) #define MIN_BLOCK (OVERHEAD + sizeof(void*)) -// Implements the hdr To Ftr operation. static inline BLOCK_FTR* KiHdrToFtr(BLOCK_HDR* h) { return (BLOCK_FTR*)((char*)h + HDR_SIZE + h->Size); } -// Implements the ftr To Hdr operation. static inline BLOCK_HDR* KiFtrToHdr(BLOCK_FTR* f) { return (BLOCK_HDR*)((char*)f - HDR_SIZE - f->Size); } -// Implements the next Block operation. static inline BLOCK_HDR* KiNextBlock(BLOCK_HDR* h) { return (BLOCK_HDR*)((char*)h + HDR_SIZE + h->Size + FTR_SIZE); } -// Implements the prev Ftr operation. static inline BLOCK_FTR* KiPrevFtr(BLOCK_HDR* h) { return (BLOCK_FTR*)((char*)h - FTR_SIZE); } @@ -385,7 +381,6 @@ static void KiFreeListRemoveLocked(HEAP* h, BLOCK_HDR* blk, uintptr_t caller) { blk->PrevFree = blk->NextFree = (BLOCK_HDR*)0; } -// Implements the heap Try Decommit Tail operation. static void KiHeapTryDecommitTail(HEAP* h, BLOCK_HDR* blk) { if (!h || !blk || blk->Free == BLOCK_STATE_USED) return; diff --git a/code/kernel/mm_virt.c b/code/kernel/mm_virt.c index 8ee98aa..e218953 100644 --- a/code/kernel/mm_virt.c +++ b/code/kernel/mm_virt.c @@ -7,6 +7,7 @@ // FFFF800000000000-FFFF87FFFFFFFFFF is reserved for kernel images and fixed kernel mappings. // FFFF880000000000-FFFF8FFFFFFFFFFF is the physical direct map. // FFFF900000000000-FFFF97FFFFFFFFFF is the PCI MMIO aperture owned by pci.sys. +// FFFF980000000000-FFFF9FFFFFFFFFFF is the generic device-MMIO aperture. // FFFFA00000000000-FFFFAFFFFFFFFFFF is the kernel shared-view arena. // FFFFC00000000000-FFFFDFFFFFFFFFFF is the kernel pool. // @@ -43,7 +44,6 @@ static KSTATUS KiCopyToUserPaged(void* userDst, const void* kernelSrc, size_t si static PHYSICAL_ADDRESS gVadZeroPageFrame; // User/kernel copy boundary helpers. -// Implements the user Range Valid operation. static bool KiUserRangeValid(uintptr_t addr, size_t size) { if (size == 0) return true; if (addr < USER_BASE) return false; @@ -2584,7 +2584,6 @@ size_t MmVadGetSizeByBase(const void* base) { return 0; } -// Implements the VAD Type Name operation. static const char* KiVadTypeName(MM_VAD_TYPE type) { switch (type) { case MmVadGeneric: return "generic"; @@ -2600,7 +2599,6 @@ static const char* KiVadTypeName(MM_VAD_TYPE type) { } } -// Implements the debug Dump VADs operation. void MmVadDebugDumpProcess(PROCESS* process) { if (!process) { DbgPrint("MM: VADs: \n"); @@ -2629,7 +2627,6 @@ void MmVadDebugDumpProcess(PROCESS* process) { if (!count) DbgPrint(" \n"); } -// Implements the debug Describe Address operation. void MmDebugDescribeAddress(uintptr_t addr) { PHYSICAL_ADDRESS phys = 0; uint64_t flags = 0; @@ -2705,7 +2702,6 @@ __declspec(dllexport) void MmFreeUserMemoryForProcess(PROCESS* process, void* pt (void)MmVadDestroy(process, ptr); } -// Implements the reallocate User Memory For Process operation. __declspec(dllexport) void* MmReallocateUserMemoryForProcess(PROCESS* process, void* ptr, size_t newSize) { if (!process) return (void*)0; if (!ptr) return MmAllocateUserMemoryForProcess(process, newSize); @@ -2737,7 +2733,6 @@ __declspec(dllexport) void MmFreeUserMemory(void* ptr) { MmFreeUserMemoryForProcess(process, ptr); } -// Implements the reallocate User Memory operation. __declspec(dllexport) void* MmReallocateUserMemory(void* ptr, size_t newSize) { PROCESS* process = KeGetCurrentProcess(); return MmReallocateUserMemoryForProcess(process, ptr, newSize); diff --git a/code/kernel/net_device.c b/code/kernel/net_device.c index 5d8ca0a..47eaf16 100644 --- a/code/kernel/net_device.c +++ b/code/kernel/net_device.c @@ -15,7 +15,6 @@ static NET_DEVICE* gNetDevices[NET_MAX_DEVICES]; static uint32_t gNetDeviceCount = 0; static SPINLOCK gNetLock = SPINLOCK_INIT; -// Implements the net Make Default Name operation. static void NetMakeDefaultName(NET_DEVICE* device, uint32_t index) { if (!device || device->Name[0]) return; @@ -27,7 +26,6 @@ static void NetMakeDefaultName(NET_DEVICE* device, uint32_t index) { device->Name[4] = '\0'; } -// Implements the net Is Device Registered Locked operation. static bool NetIsDeviceRegisteredLocked(const NET_DEVICE* device) { for (uint32_t i = 0; i < gNetDeviceCount; ++i) { if (gNetDevices[i] == device) @@ -36,12 +34,10 @@ static bool NetIsDeviceRegisteredLocked(const NET_DEVICE* device) { return false; } -// Implements the net Device Has Ethernet Address operation. static bool NetDeviceHasEthernetAddress(const NET_DEVICE* device) { return device && device->HardwareAddressLength == NET_ETHERNET_ADDRESS_LENGTH; } -// Implements the net Log Hardware Address operation. static void NetLogHardwareAddress(const NET_DEVICE* device) { if (NetDeviceHasEthernetAddress(device)) { DbgPrint("%02x:%02x:%02x:%02x:%02x:%02x", @@ -53,7 +49,6 @@ static void NetLogHardwareAddress(const NET_DEVICE* device) { } } -// Implements the net Register Device operation. __declspec(dllexport) KSTATUS NetRegisterDevice(NET_DEVICE* device) { if (!device || !device->SendFrame) return NTLSTATUS_INVALID_PARAMETER; @@ -96,7 +91,6 @@ __declspec(dllexport) KSTATUS NetRegisterDevice(NET_DEVICE* device) { return NTLSTATUS_SUCCESS; } -// Implements the net Get Device Count operation. __declspec(dllexport) uint32_t NetGetDeviceCount(void) { uintptr_t flags = KeAcquireSpinlock(&gNetLock); uint32_t count = gNetDeviceCount; @@ -104,7 +98,6 @@ __declspec(dllexport) uint32_t NetGetDeviceCount(void) { return count; } -// Implements the net Get Device operation. __declspec(dllexport) NET_DEVICE* NetGetDevice(uint32_t index) { uintptr_t flags = KeAcquireSpinlock(&gNetLock); NET_DEVICE* device = (index < gNetDeviceCount) ? gNetDevices[index] : (NET_DEVICE*)0; diff --git a/code/kernel/net_stack.c b/code/kernel/net_stack.c index b8f18bf..775f393 100644 --- a/code/kernel/net_stack.c +++ b/code/kernel/net_stack.c @@ -11,7 +11,6 @@ static const NET_STACK_PROVIDER* gNetStackProvider = 0; static SPINLOCK gNetStackLock = SPINLOCK_INIT; -// Implements the net Validate Stack Provider operation. static KSTATUS NetValidateStackProvider(const NET_STACK_PROVIDER* p) { if (!p || p->Version != NET_STACK_PROVIDER_VERSION || !p->Name) return NTLSTATUS_INVALID_PARAMETER; @@ -26,7 +25,6 @@ static KSTATUS NetValidateStackProvider(const NET_STACK_PROVIDER* p) { return NTLSTATUS_SUCCESS; } -// Implements the net Register Stack Provider operation. __declspec(dllexport) KSTATUS NetRegisterStackProvider(const NET_STACK_PROVIDER* provider) { KSTATUS st = NetValidateStackProvider(provider); if (!KSUCCESS(st)) @@ -59,7 +57,6 @@ __declspec(dllexport) KSTATUS NetRegisterStackProvider(const NET_STACK_PROVIDER* return NTLSTATUS_SUCCESS; } -// Implements the net Get Stack Provider operation. __declspec(dllexport) const NET_STACK_PROVIDER* NetGetStackProvider(void) { uintptr_t flags = KeAcquireSpinlock(&gNetStackLock); const NET_STACK_PROVIDER* p = gNetStackProvider; diff --git a/code/public/ntlite/ddi/pci.h b/code/public/ntlite/ddi/pci.h index c4fa007..bfc6e9e 100644 --- a/code/public/ntlite/ddi/pci.h +++ b/code/public/ntlite/ddi/pci.h @@ -12,6 +12,7 @@ #include #include #include +#include #ifndef PCI_API # ifdef PCI_SYS_BUILD @@ -115,8 +116,20 @@ PCI_API KSTATUS PciEnableDevice(DEVICE_OBJECT* pdo, PCI_API KSTATUS PciGetInterrupt(DEVICE_OBJECT* pdo, uint8_t* outIrq); -PCI_API KSTATUS PciEnableMsi(DEVICE_OBJECT* pdo, - uint8_t irqSlot); +typedef struct PCI_INTERRUPT_REQUEST { + KE_INTERRUPT_ROUTINE Routine; + void* Context; + uint64_t Affinity; + KE_INTERRUPT* Interrupt; + // Owned and cleared by pci.sys while the interrupt is connected. + void* BusContext; +} PCI_INTERRUPT_REQUEST; -PCI_API KSTATUS PciEnableMsiAuto(DEVICE_OBJECT* pdo, - uint8_t* outIrqSlot); +// Allocates and programs one or more MSI-X/MSI routes, or a shared INTx route. +PCI_API KSTATUS PciConnectInterrupts(DEVICE_OBJECT* pdo, + PCI_INTERRUPT_REQUEST* requests, + uint32_t count, bool* usingMessages); +// Disable the PCI source before releasing the interrupt objects. +PCI_API void PciDisconnectInterrupts(DEVICE_OBJECT* pdo, + PCI_INTERRUPT_REQUEST* requests, + uint32_t count); diff --git a/code/public/ntlite/ddk/ddk.h b/code/public/ntlite/ddk/ddk.h index 4ea8b3b..b7828ce 100644 --- a/code/public/ntlite/ddk/ddk.h +++ b/code/public/ntlite/ddk/ddk.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/code/public/ntlite/ddk/debug.h b/code/public/ntlite/ddk/debug.h index 3e80477..960cdf9 100644 --- a/code/public/ntlite/ddk/debug.h +++ b/code/public/ntlite/ddk/debug.h @@ -15,11 +15,12 @@ #define KE_DEBUG_POOL_CALLERS 0x00000040u // Track pool allocation/free callers. #define KE_DEBUG_DISPLAY_ASSERTS 0x00000080u // Enable display-path consistency assertions. #define KE_DEBUG_LIST_CHECKS 0x00000100u // Validate intrusive-list links on mutation. +#define KE_DEBUG_ACPI_INFO 0x00000200u // Include ACPICA informational output. #define KE_DEBUG_VALID_MASK (KE_DEBUG_CONSOLE | KE_DEBUG_SELFTEST | KE_DEBUG_FILE_LOG | \ KE_DEBUG_POOL_CANARY | KE_DEBUG_POOL_POISON | \ KE_DEBUG_POOL_QUARANTINE | KE_DEBUG_POOL_CALLERS | \ - KE_DEBUG_DISPLAY_ASSERTS | KE_DEBUG_LIST_CHECKS) + KE_DEBUG_DISPLAY_ASSERTS | KE_DEBUG_LIST_CHECKS | KE_DEBUG_ACPI_INFO) diff --git a/code/public/ntlite/ddk/interrupt.h b/code/public/ntlite/ddk/interrupt.h index 11941cf..6f501d5 100644 --- a/code/public/ntlite/ddk/interrupt.h +++ b/code/public/ntlite/ddk/interrupt.h @@ -1,22 +1,57 @@ -// Public nt-lite DDK interrupt declarations. - +// Kernel interrupt objects and platform source registration. #pragma once #include #include +typedef struct KE_INTERRUPT KE_INTERRUPT; +typedef void (*KE_INTERRUPT_ROUTINE)(void* context); + +typedef struct KE_INTERRUPT_INFO { + uint32_t CpuIndex; + uint32_t HardwareId; + uint32_t Gsi; + uint16_t Flags; + uint8_t Vector; + uint8_t IsMessage; + uint64_t Delivered; +} KE_INTERRUPT_INFO; + +typedef enum KE_INTERRUPT_MESSAGE_OPERATION { + KeInterruptMessageQuiesce = 1, + KeInterruptMessageProgram, + KeInterruptMessageResume +} KE_INTERRUPT_MESSAGE_OPERATION; + typedef struct NTL_DDK_MSI_MESSAGE { uint64_t Address; uint32_t Data; uint32_t Reserved; } NTL_DDK_MSI_MESSAGE; +// Only the bus owner programs a device's message source. The interrupt manager +// selects CPUs/vectors and coordinates quiescence with this device callback. +typedef KSTATUS (*KE_INTERRUPT_MESSAGE_PROGRAM)(void* context, + KE_INTERRUPT_MESSAGE_OPERATION operation, const NTL_DDK_MSI_MESSAGE* message); +// The platform owns GSI routing and ISA overrides; drivers own only their handler. +__declspec(dllexport) KSTATUS KeInterruptConnectGsi(uint32_t gsi, uint16_t flags, + uint64_t affinity, KE_INTERRUPT_ROUTINE routine, void* context, KE_INTERRUPT** out); +__declspec(dllexport) KSTATUS KeInterruptConnectIsa(uint8_t isaIrq, uint16_t sourceFlags, uint64_t affinity, + KE_INTERRUPT_ROUTINE routine, void* context, KE_INTERRUPT** out); -// Allocates one kernel IRQ slot for MSI delivery. -__declspec(dllexport) KSTATUS KeIrqAllocateMsiVector(uint8_t* outIrq); - -// Registers a legacy interrupt handler for an IRQ slot. -__declspec(dllexport) void KeIrqRegister(uint8_t irq, void (*handler)(void)); - -__declspec(dllexport) KSTATUS KeIrqComposeMsiMessage(uint8_t irq, NTL_DDK_MSI_MESSAGE* messageOut); +// PCI enables the device's MSI/MSI-X source after reserving the CPU/vector route. +__declspec(dllexport) KSTATUS KeInterruptReserveMessage(uint64_t affinity, + KE_INTERRUPT_ROUTINE routine, void* context, KE_INTERRUPT** out); +__declspec(dllexport) KSTATUS KeInterruptComposeMessage(const KE_INTERRUPT* interrupt, + NTL_DDK_MSI_MESSAGE* out); +__declspec(dllexport) KSTATUS KeInterruptQuery(const KE_INTERRUPT* interrupt, KE_INTERRUPT_INFO* out); +__declspec(dllexport) KSTATUS KeInterruptBindMessageSource(KE_INTERRUPT* interrupt, + KE_INTERRUPT_MESSAGE_PROGRAM program, void* context); +__declspec(dllexport) KSTATUS KeInterruptActivateMessage(KE_INTERRUPT* interrupt); +__declspec(dllexport) KSTATUS KeInterruptSetAffinity(KE_INTERRUPT* interrupt, + uint64_t permittedCpuMask); +// Bus drivers close a route before disabling its source, serializing migration. +__declspec(dllexport) void KeInterruptBeginDisconnect(KE_INTERRUPT* interrupt); +// Disconnect waits for active handlers and requires PASSIVE_LEVEL. +__declspec(dllexport) void KeInterruptDisconnect(KE_INTERRUPT* interrupt); diff --git a/code/public/ntlite/ddk/memory.h b/code/public/ntlite/ddk/memory.h index 8d2183c..ded5e0d 100644 --- a/code/public/ntlite/ddk/memory.h +++ b/code/public/ntlite/ddk/memory.h @@ -83,3 +83,8 @@ __declspec(dllexport) void* MmReallocatePool(void* ptr, size_t newSize); __declspec(dllexport) void* MmDdkPhysToVirt(uint64_t physicalAddress); __declspec(dllexport) KSTATUS MmDdkMapPage(uintptr_t virtualAddress, uint64_t physicalAddress, uint64_t flags, NTL_DDK_MAP_MODE mode); + +// UC device mapping with a private kernel VA and an exact matching unmap. +// Use in thread context. Returned mappings must be released with their length. +__declspec(dllexport) KSTATUS MmDdkMapIoMemory(uint64_t physicalAddress, size_t length, void** outVirtual); +__declspec(dllexport) KSTATUS MmDdkUnmapIoMemory(void* virtualAddress, size_t length); diff --git a/code/public/ntlite/ddk/module.h b/code/public/ntlite/ddk/module.h index 34fca20..6567ca8 100644 --- a/code/public/ntlite/ddk/module.h +++ b/code/public/ntlite/ddk/module.h @@ -6,10 +6,12 @@ #define NTL_DDK_MODULE_EXPORT_NAME "NtlDriverModule" #define NTL_DDK_MODULE_SIGNATURE 0x324D444Eu // "NDM2" in little-endian memory. -#define NTL_DDK_MODULE_ABI_VERSION 5u +#define NTL_DDK_MODULE_ABI_VERSION 6u typedef struct NTL_MODULE NTL_MODULE; -typedef KSTATUS (*NTL_MODULE_INITIALIZE)(NTL_MODULE* module); +typedef KSTATUS (*NTL_MODULE_PREPARE_START)(NTL_MODULE* module); +typedef void (*NTL_MODULE_COMMIT_START)(NTL_MODULE* module); +typedef void (*NTL_MODULE_ABORT_START)(NTL_MODULE* module); typedef KSTATUS (*NTL_MODULE_PREPARE_SHUTDOWN)(NTL_MODULE* module); typedef void (*NTL_MODULE_COMMIT_SHUTDOWN)(NTL_MODULE* module); @@ -20,7 +22,7 @@ typedef struct NTL_MODULE_EXPORT { uint32_t Version; uint32_t Size; uint32_t Flags; - NTL_MODULE_INITIALIZE Initialize; + NTL_MODULE_PREPARE_START PrepareStart; const NTL_DEVICE_DESC* Devices; uint32_t DeviceCount; uint32_t Reserved; @@ -29,49 +31,67 @@ typedef struct NTL_MODULE_EXPORT { uint32_t Reserved2; NTL_MODULE_PREPARE_SHUTDOWN PrepareShutdown; NTL_MODULE_COMMIT_SHUTDOWN CommitShutdown; + NTL_MODULE_COMMIT_START CommitStart; + NTL_MODULE_ABORT_START AbortStart; } NTL_MODULE_EXPORT; #ifdef __cplusplus -static_assert(sizeof(NTL_MODULE_EXPORT) == 72u, "DDK module export ABI changed"); +static_assert(sizeof(NTL_MODULE_EXPORT) == 88u, "DDK module export ABI changed"); #define NTL_DDK_C_EXPORT extern "C" #else -_Static_assert(sizeof(NTL_MODULE_EXPORT) == 72u, "DDK module export ABI changed"); +_Static_assert(sizeof(NTL_MODULE_EXPORT) == 88u, "DDK module export ABI changed"); #define NTL_DDK_C_EXPORT #endif -#define NTL_DECLARE_MODULE(initialize_fn) \ +#define NTL_DECLARE_MODULE(prepareFn) \ NTL_DDK_C_EXPORT __declspec(dllexport) const NTL_MODULE_EXPORT NtlDriverModule = { \ NTL_DDK_MODULE_SIGNATURE, NTL_DDK_MODULE_ABI_VERSION, \ - (uint32_t)sizeof(NTL_MODULE_EXPORT), 0u, (initialize_fn), 0, 0u, 0u, 0, 0u, 0u, 0, 0 \ + (uint32_t)sizeof(NTL_MODULE_EXPORT), 0u, (prepareFn), 0, 0u, 0u, 0, 0u, 0u, 0, 0, 0, 0 \ } #define NTL_DECLARE_DEVICE_MODULE(deviceArray) \ NTL_DDK_C_EXPORT __declspec(dllexport) const NTL_MODULE_EXPORT NtlDriverModule = { \ NTL_DDK_MODULE_SIGNATURE, NTL_DDK_MODULE_ABI_VERSION, \ (uint32_t)sizeof(NTL_MODULE_EXPORT), 0u, 0, (deviceArray), \ - (uint32_t)(sizeof(deviceArray) / sizeof((deviceArray)[0])), 0u, 0, 0u, 0u, 0, 0 \ + (uint32_t)(sizeof(deviceArray) / sizeof((deviceArray)[0])), 0u, 0, 0u, 0u, 0, 0, 0, 0 \ } -#define NTL_DECLARE_IO_MODULE(initialize_fn, driverArray) \ +#define NTL_DECLARE_IO_MODULE(prepareFn, driverArray) \ NTL_DDK_C_EXPORT __declspec(dllexport) const NTL_MODULE_EXPORT NtlDriverModule = { \ NTL_DDK_MODULE_SIGNATURE, NTL_DDK_MODULE_ABI_VERSION, \ - (uint32_t)sizeof(NTL_MODULE_EXPORT), 0u, (initialize_fn), 0, 0u, 0u, \ - (driverArray), (uint32_t)(sizeof(driverArray) / sizeof((driverArray)[0])), 0u, 0, 0 \ + (uint32_t)sizeof(NTL_MODULE_EXPORT), 0u, (prepareFn), 0, 0u, 0u, \ + (driverArray), (uint32_t)(sizeof(driverArray) / sizeof((driverArray)[0])), 0u, 0, 0, 0, 0 \ } -#define NTL_DECLARE_MODULE_WITH_SHUTDOWN(initialize_fn, prepareFn, commitFn) \ +#define NTL_DECLARE_MODULE_WITH_SHUTDOWN(startPrepareFn, shutdownPrepareFn, commitFn) \ NTL_DDK_C_EXPORT __declspec(dllexport) const NTL_MODULE_EXPORT NtlDriverModule = { \ NTL_DDK_MODULE_SIGNATURE, NTL_DDK_MODULE_ABI_VERSION, \ - (uint32_t)sizeof(NTL_MODULE_EXPORT), 0u, (initialize_fn), 0, 0u, 0u, \ - 0, 0u, 0u, (prepareFn), (commitFn) \ + (uint32_t)sizeof(NTL_MODULE_EXPORT), 0u, (startPrepareFn), 0, 0u, 0u, \ + 0, 0u, 0u, (shutdownPrepareFn), (commitFn), 0, 0 \ } -#define NTL_DECLARE_IO_MODULE_WITH_SHUTDOWN(initialize_fn, driverArray, prepareFn, commitFn) \ +#define NTL_DECLARE_IO_MODULE_WITH_SHUTDOWN(startPrepareFn, driverArray, shutdownPrepareFn, commitFn) \ NTL_DDK_C_EXPORT __declspec(dllexport) const NTL_MODULE_EXPORT NtlDriverModule = { \ NTL_DDK_MODULE_SIGNATURE, NTL_DDK_MODULE_ABI_VERSION, \ - (uint32_t)sizeof(NTL_MODULE_EXPORT), 0u, (initialize_fn), 0, 0u, 0u, \ + (uint32_t)sizeof(NTL_MODULE_EXPORT), 0u, (startPrepareFn), 0, 0u, 0u, \ (driverArray), (uint32_t)(sizeof(driverArray) / sizeof((driverArray)[0])), 0u, \ - (prepareFn), (commitFn) \ + (shutdownPrepareFn), (commitFn), 0, 0 \ + } + +// Prepare may fail. Commit publishes fully prepared state and returns void. +#define NTL_DECLARE_STAGED_MODULE(prepareFn, commitFn, abortFn) \ + NTL_DDK_C_EXPORT __declspec(dllexport) const NTL_MODULE_EXPORT NtlDriverModule = { \ + NTL_DDK_MODULE_SIGNATURE, NTL_DDK_MODULE_ABI_VERSION, \ + (uint32_t)sizeof(NTL_MODULE_EXPORT), 0u, (prepareFn), 0, 0u, 0u, \ + 0, 0u, 0u, 0, 0, (commitFn), (abortFn) \ + } + +#define NTL_DECLARE_STAGED_IO_MODULE(prepareFn, driverArray, commitFn, abortFn) \ + NTL_DDK_C_EXPORT __declspec(dllexport) const NTL_MODULE_EXPORT NtlDriverModule = { \ + NTL_DDK_MODULE_SIGNATURE, NTL_DDK_MODULE_ABI_VERSION, \ + (uint32_t)sizeof(NTL_MODULE_EXPORT), 0u, (prepareFn), 0, 0u, 0u, \ + (driverArray), (uint32_t)(sizeof(driverArray) / sizeof((driverArray)[0])), \ + 0u, 0, 0, (commitFn), (abortFn) \ } // Query the configured module identity; the returned string is borrowed. diff --git a/code/public/ntlite/ddk/platform.h b/code/public/ntlite/ddk/platform.h index ad82007..225cb63 100644 --- a/code/public/ntlite/ddk/platform.h +++ b/code/public/ntlite/ddk/platform.h @@ -3,6 +3,11 @@ #pragma once #include +#include __declspec(dllexport) uint32_t KePciReadConfig32(uint16_t segment, uint8_t bus, uint8_t device, uint8_t function, uint16_t offset); __declspec(dllexport) void KePciWriteConfig32(uint16_t segment, uint8_t bus, uint8_t device, uint8_t function, uint16_t offset, uint32_t value); + +// Returns a checksum-validated ACPI RSDP root, independent of its consumer. +// A firmware driver maps the physical tables using the DDK memory interface. +__declspec(dllexport) KSTATUS KeFirmwareQueryAcpiRsdp(uint64_t* physicalAddressOut); diff --git a/code/public/ntlite/ddk/power.h b/code/public/ntlite/ddk/power.h new file mode 100644 index 0000000..92620b2 --- /dev/null +++ b/code/public/ntlite/ddk/power.h @@ -0,0 +1,36 @@ +// Firmware power provider interface for resident platform drivers. + +#pragma once + +#include +#include + +// A registered provider remains resident through the final hardware transition. +// Callbacks run in thread context; Enter returns an error if the transition fails. +typedef struct NTL_FIRMWARE_POWER_PROVIDER { + uint32_t Size; + void* Context; + KSTATUS (*Prepare)(void* context, uint32_t action); + KSTATUS (*Enter)(void* context, uint32_t action); +} NTL_FIRMWARE_POWER_PROVIDER; + +#ifdef NTL_KERNEL_BUILD +#define NTL_DDK_POWER_API __declspec(dllexport) +#else +#define NTL_DDK_POWER_API __declspec(dllimport) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +// Installs one firmware power provider for the lifetime of the boot. +NTL_DDK_POWER_API KSTATUS KeRegisterFirmwarePowerProvider( + const NTL_FIRMWARE_POWER_PROVIDER* provider); + +// Reports a physical button press from a firmware driver's worker context. +NTL_DDK_POWER_API KSTATUS KeNotifyPowerButton(void); + +#ifdef __cplusplus +} +#endif diff --git a/code/public/ntlite/ddk/thread.h b/code/public/ntlite/ddk/thread.h index 07f4311..a821584 100644 --- a/code/public/ntlite/ddk/thread.h +++ b/code/public/ntlite/ddk/thread.h @@ -72,3 +72,6 @@ __declspec(dllexport) KSTATUS KeResumeThread(THREAD* thread, // Yields the current processor to another runnable thread. __declspec(dllexport) void KeYield(void); + +// Returns the stable opaque identity of the calling kernel thread. +__declspec(dllexport) uintptr_t KeCurrentThreadIdentity(void); diff --git a/code/public/ntlite/native_heap.h b/code/public/ntlite/native_heap.h new file mode 100644 index 0000000..cde29cf --- /dev/null +++ b/code/public/ntlite/native_heap.h @@ -0,0 +1,10 @@ +// Native user-mode allocation functions provided by the process runtime. + +#pragma once + +#include + +void* malloc(size_t size); +void* calloc(size_t count, size_t size); +void* realloc(void* pointer, size_t size); +void free(void* pointer); diff --git a/code/public/ntlite/string_view.h b/code/public/ntlite/string_view.h index 406ad15..1ad8f5c 100644 --- a/code/public/ntlite/string_view.h +++ b/code/public/ntlite/string_view.h @@ -23,7 +23,6 @@ typedef struct SYS_STRING_VIEW { #define SYS_SV_LITERAL(s) ((SYS_STRING_VIEW){ (s), sizeof(s) - 1 }) #define SYS_SV_NULL ((SYS_STRING_VIEW){ (const char*)0, 0 }) -// Implements the sv From Parts operation. static inline SYS_STRING_VIEW SysSvFromParts(const char* data, size_t length) { SYS_STRING_VIEW v; v.Data = data; @@ -31,7 +30,6 @@ static inline SYS_STRING_VIEW SysSvFromParts(const char* data, size_t length) { return v; } -// Implements the sv From Cstr operation. static inline SYS_STRING_VIEW SysSvFromCstr(const char* s) { SYS_STRING_VIEW v; v.Data = s; @@ -39,12 +37,10 @@ static inline SYS_STRING_VIEW SysSvFromCstr(const char* s) { return v; } -// Implements the sv Is Empty operation. static inline bool SysSvIsEmpty(SYS_STRING_VIEW s) { return s.Length == 0; } -// Implements the sv Is Valid operation. static inline bool SysSvIsValid(SYS_STRING_VIEW s) { return s.Data != (const char*)0 || s.Length == 0; } @@ -143,7 +139,6 @@ static inline size_t SysSvCopyUtf8WithReplacement(SYS_STRING_VIEW source, return written; } -// Implements the sv Equal operation. static inline bool SysSvEqual(SYS_STRING_VIEW a, SYS_STRING_VIEW b) { if (a.Length != b.Length) return false; if (a.Length == 0) return true; @@ -151,12 +146,10 @@ static inline bool SysSvEqual(SYS_STRING_VIEW a, SYS_STRING_VIEW b) { return memcmp(a.Data, b.Data, a.Length) == 0; } -// Implements the ascii Lower operation. static inline char SysAsciiLower(char c) { return (c >= 'A' && c <= 'Z') ? (char)(c + ('a' - 'A')) : c; } -// Implements the sv Equal Ascii I operation. static inline bool SysSvEqualAsciiI(SYS_STRING_VIEW a, SYS_STRING_VIEW b) { if (a.Length != b.Length) return false; if (a.Length == 0) return true; @@ -167,17 +160,14 @@ static inline bool SysSvEqualAsciiI(SYS_STRING_VIEW a, SYS_STRING_VIEW b) { return true; } -// Implements the sv Equal Lit operation. static inline bool SysSvEqualLit(SYS_STRING_VIEW a, const char* lit) { return SysSvEqual(a, SysSvFromCstr(lit)); } -// Implements the sv Equal Lit Ascii I operation. static inline bool SysSvEqualLitAsciiI(SYS_STRING_VIEW a, const char* lit) { return SysSvEqualAsciiI(a, SysSvFromCstr(lit)); } -// Implements the sv Contains Byte operation. static inline bool SysSvContainsByte(SYS_STRING_VIEW s, char ch) { if (!s.Data && s.Length) return false; for (size_t i = 0; i < s.Length; i++) { @@ -186,14 +176,12 @@ static inline bool SysSvContainsByte(SYS_STRING_VIEW s, char ch) { return false; } -// Implements the sv Slice operation. static inline SYS_STRING_VIEW SysSvSlice(SYS_STRING_VIEW s, size_t off, size_t len) { if (off > s.Length) off = s.Length; if (len > s.Length - off) len = s.Length - off; return SysSvFromParts(s.Data ? s.Data + off : (const char*)0, len); } -// Implements the sv Trim Ascii operation. static inline SYS_STRING_VIEW SysSvTrimAscii(SYS_STRING_VIEW s) { if (!SysSvIsValid(s)) return SYS_SV_NULL; size_t begin = 0; @@ -211,7 +199,6 @@ static inline SYS_STRING_VIEW SysSvTrimAscii(SYS_STRING_VIEW s) { return SysSvSlice(s, begin, end - begin); } -// Implements the sv Copy Z operation. static inline bool SysSvCopyZ(char* dst, size_t dstSize, SYS_STRING_VIEW src) { if (!dst || dstSize == 0) return false; if (src.Length && !src.Data) return false; diff --git a/code/public/ntlite/syscall.h b/code/public/ntlite/syscall.h index abe8d02..f9911cd 100644 --- a/code/public/ntlite/syscall.h +++ b/code/public/ntlite/syscall.h @@ -645,7 +645,7 @@ typedef struct SYS_QUEUE_RECV_REQUEST { // SysWaitMany copies handles through a fixed kernel stack buffer. This public // ABI/resource limit is intentionally small to keep wait setup bounded. -#define SYS_WAIT_MANY_MAX_HANDLES 32u +#define SYS_WAIT_MANY_MAX_HANDLES 64u typedef struct SYS_WAIT_MANY_REQUEST { uint32_t Size; diff --git a/code/services.ini b/code/services.ini index 735b8cc..60db57b 100644 --- a/code/services.ini +++ b/code/services.ini @@ -1,49 +1,30 @@ -; nt-lite user-mode system services. -; -; init.exe loads this mandatory file from the bootstrap system volume. -; [service.] Service identity; the suffix is case-sensitive. -; image= Executable path relative to the bootstrap system volume. -; start= auto starts at boot; disabled prevents automatic startup. -; critical= Whether service failure is fatal to system startup (true/false). -; restart= Restart policy (never or on-failure; current adapters restrict usage). -; ready_timeout_ms= Milliseconds allowed for the service READY handshake. -; stop_timeout_ms= Milliseconds allowed for graceful service shutdown. -; requires= Comma-separated service IDs that must start first; empty is allowed. -; grants= Comma-separated capability sources delegated at startup; empty is allowed. -; exports= Names of handles this service must transfer at READY; empty is allowed. -; Source names are boot. or .. -; Each service key is mandatory. Comments occupy separate lines. -; RSSRV defines publisher names and their allowed paths; init only forwards handles. +; [session] image= sets the interactive shell under /SystemRoot. +; [service.id] image= sets the executable; name= sets its display name. +; start=auto (default), delayed (after shell), disabled; critical=true requires auto. +; requires= providers reaching READY; after= providers reaching settlement. +; restart=never (default), on-failure, always; limit=3 attempts per 300000 ms by default. +; restart_limit=3, restart_window_ms=300000, restart_delay_ms=0. +; ready_timeout_ms=5000, stop_timeout_ms=5000; other omitted lists are empty. +; privileges= ambient privilege names; grants= boot.name or provider.export sources. +; exports= READY handle names. Namespace-root and registration grants share one critical auto owner. + +[session] +image=apps/shell_native.exe [service.rssrv] image=system/rssrv.exe -start=auto critical=true -restart=never -ready_timeout_ms=5000 -stop_timeout_ms=5000 -requires= grants=boot.namespace-root,boot.volume-manager,boot.input-manager,boot.display-policy,boot.resource-registration exports=session-control,desktop-publisher,posix-publisher [service.posix] image=system/posixsrv.exe -start=auto -critical=false -restart=never -ready_timeout_ms=5000 -stop_timeout_ms=5000 requires=rssrv grants=rssrv.posix-publisher exports=public [service.dwm] image=system/dwm.exe -start=auto -critical=false -restart=never -ready_timeout_ms=5000 -stop_timeout_ms=5000 requires=rssrv grants=boot.display-present,rssrv.session-control,rssrv.desktop-publisher exports=desktop diff --git a/code/tests/ddk/module_export_smoke.c b/code/tests/ddk/module_export_smoke.c deleted file mode 100644 index 7da403c..0000000 --- a/code/tests/ddk/module_export_smoke.c +++ /dev/null @@ -1,10 +0,0 @@ -// A minimal no-entry DLL image used to check the public module-export ABI. - -#include - -static KSTATUS TestInitialize(NTL_MODULE* module) { - (void)module; - return NTLSTATUS_SUCCESS; -} - -NTL_DECLARE_MODULE(TestInitialize); diff --git a/code/tests/ddk/pci_caps_test.c b/code/tests/ddk/pci_caps_test.c deleted file mode 100644 index 875c134..0000000 --- a/code/tests/ddk/pci_caps_test.c +++ /dev/null @@ -1,37 +0,0 @@ -// Host-runnable tests for the pure DDK PCI capability-list helper. - -#include -#include -#include - -static uint32_t ReadConfig(void* context, uint16_t offset) { - const uint32_t* config = (const uint32_t*)context; - return config[offset / 4u]; -} - -int main(void) { - uint32_t config[64] = {0}; - NTL_PCI_CONFIG_READER reader = { config, ReadConfig }; - uint8_t offset = 0xFFu; - - assert(NtlPciFindCapability(&reader, 0, 0x05u, &offset) == NTLSTATUS_NOT_FOUND); - assert(offset == 0); - - config[0x40u / 4u] = 0x00004801u; - config[0x48u / 4u] = 0x00000005u; - assert(KSUCCESS(NtlPciFindCapability(&reader, 0x40u, 0x05u, &offset))); - assert(offset == 0x48u); - assert(NtlPciFindCapability(&reader, 0x40u, 0x11u, &offset) == NTLSTATUS_NOT_FOUND); - assert(offset == 0); - - config[0x48u / 4u] = 0x00004002u; - assert(NtlPciFindCapability(&reader, 0x40u, 0x05u, &offset) == NTLSTATUS_DEVICE_ERROR); - assert(offset == 0); - - assert(NtlPciFindCapability(&reader, 0x20u, 0x05u, &offset) == NTLSTATUS_DEVICE_ERROR); - assert(NtlPciFindCapability(&reader, 0x41u, 0x05u, &offset) == NTLSTATUS_DEVICE_ERROR); - assert(NtlPciFindCapability((NTL_PCI_CONFIG_READER*)0, 0x40u, 0x05u, &offset) == NTLSTATUS_INVALID_PARAMETER); - assert(NtlPciFindCapability(&reader, 0x40u, 0x05u, (uint8_t*)0) == NTLSTATUS_INVALID_PARAMETER); - assert(NtlPciFindCapability(&reader, 0x40u, 0, &offset) == NTLSTATUS_INVALID_PARAMETER); - return 0; -} diff --git a/code/tests/driver_manager/README.md b/code/tests/driver_manager/README.md deleted file mode 100644 index 9372e41..0000000 --- a/code/tests/driver_manager/README.md +++ /dev/null @@ -1,13 +0,0 @@ -# Driver Manager v2 host checks - -Run the portable parser/graph regression test from the repository root: - -```sh -gcc -std=c17 -Wall -Wextra -Werror -Icode/kernel/include -Icode/public \ - code/kernel/dm_config.c code/tests/driver_manager/config_test.c \ - -o config_test -./config_test code/drivers/drivers.ini -``` - -The bootloader/kernel ABI must additionally be built with the MSVC toolchain; -these host tests do not establish a boot success or verify EFI firmware I/O. diff --git a/code/tests/driver_manager/config_test.c b/code/tests/driver_manager/config_test.c deleted file mode 100644 index e1ecb64..0000000 --- a/code/tests/driver_manager/config_test.c +++ /dev/null @@ -1,138 +0,0 @@ -// Host-side regression tests for the canonical drivers.ini v2 graph semantics. - -#include -#include -#include -#include -#include - -static DM_CONFIG* gConfig; - -static bool Parse(const char* source) { - char error[128] = {0}; - bool ok = DmConfigParse(gConfig, source, strlen(source), error, sizeof(error)); - if (!ok) fprintf(stderr, "parse rejected (%s):\n%s\n", error, source); - return ok; -} - -static bool Reject(const char* source) { - char error[128] = {0}; - if (DmConfigParse(gConfig, source, strlen(source), error, sizeof(error))) { - fprintf(stderr, "unexpected acceptance:\n%s\n", source); - return false; - } - return error[0] != '\0'; -} - -static int Find(const char* id) { - for (uint32_t i = 0; i < gConfig->DriverCount; ++i) - if (!strcmp(gConfig->Drivers[i].Id, id)) return (int)i; - return -1; -} - -int main(int argc, char** argv) { - gConfig = calloc(1, sizeof(*gConfig)); - assert(gConfig); - assert(Parse("[driver.a]\nimage=a.sys\nstart=boot\n")); - assert(gConfig->Drivers[0].Class[0] == 0 && !gConfig->Drivers[0].Critical); - assert(Parse("[driver.a]\nimage=a.sys\nstart=boot\n" - "class=\nrequires=\nafter=\ncritical=\n")); - assert(gConfig->Drivers[0].Class[0] == 0 && !gConfig->Drivers[0].Critical); - assert(Reject("[driver.a]\nimage=a.sys\n")); - assert(Reject("[driver.a]\nimage=\nstart=boot\n")); - assert(Reject("[driver.a]\nimage=a.sys\nstart=boot\nfoobar=\n")); - assert(Reject("[driver.a]\nimage=a.sys\nstart=boot\nstart=runtime\n")); - assert(Reject("[driver.a]\nimage=a.sys\nstart=boot\n[driver.a]\nimage=b.sys\nstart=boot\n")); - assert(Reject("[driver.a]\nimage=a.sys\nstart=boot\n[class.other]\n")); - assert(Reject("[driver.a]\nimage=a.sys\nstart=boot\nrequires=missing\n")); - assert(Reject("[driver.a]\nimage=a.sys\nstart=boot\nafter=missing\n")); - assert(Reject("[driver.a]\nimage=a.sys\nstart=boot\nrequires=a\n")); - assert(Reject("[driver.a]\nimage=a.sys\nstart=boot\nrequires=b\n" - "[driver.b]\nimage=b.sys\nstart=boot\nrequires=a\n")); - assert(Reject("[class.a]\nrequires=b\n[class.b]\nrequires=a\n" - "[driver.c]\nimage=c.sys\nstart=boot\n")); - assert(Reject("[class.bus]\n[class.fs]\nafter=bus\n" - "[driver.a]\nimage=a.sys\nstart=boot\nclass=bus\nrequires=b\n" - "[driver.b]\nimage=b.sys\nstart=boot\nclass=fs\n")); - assert(Reject("[driver.a]\nimage=a.sys\nstart=boot\nrequires=b\n" - "[driver.b]\nimage=b.sys\nstart=runtime\n")); - assert(Reject("[class.bus]\n[driver.a]\nimage=a.sys\nstart=boot\nclass=bus\n" - "requires=\nrequires=\n")); - assert(Reject("[class.bus]\n[driver.a]\nimage=a.sys\nstart=boot\nclass=bus\n" - "requires=a\nafter=a\n")); - assert(Reject("[driver.a]\nimage=a.sys\nstart=boot\n" - "[driver.b]\nimage=a.sys\nstart=runtime\n")); - - // Provider alternatives are OR dependencies; requiring every provider here - // would manufacture a false cycle between client and the second provider. - assert(Parse("[class.providers]\n" - "[class.clients]\nrequires=providers\n" - "[driver.p1]\nimage=p1.sys\nstart=boot\nclass=providers\n" - "[driver.p2]\nimage=p2.sys\nstart=boot\nclass=providers\nrequires=client\n" - "[driver.client]\nimage=client.sys\nstart=boot\nclass=clients\n")); - gConfig->ActivePhase = DmStartBoot; - assert(DmDriverCanStart(gConfig, (uint32_t)Find("p1"))); - assert(!DmDriverCanStart(gConfig, (uint32_t)Find("client"))); - gConfig->Drivers[Find("p1")].State = DmRunStarted; - assert(DmDriverCanStart(gConfig, (uint32_t)Find("client"))); - gConfig->Drivers[Find("client")].State = DmRunStarted; - assert(DmDriverCanStart(gConfig, (uint32_t)Find("p2"))); - - // A soft barrier waits for all current-phase providers, even failures. - assert(Parse("[class.nic]\n[class.stack]\nafter=nic\n" - "[driver.a]\nimage=a.sys\nstart=runtime\nclass=nic\n" - "[driver.b]\nimage=b.sys\nstart=runtime\nclass=nic\n" - "[driver.stack]\nimage=stack.sys\nstart=runtime\nclass=stack\n")); - gConfig->ActivePhase = DmStartRuntime; - assert(!DmDriverCanStart(gConfig, (uint32_t)Find("stack"))); - gConfig->Drivers[Find("a")].State = DmRunFailed; - gConfig->Drivers[Find("b")].State = DmRunFailed; - assert(DmDriverCanStart(gConfig, (uint32_t)Find("stack"))); - - // An empty declared class is settled, not a parser error. A soft consumer - // still starts when no driver provides that class. - assert(Parse("[class.nic]\n[class.stack]\nafter=nic\n" - "[driver.stack]\nimage=stack.sys\nstart=runtime\nclass=stack\n")); - gConfig->ActivePhase = DmStartRuntime; - assert(DmDriverCanStart(gConfig, (uint32_t)Find("stack"))); - - // A boot class requirement can use a boot provider even when additional - // providers will join the class during the runtime phase. - assert(Parse("[class.bus]\n[class.client]\nrequires=bus\n" - "[driver.pci]\nimage=pci.sys\nstart=boot\nclass=bus\n" - "[driver.virtual]\nimage=virtual.sys\nstart=runtime\nclass=bus\n" - "[driver.client]\nimage=client.sys\nstart=boot\nclass=client\n")); - gConfig->ActivePhase = DmStartBoot; - gConfig->Drivers[Find("pci")].State = DmRunStarted; - assert(DmDriverCanStart(gConfig, (uint32_t)Find("client"))); - assert(DmClassSettled(gConfig, "bus")); - gConfig->ActivePhase = DmStartRuntime; - assert(!DmClassSettled(gConfig, "bus")); - - // A boot hard dependency cannot be satisfied solely by a runtime provider. - assert(Reject("[class.bus]\n[class.client]\nrequires=bus\n" - "[driver.virtual]\nimage=virtual.sys\nstart=runtime\nclass=bus\n" - "[driver.client]\nimage=client.sys\nstart=boot\nclass=client\n")); - - // A disabled provider never satisfies a hard requires edge. - assert(Parse("[driver.a]\nimage=a.sys\nstart=disabled\n" - "[driver.b]\nimage=b.sys\nstart=runtime\nrequires=a\n")); - assert(gConfig->Drivers[Find("a")].State == DmRunDisabled); - assert(DmDriverIsBlocked(gConfig, (uint32_t)Find("b"))); - - if (argc == 2) { - FILE* file = fopen(argv[1], "rb"); - assert(file); - char* input = calloc(1, DM_CONFIG_MAX_BYTES + 1); - assert(input); - size_t size = fread(input, 1, DM_CONFIG_MAX_BYTES, file); - fclose(file); - char error[128] = {0}; - assert(DmConfigParse(gConfig, input, size, error, sizeof(error))); - assert(gConfig->DriverCount == 14); - free(input); - } - puts("driver manager config tests passed"); - free(gConfig); - return 0; -} diff --git a/code/tests/driver_manager/pnp_mock/include/kernel/ke_debug.h b/code/tests/driver_manager/pnp_mock/include/kernel/ke_debug.h deleted file mode 100644 index b80e346..0000000 --- a/code/tests/driver_manager/pnp_mock/include/kernel/ke_debug.h +++ /dev/null @@ -1,2 +0,0 @@ -#pragma once -void DbgPrint(const char* fmt, ...); diff --git a/code/tests/driver_manager/pnp_mock/include/kernel/ke_event.h b/code/tests/driver_manager/pnp_mock/include/kernel/ke_event.h deleted file mode 100644 index c5e99b5..0000000 --- a/code/tests/driver_manager/pnp_mock/include/kernel/ke_event.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once -#include -#include -#include -typedef struct EVENT EVENT; -typedef enum EVENT_TYPE { EventAutoReset, EventManualReset } EVENT_TYPE; -KSTATUS KeEventCreate(EVENT_TYPE type, bool initial, EVENT** out); -void KeSignalEvent(EVENT* event); -KSTATUS KeWaitForEvent(EVENT* event, bool alertable); -KSTATUS KeWaitForMultipleEvents(EVENT** events, uint32_t count, bool alertable, uint64_t timeoutMs, uint32_t* index); diff --git a/code/tests/driver_manager/pnp_mock/include/kernel/ke_spinlock.h b/code/tests/driver_manager/pnp_mock/include/kernel/ke_spinlock.h deleted file mode 100644 index 40ff7a9..0000000 --- a/code/tests/driver_manager/pnp_mock/include/kernel/ke_spinlock.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once -#include -#include -typedef pthread_mutex_t SPINLOCK; -#define SPINLOCK_INIT PTHREAD_MUTEX_INITIALIZER -static inline uintptr_t KeAcquireSpinlock(SPINLOCK* l) { pthread_mutex_lock(l); return 0; } -static inline void KeReleaseSpinlock(SPINLOCK* l, uintptr_t ignored) { (void)ignored; pthread_mutex_unlock(l); } diff --git a/code/tests/driver_manager/pnp_mock/include/kernel/ke_thread.h b/code/tests/driver_manager/pnp_mock/include/kernel/ke_thread.h deleted file mode 100644 index 510417e..0000000 --- a/code/tests/driver_manager/pnp_mock/include/kernel/ke_thread.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include -#include -typedef struct THREAD THREAD; -typedef enum THREAD_PRIORITY { PriorityNormal = 1 } THREAD_PRIORITY; -typedef struct KE_THREAD_CREATE_PARAMETERS { uint32_t Priority; const char* Name; } KE_THREAD_CREATE_PARAMETERS; -#define KE_THREAD_CREATE_NAMED_NORMAL(priority, name) { (priority), (name) } -KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg, - const KE_THREAD_CREATE_PARAMETERS* params, THREAD** out); diff --git a/code/tests/driver_manager/pnp_mock/include/kernel/ke_time.h b/code/tests/driver_manager/pnp_mock/include/kernel/ke_time.h deleted file mode 100644 index 069e524..0000000 --- a/code/tests/driver_manager/pnp_mock/include/kernel/ke_time.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include -uint64_t KeMonotonicDeadlineAfterMilliseconds(uint64_t ms); -uint64_t KeMonotonicMillisecondsUntil(uint64_t deadlineUs); diff --git a/code/tests/driver_manager/pnp_mock/include/kernel/ke_work.h b/code/tests/driver_manager/pnp_mock/include/kernel/ke_work.h deleted file mode 100644 index d40fff9..0000000 --- a/code/tests/driver_manager/pnp_mock/include/kernel/ke_work.h +++ /dev/null @@ -1,9 +0,0 @@ -#pragma once -#include -typedef void (*KWORK_ROUTINE)(void* context); -typedef struct KWORK_ITEM { - KWORK_ROUTINE Routine; - void* Context; -} KWORK_ITEM; -void KeInitializeWorkItem(KWORK_ITEM* item, KWORK_ROUTINE routine, void* context); -bool KeQueueWorkItem(KWORK_ITEM* item); diff --git a/code/tests/driver_manager/pnp_mock/include/kernel/mm_virt.h b/code/tests/driver_manager/pnp_mock/include/kernel/mm_virt.h deleted file mode 100644 index fd915cb..0000000 --- a/code/tests/driver_manager/pnp_mock/include/kernel/mm_virt.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include -void* MmAllocatePool(size_t size); -void MmFreePool(void* ptr); diff --git a/code/tests/driver_manager/pnp_mock/include/ntlite/ddi/io_driver.h b/code/tests/driver_manager/pnp_mock/include/ntlite/ddi/io_driver.h deleted file mode 100644 index cc0a0bc..0000000 --- a/code/tests/driver_manager/pnp_mock/include/ntlite/ddi/io_driver.h +++ /dev/null @@ -1,60 +0,0 @@ -#pragma once -#include -#include -#include - -typedef struct SYS_STRING_VIEW { - const char* Data; - size_t Length; -} SYS_STRING_VIEW; - -typedef enum IO_BUS_TYPE { IoBusUnknown, IoBusPci, IoBusUsb } IO_BUS_TYPE; -typedef enum DEVICE_OBJECT_TYPE { DeviceObjectPhysical = 1, DeviceObjectFunction = 2 } DEVICE_OBJECT_TYPE; -typedef struct DEVICE_OBJECT { - DEVICE_OBJECT_TYPE Type; - union { - struct { - IO_BUS_TYPE BusType; - uint8_t IdCount; - struct { SYS_STRING_VIEW Id; } Ids[8]; - } Pdo; - } u; - struct DEVICE_OBJECT* AttachedDevice; - struct DEVICE_OBJECT* Parent; - struct DEVICE_OBJECT* LowerDevice; - bool DeletePending; - int Refs; -} DEVICE_OBJECT; -void IoReferenceDeviceObject(DEVICE_OBJECT* device); -void IoDereferenceDeviceObject(DEVICE_OBJECT* device); - -#include -#include -#include - -typedef struct IO_DEVICE_ID { - IO_BUS_TYPE BusType; - SYS_STRING_VIEW Id; -} IO_DEVICE_ID; -typedef struct IO_DRIVER_ID_TABLE { - const IO_DEVICE_ID* Ids; - size_t Count; -} IO_DRIVER_ID_TABLE; -typedef struct DRIVER_OBJECT DRIVER_OBJECT; -struct DRIVER_OBJECT { - SYS_STRING_VIEW Name; - const IO_DRIVER_ID_TABLE* IdTable; - KSTATUS (*DriverAddDevice)(DRIVER_OBJECT*, DEVICE_OBJECT*); -}; -typedef enum IO_PNP_MINOR_FUNCTION { - IRP_MN_START_DEVICE, - IRP_MN_REMOVE_DEVICE, -} IO_PNP_MINOR_FUNCTION; -static inline SYS_STRING_VIEW SysSvFromParts(const char* ptr, size_t len) { - SYS_STRING_VIEW sv = {ptr, len}; - return sv; -} -static inline bool SysSvEqual(SYS_STRING_VIEW a, SYS_STRING_VIEW b) { - return a.Length == b.Length && (!a.Length || memcmp(a.Data, b.Data, a.Length) == 0); -} -KSTATUS IoSendPnpIrpSync(DEVICE_OBJECT* device, IO_PNP_MINOR_FUNCTION minor); diff --git a/code/tests/driver_manager/pnp_test.c b/code/tests/driver_manager/pnp_test.c deleted file mode 100644 index eae9d23..0000000 --- a/code/tests/driver_manager/pnp_test.c +++ /dev/null @@ -1,350 +0,0 @@ -#define _POSIX_C_SOURCE 200809L -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct EVENT { - pthread_mutex_t Mutex; - pthread_cond_t Cond; - int Signaled; -}; - -static _Atomic int starts, stops, cancels, releases; -static _Atomic int ioAdds, ioPnPStarts, ioPnPRemoves; -static DEVICE_OBJECT* ioDevice; -static NTL_DEVICE* pendingDevice; -static NTL_DEVICE* ordinaryDevice; - -static uint64_t NowUs(void) { - struct timespec now; - clock_gettime(CLOCK_MONOTONIC, &now); - return (uint64_t)now.tv_sec * 1000000u + (uint64_t)now.tv_nsec / 1000u; -} -uint64_t KeMonotonicDeadlineAfterMilliseconds(uint64_t ms) { return NowUs() + ms * 1000u; } -uint64_t KeMonotonicMillisecondsUntil(uint64_t deadlineUs) { - uint64_t now = NowUs(); - return now >= deadlineUs ? 0 : (deadlineUs - now + 999u) / 1000u; -} -void DbgPrint(const char* fmt, ...) { (void)fmt; } -void* MmAllocatePool(size_t size) { return malloc(size); } -void MmFreePool(void* memory) { free(memory); } -void IoReferenceDeviceObject(DEVICE_OBJECT* device) { __atomic_add_fetch(&device->Refs, 1, __ATOMIC_SEQ_CST); } -void IoDereferenceDeviceObject(DEVICE_OBJECT* device) { __atomic_sub_fetch(&device->Refs, 1, __ATOMIC_SEQ_CST); } -KSTATUS IoSendPnpIrpSync(DEVICE_OBJECT* device, IO_PNP_MINOR_FUNCTION minor) { - if (minor == IRP_MN_START_DEVICE) ++ioPnPStarts; - if (minor == IRP_MN_REMOVE_DEVICE) ++ioPnPRemoves; - assert(device == ioDevice); - return NTLSTATUS_SUCCESS; -} -static KSTATUS IoAddDevice(DRIVER_OBJECT* driver, DEVICE_OBJECT* pdo) { - (void)driver; - ioDevice = pdo; - ++ioAdds; - pdo->AttachedDevice = pdo; - return NTLSTATUS_SUCCESS; -} -KSTATUS KeEventCreate(EVENT_TYPE type, bool initial, EVENT** out) { - (void)type; - EVENT* event = calloc(1, sizeof(*event)); - assert(event); - pthread_mutex_init(&event->Mutex, NULL); - pthread_cond_init(&event->Cond, NULL); - event->Signaled = initial; - *out = event; - return NTLSTATUS_SUCCESS; -} -void KeSignalEvent(EVENT* event) { - pthread_mutex_lock(&event->Mutex); - event->Signaled = 1; - pthread_cond_signal(&event->Cond); - pthread_mutex_unlock(&event->Mutex); -} -KSTATUS KeWaitForMultipleEvents(EVENT** events, uint32_t count, bool alertable, - uint64_t timeoutMs, uint32_t* index) { - (void)alertable; - assert(count == 1); - EVENT* event = events[0]; - pthread_mutex_lock(&event->Mutex); - struct timespec ts; - clock_gettime(CLOCK_REALTIME, &ts); - ts.tv_sec += (time_t)(timeoutMs / 1000); - ts.tv_nsec += (long)(timeoutMs % 1000) * 1000000L; - if (ts.tv_nsec >= 1000000000L) { ts.tv_nsec -= 1000000000L; ++ts.tv_sec; } - while (!event->Signaled) { - int result = pthread_cond_timedwait(&event->Cond, &event->Mutex, &ts); - if (result == ETIMEDOUT) { pthread_mutex_unlock(&event->Mutex); return NTLSTATUS_TIMEOUT; } - } - event->Signaled = 0; - pthread_mutex_unlock(&event->Mutex); - if (index) *index = 0; - return NTLSTATUS_SUCCESS; -} -KSTATUS KeWaitForEvent(EVENT* event, bool alertable) { - (void)alertable; - pthread_mutex_lock(&event->Mutex); - while (!event->Signaled) pthread_cond_wait(&event->Cond, &event->Mutex); - event->Signaled = 0; - pthread_mutex_unlock(&event->Mutex); - return NTLSTATUS_SUCCESS; -} -void KeInitializeWorkItem(KWORK_ITEM* item, KWORK_ROUTINE routine, void* context) { - item->Routine = routine; - item->Context = context; -} -bool KeQueueWorkItem(KWORK_ITEM* item) { - item->Routine(item->Context); - return true; -} -static void* RunThread(void* arg) { - uintptr_t* fnArg = arg; - void (*fn)(void*) = (void(*)(void*))fnArg[0]; - void* ctx = (void*)fnArg[1]; - free(fnArg); - fn(ctx); - return NULL; -} -KSTATUS KeCreateKernelThread(uintptr_t fn, uintptr_t arg, const KE_THREAD_CREATE_PARAMETERS* params, THREAD** out) { - (void)params; (void)out; - uintptr_t* args = malloc(2 * sizeof(uintptr_t)); - assert(args); - args[0] = fn; args[1] = arg; - pthread_t id; - assert(!pthread_create(&id, NULL, RunThread, args)); - pthread_detach(id); - return NTLSTATUS_SUCCESS; -} -static pthread_mutex_t gateLock = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t gateCond = PTHREAD_COND_INITIALIZER; -static _Atomic int slowEntered, fastDone; -static bool gateOpen; -static KSTATUS SlowStart(NTL_DEVICE* device) { - (void)device; - ++slowEntered; - pthread_mutex_lock(&gateLock); - while (!gateOpen) pthread_cond_wait(&gateCond, &gateLock); - pthread_mutex_unlock(&gateLock); - return NTLSTATUS_SUCCESS; -} -static KSTATUS FastStart(NTL_DEVICE* device) { - (void)device; - ++fastDone; - return NTLSTATUS_SUCCESS; -} -static void WaitForAtomic(_Atomic int* value) { - struct timespec delay = {0, 1000000L}; - for (int i = 0; i < 1000 && !*value; ++i) nanosleep(&delay, NULL); - assert(*value); -} -static void Released(void* ctx) { assert(ctx == (void*)0x1234); ++releases; } -static KSTATUS OrdinaryStart(NTL_DEVICE* device) { - ++starts; - assert(NtlDeviceBus(device) == NtlBusPci); - assert(!strcmp(NtlDeviceId(device, 0), "PCI\\VEN_1234")); - ordinaryDevice = device; - NTL_DEVICE_RESOURCE* r = NULL; - assert(KSUCCESS(NtlDeviceOwnResource(device, (void*)0x1234, Released, &r))); - assert(r); - return NTLSTATUS_SUCCESS; -} -static KSTATUS PendingStart(NTL_DEVICE* device) { - ++starts; - pendingDevice = device; - return NTLSTATUS_PENDING; -} -static KSTATUS FailingStart(NTL_DEVICE* device) { - ++starts; - NTL_DEVICE_RESOURCE* r = NULL; - assert(KSUCCESS(NtlDeviceOwnResource(device, (void*)0x1234, Released, &r))); - return NTLSTATUS_FAILURE; -} -static void Stopped(NTL_DEVICE* device) { assert(device); ++stops; } -static void Cancelled(NTL_DEVICE* device) { - ++cancels; - assert(KSUCCESS(NtlDeviceCompleteStart(device, NTLSTATUS_CANCELLED))); -} -static _Atomic int topologyLeafStopped, topologyHubStopped, topologyControllerStopped; - -static KSTATUS TopologyStart(NTL_DEVICE* device) { - (void)device; - return NTLSTATUS_SUCCESS; -} - -static void TopologyStop(NTL_DEVICE* device) { - const char* id = NtlDeviceId(device, 0); - if (!strcmp(id, "USB\\STORAGE")) { - ++topologyLeafStopped; - } else if (!strcmp(id, "USB\\ROOT_HUB")) { - assert(topologyLeafStopped == 1); - ++topologyHubStopped; - } else if (!strcmp(id, "PCI\\USB_XHCI")) { - assert(topologyHubStopped == 1); - ++topologyControllerStopped; - } else { - assert(0); - } -} - -static DEVICE_OBJECT MakePdo(const char* id) { - DEVICE_OBJECT pdo = {0}; - pdo.Type = DeviceObjectPhysical; - pdo.Refs = 1; - pdo.u.Pdo.BusType = IoBusPci; - pdo.u.Pdo.IdCount = 1; - pdo.u.Pdo.Ids[0].Id.Data = id; - pdo.u.Pdo.Ids[0].Id.Length = strlen(id); - return pdo; -} -int main(void) { - const NTL_DEVICE_MATCH matches[] = { { NtlBusPci, "PCI\\VEN_1234" } }; - const NTL_DEVICE_DESC descriptor = { - sizeof(NTL_DEVICE_DESC), 0, "pci.test", matches, 1, 16, OrdinaryStart, Stopped, NULL - }; - assert(KSUCCESS(IoPnpInitialize())); - assert(KSUCCESS(IoPnpPublishModule((void*)1, &descriptor, 1, NULL, 0))); - assert(IoPnpPublishModule((void*)1, &descriptor, 1, NULL, 0) == NTLSTATUS_ALREADY_EXISTS); - DEVICE_OBJECT pdo = MakePdo("PCI\\VEN_1234"); - assert(KSUCCESS(IoPnpPhysicalDeviceArrived(&pdo))); - IoPnpPhysicalDevicePublished(&pdo); - assert(KSUCCESS(IoPnpWaitForIdle(1000))); - assert(starts == 1 && ordinaryDevice); - IoPnpPhysicalDeviceRemoved(&pdo); - assert(KSUCCESS(IoPnpWaitForIdle(1000))); - assert(stops == 1 && releases == 1 && pdo.Refs == 1); - - const NTL_DEVICE_DESC pending = { - sizeof(NTL_DEVICE_DESC), 0, "pci.pending", matches, 1, 0, PendingStart, Stopped, Cancelled - }; - const NTL_DEVICE_MATCH pendingMatches[] = { { NtlBusPci, "PCI\\VEN_5678" } }; - NTL_DEVICE_DESC selected = pending; - selected.Matches = pendingMatches; - assert(KSUCCESS(IoPnpPublishModule((void*)2, &selected, 1, NULL, 0))); - DEVICE_OBJECT pdo2 = MakePdo("PCI\\VEN_5678"); - assert(KSUCCESS(IoPnpPhysicalDeviceArrived(&pdo2))); - IoPnpPhysicalDevicePublished(&pdo2); - assert(IoPnpWaitForIdle(50) == NTLSTATUS_TIMEOUT); - IoPnpPhysicalDeviceRemoved(&pdo2); - assert(KSUCCESS(IoPnpWaitForIdle(1000))); - assert(cancels == 1 && pdo2.Refs == 1); - - const NTL_DEVICE_MATCH failingMatches[] = { { NtlBusPci, "PCI\\VEN_9999" } }; - const NTL_DEVICE_DESC failing = { - sizeof(NTL_DEVICE_DESC), 0, "pci.failing", failingMatches, 1, 0, FailingStart, Stopped, NULL - }; - assert(KSUCCESS(IoPnpPublishModule((void*)3, &failing, 1, NULL, 0))); - DEVICE_OBJECT pdo3 = MakePdo("PCI\\VEN_9999"); - assert(KSUCCESS(IoPnpPhysicalDeviceArrived(&pdo3))); - IoPnpPhysicalDevicePublished(&pdo3); - assert(KSUCCESS(IoPnpWaitForIdle(1000))); - assert(releases == 2); - IoPnpPhysicalDeviceRemoved(&pdo3); - assert(KSUCCESS(IoPnpWaitForIdle(1000))); - assert(pdo3.Refs == 1); - const NTL_DEVICE_MATCH slowMatches[] = { { NtlBusPci, "PCI\\VEN_AAAA" } }; - const NTL_DEVICE_MATCH fastMatches[] = { { NtlBusPci, "PCI\\VEN_BBBB" } }; - const NTL_DEVICE_DESC concurrent[] = { - {sizeof(NTL_DEVICE_DESC), 0, "pci.slow", slowMatches, 1, 0, SlowStart, NULL, NULL}, - {sizeof(NTL_DEVICE_DESC), 0, "pci.fast", fastMatches, 1, 0, FastStart, NULL, NULL}, - }; - assert(KSUCCESS(IoPnpPublishModule((void*)4, concurrent, 2, NULL, 0))); - DEVICE_OBJECT slowPdo = MakePdo("PCI\\VEN_AAAA"); - DEVICE_OBJECT fastPdo = MakePdo("PCI\\VEN_BBBB"); - assert(KSUCCESS(IoPnpPhysicalDeviceArrived(&slowPdo))); - IoPnpPhysicalDevicePublished(&slowPdo); - WaitForAtomic(&slowEntered); - assert(KSUCCESS(IoPnpPhysicalDeviceArrived(&fastPdo))); - IoPnpPhysicalDevicePublished(&fastPdo); - WaitForAtomic(&fastDone); - pthread_mutex_lock(&gateLock); - gateOpen = true; - pthread_cond_broadcast(&gateCond); - pthread_mutex_unlock(&gateLock); - assert(KSUCCESS(IoPnpWaitForIdle(1000))); - IoPnpPhysicalDeviceRemoved(&slowPdo); - IoPnpPhysicalDeviceRemoved(&fastPdo); - assert(KSUCCESS(IoPnpWaitForIdle(1000))); - assert(slowPdo.Refs == 1 && fastPdo.Refs == 1); - const IO_DEVICE_ID ids[] = { { IoBusPci, {"PCI\\VEN_CAFE", 12} } }; - const IO_DRIVER_ID_TABLE idsTable = { ids, 1 }; - DRIVER_OBJECT ioDriver = { {"pci.io", 6}, &idsTable, IoAddDevice }; - DRIVER_OBJECT* ioDrivers[] = { &ioDriver }; - assert(KSUCCESS(IoPnpPublishModule((void*)5, NULL, 0, ioDrivers, 1))); - assert(IoPnpPublishModule((void*)5, NULL, 0, ioDrivers, 1) == NTLSTATUS_ALREADY_EXISTS); - const NTL_DEVICE_DESC conflicting = { - sizeof(NTL_DEVICE_DESC), 0, "pci.io", matches, 1, 0, OrdinaryStart, NULL, NULL - }; - assert(IoPnpPublishModule((void*)6, &conflicting, 1, NULL, 0) == NTLSTATUS_ALREADY_EXISTS); - DRIVER_OBJECT sameName = { {"pci.test", 8}, &idsTable, IoAddDevice }; - DRIVER_OBJECT* conflictingIo[] = { &sameName }; - assert(IoPnpPublishModule((void*)6, NULL, 0, conflictingIo, 1) == NTLSTATUS_ALREADY_EXISTS); - DEVICE_OBJECT ioPdo = MakePdo("PCI\\VEN_CAFE"); - assert(KSUCCESS(IoPnpPhysicalDeviceArrived(&ioPdo))); - IoPnpPhysicalDevicePublished(&ioPdo); - assert(KSUCCESS(IoPnpWaitForIdle(1000))); - assert(ioAdds == 1 && ioPnPStarts == 1); - IoPnpPhysicalDeviceRemoved(&ioPdo); - assert(KSUCCESS(IoPnpWaitForIdle(1000))); - assert(ioPnPRemoves == 1 && ioPdo.Refs == 1); - DEVICE_OBJECT predeleted = MakePdo("PCI\\VEN_CAFE"); - assert(KSUCCESS(IoPnpPhysicalDeviceArrived(&predeleted))); - IoPnpPhysicalDevicePublished(&predeleted); - assert(KSUCCESS(IoPnpWaitForIdle(1000))); - int previousRemoves = ioPnPRemoves; - predeleted.DeletePending = true; - IoPnpPhysicalDeviceRemoved(&predeleted); - assert(KSUCCESS(IoPnpWaitForIdle(1000))); - assert(ioPnPRemoves == previousRemoves); - assert(predeleted.Refs == 1); - - const NTL_DEVICE_MATCH topologyMatches[] = { - {NtlBusPci, "PCI\\USB_XHCI"}, - {NtlBusUsb, "USB\\ROOT_HUB"}, - {NtlBusUsb, "USB\\STORAGE"}, - }; - NTL_DEVICE_DESC topology[3] = { - {sizeof(NTL_DEVICE_DESC), 0, "shutdown.controller", &topologyMatches[0], 1, 0, TopologyStart, TopologyStop, NULL}, - {sizeof(NTL_DEVICE_DESC), 0, "shutdown.hub", &topologyMatches[1], 1, 0, TopologyStart, TopologyStop, NULL}, - {sizeof(NTL_DEVICE_DESC), 0, "shutdown.leaf", &topologyMatches[2], 1, 0, TopologyStart, TopologyStop, NULL}, - }; - assert(KSUCCESS(IoPnpPublishModule((void*)7, topology, 3, NULL, 0))); - - DEVICE_OBJECT controller = MakePdo("PCI\\USB_XHCI"); - DEVICE_OBJECT controllerFdo = {0}; - controllerFdo.Type = DeviceObjectFunction; - controllerFdo.LowerDevice = &controller; - DEVICE_OBJECT rootHub = MakePdo("USB\\ROOT_HUB"); - rootHub.u.Pdo.BusType = IoBusUsb; - rootHub.Parent = &controllerFdo; - DEVICE_OBJECT hubFdo = {0}; - hubFdo.Type = DeviceObjectFunction; - hubFdo.LowerDevice = &rootHub; - DEVICE_OBJECT leaf = MakePdo("USB\\STORAGE"); - leaf.u.Pdo.BusType = IoBusUsb; - leaf.Parent = &hubFdo; - - assert(KSUCCESS(IoPnpPhysicalDeviceArrived(&controller))); - IoPnpPhysicalDevicePublished(&controller); - assert(KSUCCESS(IoPnpPhysicalDeviceArrived(&rootHub))); - IoPnpPhysicalDevicePublished(&rootHub); - assert(KSUCCESS(IoPnpPhysicalDeviceArrived(&leaf))); - IoPnpPhysicalDevicePublished(&leaf); - assert(KSUCCESS(IoPnpWaitForIdle(1000))); - assert(KSUCCESS(IoPnpShutdown(1000))); - assert(topologyLeafStopped == 1); - assert(topologyHubStopped == 1); - assert(topologyControllerStopped == 1); - assert(controller.Refs == 1 && rootHub.Refs == 1 && leaf.Refs == 1); - puts("pnp tests passed"); - return 0; -} diff --git a/code/tests/host/service_control_contract.c b/code/tests/host/service_control_contract.c deleted file mode 100644 index 101c338..0000000 --- a/code/tests/host/service_control_contract.c +++ /dev/null @@ -1,65 +0,0 @@ -// Host-side regression test for the native service READY/STOP wire contract. -// Build: clang -std=c17 -Wall -Wextra -Werror -Icode/public tests/host/service_control_contract.c -o /tmp/service_control_contract - -#include -#include -#include - -static NTL_SERVICE_CONTROL_MESSAGE make_ready(uint32_t count) { - NTL_SERVICE_CONTROL_MESSAGE message; - memset(&message, 0, sizeof(message)); - message.Size = sizeof(message); - message.Version = NTL_SERVICE_CONTROL_VERSION; - message.Operation = NTL_SERVICE_CONTROL_READY; - message.ExportCount = count; - message.Status = NTLSTATUS_SUCCESS; - return message; -} - -int main(void) { - NTL_SERVICE_CONTROL_MESSAGE message = make_ready(2u); - assert(NtlServiceControlNameExport(&message, 0u, "session-control")); - assert(NtlServiceControlNameExport(&message, 1u, "namespace-admin")); - assert(NtlServiceControlValid(&message, NTL_SERVICE_CONTROL_READY, 2u)); - assert(NtlServiceControlFindExport(&message, "namespace-admin") == 1); - assert(NtlServiceControlFindExport(&message, "session-control") == 0); - assert(NtlServiceControlFindExport(&message, "missing") == -1); - - assert(!NtlServiceControlValid(&message, NTL_SERVICE_CONTROL_READY, 1u)); - assert(!NtlServiceControlValid(&message, NTL_SERVICE_CONTROL_STOP, 2u)); - assert(!NtlServiceControlNameExport(&message, 2u, "outside")); - assert(!NtlServiceControlNameExport(&message, 0u, "invalid/name")); - assert(!NtlServiceControlNameExport(&message, 0u, "01234567890123456789012345678901")); - - assert(NtlServiceControlNameExport(&message, 1u, "session-control")); - assert(!NtlServiceControlValid(&message, NTL_SERVICE_CONTROL_READY, 2u)); - assert(NtlServiceControlNameExport(&message, 1u, "namespace-admin")); - message.ExportNames[1][31] = 'x'; - assert(!NtlServiceControlValid(&message, NTL_SERVICE_CONTROL_READY, 2u)); - message.ExportNames[1][31] = '\0'; - - message.ExportNames[2][0] = 'x'; - assert(!NtlServiceControlValid(&message, NTL_SERVICE_CONTROL_READY, 2u)); - message.ExportNames[2][0] = '\0'; - message.Reserved[1] = 1u; - assert(!NtlServiceControlValid(&message, NTL_SERVICE_CONTROL_READY, 2u)); - message.Reserved[1] = 0u; - message.Version = 2u; - assert(!NtlServiceControlValid(&message, NTL_SERVICE_CONTROL_READY, 2u)); - - message = make_ready(0u); - assert(NtlServiceControlValid(&message, NTL_SERVICE_CONTROL_READY, 0u)); - message = make_ready(0u); - message.Operation = NTL_SERVICE_CONTROL_STOP; - assert(NtlServiceControlValid(&message, NTL_SERVICE_CONTROL_STOP, 0u)); - message.Status = NTLSTATUS_FAILURE; - assert(!NtlServiceControlValid(&message, NTL_SERVICE_CONTROL_STOP, 0u)); - message.Status = NTLSTATUS_SUCCESS; - message.ExportNames[0][0] = 'x'; - assert(!NtlServiceControlValid(&message, NTL_SERVICE_CONTROL_STOP, 0u)); - - message = make_ready(SYS_PORT_MAX_TRANSFER_HANDLES + 1u); - assert(!NtlServiceControlValid(&message, NTL_SERVICE_CONTROL_READY, - SYS_PORT_MAX_TRANSFER_HANDLES + 1u)); - return 0; -} diff --git a/code/tests/memtop_host/test.c b/code/tests/memtop_host/test.c deleted file mode 100644 index 61af98d..0000000 --- a/code/tests/memtop_host/test.c +++ /dev/null @@ -1,62 +0,0 @@ -// Runs one memtop sample with a fake console to detect accidental per-character RPCs. -#include -#include -#include -#include -#include -#include - -#define main memtop_entry -#include "../../user/apps/memtop/memtop.c" -#undef main - -static jmp_buf gDone; -static unsigned gQueries; -static unsigned gWrites; -static uint64_t gSleep; -static char gOutput[128]; - -KSTATUS NtlConsoleQueryInfo(SYS_HANDLE handle, NTL_CONSOLE_INFO* info) { - (void)handle; - ++gQueries; - memset(info, 0, sizeof(*info)); - info->Columns = 100u; - info->Rows = 30u; - return NTLSTATUS_SUCCESS; -} -KSTATUS SysGetMemoryStatus(SYS_MEMORY_STATUS* info) { - memset(info, 0, sizeof(*info)); - info->FreePhysicalBytes = 1024u * 1024u; - info->KernelPoolBytes = 512u * 1024u; - info->UserHeapBytes = 256u * 1024u; - return NTLSTATUS_SUCCESS; -} -KSTATUS NtlConsoleWriteAt(SYS_HANDLE handle, int32_t x, int32_t y, - const char* text, size_t length, size_t* written) { - (void)handle; - if (length >= sizeof(gOutput) || x != 100 - (int32_t)length || y != 0) abort(); - memcpy(gOutput, text, length); - gOutput[length] = '\0'; - if (written) *written = length; - ++gWrites; - return NTLSTATUS_SUCCESS; -} -KSTATUS SysSleep(uint64_t milliseconds) { - gSleep = milliseconds; - longjmp(gDone, 1); - return NTLSTATUS_SUCCESS; -} - -int main(void) { - if (!setjmp(gDone)) (void)memtop_entry(); - if (gQueries != 1u || gWrites != 1u || gSleep != 2000u || - strstr(gOutput, "Free: 1024K") == NULL || - strstr(gOutput, "Pool: 512K") == NULL || - strstr(gOutput, "Heap: 256K") == NULL) { - fprintf(stderr, "memtop regression: query=%u draw=%u sleep=%llu text=%s\n", - gQueries, gWrites, (unsigned long long)gSleep, gOutput); - return 1; - } - puts("memtop positioned batch: PASS"); - return 0; -} diff --git a/code/tests/service_grants_host/test.c b/code/tests/service_grants_host/test.c deleted file mode 100644 index e4b3dd3..0000000 --- a/code/tests/service_grants_host/test.c +++ /dev/null @@ -1,72 +0,0 @@ -// Host regression checks for type-free startup and named capability delegation. -#include -#include -#include -#include "../../user/system/init/service_config.c" - -#define RSSRV "[service.rssrv]\nimage=system/rssrv.exe\nstart=auto\ncritical=true\n" \ - "restart=never\nready_timeout_ms=5000\nstop_timeout_ms=5000\nrequires=\n" \ - "grants=boot.namespace-root\nexports=session-control,desktop-publisher,posix-publisher\n" -#define DWM "[service.dwm]\nimage=system/dwm.exe\nstart=auto\ncritical=false\n" \ - "restart=never\nready_timeout_ms=5000\nstop_timeout_ms=5000\nrequires=rssrv\n" \ - "grants=rssrv.session-control,rssrv.desktop-publisher\nexports=desktop\n" - -static void expect(const char* label, const char* policy, bool shouldPass) { - size_t length = strlen(policy); - char* text = (char*)malloc(length + 1u); - if (!text) abort(); - memcpy(text, policy, length + 1u); - uint32_t count = 0; - uint32_t errorLine = 0; - INIT_SERVICE_CONFIG config; - KSTATUS result = parse_services_ini(text, &count, &errorLine); - if (KSUCCESS(result)) result = validate_services(count, &config, &errorLine); - if (KSUCCESS(result) != shouldPass) { - fprintf(stderr, "%s: result=0x%08x line=%u\n", label, (unsigned)result, errorLine); - exit(1); - } - if (shouldPass && (config.ServiceCount != 2u || - config.Services[1].GrantCount != 2u || - strcmp(config.Services[1].Grants[1], "rssrv.desktop-publisher") != 0)) { - fprintf(stderr, "%s: descriptor lost publication policy\n", label); - exit(1); - } - free(text); -} - -static void check_shipped(const char* path) { - FILE* input = fopen(path, "rb"); - if (!input) { perror(path); exit(1); } - char text[8192]; - size_t used = fread(text, 1u, sizeof(text) - 1u, input); - if (ferror(input) || !feof(input)) abort(); - fclose(input); - text[used] = '\0'; - uint32_t count = 0, errorLine = 0; - INIT_SERVICE_CONFIG config; - KSTATUS result = parse_services_ini(text, &count, &errorLine); - if (KSUCCESS(result)) result = validate_services(count, &config, &errorLine); - if (!KSUCCESS(result) || config.ServiceCount != 3u || - config.StartupCount != 3u || config.Services[0].ExportCount != 3u) { - fprintf(stderr, "shipping configuration: 0x%08x line %u\n", (unsigned)result, errorLine); - exit(1); - } -} - -int main(int argc, char** argv) { - expect("valid named grants", RSSRV DWM, true); - expect("type rejected", RSSRV DWM "type=dwm\n", false); - expect("publication syntax rejected", RSSRV DWM "publishes=desktop:/Sessions/0/Desktop\n", false); - expect("manager section rejected", "[manager]\npublication_authority=rssrv.namespace-admin\n" RSSRV DWM, false); - expect("unknown grant", RSSRV DWM "grants=boot.unknown\n", false); - expect("duplicate export", RSSRV DWM "exports=desktop\n", false); - expect("missing publisher", RSSRV "[service.dwm]\nimage=system/dwm.exe\nstart=auto\ncritical=false\n" - "restart=never\nready_timeout_ms=5000\nstop_timeout_ms=5000\nrequires=rssrv\n" - "grants=rssrv.unknown\nexports=desktop\n", false); - expect("missing grants key", RSSRV "[service.dwm]\nimage=system/dwm.exe\nstart=auto\ncritical=false\n" - "restart=never\nready_timeout_ms=5000\nstop_timeout_ms=5000\nrequires=rssrv\n" - "exports=desktop\n", false); - if (argc == 2) check_shipped(argv[1]); - puts("type-free service policy regression: PASS"); - return 0; -} diff --git a/code/tests/service_publication_host/test.c b/code/tests/service_publication_host/test.c deleted file mode 100644 index d5061b7..0000000 --- a/code/tests/service_publication_host/test.c +++ /dev/null @@ -1,30 +0,0 @@ -// Host-only regression for RSSRV's exact-path publication capability restriction. -#include -#include -#include -#include "../../user/system/rssrv/publication_scope.h" - -static void test(const char* label, const char* scope, uint32_t op, - const char* path, size_t length, bool expect) { - if (RssrvScopeAllows(scope, op, path, (uint32_t)length) != expect) { - fprintf(stderr, "publisher scope mismatch: %s\n", label); - exit(1); - } -} - -int main(void) { - const char* scope = "/Sessions/0/Desktop"; - test("exact bind", scope, NTL_RESOURCE_OP_BIND, scope, strlen(scope), true); - test("exact unbind", scope, NTL_RESOURCE_OP_UNBIND, scope, strlen(scope), true); - test("parent", scope, NTL_RESOURCE_OP_BIND, "/Sessions/0", strlen("/Sessions/0"), false); - test("child", scope, NTL_RESOURCE_OP_BIND, "/Sessions/0/Desktop/A", strlen("/Sessions/0/Desktop/A"), false); - test("prefix", scope, NTL_RESOURCE_OP_BIND, "/Sessions/0/Deskto", strlen("/Sessions/0/Deskto"), false); - test("name change", scope, NTL_RESOURCE_OP_UNBIND, "/Services/posix", strlen("/Services/posix"), false); - test("no lookup", scope, NTL_RESOURCE_OP_LOOKUP, scope, strlen(scope), false); - test("no create", scope, NTL_RESOURCE_OP_CREATE_DIRECTORY, scope, strlen(scope), false); - test("no delegation", scope, NTL_RESOURCE_OP_CREATE_PUBLISHER, scope, strlen(scope), false); - test("canonical request length", scope, NTL_RESOURCE_OP_BIND, scope, strlen(scope) - 1u, false); - test("unscoped admin", NULL, NTL_RESOURCE_OP_CREATE_PUBLISHER, scope, strlen(scope), true); - puts("scoped publication regression: PASS"); - return 0; -} diff --git a/code/tests/service_restart_host/test.c b/code/tests/service_restart_host/test.c deleted file mode 100644 index d3854d0..0000000 --- a/code/tests/service_restart_host/test.c +++ /dev/null @@ -1,18 +0,0 @@ -// Host test for the sliding restart window and exact three-attempt ceiling. -#include -#include -#include "../../user/system/init/restart_budget.h" -int main(void) { - INIT_RESTART_BUDGET b = {0}; - if (!InitConsumeRestartBudget(&b, 1000u, 10u) || - !InitConsumeRestartBudget(&b, 1010u, 10u) || - !InitConsumeRestartBudget(&b, 1020u, 10u) || - InitConsumeRestartBudget(&b, 1030u, 10u)) abort(); - // A sliding expiration depends on each attempt's own timestamp. - if (!InitConsumeRestartBudget(&b, 4000u, 10u) || b.Count != 3u || - InitConsumeRestartBudget(&b, 4001u, 10u) || - !InitConsumeRestartBudget(&b, 4010u, 10u)) abort(); - if (InitConsumeRestartBudget(&b, 4011u, 0u)) abort(); - puts("service sliding restart budget: PASS"); - return 0; -} diff --git a/code/user/apps/dirs b/code/user/apps/dirs new file mode 100644 index 0000000..014c7e9 --- /dev/null +++ b/code/user/apps/dirs @@ -0,0 +1 @@ +DIRS=doom edit httpget memtop ping resolve shell_native shell_posix shell_win32 tcpserve udp video diff --git a/code/user/apps/doom/doom.c b/code/user/apps/doom/doom.c index 87e1bcc..76c1834 100644 --- a/code/user/apps/doom/doom.c +++ b/code/user/apps/doom/doom.c @@ -4,7 +4,7 @@ #include #include -#include +#include #include #include #include diff --git a/code/user/apps/doom/doom_audio.c b/code/user/apps/doom/doom_audio.c index 2f90ff2..db9280b 100644 --- a/code/user/apps/doom/doom_audio.c +++ b/code/user/apps/doom/doom_audio.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/code/user/apps/doom/makefile b/code/user/apps/doom/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/apps/doom/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/apps/doom/sources b/code/user/apps/doom/sources new file mode 100644 index 0000000..edb63ed --- /dev/null +++ b/code/user/apps/doom/sources @@ -0,0 +1,7 @@ +TARGETNAME=doom +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/apps/doom/doom.c @/code/user/apps/doom/doom_audio.c diff --git a/code/user/apps/edit/edit.c b/code/user/apps/edit/edit.c index 335891b..b6d2fc3 100644 --- a/code/user/apps/edit/edit.c +++ b/code/user/apps/edit/edit.c @@ -70,7 +70,6 @@ typedef struct SCREEN_CELL { static SCREEN_CELL gScreenCache[MAX_SCREEN_COLS * MAX_SCREEN_ROWS]; static bool gScreenCacheValid = false; -// Implements the invalidate screen cache operation. static void invalidate_screen_cache(void) { gScreenCacheValid = false; } @@ -127,7 +126,6 @@ static void draw_text(int col, int row, const char* s, uint32_t fg, uint32_t bg) while (*s && col < gCols) put_cell(col++, row, *s++, fg, bg); } -// Implements the msg set operation. static void msg_set(const char* s) { size_t n = strlen(s); if (n >= sizeof(gMessage)) n = sizeof(gMessage) - 1; @@ -158,7 +156,6 @@ static void append_u32(char* b, size_t cap, size_t* p, uint32_t v) { while (n > 0) append_char(b, cap, p, tmp[--n]); } -// Implements the key to char operation. static char key_to_char(INPUT_KEY key, uint32_t mods) { if (key >= INPUT_KEY_A && key <= INPUT_KEY_Z) { bool shifted = (mods & INPUT_MOD_SHIFT) != 0; @@ -188,7 +185,6 @@ static char key_to_char(INPUT_KEY key, uint32_t mods) { return 0; } -// Implements the clamp cursor operation. static void clamp_cursor(void) { if (gLineCount < 1) gLineCount = 1; if (gCy < 0) gCy = 0; @@ -197,7 +193,6 @@ static void clamp_cursor(void) { if (gCx > gLines[gCy].len) gCx = gLines[gCy].len; } -// Implements the ensure visible operation. static void ensure_visible(void) { int textRows = gRows - 2; if (textRows < 1) textRows = 1; @@ -211,7 +206,6 @@ static void ensure_visible(void) { if (gLeft < 0) gLeft = 0; } -// Implements the render operation. static void render(void) { update_screen_size(); @@ -275,7 +269,6 @@ static void insert_char_at_cursor(char c) { gDirty = true; } -// Implements the newline at cursor operation. static void newline_at_cursor(void) { if (gLineCount >= MAX_LINES) { msg_set("too many lines"); return; } @@ -297,7 +290,6 @@ static void newline_at_cursor(void) { gDirty = true; } -// Implements the backspace at cursor operation. static void backspace_at_cursor(void) { if (gCx > 0) { LINE* ln = &gLines[gCy]; @@ -401,7 +393,6 @@ static void save_file(void) { msg_set("saved"); } -// Implements the reset buffer operation. static void reset_buffer(void) { gLineCount = 1; gLines[0].len = 0; @@ -450,13 +441,11 @@ static void load_file(void) { msg_set(truncated ? "loaded, truncated long file" : "loaded"); } -// Implements the skip spaces operation. static const char* skip_spaces(const char* s) { while (s && (*s == ' ' || *s == '\t')) s++; return s; } -// Implements the skip token operation. static const char* skip_token(const char* s) { s = skip_spaces(s); if (!s || !*s) return s; @@ -500,7 +489,6 @@ static void parse_filename_from_cmdline(void) { strcpy(gFilename, "untitled.txt"); } -// Implements the editor loop operation. static void editor_loop(void) { while (true) { render(); diff --git a/code/user/apps/edit/makefile b/code/user/apps/edit/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/apps/edit/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/apps/edit/sources b/code/user/apps/edit/sources new file mode 100644 index 0000000..69eab4a --- /dev/null +++ b/code/user/apps/edit/sources @@ -0,0 +1,7 @@ +TARGETNAME=edit +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/apps/edit/edit.c diff --git a/code/user/apps/httpget/httpget.c b/code/user/apps/httpget/httpget.c index e32e82d..ae45ef6 100644 --- a/code/user/apps/httpget/httpget.c +++ b/code/user/apps/httpget/httpget.c @@ -58,7 +58,6 @@ static void append_u8(char* dst, size_t cap, size_t* off, uint8_t v) { } } -// Implements the format ipv4 operation. static void format_ipv4(char* dst, size_t cap, const uint8_t ip[4]) { size_t off = 0; if (!dst || cap == 0) return; @@ -81,7 +80,6 @@ static void append_hex16(char* dst, size_t cap, size_t* off, uint16_t value) { } } -// Implements the format ipv6 operation. static void format_ipv6(char* dst, size_t cap, const uint8_t ip[16]) { size_t off = 0; if (!dst || cap == 0) return; @@ -93,7 +91,6 @@ static void format_ipv6(char* dst, size_t cap, const uint8_t ip[16]) { } } -// Implements the format socket address operation. static void format_socket_address(char* dst, size_t cap, const SYS_SOCKET_ADDRESS* address) { if (!address || address->Family == SYS_AF_INET) format_ipv4(dst, cap, address ? address->Address : (const uint8_t*)"\0\0\0\0"); @@ -131,7 +128,6 @@ static bool parse_ipv4(const char* s, uint8_t ip[4]) { return *s == 0; } -// Implements the next token operation. static const char* next_token(const char* s, char* out, size_t outSize) { if (!s || !out || outSize == 0) return NULL; while (*s == ' ' || *s == '\t') s++; @@ -146,13 +142,11 @@ static const char* next_token(const char* s, char* out, size_t outSize) { return s; } -// Implements the usage operation. static void usage(void) { print("usage: httpget.exe [host-or-ipv4] [path]\n"); print("default: httpget.exe 10.0.2.2 /\n"); } -// Implements the resolve host operation. static KSTATUS resolve_host(const char* host, SYS_SOCKET_ADDRESS* address) { uint8_t ip[4]; if (parse_ipv4(host, ip)) { diff --git a/code/user/apps/httpget/makefile b/code/user/apps/httpget/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/apps/httpget/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/apps/httpget/sources b/code/user/apps/httpget/sources new file mode 100644 index 0000000..edc9b1f --- /dev/null +++ b/code/user/apps/httpget/sources @@ -0,0 +1,7 @@ +TARGETNAME=httpget +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/apps/httpget/httpget.c diff --git a/code/user/apps/memtop/makefile b/code/user/apps/memtop/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/apps/memtop/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/apps/memtop/sources b/code/user/apps/memtop/sources new file mode 100644 index 0000000..0244b93 --- /dev/null +++ b/code/user/apps/memtop/sources @@ -0,0 +1,7 @@ +TARGETNAME=memtop +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/apps/memtop/memtop.c diff --git a/code/user/apps/ping/makefile b/code/user/apps/ping/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/apps/ping/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/apps/ping/ping.c b/code/user/apps/ping/ping.c index 2c8eec4..586da53 100644 --- a/code/user/apps/ping/ping.c +++ b/code/user/apps/ping/ping.c @@ -53,7 +53,6 @@ static void print_rtt_us(uint64_t us) { print_u64(frac); } -// Implements the format ipv4 operation. static void format_ipv4(char* out, size_t outSize, const uint8_t ip[4]) { if (!out || outSize == 0) return; size_t off = 0; @@ -70,7 +69,6 @@ static void format_ipv4(char* out, size_t outSize, const uint8_t ip[4]) { out[off < outSize ? off : outSize - 1] = 0; } -// Implements the next token operation. static const char* next_token(const char* s, char* out, size_t outSize) { if (!s || !out || outSize == 0) return NULL; while (*s == ' ' || *s == '\t') s++; @@ -130,7 +128,6 @@ static bool parse_u32(const char* s, uint32_t* out) { return true; } -// Implements the resolve host operation. static KSTATUS resolve_host(const char* host, uint8_t ip[4]) { if (parse_ipv4(host, ip)) return NTLSTATUS_SUCCESS; @@ -159,7 +156,6 @@ static KSTATUS resolve_host(const char* host, uint8_t ip[4]) { return NTLSTATUS_SUCCESS; } -// Implements the icmp checksum operation. static uint16_t icmp_checksum(const uint8_t* data, size_t length) { uint32_t sum = 0; while (length >= 2) { @@ -223,7 +219,6 @@ static bool parse_echo_reply(const uint8_t* buf, size_t len, uint16_t ident, uin return false; } -// Implements the usage operation. static void usage(void) { print("usage: apps/ping.exe [host-or-ipv4] [count]\n"); print("default: apps/ping.exe 10.0.2.2 4\n"); diff --git a/code/user/apps/ping/sources b/code/user/apps/ping/sources new file mode 100644 index 0000000..7bbaa50 --- /dev/null +++ b/code/user/apps/ping/sources @@ -0,0 +1,7 @@ +TARGETNAME=ping +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/apps/ping/ping.c diff --git a/code/user/apps/resolve/makefile b/code/user/apps/resolve/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/apps/resolve/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/apps/resolve/resolve.c b/code/user/apps/resolve/resolve.c index 8967481..fd44525 100644 --- a/code/user/apps/resolve/resolve.c +++ b/code/user/apps/resolve/resolve.c @@ -29,7 +29,6 @@ static void print_u64(uint64_t v) { while (n > 0) print_char(buf[--n]); } -// Implements the next token operation. static const char* next_token(const char* s, char* out, size_t outSize) { if (!s || !out || outSize == 0) return NULL; while (*s == ' ' || *s == '\t') s++; diff --git a/code/user/apps/resolve/sources b/code/user/apps/resolve/sources new file mode 100644 index 0000000..b405d9e --- /dev/null +++ b/code/user/apps/resolve/sources @@ -0,0 +1,7 @@ +TARGETNAME=resolve +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/apps/resolve/resolve.c diff --git a/code/user/apps/shell_native/makefile b/code/user/apps/shell_native/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/apps/shell_native/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/apps/shell_native/shell_native.c b/code/user/apps/shell_native/shell_native.c index 70804ea..37cea52 100644 --- a/code/user/apps/shell_native/shell_native.c +++ b/code/user/apps/shell_native/shell_native.c @@ -128,7 +128,6 @@ static void printUInt64(uint64_t n) { while (i > 0) { char c[2] = { buf[--i], '\0' }; print(c); } } -// Implements the u64 Digits operation. static uint32_t u64Digits(uint64_t n) { uint32_t digits = 1; while (n >= 10u) { n /= 10u; digits++; } @@ -833,7 +832,6 @@ static bool readLine(char* buf, int len) { return false; } -// Implements the trim operation. static char* trim(char* s) { while (*s == ' ') s++; int len = (int)strlen(s); @@ -1001,7 +999,6 @@ static void cmd_volume(const char* args) { print("\n"); } -// Implements the cmd stats operation. static void cmd_stats(void) { SYS_SCHEDULER_STATS sched; SYS_PMM_STATS pmm; @@ -1416,7 +1413,6 @@ static void cmd_stats(void) { SysFreeVm(cpuBuffer); } -// Implements the cmd time operation. static void cmd_time(void) { SYS_SYSTEM_TIME t; KSTATUS status = SysGetSystemTime(&t); @@ -1476,7 +1472,6 @@ static void printDisplayStats(const char* title, const DISPLAY_STATS* st) { print(" hide="); printUInt64(st->CursorHideCount); print("\n"); } -// Implements the cmd display operation. static void cmd_display(void) { SYS_DISPLAY_INFO info; KSTATUS status = SysQueryDisplayInfo(&info); @@ -1673,7 +1668,6 @@ static void cmd_surfbench(void) { shellPrintFramebufferBenchmark("full", &full); } -// Implements the cmd mem operation. static void cmd_mem(void) { SYS_MEMORY_STATUS st; if (SysGetMemoryStatus(&st) != 0) { @@ -1767,7 +1761,6 @@ static void printThreadFlags(uint32_t flags) { printStringWidth(buf, 7); } -// Implements the cmd ps operation. static void cmd_ps(void) { SYS_PROCESS_INFO procs[MAX_PROCS]; size_t count = 0; @@ -1825,7 +1818,6 @@ static void cmd_ps(void) { } } -// Implements the cmd threads operation. static void cmd_threads(const char* args) { uint32_t pid = 0; if (!parseUInt(args, &pid)) { @@ -1922,7 +1914,6 @@ static void cmd_kill(const char* args) { } } -// Implements the cmd write operation. static void cmd_write(const char* args) { char filename[MAX_CMD]; int i = 0; while (args[i] != ' ' && args[i] != '\0' && i < MAX_CMD - 1) { @@ -2083,7 +2074,6 @@ static bool shellTryResourceDir(const char* target) { return true; } -// Implements the cmd dir operation. static void cmd_dir(const char* path) { uint32_t hDir; const char* target = (path && *path != '\0') ? path : "."; @@ -2131,7 +2121,6 @@ static void cmd_dir(const char* path) { SysFreeVm(entries); } -// Implements the cmd type operation. static void cmd_type(const char* filename) { uint32_t hFile; if (open_file(filename, &hFile) != 0) { print("type: cannot open file\n"); return; } @@ -2144,7 +2133,6 @@ static void cmd_type(const char* filename) { SysCloseHandle(hFile); print("\n"); } -// Implements the extract Program Path operation. static bool extractProgramPath(const char* cmdline, char* out, size_t outSize) { if (!cmdline || !out || outSize == 0) return false; diff --git a/code/user/apps/shell_native/sources b/code/user/apps/shell_native/sources new file mode 100644 index 0000000..2f8e4ad --- /dev/null +++ b/code/user/apps/shell_native/sources @@ -0,0 +1,7 @@ +TARGETNAME=shell_native +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/apps/shell_native/shell_native.c diff --git a/code/user/apps/shell_posix/makefile b/code/user/apps/shell_posix/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/apps/shell_posix/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/apps/shell_posix/shell_posix.c b/code/user/apps/shell_posix/shell_posix.c index 792659f..9a54ec2 100644 --- a/code/user/apps/shell_posix/shell_posix.c +++ b/code/user/apps/shell_posix/shell_posix.c @@ -37,7 +37,6 @@ static void readLine(char* buf, int len) { buf[pos] = '\0'; } -// Implements the split Command Line operation. static int splitCommandLine(char* line, char** argv, int maxArgv) { int argc = 0; char* p = line; @@ -62,7 +61,6 @@ static int splitCommandLine(char* line, char** argv, int maxArgv) { return argc; } -// Implements the trim operation. static char* trim(char* s) { while (*s == ' ') s++; int len = (int)strlen(s); @@ -71,7 +69,6 @@ static char* trim(char* s) { return s; } -// Implements the cmd help operation. static void cmd_help() { print("Available commands:\n" " help - Show this list\n" @@ -86,7 +83,6 @@ static void cmd_help() { " exit - Close the shell\n"); } -// Implements the cmd write operation. static void cmd_write(const char* args) { char filename[MAX_CMD]; int i = 0; while (args[i] != ' ' && args[i] != '\0' && i < MAX_CMD - 1) { @@ -145,7 +141,6 @@ static void shellSortDirEntries(SHELL_POSIX_DIR_ENTRY* entries, size_t count) { } } -// Implements the cmd dir operation. static void cmd_dir(const char* path) { const char* target = (path && *path != '\0') ? path : "."; DIR* d = opendir(target); @@ -186,7 +181,6 @@ static void cmd_dir(const char* path) { free(entries); } -// Implements the cmd type operation. static void cmd_type(const char* filename) { int fd = open(filename, 0); // O_RDONLY if (fd < 0) { print("type: cannot open file\n"); return; } diff --git a/code/user/apps/shell_posix/sources b/code/user/apps/shell_posix/sources new file mode 100644 index 0000000..a376ea9 --- /dev/null +++ b/code/user/apps/shell_posix/sources @@ -0,0 +1,7 @@ +TARGETNAME=shell_posix +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=POSIX +TARGETLIBS="$(BASEDIR)\bin\posix.lib" "$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\posix_start.lib" +EXTRA_LFLAGS=/ENTRY:PosixStart +SOURCES=@/code/user/apps/shell_posix/shell_posix.c diff --git a/code/user/apps/shell_win32/makefile b/code/user/apps/shell_win32/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/apps/shell_win32/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/apps/shell_win32/shell_win32.c b/code/user/apps/shell_win32/shell_win32.c index b056653..f18d14d 100644 --- a/code/user/apps/shell_win32/shell_win32.c +++ b/code/user/apps/shell_win32/shell_win32.c @@ -58,7 +58,6 @@ static void readLine(char* buf, int len) { buf[pos] = '\0'; } -// Implements the trim operation. static char* trim(char* s) { while (*s == ' ') s++; int len = (int)strlen(s); @@ -82,7 +81,6 @@ static void cmd_help() { " exit - Close the shell\n"); } -// Implements the cmd write operation. static void cmd_write(const char* args) { char filename[MAX_PATH]; int i = 0; while (args[i] != ' ' && args[i] != '\0' && i < MAX_PATH - 1) { @@ -145,7 +143,6 @@ static void shellSortDirEntries(SHELL_WIN32_DIR_ENTRY* entries, size_t count) { } } -// Implements the cmd dir operation. static void cmd_dir(const char* path) { WIN32_FIND_DATAA fd; char search_path[MAX_PATH]; @@ -200,7 +197,6 @@ static void cmd_dir(const char* path) { HeapFree(heap, 0, entries); } -// Implements the cmd type operation. static void cmd_type(const char* filename) { HANDLE hFile = CreateFileA(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if (hFile == INVALID_HANDLE_VALUE) { print("type: cannot open file\n"); return; } diff --git a/code/user/apps/shell_win32/sources b/code/user/apps/shell_win32/sources new file mode 100644 index 0000000..6be0cb9 --- /dev/null +++ b/code/user/apps/shell_win32/sources @@ -0,0 +1,7 @@ +TARGETNAME=shell_win32 +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\win32.lib" "$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/apps/shell_win32/shell_win32.c diff --git a/code/user/apps/tcpserve/makefile b/code/user/apps/tcpserve/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/apps/tcpserve/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/apps/tcpserve/sources b/code/user/apps/tcpserve/sources new file mode 100644 index 0000000..ecf4f69 --- /dev/null +++ b/code/user/apps/tcpserve/sources @@ -0,0 +1,7 @@ +TARGETNAME=tcpserve +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/apps/tcpserve/tcpserve.c diff --git a/code/user/apps/tcpserve/tcpserve.c b/code/user/apps/tcpserve/tcpserve.c index 304061a..74e9170 100644 --- a/code/user/apps/tcpserve/tcpserve.c +++ b/code/user/apps/tcpserve/tcpserve.c @@ -70,7 +70,6 @@ static void print_socket_address(const SYS_SOCKET_ADDRESS* address) { } } -// Implements the next token operation. static const char* next_token(const char* s, char* out, size_t outSize) { if (!s || !out || outSize == 0) return NULL; while (*s == ' ' || *s == '\t') s++; @@ -99,7 +98,6 @@ static bool parse_port(const char* s, uint16_t* out) { return true; } -// Implements the usage operation. static void usage(void) { print("usage: tcpserve.exe [-4|-6] [port]\n"); print("default: tcpserve.exe 8080\n"); diff --git a/code/user/apps/udp/makefile b/code/user/apps/udp/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/apps/udp/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/apps/udp/sources b/code/user/apps/udp/sources new file mode 100644 index 0000000..7b9ba98 --- /dev/null +++ b/code/user/apps/udp/sources @@ -0,0 +1,7 @@ +TARGETNAME=udp +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/apps/udp/udp.c diff --git a/code/user/apps/udp/udp.c b/code/user/apps/udp/udp.c index 3ae893f..9599631 100644 --- a/code/user/apps/udp/udp.c +++ b/code/user/apps/udp/udp.c @@ -70,7 +70,6 @@ static void print_socket_address(const SYS_SOCKET_ADDRESS* address) { } } -// Implements the next token operation. static const char* next_token(const char* s, char* out, size_t outSize) { if (!s || !out || outSize == 0) return NULL; while (*s == ' ' || *s == '\t') s++; @@ -129,7 +128,6 @@ static bool parse_port(const char* s, uint16_t* out) { return true; } -// Implements the usage operation. static void usage(void) { print("usage:\n"); print(" udp.exe send [message]\n"); diff --git a/code/user/apps/video/makefile b/code/user/apps/video/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/apps/video/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/apps/video/sources b/code/user/apps/video/sources new file mode 100644 index 0000000..cdfc730 --- /dev/null +++ b/code/user/apps/video/sources @@ -0,0 +1,7 @@ +TARGETNAME=video +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" "$(BASEDIR)\code\user\apps\video\bink2w64.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/apps/video/video.c diff --git a/code/user/dirs b/code/user/dirs new file mode 100644 index 0000000..2afc59f --- /dev/null +++ b/code/user/dirs @@ -0,0 +1,2 @@ +DIRS=runtime syscall personalities system apps +OPTIONAL_DIRS=tests diff --git a/code/user/personalities/dirs b/code/user/personalities/dirs new file mode 100644 index 0000000..7bcf26f --- /dev/null +++ b/code/user/personalities/dirs @@ -0,0 +1 @@ +DIRS=posix win32 diff --git a/code/user/personalities/posix/makefile b/code/user/personalities/posix/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/personalities/posix/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/personalities/posix/posix_dir.c b/code/user/personalities/posix/posix_dir.c index 9a5a85b..e2e88a2 100644 --- a/code/user/personalities/posix/posix_dir.c +++ b/code/user/personalities/posix/posix_dir.c @@ -127,7 +127,6 @@ __declspec(dllexport) char* realpath(const char* path, char* resolved_path) { return PosixCopyResolvedPath(posix, resolved_path); } -// Implements the opendir operation. __declspec(dllexport) DIR* opendir(const char* path) { char native[512]; PosixTranslatePath(path, native, sizeof(native)); @@ -145,7 +144,6 @@ __declspec(dllexport) DIR* opendir(const char* path) { return d; } -// Implements the readdir operation. __declspec(dllexport) struct dirent* readdir(DIR* d) { if (!d) { errno = EBADF; return (struct dirent*)0; } KDIR_ENTRY ke; @@ -161,7 +159,6 @@ __declspec(dllexport) struct dirent* readdir(DIR* d) { return &d->Current; } -// Implements the closedir operation. __declspec(dllexport) int closedir(DIR* d) { if (!d) { errno = EBADF; return -1; } SysCloseHandle(d->KHandle); @@ -204,7 +201,6 @@ static int PosixFillSyntheticStat(mode_t type, struct stat* out) { return 0; } -// Implements the stat operation. __declspec(dllexport) int stat(const char* path, struct stat* out) { if (!path || !out) { errno = EINVAL; return -1; } @@ -219,7 +215,6 @@ __declspec(dllexport) int stat(const char* path, struct stat* out) { return PosixFillStat(&nativeStat, out); } -// Implements the fstat operation. __declspec(dllexport) int fstat(int fd, struct stat* out) { if (!out) { errno = EINVAL; return -1; } diff --git a/code/user/personalities/posix/posix_socket.c b/code/user/personalities/posix/posix_socket.c index a3ca7da..4dd715b 100644 --- a/code/user/personalities/posix/posix_socket.c +++ b/code/user/personalities/posix/posix_socket.c @@ -9,12 +9,10 @@ #include "posix_internal.h" #include "posix_fd.h" -// Implements the bswap16 operation. static uint16_t bswap16(uint16_t x) { return (uint16_t)((x << 8) | (x >> 8)); } -// Implements the bswap32 operation. static uint32_t bswap32(uint32_t x) { return ((x & 0x000000FFu) << 24) | ((x & 0x0000FF00u) << 8) | @@ -22,13 +20,9 @@ static uint32_t bswap32(uint32_t x) { ((x & 0xFF000000u) >> 24); } -// Implements the htons operation. __declspec(dllexport) uint16_t htons(uint16_t x) { return bswap16(x); } -// Implements the ntohs operation. __declspec(dllexport) uint16_t ntohs(uint16_t x) { return bswap16(x); } -// Implements the htonl operation. __declspec(dllexport) uint32_t htonl(uint32_t x) { return bswap32(x); } -// Implements the ntohl operation. __declspec(dllexport) uint32_t ntohl(uint32_t x) { return bswap32(x); } // Parses byte. @@ -148,7 +142,6 @@ static char* AppendHex16(char* out, uint16_t value) { return out; } -// Implements the inet addr operation. __declspec(dllexport) in_addr_t inet_addr(const char* text) { uint8_t b[4]; if (!text || !ParseIpv4Bytes(text, b)) return INADDR_NONE; @@ -158,7 +151,6 @@ __declspec(dllexport) in_addr_t inet_addr(const char* text) { return out; } -// Implements the inet ntoa operation. __declspec(dllexport) char* inet_ntoa(struct in_addr in) { static char buf[16]; const uint8_t* p = (const uint8_t*)&in.s_addr; @@ -175,7 +167,6 @@ __declspec(dllexport) char* inet_ntoa(struct in_addr in) { return buf; } -// Implements the inet pton operation. __declspec(dllexport) int inet_pton(int af, const char* src, void* dst) { if (!src || !dst) { errno = EINVAL; return -1; } if (af == AF_INET) { @@ -196,7 +187,6 @@ __declspec(dllexport) int inet_pton(int af, const char* src, void* dst) { return -1; } -// Implements the inet ntop operation. __declspec(dllexport) const char* inet_ntop(int af, const void* src, char* dst, socklen_t size) { if (!src || !dst) { errno = EINVAL; return (const char*)0; } if (af == AF_INET) { @@ -223,7 +213,6 @@ __declspec(dllexport) const char* inet_ntop(int af, const void* src, char* dst, return (const char*)0; } -// Implements the sock Addr To Sys operation. static int SockAddrToSys(const struct sockaddr* addr, socklen_t addrlen, SYS_SOCKET_ADDRESS* out) { if (!addr || !out) { errno = EINVAL; return -1; } memset(out, 0, sizeof(*out)); @@ -252,7 +241,6 @@ static int SockAddrToSys(const struct sockaddr* addr, socklen_t addrlen, SYS_SOC return -1; } -// Implements the to Sock Addr operation. static void SysToSockAddr(const SYS_SOCKET_ADDRESS* in, struct sockaddr* addr, socklen_t* addrlen) { if (!in || !addr || !addrlen) return; @@ -691,7 +679,6 @@ static unsigned ParsePort(const char* s) { return *s == '\0' ? v : 0; } -// Implements the resolve Name operation. static int ResolveNameFamily(const char* name, int family, SYS_SOCKET_ADDRESS* out) { if (!name || !out) { errno = EINVAL; return -1; } memset(out, 0, sizeof(*out)); @@ -739,7 +726,6 @@ static int ResolveNameAny(const char* name, int family, SYS_SOCKET_ADDRESS* out) return ResolveNameFamily(name, AF_INET, out); } -// Implements the gethostbyname operation. __declspec(dllexport) struct hostent* gethostbyname(const char* name) { static struct hostent h; static char hname[256]; @@ -804,7 +790,6 @@ __declspec(dllexport) int getaddrinfo(const char* node, const char* service, return 0; } -// Implements the freeaddrinfo operation. __declspec(dllexport) void freeaddrinfo(struct addrinfo* res) { if (res) free(res); } diff --git a/code/user/personalities/posix/posix_thread.c b/code/user/personalities/posix/posix_thread.c index 6074307..8651640 100644 --- a/code/user/personalities/posix/posix_thread.c +++ b/code/user/personalities/posix/posix_thread.c @@ -38,7 +38,6 @@ typedef struct { uint64_t SignalMask; } PTHREAD_TRAMP; -// Implements the pthread Trampoline operation. static void PthreadTrampoline(uintptr_t raw) { PTHREAD_TRAMP* tr = (PTHREAD_TRAMP*)raw; void* (*fn)(void*) = tr->Fn; @@ -110,7 +109,6 @@ __declspec(dllexport) int pthread_create(pthread_t* t, const pthread_attr_t* att return 0; } -// Implements the pthread join operation. __declspec(dllexport) int pthread_join(pthread_t t, void** retval) { KSTATUS s = SysWait(t.Handle, SYS_WAIT_FLAG_NONE); if (s != 0) return ESRCH; @@ -122,7 +120,6 @@ __declspec(dllexport) int pthread_join(pthread_t t, void** retval) { return 0; } -// Implements the pthread exit operation. __declspec(dllexport) void pthread_exit(void* retval) { uint32_t tid = SysGetCurrentTid(); POSIX_PTHREAD_SLOT* slot = PthreadSlotFind(tid); @@ -132,7 +129,6 @@ __declspec(dllexport) void pthread_exit(void* retval) { while (1); // unreachable } -// Implements the pthread mutex init operation. __declspec(dllexport) int pthread_mutex_init(pthread_mutex_t* m, const pthread_mutexattr_t* attr) { (void)attr; uint32_t h; @@ -142,26 +138,22 @@ __declspec(dllexport) int pthread_mutex_init(pthread_mutex_t* m, const pthread_m return 0; } -// Implements the pthread mutex destroy operation. __declspec(dllexport) int pthread_mutex_destroy(pthread_mutex_t* m) { SysCloseHandle(m->Handle); m->Handle = 0; return 0; } -// Implements the pthread mutex lock operation. __declspec(dllexport) int pthread_mutex_lock(pthread_mutex_t* m) { KSTATUS s = SysWait(m->Handle, SYS_WAIT_FLAG_NONE); return s == 0 ? 0 : EINVAL; } -// Implements the pthread mutex trylock operation. __declspec(dllexport) int pthread_mutex_trylock(pthread_mutex_t* m) { KSTATUS s = SysTryAcquireMutex(m->Handle); return s == 0 ? 0 : EAGAIN; } -// Implements the pthread mutex unlock operation. __declspec(dllexport) int pthread_mutex_unlock(pthread_mutex_t* m) { KSTATUS s = SysReleaseMutex(m->Handle); return s == 0 ? 0 : EINVAL; diff --git a/code/user/personalities/posix/posix_vfork.asm b/code/user/personalities/posix/posix_vfork.asm index be62656..18c5c3c 100644 --- a/code/user/personalities/posix/posix_vfork.asm +++ b/code/user/personalities/posix/posix_vfork.asm @@ -80,7 +80,7 @@ vfork_wait: mov ecx, dword ptr [r12 + VF_ThreadHandle] lea rdx, [r12 + VF_PreviousSuspendCount] mov eax, SYS_RESUME_THREAD_AND_WAIT - int 40h + int 02Fh mov r9d, eax ; The child may have overwritten every byte of the old vfork/helper frames. diff --git a/code/user/personalities/posix/sources b/code/user/personalities/posix/sources new file mode 100644 index 0000000..add4baa --- /dev/null +++ b/code/user/personalities/posix/sources @@ -0,0 +1,13 @@ +TARGETNAME=posix +TARGETPATH=obj +TARGETTYPE=DYNLINK +IMAGE_KIND=DLL +FLAVOR=POSIX +EXTRA_CFLAGS=/DNTL_POSIX_BUILD /DUSER_HEAP_EXPORTS /DNTL_EXCEPTION_EXPORTS +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" +EXTRA_LFLAGS=/SUBSYSTEM:NATIVE /DYNAMICBASE /HIGHENTROPYVA +EXTRA_ASFLAGS=/I"$(BASEDIR)\code\user\syscall" +INCLUDES=$(BASEDIR)\code\user\syscall +SOURCES=@/code/user/runtime/heap.c @/code/user/runtime/heap_exports.c @/code/user/runtime/native_exception.c @/code/user/personalities/posix/posix_dir.c @/code/user/personalities/posix/posix_dlfcn.c @/code/user/personalities/posix/posix_fd.c \ + @/code/user/personalities/posix/posix_io.c @/code/user/personalities/posix/posix_mman.c @/code/user/personalities/posix/posix_path.c @/code/user/personalities/posix/posix_proc.c @/code/user/personalities/posix/posix_runtime.c @/code/user/personalities/posix/posix_signal.c \ + @/code/user/personalities/posix/posix_socket.c @/code/user/personalities/posix/posix_thread.c @/code/user/personalities/posix/posix_vfork.c @/code/user/personalities/posix/posix_vfork.asm diff --git a/code/user/personalities/win32/gdi32.c b/code/user/personalities/win32/gdi32.c index 1bfd3ad..23c65bd 100644 --- a/code/user/personalities/win32/gdi32.c +++ b/code/user/personalities/win32/gdi32.c @@ -2,7 +2,7 @@ #include #include -#include +#include #include #if defined(__SSE2__) || defined(_M_X64) || defined(_M_IX86) diff --git a/code/user/personalities/win32/kernel32.c b/code/user/personalities/win32/kernel32.c index f73193b..57db57d 100644 --- a/code/user/personalities/win32/kernel32.c +++ b/code/user/personalities/win32/kernel32.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -148,7 +148,6 @@ typedef struct _MEMORY_BASIC_INFORMATION { DWORD Type; } MEMORY_BASIC_INFORMATION; -// Implements the win Protect To Sys Vm operation. static uint32_t WinProtectToSysVm(DWORD protect) { switch (protect) { case PAGE_NOACCESS: return SYS_VM_NOACCESS; @@ -182,7 +181,6 @@ static uint32_t WinFileMapAccessToSys(DWORD desiredAccess) { return access; } -// Implements the protect Vm To Win operation. static DWORD SysProtectVmToWin(uint32_t protect) { switch (protect) { case SYS_VM_NOACCESS: return PAGE_NOACCESS; @@ -279,7 +277,6 @@ static void TranslatePath(const char* input, char* output) { *dst = '\0'; } -// Implements the k32 Open File Native operation. static KSTATUS K32OpenFileNative(const char* path, uint32_t access, uint32_t disposition, @@ -287,23 +284,19 @@ static KSTATUS K32OpenFileNative(const char* path, return NtlOpenFile(SysSvFromCstr(path), access, disposition, SYS_FILE_FLAG_NONE, handleOut); } -// Implements the k32 Delete File Native operation. static KSTATUS K32DeleteFileNative(const char* path) { return NtlDeleteFile(SysSvFromCstr(path)); } -// Implements the k32 Open Dir Native operation. static KSTATUS K32OpenDirNative(const char* path, uint32_t* handleOut) { return NtlOpenDir(SysSvFromCstr(path), SYS_DIR_ACCESS_ENUMERATE | SYS_DIR_ACCESS_OPEN, SYS_DIR_FLAG_NONE, handleOut); } -// Implements the k32 Set Cwd Native operation. static KSTATUS K32SetCwdNative(const char* path) { return NtlSetCurrentDirectory(SysSvFromCstr(path)); } -// Implements the k32 Get Cwd Native operation. static KSTATUS K32GetCwdNative(char* buffer, size_t capacity, size_t* lengthOut) { size_t required = 0; KSTATUS status = NtlGetCurrentDirectory(buffer, capacity, &required); @@ -347,12 +340,10 @@ static KSTATUS K32CreateProcessNative(const char* path, uint32_t imageFile, uint return NtlCreateSystemProcess(&req); } -// Implements the k32 Write Console Span operation. static void K32WriteConsoleSpan(const char* data, size_t length) { (void)NtlConsoleWrite(SYS_HANDLE_INVALID, data, length, 0); } -// Implements the k32 Debug Print A operation. static void K32DebugPrintA(const char* s) { if (!s) return; SYS_PRINT_DEBUG_REQUEST req = { sizeof(SYS_PRINT_DEBUG_REQUEST), SysSvFromCstr(s) }; @@ -373,7 +364,6 @@ typedef struct WIN32_THREAD_ENV { static WIN32_THREAD_ENV gFallbackThreadEnv; -// Implements the k32 Thread Env operation. static WIN32_THREAD_ENV* K32ThreadEnv(void) { SYS_TEB* teb = SysGetTeb(); if (!teb || teb->Magic != SYS_TEB_MAGIC) return &gFallbackThreadEnv; @@ -388,7 +378,6 @@ static WIN32_THREAD_ENV* K32ThreadEnv(void) { return env; } -// Implements the k32 Last Error Slot operation. static DWORD* K32LastErrorSlot(void) { return &K32ThreadEnv()->LastError; } @@ -398,7 +387,6 @@ static DWORD* K32LastErrorSlot(void) { // Returns a stable nonzero identifier for the calling thread. static DWORD K32CurrentTidOrOne(void); -// Implements the file Exists A operation. static BOOL KiFileExistsA(const char* path) { if (!path || !*path) return FALSE; char native[MAX_PATH]; @@ -483,7 +471,6 @@ __declspec(dllexport) DWORD SearchPathA(const char* lpPath, const char* lpFileNa // GetLastError / SetLastError (single-threaded stub). static SYS_PEB* gProcessPeb = NULL; -// Implements the peb operation. static SYS_PEB* Win32Peb(void) { if (!gProcessPeb) gProcessPeb = SysGetPeb(); return gProcessPeb; @@ -558,7 +545,6 @@ __declspec(dllexport) void* HeapAlloc(void* heap, DWORD flags, size_t size) { return ptr; } -// Implements the heap Free operation. __declspec(dllexport) BOOL HeapFree(void* heap, DWORD flags, void* ptr) { (void)heap; (void)flags; // Win32's HeapFree doesn't need the size; we pass 0 and the user-mode heap carries the block size. @@ -624,7 +610,6 @@ __declspec(dllexport) void* VirtualAlloc(void* lpAddress, size_t dwSize, return base; } -// Implements the virtual Free operation. __declspec(dllexport) BOOL VirtualFree(void* lpAddress, size_t dwSize, DWORD dwFreeType) { (void)dwSize; (void)dwFreeType; if (!lpAddress) return TRUE; @@ -1255,13 +1240,11 @@ __declspec(dllexport) HANDLE HeapCreate(DWORD flOptions, return (HANDLE)(uintptr_t)1; // non-NULL sentinel } -// Implements the heap Destroy operation. __declspec(dllexport) BOOL HeapDestroy(HANDLE hHeap) { (void)hHeap; return TRUE; } -// Implements the heap Size operation. __declspec(dllexport) size_t HeapSize(HANDLE heap, DWORD flags, const void* ptr) { (void)heap; (void)flags; size_t size = _malloc_usable_size(ptr); @@ -1297,7 +1280,6 @@ __declspec(dllexport) DWORD GetCurrentProcessId(void) { return (DWORD)SysGetCurr // Tiny TLS index allocator; slot values are stored per thread in WIN32_THREAD_ENV. static uint64_t gTlsBitmap = 1; // reserve slot 0 -// Implements the tls Alloc operation. __declspec(dllexport) DWORD TlsAlloc(void) { for (DWORD i = 1; i < WIN32_TLS_SLOTS; i++) { uint64_t bit = 1ULL << i; @@ -1307,7 +1289,6 @@ __declspec(dllexport) DWORD TlsAlloc(void) { return 0xFFFFFFFFUL; } -// Implements the tls Free operation. __declspec(dllexport) BOOL TlsFree(DWORD dwTlsIndex) { if (dwTlsIndex >= WIN32_TLS_SLOTS || !(gTlsBitmap & (1ULL << dwTlsIndex))) { gLastError = 87; return FALSE; } WIN32_THREAD_ENV* env = K32ThreadEnv(); @@ -1316,7 +1297,6 @@ __declspec(dllexport) BOOL TlsFree(DWORD dwTlsIndex) { return TRUE; } -// Implements the tls Get Value operation. __declspec(dllexport) void* TlsGetValue(DWORD dwTlsIndex) { if (dwTlsIndex >= WIN32_TLS_SLOTS || !(gTlsBitmap & (1ULL << dwTlsIndex))) { gLastError = 87; return NULL; } WIN32_THREAD_ENV* env = K32ThreadEnv(); @@ -1324,7 +1304,6 @@ __declspec(dllexport) void* TlsGetValue(DWORD dwTlsIndex) { return env->TlsSlots[dwTlsIndex]; } -// Implements the tls Set Value operation. __declspec(dllexport) BOOL TlsSetValue(DWORD dwTlsIndex, void* lpTlsValue) { if (dwTlsIndex >= WIN32_TLS_SLOTS || !(gTlsBitmap & (1ULL << dwTlsIndex))) { gLastError = 87; return FALSE; } WIN32_THREAD_ENV* env = K32ThreadEnv(); @@ -1336,7 +1315,6 @@ __declspec(dllexport) BOOL TlsSetValue(DWORD dwTlsIndex, void* lpTlsValue) { #define WIN32_HMODULE_EXE ((HANDLE)(uintptr_t)0x00400000UL) #define WIN32_HMODULE_WIN32 ((HANDLE)(uintptr_t)0x57333232UL) // W322 -// Implements the stricmp A operation. static int KiStricmpA(const char* a, const char* b) { while (*a && (((unsigned char)*a | 0x20) == ((unsigned char)*b | 0x20))) { a++; b++; } return ((unsigned char)*a | 0x20) - ((unsigned char)*b | 0x20); @@ -1370,7 +1348,6 @@ static BOOL KiIsWin32DllNameA(const char* name) { KiMatchesWin32DllNameA(name, "win32"); } -// Implements the dbg Write A operation. static void KiDbgWriteA(const char* s) { if (s) K32WriteConsoleSpan(s, strlen(s)); } @@ -1532,7 +1509,6 @@ __declspec(dllexport) DWORD GetModuleFileNameA(HANDLE hModule, return copy; } -// Implements the terminate Process operation. __declspec(dllexport) BOOL TerminateProcess(HANDLE hProcess, unsigned int uExitCode) { if (hProcess == GetCurrentProcess()) { SysExitProcess((int32_t)uExitCode); @@ -1744,7 +1720,6 @@ __declspec(dllexport) BOOL ResetEvent(HANDLE hEvent) { return TRUE; } -// Implements the extract Application Path A operation. static BOOL ExtractApplicationPathA(const char* commandLine, char* out, size_t outSize) { if (!commandLine || !out || outSize == 0) return FALSE; @@ -1906,7 +1881,6 @@ __declspec(dllexport) uintptr_t SetThreadAffinityMask(HANDLE hThread, return 1; // previous mask: CPU 0 only } -// Implements the sleep operation. __declspec(dllexport) void Sleep(DWORD dwMilliseconds) { SysSleep(dwMilliseconds); } @@ -1917,20 +1891,17 @@ __declspec(dllexport) void Sleep(DWORD dwMilliseconds) { #define STD_OUTPUT_HANDLE ((DWORD)-11) #define STD_ERROR_HANDLE ((DWORD)-12) -// Implements the k32 Is Std Handle Value operation. static BOOL K32IsStdHandleValue(HANDLE h, DWORD stdHandle) { uintptr_t value = (uintptr_t)h; return value == (uintptr_t)stdHandle || value == (uintptr_t)(intptr_t)(int32_t)stdHandle; } -// Implements the k32 Is Console Output Handle operation. static BOOL K32IsConsoleOutputHandle(HANDLE h) { return h && h != INVALID_HANDLE_VALUE && (K32IsStdHandleValue(h, STD_OUTPUT_HANDLE) || K32IsStdHandleValue(h, STD_ERROR_HANDLE)); } -// Implements the k32 Set Console Last Error operation. static void K32SetConsoleLastError(KSTATUS status) { switch (status) { case NTLSTATUS_SUCCESS: @@ -2206,12 +2177,10 @@ static void SplitFindPath(const char* searchPath, #define FILE_ATTRIBUTE_ARCHIVE 0x00000020UL #define FILE_ATTRIBUTE_NORMAL 0x00000080UL -// Implements the k32 Dir Is Leap Year operation. static bool K32DirIsLeapYear(unsigned int year) { return ((year % 4u) == 0u && (year % 100u) != 0u) || ((year % 400u) == 0u); } -// Implements the k32 Dir Days In Month operation. static unsigned int K32DirDaysInMonth(unsigned int year, unsigned int month) { static const unsigned char days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; if (month < 1u || month > 12u) return 31u; @@ -2219,7 +2188,6 @@ static unsigned int K32DirDaysInMonth(unsigned int year, unsigned int month) { return days[month - 1u]; } -// Implements the k32 Dir Calendar To Epoch Seconds operation. static uint64_t K32DirCalendarToEpochSeconds(const SYS_SYSTEM_TIME* st) { uint64_t days = 0; for (unsigned int y = 1970u; y < st->Year; y++) @@ -2230,7 +2198,6 @@ static uint64_t K32DirCalendarToEpochSeconds(const SYS_SYSTEM_TIME* st) { return (((days * 24u) + st->Hour) * 60u + st->Minute) * 60u + st->Second; } -// Implements the k32 Dir Store File Time operation. static void K32DirStoreFileTime(FILETIME* ft, const SYS_SYSTEM_TIME* st) { if (!ft || !st || !(st->Flags & SYS_TIME_FLAG_VALID) || st->Year < 1970u) { if (ft) { ft->dwLowDateTime = 0; ft->dwHighDateTime = 0; } @@ -2245,7 +2212,6 @@ static void K32DirStoreFileTime(FILETIME* ft, const SYS_SYSTEM_TIME* st) { ft->dwHighDateTime = (DWORD)(value >> 32); } -// Implements the kdir To Find Data operation. static void KdirToFindData(const KDIR_ENTRY* ke, WIN32_FIND_DATAA* fd) { // Zero the entire struct (covers all FILETIME and reserved fields). unsigned char* p = (unsigned char*)fd; @@ -2554,7 +2520,6 @@ __declspec(dllexport) BOOL InitializeCriticalSectionAndSpinCount(CRITICAL_SECTIO } // Releases critical Section. __declspec(dllexport) void DeleteCriticalSection(CRITICAL_SECTION* lpCS) { (void)lpCS; } -// Implements the enter Critical Section operation. __declspec(dllexport) void EnterCriticalSection(CRITICAL_SECTION* lpCS) { if (!lpCS) return; DWORD tid = K32CurrentTidOrOne(); @@ -2571,7 +2536,6 @@ __declspec(dllexport) void EnterCriticalSection(CRITICAL_SECTION* lpCS) { lpCS->Owner = tid; lpCS->Recursion = 1; } -// Implements the leave Critical Section operation. __declspec(dllexport) void LeaveCriticalSection(CRITICAL_SECTION* lpCS) { if (!lpCS) return; DWORD tid = K32CurrentTidOrOne(); @@ -2584,7 +2548,6 @@ __declspec(dllexport) void LeaveCriticalSection(CRITICAL_SECTION* lpCS) { NtlAtomicExchange32(&lpCS->Lock, 0); } } -// Implements the try Enter Critical Section operation. __declspec(dllexport) BOOL TryEnterCriticalSection(CRITICAL_SECTION* lpCS) { if (!lpCS) return FALSE; DWORD tid = K32CurrentTidOrOne(); @@ -2826,7 +2789,6 @@ static long long TscFreqCalibrate(void) { return (int64_t)(delta_tsc * 1000000ULL / delta_us); } -// Implements the tsc Freq Get operation. static long long TscFreqGet(void) { int64_t cached = NtlAtomicLoad64(&gTscFreq); if (cached) @@ -2855,12 +2817,10 @@ __declspec(dllexport) BOOL QueryPerformanceCounter(LARGE_INTEGER* lpPerformanceC return TRUE; } -// Implements the k32 Is Leap Year operation. static BOOL K32IsLeapYear(unsigned int year) { return ((year % 4u) == 0u && (year % 100u) != 0u) || ((year % 400u) == 0u); } -// Implements the k32 Days In Month operation. static unsigned int K32DaysInMonth(unsigned int year, unsigned int month) { static const unsigned char days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; if (month == 2u && K32IsLeapYear(year)) return 29u; @@ -2868,7 +2828,6 @@ static unsigned int K32DaysInMonth(unsigned int year, unsigned int month) { return days[month - 1u]; } -// Implements the k32 Calendar To Epoch Seconds operation. static uint64_t K32CalendarToEpochSeconds(const SYSTEMTIME* st) { uint64_t days = 0; for (unsigned int y = 1970u; y < st->wYear; y++) @@ -2879,14 +2838,12 @@ static uint64_t K32CalendarToEpochSeconds(const SYSTEMTIME* st) { return (((days * 24u) + st->wHour) * 60u + st->wMinute) * 60u + st->wSecond; } -// Implements the k32 Epoch To File Time operation. static uint64_t K32EpochToFileTime(uint64_t epochSeconds, uint32_t nanosecond) { const uint64_t WINDOWS_EPOCH_BIAS_SECONDS = 11644473600ULL; return (epochSeconds + WINDOWS_EPOCH_BIAS_SECONDS) * 10000000ULL + ((uint64_t)nanosecond / 100ULL); } -// Implements the k32 Store File Time operation. static void K32StoreFileTime(FILETIME* ft, uint64_t value) { ft->dwLowDateTime = (DWORD)(value & 0xFFFFFFFFULL); ft->dwHighDateTime = (DWORD)(value >> 32); @@ -3663,7 +3620,6 @@ __declspec(dllexport) void RaiseException(DWORD dwExceptionCode, DWORD dwExcepti SysExitProcess((int32_t)status); } -// Implements the unhandled Exception Filter operation. __declspec(dllexport) long UnhandledExceptionFilter(EXCEPTION_POINTERS* ExceptionInfo) { (void)ExceptionInfo; return EXCEPTION_CONTINUE_SEARCH; @@ -3698,7 +3654,6 @@ __declspec(dllexport) BOOL RtlAddFunctionTable(RUNTIME_FUNCTION* FunctionTable, return TRUE; } -// Implements the rtl Delete Function Table operation. __declspec(dllexport) BOOL RtlDeleteFunctionTable(RUNTIME_FUNCTION* FunctionTable) { (void)FunctionTable; return TRUE; @@ -3729,7 +3684,6 @@ __declspec(dllexport) void* RtlVirtualUnwind(unsigned long HandlerType, return NULL; } -// Implements the rtl Capture Context operation. __declspec(dllexport) void RtlCaptureContext(void* ContextRecord) { // Zero out the context record so callers don't read garbage. if (!ContextRecord) return; @@ -3813,7 +3767,6 @@ __declspec(dllexport) int GetLocaleInfoA(unsigned int Locale, DWORD LCType, static int gFlsUsed[FLS_MAX_SLOTS]; // 0 = free, 1 = allocated -// Implements the fls Alloc operation. __declspec(dllexport) DWORD FlsAlloc(void* lpCallback) { (void)lpCallback; for (int i = 0; i < FLS_MAX_SLOTS; i++) { @@ -3827,7 +3780,6 @@ __declspec(dllexport) DWORD FlsAlloc(void* lpCallback) { return (DWORD)FLS_OUT_OF_INDEXES; } -// Implements the fls Get Value operation. __declspec(dllexport) void* FlsGetValue(DWORD dwFlsIndex) { if (dwFlsIndex >= FLS_MAX_SLOTS || !gFlsUsed[dwFlsIndex]) { gLastError = 87; // ERROR_INVALID_PARAMETER @@ -3836,7 +3788,6 @@ __declspec(dllexport) void* FlsGetValue(DWORD dwFlsIndex) { return K32ThreadEnv()->FlsSlots[dwFlsIndex]; } -// Implements the fls Set Value operation. __declspec(dllexport) BOOL FlsSetValue(DWORD dwFlsIndex, void* lpFlsData) { if (dwFlsIndex >= FLS_MAX_SLOTS || !gFlsUsed[dwFlsIndex]) { gLastError = 87; @@ -3846,7 +3797,6 @@ __declspec(dllexport) BOOL FlsSetValue(DWORD dwFlsIndex, void* lpFlsData) { return TRUE; } -// Implements the fls Free operation. __declspec(dllexport) BOOL FlsFree(DWORD dwFlsIndex) { if (dwFlsIndex >= FLS_MAX_SLOTS || !gFlsUsed[dwFlsIndex]) { gLastError = 87; @@ -3861,5 +3811,4 @@ __declspec(dllexport) BOOL FlsFree(DWORD dwFlsIndex) { // We have no security cookie; return the pointer unchanged. __declspec(dllexport) void* EncodePointer(void* Ptr) { return Ptr; } -// Implements the decode Pointer operation. __declspec(dllexport) void* DecodePointer(void* Ptr) { return Ptr; } diff --git a/code/user/personalities/win32/makefile b/code/user/personalities/win32/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/personalities/win32/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/personalities/win32/ole32.c b/code/user/personalities/win32/ole32.c index aac9815..c5f4b86 100644 --- a/code/user/personalities/win32/ole32.c +++ b/code/user/personalities/win32/ole32.c @@ -2,7 +2,7 @@ #include #include -#include +#include #include // Types. @@ -43,7 +43,6 @@ __declspec(dllexport) HRESULT CoInitializeEx(void* reserved, unsigned long coIni return S_OK; // Pretend success; no actual apartment is created. } -// Implements the co Uninitialize operation. __declspec(dllexport) void CoUninitialize(void) { // No-op. } diff --git a/code/user/personalities/win32/sources b/code/user/personalities/win32/sources new file mode 100644 index 0000000..288ef71 --- /dev/null +++ b/code/user/personalities/win32/sources @@ -0,0 +1,10 @@ +TARGETNAME=win32 +TARGETPATH=obj +TARGETTYPE=DYNLINK +IMAGE_KIND=DLL +FLAVOR=USER +EXTRA_CFLAGS=/DUSER_HEAP_EXPORTS /DNTL_EXCEPTION_EXPORTS +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" +EXTRA_LFLAGS=/SUBSYSTEM:NATIVE /DYNAMICBASE /HIGHENTROPYVA +SOURCES=@/code/user/runtime/heap.c @/code/user/runtime/heap_exports.c @/code/user/runtime/native_exception.c @/code/user/personalities/win32/gdi32.c @/code/user/personalities/win32/kernel32.c @/code/user/personalities/win32/ole32.c \ + @/code/user/personalities/win32/user32.c @/code/user/personalities/win32/winmm.c @/code/user/personalities/win32/winmm_waveout.c diff --git a/code/user/personalities/win32/user32.c b/code/user/personalities/win32/user32.c index 4fe7eee..7a95c52 100644 --- a/code/user/personalities/win32/user32.c +++ b/code/user/personalities/win32/user32.c @@ -14,7 +14,6 @@ typedef struct tagPAINTSTRUCT { HDC hdc; BOOL fErase; RECT rcPaint; BOOL fRestore; BOOL fIncUpdate; char res[32]; } PAINTSTRUCT; -// Implements the user32 Debug Print A operation. static void User32DebugPrintA(const char* s) { if (!s) return; SYS_PRINT_DEBUG_REQUEST req = { sizeof(SYS_PRINT_DEBUG_REQUEST), SysSvFromCstr(s) }; @@ -31,7 +30,6 @@ __declspec(dllexport) HDC BeginPaint(HWND hwnd, PAINTSTRUCT* lpPaint) { return (HDC)1; } -// Implements the end Paint operation. __declspec(dllexport) BOOL EndPaint(HWND hwnd, const PAINTSTRUCT* lp) { (void)hwnd; (void)lp; return 1; } // --- Message Loop Stubs ---. diff --git a/code/user/personalities/win32/winmm_waveout.c b/code/user/personalities/win32/winmm_waveout.c index 66912c8..dc60871 100644 --- a/code/user/personalities/win32/winmm_waveout.c +++ b/code/user/personalities/win32/winmm_waveout.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/code/user/runtime/dirs b/code/user/runtime/dirs new file mode 100644 index 0000000..36d4817 --- /dev/null +++ b/code/user/runtime/dirs @@ -0,0 +1 @@ +DIRS=native_runtime posix_start diff --git a/code/user/runtime/heap.c b/code/user/runtime/heap.c index 8b0ab7c..b498937 100644 --- a/code/user/runtime/heap.c +++ b/code/user/runtime/heap.c @@ -94,7 +94,6 @@ static void SplitBlock(HEAP_BLOCK* block, size_t size) { block->Next = tail; } -// Implements the coalesce Block operation. static void CoalesceBlock(HEAP_BLOCK* block) { if (block->Next && block->Next->Magic == USER_HEAP_MAGIC && block->Next->Free) { HEAP_BLOCK* next = block->Next; @@ -111,7 +110,6 @@ static void CoalesceBlock(HEAP_BLOCK* block) { } } -// Implements the add Segment operation. static HEAP_SEGMENT* AddSegment(size_t payloadSize) { size_t need = sizeof(HEAP_SEGMENT) + sizeof(HEAP_BLOCK) + AlignSize(payloadSize); size_t pages = (need + USER_HEAP_PAGE_SIZE - 1) / USER_HEAP_PAGE_SIZE; @@ -160,7 +158,6 @@ static void RemoveSegmentIfEmpty(HEAP_SEGMENT* seg) { SysFreeVm(seg); } -// Implements the malloc operation. void* _malloc(size_t size) { if (!size) return 0; size = AlignSize(size); @@ -209,7 +206,6 @@ void _free(void* ptr) { HeapUnlock(); } -// Implements the calloc operation. void* _calloc(size_t count, size_t size) { if (count && size > ((size_t)-1) / count) return 0; @@ -241,7 +237,6 @@ size_t _malloc_usable_size(const void* ptr) { return size; } -// Implements the realloc operation. void* _realloc(void* ptr, size_t newSize) { if (!ptr) return _malloc(newSize); if (!newSize) { diff --git a/code/user/runtime/native_runtime/makefile b/code/user/runtime/native_runtime/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/runtime/native_runtime/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/runtime/native_runtime/sources b/code/user/runtime/native_runtime/sources new file mode 100644 index 0000000..c130b51 --- /dev/null +++ b/code/user/runtime/native_runtime/sources @@ -0,0 +1,5 @@ +TARGETNAME=native_runtime +TARGETPATH=obj +TARGETTYPE=LIBRARY +FLAVOR=USER +SOURCES=@/code/user/runtime/heap.c @/code/user/runtime/heap_exports.c @/code/user/runtime/native_exception.c @/code/user/runtime/native_start.c diff --git a/code/user/runtime/posix_start/makefile b/code/user/runtime/posix_start/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/runtime/posix_start/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/runtime/posix_start/sources b/code/user/runtime/posix_start/sources new file mode 100644 index 0000000..54335e2 --- /dev/null +++ b/code/user/runtime/posix_start/sources @@ -0,0 +1,5 @@ +TARGETNAME=posix_start +TARGETPATH=obj +TARGETTYPE=LIBRARY +FLAVOR=POSIX +SOURCES=@/code/user/runtime/posix_start.c diff --git a/code/user/syscall/dirs b/code/user/syscall/dirs new file mode 100644 index 0000000..0fcae9f --- /dev/null +++ b/code/user/syscall/dirs @@ -0,0 +1 @@ +DIRS=dynamic static diff --git a/code/user/syscall/dynamic/makefile b/code/user/syscall/dynamic/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/syscall/dynamic/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/syscall/dynamic/sources b/code/user/syscall/dynamic/sources new file mode 100644 index 0000000..117b310 --- /dev/null +++ b/code/user/syscall/dynamic/sources @@ -0,0 +1,12 @@ +TARGETNAME=syscall +TARGETPATH=obj +TARGETTYPE=DYNLINK +IMAGE_KIND=DLL +FLAVOR=USER +EXTRA_CFLAGS=/DNTL_SYSCALL_BUILD +TARGETLIBS="$(BASEDIR)\bin\libc.lib" +EXTRA_LFLAGS=/SUBSYSTEM:NATIVE /DYNAMICBASE /HIGHENTROPYVA +EXTRA_ASFLAGS=/I"$(BASEDIR)\code\user\syscall" +INCLUDES=$(BASEDIR)\code\user\syscall +SOURCES=@/code/user/syscall/pe_loader.c @/code/user/syscall/module_loader.c @/code/user/syscall/process_loader.c @/code/user/syscall/resource.c @/code/user/syscall/input_service.c @/code/user/syscall/console_service.c \ + @/code/user/syscall/desktop.c @/code/user/syscall/path.c @/code/user/syscall/syscall_stubs.asm diff --git a/code/user/syscall/static/makefile b/code/user/syscall/static/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/syscall/static/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/syscall/static/sources b/code/user/syscall/static/sources new file mode 100644 index 0000000..6e83dd7 --- /dev/null +++ b/code/user/syscall/static/sources @@ -0,0 +1,9 @@ +TARGETNAME=syscall_s +TARGETPATH=obj +TARGETTYPE=LIBRARY +FLAVOR=USER +EXTRA_CFLAGS=/DNTL_SYSCALL_STATIC +EXTRA_ASFLAGS=/DNTL_SYSCALL_STATIC /I"$(BASEDIR)\code\user\syscall" +INCLUDES=$(BASEDIR)\code\user\syscall +SOURCES=@/code/user/syscall/pe_loader.c @/code/user/syscall/module_loader.c @/code/user/syscall/process_loader.c @/code/user/syscall/resource.c @/code/user/syscall/input_service.c @/code/user/syscall/console_service.c \ + @/code/user/syscall/desktop.c @/code/user/syscall/path.c @/code/user/syscall/syscall_stubs.asm diff --git a/code/user/syscall/syscall_stubs.asm b/code/user/syscall/syscall_stubs.asm index a570f8e..ab8abaa 100644 --- a/code/user/syscall/syscall_stubs.asm +++ b/code/user/syscall/syscall_stubs.asm @@ -1,4 +1,4 @@ -; syscall_stubs.asm - user-mode INT 0x40 stubs for syscall.dll and syscall_s.lib (MASM64) +; syscall_stubs.asm - user-mode INT 0x2F stubs for syscall.dll and syscall_s.lib (MASM64) ; ; Calling convention: ; RAX = syscall number. @@ -30,7 +30,7 @@ ELSE Sys&name PROC EXPORT ENDIF mov rax, nr - int 40h + int 02Fh ret Sys&name ENDP ENDM @@ -104,7 +104,7 @@ ENDIF mov rbx, [rsp] ; restore original user RBX add rsp, 8 mov rax, SYS_APC_RETURN - int 40h + int 02Fh SysUserApcDispatcher_Failed: jmp SysUserApcDispatcher_Failed diff --git a/code/user/system/dirs b/code/user/system/dirs new file mode 100644 index 0000000..118f9f7 --- /dev/null +++ b/code/user/system/dirs @@ -0,0 +1 @@ +DIRS=dwm init posixsrv rssrv diff --git a/code/user/system/dwm/dwm.c b/code/user/system/dwm/dwm.c index 91b2121..74b314b 100644 --- a/code/user/system/dwm/dwm.c +++ b/code/user/system/dwm/dwm.c @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/code/user/system/dwm/makefile b/code/user/system/dwm/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/system/dwm/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/system/dwm/sources b/code/user/system/dwm/sources new file mode 100644 index 0000000..0c010f6 --- /dev/null +++ b/code/user/system/dwm/sources @@ -0,0 +1,7 @@ +TARGETNAME=dwm +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall_s.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:_start +SOURCES=@/code/user/system/dwm/dwm.c diff --git a/code/user/system/init/init.c b/code/user/system/init/init.c index 3db1a9a..a6a0762 100644 --- a/code/user/system/init/init.c +++ b/code/user/system/init/init.c @@ -21,6 +21,7 @@ typedef enum INIT_SERVICE_STATE { InitServiceStopped = 0, InitServiceStarting, + InitServiceRestartPending, InitServiceReady, InitServiceStopping, InitServiceFailed, @@ -31,10 +32,16 @@ typedef struct INIT_SERVICE { SYS_HANDLE Process; SYS_HANDLE ControlEndpoint; INIT_SERVICE_STATE State; + uint64_t StartedTick; + uint64_t RestartTick; } INIT_SERVICE; static INIT_SERVICE_CONFIG gServiceConfig; static INIT_SERVICE gServices[INIT_SERVICE_MAX_COUNT]; +static uint64_t gTickFrequency; +static INIT_RESTART_BUDGET gRestartBudgets[INIT_SERVICE_MAX_COUNT]; +_Static_assert(INIT_SERVICE_MAX_COUNT + 2u <= SYS_WAIT_MANY_MAX_HANDLES, + "Service supervisor exceeds WaitMany capacity"); // Capability sources are referenced by name; the catalog owns READY handles // and borrows kernel-provided bootstrap handles for the lifetime of init. @@ -82,13 +89,12 @@ static void forget_service_grants(const INIT_SERVICE_DESCRIPTOR* provider) { } } -// Keeps the named READY exports for subsequent dependent services. Ownership of -// an export handle passes to the catalog only when retainHandles is true. +// READY exports enter the catalog atomically after name and capacity validation. static KSTATUS register_ready_exports(const INIT_SERVICE_DESCRIPTOR* provider, - const NTL_SERVICE_CONTROL_MESSAGE* message, - const SYS_HANDLE* handles, uint32_t count, - bool retainHandles) { - if (!provider || !message || count != message->ExportCount) return NTLSTATUS_INVALID_PARAMETER; + const NTL_SERVICE_CONTROL_MESSAGE* message, + const SYS_HANDLE* handles, uint32_t count) { + if (!provider || !message || (count && !handles) || count != message->ExportCount || + count > SYS_PORT_MAX_TRANSFER_HANDLES) return NTLSTATUS_INVALID_PARAMETER; if (gGrantSourceCount + count > INIT_GRANT_SOURCE_MAX) return NTLSTATUS_LIMIT_REACHED; char names[SYS_PORT_MAX_TRANSFER_HANDLES][SYS_STARTUP_CAPABILITY_NAME_MAX + 1u]; for (uint32_t i = 0; i < count; ++i) { @@ -100,16 +106,17 @@ static KSTATUS register_ready_exports(const INIT_SERVICE_DESCRIPTOR* provider, memcpy(names[i] + left + 1u, message->ExportNames[i], right + 1u); for (uint32_t j = 0; j < gGrantSourceCount; ++j) if (strcmp(names[i], gGrantSources[j].Name) == 0) return NTLSTATUS_OBJECT_NAME_COLLISION; + for (uint32_t j = 0; j < i; ++j) + if (strcmp(names[i], names[j]) == 0) return NTLSTATUS_OBJECT_NAME_COLLISION; } for (uint32_t i = 0; i < count; ++i) { - KSTATUS status = add_grant_source(names[i], handles[i], - SYS_RIGHT_QUERY | SYS_PORT_RIGHT_CONNECT, - provider, retainHandles); - if (!KSUCCESS(status)) { - // All names and available capacity were validated before mutation. - forget_service_grants(provider); - return status; - } + INIT_GRANT_SOURCE* source = &gGrantSources[gGrantSourceCount++]; + memset(source, 0, sizeof(*source)); + memcpy(source->Name, names[i], strlen(names[i]) + 1u); + source->Handle = handles[i]; + source->RightsCeiling = SYS_RIGHT_QUERY | SYS_PORT_RIGHT_CONNECT; + source->Provider = provider; + source->OwnsHandle = true; } return NTLSTATUS_SUCCESS; } @@ -296,10 +303,12 @@ static KSTATUS start_service_process(SYS_HANDLE systemVolume, service->Descriptor->GrantCount > SYS_STARTUP_CAPABILITY_MAX - 1u) return NTLSTATUS_INVALID_PARAMETER; if (service->Process != SYS_HANDLE_INVALID || service->ControlEndpoint != SYS_HANDLE_INVALID || - (service->State != InitServiceStopped && service->State != InitServiceFailed)) + (service->State != InitServiceStopped && service->State != InitServiceFailed && + service->State != InitServiceRestartPending)) return NTLSTATUS_FAILURE; service->State = InitServiceStarting; + service->StartedTick = SysGetTick(); SYS_HANDLE controlListener = SYS_HANDLE_INVALID; KSTATUS status = create_control_listener(&controlListener); @@ -341,7 +350,23 @@ static KSTATUS start_service_process(SYS_HANDLE systemVolume, create.StartupCapabilities = startup; create.StartupCapabilityCount = capabilityCount; create.ProcessHandleOut = &process; + SYS_HANDLE privilegedContext = SYS_HANDLE_INVALID; + if (service->Descriptor->Privileges) { + SYS_DERIVE_SECURITY_CONTEXT_REQUEST derive = {0}; + derive.Size = sizeof(derive); + derive.SourceContext = SYS_SECURITY_CONTEXT_CURRENT; + derive.EffectivePrivileges = service->Descriptor->Privileges; + derive.ContextHandleOut = &privilegedContext; + status = SysDeriveSecurityContext(&derive); + if (!KSUCCESS(status)) { + (void)SysCloseHandle(controlListener); + service->State = InitServiceFailed; + return status; + } + create.SecurityContext = privilegedContext; + } status = NtlCreateProcessAt(&create); + if (privilegedContext != SYS_HANDLE_INVALID) (void)SysCloseHandle(privilegedContext); if (!KSUCCESS(status)) { (void)SysCloseHandle(controlListener); service->State = InitServiceFailed; @@ -364,7 +389,7 @@ static KSTATUS start_service_process(SYS_HANDLE systemVolume, } // Waits for one service READY notification and receives its service-defined export handles. -static KSTATUS wait_service_ready(INIT_SERVICE* service, +static KSTATUS wait_service_ready(INIT_SERVICE* service, uint64_t timeout, SYS_HANDLE* exportsOut, uint32_t exportCapacity, uint32_t* exportCountOut, @@ -392,7 +417,7 @@ static KSTATUS wait_service_ready(INIT_SERVICE* service, receive.HandlesOut = exportsOut; receive.HandleCapacity = exportCapacity; receive.InfoOut = &info; - receive.TimeoutMilliseconds = service->Descriptor->ReadyTimeoutMilliseconds; + receive.TimeoutMilliseconds = timeout; KSTATUS status = SysReceivePort(&receive); if (!KSUCCESS(status)) return status; @@ -415,23 +440,13 @@ static KSTATUS wait_service_ready(INIT_SERVICE* service, return NTLSTATUS_SUCCESS; } -// Every service uses the same process, READY, export and failure path. -static KSTATUS start_managed_service(SYS_HANDLE systemVolume, - SYS_HANDLE securityContext, INIT_SERVICE* service) { - KSTATUS status = start_service_process(systemVolume, securityContext, service); - if (!KSUCCESS(status)) { - debug_print("[init] process or startup grant creation failed for "); - debug_print(service->Descriptor->Id); - debug_print(": "); - debug_status(status); - debug_print("\n"); - return status; - } - +// Consumes one READY record, transferring published handles on success. +static KSTATUS finish_service_ready(INIT_SERVICE* service, uint64_t timeout) { + KSTATUS status; SYS_HANDLE handles[SYS_PORT_MAX_TRANSFER_HANDLES]; uint32_t count = 0; NTL_SERVICE_CONTROL_MESSAGE ready; - status = wait_service_ready(service, handles, SYS_PORT_MAX_TRANSFER_HANDLES, &count, &ready); + status = wait_service_ready(service, timeout, handles, SYS_PORT_MAX_TRANSFER_HANDLES, &count, &ready); if (!KSUCCESS(status)) { debug_print("[init] READY receive failed for "); debug_print(service->Descriptor->Id); @@ -450,7 +465,7 @@ static KSTATUS start_managed_service(SYS_HANDLE systemVolume, status = NTLSTATUS_INVALID_PARAMETER; } if (KSUCCESS(status)) { - status = register_ready_exports(descriptor, &ready, handles, count, true); + status = register_ready_exports(descriptor, &ready, handles, count); if (KSUCCESS(status)) for (uint32_t i = 0; i < count; ++i) handles[i] = SYS_HANDLE_INVALID; } @@ -469,6 +484,225 @@ static KSTATUS start_managed_service(SYS_HANDLE systemVolume, return NTLSTATUS_SUCCESS; } +// Schedules a bounded retry for failed startup or a matching process exit. +static bool queue_service_restart(INIT_SERVICE* service) { + if (!service || service->Descriptor->RestartPolicy == InitServiceRestartNever) return false; + uint32_t index = (uint32_t)(service - gServices); + if (index >= gServiceConfig.ServiceCount || + !InitConsumeRestartBudget(&gRestartBudgets[index], SysGetTick(), gTickFrequency, + service->Descriptor->RestartLimit, + service->Descriptor->RestartWindowMilliseconds)) return false; + uint64_t now = SysGetTick(); + uint64_t delay = (uint64_t)service->Descriptor->RestartDelayMilliseconds * gTickFrequency; + delay = delay / 1000u + (delay % 1000u != 0u); + service->RestartTick = delay <= UINT64_MAX - now ? now + delay : UINT64_MAX; + service->State = InitServiceRestartPending; + return true; +} + +// Starts eligible services, leaving READY completion to the supervisor. +static KSTATUS launch_services(bool includeDelayed, SYS_HANDLE volume, + SYS_HANDLE context) { + for (uint32_t order = 0; order < gServiceConfig.StartupCount; ++order) { + uint16_t index = gServiceConfig.StartupOrder[order]; + INIT_SERVICE* service = &gServices[index]; + const INIT_SERVICE_DESCRIPTOR* descriptor = service->Descriptor; + if (service->State != InitServiceStopped || + (descriptor->StartPolicy != InitServiceStartAuto && + (!includeDelayed || descriptor->StartPolicy != InitServiceStartDelayed))) continue; + bool pending = false, failed = false; + for (uint32_t d = 0; d < descriptor->DependencyCount; ++d) { + INIT_SERVICE_STATE state = gServices[descriptor->Dependencies[d]].State; + if (state == InitServiceFailed) failed = true; + else if (state != InitServiceReady) pending = true; + } + if (pending && !failed) continue; + if (!failed) { + for (uint32_t d = 0; d < descriptor->AfterCount; ++d) { + const INIT_SERVICE* predecessor = &gServices[descriptor->After[d]]; + INIT_SERVICE_STATE state = predecessor->State; + if (predecessor->Descriptor->StartPolicy == InitServiceStartDisabled) continue; + if (state == InitServiceStopped || state == InitServiceStarting || + state == InitServiceRestartPending) { + pending = true; + break; + } + } + } + if (pending && !failed) continue; + if (failed) { + service->State = InitServiceFailed; + debug_print("[init] service blocked: "); + debug_print(descriptor->Id); + debug_print("\n"); + } else { + KSTATUS status = start_service_process(volume, context, service); + if (KSUCCESS(status)) continue; + debug_print("[init] service launch failed: "); + debug_print(descriptor->Id); + debug_print(" "); + debug_status(status); + debug_print("\n"); + } + if (!failed && service->State == InitServiceFailed && queue_service_restart(service)) continue; + if (descriptor->Critical) return NTLSTATUS_FAILURE; + } + return NTLSTATUS_SUCCESS; +} + +// Tests a transitive hard dependency in the validated acyclic service graph. +static bool service_depends_on(uint16_t serviceIndex, uint16_t providerIndex) { + const INIT_SERVICE_DESCRIPTOR* desc = &gServiceConfig.Services[serviceIndex]; + for (uint32_t i = 0; i < desc->DependencyCount; ++i) { + uint16_t dep = desc->Dependencies[i]; + if (dep == providerIndex || service_depends_on(dep, providerIndex)) return true; + } + return false; +} + +// Critical consumers make their provider's startup a critical dependency. +static bool critical_service_affected(uint16_t providerIndex) { + if (gServices[providerIndex].Descriptor->Critical) return true; + for (uint32_t i = 0; i < gServiceConfig.ServiceCount; ++i) + if (gServices[i].Descriptor->Critical && + service_depends_on((uint16_t)i, providerIndex)) return true; + return false; +} + +// Advances one completed READY handshake from the existing Port wait event. +static KSTATUS complete_starting_service(INIT_SERVICE* service) { + KSTATUS status = finish_service_ready(service, 0u); + if (KSUCCESS(status)) { + debug_print("service: ready id="); + debug_print(service->Descriptor->Id); + debug_print("\n"); + } else { + debug_print("[init] service startup failed: "); + debug_print(service->Descriptor->Id); + debug_print(" "); + debug_status(status); + debug_print("\n"); + } + return status; +} + +// Uses the original launch timestamp for each independent READY deadline. +static uint64_t starting_timeout_ms(uint64_t now) { + uint64_t nearest = SYS_WAIT_TIMEOUT_INFINITE; + for (uint32_t i = 0; i < gServiceConfig.ServiceCount; ++i) { + const INIT_SERVICE* service = &gServices[i]; + if (service->State != InitServiceStarting) continue; + uint64_t elapsed = now >= service->StartedTick ? now - service->StartedTick : 0u; + uint64_t limit = ((uint64_t)service->Descriptor->ReadyTimeoutMilliseconds * + gTickFrequency + 999u) / 1000u; + if (elapsed >= limit) return 0u; + uint64_t remaining = limit - elapsed; + uint64_t ms = (remaining / gTickFrequency) * 1000u + + ((remaining % gTickFrequency) * 1000u + gTickFrequency - 1u) / gTickFrequency; + if (ms < nearest) nearest = ms; + } + return nearest; +} + +// Starts due restart attempts and reports a failed critical provider. +static KSTATUS start_pending_restarts(SYS_HANDLE volume, SYS_HANDLE context) { + uint64_t now = SysGetTick(); + for (uint32_t i = 0; i < gServiceConfig.ServiceCount; ++i) { + INIT_SERVICE* service = &gServices[i]; + if (service->State != InitServiceRestartPending || now < service->RestartTick) continue; + KSTATUS status = start_service_process(volume, context, service); + if (KSUCCESS(status)) continue; + debug_print("[init] service restart failed: "); + debug_print(service->Descriptor->Id); + debug_print("\n"); + if (!queue_service_restart(service) && critical_service_affected((uint16_t)i)) + return NTLSTATUS_FAILURE; + } + return NTLSTATUS_SUCCESS; +} + +static uint64_t restart_timeout_ms(uint64_t now) { + uint64_t nearest = SYS_WAIT_TIMEOUT_INFINITE; + for (uint32_t i = 0; i < gServiceConfig.ServiceCount; ++i) { + INIT_SERVICE* service = &gServices[i]; + if (service->State != InitServiceRestartPending) continue; + if (now >= service->RestartTick) return 0u; + uint64_t ticks = service->RestartTick - now; + uint64_t ms = (ticks / gTickFrequency) * 1000u + + ((ticks % gTickFrequency) * 1000u + gTickFrequency - 1u) / gTickFrequency; + if (ms < nearest) nearest = ms; + } + return nearest; +} + +// Expires all overdue handshakes even if another endpoint remains busy. +static KSTATUS expire_starting_services(void) { + uint64_t now = SysGetTick(); + for (uint32_t i = 0; i < gServiceConfig.ServiceCount; ++i) { + INIT_SERVICE* service = &gServices[i]; + if (service->State != InitServiceStarting) continue; + uint64_t elapsed = now >= service->StartedTick ? now - service->StartedTick : 0u; + uint64_t limit = ((uint64_t)service->Descriptor->ReadyTimeoutMilliseconds * + gTickFrequency + 999u) / 1000u; + if (elapsed < limit) continue; + debug_print("[init] READY timeout: "); + debug_print(service->Descriptor->Id); + debug_print("\n"); + (void)SysKillProcess(service->Process, 1); + close_service_handles(service); + service->State = InitServiceFailed; + if (!queue_service_restart(service) && critical_service_affected((uint16_t)i)) + return NTLSTATUS_FAILURE; + } + return NTLSTATUS_SUCCESS; +} + +// Waits for the automatic graph to settle before the shell starts. +static KSTATUS start_automatic_services(SYS_HANDLE volume, SYS_HANDLE context) { + for (;;) { + KSTATUS status = start_pending_restarts(volume, context); + if (KSUCCESS(status)) status = launch_services(false, volume, context); + if (!KSUCCESS(status)) return status; + SYS_HANDLE waits[INIT_SERVICE_MAX_COUNT]; + uint16_t indices[INIT_SERVICE_MAX_COUNT]; + uint32_t count = 0; + for (uint32_t i = 0; i < gServiceConfig.ServiceCount; ++i) { + if (gServices[i].State != InitServiceStarting) continue; + waits[count] = gServices[i].ControlEndpoint; + indices[count++] = (uint16_t)i; + } + if (!count) { + uint64_t retry = restart_timeout_ms(SysGetTick()); + if (retry == SYS_WAIT_TIMEOUT_INFINITE) return NTLSTATUS_SUCCESS; + if (retry) (void)SysSleep(retry); + continue; + } + uint32_t selected = 0; + SYS_WAIT_MANY_REQUEST request = {0}; + request.Size = sizeof(request); + request.Handles = waits; + request.Count = count; + request.SignaledIndexOut = &selected; + uint64_t now = SysGetTick(); + uint64_t readyWait = starting_timeout_ms(now); + uint64_t retryWait = restart_timeout_ms(now); + request.TimeoutMilliseconds = readyWait < retryWait ? readyWait : retryWait; + if (request.TimeoutMilliseconds) { + status = SysWaitMany(&request); + if (status != NTLSTATUS_TIMEOUT && !KSUCCESS(status)) return status; + if (KSUCCESS(status)) { + INIT_SERVICE* service = &gServices[indices[selected]]; + if (!KSUCCESS(complete_starting_service(service)) && + !queue_service_restart(service) && critical_service_affected(indices[selected])) + return NTLSTATUS_FAILURE; + } + } + status = expire_starting_services(); + if (!KSUCCESS(status)) return status; + } +} + + // Requests graceful STOP and bounds the fallback termination of any service. static void stop_service(INIT_SERVICE* service) { if (!service || service->Process == SYS_HANDLE_INVALID) return; @@ -482,10 +716,17 @@ static void stop_service(INIT_SERVICE* service) { send.EndpointHandle = service->ControlEndpoint; send.Payload = &message; send.PayloadLength = sizeof(message); + uint64_t started = SysGetTick(); + uint64_t duration = ((uint64_t)service->Descriptor->StopTimeoutMilliseconds * + gTickFrequency + 999u) / 1000u; send.TimeoutMilliseconds = service->Descriptor->StopTimeoutMilliseconds; (void)SysSendPort(&send); - KSTATUS status = SysWaitSingle(service->Process, SYS_WAIT_FLAG_NONE, - service->Descriptor->StopTimeoutMilliseconds); + uint64_t elapsed = SysGetTick() - started; + uint64_t remaining = elapsed >= duration ? 0u : duration - elapsed; + uint64_t remainingMs = gTickFrequency ? + (remaining / gTickFrequency) * 1000u + + ((remaining % gTickFrequency) * 1000u + gTickFrequency - 1u) / gTickFrequency : 0u; + KSTATUS status = SysWaitSingle(service->Process, SYS_WAIT_FLAG_NONE, remainingMs); if (!KSUCCESS(status)) { (void)SysKillProcess(service->Process, 1); status = SysWaitSingle(service->Process, SYS_WAIT_FLAG_NONE, 2000u); @@ -501,17 +742,7 @@ static void stop_all_services(void) { stop_service(&gServices[gServiceConfig.StartupOrder[order - 1u]]); } -// Tests a transitive hard dependency in the validated acyclic service graph. -static bool service_depends_on(uint16_t serviceIndex, uint16_t providerIndex) { - const INIT_SERVICE_DESCRIPTOR* desc = &gServiceConfig.Services[serviceIndex]; - for (uint32_t i = 0; i < desc->DependencyCount; ++i) { - uint16_t dep = desc->Dependencies[i]; - if (dep == providerIndex || service_depends_on(dep, providerIndex)) return true; - } - return false; -} - -// Before restarting a provider, quiesce every transitive consumer in reverse order. +// Quiesces dependent services before the provider generation changes. static void stop_service_dependents(uint16_t providerIndex) { for (uint32_t order = gServiceConfig.StartupCount; order > 0; --order) { uint16_t index = gServiceConfig.StartupOrder[order - 1u]; @@ -520,19 +751,7 @@ static void stop_service_dependents(uint16_t providerIndex) { } } -// Starts eligible descendants again using the dependency-first startup order. -static KSTATUS restart_service_dependents(uint16_t providerIndex, SYS_HANDLE volume, - SYS_HANDLE context) { - for (uint32_t order = 0; order < gServiceConfig.StartupCount; ++order) { - uint16_t index = gServiceConfig.StartupOrder[order]; - if (!service_depends_on(index, providerIndex)) continue; - KSTATUS status = start_managed_service(volume, context, &gServices[index]); - if (!KSUCCESS(status)) return status; - } - return NTLSTATUS_SUCCESS; -} - -// Starts the configured native session process from the system-volume capability. +// Starts the configured session image from the system volume. static KSTATUS start_configured_child(SYS_HANDLE systemVolume, SYS_STRING_VIEW path, SYS_HANDLE* processOut) { NTL_CREATE_PROCESS_AT_REQUEST create; memset(&create, 0, sizeof(create)); @@ -627,47 +846,32 @@ void _start(void) { exit_now(1); } - SYS_STRING_VIEW childPath = SysGetPeb()->CommandLine; + SYS_STRING_VIEW childPath = SysSvFromCstr(gServiceConfig.SessionImage); if (!childPath.Data || childPath.Length == 0) { debug_print("[init] FATAL: no configured session process\n"); if (unprivilegedServiceContext != SYS_HANDLE_INVALID) (void)SysCloseHandle(unprivilegedServiceContext); exit_now(1); } - uint32_t autoCount = gServiceConfig.StartupCount; - if (autoCount + 2u > SYS_WAIT_MANY_MAX_HANDLES) { + if (gServiceConfig.StartupCount + 2u > SYS_WAIT_MANY_MAX_HANDLES) { debug_print("[init] FATAL: service graph exceeds supervision wait capacity\n"); exit_now(1); } for (uint32_t i = 0; i < gServiceConfig.ServiceCount; ++i) initialize_service(&gServices[i], &gServiceConfig.Services[i]); - for (uint32_t order = 0; order < gServiceConfig.StartupCount; ++order) { - uint16_t index = gServiceConfig.StartupOrder[order]; - INIT_SERVICE* service = &gServices[index]; - status = start_managed_service(systemVolume, unprivilegedServiceContext, service); - debug_print("[init] service "); - debug_print(service->Descriptor->Id); - if (KSUCCESS(status)) debug_print(" READY\n"); - else { - debug_print(" startup failed: "); - debug_status(status); - debug_print("\n"); - if (service->Descriptor->Critical) { - stop_all_services(); - exit_now(1); - } - } - } - - INIT_RESTART_BUDGET restartBudgets[INIT_SERVICE_MAX_COUNT] = {0}; - uint64_t tickFrequency = 0; - status = SysGetTickFrequency(&tickFrequency); - if (!KSUCCESS(status) || tickFrequency == 0u) { + status = SysGetTickFrequency(&gTickFrequency); + if (!KSUCCESS(status) || gTickFrequency == 0u || gTickFrequency > UINT64_MAX / 600000u) { debug_print("[init] FATAL: monotonic clock unavailable for supervision\n"); stop_all_services(); exit_now(1); } + status = start_automatic_services(systemVolume, unprivilegedServiceContext); + if (!KSUCCESS(status)) { + debug_print("[init] FATAL: automatic service startup failed\n"); + stop_all_services(); + exit_now(1); + } for (;;) { SYS_HANDLE child = SYS_HANDLE_INVALID; status = start_configured_child(systemVolume, childPath, &child); @@ -678,10 +882,22 @@ void _start(void) { stop_all_services(); exit_now(1); } - debug_print("[init] session process started\n"); + debug_print("init: session started\n"); + status = launch_services(true, systemVolume, unprivilegedServiceContext); + if (!KSUCCESS(status)) { + stop_all_services(); + exit_now(1); + } bool restartChild = false; for (;;) { + status = start_pending_restarts(systemVolume, unprivilegedServiceContext); + if (KSUCCESS(status)) status = launch_services(true, systemVolume, unprivilegedServiceContext); + if (!KSUCCESS(status) || !KSUCCESS(expire_starting_services())) { + debug_print("[init] FATAL: delayed service dependency failed\n"); + stop_all_services(); + exit_now(1); + } SYS_HANDLE waits[SYS_WAIT_MANY_MAX_HANDLES]; uint32_t kinds[SYS_WAIT_MANY_MAX_HANDLES]; uint32_t waitCount = 0; @@ -690,9 +906,11 @@ void _start(void) { waits[waitCount] = child; kinds[waitCount++] = UINT32_MAX - 1u; for (uint32_t i = 0; i < gServiceConfig.ServiceCount; ++i) { - if (gServices[i].State != InitServiceReady || - gServices[i].Process == SYS_HANDLE_INVALID) continue; - waits[waitCount] = gServices[i].Process; + if (gServices[i].Process == SYS_HANDLE_INVALID) continue; + if (gServices[i].State != InitServiceReady && + gServices[i].State != InitServiceStarting) continue; + waits[waitCount] = gServices[i].State == InitServiceStarting ? + gServices[i].ControlEndpoint : gServices[i].Process; kinds[waitCount++] = i; } uint32_t signaled = 0; @@ -701,8 +919,12 @@ void _start(void) { wait.Handles = waits; wait.Count = waitCount; wait.SignaledIndexOut = &signaled; - wait.TimeoutMilliseconds = SYS_WAIT_TIMEOUT_INFINITE; + uint64_t now = SysGetTick(); + uint64_t readyWait = starting_timeout_ms(now); + uint64_t retryWait = restart_timeout_ms(now); + wait.TimeoutMilliseconds = readyWait < retryWait ? readyWait : retryWait; status = SysWaitMany(&wait); + if (status == NTLSTATUS_TIMEOUT) continue; if (!KSUCCESS(status)) { debug_print("[init] FATAL: service supervision wait failed\n"); (void)SysKillProcess(child, 1); @@ -742,6 +964,19 @@ void _start(void) { } uint16_t failedIndex = (uint16_t)kinds[signaled]; INIT_SERVICE* failed = &gServices[failedIndex]; + if (failed->State == InitServiceStarting) { + KSTATUS readyStatus = complete_starting_service(failed); + if (!KSUCCESS(readyStatus) && !queue_service_restart(failed) && + critical_service_affected(failedIndex)) { + debug_print("[init] FATAL: critical service READY failed\n"); + (void)SysKillProcess(child, 1); + (void)SysWait(child, SYS_WAIT_FLAG_NONE); + (void)SysCloseHandle(child); + stop_all_services(); + exit_now(1); + } + continue; + } int32_t exitCode = -1; (void)SysGetProcessExitCode(failed->Process, &exitCode); debug_print("[init] service exited: "); @@ -752,21 +987,12 @@ void _start(void) { stop_service_dependents(failedIndex); close_service_handles(failed); failed->State = InitServiceFailed; - if (failed->Descriptor->RestartPolicy == InitServiceRestartOnFailure && - InitConsumeRestartBudget(&restartBudgets[failedIndex], - SysGetTick(), tickFrequency)) { - status = start_managed_service(systemVolume, unprivilegedServiceContext, failed); - if (KSUCCESS(status)) - status = restart_service_dependents(failedIndex, systemVolume, unprivilegedServiceContext); - if (KSUCCESS(status)) continue; - debug_print("[init] service restart failed\n"); - } + const INIT_SERVICE_RESTART_POLICY restart = failed->Descriptor->RestartPolicy; + if ((restart == InitServiceRestartAlways || + (restart == InitServiceRestartOnFailure && exitCode != 0)) && + queue_service_restart(failed)) continue; // Any affected critical service is a fatal dependency loss. - bool fatal = failed->Descriptor->Critical; - for (uint32_t i = 0; i < gServiceConfig.ServiceCount; ++i) - if (gServices[i].Descriptor->Critical && service_depends_on((uint16_t)i, failedIndex)) - fatal = true; - if (fatal) { + if (critical_service_affected(failedIndex)) { (void)SysKillProcess(child, 1); (void)SysWait(child, SYS_WAIT_FLAG_NONE); (void)SysCloseHandle(child); diff --git a/code/user/system/init/makefile b/code/user/system/init/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/system/init/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/system/init/restart_budget.h b/code/user/system/init/restart_budget.h index 41d8127..6546e4a 100644 --- a/code/user/system/init/restart_budget.h +++ b/code/user/system/init/restart_budget.h @@ -1,19 +1,26 @@ -// Service restart budget: three automatic attempts in any sliding five-minute interval. +// A per-service sliding restart budget with explicit count and time window. #pragma once #include #include +#define INIT_RESTART_MAX_ATTEMPTS 16u + typedef struct INIT_RESTART_BUDGET { - uint64_t Attempts[3]; + uint64_t Attempts[INIT_RESTART_MAX_ATTEMPTS]; uint32_t Count; } INIT_RESTART_BUDGET; static inline bool InitConsumeRestartBudget(INIT_RESTART_BUDGET* budget, - uint64_t now, uint64_t frequency) { - if (!budget || !frequency || budget->Count > 3u || - frequency > UINT64_MAX / 300u) return false; - uint64_t window = frequency * 300u; + uint64_t now, uint64_t frequency, + uint32_t limit, uint32_t windowMilliseconds) { + if (!budget || !frequency || !limit || limit > INIT_RESTART_MAX_ATTEMPTS || + !windowMilliseconds || budget->Count > INIT_RESTART_MAX_ATTEMPTS || + frequency > UINT64_MAX / windowMilliseconds) + return false; + uint64_t window = frequency * windowMilliseconds; + window = window / 1000u + (window % 1000u != 0u); + if (!window) window = 1; uint32_t keep = 0; for (uint32_t i = 0; i < budget->Count; ++i) { uint64_t started = budget->Attempts[i]; @@ -21,7 +28,7 @@ static inline bool InitConsumeRestartBudget(INIT_RESTART_BUDGET* budget, budget->Attempts[keep++] = started; } budget->Count = keep; - if (keep == 3u) return false; + if (keep >= limit) return false; budget->Attempts[budget->Count++] = now; return true; } diff --git a/code/user/system/init/service_config.c b/code/user/system/init/service_config.c index 1c03258..5d3aa9d 100644 --- a/code/user/system/init/service_config.c +++ b/code/user/system/init/service_config.c @@ -7,6 +7,7 @@ #include #include +#define INIT_SERVICE_KEY_NAME 0x00000001u #define INIT_SERVICE_KEY_IMAGE 0x00000002u #define INIT_SERVICE_KEY_START 0x00000004u #define INIT_SERVICE_KEY_CRITICAL 0x00000008u @@ -16,18 +17,25 @@ #define INIT_SERVICE_KEY_REQUIRES 0x00000080u #define INIT_SERVICE_KEY_GRANTS 0x00000100u #define INIT_SERVICE_KEY_EXPORTS 0x00000200u -#define INIT_SERVICE_REQUIRED_KEYS 0x000003FEu +#define INIT_SERVICE_KEY_AFTER 0x00000400u +#define INIT_SERVICE_KEY_PRIVILEGES 0x00000800u +#define INIT_SERVICE_KEY_RESTART_LIMIT 0x00001000u +#define INIT_SERVICE_KEY_RESTART_WINDOW 0x00002000u +#define INIT_SERVICE_KEY_RESTART_DELAY 0x00004000u typedef struct INIT_PARSED_SERVICE { INIT_SERVICE_DESCRIPTOR Descriptor; char DependencyIds[INIT_SERVICE_DEPENDENCY_MAX][INIT_SERVICE_ID_MAX + 1u]; uint32_t DependencyCount; + char AfterIds[INIT_SERVICE_DEPENDENCY_MAX][INIT_SERVICE_ID_MAX + 1u]; + uint32_t AfterCount; uint32_t PresentKeys; uint32_t SectionLine; } INIT_PARSED_SERVICE; static char gServicesIniBuffer[INIT_SERVICES_MAX_FILE_BYTES + 1u]; static INIT_PARSED_SERVICE gParsedServices[INIT_SERVICE_MAX_COUNT]; +static char gSessionImage[SYS_PATH_MAX]; // Returns whether one byte is horizontal configuration whitespace. static bool is_space(char c) { @@ -129,29 +137,66 @@ static int32_t find_parsed_service(const INIT_PARSED_SERVICE* services, return -1; } -// Parses the comma-separated hard dependency list for one service. -static bool parse_requires(char* value, INIT_PARSED_SERVICE* service) { - service->DependencyCount = 0; +// Parses distinct service IDs for one dependency edge type. +static bool parse_edges(char* value, + char ids[INIT_SERVICE_DEPENDENCY_MAX][INIT_SERVICE_ID_MAX + 1u], + uint32_t* countOut) { + *countOut = 0; if (!*value) return true; - char* cursor = value; for (;;) { char* comma = strchr(cursor, ','); if (comma) *comma = '\0'; char* id = trim_left(cursor); trim_right(id); - if (!validate_service_id(id) || service->DependencyCount >= INIT_SERVICE_DEPENDENCY_MAX) + if (!validate_service_id(id) || *countOut >= INIT_SERVICE_DEPENDENCY_MAX) return false; - - for (uint32_t i = 0; i < service->DependencyCount; ++i) - if (strcmp(service->DependencyIds[i], id) == 0) return false; - if (!copy_bounded(service->DependencyIds[service->DependencyCount], - sizeof(service->DependencyIds[0]), id)) - return false; - ++service->DependencyCount; - + for (uint32_t i = 0; i < *countOut; ++i) + if (strcmp(ids[i], id) == 0) return false; + if (!copy_bounded(ids[*countOut], sizeof(ids[0]), id)) return false; + ++*countOut; if (!comma) break; - cursor = comma + 1; + cursor = comma + 1u; + if (!*cursor) return false; + } + return true; +} + +static bool parse_privileges(char* value, SYS_PRIVILEGES* privilegesOut) { + static const struct { const char* Name; SYS_PRIVILEGES Bit; } names[] = { + { "process-open-any", SYS_PRIV_PROCESS_OPEN_ANY }, + { "process-enumerate", SYS_PRIV_PROCESS_ENUMERATE }, + { "thread-enumerate-any", SYS_PRIV_THREAD_ENUMERATE_ANY }, + { "kernel-diagnostics", SYS_PRIV_KERNEL_DIAGNOSTICS }, + { "system-power", SYS_PRIV_SYSTEM_POWER }, + { "audio-access", SYS_PRIV_AUDIO_ACCESS }, + { "audio-master-control", SYS_PRIV_AUDIO_MASTER_CONTROL }, + { "console-access", SYS_PRIV_CONSOLE_ACCESS }, + { "display-access", SYS_PRIV_DISPLAY_ACCESS }, + { "debug-output", SYS_PRIV_DEBUG_OUTPUT }, + { "raw-storage", SYS_PRIV_RAW_STORAGE }, + { "filesystem-provider", SYS_PRIV_FILESYSTEM_PROVIDER }, + { "network-access", SYS_PRIV_NETWORK_ACCESS } + }; + *privilegesOut = 0; + if (!*value) return true; + char* cursor = value; + for (;;) { + char* comma = strchr(cursor, ','); + if (comma) *comma = '\0'; + char* name = trim_left(cursor); + trim_right(name); + bool found = false; + for (uint32_t i = 0; i < sizeof(names) / sizeof(names[0]); ++i) { + if (strcmp(names[i].Name, name) != 0) continue; + if (*privilegesOut & names[i].Bit) return false; + *privilegesOut |= names[i].Bit; + found = true; + break; + } + if (!found) return false; + if (!comma) break; + cursor = comma + 1u; if (!*cursor) return false; } return true; @@ -215,7 +260,11 @@ static bool parse_exports(char* value, INIT_PARSED_SERVICE* service) { static bool parse_service_key(INIT_PARSED_SERVICE* service, char* key, char* value) { uint32_t bit = 0; - if (strcmp(key, "image") == 0) { + if (strcmp(key, "name") == 0) { + bit = INIT_SERVICE_KEY_NAME; + if (!*value || !copy_bounded(service->Descriptor.Name, sizeof(service->Descriptor.Name), value)) + return false; + } else if (strcmp(key, "image") == 0) { bit = INIT_SERVICE_KEY_IMAGE; if (!validate_image_path(value) || !copy_bounded(service->Descriptor.ImagePath, sizeof(service->Descriptor.ImagePath), value)) @@ -223,6 +272,7 @@ static bool parse_service_key(INIT_PARSED_SERVICE* service, char* key, char* val } else if (strcmp(key, "start") == 0) { bit = INIT_SERVICE_KEY_START; if (strcmp(value, "auto") == 0) service->Descriptor.StartPolicy = InitServiceStartAuto; + else if (strcmp(value, "delayed") == 0) service->Descriptor.StartPolicy = InitServiceStartDelayed; else if (strcmp(value, "disabled") == 0) service->Descriptor.StartPolicy = InitServiceStartDisabled; else return false; } else if (strcmp(key, "critical") == 0) { @@ -232,7 +282,17 @@ static bool parse_service_key(INIT_PARSED_SERVICE* service, char* key, char* val bit = INIT_SERVICE_KEY_RESTART; if (strcmp(value, "never") == 0) service->Descriptor.RestartPolicy = InitServiceRestartNever; else if (strcmp(value, "on-failure") == 0) service->Descriptor.RestartPolicy = InitServiceRestartOnFailure; + else if (strcmp(value, "always") == 0) service->Descriptor.RestartPolicy = InitServiceRestartAlways; else return false; + } else if (strcmp(key, "restart_limit") == 0) { + bit = INIT_SERVICE_KEY_RESTART_LIMIT; + if (!parse_u32(value, 1u, 16u, &service->Descriptor.RestartLimit)) return false; + } else if (strcmp(key, "restart_window_ms") == 0) { + bit = INIT_SERVICE_KEY_RESTART_WINDOW; + if (!parse_u32(value, 1u, 3600000u, &service->Descriptor.RestartWindowMilliseconds)) return false; + } else if (strcmp(key, "restart_delay_ms") == 0) { + bit = INIT_SERVICE_KEY_RESTART_DELAY; + if (!parse_u32(value, 0u, 600000u, &service->Descriptor.RestartDelayMilliseconds)) return false; } else if (strcmp(key, "ready_timeout_ms") == 0) { bit = INIT_SERVICE_KEY_READY_TIMEOUT; if (!parse_u32(value, 1u, 600000u, &service->Descriptor.ReadyTimeoutMilliseconds)) return false; @@ -241,7 +301,13 @@ static bool parse_service_key(INIT_PARSED_SERVICE* service, char* key, char* val if (!parse_u32(value, 1u, 600000u, &service->Descriptor.StopTimeoutMilliseconds)) return false; } else if (strcmp(key, "requires") == 0) { bit = INIT_SERVICE_KEY_REQUIRES; - if (!parse_requires(value, service)) return false; + if (!parse_edges(value, service->DependencyIds, &service->DependencyCount)) return false; + } else if (strcmp(key, "after") == 0) { + bit = INIT_SERVICE_KEY_AFTER; + if (!parse_edges(value, service->AfterIds, &service->AfterCount)) return false; + } else if (strcmp(key, "privileges") == 0) { + bit = INIT_SERVICE_KEY_PRIVILEGES; + if (!parse_privileges(value, &service->Descriptor.Privileges)) return false; } else if (strcmp(key, "grants") == 0) { bit = INIT_SERVICE_KEY_GRANTS; if (!parse_grants(value, service)) return false; @@ -261,6 +327,9 @@ static bool parse_service_key(INIT_PARSED_SERVICE* service, char* key, char* val static KSTATUS parse_services_ini(char* buffer, uint32_t* serviceCountOut, uint32_t* errorLineOut) { uint32_t serviceCount = 0; INIT_PARSED_SERVICE* current = NULL; + bool inSession = false; + bool sessionSeen = false; + bool sessionImageSeen = false; uint32_t lineNumber = 0; char* line = buffer; @@ -279,14 +348,22 @@ static KSTATUS parse_services_ini(char* buffer, uint32_t* serviceCountOut, uint3 // Blank and whole-line comments are the only ignored line forms. } else if (*text == '[') { size_t length = strlen(text); - if (length < 11u || text[length - 1u] != ']' || strchr(text + 1, ']') != &text[length - 1u]) { + if (length < 3u || text[length - 1u] != ']' || strchr(text + 1, ']') != &text[length - 1u]) { valid = false; } else { text[length - 1u] = '\0'; const char prefix[] = "service."; - if (strncmp(text + 1, prefix, sizeof(prefix) - 1u) != 0) { + if (strcmp(text + 1, "session") == 0) { + if (sessionSeen) valid = false; + else { + sessionSeen = true; + inSession = true; + current = NULL; + } + } else if (strncmp(text + 1, prefix, sizeof(prefix) - 1u) != 0) { valid = false; } else { + inSession = false; char* id = text + 1u + sizeof(prefix) - 1u; if (!validate_service_id(id) || serviceCount >= INIT_SERVICE_MAX_COUNT || find_parsed_service(gParsedServices, serviceCount, id) >= 0) { @@ -295,13 +372,20 @@ static KSTATUS parse_services_ini(char* buffer, uint32_t* serviceCountOut, uint3 current = &gParsedServices[serviceCount++]; memset(current, 0, sizeof(*current)); current->SectionLine = lineNumber; - if (!copy_bounded(current->Descriptor.Id, sizeof(current->Descriptor.Id), id)) + current->Descriptor.StartPolicy = InitServiceStartAuto; + current->Descriptor.RestartPolicy = InitServiceRestartNever; + current->Descriptor.ReadyTimeoutMilliseconds = 5000u; + current->Descriptor.StopTimeoutMilliseconds = 5000u; + current->Descriptor.RestartLimit = 3u; + current->Descriptor.RestartWindowMilliseconds = 300000u; + if (!copy_bounded(current->Descriptor.Id, sizeof(current->Descriptor.Id), id) || + !copy_bounded(current->Descriptor.Name, sizeof(current->Descriptor.Name), id)) valid = false; } } } } else { - if (!current) { + if (!current && !inSession) { valid = false; } else { char* equals = strchr(text, '='); @@ -313,7 +397,14 @@ static KSTATUS parse_services_ini(char* buffer, uint32_t* serviceCountOut, uint3 char* value = trim_left(equals + 1); trim_right(key); trim_right(value); - if (!*key || !parse_service_key(current, key, value)) valid = false; + if (inSession) { + if (strcmp(key, "image") != 0 || sessionImageSeen || + !validate_image_path(value) || + !copy_bounded(gSessionImage, sizeof(gSessionImage), value)) valid = false; + else sessionImageSeen = true; + } else if (!*key || !parse_service_key(current, key, value)) { + valid = false; + } } } } @@ -326,7 +417,7 @@ static KSTATUS parse_services_ini(char* buffer, uint32_t* serviceCountOut, uint3 line = saved ? end + 1u : end; } - if (serviceCount == 0) + if (serviceCount == 0 || !sessionImageSeen) return NTLSTATUS_INVALID_PARAMETER; *serviceCountOut = serviceCount; return NTLSTATUS_SUCCESS; @@ -337,6 +428,7 @@ static KSTATUS validate_services(uint32_t serviceCount, INIT_SERVICE_CONFIG* configOut, uint32_t* errorLineOut) { memset(configOut, 0, sizeof(*configOut)); + memcpy(configOut->SessionImage, gSessionImage, strlen(gSessionImage) + 1u); static const char* const bootGrants[] = { NTL_BOOT_CAP_NAMESPACE_ROOT, NTL_BOOT_CAP_VOLUME_MANAGER, NTL_BOOT_CAP_INPUT_MANAGER, @@ -369,7 +461,7 @@ static KSTATUS validate_services(uint32_t serviceCount, } bool declaredDependency = false; if (provider >= 0 && (uint32_t)provider != i && - gParsedServices[provider].Descriptor.StartPolicy == InitServiceStartAuto) { + gParsedServices[provider].Descriptor.StartPolicy != InitServiceStartDisabled) { for (uint32_t d = 0; d < gParsedServices[i].DependencyCount; ++d) if (strcmp(gParsedServices[i].DependencyIds[d], gParsedServices[provider].Descriptor.Id) == 0) @@ -390,9 +482,29 @@ static KSTATUS validate_services(uint32_t serviceCount, } } + // Exactly one critical automatic service owns the primordial namespace authority. + uint32_t namespaceProviders = 0; + for (uint32_t i = 0; i < serviceCount; ++i) { + const INIT_SERVICE_DESCRIPTOR* descriptor = &gParsedServices[i].Descriptor; + bool namespaceRoot = false; + bool registration = false; + for (uint32_t g = 0; g < descriptor->GrantCount; ++g) { + if (strcmp(descriptor->Grants[g], NTL_BOOT_CAP_NAMESPACE_ROOT) == 0) namespaceRoot = true; + if (strcmp(descriptor->Grants[g], NTL_BOOT_CAP_RESOURCE_REGISTRATION) == 0) registration = true; + } + if (!namespaceRoot && !registration) continue; + if (!namespaceRoot || !registration || !descriptor->Critical || + descriptor->StartPolicy != InitServiceStartAuto) { + if (errorLineOut) *errorLineOut = gParsedServices[i].SectionLine; + return NTLSTATUS_INVALID_PARAMETER; + } + ++namespaceProviders; + } + if (namespaceProviders != 1u) return NTLSTATUS_INVALID_PARAMETER; + for (uint32_t i = 0; i < serviceCount; ++i) { INIT_PARSED_SERVICE* parsed = &gParsedServices[i]; - if (parsed->PresentKeys != INIT_SERVICE_REQUIRED_KEYS) { + if ((parsed->PresentKeys & INIT_SERVICE_KEY_IMAGE) == 0u) { if (errorLineOut) *errorLineOut = parsed->SectionLine; return NTLSTATUS_INVALID_PARAMETER; } @@ -415,14 +527,43 @@ static KSTATUS validate_services(uint32_t serviceCount, } descriptor->Dependencies[d] = (uint16_t)dependency; } + descriptor->AfterCount = parsed->AfterCount; + for (uint32_t d = 0; d < parsed->AfterCount; ++d) { + int32_t dependency = find_parsed_service(gParsedServices, serviceCount, parsed->AfterIds[d]); + if (dependency < 0 || (uint32_t)dependency == i) { + if (errorLineOut) *errorLineOut = parsed->SectionLine; + return NTLSTATUS_INVALID_PARAMETER; + } + for (uint32_t r = 0; r < descriptor->DependencyCount; ++r) { + if (descriptor->Dependencies[r] == (uint16_t)dependency) { + if (errorLineOut) *errorLineOut = parsed->SectionLine; + return NTLSTATUS_INVALID_PARAMETER; + } + } + descriptor->After[d] = (uint16_t)dependency; + } } for (uint32_t i = 0; i < serviceCount; ++i) { INIT_SERVICE_DESCRIPTOR* descriptor = &configOut->Services[i]; - if (descriptor->StartPolicy != InitServiceStartAuto) continue; + if (descriptor->Critical && descriptor->StartPolicy != InitServiceStartAuto) { + if (errorLineOut) *errorLineOut = gParsedServices[i].SectionLine; + return NTLSTATUS_INVALID_PARAMETER; + } + if (descriptor->StartPolicy == InitServiceStartDisabled) continue; for (uint32_t d = 0; d < descriptor->DependencyCount; ++d) { INIT_SERVICE_DESCRIPTOR* dependency = &configOut->Services[descriptor->Dependencies[d]]; - if (dependency->StartPolicy == InitServiceStartDisabled) { + if (dependency->StartPolicy == InitServiceStartDisabled || + (descriptor->StartPolicy == InitServiceStartAuto && + dependency->StartPolicy != InitServiceStartAuto)) { + if (errorLineOut) *errorLineOut = gParsedServices[i].SectionLine; + return NTLSTATUS_INVALID_PARAMETER; + } + } + for (uint32_t d = 0; d < descriptor->AfterCount; ++d) { + INIT_SERVICE_DESCRIPTOR* dependency = &configOut->Services[descriptor->After[d]]; + if (descriptor->StartPolicy == InitServiceStartAuto && + dependency->StartPolicy == InitServiceStartDelayed) { if (errorLineOut) *errorLineOut = gParsedServices[i].SectionLine; return NTLSTATUS_INVALID_PARAMETER; } @@ -432,7 +573,7 @@ static KSTATUS validate_services(uint32_t serviceCount, uint32_t indegree[INIT_SERVICE_MAX_COUNT] = {0}; bool emitted[INIT_SERVICE_MAX_COUNT] = {0}; for (uint32_t i = 0; i < serviceCount; ++i) - indegree[i] = configOut->Services[i].DependencyCount; + indegree[i] = configOut->Services[i].DependencyCount + configOut->Services[i].AfterCount; uint32_t emittedCount = 0; while (emittedCount < serviceCount) { @@ -456,19 +597,17 @@ static KSTATUS validate_services(uint32_t serviceCount, } emitted[next] = true; - if (configOut->Services[next].StartPolicy == InitServiceStartAuto) + if (configOut->Services[next].StartPolicy != InitServiceStartDisabled) configOut->StartupOrder[configOut->StartupCount++] = (uint16_t)next; ++emittedCount; for (uint32_t i = 0; i < serviceCount; ++i) { if (emitted[i]) continue; INIT_SERVICE_DESCRIPTOR* descriptor = &configOut->Services[i]; - for (uint32_t d = 0; d < descriptor->DependencyCount; ++d) { - if (descriptor->Dependencies[d] == (uint16_t)next) { - --indegree[i]; - break; - } - } + for (uint32_t d = 0; d < descriptor->DependencyCount; ++d) + if (descriptor->Dependencies[d] == (uint16_t)next) --indegree[i]; + for (uint32_t d = 0; d < descriptor->AfterCount; ++d) + if (descriptor->After[d] == (uint16_t)next) --indegree[i]; } } @@ -532,6 +671,7 @@ KSTATUS InitLoadServiceConfig(SYS_HANDLE systemVolume, if (errorLineOut) *errorLineOut = 0; memset(gParsedServices, 0, sizeof(gParsedServices)); + memset(gSessionImage, 0, sizeof(gSessionImage)); size_t size = 0; KSTATUS status = read_services_ini(systemVolume, &size); if (!KSUCCESS(status)) return status; diff --git a/code/user/system/init/service_config.h b/code/user/system/init/service_config.h index 374397f..e743780 100644 --- a/code/user/system/init/service_config.h +++ b/code/user/system/init/service_config.h @@ -6,6 +6,7 @@ #include #include #include +#include #define INIT_SERVICES_PATH "system/services.ini" #define INIT_SERVICES_MAX_FILE_BYTES (64u * 1024u) @@ -18,24 +19,33 @@ typedef enum INIT_SERVICE_START_POLICY { InitServiceStartAuto = 0, + InitServiceStartDelayed, InitServiceStartDisabled, } INIT_SERVICE_START_POLICY; typedef enum INIT_SERVICE_RESTART_POLICY { InitServiceRestartNever = 0, InitServiceRestartOnFailure, + InitServiceRestartAlways, } INIT_SERVICE_RESTART_POLICY; typedef struct INIT_SERVICE_DESCRIPTOR { char Id[INIT_SERVICE_ID_MAX + 1u]; + char Name[64]; char ImagePath[SYS_PATH_MAX]; INIT_SERVICE_START_POLICY StartPolicy; bool Critical; INIT_SERVICE_RESTART_POLICY RestartPolicy; uint32_t ReadyTimeoutMilliseconds; uint32_t StopTimeoutMilliseconds; + uint32_t RestartLimit; + uint32_t RestartWindowMilliseconds; + uint32_t RestartDelayMilliseconds; + SYS_PRIVILEGES Privileges; uint32_t DependencyCount; uint16_t Dependencies[INIT_SERVICE_DEPENDENCY_MAX]; + uint32_t AfterCount; + uint16_t After[INIT_SERVICE_DEPENDENCY_MAX]; uint32_t GrantCount; char Grants[INIT_SERVICE_GRANT_MAX][INIT_SERVICE_GRANT_NAME_MAX + 1u]; uint32_t ExportCount; @@ -43,6 +53,7 @@ typedef struct INIT_SERVICE_DESCRIPTOR { } INIT_SERVICE_DESCRIPTOR; typedef struct INIT_SERVICE_CONFIG { + char SessionImage[SYS_PATH_MAX]; INIT_SERVICE_DESCRIPTOR Services[INIT_SERVICE_MAX_COUNT]; uint16_t StartupOrder[INIT_SERVICE_MAX_COUNT]; uint32_t ServiceCount; diff --git a/code/user/system/init/sources b/code/user/system/init/sources new file mode 100644 index 0000000..170fb16 --- /dev/null +++ b/code/user/system/init/sources @@ -0,0 +1,7 @@ +TARGETNAME=init +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall_s.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:_start +SOURCES=@/code/user/system/init/init.c @/code/user/system/init/service_config.c diff --git a/code/user/system/posixsrv/makefile b/code/user/system/posixsrv/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/system/posixsrv/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/system/posixsrv/posixsrv.c b/code/user/system/posixsrv/posixsrv.c index 3303057..3ee8d4b 100644 --- a/code/user/system/posixsrv/posixsrv.c +++ b/code/user/system/posixsrv/posixsrv.c @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/code/user/system/posixsrv/sources b/code/user/system/posixsrv/sources new file mode 100644 index 0000000..4fe92be --- /dev/null +++ b/code/user/system/posixsrv/sources @@ -0,0 +1,7 @@ +TARGETNAME=posixsrv +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall_s.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:_start +SOURCES=@/code/user/system/posixsrv/posixsrv.c diff --git a/code/user/system/rssrv/console.c b/code/user/system/rssrv/console.c index f584202..fd339c9 100644 --- a/code/user/system/rssrv/console.c +++ b/code/user/system/rssrv/console.c @@ -1,7 +1,7 @@ // RSSRV native console. One logical console owns text output policy and consumes RSSRV logical input. #include "rssrv_internal.h" -#include +#include #include #define RSSRV_EVENT_MANUAL_RESET 1u diff --git a/code/user/system/rssrv/input.c b/code/user/system/rssrv/input.c index 5e5bfbd..ce8652e 100644 --- a/code/user/system/rssrv/input.c +++ b/code/user/system/rssrv/input.c @@ -3,7 +3,7 @@ #include #include "rssrv_internal.h" #include -#include +#include #include #define RSSRV_EVENT_MANUAL_RESET 1u diff --git a/code/user/system/rssrv/makefile b/code/user/system/rssrv/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/system/rssrv/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/system/rssrv/namespace.c b/code/user/system/rssrv/namespace.c index d2d10fc..eff77a6 100644 --- a/code/user/system/rssrv/namespace.c +++ b/code/user/system/rssrv/namespace.c @@ -2,7 +2,7 @@ #include "rssrv_internal.h" #include -#include +#include #include typedef enum RSSRV_NODE_TYPE { diff --git a/code/user/system/rssrv/resource_service.c b/code/user/system/rssrv/resource_service.c index 18f9897..2b3883e 100644 --- a/code/user/system/rssrv/resource_service.c +++ b/code/user/system/rssrv/resource_service.c @@ -3,7 +3,7 @@ #include #include "rssrv_internal.h" #include "publication_scope.h" -#include +#include #include typedef struct RSSRV_SESSION { diff --git a/code/user/system/rssrv/sources b/code/user/system/rssrv/sources new file mode 100644 index 0000000..46460ff --- /dev/null +++ b/code/user/system/rssrv/sources @@ -0,0 +1,8 @@ +TARGETNAME=rssrv +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall_s.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:_start +SOURCES=@/code/user/system/rssrv/console.c @/code/user/system/rssrv/display.c @/code/user/system/rssrv/input.c @/code/user/system/rssrv/namespace.c @/code/user/system/rssrv/resource_service.c @/code/user/system/rssrv/rssrv.c \ + @/code/user/system/rssrv/session.c @/code/user/system/rssrv/volume.c diff --git a/code/user/system/rssrv/volume.c b/code/user/system/rssrv/volume.c index 572c220..cb6727a 100644 --- a/code/user/system/rssrv/volume.c +++ b/code/user/system/rssrv/volume.c @@ -2,7 +2,7 @@ #include #include "rssrv_internal.h" -#include +#include #include struct RSSRV_VOLUME_PUBLICATION { diff --git a/code/user/tests/all_tests/all_tests.c b/code/user/tests/all_tests/all_tests.c index 7a6c461..82e2376 100644 --- a/code/user/tests/all_tests/all_tests.c +++ b/code/user/tests/all_tests/all_tests.c @@ -14,13 +14,11 @@ typedef struct TEST_ENTRY { char Name[SYS_DIR_NAME_MAX]; } TEST_ENTRY; -// Writes one NUL-terminated string to the console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Writes one unsigned integer to the console. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -38,7 +36,6 @@ static void print_u64(uint64_t v) { } } -// Writes one signed integer to the console. static void print_i32(int32_t v) { if (v < 0) { print("-"); @@ -48,7 +45,6 @@ static void print_i32(int32_t v) { print_u64((uint32_t)v); } -// Writes one 32-bit value as hexadecimal. static void print_hex32(uint32_t v) { static const char hex[] = "0123456789abcdef"; for (int i = 7; i >= 0; i--) { @@ -294,7 +290,6 @@ static uint32_t run_test(const char* path, int32_t* exitCodeOut) { return NTLSTATUS_SUCCESS; } -// Program entry point. int main(void) { print("all_tests: start\n"); diff --git a/code/user/tests/all_tests/makefile b/code/user/tests/all_tests/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/all_tests/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/all_tests/sources b/code/user/tests/all_tests/sources new file mode 100644 index 0000000..7e40c95 --- /dev/null +++ b/code/user/tests/all_tests/sources @@ -0,0 +1,7 @@ +TARGETNAME=all_tests +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/all_tests/all_tests.c diff --git a/code/user/tests/anonymous_queue_smoke/anonymous_queue_smoke.c b/code/user/tests/anonymous_queue_smoke/anonymous_queue_smoke.c index 620a393..2c782ca 100644 --- a/code/user/tests/anonymous_queue_smoke/anonymous_queue_smoke.c +++ b/code/user/tests/anonymous_queue_smoke/anonymous_queue_smoke.c @@ -18,13 +18,11 @@ typedef char TEST_QUEUE_MESSAGE_SIZE_CHECK[ (sizeof(TEST_QUEUE_MESSAGE) == SYS_QUEUE_MESSAGE_SIZE) ? 1 : -1 ]; -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer to the kernel console. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -43,12 +41,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current test process. static void exit_now(int code) { while (true) SysExitProcess(code); } -// Fails the test with one plain message. static void fail(const char* msg) { print("anonymous_queue_smoke: "); print(msg); @@ -56,7 +52,6 @@ static void fail(const char* msg) { exit_now(1); } -// Fails the test with one status value. static void fail_status(const char* what, KSTATUS status) { print("anonymous_queue_smoke: "); print(what); diff --git a/code/user/tests/anonymous_queue_smoke/makefile b/code/user/tests/anonymous_queue_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/anonymous_queue_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/anonymous_queue_smoke/sources b/code/user/tests/anonymous_queue_smoke/sources new file mode 100644 index 0000000..2116cec --- /dev/null +++ b/code/user/tests/anonymous_queue_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=anonymous_queue_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/anonymous_queue_smoke/anonymous_queue_smoke.c diff --git a/code/user/tests/apc_return_smoke/apc_return_smoke.c b/code/user/tests/apc_return_smoke/apc_return_smoke.c index 3baa615..551a6ea 100644 --- a/code/user/tests/apc_return_smoke/apc_return_smoke.c +++ b/code/user/tests/apc_return_smoke/apc_return_smoke.c @@ -72,7 +72,6 @@ typedef struct DIRECT_APC_STATE { volatile uint32_t ArgumentsValid; } DIRECT_APC_STATE; -// Records one directly queued generic user APC. static void direct_apc(void* context, void* argument1, void* argument2) { DIRECT_APC_STATE* state = (DIRECT_APC_STATE*)context; if (!state) return; diff --git a/code/user/tests/apc_return_smoke/makefile b/code/user/tests/apc_return_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/apc_return_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/apc_return_smoke/sources b/code/user/tests/apc_return_smoke/sources new file mode 100644 index 0000000..2fb731d --- /dev/null +++ b/code/user/tests/apc_return_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=apc_return_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/apc_return_smoke/apc_return_smoke.c diff --git a/code/user/tests/async_apc/makefile b/code/user/tests/async_apc/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/async_apc/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/async_apc/sources b/code/user/tests/async_apc/sources new file mode 100644 index 0000000..1c2af4d --- /dev/null +++ b/code/user/tests/async_apc/sources @@ -0,0 +1,7 @@ +TARGETNAME=async_apc +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/async_apc/async_apc.c diff --git a/code/user/tests/async_cancel/makefile b/code/user/tests/async_cancel/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/async_cancel/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/async_cancel/sources b/code/user/tests/async_cancel/sources new file mode 100644 index 0000000..a46ba25 --- /dev/null +++ b/code/user/tests/async_cancel/sources @@ -0,0 +1,7 @@ +TARGETNAME=async_cancel +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/async_cancel/async_cancel.c diff --git a/code/user/tests/audio_stream_smoke/audio_stream_smoke.c b/code/user/tests/audio_stream_smoke/audio_stream_smoke.c index d9a0d56..9d4bcf6 100644 --- a/code/user/tests/audio_stream_smoke/audio_stream_smoke.c +++ b/code/user/tests/audio_stream_smoke/audio_stream_smoke.c @@ -32,7 +32,6 @@ typedef char TEST_AUDIO_STREAM_INFO_SIZE[(sizeof(SYS_AUDIO_STREAM_INFO) == 128) typedef char TEST_AUDIO_VOLUME_REQUEST_SIZE[(sizeof(SYS_AUDIO_SET_VOLUME_REQUEST) == 24) ? 1 : -1]; typedef char TEST_AUDIO_MASTER_VOLUME_REQUEST_SIZE[(sizeof(SYS_AUDIO_SET_MASTER_VOLUME_REQUEST) == 20) ? 1 : -1]; -// Writes one NUL-terminated string to the console. static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); @@ -45,7 +44,6 @@ static void trace_stage(const char* message) { print(message); } -// Writes one unsigned integer to the console. static void print_u64(uint64_t value) { char digits[32]; uint32_t count = 0; @@ -73,13 +71,11 @@ static void cleanup_stream(void) { gOpenStream = 0; } -// Terminates the test process. static void exit_now(int32_t code) { cleanup_stream(); while (true) (void)SysExitProcess(code); } -// Fails the test with one status value. static void fail_status(const char* operation, KSTATUS status) { print("audio_stream_smoke: "); print(operation); @@ -89,7 +85,6 @@ static void fail_status(const char* operation, KSTATUS status) { exit_now(1); } -// Fails the test with one plain diagnostic. static void fail(const char* message) { print("audio_stream_smoke: "); print(message); @@ -307,7 +302,6 @@ static uint32_t open_stream(uint32_t endpointId) { NTLSTATUS_SUCCESS); } -// Writes one sample run and returns the accepted frame count. static uint32_t write_samples(uint32_t stream, const int16_t* frames, uint32_t frameCount, @@ -327,7 +321,6 @@ static uint32_t write_samples(uint32_t stream, return written; } -// Writes one contract-tone range and returns the accepted frame count. static uint32_t write_frames(uint32_t stream, uint32_t frameOffset, uint32_t frameCount, diff --git a/code/user/tests/audio_stream_smoke/makefile b/code/user/tests/audio_stream_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/audio_stream_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/audio_stream_smoke/sources b/code/user/tests/audio_stream_smoke/sources new file mode 100644 index 0000000..9d954fa --- /dev/null +++ b/code/user/tests/audio_stream_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=audio_stream_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/audio_stream_smoke/audio_stream_smoke.c diff --git a/code/user/tests/console_service_smoke/console_service_smoke.c b/code/user/tests/console_service_smoke/console_service_smoke.c index d2905a3..64c3d6b 100644 --- a/code/user/tests/console_service_smoke/console_service_smoke.c +++ b/code/user/tests/console_service_smoke/console_service_smoke.c @@ -10,13 +10,11 @@ static void exit_test(int code) { for (;;) SysExitProcess(code); } -// Writes one diagnostic string through the transitional native console. static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(request), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); } -// Writes one status value in hexadecimal without a formatting runtime. static void print_status(KSTATUS status) { static const char digits[] = "0123456789ABCDEF"; char buffer[11] = "0x00000000"; diff --git a/code/user/tests/console_service_smoke/makefile b/code/user/tests/console_service_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/console_service_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/console_service_smoke/sources b/code/user/tests/console_service_smoke/sources new file mode 100644 index 0000000..a93b453 --- /dev/null +++ b/code/user/tests/console_service_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=console_service_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/console_service_smoke/console_service_smoke.c diff --git a/code/user/tests/cwd_userspace_smoke/makefile b/code/user/tests/cwd_userspace_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/cwd_userspace_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/cwd_userspace_smoke/sources b/code/user/tests/cwd_userspace_smoke/sources new file mode 100644 index 0000000..2972a05 --- /dev/null +++ b/code/user/tests/cwd_userspace_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=cwd_userspace_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/cwd_userspace_smoke/cwd_userspace_smoke.c diff --git a/code/user/tests/desktop_smoke/desktop_smoke.c b/code/user/tests/desktop_smoke/desktop_smoke.c index 970ccfc..a1bba8f 100644 --- a/code/user/tests/desktop_smoke/desktop_smoke.c +++ b/code/user/tests/desktop_smoke/desktop_smoke.c @@ -14,13 +14,11 @@ static void exit_now(int code) { while (true) SysExitProcess(code); } -// Writes one diagnostic string through the transitional native console. static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(request), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); } -// Writes one status value in hexadecimal without a formatting runtime. static void print_status(KSTATUS status) { static const char digits[] = "0123456789ABCDEF"; char buffer[11] = "0x00000000"; diff --git a/code/user/tests/desktop_smoke/makefile b/code/user/tests/desktop_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/desktop_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/desktop_smoke/sources b/code/user/tests/desktop_smoke/sources new file mode 100644 index 0000000..ededa08 --- /dev/null +++ b/code/user/tests/desktop_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=desktop_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/desktop_smoke/desktop_smoke.c diff --git a/code/user/tests/dirs b/code/user/tests/dirs new file mode 100644 index 0000000..9e441fc --- /dev/null +++ b/code/user/tests/dirs @@ -0,0 +1 @@ +DIRS=all_tests anonymous_queue_smoke apc_return_smoke async_apc async_cancel audio_stream_smoke console_service_smoke cwd_userspace_smoke desktop_smoke dirty_writeback exception_dispatcher_smoke exception_smoke file_lock_smoke file_stat_smoke handle_dup_smoke input_service_smoke mmap_smoke module_load_smoke native_exception_runtime_smoke native_raise_exception_smoke net_irp_smoke pcache_invalidate pcache_mmap_read_reuse pcache_multithread pcache_pressure pcache_smoke port_ipc_smoke posix_fd_smoke posix_module_smoke posix_pipe_smoke posix_process_smoke posix_runtime_smoke posix_service_smoke posix_signal_smoke process_builder_smoke process_exit_multithread_smoke process_protection_smoke realpath_smoke resource_service_smoke security_smoke shared_mmap socket_addr_smoke stats_abi_smoke surface_cross_process_smoke surface_invalid_rect surface_multithread_commit surface_smoke syscall_contract_smoke thread_name_smoke timer_smoke win32_condition_variable_smoke win32_exception_smoke win32_module_lookup_smoke win32_mutex_smoke win32_seh_smoke win32_thread_suspend_smoke winmm_waveout_smoke would_block_smoke diff --git a/code/user/tests/dirty_writeback/makefile b/code/user/tests/dirty_writeback/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/dirty_writeback/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/dirty_writeback/sources b/code/user/tests/dirty_writeback/sources new file mode 100644 index 0000000..edd7f90 --- /dev/null +++ b/code/user/tests/dirty_writeback/sources @@ -0,0 +1,7 @@ +TARGETNAME=dirty_writeback +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/dirty_writeback/dirty_writeback.c diff --git a/code/user/tests/exception_dispatcher_smoke/exception_dispatcher_smoke.c b/code/user/tests/exception_dispatcher_smoke/exception_dispatcher_smoke.c index 5ed134e..1df6df7 100644 --- a/code/user/tests/exception_dispatcher_smoke/exception_dispatcher_smoke.c +++ b/code/user/tests/exception_dispatcher_smoke/exception_dispatcher_smoke.c @@ -6,13 +6,11 @@ #include #include -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -31,12 +29,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current process. static void exit_now(int32_t code) { while (true) SysExitProcess(code); } -// Fails the test with one message. static void fail(const char* message) { print("exception_dispatcher_smoke: "); print(message); @@ -44,7 +40,6 @@ static void fail(const char* message) { exit_now(1); } -// Fails the test with one status value. static void fail_status(const char* what, KSTATUS status) { print("exception_dispatcher_smoke: "); print(what); diff --git a/code/user/tests/exception_dispatcher_smoke/makefile b/code/user/tests/exception_dispatcher_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/exception_dispatcher_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/exception_dispatcher_smoke/sources b/code/user/tests/exception_dispatcher_smoke/sources new file mode 100644 index 0000000..4cdb908 --- /dev/null +++ b/code/user/tests/exception_dispatcher_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=exception_dispatcher_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/exception_dispatcher_smoke/exception_dispatcher_smoke.c diff --git a/code/user/tests/exception_smoke/exception_smoke.c b/code/user/tests/exception_smoke/exception_smoke.c index ae03b4b..f95cebb 100644 --- a/code/user/tests/exception_smoke/exception_smoke.c +++ b/code/user/tests/exception_smoke/exception_smoke.c @@ -15,13 +15,11 @@ #define CHILD_NONCONTINUABLE "child-noncontinuable" #define SMOKE_NONCONTINUABLE_CODE 0xE1111003u -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -40,12 +38,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current process. static void exit_now(int32_t code) { while (true) SysExitProcess(code); } -// Fails the test with one message. static void fail(const char* message) { print("exception_smoke: "); print(message); @@ -53,7 +49,6 @@ static void fail(const char* message) { exit_now(1); } -// Fails the test with one status value. static void fail_status(const char* what, KSTATUS status) { print("exception_smoke: "); print(what); diff --git a/code/user/tests/exception_smoke/makefile b/code/user/tests/exception_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/exception_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/exception_smoke/sources b/code/user/tests/exception_smoke/sources new file mode 100644 index 0000000..11786d6 --- /dev/null +++ b/code/user/tests/exception_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=exception_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/exception_smoke/exception_smoke.c diff --git a/code/user/tests/file_lock_smoke/file_lock_smoke.c b/code/user/tests/file_lock_smoke/file_lock_smoke.c index 4dc85d1..c65cbab 100644 --- a/code/user/tests/file_lock_smoke/file_lock_smoke.c +++ b/code/user/tests/file_lock_smoke/file_lock_smoke.c @@ -15,13 +15,11 @@ #define CHILD_PREFIX_MAX 32u #define CHILD_PATH_MAX 256u -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer to the kernel console. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -40,12 +38,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current test process. static void exit_now(int32_t code) { while (true) SysExitProcess(code); } -// Fails the test with one status value. static void fail_status(const char* what, KSTATUS status) { print("file_lock_smoke: "); print(what); @@ -55,7 +51,6 @@ static void fail_status(const char* what, KSTATUS status) { exit_now(1); } -// Fails the test with one plain message. static void fail(const char* what) { print("file_lock_smoke: "); print(what); @@ -333,7 +328,6 @@ static void test_validation(uint32_t file) { if (s != NTLSTATUS_INVALID_HANDLE) fail_status("bad lock handle", s); } -// Program entry point. int main(void) { SYS_PEB* peb = SysGetPeb(); if (peb && peb->CommandLine.Data && peb->CommandLine.Length != 0) { diff --git a/code/user/tests/file_lock_smoke/makefile b/code/user/tests/file_lock_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/file_lock_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/file_lock_smoke/sources b/code/user/tests/file_lock_smoke/sources new file mode 100644 index 0000000..3bd67f8 --- /dev/null +++ b/code/user/tests/file_lock_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=file_lock_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/file_lock_smoke/file_lock_smoke.c diff --git a/code/user/tests/file_stat_smoke/file_stat_smoke.c b/code/user/tests/file_stat_smoke/file_stat_smoke.c index aeaa512..6175fb2 100644 --- a/code/user/tests/file_stat_smoke/file_stat_smoke.c +++ b/code/user/tests/file_stat_smoke/file_stat_smoke.c @@ -11,13 +11,11 @@ static char gSelfPath[SYS_PATH_MAX]; static char gSelfDir[SYS_PATH_MAX]; -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer to the kernel console. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -36,12 +34,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current test process. static void exit_now(int code) { while (true) SysExitProcess(code); } -// Fails the test with one plain message. static void fail(const char* msg) { print("file_stat_smoke: "); print(msg); @@ -49,7 +45,6 @@ static void fail(const char* msg) { exit_now(1); } -// Fails the test with one status value. static void fail_status(const char* what, KSTATUS status) { print("file_stat_smoke: "); print(what); diff --git a/code/user/tests/file_stat_smoke/makefile b/code/user/tests/file_stat_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/file_stat_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/file_stat_smoke/sources b/code/user/tests/file_stat_smoke/sources new file mode 100644 index 0000000..92103e0 --- /dev/null +++ b/code/user/tests/file_stat_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=file_stat_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/file_stat_smoke/file_stat_smoke.c diff --git a/code/user/tests/handle_dup_smoke/handle_dup_smoke.c b/code/user/tests/handle_dup_smoke/handle_dup_smoke.c index 98aa3ff..e50d7f8 100644 --- a/code/user/tests/handle_dup_smoke/handle_dup_smoke.c +++ b/code/user/tests/handle_dup_smoke/handle_dup_smoke.c @@ -19,13 +19,11 @@ typedef char TEST_QUEUE_MESSAGE_SIZE_CHECK[ (sizeof(TEST_QUEUE_MESSAGE) == SYS_QUEUE_MESSAGE_SIZE) ? 1 : -1 ]; -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer to the kernel console. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -44,12 +42,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current test process. static void exit_now(int code) { while (true) SysExitProcess(code); } -// Fails the test with one plain message. static void fail(const char* msg) { print("handle_dup_smoke: "); print(msg); @@ -57,7 +53,6 @@ static void fail(const char* msg) { exit_now(1); } -// Fails the test with one status value. static void fail_status(const char* what, KSTATUS status) { print("handle_dup_smoke: "); print(what); diff --git a/code/user/tests/handle_dup_smoke/makefile b/code/user/tests/handle_dup_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/handle_dup_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/handle_dup_smoke/sources b/code/user/tests/handle_dup_smoke/sources new file mode 100644 index 0000000..24bceab --- /dev/null +++ b/code/user/tests/handle_dup_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=handle_dup_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/handle_dup_smoke/handle_dup_smoke.c diff --git a/code/user/tests/input_api_smoke/input_api_smoke.c b/code/user/tests/input_api_smoke/input_api_smoke.c index 374bf4f..c236829 100644 --- a/code/user/tests/input_api_smoke/input_api_smoke.c +++ b/code/user/tests/input_api_smoke/input_api_smoke.c @@ -5,13 +5,11 @@ #include #include -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer to the kernel console. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -30,12 +28,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current test process. static void exit_now(int code) { while (true) SysExitProcess(code); } -// Fails the test with one status value. static void fail_status(const char* what, uint32_t status) { print("input_api_smoke: "); print(what); @@ -58,7 +54,6 @@ static void expect_status(const char* what, uint32_t got, uint32_t expected) { exit_now(1); } -// Program entry point. int main(void) { print("input_api_smoke: start\n"); diff --git a/code/user/tests/input_model_smoke/input_model_smoke.c b/code/user/tests/input_model_smoke/input_model_smoke.c index ec46fb2..9f5b392 100644 --- a/code/user/tests/input_model_smoke/input_model_smoke.c +++ b/code/user/tests/input_model_smoke/input_model_smoke.c @@ -4,13 +4,11 @@ #include #include -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer to the kernel console. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -29,12 +27,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current test process. static void exit_now(int code) { while (true) SysExitProcess(code); } -// Fails the test with one status value. static void fail_status(const char* what, uint32_t status) { print("input_model_smoke: "); print(what); @@ -57,7 +53,6 @@ static void expect_status(const char* what, uint32_t got, uint32_t expected) { exit_now(1); } -// Program entry point. int main(void) { print("input_model_smoke: start\n"); diff --git a/code/user/tests/input_service_smoke/input_service_smoke.c b/code/user/tests/input_service_smoke/input_service_smoke.c index 7183143..e3e1a89 100644 --- a/code/user/tests/input_service_smoke/input_service_smoke.c +++ b/code/user/tests/input_service_smoke/input_service_smoke.c @@ -8,13 +8,11 @@ static int gFailures; -// Writes one diagnostic line fragment. static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(request), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); } -// Records one failed expectation. static void fail(const char* text) { print("input_service_smoke: FAIL: "); print(text); diff --git a/code/user/tests/input_service_smoke/makefile b/code/user/tests/input_service_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/input_service_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/input_service_smoke/sources b/code/user/tests/input_service_smoke/sources new file mode 100644 index 0000000..84491c2 --- /dev/null +++ b/code/user/tests/input_service_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=input_service_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/input_service_smoke/input_service_smoke.c diff --git a/code/user/tests/mmap_smoke/makefile b/code/user/tests/mmap_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/mmap_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/mmap_smoke/sources b/code/user/tests/mmap_smoke/sources new file mode 100644 index 0000000..9bc06e4 --- /dev/null +++ b/code/user/tests/mmap_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=mmap_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/mmap_smoke/mmap_smoke.c diff --git a/code/user/tests/module_load_smoke/makefile b/code/user/tests/module_load_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/module_load_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/module_load_smoke/sources b/code/user/tests/module_load_smoke/sources new file mode 100644 index 0000000..1c4bce2 --- /dev/null +++ b/code/user/tests/module_load_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=module_load_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/module_load_smoke/module_load_smoke.c diff --git a/code/user/tests/named_queue_lifetime_smoke/named_queue_lifetime_smoke.c b/code/user/tests/named_queue_lifetime_smoke/named_queue_lifetime_smoke.c index d03668e..55207e7 100644 --- a/code/user/tests/named_queue_lifetime_smoke/named_queue_lifetime_smoke.c +++ b/code/user/tests/named_queue_lifetime_smoke/named_queue_lifetime_smoke.c @@ -18,13 +18,11 @@ typedef char TEST_QUEUE_MESSAGE_SIZE_CHECK[ (sizeof(TEST_QUEUE_MESSAGE) == SYS_QUEUE_MESSAGE_SIZE) ? 1 : -1 ]; -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer to the kernel console. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -43,12 +41,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current test process. static void exit_now(int code) { while (true) SysExitProcess(code); } -// Fails the test with one plain message. static void fail(const char* msg) { print("named_queue_lifetime_smoke: "); print(msg); @@ -56,7 +52,6 @@ static void fail(const char* msg) { exit_now(1); } -// Fails the test with one status value. static void fail_status(const char* what, uint32_t status) { print("named_queue_lifetime_smoke: "); print(what); diff --git a/code/user/tests/native_exception_runtime_smoke/makefile b/code/user/tests/native_exception_runtime_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/native_exception_runtime_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/native_exception_runtime_smoke/native_exception_runtime_smoke.c b/code/user/tests/native_exception_runtime_smoke/native_exception_runtime_smoke.c index 02f77c7..d660e46 100644 --- a/code/user/tests/native_exception_runtime_smoke/native_exception_runtime_smoke.c +++ b/code/user/tests/native_exception_runtime_smoke/native_exception_runtime_smoke.c @@ -9,13 +9,11 @@ static volatile uint32_t gSearchHits; static volatile uint32_t gContinueHits; -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -34,12 +32,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current process. static void exit_now(int32_t code) { while (true) SysExitProcess(code); } -// Fails the test with one message. static void fail(const char* message) { print("native_exception_runtime_smoke: "); print(message); @@ -47,7 +43,6 @@ static void fail(const char* message) { exit_now(1); } -// Fails the test with one status value. static void fail_status(const char* what, KSTATUS status) { print("native_exception_runtime_smoke: "); print(what); diff --git a/code/user/tests/native_exception_runtime_smoke/sources b/code/user/tests/native_exception_runtime_smoke/sources new file mode 100644 index 0000000..5b30ed8 --- /dev/null +++ b/code/user/tests/native_exception_runtime_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=native_exception_runtime_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/native_exception_runtime_smoke/native_exception_runtime_smoke.c diff --git a/code/user/tests/native_raise_exception_smoke/makefile b/code/user/tests/native_raise_exception_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/native_raise_exception_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/native_raise_exception_smoke/native_raise_exception_smoke.c b/code/user/tests/native_raise_exception_smoke/native_raise_exception_smoke.c index 898a710..816dee7 100644 --- a/code/user/tests/native_raise_exception_smoke/native_raise_exception_smoke.c +++ b/code/user/tests/native_raise_exception_smoke/native_raise_exception_smoke.c @@ -10,13 +10,11 @@ static volatile uint32_t gHandlerHits; -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -35,12 +33,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current process. static void exit_now(int32_t code) { while (true) SysExitProcess(code); } -// Fails the test with one message. static void fail(const char* message) { print("native_raise_exception_smoke: "); print(message); @@ -48,7 +44,6 @@ static void fail(const char* message) { exit_now(1); } -// Fails the test with one status value. static void fail_status(const char* what, KSTATUS status) { print("native_raise_exception_smoke: "); print(what); diff --git a/code/user/tests/native_raise_exception_smoke/sources b/code/user/tests/native_raise_exception_smoke/sources new file mode 100644 index 0000000..3ffdf89 --- /dev/null +++ b/code/user/tests/native_raise_exception_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=native_raise_exception_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/native_raise_exception_smoke/native_raise_exception_smoke.c diff --git a/code/user/tests/net_irp_smoke/makefile b/code/user/tests/net_irp_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/net_irp_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/net_irp_smoke/net_irp_smoke.c b/code/user/tests/net_irp_smoke/net_irp_smoke.c index 14deffc..177f285 100644 --- a/code/user/tests/net_irp_smoke/net_irp_smoke.c +++ b/code/user/tests/net_irp_smoke/net_irp_smoke.c @@ -9,13 +9,11 @@ #define NET_IRP_SMOKE_UDP_PORT 40219u #define NET_IRP_SMOKE_HTTP_PORT 80u -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer to the kernel console. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -34,12 +32,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current process. static void exit_now(int32_t code) { while (true) SysExitProcess(code); } -// Fails the test with one message. static void fail(const char* message) { print("net_irp_smoke: "); print(message); @@ -47,7 +43,6 @@ static void fail(const char* message) { exit_now(1); } -// Fails the test with one status value. static void fail_status(const char* what, KSTATUS status) { print("net_irp_smoke: "); print(what); diff --git a/code/user/tests/net_irp_smoke/sources b/code/user/tests/net_irp_smoke/sources new file mode 100644 index 0000000..36d9133 --- /dev/null +++ b/code/user/tests/net_irp_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=net_irp_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/net_irp_smoke/net_irp_smoke.c diff --git a/code/user/tests/pcache_invalidate/makefile b/code/user/tests/pcache_invalidate/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/pcache_invalidate/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/pcache_invalidate/sources b/code/user/tests/pcache_invalidate/sources new file mode 100644 index 0000000..25075cc --- /dev/null +++ b/code/user/tests/pcache_invalidate/sources @@ -0,0 +1,7 @@ +TARGETNAME=pcache_invalidate +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/pcache_invalidate/pcache_invalidate.c diff --git a/code/user/tests/pcache_mmap_read_reuse/makefile b/code/user/tests/pcache_mmap_read_reuse/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/pcache_mmap_read_reuse/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/pcache_mmap_read_reuse/sources b/code/user/tests/pcache_mmap_read_reuse/sources new file mode 100644 index 0000000..3e6fd53 --- /dev/null +++ b/code/user/tests/pcache_mmap_read_reuse/sources @@ -0,0 +1,7 @@ +TARGETNAME=pcache_mmap_read_reuse +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/pcache_mmap_read_reuse/pcache_mmap_read_reuse.c diff --git a/code/user/tests/pcache_multithread/makefile b/code/user/tests/pcache_multithread/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/pcache_multithread/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/pcache_multithread/sources b/code/user/tests/pcache_multithread/sources new file mode 100644 index 0000000..c7b641b --- /dev/null +++ b/code/user/tests/pcache_multithread/sources @@ -0,0 +1,7 @@ +TARGETNAME=pcache_multithread +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/pcache_multithread/pcache_multithread.c diff --git a/code/user/tests/pcache_pressure/makefile b/code/user/tests/pcache_pressure/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/pcache_pressure/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/pcache_pressure/sources b/code/user/tests/pcache_pressure/sources new file mode 100644 index 0000000..1e2822a --- /dev/null +++ b/code/user/tests/pcache_pressure/sources @@ -0,0 +1,7 @@ +TARGETNAME=pcache_pressure +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/pcache_pressure/pcache_pressure.c diff --git a/code/user/tests/pcache_smoke/makefile b/code/user/tests/pcache_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/pcache_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/pcache_smoke/sources b/code/user/tests/pcache_smoke/sources new file mode 100644 index 0000000..540964b --- /dev/null +++ b/code/user/tests/pcache_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=pcache_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/pcache_smoke/pcache_smoke.c diff --git a/code/user/tests/port_ipc_smoke/makefile b/code/user/tests/port_ipc_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/port_ipc_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/port_ipc_smoke/port_ipc_smoke.c b/code/user/tests/port_ipc_smoke/port_ipc_smoke.c index 0756698..149bb31 100644 --- a/code/user/tests/port_ipc_smoke/port_ipc_smoke.c +++ b/code/user/tests/port_ipc_smoke/port_ipc_smoke.c @@ -11,13 +11,11 @@ #define EVENT_AUTO_RESET 0u #define TEST_TIMEOUT_MS 2000u -// Writes one string to the console. static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(request), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); } -// Writes one unsigned integer without requiring formatted libc helpers. static void print_u32(uint32_t value) { char digits[16]; uint32_t count = 0; diff --git a/code/user/tests/port_ipc_smoke/sources b/code/user/tests/port_ipc_smoke/sources new file mode 100644 index 0000000..16c8bda --- /dev/null +++ b/code/user/tests/port_ipc_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=port_ipc_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/port_ipc_smoke/port_ipc_smoke.c diff --git a/code/user/tests/posix_fd_smoke/makefile b/code/user/tests/posix_fd_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/posix_fd_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/posix_fd_smoke/posix_fd_smoke.c b/code/user/tests/posix_fd_smoke/posix_fd_smoke.c index 41d4dd1..3b02257 100644 --- a/code/user/tests/posix_fd_smoke/posix_fd_smoke.c +++ b/code/user/tests/posix_fd_smoke/posix_fd_smoke.c @@ -12,7 +12,6 @@ #include #include -// Writes one NUL-terminated diagnostic to stdout. static void print(const char* text) { (void)write(1, text, strlen(text)); } @@ -25,7 +24,6 @@ static void fail(const char* message) { exit(1); } -// Prints one decimal integer without depending on stdio. static void print_int(int value) { char buffer[16]; unsigned int magnitude = value < 0 ? (unsigned int)(-(value + 1)) + 1u : (unsigned int)value; diff --git a/code/user/tests/posix_fd_smoke/sources b/code/user/tests/posix_fd_smoke/sources new file mode 100644 index 0000000..2e55419 --- /dev/null +++ b/code/user/tests/posix_fd_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=posix_fd_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=POSIX +TARGETLIBS="$(BASEDIR)\bin\posix.lib" "$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\posix_start.lib" +EXTRA_LFLAGS=/ENTRY:PosixStart +SOURCES=@/code/user/tests/posix_fd_smoke/posix_fd_smoke.c diff --git a/code/user/tests/posix_module_smoke/makefile b/code/user/tests/posix_module_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/posix_module_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/posix_module_smoke/posix_module_smoke.c b/code/user/tests/posix_module_smoke/posix_module_smoke.c index 8c15708..4db797e 100644 --- a/code/user/tests/posix_module_smoke/posix_module_smoke.c +++ b/code/user/tests/posix_module_smoke/posix_module_smoke.c @@ -8,17 +8,14 @@ #include #include -// Writes one NUL-terminated string to stdout. static void print(const char* s) { write(1, s, strlen(s)); } -// Terminates the current process. static void exit_now(int code) { while (true) exit(code); } -// Fails the smoke test with one message. static void fail(const char* message) { print("posix_module_smoke: "); print(message); diff --git a/code/user/tests/posix_module_smoke/sources b/code/user/tests/posix_module_smoke/sources new file mode 100644 index 0000000..4b22bdf --- /dev/null +++ b/code/user/tests/posix_module_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=posix_module_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=POSIX +TARGETLIBS="$(BASEDIR)\bin\posix.lib" "$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\posix_start.lib" +EXTRA_LFLAGS=/ENTRY:PosixStart +SOURCES=@/code/user/tests/posix_module_smoke/posix_module_smoke.c diff --git a/code/user/tests/posix_pipe_smoke/makefile b/code/user/tests/posix_pipe_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/posix_pipe_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/posix_pipe_smoke/posix_pipe_smoke.c b/code/user/tests/posix_pipe_smoke/posix_pipe_smoke.c index 5361fa8..8d2baaa 100644 --- a/code/user/tests/posix_pipe_smoke/posix_pipe_smoke.c +++ b/code/user/tests/posix_pipe_smoke/posix_pipe_smoke.c @@ -9,7 +9,6 @@ #include #include -// Writes one NUL-terminated diagnostic to stdout. static void print(const char* text) { (void)write(1, text, strlen(text)); } diff --git a/code/user/tests/posix_pipe_smoke/sources b/code/user/tests/posix_pipe_smoke/sources new file mode 100644 index 0000000..cdb4da7 --- /dev/null +++ b/code/user/tests/posix_pipe_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=posix_pipe_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=POSIX +TARGETLIBS="$(BASEDIR)\bin\posix.lib" "$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\posix_start.lib" +EXTRA_LFLAGS=/ENTRY:PosixStart +SOURCES=@/code/user/tests/posix_pipe_smoke/posix_pipe_smoke.c diff --git a/code/user/tests/posix_process_smoke/makefile b/code/user/tests/posix_process_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/posix_process_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/posix_process_smoke/posix_process_smoke.c b/code/user/tests/posix_process_smoke/posix_process_smoke.c index 8660bb1..d2fc114 100644 --- a/code/user/tests/posix_process_smoke/posix_process_smoke.c +++ b/code/user/tests/posix_process_smoke/posix_process_smoke.c @@ -27,7 +27,6 @@ static const char* gExecFile = "posix_process_exec.tmp"; static volatile uint32_t gVforkChildTouched; -// Writes one NUL-terminated diagnostic to stdout. static void print(const char* text) { (void)write(1, text, strlen(text)); } diff --git a/code/user/tests/posix_process_smoke/sources b/code/user/tests/posix_process_smoke/sources new file mode 100644 index 0000000..1b77da1 --- /dev/null +++ b/code/user/tests/posix_process_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=posix_process_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=POSIX +TARGETLIBS="$(BASEDIR)\bin\posix.lib" "$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\posix_start.lib" +EXTRA_LFLAGS=/ENTRY:PosixStart +SOURCES=@/code/user/tests/posix_process_smoke/posix_process_smoke.c diff --git a/code/user/tests/posix_runtime_smoke/makefile b/code/user/tests/posix_runtime_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/posix_runtime_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/posix_runtime_smoke/posix_runtime_smoke.c b/code/user/tests/posix_runtime_smoke/posix_runtime_smoke.c index 7512e35..5f8d2e8 100644 --- a/code/user/tests/posix_runtime_smoke/posix_runtime_smoke.c +++ b/code/user/tests/posix_runtime_smoke/posix_runtime_smoke.c @@ -16,7 +16,6 @@ static volatile uintptr_t gWorkerErrnoAddress; static volatile int gWorkerDlErrorOk; static volatile pid_t gWorkerPid; -// Writes one NUL-terminated string to stdout. static void print(const char* text) { (void)write(1, text, strlen(text)); } diff --git a/code/user/tests/posix_runtime_smoke/sources b/code/user/tests/posix_runtime_smoke/sources new file mode 100644 index 0000000..08320ec --- /dev/null +++ b/code/user/tests/posix_runtime_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=posix_runtime_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=POSIX +TARGETLIBS="$(BASEDIR)\bin\posix.lib" "$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\posix_start.lib" +EXTRA_LFLAGS=/ENTRY:PosixStart +SOURCES=@/code/user/tests/posix_runtime_smoke/posix_runtime_smoke.c diff --git a/code/user/tests/posix_service_smoke/makefile b/code/user/tests/posix_service_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/posix_service_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/posix_service_smoke/posix_service_smoke.c b/code/user/tests/posix_service_smoke/posix_service_smoke.c index a7a9f1b..d185db5 100644 --- a/code/user/tests/posix_service_smoke/posix_service_smoke.c +++ b/code/user/tests/posix_service_smoke/posix_service_smoke.c @@ -13,7 +13,6 @@ #define CHILD_ARGUMENT "--pid-child" -// Writes one test diagnostic through the native console. static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(request), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); diff --git a/code/user/tests/posix_service_smoke/sources b/code/user/tests/posix_service_smoke/sources new file mode 100644 index 0000000..a39656f --- /dev/null +++ b/code/user/tests/posix_service_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=posix_service_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/posix_service_smoke/posix_service_smoke.c diff --git a/code/user/tests/posix_signal_smoke/makefile b/code/user/tests/posix_signal_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/posix_signal_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/posix_signal_smoke/posix_signal_smoke.c b/code/user/tests/posix_signal_smoke/posix_signal_smoke.c index 88fd661..1f0ca4a 100644 --- a/code/user/tests/posix_signal_smoke/posix_signal_smoke.c +++ b/code/user/tests/posix_signal_smoke/posix_signal_smoke.c @@ -25,7 +25,6 @@ static volatile sig_atomic_t gNestedCount; static volatile sig_atomic_t gAlarmCount; static volatile sig_atomic_t gPipeCount; -// Writes one test diagnostic line to the native console. static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(request), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); @@ -82,7 +81,6 @@ static void nested_handler(int signalNumber) { _exit(91); } -// Records one SIGALRM used to interrupt alertable POSIX waits. static void alarm_handler(int signalNumber) { if (signalNumber == SIGALRM) ++gAlarmCount; } diff --git a/code/user/tests/posix_signal_smoke/sources b/code/user/tests/posix_signal_smoke/sources new file mode 100644 index 0000000..8681403 --- /dev/null +++ b/code/user/tests/posix_signal_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=posix_signal_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=POSIX +TARGETLIBS="$(BASEDIR)\bin\posix.lib" "$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\posix_start.lib" +EXTRA_LFLAGS=/ENTRY:PosixStart +SOURCES=@/code/user/tests/posix_signal_smoke/posix_signal_smoke.c diff --git a/code/user/tests/process_builder_smoke/makefile b/code/user/tests/process_builder_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/process_builder_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/process_builder_smoke/sources b/code/user/tests/process_builder_smoke/sources new file mode 100644 index 0000000..b6d8715 --- /dev/null +++ b/code/user/tests/process_builder_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=process_builder_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/process_builder_smoke/process_builder_smoke.c diff --git a/code/user/tests/process_exit_multithread_smoke/makefile b/code/user/tests/process_exit_multithread_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/process_exit_multithread_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/process_exit_multithread_smoke/process_exit_multithread_smoke.c b/code/user/tests/process_exit_multithread_smoke/process_exit_multithread_smoke.c index 3e51a75..d8b92b5 100644 --- a/code/user/tests/process_exit_multithread_smoke/process_exit_multithread_smoke.c +++ b/code/user/tests/process_exit_multithread_smoke/process_exit_multithread_smoke.c @@ -19,13 +19,11 @@ typedef struct WORKER_CONTEXT { static WORKER_CONTEXT gWorker; -// Writes one test message to the native console. static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); } -// Terminates the current test process after one failure. static void fail(const char* message) { print("process_exit_multithread_smoke: "); print(message); diff --git a/code/user/tests/process_exit_multithread_smoke/sources b/code/user/tests/process_exit_multithread_smoke/sources new file mode 100644 index 0000000..b758749 --- /dev/null +++ b/code/user/tests/process_exit_multithread_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=process_exit_multithread_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/process_exit_multithread_smoke/process_exit_multithread_smoke.c diff --git a/code/user/tests/process_protection_smoke/makefile b/code/user/tests/process_protection_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/process_protection_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/process_protection_smoke/process_protection_smoke.c b/code/user/tests/process_protection_smoke/process_protection_smoke.c index 3d0bd40..227ac7c 100644 --- a/code/user/tests/process_protection_smoke/process_protection_smoke.c +++ b/code/user/tests/process_protection_smoke/process_protection_smoke.c @@ -8,13 +8,11 @@ #define MAX_PROCESSES 64u -// Prints one NUL-terminated string to the console. static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); } -// Prints one unsigned integer to the console. static void print_u32(uint32_t value) { char buffer[16]; size_t length = 0; @@ -36,12 +34,10 @@ static void print_u32(uint32_t value) { } } -// Terminates the current test process. static void exit_now(int32_t code) { while (true) (void)SysExitProcess(code); } -// Fails the test with one status value. static void fail_status(const char* operation, KSTATUS status) { print("process_protection_smoke: "); print(operation); diff --git a/code/user/tests/process_protection_smoke/sources b/code/user/tests/process_protection_smoke/sources new file mode 100644 index 0000000..954447c --- /dev/null +++ b/code/user/tests/process_protection_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=process_protection_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/process_protection_smoke/process_protection_smoke.c diff --git a/code/user/tests/realpath_smoke/makefile b/code/user/tests/realpath_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/realpath_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/realpath_smoke/sources b/code/user/tests/realpath_smoke/sources new file mode 100644 index 0000000..28cd2b9 --- /dev/null +++ b/code/user/tests/realpath_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=realpath_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/realpath_smoke/realpath_smoke.c diff --git a/code/user/tests/resource_service_smoke/makefile b/code/user/tests/resource_service_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/resource_service_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/resource_service_smoke/sources b/code/user/tests/resource_service_smoke/sources new file mode 100644 index 0000000..de11fe2 --- /dev/null +++ b/code/user/tests/resource_service_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=resource_service_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/resource_service_smoke/resource_service_smoke.c diff --git a/code/user/tests/security_smoke/makefile b/code/user/tests/security_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/security_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/security_smoke/security_smoke.c b/code/user/tests/security_smoke/security_smoke.c index 11c5c6e..d94464b 100644 --- a/code/user/tests/security_smoke/security_smoke.c +++ b/code/user/tests/security_smoke/security_smoke.c @@ -7,13 +7,11 @@ #include #include -// Writes one string from the privileged parent process. static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(request), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); } -// Writes one unsigned integer from the privileged parent process. static void print_u32(uint32_t value) { char digits[16]; uint32_t count = 0; diff --git a/code/user/tests/security_smoke/sources b/code/user/tests/security_smoke/sources new file mode 100644 index 0000000..93d351a --- /dev/null +++ b/code/user/tests/security_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=security_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/security_smoke/security_smoke.c diff --git a/code/user/tests/shared_mmap/makefile b/code/user/tests/shared_mmap/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/shared_mmap/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/shared_mmap/shared_mmap.c b/code/user/tests/shared_mmap/shared_mmap.c index 3807e07..3186d5d 100644 --- a/code/user/tests/shared_mmap/shared_mmap.c +++ b/code/user/tests/shared_mmap/shared_mmap.c @@ -33,7 +33,6 @@ static void print_u64(uint64_t v) { } } -// Prints one pointer-sized value in hexadecimal for VM alias diagnostics. static void print_hex_uintptr(uintptr_t value) { static const char digits[] = "0123456789abcdef"; char text[2 + sizeof(uintptr_t) * 2 + 1]; diff --git a/code/user/tests/shared_mmap/sources b/code/user/tests/shared_mmap/sources new file mode 100644 index 0000000..82b2993 --- /dev/null +++ b/code/user/tests/shared_mmap/sources @@ -0,0 +1,7 @@ +TARGETNAME=shared_mmap +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/shared_mmap/shared_mmap.c diff --git a/code/user/tests/socket_addr_smoke/makefile b/code/user/tests/socket_addr_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/socket_addr_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/socket_addr_smoke/socket_addr_smoke.c b/code/user/tests/socket_addr_smoke/socket_addr_smoke.c index 1ce39fb..597778c 100644 --- a/code/user/tests/socket_addr_smoke/socket_addr_smoke.c +++ b/code/user/tests/socket_addr_smoke/socket_addr_smoke.c @@ -6,13 +6,11 @@ #include #include -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -31,12 +29,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current process. static void exit_now(int32_t code) { while (true) SysExitProcess(code); } -// Fails the test with one message. static void fail(const char* message) { print("socket_addr_smoke: "); print(message); @@ -44,7 +40,6 @@ static void fail(const char* message) { exit_now(1); } -// Fails the test with one status value. static void fail_status(const char* what, KSTATUS status) { print("socket_addr_smoke: "); print(what); diff --git a/code/user/tests/socket_addr_smoke/sources b/code/user/tests/socket_addr_smoke/sources new file mode 100644 index 0000000..3afd367 --- /dev/null +++ b/code/user/tests/socket_addr_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=socket_addr_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/socket_addr_smoke/socket_addr_smoke.c diff --git a/code/user/tests/stats_abi_smoke/makefile b/code/user/tests/stats_abi_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/stats_abi_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/stats_abi_smoke/sources b/code/user/tests/stats_abi_smoke/sources new file mode 100644 index 0000000..44d175e --- /dev/null +++ b/code/user/tests/stats_abi_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=stats_abi_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/stats_abi_smoke/stats_abi_smoke.c diff --git a/code/user/tests/stats_abi_smoke/stats_abi_smoke.c b/code/user/tests/stats_abi_smoke/stats_abi_smoke.c index f1b5728..5a92ed4 100644 --- a/code/user/tests/stats_abi_smoke/stats_abi_smoke.c +++ b/code/user/tests/stats_abi_smoke/stats_abi_smoke.c @@ -6,13 +6,11 @@ #include #include -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer to the kernel console. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -31,12 +29,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current test process. static void exit_now(int code) { while (true) SysExitProcess(code); } -// Fails the test with one plain message. static void fail(const char* what) { print("stats_abi_smoke: "); print(what); @@ -44,7 +40,6 @@ static void fail(const char* what) { exit_now(1); } -// Fails the test with one status value. static void fail_status(const char* what, KSTATUS status) { print("stats_abi_smoke: "); print(what); diff --git a/code/user/tests/surface_cross_process_smoke/makefile b/code/user/tests/surface_cross_process_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/surface_cross_process_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/surface_cross_process_smoke/sources b/code/user/tests/surface_cross_process_smoke/sources new file mode 100644 index 0000000..c1fc718 --- /dev/null +++ b/code/user/tests/surface_cross_process_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=surface_cross_process_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/surface_cross_process_smoke/surface_cross_process_smoke.c diff --git a/code/user/tests/surface_cross_process_smoke/surface_cross_process_smoke.c b/code/user/tests/surface_cross_process_smoke/surface_cross_process_smoke.c index e84c537..008b4b6 100644 --- a/code/user/tests/surface_cross_process_smoke/surface_cross_process_smoke.c +++ b/code/user/tests/surface_cross_process_smoke/surface_cross_process_smoke.c @@ -14,12 +14,10 @@ #define TEST_VALUE_A 0x00123456u #define TEST_VALUE_B 0x00ABCDEFu -// Terminates the test without depending on a compiler runtime return path. static void exit_now(int code) { for (;;) SysExitProcess(code); } -// Writes one diagnostic string through the native console path. static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(request), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); @@ -39,7 +37,6 @@ static uint32_t read_pixel(const void* base, uint32_t pitch) { return ((const uint32_t*)row)[TEST_PIXEL_X]; } -// Writes one pixel to a pitch-based XRGB8888 mapping. static void write_pixel(void* base, uint32_t pitch, uint32_t value) { uint8_t* row = (uint8_t*)base + (size_t)TEST_PIXEL_Y * pitch; ((uint32_t*)row)[TEST_PIXEL_X] = value; diff --git a/code/user/tests/surface_invalid_rect/makefile b/code/user/tests/surface_invalid_rect/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/surface_invalid_rect/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/surface_invalid_rect/sources b/code/user/tests/surface_invalid_rect/sources new file mode 100644 index 0000000..99adad5 --- /dev/null +++ b/code/user/tests/surface_invalid_rect/sources @@ -0,0 +1,7 @@ +TARGETNAME=surface_invalid_rect +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/surface_invalid_rect/surface_invalid_rect.c diff --git a/code/user/tests/surface_multithread_commit/makefile b/code/user/tests/surface_multithread_commit/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/surface_multithread_commit/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/surface_multithread_commit/sources b/code/user/tests/surface_multithread_commit/sources new file mode 100644 index 0000000..75000d2 --- /dev/null +++ b/code/user/tests/surface_multithread_commit/sources @@ -0,0 +1,7 @@ +TARGETNAME=surface_multithread_commit +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/surface_multithread_commit/surface_multithread_commit.c diff --git a/code/user/tests/surface_smoke/makefile b/code/user/tests/surface_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/surface_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/surface_smoke/sources b/code/user/tests/surface_smoke/sources new file mode 100644 index 0000000..88d9fcf --- /dev/null +++ b/code/user/tests/surface_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=surface_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/surface_smoke/surface_smoke.c diff --git a/code/user/tests/syscall_contract_smoke/makefile b/code/user/tests/syscall_contract_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/syscall_contract_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/syscall_contract_smoke/sources b/code/user/tests/syscall_contract_smoke/sources new file mode 100644 index 0000000..bc5735b --- /dev/null +++ b/code/user/tests/syscall_contract_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=syscall_contract_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/syscall_contract_smoke/syscall_contract_smoke.c diff --git a/code/user/tests/syscall_contract_smoke/syscall_contract_smoke.c b/code/user/tests/syscall_contract_smoke/syscall_contract_smoke.c index 417eddd..341e480 100644 --- a/code/user/tests/syscall_contract_smoke/syscall_contract_smoke.c +++ b/code/user/tests/syscall_contract_smoke/syscall_contract_smoke.c @@ -9,13 +9,11 @@ #define CHILD_EXIT_CODE ((int32_t)-1234567) -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer to the kernel console. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -34,7 +32,6 @@ static void print_u64(uint64_t v) { } } -// Terminates the current test process. static void exit_now(int32_t code) { while (true) SysExitProcess(code); } @@ -50,7 +47,6 @@ static bool view_equals_cstr(SYS_STRING_VIEW view, const char* text) { return true; } -// Fails the test with one plain message. static void fail(const char* msg) { print("syscall_contract_smoke: "); print(msg); @@ -58,7 +54,6 @@ static void fail(const char* msg) { exit_now(1); } -// Fails the test with one status value. static void fail_status(const char* what, KSTATUS status) { print("syscall_contract_smoke: "); print(what); diff --git a/code/user/tests/thread_name_smoke/makefile b/code/user/tests/thread_name_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/thread_name_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/thread_name_smoke/sources b/code/user/tests/thread_name_smoke/sources new file mode 100644 index 0000000..d9af566 --- /dev/null +++ b/code/user/tests/thread_name_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=thread_name_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/thread_name_smoke/thread_name_smoke.c diff --git a/code/user/tests/thread_name_smoke/thread_name_smoke.c b/code/user/tests/thread_name_smoke/thread_name_smoke.c index 56f3773..4ef7de5 100644 --- a/code/user/tests/thread_name_smoke/thread_name_smoke.c +++ b/code/user/tests/thread_name_smoke/thread_name_smoke.c @@ -12,18 +12,15 @@ #define TEST_MAX_THREADS 16u #define TEST_EVENT_AUTO_RESET 0u -// Writes one NUL-terminated string to the console. static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); } -// Terminates the test immediately. static void exit_now(int32_t code) { for (;;) SysExitProcess(code); } -// Fails the test with one diagnostic. static void fail(const char* text) { print("thread_name_smoke: "); print(text); diff --git a/code/user/tests/timer_smoke/makefile b/code/user/tests/timer_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/timer_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/timer_smoke/sources b/code/user/tests/timer_smoke/sources new file mode 100644 index 0000000..7c70595 --- /dev/null +++ b/code/user/tests/timer_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=timer_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/timer_smoke/timer_smoke.c diff --git a/code/user/tests/timer_smoke/timer_smoke.c b/code/user/tests/timer_smoke/timer_smoke.c index 5c3cfb6..9b3a099 100644 --- a/code/user/tests/timer_smoke/timer_smoke.c +++ b/code/user/tests/timer_smoke/timer_smoke.c @@ -4,13 +4,11 @@ #include #include -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer to the kernel console. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -29,12 +27,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current test process. static void exit_now(int code) { while (true) SysExitProcess(code); } -// Fails the test with one status value. static void fail_status(const char* what, KSTATUS status) { print("timer_smoke: "); print(what); @@ -177,7 +173,6 @@ static void test_periodic(void) { SysCloseHandle(timer); } -// Program entry point. int main(void) { print("timer_smoke: start\n"); diff --git a/code/user/tests/win32_condition_variable_smoke/makefile b/code/user/tests/win32_condition_variable_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/win32_condition_variable_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/win32_condition_variable_smoke/sources b/code/user/tests/win32_condition_variable_smoke/sources new file mode 100644 index 0000000..53b907a --- /dev/null +++ b/code/user/tests/win32_condition_variable_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=win32_condition_variable_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\win32.lib" "$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/win32_condition_variable_smoke/win32_condition_variable_smoke.c diff --git a/code/user/tests/win32_condition_variable_smoke/win32_condition_variable_smoke.c b/code/user/tests/win32_condition_variable_smoke/win32_condition_variable_smoke.c index d2542d4..0f7f74a 100644 --- a/code/user/tests/win32_condition_variable_smoke/win32_condition_variable_smoke.c +++ b/code/user/tests/win32_condition_variable_smoke/win32_condition_variable_smoke.c @@ -45,7 +45,6 @@ static uint32_t gRelease; static uint32_t gWoke; static uint32_t gWorkerFailure; -// Writes one test message to the native console. static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); diff --git a/code/user/tests/win32_exception_smoke/makefile b/code/user/tests/win32_exception_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/win32_exception_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/win32_exception_smoke/sources b/code/user/tests/win32_exception_smoke/sources new file mode 100644 index 0000000..ad01858 --- /dev/null +++ b/code/user/tests/win32_exception_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=win32_exception_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\win32.lib" "$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/win32_exception_smoke/win32_exception_smoke.c diff --git a/code/user/tests/win32_exception_smoke/win32_exception_smoke.c b/code/user/tests/win32_exception_smoke/win32_exception_smoke.c index 780700a..f6284ec 100644 --- a/code/user/tests/win32_exception_smoke/win32_exception_smoke.c +++ b/code/user/tests/win32_exception_smoke/win32_exception_smoke.c @@ -14,13 +14,11 @@ static volatile uint32_t gContinueHits; static volatile uint32_t gOnlyHits; static volatile uint32_t gRaisedHits; -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -39,12 +37,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current process. static void exit_now(int32_t code) { while (true) SysExitProcess(code); } -// Fails the test with one message. static void fail(const char* message) { print("win32_exception_smoke: "); print(message); @@ -52,7 +48,6 @@ static void fail(const char* message) { exit_now(1); } -// Fails the test with one integer value. static void fail_value(const char* message, uint64_t value) { print("win32_exception_smoke: "); print(message); diff --git a/code/user/tests/win32_module_lookup_smoke/makefile b/code/user/tests/win32_module_lookup_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/win32_module_lookup_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/win32_module_lookup_smoke/sources b/code/user/tests/win32_module_lookup_smoke/sources new file mode 100644 index 0000000..6eb8541 --- /dev/null +++ b/code/user/tests/win32_module_lookup_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=win32_module_lookup_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\win32.lib" "$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/win32_module_lookup_smoke/win32_module_lookup_smoke.c diff --git a/code/user/tests/win32_module_lookup_smoke/win32_module_lookup_smoke.c b/code/user/tests/win32_module_lookup_smoke/win32_module_lookup_smoke.c index 527b5b2..7a016e9 100644 --- a/code/user/tests/win32_module_lookup_smoke/win32_module_lookup_smoke.c +++ b/code/user/tests/win32_module_lookup_smoke/win32_module_lookup_smoke.c @@ -11,13 +11,11 @@ typedef BOOL (__stdcall *IS_DEBUGGER_PRESENT_ROUTINE)(void); __declspec(dllimport) HANDLE GetModuleHandleA(const char* moduleName); __declspec(dllimport) void* GetProcAddress(HANDLE module, const char* procedureName); -// Writes one test message to the native console. static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); } -// Terminates the test after one contract failure. static void fail(const char* message) { print("win32_module_lookup_smoke: "); print(message); diff --git a/code/user/tests/win32_mutex_smoke/makefile b/code/user/tests/win32_mutex_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/win32_mutex_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/win32_mutex_smoke/sources b/code/user/tests/win32_mutex_smoke/sources new file mode 100644 index 0000000..a79ba48 --- /dev/null +++ b/code/user/tests/win32_mutex_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=win32_mutex_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\win32.lib" "$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/win32_mutex_smoke/win32_mutex_smoke.c diff --git a/code/user/tests/win32_mutex_smoke/win32_mutex_smoke.c b/code/user/tests/win32_mutex_smoke/win32_mutex_smoke.c index a5ddf75..3fbe224 100644 --- a/code/user/tests/win32_mutex_smoke/win32_mutex_smoke.c +++ b/code/user/tests/win32_mutex_smoke/win32_mutex_smoke.c @@ -34,13 +34,11 @@ static DWORD gWorkerWait; static DWORD gWorkerError; static BOOL gWorkerRelease; -// Writes one test message to the native console. static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); } -// Terminates the test after one contract failure. static void fail(const char* message) { print("win32_mutex_smoke: "); print(message); @@ -48,7 +46,6 @@ static void fail(const char* message) { while (true) (void)SysExitProcess(1); } -// Writes one fixed-width hexadecimal value to the native console. static void print_hex32(DWORD value) { static const char digits[] = "0123456789ABCDEF"; char text[] = "0x00000000"; diff --git a/code/user/tests/win32_seh_smoke/makefile b/code/user/tests/win32_seh_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/win32_seh_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/win32_seh_smoke/sources b/code/user/tests/win32_seh_smoke/sources new file mode 100644 index 0000000..db3e84e --- /dev/null +++ b/code/user/tests/win32_seh_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=win32_seh_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\win32.lib" "$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/win32_seh_smoke/win32_seh_smoke.c diff --git a/code/user/tests/win32_seh_smoke/win32_seh_smoke.c b/code/user/tests/win32_seh_smoke/win32_seh_smoke.c index 543d554..100cd01 100644 --- a/code/user/tests/win32_seh_smoke/win32_seh_smoke.c +++ b/code/user/tests/win32_seh_smoke/win32_seh_smoke.c @@ -27,13 +27,11 @@ static volatile uint32_t gTopHits; static volatile uint32_t gBottomHits; static volatile uint32_t gVehHits; -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -52,12 +50,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current process. static void exit_now(int32_t code) { while (true) SysExitProcess(code); } -// Fails the test with one message. static void fail(const char* message) { print("win32_seh_smoke: "); print(message); @@ -65,7 +61,6 @@ static void fail(const char* message) { exit_now(1); } -// Fails the test with one integer value. static void fail_value(const char* message, uint64_t value) { print("win32_seh_smoke: "); print(message); diff --git a/code/user/tests/win32_thread_suspend_smoke/makefile b/code/user/tests/win32_thread_suspend_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/win32_thread_suspend_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/win32_thread_suspend_smoke/sources b/code/user/tests/win32_thread_suspend_smoke/sources new file mode 100644 index 0000000..f28f8e8 --- /dev/null +++ b/code/user/tests/win32_thread_suspend_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=win32_thread_suspend_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\win32.lib" "$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/win32_thread_suspend_smoke/win32_thread_suspend_smoke.c diff --git a/code/user/tests/win32_thread_suspend_smoke/win32_thread_suspend_smoke.c b/code/user/tests/win32_thread_suspend_smoke/win32_thread_suspend_smoke.c index 267e071..48e63a8 100644 --- a/code/user/tests/win32_thread_suspend_smoke/win32_thread_suspend_smoke.c +++ b/code/user/tests/win32_thread_suspend_smoke/win32_thread_suspend_smoke.c @@ -28,13 +28,11 @@ __declspec(dllimport) BOOL CloseHandle(HANDLE handle); static volatile int32_t gStarted; static volatile int32_t gRelease; -// Writes one test message to the native console. static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); } -// Terminates the test after one contract failure. static void fail(const char* message) { print("win32_thread_suspend_smoke: "); print(message); diff --git a/code/user/tests/winmm_waveout_smoke/makefile b/code/user/tests/winmm_waveout_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/winmm_waveout_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/winmm_waveout_smoke/sources b/code/user/tests/winmm_waveout_smoke/sources new file mode 100644 index 0000000..b7fde8f --- /dev/null +++ b/code/user/tests/winmm_waveout_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=winmm_waveout_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\win32.lib" "$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/winmm_waveout_smoke/winmm_waveout_smoke.c diff --git a/code/user/tests/winmm_waveout_smoke/winmm_waveout_smoke.c b/code/user/tests/winmm_waveout_smoke/winmm_waveout_smoke.c index f807cab..07ea9af 100644 --- a/code/user/tests/winmm_waveout_smoke/winmm_waveout_smoke.c +++ b/code/user/tests/winmm_waveout_smoke/winmm_waveout_smoke.c @@ -133,13 +133,11 @@ static int32_t gOpenCallbacks; static int32_t gDoneCallbacks; static int32_t gCloseCallbacks; -// Writes one NUL-terminated string to the kernel console. static void print(const char* text) { SYS_WRITE_CONSOLE_REQUEST request = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(text) }; (void)SysWriteConsole(&request); } -// Terminates the test process after one failure. static void fail(const char* message) { print("winmm_waveout_smoke: "); print(message); diff --git a/code/user/tests/would_block_smoke/makefile b/code/user/tests/would_block_smoke/makefile new file mode 100644 index 0000000..1645a3f --- /dev/null +++ b/code/user/tests/would_block_smoke/makefile @@ -0,0 +1 @@ +!include $(BASEDIR)\makefile.def diff --git a/code/user/tests/would_block_smoke/sources b/code/user/tests/would_block_smoke/sources new file mode 100644 index 0000000..2c5b225 --- /dev/null +++ b/code/user/tests/would_block_smoke/sources @@ -0,0 +1,7 @@ +TARGETNAME=would_block_smoke +TARGETPATH=obj +TARGETTYPE=PROGRAM +FLAVOR=USER +TARGETLIBS="$(BASEDIR)\bin\syscall.lib" "$(BASEDIR)\bin\libc.lib" "$(BASEDIR)\bin\native_runtime.lib" +EXTRA_LFLAGS=/ENTRY:NtlNativeStart +SOURCES=@/code/user/tests/would_block_smoke/would_block_smoke.c diff --git a/code/user/tests/would_block_smoke/would_block_smoke.c b/code/user/tests/would_block_smoke/would_block_smoke.c index bfa15a0..5590e6c 100644 --- a/code/user/tests/would_block_smoke/would_block_smoke.c +++ b/code/user/tests/would_block_smoke/would_block_smoke.c @@ -47,13 +47,11 @@ static uint32_t recv_queue(uint32_t queue, TEST_QUEUE_MESSAGE* msg, uint64_t tim return SysRecvQueue(&req); } -// Prints one NUL-terminated string to the kernel console. static void print(const char* s) { SYS_WRITE_CONSOLE_REQUEST req = { sizeof(SYS_WRITE_CONSOLE_REQUEST), SysSvFromCstr(s) }; SysWriteConsole(&req); } -// Prints one unsigned integer to the kernel console. static void print_u64(uint64_t v) { char buf[32]; int i = 0; @@ -72,12 +70,10 @@ static void print_u64(uint64_t v) { } } -// Terminates the current test process. static void exit_now(int code) { while (true) SysExitProcess(code); } -// Fails the test with one plain message. static void fail(const char* msg) { print("would_block_smoke: "); print(msg); @@ -85,7 +81,6 @@ static void fail(const char* msg) { exit_now(1); } -// Fails the test with one status value. static void fail_status(const char* what, KSTATUS status) { print("would_block_smoke: "); print(what); diff --git a/dirs b/dirs new file mode 100644 index 0000000..57a96b9 --- /dev/null +++ b/dirs @@ -0,0 +1 @@ +DIRS=code diff --git a/image.png b/image.png deleted file mode 100644 index 3a000b319c4a2ca3cb764f0918546dbc6bf89a1a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 387088 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 diff --git a/makefile.def b/makefile.def new file mode 100644 index 0000000..5ce1803 --- /dev/null +++ b/makefile.def @@ -0,0 +1,137 @@ +# Shared x64 build rules. BUILD owns source scanning and object dependencies. +!include sources + +!IF "$(AMD64)" != "1" +!ERROR nt-lite currently targets AMD64 only. +!ENDIF + +ARCHDIR=amd64 +OBJDIR=$(TARGETPATH)\$(ARCHDIR) +_OBJ_DIR=obj +BINDIR=$(BASEDIR)\bin + +CC=cl +CXX=cl +AS=ml64 +RC=rc + +COMMON=/nologo /WX /O2 /GS- /Gs999999 /Gz /Gy /EHsc- /GR- /Oi- /Z7 /std:c17 /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS /I"$(BASEDIR)\code\public" /I"$(BASEDIR)\code\common\include" +DRIVER_CFLAGS=$(COMMON) /W3 +USER_CFLAGS=$(COMMON) /W3 +KERNEL_CFLAGS=$(COMMON) /W3 /I"$(BASEDIR)\code\kernel\include" +POSIX_CFLAGS=/X /I"$(BASEDIR)\code\public\posix" /I"$(BASEDIR)\code\public\freestanding" $(USER_CFLAGS) + +!IF "$(FLAVOR)" == "KERNEL" +CFLAGS=$(KERNEL_CFLAGS) $(EXTRA_CFLAGS) +!ELSEIF "$(FLAVOR)" == "BOOT" +CFLAGS=$(KERNEL_CFLAGS) $(EXTRA_CFLAGS) +!ELSEIF "$(FLAVOR)" == "LIBC" +CFLAGS=$(COMMON) /W3 $(EXTRA_CFLAGS) +!ELSEIF "$(FLAVOR)" == "COMMON" +CFLAGS=$(COMMON) /W3 $(EXTRA_CFLAGS) +!ELSEIF "$(FLAVOR)" == "ACPICA" +CFLAGS=$(COMMON) /W0 /DACPI_NTLITE /I"$(BASEDIR)\code\drivers\platform\acpi\third_party\acpica\include" /wd4100 /wd4101 /wd4127 /wd4214 /wd4244 /wd4267 /wd4706 /wd4702 $(EXTRA_CFLAGS) +!ELSEIF "$(FLAVOR)" == "LWIP" +CFLAGS=$(DRIVER_CFLAGS) /I"$(BASEDIR)\code\drivers\net\lwip\include" /I"$(BASEDIR)\code\drivers\net\lwip\third_party\lwip\src\include" /wd4005 /wd4100 /wd4103 /wd4127 /wd4244 /wd4267 /wd4706 $(EXTRA_CFLAGS) +!ELSEIF "$(FLAVOR)" == "EXT4" +CFLAGS=$(DRIVER_CFLAGS) /I"$(BASEDIR)\code\drivers\fs\ext4\include" /I"$(BASEDIR)\code\drivers\fs\ext4\third_party\lwext4\include" /DCONFIG_USE_DEFAULT_CFG=1 /DCONFIG_HAVE_OWN_ERRNO=1 /DCONFIG_DEBUG_PRINTF=0 /DCONFIG_DEBUG_ASSERT=0 /DCONFIG_BLOCK_DEV_ENABLE_STATS=0 /DCONFIG_EXT4_BLOCKDEVS_COUNT=8 /DCONFIG_EXT4_MOUNTPOINTS_COUNT=8 /wd4005 /wd4100 /wd4101 /wd4103 /wd4127 /wd4244 /wd4267 /wd4706 /wd4996 $(EXTRA_CFLAGS) +!ELSEIF "$(FLAVOR)" == "NTFS" +CFLAGS=$(DRIVER_CFLAGS) /I"$(BASEDIR)\code\drivers\fs\ntfs\ntfs3g\include" /I"$(BASEDIR)\code\drivers\fs\ntfs\ntfs3g\third_party\ntfs-3g\include" /I"$(BASEDIR)\code\drivers\fs\ntfs\ntfs3g\third_party\ntfs-3g\include\ntfs-3g" /DHAVE_CONFIG_H=1 /DNO_NTFS_DEVICE_DEFAULT_IO_OPS=1 /wd4005 /wd4018 /wd4100 /wd4101 /wd4103 /wd4127 /wd4133 /wd4146 /wd4244 /wd4267 /wd4305 /wd4311 /wd4312 /wd4706 /wd4996 $(EXTRA_CFLAGS) +!ELSEIF "$(FLAVOR)" == "POSIX" +CFLAGS=$(POSIX_CFLAGS) $(EXTRA_CFLAGS) +!ELSEIF "$(FLAVOR)" == "DRIVER" +CFLAGS=$(DRIVER_CFLAGS) $(EXTRA_CFLAGS) +!ELSE +CFLAGS=$(USER_CFLAGS) $(EXTRA_CFLAGS) +!ENDIF + +CXXFLAGS=$(CFLAGS) /EHsc +ASFLAGS=/nologo $(EXTRA_ASFLAGS) +RCFLAGS=/nologo +LFLAGS=/nologo /NODEFAULTLIB /DEBUG + +# Select the build before generated object rules. +all: + +# Generated rules use the compiler and object-directory macros above. +!IF EXIST("obj\_objects.mac") +!include obj\_objects.mac +!ENDIF +OBJECTS=$(AMD64_OBJECTS) + +!IF "$(TARGETTYPE)" == "LIBRARY" +TARGET=$(BINDIR)\$(TARGETNAME).lib +!ELSEIF "$(IMAGE_KIND)" == "EFI" +TARGET=$(BINDIR)\$(TARGETNAME).efi +!ELSEIF "$(IMAGE_KIND)" == "KERNEL" +TARGET=$(BINDIR)\$(TARGETNAME).exe +!ELSEIF "$(TARGETTYPE)" == "DRIVER" +TARGET=$(BINDIR)\$(TARGETNAME).sys +!ELSEIF "$(IMAGE_KIND)" == "DLL" +TARGET=$(BINDIR)\$(TARGETNAME).dll +!ELSEIF "$(TARGETTYPE)" == "PROGRAM" +TARGET=$(BINDIR)\$(TARGETNAME).exe +!ELSE +!ERROR Unsupported target type. +!ENDIF + +!IF "$(PASS0ONLY)" == "1" +all: + @echo Pass zero complete. +!ELSEIF "$(TARGETTYPE)" == "LIBRARY" +# BUILD treats libraries as compile-pass targets. +all: $(TARGET) +!ELSEIF "$(NOLINK)" == "1" +all: $(OBJECTS) +!ELSE +all: $(TARGET) +!ENDIF + +.SUFFIXES: .c .cpp .cxx .asm .obj + +{.}.c{$(OBJDIR)}.obj: + @echo BUILDMSG: Compiling "$<" + @$(CC) $(CFLAGS) /c /Fo"$@" "$<" + +{.}.cpp{$(OBJDIR)}.obj: + @echo BUILDMSG: Compiling "$<" + @$(CXX) $(CXXFLAGS) /c /Fo"$@" "$<" + +{.}.asm{$(OBJDIR)}.obj: + @echo BUILDMSG: Compiling "$<" + @$(AS) $(ASFLAGS) /c /Fo"$@" "$<" + +!IF "$(TARGETTYPE)" == "LIBRARY" +$(TARGET): $(OBJECTS) + @if not exist "$(BINDIR)" mkdir "$(BINDIR)" + @echo BUILDMSG: Archiving $(TARGET) + @lib /nologo /OUT:"$@" $(OBJECTS) +!ELSEIF "$(IMAGE_KIND)" == "EFI" +$(TARGET): $(OBJECTS) $(TARGETLIBS) + @if not exist "$(BINDIR)" mkdir "$(BINDIR)" + @echo BUILDMSG: Linking $(TARGET) + @link $(LFLAGS) /SUBSYSTEM:EFI_APPLICATION $(EXTRA_LFLAGS) /OUT:"$@" $(OBJECTS) $(TARGETLIBS) +!ELSEIF "$(IMAGE_KIND)" == "KERNEL" +$(TARGET): $(OBJECTS) $(TARGETLIBS) + @if not exist "$(BINDIR)" mkdir "$(BINDIR)" + @echo BUILDMSG: Linking $(TARGET) + @link $(LFLAGS) /SUBSYSTEM:NATIVE $(EXTRA_LFLAGS) /OUT:"$@" $(OBJECTS) $(TARGETLIBS) +!ELSEIF "$(IMAGE_KIND)" == "DLL" +$(TARGET): $(OBJECTS) $(TARGETLIBS) + @if not exist "$(BINDIR)" mkdir "$(BINDIR)" + @echo BUILDMSG: Linking $(TARGET) + @link $(LFLAGS) /SUBSYSTEM:NATIVE /DLL /IMPLIB:"$(BINDIR)\$(TARGETNAME).lib" $(EXTRA_LFLAGS) /OUT:"$@" $(OBJECTS) $(TARGETLIBS) +!ELSEIF "$(TARGETTYPE)" == "DRIVER" +$(TARGET): $(OBJECTS) $(TARGETLIBS) + @if not exist "$(BINDIR)" mkdir "$(BINDIR)" + @echo BUILDMSG: Linking $(TARGET) + @link $(LFLAGS) /SUBSYSTEM:NATIVE /DLL $(EXTRA_LFLAGS) /OUT:"$@" $(OBJECTS) $(TARGETLIBS) +!ELSE +$(TARGET): $(OBJECTS) $(TARGETLIBS) + @if not exist "$(BINDIR)" mkdir "$(BINDIR)" + @echo BUILDMSG: Linking $(TARGET) + @link $(LFLAGS) /SUBSYSTEM:NATIVE /DYNAMICBASE /HIGHENTROPYVA $(EXTRA_LFLAGS) /OUT:"$@" /PDB:"$(BINDIR)\$(TARGETNAME).pdb" $(OBJECTS) $(TARGETLIBS) +!ENDIF + +clean: + @if exist "obj" rmdir /s /q "obj" diff --git a/project.mk b/project.mk new file mode 100644 index 0000000..2a076a2 --- /dev/null +++ b/project.mk @@ -0,0 +1 @@ +_PROJECT_=nt-lite diff --git a/readme.md b/readme.md index 0720307..9498363 100644 --- a/readme.md +++ b/readme.md @@ -96,10 +96,6 @@ apps/ memtop.exe ``` -## screenshots - -![video.exe running bink video 2](image.png) - ## faq Q: Is it secure? diff --git a/roadmap.md b/roadmap.md index ace5c10..921ab01 100644 --- a/roadmap.md +++ b/roadmap.md @@ -1,50 +1,33 @@ # nt-lite — remaining roadmap -**Status:** working plan; remaining implementation, integration, and validation only. -**Scope:** lean-boot verification, the Linux-derived USB/SCSI/HID/input replacement, parallel driver/services startup, then deferred native filesystem/security, POSIX, desktop, personality, debugging, graphics, and driver compatibility work. +**Status:** lean-boot and cleanup work completed; Phase 2 remains open; Phase 3 startup work implemented, with service administration and release validation remaining. +**Scope:** Linux-derived USB/SCSI/HID/input replacement, final native service control, then deferred filesystem, security, POSIX, desktop, loader, debugging, graphics and driver compatibility work. -## Current state and evidence +## Completed foundation (brief) -- **Latest boot result:** user reports roughly **8 seconds**, **with tests enabled**. This is a substantial improvement over the earlier approximately 96-second ThinkPad run. Exact build flags and measured interval were not supplied; retain the report as an observed result, not a verified per-stage benchmark or proof that all regressions are fixed. -- **Implemented foundation:** POSIX P0–P7 (including server-owned `execve()` and `vfork()`), native UABI.1–UABI.4 cleanup, `drivers.ini` v2 class/exact-dependency parsing and driver-state management, driver/device prepare/commit shutdown, and prior USB/display shutdown-lifetime fixes. Preserve and test these contracts rather than rewriting them. -- **Lean-boot work:** a patch implementing reduced/gated boot checks, deletion of the unconditional SMP scheduler self-test, central monotonic `DbgPrint` timestamps, lightweight default debug flags, and opt-in test packaging was prepared (`ntlite_lean_boot_after_usb_lifetime.patch`). Before marking every component integrated, compare it against the *actual current tree*; the user-reported eight-second result is not a substitute for checking what was applied. -- **Graphical system:** native DWM/surfaces and DOOM integration work, but native console/window management, shell policy, and restart semantics are still incomplete. -- **Desktop PC unresolved:** AMD xHCI `1022:43d5`/`1022:149c` stalls with both external hubs connected. Latest supplied build marker `phase2-usb-rundown-20261022` reached `root hub started ... scan=queued` and `initial scan wake returned` for `28:00.3` before the log ended; source patches have yet to establish a hardware fix. -- **ThinkPad T14 Gen 5 (AMD, machine `21MDS30F00`):** four xHCI PCI functions (`1022:15b9`, `15ba`, `15c0`, `15c1`), recurring USB control-transfer timeouts and hub-attached child descriptor failures. A directly connected `09da:2268` boot keyboard works despite a secondary nonboot HID interface returning PnP unsupported; the built-in keyboard/TrackPoint provide no confirmed input events. Linux identifies i8042/serio keyboard and TrackPoint, plus `ELAN0676` HID-over-I²C on `AMDI0010:01`. The Unifying receiver (`046d:c52b`) has boot mouse capability, so report parsing alone does not explain its missing input. ACPI fixed power button is unavailable and AML event handling remains open. -- **No claim of a real integration test** follows from syntax checks, patch apply checks, or host models. Use the current real-hardware logs and fresh checkout for the next change. +- **Boot and build:** lean boot with gated checks, timestamped diagnostics, opt-in tests, historical BUILD.EXE integration, and VHD packaging. Six correctness, structure, configuration, logging and test-pruning passes completed. +- **Drivers:** dynamic PnP registrations, two-phase load/start and rollback, exact/class dependency settlement, bounded parallel driver startup and kernel-thread exit synchronization. Keep module readiness distinct from PnP device readiness. +- **Services:** strict `services.ini` with `[session]`, `auto|delayed|disabled`, `requires`/`after`, concurrent READY settlement, retry budgets for launch/READY/exit failures, named privileges, capability grants, and generic RSSRV bootstrap authority. Automatic services settle before the shell; delayed services follow it. +- **Existing subsystems:** POSIX P0–P7, native UABI.1–UABI.4, native surfaces/DWM, and driver/device shutdown contracts. + +## Hardware still needing work + +- **Desktop AMD:** xHCI `1022:43d5`/`1022:149c`, especially with both external hubs attached. +- **ThinkPad T14 Gen 5 AMD:** xHCI `1022:15b9/15ba/15c0/15c1`, hub/control timeouts, internal i8042 keyboard/TrackPoint, `ELAN0676` over `AMDI0010:01`, Unifying `046d:c52b`, and AML power-button handling. The direct `09da:2268` boot keyboard has worked in prior tests. ## Operating decisions -1. Favor one clean owner and one native interface per concern. Breaking obsolete APIs is acceptable; delete stale callers and compatibility paths as part of a change. -2. **Normal boot is not a regression harness.** Runtime failure checks remain mandatory, but deterministic regression, synchronization stress, and intrusive diagnostics must be explicit. Avoid creating a new standalone test for every feature. -3. Use centrally timestamped `DbgPrint` records to find waits before adding profiling frameworks or blindly parallelizing work. Times must be monotonic elapsed values, prefixed once per logical line in both console/file output, safely under concurrent writers. Pre-clock logging may remain unprefixed. -4. No permanent vendor/model shortcut in place of standard hardware protocols. Use imported Linux state machines where practicable; otherwise implement the narrowest native component to Linux/spec behavior, with tests and recorded provenance. Protocol-defined fallback remains legitimate. -5. The driver/module dependency graph and the runtime PnP device topology are distinct. `requires` needs provider **success**; `after` needs provider **settlement**, regardless of success. Reverse dependency order governs graceful shutdown. -6. The user-mode service manager should be *generic*: **RSSRV is an ordinary critical service with declared bootstrap resources and authority**, not `type=resource` and not selected by hard-coded executable name. No service gains privileges merely because it uses a familiar image/ID. -7. A service's privilege mask and granted capabilities are separate: use minimal named ambient privileges where unavoidable; delegate scoped handles for actual resources. The current shared-address-space/SASOS model does not promise hostile-user-process memory isolation. -8. Prioritize a usable, correct system. Do not keep testing, scaffolding, or instrumentation merely because it already exists. Preserve only focused coverage for genuinely subtle regressions. +1. One owner and one native interface per concern. Delete obsolete callers and compatibility paths during API changes. +2. Regression and stress tests are opt-in; production boot retains necessary runtime failure checks. +3. Use monotonic `DbgPrint` timestamps to measure actual stalls. Preserve concurrent, logical-line-safe output. +4. Prefer Linux-derived standard hardware state machines to vendor-specific shortcuts; retain provenance and applicable licensing obligations. +5. Keep the driver graph distinct from runtime PnP: `requires` waits for success, `after` for settlement; shutdown reverses dependencies. +6. RSSRV is an ordinary critical service with explicitly delegated bootstrap authority, independent of its image or ID. Ambient privileges and capability handles are separate; SASOS implies limited isolation. +7. Keep instrumentation and tests only where they protect important behavioral contracts. --- -# Active modernization: three phases - -## Phase 1 — Close lean boot and make delays observable - -**Status:** substantially progressed; verification and any measured residual stalls remain. - -**Work** - -- Verify that the current source contains the intended self-test cleanup: - - Rename `KiRunCoreHardeningSelfTests()` to a modest `KiCheckBootState()` (or equivalent), containing only cheap indispensable consistency checks, gated by the existing explicit diagnostic flag. - - Remove `KiRunEarlyKernelSelfTests()` and its unconditional call; do not run 64 rounds of AP-affine scheduler workers as part of boot. - - Heavily prune debug-only `KiRunKernelSelfTests()`; retain at most focused, uniquely valuable concurrency/memory tests (the prepared patch keeps APC wait-race and COW coverage). Remove in-kernel `STRINGVIEW`, trap-frame, filesystem/path, async-file, extensive scheduler, PFN/DMA/PTE/VAD and similar redundant tests instead of blindly relocating everything. - - Keep actual failure handling and initialization assertions where correctness requires them. Compile-time ABI layout checks belong in compile-time assertions. -- Verify the central `DbgPrint` monotonic timestamp implementation, across logical lines and persisted `kernel.log`; guard early/pre-clock and concurrent output without allocation or blocking hot paths. -- Default to light diagnostics (`debug=0x004` for file logs, optionally `0x005` with console mirroring); reserve intrusive flags and `0x002` regression diagnostics for explicit investigations. Do not assume a user must always use one particular mask. -- Normal build must not compile/package the fleet of test executables into `/tests` by default. The proposed build option is `--with-tests`. Prune duplicate/low-value tests selectively; preserve a runnable development suite. -- Use timestamps to distinguish firmware/EFI loading, CPU admission, PCI enumeration, storage readiness, USB timeouts, and service READY latency. Measure cold boots on both QEMU and real machines. Profile 256-bus PCI probing before replacing it; prefer real bridge-topology discovery when justified, while preserving access to buses `c4` and `c6`. - -**Done when:** ordinary boot invokes no regression/stress suite; debug-mode tests are opt-in; logs identify meaningful delay intervals; production images exclude test programs by default; the ~8-second result is reproducible with a defined start/end point and actual flags. This phase is **not** blocked on achieving an arbitrary sub-second boot time. +# Active work ## Phase 2 — Linux-derived USB, SCSI, block, HID and input replacement @@ -80,67 +63,24 @@ **Phase 2 acceptance:** QEMU boots and enumerates keyboard/tablet/storage; both real machines boot reliably with the previously failing hub topologies; direct and behind-hub control/bulk/interrupt transfers work; generic HID/Unifying input reaches RSSRV; storage survives multiple LUNs and abort/reconnect tests; native disk geometry/partition discovery is correct; shutdown/reboot drain owned DMA and callbacks. ThinkPad PS/2/TrackPoint, I²C touchpad and AML power button retain their separately tracked hardware/platform gates. A release with only syntax checks, successful module loading or direct-device enumeration leaves this phase open. -## Phase 3 — Parallel graph startup and native service manager +## Phase 3 — Parallel graph startup and native service management -**Status:** dependency-graph **foundation implemented** for drivers; concurrency, service policy and remaining lifecycle work open. Its service design work may proceed in parallel with Phase 2 import feasibility, while shared module/runtime and authorization decisions are coordinated. +**Status:** startup implementation in place; service administration and integrated validation remain before the nightly. -**Driver initialization** +**Implemented:** four-worker driver graph, dependency settlement and worker-exit synchronization; concurrent `auto` services, post-session `delayed` services, `requires`/`after`, READY/failure handling, per-service fixed-delay restart budgets, `[session]` shell selection, named privileges and scoped capability grants, and configuration-selected RSSRV bootstrap authority. -- Evolve the existing `drivers.ini` v2 manager—not another parser—into a **bounded graph worker scheduler**. Start independent drivers concurrently, with exact- and class-level `requires`/`after` semantics unchanged. Deterministic eligibility and reporting do **not** require deterministic completion order. -- Protect image loading, import/export/module registries and module-state transitions with precisely scoped synchronization. Distinguish module `DriverEntry` completion from runtime device readiness. Preserve boot-critical storage availability, PnP/device ownership, failure propagation, and reverse-order shutdown. Recheck imported xHCI/USB/SCSI module startup, AHCI, PS/2, HDA, PCI and network on SMP hardware. -- Preserve the soft NIC-first behavior: a network stack may wait for the adapter class to **settle** (`after=network-adapter`) rather than fail if no NIC works. No file-order coupling. -- Driver `start=demand`, unload/reload, and optional cascade reload are **later extensions**, not prerequisites to making service demand startup work. Before unloading images: block new binding, quiesce owned device stacks, drain IRPs/DPCs/timers/threads/IRQs/DMA, and prove no import/executable references remain. +**Finish for nightly:** -**Simpler `services.ini`** +- Add an **init-owned service control interface** through existing IPC/security primitives: query status and failure/wait reason; authorized start, stop and restart; expose restart counters. Enforce critical-service protection, `requires` dependencies, and reverse-order shutdown. +- Validate QEMU with one and four CPUs and an SMP hardware boot. Exercise worker idle wakes/joins, dependency success/failure/settlement, READY timeout, startup failure and restart exhaustion, delayed-service ordering, and RSSRV least-privilege authorization. Remove temporary diagnostics afterward. -- Adopt the useful dependency model of `drivers.ini`: stable service IDs (`[service.id]`), optional display `name`, `image`, `requires`, `after`, optional classes, strict whole-file validation and cycle rejection. Defaults should eliminate mandatory noise; omit `type` entirely. Services may have no published endpoint. -- Support `start=auto|delayed|demand|disabled`. `delayed` becomes eligible **after the interactive session is usable**, not after an arbitrary sleep. Demand services start through explicit authorized management requests and optional declared resource/connection activation. Coalesce simultaneous activations into one startup attempt; never start a disabled service through dependency resolution. -- Startup is dependency-driven and concurrent. Launch all currently eligible services before waiting for READY; collect asynchronous READY/exit/timeout events. Do not bind the long-term manager to one fixed 32-handle `WaitMany` array. Failed `requires` blocks dependents; `after` only waits for settlement. Shutdown stops in reverse graph order and prevents new demand activation. -- Per-service restart policy: `never|on-failure|always` plus optional retry limit, time window, initial delay, backoff scheme and maximum delay. Avoid hard-coding one 3-in-5-minutes policy for all services. Prevent restart storms, exclude deliberate stops, and define failure behavior for exhausted budgets. DWM restarts only once window/client reconstruction or explicit-loss semantics are defined. -- Expose human-readable `name`, stable service identity, status, reason for waiting/failure, and explicit service administration. The service manager's control plane is separate from ordinary client access to a service Port. -- Resource publication: `/Services` is an RSSRV-owned **resource namespace**, not a disk directory. Declare publication/activation endpoints explicitly where useful; the desktop session endpoint is separate (e.g. `/Sessions/0/Desktop`). Document this in a dedicated short service/namespace specification, not misleading comments in the INI. -- **RSSRV remains generic:** configuration declares a namespace-provider role/resource contract, `critical=true`, and narrowly defined bootstrap capabilities. Init gives the designated provider the primordial namespace/bootstrap handles via a generic descriptor-driven mechanism. No magic `[service.rssrv]`, `type=resource`, or privileged image-name comparison. Resolve the one-provider/bootstrap-cycle invariant explicitly in the schema/validator. -- Privileges: parse named `privileges` into a derived immutable service security context; separately grant handles/capabilities with scoped rights (storage, Port publication, display/session, network where needed). An ordinary database service must not inherit RSSRV authority. Enforce who may configure, activate, query, stop, or reconfigure services. Integrate later with SEC principals/ACLs rather than inventing an alternate security framework now. -- Move the session image selection out of `[init] commandline` in `boot.ini` into init-owned configuration (for example `[session] image=...`). Define executable path separately from future command-line arguments. Keep `boot.ini` for EFI/bootstrap selection and kernel diagnostics; no Windows Boot Manager clone. +**Deferred:** service `start=demand`, resource/connection-triggered activation and deduplication, reconfiguration, and advanced restart backoff belong to D6. Keep startup policy `auto|delayed|disabled` for this release. -**Illustrative policy only; final grammar needs a small design review:** - -```ini -[session] -image=apps/shell_native.exe - -[service.namespace] -name=Resource Service -image=system/rssrv.exe -class=resource-namespace -critical=true -privileges=resource-admin - -[service.posix] -name=POSIX Server -image=system/posixsrv.exe -requires=namespace - -[service.dwm] -name=Desktop Window Manager -image=system/dwm.exe -requires=namespace - -[service.mysql] -name=MySQL Server -image=apps/mysql.exe -start=demand -requires=posix -privileges=network -``` - -`mysql` is an example of service policy, **not** a claim that the program already runs; its writable database storage should be delegated as a scoped resource. The example `resource-admin` and role syntax are provisional: use existing native privilege/capability vocabulary rather than freeze arbitrary new policy names. - -**Acceptance:** independent drivers and services visibly overlap in timestamped logs; dependency failures and shutdown remain correct; services can be auto/delayed/demand/disabled; resource activation deduplicates; per-service restarts obey their own budgets; RSSRV and ordinary services share one lifecycle mechanism but different delegated authority; configuration is shorter and self-explanatory. +**Done when:** management authorization and lifecycle regressions pass, services reach the shell reliably, and driver workers exit cleanly on the tested SMP configurations. --- -# Deferred work after the three active phases +# Deferred work These are **still outstanding**. The previous roadmap's detailed designs should not be mistaken for implemented behavior. Resume in dependency order, not by the age of its section numbers. @@ -191,8 +131,9 @@ Phase 3's service-specific privilege/capability grants must be designed to exten - Use PE32+ subsystem to select native (1), Win32 GUI/CUI (2/3), or POSIX marker (7). Win32 userspace bootstrap creates its PEB/TEB shim and uses generic persistent per-thread FS/GS bases; native and POSIX remain on their existing TEB layout. Do not introduce personality-specific kernel scheduler state. - Split `crt.dll`, `posix.dll`, and Win32-facing libraries along true ownership boundaries; add thin USER/GDI translation to native DWM/surfaces only when the native desktop is mature. -## D6 — Driver on-demand lifecycle, observability, and cleanup +## D6 — On-demand lifecycle, observability, and cleanup +- Service demand and resource/connection activation: `start=demand`, authorized requests, deduplicated triggers, optional service reconfiguration and advanced restart backoff. Keep one init-owned control plane. - Complete module import/reference accounting and PnP-owned device/worker/DPC/IRP/IRQ/DMA quiescence before any actual unload; then exact-driver reload and optional cascade reload over the same graph. - Add `start=demand` for drivers, activated by PnP IDs, authorized management requests, or dependency demand, not by a parallel private graph. - Structured native read-only driver/class status and wait/failure causes; no requirement to scrape `DbgPrint` for management. @@ -211,15 +152,9 @@ These are intentionally **not prerequisites** for boot, service cleanup, KFS, or # Verification and handoff rules -- **Boot:** record source revision/patch set, machine, firmware, debug mask, `--with-tests` mode, wall-clock start/end definition, and timestamped kernel log. Keep cold/warm comparisons distinct. The ~8-second result is the latest user report, not a universal target or a subsystem timing profile. +- **Boot:** record source revision/patch set, machine, firmware, debug mask, test-packaging mode, wall-clock start/end definition, and timestamped kernel log. Keep cold/warm comparisons distinct. Track reproducible cold/warm boot intervals and the actual build flags. - **Hardware:** validate each controller/port/hub/interface separately and capture the first failing stage. For imported USB/xHCI/SCSI/HID ensure timeout, disconnect, cancellation, DPC, I/O, remove, shutdown and reboot ownership. Include both desktop external hubs and ThinkPad `046d:c52b`/`09da:2268`, plus USB storage directly and behind hubs. -- **Concurrency:** stress dependency cycles/failure/settlement, deterministic selection, ready-event races, service activation coalescing, cancellation and reverse shutdown—not only a clean boot. Do not restore mandatory stress tests to the boot path. +- **Concurrency:** stress dependency cycles/failure/settlement, deterministic selection, ready-event races, worker idle wakeups and completion joins, service restart budgets, cancellation and reverse shutdown—not only a clean boot. Do not restore mandatory stress tests to the boot path. - **Services/security:** prove a minimally privileged database-like service cannot obtain RSSRV namespace management, display, input, raw storage or shutdown capabilities; explicit granted handles work; only authorized callers can control services. - **KFS/SEC/POSIX:** preserve file/provider identity across rename/unlink and native capability rights; run the focused filesystem, security and POSIX integration suite in development builds. - **Code baseline:** use a newly provided current source tree when starting implementation. Earlier chat archives, `code(5).zip`, and prior cumulative patches may not represent the user's latest checkout. Never call a patch 'built' when only `git apply --check`, a syntax check, or a standalone model has passed. - -## Next work item — `docs/services.md` contract review - -Review the revised service architecture against `init/service_config.{h,c}`, `init.c`, `services.ini`, `service_control.h` and RSSRV namespace/publication code. Agree the minimal grammar and authority/bootstrap contracts before changing the service ABI. First choices: how a service declares the unique namespace-provider role, how config requests audited named privileges versus capability grants, and how READY exports name resources without service-type adapters. Then implement a strict parser and deterministic graph validator, followed by event-driven parallel startup, demand activation, restart budgets and management authorization. Keep service boot independent from the Phase 2 imported USB device model: drivers remain driver-manager/PnP objects, not ordinary user-mode services. - -**Parallel Phase 2 first action:** pin Linux source and complete the compiler/ABI + minimal-runtime feasibility gate before large-scale driver import. diff --git a/sdktools/build.bat b/sdktools/build.bat new file mode 100644 index 0000000..338b444 --- /dev/null +++ b/sdktools/build.bat @@ -0,0 +1,34 @@ +@echo off +setlocal +cd /d "%~dp0" + +if /i "%~1"=="clean" ( + if exist out rmdir /s /q out + exit /b 0 +) + +where cl.exe >nul 2>nul || ( + echo build.bat: run from a Visual Studio Developer Command Prompt. + exit /b 1 +) + +if not exist out\obj mkdir out\obj + +del /q out\obj\*.obj out\build.exe >nul 2>nul + +set "CFLAGS=/nologo /W3 /wd4101 /wd4267 /D_CRT_SECURE_NO_WARNINGS /D_CRT_NONSTDC_NO_WARNINGS /DVER_PRODUCTBUILD=0 /I." + +cl %CFLAGS% /TC /std:c17 /Foout\obj\ /c ^ + build.c builddb.c buildexe.c buildmak.c buildscn.c ^ + buildsrc.c buildutl.c buildinc.c buildglobals.c watch.c || exit /b 1 + +cl %CFLAGS% /TP /std:c++17 /Foout\obj\buildscr.obj /c buildscr.cpp || exit /b 1 + +link /nologo /out:out\build.exe ^ + out\obj\build.obj out\obj\builddb.obj out\obj\buildexe.obj ^ + out\obj\buildmak.obj out\obj\buildscn.obj out\obj\buildsrc.obj ^ + out\obj\buildutl.obj out\obj\buildinc.obj out\obj\buildglobals.obj ^ + out\obj\buildscr.obj out\obj\watch.obj ^ + ole32.lib user32.lib uuid.lib oleaut32.lib shell32.lib || exit /b 1 + +echo Built %CD%\out\build.exe for %VSCMD_ARG_TGT_ARCH% diff --git a/sdktools/build.c b/sdktools/build.c new file mode 100644 index 0000000..60539c3 --- /dev/null +++ b/sdktools/build.c @@ -0,0 +1,1731 @@ +//+--------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1989 - 1994. +// +// File: build.c +// +// Contents: Parameter processing and main entry point for Build.exe +// +// History: 16-May-89 SteveWo Created +// ... See SLM log +// 26-Jul-94 LyleC Cleanup/Add Pass0 support +// +//---------------------------------------------------------------------------- + +#include "build.h" + +#ifndef VER_PRODUCTBUILD +#define VER_PRODUCTBUILD 0 +#endif + +static BOOL +FileExistsInDirectory( + LPCSTR Directory, + LPCSTR FileName + ) +{ + CHAR Path[DB_MAX_PATH_LENGTH]; + + sprintf(Path, "%s\\%s", Directory, FileName); + return _access(Path, 0) == 0; +} + +static VOID +ResolveBaseDirectory(VOID) +{ + CHAR Candidate[DB_MAX_PATH_LENGTH]; + CHAR Original[DB_MAX_PATH_LENGTH]; + CHAR *Slash; + LPCSTR BaseDir; + DWORD Length; + + BaseDir = getenv("BASEDIR"); + if (BaseDir && *BaseDir) { + Length = GetFullPathNameA(BaseDir, sizeof(Candidate), Candidate, NULL); + if (Length == 0 || Length >= sizeof(Candidate)) { + BuildError("Unable to resolve BASEDIR=%s\n", BaseDir); + exit(1); + } + } else { + Length = GetCurrentDirectoryA(sizeof(Candidate), Candidate); + if (Length == 0 || Length >= sizeof(Candidate)) { + BuildError("Unable to resolve the current directory\n"); + exit(1); + } + } + + strcpy(Original, Candidate); + + if (!(BaseDir && *BaseDir)) { + for (;;) { + if (FileExistsInDirectory(Candidate, "project.mk")) { + break; + } + + Slash = strrchr(Candidate, '\\'); + if (!Slash) { + strcpy(Candidate, Original); + break; + } + + if (Slash == Candidate + 2 && Candidate[1] == ':') { + if (Slash[1] == '\0') { + strcpy(Candidate, Original); + break; + } + Slash[1] = '\0'; + continue; + } + + *Slash = '\0'; + } + } + + strcpy(NtRoot, Candidate); + if (!SetEnvironmentVariableA("BASEDIR", NtRoot)) { + BuildError("Unable to set BASEDIR=%s\n", NtRoot); + exit(1); + } + sprintf(DbMasterName, "%s\\%s", NtRoot, DBMASTER_NAME); +} + +static LPCSTR +DefaultProcessorArchitecture(VOID) +{ + LPCSTR Architecture = getenv("VSCMD_ARG_TGT_ARCH"); + + // A Visual Studio developer prompt explicitly tells us which toolchain + // target is active. Prefer that for cross-target prompts. + if (Architecture && *Architecture) { + if (!_stricmp(Architecture, "x64") || !_stricmp(Architecture, "amd64")) + return "AMD64"; + if (!_stricmp(Architecture, "x86")) + return "x86"; + if (!_stricmp(Architecture, "ia64")) + return "IA64"; + if (!_stricmp(Architecture, "arm64")) + return "ARM64"; + } + + // Otherwise prefer the architecture of this build.exe. This keeps a + // standalone x64 bootstrap from unexpectedly defaulting to i386 because + // of inherited process-environment quirks. +#if defined(_M_ARM64) + return "ARM64"; +#elif defined(_M_IA64) + return "IA64"; +#elif defined(_M_AMD64) || defined(_WIN64) + return "AMD64"; +#else + Architecture = getenv("PROCESSOR_ARCHITECTURE"); + if (Architecture && *Architecture) { + return Architecture; + } + return "x86"; +#endif +} + +// +// Target machine info: +// +// SourceSubDirMask, Description, Switch, MakeVariable, +// SourceVariable, ObjectVariable, AssociateDirectory, +// SourceDirectory, ObjectDirectory +// + +TARGET_MACHINE_INFO i386TargetMachine = { + TMIDIR_I386, "i386", "-386", "-x86", "386=1", + "i386_SOURCES", "386_OBJECTS", "i386", + "i386", "i386dirs", { "i386" }, + DIR_INCLUDE_X86 | DIR_INCLUDE_WIN32 +}; + +TARGET_MACHINE_INFO ia64TargetMachine = { + TMIDIR_IA64, "IA64", "-ia64", "-merced", "IA64=1", + "IA64_SOURCES", "IA64_OBJECTS", "ia64", + "ia64", "ia64dirs", { "ia64" }, + DIR_INCLUDE_IA64 | DIR_INCLUDE_RISC | DIR_INCLUDE_WIN64 +}; + +TARGET_MACHINE_INFO Amd64TargetMachine = { + TMIDIR_AMD64, "AMD64", "-amd64", "-amd64", "AMD64=1", + "AMD64_SOURCES", "AMD64_OBJECTS", "amd64", + "amd64", "amd64dirs", { "amd64" }, + DIR_INCLUDE_AMD64 | DIR_INCLUDE_RISC | DIR_INCLUDE_WIN64 +}; + +TARGET_MACHINE_INFO Arm64TargetMachine = { + TMIDIR_ARM64, "ARM64", "-arm64", "-aarch64", "ARM64=1", + "ARM64_SOURCES", "ARM64_OBJECTS", "arm64", + "arm64", "arm64dirs", { "arm64" }, + DIR_INCLUDE_ARM64 | DIR_INCLUDE_RISC | DIR_INCLUDE_WIN64 +}; + +TARGET_MACHINE_INFO *PossibleTargetMachines[MAX_TARGET_MACHINES] = { + &i386TargetMachine, + &ia64TargetMachine, + &Amd64TargetMachine, + &Arm64TargetMachine +}; + +UINT NumberCompileWarnings; +UINT NumberCompileErrors; +UINT NumberCompiles; +UINT NumberLibraries; +UINT NumberLibraryWarnings; +UINT NumberLibraryErrors; +UINT NumberLinks; +UINT NumberLinkWarnings; +UINT NumberLinkErrors; +UINT NumberBinplaces; +UINT NumberBinplaceWarnings; +UINT NumberBinplaceErrors; + +// +// Machine specific target dirs default. If one there is only one build +// target and a target specific dirs file is selected, then this gets +// filled with a pointer to the target specific dirs filename. +// + +LPSTR pszTargetDirs = ""; + +#define AltDirMaxSize 10 // Maximum size for alternate obj dir name + +CHAR LogDirectory[DB_MAX_PATH_LENGTH] = "."; +CHAR LogFileName[DB_MAX_PATH_LENGTH] = "build"; +CHAR WrnFileName[DB_MAX_PATH_LENGTH] = "build"; +CHAR ErrFileName[DB_MAX_PATH_LENGTH] = "build"; +CHAR IncFileName[DB_MAX_PATH_LENGTH] = "build"; + +CHAR szObjRoot[DB_MAX_PATH_LENGTH]; +CHAR *pszObjRoot; + +CHAR szBuildAltDir[DB_MAX_PATH_LENGTH]; +CHAR *pszBuildAltDir = NULL; + +CHAR szObjDir[DB_MAX_PATH_LENGTH]; +CHAR szObjDirSlash[DB_MAX_PATH_LENGTH]; +CHAR szObjDirSlashStar[DB_MAX_PATH_LENGTH]; + +CHAR szObjDirD[DB_MAX_PATH_LENGTH]; +CHAR szObjDirSlashD[DB_MAX_PATH_LENGTH]; +CHAR szObjDirSlashStarD[DB_MAX_PATH_LENGTH]; + +CHAR *pszObjDir = szObjDir; +CHAR *pszObjDirSlash = szObjDirSlash; +CHAR *pszObjDirSlashStar = szObjDirSlashStar; +CHAR *pszObjDirD = szObjDirD; + +BOOL fCheckedBuild = TRUE; +ULONG iObjectDir = 0; +BOOL fDependencySwitchUsed; +BOOL fCmdLineDependencySwitchUsed; +BOOL fCmdLineQuicky; +BOOL fCmdLineSemiQuicky; +BOOL fCmdLineQuickZero; +CHAR *BuildProduct; + +ULONG DefaultProcesses = 0; +CHAR *szBuildTag; + +#define MAX_ENV_ARG 512 + +const char szNewLine[] = "\n"; +const char szUsage[] = + "Usage: build [-M[ n]][-w][-e][-f][-q][-c] [-why] [-clean]\n" + " [-386|-amd64|-ia64|-arm64] [-nmake arg]\n" + " -M [n] parallel build (automatic up to 32 workers)\n" + " -w watch tree and rebuild on changes\n" + " -e write build logs\n" + " -f rescan dependencies\n" + " -q query only\n" + " -c clean object files\n" + " -why explain rebuilds\n" + " -clean run project clean rules\n"; + + +BOOL +ProcessParameters(int argc, LPSTR argv[], BOOL SkipFirst); + +VOID +GetEnvParameters( + LPSTR EnvVarName, + LPSTR DefaultValue, + int *pargc, + int maxArgc, + LPSTR argv[]); + +VOID +FreeEnvParameters(int argc, LPSTR argv[]); + +VOID +FreeCmdStrings(VOID); + +VOID +MungePossibleTarget( + PTARGET_MACHINE_INFO pti + ); + +VOID +GetIncludePatterns( + LPSTR EnvVarName, + int maxArgc, + LPSTR argv[]); + +VOID +FreeIncludePatterns( + int argc, + LPSTR argv[]); + + +//+--------------------------------------------------------------------------- +// +// Function: main +// +//---------------------------------------------------------------------------- + +int +__cdecl main( + int argc, + LPSTR argv[] + ) +{ + char c; + PDIRREC DirDB; + UINT i; + int EnvArgc = 0; + LPSTR EnvArgv[ MAX_ENV_ARG ] = {0}; + LPSTR s, s1; + LPSTR PostBuildCmd; + BOOL fPauseDone = FALSE; +#if DBG + BOOL fDebugSave; + + fDebug = 0; +#endif + + { + int watchResult = TryWatchMode(); + if (watchResult >= 0) return watchResult; + } + + strcpy(szObjDir, "obj"); + strcpy(szObjDirSlash, "obj\\"); + strcpy(szObjDirSlashStar, "obj\\*"); + strcpy(szObjDirD, "objd"); + strcpy(szObjDirSlashD, "objd\\"); + strcpy(szObjDirSlashStarD, "objd\\*"); + + /* + * The historical tool closed every CRT descriptor from 3 through _NFILE. + * Modern MSVC treats _close() on an invalid descriptor as an invalid- + * parameter failure, which can terminate the process before normal startup. + * Do not sweep the CRT descriptor table; inherited handles are the caller's + * responsibility and are not needed by build.exe. + */ + + pGetFileAttributesExA = (BOOL (WINAPI *)(LPCSTR, GET_FILEEX_INFO_LEVELS, LPVOID)) + GetProcAddress(GetModuleHandle("kernel32.dll"), "GetFileAttributesExA"); + + if (pGetFileAttributesExA) { + pDateTimeFile = DateTimeFile2; + } else { + pDateTimeFile = DateTimeFile; + } + + InitializeCriticalSection(&TTYCriticalSection); + + s1 = getenv("COMSPEC"); + if (s1) { + cmdexe = s1; + } else { + cmdexe = "cmd.exe"; + } + + { + SYSTEMTIME st; + FILETIME ft; + + GetSystemTime(&st); + SystemTimeToFileTime(&st, &ft); + + FileTimeToDosDateTime( &ft, + ((LPWORD)&BuildStartTime)+1, + (LPWORD)&BuildStartTime + ); + } + + BigBufSize = 0xFFF0; + AllocMem(BigBufSize, &BigBuf, MT_IOBUFFER); + + // All env parsing should happen here (after the cmd line is processed) + + ResolveBaseDirectory(); + + + s = getenv("_OBJ_ROOT"); + if (s) { + pszObjRoot = strcpy(szObjRoot, s); + } + + s = getenv("BUILD_ALT_DIR"); + if (s) { + if (strlen(s) > sizeof(szObjDir) - strlen(szObjDir) - 1) { + BuildError("environment variable BUILD_ALT_DIR may not be longer than %d characters.\n", + sizeof(szObjDir) - strlen(szObjDir) - 1); + exit(1); + } + strcat(szObjDir, s); + strcpy(szObjDirSlash, szObjDir); + strcpy(szObjDirSlashStar, szObjDir); + strcat(szObjDirSlash, "\\"); + strcat(szObjDirSlashStar, "\\*"); + strcat(LogFileName, s); + strcat(WrnFileName, s); + strcat(ErrFileName, s); + strcat(IncFileName, s); + BuildMsg("Object root set to: ==> obj%s\n", s); + } + + s = getenv("NTDEBUG"); + if (!s || *s == '\0' || strcmp(s, "retail") == 0 || strcmp(s, "ntsdnodbg") == 0) { + fCheckedBuild = FALSE; + } + + s = getenv("OS2_INC_PATH"); + if (s) { + MakeString(&pszIncOs2, s, TRUE, MT_DIRSTRING); + } else { + MakeExpandedString(&pszIncOs2, "\\public\\sdk\\inc\\os2"); + } + s = getenv("POSIX_INC_PATH"); + if (s) { + MakeString(&pszIncPosix, s, TRUE, MT_DIRSTRING); + } else { + MakeExpandedString(&pszIncPosix, "\\public\\sdk\\inc\\posix"); + } + s = getenv("CHICAGO_INC_PATH"); + if (s) { + MakeString(&pszIncChicago, s, TRUE, MT_DIRSTRING); + } else { + MakeExpandedString(&pszIncChicago, "\\public\\sdk\\inc\\chicago"); + } + s = getenv("CRT_INC_PATH"); + if (s) { + MakeString(&pszIncCrt, s, TRUE, MT_DIRSTRING); + } else { + MakeExpandedString(&pszIncCrt, "\\public\\sdk\\inc\\crt"); + } + s = getenv("SDK_INC_PATH"); + if (s) { + MakeString(&pszIncSdk, s, TRUE, MT_DIRSTRING); + } else { + MakeExpandedString(&pszIncSdk, "\\public\\sdk\\inc"); + } + s = getenv("OAK_INC_PATH"); + if (s) { + MakeString(&pszIncOak, s, TRUE, MT_DIRSTRING); + } else { + MakeExpandedString(&pszIncOak, "\\public\\oak\\inc"); + } + s = getenv("DDK_INC_PATH"); + if (s) { + MakeString(&pszIncDdk, s, TRUE, MT_DIRSTRING); + } else { + MakeExpandedString(&pszIncDdk, "\\public\\ddk\\inc"); + } + s = getenv("WDM_INC_PATH"); + if (s) { + MakeString(&pszIncWdm, s, TRUE, MT_DIRSTRING); + } else { + MakeExpandedString(&pszIncWdm, "\\public\\ddk\\inc\\wdm"); + } + s = getenv("PRIVATE_INC_PATH"); + if (s) { + MakeString(&pszIncPri, s, TRUE, MT_DIRSTRING); + } else { + MakeExpandedString(&pszIncPri, "\\private\\inc"); + } + s = getenv("MFC_INCLUDES"); + if (s) { + MakeString(&pszIncMfc, s, TRUE, MT_DIRSTRING); + } else { + MakeExpandedString(&pszIncMfc, "\\public\\sdk\\inc\\mfc42"); + } + s = getenv("SDK_LIB_DEST"); + if (s) { + MakeString(&pszSdkLibDest, s, TRUE, MT_DIRSTRING); + } else { + MakeExpandedString(&pszSdkLibDest, "\\public\\sdk\\lib"); + } + s = getenv("DDK_LIB_DEST"); + if (s) { + MakeString(&pszDdkLibDest, s, TRUE, MT_DIRSTRING); + } else { + MakeExpandedString(&pszDdkLibDest, "\\public\\sdk\\lib"); + } + + s = getenv("PUBLIC_INTERNAL_PATH"); + if (s) { + MakeString(&pszPublicInternalPath, s, TRUE, MT_DIRSTRING); + } else { + MakeExpandedString(&pszPublicInternalPath, "\\public\\internal"); + } + + + szBuildTag = getenv("BUILD_TAG"); + + strcpy( MakeParameters, "" ); + MakeParametersTail = AppendString( MakeParameters, + "/c BUILDMSG=Stop.", + FALSE); + + RecurseLevel = 0; + +#if DBG + if ((s = getenv("BUILD_DEBUG_FLAG")) != NULL) { + i = atoi(s); + if (!isdigit(*s)) { + i = 1; + } + BuildMsg("Debug Output Enabled: %u ==> %u\n", fDebug, fDebug | i); + fDebug |= i; + } +#endif + + if (!(MakeProgram = getenv( "BUILD_MAKE_PROGRAM" ))) { + MakeProgram = "NMAKE.EXE"; + } + + if (s = getenv("BUILD_PATH")) { + SetEnvironmentVariable("PATH", s); + } + + if (s = getenv("COPYCMD")) { + if (!strchr(s, 'y') && !strchr(s, 'Y')) { + // COPYCMD is set, but /y isn't a part of it. Add /Y. + s1 = malloc(strlen(s) + sizeof(" /Y") + 1); + if (s1) { + strcpy(s1, s); + strcat(s1, " /Y"); + SetEnvironmentVariable("COPYCMD", s1); + } + } + } else { + // COPYCMD not set. Do so. + SetEnvironmentVariable("COPYCMD", "/Y"); + } + + PostBuildCmd = getenv("BUILD_POST_PROCESS"); + + SystemIncludeEnv = getenv( "INCLUDE" ); + GetCurrentDirectory( sizeof( CurrentDirectory ), CurrentDirectory ); + + for (i = 0; i < MAX_TARGET_MACHINES; i++) { + TargetMachines[i] = NULL; + TargetToPossibleTarget[i] = 0; + MungePossibleTarget(PossibleTargetMachines[i]); + } + + if (!(BuildProduct = getenv("BUILD_PRODUCT"))) { + BuildProduct = ""; + } + + if (!ProcessParameters( argc, argv, TRUE )) { + fUsage = TRUE; + } else { + fCmdLineDependencySwitchUsed = fDependencySwitchUsed; + fCmdLineQuicky = fQuicky; + fCmdLineSemiQuicky = fSemiQuicky; + fCmdLineQuickZero = fQuickZero; + GetEnvParameters( "BUILD_DEFAULT", NULL, &EnvArgc, MAX_ENV_ARG, EnvArgv ); + GetEnvParameters( "BUILD_OPTIONS", NULL, &EnvArgc, MAX_ENV_ARG, EnvArgv ); + if (CountTargetMachines == 0) { + LPCSTR Architecture = DefaultProcessorArchitecture(); + + if (!_stricmp(Architecture, "IA64")) + GetEnvParameters( "BUILD_DEFAULT_TARGETS", "-ia64", &EnvArgc, MAX_ENV_ARG, EnvArgv ); + else + if (!_stricmp(Architecture, "ARM64")) + GetEnvParameters( "BUILD_DEFAULT_TARGETS", "-arm64", &EnvArgc, MAX_ENV_ARG, EnvArgv ); + else + if (!_stricmp(Architecture, "AMD64") || !_stricmp(Architecture, "x64")) + GetEnvParameters( "BUILD_DEFAULT_TARGETS", "-amd64", &EnvArgc, MAX_ENV_ARG, EnvArgv ); + else + GetEnvParameters( "BUILD_DEFAULT_TARGETS", "-386", &EnvArgc, MAX_ENV_ARG, EnvArgv ); + } + if (!ProcessParameters( EnvArgc, EnvArgv, FALSE )) { + fUsage = TRUE; + } + } + FreeEnvParameters(EnvArgc, EnvArgv); + + if (!fUsage && CountTargetMachines == 1) { + LPCSTR vsTarget = getenv("VSCMD_ARG_TGT_ARCH"); + if (vsTarget && *vsTarget) { + LPCSTR actual = TargetMachines[0]->Description; + if ((_stricmp(vsTarget, "x64") == 0 && _stricmp(actual, "amd64") != 0) || + (_stricmp(vsTarget, "amd64") == 0 && _stricmp(actual, "amd64") != 0) || + (_stricmp(vsTarget, "x86") == 0 && _stricmp(actual, "i386") != 0) || + (_stricmp(vsTarget, "arm64") == 0 && _stricmp(actual, "arm64") != 0)) { + BuildError("error: target/toolchain mismatch (%s/%s)\n", actual, vsTarget); + return 1; + } + } + } + if (!fUsage && !fQuery && !SearchPathA(NULL, MakeProgram, NULL, 0, NULL, NULL)) { + BuildError("error: %s missing\n", MakeProgram); + return 1; + } + + if (!fUsage && !fGenerateObjectsDotMacOnly) { + if (!_stricmp(BuildProduct, "NT")) { + if (fCmdLineDependencySwitchUsed) { + fDependencySwitchUsed = fCmdLineDependencySwitchUsed; + fQuicky = fCmdLineQuicky; + fSemiQuicky = fCmdLineSemiQuicky; + fQuickZero = fCmdLineQuickZero; + } + if (!fDependencySwitchUsed) { + BuildError("(Fatal Error) One of either /D, /Z, /z, or /3 is required for NT builds\n"); + exit( 1 ); + } else { + if (fDependencySwitchUsed == 1) { + if (fQuicky) { + BuildError("(Fatal Error) switch can not be used with /Z, /z, or /3\n"); + exit( 1 ); + } + BuildMsgRaw( "BUILD: /D specified - The NT build lab will not accept build requests using this switch\n"); + } + if (fDependencySwitchUsed == 2){ + if (fStopAfterPassZero) { + BuildError("(Fatal Error) switch /0 can not be used with /z\n"); + exit( 1 ); + } + } + } + } + } + + GetIncludePatterns( "BUILD_ACCEPTABLE_INCLUDES", MAX_INCLUDE_PATTERNS, AcceptableIncludePatternList ); + GetIncludePatterns( "BUILD_UNACCEPTABLE_INCLUDES", MAX_INCLUDE_PATTERNS, UnacceptableIncludePatternList ); + + if (( fCheckIncludePaths ) && + ( AcceptableIncludePatternList[ 0 ] == NULL ) && + ( UnacceptableIncludePatternList[ 0 ] == NULL )) { + + BuildMsgRaw( "WARNING: -# specified without BUILD_[UN]ACCEPTABLE_INCLUDES set\n" ); + } + + + if (fCleanRestart) { + if (fClean) { + fClean = FALSE; + fRestartClean = TRUE; + } + else + if (fCleanLibs) { + fCleanLibs = FALSE; + fRestartCleanLibs = TRUE; + } + else { + BuildError("/R switch only valid with /c or /C switch.\n"); + fUsage = TRUE; + } + } + + NumberProcesses = 1; + if (fParallel || getenv("BUILD_MULTIPROCESSOR")) { + SYSTEM_INFO SystemInfo; + + if (DefaultProcesses == 0) { + GetSystemInfo(&SystemInfo); + NumberProcesses = SystemInfo.dwNumberOfProcessors; + } else { + NumberProcesses = DefaultProcesses; + } + if (NumberProcesses == 1) { + fParallel = FALSE; + } else { + if (NumberProcesses > 32) { + if (DefaultProcesses != 0) { + BuildError("error: maximum worker count is 32\n"); + exit(1); + } + NumberProcesses = 32; + } + fParallel = TRUE; + BuildMsg("Using %d child processes\n", NumberProcesses); + } + } + + if (fUsage) { + BuildMsgRaw( + "\nBUILD: Version %x.%02x.%04d\n\n", + BUILD_VERSION >> 8, + BUILD_VERSION & 0xFF, + VER_PRODUCTBUILD); + BuildMsgRaw(szUsage); + } + else + if (CountTargetMachines != 0) { + BuildError( + "%s for ", + fLinkOnly? "Link" : (fCompileOnly? "Compile" : "Compile and Link")); + for (i = 0; i < CountTargetMachines; i++) { + BuildErrorRaw(i==0? "%s" : ", %s", TargetMachines[i]->Description); + AppendString( + MakeTargets, + TargetMachines[i]->MakeVariable, + TRUE); + + } + + BuildErrorRaw(szNewLine); + + // + // If there is one and only one build target and target dirs has + // been enabled, then fill in the appropriate target dirs name. + // + + if (CountTargetMachines == 1) { + if (fTargetDirs == TRUE) { + pszTargetDirs = TargetMachines[0]->TargetDirs; + FileDesc[0].pszPattern = TargetMachines[0]->TargetDirs; + } + } + + if (DEBUG_1) { + if (CountExcludeIncs) { + BuildError("Include files that will be excluded:"); + for (i = 0; i < CountExcludeIncs; i++) { + BuildErrorRaw(i == 0? " %s" : ", %s", ExcludeIncs[i]); + } + BuildErrorRaw(szNewLine); + } + if (CountOptionalDirs) { + BuildError("Optional Directories that will be built:"); + for (i = 0; i < CountOptionalDirs; i++) { + BuildErrorRaw(i == 0? " %s" : ", %s", OptionalDirs[i]); + } + BuildErrorRaw(szNewLine); + } + if (CountExcludeDirs) { + BuildError("Directories that will be NOT be built:"); + for (i = 0; i < CountExcludeDirs; i++) { + BuildErrorRaw(i == 0? " %s" : ", %s", ExcludeDirs[i]); + } + BuildErrorRaw(szNewLine); + } + BuildMsg("MakeParameters == %s\n", MakeParameters); + BuildMsg("MakeTargets == %s\n", MakeTargets); + } + +#if DBG + fDebugSave = fDebug; + // fDebug = 0; +#endif + + // + // Generate the _objects.mac file if requested + // + + if (fGenerateObjectsDotMacOnly) { + DIRSUP DirSup; + ULONG DateTimeSources; + + DirDB = ScanDirectory( CurrentDirectory ); + + if (DirDB && (DirDB->DirFlags & (DIRDB_DIRS | DIRDB_SOURCES))) { + if (!ReadSourcesFile(DirDB, &DirSup, &DateTimeSources)) { + BuildError("Current directory not a SOURCES directory.\n"); + return( 1 ); + } + + GenerateObjectsDotMac(DirDB, &DirSup, DateTimeSources); + + FreeDirSupData(&DirSup); + ReportDirsUsage(); + FreeCmdStrings(); + ReportMemoryUsage(); + return(0); + } + } + + if (!fQuery && fErrorLog) { + strcat(LogFileName, ".log"); + if (!MyOpenFile(LogDirectory, LogFileName, "wb", &LogFile, TRUE)) { + BuildError("(Fatal Error) Unable to open log file\n"); + exit( 1 ); + } + CreatedBuildFile(LogDirectory, LogFileName); + + strcat(WrnFileName, ".wrn"); + if (!MyOpenFile(LogDirectory, WrnFileName, "wb", &WrnFile, FALSE)) { + BuildError("(Fatal Error) Unable to open warning file\n"); + exit( 1 ); + } + CreatedBuildFile(LogDirectory, WrnFileName); + + strcat(ErrFileName, ".err"); + if (!MyOpenFile(LogDirectory, ErrFileName, "wb", &ErrFile, FALSE)) { + BuildError("(Fatal Error) Unable to open error file\n"); + exit( 1 ); + } + CreatedBuildFile(LogDirectory, ErrFileName); + + if ( fCheckIncludePaths ) { + + strcat( IncFileName, ".inc"); + if (!MyOpenFile( LogDirectory, IncFileName, "wb", &IncFile, FALSE ) ) { + BuildError( "(Fatal Error) Unable to open include log file\n"); + exit( 1 ); + } + CreatedBuildFile( LogDirectory, IncFileName ); + } + } + else { + LogFile = NULL; + WrnFile = NULL; + ErrFile = NULL; + IncFile = NULL; + } + + s = getenv("__MTSCRIPT_ENV_ID"); + if (s) { + + if (fDependencySwitchUsed == 2 && fPause) + { + BuildError("Cannot combine -z (or -2) and -p switches under MTScript"); + exit(1); + } + + // Make sure any other build.exe's that get launched as child + // processes don't try to connect to the script engine. + SetEnvironmentVariable("__MTSCRIPT_ENV_ID", NULL); + + g_hMTEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + if (g_hMTEvent != NULL) + { + g_hMTThread = CreateThread(NULL, + 0, + (LPTHREAD_START_ROUTINE)MTScriptThread, + NULL, + 0, + &g_dwMTThreadId); + + if (g_hMTThread) + { + // Wait for the thread to tell us it's ready. + WaitForSingleObject(g_hMTEvent, INFINITE); + + ResetEvent(g_hMTEvent); + + if (!g_hMTThread) + { + // An error occurred connecting to the script engine. + // We can't continue. + BuildError("Unable to connect to script engine. Exiting."); + exit(2); + } + + fMTScriptSync = TRUE; + } + else + { + BuildError("Failed to launch script handling thread! (%d)", GetLastError()); + + CloseHandle(g_hMTEvent); + g_hMTEvent = NULL; + fPause = FALSE; + } + } + else + { + BuildError("Failed to create script communication event! (%d)", GetLastError()); + fPause = FALSE; + } + } + + // + // The user should not have CHICAGO_PRODUCT in + // their environment, as it can cause problems on other machines with + // other users that don't have them set. The following warning + // messages are intended to alert the user to the presence of these + // environment variables. + // + + if (getenv("CHICAGO_PRODUCT") != NULL) { + BuildError("CHICAGO_PRODUCT was detected in the environment.\n" ); + BuildMsg(" ALL directories will be built targeting Chicago!\n" ); + fChicagoProduct = TRUE; + } + + if (!fQuicky) { + LoadMasterDB(); + + BuildError("Computing Include file dependencies:\n"); + + ScanIncludeEnv(SystemIncludeEnv); + ScanGlobalIncludeDirectory(pszIncMfc); + ScanGlobalIncludeDirectory(pszIncOak); + ScanGlobalIncludeDirectory(pszIncDdk); + ScanGlobalIncludeDirectory(pszIncWdm); + ScanGlobalIncludeDirectory(pszIncSdk); + ScanGlobalIncludeDirectory(pszIncPri); + CountSystemIncludeDirs = CountIncludeDirs; + } + +#if DBG + fDebug = fDebugSave; +#endif + fFirstScan = TRUE; + fPassZero = FALSE; + ScanSourceDirectories( CurrentDirectory ); + + if (!fQuicky) { + if (SaveMasterDB() == FALSE) { + BuildError("Unable to save the dependency database: %s\n", DbMasterName); + } + } + + c = '\n'; + if (!fLinkOnly && CountPassZeroDirs) { + if (!fQuicky) { + TotalFilesToCompile = 0; + TotalLinesToCompile = 0L; + + for (i=0; iCountOfPassZeroFiles; + TotalLinesToCompile += DirDB->PassZeroLines; + } + + if (CountPassZeroDirs > 1 && + TotalFilesToCompile != 0 && + TotalLinesToCompile != 0L) { + + BuildMsgRaw( + "Total of %d pass zero files (%s lines) to compile in %d directories\n\n", + TotalFilesToCompile, + FormatNumber( TotalLinesToCompile ), + CountPassZeroDirs); + } + } + + TotalFilesCompiled = 0; + TotalLinesCompiled = 0L; + ElapsedCompileTime = 0L; + + if (fPause && !fMTScriptSync) { + BuildMsg("Press enter to continue with compilations (or 'q' to quit)..."); + c = (char)getchar(); + } + + if ((CountPassZeroDirs > 0) && (c == '\n')) { + CompilePassZeroDirectories(); + WaitForParallelThreads(); + + // + // Rescan now that we've generated all the generated files + // + CountPassZeroDirs = 0; + CountCompileDirs = 0; + CountLinkDirs = 0; + + UnsnapAllDirectories(); + + fPassZero = FALSE; + fFirstScan = FALSE; + RecurseLevel = 0; + + if (fMTScriptSync) { + WaitForResume(fPause, PE_PASS0_COMPLETE); + + fPauseDone = TRUE; + } + + // This will compile directories if fQuicky is TRUE + if (!fStopAfterPassZero) { + ScanSourceDirectories( CurrentDirectory ); + } + + if (!fQuicky) { + if (SaveMasterDB() == FALSE) { + BuildError("Unable to save the dependency database: %s\n", DbMasterName); + } + } + } + } + + if (fMTScriptSync && !fPauseDone) { + WaitForResume(fPause, PE_PASS0_COMPLETE); + } + + if (fStopAfterPassZero) { + BuildError("Stopping after pass zero requested: Pass0 done.\n"); + } + + if (!fStopAfterPassZero && !fLinkOnly && (c == '\n')) { + if (!fQuicky) { + TotalFilesToCompile = 0; + TotalLinesToCompile = 0L; + + for (i=0; iCountOfFilesToCompile; + TotalLinesToCompile += DirDB->SourceLinesToCompile; + } + + if (CountCompileDirs > 1 && + TotalFilesToCompile != 0 && + TotalLinesToCompile != 0L) { + + BuildMsgRaw( + "Total of %d source files (%s lines) to compile in %d directories\n\n", + TotalFilesToCompile, + FormatNumber( TotalLinesToCompile ), + CountCompileDirs); + } + } + + TotalFilesCompiled = 0; + TotalLinesCompiled = 0L; + ElapsedCompileTime = 0L; + + if (fPause && !fMTScriptSync) { + BuildMsg("Press enter to continue with compilations (or 'q' to quit)..."); + c = (char)getchar(); + } + + if (c == '\n') { + // Does nothing if fQuicky is TRUE + CompileSourceDirectories(); + WaitForParallelThreads(); + } + } + + if (fMTScriptSync) { + WaitForResume(fPause, PE_PASS1_COMPLETE); + } + + if (!fStopAfterPassZero && !fCompileOnly && (c == '\n')) { + LinkSourceDirectories(); + WaitForParallelThreads(); + } + + if (!fStopAfterPassZero && PostBuildCmd && !fMTScriptSync) { + // If there's a post build process to invoke, do so but only if + // not running under the buildcon. + + // PostBuildCmd is of the form + // The Message is delimiated with curly brackets. ie: + // POST_BUILD_PROCESS={Do randomness}randomness.cmd + + // would display: + // + // BUILD: Do randomness + // + // while randomness.cmd was running. The process is run synchronously and + // we've still got the i/o pipes setup so any output will be logged to + // build.log (and wrn/err if formated correctly) + + if (*PostBuildCmd == '{') { + LPSTR PostBuildMessage = PostBuildCmd+1; + LogMsg("Executing post build scripts %s\n", szAsterisks); + while (*PostBuildCmd && *PostBuildCmd != '}') + PostBuildCmd++; + + if (*PostBuildCmd == '}') { + *PostBuildCmd = '\0'; + PostBuildCmd++; + BuildMsg("%s\n", PostBuildMessage); + LogMsg("%s\n", PostBuildMessage); + ExecuteProgram(PostBuildCmd, "", "", TRUE); + } + } else { + ExecuteProgram(PostBuildCmd, "", "", TRUE); + } + } + + if (fShowTree) { + for (i = 0; i < CountShowDirs; i++) { + PrintDirDB(ShowDirs[i], 1|4); + } + } + } + else { + BuildError("No target machine specified\n"); + } + + if (!fUsage && !fQuery && fErrorLog) { + ULONG cbLogMin = 32; + ULONG cbWarnMin = 0; + + if (!fAlwaysKeepLogfile) { + if (fQuicky && !fSemiQuicky && ftell(ErrFile) == 0) { + cbLogMin = cbWarnMin = ULONG_MAX; + } + } + CloseOrDeleteFile(&LogFile, LogDirectory, LogFileName, cbLogMin); + CloseOrDeleteFile(&WrnFile, LogDirectory, WrnFileName, cbWarnMin); + CloseOrDeleteFile(&ErrFile, LogDirectory, ErrFileName, 0L); + if ( fCheckIncludePaths ) { + CloseOrDeleteFile(&IncFile, LogDirectory, IncFileName, cbLogMin); + } + } + if (NumberCompileErrors || NumberLibraryErrors || NumberLinkErrors || + NumberBinplaceErrors || BuildChildFailures) { + BuildError("Failed (%ld errors)\n\n", + (long)(NumberCompileErrors + NumberLibraryErrors + NumberLinkErrors + + NumberBinplaceErrors + BuildChildFailures)); + } else { + BuildError("Done\n\n"); + } + + if (fMTScriptSync) { + WaitForResume(FALSE, PE_PASS2_COMPLETE); + } + + if (NumberCompiles) { + BuildMsgRaw(" %d file%s compiled", NumberCompiles, NumberCompiles == 1 ? "" : "s"); + if (NumberCompileWarnings) { + BuildMsgRaw(" - %d Warning%s", NumberCompileWarnings, NumberCompileWarnings == 1 ? "" : "s"); + } + if (NumberCompileErrors) { + BuildMsgRaw(" - %d Error%s", NumberCompileErrors, NumberCompileErrors == 1 ? "" : "s"); + } + + if (ElapsedCompileTime) { + BuildMsgRaw(" - %5ld LPS", TotalLinesCompiled / ElapsedCompileTime); + } + + BuildMsgRaw(szNewLine); + } + + if (NumberLibraries) { + BuildMsgRaw(" %d librar%s built", NumberLibraries, NumberLibraries == 1 ? "y" : "ies"); + if (NumberLibraryWarnings) { + BuildMsgRaw(" - %d Warning%s", NumberLibraryWarnings, NumberLibraryWarnings == 1 ? "" : "s"); + } + if (NumberLibraryErrors) { + BuildMsgRaw(" - %d Error%s", NumberLibraryErrors, NumberLibraryErrors == 1 ? "" : "s"); + } + BuildMsgRaw(szNewLine); + } + + if (NumberLinks) { + BuildMsgRaw(" %d executable%sbuilt", NumberLinks, NumberLinks == 1 ? " " : "s "); + if (NumberLinkWarnings) { + BuildMsgRaw(" - %d Warning%s", NumberLinkWarnings, NumberLinkWarnings == 1 ? "" : "s"); + } + if (NumberLinkErrors) { + BuildMsgRaw(" - %d Error%s", NumberLinkErrors, NumberLinkErrors == 1 ? "" : "s"); + } + BuildMsgRaw(szNewLine); + } + + if (NumberBinplaces) { + BuildMsgRaw(" %d file%sbinplaced", NumberBinplaces, NumberBinplaces == 1 ? " " : "s "); + if (NumberBinplaceWarnings) { + BuildMsgRaw(" - %d Warning%s", NumberBinplaceWarnings, NumberBinplaceWarnings == 1 ? "" : "s"); + } + if (NumberBinplaceErrors) { + BuildMsgRaw(" - %d Error%s", NumberBinplaceErrors, NumberBinplaceErrors == 1 ? "" : "s"); + } + BuildMsgRaw(szNewLine); + } + + ReportDirsUsage(); + FreeCmdStrings(); + FreeIncludePatterns( MAX_INCLUDE_PATTERNS, AcceptableIncludePatternList ); + FreeIncludePatterns( MAX_INCLUDE_PATTERNS, UnacceptableIncludePatternList ); + ReportMemoryUsage(); + + ExitMTScriptThread(); + + if (NumberCompileErrors || NumberLibraryErrors || NumberLinkErrors || NumberBinplaceErrors || BuildChildFailures || fUsage) { + return 1; + } + else { + return( 0 ); + } +} + + +VOID +ReportDirsUsage( VOID ) +{ + ULONG i; + BOOLEAN fHeaderPrinted; + + if (!fShowUnusedDirs) { + return; + } + + fHeaderPrinted = FALSE; + for (i=0; iSwitch) || + !_stricmp(p, PossibleTargetMachines[i]->Switch2)) { + AddTargetMachine(i); + break; + } + } + + if (i < MAX_TARGET_MACHINES) { + } + else + if (!_stricmp(p + 1, "all")) { + for (i = 0; i < MAX_TARGET_MACHINES; i++) { + AddTargetMachine(i); + } + } + else + if (!_stricmp(p + 1, "why")) { + fWhyBuild = TRUE; + } + else + while (c = *++p) + switch (toupper( c )) { + case '?': + fUsage = TRUE; + break; + + case 'C': + if (!_stricmp(p, "clean")) { + MakeParametersTail = AppendString(MakeParametersTail, "clean", TRUE); + *p-- = '\0'; + } else if (c == 'c') { + fClean = TRUE; + } else { + Result = FALSE; + } + break; + case 'E': + fErrorLog = TRUE; + break; + case 'F': + fForce = TRUE; + break; + case 'M': + if (c != 'M') { Result = FALSE; break; } + fParallel = TRUE; + if (argc > 1 && isdigit((unsigned char)(* (argv + 1))[0])) { + long n = strtol(*(argv + 1), NULL, 10); + if (n < 1 || n > 32) { Result = FALSE; break; } + DefaultProcesses = (ULONG)n; + --argc; + ++argv; + } + break; + case 'N': + if (_stricmp(p, "nmake") == 0) { + if (argc > 1) { + --argc; + ++argv; + MakeParametersTail = AppendString(MakeParametersTail, *argv, TRUE); + } else { + Result = FALSE; + } + *p-- = '\0'; + } else { + Result = FALSE; + } + break; + case 'Q': + fQuery = TRUE; + break; + case 'W': + // -w is intercepted by the supervising watcher before main. + Result = FALSE; + break; + default: + BuildError("Invalid switch - /%c\n", c); + Result = FALSE; + break; + } + } + else + if (*p == '~') { + if (CountExcludeDirs >= MAX_EXCLUDE_DIRECTORIES) { + static BOOL fError = FALSE; + + if (!fError) { + BuildError( + "Exclude directory table overflow, using first %u entries\n", + MAX_EXCLUDE_DIRECTORIES); + fError = TRUE; + } + } + else { + MakeString( + &ExcludeDirs[CountExcludeDirs++], + p + 1, + TRUE, + MT_CMDSTRING); + } + } + else { + for (i = 0; i < MAX_TARGET_MACHINES; i++) { + if (!_stricmp(p, PossibleTargetMachines[i]->MakeVariable)) { + AddTargetMachine(i); + break; + } + } + if (i >= MAX_TARGET_MACHINES) { + if (iscsym(*p) || *p == '.') { + if (CountOptionalDirs >= MAX_OPTIONAL_DIRECTORIES) { + static BOOL fError = FALSE; + + if (!fError) { + BuildError( + "Optional directory table overflow, using first %u entries\n", + MAX_OPTIONAL_DIRECTORIES); + fError = TRUE; + } + } + else { + MakeString( + &OptionalDirs[CountOptionalDirs++], + p, + TRUE, + MT_CMDSTRING); + } + } + else + if (!strcmp(p, "*")) { + BuildAllOptionalDirs = TRUE; + } + else { + MakeParametersTail = AppendString( + MakeParametersTail, + p, + TRUE); + } + } + } + --argc; + ++argv; + } + return(Result); +} + + +//+--------------------------------------------------------------------------- +// +// Function: GetEnvParameters +// +//---------------------------------------------------------------------------- + +VOID +GetEnvParameters( + LPSTR EnvVarName, + LPSTR DefaultValue, + int *pargc, + int maxArgc, + LPSTR argv[] + ) +{ + LPCSTR Value; + WCHAR *CommandLine; + LPWSTR *WideArgv; + int WideArgc; + int ValueChars; + int i; + static const WCHAR Prefix[] = L"build.exe "; + + Value = getenv(EnvVarName); + if (!Value) { + if (DefaultValue == NULL) { + return; + } + Value = DefaultValue; + } + else if (DEBUG_1) { + BuildMsg("Using %s=%s\n", EnvVarName, Value); + } + + ValueChars = MultiByteToWideChar(CP_ACP, 0, Value, -1, NULL, 0); + if (!ValueChars) { + BuildError("Unable to parse %s\n", EnvVarName); + exit(1); + } + + CommandLine = (WCHAR *)malloc(sizeof(Prefix) + + (ValueChars * sizeof(WCHAR))); + if (!CommandLine) { + BuildError("Unable to allocate command line for %s\n", EnvVarName); + exit(1); + } + + wcscpy(CommandLine, Prefix); + if (!MultiByteToWideChar(CP_ACP, + 0, + Value, + -1, + CommandLine + ((sizeof(Prefix) / sizeof(Prefix[0])) - 1), + ValueChars)) { + free(CommandLine); + BuildError("Unable to convert %s\n", EnvVarName); + exit(1); + } + + WideArgv = CommandLineToArgvW(CommandLine, &WideArgc); + free(CommandLine); + if (!WideArgv) { + BuildError("Unable to parse %s\n", EnvVarName); + exit(1); + } + + for (i = 1; i < WideArgc; i++) { + LPSTR Argument; + int ArgumentBytes; + LPSTR q; + + if (*pargc >= maxArgc) { + LocalFree(WideArgv); + BuildError("Too many parameters (> %d)\n", maxArgc); + exit(1); + } + + ArgumentBytes = WideCharToMultiByte(CP_ACP, + 0, + WideArgv[i], + -1, + NULL, + 0, + NULL, + NULL); + if (!ArgumentBytes) { + LocalFree(WideArgv); + BuildError("Unable to convert a parameter from %s\n", EnvVarName); + exit(1); + } + + Argument = (LPSTR)malloc(ArgumentBytes); + if (!Argument || !WideCharToMultiByte(CP_ACP, + 0, + WideArgv[i], + -1, + Argument, + ArgumentBytes, + NULL, + NULL)) { + if (Argument) { + free(Argument); + } + LocalFree(WideArgv); + BuildError("Unable to convert a parameter from %s\n", EnvVarName); + exit(1); + } + + for (q = Argument; *q; q++) { + if (*q == '#') { + *q = '='; + } + } + + MakeString(&argv[*pargc], Argument, FALSE, MT_CMDSTRING); + (*pargc)++; + free(Argument); + } + + LocalFree(WideArgv); +} + + +//+--------------------------------------------------------------------------- +// +// Function: FreeEnvParameters +// +//---------------------------------------------------------------------------- + +VOID +FreeEnvParameters(int argc, LPSTR argv[]) +{ + while (--argc >= 0) { + FreeMem(&argv[argc], MT_CMDSTRING); + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: FreeCmdStrings +// +//---------------------------------------------------------------------------- + +VOID +FreeCmdStrings(VOID) +{ +#if DBG + UINT i; + + for (i = 0; i < CountExcludeIncs; i++) { + FreeMem(&ExcludeIncs[i], MT_CMDSTRING); + } + for (i = 0; i < CountOptionalDirs; i++) { + FreeMem(&OptionalDirs[i], MT_CMDSTRING); + } + for (i = 0; i < CountExcludeDirs; i++) { + FreeMem(&ExcludeDirs[i], MT_CMDSTRING); + } + // It's possible the user may have done: + // = + + // in a sources file. Don't free mem unless it's still set... + + if (pszSdkLibDest) + FreeMem(&pszSdkLibDest, MT_DIRSTRING); + if (pszDdkLibDest) + FreeMem(&pszDdkLibDest, MT_DIRSTRING); + if (pszPublicInternalPath) + FreeMem(&pszPublicInternalPath, MT_DIRSTRING); + if (pszIncOs2) + FreeMem(&pszIncOs2, MT_DIRSTRING); + if (pszIncPosix) + FreeMem(&pszIncPosix, MT_DIRSTRING); + if (pszIncChicago) + FreeMem(&pszIncChicago, MT_DIRSTRING); + if (pszIncMfc) + FreeMem(&pszIncMfc, MT_DIRSTRING); + if (pszIncSdk) + FreeMem(&pszIncSdk, MT_DIRSTRING); + if (pszIncCrt) + FreeMem(&pszIncCrt, MT_DIRSTRING); + if (pszIncOak) + FreeMem(&pszIncOak, MT_DIRSTRING); + if (pszIncDdk) + FreeMem(&pszIncDdk, MT_DIRSTRING); + if (pszIncWdm) + FreeMem(&pszIncWdm, MT_DIRSTRING); + if (pszIncPri) + FreeMem(&pszIncPri, MT_DIRSTRING); +#endif +} + +//+--------------------------------------------------------------------------- +// +// Function: MungePossibleTarget +// +//---------------------------------------------------------------------------- + +VOID +MungePossibleTarget( + PTARGET_MACHINE_INFO pti + ) +{ + PCHAR s; + char *pszDir; + + if (!pti) { + return; + } + + // save "i386" string + + pszDir = pti->ObjectDirectory[0]; + + // Create "$(_OBJ_DIR)\i386" string + + s = malloc(12 + strlen(pszDir) + 1); + if (!s) + return; + sprintf(s, "$(_OBJ_DIR)\\%s", pszDir); + pti->ObjectMacro = s; + + // Create "obj$(BUILD_ALT_DIR)\i386" string for default obj dir + + s = malloc(strlen(szObjDir) + 1 + strlen(pszDir) + 1); + if (!s) + return; + sprintf(s, "%s\\%s", szObjDir, pszDir); + pti->ObjectDirectory[0] = s; + + // Create "objd\i386" string for alternate checked obj dir + + s = malloc(strlen(szObjDirD) + 1 + strlen(pszDir) + 1); + if (!s) + return; + sprintf(s, "%s\\%s", szObjDirD, pszDir); + pti->ObjectDirectory[1] = s; +} + +//+--------------------------------------------------------------------------- +// +// Function: GetIncludePatterns +// +//---------------------------------------------------------------------------- + +VOID +GetIncludePatterns( + LPSTR EnvVarName, + int maxArgc, + LPSTR argv[] + ) +{ + LPSTR p, p1, psz; + int argc; + + argc = 0; + + if ( ( p = getenv(EnvVarName ) ) == NULL ) { + return; + } + + MakeString( &psz, p, FALSE, MT_DIRSTRING ); + + p1 = psz; + while ( *p1 ) { + while ( *p1 == ';' || *p1 == ' ' ) { + p1++; + } + p = p1; + while ( *p && *p != ';' ) { + p++; + } + if ( *p ) { + *p++ = '\0'; + } + MakeString( &argv[argc], p1, FALSE, MT_DIRSTRING ); + if ( ( argc += 1 ) == maxArgc ) { + BuildError( "Too many include patterns ( > %d)\n", maxArgc ); + exit( 1 ); + } + + p1 = p; + } + + FreeMem(&psz, MT_DIRSTRING); +} + +//+--------------------------------------------------------------------------- +// +// Function: FreeIncludePatterns +// +//---------------------------------------------------------------------------- + +VOID +FreeIncludePatterns(int argc, LPSTR argv[]) +{ + while ( argc ) { + if ( argv[--argc] ) { + FreeMem( &argv[argc], MT_DIRSTRING ); + } + } +} diff --git a/sdktools/build.h b/sdktools/build.h new file mode 100644 index 0000000..1a048ce --- /dev/null +++ b/sdktools/build.h @@ -0,0 +1,1094 @@ +/*++ BUILD Version: 0001 // Increment this if a change has global effects + +--*/ + +//+--------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1994 +// +// File: build.h +// +// Contents: Main Include file for build.exe +// +// History: 16-May-89 SteveWo Created +// 26-Jul-94 LyleC Cleanup/Add Support for Pass0 +// +//---------------------------------------------------------------------------- + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define INC_OLE2 + +#include +#include +#include + +#define UINT DWORD +#define HDIR HANDLE + + +VOID +ClearLine(VOID); + + +// +// Types and Constant Definitions +// + +#if DBG +#define DEBUG_1 (fDebug & 1) +#else +#define DEBUG_1 FALSE +#endif + +extern BOOL fDebug; +#define DEBUG_2 (fDebug & 3) +#define DEBUG_4 (fDebug & 4) + +// +// Target specific dirs file name. +// + +extern LPSTR pszTargetDirs; + +#define MAX_TARGET_MACHINES 4 + +typedef struct _TARGET_MACHINE_INFO { + UCHAR SourceSubDirMask; // TMIDIR_I386 + LPSTR Description; // "i386" + LPSTR Switch; // "-386" + LPSTR Switch2; // "-x86" + LPSTR MakeVariable; // "386=1" + LPSTR SourceVariable; // "i386_SOURCES" + LPSTR ObjectVariable; // "386_OBJECTS" + LPSTR AssociateDirectory; // "i386" + LPSTR SourceDirectory; // "i386" + LPSTR TargetDirs; // "i386dirs" + LPSTR ObjectDirectory[2]; // "i386" -- initialize only first entry + ULONG DirIncludeMask; // Platform/Group/etc. + LPSTR ObjectMacro; // don't initialize + +} TARGET_MACHINE_INFO, *PTARGET_MACHINE_INFO; + +#define DIR_INCLUDE_NONE 0x00000000 +#define DIR_INCLUDE_X86 0x00000001 +// 0x00000002 +#define DIR_INCLUDE_IA64 0x00000004 +// 0x00000008 +#define DIR_INCLUDE_WIN32 0x00000010 +#define DIR_INCLUDE_WIN64 0x00000020 +#define DIR_INCLUDE_RISC 0x00000040 +#define DIR_INCLUDE_AMD64 0x00000080 +#define DIR_INCLUDE_ARM64 0x00000100 +#define DIR_INCLUDE_ALL 0xffffffff + +// It's possible to have SOURCES= entries of the following forms: +// entry SourceSubDirMask +// ----- ---------------- +// foo.c 0 +// i386\foo.c 1 +// amd64\foo.c 2 +// ia64\foo.c 4 +// ..\foo.c 80 +// ..\i386\foo.c 81 +// ..\amd64\foo.c 82 +// ..\ia64\foo.c 84 + +#define TMIDIR_I386 0x0001 +#define TMIDIR_AMD64 0x0002 +#define TMIDIR_IA64 0x0004 +#define TMIDIR_ARM64 0x0008 +#define TMIDIR_PARENT 0x0080 // or'd in with above bits + + +#define SIG_DIRREC 0x44644464 // "DdDd" + +#ifdef SIG_DIRREC +#define SIG_FILEREC 0x46664666 // "FfFf" +#define SIG_INCLUDEREC 0x49694969 // "IiIi" +#define SIG_SOURCEREC 0x53735373 // "SsSs" +#define SigCheck(s) s +#else +#define SigCheck(s) +#endif + +#define AssertDir(pdr) \ + SigCheck(assert((pdr) != NULL && (pdr)->Sig == SIG_DIRREC)) + +#define AssertOptionalDir(pdr) \ + SigCheck(assert((pdr) == NULL || (pdr)->Sig == SIG_DIRREC)) + +#define AssertFile(pfr) \ + SigCheck(assert((pfr) != NULL && (pfr)->Sig == SIG_FILEREC)) + +#define AssertOptionalFile(pfr) \ + SigCheck(assert((pfr) == NULL || (pfr)->Sig == SIG_FILEREC)) + +#define AssertInclude(pir) \ + SigCheck(assert((pir) != NULL && (pir)->Sig == SIG_INCLUDEREC)) + +#define AssertOptionalInclude(pir) \ + SigCheck(assert((pir) == NULL || (pir)->Sig == SIG_INCLUDEREC)) + +#define AssertSource(psr) \ + SigCheck(assert((psr) != NULL && (psr)->Sig == SIG_SOURCEREC)) + +#define AssertOptionalSource(psr) \ + SigCheck(assert((psr) == NULL || (psr)->Sig == SIG_SOURCEREC)) + +// +// Information about source directories is stored an in-memory database. +// The information is saved on disk by writing the contents of the database +// to "build.dat". It is reloaded from disk for subsequent invocations, +// and re-written only when it has been updated. +// + + +typedef struct _INCLUDEREC { + SigCheck(ULONG Sig;) + struct _INCLUDEREC *Next; // static list describes original arcs + struct _INCLUDEREC *NextTree; // dynamic list -- cycles are collapsed + struct _FILEREC *pfrCycleRoot; + struct _FILEREC *pfrInclude; + USHORT Version; + USHORT IncFlags; + char Name[1]; +} INCLUDEREC, *PINCLUDEREC; + + +#define INCLUDEDB_LOCAL 0x0001 // include "foo.h" +#define INCLUDEDB_POST_HDRSTOP 0x0002 // appears after #pragma hdrstop +#define INCLUDEDB_MISSING 0x0400 // include file was once missing +#define INCLUDEDB_GLOBAL 0x0800 // include file is in global directory +#define INCLUDEDB_SNAPPED 0x1000 // include file snapped +#define INCLUDEDB_CYCLEALLOC 0x2000 // allocated to flatten cycle +#define INCLUDEDB_CYCLEROOT 0x4000 // moved to root file to flatten cycle +#define INCLUDEDB_CYCLEORPHAN 0x8000 // orphaned to flatten cycle + +// Flags preserved when loading build.dat: + +#define INCLUDEDB_DBPRESERVE (INCLUDEDB_LOCAL | INCLUDEDB_POST_HDRSTOP) + + + +#define IsCleanTree(pir) \ + ((pir)->NextTree == NULL && \ + ((pir)->IncFlags & \ + (INCLUDEDB_CYCLEALLOC | INCLUDEDB_CYCLEROOT | INCLUDEDB_CYCLEORPHAN)) == 0) + + +#if DBG +VOID AssertCleanTree(INCLUDEREC *pir, OPTIONAL struct _FILEREC *pfr); +#else +#define AssertCleanTree(pir, pfr) assert(IsCleanTree(pir)) +#endif + +// +// Make file description structure definition. +// + +typedef struct _FILEDESC { + LPSTR pszPattern; // pattern to match file name + LPSTR pszCommentToEOL; // comment-to-eol string + BOOL fNeedFileRec; // TRUE => file needs a file record + ULONG FileFlags; // flags to be set in file record + ULONG DirFlags; // flags to be set in directory record +} FILEDESC; + +extern FILEDESC FileDesc[]; + +typedef struct _FILEREC { + SigCheck(ULONG Sig;) + struct _FILEREC *Next; + struct _DIRREC *Dir; + INCLUDEREC *IncludeFiles; // static list describes original arcs + INCLUDEREC *IncludeFilesTree; // dynamic list -- cycles are collapsed + struct _FILEREC *NewestDependency; + LPSTR pszCommentToEOL; // comment-to-eol string in source + ULONG DateTime; + ULONG DateTimeTree; // Newest DateTime for included tree + ULONG TotalSourceLines; // line count in all included files + ULONG FileFlags; + ULONG SourceLines; + USHORT Attr; + USHORT SubDirIndex; + USHORT Version; + USHORT GlobalSequence; // Sequence number for dynamic include tree + USHORT LocalSequence; // Sequence number for dynamic include tree + USHORT idScan; // id used for detecting multiple inclusion + USHORT CheckSum; // Name checksum + UCHAR fDependActive; + char Name[1]; +} FILEREC, *PFILEREC; + +#define MAKE_DATE_TIME( date, time ) \ + ((ULONG)(((USHORT)(time)) | ((ULONG)((USHORT)(date))) << 16)) + +#define FILEDB_SOURCE 0x00000001 +#define FILEDB_DIR 0x00000002 +#define FILEDB_HEADER 0x00000004 +#define FILEDB_ASM 0x00000008 +#define FILEDB_MASM 0x00000010 +#define FILEDB_RC 0x00000020 +#define FILEDB_C 0x00000040 +#define FILEDB_MIDL 0x00000080 +#define FILEDB_ASN 0x00000100 +#define FILEDB_JAVA 0x00000200 +#define FILEDB_MOF 0x00000400 +#define FILEDB_CSHARP 0x00000800 +#define FILEDB_SCANNED 0x00001000 +#define FILEDB_OBJECTS_LIST 0x00002000 +#define FILEDB_FILE_MISSING 0x00004000 +#define FILEDB_MKTYPLIB 0x00008000 +#define FILEDB_MULTIPLEPASS 0x00010000 +#define FILEDB_PASS0 0x00020000 +#define FILEDB_SOURCEREC_EXISTS 0x00040000 + +// Flags preserved when loading build.dat: + +#define FILEDB_DBPRESERVE (FILEDB_SOURCE | \ + FILEDB_DIR | \ + FILEDB_HEADER | \ + FILEDB_ASM | \ + FILEDB_MASM | \ + FILEDB_RC | \ + FILEDB_C | \ + FILEDB_MIDL | \ + FILEDB_ASN | \ + FILEDB_JAVA | \ + FILEDB_MOF | \ + FILEDB_CSHARP | \ + FILEDB_MKTYPLIB | \ + FILEDB_MULTIPLEPASS | \ + FILEDB_PASS0) + + +typedef struct _SOURCEREC { + SigCheck(ULONG Sig;) + struct _SOURCEREC *psrNext; + FILEREC *pfrSource; + UCHAR SourceSubDirMask; + UCHAR SrcFlags; + LPSTR ProjectSource; // Canonical absolute source path for project-relative inputs. + LPSTR ObjectStem; // Stable, path-derived object filename without extension. + LPSTR ObjectSourceName; // Path-derived basename with original source extension. +} SOURCEREC; + +#define SOURCEDB_SOURCES_LIST 0x01 +#define SOURCEDB_FILE_MISSING 0x02 +#define SOURCEDB_PCH 0x04 +#define SOURCEDB_OUT_OF_DATE 0x08 +#define SOURCEDB_COMPILE_NEEDED 0x10 + + +typedef struct _DIRSUP { + LPSTR TestType; + LPSTR LocalIncludePath; + LPSTR PchIncludeDir; + LPSTR PchInclude; + LPSTR PchTargetDir; + LPSTR PchTarget; + LPSTR PassZeroHdrDir; + LPSTR PassZeroSrcDir1; + LPSTR PassZeroSrcDir2; + LPSTR ConditionalIncludes; + ULONG DateTimeSources; + ULONG IdlType; + ULONG fNoTarget; + LPSTR SourcesVariables[MAX_TARGET_MACHINES + 1]; + SOURCEREC *psrSourcesList[MAX_TARGET_MACHINES + 1]; +} DIRSUP; + + +typedef struct _DIRREC { + SigCheck(ULONG Sig;) + struct _DIRREC *Next; + DIRSUP *pds; // Used to preserve info from pass zero + PFILEREC Files; + LPSTR TargetPath; + LPSTR TargetPathLib; + LPSTR TargetName; + LPSTR TargetExt; + LPSTR KernelTest; + LPSTR UserAppls; + LPSTR UserTests; + LPSTR NTTargetFile0; + LPSTR Pch; + LPSTR PchObj; + LONG SourceLinesToCompile; + LONG PassZeroLines; + ULONG DirFlags; + ULONG RecurseLevel; + USHORT FindCount; + USHORT CountSubDirs; + SHORT CountOfFilesToCompile; + SHORT CountOfPassZeroFiles; + USHORT CheckSum; // Name checksum + char Name[1]; +} DIRREC, *PDIRREC; + + +#define DIRDB_SOURCES 0x00000001 +#define DIRDB_DIRS 0x00000002 +#define DIRDB_MAKEFILE 0x00000004 +#define DIRDB_MAKEFIL0 0x00000008 +#define DIRDB_TARGETFILE0 0x00000010 +#define DIRDB_TARGETFILES 0x00000020 +#define DIRDB_RESOURCE 0x00000040 +#define DIRDB_PASS0 0x00000080 + +#define DIRDB_SOURCES_SET 0x00000100 + +#define DIRDB_CHICAGO_INCLUDES 0x00000800 + +#define DIRDB_NEW 0x00001000 +#define DIRDB_SCANNED 0x00002000 +#define DIRDB_SHOWN 0x00004000 +#define DIRDB_GLOBAL_INCLUDES 0x00008000 + +#define DIRDB_SYNCHRONIZE_BLOCK 0x00010000 +#define DIRDB_SYNCHRONIZE_DRAIN 0x00020000 +#define DIRDB_COMPILENEEDED 0x00040000 +#define DIRDB_COMPILEERRORS 0x00080000 + +#define DIRDB_SOURCESREAD 0x00100000 +#define DIRDB_DLLTARGET 0x00200000 +#define DIRDB_LINKNEEDED 0x00400000 +#define DIRDB_FORCELINK 0x00800000 +#define DIRDB_PASS0NEEDED 0x01000000 +#define DIRDB_MAKEFIL1 0x02000000 +#define DIRDB_CHECKED_ALT_DIR 0x04000000 + +// Flags preserved when loading build.dat: + +#define DIRDB_DBPRESERVE 0 + + + +typedef struct _TARGET { + FILEREC *pfrCompiland; + DIRREC *pdrBuild; + LPSTR pszSourceDirectory; + LPSTR ConditionalIncludes; + ULONG DateTime; + ULONG DirFlags; + char Name[1]; +} TARGET, *PTARGET; + + +#define BUILD_VERSION 0x0403 +#define DBMASTER_NAME "build.dat" +#define DB_MAX_PATH_LENGTH 256 + +// If you change or add any values to this enum, +// also fix MemTab in buildutl.c: + +typedef enum _MemType { + MT_TOTALS = 0, + MT_UNKNOWN, + + MT_CHILDDATA, + MT_CMDSTRING, + MT_DIRDB, + MT_DIRSUP, + MT_DIRPATH, + MT_DIRSTRING, + MT_EVENTHANDLES, + MT_FILEDB, + MT_FILEREADBUF, + MT_FRBSTRING, + MT_INCLUDEDB, + MT_IOBUFFER, + MT_MACRO, + MT_SOURCEDB, + MT_TARGET, + MT_THREADFILTER, + MT_THREADHANDLES, + MT_THREADSTATE, + + MT_INVALID = 255, +} MemType; + +struct _THREADSTATE; + +typedef BOOL (*FILTERPROC)(struct _THREADSTATE *ThreadState, LPSTR p); + +typedef struct _THREADSTATE { + USHORT cRowTotal; + USHORT cColTotal; + BOOL IsStdErrTty; + FILE *ChildOutput; + UINT ChildState; + UINT ChildFlags; + LPSTR ChildTarget; + UINT LinesToIgnore; + FILTERPROC FilterProc; + ULONG ThreadIndex; + CHAR UndefinedId[ DB_MAX_PATH_LENGTH ]; + CHAR ChildCurrentDirectory[ DB_MAX_PATH_LENGTH ]; + CHAR ChildCurrentFile[ DB_MAX_PATH_LENGTH ]; + DIRREC *CompileDirDB; +} THREADSTATE, *PTHREADSTATE; + +// +// Global Data (uninit will always be FALSE) +// + +extern BOOL fUsage; // Set when usage message is to be displayed +extern BOOL fStatus; // Set by -s and -S options +extern BOOL fStatusTree; // Set by -S option +extern BOOL fShowTree; // Set by -t and -T options +extern BOOL fShowTreeIncludes; // Set by -T option +extern BOOL fClean; // Set by -c option +extern BOOL fCleanLibs; // Set by -C option +extern BOOL fCleanRestart; // Set by -r option +extern BOOL fRestartClean; // Set if -c and -r were both given +extern BOOL fRestartCleanLibs; // Set if -C and -r were both given +extern BOOL fPause; // Set by -p option +extern BOOL fParallel; // Set on a multiprocessor machine or by -M +extern BOOL fPrintElapsed; // Set by -P option +extern BOOL fQuery; // Set by -q option +extern BOOL fStopAfterPassZero; // Set by -0 option +extern BOOL fQuicky; // Set by -z and -Z options +extern BOOL fQuickZero; // Set by -3 +extern BOOL fSemiQuicky; // Set by -Z option +extern BOOL fShowOutOfDateFiles; // Set by -o option +extern BOOL fSyncLink; // Set by -a option +extern BOOL fForce; // Set by -f option +extern BOOL fEnableVersionCheck; // Set by -v option +extern BOOL fSilent; // Set by -i option +extern BOOL fKeep; // Set by -k option +extern BOOL fCompileOnly; // Set by -L option +extern BOOL fLinkOnly; // Set by -l option +extern BOOL fErrorLog; // Set by -e option +extern BOOL fGenerateObjectsDotMacOnly; // Set by -O option +extern BOOL fShowWarningsOnScreen; // Set by -w option +extern BOOL fNoisyScan; // Set by -y option +extern BOOL fFullErrors; // Set by -b option +extern BOOL fWhyBuild; // Set by -why option +extern BOOL fChicagoProduct; // Set if CHICAGO_PRODUCT is set in environment +extern BOOL fLineCleared; // Current line on screen clear? +extern BOOL fPassZero; // Indicates we've found pass zero dirs +extern BOOL fFirstScan; // Indicates this is the first scan +extern BOOL fAlwaysPrintFullPath; // Set by -F option +extern BOOL fTargetDirs; // Set by -g option +extern BOOL fAlwaysKeepLogfile; // Set by -E option +extern BOOL fShowUnusedDirs; // Set by -u option +extern BOOL fCheckIncludePaths; // Set by -# option +extern BOOL fNoThreadIndex; // Set by -I option +extern BOOL fMTScriptSync; // Set when communicating with the MTScript engine + +#define MAX_INCLUDE_PATTERNS 32 + +extern LPSTR AcceptableIncludePatternList[ MAX_INCLUDE_PATTERNS + 1 ]; +extern LPSTR UnacceptableIncludePatternList[ MAX_INCLUDE_PATTERNS + 1 ]; + +extern LPSTR MakeProgram; +extern char MakeParameters[ 512 ]; +extern LPSTR MakeParametersTail; +extern char MakeTargets[ 256 ]; +extern char RestartDir[ 256 ]; +extern char NtRoot[ 256 ]; +extern char DbMasterName[ 256 ]; +extern const char szNewLine[]; + +extern char *pszSdkLibDest; +extern char *pszDdkLibDest; +extern char *pszPublicInternalPath; +extern char *pszIncOak; +extern char *pszIncDdk; +extern char *pszIncWdm; +extern char *pszIncSdk; +extern char *pszIncMfc; +extern char *pszIncCrt; +extern char *pszIncPri; +extern char *pszIncOs2; +extern char *pszIncPosix; +extern char *pszIncChicago; + +extern char *szBuildTag; +extern char *pszObjDir; +extern char *pszObjDirSlash; +extern char *pszObjDirSlashStar; +extern BOOL fCheckedBuild; +extern ULONG iObjectDir; +extern ULONG NumberProcesses; +extern CRITICAL_SECTION TTYCriticalSection; + +extern CHAR const *cmdexe; + +extern LONG TotalFilesToCompile; +extern LONG TotalFilesCompiled; + +extern LONG TotalLinesToCompile; +extern LONG TotalLinesCompiled; + +extern ULONG ElapsedCompileTime; +extern DIRREC *CurrentCompileDirDB; + +// Fixed length arrays... + +extern UINT CountTargetMachines; +extern TARGET_MACHINE_INFO *TargetMachines[MAX_TARGET_MACHINES]; +extern TARGET_MACHINE_INFO *PossibleTargetMachines[MAX_TARGET_MACHINES]; +extern TARGET_MACHINE_INFO i386TargetMachine; +extern TARGET_MACHINE_INFO ia64TargetMachine; +extern TARGET_MACHINE_INFO Amd64TargetMachine; +extern TARGET_MACHINE_INFO Arm64TargetMachine; +extern UINT TargetToPossibleTarget[MAX_TARGET_MACHINES]; + + +#define MAX_OPTIONAL_DIRECTORIES 256 +extern UINT CountOptionalDirs; +extern LPSTR OptionalDirs[MAX_OPTIONAL_DIRECTORIES]; +extern BOOLEAN OptionalDirsUsed[MAX_OPTIONAL_DIRECTORIES]; +extern BOOL BuildAllOptionalDirs; + + +#define MAX_EXCLUDE_DIRECTORIES MAX_OPTIONAL_DIRECTORIES +extern UINT CountExcludeDirs; +extern LPSTR ExcludeDirs[MAX_EXCLUDE_DIRECTORIES]; +extern BOOLEAN ExcludeDirsUsed[MAX_OPTIONAL_DIRECTORIES]; + + +#define MAX_EXCLUDE_INCS 128 +extern UINT CountExcludeIncs; +extern LPSTR ExcludeIncs[MAX_EXCLUDE_INCS]; + + +#define MAX_INCLUDE_DIRECTORIES 128 +extern UINT CountIncludeDirs; +extern UINT CountSystemIncludeDirs; +extern DIRREC *IncludeDirs[MAX_INCLUDE_DIRECTORIES]; + + + +#define MAX_BUILD_DIRECTORIES 8192 + +extern UINT CountPassZeroDirs; +extern DIRREC *PassZeroDirs[MAX_BUILD_DIRECTORIES]; + +extern UINT CountCompileDirs; +extern DIRREC *CompileDirs[MAX_BUILD_DIRECTORIES]; + +extern UINT CountLinkDirs; +extern DIRREC *LinkDirs[MAX_BUILD_DIRECTORIES]; + +extern UINT CountShowDirs; +extern DIRREC *ShowDirs[MAX_BUILD_DIRECTORIES]; + + + +extern DIRREC *AllDirs; +extern CHAR CurrentDirectory[DB_MAX_PATH_LENGTH]; + +extern BOOL AllDirsInitialized; +extern BOOL AllDirsModified; + +extern USHORT GlobalSequence; +extern USHORT LocalSequence; + +extern BOOLEAN fConsoleInitialized; +extern DWORD NewConsoleMode; + +extern LPSTR BuildDefault; +extern LPSTR BuildParameters; + +extern LPSTR SystemIncludeEnv; +extern LPSTR LocalIncludeEnv; + +extern LPSTR BigBuf; +extern UINT BigBufSize; + +extern UINT RecurseLevel; + +extern FILE *LogFile; +extern FILE *WrnFile; +extern FILE *ErrFile; +extern FILE *IPGScriptFile; +extern FILE *IncFile; + +EXTERN_C UINT NumberCompileWarnings; +EXTERN_C UINT NumberCompileErrors; +EXTERN_C UINT NumberCompiles; +EXTERN_C UINT NumberLibraries; +EXTERN_C UINT NumberLibraryWarnings; +EXTERN_C UINT NumberLibraryErrors; +EXTERN_C UINT NumberLinks; +EXTERN_C UINT NumberLinkWarnings; +EXTERN_C UINT NumberLinkErrors; +EXTERN_C UINT NumberBinplaces; +EXTERN_C UINT NumberBinplaceWarnings; +EXTERN_C UINT NumberBinplaceErrors; + +extern char szAsterisks[]; +extern ULONG BuildStartTime; + +VOID ReportDirsUsage(VOID); + +VOID SetObjDir(BOOL fAlternate); + +// +// Stuff defined in buildscr.cpp +// + +typedef enum _PROC_EVENTS +{ + PE_PASS0_COMPLETE = WM_USER, + PE_PASS1_COMPLETE, + PE_PASS2_COMPLETE, + PE_EXIT +} PROC_EVENTS; + + +EXTERN_C HANDLE g_hMTThread; +EXTERN_C HANDLE g_hMTEvent; +EXTERN_C DWORD g_dwMTThreadId; + +EXTERN_C DWORD WINAPI MTScriptThread(LPVOID pv); +EXTERN_C void WaitForResume(BOOL fPause, PROC_EVENTS pe); +EXTERN_C void ExitMTScriptThread(); + +// +// Data Base functions defined in builddb.c +// + +PDIRREC +LoadDirDB(LPSTR DirName); + +#if DBG +VOID +PrintAllDirs(VOID); +#endif + +VOID +PrintSourceDBList(SOURCEREC *psr, int i); + +VOID +PrintFileDB(FILE *pf, FILEREC *pfr, int DetailLevel); + +VOID +PrintDirDB(DIRREC *pdr, int DetailLevel); + +FILEREC * +FindSourceFileDB(DIRREC *pdr, LPSTR pszRelPath, DIRREC **ppdr); + +DIRREC * +FindSourceDirDB( + LPSTR pszDir, // directory + LPSTR pszRelPath, // relative path + BOOL fTruncateFileName); // TRUE: drop last component of path + +SOURCEREC * +FindSourceDB( + SOURCEREC *psr, + FILEREC *pfr); + +SOURCEREC * +InsertSourceDB( + SOURCEREC **ppsrNext, + FILEREC *pfr, + UCHAR SubDirMask, + UCHAR SrcFlags); + +VOID +FreeSourceDB(SOURCEREC **ppsr); + +VOID +UnsnapIncludeFiles(FILEREC *pfr, BOOL fUnsnapGlobal); + +VOID +UnsnapAllDirectories(VOID); + +VOID +FreeAllDirs(VOID); + +PFILEREC +LookupFileDB( + PDIRREC DirDB, + LPSTR FileName); + + +PFILEREC +InsertFileDB( + PDIRREC DirDB, + LPSTR FileName, + ULONG DateTime, + USHORT Attr, + ULONG FileFlags); + +VOID +DeleteUnscannedFiles(PDIRREC DirDB); + +PINCLUDEREC +InsertIncludeDB( + PFILEREC FileDB, + LPSTR IncludeFileName, + USHORT IncFlags); + +VOID +LinkToCycleRoot(INCLUDEREC *pir, FILEREC *pfrRoot); + +VOID +RemoveFromCycleRoot(INCLUDEREC *pir, FILEREC *pfrRoot); + +VOID +MergeIncludeFiles(FILEREC *pfr, INCLUDEREC *pirList, FILEREC *pfrRoot); + +VOID +MarkIncludeFileRecords(PFILEREC FileDB); + +VOID +DeleteIncludeFileRecords(PFILEREC FileDB); + +PFILEREC +FindIncludeFileDB( + FILEREC *pfrSource, + FILEREC *pfrCompiland, + DIRREC *pdrBuild, + LPSTR pszSourceDirectory, + INCLUDEREC *IncludeDB); + +BOOL +SaveMasterDB(VOID); + +void +LoadMasterDB(VOID); + +PDIRREC +LoadMasterDirDB(LPSTR s); + +PFILEREC +LoadMasterFileDB(LPSTR s); + +PINCLUDEREC +LoadMasterIncludeDB(LPSTR s); + + +// +// Scanning functions defined in buildscn.c +// + +VOID +AddIncludeDir(DIRREC *pdr, UINT *pui); + +VOID +AddShowDir(DIRREC *pdr); + +VOID +ScanGlobalIncludeDirectory(LPSTR path); + +VOID +ScanIncludeEnv(LPSTR IncludeEnv); + +PDIRREC +ScanDirectory(LPSTR DirName); + +BOOL +ScanFile(PFILEREC FileDB); + + +// +// Functions defined in buildmak.c +// + +VOID +ScanSourceDirectories(LPSTR DirName); + +VOID +CompilePassZeroDirectories(VOID); + +VOID +CompileSourceDirectories(VOID); + +VOID +LinkSourceDirectories(VOID); + + +VOID +FreeDirSupData(DIRSUP *pds); + +VOID +FreeDirData(DIRREC *pdr); + +BOOL +CheckDependencies( + PTARGET Target, + FILEREC *FileDB, + BOOL CheckDate, + FILEREC **ppFileDBRoot); + +BOOL +CreateBuildDirectory(LPSTR Name); + +VOID +CreatedBuildFile(LPSTR DirName, LPSTR FileName); + +VOID +GenerateObjectsDotMac(DIRREC *DirDB, DIRSUP *pds, ULONG DateTimeSources); + +VOID +ExpandObjAsterisk( + LPSTR pbuf, + LPSTR pszpath, + LPSTR *ppszObjectDirectory); + +// +// Build -# functions defined in buildinc.c +// + +LPCTSTR +FindCountedSequenceInString( + IN LPCTSTR String, + IN LPCTSTR Sequence, + IN DWORD Length); + +BOOL +DoesInstanceMatchPattern( + IN LPCTSTR Instance, + IN LPCTSTR Pattern); + +LPSTR +CombinePaths( + IN LPCSTR ParentPath, + IN LPCSTR ChildPath, + OUT LPSTR TargetPath); + +VOID +CreateRelativePath( + IN LPCSTR SourceAbsName, + IN LPCSTR TargetAbsName, + OUT LPSTR RelativePath); + +BOOL +ShouldWarnInclude( + IN LPCSTR CompilandFullName, + IN LPCSTR IncludeeFullName); + +VOID +CheckIncludeForWarning( + IN LPCSTR CompilandDir, + IN LPCSTR CompilandName, + IN LPCSTR IncluderDir, + IN LPCSTR IncluderName, + IN LPCSTR IncludeeDir, + IN LPCSTR IncludeeName); + +// +// Utility functions defined in buildutl.c +// + +VOID +AllocMem(UINT cb, VOID **ppv, MemType mt); + +VOID +FreeMem(VOID **ppv, MemType mt); + +VOID +ReportMemoryUsage(VOID); + + +BOOL +MyOpenFile( + LPSTR DirName, + LPSTR FileName, + LPSTR Access, + FILE **Stream, + BOOL fBufferedIO); + +BOOL +OpenFilePush( + LPSTR pszdir, + LPSTR pszfile, + LPSTR pszCommentToEOL, + FILE **ppf + ); + +BOOL +SetupReadFile(LPSTR pszdir, LPSTR pszfile, LPSTR pszCommentToEOL, + FILE **ppf); + +ULONG +CloseReadFile(UINT *pcline); + +LPSTR +ReadLine(FILE *pf); + +UINT +ProbeFile( + LPSTR DirName, + LPSTR FileName); + +BOOL +EnsureDirectoriesExist( + LPSTR DirName); + +ULONG +DateTimeFile( + LPSTR DirName, + LPSTR FileName); + +ULONG +DateTimeFile2( + LPSTR DirName, + LPSTR FileName); + +ULONG (*pDateTimeFile)(LPSTR, LPSTR); + +BOOL (WINAPI * pGetFileAttributesExA)(LPCSTR, GET_FILEEX_INFO_LEVELS, LPVOID); + +BOOL +DeleteSingleFile( + LPSTR DirName, + LPSTR FileName, + BOOL QuietFlag); + +BOOL +DeleteMultipleFiles( + LPSTR DirName, + LPSTR FilePattern); + +BOOL +CloseOrDeleteFile( + FILE **Stream, + LPSTR DirName, + LPSTR FileName, + ULONG SizeThreshold); + +LPSTR +PushCurrentDirectory(LPSTR NewCurrentDirectory); + +VOID +PopCurrentDirectory(LPSTR OldCurrentDirectory); + +UINT +ExecuteProgram( + LPSTR ProgramName, + LPSTR CommandLine, + LPSTR MoreCommandLine, + BOOL MustBeSynchronous); + +VOID +WaitForParallelThreads(VOID); + + +BOOL +CanonicalizePathName( + LPSTR SourcePath, + UINT Action, + LPSTR FullPath); + + +#define CANONICALIZE_ONLY 0 +#define CANONICALIZE_FILE 1 +#define CANONICALIZE_DIR 2 + +LPSTR +FormatPathName( + LPSTR DirName, + LPSTR FileName); + +#if DBG +VOID +AssertPathString(LPSTR pszPath); +#else +#define AssertPathString(p) +#endif + +LPSTR +AppendString( + LPSTR Destination, + LPSTR Source, + BOOL PrefixWithSpace); + +LPSTR CopyString(LPSTR Destination, LPSTR Source, BOOL fPath); +VOID MakeString(LPSTR *Destination, LPSTR Source, BOOL fPath, MemType mt); +VOID MakeExpandedString(LPSTR *Destination, LPSTR Source); +VOID FreeString(LPSTR *Source, MemType mt); +LPSTR FormatNumber(ULONG Number); +LPSTR FormatTime(ULONG Seconds); + +BOOL AToX(LPSTR *pp, ULONG *pul); +BOOL AToD(LPSTR *pp, ULONG *pul); +EXTERN_C VOID __cdecl LogMsg(const char *pszfmt, ...); +EXTERN_C VOID __cdecl BuildMsg(const char *pszfmt, ...); +VOID __cdecl BuildMsgRaw(const char *pszfmt, ...); +VOID __cdecl BuildError(const char *pszfmt, ...); +EXTERN_C VOID __cdecl BuildErrorRaw(const char *pszfmt, ...); + +// +// Functions in buildsrc.c +// + +VOID +StartElapsedTime(VOID); + +VOID +PrintElapsedTime(VOID); + +BOOL +ReadDirsFile(DIRREC *DirDB); + + +VOID +ProcessLinkTargets(PDIRREC DirDB, LPSTR CurrentDirectory); + +BOOL +SplitToken(LPSTR pbuf, char chsep, LPSTR *ppstr); + +BOOL +MakeMacroString(LPSTR *pp, LPSTR p); + +VOID +SaveMacro(LPSTR pszName, LPSTR pszValue); + +VOID +FormatLinkTarget( + LPSTR path, + LPSTR *ObjectDirectory, + LPSTR TargetPath, + LPSTR TargetName, + LPSTR TargetExt); + +BOOL +ReadSourcesFile(DIRREC *DirDB, DIRSUP *pds, ULONG *pDateTimeSources); + +VOID +PostProcessSources(DIRREC *pdr, DIRSUP *pds); + +VOID +PrintDirSupData(DIRSUP *pds); + +//+--------------------------------------------------------------------------- +// +// Function: IsFullPath +// +//---------------------------------------------------------------------------- + +__inline BOOL +IsFullPath(char *pszfile) +{ + return(pszfile[0] == '\\' || (isalpha(pszfile[0]) && pszfile[1] == ':')); +} + +/* Single-purpose out-of-process file watcher. */ +int TryWatchMode(void); + +extern volatile LONG BuildChildFailures; diff --git a/sdktools/build.htm b/sdktools/build.htm new file mode 100644 index 0000000..09b12c0 --- /dev/null +++ b/sdktools/build.htm @@ -0,0 +1,331 @@ + + + +

BASEDIR

+The BASEDIR macro refers to the base of the source tree. +By default, +
    BASEDIR=$(_NTDRIVE)$(_NTROOT)
+The following three statements are equivalent, but using the third one is recommended. +
+    TARGETLIBS=d:\nt\public\sdk\lib\*\kernel32.lib
+    TARGETLIBS=$(BASEDIR)\public\sdk\lib\*\kernel32.lib
+    TARGETLIBS=$(SDK_LIB_PATH)\kernel32.lib
+
+ +sources +dirs +makefile +makefile.inc + +makefile.def +makefile.plt +build.dat +objects.mac +

BUILD_DEFAULT_TARGETS

+This envirnoment variable specifies the platform for which you are building. This variables allows the possibly of cross platform compilation, when such compilers are available. +Here is an exmaple of this environment variable: +
    BUILD_DEFAULT_TARGETS=-axp64
+ + +

BUILD_DEFAULT

+This envirnoment variable specifies the default options used by build.exe +Here is an example of this environment variable: +
    BUILD_DEFAULT=-eswM -nmake -i
+ + +

BUILD_MAKE_PROGRAM

+This envirnoment variable specifies the default program make executed by build.exe to in order to compile a directory. +The default value of this environment variable should be nmake.exe. + + +

BUILD_OPTIONS

+By default, build.exe will traverse the entire source tree, processing the directories listed in the DIRS section of the dirs file. +This envirnoment variable specifies which of the optional directories, listed under OPTIONAL_DIRS should be processed by build.exe +Here are some examples of this environment variable: +
    BUILD_OPTIONS=OptDir1 OptDir2
+would cause build to also process all OptDir1 and OptDir2 directories listed under an OPTIONAL_DIRS section. +
    BUILD_OPTIONS=~OptDir1 OptDir2
+would cause build to all OptDir2 directories listed under an OPTIONAL_DIRS section, but force it to skip over all OptDir1 directories, whether listed in the DIRS or OPTIONAL_DIRS section of a dirs file. + + +

CRT_INC_PATH

+

This envirnoment variable specifies the location of the C Runtime header files. The default value of this macro is:

+
    $(BASEDIR)\public\sdk\inc\crt
+

Set this macro in your environment variables if you wish to override the default location of the C Runtime header files.
+This macro should no be redefined from within a sources file.

+ + +

CRT_LIB_PATH

+

This envirnoment variable specifies the location of the C Runtime libraries. The default value of this macro is:

+
    $(BASEDIR)\public\sdk\lib\crt
+

Set this macro in your environment variables if you wish to override the default location of the C runtime libraries.
+This macro should no be redefined from within a sources file.

+

Here is an example of the usage of this macro:

+
    TARGETLIB=$(CRT_LIB_PATH)\libcntpr.lib \
$(SDK_LIB_PATH)\advapi32.lib
+ + +

DDK_INC_PATH

+

This macro specifies the location of the DDK header files. The default value of this macro is:

+
    $(BASEDIR)\public\ddk\inc
+

Set this macro in your environment variables if you wish to override the default location of the DDK header files.
+This macro should no be redefined from within a sources file.

+ + +

DDK_LIB_DEST

+

This macro specifies the destination location of a DDK library. The default value of this macro is:

+
    $(BASEDIR)\public\ddk\lib\*
+

Set this macro in your environment variables if you wish to override the default location of the DDK libraries.
+This macro should no be redefined from within a sources file.

+

Here is an example of the usage of this macro:

+
    TARGETPATHLIB=$(DDK_LIB_DEST)\ndis.lib
+ + +

DDK_LIB_PATH

+

This macro specifies the location of the DDK libraries. The default value of this macro is:

+
    $(BASEDIR)\public\ddk\lib
+

Set this macro in your environment variables if you wish to override the default location of the DDK libraries.
+This macro should no be redefined from within a sources file.

+

Here is an example of the usage of this macro:

+
    TARGETLIB=$(DDK_LIB_PATH)\ndis.lib \
$(DDK_LIB_PATH)\tdikrnl.lib
+ + +

DDK_LIB_PATH

+

This macro specifies the location of the DDK libraries. The default value of this macro is:

+
    $(BASEDIR)\public\ddk\lib
+

Set this macro in your environment variables if you wish to override the default location of the DDK libraries.
+This macro should no be redefined from within a sources file.

+

Here is an example of the usage of this macro:

+
    TARGETLIB=$(DDK_LIB_PATH)\ndis.lib \
$(DDK_LIB_PATH)\tdikrnl.lib
+ + +

MASTER_VERSION_FILE

+This macro contains the name of the master version file for Windows 2000. +It contains, among other things, the default operating system version number +which all binaries should have defined in the resource section. + +The default value of this variable is $(SDK_INC_PATH)\ntverp.h + +You should not override this value in your environment variables unless your component is not integrated in the Windows 2000 product (please contact BryanT for more information). + +

OAK_INC_PATH

+

This macro specifies the location of the OAK header files. The default value of this macro is:

+
    $(BASEDIR)\public\oak\inc
+

Set this macro in your environment variables if you wish to override the default location of the OAK header files.
+This macro should no be redefined from within a sources file.

+ + +

PRIVATE_INC_PATH

+

This macro specifies the location of the private windows 2000 header files. The default value of this macro is:

+
    $(BASEDIR)\private\inc
+

Set this macro in your environment variables if you wish to override the default location of the private windows 2000 header files.
+This macro should no be redefined from within a sources file.

+ + +

SDK_LIB_DEST

+

This macro specifies the destination location of a SDK library. The default value of this macro is:

+
    $(BASEDIR)\public\sdk\lib\*
+

Set this macro in your environment variables if you wish to override the default location of the SDK libraries.
+This macro should no be redefined from within a sources file.

+

Here is an example of the usage of this macro:

+
    TARGETPATHLIB=$(SDK_LIB_DEST)\kernel32.lib
+ + +

SDK_LIB_PATH

+

This macro specifies the location of the SDK libraries. The default value of this macro is:

+
    $(BASEDIR)\public\sdk\lib
+

Set this macro in your environment variables if you wish to override the default location of the SDK libraries.
+This macro should no be redefined from within a sources file.

+

Here is an example of the usage of this macro:

+
    TARGETLIB=$(SDK_LIB_PATH)\kernel32.lib \
$(SDK_LIB_PATH)\advapi32.lib
+ + +

WDM_INC_PATH

+

This macro specifies the location of the WDM header file. The default value of this macro is:

+
    $(BASEDIR)\public\ddk\inc\wdm
+

Set this macro in your environment variables if you wish to override the default location of the WDM header files.
+This macro should no be redefined from within a sources file.

+ + + + +

C_DEFINES - optional

+Use this macro to specify switches you want passed to the compiler. +Typically, they are compiler #defines. +You might specify: +
    C_DEFINES = -DENABLE_FEATURE1
+to define ENABLE_FEATURE1 to the compiler. +C_DEFINES gets passed to both the C compiler and the MIDL compiler. +Therefore, you cannot put compiler optimization or other machine or +tool specific switches in the C_DEFINES macro. +Use MSC_OPTIMIZATION for C compiler only optimizations +See also ASM_DEFINES, RC_DEFINES + + +

DLLORDER - optional

+When you are building a DLL, you can specify an order file that will be passed +to the linker. This order file lists the order in which functions should be +layed out in the image. +This is the same as NTPROFILEINPUT except that +a full name for the profile can be specified. + + +

EXEPROFILEINPUT - obsolete

+Use NTPROFILEINPUT instead. + + + + +

INCLUDES - optional

+

Build.exe use a default list of public include directories from which to search for header files. +The default list of include directories is dependent on the value of TARGETTYPE in the sources file.

+

Use the INCLUDES macro to indicate an additional list of private include directories to be searched for include files during compilation. +Separate the entries in this list with a semicolon. +Path names can be absolute or relative.

+For example: +
+    INCLUDES=..\inc;..\..\inc
+
+    INCLUDES=$(INCLUDES); \
+             h;           \
+             ..\headers;
+
+The INCLUDES macro is read by build.exe and passed to the MAKE program. +The list of directories in the INCULDES macro will have precedence over the default include directories. + + +

MAJORCOMP - obsolete

+Please remove from your sources file + +

MINORCOMP - obsolete

+Please remove from your sources file + + +

NO_NTDLL - optional

+Set this macro to 0 to force your binary not to link against NTDLL.LIB. + +

NTPROFILEINPUT - optional

+When you are building a DLL, you can specify an order file that will be passed +to the linker. This order file lists the order in which functions should be +layed out in the image. + +To use the profile, specify the following in your sources file: +
    NTPROFILEINPUT=1
+If you set this value, build.exe expect to find +
    $(TARGETNAME).prf
+in the current subdirectory. +

See also DLLORDER

+ + +

PNP_POWER - obsolete

+Please remove from your sources file + + +

SOURCES - required

+

The SOURCES macro is the most important macro in a sources file. +It specifies the list of files to be compiled. +Build.exe will look at these files and generate a dependency list. +For any source file whose dependencies changed, build.exe will rebuild +this file.

+

Use this macro to list your source filenames (except for the file containing +main in the case where UMAPPL or UMTEST +is used. Include the filename extension and separate the entries in this list +with spaces or tabs.

+

Nested paths are relative to the current SOURCES directory. Prefix a path +with @/ to resolve it under BASEDIR:

+
    SOURCES=main.c nested/worker.c @/shared/alpha/core.c
+

Project source paths remain inside BASEDIR. Object names include a stable +path-derived suffix, allowing identical source basenames from different directories. +The project makefile defines CC, CXX, AS, RC, and their matching flags for +explicit source rules.

+ + +

TARGETEXT - optional

+Set this macro to specify the extension name (such as .cpl) when you want your binary to have something other than the default extension generated by TARGETTYPE. +If you specify something unexpected, you will see a message "Unexpected Target Ext." If you want an extension added to the Build Utility, contact Bryan Tuttle (bryant). + + +

TARGETLIBS - required

+

Set this macro to specify the set of libraries with which your final image must be linked.

+If your components generates a library (.lib) and this library must link in code from other libraries, use the LINKLIBS macro. +Use LINKLIBS only for the case that meets the following conditions: +You are building a dynamic link. +You are exporting something that's defined in some other component library that you also build. +In your dirs file in the subdirectory above, you have ordered it so that the component libraries are around before you build the dynamic link. +There is a similar macro called UMLIBSUMLIBS that you can use if you are building UMAPPLs. + + +

TARGETNAME - required

+Use this macro to specify the name of the binary being built, excluding the filename extension. +You must have this macro in your sources file. + + +

TARGETPATH - required

+Use this macro to specify the target directory in which the resulting binary will be placed. +Notice that object files always end up in the obj subdirectory. Object file can only be generated in the $(O) directory. +You must have this macro in your sources file. For example: + + +
    TARGETPATH=obj
+See Also TARGETPATHLIB + + +

TARGETPATHLIB - optional

+Set this value to specify where to put the import library associated with this binary.
+When you are building a DLL, you create the DLL itself and you create an import library that other images can use to reference functions exported by your DLL.
+
    TARGETPATHLIB=$(SDK_LIB_PATH)mydll.lib
+

Setting TARGETPATH independently from TARGETPATHLIB allows the binary to be kept in the +current directory, while the .lib and .exp files can be shared with other components.

+ + +

TARGETTYPE - required

+Use this macro to specify the type of binary being built. This is typically LIBRARY or +DYNLINK (for DLLs), but can take other values. This is a required field in the sources file. +TARGETTYPE allows build.exe to select appropriate defaults for include paths and link options. +You must have this macro in your sources file. +The valid values for TARGETYPE include: + + + + + + + + + + + + +
TARGETTYPE values File Extension Description
PROGLIB .exe Executable program which also exports functions for other programs.
PROGRAM .exe Simple user mode program.
DYNLINK .dll Dynamic Link Library (dll).
LIBRARY .lib Component library whose code will be linked into another binary (such as a dll).
DRIVER_LIBRARY .lib Component library for a driver. The only difference with the LIBRARY type is that the default header file include path is different.
DRIVER .sys Kernel mode driver. +
EXPORT_DRIVER .sys Kernel mode driver which also exports routines other drivers can link against and call.
HAL .dll Hardware Abstraction Layer (HAL)
BOOTPGM .exe Kernel mode driver.
MINIPORT .sys Kernel mode driver which does not link against ntoskrnl.lib or hal.lib.
GDI_DRIVER .dll Kernel mode driver which only links against win32k.sys (Display or print driver).
+ + +

UMAPPL

+ + +

UMAPPLEXT

+Use this macro to specify the extension name (for example .COM or .SCR) that +will be appended to the name specified in UMAPPL. +Use UMAPPLEXT when you want the extension to be something other than .exe. +Contact Bryan Tuttle if you need to add a new type of extension. + + +

UMLIBS

+ + +

UMTEST

+ + +

Sample Driver Sources File

+ +
+TARGETNAME=sample
+TARGETPATH=obj
+TARGETTYPE=DRIVER
+
+TARGETLIBS=$(DDK_LIB_PATH)\videoprt.lib
+
+SOURCES=file1.c \
file2.c \
file3.c + +
+ + diff --git a/sdktools/builddb.c b/sdktools/builddb.c new file mode 100644 index 0000000..5c9d1f2 --- /dev/null +++ b/sdktools/builddb.c @@ -0,0 +1,2081 @@ +//+--------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1989 - 1994 +// +// File: builddb.c +// +// Contents: Contains the file and directory database manipulation +// functions. +// +// History: 16-May-94 SteveWo Created +// ... see SLM logs +// 26-Jul-94 LyleC Cleanup/Add Pass0 Support +// +//---------------------------------------------------------------------------- + +#include "build.h" + +BOOL fAssertCleanTree = FALSE; + +typedef struct _FLAGSTRINGS { + ULONG Mask; + LPSTR pszName; +} FLAGSTRINGS; + +FLAGSTRINGS DirFlags[] = { + { DIRDB_SOURCES, "Sources" }, + { DIRDB_DIRS, "Dirs" }, + { DIRDB_MAKEFILE, "Makefile" }, + { DIRDB_MAKEFIL0, "Makefil0" }, + { DIRDB_TARGETFILE0, "Targetfile0" }, + { DIRDB_TARGETFILES, "Targetfiles" }, + { DIRDB_RESOURCE, "Resource" }, + { DIRDB_PASS0, "PassZero" }, + { DIRDB_SOURCES_SET, "SourcesSet" }, + { DIRDB_CHICAGO_INCLUDES, "ChicagoIncludes" }, + { DIRDB_NEW, "New" }, + { DIRDB_SCANNED, "Scanned" }, + { DIRDB_SHOWN, "Shown" }, + { DIRDB_GLOBAL_INCLUDES, "GlobalIncludes" }, + { DIRDB_SYNCHRONIZE_BLOCK, "SynchronizeBlock" }, + { DIRDB_SYNCHRONIZE_DRAIN, "SynchronizeDrain" }, + { DIRDB_COMPILENEEDED, "CompileNeeded" }, + { DIRDB_COMPILEERRORS, "CompileErrors" }, + { DIRDB_SOURCESREAD, "SourcesRead" }, + { DIRDB_DLLTARGET, "DllTarget" }, + { DIRDB_LINKNEEDED, "LinkNeeded" }, + { DIRDB_FORCELINK, "ForceLink" }, + { DIRDB_PASS0NEEDED, "Pass0Needed" }, + { DIRDB_MAKEFIL1, "Makefil1" }, + { DIRDB_CHECKED_ALT_DIR, "CheckedAltDir" }, + { 0, NULL }, +}; + +FLAGSTRINGS FileFlags[] = { + { FILEDB_SOURCE, "Source" }, + { FILEDB_DIR, "Dir" }, + { FILEDB_HEADER, "Header" }, + { FILEDB_ASM, "Asm" }, + { FILEDB_MASM, "Masm" }, + { FILEDB_RC, "Rc" }, + { FILEDB_C, "C" }, + { FILEDB_MIDL, "Midl" }, + { FILEDB_ASN, "Asn" }, + { FILEDB_JAVA, "Java" }, + { FILEDB_MOF, "ManagedObjectFormat" }, + { FILEDB_CSHARP, "C#"}, + { FILEDB_SCANNED, "Scanned" }, + { FILEDB_OBJECTS_LIST, "ObjectsList" }, + { FILEDB_FILE_MISSING, "FileMissing" }, + { FILEDB_MKTYPLIB, "MkTypeLib" }, + { FILEDB_MULTIPLEPASS, "MultiplePass" }, + { FILEDB_PASS0, "PassZero" }, + { 0, NULL }, +}; + +FLAGSTRINGS IncludeFlags[] = { + { INCLUDEDB_LOCAL, "Local" }, + { INCLUDEDB_POST_HDRSTOP, "PostHdrStop" }, + { INCLUDEDB_MISSING, "Missing" }, + { INCLUDEDB_GLOBAL, "Global" }, + { INCLUDEDB_SNAPPED, "Snapped" }, + { INCLUDEDB_CYCLEALLOC, "CycleAlloc" }, + { INCLUDEDB_CYCLEROOT, "CycleRoot" }, + { INCLUDEDB_CYCLEORPHAN, "CycleOrphan" }, + { 0, NULL }, +}; + +FLAGSTRINGS SourceFlags[] = { + { SOURCEDB_SOURCES_LIST, "SourcesList" }, + { SOURCEDB_FILE_MISSING, "FileMissing" }, + { SOURCEDB_PCH, "Pch" }, + { SOURCEDB_OUT_OF_DATE, "OutOfDate" }, + { SOURCEDB_COMPILE_NEEDED, "CompileNeeded" }, + { 0, NULL }, +}; + +// +// Function prototypes +// + +VOID +FreeFileDB(PFILEREC *FileDB); + +VOID +PrintFlags(FILE *pf, ULONG Flags, FLAGSTRINGS *pfs); + + +//+--------------------------------------------------------------------------- +// +// Function: CheckSum +// +// Synopsis: Returns a checksum value for a string. +// +//---------------------------------------------------------------------------- + +USHORT +CheckSum(LPSTR psz) +{ + USHORT sum = 0; + + while (*psz != '\0') { + if (sum & 0x8000) { + sum = ((sum << 1) | 1) + *psz++; + } + else { + sum = (sum << 1) + *psz++; + } + } + return(sum); +} + + +//+--------------------------------------------------------------------------- +// +// Function: FindSourceDirDB +// +// Synopsis: Builds a path from the two given components and returns +// a filled DIRREC structure from it. +// +// Arguments: [pszDir] -- Directory +// [pszRelPath] -- Path relative to [pszDir] +// [fTruncateFileName] -- Remove a filename from [pszRelPath] +// +// Returns: A filled DIRREC structure for the given directory. +// +// Notes: If the directory does not exist in the data base, then a +// DIRREC structure will be returned with the DIRDB_NEW flag +// set and no other data (i.e. the directory will not have +// been scanned.) +// +//---------------------------------------------------------------------------- + +DIRREC * +FindSourceDirDB( + LPSTR pszDir, // directory + LPSTR pszRelPath, // relative path + BOOL fTruncateFileName) // TRUE: drop last component of path +{ + LPSTR pszFile; + char path[DB_MAX_PATH_LENGTH]; + + AssertPathString(pszDir); + AssertPathString(pszRelPath); + strcpy(path, pszDir); + if (path[0] != '\0') + strcat(path, "\\"); + strcat(path, pszRelPath); + + pszFile = path + strlen(path); + if (fTruncateFileName) { + while (pszFile > path) { + pszFile--; + if (*pszFile == '\\' || *pszFile == '/') { + *pszFile = '\0'; + break; + } + } + } + if (!CanonicalizePathName(path, CANONICALIZE_ONLY, path)) { + return(NULL); + } + if (DEBUG_4) { + BuildMsgRaw( + "FindSourceDirDB(%s, %s, %u)\n", + path, + pszFile, + fTruncateFileName); + } + AssertPathString(path); + return(LoadDirDB(path)); +} + + +//+--------------------------------------------------------------------------- +// +// Function: FindSourceFileDB +// +// Synopsis: Returns a FILEREC with information about the given file. +// +// Arguments: [pdr] -- DIRREC giving directory from which to start +// looking for [pszRelPath] +// [pszRelPath] -- Relative path from [pdr] of the file +// [ppdr] -- [out] DIRREC of directory actually containing +// the file. Can be NULL. +// +// Returns: FILEREC for file of interest. +// +// Notes: If the directory containing the file has not yet been scanned, +// then it will be scanned using ScanDirectory(). +// +//---------------------------------------------------------------------------- + +FILEREC * +FindSourceFileDB( + DIRREC *pdr, + LPSTR pszRelPath, + DIRREC **ppdr) +{ + LPSTR p, pszFile; + + AssertPathString(pszRelPath); + + if (strchr(pszRelPath, '\\') != NULL) { + // There's a path component in this filename. Let's see where it points to. + if ( (pszRelPath[0] == '\\') || /* Absolute from root or UNC Path */ + (pszRelPath[1] == ':' )) /* drive : path */ + { + pdr = FindSourceDirDB("", pszRelPath, TRUE); + } else { + pdr = FindSourceDirDB(pdr->Name, pszRelPath, TRUE); + } + } + if (ppdr != NULL) { + *ppdr = pdr; + } + if (pdr == NULL ) { + return(NULL); + } + pszFile = pszRelPath; + for (p = pszFile; *p != '\0'; p++) { + if (*p == '\\') { + pszFile = p + 1; + } + } + if (DEBUG_4) { + BuildMsgRaw("FindSourceFileDB(%s, %s)\n", pdr->Name, pszFile); + } + + // + // Scan the directory containing the file if we haven't already. + // + if ((pdr->DirFlags & DIRDB_SCANNED) == 0) { + if (DEBUG_1) { + BuildMsgRaw( + "FindSourceFileDB(%s, %s) Delayed scan\n", + pdr->Name, + pszFile); + } + pdr = ScanDirectory(pdr->Name); + if (pdr == NULL) { + return(NULL); + } + } + + return(LookupFileDB(pdr, pszFile)); +} + + +//+--------------------------------------------------------------------------- +// +// Function: InsertSourceDB +// +// Synopsis: Insert a file listed in SOURCES= into a list of SOURCEREC +// structures. +// +// Arguments: [ppsrNext] -- Head of list of sources files to add to. +// [pfr] -- File to be inserted. +// [SubDirMask] -- Indicates what directory the file is in. +// (Current, Parent, or a machine-specific dir) +// [SrcFlags] -- SOURCEDB flags appropriate to this file. +// +// Returns: SOURCEREC that was inserted. May be ignored. +// +// Notes: InsertSourceDB maintains a sort order for PickFirst() based +// first on the filename extension, then on the subdirectory +// mask. +// +// Two exceptions to the alphabetic sort are: +// - No extension sorts last. +// - .rc extension sorts first. +// +// If the file is already in the list of sources then this +// function just updates the flags and returns. +// +//---------------------------------------------------------------------------- + +SOURCEREC * +InsertSourceDB( + SOURCEREC **ppsrNext, + FILEREC *pfr, + UCHAR SubDirMask, + UCHAR SrcFlags) +{ + SOURCEREC *psr; + SOURCEREC **ppsrInsert; + LPSTR pszext; + BOOL fRC; + + AssertFile(pfr); + + ppsrInsert = NULL; + pszext = strrchr(pfr->Name, '.'); + fRC = FALSE; + if (pszext != NULL && _stricmp(pszext, ".rc") == 0) { + fRC = TRUE; + } + for ( ; (psr = *ppsrNext) != NULL; ppsrNext = &psr->psrNext) { + LPSTR p; + int r; + + AssertSource(psr); + if (psr->pfrSource == pfr) { + assert(psr->SourceSubDirMask == SubDirMask); + psr->SrcFlags = SrcFlags; + return(psr); + } + if (ppsrInsert == NULL && pszext != NULL) { + if ((p = strrchr(psr->pfrSource->Name, '.')) == NULL) { + r = -1; // insert new file here + } + else { + r = strcmp(pszext, p); + if (r != 0) { + if (fRC) { + r = -1; // insert new RC file here + } + else if (strcmp(p, ".rc") == 0) { + r = 1; // old RC file comes first + } + } + } + if (r < 0 || SubDirMask > psr->SourceSubDirMask) { + ppsrInsert = ppsrNext; + } + } + } + AllocMem(sizeof(SOURCEREC), &psr, MT_SOURCEDB); + memset(psr, 0, sizeof(*psr)); + SigCheck(psr->Sig = SIG_SOURCEREC); + + if (ppsrInsert != NULL) { + ppsrNext = ppsrInsert; + } + psr->psrNext = *ppsrNext; + *ppsrNext = psr; + + psr->pfrSource = pfr; + pfr->FileFlags |= FILEDB_SOURCEREC_EXISTS; + psr->SourceSubDirMask = SubDirMask; + psr->SrcFlags = SrcFlags; + return(psr); +} + + +//+--------------------------------------------------------------------------- +// +// Function: FindSourceDB +// +// Synopsis: Finds the SOURCEREC in a list which corresponds to the given +// FILEREC. +// +//---------------------------------------------------------------------------- + +SOURCEREC * +FindSourceDB( + SOURCEREC *psr, + FILEREC *pfr) +{ + + while (psr != NULL) { + AssertSource(psr); + if (psr->pfrSource == pfr) { + return(psr); + } + psr = psr->psrNext; + } + return(NULL); +} + + +//+--------------------------------------------------------------------------- +// +// Function: FreeSourceDB +// +// Synopsis: Frees a list of SOURCERECs +// +// Arguments: [ppsr] -- List to free +// +//---------------------------------------------------------------------------- + +VOID +FreeSourceDB(SOURCEREC **ppsr) +{ + if (*ppsr != NULL) { + SOURCEREC *psr; + SOURCEREC *psrNext; + + psr = *ppsr; + AssertSource(psr); + psrNext = psr->psrNext; + SigCheck(psr->Sig = 0); + FreeString(&psr->ProjectSource, MT_DIRSTRING); + FreeString(&psr->ObjectStem, MT_DIRSTRING); + FreeString(&psr->ObjectSourceName, MT_DIRSTRING); + FreeMem(ppsr, MT_SOURCEDB); + *ppsr = psrNext; + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: FreeIncludeDB +// +//---------------------------------------------------------------------------- + +VOID +FreeIncludeDB(INCLUDEREC **ppir) +{ + if (*ppir != NULL) { + INCLUDEREC *pir; + INCLUDEREC *pirNext; + + pir = *ppir; + AssertInclude(pir); + AssertCleanTree(pir, NULL); // Tree must be clean + pirNext = pir->Next; + SigCheck(pir->Sig = 0); + FreeMem(ppir, MT_INCLUDEDB); + *ppir = pirNext; + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: FreeFileDB +// +//---------------------------------------------------------------------------- + +VOID +FreeFileDB(FILEREC **ppfr) +{ + if (*ppfr != NULL) { + FILEREC *pfr; + FILEREC *pfrNext; + + pfr = *ppfr; + AssertFile(pfr); + UnsnapIncludeFiles(pfr, TRUE); + while (pfr->IncludeFiles) { + FreeIncludeDB(&pfr->IncludeFiles); + } + pfrNext = pfr->Next; + SigCheck(pfr->Sig = 0); + FreeMem(ppfr, MT_FILEDB); + *ppfr = pfrNext; + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: FreeDirDB +// +//---------------------------------------------------------------------------- + +VOID +FreeDirDB(DIRREC **ppdr) +{ + if (*ppdr != NULL) { + DIRREC *pdr; + DIRREC *pdrNext; + + pdr = *ppdr; + AssertDir(pdr); + FreeDirData(pdr); + while (pdr->Files) { + FreeFileDB(&pdr->Files); + } + pdrNext = pdr->Next; + SigCheck(pdr->Sig = 0); + FreeMem(ppdr, MT_DIRDB); + *ppdr = pdrNext; + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: FreeAllDirs +// +//---------------------------------------------------------------------------- + +VOID +FreeAllDirs(VOID) +{ + while (AllDirs != NULL) { + FreeDirDB(&AllDirs); +#if DBG + if (fDebug & 8) { + BuildMsgRaw("Freed one directory\n"); + PrintAllDirs(); + } +#endif + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: LookupDirDB +// +// Synopsis: Searches the database for a given directory. +// +// Arguments: [DirName] -- Directory to search for. +// +// Returns: DIRREC of the given directory. NULL if not found. +// +// Notes: If the directory is not in the database it will not be added. +// Use LoadDirDB in this case. +// +//---------------------------------------------------------------------------- + +PDIRREC +LookupDirDB( + LPSTR DirName + ) +{ + PDIRREC *DirDBNext = &AllDirs; + PDIRREC DirDB; + USHORT sum; + + AssertPathString(DirName); + sum = CheckSum(DirName); + while (DirDB = *DirDBNext) { + if (sum == DirDB->CheckSum && strcmp(DirName, DirDB->Name) == 0) { + + if (DirDB->FindCount == 0 && fForce) { + FreeDirDB(DirDBNext); + return(NULL); + } + DirDB->FindCount++; + + // Move to head of list to make next lookup faster + + // *DirDBNext = DirDB->Next; + // DirDB->Next = AllDirs; + // AllDirs = DirDB; + + return(DirDB); + } + DirDBNext = &DirDB->Next; + } + return(NULL); +} + + +//+--------------------------------------------------------------------------- +// +// Function: LoadDirDB +// +// Synopsis: Searches the database for a directory name, and if not found +// creates a new DIRREC entry in the database. +// +// Arguments: [DirName] -- Directory to search for. +// +// Returns: Filled in DIRREC structure for the given directory. +// +// Notes: The directory will not be scanned if it wasn't in the +// database. Use ScanDirectory to scan the directory, +// however, note that InsertSourceDB will automatically scan +// the directory only when necessary. +// +//---------------------------------------------------------------------------- + +PDIRREC +LoadDirDB( + LPSTR DirName + ) +{ + UINT i; + PDIRREC DirDB, *DirDBNext; + LPSTR s; + + AssertPathString(DirName); + if (DirDB = LookupDirDB(DirName)) { + return(DirDB); + } + + if (ProbeFile(NULL, DirName) == -1) { + return( NULL ); + } + + DirDBNext = &AllDirs; + while (DirDB = *DirDBNext) { + DirDBNext = &DirDB->Next; + } + + AllDirsModified = TRUE; + + AllocMem(sizeof(DIRREC) + strlen(DirName), &DirDB, MT_DIRDB); + memset(DirDB, 0, sizeof(*DirDB)); + SigCheck(DirDB->Sig = SIG_DIRREC); + + DirDB->DirFlags = DIRDB_NEW; + DirDB->FindCount = 1; + CopyString(DirDB->Name, DirName, TRUE); + DirDB->CheckSum = CheckSum(DirDB->Name); + + if (DEBUG_1) { + BuildMsgRaw("LoadDirDB creating %s\n", DirDB->Name); + } + + *DirDBNext = DirDB; + return( DirDB ); +} + +//+--------------------------------------------------------------------------- +// +// Debug helper functions to print parts of the database. +// +//---------------------------------------------------------------------------- + +#if DBG +VOID +PrintAllDirs(VOID) +{ + DIRREC **ppdr, *pdr; + + for (ppdr = &AllDirs; (pdr = *ppdr) != NULL; ppdr = &pdr->Next) { + PrintDirDB(pdr, 1|2|4); + } +} +#endif + + +VOID +PrintFlags(FILE *pf, ULONG Flags, FLAGSTRINGS *pfs) +{ + LPSTR p = ","; + + while (pfs->pszName != NULL) { + if (pfs->Mask & Flags) { + fprintf(pf, "%s %s", p, pfs->pszName); + p = ""; + } + pfs++; + } + fprintf(pf, szNewLine); +} + + +BOOL +PrintIncludes(FILE *pf, FILEREC *pfr, BOOL fTree) +{ + INCLUDEREC *pir; + BOOL fMatch = pfr->IncludeFilesTree == pfr->IncludeFiles; + + pir = fTree? pfr->IncludeFilesTree : pfr->IncludeFiles; + while (pir != NULL) { + LPSTR pszdir = ""; + char OpenQuote, CloseQuote; + + if (pir->IncFlags & INCLUDEDB_LOCAL) { + OpenQuote = CloseQuote = '"'; + } + else { + OpenQuote = '<'; + CloseQuote = '>'; + } + + fprintf( + pf, + " %c#include %c%s%c", + fMatch? ' ' : fTree? '+' : '-', + OpenQuote, + pir->Name, + CloseQuote); + if (pir->Version != 0) { + fprintf(pf, " (v%d)", pir->Version); + } + if (pir->pfrCycleRoot != NULL) { + fprintf( + pf, + " (root=%s\\%s)", + pir->pfrCycleRoot->Dir->Name, + pir->pfrCycleRoot->Name); + } + if (pir->pfrInclude != NULL) { + if (pir->pfrInclude->Dir == pfr->Dir) { + pszdir = "."; + } + else { + pszdir = pir->pfrInclude->Dir->Name; + } + } + fprintf(pf, " %s", pszdir); + PrintFlags(pf, pir->IncFlags, IncludeFlags); + if (pir->NextTree != pir->Next) { + fMatch = FALSE; + } + pir = fTree? pir->NextTree : pir->Next; + } + return(fMatch); +} + + +VOID +PrintSourceDBList(SOURCEREC *psr, int i) +{ + TARGET_MACHINE_INFO *pMachine; + + pMachine = i < 0 ? TargetMachines[0] : PossibleTargetMachines[i]; + + for ( ; psr != NULL; psr = psr->psrNext) { + assert( + (psr->SourceSubDirMask & ~TMIDIR_PARENT) == 0 || + pMachine->SourceSubDirMask == + (psr->SourceSubDirMask & ~TMIDIR_PARENT)); + BuildMsgRaw( + " %s%s%s%s%s", + (psr->SourceSubDirMask & TMIDIR_PARENT)? "..\\" : "", + (psr->SourceSubDirMask & ~TMIDIR_PARENT)? + pMachine->SourceDirectory : "", + (psr->SourceSubDirMask & ~TMIDIR_PARENT)? "\\" : "", + psr->ProjectSource ? psr->ProjectSource : psr->pfrSource->Name, + (psr->SrcFlags & SOURCEDB_PCH)? + " (pch)" : + (psr->SrcFlags & SOURCEDB_SOURCES_LIST) == 0? + " (From exe list)" : ""); + PrintFlags(stderr, psr->SrcFlags, SourceFlags); + } +} + + +VOID +PrintFileDB(FILE *pf, FILEREC *pfr, int DetailLevel) +{ + fprintf(pf, " File: %s", pfr->Name); + if (pfr->FileFlags & FILEDB_DIR) { + fprintf(pf, " (Sub-Directory)"); + } + else + if (pfr->FileFlags & (FILEDB_SOURCE | FILEDB_HEADER)) { + LPSTR pszType = (pfr->FileFlags & FILEDB_SOURCE)? "Source" : "Header"; + + if (pfr->FileFlags & FILEDB_ASM) { + fprintf(pf, " (Assembler (CPP) %s File)", pszType); + } + else + if (pfr->FileFlags & FILEDB_MASM) { + fprintf(pf, " (Assembler (MASM) %s File)", pszType); + } + else + if (pfr->FileFlags & FILEDB_RC) { + fprintf(pf, " (Resource Compiler (RC) %s File)", pszType); + } + else + if (pfr->FileFlags & FILEDB_MIDL) { + fprintf(pf, " (MIDL %s File)", pszType); + } + else + if (pfr->FileFlags & FILEDB_ASN) { + fprintf(pf, " (ASN %s File)", pszType); + } + else + if (pfr->FileFlags & FILEDB_MKTYPLIB) { + fprintf(pf, " (Type Library (MkTypLib) %s File)", pszType); + } + else { + fprintf(pf, " (C %s File)", pszType); + } + if ((pfr->FileFlags & FILEDB_HEADER) && pfr->Version != 0) { + fprintf(pf, " (v%d)", pfr->Version); + } + if (pfr->GlobalSequence != 0) { + fprintf(pf, " (GlobalSeq=%d)", pfr->GlobalSequence); + } + if (pfr->LocalSequence != 0) { + fprintf(pf, " (LocalSeq=%d)", pfr->LocalSequence); + } + fprintf(pf, " - %u lines", pfr->SourceLines); + } + PrintFlags(pf, pfr->FileFlags, FileFlags); + + if (pfr->IncludeFiles != NULL) { + BOOL fMatch; + + fMatch = PrintIncludes(pf, pfr, FALSE); + if (pfr->IncludeFilesTree != NULL) { + fprintf(pf, " IncludeTree %s\n", fMatch? "matches" : "differs:"); + if (!fMatch) { + PrintIncludes(pf, pfr, TRUE); + } + } + } +} + + +VOID +PrintDirDB(DIRREC *pdr, int DetailLevel) +{ + FILE *pf = stderr; + FILEREC *pfr, **ppfr; + + if (DetailLevel & 1) { + fprintf(pf, "Directory: %s", pdr->Name); + if (pdr->DirFlags & DIRDB_DIRS) { + fprintf(pf, " (Dirs Present)"); + } + if (pdr->DirFlags & DIRDB_SOURCES) { + fprintf(pf, " (Sources Present)"); + } + if (pdr->DirFlags & DIRDB_MAKEFILE) { + fprintf(pf, " (Makefile Present)"); + } + PrintFlags(pf, pdr->DirFlags, DirFlags); + } + if (DetailLevel & 2) { + if (pdr->TargetPath != NULL) { + fprintf(pf, " TargetPath: %s\n", pdr->TargetPath); + } + if (pdr->TargetName != NULL) { + fprintf(pf, " TargetName: %s\n", pdr->TargetName); + } + if (pdr->TargetExt != NULL) { + fprintf(pf, " TargetExt: %s\n", pdr->TargetExt); + } + if (pdr->KernelTest != NULL) { + fprintf(pf, " KernelTest: %s\n", pdr->KernelTest); + } + if (pdr->UserAppls != NULL) { + fprintf(pf, " UserAppls: %s\n", pdr->UserAppls); + } + if (pdr->UserTests != NULL) { + fprintf(pf, " UserTests: %s\n", pdr->UserTests); + } + if (pdr->PchObj != NULL) { + fprintf(pf, " PchObj: %s\n", pdr->PchObj); + } + if (pdr->Pch != NULL) { + fprintf(pf, " Pch: %s\n", pdr->Pch); + } + } + if (DetailLevel & 4) { + for (ppfr = &pdr->Files; (pfr = *ppfr) != NULL; ppfr = &pfr->Next) { + PrintFileDB(pf, pfr, DetailLevel); + } + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: LookupFileDB +// +// Synopsis: Search the database for the given file. +// +// Arguments: [DirDB] -- Directory containing the file +// [FileName] -- File to look for +// +// Returns: FILEREC of file if found, NULL if not. +// +// Notes: The file will not be added to the database if not already +// there. +// +//---------------------------------------------------------------------------- + +PFILEREC +LookupFileDB( + PDIRREC DirDB, + LPSTR FileName + ) +{ + PFILEREC FileDB, *FileDBNext; + USHORT sum; + + AssertPathString(FileName); + sum = CheckSum(FileName); + if (DEBUG_4) { + BuildMsgRaw("LookupFileDB(%s, %s) - ", DirDB->Name, FileName); + } + FileDBNext = &DirDB->Files; + while (FileDB = *FileDBNext) { + if (sum == FileDB->CheckSum && strcmp(FileName, FileDB->Name) == 0) { + if (DEBUG_4) { + BuildMsgRaw("success\n"); + } + return(FileDB); + } + FileDBNext = &FileDB->Next; + } + + if (DEBUG_4) { + BuildMsgRaw("failure\n"); + } + return(NULL); +} + +//+--------------------------------------------------------------------------- +// +// FILEDESC +// +// FileDesc is a table describing file names and patterns that we recognize +// and handle specially. WARNING: This table is ordered so the patterns +// at the front are necessarily more specific than those later on. +// +//---------------------------------------------------------------------------- + +char szMakefile[] = "#"; +char szClang[] = "//"; +char szAsn[] = "--"; +char szMasm[] = ";"; + +// +// N.B. The first entry in the file descriptor list is an entry that is +// optionally filled with the name of the target dirs file for the +// first build target. +// + +FILEDESC FileDesc[] = +{ { "/0dirs", szMakefile, FALSE, 0, DIRDB_DIRS }, + { "makefile", szMakefile, FALSE, 0, DIRDB_MAKEFILE }, + { "makefil0", szMakefile, FALSE, 0, DIRDB_MAKEFIL0 | DIRDB_PASS0 }, + { "makefil1", szMakefile, FALSE, 0, DIRDB_MAKEFIL1 }, + { "sources", szMakefile, FALSE, 0, DIRDB_SOURCES }, + { "dirs", szMakefile, FALSE, 0, DIRDB_DIRS }, + { "mydirs", szMakefile, FALSE, 0, DIRDB_DIRS }, + + { "makefile.inc", szMakefile, FALSE, 0, 0 }, + { "common.ver", szClang, TRUE, FILEDB_HEADER, 0 }, + + { ".rc", szClang, TRUE, FILEDB_SOURCE | FILEDB_RC, DIRDB_RESOURCE }, + { ".rc2", szClang, TRUE, FILEDB_SOURCE | FILEDB_RC, DIRDB_RESOURCE }, + { ".rcs", szClang, TRUE, FILEDB_SOURCE | FILEDB_RC, DIRDB_RESOURCE }, + { ".rcv", szClang, TRUE, FILEDB_SOURCE | FILEDB_RC, DIRDB_RESOURCE }, + { ".ver", szClang, TRUE, FILEDB_SOURCE | FILEDB_RC, DIRDB_RESOURCE }, + { ".c", szClang, TRUE, FILEDB_SOURCE | FILEDB_C, 0 }, + { ".cxx", szClang, TRUE, FILEDB_SOURCE | FILEDB_C, 0 }, + { ".cpp", szClang, TRUE, FILEDB_SOURCE | FILEDB_C, 0 }, + { ".f", szClang, TRUE, FILEDB_SOURCE, 0 }, + { ".p", szClang, TRUE, FILEDB_SOURCE, 0 }, + { ".s", szClang, TRUE, FILEDB_SOURCE | FILEDB_ASM, 0 }, + { ".asm", szMasm, TRUE, FILEDB_SOURCE | FILEDB_MASM, 0 }, + { ".mc", szMasm, TRUE, FILEDB_SOURCE | FILEDB_RC | + FILEDB_PASS0, DIRDB_PASS0 }, + { ".idl", szClang, TRUE, FILEDB_SOURCE | FILEDB_MIDL | + FILEDB_PASS0, DIRDB_PASS0 }, + { ".asn", szAsn, TRUE, FILEDB_SOURCE | FILEDB_ASN | + FILEDB_MULTIPLEPASS | FILEDB_PASS0, + DIRDB_PASS0 }, + { ".tdl", szClang, TRUE, FILEDB_SOURCE | FILEDB_MKTYPLIB | FILEDB_PASS0, 0 }, + { ".odl", szClang, TRUE, FILEDB_SOURCE | FILEDB_MKTYPLIB | FILEDB_PASS0, 0 }, + { ".pdl", szClang, TRUE, FILEDB_SOURCE | FILEDB_PASS0, 0 }, + { ".h", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 }, + { ".hxx", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 }, + { ".hpp", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 }, + { ".hmd", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 }, + { ".hdl", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 }, + { ".inl", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 }, + { ".rh", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 }, + { ".dlg", szClang, TRUE, FILEDB_HEADER | FILEDB_RC, 0 }, + { ".inc", szMasm, TRUE, FILEDB_HEADER | FILEDB_MASM, 0 }, + { ".src", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 }, // see mvdm\softpc.new\obj.vdm\imlibdep.c + { ".def", szClang, TRUE, FILEDB_HEADER | FILEDB_C, 0 }, + { ".thk", szClang, TRUE, FILEDB_SOURCE | FILEDB_MULTIPLEPASS | + FILEDB_PASS0, DIRDB_PASS0 }, + { ".java", szClang, TRUE, FILEDB_SOURCE | FILEDB_JAVA, 0 }, + { ".mof", szClang, TRUE, FILEDB_SOURCE | FILEDB_MOF | + FILEDB_PASS0, DIRDB_PASS0 }, + + { ".cs", szClang, TRUE, FILEDB_SOURCE | FILEDB_CSHARP, 0 }, +// MUST BE LAST + { NULL, "", FALSE, 0, 0 } +}; + + +//+--------------------------------------------------------------------------- +// +// Function: MatchFileDesc +// +// Synopsis: Matches the given filename to an entry in FileDesc, if +// possible. +// +// Arguments: [pszFile] -- File to match +// +// Returns: A FILEDESC structure. If a match was not found the data +// in the FILEDESC will be empty. +// +//---------------------------------------------------------------------------- + +FILEDESC * +MatchFileDesc(LPSTR pszFile) +{ + LPSTR pszExt = strrchr(pszFile, '.'); + FILEDESC *pfd; + + AssertPathString(pszFile); + pfd = &FileDesc[0]; + + while (pfd->pszPattern != NULL) { + if (pfd->pszPattern[0] == '.') { + if (pszExt != NULL && !strcmp(pszExt, pfd->pszPattern)) + break; + } + else + if (!strcmp(pszFile, pfd->pszPattern)) + break; + + pfd++; + } + return pfd; +} + + +//+--------------------------------------------------------------------------- +// +// Function: InsertFileDB +// +// Synopsis: Adds a file to the database. +// +// Arguments: [DirDB] -- Directory containing the file +// [FileName] -- File to add +// [DateTime] -- Timestamp of file +// [Attr] -- File attributes (directory or file) +// [FileFlags] -- FILEDB flags +// +// Returns: New FILEREC of file +// +//---------------------------------------------------------------------------- + +PFILEREC +InsertFileDB( + PDIRREC DirDB, + LPSTR FileName, + ULONG DateTime, + USHORT Attr, + ULONG FileFlags) +{ + PFILEREC FileDB, *FileDBNext; + LPSTR pszCommentToEOL = NULL; + + AssertPathString(FileName); + if (Attr & FILE_ATTRIBUTE_DIRECTORY) { + if (!strcmp(FileName, ".")) { + return(NULL); + } + if (!strcmp(FileName, "..")) { + return(NULL); + } + assert(FileFlags == 0); + FileFlags = FILEDB_DIR; + } + else { + FILEDESC *pfd = MatchFileDesc(FileName); + + DirDB->DirFlags |= pfd->DirFlags; + FileFlags |= pfd->FileFlags; + + if (!pfd->fNeedFileRec) { + return (NULL); + } + pszCommentToEOL = pfd->pszCommentToEOL; + } + + FileDBNext = &DirDB->Files; + + while ((FileDB = *FileDBNext) != NULL) { + FileDBNext = &(*FileDBNext)->Next; + if (strcmp(FileName, FileDB->Name) == 0) { + BuildError( + "%s: ignoring second instance of %s\n", + DirDB->Name, + FileName); + return(NULL); + } + } + + AllocMem(sizeof(FILEREC) + strlen(FileName), &FileDB, MT_FILEDB); + memset(FileDB, 0, sizeof(*FileDB)); + SigCheck(FileDB->Sig = SIG_FILEREC); + + CopyString(FileDB->Name, FileName, TRUE); + FileDB->CheckSum = CheckSum(FileDB->Name); + + FileDB->DateTime = DateTime; + FileDB->Attr = Attr; + FileDB->Dir = DirDB; + FileDB->FileFlags = FileFlags; + FileDB->NewestDependency = FileDB; + FileDB->pszCommentToEOL = pszCommentToEOL; + + if ((FileFlags & FILEDB_FILE_MISSING) == 0) { + AllDirsModified = TRUE; + } + *FileDBNext = FileDB; + return(FileDB); +} + + + +//+--------------------------------------------------------------------------- +// +// Function: DeleteUnscannedFiles +// +// Synopsis: Removes unscanned files (leaving scanned files and directories) +// from the Files list of the given directory +// +// Arguments: [DirDB] -- Directory to clean up +// +//---------------------------------------------------------------------------- + +VOID +DeleteUnscannedFiles( + PDIRREC DirDB + ) +{ + PFILEREC FileDB, *FileDBNext; + + FileDBNext = &DirDB->Files; + while (FileDB = *FileDBNext) { + // + // If a file has the missing flag set then it doesn't exist. But for + // it to be in the list of files it has to be listed in a SOURCES line + // (or some equivalent). This means there is a SOURCEREC somewhere + // which is pointing to the FILEREC for that file, so we don't want to + // free its memory. + // + if ( (FileDB->FileFlags & (FILEDB_SCANNED | FILEDB_FILE_MISSING | FILEDB_SOURCEREC_EXISTS)) || + (FileDB->Attr & FILE_ATTRIBUTE_DIRECTORY) ) { + FileDBNext = &FileDB->Next; + } + else { + FreeFileDB( FileDBNext ); + AllDirsModified = TRUE; + } + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: InsertIncludeDB +// +// Synopsis: Inserts an include file into the database +// +// Arguments: [FileDB] -- File which includes this file +// [IncludeFileName] -- Name of include file +// [IncFlags] -- INCLUDEDB flags for this file +// +// Returns: INCLUDEREC of previously existing or new entry one. +// +//---------------------------------------------------------------------------- + +PINCLUDEREC +InsertIncludeDB( + PFILEREC FileDB, + LPSTR IncludeFileName, + USHORT IncFlags + ) +{ + PINCLUDEREC IncludeDB, *IncludeDBNext; + + AssertPathString(IncludeFileName); + + IncludeDBNext = &FileDB->IncludeFiles; + + while (IncludeDB = *IncludeDBNext) { + AssertCleanTree(IncludeDB, FileDB); // Tree must be clean + if (!strcmp(IncludeDB->Name, IncludeFileName)) { + IncludeDB->IncFlags &= ~INCLUDEDB_GLOBAL; + IncludeDB->pfrInclude = NULL; + return(IncludeDB); + } + IncludeDBNext = &IncludeDB->Next; + } + + AllocMem( + sizeof(INCLUDEREC) + strlen(IncludeFileName), + IncludeDBNext, + MT_INCLUDEDB); + + IncludeDB = *IncludeDBNext; + + memset(IncludeDB, 0, sizeof(*IncludeDB)); + SigCheck(IncludeDB->Sig = SIG_INCLUDEREC); + + IncludeDB->IncFlags = IncFlags; + CopyString(IncludeDB->Name, IncludeFileName, TRUE); + + AllDirsModified = TRUE; + + return(IncludeDB); +} + + +//+--------------------------------------------------------------------------- +// +// Function: LinkToCycleRoot +// +//---------------------------------------------------------------------------- + +VOID +LinkToCycleRoot(INCLUDEREC *pirOrg, FILEREC *pfrCycleRoot) +{ + INCLUDEREC *pir; + + AllocMem( + sizeof(INCLUDEREC) + strlen(pfrCycleRoot->Name), + &pir, + MT_INCLUDEDB); + memset(pir, 0, sizeof(*pir)); + SigCheck(pir->Sig = SIG_INCLUDEREC); + + pir->IncFlags = INCLUDEDB_SNAPPED | INCLUDEDB_CYCLEALLOC; + pir->pfrInclude = pfrCycleRoot; + + CopyString(pir->Name, pfrCycleRoot->Name, TRUE); + if (DEBUG_1) { + BuildMsgRaw( + "%x CycleAlloc %s\\%s <- %s\\%s\n", + pir, + pir->pfrInclude->Dir->Name, + pir->pfrInclude->Name, + pirOrg->pfrInclude->Dir->Name, + pirOrg->pfrInclude->Name); + } + + MergeIncludeFiles(pirOrg->pfrInclude, pir, NULL); + + assert((pir->IncFlags & INCLUDEDB_CYCLEORPHAN) == 0); + assert(pir->IncFlags & INCLUDEDB_CYCLEROOT); +} + + +//+--------------------------------------------------------------------------- +// +// Function: MergeIncludeFiles +// +//---------------------------------------------------------------------------- + +VOID +MergeIncludeFiles(FILEREC *pfr, INCLUDEREC *pirList, FILEREC *pfrRoot) +{ + INCLUDEREC *pirT; + INCLUDEREC *pir, **ppir; + + while ((pirT = pirList) != NULL) { + pirList = pirList->NextTree; + pirT->NextTree = NULL; + assert(pirT->pfrInclude != NULL); + + for (ppir = &pfr->IncludeFilesTree; + (pir = *ppir) != NULL; + ppir = &pir->NextTree) { + + if (pirT->pfrInclude == pir->pfrInclude) { + if (pirT->IncFlags & INCLUDEDB_CYCLEROOT) { + RemoveFromCycleRoot(pirT, pfrRoot); + } + pirT->IncFlags |= INCLUDEDB_CYCLEORPHAN; + if (DEBUG_1) { + BuildMsgRaw( + "%x CycleOrphan %s\\%s <- %s\\%s\n", + pirT, + pirT->pfrInclude->Dir->Name, + pirT->pfrInclude->Name, + pfr->Dir->Name, + pfr->Name); + } + break; + } + } + if (*ppir == NULL) { + *ppir = pirT; + pirT->pfrCycleRoot = pfr; + pirT->IncFlags |= INCLUDEDB_CYCLEROOT; + if (DEBUG_1) { + BuildMsgRaw( + "%x CycleRoot %s\\%s <- %s\\%s\n", + pirT, + pirT->pfrInclude->Dir->Name, + pirT->pfrInclude->Name, + pirT->pfrCycleRoot->Dir->Name, + pirT->pfrCycleRoot->Name); + } + } + } + if (fDebug & 16) { + PrintFileDB(stderr, pfr, 2); + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: RemoveFromCycleRoot +// +//---------------------------------------------------------------------------- + +VOID +RemoveFromCycleRoot(INCLUDEREC *pir, FILEREC *pfrRoot) +{ + INCLUDEREC **ppir; + + assert(pir->pfrCycleRoot != NULL); + + // if pfrRoot was passed in, the caller knows it's on pfrRoot's list, + // and is already dealing with the linked list without our help. + + if (pfrRoot != NULL) { + assert((pir->IncFlags & INCLUDEDB_CYCLEALLOC) == 0); + assert(pir->pfrCycleRoot == pfrRoot); + pir->pfrCycleRoot = NULL; + pir->IncFlags &= ~INCLUDEDB_CYCLEROOT; + if (DEBUG_1) { + BuildMsgRaw( + "%x CycleUnroot %s\\%s <- %s\\%s\n", + pir, + pir->pfrInclude->Dir->Name, + pir->pfrInclude->Name, + pfrRoot->Dir->Name, + pfrRoot->Name); + } + return; + } + ppir = &pir->pfrCycleRoot->IncludeFilesTree; + while (*ppir != NULL) { + if (*ppir == pir) { + *ppir = pir->NextTree; // remove from tree list + pir->NextTree = NULL; + pir->pfrCycleRoot = NULL; + pir->IncFlags &= ~INCLUDEDB_CYCLEROOT; + return; + } + ppir = &(*ppir)->NextTree; + } + BuildError( + "%s\\%s: %x %s: not on cycle root's list\n", + pir->pfrCycleRoot->Dir->Name, + pir->pfrCycleRoot->Name, + pir, + pir->Name); + + assert(pir->pfrCycleRoot == NULL); // always asserts if loop exhausted +} + + +//+--------------------------------------------------------------------------- +// +// Function: UnsnapIncludeFiles +// +// Synopsis: Removes pointers from INCLUDEREC to the actual FILEREC of +// the include file so we can 'resnap' them. +// +// Arguments: [pfr] -- FILEREC to unsnap +// [fUnsnapGlobal] -- If TRUE, global and local includes are +// unsnapped. Otherwise, just local ones are. +// +//---------------------------------------------------------------------------- + +VOID +UnsnapIncludeFiles(FILEREC *pfr, BOOL fUnsnapGlobal) +{ + INCLUDEREC **ppir; + INCLUDEREC *pir; + + // Dynamic Tree List: + // - no cycle orphans + // - cycle roots must belong to current file record + // - cycle allocs must be freed + + AssertFile(pfr); + while (pfr->IncludeFilesTree != NULL) { + pir = pfr->IncludeFilesTree; // pick up next entry + AssertInclude(pir); + pfr->IncludeFilesTree = pir->NextTree; // remove from tree list + + assert((pir->IncFlags & INCLUDEDB_CYCLEORPHAN) == 0); + + if (pir->IncFlags & (INCLUDEDB_CYCLEROOT | INCLUDEDB_CYCLEALLOC)) { + + // unsnap the record + + pir->IncFlags &= ~(INCLUDEDB_SNAPPED | INCLUDEDB_GLOBAL); + pir->pfrInclude = NULL; + pir->NextTree = NULL; + } + + if (pir->IncFlags & INCLUDEDB_CYCLEROOT) { + assert(pir->pfrCycleRoot == pfr); + pir->pfrCycleRoot = NULL; + pir->IncFlags &= ~INCLUDEDB_CYCLEROOT; + } + assert(pir->pfrCycleRoot == NULL); + + if (pir->IncFlags & INCLUDEDB_CYCLEALLOC) { + pir->IncFlags &= ~INCLUDEDB_CYCLEALLOC; + assert(pir->Next == NULL); + FreeIncludeDB(&pir); + } + } + + // Static List: + // - no cycle allocs + // - cycle roots must be removed from a different file's Dynamic list + // - cycle orphans are nops + + for (ppir = &pfr->IncludeFiles; (pir = *ppir) != NULL; ppir = &pir->Next) { + assert((pir->IncFlags & INCLUDEDB_CYCLEALLOC) == 0); + if (pir->IncFlags & INCLUDEDB_CYCLEROOT) { + assert(pir->pfrCycleRoot != pfr); + RemoveFromCycleRoot(pir, NULL); + } + pir->IncFlags &= ~INCLUDEDB_CYCLEORPHAN; + + if (pir->pfrInclude != NULL && + (fUnsnapGlobal || + (pir->pfrInclude->Dir->DirFlags & DIRDB_GLOBAL_INCLUDES) == 0)) { + + // unsnap the record + + pir->IncFlags &= ~(INCLUDEDB_SNAPPED | INCLUDEDB_GLOBAL); + pir->pfrInclude = NULL; + } + pir->NextTree = NULL; + } +} + +#if DBG +//+--------------------------------------------------------------------------- +// +// Function: AssertCleanTree +// +// Synopsis: Enforce that no include files are snapped. +// +// Arguments: [pir] - include record to test +// [pfr] - optional containing file record +// +//---------------------------------------------------------------------------- + +VOID +AssertCleanTree(INCLUDEREC *pir, OPTIONAL FILEREC *pfr) +{ + if (IsCleanTree(pir)) { + return; + } + if (fAssertCleanTree) { + BuildMsgRaw("\n*************************************\n"); + BuildMsgRaw("Persistent Cycle: pir=%x: %s\n", pir, pir->Name); + if (pfr != NULL) { + BuildMsgRaw(" pfr=%x: %s\n", pfr, pfr->Name); + if (pfr->Dir != NULL) { + BuildMsgRaw(" pdr=%x: %s\n", pfr->Dir, pfr->Dir->Name); + } + } + if (pir->pfrInclude != NULL) { + BuildMsgRaw(" pfrInclude=%x: %s\n", pir->pfrInclude, pir->pfrInclude->Name); + if (pir->pfrInclude->Dir != NULL) { + BuildMsgRaw(" pdrInclude=%x: %s\n", pir->pfrInclude->Dir, pir->pfrInclude->Dir->Name); + } + } + BuildMsgRaw("\n*************************************\n"); + fflush(stdout); + fflush(stderr); + + PrintAllDirs(); + BuildMsgRaw("\n*************************************\n"); + fflush(stdout); + fflush(stderr); + } + assert(IsCleanTree(pir)); +} +#endif + + +//+--------------------------------------------------------------------------- +// +// Function: UnsnapAllDirectories +// +// Synopsis: Removes pointers from all INCLUDERECs to the actual FILERECs +// of include files so we can 'resnap' them. +// +// Arguments: None +//---------------------------------------------------------------------------- + +VOID +UnsnapAllDirectories(VOID) +{ + DIRREC *pdr; + UINT i; + + GlobalSequence = LocalSequence = 0; + + for (pdr = AllDirs; pdr != NULL; pdr = pdr->Next) { + FILEREC *pfr; + + AssertDir(pdr); + + // Clear unwanted flags on each directory + + pdr->DirFlags &= ~(DIRDB_SCANNED | + DIRDB_PASS0NEEDED | + DIRDB_COMPILENEEDED | + DIRDB_NEW); + + pdr->CountOfFilesToCompile = 0; + pdr->SourceLinesToCompile = 0; + pdr->CountOfPassZeroFiles = 0; + pdr->PassZeroLines = 0; + + // Free all source records that point to missing files, because the + // file records may be freed when rescanning directories after pass 0. + + if (pdr->pds != NULL) + { + for (i = 0; i < MAX_TARGET_MACHINES + 1; i++) { + SOURCEREC **ppsr; + SOURCEREC *psr; + + ppsr = &pdr->pds->psrSourcesList[i]; + while ((psr = *ppsr) != NULL) + { + if (psr->SrcFlags & SOURCEDB_FILE_MISSING) + { + FreeSourceDB(ppsr); + } + else + { + ppsr = &psr->psrNext; + } + } + } + } + + // Clear out all snapped include files and sequence numbers + + for (pfr = pdr->Files; pfr != NULL; pfr = pfr->Next) { + + AssertFile(pfr); + UnsnapIncludeFiles(pfr, TRUE); + pfr->GlobalSequence = pfr->LocalSequence = 0; + } + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: MarkIncludeFileRecords +// +//---------------------------------------------------------------------------- + +VOID +MarkIncludeFileRecords( + PFILEREC FileDB + ) +{ + PINCLUDEREC IncludeDB, *IncludeDBNext; + + IncludeDBNext = &FileDB->IncludeFiles; + while (IncludeDB = *IncludeDBNext) { + AssertCleanTree(IncludeDB, FileDB); // Tree must be clean + IncludeDB->pfrInclude = (PFILEREC) -1; + IncludeDBNext = &IncludeDB->Next; + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: DeleteIncludeFileRecords +// +//---------------------------------------------------------------------------- + +VOID +DeleteIncludeFileRecords( + PFILEREC FileDB + ) +{ + PINCLUDEREC IncludeDB, *IncludeDBNext; + + IncludeDBNext = &FileDB->IncludeFiles; + while (IncludeDB = *IncludeDBNext) { + AssertCleanTree(IncludeDB, FileDB); // Tree must be clean + if (IncludeDB->pfrInclude == (PFILEREC) -1) { + FreeIncludeDB(IncludeDBNext); + } + else { + IncludeDBNext = &IncludeDB->Next; + } + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: FindIncludeFileDB +// +// Synopsis: Find the FILEREC for an include file that our compiland +// includes. +// +// Arguments: [pfrSource] -- FILEREC of file which includes the one +// we're looking for. Might be a header. +// [pfrCompiland] -- FILEREC of ultimate source file. +// [pdrBuild] -- DIRREC of directory being built +// [pszSourceDirectory] -- Name of machine-specific dir +// [IncludeDB] -- INCLUDEDB of include file we're looking +// for. +// +// Returns: FILEREC of include file, if found. +// +//---------------------------------------------------------------------------- + +PFILEREC +FindIncludeFileDB( + FILEREC *pfrSource, + FILEREC *pfrCompiland, + DIRREC *pdrBuild, + LPSTR pszSourceDirectory, + INCLUDEREC *IncludeDB) +{ + DIRREC *pdr; + DIRREC *pdrMachine; + FILEREC *pfr; + UINT n; + + AssertFile(pfrSource); + AssertFile(pfrCompiland); + AssertDir(pfrSource->Dir); + AssertDir(pfrCompiland->Dir); + AssertDir(pdrBuild); + assert(pfrSource->Dir->FindCount >= 1); + assert(pfrCompiland->Dir->FindCount >= 1); + assert(pdrBuild->FindCount >= 1); + AssertInclude(IncludeDB); + + // The rules for #include "foo.h" and #include are: + // - "foo.h" searches in the directory of the source file that has the + // #include statement first, then falls into the INCLUDES= directories + // - simply searches the INCLUDES= directories + // + // - since makefile.def *always* passes -I. -ITargetMachines[i] first, + // that has to be handled here as well. + // + // - deal with #include and #include "..\foo\bar.h" by + // scanning those directories, too. + + n = CountIncludeDirs; + pdrMachine = FindSourceDirDB(pdrBuild->Name, pszSourceDirectory, FALSE); + + // If local ("foo.h"), search the current file's directory, too. + // The compiler also will search the directory of each higher level + // file in the include hierarchy, but we won't get quite so fancy here. + // Just search the directory of the current file and of the compiland. + // + // Skip these directories if they match the current build directory or + // the machine subdirectory, because that's handled below. + + if (IncludeDB->IncFlags & INCLUDEDB_LOCAL) { + if (pfrCompiland->Dir != pdrBuild && + pfrCompiland->Dir != pdrMachine && + pfrCompiland->Dir != pfrSource->Dir) { + AddIncludeDir(pfrCompiland->Dir, &n); + } + if (pfrSource->Dir != pdrBuild && pfrSource->Dir != pdrMachine) { + AddIncludeDir(pfrSource->Dir, &n); + } + } + + // Search the current target machine subdirectory of the build directory + // -- as per makefile.def + + if (pdrMachine != NULL) { + AddIncludeDir(pdrMachine, &n); + } + + // Search the current build directory -- as per makefile.def. + + AddIncludeDir(pdrBuild, &n); + + while (n--) { + pdr = IncludeDirs[n]; + if (pdr == NULL) { + continue; + } + AssertDir(pdr); + assert(pdr->FindCount >= 1); + pfr = FindSourceFileDB(pdr, IncludeDB->Name, NULL); + if (pfr != NULL) { + if (DEBUG_1) { + BuildMsgRaw( + "Found include file %s\\%s\n", + pfr->Dir->Name, + pfr->Name); + } + return(pfr); + } + } + return(NULL); +} + + +//+--------------------------------------------------------------------------- +// +// Function: SaveMasterDB +// +// Synopsis: Save the database to disk in build.dat +// +// Arguments: (none) +// +// Returns: TRUE if successful +// +//---------------------------------------------------------------------------- + +BOOL +SaveMasterDB(VOID) +{ + PDIRREC DirDB, *DirDBNext; + PFILEREC FileDB, *FileDBNext; + PINCLUDEREC IncludeDB, *IncludeDBNext; + FILE *fh; + + if (!AllDirsModified) { + return(TRUE); + } + + if (!(fh = fopen(DbMasterName, "wb"))) { + return( FALSE ); + } + + setvbuf(fh, NULL, _IOFBF, 0x7000); + BuildMsg("Saving %s...", DbMasterName); + + AllDirsModified = FALSE; + DirDBNext = &AllDirs; + fprintf(fh, "V %x\r\n", BUILD_VERSION); + while (DirDB = *DirDBNext) { + fprintf(fh, "D \"%s\" %x\r\n", DirDB->Name, DirDB->DirFlags); + FileDBNext = &DirDB->Files; + while (FileDB = *FileDBNext) { + if ((FileDB->FileFlags & FILEDB_FILE_MISSING) == 0) { + fprintf( + fh, + " F \"%s\" %x %x %lx %u %u\r\n", + FileDB->Name, + FileDB->FileFlags, + FileDB->Attr, + FileDB->DateTime, + FileDB->SourceLines, + FileDB->Version); + } + IncludeDBNext = &FileDB->IncludeFiles; + while (IncludeDB = *IncludeDBNext) { + fprintf( + fh, + " I \"%s\" %x %u\r\n", + IncludeDB->Name, + IncludeDB->IncFlags, + IncludeDB->Version); + + IncludeDBNext= &IncludeDB->Next; + } + FileDBNext = &FileDB->Next; + } + fprintf(fh, "\r\n"); + DirDBNext = &DirDB->Next; + } + fclose(fh); + BuildMsgRaw(szNewLine); + return(TRUE); +} + +//+--------------------------------------------------------------------------- +// +// Function: LoadMasterDB +// +// Synopsis: Load the master database from build.dat +// +// Arguments: (none) +// +//---------------------------------------------------------------------------- + +void +LoadMasterDB( void ) +{ + PDIRREC DirDB, *DirDBNext; + PFILEREC FileDB, *FileDBNext; + PINCLUDEREC IncludeDB, *IncludeDBNext; + FILE *fh; + LPSTR s; + char ch, ch2; + BOOL fFirst = TRUE; + UINT Version; + LPSTR pszerr = NULL; + + AllDirs = NULL; + AllDirsModified = FALSE; + AllDirsInitialized = FALSE; + + if (!SetupReadFile("", DbMasterName, ";", &fh)) { + return; + } + BuildMsg("Loading %s...", DbMasterName); + + DirDBNext = &AllDirs; + FileDBNext = NULL; + IncludeDBNext = NULL; + + while ((s = ReadLine(fh)) != NULL) { + ch = *s++; + if (ch == '\0') { + continue; // skip empty lines + } + ch2 = *s++; // should be a blank + if (ch2 == '\0') { + pszerr = "missing field"; + break; // fail on single character lines + } + if (fFirst) { + if (ch != 'V' || ch2 != ' ' || !AToX(&s, &Version)) { + pszerr = "bad version format"; + break; + } + if (Version != BUILD_VERSION) { + break; + } + fFirst = FALSE; + continue; + } + if (ch2 != ' ') { + pszerr = "bad separator"; + break; + } + if (ch == 'D') { + DirDB = LoadMasterDirDB(s); + if (DirDB == NULL) { + pszerr = "Directory error"; + break; + } + *DirDBNext = DirDB; + DirDBNext = &DirDB->Next; + FileDBNext = &DirDB->Files; + IncludeDBNext = NULL; + } + else + if (ch == 'F' && FileDBNext != NULL) { + FileDB = LoadMasterFileDB(s); + if (FileDB == NULL) { + pszerr = "File error"; + break; + } + *FileDBNext = FileDB; + FileDBNext = &FileDB->Next; + FileDB->Dir = DirDB; + IncludeDBNext = &FileDB->IncludeFiles; + } + else + if (ch == 'I' && IncludeDBNext != NULL) { + IncludeDB = LoadMasterIncludeDB(s); + if (IncludeDB == NULL) { + pszerr = "Include error"; + break; + } + *IncludeDBNext = IncludeDB; + IncludeDBNext = &IncludeDB->Next; + } + else { + pszerr = "bad entry type"; + break; + } + } + + if (s != NULL) { + if (pszerr == NULL) { + BuildMsgRaw(" - old version - recomputing.\n"); + } else { + BuildMsgRaw(szNewLine); + BuildError("corrupt database (%s)\n", pszerr); + } + FreeAllDirs(); + } + else { + BuildMsgRaw(szNewLine); + AllDirsInitialized = TRUE; + } + CloseReadFile(NULL); + return; +} + + +//+--------------------------------------------------------------------------- +// +// Function: LoadMasterDirDB +// +// Synopsis: Load a directory entry from build.dat +// +// Arguments: [s] -- line containing text from file. +// +// Returns: DIRRECT +// +//---------------------------------------------------------------------------- + +PDIRREC +LoadMasterDirDB( + LPSTR s + ) +{ + PDIRREC DirDB; + LPSTR DirName; + ULONG DirFlags; + + if (*s == '"') { + s++; + DirName = s; + while (*s != '"') { + s++; + } + *s++ = '\0'; + } + else + { + DirName = s; + while (*s > ' ') { + s++; + } + } + *s++ = '\0'; + + if (!AToX(&s, &DirFlags)) { + return(NULL); + } + AllocMem(sizeof(DIRREC) + strlen(DirName), &DirDB, MT_DIRDB); + memset(DirDB, 0, sizeof(*DirDB)); + SigCheck(DirDB->Sig = SIG_DIRREC); + + DirDB->DirFlags = DirFlags & DIRDB_DBPRESERVE; + CopyString(DirDB->Name, DirName, TRUE); + DirDB->CheckSum = CheckSum(DirDB->Name); + return( DirDB ); +} + + +//+--------------------------------------------------------------------------- +// +// Function: LoadMasterFileDB +// +// Synopsis: Load a file entry from build.dat +// +// Arguments: [s] -- line containing text from file +// +// Returns: FILEREC +// +//---------------------------------------------------------------------------- + +PFILEREC +LoadMasterFileDB( + LPSTR s + ) +{ + PFILEREC FileDB; + LPSTR FileName; + ULONG Version; + ULONG FileFlags; + ULONG Attr; + ULONG SourceLines; + ULONG DateTime; + FILEDESC *pfd; + + if (*s == '"') { + s++; + FileName = s; + while (*s != '"') { + s++; + } + *s++ = '\0'; + } + else + { + FileName = s; + while (*s > ' ') { + s++; + } + } + *s++ = '\0'; + + if (!AToX(&s, &FileFlags) || + !AToX(&s, &Attr) || + !AToX(&s, &DateTime) || + !AToD(&s, &SourceLines) || + !AToD(&s, &Version) || + strchr(FileName, '/') != NULL || + strchr(FileName, '\\') != NULL) { + return(NULL); + } + AllocMem(sizeof(FILEREC) + strlen(FileName), &FileDB, MT_FILEDB); + memset(FileDB, 0, sizeof(*FileDB)); + SigCheck(FileDB->Sig = SIG_FILEREC); + + CopyString(FileDB->Name, FileName, TRUE); + FileDB->CheckSum = CheckSum(FileDB->Name); + + FileDB->FileFlags = FileFlags & FILEDB_DBPRESERVE; + FileDB->Attr = (USHORT) Attr; + FileDB->DateTime = DateTime; + FileDB->Version = (USHORT) Version; + FileDB->SourceLines = SourceLines; + FileDB->NewestDependency = FileDB; + + pfd = MatchFileDesc(FileDB->Name); + FileDB->pszCommentToEOL = pfd->pszCommentToEOL; + return(FileDB); +} + + +//+--------------------------------------------------------------------------- +// +// Function: LoadMasterIncludeDB +// +// Synopsis: Loads an include file entry from build.dat +// +// Arguments: [s] -- line containing text from file. +// +// Returns: INCLUDEREC +// +//---------------------------------------------------------------------------- + +PINCLUDEREC +LoadMasterIncludeDB( + LPSTR s + ) +{ + PINCLUDEREC IncludeDB; + LPSTR FileName; + ULONG Version; + ULONG IncFlags; + + if (*s == '"') { + s++; + FileName = s; + while (*s != '"') { + s++; + } + *s++ = '\0'; + } + else + { + FileName = s; + while (*s > ' ') { + s++; + } + } + *s++ = '\0'; + + if (!AToX(&s, &IncFlags) || !AToD(&s, &Version)) { + return(NULL); + } + AllocMem( + sizeof(INCLUDEREC) + strlen(FileName), + &IncludeDB, + MT_INCLUDEDB); + memset(IncludeDB, 0, sizeof(*IncludeDB)); + SigCheck(IncludeDB->Sig = SIG_INCLUDEREC); + + IncludeDB->IncFlags = (USHORT) (IncFlags & INCLUDEDB_DBPRESERVE); + IncludeDB->Version = (USHORT) Version; + CopyString(IncludeDB->Name, FileName, TRUE); + return(IncludeDB); +} diff --git a/sdktools/buildexe.c b/sdktools/buildexe.c new file mode 100644 index 0000000..f5b9192 --- /dev/null +++ b/sdktools/buildexe.c @@ -0,0 +1,3143 @@ +//+--------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1994 +// +// File: buildexe.c +// +// Contents: Functions related to spawning processes and processing +// their output, using pipes and multiple threads. +// +// History: 22-May-89 SteveWo Created +// ... see SLM logs +// 26-Jul-94 LyleC Cleanup/Add Pass0 Support +// +//---------------------------------------------------------------------------- + +#include "build.h" + +#include + +//+--------------------------------------------------------------------------- +// +// Global Data +// +//---------------------------------------------------------------------------- + +#define DEFAULT_LPS (fStatusTree? 5000 : 50) + +#define LastRow(pts) ((USHORT) ((pts)->cRowTotal - 1)) +#define LastCol(pts) ((USHORT) ((pts)->cColTotal - 1)) + +typedef struct _PARALLEL_CHILD { + PTHREADSTATE ThreadState; + HANDLE Event; + CHAR ExecuteProgramCmdLine[1024]; +} PARALLEL_CHILD, *PPARALLEL_CHILD; + +time_t StartCompileTime; + +DWORD OldConsoleMode; +DWORD NewConsoleMode; + +HANDLE *WorkerThreads; +HANDLE *WorkerEvents; +ULONG NumberProcesses; +volatile LONG BuildChildFailures = 0; +ULONG ThreadsStarted; + +BOOLEAN fConsoleInitialized = FALSE; +BYTE ScreenCell[2]; +BYTE StatusCell[2]; + +#define STATE_UNKNOWN 0 +#define STATE_COMPILING 1 +#define STATE_ASSEMBLING 2 +#define STATE_LIBING 3 +#define STATE_LINKING 4 +#define STATE_C_PREPROC 5 +#define STATE_S_PREPROC 6 +#define STATE_PRECOMP 7 +#define STATE_MKTYPLIB 8 +#define STATE_MIDL 9 +#define STATE_MC 10 +#define STATE_STATUS 11 +#define STATE_BINPLACE 12 +#define STATE_VCTOOL 13 +#define STATE_ASN 14 +#define STATE_PACKING 15 + +#define FLAGS_CXX_FILE 0x0001 +#define FLAGS_WARNINGS_ARE_ERRORS 0x0002 + +LPSTR States[] = { + "Unknown", // 0 + "Compiling", // 1 + "Assembling", // 2 + "Building Library", // 3 + "Linking Executable", // 4 + "Preprocessing", // 5 + "Assembling", // 6 + "Compiling Precompiled Header", // 7 + "Building Type Library", // 8 + "Running MIDL on", // 9 + "Compiling message file", // 10 + "Build Status Line", // 11 + "Binplacing", // 12 + "Processing", // 13 + "Running ASN Compiler on", // 14 + "Packing Theme", // 15 +}; + +//---------------------------------------------------------------------------- +// +// Function prototypes +// +//---------------------------------------------------------------------------- + +VOID +GetScreenSize(THREADSTATE *ThreadState); + +VOID +GetCursorPosition(USHORT *pRow, USHORT *pCol, USHORT *pRowTop); + +VOID +SetCursorPosition(USHORT Row, USHORT Col); + +VOID +WriteConsoleCells( + LPSTR String, + USHORT StringLength, + USHORT Row, + USHORT Col, + BYTE *Attribute); + +VOID +MoveRectangleUp ( + USHORT Top, + USHORT Left, + USHORT Bottom, + USHORT Right, + USHORT NumRow, + BYTE *FillCell); + +VOID +ReadConsoleCells( + BYTE *pScreenCell, + USHORT cb, + USHORT Row, + USHORT Column); + +VOID +ClearRows( + PTHREADSTATE ThreadState, + USHORT Top, + USHORT NumRows, + PBYTE Cell + ); + +LPSTR +IsolateFirstToken( + LPSTR *pp, + CHAR delim + ); + +LPSTR +IsolateLastToken( + LPSTR p, + CHAR delim + ); + +DWORD +ParallelChildStart( + PPARALLEL_CHILD Data + ); + +DWORD +PipeSpawnClose ( + FILE *pstream + ); + +FILE * +PipeSpawn ( + const CHAR *cmdstring + ); + +BOOL +DetermineChildState( + PTHREADSTATE ThreadState, + LPSTR p + ); + +void +PrintChildState( + PTHREADSTATE ThreadState, + LPSTR p, + PFILEREC FileDB + ); + + +//+--------------------------------------------------------------------------- +// +// Function: RestoreConsoleMode +// +//---------------------------------------------------------------------------- + +VOID +RestoreConsoleMode(VOID) +{ + SetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), OldConsoleMode); + NewConsoleMode = OldConsoleMode; +} + +//+--------------------------------------------------------------------------- +// +// Function: IsolateFirstToken +// +// Synopsis: Returns the first token in a string. +// +// Arguments: [pp] -- String to parse +// [delim] -- Token delimiter +// +// Returns: Pointer to first token +// +// Notes: Leading spaces are ignored. +// +//---------------------------------------------------------------------------- + +LPSTR +IsolateFirstToken( + LPSTR *pp, + CHAR delim + ) +{ + LPSTR p, Result; + + p = *pp; + while (*p <= ' ') { + if (!*p) { + *pp = p; + return( "" ); + } + else + p++; + } + + Result = p; + while (*p) { + if (*p == delim) { + *p++ = '\0'; + break; + } + else { + p++; + } + } + *pp = p; + if (*Result == '.' && Result[1] == '\\') { + return( Result+2 ); + } + else { + return( Result ); + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: IsolateLastToken +// +// Synopsis: Return the last token in a string. +// +// Arguments: [p] -- String to parse +// [delim] -- Token delimiter +// +// Returns: Pointer to last token +// +// Notes: Trailing spaces are skipped. +// +//---------------------------------------------------------------------------- + +LPSTR +IsolateLastToken( + LPSTR p, + CHAR delim + ) +{ + LPSTR Start; + + Start = p; + while (*p) { + p++; + } + + while (--p > Start) { + if (*p <= ' ') { + *p = '\0'; + } + else + break; + } + + while (p > Start) { + if (*--p == delim) { + p++; + break; + } + } + + if (*p == '.' && p[1] == '\\') { + return( p+2 ); + } + else { + return( p ); + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: TestPrefix +// +// Synopsis: Returns TRUE if [Prefix] is the first part of [pp] +// +//---------------------------------------------------------------------------- + +BOOL +TestPrefix( + LPSTR *pp, + LPSTR Prefix + ) +{ + LPSTR p = *pp; + UINT cb; + + if (!_strnicmp( p, Prefix, cb = strlen( Prefix ) )) { + *pp = p + cb; + return( TRUE ); + } + else { + return( FALSE ); + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: TestPrefixPath +// +// Synopsis: Returns TRUE if [Prefix] is the first part of [pp] +// If the firstpart of [pp] (excluding whitespace) contains +// backslashes, then only the right-most component is used +// +//---------------------------------------------------------------------------- + +BOOL +TestPrefixPath( + LPSTR *pp, + LPSTR Prefix + ) +{ + LPSTR p = *pp; + UINT cb; + LPSTR PathString; + INT PathStringLength ; + LPSTR LastComp ; + + cb = strlen( Prefix ); + + if (_strnicmp( p, Prefix, cb ) == 0 ) { + *pp = p + cb; + return( TRUE ); + } + else { + PathString = strchr( p, ' ' ); + + if ( PathString ) { + PathStringLength = (INT) (PathString - p) ; + + *PathString = '\0'; + + LastComp = strrchr( p, '\\' ); + + *PathString = ' '; + + if ( LastComp ) { + + if ( _strnicmp( p, Prefix, cb ) == 0 ) { + *pp = p + cb ; + return( TRUE ); + } + } + + } + + return( FALSE ); + + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: Substr +// +//---------------------------------------------------------------------------- + +BOOL +Substr( + LPSTR s, + LPSTR p + ) +{ + LPSTR x; + + while (*p) { + x = s; + while (*p++ == *x) { + if (*x == '\0') { + return( TRUE ); + } + x++; + } + if (*x == '\0') { + return( TRUE ); + } + } + return( FALSE ); +} + + + +//+--------------------------------------------------------------------------- +// +// Function: WriteTTY +// +// Synopsis: Writes the given string to the output device. +// +// Arguments: [ThreadState] -- Struct containing info about the output dev. +// [p] -- String to display +// [fStatusOutput] -- If TRUE then put on the status line. +// +//---------------------------------------------------------------------------- + +VOID +WriteTTY (THREADSTATE *ThreadState, LPSTR p, BOOL fStatusOutput) +{ + USHORT SaveRow; + USHORT SaveCol; + USHORT SaveRowTop; + USHORT cb, cbT; + PBYTE Attribute; + BOOL ForceNewline; + + // + // If we're not writing to the screen then don't do anything fancy, just + // output the string. + // + if (!fStatus || !ThreadState->IsStdErrTty) { + while (TRUE) { + int cch; + + cch = strcspn(p, "\r"); + if (cch != 0) { + fwrite(p, 1, cch, stderr); + p += cch; + } + if (*p == '\0') { + break; + } + if (p[1] != '\n') { + fwrite(p, 1, 1, stderr); + } + p++; + } + fflush(stderr); + return; + } + assert(ThreadState->cColTotal != 0); + assert(ThreadState->cRowTotal != 0); + + // + // Scroll as necessary + // + GetCursorPosition(&SaveRow, &SaveCol, &SaveRowTop); + + // During processing, there might be N threads that are displaying + // messages and a single thread displaying directory-level + // linking and building messages. We need to make sure there's room for + // the single thread's message as well as ours. Since that single + // thread displays one line at a time (including CRLF) we must make sure + // that his display (as well as ours) doesn't inadvertantly scroll + // the status line at the top. We do this by guaranteeing that there is + // a blank line at the end. + + + // We are synchronized with the single top-level thread + // at a higher level than this routine via TTYCriticalSection. We + // are, thus, assured that we control the cursor completely. + + + // Stay off the LastRow + if (SaveRow == LastRow(ThreadState)) { + USHORT RowTop = 2; + + if (fStatus) { + RowTop += SaveRowTop + (USHORT) NumberProcesses + 1; + } + + MoveRectangleUp ( + RowTop, // Top + 0, // Left + LastRow(ThreadState), // Bottom + LastCol(ThreadState), // Right + 2, // NumRow + ScreenCell); // FillCell + + SaveRow -= 2; + SetCursorPosition(SaveRow, SaveCol); + } + + // + // Different color for the status line. + // + if (fStatusOutput) { + Attribute = &StatusCell[1]; + } + else { + Attribute = &ScreenCell[1]; + } + cb = (USHORT) strlen(p); + + // + // Write out the string. + // + while (cb > 0) { + ForceNewline = FALSE; + + if (cb > 1) { + if (p[cb - 1] == '\n' && p[cb - 2] == '\r') { + cb -= 2; + ForceNewline = TRUE; + } + } + + if (cb >= ThreadState->cColTotal - SaveCol) { + cbT = ThreadState->cColTotal - SaveCol; + if (fFullErrors) + ForceNewline = TRUE; + } + else { + cbT = cb; + } + + WriteConsoleCells(p, cbT, SaveRow, SaveCol, Attribute); + SetCursorPosition(SaveRow, SaveCol); + + if (ForceNewline) { + SaveCol = 0; + SaveRow++; + } + else { + SaveCol += cbT; + } + + if (!fFullErrors) { + break; + } + + if (cb > cbT) { + // we have more to go... do a newline + + // If we're back at the beginning of the bottom line + if (SaveRow == LastRow(ThreadState)) { + USHORT RowTop = 1; + + if (fStatus) { + RowTop += SaveRowTop + (USHORT) NumberProcesses + 1; + } + + // move window up one line (leaving two lines blank at bottom) + MoveRectangleUp ( + RowTop, // Top + 0, // Left + LastRow(ThreadState), // Bottom + LastCol(ThreadState), // Right + 1, // NumRow + ScreenCell); // FillCell + + SaveRow--; + } + SetCursorPosition(SaveRow, SaveCol); + } + + cb -= cbT; + p += cbT; + } + + SetCursorPosition(SaveRow, SaveCol); +} + + +//+--------------------------------------------------------------------------- +// +// Function: WriteTTYLoggingErrors +// +// Synopsis: Writes a message to the appropriate log file and also the +// screen if specified. +// +// Arguments: [Warning] -- TRUE if the message is a warning +// [ThreadState] -- Info about output device +// [p] -- String +// +//---------------------------------------------------------------------------- + +VOID +WriteTTYLoggingErrors( + BOOL Warning, + PTHREADSTATE ThreadState, + LPSTR p + ) +{ + UINT cb; + + if (fErrorLog) { + cb = strlen( p ); + fwrite( p, 1, cb, Warning ? WrnFile : ErrFile ); + } + if (fShowWarningsOnScreen && Warning) + { + WriteTTY(ThreadState, p, FALSE); + return; + } + if (!fErrorLog || !Warning) { + WriteTTY(ThreadState, p, FALSE); + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: MsCompilerFilter +// +// Synopsis: Filters output from the compiler so we know what's happening +// +// Arguments: [ThreadState] -- State of thread watching the compiler +// (compiling, linking, etc...) +// [p] -- Message we're trying to parse. +// [FileName] -- [out] Filename in message +// [LineNumber] -- [out] Line number in message +// [Message] -- [out] Message number (for post processing) +// [Warning] -- [out] TRUE if message is a warning. +// +// Returns: TRUE - Message is an error or warning +// FALSE - Message is not an error or a warning +// +// History: 26-Jul-94 LyleC Created +// +// Notes: +// +// This routine filters strings in the MS compiler format. That is: +// +// {toolname} : {number}: {text} +// +// where: +// +// toolname If possible, the container and specific module that has +// the error. For instance, the compiler uses +// filename(linenum), the linker uses library(objname), etc. +// If unable to provide a container, use the tool name. +// number A number, prefixed with some tool identifier (C for +// compiler, LNK for linker, LIB for librarian, N for nmake, +// etc). +// test The descriptive text of the message/error. +// +// Accepted String formats are: +// +// container(module): error/warning NUM ... +// container(module) : error/warning NUM ... +// container (module): error/warning NUM ... +// container (module) : error/warning NUM ... +// +//---------------------------------------------------------------------------- + +BOOL +MsCompilerFilter( + PTHREADSTATE ThreadState, + LPSTR p, + LPSTR *FileName, + LPSTR *LineNumber, + LPSTR *Message, + BOOL *Warning + ) +{ + LPSTR p1; + BOOL fCommandLineWarning; + + *Message = NULL; + + p1 = p; + + if (strstr(p, "Compiler error (")) { + *Message = p; + *Warning = FALSE; + if ((p1 = strstr( p, "source=" ))) + *LineNumber = p1+7; + else + *LineNumber = "1"; + *FileName = ThreadState->ChildCurrentFile; + return TRUE; + } + + if (0 == strncmp(p, "fatal error ", strlen("fatal error "))) { + *Message = p; + *Warning = FALSE; + *LineNumber = "1"; + *FileName = ThreadState->ChildCurrentFile; + return TRUE; + } + + // First look for the " : " or "): " sequence. + + while (*p1) { + if ((p1[0] == ')') && (p1[1] == ' ')) p1++; + + if ((p1[0] == ' ') || (p1[0] == ')')) { + if (p1[1] == ':') { + if (p1[2] == ' ') { + *Message = p1 + 3; + *p1 = '\0'; + + break; + } + else + break; // No sense going any further + } + else if ((p1[0] == ' ') && (p1[1] == '(')) + p1++; + else + break; // No sense going any further + } + else + p1++; + } + + if (*Message != NULL) { + // then figure out if this is an error or warning. + + *Warning = TRUE; // Assume the best. + fCommandLineWarning = FALSE; + + if (TestPrefix( Message, "error " ) || + TestPrefix( Message, "fatal error " ) || + TestPrefix( Message, "command line error " ) || + TestPrefix( Message, "Compiler error " )) { + *Warning = FALSE; + } else + if (TestPrefix( Message, "warning " )) { + *Warning = TRUE; + } else + if (TestPrefix( Message, "command line warning " )) { + // Command-line warnings don't count when considering whether + // warnings should be errors (under /WX). + *Warning = TRUE; + fCommandLineWarning = TRUE; + } + + if (!fCommandLineWarning && (ThreadState->ChildFlags & FLAGS_WARNINGS_ARE_ERRORS) != 0) { + if (Substr( "X0000", *Message )) { + *Warning = TRUE; // Special case this one. Never an error + } else { + *Warning = FALSE; // Warnings treated as errors for this compile + } + } + + // Set the container name and look for the module paren's + + *FileName = p; + *LineNumber = NULL; + + p1 = p; + + while (*p1) { + if (*p1 == '(' && p1[1] != ')') { + *p1 = '\0'; + p1++; + *LineNumber = p1; + while (*p1) { + if (*p1 == ')') { + *p1 = '\0'; + break; + } + p1++; + } + + break; + } + + p1++; + } + + return(TRUE); + } + + return(FALSE); +} + + +//+--------------------------------------------------------------------------- +// +// Function: FormatMsErrorMessage +// +// Synopsis: Take the information obtained from MsCompilerFilter, +// reconstruct the error message, and print it to the screen. +// +//---------------------------------------------------------------------------- + +VOID +FormatMsErrorMessage( + PTHREADSTATE ThreadState, + LPSTR FileName, + LPSTR LineNumber, + LPSTR Message, + BOOL Warning + ) +{ + char *DirectoryToUse; + + if (ThreadState->ChildState == STATE_LIBING) { + if (Warning) { + NumberLibraryWarnings++; + } + else { + NumberLibraryErrors++; + } + } + else + if (ThreadState->ChildState == STATE_LINKING) { + if (Warning) { + NumberLinkWarnings++; + } + else { + NumberLinkErrors++; + } + } + else if (ThreadState->ChildState == STATE_BINPLACE) { + if (Warning) { + NumberBinplaceWarnings++; + } + else { + NumberBinplaceErrors++; + } + } + else { + if (Warning) { + NumberCompileWarnings++; + } + else { + NumberCompileErrors++; + if (ThreadState->CompileDirDB) { + ThreadState->CompileDirDB->DirFlags |= DIRDB_COMPILEERRORS; + } + } + } + + if (fParallel && !fNoThreadIndex) { + char buffer[50]; + sprintf(buffer, "%d>", ThreadState->ThreadIndex); + WriteTTYLoggingErrors(Warning, ThreadState, buffer); + } + + if (FileName) { + DirectoryToUse = ThreadState->ChildCurrentDirectory; + + if (TestPrefix( &FileName, CurrentDirectory )) { + DirectoryToUse = CurrentDirectory; + if (*FileName == '\\') { + FileName++; + } + } + + if (TestPrefix( &FileName, ThreadState->ChildCurrentDirectory )) { + DirectoryToUse = ThreadState->ChildCurrentDirectory; + if (*FileName == '\\') { + FileName++; + } + } + + WriteTTYLoggingErrors( Warning, + ThreadState, + FormatPathName( DirectoryToUse, + FileName + ) + ); + } + + WriteTTYLoggingErrors( Warning, ThreadState, "(" ); + if (LineNumber) { + WriteTTYLoggingErrors( Warning, ThreadState, LineNumber ); + } + WriteTTYLoggingErrors( Warning, ThreadState, ") : " ); + if (Warning) { + WriteTTYLoggingErrors( Warning, ThreadState, "warning " ); + } + else { + WriteTTYLoggingErrors( Warning, ThreadState, "error " ); + } + WriteTTYLoggingErrors( Warning, ThreadState, Message ); + WriteTTYLoggingErrors( Warning, ThreadState, "\r\n" ); +} + + +//+--------------------------------------------------------------------------- +// +// Function: PassThrough +// +// Synopsis: Keep track of and print the given message without any +// filtering. +// +// Arguments: [ThreadState] -- +// [p] -- Message +// [Warning] -- TRUE if warning +// +// Returns: FALSE +// +//---------------------------------------------------------------------------- + +BOOL +PassThrough( + PTHREADSTATE ThreadState, + LPSTR p, + BOOL Warning + ) +{ + if (ThreadState->ChildState == STATE_LIBING) { + if (Warning) { + NumberLibraryWarnings++; + } + else { + NumberLibraryErrors++; + } + } + else + if (ThreadState->ChildState == STATE_LINKING) { + if (Warning) { + NumberLinkWarnings++; + } + else { + NumberLinkErrors++; + } + } + else + if (ThreadState->ChildState == STATE_BINPLACE) { + if (Warning) { + NumberBinplaceWarnings++; + } + else { + NumberBinplaceErrors++; + } + } + else { + if (Warning) { + NumberCompileWarnings++; + } + else { + NumberCompileErrors++; + if (ThreadState->CompileDirDB) { + ThreadState->CompileDirDB->DirFlags |= DIRDB_COMPILEERRORS; + } + } + } + + if (fParallel && !fNoThreadIndex) { + char buffer[50]; + sprintf(buffer, "%d>", ThreadState->ThreadIndex); + WriteTTYLoggingErrors(Warning, ThreadState, buffer); + } + + WriteTTYLoggingErrors( Warning, ThreadState, p ); + WriteTTYLoggingErrors( Warning, ThreadState, "\r\n" ); + return( FALSE ); +} + + +//+--------------------------------------------------------------------------- +// +// Function: PassThroughFilter +// +// Synopsis: Straight pass-through filter for compiler messages +// +//---------------------------------------------------------------------------- + +BOOL +PassThroughFilter( + PTHREADSTATE ThreadState, + LPSTR p + ) +{ + return PassThrough( ThreadState, p, FALSE ); +} + + +//+--------------------------------------------------------------------------- +// +// Function: C510Filter +// +// Synopsis: Compiler filter which strips out unwanted warnings. +// +// Arguments: [ThreadState] -- +// [p] -- +// +//---------------------------------------------------------------------------- + +BOOL +C510Filter( + PTHREADSTATE ThreadState, + LPSTR p + ) +{ + LPSTR FileName; + LPSTR LineNumber; + LPSTR Message; + BOOL Warning; + LPSTR t; + PFILEREC FileDB; + + if (MsCompilerFilter( ThreadState, p, + &FileName, + &LineNumber, + &Message, + &Warning + ) + ) { + if (fSilent && Warning) { + if (Substr( "C4001", Message ) || + Substr( "C4010", Message ) || + Substr( "C4056", Message ) || + Substr( "C4061", Message ) || + Substr( "C4100", Message ) || + Substr( "C4101", Message ) || + Substr( "C4102", Message ) || + Substr( "C4127", Message ) || + Substr( "C4135", Message ) || + Substr( "C4201", Message ) || + Substr( "C4204", Message ) || + Substr( "C4208", Message ) || + Substr( "C4509", Message ) + ) { + return( FALSE ); + } + + if (ThreadState->ChildFlags & FLAGS_CXX_FILE) { + if (Substr( "C4047", Message ) || + Substr( "C4022", Message ) || + Substr( "C4053", Message ) + ) { + return( FALSE ); + } + } + } + + FormatMsErrorMessage( ThreadState, + FileName, LineNumber, Message, Warning ); + return( TRUE ); + } + else { + + // If we're compiling, then the compiler spits out various bit of info, + // namely: + // 1. filename alone on a line (.c, .cpp, .cxx) + // 2. "Generating Code..." when the back-end is invoked + // 3. "Compiling..." when the front-end is invoked again + + if (ThreadState->ChildState == STATE_COMPILING) { + + if (0 == strcmp(p, "Generating Code...")) { + + strcpy( ThreadState->ChildCurrentFile, "Generating Code..." ); + PrintChildState(ThreadState, p, NULL); + return FALSE; + } + + t = strrchr(p, '.'); + if (t != NULL && + (0 == strcmp(t, ".cxx") || + 0 == strcmp(t, ".cpp") || + 0 == strcmp(t, ".c"))) { + + strcpy( ThreadState->ChildCurrentFile, IsolateLastToken(p, ' ')); +// strcpy(ThreadState->ChildCurrentFile, p); + if (strstr(ThreadState->ChildCurrentFile, ".cxx") || + strstr(ThreadState->ChildCurrentFile, ".cpp")) { + ThreadState->ChildFlags |= FLAGS_CXX_FILE; + } else { + ThreadState->ChildFlags &= ~FLAGS_CXX_FILE; + } + + FileDB = NULL; + if (ThreadState->CompileDirDB) { + NumberCompiles++; + CopyString( // fixup path string + ThreadState->ChildCurrentFile, + ThreadState->ChildCurrentFile, + TRUE); + + if (!fQuicky) { + FileDB = FindSourceFileDB( + ThreadState->CompileDirDB, + ThreadState->ChildCurrentFile, + NULL); + } + } + + PrintChildState(ThreadState, p, FileDB); + return FALSE; + } + } + + return( FALSE ); + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: MSToolFilter +// +//---------------------------------------------------------------------------- + +BOOL +MSToolFilter( + PTHREADSTATE ThreadState, + LPSTR p + ) +{ + LPSTR FileName; + LPSTR LineNumber; + LPSTR Message; + BOOL Warning; + + if (MsCompilerFilter( ThreadState, p, + &FileName, + &LineNumber, + &Message, + &Warning + ) + ) { + FormatMsErrorMessage( ThreadState, + FileName, LineNumber, Message, Warning ); + return( TRUE ); + } + else { + return( FALSE ); + } +} + + +BOOL +LinkFilter( + PTHREADSTATE ThreadState, + LPSTR p + ); + +//+--------------------------------------------------------------------------- +// +// Function: LinkFilter1 +// +//---------------------------------------------------------------------------- + +BOOL +LinkFilter1( + PTHREADSTATE ThreadState, + LPSTR p + ) +{ + LPSTR FileName; + LPSTR p1; + char buffer[ 256 ]; + + if (p[ strlen( p ) - 1 ] == ':') { + return( LinkFilter( ThreadState, p ) ); + } + + p1 = p; + while (*p1) { + if (*p1 == '(') { + *p1++ = 0; + if (*p1 == '.' && p1[1] == '\\') { + p1 += 2; + } + FileName = p1; + while (*p1) { + if (*p1 == ')') { + *p1++ = 0; + strcpy( buffer, "L2029: Unresolved external reference to " ); + strcat( buffer, ThreadState->UndefinedId ); + FormatMsErrorMessage( ThreadState, FileName, "1", + buffer, FALSE + ); + return( TRUE ); + } + else { + p1++; + } + } + } + else { + p1++; + } + } + + return( FALSE ); +} + + +//+--------------------------------------------------------------------------- +// +// Function: LinkFilter +// +//---------------------------------------------------------------------------- + +BOOL +LinkFilter( + PTHREADSTATE ThreadState, + LPSTR p + ) +{ + LPSTR FileName; + LPSTR LineNumber; + LPSTR Message; + BOOL Warning; + LPSTR p1; + + p1 = p; + while (*p1) { + if (*p1 == ':') { + if (p1[-1] == ']') { + return( FALSE ); + } + + if (p1[-1] == ' ' && p1[1] == ' ') { + if (MsCompilerFilter( ThreadState, p, + &FileName, + &LineNumber, + &Message, + &Warning + ) + ) { + + if (!Warning || !(_strnicmp(Message, "L4021", 5) || + _strnicmp(Message, "L4038", 5) || + _strnicmp(Message, "L4046", 5))) { + if (LineNumber) + FileName = LineNumber; + if (FileName[0] == '.' && FileName[1] == '\\') { + FileName += 2; + } + FormatMsErrorMessage( ThreadState, FileName, "1", + Message, FALSE ); + return( TRUE ); + } + } + + FormatMsErrorMessage( ThreadState, FileName, "1", + Message, TRUE ); + + + return( TRUE ); + } + + if (p1[-1] == ')') { + p1 -= 11; + if (p1 > p && !strcmp( p1, " in file(s):" )) { + strcpy( ThreadState->UndefinedId, + IsolateFirstToken( &p, ' ' ) + ); + ThreadState->FilterProc = LinkFilter1; + return( TRUE ); + } + } + + return( FALSE ); + } + else { + p1++; + } + } + + return( FALSE ); +} + +//+--------------------------------------------------------------------------- +// +// Function: CoffFilter +// +//---------------------------------------------------------------------------- + +BOOL +CoffFilter( + PTHREADSTATE ThreadState, + LPSTR p + ) +{ + LPSTR FileName; + LPSTR LineNumber; + LPSTR Message; + BOOL Warning; + + if (MsCompilerFilter( ThreadState, p, + &FileName, + &LineNumber, + &Message, + &Warning + ) + ) { + if (fSilent && Warning) { + if (Substr( "LNK4016", Message )) { + Warning = FALSE; // undefined turns into an error + // for builds + } + } + + FormatMsErrorMessage( ThreadState, + FileName, LineNumber, Message, Warning ); + return( TRUE ); + } + else { + return( FALSE ); + } +} + +//+--------------------------------------------------------------------------- +// +// Function: ClRiscFilter +// +// Synopsis: Risc compiler filter +// +// Note: It may be possible to remove this filter. +// +//---------------------------------------------------------------------------- + +BOOL +ClRiscFilter( + PTHREADSTATE ThreadState, + LPSTR p + ) +{ + LPSTR FileName; + LPSTR LineNumber; + LPSTR Message; + BOOL Warning; + LPSTR q; + + if (TestPrefix( &p, "cfe: " )) { + if (strncmp(p, "Error: ", strlen("Error: ")) == 0) { + p += strlen("Error: "); + Warning = FALSE; + + } else if (strncmp(p, "Warning: ", strlen("Warning: ")) == 0) { + p += strlen("Warning: "); + Warning = TRUE; + } else { + return(FALSE); + } + + q = p; + if (p = strstr( p, ".\\\\" )) { + p += 3; + } else { + p = q; + } + + FileName = p; + while (*p > ' ') { + if (*p == ',' || (*p == ':' && *(p+1) == ' ')) { + *p++ = '\0'; + break; + } + + p++; + } + + if (*p != ' ') { + return( FALSE ); + } + + *p++ = '\0'; + + if (strcmp(p, "line ") == 0) { + p += strlen("line "); + + } + + LineNumber = p; + while (*p != '\0' && *p != ':') { + p++; + } + + if (*p != ':') { + return( FALSE ); + } + + *p++ = '\0'; + if (*p == ' ') { + Message = p+1; + ThreadState->LinesToIgnore = 2; + + if (fSilent && Warning) { + if (!strcmp( Message, "Unknown Control Statement" ) + ) { + return( FALSE ); + } + } + + FormatMsErrorMessage( ThreadState, + FileName, + LineNumber, + Message, + Warning + ); + return( TRUE ); + } + } + // + // If we did not recognize the cfe compiler, pass it to the MS compiler + // message filter + // + + return( C510Filter( ThreadState, p ) ); +} + +//+--------------------------------------------------------------------------- +// +// Function: MgClientFilter +// +//---------------------------------------------------------------------------- + +BOOL +MgClientFilter( + PTHREADSTATE ThreadState, + LPSTR p + ) +{ + return( PassThrough( ThreadState, p, TRUE ) ); +} + +BOOL fAlreadyUnknown = FALSE; + +//+--------------------------------------------------------------------------- +// +// Function: DetermineChildState +// +// Synopsis: Parse the message given by the compiler (or whatever) and try +// to figure out what it's doing. +// +// Arguments: [ThreadState] -- Current thread state +// [p] -- New message string +// +// Returns: TRUE if we figured it out, FALSE if we didn't recognize +// anything. +// +//---------------------------------------------------------------------------- + +BOOL +DetermineChildState( + PTHREADSTATE ThreadState, + LPSTR p + ) +{ + PFILEREC FileDB; + LPSTR FileName; + BOOL fPrintChildState = TRUE; + + // + // ************ Determine what state the child process is in. + // (Compiling, linking, running MIDL, etc.) + // + if ( TestPrefix( &p, "rc ") ) { + if (*p == ':') + return FALSE; // This is a warning/error string + if (strstr(p, "arm64") || strstr(p, "ARM64")) { + ThreadState->ChildTarget = Arm64TargetMachine.Description; + } else if (strstr( p, "amd64") || strstr( p, "AMD64")) { + ThreadState->ChildTarget = Amd64TargetMachine.Description; + } + else if (strstr( p, "i386") || strstr( p, "I386")) { + ThreadState->ChildTarget = i386TargetMachine.Description; + } + else if (strstr( p, "ia64") || strstr( p, "IA64")) { + ThreadState->ChildTarget = ia64TargetMachine.Description; + } + else { + ThreadState->ChildTarget = "unknown target"; + } + ThreadState->FilterProc = MSToolFilter; + ThreadState->ChildState = STATE_COMPILING; + ThreadState->ChildFlags = 0; + strcpy( ThreadState->ChildCurrentFile, + IsolateLastToken( p, ' ' ) + ); + } + else + + if (TestPrefix( &p, "rc16 ") ) { + if (*p == ':') + return FALSE; // This is a warning/error string + if (strstr(p, "arm64") || strstr(p, "ARM64")) { + ThreadState->ChildTarget = Arm64TargetMachine.Description; + } else if (strstr( p, "amd64") || strstr( p, "AMD64")) { + ThreadState->ChildTarget = Amd64TargetMachine.Description; + } + else if (strstr( p, "i386") || strstr( p, "I386")) { + ThreadState->ChildTarget = i386TargetMachine.Description; + } + else if (strstr( p, "ia64") || strstr( p, "IA64")) { + ThreadState->ChildTarget = ia64TargetMachine.Description; + } + else { + ThreadState->ChildTarget = "unknown target"; + } + ThreadState->FilterProc = MSToolFilter; + ThreadState->ChildState = STATE_COMPILING; + ThreadState->ChildFlags = 0; + strcpy( ThreadState->ChildCurrentFile, + IsolateLastToken( p, ' ' ) + ); + } + else + + if ( TestPrefix( &p, "cl " ) || TestPrefix( &p, "cl386 " ) ) { + LPSTR pch; + if (*p == ':') + return FALSE; // This is a warning/error string + ThreadState->FilterProc = C510Filter; + ThreadState->ChildFlags = 0; + if ( strstr( p, "/WX" ) != NULL || strstr( p, "-WX" ) != NULL) { + ThreadState->ChildFlags |= FLAGS_WARNINGS_ARE_ERRORS; + } + if ((strstr( p, "/EP " ) != NULL) || + (strstr( p, "/E " ) != NULL) || + (strstr( p, "/P " ) != NULL) || + (strstr( p, "-EP " ) != NULL) || + (strstr( p, "-E " ) != NULL) || + (strstr( p, "-P " ) != NULL) + ) { + if (strstr(p, "arm64") || strstr(p, "ARM64")) { + ThreadState->ChildTarget = Arm64TargetMachine.Description; + } else if (strstr( p, "amd64") || strstr( p, "AMD64")) { + ThreadState->ChildTarget = Amd64TargetMachine.Description; + } + else if (strstr( p, "i386") || strstr( p, "I386")) { + ThreadState->ChildTarget = i386TargetMachine.Description; + } + else if (strstr( p, "ia64") || strstr( p, "IA64")) { + ThreadState->ChildTarget = ia64TargetMachine.Description; + } + else { + ThreadState->ChildTarget = "unknown target"; + } + + strcpy( ThreadState->ChildCurrentFile,IsolateLastToken( p, ' ' ) ); + if ( strstr( p, ".s" ) != NULL ) + ThreadState->ChildState = STATE_S_PREPROC; + else + ThreadState->ChildState = STATE_C_PREPROC; + } + else + if ( (pch = strstr( p, "/Yc" )) != NULL ) { + size_t namelen = strcspn( pch+3, " \t" ); + if (strstr( p, "ia64") || strstr( p, "IA64")) { + ThreadState->ChildTarget = ia64TargetMachine.Description; + } else if (strstr( p, "amd64") || strstr( p, "AMD64")) { + ThreadState->ChildTarget = Amd64TargetMachine.Description; + } else { + ThreadState->ChildTarget = i386TargetMachine.Description; + } + + ThreadState->ChildState = STATE_PRECOMP; + strncpy( ThreadState->ChildCurrentFile, + pch + 3, namelen + ); + ThreadState->ChildCurrentFile[namelen] = '\0'; + } + else { + if (strstr( p, "ia64") || strstr( p, "IA64")) { + ThreadState->ChildTarget = ia64TargetMachine.Description; + } else if (strstr( p, "amd64") || strstr( p, "AMD64")) { + ThreadState->ChildTarget = Amd64TargetMachine.Description; + } else { + ThreadState->ChildTarget = i386TargetMachine.Description; + } + ThreadState->ChildState = STATE_COMPILING; + strcpy( ThreadState->ChildCurrentFile, "" ); + fPrintChildState = FALSE; + } + } + else + if ( TestPrefixPath( &p, "csc " ) || TestPrefixPath( &p, "csc.exe " ) ) { + + ThreadState->ChildState = STATE_COMPILING; + ThreadState->ChildFlags = 0; + ThreadState->ChildTarget = "all platforms"; + ThreadState->FilterProc = C510Filter; + strcpy( ThreadState->ChildCurrentFile, + IsolateLastToken( p, ' ' ) + ); + } + else + + if ( TestPrefix( &p, "cl16 " )) { + if (*p == ':') + return FALSE; // This is a warning/error string + ThreadState->FilterProc = C510Filter; + ThreadState->ChildFlags = 0; + if (strstr(p, "arm64") || strstr(p, "ARM64")) { + ThreadState->ChildTarget = Arm64TargetMachine.Description; + } else if (strstr( p, "amd64") || strstr( p, "AMD64")) { + ThreadState->ChildTarget = Amd64TargetMachine.Description; + } + else if (strstr( p, "i386") || strstr( p, "I386")) { + ThreadState->ChildTarget = i386TargetMachine.Description; + } + else if (strstr( p, "ia64") || strstr( p, "IA64")) { + ThreadState->ChildTarget = ia64TargetMachine.Description; + } + else { + ThreadState->ChildTarget = "unknown target"; + } + + ThreadState->ChildState = STATE_COMPILING; + strcpy( ThreadState->ChildCurrentFile, + IsolateLastToken( p, ' ' )); + } + else + + if ((TestPrefix( &p, "ml " )) || + (TestPrefix( &p, "ml64 " ))) { + if (*p == ':') + return FALSE; // This is a warning/error string + ThreadState->FilterProc = MSToolFilter; + ThreadState->ChildState = STATE_ASSEMBLING; + ThreadState->ChildFlags = 0; + if (strstr(p, "arm64") || strstr(p, "ARM64")) { + ThreadState->ChildTarget = Arm64TargetMachine.Description; + } else if (strstr( p, "amd64") || strstr( p, "AMD64")) { + ThreadState->ChildTarget = Amd64TargetMachine.Description; + } + else if (strstr( p, "i386") || strstr( p, "I386")) { + ThreadState->ChildTarget = i386TargetMachine.Description; + } + else { + ThreadState->ChildTarget = "unknown target"; + } + strcpy( ThreadState->ChildCurrentFile, + IsolateLastToken( p, ' ' ) + ); + } + else + + if (TestPrefix( &p, "masm386 ") || TestPrefix( &p, "masm ")) { + if (*p == ':') + return FALSE; // This is a warning/error string + ThreadState->FilterProc = MSToolFilter; + ThreadState->ChildState = STATE_ASSEMBLING; + ThreadState->ChildFlags = 0; + if (strstr(p, "arm64") || strstr(p, "ARM64")) { + ThreadState->ChildTarget = Arm64TargetMachine.Description; + } else if (strstr( p, "amd64") || strstr( p, "AMD64")) { + ThreadState->ChildTarget = Amd64TargetMachine.Description; + } + else if (strstr( p, "i386") || strstr( p, "I386")) { + ThreadState->ChildTarget = i386TargetMachine.Description; + } + else if (strstr( p, "ia64") || strstr( p, "IA64")) { + ThreadState->ChildTarget = ia64TargetMachine.Description; + } + else { + ThreadState->ChildTarget = "unknown target"; + } + + if (strstr(p, ",")) { + strcpy( ThreadState->ChildCurrentFile, + IsolateLastToken(IsolateFirstToken(&p,','), ' ')); + } + else { + strcpy( ThreadState->ChildCurrentFile, + IsolateLastToken(IsolateFirstToken(&p,';'), ' ')); + } + + } + else + + if (TestPrefix( &p, "lib " ) ) { + if (*p == ':') + return FALSE; // This is a warning/error string + while (*p == ' ') { + p++; + } + if (strstr(p, "arm64") || strstr(p, "ARM64")) { + ThreadState->ChildTarget = Arm64TargetMachine.Description; + } else if (strstr( p, "amd64") || strstr( p, "AMD64")) { + ThreadState->ChildTarget = Amd64TargetMachine.Description; + } + else if (strstr( p, "i386") || strstr( p, "I386")) { + ThreadState->ChildTarget = i386TargetMachine.Description; + } + else if (strstr( p, "ia64") || strstr( p, "IA64")) { + ThreadState->ChildTarget = ia64TargetMachine.Description; + } + else { + ThreadState->ChildTarget = "unknown target"; + } + ThreadState->FilterProc = CoffFilter; + ThreadState->ChildFlags = 0; + if (TestPrefix( &p, "-out:" )) { + ThreadState->LinesToIgnore = 1; + ThreadState->ChildState = STATE_LIBING; + strcpy( ThreadState->ChildCurrentFile, + IsolateFirstToken( &p, ' ' ) + ); + } + else + if (TestPrefix( &p, "-def:" )) { + ThreadState->LinesToIgnore = 1; + ThreadState->ChildState = STATE_LIBING; + strcpy( ThreadState->ChildCurrentFile, + IsolateFirstToken( &p, ' ' ) + ); + if (TestPrefix( &p, "-out:" )) { + strcpy( ThreadState->ChildCurrentFile, + IsolateFirstToken( &p, ' ' ) + ); + } + } + else { + return FALSE; + } + } + else + + if (TestPrefix( &p, "lib16 " ) || TestPrefix( &p, "implib " ) ) { + if (*p == ':') + return FALSE; // This is a warning/error string + while (*p == ' ') { + p++; + } + if (strstr(p, "arm64") || strstr(p, "ARM64")) { + ThreadState->ChildTarget = Arm64TargetMachine.Description; + } else if (strstr( p, "amd64") || strstr( p, "AMD64")) { + ThreadState->ChildTarget = Amd64TargetMachine.Description; + } + else if (strstr( p, "i386") || strstr( p, "I386")) { + ThreadState->ChildTarget = i386TargetMachine.Description; + } + else if (strstr( p, "ia64") || strstr( p, "IA64")) { + ThreadState->ChildTarget = ia64TargetMachine.Description; + } + else { + ThreadState->ChildTarget = "unknown target"; + } + + ThreadState->FilterProc = MSToolFilter; + ThreadState->ChildFlags = 0; + ThreadState->ChildState = STATE_LIBING; + if (strstr(p, ";")) { + strcpy( ThreadState->ChildCurrentFile, + IsolateFirstToken( &p, ';' )); + } + else { + strcpy( ThreadState->ChildCurrentFile, + IsolateFirstToken( &p, ' ' )); + } + } + else + + if (TestPrefix( &p, "link " ) ) { + if (*p == ':') + return FALSE; // This is a warning/error string + while (*p == ' ') { + p++; + } + if (strstr(p, "arm64") || strstr(p, "ARM64")) { + ThreadState->ChildTarget = Arm64TargetMachine.Description; + } else if (strstr( p, "amd64") || strstr( p, "AMD64")) { + ThreadState->ChildTarget = Amd64TargetMachine.Description; + } + else if (strstr( p, "i386") || strstr( p, "I386")) { + ThreadState->ChildTarget = i386TargetMachine.Description; + } + else if (strstr( p, "ia64") || strstr( p, "IA64")) { + ThreadState->ChildTarget = ia64TargetMachine.Description; + } + else { + ThreadState->ChildTarget = "unknown target"; + } + ThreadState->FilterProc = CoffFilter; + ThreadState->ChildFlags = 0; + if (TestPrefix( &p, "-out:" )) { + ThreadState->LinesToIgnore = 2; + ThreadState->ChildState = STATE_LINKING; + strcpy( ThreadState->ChildCurrentFile, + IsolateFirstToken( &p, ' ' ) + ); + } + } + else + + if (TestPrefix( &p, "link16" ) ) { + if (*p == ':') + return FALSE; // This is a warning/error string + while (*p == ' ') { + p++; + } + if (strstr(p, "arm64") || strstr(p, "ARM64")) { + ThreadState->ChildTarget = Arm64TargetMachine.Description; + } else if (strstr( p, "amd64") || strstr( p, "AMD64")) { + ThreadState->ChildTarget = Amd64TargetMachine.Description; + } + else if (strstr( p, "i386") || strstr( p, "I386")) { + ThreadState->ChildTarget = i386TargetMachine.Description; + } + else if (strstr( p, "ia64") || strstr( p, "IA64")) { + ThreadState->ChildTarget = ia64TargetMachine.Description; + } + else { + ThreadState->ChildTarget = "unknown target"; + } + + ThreadState->FilterProc = LinkFilter; + ThreadState->ChildFlags = 0; + ThreadState->ChildState = STATE_LINKING; + p = IsolateLastToken(p, ' '); + if (strstr(p, ";")) { + strcpy( ThreadState->ChildCurrentFile, + IsolateFirstToken( &p, ';' )); + } + else { + strcpy( ThreadState->ChildCurrentFile, + IsolateFirstToken( &p, ',' )); + } + + } + else + + + if (TestPrefix( &p, "icl ")) { + while (*p == ' ') { + p++; + } + ThreadState->ChildState = STATE_COMPILING; + ThreadState->ChildFlags = 0; + ThreadState->ChildTarget = ia64TargetMachine.Description; + ThreadState->FilterProc = C510Filter; + + strcpy( ThreadState->ChildCurrentFile, + IsolateLastToken( p, ' ' ) + ); + } + else + + if (TestPrefix( &p, "mktyplib " )) { + if (*p == ':') + return FALSE; // This is a warning/error string + while (*p == ' ') { + p++; + } + + ThreadState->ChildState = STATE_MKTYPLIB; + ThreadState->ChildFlags = 0; + ThreadState->ChildTarget = "all platforms"; + ThreadState->FilterProc = C510Filter; + + strcpy( ThreadState->ChildCurrentFile, + IsolateLastToken( p, ' ' ) + ); + } + else + + if (TestPrefix( &p, "MC: Compiling " )) { + if (*p == ':') + return FALSE; // This is a warning/error string + while (*p == ' ') { + p++; + } + + ThreadState->ChildState = STATE_MC; + ThreadState->ChildFlags = 0; + ThreadState->ChildTarget = "all platforms"; + ThreadState->FilterProc = C510Filter; + + strcpy( ThreadState->ChildCurrentFile, + IsolateLastToken( p, ' ' ) + ); + } + else + + if (TestPrefix( &p, "midl " )) { + if (*p == ':') + return FALSE; // This is a warning/error string + while (*p == ' ') { + p++; + } + + ThreadState->ChildState = STATE_MIDL; + ThreadState->ChildFlags = 0; + ThreadState->ChildTarget = "all platforms"; + ThreadState->FilterProc = C510Filter; + + strcpy( ThreadState->ChildCurrentFile, + IsolateLastToken( p, ' ' ) + ); + } + else + + if (TestPrefix( &p, "asn1 " )) { + if (*p == ':') + return FALSE; // This is a warning/error string + while (*p == ' ') { + p++; + } + + ThreadState->ChildState = STATE_ASN; + ThreadState->ChildFlags = 0; + ThreadState->ChildTarget = "all platforms"; + ThreadState->FilterProc = C510Filter; + + strcpy(ThreadState->ChildCurrentFile, IsolateLastToken(p, ' ')); + } + else + + if (TestPrefix( &p, "Build_Status " )) { + while (*p == ' ') { + p++; + } + + ThreadState->ChildState = STATE_STATUS; + ThreadState->ChildFlags = 0; + ThreadState->ChildTarget = ""; + ThreadState->FilterProc = C510Filter; + + strcpy( ThreadState->ChildCurrentFile, "" ); + } + + else + if (TestPrefix( &p, "binplace " )) { + if (*p == ':') + return FALSE; // This is a warning/error string + + NumberBinplaces++; + + while (*p == ' ') { + p++; + } + + // If this is a standard link/binplace step, don't tell the + // user what's going on, just pass any errors/warnings to + // the output. If this is a straight binplace, list the state. + + if (ThreadState->ChildState == STATE_LINKING) { + ThreadState->ChildState = STATE_BINPLACE; + ThreadState->ChildFlags = 0; + ThreadState->FilterProc = MSToolFilter; + return TRUE; + } else { + ThreadState->ChildState = STATE_BINPLACE; + ThreadState->ChildFlags = 0; + ThreadState->FilterProc = MSToolFilter; + strcpy( ThreadState->ChildCurrentFile, IsolateLastToken( p, ' ' ) ); + } + } + + else + if (TestPrefix( &p, "cmdcomp " ) || + TestPrefix( &p, "cmtempl " ) || + TestPrefix( &p, "maptweak ") || + TestPrefix( &p, "genord ") || + TestPrefix( &p, "makehm ") + ) { + if (*p == ':') + return FALSE; // This is a warning/error string + while (*p == ' ') { + p++; + } + + ThreadState->ChildState = STATE_VCTOOL; + ThreadState->ChildFlags = 0; + ThreadState->FilterProc = MSToolFilter; + strcpy( ThreadState->ChildCurrentFile, IsolateLastToken( p, ' ' ) ); + } + + else + if ((TestPrefix( &p, "packthem " )) || (TestPrefix( &p, "..\\packthem " ))) + { + if (*p == ':') + return FALSE; // This is a warning/error string + + while (*p == ' ') + p++; + + ThreadState->ChildTarget = i386TargetMachine.Description; + + ThreadState->FilterProc = CoffFilter; + ThreadState->ChildFlags = 0; + ThreadState->ChildState = STATE_PACKING; + + if (TestPrefix( &p, "-o" )) + { + strcpy( ThreadState->ChildCurrentFile, IsolateFirstToken( &p, ' ' )); + } + } + + else { + + return FALSE; + } + + // + // ***************** Set the Thread State according to what we determined. + // + FileName = ThreadState->ChildCurrentFile; + + if (TestPrefix( &FileName, CurrentDirectory )) { + if (*FileName == '\\') { + FileName++; + } + + if (TestPrefix( &FileName, ThreadState->ChildCurrentDirectory )) { + if (*FileName == '\\') { + FileName++; + } + } + + strcpy( ThreadState->ChildCurrentFile, FileName ); + } + + FileDB = NULL; + + if (ThreadState->ChildState == STATE_LIBING) { + NumberLibraries++; + } + else + if (ThreadState->ChildState == STATE_LINKING) { + NumberLinks++; + } + else + if ((ThreadState->ChildState == STATE_STATUS) || + // Don't need to do anything here - binplace count already handled above + (ThreadState->ChildState == STATE_BINPLACE) || + (ThreadState->ChildState == STATE_UNKNOWN)) { + ; // Do nothing. + } + else { + if (ThreadState->CompileDirDB) { + NumberCompiles++; + CopyString( // fixup path string + ThreadState->ChildCurrentFile, + ThreadState->ChildCurrentFile, + TRUE); + + if (!fQuicky) { + FileDB = FindSourceFileDB( + ThreadState->CompileDirDB, + ThreadState->ChildCurrentFile, + NULL); + } + } + } + + if (strstr(ThreadState->ChildCurrentFile, ".cxx") || + strstr(ThreadState->ChildCurrentFile, ".cpp")) { + ThreadState->ChildFlags |= FLAGS_CXX_FILE; + } + + if (fPrintChildState) + PrintChildState(ThreadState, p, FileDB); + return TRUE; +} + +//+--------------------------------------------------------------------------- +// +// Function: PrintChildState +// +// Synopsis: +// +// Arguments: [ThreadState] -- Current thread state +// +// Returns: TRUE if we figured it out, FALSE if we didn't recognize +// anything. +// +//---------------------------------------------------------------------------- + +void +PrintChildState( + PTHREADSTATE ThreadState, + LPSTR p, + PFILEREC FileDB + ) +{ + USHORT SaveCol; + USHORT SaveRow; + USHORT SaveRowTop; + BOOL fStatusOutput = FALSE; + char buffer[ DB_MAX_PATH_LENGTH ]; + LONG FilesLeft; + LONG LinesLeft; + ULONG LinesPerSecond; + ULONG SecondsLeft; + ULONG PercentDone; + + // + // *********************** Print the thread state to the screen + // + if (ThreadState->IsStdErrTty) { + GetScreenSize(ThreadState); + assert(ThreadState->cColTotal != 0); + assert(ThreadState->cRowTotal != 0); + + if (fStatus) { + GetCursorPosition(&SaveRow, &SaveCol, &SaveRowTop); + + // Clear row for process message + ClearRows (ThreadState, + (USHORT) (SaveRowTop + ThreadState->ThreadIndex - 1), + 1, + StatusCell); + + // Clear row for status message + ClearRows (ThreadState, + (USHORT) (SaveRowTop + NumberProcesses), + 1, + StatusCell); + + // Make sure there's still some room at the bottom + if (SaveRow == LastRow(ThreadState)) { + USHORT RowTop = 1 + SaveRowTop + (USHORT) NumberProcesses + 1; + + MoveRectangleUp ( + RowTop, // Top + 0, // Left + LastRow(ThreadState), // Bottom + LastCol(ThreadState), // Right + 1, // NumRow + ScreenCell); // FillCell + + SaveRow--; + } + + SetCursorPosition( + (USHORT) (SaveRowTop + ThreadState->ThreadIndex - 1), + 0); + fStatusOutput = TRUE; + } + } + + if (szBuildTag) { + sprintf(buffer, "%s: ", szBuildTag); + WriteTTY(ThreadState, buffer, fStatusOutput); + } + + if (fParallel && !fNoThreadIndex) { + sprintf(buffer, "%d>", ThreadState->ThreadIndex); + WriteTTY(ThreadState, buffer, fStatusOutput); + } + + if (ThreadState->ChildState == STATE_UNKNOWN) { + if (!fAlreadyUnknown) { + WriteTTY( + ThreadState, + "Processing Unknown item(s)...\r\n", + fStatusOutput); + fAlreadyUnknown = TRUE; + } + } + else + if (ThreadState->ChildState == STATE_STATUS) { + WriteTTY(ThreadState, p, fStatusOutput); + WriteTTY(ThreadState, "\r\n", fStatusOutput); + } + else { + fAlreadyUnknown = FALSE; + WriteTTY(ThreadState, States[ThreadState->ChildState], fStatusOutput); + WriteTTY(ThreadState, " - ", fStatusOutput); + WriteTTY( + ThreadState, + FormatPathName(ThreadState->ChildCurrentDirectory, + ThreadState->ChildCurrentFile), + fStatusOutput); + + WriteTTY(ThreadState, " for ", fStatusOutput); + WriteTTY(ThreadState, ThreadState->ChildTarget, fStatusOutput); + WriteTTY(ThreadState, "\r\n", fStatusOutput); + } + + if (StartCompileTime) { + ElapsedCompileTime += (ULONG)(time(NULL) - StartCompileTime); + } + + if (FileDB != NULL) { + StartCompileTime = time(NULL); + } + else { + StartCompileTime = 0L; + } + + // + // ****************** Update the status line + // + if (fStatus) { + if (FileDB != NULL) { + FilesLeft = TotalFilesToCompile - TotalFilesCompiled; + if (FilesLeft < 0) { + FilesLeft = 0; + } + LinesLeft = TotalLinesToCompile - TotalLinesCompiled; + if (LinesLeft < 0) { + LinesLeft = 0; + PercentDone = 99; + } + else if (TotalLinesToCompile != 0) { + if (TotalLinesCompiled > 20000000L) { + int TLC = TotalLinesCompiled / 100; + int TLTC = TotalLinesToCompile / 100; + + PercentDone = (TLC * 100L)/TLTC; + } + else + PercentDone = (TotalLinesCompiled * 100L)/TotalLinesToCompile; + } + else { + PercentDone = 0; + } + + if (ElapsedCompileTime != 0) { + LinesPerSecond = TotalLinesCompiled / ElapsedCompileTime; + } + else { + LinesPerSecond = 0; + } + + if (LinesPerSecond != 0) { + SecondsLeft = LinesLeft / LinesPerSecond; + } + else { + SecondsLeft = LinesLeft / DEFAULT_LPS; + } + + sprintf( + buffer, + "%2d%% done. %4ld %sLPS Time Left:%s Files: %d %sLines: %s\r\n", + PercentDone, + LinesPerSecond, + fStatusTree? "T" : "", + FormatTime(SecondsLeft), + FilesLeft, + fStatusTree? "Total " : "", + FormatNumber(LinesLeft)); + + SetCursorPosition((USHORT) (SaveRowTop + NumberProcesses), 0); + + WriteTTY(ThreadState, buffer, fStatusOutput); + } + + if (ThreadState->IsStdErrTty) { + assert(ThreadState->cColTotal != 0); + assert(ThreadState->cRowTotal != 0); + SetCursorPosition(SaveRow, SaveCol); + } + } + + // + // ***************** Keep track of how many files have been compiled. + // + if (ThreadState->ChildState == STATE_COMPILING || + ThreadState->ChildState == STATE_ASSEMBLING || + ThreadState->ChildState == STATE_MKTYPLIB || + ThreadState->ChildState == STATE_MIDL || + ThreadState->ChildState == STATE_ASN || + (FileDB != NULL && ThreadState->ChildState == STATE_PRECOMP)) { + TotalFilesCompiled++; + } + if (FileDB != NULL) { + TotalLinesCompiled += FileDB->TotalSourceLines; + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: ProcessLine +// +// Synopsis: Watch the lines coming from the thread for special strings. +// +//---------------------------------------------------------------------------- + +BOOL +ProcessLine( + PTHREADSTATE ThreadState, + LPSTR p + ) +{ + LPSTR p1; + + while (*p <= ' ') { + if (!*p) { + return( FALSE ); + } + else { + p++; + } + } + + p1 = p; + while (*p1) { + if (*p1 == '\r') + break; + else + p1++; + } + *p1 = '\0'; + + p1 = p; + if (TestPrefix( &p1, "Stop." )) { + return( TRUE ); + } + + // Stop multithread access to shared: + // database + // window + // compilation stats + + EnterCriticalSection(&TTYCriticalSection); + + if (strstr(p, ": error ") != NULL || + strstr(p, ": fatal error ") != NULL || + strstr(p, ": command line error ") != NULL) { + PassThrough(ThreadState, p, FALSE); + } else + if (strstr(p, ": warning ") != NULL) { + PassThrough(ThreadState, p, TRUE); + } else + if (TestPrefix( &p1, "nmake :" )) { + PassThrough( ThreadState, p, FALSE ); + } else + if (TestPrefix( &p1, "BUILDMSG: " )) { + if (TestPrefix(&p1, "Warning")) { + PassThrough(ThreadState, p, TRUE); + } else { + WriteTTY(ThreadState, p, TRUE); + WriteTTY(ThreadState, "\r\n", TRUE); + } + } else + if (ThreadState->LinesToIgnore) { + ThreadState->LinesToIgnore--; + } + else { + if ( !DetermineChildState( ThreadState, p ) ) { + if (ThreadState->FilterProc != NULL) { + (*ThreadState->FilterProc)( ThreadState, p ); + } + } + } + + LeaveCriticalSection(&TTYCriticalSection); + + return( FALSE ); +} + + +//+--------------------------------------------------------------------------- +// +// Function: FilterThread +// +// Synopsis: Capture the output of the thread and process it. +// +//---------------------------------------------------------------------------- + +VOID +FilterThread( + PTHREADSTATE ThreadState + ) +{ + UINT CountBytesRead; + LPSTR StartPointer = NULL; + LPSTR EndPointer; + LPSTR NewPointer; + ULONG BufSize = 512; + + AllocMem(BufSize, &StartPointer, MT_THREADFILTER); + while (TRUE) { + EndPointer = StartPointer; + do { + if (BufSize - (EndPointer-StartPointer) < 512) { + AllocMem(BufSize*2, &NewPointer, MT_THREADFILTER); + RtlCopyMemory( + NewPointer, + StartPointer, + EndPointer - StartPointer + 1); // copy null byte, too + EndPointer += NewPointer - StartPointer; + FreeMem(&StartPointer, MT_THREADFILTER); + StartPointer = NewPointer; + BufSize *= 2; + } + errno = 0; + if (!fgets(EndPointer, 512, ThreadState->ChildOutput)) { + // EOF is the normal end of a redirected child process. + // Modern CRTs do not guarantee errno is cleared on EOF, so + // testing errno here reports stale errors from unrelated I/O. + if (ferror(ThreadState->ChildOutput)) { + BuildError("Pipe read failed - errno = %d\n", errno); + } + FreeMem(&StartPointer, MT_THREADFILTER); + return; + } + CountBytesRead = strlen(EndPointer); + EndPointer = EndPointer + CountBytesRead; + } while (CountBytesRead == 511 && EndPointer[-1] != '\n'); + + CountBytesRead = (UINT)(EndPointer - StartPointer); + if (LogFile != NULL && CountBytesRead) { + if (fParallel && !fNoThreadIndex) { + char buffer[50]; + sprintf(buffer, "%d>", ThreadState->ThreadIndex); + fwrite(buffer, 1, strlen(buffer), LogFile); + } + fwrite(StartPointer, 1, CountBytesRead, LogFile); + } + + if (ProcessLine(ThreadState, StartPointer)) { + FreeMem(&StartPointer, MT_THREADFILTER); + return; + } + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: ExecuteProgram +// +// Synopsis: Spawn a new thread to execute the given program and filter +// its output. +// +// Arguments: [ProgramName] -- +// [CommandLine] -- +// [MoreCommandLine] -- +// [MustBeSynchronous] -- For synchronous operation on a +// multi-processor machine. +// +// Returns: ERROR_SUCCESS, ERROR_NOTENOUGHMEMORY, or return code from +// PipeSpawnClose. +// +// Notes: On a multiprocessor machine, this will spawn a new thread +// and then return, letting the thread run asynchronously. Use +// WaitForParallelThreads() to ensure all threads are finished. +// By default, this routine will spawn as many threads as the +// machine has processors. This can be overridden with the -M +// option. +// +//---------------------------------------------------------------------------- + +char ExecuteProgramCmdLine[ 1024 ]; + +UINT +ExecuteProgram( + LPSTR ProgramName, + LPSTR CommandLine, + LPSTR MoreCommandLine, + BOOL MustBeSynchronous) +{ + LPSTR p; + UINT rc; + THREADSTATE *ThreadState; + UINT OldErrorMode; + + AllocMem(sizeof(THREADSTATE), &ThreadState, MT_THREADSTATE); + + memset(ThreadState, 0, sizeof(*ThreadState)); + ThreadState->ChildState = STATE_UNKNOWN; + ThreadState->ChildTarget = "Unknown Target"; + ThreadState->IsStdErrTty = (BOOL) _isatty(_fileno(stderr)); + ThreadState->CompileDirDB = CurrentCompileDirDB; + + if (ThreadState->IsStdErrTty) { + GetScreenSize(ThreadState); + assert(ThreadState->cColTotal != 0); + assert(ThreadState->cRowTotal != 0); + + // We're displaying to the screen, so initialize the console. + + if (!fConsoleInitialized) { + StatusCell[1] = + BACKGROUND_RED | + FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN | + FOREGROUND_INTENSITY; + + ReadConsoleCells(ScreenCell, sizeof(ScreenCell), 2, 0); + + // If we stumbled upon an old Status line in row 2 of the window, + // try the current row to avoid using the Status line background + // colors for fill when scrolling. + + if (ScreenCell[1] == StatusCell[1]) { + USHORT Row, Col; + + GetCursorPosition(&Row, &Col, NULL); + ReadConsoleCells(ScreenCell, sizeof(ScreenCell), Row, 0); + } + ScreenCell[0] = StatusCell[0] = ' '; + + GetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), &OldConsoleMode); + NewConsoleMode = OldConsoleMode; + fConsoleInitialized = TRUE; + } + if (fStatus) + { + NewConsoleMode = OldConsoleMode & ~(ENABLE_WRAP_AT_EOL_OUTPUT); + } else + { + NewConsoleMode = OldConsoleMode | ENABLE_WRAP_AT_EOL_OUTPUT; + } + SetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), NewConsoleMode); + } + else { + ThreadState->cRowTotal = 0; + ThreadState->cColTotal = 0; + } + + p = ThreadState->ChildCurrentDirectory; + GetCurrentDirectory(sizeof(ThreadState->ChildCurrentDirectory), p); + + if (TestPrefix(&p, CurrentDirectory)) { + if (*p == '\\') { + p++; + } + strcpy(ThreadState->ChildCurrentDirectory, p); + } + + if (ThreadState->ChildCurrentDirectory[0]) { + strcat(ThreadState->ChildCurrentDirectory, "\\"); + } + + sprintf( + ExecuteProgramCmdLine, + "%s %s%s", + ProgramName, + CommandLine, + MoreCommandLine); + LogMsg("'%s %s%s'\n", ProgramName, CommandLine, MoreCommandLine); + + if (fParallel && !MustBeSynchronous) { + PPARALLEL_CHILD ChildData; + DWORD i; + DWORD ThreadId; + + AllocMem(sizeof(PARALLEL_CHILD), &ChildData, MT_CHILDDATA); + strcpy(ChildData->ExecuteProgramCmdLine,ExecuteProgramCmdLine); + ChildData->ThreadState = ThreadState; + + if (ThreadsStarted < NumberProcesses) { + if (ThreadsStarted == 0) { + AllocMem( + sizeof(HANDLE) * NumberProcesses, + (VOID **) &WorkerThreads, + MT_THREADHANDLES); + AllocMem( + sizeof(HANDLE) * NumberProcesses, + (VOID **) &WorkerEvents, + MT_EVENTHANDLES); + } + WorkerEvents[ThreadsStarted] = CreateEvent(NULL, + FALSE, + FALSE, + NULL); + ChildData->Event = WorkerEvents[ThreadsStarted]; + + ThreadState->ThreadIndex = ThreadsStarted+1; + WorkerThreads[ThreadsStarted] = CreateThread(NULL, + 0, + (LPTHREAD_START_ROUTINE)ParallelChildStart, + ChildData, + 0, + &ThreadId); + if ((WorkerThreads[ThreadsStarted] == NULL) || + (WorkerEvents[ThreadsStarted] == NULL)) { + FreeMem(&ChildData, MT_CHILDDATA); + FreeMem(&ThreadState, MT_THREADSTATE); + return(ERROR_NOT_ENOUGH_MEMORY); + } else { + WaitForSingleObject(WorkerEvents[ThreadsStarted],INFINITE); + ++ThreadsStarted; + } + } else { + // + // Wait for a thread to complete before starting + // the next one. + // + i = WaitForMultipleObjects(NumberProcesses, + WorkerThreads, + FALSE, + INFINITE); + CloseHandle(WorkerThreads[i]); + ChildData->Event = WorkerEvents[i]; + ThreadState->ThreadIndex = i+1; + WorkerThreads[i] = CreateThread(NULL, + 0, + (LPTHREAD_START_ROUTINE)ParallelChildStart, + ChildData, + 0, + &ThreadId); + if (WorkerThreads[i] == NULL) { + FreeMem(&ChildData, MT_CHILDDATA); + FreeMem(&ThreadState, MT_THREADSTATE); + return(ERROR_NOT_ENOUGH_MEMORY); + } else { + WaitForSingleObject(WorkerEvents[i],INFINITE); + } + } + + return(ERROR_SUCCESS); + + } else { + + // + // Synchronous operation + // + StartCompileTime = 0L; + ThreadState->ThreadIndex = 1; + + // + // Disable child error popups in child processes. + // + + if (fClean) { + OldErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX ); + } + + ThreadState->ChildOutput = PipeSpawn( ExecuteProgramCmdLine ); + if (fClean) { + SetErrorMode( OldErrorMode ); + } + + rc = ERROR_SUCCESS; + + if (ThreadState->ChildOutput == NULL) { + rc = ERROR_FILE_NOT_FOUND; + InterlockedIncrement(&BuildChildFailures); + BuildError( + "Exec of '%s' failed - errno = %d\n", + ExecuteProgramCmdLine, + errno); + } + else { + FilterThread( ThreadState ); + + if (StartCompileTime) { + ElapsedCompileTime += (ULONG)(time(NULL) - StartCompileTime); + } + + rc = PipeSpawnClose( ThreadState->ChildOutput ); + if (rc == -1) { + InterlockedIncrement(&BuildChildFailures); + BuildError("Child terminate failed - errno = %d\n", errno); + } + else if (rc) { + InterlockedIncrement(&BuildChildFailures); + BuildError("%s failed - rc = %d\n", ProgramName, rc); + } + } + + if (ThreadState->IsStdErrTty) { + RestoreConsoleMode(); + } + + FreeMem(&ThreadState, MT_THREADSTATE); + return( rc ); + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: WaitForParallelThreads +// +// Synopsis: Wait for all threads to finish before returning. +// +//---------------------------------------------------------------------------- + +VOID +WaitForParallelThreads( + VOID + ) +{ + if (fParallel) { + WaitForMultipleObjects(ThreadsStarted, + WorkerThreads, + TRUE, + INFINITE); + while (ThreadsStarted) { + CloseHandle(WorkerThreads[--ThreadsStarted]); + CloseHandle(WorkerEvents[ThreadsStarted]); + } + if (WorkerThreads != NULL) { + FreeMem((VOID **) &WorkerThreads, MT_THREADHANDLES); + FreeMem((VOID **) &WorkerEvents, MT_EVENTHANDLES); + } + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: ParallelChildStart +// +// Synopsis: Function that is run once for each thread. +// +// Arguments: [Data] -- Data given to CreateThread. +// +//---------------------------------------------------------------------------- + +DWORD +ParallelChildStart( + PPARALLEL_CHILD Data + ) +{ + UINT OldErrorMode; + UINT rc = ERROR_SUCCESS; + + // + // Disable child error popups + // + if (fClean) { + OldErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX ); + } + Data->ThreadState->ChildOutput = PipeSpawn(Data->ExecuteProgramCmdLine); + + if (fClean) { + SetErrorMode(OldErrorMode); + } + + // + // Poke the event to indicate that the child process has + // started and it is ok for the main thread to change + // the current directory. + // + SetEvent(Data->Event); + + if (Data->ThreadState->ChildOutput==NULL) { + rc = ERROR_FILE_NOT_FOUND; + InterlockedIncrement(&BuildChildFailures); + BuildError( + "Exec of '%s' failed - errno = %d\n", + ExecuteProgramCmdLine, + errno); + } else { + FilterThread(Data->ThreadState); + rc = PipeSpawnClose(Data->ThreadState->ChildOutput); + if (rc == -1) { + InterlockedIncrement(&BuildChildFailures); + BuildError("Child terminate failed - errno = %d\n", errno); + } else if (rc) { + InterlockedIncrement(&BuildChildFailures); + BuildError("%s failed - rc = %d\n", Data->ExecuteProgramCmdLine, rc); + } + } + + if (Data->ThreadState->IsStdErrTty) { + RestoreConsoleMode(); + } + FreeMem(&Data->ThreadState, MT_THREADSTATE); + FreeMem(&Data, MT_CHILDDATA); + return(rc); + +} + + +//+--------------------------------------------------------------------------- +// +// Function: ClearRows +// +//---------------------------------------------------------------------------- + +VOID +ClearRows( + THREADSTATE *ThreadState, + USHORT Top, + USHORT NumRows, + BYTE *Cell) +{ + COORD Coord; + DWORD NumWritten; + + Coord.X = 0; + Coord.Y = Top; + + FillConsoleOutputCharacter( + GetStdHandle(STD_ERROR_HANDLE), + Cell[0], + ThreadState->cColTotal * NumRows, + Coord, + &NumWritten); + FillConsoleOutputAttribute( + GetStdHandle(STD_ERROR_HANDLE), + (WORD) Cell[1], + ThreadState->cColTotal * NumRows, + Coord, + &NumWritten); +} + + +//+--------------------------------------------------------------------------- +// +// Function: GetScreenSize +// +//---------------------------------------------------------------------------- + +VOID +GetScreenSize(THREADSTATE *ThreadState) +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + + if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi)) { + ThreadState->cRowTotal = 25; + ThreadState->cColTotal = 80; + } + else { + ThreadState->cRowTotal = csbi.srWindow.Bottom + 1; + ThreadState->cColTotal = csbi.dwSize.X; + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: GetCursorPosition +// +//---------------------------------------------------------------------------- + +VOID +GetCursorPosition( + USHORT *pRow, + USHORT *pCol, + USHORT *pRowTop) +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + + GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi); + *pRow = csbi.dwCursorPosition.Y; + *pCol = csbi.dwCursorPosition.X; + if (pRowTop != NULL) { + *pRowTop = csbi.srWindow.Top; + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: SetCursorPosition +// +//---------------------------------------------------------------------------- + +VOID +SetCursorPosition(USHORT Row, USHORT Col) +{ + COORD Coord; + + Coord.X = Col; + Coord.Y = Row; + SetConsoleCursorPosition(GetStdHandle(STD_ERROR_HANDLE), Coord); +} + + +//+--------------------------------------------------------------------------- +// +// Function: WriteConsoleCells +// +//---------------------------------------------------------------------------- + +VOID +WriteConsoleCells( + LPSTR String, + USHORT StringLength, + USHORT Row, + USHORT Col, + BYTE *Attribute) +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + DWORD NumWritten; + WORD OldAttribute; + COORD StartCoord; + + // + // Get current default attribute and save it. + // + + GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi); + + OldAttribute = csbi.wAttributes; + + // + // Set the default attribute to the passed parameter, along with + // the cursor position. + // + + if ((BYTE) OldAttribute != *Attribute) { + SetConsoleTextAttribute( + GetStdHandle(STD_ERROR_HANDLE), + (WORD) *Attribute); + } + + StartCoord.X = Col; + StartCoord.Y = Row; + SetConsoleCursorPosition(GetStdHandle(STD_ERROR_HANDLE), StartCoord); + + // + // Write the passed string at the current cursor position, using the + // new default attribute. + // + + WriteFile( + GetStdHandle(STD_ERROR_HANDLE), + String, + StringLength, + &NumWritten, + NULL); + + // + // Restore previous default attribute. + // + + if ((BYTE) OldAttribute != *Attribute) { + SetConsoleTextAttribute(GetStdHandle(STD_ERROR_HANDLE), OldAttribute); + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: MoveRectangleUp +// +//---------------------------------------------------------------------------- + +VOID +MoveRectangleUp ( + USHORT Top, + USHORT Left, + USHORT Bottom, + USHORT Right, + USHORT NumRow, + BYTE *FillCell) +{ + SMALL_RECT ScrollRectangle; + COORD DestinationOrigin; + CHAR_INFO Fill; + + ScrollRectangle.Left = Left; + ScrollRectangle.Top = Top; + ScrollRectangle.Right = Right; + ScrollRectangle.Bottom = Bottom; + DestinationOrigin.X = Left; + DestinationOrigin.Y = Top - NumRow; + Fill.Char.AsciiChar = FillCell[0]; + Fill.Attributes = (WORD) FillCell[1]; + + ScrollConsoleScreenBuffer( + GetStdHandle(STD_ERROR_HANDLE), + &ScrollRectangle, + NULL, + DestinationOrigin, + &Fill); +} + + +//+--------------------------------------------------------------------------- +// +// Function: ReadConsoleCells +// +//---------------------------------------------------------------------------- + +VOID +ReadConsoleCells( + BYTE *ScreenCell, + USHORT cb, + USHORT Row, + USHORT Column) +{ + COORD BufferSize, BufferCoord; + SMALL_RECT ReadRegion; + CHAR_INFO CharInfo[1], *p; + USHORT CountCells; + + CountCells = cb >> 1; + assert(CountCells * sizeof(CHAR_INFO) <= sizeof(CharInfo)); + ReadRegion.Top = Row; + ReadRegion.Left = Column; + ReadRegion.Bottom = Row; + ReadRegion.Right = Column + CountCells - 1; + BufferSize.X = 1; + BufferSize.Y = CountCells; + BufferCoord.X = 0; + BufferCoord.Y = 0; + ReadConsoleOutput( + GetStdHandle(STD_ERROR_HANDLE), + CharInfo, + BufferSize, + BufferCoord, + &ReadRegion); + + p = CharInfo; + while (CountCells--) { + *ScreenCell++ = p->Char.AsciiChar; + *ScreenCell++ = (BYTE) p->Attributes; + p++; + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: ClearLine +// +//---------------------------------------------------------------------------- + +VOID +ClearLine(VOID) +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + COORD Coord; + DWORD NumWritten; + + if (!GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi)) { + fLineCleared = TRUE; + return; + } + + Coord.Y = csbi.dwCursorPosition.Y; + Coord.X = csbi.dwCursorPosition.X = 0; + FillConsoleOutputCharacter( + GetStdHandle(STD_ERROR_HANDLE), + ' ', + csbi.dwSize.X, + csbi.dwCursorPosition, + &NumWritten); + + SetConsoleCursorPosition(GetStdHandle(STD_ERROR_HANDLE), Coord); + fLineCleared = TRUE; +} + + +// PipeSpawn variables. We can get away with one copy per thread. + +__declspec(thread) HANDLE ProcHandle; +__declspec(thread) FILE *pstream; + +//+--------------------------------------------------------------------------- +// +// Function: PipeSpawn (similar to _popen) +// +//---------------------------------------------------------------------------- + +FILE * +PipeSpawn ( + const CHAR *cmdstring + ) +{ + int PipeHandle[2]; + HANDLE WriteHandle, ErrorHandle; + STARTUPINFO StartupInfo; + PROCESS_INFORMATION ProcessInformation; + BOOL Status; + char CmdLine[1024]; + + if (cmdstring == NULL) + return (NULL); + + // Open the pipe where we'll collect the output. + + _pipe(PipeHandle, 1024, _O_BINARY|_O_NOINHERIT); + + DuplicateHandle(GetCurrentProcess(), + (HANDLE)_get_osfhandle((LONG)PipeHandle[1]), + GetCurrentProcess(), + &WriteHandle, + 0L, + TRUE, + DUPLICATE_SAME_ACCESS); + + DuplicateHandle(GetCurrentProcess(), + (HANDLE)_get_osfhandle((LONG)PipeHandle[1]), + GetCurrentProcess(), + &ErrorHandle, + 0L, + TRUE, + DUPLICATE_SAME_ACCESS); + + _close(PipeHandle[1]); + + pstream = _fdopen(PipeHandle[0], "rb" ); + if (!pstream) { + CloseHandle(WriteHandle); + CloseHandle(ErrorHandle); + _close(PipeHandle[0]); + return(NULL); + } + + strcpy(CmdLine, cmdexe); + strcat(CmdLine, " /c "); + strcat(CmdLine, cmdstring); + + memset(&StartupInfo, 0, sizeof(STARTUPINFO)); + StartupInfo.cb = sizeof(STARTUPINFO); + + StartupInfo.hStdOutput = WriteHandle; + StartupInfo.hStdError = ErrorHandle; + StartupInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + StartupInfo.dwFlags = STARTF_USESTDHANDLES; + + memset(&ProcessInformation, 0, sizeof(PROCESS_INFORMATION)); + + // And start the process. + + Status = CreateProcess(cmdexe, CmdLine, NULL, NULL, TRUE, 0, NULL, NULL, &StartupInfo, &ProcessInformation); + + CloseHandle(WriteHandle); + CloseHandle(ErrorHandle); + CloseHandle(ProcessInformation.hThread); + + if (!Status) { + fclose(pstream); // This will close the read handle + pstream = NULL; + ProcHandle = NULL; + } else { + ProcHandle = ProcessInformation.hProcess; + } + + return(pstream); +} + + +//+--------------------------------------------------------------------------- +// +// Function: PipeSpawnClose (similar to _pclose) +// +//---------------------------------------------------------------------------- + +DWORD +PipeSpawnClose ( + FILE *pstream + ) +{ + DWORD retval = 0; /* return value (to caller) */ + + if ( pstream == NULL) { + return retval; + } + + (void)fclose(pstream); + + if ( WaitForSingleObject(ProcHandle, (DWORD) -1L) == 0) { + GetExitCodeProcess(ProcHandle, &retval); + } + CloseHandle(ProcHandle); + + return(retval); +} diff --git a/sdktools/buildglobals.c b/sdktools/buildglobals.c new file mode 100644 index 0000000..93165f6 --- /dev/null +++ b/sdktools/buildglobals.c @@ -0,0 +1,122 @@ +// Standalone definitions for globals that were historically emitted as +// tentative definitions by every translation unit through build.h. +#include "build.h" + +BOOL fDebug; + +BOOL fUsage; +BOOL fStatus; +BOOL fStatusTree; +BOOL fShowTree; +BOOL fShowTreeIncludes; +BOOL fClean; +BOOL fCleanLibs; +BOOL fCleanRestart; +BOOL fRestartClean; +BOOL fRestartCleanLibs; +BOOL fPause; +BOOL fParallel; +BOOL fPrintElapsed; +BOOL fQuery; +BOOL fStopAfterPassZero; +BOOL fQuicky; +BOOL fQuickZero; +BOOL fSemiQuicky; +BOOL fShowOutOfDateFiles; +BOOL fSyncLink; +BOOL fForce; +BOOL fEnableVersionCheck; +BOOL fSilent; +BOOL fKeep; +BOOL fCompileOnly; +BOOL fLinkOnly; +BOOL fErrorLog; +BOOL fGenerateObjectsDotMacOnly; +BOOL fShowWarningsOnScreen; +BOOL fNoisyScan; +BOOL fFullErrors; +BOOL fWhyBuild; +BOOL fChicagoProduct; +BOOL fPassZero; +BOOL fFirstScan; +BOOL fAlwaysPrintFullPath; +BOOL fTargetDirs; +BOOL fAlwaysKeepLogfile; +BOOL fShowUnusedDirs; +BOOL fCheckIncludePaths; +BOOL fNoThreadIndex; +BOOL fMTScriptSync; + +LPSTR AcceptableIncludePatternList[MAX_INCLUDE_PATTERNS + 1]; +LPSTR UnacceptableIncludePatternList[MAX_INCLUDE_PATTERNS + 1]; + +LPSTR MakeProgram; +char MakeParameters[512]; +LPSTR MakeParametersTail; +char MakeTargets[256]; +char RestartDir[256]; +char NtRoot[256]; +char DbMasterName[256]; + +char *pszPublicInternalPath; +char *pszIncPri; + +CRITICAL_SECTION TTYCriticalSection; +CHAR const *cmdexe; + +LONG TotalFilesToCompile; +LONG TotalFilesCompiled; +LONG TotalLinesToCompile; +LONG TotalLinesCompiled; +ULONG ElapsedCompileTime; +DIRREC *CurrentCompileDirDB; + +UINT CountTargetMachines; +TARGET_MACHINE_INFO *TargetMachines[MAX_TARGET_MACHINES]; +UINT TargetToPossibleTarget[MAX_TARGET_MACHINES]; + +UINT CountOptionalDirs; +LPSTR OptionalDirs[MAX_OPTIONAL_DIRECTORIES]; +BOOLEAN OptionalDirsUsed[MAX_OPTIONAL_DIRECTORIES]; +BOOL BuildAllOptionalDirs; + +UINT CountExcludeDirs; +LPSTR ExcludeDirs[MAX_EXCLUDE_DIRECTORIES]; +BOOLEAN ExcludeDirsUsed[MAX_OPTIONAL_DIRECTORIES]; + +UINT CountExcludeIncs; +LPSTR ExcludeIncs[MAX_EXCLUDE_INCS]; + +UINT CountIncludeDirs; +UINT CountSystemIncludeDirs; +DIRREC *IncludeDirs[MAX_INCLUDE_DIRECTORIES]; + +UINT CountPassZeroDirs; +DIRREC *PassZeroDirs[MAX_BUILD_DIRECTORIES]; +UINT CountCompileDirs; +DIRREC *CompileDirs[MAX_BUILD_DIRECTORIES]; +UINT CountLinkDirs; +DIRREC *LinkDirs[MAX_BUILD_DIRECTORIES]; +UINT CountShowDirs; +DIRREC *ShowDirs[MAX_BUILD_DIRECTORIES]; + +DIRREC *AllDirs; +CHAR CurrentDirectory[DB_MAX_PATH_LENGTH]; +BOOL AllDirsInitialized; +BOOL AllDirsModified; + +LPSTR BuildDefault; +LPSTR BuildParameters; +LPSTR SystemIncludeEnv; +LPSTR LocalIncludeEnv; +LPSTR BigBuf; +UINT BigBufSize; +UINT RecurseLevel; + +FILE *LogFile; +FILE *WrnFile; +FILE *ErrFile; +FILE *IPGScriptFile; +FILE *IncFile; + +ULONG BuildStartTime; diff --git a/sdktools/buildinc.c b/sdktools/buildinc.c new file mode 100644 index 0000000..754794f --- /dev/null +++ b/sdktools/buildinc.c @@ -0,0 +1,540 @@ +//+--------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1989 - 1994. +// +// File: buildinc.c +// +// Contents: This is the checking include module for the NT Build Tool (BUILD.EXE) +// +// Used for detecting the includes that do not satisfy the acceptable +// patterns. +// +// History: see SLM +//---------------------------------------------------------------------------- + +#include "build.h" + +//+--------------------------------------------------------------------------- +// +// Function: FoundCountedSequenceInString +// +// Synopsis: Roughly equivalent to "strstr" except that the substring doesn't +// have to be NULL-terminated. +// +// Arguments: [String] -- null-terminated string to search +// [Sequence] -- string to search for +// [Length] -- the length of the sequence +//---------------------------------------------------------------------------- + +LPCTSTR +FindCountedSequenceInString( + IN LPCTSTR String, + IN LPCTSTR Sequence, + IN DWORD Length + ) + { + + assert( Sequence ); + assert( String ); + + if ( Length > 0 ) { + + while ( *String ) { + + while (( *String ) && ( *String != *Sequence )) { + String++; + } + + if ( *String ) { + + LPCTSTR SubString = String + 1; + LPCTSTR SubSequence = Sequence + 1; + DWORD Remaining = Length - 1; + + while (( Remaining ) && ( *SubString++ == *SubSequence++ )) { + Remaining--; + } + + if ( Remaining == 0 ) { + return String; + } + + String++; + } + } + + return NULL; + } + + return String; + } + + +//+--------------------------------------------------------------------------- +// +// Function: DoesInstanceMatchPattern +// +// Synopsis: Returns TRUE if pattern matches instance. +// Wildcards: +// * matches any text +// ? matches any and exactly one character +// # matches any text up to backslash character or end of string +// +// Arguments: [Instance] -- the string to be matched +// [Pattern] -- the pattern +//---------------------------------------------------------------------------- + +BOOL +DoesInstanceMatchPattern( + IN LPCTSTR Instance, + IN LPCTSTR Pattern + ) + { + + assert( Instance ); + assert( Pattern ); + + while ( *Pattern ) { + + if ( *Pattern == TEXT('*')) { + + Pattern++; + + while ( *Pattern == TEXT('*')) { // skip multiple '*' characters + Pattern++; + } + + if ( *Pattern == 0 ) { // '*' at end of pattern matches rest + return TRUE; + } + + if ( *Pattern == '?' ) { // '?' following '*' + + // + // Expensive because we have to restart match for every + // character position remaining since '?' can match anything. + // + + while ( *Instance ) { + + if ( DoesInstanceMatchPattern( Instance, Pattern )) { + return TRUE; + } + + Instance++; + } + + return FALSE; + } + + else { + + // + // Now we know that next character in pattern is a regular + // character to be matched. Find out the length of that + // string to the next wildcard or end of string. + // + + LPCTSTR NextWildCard = Pattern + 1; + DWORD MatchLength; + + while (( *NextWildCard ) && ( *NextWildCard != TEXT('*')) && ( *NextWildCard != TEXT('?')) && ( *NextWildCard != TEXT('#'))) { + NextWildCard++; + } + + MatchLength = (DWORD)(NextWildCard - Pattern); // always non-zero + + // + // Now try to match with any instance of substring in pattern + // found in the instance. + // + + Instance = FindCountedSequenceInString( Instance, Pattern, MatchLength ); + + while ( Instance ) { + + if ( DoesInstanceMatchPattern( Instance + MatchLength, NextWildCard )) { + return TRUE; + } + + Instance = FindCountedSequenceInString( Instance + 1, Pattern, MatchLength ); + } + + return FALSE; + } + } + + else if ( *Pattern == TEXT('#')) { + + // + // Match text up to backslash character or end of string + // + + Pattern++; + + while (( *Instance != 0 ) && ( *Instance != '\\' )) { + Instance++; + } + + continue; + } + + else if ( *Pattern == TEXT('?')) { + + if ( *Instance == 0 ) { + return FALSE; + } + } + + else if ( *Pattern != *Instance ) { + + return FALSE; + } + + Pattern++; + Instance++; + } + + return ( *Instance == 0 ); + } + + +//+--------------------------------------------------------------------------- +// +// Function: CombinePaths +// +// Synopsis: Combine two strings to get a full path. +// +// Arguments: [ParentPath] -- head path +// [ChildPath] -- path to be added +// [TargetPath] -- full path +//---------------------------------------------------------------------------- + +LPSTR +CombinePaths( + IN LPCSTR ParentPath, + IN LPCSTR ChildPath, + OUT LPSTR TargetPath // can be same as ParentPath if want to append + ) + { + + ULONG ParentLength = strlen( ParentPath ); + LPSTR p; + + assert( ParentPath ); + assert( ChildPath ); + + if ( ParentPath != TargetPath ) { + memcpy( TargetPath, ParentPath, ParentLength ); + } + + p = TargetPath + ParentLength; + + if (( ParentLength > 0 ) && + ( *( p - 1 ) != '\\' ) && + ( *( p - 1 ) != '/' )) { + *p++ = '\\'; + } + + strcpy( p, ChildPath ); + + return TargetPath; + } + + +//+--------------------------------------------------------------------------- +// +// Function: CreateRelativePath +// +// Synopsis: Determine the "canonical" path of one file relative to +// another file +// +// Arguments: [SourceAbsName] -- absolute path of the source file +// [TargetAbsName] -- absolute path of the target file +// [RelativePath] -- resulted relative path +//---------------------------------------------------------------------------- + +VOID +CreateRelativePath( + IN LPCSTR SourceAbsName, // must be lowercase + IN LPCSTR TargetAbsName, // must be lowercase + OUT LPSTR RelativePath // must be large enough + ) + { + + // + // First, walk through path components that match in Source and Target. + // For example: + // + // d:\nt\private\ntos\dd\efs.h + // d:\nt\private\windows\base\ntcrypto\des.h + // ^ + // This is where the relative path stops going up (..) + // and starts going back down. + // + // So, the "cannonical" relative path generated should look like: + // + // ..\..\..\windows\base\ntcrypto\des.h + // + // For relative includes that are "below" the includer in the path should + // look like this: + // + // .\foo\bar\foobar.h + // + + LPCSTR Source = SourceAbsName; + LPCSTR Target = TargetAbsName; + LPSTR Output = RelativePath; + ULONG PathSeparatorIndex; + BOOL AnyParent; + ULONG i; + + assert( SourceAbsName ); + assert( TargetAbsName ); + + PathSeparatorIndex = 0; + + i = 0; + + // + // Scan forward to first non-matching character, and keep track of + // most recent path separator character. + // + + while (( Source[ i ] == Target[ i ] ) && ( Source[ i ] != 0 )) { + + if ( Source[ i ] == '\\' ) { + PathSeparatorIndex = i; + } + + ++i; + } + + // + // Coming out of this loop, there are 2 possibilities: + // + // 1) Found common ancestor path ( *PathSeparatorIndex == '\\' ) + // 2) Don't have common ancestor ( *PathSeparatorIndex != '\\' ) + // + + if ( Source[ PathSeparatorIndex ] != '\\' ) { + strcpy( RelativePath, TargetAbsName ); + return; + } + + i = PathSeparatorIndex + 1; + + // + // Now continue to walk down source path and insert a "..\" in the result + // for each path separator encountered. + // + + AnyParent = FALSE; + + while ( Source[ i ] != 0 ) { + + if ( Source[ i ] == '\\' ) { + + AnyParent = TRUE; + *Output++ = '.'; + *Output++ = '.'; + *Output++ = '\\'; + } + + ++i; + } + + if ( ! AnyParent ) { + + // + // Relative path is below current directory. + // + + *Output++ = '.'; + *Output++ = '\\'; + } + + + // + // Now we simply append what's remaining of the Target path from the + // ancestor match point. + // + + strcpy( Output, Target + PathSeparatorIndex + 1 ); + } + + +//+--------------------------------------------------------------------------- +// +// Function: ShouldWarnInclude +// +// Synopsis: Returns true if the name of the included file matches a +// BUILD_UNACCEPTABLE_INCLUDES pattern or it does not match +// any of the patterns specified in BUILD_ACCEPTABLE_INCLUDES. +// +// Arguments: [CompilandFullName] -- name of the including file +// [IncludeeFullName] -- name of the included file +//---------------------------------------------------------------------------- + +BOOL +ShouldWarnInclude( + IN LPCSTR CompilandFullName, + IN LPCSTR IncludeeFullName + ) + { + UINT i; + CHAR IncludeeRelativeName[ MAX_PATH ]; + + + assert( CompilandFullName ); + assert( IncludeeFullName ); + + CreateRelativePath( CompilandFullName, IncludeeFullName, IncludeeRelativeName ); + + // + // First we check for a match against any unacceptable include path + // because we always want to warn about these. + // + + for ( i = 0; UnacceptableIncludePatternList[ i ] != NULL; i++ ) { + + if ( DoesInstanceMatchPattern( IncludeeFullName, UnacceptableIncludePatternList[ i ] )) { + return TRUE; + } + + if ( DoesInstanceMatchPattern( IncludeeRelativeName, UnacceptableIncludePatternList[ i ] )) { + return TRUE; + } + } + + // + // If we get to here, the include path was not explicitly unacceptable, so + // we now want to see if it matches any acceptable paths. But, if no + // acceptable paths are specified, we don't want to warn. + // + + if ( AcceptableIncludePatternList[ 0 ] == NULL ) { + return FALSE; + } + + for ( i = 0; AcceptableIncludePatternList[ i ] != NULL; i++ ) { + + if ( DoesInstanceMatchPattern( IncludeeFullName, AcceptableIncludePatternList[ i ] )) { + return FALSE; + } + + if ( DoesInstanceMatchPattern( IncludeeRelativeName, AcceptableIncludePatternList[ i ] )) { + return FALSE; + } + } + + return TRUE; + } + + +//+--------------------------------------------------------------------------- +// +// Function: CheckIncludeForWarning +// +// Synopsis: Warnings if the dependency does not respect the +// BUILD_UNACCEPTABLE_INCLUDES or BUILD_ACCEPTABLE_INCLUDES +// restristions. Works with build -#. +// +// Arguments: [CompilandDir] +// [CompilandName] +// [IncluderDir] +// [IncluderName] +// [IncludeeDir] +// [IncludeeName] +//---------------------------------------------------------------------------- + +VOID +CheckIncludeForWarning( + IN LPCSTR CompilandDir, + IN LPCSTR CompilandName, + IN LPCSTR IncluderDir, + IN LPCSTR IncluderName, + IN LPCSTR IncludeeDir, + IN LPCSTR IncludeeName + ) + { + + CHAR CompilandFullName[ MAX_PATH ]; + CHAR IncluderFullName[ MAX_PATH ]; + CHAR IncludeeFullName[ MAX_PATH ]; + + assert( CompilandDir ); + assert( CompilandName ); + assert( IncluderDir ); + assert( IncluderName ); + assert( IncludeeDir ); + assert( IncludeeName ); + + CombinePaths( CompilandDir, CompilandName, CompilandFullName ); + CombinePaths( IncluderDir, IncluderName, IncluderFullName ); + CombinePaths( IncludeeDir, IncludeeName, IncludeeFullName ); + + _strlwr( CompilandFullName ); + _strlwr( IncluderFullName ); + _strlwr( IncludeeFullName ); + + if ( IncFile ) { + fprintf( + IncFile, + "%s includes %s\r\n", + IncluderFullName, + IncludeeFullName + ); + } + + if ( ShouldWarnInclude( CompilandFullName, IncludeeFullName )) { + + if ( strcmp( IncluderFullName, CompilandFullName ) == 0 ) { + + if ( WrnFile ) { + + fprintf( + WrnFile, + "WARNING: %s includes %s\n", + CompilandFullName, + IncludeeFullName + ); + } + + if ( fShowWarningsOnScreen ) { + + BuildMsgRaw( + "WARNING: %s includes %s\n", + CompilandFullName, + IncludeeFullName + ); + } + } + + else { + + if ( WrnFile ) { + + fprintf( + WrnFile, + "WARNING: %s includes %s through %s\n", + CompilandFullName, + IncludeeFullName, + IncluderFullName + ); + } + + if ( fShowWarningsOnScreen ) { + + BuildMsgRaw( + "WARNING: %s includes %s through %s\n", + CompilandFullName, + IncludeeFullName, + IncluderFullName + ); + } + } + } + } + diff --git a/sdktools/buildmak.c b/sdktools/buildmak.c new file mode 100644 index 0000000..f004a35 --- /dev/null +++ b/sdktools/buildmak.c @@ -0,0 +1,3485 @@ +//+--------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1989 - 1994. +// +// File: buildmak.c +// +// Contents: This is the Make module for the NT Build Tool (BUILD.EXE) +// +// The Make module scans directories for file names and edits the +// data base appropriately. +// +// Functions: +// +// History: 16-May-89 SteveWo Created +// ... See SLM log +// 26-Jul-94 LyleC Cleanup/Add Pass0 support +// +//---------------------------------------------------------------------------- + +#include "build.h" + + +#define SCANFLAGS_CHICAGO 0x00000002 +#define SCANFLAGS_OS2 0x00000004 +#define SCANFLAGS_POSIX 0x00000008 +#define SCANFLAGS_CRT 0x00000010 + +ULONG ScanFlagsLast; +ULONG ScanFlagsCurrent; + +USHORT GlobalSequence; +USHORT LocalSequence; +ULONG idFileToCompile = 1; +BOOL fLineCleared = TRUE; + +char szRecurse[] = " . . . . . . . . ."; +char szAsterisks[] = " ********************"; + +char *pszSdkLibDest; +char *pszDdkLibDest; +char *pszIncOak; +char *pszIncDdk; +char *pszIncWdm; +char *pszIncSdk; +char *pszIncCrt; +char *pszIncMfc; +char *pszIncOs2; +char *pszIncPosix; +char *pszIncChicago; + +char szCheckedAltDir[] = " CHECKED_ALT_DIR=1"; + + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(array, type) (sizeof(array)/sizeof(type)) +#endif + +// +// The following definitions are for the ObjectDirFlag entry in the TARGETDATA +// struct. +// + +// +// TD_OBJECTDIR maps to ObjectDirectory[iObjectDir]\foobar.tar +// TD_PASS0HDRDIR maps to $(PASS0_HEADERDIR)\foobar.tar +// TD_PASS0DIR1 maps to $(PASS0_SOURCEDIR)\foobar.tar or $(PASS0_CLIENTDIR)\foobar.tar +// TD_PASS0DIR2 maps to $(MIDL_UUIDDIR)\foobar.tar or $(PASS0_SERVERDIR)\foobar.tar +// +// where .tar is the given target extension, ObjectDirectory[iObjectDir] is the +// appropriate object directory for that platform, and the macros are expanded +// to the values given in the sources file. +// +#define TD_OBJECTDIR 1 +#define TD_PASS0HDRDIR 2 +#define TD_PASS0DIR1 3 +#define TD_PASS0DIR2 4 +#define TD_MCSOURCEDIR 5 + +typedef struct _tagTARGETDATA +{ + UCHAR ObjectDirFlag; // Indicates what object dir should be used. + LPSTR pszTargetExt; // Extension of target. (Including '.') +} TARGETDATA, *LPTARGETDATA; + +typedef struct _tagOBJECTTARGETINFO +{ + LPSTR pszSourceExt; // Extension of source file (including '.'). + UCHAR NumData; // Number of entries in [Data]. + LPTARGETDATA Data; // Pointer to array of TARGETDATAs. +} OBJECTTARGETINFO, *LPOBJECTTARGETINFO; + +typedef struct _tagOBJECTTARGETARRAY +{ + int cTargetInfo; + OBJECTTARGETINFO **aTargetInfo; +} OBJECTTARGETARRAY; + + +// +// TARGETDATA information is used by both BuildCompileTarget() and +// WriteObjectsDefinition() via the GetTargetData() function. Do not put +// extensions in this table whose TARGETDATA consists entirely of +// { TD_OBJECTDIR, ".obj" } because that is the default. Instead you must +// modify the switch statement in WriteObjectsDefinition. +// +// The first target in each TARGETDATA array is considered the 'rule target' +// because that is the target for which the inference rule in makefile.def is +// written. The 'rule target' will always be deleted in addition to the +// out-of-date target if *any* of the targets are out of date. +// + + +// +// The following data defines the *PASS0* mappings of source extensions +// to target files: +// +// .idl -> $(PASS0_HEADERDIR)\.h, +// $(PASS0_SOURCEDIR)\_p.c, +// $(MIDL_UUIDDIR)\_i.c +// .asn -> $(PASS0_HEADERDIR)\.h, +// $(PASS0_HEADERDIR)\.c +// .mc -> $(PASS0_HEADERDIR)\.h, $(PASS0_SOURCEDIR)\.rc +// .odl -> obj\*\.tlb +// .tdl -> obj\*\.tlb +// + +// .mc -> $(PASS0_HEADERDIR)\.h, $(PASS0_HEADERDIR)\.rc +TARGETDATA MCData0[] = { + { TD_PASS0HDRDIR, ".h" }, + { TD_MCSOURCEDIR, ".rc" } + }; +OBJECTTARGETINFO MCInfo0 = { ".mc", ARRAY_SIZE(MCData0, TARGETDATA), MCData0 }; + +// .asn -> $(PASS0_HEADERDIR)\.h, $(PASS0_SOURCEDIR)\.c +TARGETDATA AsnData0[] = { + { TD_PASS0HDRDIR, ".h" }, + { TD_PASS0DIR1, ".c" }, + }; +OBJECTTARGETINFO AsnInfo0 = + { ".asn", ARRAY_SIZE(AsnData0, TARGETDATA), AsnData0 }; + + +// .odl/.tdl -> obj\*\.tlb +TARGETDATA TLBData0 = { TD_OBJECTDIR, ".tlb" }; + +OBJECTTARGETINFO TLBInfo0 = + { ".tdl", ARRAY_SIZE(TLBData0, TARGETDATA), &TLBData0 }; + +OBJECTTARGETINFO TLB2Info0 = + { ".odl", ARRAY_SIZE(TLBData0, TARGETDATA), &TLBData0 }; + +// .thk -> obj\*\.asm +TARGETDATA THKData0 = { TD_OBJECTDIR, ".asm" }; + +OBJECTTARGETINFO THKInfo0 = + { ".thk", ARRAY_SIZE(THKData0, TARGETDATA), &THKData0 }; + + +// .mof -> obj\*\.mof, obj\*\.bmf +TARGETDATA MOFData0[] = { + {TD_OBJECTDIR, ".mof" }, + {TD_OBJECTDIR, ".bmf" } + }; +OBJECTTARGETINFO MOFInfo0 = { ".mof", ARRAY_SIZE(MOFData0, TARGETDATA), + MOFData0 }; + +// ------ +LPOBJECTTARGETINFO aTargetInfo0[] = { + &MCInfo0, + &AsnInfo0, + &TLBInfo0, + &TLB2Info0, + &THKInfo0, + &MOFInfo0, + }; +#define CTARGETINFO0 ARRAY_SIZE(aTargetInfo0, LPOBJECTTARGETINFO) + + +// +// The following data defines the *PASS1* mappings of source extensions +// to target files: +// +// .rc -> obj\*\.res +// .asn -> obj\*\.obj +// .thk -> obj\*\.asm, +// .java -> obj\*\.class, +// obj\*\.obj, +// + +// .rc -> obj\*\.res +TARGETDATA RCData1 = { TD_OBJECTDIR, ".res" }; +OBJECTTARGETINFO RCInfo1 = { ".rc", ARRAY_SIZE(RCData1, TARGETDATA), &RCData1 }; + +// .thk -> .asm -> .obj +TARGETDATA THKData1[] = { + {TD_OBJECTDIR, ".obj" } + }; +OBJECTTARGETINFO THKInfo1 = + { ".thk", ARRAY_SIZE(THKData1, TARGETDATA), THKData1 }; + +// .java -> .class +TARGETDATA JAVAData1[] = { + {TD_OBJECTDIR, ".class" } + }; +OBJECTTARGETINFO JAVAInfo1 = + { ".java", ARRAY_SIZE(JAVAData1, TARGETDATA), JAVAData1 }; + + + + +// ------ +LPOBJECTTARGETINFO aTargetInfo1[] = { + &RCInfo1, + &THKInfo1, + &JAVAInfo1, + }; +#define CTARGETINFO1 ARRAY_SIZE(aTargetInfo1, LPOBJECTTARGETINFO) + + +OBJECTTARGETARRAY aTargetArray[] = { + { CTARGETINFO0, aTargetInfo0 }, + { CTARGETINFO1, aTargetInfo1 }, +}; + + +// ------ +// MIDL stuff -- IDL files have two potential sets of targets, depending +// on if the IDL_TYPE flag was set to 'ole' in the sources file or not. +// +// IDL_TYPE = ole +// .idl -> $(PASS0_HEADERDIR)\.h, +// $(PASS0_SOURCEDIR)\_p.c, +// $(MIDL_UUIDDIR)\_i.c +TARGETDATA IDLDataOle0[] = { + { TD_PASS0HDRDIR, ".h" }, // Header File +// { TD_PASS0DIR1, "_p.c" }, // Proxy Stub File +// { TD_PASS0DIR2, "_i.c" }, // UUID file + }; +OBJECTTARGETINFO IDLInfoOle0 = + { ".idl", ARRAY_SIZE(IDLDataOle0, TARGETDATA), IDLDataOle0 }; + +// IDL_TYPE = rpc +// .idl -> $(PASS0_HEADERDIR)\.h, +// $(PASS0_CLIENTDIR)\_c.c, +// $(PASS0_SERVERDIR)\_s.c, +TARGETDATA IDLDataRpc0[] = { + { TD_PASS0HDRDIR, ".h" }, // Header File +// { TD_PASS0DIR1, "_c.c" }, // Client Stub File +// { TD_PASS0DIR2, "_s.c" }, // Server Stub File + }; +OBJECTTARGETINFO IDLInfoRpc0 = + { ".idl", ARRAY_SIZE(IDLDataRpc0, TARGETDATA), IDLDataRpc0 }; + +// ------ +LPOBJECTTARGETINFO aMidlTargetInfo0[] = { + &IDLInfoOle0, + &IDLInfoRpc0, + }; +UCHAR cMidlTargetInfo0 = ARRAY_SIZE(aMidlTargetInfo0, LPOBJECTTARGETINFO); + +// ------ +// +// Any extension not given in the above table is assumed to have a target in +// the ObjectDirectory[iObjectDir] (obj\*) & have a target extension of .obj. +// + +TARGETDATA DefaultData = { TD_OBJECTDIR, ".obj" }; + + +//******* + +TARGET * +BuildCompileTarget( + FILEREC *pfr, + LPSTR pszfile, + USHORT TargetIndex, + LPSTR pszConditionalIncludes, + DIRREC *pdrBuild, + DIRSUP *pdsBuild, + LONG iPass, + LPSTR *ppszObjectDir, + LPSTR pszSourceDir); + + +//+--------------------------------------------------------------------------- +// +// Function: ExpandObjAsterisk +// +// Synopsis: Expand an asterisk in a filename to a platform name +// +// Arguments: [pbuf] -- Output buffer for new filename +// [pszpath] -- Input filename w/ asterisk +// [ppszObjectDirectory] -- String[2] to replace asterisk with +// +//---------------------------------------------------------------------------- + +VOID +ExpandObjAsterisk( + LPSTR pbuf, + LPSTR pszpath, + LPSTR *ppszObjectDirectory) +{ + SplitToken(pbuf, '*', &pszpath); + if (*pszpath == '*') { + assert(strncmp( + pszObjDirSlash, + ppszObjectDirectory[iObjectDir], + strlen(pszObjDirSlash)) == 0); + strcat(pbuf, ppszObjectDirectory[iObjectDir] + strlen(pszObjDirSlash)); + strcat(pbuf, pszpath + 1); + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: CountSourceLines +// +// Synopsis: Counts the source lines in a given file, including headers if +// the '-S' option was given. +// +// Arguments: [idScan] -- Used to catch multiple inclusions +// [pfr] -- File to scan +// +// Returns: Number of lines +// +//---------------------------------------------------------------------------- + +LONG +CountSourceLines(USHORT idScan, FILEREC *pfr) +{ + INCLUDEREC *pir; + + AssertFile(pfr); + + // if we have already seen this file before, then assume + // that #if guards prevent it's inclusion + + if (pfr->idScan == idScan) { + return(0L); + } + + pfr->idScan = idScan; + + // Start off with the file itself + pfr->TotalSourceLines = pfr->SourceLines; + + if (fStatusTree) { + + // + // If the user asked for include file line counts, then walk include + // tree, accruing nested include file line counts . + // + + for (pir = pfr->IncludeFilesTree; pir != NULL; pir = pir->NextTree) { + AssertInclude(pir); + if (pir->pfrInclude != NULL) { + AssertFile(pir->pfrInclude); + pfr->TotalSourceLines += + CountSourceLines(idScan, pir->pfrInclude); + } + } + } + return(pfr->TotalSourceLines); +} + +//+--------------------------------------------------------------------------- +// +// Function: CleanNTTargetFile0 +// +// Synopsis: Parses pzFiles and deletes all files listed. +// pzFile must have been allocated by MakeMacroString. +// No asterisk expansion performed. +// +// This is used when fClean is TRUE and SOURCES_OPTIONS +// includes -c0. See ReadSourcesFile. Note that +// SOURCES_OPTIONS must be defined before NTTARGETFILE0. +// This is a mechanism to delete target files not +// included in _objects.mac. +// +// Arguments: [pzFiles] -- List of files +// +//---------------------------------------------------------------------------- +VOID +CleanNTTargetFile0 (char * pzFiles) +{ + BOOL fRestoreSep; + char * pzDelete; + + while (*pzFiles != '\0') { + pzDelete = pzFiles; + + // Find end of the next file name and NULL terminate it (if needed) + fRestoreSep = FALSE; + while (*pzFiles != '\0') { + if (*pzFiles == ' ') { + fRestoreSep = TRUE; + *pzFiles = '\0'; + break; + } else { + pzFiles++; + } + } + + DeleteSingleFile (NULL, pzDelete, FALSE); + + if (fRestoreSep) { + *pzFiles++ = ' '; + } + } +} + +//+--------------------------------------------------------------------------- +// +// Function: ProcessSourceDependencies +// +// Synopsis: Scan all source files in a given directory tree to determine +// which files are out of date and need to be compiled and/or +// linked. +// +// Arguments: [DirDB] -- Directory to process +// [pds] -- Supplementary directory information +// [DateTimeSources] -- Timestamp of 'sources' file +// +//---------------------------------------------------------------------------- + +VOID +ProcessSourceDependencies(DIRREC *DirDB, DIRSUP *pds, ULONG DateTimeSources) +{ + TARGET *Target; + ULONG DateTimePch = 0; // Actual timestamp of pch preserved here. + UINT i; + SOURCEREC *apsr[3]; + SOURCEREC **ppsr; + char path[DB_MAX_PATH_LENGTH]; + static USHORT idScan = 0; + + AssertDir(DirDB); + + apsr[0] = pds->psrSourcesList[0]; + apsr[2] = NULL; + + // + // For a clean build, just delete all targets + // + if (fFirstScan && fClean && !fKeep) { + DeleteMultipleFiles("obj", "*.*"); // _objects.mac + for (i = 0; i < CountTargetMachines; i++) { + assert(strncmp( + pszObjDirSlash, + TargetMachines[i]->ObjectDirectory[iObjectDir], + strlen(pszObjDirSlash)) == 0); + DeleteMultipleFiles(TargetMachines[i]->ObjectDirectory[iObjectDir], "*.*"); + + apsr[1] = pds->psrSourcesList[TargetToPossibleTarget[i] + 1]; + + // + // Delete the pch file if we have one. + // + if (pds->PchTarget != NULL) + { + char TargetDir[DB_MAX_PATH_LENGTH]; + ExpandObjAsterisk(TargetDir, + pds->PchTargetDir, + TargetMachines[i]->ObjectDirectory); + + // + // Kind of a cludgy way to do this, but we must ensure that + // we don't delete a pch file that was built earlier on during + // this same build. We do this by comparing the timestamp of + // the pch file against the time we started the build. + // + if ((*pDateTimeFile)(TargetDir, pds->PchTarget) <= BuildStartTime) + { + DeleteSingleFile(TargetDir, pds->PchTarget, FALSE); + if (DirDB->PchObj != NULL) { + ExpandObjAsterisk(path, + DirDB->PchObj, + TargetMachines[i]->ObjectDirectory); + DeleteSingleFile(NULL, path, FALSE); + } else { + char *p; + strcpy(path, pds->PchTarget); + p = strrchr(path, '.'); + if (p != NULL && strcmp(p, ".pch") == 0) { + strcpy(p, ".obj"); + DeleteSingleFile(TargetDir, path, FALSE); + } + } + } + } + + if (DirDB->DirFlags & DIRDB_PASS0) { + for (ppsr = apsr; *ppsr != NULL; ppsr++) { + SOURCEREC *psr; + + for (psr = *ppsr; psr != NULL; psr = psr->psrNext) { + FILEREC *pfr; + + AssertSource(psr); + + pfr = psr->pfrSource; + + // + // Pass Zero files have different target directories. + // + if (pfr->FileFlags & FILEDB_PASS0) + { + USHORT j; + // + // If the file has multiple targets, (e.g. .mc, + // .idl or .asn), then loop through all targets. + // + j = 0; + while (Target = BuildCompileTarget( + pfr, + psr->ObjectSourceName ? psr->ObjectSourceName : pfr->Name, + j, + pds->ConditionalIncludes, + DirDB, + pds, + 0, // pass 0 + TargetMachines[i]->ObjectDirectory, + TargetMachines[i]->SourceDirectory)) { + + DeleteSingleFile(NULL, Target->Name, FALSE); + + FreeMem(&Target, MT_TARGET); + + j++; + } + } + } + } + } + + if ((DirDB->DirFlags & DIRDB_TARGETFILE0) && (DirDB->NTTargetFile0 != NULL)) { + CleanNTTargetFile0 (DirDB->NTTargetFile0); + } + } + } + + if (fFirstScan && (DirDB->DirFlags & DIRDB_TARGETFILE0)) { + DirDB->DirFlags |= DIRDB_PASS0NEEDED; + } + + if (!fQuickZero || !fFirstScan || !RecurseLevel) + { + GenerateObjectsDotMac(DirDB, pds, DateTimeSources); + } + else if (fFirstScan) + { + SOURCEREC *psr; + USHORT i; + USHORT j; + BOOL fNeedCompile = FALSE; + + if ( !(DirDB->DirFlags & DIRDB_PASS0NEEDED)) { + + for (i = 0; i < CountTargetMachines; i++) { + + for (psr = pds->psrSourcesList[0]; psr != NULL; psr = psr->psrNext) { + FILEREC *pfr; + + AssertSource(psr); + + pfr = psr->pfrSource; + + AssertFile(pfr); + + if (pfr->FileFlags & FILEDB_PASS0) + { + + for (j = 0; + Target = BuildCompileTarget( + pfr, + psr->ObjectSourceName ? psr->ObjectSourceName : pfr->Name, + j, + pds->ConditionalIncludes, + DirDB, + pds, + 0, + TargetMachines[i]->ObjectDirectory, + TargetMachines[i]->SourceDirectory); + j++) { + + if ((psr->SrcFlags & SOURCEDB_FILE_MISSING) || + (Target->DateTime == 0) || + ((pfr->FileFlags & FILEDB_C) && Target->DateTime < DateTimePch)) + { + fNeedCompile = TRUE; + } + + FreeMem(&Target, MT_TARGET); + } + + if (fNeedCompile) + { + DirDB->DirFlags |= DIRDB_PASS0NEEDED; + } + } + } + } + } + + if (DirDB->DirFlags & DIRDB_PASS0NEEDED) + { + GenerateObjectsDotMac(DirDB, pds, DateTimeSources); + } + } + + if ((DirDB->TargetExt != NULL) && + (DirDB->TargetName != NULL) && + (DirDB->TargetPath != NULL) && + (fClean && !fKeep)) + { + // If we haven't already deleted the final target, do so now. + if (_memicmp(DirDB->TargetPath, pszObjDirSlash, strlen(pszObjDirSlash) -1)) { + for (i = 0; i < CountTargetMachines; i++) { + FormatLinkTarget( + path, + TargetMachines[i]->ObjectDirectory, + DirDB->TargetPath, + DirDB->TargetName, + DirDB->TargetExt); + DeleteSingleFile(NULL, path, FALSE); + FormatLinkTarget( + path, + TargetMachines[i]->ObjectDirectory, + DirDB->TargetPath, + DirDB->TargetName, + ".pdb"); + DeleteSingleFile(NULL, path, FALSE); + } + } + } + + if (pds->fNoTarget) { + if (apsr[0] || !(DirDB->DirFlags & DIRDB_PASS0NEEDED) || fSemiQuicky) { + // If there's sources to compile, mark as such then get out. + DirDB->DirFlags |= DIRDB_COMPILENEEDED; + } + return; + } + + if (fQuicky) { + if (fSemiQuicky) + DirDB->DirFlags |= DIRDB_COMPILENEEDED; + else + DirDB->DirFlags |= DIRDB_PASS0NEEDED; + return; + } + + // + // For a DLL or LIB target, ensure that it will be rebuilt + // + if (DirDB->TargetPath != NULL && + DirDB->TargetName != NULL && + ((DirDB->DirFlags & DIRDB_DLLTARGET) || + (DirDB->TargetExt != NULL && strcmp(DirDB->TargetExt, ".lib") == 0))) { + + for (i = 0; i < CountTargetMachines; i++) { + FormatLinkTarget( + path, + TargetMachines[i]->ObjectDirectory, + DirDB->TargetPath, + DirDB->TargetName, + ".lib"); + + if (ProbeFile(NULL, path) == -1) { + DirDB->DirFlags |= DIRDB_COMPILENEEDED; + } + else + if (fFirstScan && (fCleanLibs || (fClean && !fKeep))) { + DeleteSingleFile(NULL, path, FALSE); + DirDB->DirFlags |= DIRDB_COMPILENEEDED; + } + } + } + + // + // If the scan flags have changed (or haven't been set), then indicate + // that we should look for the actual location of global included files + // instead of assuming it's in the same location as we last knew. This is + // because different directories my include the same file from different + // places. + // + if (GlobalSequence == 0 || + ScanFlagsLast == 0 || + ScanFlagsLast != ScanFlagsCurrent) { + + GlobalSequence++; // don't reuse snapped global includes + if (GlobalSequence == 0) { + GlobalSequence++; + } + ScanFlagsLast = ScanFlagsCurrent; + } + + // + // Do the same as above for locally included files. + // + LocalSequence++; // don't reuse snapped local includes + if (LocalSequence == 0) { + LocalSequence++; + } + + for (i = 0; i < CountTargetMachines; i++) { + + // + // Ensure that precompiled headers are rebuilt as necessary. + // + + if (!fPassZero && (pds->PchInclude != NULL || pds->PchTarget != NULL)) { + LPSTR p; + + ExpandObjAsterisk( + path, + pds->PchTargetDir != NULL? + pds->PchTargetDir : pszObjDirSlashStar, + TargetMachines[i]->ObjectDirectory); + + if (!CanonicalizePathName(path, CANONICALIZE_DIR, path)) { + DateTimePch = ULONG_MAX; // always out of date + goto ProcessSourceList; + } + strcat(path, "\\"); + + // + // If they gave a target directory for the pch file, then use it, + // otherwise assume it's in the same directory as the .h file. + // + if (pds->PchTarget != NULL) { + strcat(path, pds->PchTarget); + } + else { + assert(pds->PchInclude != NULL); + p = path + strlen(path); + if ( DirDB->Pch ) { + strcpy(p, DirDB->Pch); + } else { + strcpy(p, pds->PchInclude); + if ((p = strrchr(p, '.')) != NULL) { + *p = '\0'; + } + strcat(path, ".pch"); + } + } + + // + // 'path' now contains the (possibly relative) path name of + // the PCH target: "..\path\foobar.pch" + // + Target = BuildCompileTarget( + NULL, + path, + 0, + pds->ConditionalIncludes, + DirDB, + NULL, + 1, // pass 1 + TargetMachines[i]->ObjectDirectory, + TargetMachines[i]->SourceDirectory); + + DateTimePch = Target->DateTime; + + if (DateTimePch == 0) { // Target doesn't exist + DateTimePch = ULONG_MAX; // Always out of date + } + + if (fClean && !fKeep && fFirstScan) { + // Target will be deleted later if it exists. + } + else if (pds->PchInclude == NULL) { + + // + // The SOURCES file didn't indicate where the source file + // for the .pch is, so assume the .pch binary is up to date + // with respect to the source includes and with respect to + // the pch source file itself. + // + // char szFullPath[DB_MAX_PATH_LENGTH]; + + // CanonicalizePathName(DirDB->Name, CANONICALIZE_DIR, szFullPath); + + //BuildMsg("SOURCES file in %s gives PRECOMPILED_TARGET but not " + // "PRECOMPILED_INCLUDE.\n", szFullPath); + Target->DateTime = 0; // Don't delete pch target + } + else { + FILEREC *pfrPch = NULL; + + path[0] = '\0'; + + if (pds->PchIncludeDir != NULL) { + strcpy(path, pds->PchIncludeDir); + strcat(path, "\\"); + } + strcat(path, pds->PchInclude); + + if ((pds->PchIncludeDir != NULL) && + (IsFullPath(pds->PchIncludeDir))) { + DIRREC *DirDBPch; + + DirDBPch = FindSourceDirDB(pds->PchIncludeDir, + pds->PchInclude, TRUE); + + if (DirDBPch) { + pfrPch = FindSourceFileDB(DirDBPch, + pds->PchInclude, + NULL); + } + } + else { + pfrPch = FindSourceFileDB(DirDB, path, NULL); + } + + + if (pfrPch != NULL) { + FILEREC *pfrRoot; + SOURCEREC *psr = NULL; + + BOOL fCase1; + BOOL fCase2; + BOOL fCase3; + BOOL fNeedCompile; + BOOL fCheckDepends; + + // Remote directory PCH files can't be found here + + if (pfrPch->Dir == DirDB) { + psr = FindSourceDB(pds->psrSourcesList[0], pfrPch); + assert(psr != NULL); + psr->SrcFlags |= SOURCEDB_PCH; + } + + Target->pfrCompiland = pfrPch; + assert((pfrRoot = NULL) == NULL); // assign NULL + + fNeedCompile = FALSE; + fCheckDepends = FALSE; + + switch(0) { + default: + fCase1 = (fStatusTree && (fCheckDepends=TRUE) && CheckDependencies(Target, pfrPch, TRUE, &pfrRoot)); + if ( fCase1 ) { + fNeedCompile = TRUE; + break; + } + fCase2 = (Target->DateTime == 0); + if ( fCase2 ) { + fNeedCompile = TRUE; + break; + } + fCase3 = (!fStatusTree && (fCheckDepends=TRUE) && CheckDependencies(Target, pfrPch, TRUE, &pfrRoot)); + if ( fCase3 ) { + fNeedCompile = TRUE; + break; + } + break; + } + + if (( fCheckIncludePaths ) && ( ! fCheckDepends )) { + CheckDependencies(Target, pfrPch, TRUE, &pfrRoot); + } + + if (fNeedCompile) { + + if (psr != NULL) { + if (fWhyBuild) { + BuildMsgRaw("\n"); + if (fCase1) { + BuildMsgRaw("Compiling %s because (Case 1) *1\n", psr->pfrSource->Name); + } else + if (fCase2) { + BuildMsgRaw("Compiling %s because Target date == 0 (Target->Compiland=%s) *1\n", psr->pfrSource->Name, Target->pfrCompiland->Name); + } else + if (fCase3) { + BuildMsgRaw("Compiling %s because (Case 3) *1\n", psr->pfrSource->Name); + } + } + + psr->SrcFlags |= SOURCEDB_COMPILE_NEEDED; + } else { + if (fWhyBuild) { + BuildMsgRaw("\n"); + BuildMsgRaw("Compiling %s because Target date == 0 (Target->Compiland=%s) *1\n", Target->Name, Target->pfrCompiland->Name); + } + } + + pfrPch->Dir->DirFlags |= DIRDB_COMPILENEEDED; + DateTimePch = ULONG_MAX; // always out of date + if (fKeep) { + Target->DateTime = 0; // don't delete pch target + } + } + else { // else it exists and is up to date... + Target->DateTime = 0; // don't delete pch target + } + + // No cycle possible at the root of the tree. + assert(pfrRoot == NULL); + } + else if (DEBUG_1) { + BuildError("Cannot locate precompiled header file: %s.\n", + path); + } + } + + // + // Target->DateTime will be zero if the file is up to date (or we + // don't want to delete it). If Target->DateTime is non-zero, + // delete the .pch and corresponding .obj file so they will be + // rebuilt. + // + if (Target->DateTime != 0) { + DeleteSingleFile(NULL, Target->Name, FALSE); + if (DirDB->PchObj != NULL) { + ExpandObjAsterisk( + path, + DirDB->PchObj, + TargetMachines[i]->ObjectDirectory); + DeleteSingleFile(NULL, path, FALSE); + } else { + p = strrchr(Target->Name, '.'); + if (p != NULL && strcmp(p, ".pch") == 0) { + strcpy(p, ".obj"); + DeleteSingleFile(NULL, Target->Name, FALSE); + } + } + } + FreeMem(&Target, MT_TARGET); + } + + // + // Check to see which files given in the SOURCES macro need to be + // rebuilt, and delete their targets (.obj) if they're out of date. + // + +ProcessSourceList: + + apsr[1] = pds->psrSourcesList[TargetToPossibleTarget[i] + 1]; + + for (ppsr = apsr; ppsr < apsr + (sizeof(apsr)/sizeof(*apsr)); ppsr++) { + SOURCEREC *psr; + + if (*ppsr == NULL) { + continue; + } + + + for (psr = *ppsr; psr != NULL; psr = psr->psrNext) { + FILEREC *pfr, *pfrRoot; + + AssertSource(psr); + + pfr = psr->pfrSource; + + AssertFile(pfr); + + if ((psr->SrcFlags & SOURCEDB_PCH) == 0) { + + USHORT j; + LONG iPass, iPassEnd; + + iPass = 1; + iPassEnd = 0; + + if (pfr->FileFlags & FILEDB_PASS0) + iPass = 0; + + if ((pfr->FileFlags & FILEDB_MULTIPLEPASS) || + !(pfr->FileFlags & FILEDB_PASS0)) + iPassEnd = 1; + + assert(iPass <= iPassEnd); + + // + // If we're doing a pass zero scan and the file is + // not a pass zero file, then continue because we + // don't care about it right now. + // + if (fFirstScan && fPassZero && iPass == 1) { + continue; + } + + // + // Don't check dependencies of pass zero files on the + // second scan, because they're all supposed to be built + // by now. + // + if (!fFirstScan && iPassEnd == 0) { + continue; + } + + // + // If the file was created during pass zero, then make sure + // we don't think it's still missing. + // + if (!fFirstScan && + (psr->SrcFlags & SOURCEDB_FILE_MISSING) && + !(pfr->FileFlags & FILEDB_FILE_MISSING)) + { + psr->SrcFlags &= ~SOURCEDB_FILE_MISSING; + } + + // If the file is a multiple pass file (e.g. .asn), loop + // through both passes. + + for ( ; iPass <= iPassEnd; iPass++) { + + // + // If the file has multiple targets (e.g. .mc, .idl or + // .asn), then loop through all the targets. + // + for (j = 0; + Target = BuildCompileTarget( + pfr, + psr->ObjectSourceName ? psr->ObjectSourceName : pfr->Name, + j, + pds->ConditionalIncludes, + DirDB, + pds, + iPass, + TargetMachines[i]->ObjectDirectory, + TargetMachines[i]->SourceDirectory); + j++) + { + + BOOL fCase1; + BOOL fCase2; + BOOL fCase3; + BOOL fCase4; + BOOL fCase5; + BOOL fNeedCompile; + BOOL fCheckDepends; + + if (DEBUG_4) { + BuildMsgRaw(szNewLine); + } + assert((pfrRoot = NULL) == NULL); // assign NULL + + // Decide whether the target needs to be compiled. + // Forcibly examine dependencies to get line count. + + fNeedCompile = FALSE; + fCheckDepends = FALSE; + + switch(0) { + default: + fCase1 = (psr->SrcFlags & SOURCEDB_FILE_MISSING); + if ( fCase1 ) { + fNeedCompile = TRUE; + break; + } + fCase2 = (fStatusTree && (fCheckDepends=TRUE) && CheckDependencies(Target, pfr, TRUE, &pfrRoot)); + if ( fCase2 ) { + fNeedCompile = TRUE; + break; + } + fCase3 = (Target->DateTime == 0); + if ( fCase3 ) { + fNeedCompile = TRUE; + break; + } + fCase4 = ((pfr->FileFlags & FILEDB_C) && Target->DateTime < DateTimePch); + if ( fCase4 ) { + fNeedCompile = TRUE; + break; + } + fCase5 = (!fStatusTree && (fCheckDepends=TRUE) && CheckDependencies(Target, pfr, TRUE, &pfrRoot)); + if ( fCase5 ) { + fNeedCompile = TRUE; + break; + } + break; + } + + if (( fCheckIncludePaths ) && ( ! fCheckDepends )) { + CheckDependencies(Target, pfr, TRUE, &pfrRoot); + } + + if ( fNeedCompile ) + { + if (fWhyBuild) { + BuildMsgRaw("\n"); + if (fCase1) { + BuildMsgRaw("Compiling %s because filename is missing from build database *2\n", psr->pfrSource->Name); + } else + if (fCase2) { + BuildMsgRaw("Compiling %s because (Case 2) *2\n", psr->pfrSource->Name); + } else + if (fCase3) { + BuildMsgRaw("Compiling %s because Target date == 0 *2\n", psr->pfrSource->Name); + } else + if (fCase4) { + BuildMsgRaw("Compiling %s because C file is later earlier than pch *2\n", psr->pfrSource->Name); + } else + if (fCase5) { + BuildMsgRaw("Compiling %s because (Case 5) *2\n", psr->pfrSource->Name); + } + } + + psr->SrcFlags |= SOURCEDB_COMPILE_NEEDED; + + if (pfr->FileFlags & FILEDB_PASS0) { + DirDB->DirFlags |= DIRDB_PASS0NEEDED; + } + else + DirDB->DirFlags |= DIRDB_COMPILENEEDED; + + if (Target->DateTime != 0 && !fKeep) + { + DeleteSingleFile(NULL, Target->Name, FALSE); + } + + FreeMem(&Target, MT_TARGET); + + if (j != 0) { + // + // Delete the 'rule target' so nmake + // doesn't complain about "don't know how + // to make ..." + // + Target = BuildCompileTarget( + pfr, + psr->ObjectSourceName ? psr->ObjectSourceName : pfr->Name, + 0, + pds->ConditionalIncludes, + DirDB, + pds, + iPass, + TargetMachines[i]->ObjectDirectory, + TargetMachines[i]->SourceDirectory); + if (Target) { + DeleteSingleFile( + NULL, + Target->Name, + FALSE); + + FreeMem(&Target, MT_TARGET); + } + } + + // No need to check other targets, + // we know they all will be rebuilt. + break; + } + + // No cycle possible at the root of the tree. + + assert(pfrRoot == NULL); + FreeMem(&Target, MT_TARGET); + } + } + } + if (fClean || (psr->SrcFlags & SOURCEDB_COMPILE_NEEDED)) { + ULONG cline; + + if (++idScan == 0) { + ++idScan; // skip zero + } + + if (fFirstScan && (pfr->FileFlags & FILEDB_PASS0)) + { + cline = CountSourceLines(idScan, pfr); + DirDB->PassZeroLines += cline; + DirDB->CountOfPassZeroFiles++; + } + + // For a multiple pass file, we really need to count the + // lines in the file compiled duing pass1 (and generated + // during pass 0). Instead, we just count the pass 0 + // source file all over again. It's cheap, but the line + // count is inaccurate. + + if (!fPassZero && + ((pfr->FileFlags & FILEDB_MULTIPLEPASS) || + !(pfr->FileFlags & FILEDB_PASS0))) + { + cline = CountSourceLines(idScan, pfr); + DirDB->SourceLinesToCompile += cline; + DirDB->CountOfFilesToCompile++; + } + } + } + } + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: ScanSourceDirectories +// +// Synopsis: Scan a source directory to determine what files it +// contains, whether it should be compiled or linked, and +// whether it has subdirectories that we should process. +// +// Arguments: [DirName] -- Directory to scan +// +//---------------------------------------------------------------------------- + +VOID +ScanSourceDirectories(LPSTR DirName) +{ + char path[DB_MAX_PATH_LENGTH]; + PDIRREC DirDB; + DIRSUP *pds = NULL; + LPSTR SavedCurrentDirectory; + BOOL DirsPresent; + ULONG DateTimeSources = 0; + UINT i; + + if (DEBUG_4) { + BuildMsgRaw( + "ScanSourceDirectories(%s) level = %d\n", + DirName, + RecurseLevel); + } + + // Change to the given directory + SavedCurrentDirectory = PushCurrentDirectory(DirName); + + // Process all the files in this directory + DirDB = ScanDirectory(DirName); + + AssertOptionalDir(DirDB); + if (fCleanRestart && DirDB != NULL && !strcmp(DirDB->Name, RestartDir)) { + fCleanRestart = FALSE; + fClean = fRestartClean; + fCleanLibs = fRestartCleanLibs; + } + + if (!DirDB || !(DirDB->DirFlags & (DIRDB_DIRS | DIRDB_SOURCES))) { + PopCurrentDirectory(SavedCurrentDirectory); + return; + } + + if (fShowTree && !(DirDB->DirFlags & DIRDB_SHOWN)) { + AddShowDir(DirDB); + } + + if (DirDB->DirFlags & DIRDB_SOURCES) { + BOOL fSourcesRead = TRUE; + + SetObjDir((DirDB->DirFlags & DIRDB_CHECKED_ALT_DIR) != 0); + + // + // This directory contains a SOURCES file + // + + if (fFirstScan) + { + AllocMem(sizeof(DIRSUP), &pds, MT_DIRSUP); + memset(pds, 0, sizeof(*pds)); + fSourcesRead = ReadSourcesFile(DirDB, pds, &DateTimeSources); + + DirDB->pds = pds; + } + else + { + pds = DirDB->pds; + + assert(pds); + + DateTimeSources = pds->DateTimeSources; + + // + // We need to rebuild the sources list because + // the previous scan was probably not complete. + // + if (pds) + PostProcessSources(DirDB, pds); + + } + + assert(pds); + + if (DEBUG_4) { + BuildMsgRaw("ScanSourceDirectories(%s) SOURCES\n", DirName); + } + + ScanFlagsCurrent = 0; + CountIncludeDirs = CountSystemIncludeDirs; + + // Scan the include environments in the order that MAKEFILE.DEF + // processes them. This order is: + // + // 1) Sources variable INCLUDE + // 2) Cairo/Chicago directories + // 3) System includes + // 4) UMTYPE-derived includes + // + // The subtlety is that we must do this in the reverse order + // since each of the processing routines pushes search directories + // onto the HEAD of the include search list. + // + // Note: we come in here with the system includes already set. + // There's no way to stick the UMTYPE-derived ones ahead of the + // system includes + + // 4) UMTYPE-derived includes + if (pds->TestType != NULL && !strcmp(pds->TestType, "os2")) { + ScanGlobalIncludeDirectory(pszIncCrt); + ScanGlobalIncludeDirectory(pszIncOs2); + ScanFlagsCurrent |= SCANFLAGS_OS2; + } + else + if (pds->TestType != NULL && !strcmp(pds->TestType, "posix")) { + ScanGlobalIncludeDirectory(pszIncPosix); + ScanFlagsCurrent |= SCANFLAGS_POSIX; + } + else { + ScanGlobalIncludeDirectory(pszIncCrt); + ScanFlagsCurrent |= SCANFLAGS_CRT; + } + + if (DirDB->DirFlags & DIRDB_CHICAGO_INCLUDES) { + ScanGlobalIncludeDirectory(pszIncChicago); + ScanFlagsCurrent |= SCANFLAGS_CHICAGO; + } + + // 1) Sources variable INCLUDE + if (pds->LocalIncludePath) { + + ScanIncludeEnv(pds->LocalIncludePath); + } + + DirsPresent = FALSE; + + } + else + if (DirDB->DirFlags & DIRDB_DIRS) { + // + // This directory contains a DIRS or MYDIRS file + // + DirsPresent = ReadDirsFile(DirDB); + + if (DEBUG_4) { + BuildMsgRaw("ScanSourceDirectories(%s) DIRS\n", DirName); + } + } + + if (!fQuicky || (fQuickZero && fFirstScan)) { + if (!RecurseLevel) { + BuildError( + "Examining %s directory%s for %s.%s\n", + DirDB->Name, + DirsPresent? " tree" : "", + fLinkOnly? "targets to link" : "files to compile", + fFirstScan ? "" : " (2nd Pass)" + ); + } + ClearLine(); + BuildMsgRaw(" %s ", DirDB->Name); + fLineCleared = FALSE; + if (fDebug || !(BOOL) _isatty(_fileno(stderr))) { + BuildMsgRaw(szNewLine); + fLineCleared = TRUE; + } + } + + if (!fLinkOnly) { + + if (DirDB->DirFlags & DIRDB_SOURCESREAD) { + // + // Determine what files need to be compiled + // + ProcessSourceDependencies(DirDB, pds, DateTimeSources); + } + else + if (fFirstScan && DirsPresent && (DirDB->DirFlags & DIRDB_MAKEFIL0)) { + DirDB->DirFlags |= ((fSemiQuicky && (!fQuickZero || !fFirstScan)) ? DIRDB_COMPILENEEDED : + DIRDB_PASS0NEEDED); + } + else + if (DirsPresent && (DirDB->DirFlags & DIRDB_MAKEFIL1)) { + DirDB->DirFlags |= DIRDB_COMPILENEEDED; + } + + if (fFirstScan && (DirDB->DirFlags & DIRDB_PASS0NEEDED)) + { + if (CountPassZeroDirs >= MAX_BUILD_DIRECTORIES) { + BuildError( + "%s: Ignoring PassZero Directory table overflow, %u " + "entries allowed\n", + DirDB->Name, + MAX_BUILD_DIRECTORIES); + } + else { + // + // This directory needs to be compiled in pass zero. Add it + // to the list. + // + PassZeroDirs[CountPassZeroDirs++] = DirDB; + } + + if (fQuicky && !fQuickZero) { + if (!(fSemiQuicky && (DirDB->DirFlags & DIRDB_COMPILENEEDED))) { + // For -Z with compile needed anyway, CompileSourceDirectories do it. + CompilePassZeroDirectories(); + } + CountPassZeroDirs = 0; + } + else { + if (fFirstScan) { + fPassZero = TRUE; // Limits scanning during pass zero. + } + + if (DirDB->CountOfPassZeroFiles) { + if (fLineCleared) { + BuildMsgRaw(" %s ", DirDB->Name); + } + BuildMsgRaw( + "- %d Pass Zero files (%s lines)\n", + DirDB->CountOfPassZeroFiles, + FormatNumber(DirDB->PassZeroLines)); + } + } + } + + if ((DirDB->DirFlags & DIRDB_COMPILENEEDED) && + (!fFirstScan || !fPassZero)) { + + if (CountCompileDirs >= MAX_BUILD_DIRECTORIES) { + BuildError( + "%s: Ignoring Compile Directory table overflow, %u " + "entries allowed\n", + DirDB->Name, + MAX_BUILD_DIRECTORIES); + } + else { + // + // This directory needs to be compiled. Add it to the list. + // + CompileDirs[CountCompileDirs++] = DirDB; + } + + if (fQuicky && (!fQuickZero || !fFirstScan)) { + CompileSourceDirectories(); + CountCompileDirs = 0; + } + else + if (DirDB->CountOfFilesToCompile) { + if (fLineCleared) { + BuildMsgRaw(" %s ", DirDB->Name); + } + BuildMsgRaw( + "- %d source files (%s lines)\n", + DirDB->CountOfFilesToCompile, + FormatNumber(DirDB->SourceLinesToCompile)); + } + } + } + + if (DirsPresent && (DirDB->DirFlags & DIRDB_MAKEFILE)) { + DirDB->DirFlags |= DIRDB_LINKNEEDED | DIRDB_FORCELINK; + } + else + if (DirDB->DirFlags & DIRDB_TARGETFILES) { + DirDB->DirFlags |= DIRDB_LINKNEEDED | DIRDB_FORCELINK; + } + + if ((DirDB->DirFlags & DIRDB_LINKNEEDED) && (!fQuicky || fSemiQuicky)) { + if (CountLinkDirs >= MAX_BUILD_DIRECTORIES) { + BuildError( + "%s: Ignoring Link Directory table overflow, %u entries allowed\n", + DirDB->Name, + MAX_BUILD_DIRECTORIES); + } + else { + LinkDirs[CountLinkDirs++] = DirDB; + } + } + if ((DirDB->DirFlags & DIRDB_SOURCESREAD) && !fFirstScan) { + FreeDirSupData(pds); // free data that are no longer needed + FreeMem(&pds, MT_DIRSUP); + DirDB->pds = NULL; + } + + // + // Recurse into subdirectories + // + if (DirsPresent) { + for (i = 1; i <= DirDB->CountSubDirs; i++) { + FILEREC *FileDB, **FileDBNext; + + FileDBNext = &DirDB->Files; + while (FileDB = *FileDBNext) { + if (FileDB->SubDirIndex == (USHORT) i) { + GetCurrentDirectory(DB_MAX_PATH_LENGTH, path); + strcat(path, "\\"); + strcat(path, FileDB->Name); + DirDB->RecurseLevel = (USHORT) ++RecurseLevel; + ScanSourceDirectories(path); + RecurseLevel--; + break; + } + FileDBNext = &FileDB->Next; + } + } + } + + if (((fQuickZero && fFirstScan) || (!fQuicky)) && !RecurseLevel) { + ClearLine(); + } + + PopCurrentDirectory(SavedCurrentDirectory); +} + + +//+--------------------------------------------------------------------------- +// +// Function: CompilePassZeroDirectories +// +// Synopsis: Spawns the compiler on the directories in the PassZeroDirs +// array. +// +// Arguments: (none) +// +//---------------------------------------------------------------------------- + +VOID +CompilePassZeroDirectories( + VOID + ) +{ + PDIRREC DirDB; + LPSTR SavedCurrentDirectory; + UINT i; + + StartElapsedTime(); + for (i = 0; i < CountPassZeroDirs; i++) { + + DirDB = PassZeroDirs[ i ]; + AssertDir(DirDB); + + if ((fQuickZero && fFirstScan) || !fQuicky) { + SavedCurrentDirectory = PushCurrentDirectory( DirDB->Name ); + } + + if (DirDB->DirFlags & DIRDB_DIRS) { + if (DirDB->DirFlags & DIRDB_MAKEFIL0) { + strcpy( MakeParametersTail, " -f makefil0." ); + strcat( MakeParametersTail, " NOLINK=1" ); + if (fClean) { + strcat( MakeParametersTail, " clean" ); + } + + if (fQuery) { + BuildErrorRaw("'%s %s'\n", MakeProgram, MakeParameters); + } + else { + if (DEBUG_1) { + BuildMsg( + "Executing: %s %s\n", + MakeProgram, + MakeParameters); + } + + CurrentCompileDirDB = NULL; + RecurseLevel = DirDB->RecurseLevel; + ExecuteProgram(MakeProgram, MakeParameters, MakeTargets, TRUE); + } + } + } + else { + strcpy(MakeParametersTail, " NTTEST="); + if (DirDB->KernelTest) { + strcat(MakeParametersTail, DirDB->KernelTest); + } + + strcat(MakeParametersTail, " UMTEST="); + if (DirDB->UserTests) { + strcat(MakeParametersTail, DirDB->UserTests); + } + + if (DirDB->DirFlags & DIRDB_CHECKED_ALT_DIR) { + strcat(MakeParametersTail, szCheckedAltDir); + } + if (fQuicky && !fSemiQuicky) { + if (DirDB->DirFlags & DIRDB_DLLTARGET) { + strcat(MakeParametersTail, " MAKEDLL=1"); + } + ProcessLinkTargets(DirDB, NULL); + } + else { + strcat( MakeParametersTail, " NOLINK=1 PASS0ONLY=1"); + } + + if (fQuery) { + BuildErrorRaw( + "'%s %s%s'\n", + MakeProgram, + MakeParameters, + MakeTargets); + } + else { + if ((DirDB->DirFlags & DIRDB_SYNCHRONIZE_DRAIN) && + (fParallel)) { + // + // Wait for all threads to complete before + // trying to compile this directory. + // + WaitForParallelThreads(); + } + if (DEBUG_1) { + BuildMsg("Executing: %s %s%s\n", + MakeProgram, + MakeParameters, + MakeTargets); + } + CurrentCompileDirDB = DirDB; + RecurseLevel = DirDB->RecurseLevel; + ExecuteProgram( + MakeProgram, + MakeParameters, + MakeTargets, + (DirDB->DirFlags & DIRDB_SYNCHRONIZE_BLOCK) != 0); + } + } + PrintElapsedTime(); + if ((fQuickZero && fFirstScan) || !fQuicky) { + PopCurrentDirectory(SavedCurrentDirectory); + } + + DirDB->DirFlags &= ~DIRDB_PASS0NEEDED; + DirDB->CountOfPassZeroFiles = 0; + DirDB->PassZeroLines = 0; + } +} + +//+--------------------------------------------------------------------------- +// +// Function: CompileSourceDirectories +// +// Synopsis: Spawns the compiler on the directories in the CompileDirs +// array. +// +// Arguments: (none) +// +//---------------------------------------------------------------------------- + +VOID +CompileSourceDirectories( + VOID + ) +{ + PDIRREC DirDB; + LPSTR SavedCurrentDirectory; + UINT i,j; + char path[DB_MAX_PATH_LENGTH]; + + StartElapsedTime(); + for (i = 0; i < CountCompileDirs; i++) { + + DirDB = CompileDirs[ i ]; + + AssertDir(DirDB); + + if (!fQuicky || (fQuickZero && (!fFirstScan || !RecurseLevel))) { + SavedCurrentDirectory = PushCurrentDirectory( DirDB->Name ); + if (fQuickZero && !RecurseLevel && fFirstScan) + { + GenerateObjectsDotMac(DirDB, DirDB->pds, DirDB->pds->DateTimeSources); + } + } + + if (DirDB->DirFlags & DIRDB_DIRS) { + if ((DirDB->DirFlags & DIRDB_SYNCHRONIZE_DRAIN) && + (fParallel)) { + // + // Wait for all threads to complete before + // trying to compile this directory. + // + WaitForParallelThreads(); + } + if (fSemiQuicky && (DirDB->DirFlags & DIRDB_MAKEFIL0)) { + strcpy( MakeParametersTail, " -f makefil0." ); + strcat( MakeParametersTail, " NOLINK=1" ); + if (fClean) { + strcat( MakeParametersTail, " clean" ); + } + + if (fQuery) { + BuildErrorRaw("'%s %s'\n", MakeProgram, MakeParameters); + } + else { + if (DEBUG_1) { + BuildMsg( + "Executing: %s %s\n", + MakeProgram, + MakeParameters); + } + + CurrentCompileDirDB = NULL; + RecurseLevel = DirDB->RecurseLevel; + ExecuteProgram(MakeProgram, MakeParameters, MakeTargets, TRUE); + } + } + + if (DirDB->DirFlags & DIRDB_MAKEFIL1) { + strcpy( MakeParametersTail, " -f makefil1." ); + strcat( MakeParametersTail, " NOLINK=1 NOPASS0=1" ); + if (fClean) { + strcat( MakeParametersTail, " clean" ); + } + + if (fQuery) { + BuildErrorRaw("'%s %s'\n", MakeProgram, MakeParameters); + } + else { + if (DEBUG_1) { + BuildMsg( + "Executing: %s %s\n", + MakeProgram, + MakeParameters); + } + + CurrentCompileDirDB = NULL; + RecurseLevel = DirDB->RecurseLevel; + ExecuteProgram(MakeProgram, MakeParameters, MakeTargets, TRUE); + } + } + } + else { + strcpy(MakeParametersTail, " NTTEST="); + if (DirDB->KernelTest) { + strcat(MakeParametersTail, DirDB->KernelTest); + } + + strcat(MakeParametersTail, " UMTEST="); + if (DirDB->UserTests) { + strcat(MakeParametersTail, DirDB->UserTests); + } + + if (fQuicky && DirDB->PchObj) { + for (j = 0; j < CountTargetMachines; j++) { + FormatLinkTarget( + path, + TargetMachines[j]->ObjectDirectory, + DirDB->TargetPath, + DirDB->PchObj, + ""); + + if (ProbeFile( NULL, path ) != -1) { + // + // the pch.obj file is present so we therefore + // must do this incremental build without pch + // + strcat( MakeParametersTail, " NTNOPCH=yes" ); + break; + } + } + } + + if (DirDB->DirFlags & DIRDB_CHECKED_ALT_DIR) { + strcat(MakeParametersTail, szCheckedAltDir); + } + if (fQuicky && !fSemiQuicky) { + if (DirDB->DirFlags & DIRDB_DLLTARGET) { + strcat(MakeParametersTail, " MAKEDLL=1"); + } + ProcessLinkTargets(DirDB, NULL); + } + else + if (fQuicky && fSemiQuicky) { + strcat(MakeParametersTail, " NOLINK=1"); + } + else { + strcat(MakeParametersTail, " NOLINK=1 NOPASS0=1"); + } + + if (fQuery) { + BuildErrorRaw( + "'%s %s%s'\n", + MakeProgram, + MakeParameters, + MakeTargets); + } + else { + if ((DirDB->DirFlags & DIRDB_SYNCHRONIZE_DRAIN) && + (fParallel)) { + // + // Wait for all threads to complete before + // trying to compile this directory. + // + WaitForParallelThreads(); + } + if (DEBUG_1) { + BuildMsg("Executing: %s %s%s\n", + MakeProgram, + MakeParameters, + MakeTargets); + } + CurrentCompileDirDB = DirDB; + RecurseLevel = DirDB->RecurseLevel; + ExecuteProgram( + MakeProgram, + MakeParameters, + MakeTargets, + (DirDB->DirFlags & DIRDB_SYNCHRONIZE_BLOCK) != 0); + } + } + PrintElapsedTime(); + if (!fQuicky || (fQuickZero && (!fFirstScan || !RecurseLevel))) { + PopCurrentDirectory(SavedCurrentDirectory); + } + } +} + +static int CountLinkTargets; + +//+--------------------------------------------------------------------------- +// +// Function: LinkSourceDirectories +// +// Synopsis: Link the directories given in the LinkDirs array. This is +// done by passing LINKONLY=1 to nmake. +// +// Arguments: (none) +// +//---------------------------------------------------------------------------- + +VOID +LinkSourceDirectories(VOID) +{ + PDIRREC DirDB; + LPSTR SavedCurrentDirectory; + UINT i; + + CountLinkTargets = 0; + StartElapsedTime(); + for (i = 0; i < CountLinkDirs; i++) { + DirDB = LinkDirs[ i ]; + AssertDir(DirDB); + SavedCurrentDirectory = PushCurrentDirectory(DirDB->Name); + + // + // Deletes link targets as necessary + // + ProcessLinkTargets(DirDB, SavedCurrentDirectory); + + PopCurrentDirectory(SavedCurrentDirectory); + } + + if (fPause && !fMTScriptSync) { + BuildMsg("Press enter to continue with linking (or 'q' to quit)..."); + if (getchar() == 'q') { + return; + } + } + + for (i = 0; i < CountLinkDirs; i++) { + DirDB = LinkDirs[i]; + + if (!fMTScriptSync && + (DirDB->DirFlags & DIRDB_COMPILEERRORS) && + (DirDB->DirFlags & DIRDB_FORCELINK) == 0) { + + BuildMsg("Compile errors: not linking %s directory\n", DirDB->Name); + LogMsg( + "Compile errors: not linking %s directory%s\n", + DirDB->Name, + szAsterisks); + continue; + } + + SavedCurrentDirectory = PushCurrentDirectory(DirDB->Name); + + strcpy(MakeParametersTail, " LINKONLY=1 NOPASS0=1"); + strcat(MakeParametersTail, " NTTEST="); + if (DirDB->KernelTest) { + strcat(MakeParametersTail, DirDB->KernelTest); + } + + strcat(MakeParametersTail, " UMTEST="); + if (DirDB->UserTests) { + strcat(MakeParametersTail, DirDB->UserTests); + } + + if (DirDB->DirFlags & DIRDB_CHECKED_ALT_DIR) { + strcat(MakeParametersTail, szCheckedAltDir); + } + + if (DirDB->DirFlags & DIRDB_DLLTARGET) { + strcat(MakeParametersTail, " MAKEDLL=1"); + } + + if ((DirDB->DirFlags & DIRDB_DIRS) && + (DirDB->DirFlags & DIRDB_MAKEFILE) && + fClean) { + strcat(MakeParametersTail, " clean"); + } + + if (fQuery) { + BuildErrorRaw( + "'%s %s%s'\n", + MakeProgram, + MakeParameters, + MakeTargets); + } + else { + if ((DirDB->DirFlags & DIRDB_SYNCHRONIZE_DRAIN) && + (fParallel) && (fSyncLink)) { + // + // Wait for all threads to complete before + // trying to compile this directory. + // + WaitForParallelThreads(); + } + if (DEBUG_1) { + BuildMsg("Executing: %s %s%s\n", + MakeProgram, + MakeParameters, + MakeTargets); + } + + CurrentCompileDirDB = NULL; + RecurseLevel = DirDB->RecurseLevel; + ExecuteProgram(MakeProgram, + MakeParameters, + MakeTargets, + (fSyncLink) && (DirDB->DirFlags & DIRDB_SYNCHRONIZE_BLOCK) != 0); + } + PopCurrentDirectory(SavedCurrentDirectory); + PrintElapsedTime(); + } +} + +//+--------------------------------------------------------------------------- +// +// Function: GetTargetData +// +// Synopsis: Searches aTargetInfo for an entry corresponding to the given +// extension. +// +// Arguments: [ext] -- Extension to look up (including '.'). +// [iPass] -- 0 for pass zero; 1 for pass 1 +// [index] -- Index used to differentiate multiple targets +// [usMidlFlag] -- Indicates which set of MIDL targets should +// be used for MIDL source files. +// +// Returns: A TARGETDATA for the given extension and index. NULL if +// Index is invalid. +// +// History: 29-Jul-94 LyleC Created +// +// Notes: If ext is not found in the aTargetInfo array, then a default +// TARGETINFO is used which maps the extension to obj\*\.obj. +// +//---------------------------------------------------------------------------- + +LPTARGETDATA +GetTargetData(LPSTR ext, LONG iPass, USHORT index, ULONG usMidlIndex) +{ + int i; + OBJECTTARGETINFO **aTargetInfo; + int cTargetInfo; + + if (!ext || (ext[0] == '\0') || (ext[1] == '\0')) + return &DefaultData; + + if ((ext[1] == aMidlTargetInfo0[usMidlIndex]->pszSourceExt[1]) && + (strcmp(ext, aMidlTargetInfo0[usMidlIndex]->pszSourceExt) == 0)) + { + if (index >= aMidlTargetInfo0[usMidlIndex]->NumData) + return NULL; + + return &(aMidlTargetInfo0[usMidlIndex]->Data[index]); + } + + assert(iPass == 0 || iPass == 1); + cTargetInfo = aTargetArray[iPass].cTargetInfo; + aTargetInfo = aTargetArray[iPass].aTargetInfo; + + for (i = 0; i < cTargetInfo; i++) + { + if ((ext[1] == aTargetInfo[i]->pszSourceExt[1]) && + (strcmp(ext, aTargetInfo[i]->pszSourceExt) == 0)) + { + if (index >= aTargetInfo[i]->NumData) + return NULL; + + return(&aTargetInfo[i]->Data[index]); + } + } + + if (index) + return NULL; + + return &DefaultData; +} + +//+--------------------------------------------------------------------------- +// +// Function: BuildCompileTarget +// +// Synopsis: Fills a TARGET struct with data about the target of a given +// source file. +// +// Arguments: [pfr] -- FileRec of source file +// [pszfile] -- Path of source file (compiland) +// [TargetIndex] -- Which target for a source file +// with multiple targets. +// [pszConditionalIncludes] -- List of conditional includes +// [pdrBuild] -- Build directory (with source file) +// [iPass] -- 0 for pass zero; 1 for pass 1 +// [ppszObjectDir] -- Names of target object directories +// [pszSourceDir] -- Name of machine specific source dir +// +// Returns: A filled TARGET struct. NULL if TargetIndex is an invalid +// value for the given file type. +// +// Notes: If [pfr] is NULL, then [pszfile] is not modified and is +// used as the full pathname of the target file. +// [pszObjectDir] is ignored in this case. if [pfr] is not +// NULL, the filename component of [pszfile] is taken, its +// extension is modified, and it is appended to [pszObjectDir] +// to obtain the pathname of the target. The other data is +// used to fill in the rest of the TARGET struct in all cases. +// +// For source files with multiple targets, use the TargetIndex +// parameter to indicate which target you want the path of. For +// instance, .idl files have two targets, so a TargetIndex of 0 +// will return the .h target and TargetIndex=1 will return the +// .c target. A TargetIndex of 2 or above in this case will +// return NULL. TargetIndex is ignored if [pfr] is NULL. +// +//---------------------------------------------------------------------------- + +TARGET * +BuildCompileTarget( + FILEREC *pfr, + LPSTR pszfile, + USHORT TargetIndex, + LPSTR pszConditionalIncludes, + DIRREC *pdrBuild, + DIRSUP *pdsBuild, + LONG iPass, + LPSTR *ppszObjectDir, + LPSTR pszSourceDir) +{ + LPSTR p, p1; + PTARGET Target; + char path[DB_MAX_PATH_LENGTH]; + LPTARGETDATA pData; + + p = pszfile; + if (pfr != NULL) { + p1 = p; + while (*p) { + if (*p++ == '\\') { + p1 = p; // point to last component of pathname + } + } + + sprintf(path, "%s", p1); + + p = strrchr(path, '.'); + + pData = GetTargetData(p, iPass, TargetIndex, pdsBuild->IdlType); + + if (!pData) { + if (DEBUG_1) { + BuildMsg( + "BuildCompileTarget(\"%s\"[%u][%u], \"%s\") -> NULL\n", + pszfile, + iPass, + TargetIndex, + ppszObjectDir[iObjectDir]); + } + return NULL; + } + + assert(pdsBuild); + + switch (pData->ObjectDirFlag) + { + case TD_OBJECTDIR: + p = ppszObjectDir[iObjectDir]; + break; + + case TD_PASS0HDRDIR: + p = pdsBuild->PassZeroHdrDir; + break; + + p = pdsBuild->PassZeroSrcDir1; + break; + + case TD_MCSOURCEDIR: + case TD_PASS0DIR1: + p = pdsBuild->PassZeroSrcDir1; + break; + + case TD_PASS0DIR2: + p = pdsBuild->PassZeroSrcDir2; + break; + + default: + assert(0 && "Invalid ObjectDirFlag"); + break; + } + + if (!p) { + // Make sure path ends in a period + sprintf(path, "%s.", p1); + } else + if (p[0] == '.' && p[1] == '\0') { + strcpy(path, p1); + } + else { + sprintf(path, "%s\\%s", p, p1); + } + + p = strrchr(path, '.'); + + if (p) { + strcpy(p, pData->pszTargetExt); + } + + p = path; + } + + AllocMem(sizeof(TARGET) + strlen(p), &Target, MT_TARGET); + strcpy(Target->Name, p); + Target->pdrBuild = pdrBuild; + Target->DateTime = (*pDateTimeFile)(NULL, p); + Target->pfrCompiland = pfr; + Target->pszSourceDirectory = pszSourceDir; + Target->ConditionalIncludes = pszConditionalIncludes; + Target->DirFlags = pdrBuild->DirFlags; + if (DEBUG_1) { + BuildMsg( + "BuildCompileTarget(\"%s\"[%u][%u], \"%s\") -> \"%s\"\n", + pszfile, + iPass, + TargetIndex, + ppszObjectDir[iObjectDir], + Target->Name); + } + if (Target->DateTime == 0) { + if (fShowOutOfDateFiles) { + BuildError("%s target is missing.\n", Target->Name); + } + } + return(Target); +} + + +//+--------------------------------------------------------------------------- +// +// Function: FormatLinkTarget +// +// Synopsis: Builds a link target path name. +// +// Arguments: [path] -- Place to put constructed name +// [ObjectDirectory] -- e.g. "obj\i386" +// [TargetPath] -- Path (w/o platfrom spec. name) for target +// [TargetName] -- Base name of target +// [TargetExt] -- Extension of target +// +// Notes: Sample input: (path, "obj\i386", "..\obj", "foobar", ".dll") +// +// output: path = "..\obj\i386\foobar.dll" +// +//---------------------------------------------------------------------------- + +VOID +FormatLinkTarget( + LPSTR path, + LPSTR *ObjectDirectory, + LPSTR TargetPath, + LPSTR TargetName, + LPSTR TargetExt) +{ + LPSTR p, p1; + + p = ObjectDirectory[iObjectDir]; + assert(strncmp(pszObjDirSlash, p, strlen(pszObjDirSlash)) == 0); + p1 = p + strlen(p); + while (p1 > p) { + if (*--p1 == '\\') { + p1++; + break; + } + } + sprintf(path, "%s\\%s\\%s%s", TargetPath, p1, TargetName, TargetExt); +} + + +//+--------------------------------------------------------------------------- +// +// Function: ProcessLinkTargets +// +// Synopsis: Deletes link targets for the given directory (.lib & .dll) +// +// Arguments: [DirDB] -- Directory to process +// [CurrentDirectory] -- Current directory +// +//---------------------------------------------------------------------------- + +VOID +ProcessLinkTargets(PDIRREC DirDB, LPSTR CurrentDirectory) +{ + UINT i; + char path[DB_MAX_PATH_LENGTH]; + + AssertDir(DirDB); + for (i = 0; i < CountTargetMachines; i++) { + // + // Delete 'special' link targets + // + if (DirDB->KernelTest) { + FormatLinkTarget( + path, + TargetMachines[i]->ObjectDirectory, + pszObjDir, + DirDB->KernelTest, + ".exe"); + if (fClean && !fKeep && fFirstScan) { + DeleteSingleFile(NULL, path, FALSE); + } + } + else { + UINT j; + + for (j = 0; j < 2; j++) { + LPSTR pNextName; + + pNextName = j == 0? DirDB->UserAppls : DirDB->UserTests; + if (pNextName != NULL) { + char name[256]; + + while (SplitToken(name, '*', &pNextName)) { + FormatLinkTarget( + path, + TargetMachines[i]->ObjectDirectory, + pszObjDir, + name, + ".exe"); + + if (fClean && !fKeep && fFirstScan) { + DeleteSingleFile(NULL, path, FALSE); + } + } + } + } + } + + if (DirDB->TargetPath != NULL && + DirDB->TargetName != NULL && + DirDB->TargetExt != NULL && + strcmp(DirDB->TargetExt, ".lib")) { + + FormatLinkTarget( + path, + TargetMachines[i]->ObjectDirectory, + DirDB->TargetPath, + DirDB->TargetName, + DirDB->TargetExt); + + if (fClean && !fKeep && fFirstScan) { + DeleteSingleFile(NULL, path, FALSE); + } + } + if (DirDB->DirFlags & DIRDB_DIRS) { + if (fDebug && (DirDB->DirFlags & DIRDB_MAKEFILE)) { + BuildError( + "%s\\makefile. unexpected in directory with DIRS file\n", + DirDB->Name); + } + if ((DirDB->DirFlags & DIRDB_SOURCES)) { + BuildError( + "%s\\sources. unexpected in directory with DIRS file\n", + DirDB->Name); + BuildError("Ignoring %s\\sources.\n", DirDB->Name); + DirDB->DirFlags &= ~DIRDB_SOURCES; + } + } + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: IncludeError +// +// Synopsis: Print out the name of an include file and an error message +// to the screen. +// +// Arguments: [pt] -- Target of the file which includes the include +// file or [pfr]. +// [pfr] -- File which includes the include file +// [pir] -- Include file at issue +// [pszError] -- Error string +// +// Notes: If [pt]->pfrCompiland and [pfr] are different, then the names +// of both are printed. +// +//---------------------------------------------------------------------------- + +VOID +IncludeError(TARGET *pt, FILEREC *pfr, INCLUDEREC *pir, LPSTR pszError) +{ + char c1, c2; + + AssertFile(pfr); + AssertInclude(pir); + if (pir->IncFlags & INCLUDEDB_LOCAL) { + c1 = c2 = '"'; + } + else { + c1 = '<'; + c2 = '>'; + } + BuildError("%s\\%s: ", pt->pfrCompiland->Dir->Name, pt->pfrCompiland->Name); + if (pt->pfrCompiland != pfr) { + if (pt->pfrCompiland->Dir != pfr->Dir) { + BuildErrorRaw("%s\\", pfr->Dir->Name); + } + BuildErrorRaw("%s: ", pfr->Name); + } + BuildErrorRaw("%s %c%s%c\n", pszError, c1, pir->Name, c2); +} + + +//+--------------------------------------------------------------------------- +// +// Function: IsConditionalInc +// +// Synopsis: Returns TRUE if the given filename is a conditional include +// for this directory. (As given by the CONDITIONAL_INCLUDES +// macro). +// +// Arguments: [pszFile] -- Name of file to check +// [pt] -- Target struct giving list of conditional includes +// +// Returns: TRUE if it's a conditional include +// +//---------------------------------------------------------------------------- + +BOOL +IsConditionalInc(LPSTR pszFile, TARGET *pt) +{ + AssertPathString(pszFile); + + if (pt->ConditionalIncludes != NULL) { + LPSTR p; + char name[DB_MAX_PATH_LENGTH]; + + p = pt->ConditionalIncludes; + while (SplitToken(name, ' ', &p)) { + if (strcmp(name, pszFile) == 0) { + return(TRUE); + } + } + } + return(FALSE); +} + + +//+--------------------------------------------------------------------------- +// +// Function: IsExcludedInc +// +// Synopsis: Returns TRUE if the given file is listed in the ExcludeIncs +// array. +// +// Arguments: [pszFile] -- File to check +// +//---------------------------------------------------------------------------- + +BOOL +IsExcludedInc(LPSTR pszFile) +{ + ULONG i; + + AssertPathString(pszFile); + for (i = 0; i < CountExcludeIncs; i++) { + if (!strcmp(pszFile, ExcludeIncs[i])) { + return(TRUE); + } + } + return(FALSE); +} + + +//+--------------------------------------------------------------------------- +// +// Function: CheckDependencies +// +// Synopsis: Process dependencies to see if a target is out of date +// +// Arguments: [Target] -- Target to check date on +// [FileDB] -- File which makes [Target] +// [CheckDate] -- If FALSE, then the date check is bypassed. +// [ppfrRoot] -- Returns a cycle root if a cycle is encountered. +// Used only during recursion. +// +// Returns: TRUE if [Target] is out of date w/r/t [FileDB] +// +//---------------------------------------------------------------------------- + +BOOL +CheckDependencies( + PTARGET Target, + FILEREC *FileDB, + BOOL CheckDate, + FILEREC **ppfrRoot) +{ + BOOL fOutOfDate; + BOOL CheckVersion; + static ULONG ChkRecursLevel = 0; + + *ppfrRoot = NULL; + ChkRecursLevel++; + + assert(FileDB != NULL); // NULL FileDB should never happen. + AssertFile(FileDB); + + if (FileDB->fDependActive) { + + // We have detected a loop in the graph of include files. + // Just return, to terminate the recursion. + + if (DEBUG_1) { + BuildMsgRaw( + "ChkDepend(%s, %s, %u) %s\n", + Target->Name, + FileDB->Name, + CheckDate, + "Target Match, *** ASSUME UP TO DATE ***"); + } + if (DEBUG_4) { + BuildMsgRaw( + "%lu-%hu/%hu: ChkDepend(%s %x, %4s%.*s%s, %u) %x %s\n", + ChkRecursLevel, + LocalSequence, + GlobalSequence, + Target->Name, + Target->DateTime, + "", + ChkRecursLevel, + szRecurse, + FileDB->Name, + CheckDate, + FileDB->DateTime, + "Target Match"); + } + *ppfrRoot = FileDB; + ChkRecursLevel--; + return(FALSE); + } + if (DEBUG_4) { + BuildMsgRaw( + "%lu-%hu/%hu: ChkDepend(%s %x, %4s%.*s%s, %u) %x\n", + ChkRecursLevel, + LocalSequence, + GlobalSequence, + Target->Name, + Target->DateTime, + "++", + ChkRecursLevel, + szRecurse, + FileDB->Name, + CheckDate, + FileDB->DateTime); + } + + // We've decided to process this file: + + FileDB->fDependActive = TRUE; + CheckVersion = fEnableVersionCheck; + fOutOfDate = FALSE; + + if (FileDB->GlobalSequence != GlobalSequence || + FileDB->LocalSequence != LocalSequence) { + if (FileDB->GlobalSequence != 0 || FileDB->LocalSequence != 0) { + if (DEBUG_1) { + BuildError( + "Include Sequence %hu/%hu -> %hu/%hu\n", + FileDB->LocalSequence, + FileDB->GlobalSequence, + LocalSequence, + GlobalSequence); + } + if (fDebug & 16) { + PrintFileDB(stderr, FileDB, 0); + } + UnsnapIncludeFiles( + FileDB, + (FileDB->Dir->DirFlags & DIRDB_GLOBAL_INCLUDES) == 0 || + FileDB->GlobalSequence != GlobalSequence); + } + FileDB->GlobalSequence = GlobalSequence; + FileDB->LocalSequence = LocalSequence; + FileDB->DateTimeTree = 0; + } + + if (DEBUG_1) { + BuildMsgRaw( + "ChkDepend(%s, %s, %u)\n", + Target->Name, + FileDB->Name, + CheckDate); + } + + if (CheckDate && + (FileDB->FileFlags & FILEDB_HEADER) && + FileDB->DateTimeTree == 0 && + IsExcludedInc(FileDB->Name)) { + + if (DEBUG_1) { + BuildMsg("Skipping date check for %s\n", FileDB->Name); + } + CheckVersion = FALSE; + FileDB->DateTimeTree = 1; // never out of date + } + + if (FileDB->IncludeFiles == NULL && FileDB->DateTimeTree == 0) { + FileDB->DateTimeTree = FileDB->DateTime; + if (DEBUG_4) { + BuildMsgRaw( + "%lu-%hu/%hu: ChkDepend(%s %x, %4s%.*s%s, %u) %x\n", + ChkRecursLevel, + LocalSequence, + GlobalSequence, + Target->Name, + Target->DateTime, + "t<-f", + ChkRecursLevel, + szRecurse, + FileDB->Name, + CheckDate, + FileDB->DateTime); + } + } + if (CheckDate && + (Target->DateTime < FileDB->DateTime || + Target->DateTime < FileDB->DateTimeTree)) { + if (Target->DateTime != 0) { + if (DEBUG_1 || fShowOutOfDateFiles) { + BuildMsg("%s is out of date with respect to %s\\%s.\n", + Target->Name, + FileDB->NewestDependency->Dir->Name, + FileDB->NewestDependency->Name); + } + } + fOutOfDate = TRUE; + } + + // + // If FileDB->DateTimeTree is non-zero, then the field is equal to the + // newest DateTime of this file or any of its dependants, so we don't + // need to go through the dependency tree again. + // + + if (FileDB->DateTimeTree == 0) { + INCLUDEREC *IncludeDB, **IncludeDBNext, **ppirTree; + + // + // Find the file records for all include files so that after cycles are + // collapsed, we won't attempt to lookup an include file relative to + // the wrong directory. + // + + ppirTree = &FileDB->IncludeFilesTree; + for (IncludeDBNext = &FileDB->IncludeFiles; + (IncludeDB = *IncludeDBNext) != NULL; + IncludeDBNext = &IncludeDB->Next) { + + AssertInclude(IncludeDB); + AssertCleanTree(IncludeDB, FileDB); + IncludeDB->IncFlags |= INCLUDEDB_SNAPPED; + if (IncludeDB->pfrInclude == NULL) { + IncludeDB->pfrInclude = + FindIncludeFileDB( + FileDB, + Target->pfrCompiland, + Target->pdrBuild, + Target->pszSourceDirectory, + IncludeDB); + AssertOptionalFile(IncludeDB->pfrInclude); + if (IncludeDB->pfrInclude != NULL && + (IncludeDB->pfrInclude->Dir->DirFlags & DIRDB_GLOBAL_INCLUDES)) + { + IncludeDB->IncFlags |= INCLUDEDB_GLOBAL; + } + + } + if (IncludeDB->pfrInclude == NULL) { + if (!IsConditionalInc(IncludeDB->Name, Target)) { + // Textual scanning sees headers in inactive preprocessor branches. + // The compiler reports unresolved active includes. + if (fCheckIncludePaths || DEBUG_1) { + IncludeError( + Target, + FileDB, + IncludeDB, + "cannot find include file"); + } + IncludeDB->IncFlags |= INCLUDEDB_MISSING; + } else + if (DEBUG_1) { + IncludeError( + Target, + FileDB, + IncludeDB, + "Skipping missing conditional include file"); + } + continue; + } + *ppirTree = IncludeDB; + ppirTree = &IncludeDB->NextTree; + } + *ppirTree = NULL; // truncate any links from previous sequence + FileDB->DateTimeTree = FileDB->DateTime; + + // + // Walk through the dynamic list. + // +rescan: + for (IncludeDBNext = &FileDB->IncludeFilesTree; + (IncludeDB = *IncludeDBNext) != NULL; + IncludeDBNext = &IncludeDB->NextTree) { + + AssertInclude(IncludeDB); + if (DEBUG_2) { + BuildMsgRaw( + "%lu-%hu/%hu %s %*s%-10s %*s%s\n", + ChkRecursLevel, + LocalSequence, + GlobalSequence, + Target->pfrCompiland->Name, + (ChkRecursLevel - 1) * 2, + "", + IncludeDB->Name, + max(0, 12 - ((int)ChkRecursLevel - 1) * 2), + "", + IncludeDB->pfrInclude != NULL? + IncludeDB->pfrInclude->Dir->Name : "not found"); + } + + // + // tommcg 5/21/98 + // + // If included file is not in "sanctioned" path, warn about it. + // Sanctioned paths are set in an environment variable named + // BUILD_ACCEPTABLE_INCLUDES which can contain wildcards and look + // something like this: + // + // *\nt\public\*;*\nt\private\inc\*;*\..\inc\*;*\..\include\* + // + + if (( fCheckIncludePaths ) && ( IncludeDB->pfrInclude != NULL )) { + + CheckIncludeForWarning( + Target->pfrCompiland->Dir->Name, + Target->pfrCompiland->Name, + FileDB->Dir->Name, + FileDB->Name, + IncludeDB->pfrInclude->Dir->Name, + IncludeDB->pfrInclude->Name + ); + } + + assert(IncludeDB->IncFlags & INCLUDEDB_SNAPPED); + if (IncludeDB->pfrInclude != NULL) { + if (fEnableVersionCheck) { + CheckDate = (IncludeDB->pfrInclude->Version == 0); + } + + if (IncludeDB->Version != IncludeDB->pfrInclude->Version) { + if (CheckVersion) { + if (DEBUG_1 || fShowOutOfDateFiles) { + BuildError( + "%s (v%d) is out of date with " + "respect to %s\\%s (v%d).\n", + FileDB->Name, + IncludeDB->Version, + IncludeDB->pfrInclude->Dir->Name, + IncludeDB->pfrInclude->Name, + IncludeDB->pfrInclude->Version); + } + FileDB->DateTimeTree = ULONG_MAX; // always out of date + fOutOfDate = TRUE; + } + else + if (!fClean && fEnableVersionCheck && !fSilent) { + BuildError( + "%s - #include %s (v%d updated to v%d)\n", + FileDB->Name, + IncludeDB->pfrInclude->Name, + IncludeDB->Version, + IncludeDB->pfrInclude->Version); + } + IncludeDB->Version = IncludeDB->pfrInclude->Version; + AllDirsModified = TRUE; + } + if (CheckDependencies(Target, + IncludeDB->pfrInclude, + CheckDate, + ppfrRoot)) { + fOutOfDate = TRUE; + + // No cycle possible if recursive call returned TRUE. + + assert(*ppfrRoot == NULL); + } + + // if the include file is involved in a cycle, unwind the + // recursion up to the root of the cycle while collpasing + // the cycle, then process the tree again from cycle root. + + else if (*ppfrRoot != NULL) { + + AssertFile(*ppfrRoot); + + // Don't say the file is out of date, yet. + + fOutOfDate = FALSE; + + // Remove the current include file record from the list, + // because it participates in the cycle. + + *IncludeDBNext = IncludeDB->NextTree; + if (IncludeDB->IncFlags & INCLUDEDB_CYCLEROOT) { + RemoveFromCycleRoot(IncludeDB, FileDB); + } + IncludeDB->NextTree = NULL; + IncludeDB->IncFlags |= INCLUDEDB_CYCLEORPHAN; + + // If the included file is not the cycle root, add the + // cycle root to the included file's include file list. + + if (*ppfrRoot != IncludeDB->pfrInclude) { + LinkToCycleRoot(IncludeDB, *ppfrRoot); + } + + if (*ppfrRoot == FileDB) { + + // We're at the cycle root; clear the root pointer. + // Then go rescan the list. + + *ppfrRoot = NULL; + if (DEBUG_4) { + BuildMsgRaw( + "%lu-%hu/%hu: ChkDepend(%s %x, %4s%.*s%s, %u) %x %s\n", + ChkRecursLevel, + LocalSequence, + GlobalSequence, + Target->Name, + Target->DateTime, + "^^", + ChkRecursLevel, + szRecurse, + FileDB->Name, + CheckDate, + FileDB->DateTime, + "ReScan"); + BuildMsgRaw("^^\n"); + } + goto rescan; + } + + // Merge the list for the file involved in the + // cycle into the root file's include list. + + MergeIncludeFiles( + *ppfrRoot, + FileDB->IncludeFilesTree, + FileDB); + FileDB->IncludeFilesTree = NULL; + + // Return immediately and reprocess the flattened + // tree, which now excludes the include files + // directly involved in the cycle. First, make + // sure the files removed from the cycle have their file + // (not tree) time stamps reflected in the cycle root. + + if ((*ppfrRoot)->DateTimeTree < FileDB->DateTime) { + (*ppfrRoot)->DateTimeTree = FileDB->DateTime; + (*ppfrRoot)->NewestDependency = FileDB; + + if (DEBUG_4) { + BuildMsgRaw( + "%lu-%hu/%hu: ChkDepend(%s %x, %4s%.*s%s, %u) %x\n", + ChkRecursLevel, + LocalSequence, + GlobalSequence, + Target->Name, + Target->DateTime, + "t<-c", + ChkRecursLevel, + szRecurse, + (*ppfrRoot)->Name, + CheckDate, + (*ppfrRoot)->DateTimeTree); + } + } + break; + } + + // + // Propagate newest time up through the dependency tree. + // This way, each parent will have the date of its newest + // dependent, so we don't have to check through the whole + // dependency tree for each file more than once. + // + // Note that similar behavior has not been enabled for + // version checking. + // + + if (FileDB->DateTimeTree < IncludeDB->pfrInclude->DateTimeTree) + { + FileDB->DateTimeTree = IncludeDB->pfrInclude->DateTimeTree; + FileDB->NewestDependency = + IncludeDB->pfrInclude->NewestDependency; + + if (DEBUG_4) { + BuildMsgRaw( + "%lu-%hu/%hu: ChkDepend(%s %x, %4s%.*s%s, %u) %x\n", + ChkRecursLevel, + LocalSequence, + GlobalSequence, + Target->Name, + Target->DateTime, + "t<-s", + ChkRecursLevel, + szRecurse, + FileDB->Name, + CheckDate, + FileDB->DateTimeTree); + } + } + } + else + { + // + // Couldn't find the FILEDB for the include file, but this + // could be because the file is 'rcinclude'd, or 'importlib'd + // and isn't considered a source file. In this case, just get + // the timestamp on the file if possible. + // + // Time will be zero if the file is not found. + // + ULONG Time = (*pDateTimeFile)(NULL, IncludeDB->Name); + if (FileDB->DateTimeTree < Time) + { + FileDB->DateTimeTree = Time; + // + // Since we don't have a FILEDB for this dependency, just + // set the pointer to itself and print a message. + // + FileDB->NewestDependency = FileDB; + + if (DEBUG_1 || fShowOutOfDateFiles) { + BuildError( + "%s (v%d) is out of date with respect to %s.\n", + FileDB->Name, + IncludeDB->Version, + IncludeDB->Name); + } + + if (DEBUG_4) { + BuildMsgRaw( + "%lu-%hu/%hu: ChkDepend(%s %x, %4s%.*s%s, %u) %x\n", + ChkRecursLevel, + LocalSequence, + GlobalSequence, + Target->Name, + Target->DateTime, + "t<-s", + ChkRecursLevel, + szRecurse, + FileDB->Name, + CheckDate, + FileDB->DateTimeTree); + } + + } + } + } + } + if (DEBUG_4) { + BuildMsgRaw( + "%lu-%hu/%hu: ChkDepend(%s %x, %4s%.*s%s, %u) %x %s\n", + ChkRecursLevel, + LocalSequence, + GlobalSequence, + Target->Name, + Target->DateTime, + "--", + ChkRecursLevel, + szRecurse, + FileDB->Name, + CheckDate, + FileDB->DateTimeTree, + *ppfrRoot != NULL? "Collapse Cycle" : + fOutOfDate? "OUT OF DATE" : "up-to-date"); + } + assert(FileDB->fDependActive); + FileDB->fDependActive = FALSE; + ChkRecursLevel--; + return(fOutOfDate); +} + + + +//+--------------------------------------------------------------------------- +// +// Function: PickFirst +// +// Synopsis: When called iteratively, the set of returned values is +// effectively a merge sort of the two source lists. +// +// Effects: The pointers given in [ppsr1] and [ppsr2] are modified to point +// to the next appropriate item in the list. +// +// Arguments: [ppsr1] -- First SOURCEREC list +// [ppsr2] -- Second SOURCEREC list +// +// Returns: The appropriate next item from either [ppsr1] or [ppsr2] +// +// Notes: [ppsr1] and [ppsr2] should each be appropriately sorted. +// +// InsertSourceDB maintains a sort order for PickFirst() based first on the +// filename extension, then on the subdirectory mask. Two exceptions to the +// alphabetic sort are: +// - No extension sorts last. +// - .rc extension sorts first. +// +//---------------------------------------------------------------------------- + +#define PF_FIRST -1 +#define PF_SECOND 1 + +SOURCEREC * +PickFirst(SOURCEREC **ppsr1, SOURCEREC **ppsr2) +{ + SOURCEREC **ppsr; + SOURCEREC *psr; + int r = 0; + + AssertOptionalSource(*ppsr1); + AssertOptionalSource(*ppsr2); + if (*ppsr1 == NULL) { + if (*ppsr2 == NULL) { + return(NULL); // both lists NULL -- no more + } + r = PF_SECOND; // 1st is NULL -- return 2nd + } + else if (*ppsr2 == NULL) { + r = PF_FIRST; // 2nd is NULL -- return 1st + } + else { + LPSTR pszext1, pszext2; + + pszext1 = strrchr((*ppsr1)->pfrSource->Name, '.'); + pszext2 = strrchr((*ppsr2)->pfrSource->Name, '.'); + if (pszext1 == NULL) { + r = PF_SECOND; // 1st has no extension -- return 2nd + } + else if (pszext2 == NULL) { + r = PF_FIRST; // 2nd has no extension -- return 1st + } + else if (strcmp(pszext1, ".rc") == 0) { + r = PF_FIRST; // 1st is .rc -- return 1st + } + else if (strcmp(pszext2, ".rc") == 0) { + r = PF_SECOND; // 2nd is .rc -- return 2nd + } + else { + r = strcmp(pszext1, pszext2); + if (r == 0 && + (*ppsr1)->SourceSubDirMask != (*ppsr2)->SourceSubDirMask) { + if ((*ppsr1)->SourceSubDirMask > (*ppsr2)->SourceSubDirMask) { + r = PF_FIRST; // 2nd subdir after 1st -- return 1st + } else { + r = PF_SECOND; // 1st subdir after 2nd -- return 2nd + } + } + } + } + if (r <= 0) { + ppsr = ppsr1; + } else { + ppsr = ppsr2; + } + psr = *ppsr; + *ppsr = psr->psrNext; + return(psr); +} + + +//+--------------------------------------------------------------------------- +// +// Function: WriteObjectsDefinition +// +// Synopsis: Writes out a single platform-specific section of the +// _objects.mac file. +// +// Arguments: [OutFileHandle] -- File handle to write to +// [psrCommon] -- List of common source files +// [psrMachine] -- List of machine-specific source files +// [DirDB] -- directory record +// [ObjectVariable] -- e.g. 386_SOURCES +// [ObjectDirectory] -- name of machine obj dir (e.g. obj\i386) +// +// Returns: +// +// History: 26-Jul-94 LyleC Created +// +// Notes: +// +//---------------------------------------------------------------------------- + +VOID +WriteObjectsDefinition( + FILE *OutFileHandle, + SOURCEREC *psrMachine, + DIRSUP *pds, + LPSTR ObjectVariable, + LPSTR ObjectDirectory, + LPSTR DirName + ) +{ + LPSTR pbuf; + LPSTR pszextsrc; + LPSTR pszextdir; + LPTARGETDATA pData; + SOURCEREC *psrComCopy; + SOURCEREC *psrMachCopy; + SOURCEREC *psrCommon = pds->psrSourcesList[0]; + + SOURCEREC *psr; + USHORT i; + LONG iPass; + + // + // We loop twice - the first time writing out the non-pass-zero files + // to the ObjectVariable, the second time writing out pass zero + // files to the PASS0_ObjectVariable. + // + for (iPass = 1; iPass >= 0; iPass--) + { + pbuf = BigBuf; + + pbuf[0] = '\0'; + if (iPass == 0) { + strcpy(pbuf, "PASS0_"); + } + strcat(pbuf, ObjectVariable); + strcat(pbuf, "="); + pbuf += strlen(pbuf); + + psrComCopy = psrCommon; + psrMachCopy = psrMachine; + + while ((psr = PickFirst(&psrComCopy, &psrMachCopy)) != NULL) { + + AssertSource(psr); + if ((psr->SrcFlags & SOURCEDB_SOURCES_LIST) == 0) { + continue; + } + + // if pass 0 macro and not a pass 0 file, skip it. + + if (iPass == 0 && !(psr->pfrSource->FileFlags & FILEDB_PASS0)) + continue; + + // if pass 1 macro and not a pass 1 file, skip it. + + if (iPass == 1 && + (psr->pfrSource->FileFlags & FILEDB_PASS0) && + !(psr->pfrSource->FileFlags & FILEDB_MULTIPLEPASS)) + continue; + + pszextsrc = strrchr(psr->pfrSource->Name, '.'); + + if (!pszextsrc) { + BuildError("Bad sources extension: %s\n", psr->pfrSource->Name); + continue; + } + + i = 0; + while (pData = GetTargetData(pszextsrc, iPass, i, pds->IdlType)) + { + if (pData == &DefaultData) + { + // + // Check for implicitly 'known' extensions... + // + switch (pszextsrc[1]) { + case 'f': // Fortran + case 'h': // Header file ? + case 'p': // Pascal + BuildError( + "%s: Interesting sources extension: %s\n", + DirName, + psr->pfrSource->Name); + // FALL THROUGH + + case 'a': // Assembly file (.asm) + case 'c': // C file (.c or .cxx) + case 's': // Assembly file (.s) + break; + + default: + BuildError("Bad sources extension: %s\n", + psr->pfrSource->Name); + } + } + + switch (pData->ObjectDirFlag) + { + case TD_OBJECTDIR: + pszextdir = ObjectDirectory; + break; + + case TD_PASS0HDRDIR: + pszextdir = "$(PASS0_HEADERDIR)"; + break; + + case TD_MCSOURCEDIR: + pszextdir = "$(MC_SOURCEDIR)"; + break; + + case TD_PASS0DIR1: + pszextdir = pds->PassZeroSrcDir1; + break; + + case TD_PASS0DIR2: + pszextdir = pds->PassZeroSrcDir2; + break; + + default: + assert(0 && "Invalid ObjectDirFlag"); + break; + } + assert(pszextdir); + assert(pData->pszTargetExt); + + sprintf( + pbuf, + " \\\r\n %s\\%.*s%s", + pszextdir, + (int)(psr->ObjectStem ? strlen(psr->ObjectStem) : + (size_t)(pszextsrc - psr->pfrSource->Name)), + psr->ObjectStem ? psr->ObjectStem : psr->pfrSource->Name, + pData->pszTargetExt); + pbuf += strlen(pbuf); + + i++; + } + } + strcpy(pbuf, "\r\n\r\n"); + pbuf += 4; + + fwrite(BigBuf, 1, (UINT) (pbuf - BigBuf), OutFileHandle); + } + + // Inference rules cover local files; external sources need explicit inputs. + // Resolve each source from the canonical path rather than its basename. + for (i = 0; i < 2; ++i) { + SOURCEREC *entry = i ? psrMachine : psrCommon; + for ( ; entry; entry = entry->psrNext) { + LPSTR extension; + LPSTR compiler; + if (!entry->ProjectSource || !(entry->SrcFlags & SOURCEDB_SOURCES_LIST)) + continue; + extension = strrchr(entry->ProjectSource, '.'); + if (!extension) continue; + if (!_stricmp(extension, ".c")) compiler = "@$(CC) $(CFLAGS) /c /Fo\"$@\""; + else if (!_stricmp(extension, ".cpp") || !_stricmp(extension, ".cxx")) + compiler = "@$(CXX) $(CXXFLAGS) /c /Fo\"$@\""; + else if (!_stricmp(extension, ".asm")) compiler = "@$(AS) $(ASFLAGS) /c /Fo\"$@\""; + else if (!_stricmp(extension, ".rc")) compiler = "@$(RC) $(RCFLAGS) /fo\"$@\""; + else { + BuildError("Unsupported project source extension: %s\n", entry->ProjectSource); + exit(16); + } + fprintf(OutFileHandle, + "%s\\%s%s: \"%s\"\r\n" + "\t@echo BUILDMSG: Compiling \"%s\"\r\n" + "\t%s \"%s\"\r\n\r\n", + ObjectDirectory, entry->ObjectStem, + !_stricmp(extension, ".rc") ? ".res" : ".obj", + entry->ProjectSource, entry->ProjectSource, + compiler, entry->ProjectSource); + } + } +} + + +DWORD +CreateDirectoriesOnPath( + LPTSTR pszPath, + LPSECURITY_ATTRIBUTES psa) +{ + DWORD dwErr = ERROR_SUCCESS; + + if (pszPath && *pszPath) + { + LPTSTR pch = pszPath; + + // If the path is a UNC path, we need to skip the \\server\share + // portion. + // + if ((TEXT('\\') == *pch) && (TEXT('\\') == *(pch+1))) + { + // pch now pointing at the server name. Skip to the backslash + // before the share name. + // + pch += 2; + while (*pch && (TEXT('\\') != *pch)) + { + pch++; + } + + if (!*pch) + { + // Just the \\server was specified. This is bogus. + // + return ERROR_INVALID_PARAMETER; + } + + // pch now pointing at the backslash before the share name. + // Skip to the backslash that should come after the share name. + // + pch++; + while (*pch && (TEXT('\\') != *pch)) + { + pch++; + } + + if (!*pch) + { + // Just the \\server\share was specified. No subdirectories + // to create. + // + return ERROR_SUCCESS; + } + } + + // Loop through the path. + // + for (; *pch; pch++) + { + // Stop at each backslash and make sure the path + // is created to that point. Do this by changing the + // backslash to a null-terminator, calling CreateDirecotry, + // and changing it back. + // + if (TEXT('\\') == *pch) + { + BOOL fOk; + + *pch = 0; + fOk = CreateDirectory (pszPath, psa); + *pch = TEXT('\\'); + + // Any errors other than path alredy exists and we should + // bail out. We also get access denied when trying to + // create a root drive (i.e. c:) so check for this too. + // + if (!fOk) + { + dwErr = GetLastError (); + if (ERROR_ALREADY_EXISTS == dwErr) + { + dwErr = ERROR_SUCCESS; + } + else if ((ERROR_ACCESS_DENIED == dwErr) && + (pch - 1 > pszPath) && (TEXT(':') == *(pch - 1))) + { + dwErr = ERROR_SUCCESS; + } + else + { + break; + } + } + } + } + + if (ERROR_ALREADY_EXISTS == dwErr) + { + dwErr = ERROR_SUCCESS; + } + + if (ERROR_SUCCESS == dwErr) + { + // All dirs up to the last are created. Make the last one also. + if (CreateDirectory(pszPath, psa)) + { + dwErr = GetLastError (); + if (ERROR_ALREADY_EXISTS == dwErr) + { + dwErr = ERROR_SUCCESS; + } + } + } + } + + return dwErr; +} + +//+--------------------------------------------------------------------------- +// +// Function: CreateBuildDirectory +// +// Synopsis: Creates a directory to hold generate object files. SET the +// FILE_ATTRIBUTE_ARCHIVE bit for the directory, since there is nothing +// to backup. We use SET since the default setting for a new directory +// is clear. Go figure. DOS was such a well planned product. +// +// Arguments: [Name] -- Directory to create +// +// Returns: TRUE if directory already exists or was created successfully. +// FALSE otherwise. +//---------------------------------------------------------------------------- + +BOOL +CreateBuildDirectory(LPSTR Name) +{ + DWORD Attributes; + + Attributes = GetFileAttributes(Name); + if (Attributes == -1) { + CreateDirectoriesOnPath(Name, NULL); + Attributes = GetFileAttributes(Name); + } + + if (Attributes != -1 && ((Attributes & FILE_ATTRIBUTE_ARCHIVE) == 0)) { + SetFileAttributes(Name, Attributes | FILE_ATTRIBUTE_ARCHIVE); + } + + return((BOOL)(Attributes != -1)); +} + +//+--------------------------------------------------------------------------- +// +// Function: CreatedBuildFile +// +// Synopsis: Called whenever BUILD creates a file. Clears the FILE_ATTRIBUTE_ARCHIVE +// bit for the file, since there is nothing to backup with a generated file. +// +// Arguments: [DirName] -- DIRDB for directory +// [FileName] -- file name path relative to DirName +// +//---------------------------------------------------------------------------- + +VOID +CreatedBuildFile(LPSTR DirName, LPSTR FileName) +{ + char Name[ DB_MAX_PATH_LENGTH * 2 + 1]; // ensure we have enough space for "DirName" + "\\" + "FileName" + DWORD Attributes; + + strcpy(Name, DirName); + if (Name[0] != '\0') { + strcat(Name, "\\"); + } + strcat(Name, FileName); + + Attributes = GetFileAttributes(Name); + if (Attributes != -1 && (Attributes & FILE_ATTRIBUTE_ARCHIVE)) { + SetFileAttributes(Name, Attributes & ~FILE_ATTRIBUTE_ARCHIVE); + } + return; +} + +//+--------------------------------------------------------------------------- +// +// Function: GenerateObjectsDotMac +// +// Synopsis: Creates the _objects.mac file containing info for all platforms +// +// Arguments: [DirDB] -- Directory to create file for +// [pds] -- Supplementary information on [DirDB] +// [DateTimeSources] -- Timestamp of the SOURCES file +// +//---------------------------------------------------------------------------- + +VOID +GenerateObjectsDotMac(DIRREC *DirDB, DIRSUP *pds, ULONG DateTimeSources) +{ + FILE *OutFileHandle; + UINT i; + ULONG ObjectsDateTime; + + CreateBuildDirectory("obj"); + if (strcmp(pszObjDir, "obj") != 0) { + if (ProbeFile(".", pszObjDir) == -1) { + CreateDirectory(pszObjDir, NULL); + } + } + for (i = 0; i < CountTargetMachines; i++) { + assert(strncmp( + pszObjDirSlash, + TargetMachines[i]->ObjectDirectory[iObjectDir], + strlen(pszObjDirSlash)) == 0); + CreateBuildDirectory(TargetMachines[i]->ObjectDirectory[iObjectDir]); + } + + if (ObjectsDateTime = (*pDateTimeFile)(DirDB->Name, "obj\\_objects.mac")) { + + if (DateTimeSources == 0) { + BuildError("%s: no sources timestamp\n", DirDB->Name); + } + + if (ObjectsDateTime >= DateTimeSources) { + if (!fForce) { + return; + } + } + } + if (!MyOpenFile(DirDB->Name, "obj\\_objects.mac", "wb", &OutFileHandle, TRUE)) { + return; + } + + if ((DirDB->DirFlags & DIRDB_SOURCES_SET) == 0) { + BuildError("Missing SOURCES= definition in %s\n", DirDB->Name); + } else { + for (i = 0; i < MAX_TARGET_MACHINES; i++) { + WriteObjectsDefinition( + OutFileHandle, + pds->psrSourcesList[i + 1], + pds, + PossibleTargetMachines[i]->ObjectVariable, + PossibleTargetMachines[i]->ObjectMacro, + DirDB->Name); + } + } + fclose(OutFileHandle); + CreatedBuildFile(DirDB->Name, "obj\\_objects.mac"); + + // + // If the _objects.mac file was generated during the first pass, then we + // want to regenerate it during the second scan because the first scan + // wasn't complete and _objects.mac may not be correct for non-pass-zero + // files. We do this by setting the timestamp back to the old time. + // + if (fFirstScan && fPassZero) + { + HANDLE hf; + FILETIME ft; + + hf = CreateFile("obj\\_objects.mac", GENERIC_WRITE, 0, + (LPSECURITY_ATTRIBUTES)NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, + (HANDLE)NULL); + + if (hf != INVALID_HANDLE_VALUE) { + ULONG time; + + if (ObjectsDateTime) { + time = ObjectsDateTime; + } + else if (DateTimeSources) { + // + // All we care about is that time time stamp on _objects.mac + // is less than that of the sources file so it will get + // regenerated during the second scan. + // + time = DateTimeSources; + if (LOWORD(time) != 0) + time &= 0xFFFF0000; // 00:00:00 on the same date + else + time = 0x1421A000; // 12:00:00 1/1/1990 + } + else { + time = 0x1421A000; // 12:00:00 1/1/1990 + } + + DosDateTimeToFileTime(HIWORD(time), LOWORD(time), &ft); + + SetFileTime(hf, (LPFILETIME)NULL, (LPFILETIME)NULL, &ft); + + CloseHandle(hf); + } + } +} diff --git a/sdktools/buildscn.c b/sdktools/buildscn.c new file mode 100644 index 0000000..c5611f5 --- /dev/null +++ b/sdktools/buildscn.c @@ -0,0 +1,844 @@ +//+--------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1989 - 1994 +// +// File: buildscn.c +// +// Contents: Directory and File scanning functions for Build.exe +// +// +// History: 16-May-89 SteveWo Created +// ... see SLM logs +// 26-Jul-94 LyleC Cleanup/Add pass0 support +// +//---------------------------------------------------------------------------- + +#include "build.h" + +//+--------------------------------------------------------------------------- +// +// Function: AddShowDir +// +// Synopsis: Add a directory to the ShowDir array +// +//---------------------------------------------------------------------------- + +VOID +AddShowDir(DIRREC *pdr) +{ + AssertDir(pdr); + if (CountShowDirs >= MAX_BUILD_DIRECTORIES) { + static BOOL fError = FALSE; + + if (!fError) { + BuildError( + "Show Directory table overflow, using first %u entries\n", + MAX_BUILD_DIRECTORIES); + fError = TRUE; + } + } + else { + ShowDirs[CountShowDirs++] = pdr; + } + pdr->DirFlags |= DIRDB_SHOWN; +} + +//+--------------------------------------------------------------------------- +// +// Function: AddIncludeDir +// +// Synopsis: Add a directory to the IncludeDirs array +// +//---------------------------------------------------------------------------- + +VOID +AddIncludeDir(DIRREC *pdr, UINT *pui) +{ + AssertDir(pdr); + assert(pdr->FindCount >= 1); + assert(*pui <= MAX_INCLUDE_DIRECTORIES); + if (*pui >= MAX_INCLUDE_DIRECTORIES) { + BuildError( + "Include Directory table overflow, %u entries allowed\n", + MAX_INCLUDE_DIRECTORIES); + exit(16); + } + IncludeDirs[(*pui)++] = pdr; +} + + +//+--------------------------------------------------------------------------- +// +// Function: ScanGlobalIncludeDirectory +// +// Synopsis: Scans a global include directory and adds it to the +// IncludeDir array. +// +//---------------------------------------------------------------------------- + +VOID +ScanGlobalIncludeDirectory(LPSTR path) +{ + DIRREC *pdr; + + char FullPath[DB_MAX_PATH_LENGTH]; + + // Mark a compiler/system include directory before scanning it. In + // particular, modern MSVC's ATLMFC include path contains UTF-16 .rc + // resources which our byte-oriented include scanner cannot parse. + if (!CanonicalizePathName(path, CANONICALIZE_DIR, FullPath)) { + return; + } + pdr = LoadDirDB(FullPath); + if (pdr == NULL) { + return; + } + pdr->DirFlags |= DIRDB_GLOBAL_INCLUDES; + if (ScanDirectory(FullPath) != NULL) { + AddIncludeDir(pdr, &CountIncludeDirs); + if (fShowTreeIncludes && !(pdr->DirFlags & DIRDB_SHOWN)) { + AddShowDir(pdr); + } + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: ScanIncludeEnv +// +// Synopsis: Scans all include directories specified in the INCLUDE +// environment variable. +// +// Arguments: [IncludeEnv] -- value of the INCLUDE environment variable. +// +// Notes: The INCLUDE variable is a string with a list of directories +// separated by semicolons (;). +// +//---------------------------------------------------------------------------- + +VOID +ScanIncludeEnv( + LPSTR IncludeEnv + ) +{ + char path[DB_MAX_PATH_LENGTH] = {0}; + LPSTR IncDir, IncDirEnd; + UINT cb; + + if (!IncludeEnv) { + return; + } + + if (DEBUG_1) { + BuildMsgRaw("ScanIncludeEnv(%s)\n", IncludeEnv); + } + + IncDir = IncludeEnv; + while (*IncDir) { + IncDir++; + } + + while (IncDir > IncludeEnv) { + IncDirEnd = IncDir; + while (IncDir > IncludeEnv) { + if (*--IncDir == ';') { + break; + } + } + + if (*IncDir == ';') { + if (cb = (UINT)(IncDirEnd-IncDir-1)) { + strncpy( path, IncDir+1, cb ); + } + } else { + if (cb = (UINT)(IncDirEnd-IncDir)) { + strncpy( path, IncDir, cb ); + } + } + if (cb) { + path[ cb ] = '\0'; + while (path[ 0 ] == ' ') { + strcpy( path, &path[ 1 ] ); + cb--; + } + + while (cb && path[--cb] == ' ') { + path[ cb ] = '\0'; + } + if (path[0]) { + ScanGlobalIncludeDirectory(path); + } + } + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: ScanSubDir +// +// Synopsis: Scans all the files in the given directory, sets the +// directory flags appropriately (e.g. DIRDB_SOURCES, etc), +// and adds a list of interesting files to the Files list in +// the DirDB structure for the directory. +// +// Arguments: [pszDir] -- Name of directory to scan +// [pdr] -- [out] Filled in DIRREC on return +// +// Notes: An 'interesting' file is one which has a recognized +// extension. See the InsertFileDB and MatchFileDesc +// functions for more info. +// +//---------------------------------------------------------------------------- + +VOID +ScanSubDir(LPSTR pszDir, DIRREC *pdr) +{ + char FileName[DB_MAX_PATH_LENGTH]; + FILEREC *FileDB, **FileDBNext; + WIN32_FIND_DATA FindFileData; + HDIR FindHandle; + ULONG DateTime; + USHORT Attr; + + strcat(pszDir, "\\"); + strcat(pszDir, "*.*"); + + pdr->DirFlags |= DIRDB_SCANNED; + FindHandle = FindFirstFile(pszDir, &FindFileData); + if (FindHandle == (HDIR)INVALID_HANDLE_VALUE) { + if (DEBUG_1) { + BuildMsg("FindFirstFile(%s) failed.\n", pszDir); + } + return; + } + do { + Attr = (USHORT)(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY); + if ((Attr & FILE_ATTRIBUTE_DIRECTORY) && + (!strcmp(FindFileData.cFileName, ".") || + !strcmp(FindFileData.cFileName, ".."))) { + continue; + } + + CopyString(FileName, FindFileData.cFileName, TRUE); + + FileTimeToDosDateTime(&FindFileData.ftLastWriteTime, + ((LPWORD) &DateTime) + 1, + (LPWORD) &DateTime); + + if ((pdr->DirFlags & DIRDB_NEW) == 0 && + (FileDB = LookupFileDB(pdr, FileName)) != NULL) { + + if (FileDB->FileFlags & FILEDB_PASS0) + pdr->DirFlags |= DIRDB_PASS0; + + // + // Clear the file missing flag, since we know the file exists now. + // This flag may be set if the file was generated during pass zero. + // + if (FileDB->FileFlags & FILEDB_FILE_MISSING) + FileDB->FileFlags &= ~FILEDB_FILE_MISSING; + + // + // The time we last stored for this file is different than the + // actual time on the file, so force it to be rescanned. + // + if (FileDB->DateTime != DateTime) { + if (FileDB->FileFlags & (FILEDB_SOURCE | FILEDB_HEADER)) { + FileDB->FileFlags &= ~FILEDB_SCANNED; + } + else { + FileDB->FileFlags |= FILEDB_SCANNED; + } + + if (DEBUG_1) { + BuildMsg( + "%s - DateTime (%lx != %lx)\n", + FileDB->Name, + FileDB->DateTime, + DateTime); + } + + FileDB->DateTime = DateTime; + FileDB->Attr = Attr; + } + else { + FileDB->FileFlags |= FILEDB_SCANNED; + } + } + else { + FileDB = InsertFileDB(pdr, FileName, DateTime, Attr, 0); + } + } while (FindNextFile(FindHandle, &FindFileData)); + + FindClose(FindHandle); + + if ((pdr->DirFlags & DIRDB_DIRS) && (pdr->DirFlags & DIRDB_SOURCES)) + { + BuildError("%s\\sources. unexpected in directory with DIRS file\n", + pdr->Name); + BuildError("Ignoring %s\\sources.\n", pdr->Name); + + pdr->DirFlags &= ~DIRDB_SOURCES; + } + // + // Scan each file in this directory unless using QuickZero + // + if (fQuickZero && fFirstScan) + { + return; + } + FileDBNext = &pdr->Files; + while (FileDB = *FileDBNext) { + if (!(FileDB->FileFlags & (FILEDB_DIR | FILEDB_SCANNED))) { + if ((pdr->DirFlags & DIRDB_GLOBAL_INCLUDES) && + (FileDB->FileFlags & FILEDB_RC)) { + // System resource scripts are irrelevant to C/C++ header + // discovery. Some MSVC ATLMFC .rc files are UTF-16 and + // would otherwise produce bogus "null byte" diagnostics. + // Keep local project .rc files on the normal scanner path. + FileDB->FileFlags |= FILEDB_SCANNED; + } + else if (ScanFile(FileDB)) { + AllDirsModified = TRUE; + } + } + FileDBNext = &FileDB->Next; + } + DeleteUnscannedFiles(pdr); +} + + +//+--------------------------------------------------------------------------- +// +// Function: ScanDirectory +// +// Synopsis: Tries to find the given directory in the database, and if +// not found calls ScanSubDir. +// +// Arguments: [pszDir] -- Directory to scan +// +// Returns: Filled in DIRREC structure for the directory. +// +// Notes: If fQuicky (-z or -Z options) are set, then instead of calling +// ScanSubDir, which is long, it just checks for known files, like +// 'sources' for 'makefile' to determine whether or not the +// directory should be compiled. +// +//---------------------------------------------------------------------------- + +PDIRREC +ScanDirectory(LPSTR pszDir) +{ + DIRREC *pdr; + char FullPath[DB_MAX_PATH_LENGTH]; + + if (DEBUG_1) { + BuildMsgRaw("ScanDirectory(%s)\n", pszDir); + } + + if (!CanonicalizePathName(pszDir, CANONICALIZE_DIR, FullPath)) { + if (DEBUG_1) { + BuildMsgRaw("CanonicalizePathName failed\n"); + } + return(NULL); + } + pszDir = FullPath; + + if ((pdr = LoadDirDB(pszDir)) == NULL) { + return(NULL); + } + + if (fQuicky && (!fQuickZero)) { + + if (!(pdr->DirFlags & DIRDB_SCANNED)) { + pdr->DirFlags |= DIRDB_SCANNED; + if (ProbeFile(pdr->Name, "sources") != -1) { + pdr->DirFlags |= DIRDB_SOURCES | DIRDB_MAKEFILE; + } + else + if (ProbeFile(pdr->Name, "mydirs") != -1 || + ProbeFile(pdr->Name, "dirs") != -1 || + ProbeFile(pdr->Name, pszTargetDirs) != -1) { + + pdr->DirFlags |= DIRDB_DIRS; + if (ProbeFile(pdr->Name, "makefil0") != -1) { + pdr->DirFlags |= DIRDB_MAKEFIL0; + } + if (ProbeFile(pdr->Name, "makefil1") != -1) { + pdr->DirFlags |= DIRDB_MAKEFIL1; + } + if (ProbeFile(pdr->Name, "makefile") != -1) { + pdr->DirFlags |= DIRDB_MAKEFILE; + } + } + } + return(pdr); + } + + if (pdr->DirFlags & DIRDB_SCANNED) { + return(pdr); + } + + if (!RecurseLevel && fNoisyScan) { + ClearLine(); + BuildMsgRaw(" Scanning %s ", pszDir); + if (fDebug || !(BOOL) _isatty(_fileno(stderr))) { + BuildMsgRaw(szNewLine); + } + } + + ScanSubDir(pszDir, pdr); + + if (!RecurseLevel) { + ClearLine(); + } + return(pdr); +} + + +#define BUILD_TLIB_INCLUDE_STMT "importlib" +#define BUILD_TLIB_INCLUDE_STMT_LENGTH (sizeof( BUILD_TLIB_INCLUDE_STMT )-1) + +#define BUILD_MIDL_INCLUDE_STMT "import" +#define BUILD_MIDL_INCLUDE_STMT_LENGTH (sizeof( BUILD_MIDL_INCLUDE_STMT )-1) + +#define BUILD_RC_INCLUDE_STMT "rcinclude" +#define BUILD_RC_INCLUDE_STMT_LENGTH (sizeof( BUILD_RC_INCLUDE_STMT )-1) + +#define BUILD_ASN_INCLUDE_STMT "--<" +#define BUILD_ASN_INCLUDE_STMT_LENGTH (sizeof( BUILD_ASN_INCLUDE_STMT )-1) + +#define BUILD_INCLUDE_STMT "include" +#define BUILD_INCLUDE_STMT_LENGTH (sizeof( BUILD_INCLUDE_STMT )-1) + +#define BUILD_VER_COMMENT "/*++ BUILD Version: " +#define BUILD_VER_COMMENT_LENGTH (sizeof( BUILD_VER_COMMENT )-1) + +#define BUILD_MASM_VER_COMMENT ";;;; BUILD Version: " +#define BUILD_MASM_VER_COMMENT_LENGTH (sizeof( BUILD_MASM_VER_COMMENT )-1) + + +//+--------------------------------------------------------------------------- +// +// Function: IsIncludeStatement +// +// Synopsis: Tries to determine whether or not a given line contains an +// include statement (e.g. #include ). +// +// Arguments: [pfr] -- FILEREC of file being scanned +// [p] -- Current line of file +// +// Returns: NULL if line is not an include statment. Returns pointer to +// beginning of filename if it is (e.g. ). +// +// Notes: The returned filename includes the surrounding quotes or +// brackets, if any. Also, the pointer is just a pointer into +// the given string, not a separate copy. +// +// Supported statements are: +// All file types: #include and #include "filename" +// MIDL files: import "filename" +// RC files: rcinclude filename +// MKTYPLIB files: importlib("filename") +// +//---------------------------------------------------------------------------- + +#define IsTokenPrefix0(psz, szToken, cchToken) \ + (strncmp((psz), (szToken), (cchToken)) == 0) + +#define IsTokenPrefix(psz, szToken, cchToken) \ + (IsTokenPrefix0((psz), (szToken), (cchToken)) && \ + (psz)[cchToken] != '\0') + +#define IsTokenMatch(psz, szToken, cchToken) \ + (IsTokenPrefix((psz), (szToken), (cchToken)) && \ + !iscsym((psz)[cchToken])) + +#define IsCiTokenPrefix0(psz, szToken, cchToken) \ + (_strnicmp((psz), (szToken), (cchToken)) == 0) + +#define IsCiTokenPrefix(psz, szToken, cchToken) \ + (IsCiTokenPrefix0((psz), (szToken), (cchToken)) && \ + (psz)[cchToken] != '\0') + +#define IsCiTokenMatch(psz, szToken, cchToken) \ + (IsCiTokenPrefix((psz), (szToken), (cchToken)) && \ + !iscsym((psz)[cchToken])) + +LPSTR +IsIncludeStatement(FILEREC *pfr, LPSTR p) +{ + if (!p || *p == '\0') + return NULL; + + if (!(pfr->FileFlags & (FILEDB_MASM | FILEDB_MIDL | FILEDB_MKTYPLIB | FILEDB_RC | FILEDB_ASN))) { + if (*p != '#') { + return(NULL); + } + } + + if (*p == '#') + p++; + + while (isspace(*p)) { + p++; + } + + if (IsTokenMatch(p, BUILD_INCLUDE_STMT, BUILD_INCLUDE_STMT_LENGTH)) { + p += BUILD_INCLUDE_STMT_LENGTH; + } + else + if ((pfr->FileFlags & FILEDB_MASM) && + IsCiTokenMatch(p, BUILD_INCLUDE_STMT, BUILD_INCLUDE_STMT_LENGTH)) { + p += BUILD_INCLUDE_STMT_LENGTH; + } + else + if ((pfr->FileFlags & FILEDB_MIDL) && + IsTokenMatch(p, BUILD_MIDL_INCLUDE_STMT, BUILD_MIDL_INCLUDE_STMT_LENGTH)) { + p += BUILD_MIDL_INCLUDE_STMT_LENGTH; + } + else + if ((pfr->FileFlags & FILEDB_RC) && + IsTokenMatch(p, BUILD_RC_INCLUDE_STMT, BUILD_RC_INCLUDE_STMT_LENGTH)) { + + p += BUILD_RC_INCLUDE_STMT_LENGTH; + } + else + if ((pfr->FileFlags & FILEDB_ASN) && + IsTokenPrefix0(p, BUILD_ASN_INCLUDE_STMT, BUILD_ASN_INCLUDE_STMT_LENGTH)) { + + p += BUILD_ASN_INCLUDE_STMT_LENGTH; + } + else + if ((pfr->FileFlags & FILEDB_MKTYPLIB) && + IsTokenMatch(p, BUILD_TLIB_INCLUDE_STMT, BUILD_TLIB_INCLUDE_STMT_LENGTH)) { + p += BUILD_TLIB_INCLUDE_STMT_LENGTH; + while (isspace(*p)) { + p++; + } + + if (*p == '(') // Skip the open paren and get to the quote. + p++; + } + else { + return(NULL); + } + + while (isspace(*p)) { + p++; + } + return(p); +} + + +//+--------------------------------------------------------------------------- +// +// Function: IsPragmaHdrStop +// +// Synopsis: Determines if the given line is a #pragma hdrstop line +// +// Arguments: [p] -- String to analyze +// +// Returns: TRUE if the line is a pragma hdrstop +// +//---------------------------------------------------------------------------- + +BOOL +IsPragmaHdrStop(LPSTR p) +{ + static char szPragma[] = "pragma"; + static char szHdrStop[] = "hdrstop"; + + if (*p == '#') { + while (*++p == ' ') { + ; + } + if (strncmp(p, szPragma, sizeof(szPragma) - 1) == 0 && + *(p += sizeof(szPragma) - 1) == ' ') { + + while (*p == ' ') { + p++; + } + if (strncmp(p, szHdrStop, sizeof(szHdrStop) - 1) == 0 && + !iscsym(p[sizeof(szHdrStop) - 1])) { + + return(TRUE); + } + } + } + return(FALSE); +} + + +//+--------------------------------------------------------------------------- +// +// Function: ScanFile +// +// Synopsis: Scans the given file to determine files which it includes. +// +// Arguments: [FileDB] -- File to scan. +// +// Returns: TRUE if successful +// +// Notes: This function is a nop if the given file does not have either +// the FILEDB_SOURCE or FILEDB_HEADER flag set. +// (see InsertSourceDB) +// +// Note that the performance of this function is critical since +// it is called for every file in each directory. +// +//---------------------------------------------------------------------------- + +#define ASN_NONE 0 // not in Asn INCLUDES statement +#define ASN_START 1 // expectimg "INCLUDES" token +#define ASN_FILENAME 2 // expecting a quoted "filename" +#define ASN_COMMA 3 // expecting end token (">--") or comma + +#define ASN_CONTINUATION 8 // expecting comment token first + +char * +AsnStateToString(UINT AsnState) +{ + static char buf[100]; + char *psz; + + switch (AsnState & ~ASN_CONTINUATION) { + case ASN_NONE: psz = "None"; break; + case ASN_START: psz = "Start"; break; + case ASN_FILENAME: psz = "Filename"; break; + case ASN_COMMA: psz = "Comma"; break; + default: psz = "???"; break; + } + sprintf(buf, "%s%s", psz, (AsnState & ASN_CONTINUATION)? "+Cont" : ""); + return(buf); +} + + +BOOL +ScanFile( + PFILEREC FileDB + ) +{ + FILE *FileHandle; + char CloseQuote; + LPSTR p; + LPSTR IncludeFileName, TextLine; + BOOL fFirst = TRUE; + USHORT IncFlags = 0; + UINT i, cline; + UINT AsnState = ASN_NONE; + + if ((FileDB->FileFlags & (FILEDB_SOURCE | FILEDB_HEADER)) == 0) { + FileDB->FileFlags |= FILEDB_SCANNED; + return(TRUE); + } + + // + // Don't scan non-pass-zero files if we're doing pass zero. + // + if (fPassZero && (FileDB->FileFlags & FILEDB_PASS0) == 0) + return TRUE; + + if (!SetupReadFile( + FileDB->Dir->Name, + FileDB->Name, + FileDB->pszCommentToEOL, + &FileHandle)) { + return(FALSE); + } + + if (!RecurseLevel && fNoisyScan) { + ClearLine(); + BuildMsgRaw( + " Scanning %s ", + FormatPathName(FileDB->Dir->Name, FileDB->Name)); + if (!(BOOL) _isatty(_fileno(stderr))) { + BuildMsgRaw(szNewLine); + } + } + + FileDB->SourceLines = 0; + FileDB->Version = 0; + + MarkIncludeFileRecords( FileDB ); + FileDB->FileFlags |= FILEDB_SCANNED; + + AllDirsModified = TRUE; + + while ((TextLine = ReadLine(FileHandle)) != NULL) { + if (fFirst) { + fFirst = FALSE; + if (FileDB->FileFlags & FILEDB_HEADER) { + if (FileDB->FileFlags & FILEDB_MASM) { + if (!strncmp( TextLine, + BUILD_MASM_VER_COMMENT, + BUILD_MASM_VER_COMMENT_LENGTH)) { + FileDB->Version = (USHORT) + atoi( TextLine + BUILD_MASM_VER_COMMENT_LENGTH); + } + } + else + if (!strncmp( TextLine, + BUILD_VER_COMMENT, + BUILD_VER_COMMENT_LENGTH)) { + FileDB->Version = (USHORT) + atoi( TextLine + BUILD_VER_COMMENT_LENGTH); + } + } + } + + if (AsnState != ASN_NONE) { + p = TextLine; + } + else { + p = IsIncludeStatement(FileDB, TextLine); + } + + if (p != NULL) { + USHORT IncFlagsNew = IncFlags; + + if (FileDB->FileFlags & FILEDB_ASN) { + if (AsnState & ASN_CONTINUATION) { + if (p[0] != '-' || p[1] != '-') { + AsnState = ASN_NONE; // ignore includes and ... + p = NULL; + break; // get next line + } + p += 2; + AsnState &= ~ASN_CONTINUATION; + } +moreasn: + while (p != NULL) { + while (isspace(*p)) { + p++; + } + if (*p == '\0') { + AsnState |= ASN_CONTINUATION; + goto nextline; // get next line + } + switch (AsnState) { + case ASN_NONE: + AsnState = ASN_START; + continue; // re-enter state machine + + case ASN_START: + if (!IsTokenPrefix0( + p, + "INCLUDES", + sizeof("INCLUDES") - 1)) { + goto terminate; + } + AsnState = ASN_FILENAME; + p += sizeof("INCLUDES") - 1; + continue; // re-enter state machine + + case ASN_FILENAME: + if (*p != '"') { + goto terminate; + } + AsnState = ASN_COMMA; + goto parsefilename; + + case ASN_COMMA: + if (*p == '>' && p[1] == '-' && p[2] == '-') { + goto terminate; + } + if (*p != ',') { + goto terminate; + } + p++; + AsnState = ASN_FILENAME; + continue; // re-enter state machine + } + assert(FALSE); // Bad AsnState +terminate: + AsnState = ASN_NONE; // ignore includes statement, & ... +nextline: + p = NULL; // get next line + break; + } + } + +parsefilename: + if (p != NULL) { + CloseQuote = (UCHAR) 0xff; + if (*p == '<') { + p++; + CloseQuote = '>'; + } + else + if (*p == '"') { + p++; + IncFlagsNew |= INCLUDEDB_LOCAL; + CloseQuote = '"'; + } + else + if (FileDB->FileFlags & FILEDB_MASM) { + IncFlagsNew |= INCLUDEDB_LOCAL; + CloseQuote = ';'; + } + else { + // C/C++ permits macro-expanded include operands, e.g. + // #include _STL_INTRIN_HEADER + // The compiler/preprocessor owns expansion of these. + // They cannot be resolved reliably by build.exe's textual + // scanner, so leave them opaque instead of reporting a + // malformed include. + continue; + } + + IncludeFileName = p; + while (*p != '\0' && *p != CloseQuote && *p != ' ') { + p++; + } + if (CloseQuote == ';' && (*p == ' ' || *p == '\0')) { + CloseQuote = *p; + } + + if (*p != CloseQuote || CloseQuote == (UCHAR) 0xff) { + BuildError( + "%s - invalid include statement: %s\n", + FormatPathName(FileDB->Dir->Name, FileDB->Name), + TextLine); + break; + } + + *p = '\0'; + CopyString(IncludeFileName, IncludeFileName, TRUE); + for (i = 0; i < CountExcludeIncs; i++) { + if (!strcmp(IncludeFileName, ExcludeIncs[i])) { + IncludeFileName = NULL; + break; + } + } + + if (IncludeFileName != NULL) { + InsertIncludeDB(FileDB, IncludeFileName, IncFlagsNew); + } + if (FileDB->FileFlags & FILEDB_ASN) { + p++; + goto moreasn; + } + } + } + else + if (IncFlags == 0 && + (FileDB->FileFlags & (FILEDB_ASM | FILEDB_MASM | FILEDB_MIDL | FILEDB_ASN | FILEDB_RC | FILEDB_HEADER)) == 0 && + IsPragmaHdrStop(TextLine)) { + + IncFlags = INCLUDEDB_POST_HDRSTOP; + } + } + CloseReadFile(&cline); + FileDB->SourceLines = cline; + + DeleteIncludeFileRecords( FileDB ); + + if (!RecurseLevel) { + ClearLine(); + } + return(TRUE); +} diff --git a/sdktools/buildscr.cpp b/sdktools/buildscr.cpp new file mode 100644 index 0000000..a7cb563 --- /dev/null +++ b/sdktools/buildscr.cpp @@ -0,0 +1,467 @@ +//+--------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1992 - 1995 +// +// File: buildscr.cpp +// +// Contents: Implementation of the code which talks to the MTScript engine +// when doing a distributed build using the build console. +// +//---------------------------------------------------------------------------- + +#include "scrproc.h" + +#include "build.h" +#include "buildscr.h" + +#define INITGUID +#include + +DEFINE_GUID(CLSID_LocalScriptedProcess, 0x854c316f,0xc854,0x4a77,0xb1,0x89,0x60,0x68,0x59,0xe4,0x39,0x1b); +DEFINE_GUID(IID_IScriptedProcess, 0x854c3171,0xc854,0x4a77,0xb1,0x89,0x60,0x68,0x59,0xe4,0x39,0x1b); +DEFINE_GUID(IID_IScriptedProcessSink, 0x854c3172,0xc854,0x4a77,0xb1,0x89,0x60,0x68,0x59,0xe4,0x39,0x1b); + +DEFINE_GUID(CLSID_ObjectDaemon,0x854c3184,0xc854,0x4a77,0xb1,0x89,0x60,0x68,0x59,0xE4,0x39,0x1b); +DEFINE_GUID(IID_IConnectedMachine,0x854c316c,0xc854,0x4a77,0xb1,0x89,0x60,0x68,0x59,0xe4,0x39,0x1b); +DEFINE_GUID(IID_IObjectDaemon,0x854c3183,0xc854,0x4a77,0xb1,0x89,0x60,0x68,0x59,0xE4,0x39,0x1b); + +#define MAX_RETRIES 2 + +HANDLE g_hMTEvent = NULL; +HANDLE g_hMTThread = NULL; +DWORD g_dwMTThreadId = 0; + +//+--------------------------------------------------------------------------- +// +// Function: WaitForResume +// +// Synopsis: Sends a "phase complete" message to the script engine and then +// waits for it to tell us to resume (if specified). +// +// Arguments: [fPause] -- If TRUE, we wait for a resume command +// [pe] -- Message to send to the script engine +// +//---------------------------------------------------------------------------- + +void +WaitForResume(BOOL fPause, PROC_EVENTS pe) +{ + if (g_hMTEvent) + { + HANDLE aHandles[2] = { g_hMTEvent, g_hMTThread }; + + ResetEvent(g_hMTEvent); + + PostThreadMessage(g_dwMTThreadId, pe, 0, 0); + + if (fPause) + { + // Wait until either the event object is signaled or the thread dies + WaitForMultipleObjects(2, aHandles, FALSE, INFINITE); + } + } +} + +//+--------------------------------------------------------------------------- +// +// Function: ExitMTScriptThread +// +// Synopsis: Tells the thread talking to the MTScript engine to exit. +// +//---------------------------------------------------------------------------- + +void +ExitMTScriptThread() +{ + if (g_hMTEvent) + { + PostThreadMessage(g_dwMTThreadId, PE_EXIT, 0, 0); + + WaitForSingleObject(g_hMTThread, INFINITE); + + CloseHandle(g_hMTThread); + CloseHandle(g_hMTEvent); + } +} + +//+--------------------------------------------------------------------------- +// +// Function: SendStatus +// +// Synopsis: Sends a status message to the MTScript engine with the +// current number of errors, warnings, and completed files. +// +// Arguments: [pSP] -- Pointer to MTScript engine interface +// +//---------------------------------------------------------------------------- + +void +SendStatus(IScriptedProcess *pSP) +{ + wchar_t achBuf[300]; + long lRet; + + static ULONG cErrorsPrev = MAXDWORD; + static ULONG cWarnPrev = MAXDWORD; + static ULONG cFilesPrev = MAXDWORD; + + ULONG cErrors = NumberCompileErrors + NumberLibraryErrors + NumberLinkErrors + NumberBinplaceErrors; + ULONG cWarn = NumberCompileWarnings + NumberLibraryWarnings + NumberLinkWarnings + NumberBinplaceWarnings; + ULONG cFiles = NumberCompiles + NumberLibraries + NumberLinks /* + NumberBinplaces */; + + // Only send status if it's changed since last time we did it. + if ( cErrors != cErrorsPrev + || cWarn != cWarnPrev + || cFiles != cFilesPrev) + { + cErrorsPrev = cErrors; + cWarnPrev = cWarn; + cFilesPrev = cFiles; + + wsprintfW(achBuf, L"errors=%d,warnings=%d,files=%d", cErrors, cWarn, cFiles); + + pSP->SendData(L"status", achBuf, &lRet); + } +} + +//+--------------------------------------------------------------------------- +// +// Function: HandleMessage +// +// Synopsis: Handles a message that has come across our message queue. +// +// Arguments: [pmsg] -- Message +// [pSP] -- Pointer to MTScript engine interface +// +//---------------------------------------------------------------------------- + +BOOL +HandleMessage(MSG *pmsg, IScriptedProcess *pSP) +{ + long lRet; + HRESULT hr = S_OK; + + switch (pmsg->message) + { + case PE_PASS0_COMPLETE: + SendStatus(pSP); + + hr = pSP->SendData(L"pass 0 complete", L"", &lRet); + + break; + + case PE_PASS1_COMPLETE: + SendStatus(pSP); + + hr = pSP->SendData(L"pass 1 complete", L"", &lRet); + + break; + + case PE_PASS2_COMPLETE: + SendStatus(pSP); + + hr = pSP->SendData(L"pass 2 complete", L"", &lRet); + + break; + + case PE_EXIT: + SendStatus(pSP); + + hr = pSP->SendData(L"build complete", L"", &lRet); + + return TRUE; + break; + } + + if (hr) + { + BuildErrorRaw("\nBUILD: Communication with script engine failed: %x", hr); + } + + return (hr) ? TRUE : FALSE; +} + +const DWORD UPDATE_INTERVAL = 2 * 1000; // Update every 2 seconds + +//+--------------------------------------------------------------------------- +// +// Function: MTScriptThread +// +// Synopsis: Thread entrypoint. Initializes and then sits around +// handling various events. +// +// Arguments: [pv] -- Not used. +// +//---------------------------------------------------------------------------- + +DWORD WINAPI +MTScriptThread(LPVOID pv) +{ + HRESULT hr; + IScriptedProcess * pSP = NULL; + wchar_t achBuf[100]; + MSG msg; + DWORD dwRet; + CProcessSink cps; + BOOL fExit = FALSE; + int cRetries = 0; + + BuildMsg("Establishing connection with Script engine...\n"); + LogMsg("Establishing connection with Script engine...\n"); + + // Force Windows to create a message queue for this thread, since we will + // be communicated to via PostThreadMessage. + + PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); + + // If anything fails we just quit this thread and communication with + // the MTScript engine won't happen. + + hr = CoInitializeEx(NULL, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE); + if (hr) + { + BuildErrorRaw("BUILD: CoInitializeEx failed with %x\n", hr); + goto Cleanup; + } + + hr = S_FALSE; + + while (hr) + { + pSP = NULL; + IObjectDaemon *pIObjectDaemon; + hr = CoCreateInstance(CLSID_ObjectDaemon, NULL, CLSCTX_SERVER, + IID_IObjectDaemon, (LPVOID*)&pIObjectDaemon); + + if (!hr) + { + IDispatch *pIDispatch; + BSTR bstrProgID = SysAllocString(L"MTScript.Remote"); + BSTR bstrIdentity = SysAllocString(_wgetenv(L"__MTSCRIPT_ENV_IDENTITY")); + hr = pIObjectDaemon->OpenInterface(bstrIdentity, bstrProgID, (BOOL)FALSE, (IDispatch**)&pIDispatch); + if (!hr) + { + IConnectedMachine *pIConnectedMachine; + hr = pIDispatch->QueryInterface(IID_IConnectedMachine, (LPVOID*)&pIConnectedMachine); + if (!hr) + { + hr = pIConnectedMachine->CreateIScriptedProcess(GetCurrentProcessId(), (wchar_t *)_wgetenv(L"__MTSCRIPT_ENV_ID"), (IScriptedProcess **)&pSP); + pIConnectedMachine->Release(); + } + else + { + BuildMsg("CreateIScriptedProcess failed with %x.\n", hr); + LogMsg("CreateIScriptedProcess failed with %x.\n", hr); + } + pIDispatch->Release(); + } + else + { + BuildMsg("OpenInterface failed with %x.\n", hr); + LogMsg("OpenInterface failed with %x.\n", hr); + } + SysFreeString(bstrProgID); + SysFreeString(bstrIdentity); + pIObjectDaemon->Release(); + } + else + { + BuildMsg("CoCreateInstance failed with %x.\n", hr); + LogMsg("CoCreateInstance failed with %x.\n", hr); + } + + + if (!hr) + { + hr = pSP->SetProcessSink(&cps); + if (hr) + { + BuildMsg("SetProcessSink failed with %x.\n", hr); + LogMsg("SetProcessSink failed with %x.\n", hr); + } + } + + if (hr) + { + if (cRetries >= MAX_RETRIES) + { + BuildErrorRaw("BUILD: FATAL: Connection to script engine could not be established. (%x)\n", hr); + + goto Cleanup; + } + + if (pSP) + { + pSP->Release(); + pSP = NULL; + } + + BuildMsg("Connection to script engine failed with %x, retries=%d...\n", hr, cRetries); + LogMsg("Connection to script engine failed with %x, retries=%d...\n", hr, cRetries); + + Sleep(500); + + cRetries++; + } + } + + BuildMsg("Connection to script engine established...\n"); + LogMsg("Connection to script engine established...\r\n"); + + // Tell build.c that it can continue + SetEvent(g_hMTEvent); + + while (TRUE) + { + while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + if (HandleMessage(&msg, pSP)) + { + fExit = TRUE; + } + } + + if (fExit) + { + break; + } + + dwRet = MsgWaitForMultipleObjects(0, + NULL, + FALSE, + UPDATE_INTERVAL, + QS_ALLINPUT); + + if (dwRet == WAIT_OBJECT_0) + { + // A message is coming through on our message queue. Just loop + // around. + } + else if (dwRet == WAIT_TIMEOUT) + { + SendStatus(pSP); + } + else + { + // MWFMO failed. Just bail out. + break; + } + } + +Cleanup: + if (pSP) + { + pSP->SetProcessSink(NULL); + pSP->Release(); + } + + CoUninitialize(); + + if (hr) + { + g_hMTThread = NULL; + } + + SetEvent(g_hMTEvent); + + return 0; +} + +// *********************************************************************** +// +// CProcessSink implementation +// +// We hand this class to the MTScript engine so it can communicate back +// to us. +// +// *********************************************************************** + +CProcessSink::CProcessSink() +{ + _ulRefs = 1; +} + +HRESULT +CProcessSink::QueryInterface(REFIID riid, LPVOID *ppv) +{ + if (riid == IID_IUnknown || riid == IID_IScriptedProcessSink) + { + *ppv = (IScriptedProcessSink*)this; + } + else + { + *ppv = NULL; + return E_NOINTERFACE; + } + + ((IUnknown *)*ppv)->AddRef(); + + return S_OK; +} + +ULONG +CProcessSink::AddRef() +{ + return InterlockedIncrement((long*)&_ulRefs); +} + +ULONG +CProcessSink::Release() +{ + if (InterlockedDecrement((long*)&_ulRefs) == 0) + { + _ulRefs = 0xFF; + delete this; + return 0; + } + + return _ulRefs; +} + +//+--------------------------------------------------------------------------- +// +// Member: CProcessSink::RequestExit, public +// +// Synopsis: Called when the MTScript engine wants us to quit. If we don't, +// it will terminate us. +// +//---------------------------------------------------------------------------- + +HRESULT +CProcessSink::RequestExit() +{ + // There is no easy way to tell build.exe to abort. We'll just let + // MTScript terminate us. + + return S_OK; +} + +//+--------------------------------------------------------------------------- +// +// Member: CProcessSink::ReceiveData, public +// +// Synopsis: Called when the MTScript engine wants to send us a message. +// +// Arguments: [pszType] -- String giving the message +// [pszData] -- String giving data associated with the message. +// [plReturn] -- A place we can return a value back. +// +//---------------------------------------------------------------------------- + +HRESULT +CProcessSink::ReceiveData(wchar_t *pszType, wchar_t *pszData, long *plReturn) +{ + *plReturn = 0; + + if (wcscmp(pszType, L"resume") == 0) + { + SetEvent(g_hMTEvent); + } + else + { + *plReturn = -1; // Signals an error + } + + return S_OK; +} diff --git a/sdktools/buildscr.h b/sdktools/buildscr.h new file mode 100644 index 0000000..545f1fa --- /dev/null +++ b/sdktools/buildscr.h @@ -0,0 +1,35 @@ +//+--------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1992 - 1995 +// +// File: buildscr.h +// +// Contents: Header file defining the objects needed to interface with +// the MTScript engine. +// +//---------------------------------------------------------------------------- + +class CProcessSink : public IScriptedProcessSink +{ +public: + CProcessSink(); + ~CProcessSink() {} + + // IUnknown methods + + STDMETHOD(QueryInterface) (REFIID riid, LPVOID * ppv); + STDMETHOD_(ULONG, AddRef) (void); + STDMETHOD_(ULONG, Release) (void); + + // IScriptedProcessSink methods + + STDMETHOD(RequestExit)(); + STDMETHOD(ReceiveData)(wchar_t *pszType, + wchar_t *pszData, + long *plReturn); + +private: + ULONG _ulRefs; +}; + diff --git a/sdktools/buildsrc.c b/sdktools/buildsrc.c new file mode 100644 index 0000000..e7b1a4e --- /dev/null +++ b/sdktools/buildsrc.c @@ -0,0 +1,2177 @@ +//+--------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1992 - 1993. +// +// File: buildsrc.c +// +// Contents: Functions used to process SOURCES and DIRS files +// +// History: 16-May-89 SteveWo Created +// 26-Jul-94 LyleC Split out from buildmak.c +// +//---------------------------------------------------------------------------- + +#include "build.h" + +// +// Definitions used by the macro functions +// + +#define LPAREN '(' +#define RPAREN ')' + +// Legal character for a macro name. +#define MACRO_CHAR(ch) iscsym(ch) + +#define CMACROMAX 1000 // maximum unique macros per sources/dirs file + +typedef struct _MACRO { + LPSTR pszValue; + UCHAR szName[1]; +} MACRO; + + +MACRO *apMacro[CMACROMAX]; +UINT cMacro = 0; + +LPSTR *ppCurrentDirsFileName; +DWORD StartTime; + +#define SOURCES_TARGETNAME 0 +#define SOURCES_TARGETPATH 1 +#define SOURCES_TARGETPATHLIB 2 +#define SOURCES_TARGETTYPE 3 +#define SOURCES_TARGETEXT 4 +#define SOURCES_INCLUDES 5 +#define SOURCES_NTTEST 6 +#define SOURCES_UMTYPE 7 +#define SOURCES_UMTEST 8 +#define SOURCES_OPTIONAL_UMTEST 9 +#define SOURCES_UMAPPL 10 +#define SOURCES_UMAPPLEXT 11 +#define SOURCES_NTTARGETFILE0 12 +#define SOURCES_NTTARGETFILES 13 +#define SOURCES_PRECOMPILED_INCLUDE 14 +#define SOURCES_PRECOMPILED_PCH 15 +#define SOURCES_PRECOMPILED_OBJ 16 +#define SOURCES_PRECOMPILED_TARGET 17 +#define SOURCES_CHICAGO_PRODUCT 18 +#define SOURCES_CONDITIONAL_INCLUDES 19 +#define SOURCES_SYNCHRONIZE_BLOCK 20 +#define SOURCES_SYNCHRONIZE_DRAIN 21 +#define SOURCES_PASS0_SOURCEDIR 22 +#define SOURCES_PASS0_HEADERDIR 23 +#define SOURCES_MIDL_UUIDDIR 24 +#define SOURCES_PASS0_CLIENTDIR 25 +#define SOURCES_PASS0_SERVERDIR 26 +#define SOURCES_IDLTYPE 27 +#define SOURCES_SOURCES_OPTIONS 28 +#define SOURCES_MFC_INCLUDES 29 +#define SOURCES_SDK_LIB_DEST 30 +#define SOURCES_DDK_LIB_DEST 31 +#define SOURCES_SDK_INC_PATH 32 +#define SOURCES_CRT_INC_PATH 33 +#define SOURCES_OAK_INC_PATH 34 +#define SOURCES_DDK_INC_PATH 35 +#define SOURCES_WDM_INC_PATH 36 +#define SOURCES_PRIVATE_INC_PATH 37 +#define SOURCES_CHECKED_ALT_DIR 38 +#define SOURCES_PROJECT_NAME 39 +#define SOURCES_PASS0_PUBLISH 40 + +LPSTR RelevantSourcesMacros[] = { + "TARGETNAME", + "TARGETPATH", + "TARGETPATHLIB", + "TARGETTYPE", + "TARGETEXT", + "INCLUDES", + "NTTEST", + "UMTYPE", + "UMTEST", + "OPTIONAL_UMTEST", + "UMAPPL", + "UMAPPLEXT", + "NTTARGETFILE0", + "NTTARGETFILES", + "PRECOMPILED_INCLUDE", + "PRECOMPILED_PCH", + "PRECOMPILED_OBJ", + "PRECOMPILED_TARGET", + "CHICAGO_PRODUCT", + "CONDITIONAL_INCLUDES", + "SYNCHRONIZE_BLOCK", + "SYNCHRONIZE_DRAIN", + "PASS0_SOURCEDIR", + "PASS0_HEADERDIR", + "MIDL_UUIDDIR", + "PASS0_CLIENTDIR", + "PASS0_SERVERDIR", + "IDL_TYPE", + "SOURCES_OPTIONS", + "MFC_INCLUDES", + "SDK_LIB_DEST", + "DDK_LIB_DEST", + "SDK_INC_PATH", + "CRT_INC_PATH", + "OAK_INC_PATH", + "DDK_INC_PATH", + "WDM_INC_PATH", + "PRIVATE_INC_PATH", + "CHECKED_ALT_DIR", + "_PROJECT_", + "PASS0_PUBLISH", + NULL +}; + +#define SOURCES_MAX \ + (sizeof(RelevantSourcesMacros)/sizeof(RelevantSourcesMacros[0]) - 1) + +VOID +MarkDirNames(PDIRREC DirDB, LPSTR TextLine, BOOL Required); + +//+--------------------------------------------------------------------------- +// +// Function: CompressBlanks +// +// Synopsis: Compress multiple blank characters out of macro value, in +// place. +// +// Arguments: [psrc] -- String to compress +// +// Notes: Note that tabs, CRs, continuation lines (and their line +// breaks) have already been replaced with blanks. +// +//---------------------------------------------------------------------------- + +VOID +CompressBlanks(LPSTR psrc) +{ + LPSTR pdst = psrc; + + while (*psrc == ' ') { + psrc++; // skip leading macro value blanks + } + while (*psrc != '\0') { + if (*psrc == '#') { // stop at comment + break; + } + if ((*pdst++ = *psrc++) == ' ') { + while (*psrc == ' ') { + psrc++; // skip multiple blanks + } + } + } + *pdst = '\0'; // terminate the compressed copy + if (*--pdst == ' ') { + *pdst = '\0'; // trim trailing macro value blanks + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: GetBaseDir +// +// Synopsis: Return the value of BASEDIR, the base NT directory, if +// appropriate. +// +// Arguments: [pname] -- path to split +// +//---------------------------------------------------------------------------- + +LPSTR +GetBaseDir(LPSTR pname) +{ + if (_stricmp("BASEDIR", pname) == 0) { + return(NtRoot); + } + return(NULL); +} + + +//+--------------------------------------------------------------------------- +// +// Function: FindMacro +// +// Synopsis: Returns the value of a given macro by name. +// +// Arguments: [pszName] -- Name of macro who's value is desired. +// +// Returns: String containing the value of the macro +// +//---------------------------------------------------------------------------- + +LPSTR +FindMacro(LPSTR pszName) +{ + MACRO **ppm; + + for (ppm = apMacro; ppm < &apMacro[cMacro]; ppm++) { + if (_stricmp(pszName, (*ppm)->szName) == 0) { + return((*ppm)->pszValue); + } + } + return(NULL); +} + + +//+--------------------------------------------------------------------------- +// +// Function: SaveMacro +// +// Synopsis: Save the value of a macro +// +// Arguments: [pszName] -- Name of macro to save +// [pszValue] -- Value of macro +// +// Notes: A new string must be allocated and initialized prior to +// freeing the old string when updating a macro value. +// +//---------------------------------------------------------------------------- + +VOID +SaveMacro(LPSTR pszName, LPSTR pszValue) +{ + MACRO **ppm; + + for (ppm = apMacro; ppm < &apMacro[cMacro]; ppm++) { + if (_stricmp(pszName, (*ppm)->szName) == 0) { + break; + } + } + if (ppm == &apMacro[CMACROMAX]) { + BuildError("Macro table full, ignoring: %s = %s\n", pszName, pszValue); + return; + } + if (ppm == &apMacro[cMacro]) { + cMacro++; + AllocMem(sizeof(MACRO) + strlen(pszName), ppm, MT_MACRO); + strcpy((*ppm)->szName, pszName); + (*ppm)->pszValue = NULL; + } + MakeMacroString(&(*ppm)->pszValue, pszValue); + if (DEBUG_1) { + BuildMsg( + "SaveMacro(%s = %s)\n", + (*ppm)->szName, + (*ppm)->pszValue == NULL? "NULL" : (*ppm)->pszValue); + } + if ((*ppm)->pszValue == NULL) { + FreeMem(ppm, MT_MACRO); + *ppm = apMacro[--cMacro]; + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: FreeMacros +// +// Synopsis: Free all macros +// +// Arguments: (none) +// +//---------------------------------------------------------------------------- + +VOID +FreeMacros(VOID) +{ + MACRO **ppm; + + for (ppm = apMacro; ppm < &apMacro[cMacro]; ppm++) { + FreeString(&(*ppm)->pszValue, MT_DIRSTRING); + FreeMem(ppm, MT_MACRO); + assert(*ppm == NULL); + } + cMacro = 0; +} + + +//+--------------------------------------------------------------------------- +// +// Function: SplitMacro +// +// Synopsis: Take a string containing "MACRONAME = VALUE" and return +// the target and value. +// +// Arguments: [pline] -- String to split and target return. +// +// Returns: Value of macro. +// +//---------------------------------------------------------------------------- + +LPSTR +SplitMacro(LPSTR *pszTarget) +{ + LPSTR pvalue, p, pline; + + pvalue = NULL; + pline = *pszTarget; + + // Quickly reject comments and ! directives. + if (*pline == '#' || *pline == '!') { + return NULL; + } + + if ((p = strchr(pline, '=')) != NULL) { + pvalue = p + 1; // point past old '=' + while (p > pline && p[-1] == ' ') { + p--; // point to start of trailing blanks + } + + // Check for missing target. + if (p == pline) { + return NULL; + } + + *p = '\0'; // trim trailing blanks & '=' + + // Perform macro substitution on target. + *pszTarget = NULL; + if (!MakeMacroString(pszTarget, pline)) { + return NULL; + } + + // Validate target name. If must be a non-empty string of + // valid macro name characters. + if (**pszTarget == 0) { + FreeString(pszTarget, MT_DIRSTRING); + return NULL; + } + for (p = *pszTarget; *p != 0; p++) { + if (!MACRO_CHAR(*p)) { + FreeString(pszTarget, MT_DIRSTRING); + return NULL; + } + } + + CompressBlanks(pvalue); + } + return(pvalue); +} + + +//+--------------------------------------------------------------------------- +// +// Function: SubstituteString +// +// Synopsis: Perform any macro substitution. This code was copied from the +// nmake source. +// +// Arguments: +// +// Returns: +// +// Notes: +// +//---------------------------------------------------------------------------- + +void +SubstituteString( + char **result, + char **name, + char **dest, + char **end, + char *source, + unsigned *length + ) +{ + +#define ESCH '^' + + char *oldString, *newString; + char *pEq, *pPar, *t; + char *s; + unsigned i; + + ++*name; + for (pEq = *name; *pEq && *pEq != '='; pEq++) + if (*pEq == ESCH) + pEq++; + + // Did we find the '=' sign? + if (*pEq != '=') + printf("Error1\n"); + + // Did the user forget the initial string? + if (pEq == *name) + printf("Error2\n"); + + for (pPar = pEq; *pPar && *pPar != ')'; pPar++) + if (*pPar == ESCH) + pPar++; + + if (*pPar != ')') + printf("Error3\n"); + + oldString = (char *)malloc((UINT)((pEq - *name) + 1)); + if (!oldString) { + BuildError("(Fatal Error) Out Of Memory: SubstituteString()\n"); + exit(16); + } + for (s = oldString, t = *name; *t != '='; *s++ = *t++) + if (*t == ESCH) + ++t; + + *s = '\0'; + i = strlen(oldString); + newString = (char *)malloc((UINT)(pPar - pEq)); + if (!newString) { + BuildError("(Fatal Error) Out Of Memory: SubstituteString()\n"); + exit(16); + } + for (s = newString, t++; *t != ')'; *s++ = *t++) + if (*t == ESCH) + ++t; + + *s = '\0'; + *name = pPar + 1; + while (*source) { + if ((*source == *oldString) // check for match + && !strncmp(source, oldString, i)) { // copy new in for + for (s = newString; *s; *(*dest)++ = *s++) // old string + if (*dest == *end) { + *result = realloc(*result, *length + 100); + if (!*result) { + BuildError("(Fatal Error) Out Of Memory: SubstituteString()\n"); + exit(16); + } + *dest = *result + *length; + *length += 100; + *end = *result + *length; + } + source += i; + continue; + } + if (*dest == *end) { + *result = realloc(*result, *length + 100); + if (!*result) { + BuildError("(Fatal Error) Out Of Memory: SubstituteString()\n"); + exit(16); + } + *dest = *result + *length; + *length += 100; + *end = *result + *length; + } + *(*dest)++ = *source++; // else copy 1 char + } + free(oldString); + free(newString); +} + + +//+--------------------------------------------------------------------------- +// +// Function: MakeMacroString +// +// Synopsis: Take a string, and expand any macros in it. (e.g. +// "$(BASEDIR)\foobar\myfile.lib" is expanded to +// "f:\nt\private\foobar\myfile.lib" if $(BASEDIR) has a value of +// "f:\nt\private". +// +// Arguments: [pp] -- Output string +// [psrc] -- Input string +// +// Returns: +// +// Notes: Any previous string value in [pp] is freed before updating it. +// +//---------------------------------------------------------------------------- + +char MMSBuffer[64*1024]; +BOOL +MakeMacroString(LPSTR *pp, LPSTR psrc) +{ + LPSTR pname, p2, pdst, p3; + int cb; + char chTerminator; + int cNameChars; + int cChars; + + pdst = MMSBuffer; + cb = strlen(psrc); + if (cb > sizeof(MMSBuffer) - 1) { + BuildError( + "(Fatal Error) Buffer overflow: MakeMacroString(%s)\n", + psrc); + exit(16); + } + while ((pname = strchr(psrc, '$')) != NULL && + ((pname[1] == LPAREN && + (p2 = strchr(pname, RPAREN)) != NULL) || + (MACRO_CHAR(pname[1]) && + !MACRO_CHAR(pname[2])))) { + + LPSTR pszvalue; + + // Handle one-character non-paren macro usage. + if (pname[1] == LPAREN) { + // Initialize cNameChars with the number of chars to + // skip to get to the first name character. + cNameChars = 2; + } else { + p2 = pname + 2; + cNameChars = 1; + } + + chTerminator = *p2; + *pname = *p2 = '\0'; + + // copy up to macro name + cChars = strlen(psrc); + memcpy(pdst, psrc, cChars + 1); + psrc += cChars; + pdst += cChars; + + *pname = '$'; + pname += cNameChars; + cNameChars += strlen(pname) + (chTerminator == RPAREN ? 1 : 0); + + p3 = NULL; + if (chTerminator == RPAREN && + (p3 = strchr(pname, ':')) != NULL) { + // macro substitution exists. ie: $(foo:old=new) + *p3 = '\0'; + } + + if ((pszvalue = FindMacro(pname)) == NULL && + (pszvalue = getenv(pname)) == NULL && + (pszvalue = GetBaseDir(pname)) == NULL) { + + pszvalue = ""; // can't find macro name -- ignore it + } + + if (p3) { + char *pNew = malloc(10); + char *pResult = pNew; + char *pEnd = pNew+10; + unsigned Len = 10; + + if (!pNew) { + BuildError("(Fatal Error) Internal buffer overflow: MakeMacroString(%s[%s = %s]%s)\n", + MMSBuffer, + pname, + pszvalue, + p2 + 1); + exit(16); + } + + *p3 = ':'; + *p2=RPAREN; + SubstituteString(&pResult, &p3, &pNew, &pEnd, pszvalue, &Len); + *pNew = '\0'; + *p2='\0'; + pszvalue = pResult; + } + + cb += strlen(pszvalue) - cNameChars; + assert(cb >= 0); + if (cb > sizeof(MMSBuffer) - 1) { + BuildError( + "(Fatal Error) Internal buffer overflow: MakeMacroString(%s[%s = %s]%s)\n", + MMSBuffer, + pname, + pszvalue, + p2 + 1); + exit(16); + } + strcpy(pdst, pszvalue); // copy expanded value + + if (p3) { + free(pszvalue); + } + + pdst += strlen(pdst); + *p2 = chTerminator; + psrc += cNameChars; + } + strcpy(pdst, psrc); // copy rest of string + if (pdst != MMSBuffer) { + CompressBlanks(MMSBuffer); + } + p2 = *pp; + *pp = NULL; + if (MMSBuffer[0] != '\0') { + MakeString(pp, MMSBuffer, TRUE, MT_DIRSTRING); + } + if (p2 != NULL) { + FreeMem(&p2, MT_DIRSTRING); + } + + return(MMSBuffer[0] != '\0'); +} + + +//+--------------------------------------------------------------------------- +// +// Function: SetMacroString +// +// Synopsis: If the two macro names are the same, store the value in that +// macro +// +// Arguments: [pMacro1] -- Name of first macro +// [pMacro2] -- Name of second macro +// [pValue] -- Unexpanded value to store. +// [ppValue] -- Expanded value of macro. +// +// Returns: BOOL +// +//---------------------------------------------------------------------------- + +BOOL +SetMacroString(LPSTR pMacro1, LPSTR pMacro2, LPSTR pValue, LPSTR *ppValue) +{ + if (_stricmp(pMacro1, pMacro2) == 0) { + MakeMacroString(ppValue, pValue); + return(TRUE); // return TRUE even if MakeMacroString stored a NULL + } + return(FALSE); +} + + +//+--------------------------------------------------------------------------- +// +// Function: SplitToken +// +// Synopsis: Split the string at the given separator character or space. +// +// Arguments: [pbuf] -- First part of split string returned here. +// [chsep] -- Separator character. +// [ppstr] -- Source string to split. Becomes the second half. +// +// Returns: TRUE if the split was successful. FALSE if it wasn't split. +// +// Notes: If *ppstr = "path\filename" and chsep = '\' on input, then +// pbuf = "path" and *ppstr = "\filename" on output. +// +//---------------------------------------------------------------------------- + +BOOL +SplitToken(LPSTR pbuf, char chsep, LPSTR *ppstr) +{ + LPSTR psrc, pdst; + + psrc = *ppstr; + pdst = pbuf; + //BuildError("SplitToken('%c', '%s') ==> ", chsep, psrc); + while (*psrc == chsep || *psrc == ' ') { + psrc++; + } + while (*psrc != '\0' && *psrc != chsep && *psrc != ' ') { + *pdst = *psrc++; + if (*pdst == '/') { + *pdst = '\\'; + } + pdst++; + } + *pdst = '\0'; + *ppstr = psrc; + //BuildErrorRaw("('%s', '%s')\n", psrc, pbuf); + return(pdst != pbuf); +} + + +// Project-relative sources share the normal file database and dependency scanner. +// @/ paths are relative to BASEDIR; other nested paths are relative to SOURCES. +static BOOL +AddProjectSource(DIRREC *pdr, DIRSUP *pds, int i, LPSTR token) +{ + char input[DB_MAX_PATH_LENGTH * 2]; + char resolved[DB_MAX_PATH_LENGTH * 2]; + char stem[DB_MAX_PATH_LENGTH]; + char *part, *ext; + const char *relative; + DWORD length; + unsigned __int64 hash = 14695981039346656037ui64; + FILEREC *file; + SOURCEREC *record, *other; + size_t n; + int group; + + if (token[0] == '@' && (token[1] == '/' || token[1] == '\\')) { + if (snprintf(input, sizeof(input), "%s\\%s", NtRoot, token + 2) >= sizeof(input)) { + BuildError("%s: Source path too long: %s\n", pdr->Name, token); + exit(16); + } + } else { + if (snprintf(input, sizeof(input), "%s\\%s", pdr->Name, token) >= sizeof(input)) { + BuildError("%s: Source path too long: %s\n", pdr->Name, token); + exit(16); + } + } + for (part = input; *part; ++part) { + if (*part == '/') *part = '\\'; + } + length = GetFullPathNameA(input, sizeof(resolved), resolved, NULL); + if (!length || length >= sizeof(resolved)) { + BuildError("%s: Invalid source path: %s\n", pdr->Name, token); + exit(16); + } + n = strlen(NtRoot); + if (length >= DB_MAX_PATH_LENGTH - 1) { + BuildError("%s: Source exceeds build database path capacity: %s\n", pdr->Name, token); + exit(16); + } + if (_strnicmp(resolved, NtRoot, n) || resolved[n] != '\\') { + BuildError("%s: Source escapes project root: %s\n", pdr->Name, token); + exit(16); + } + // The build database stores normalized lowercase paths. + for (part = resolved; *part; ++part) { + if (*part >= 'A' && *part <= 'Z') *part += 'a' - 'A'; + } + relative = resolved + n + 1; + for (part = (char *)relative; *part; ++part) { + hash = (hash ^ (unsigned char)*part) * 1099511628211ui64; + } + part = strrchr(resolved, '\\'); + part = part ? part + 1 : resolved; + ext = strrchr(part, '.'); + if (!ext || ext == part || strlen(part) >= 120) { + BuildError("%s: Invalid source name: %s\n", pdr->Name, token); + exit(16); + } + if (snprintf(stem, sizeof(stem), "%.*s_%016I64x", (int)(ext-part), part, hash) < 0) { + BuildError("%s: Unable to name source object: %s\n", pdr->Name, token); + exit(16); + } + file = FindSourceFileDB(pdr, resolved, NULL); + if (!file) { + BuildError("%s: Missing project source: %s\n", pdr->Name, token); + exit(16); + } + for (group = 0; group <= MAX_TARGET_MACHINES; ++group) { + for (other = pds->psrSourcesList[group]; other; other = other->psrNext) { + if (other->ObjectStem && !_stricmp(other->ObjectStem, stem) && + _stricmp(other->ProjectSource, resolved)) { + BuildError("%s: Source object identity collision: %s\n", pdr->Name, token); + exit(16); + } + } + } + record = InsertSourceDB(&pds->psrSourcesList[i], file, 0, SOURCEDB_SOURCES_LIST); + if (record->ProjectSource && _stricmp(record->ProjectSource, resolved)) { + BuildError("%s: Conflicting source identity: %s\n", pdr->Name, token); + exit(16); + } + if (!record->ProjectSource) { + char objectSource[DB_MAX_PATH_LENGTH]; + MakeString(&record->ProjectSource, resolved, TRUE, MT_DIRSTRING); + MakeString(&record->ObjectStem, stem, FALSE, MT_DIRSTRING); + if (snprintf(objectSource, sizeof(objectSource), "%s%s", stem, ext) < 0 || + strlen(stem) + strlen(ext) >= sizeof(objectSource)) { + BuildError("%s: Source object name too long: %s\n", pdr->Name, token); + exit(16); + } + MakeString(&record->ObjectSourceName, objectSource, FALSE, MT_DIRSTRING); + } + file->FileFlags |= FILEDB_OBJECTS_LIST; + return TRUE; +} + +//+--------------------------------------------------------------------------- +// +// Function: CrackSources +// +// Synopsis: Parse the SOURCES= line in a sources file and adds those source +// files to the list of sources in the DIRREC struct. +// +// Arguments: [pdr] -- Directory record +// [pds] -- Supplemental directory information +// [i] -- Which platform we're parsing +// +//---------------------------------------------------------------------------- + +VOID +CrackSources( + DIRREC *pdr, + DIRSUP *pds, + int i) + +{ + + LPSTR pszsubdir, plist; + LPSTR pszfile, pszpath; + FILEREC *pfr; + DIRREC *pdrAssociate; + DIRREC *pdrParent; + DIRREC *pdrMachine; + DIRREC *pdrParentMachine; + DIRREC *pdrTarget; + DIRREC **ppdr; + LPSTR pszSources; + char path[DB_MAX_PATH_LENGTH]; + TARGET_MACHINE_INFO *pMachine; + + if (i == 0) { + pMachine = TargetMachines[0]; + pszSources = "SOURCES"; + + } else { + pMachine = PossibleTargetMachines[i - 1]; + pszSources = pMachine->SourceVariable; + } + + pdrAssociate = pdrParent = pdrMachine = pdrParentMachine = pdrTarget = NULL; + plist = pds->SourcesVariables[i]; + while (SplitToken(path, ' ', &plist)) { + UCHAR SubDirMask, SrcFlags; + char *separator = strpbrk(path, "\\/"); + BOOL legacyMachine = FALSE; + if (separator) { + size_t prefix = (size_t)(separator - path); + legacyMachine = + (prefix == 4 && !_strnicmp(path, "i386", prefix)) || + (prefix == 5 && !_strnicmp(path, "amd64", prefix)) || + (prefix == 4 && !_strnicmp(path, "ia64", prefix)) || + (prefix == 5 && !_strnicmp(path, "arm64", prefix)) || + (strlen(pMachine->AssociateDirectory) == prefix && + !_strnicmp(path, pMachine->AssociateDirectory, prefix)); + } + if (path[0] == '@' || (separator && + !(separator == path + 2 && path[0] == '.' && path[1] == '.' && + !strpbrk(separator + 1, "\\/")) && + !(legacyMachine && !strpbrk(separator + 1, "\\/")))) { + AddProjectSource(pdr, pds, i, path); + continue; + } + + SubDirMask = 0; + ppdr = &pdr; // assume current directory + pszsubdir = path; + if (pszsubdir[0] == '.' && pszsubdir[1] == '\\') { + BuildError( + "%s: Ignoring current directory prefix in %s= entry: %s\n", + pdr->Name, + pszSources, + path); + pszsubdir += 2; + } + + if (pszsubdir[0] == '.' && + pszsubdir[1] == '.' && + pszsubdir[2] == '\\') { + + SubDirMask = TMIDIR_PARENT; + ppdr = &pdrParent; // assume parent directory + pszsubdir += 3; + } + + pszpath = path; + pszfile = strchr(pszsubdir, '\\'); + if (pszfile == NULL) { + pszfile = pszsubdir; + + } else { + LPSTR pszSecondSlash; + LPSTR pszAssociateDir; + LPSTR pszMachineDir; + + // Check for second slash and handle $O\. If there is + // no second slash, check for a machine specific directory name. + // Second slashes are not legal if there's already been + // a '..'. + + if ((SubDirMask & TMIDIR_PARENT) == 0) { + pszSecondSlash = strchr(pszfile + 1, '\\'); + if (pszSecondSlash != NULL) { + pszfile = pszSecondSlash; + } + + } else { + pszSecondSlash = NULL; + } + + + *pszfile = '\0'; + if (pszSecondSlash != NULL) { + pszMachineDir = pMachine->ObjectDirectory[iObjectDir]; + pszAssociateDir = pszMachineDir; + + } else { + pszMachineDir = pMachine->SourceDirectory; + pszAssociateDir = pMachine->AssociateDirectory; + } + + if (((_stricmp(pszsubdir, pszAssociateDir) != 0) && + (_stricmp(pszsubdir, pszMachineDir) != 0)) || + strchr(pszfile + 1, '\\') != NULL) { + + *pszfile = '\\'; + BuildError( + "%s: Ignoring invalid directory prefix in %s= entry: %s\n", + pdr->Name, + pszSources, + path); + + // + + pszpath = strrchr(path, '\\'); + assert(pszpath != NULL); + pszpath++; + SubDirMask = 0; + ppdr = &pdr; // default to current direcory + + } else { + SubDirMask |= pMachine->SourceSubDirMask; + *pszfile++ = '\\'; + if (SubDirMask & TMIDIR_PARENT) { + ppdr = &pdrParentMachine; + + } else if (pszSecondSlash != NULL) { + // Must have matched $O. + ppdr = &pdrTarget; + + } else { + if (_stricmp(pszsubdir, pszMachineDir) != 0) { + ppdr = &pdrMachine; + + } else { + ppdr = &pdrAssociate; + } + } + } + } + +NewDirectory: + if (*ppdr == NULL) { + pfr = FindSourceFileDB(pdr, pszpath, ppdr); + + } else { + pfr = LookupFileDB(*ppdr, pszfile); + } + + SrcFlags = SOURCEDB_SOURCES_LIST; + if ((pfr == NULL) && !fPassZero) { + if (fDebug) { + BuildError("%s: Missing source file: %s\n", pdr->Name, path); + } + if (*ppdr == NULL) { + if (fDebug || pszpath == path) { + BuildError( + "%s: Directory does not exist: %s\n", + pdr->Name, + path); + } + + // Probably an error in the subordinate sources file. + // since old versions of build managed to get these entries + // into the objects lists, we have to do the same... + // + // If ..\ prefix exists, strip it off and try again. + // Else try again with the current directory. + + if (SubDirMask & TMIDIR_PARENT) { + SubDirMask &= ~TMIDIR_PARENT; // strip off "..\\" + } + else { + SubDirMask = 0; // use current direcory + } + if (SubDirMask == 0) { + ppdr = &pdr; // current direcory + pszpath = pszfile; + } + else { + ppdr = &pdrMachine; // machine sub dir + pszpath = pszsubdir; + } + goto NewDirectory; + } + pfr = InsertFileDB(*ppdr, pszfile, 0, 0, FILEDB_FILE_MISSING); + if (pfr == NULL) { + BuildError( + "%s: Ignoring invalid %s= entry: %s\n", + pdr->Name, + pszSources, + path); + } + } + if (pfr != NULL) { + AssertFile(pfr); + if (SubDirMask == 0) { + pfr->FileFlags |= FILEDB_OBJECTS_LIST; + } + if (pfr->FileFlags & FILEDB_FILE_MISSING) { + SrcFlags |= SOURCEDB_FILE_MISSING; + } + InsertSourceDB(&pds->psrSourcesList[i], pfr, SubDirMask, SrcFlags); + } + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: SaveUserTests +// +// Synopsis: Save the value of the UMTEST macro into the DIRREC struct. +// +// Arguments: [DirDB] -- Dir struct to save into +// [TextLine] -- String from UMTEST= line in sources file +// +//---------------------------------------------------------------------------- + +VOID +SaveUserTests( + PDIRREC DirDB, + LPSTR TextLine) +{ + UINT i; + BOOL fSave = FALSE; + char name[DB_MAX_PATH_LENGTH]; + char buf[512]; + + buf[0] = '\0'; + if (DirDB->UserTests != NULL) { + strcpy(buf, DirDB->UserTests); + } + CopyString(TextLine, TextLine, TRUE); + while (SplitToken(name, '*', &TextLine)) { + for (i = 0; i < CountOptionalDirs; i++) { + if (!strcmp(name, OptionalDirs[i])) { + if (buf[0] != '\0') { + strcat(buf, "*"); + DirDB->DirFlags |= DIRDB_FORCELINK; // multiple targets + } + strcat(buf, name); + fSave = TRUE; + break; + } + } + } + if (fSave) { + MakeMacroString(&DirDB->UserTests, buf); + DirDB->DirFlags |= DIRDB_LINKNEEDED; + } +} + +//+--------------------------------------------------------------------------- +// +// Function: ProcessSourcesFileLine +// +// Synopsis: Given a line from a sources file, do the right thing. +// +// Arguments: [DirDB] -- Directory containing sources file +// [pds] -- Supplementary info on directory +// [TextLine] -- Line to process +// +// Returns: void +// +//---------------------------------------------------------------------------- + +void +ProcessSourcesFileLine( + DIRREC *DirDB, // Current Directory record + DIRSUP *pds, // Supplemental Directory record + LPSTR TextLine, // Line to process + int iTarget // Index into target machine array. + ) +{ + LPSTR MacroName, p1; + UINT i, iMacro; + char path[DB_MAX_PATH_LENGTH]; + BOOL fCleanNTTargetFile0 = FALSE; + LPSTR pValue; // right side of equal sign + + pValue = SplitMacro(&TextLine); + if (pValue == NULL) { + return; + } + + // Note: TextLine is now the left side of the equal sign. See if it's interesting. + + // + // This sets pds->SourcesVariables[0] to the value of SOURCES= if + // the current line is SOURCES=... + // + if (SetMacroString( + "SOURCES", + TextLine, + pValue, + &pds->SourcesVariables[0])) { + + DirDB->DirFlags |= DIRDB_SOURCES_SET; + goto SaveAndFreeMacro; + } + else { + for (i = 0; i < MAX_TARGET_MACHINES; i++) { + // + // This sets pds->SourcesVariables[0] to the value of + // PLAT_SOURCES= if the current line is PLAT_SOURCES=... + // + if (SetMacroString( + PossibleTargetMachines[i]->SourceVariable, + TextLine, + pValue, + &pds->SourcesVariables[i + 1])) { + + DirDB->DirFlags |= DIRDB_SOURCES_SET; + goto SaveAndFreeMacro; + } + } + } + + // Not a SOURCES or xxx_SOURCES macro, check against all the other interesting + // macro names. + + iMacro = 0; + + while ((MacroName = RelevantSourcesMacros[iMacro]) != NULL) { + if (_stricmp(TextLine, MacroName) == 0) { + break; + } + iMacro++; + } + if (MacroName != NULL) { // if macro name found in list + switch (iMacro) { + case SOURCES_TARGETNAME: + MakeMacroString(&DirDB->TargetName, pValue); + break; + + case SOURCES_TARGETPATH: + if (strcmp(pValue, "obj") == 0) { + pValue = pszObjDir; + } + MakeMacroString(&DirDB->TargetPath, pValue); + if (DirDB->TargetPath != NULL) { + CreateBuildDirectory(DirDB->TargetPath); + for (i = 0; i < CountTargetMachines; i++) { + p1 = TargetMachines[i]->ObjectDirectory[iObjectDir]; + assert(strncmp(pszObjDirSlash, p1, strlen(pszObjDirSlash)) == 0); + p1 += strlen(pszObjDirSlash); + sprintf(path, "%s\\%s", DirDB->TargetPath, p1); + CreateBuildDirectory(path); + } + } + break; + + case SOURCES_TARGETPATHLIB: + if (strcmp(pValue, "obj") == 0) { + pValue = pszObjDir; + } + MakeMacroString(&DirDB->TargetPathLib, pValue); + if (DirDB->TargetPathLib != NULL) { + CreateBuildDirectory(DirDB->TargetPathLib); + for (i = 0; i < CountTargetMachines; i++) { + p1 = TargetMachines[i]->ObjectDirectory[iObjectDir]; + assert(strncmp(pszObjDirSlash, p1, strlen(pszObjDirSlash)) == 0); + p1 += strlen(pszObjDirSlash); + sprintf(path, "%s\\%s", DirDB->TargetPathLib, p1); + CreateBuildDirectory(path); + } + } + break; + + case SOURCES_TARGETTYPE: + if (!_stricmp(pValue, "PROGRAM") || !_stricmp(pValue, "PROGLIB")) { + MakeMacroString(&DirDB->TargetExt, ".exe"); + DirDB->DirFlags |= DIRDB_LINKNEEDED; + } else if (!_stricmp(pValue, "OBJLIB")) { + MakeMacroString(&DirDB->TargetExt, ".olb"); + DirDB->DirFlags |= DIRDB_LINKNEEDED; + } else if (!_stricmp(pValue, "DRIVER") || !_stricmp(pValue, "MINIPORT")) { + MakeMacroString(&DirDB->TargetExt, ".sys"); + DirDB->DirFlags |= DIRDB_LINKNEEDED; + } else if (!_stricmp(pValue, "GDI_DRIVER")) { + MakeMacroString(&DirDB->TargetExt, ".dll"); + DirDB->DirFlags |= DIRDB_LINKNEEDED; + } else if (!_stricmp(pValue, "EXPORT_DRIVER")) { + MakeMacroString(&DirDB->TargetExt, ".sys"); + DirDB->DirFlags |= DIRDB_LINKNEEDED; + DirDB->DirFlags |= DIRDB_DLLTARGET; + } else if (!_stricmp(pValue, "DYNLINK") || !_stricmp(pValue, "HAL")) { + MakeMacroString(&DirDB->TargetExt, ".dll"); + DirDB->DirFlags |= DIRDB_LINKNEEDED; + DirDB->DirFlags |= DIRDB_DLLTARGET; + } else if ((!_stricmp(pValue, "LIBRARY")) || (!_stricmp(pValue, "DRIVER_LIBRARY"))) { + MakeMacroString(&DirDB->TargetExt, ".lib"); + DirDB->DirFlags &= ~DIRDB_LINKNEEDED; + } else if (!_stricmp(pValue, "UMAPPL_NOLIB")) { + DirDB->DirFlags &= ~DIRDB_LINKNEEDED; + } else if (!_stricmp(pValue, "NOTARGET")) { + // + // Used to indicate no target for a directory, + // e.g. if only pass0 files are generated + pds->fNoTarget = TRUE; + if (!fQuicky || (fQuickZero && fFirstScan)) { + DirDB->DirFlags |= DIRDB_PASS0NEEDED; + } + } else { + BuildError( "Unsupported TARGETTYPE value - %s\n", pValue); + } + break; + + case SOURCES_TARGETEXT: + { + char TargetExt[_MAX_EXT] = "."; + strcat(TargetExt, pValue); + MakeMacroString(&DirDB->TargetExt, TargetExt); + } + break; + + case SOURCES_INCLUDES: + MakeMacroString(&pds->LocalIncludePath, pValue); + if (DEBUG_1) { + BuildMsg( + " Found local INCLUDES=%s\n", + pds->LocalIncludePath); + } + break; + + case SOURCES_MFC_INCLUDES: + // MFC_INCLUDES/SDK_INC/CRT_INC/OAK_INC really can't be changed + // in the sources file (yet) since we've already processed the + // system includes. Lay the groundwork for now. + MakeMacroString((char **)&pszIncMfc, pValue); + break; + + case SOURCES_SDK_LIB_DEST: + MakeMacroString((char **)&pszSdkLibDest, pValue); + break; + + case SOURCES_DDK_LIB_DEST: + MakeMacroString((char **)&pszDdkLibDest, pValue); + break; + + case SOURCES_SDK_INC_PATH: + MakeMacroString((char **)&pszIncSdk, pValue); + break; + + case SOURCES_CRT_INC_PATH: + MakeMacroString((char **)&pszIncCrt, pValue); + break; + + case SOURCES_OAK_INC_PATH: + MakeMacroString((char **)&pszIncOak, pValue); + break; + + case SOURCES_DDK_INC_PATH: + MakeMacroString((char **)&pszIncDdk, pValue); + break; + + case SOURCES_WDM_INC_PATH: + MakeMacroString((char **)&pszIncWdm, pValue); + break; + + case SOURCES_PRIVATE_INC_PATH: + MakeMacroString((char **)&pszIncPri, pValue); + break; + + case SOURCES_PRECOMPILED_PCH: + MakeMacroString(&DirDB->Pch, pValue); + break; + + case SOURCES_PRECOMPILED_OBJ: + MakeMacroString(&DirDB->PchObj, pValue); + break; + + case SOURCES_PRECOMPILED_INCLUDE: + case SOURCES_PRECOMPILED_TARGET: + { + LPSTR *ppszPath, *ppszFile, p; + if (iMacro == SOURCES_PRECOMPILED_INCLUDE) { + ppszPath = &pds->PchIncludeDir; + ppszFile = &pds->PchInclude; + } else { + ppszPath = &pds->PchTargetDir; + ppszFile = &pds->PchTarget; + } + + MakeMacroString(ppszPath, ""); // free old string + if (!MakeMacroString(ppszFile, pValue)) { + break; + } + p = *ppszFile + strlen(*ppszFile); + while (p > *ppszFile && *--p != '\\') + ; + + if (p > *ppszFile) { + *p = '\0'; + MakeMacroString(ppszPath, *ppszFile); + MakeMacroString(ppszFile, p + 1); + } + + if (DEBUG_1) { + BuildMsg( + "Precompiled header%s is %s in directory %s\n", + iMacro == SOURCES_PRECOMPILED_INCLUDE? + "" : " target", + *ppszFile, + *ppszPath != NULL? + *ppszPath : "'.'"); + } + } + + if (iMacro == SOURCES_PRECOMPILED_INCLUDE || + pds->PchTargetDir == NULL) { + + break; + } + + EnsureDirectoriesExist(pds->PchTargetDir); + break; + + case SOURCES_PASS0_HEADERDIR: + MakeMacroString(&pds->PassZeroHdrDir, pValue); + EnsureDirectoriesExist(pds->PassZeroHdrDir); + if (DEBUG_1) + { + BuildMsg("Pass Zero Header Directory is '%s'\n", + pds->PassZeroHdrDir); + } + break; + + case SOURCES_PASS0_SOURCEDIR: + case SOURCES_PASS0_CLIENTDIR: + // SOURCES_PASS0_SOURCEDIR and SOURCES_PASS0_CLIENTDIR + // are mutually exclusive - enforced by makefile.def + MakeMacroString(&pds->PassZeroSrcDir1, pValue); + EnsureDirectoriesExist(pds->PassZeroSrcDir1); + if (DEBUG_1) + { + BuildMsg("Pass Zero Source/Client Directory is '%s'\n", + pds->PassZeroSrcDir1); + } + break; + + case SOURCES_MIDL_UUIDDIR: + case SOURCES_PASS0_SERVERDIR: + // SOURCES_MIDL_UUIDDIR and SOURCES_PASS0_SERVERDIR + // are mutually exclusive - enforced by makefile.def + MakeMacroString(&pds->PassZeroSrcDir2, pValue); + EnsureDirectoriesExist(pds->PassZeroSrcDir2); + if (DEBUG_1) + { + BuildMsg("Midl UUID/Server Source Directory is '%s'\n", + pds->PassZeroSrcDir2); + } + break; + + case SOURCES_NTTEST: + if (MakeMacroString(&DirDB->KernelTest, pValue)) { + DirDB->DirFlags |= DIRDB_LINKNEEDED; + } + break; + + case SOURCES_UMTYPE: + MakeMacroString(&pds->TestType, pValue); + if (DEBUG_1) { + BuildMsg( + " Found UMTYPE=%s\n", + pds->TestType); + } + break; + + case SOURCES_UMTEST: + case SOURCES_OPTIONAL_UMTEST: + SaveUserTests(DirDB, pValue); + break; + + case SOURCES_UMAPPL: + if (MakeMacroString(&DirDB->UserAppls, pValue)) { + DirDB->DirFlags |= DIRDB_LINKNEEDED; + } + break; + + case SOURCES_UMAPPLEXT: + if (!_stricmp(pValue, ".exe")) { + MakeMacroString(&DirDB->TargetExt, ".exe"); + } + else + if (!_stricmp(pValue, ".com")) { + MakeMacroString(&DirDB->TargetExt, ".com"); + } + else + if (!_stricmp(pValue, ".scr")) { + MakeMacroString(&DirDB->TargetExt, ".scr"); + } + else { + BuildError( + "Unsupported UMAPPLEXT value - %s\n", + pValue); + } + break; + + case SOURCES_IDLTYPE: + if (!_stricmp(pValue, "ole")) { + pds->IdlType = 0; + } + else + if (!_stricmp(pValue, "rpc")) { + pds->IdlType = 1; + } + else { + BuildError( + "Unsupported IDL_TYPE value - %s\n", + pValue); + } + break; + + case SOURCES_SOURCES_OPTIONS: + fCleanNTTargetFile0 = fClean && strstr(pValue, "-c0"); + break; + + case SOURCES_NTTARGETFILE0: + DirDB->DirFlags |= DIRDB_TARGETFILE0; + if (fCleanNTTargetFile0) { + MakeMacroString(&DirDB->NTTargetFile0, pValue); + } + break; + + case SOURCES_NTTARGETFILES: + DirDB->DirFlags |= DIRDB_TARGETFILES; + break; + + case SOURCES_CHICAGO_PRODUCT: + DirDB->DirFlags |= DIRDB_CHICAGO_INCLUDES; + break; + + case SOURCES_CONDITIONAL_INCLUDES: + MakeMacroString(&pds->ConditionalIncludes, pValue); + break; + + case SOURCES_SYNCHRONIZE_BLOCK: + DirDB->DirFlags |= DIRDB_SYNCHRONIZE_BLOCK; + break; + + case SOURCES_SYNCHRONIZE_DRAIN: + DirDB->DirFlags |= DIRDB_SYNCHRONIZE_DRAIN; + break; + + case SOURCES_CHECKED_ALT_DIR: + DirDB->DirFlags |= DIRDB_CHECKED_ALT_DIR; + if (DEBUG_1) { + BuildMsg("Found CHECKED_ALT_DIR\n"); + } + SetObjDir(TRUE); + if (fCheckedBuild) { + SaveMacro("_OBJ_DIR", pszObjDir); + if (iTarget < 0) { + SaveMacro("O", TargetMachines[0]-> + ObjectDirectory[iObjectDir]); + } else { + SaveMacro("O", + PossibleTargetMachines[iTarget/2]-> + ObjectDirectory[iObjectDir]); + } + } + break; + + case SOURCES_PROJECT_NAME: + sprintf(path, "%s\\%s", NtRoot, pValue); + SaveMacro("PROJECT_ROOT", path); + break; + + case SOURCES_PASS0_PUBLISH: + DirDB->DirFlags |= DIRDB_PASS0NEEDED; + break; + } + } + +SaveAndFreeMacro: + SaveMacro(TextLine, pValue); + + // Make sure we cleanup from the SplitMacro call at the top. + FreeString(&TextLine, MT_DIRSTRING); +} + +void +ReadProjectsInfo( + DIRREC *DirDB, + DIRSUP *pds + ) +{ + FILE *FileHandle; + LPSTR TextLine, pBackSlash, pszProject; + BOOL Found; + + char pszProjectMkPath[DB_MAX_PATH_LENGTH]; + char path[DB_MAX_PATH_LENGTH]; + + // First load project.mk for this project. + + strcpy(pszProjectMkPath, DirDB->Name); + strcpy(path, pszProjectMkPath); + strcat(path, "\\project.mk"); + Found = !_access(path, 0); + while (!Found && strlen(pszProjectMkPath)) + { + pBackSlash=strrchr(pszProjectMkPath, '\\'); + if (pBackSlash) { + *pBackSlash = '\0'; + } else { + return; + } + strcpy(path, pszProjectMkPath); + strcat(path, "\\project.mk"); + Found = !_access(path, 0); + } + + if (!Found) { + return; + } + + if (!OpenFilePush(pszProjectMkPath, "project.mk", "#", &FileHandle)) { + return; + } + + SaveMacro("_PROJECT_MK_PATH", pszProjectMkPath); + while ((TextLine = ReadLine(FileHandle)) != NULL) { + ProcessSourcesFileLine(DirDB, pds, TextLine, -1); + } + CloseReadFile(NULL); + + // Load the optional myproject.mk + + if (OpenFilePush(pszProjectMkPath, "myproject.mk", "#", &FileHandle)) { + + while ((TextLine = ReadLine(FileHandle)) != NULL) { + ProcessSourcesFileLine(DirDB, pds, TextLine, -1); + } + CloseReadFile(NULL); + } + + // Optionally load a project-owned projects.inc. Historically this lived + // under NTMAKEENV; a standalone tree keeps it beside project.mk instead. + + if (OpenFilePush(pszProjectMkPath, "projects.inc", "#", &FileHandle)) { + while ((TextLine = ReadLine(FileHandle)) != NULL) { + ProcessSourcesFileLine(DirDB, pds, TextLine, -1); + } + CloseReadFile(NULL); + } +} + +//+--------------------------------------------------------------------------- +// +// Function: ReadSourcesFile +// +// Synopsis: Parses the sources files (common and platform specific) +// +// Arguments: [DirDB] -- Directory containing sources file +// [pds] -- Supplementary info on directory +// [pDateTimeSources] -- Timestamp of Sources file +// +// Returns: TRUE if read successfully +// +//---------------------------------------------------------------------------- + +BOOL +ReadSourcesFile(DIRREC *DirDB, DIRSUP *pds, ULONG *pDateTimeSources) +{ + FILE *InFileHandle; + LPSTR p, TextLine; + UINT i; + int iTarget; + ULONG DateTime; + char path[DB_MAX_PATH_LENGTH]; + + memset(pds, 0, sizeof(*pds)); + pds->fNoTarget=FALSE; + assert(DirDB->TargetPath == NULL); + assert(DirDB->TargetPathLib == NULL); + assert(DirDB->TargetName == NULL); + assert(DirDB->TargetExt == NULL); + assert(DirDB->KernelTest == NULL); + assert(DirDB->UserAppls == NULL); + assert(DirDB->UserTests == NULL); + assert(DirDB->NTTargetFile0 == NULL); + assert(DirDB->Pch == NULL); + assert(DirDB->PchObj == NULL); + assert(cMacro == 0); + *pDateTimeSources = 0; + + // + // Read the information in each of the target specific directories + // and simulate concatenation of all of the sources files. + // + // Possible sources files are read from DirDB->Name | target-source + // and DirDb->Name | ..\target-source. + // + // iTarget values, and the corresponding files processed are: + // -1 sources. + // 0 PossibleTargetMachines[0]\sources. + // 1 ..\PossibleTargetMachines[0]\sources. + // 2 PossibleTargetMachines[1]\sources. + // 3 ..\PossibleTargetMachines[1]\sources. + // 4 PossibleTargetMachines[2]\sources. + // 5 ..\PossibleTargetMachines[2]\sources. + + SaveMacro("MAKEDIR", DirDB->Name); + SaveMacro("SDK_LIB_DEST", pszSdkLibDest); + SaveMacro("DDK_LIB_DEST", pszDdkLibDest); + SaveMacro("PUBLIC_INTERNAL_PATH", pszPublicInternalPath); + // Use the default architecture for now + SaveMacro("TARGET_DIRECTORY", TargetMachines[0]->SourceDirectory); + + SetObjDir(FALSE); + SaveMacro("_OBJ_DIR", pszObjDir); + // Define a default CONDITIONAL_INCLUDES line to deal with the mac hdrs in windows/rpc/ole32.h. + MakeMacroString(&pds->ConditionalIncludes, "winwlm.h rpcmac.h rpcerr.h macpub.h macapi.h macname1.h macname2.h"); + + // Before processing the sources file, see if there's a projects.mk in the tree. + ReadProjectsInfo(DirDB, pds); + + for (iTarget = -1; iTarget < 2*MAX_TARGET_MACHINES; iTarget++) { + path[0] = '\0'; + if (iTarget >= 0) { + if (iTarget & 1) { + strcat(path, "..\\"); + } + strcat(path, PossibleTargetMachines[iTarget/2]->SourceDirectory); + strcat(path, "\\"); + } + strcat(path, "sources."); + if (!OpenFilePush(DirDB->Name, path, "#", &InFileHandle)) { + if (iTarget == -1) { + FreeMacros(); + return(FALSE); + } + continue; // skip non-existent subordinate sources files + } + if (DEBUG_1) { + BuildMsg( + " Scanning%s file %s\n", + iTarget >= 0 ? " subordinate" : "", + FormatPathName(DirDB->Name, path)); + } + + // Update per-target macros. + if (iTarget < 0) { + SaveMacro("TARGET_DIRECTORY", + TargetMachines[0]->SourceDirectory); + SaveMacro("O", TargetMachines[0]-> + ObjectDirectory[iObjectDir]); + } else { + SaveMacro("TARGET_DIRECTORY", + PossibleTargetMachines[iTarget/2]->SourceDirectory); + SaveMacro("O", PossibleTargetMachines[iTarget/2]-> + ObjectDirectory[iObjectDir]); + } + + DirDB->DirFlags |= DIRDB_SOURCESREAD; + + while ((TextLine = ReadLine(InFileHandle)) != NULL) { + ProcessSourcesFileLine(DirDB, pds, TextLine, iTarget); + } + + // Subordinate files close themselves at EOF. Timestamps + // are propagated in CloseReadFile so the primary + // file's timestamp is automatically updated. + } + + // Close the primary file. + DateTime = CloseReadFile(NULL); + if (*pDateTimeSources < DateTime) { + *pDateTimeSources = DateTime; // keep newest timestamp + } + + if (!pds->fNoTarget && (DirDB->TargetPath == NULL)) { + strcpy(path, "sources."); + SetupReadFile(DirDB->Name, path, "#", &InFileHandle); + BuildError( + "Unknown TARGETPATH value\n", + NULL); + CloseReadFile(NULL); + } + + FreeMacros(); + + if (fChicagoProduct) { + DirDB->DirFlags |= DIRDB_CHICAGO_INCLUDES; + } + + // + // Directory has pass0 files in it (.idl, .mc, .asn, etc), check to make + // sure they specified where the generated files should go. Default to the + // obj subdirectories if they didn't. These always need to be non-null. + // + if (!pds->PassZeroHdrDir) { + MakeString(&pds->PassZeroHdrDir, ".", TRUE, MT_DIRSTRING); + } + + if (!pds->PassZeroSrcDir1) { + MakeString(&pds->PassZeroSrcDir1, ".", TRUE, MT_DIRSTRING); + } + + if (!pds->PassZeroSrcDir2) + MakeString(&pds->PassZeroSrcDir2, pds->PassZeroSrcDir1, TRUE, MT_DIRSTRING); + + if (DirDB->UserTests != NULL) { + _strlwr(DirDB->UserTests); + } + if (DirDB->UserAppls != NULL) { + if (DirDB->UserTests != NULL || strchr(DirDB->UserAppls, '*') != NULL) { + DirDB->DirFlags |= DIRDB_FORCELINK; // multiple targets + } + } + + PostProcessSources(DirDB, pds); + + if (DEBUG_1) { + PrintDirDB(DirDB, 1|2); + PrintDirSupData(pds); + PrintDirDB(DirDB, 4); + } + + pds->DateTimeSources = *pDateTimeSources; + + return(TRUE); +} + +//+--------------------------------------------------------------------------- +// +// Function: PostProcessSources +// +// Synopsis: Scan the files in the given directory and add files to the +// directory's list of source files (SOURCEREC), including PCH +// files, UMTEST files, etc. +// +// Arguments: [pdr] -- Directory to process +// [pds] -- Directory supplemental information +// +//---------------------------------------------------------------------------- + +void +PostProcessSources(DIRREC *pdr, DIRSUP *pds) +{ + PFILEREC FileDB, *FileDBNext; + char path[DB_MAX_PATH_LENGTH]; + LPSTR p, p1; + UINT i; + + for (i = 0; i < MAX_TARGET_MACHINES + 1; i++) { + if (pds->SourcesVariables[i] != NULL) { + CrackSources(pdr, pds, i); + } + } + + FileDBNext = &pdr->Files; + while (FileDB = *FileDBNext) { + + if (pds->PchInclude && strcmp(FileDB->Name, pds->PchInclude) == 0) { + InsertSourceDB(&pds->psrSourcesList[0], FileDB, 0, SOURCEDB_PCH); + if (DEBUG_1) { + BuildMsg("Adding PCH file to Sources List: %s.\n", FileDB->Name); + } + } + + if ((FileDB->FileFlags & (FILEDB_SOURCE | FILEDB_OBJECTS_LIST)) == + FILEDB_SOURCE) { + + p = FileDB->Name; + p1 = path; + while (*p != '\0' && *p != '.') { + *p1++ = *p++; + } + *p1 = '\0'; + _strlwr(path); + if (pdr->KernelTest != NULL && + !strcmp(path, pdr->KernelTest)) { + + FileDB->FileFlags |= FILEDB_OBJECTS_LIST; + } + else + if (pdr->UserAppls != NULL && + (p = strstr(pdr->UserAppls, path)) && + (p == pdr->UserAppls || p[-1] == '*' || p[-1] == ' ')) { + FileDB->FileFlags |= FILEDB_OBJECTS_LIST; + } + else + if (pdr->UserTests != NULL && + (p = strstr(pdr->UserTests, path)) && + (p == pdr->UserTests || p[-1] == '*' || p[-1] == ' ')) { + + FileDB->FileFlags |= FILEDB_OBJECTS_LIST; + } + if (FileDB->FileFlags & FILEDB_OBJECTS_LIST) { + InsertSourceDB(&pds->psrSourcesList[0], FileDB, 0, 0); + } + } + FileDBNext = &FileDB->Next; + } + + return; +} + +//+--------------------------------------------------------------------------- +// +// Function: ReadDirsFile +// +// Synopsis: Parse the DIRS file +// +// Arguments: [DirDB] -- Directory to look in +// +// Returns: TRUE if parsed +// +// Notes: The existence of a file named 'mydirs' or the name of the +// target specific dirs will override the normal 'dirs' file. +// +//---------------------------------------------------------------------------- + +BOOL +ReadDirsFile( + PDIRREC DirDB + ) + +{ + FILE *InFileHandle; + LPSTR TextLine, pValue; + LPSTR apszDirs[] = { "mydirs.", NULL, "dirs.", NULL }; + CHAR TargetName[16]; + + strcpy(&TargetName[0], pszTargetDirs); + strcat(&TargetName[0], "."); + apszDirs[1] = &TargetName[0]; + + for (ppCurrentDirsFileName = apszDirs; + *ppCurrentDirsFileName != NULL; + ppCurrentDirsFileName++) { + if (SetupReadFile(DirDB->Name, *ppCurrentDirsFileName, "#", &InFileHandle)) { + break; + } + } + + if (*ppCurrentDirsFileName == NULL) { + FreeMacros(); + return(FALSE); + } + + if (fFirstScan && (ppCurrentDirsFileName <= &apszDirs[1])) { + BuildMsg("Using .\\%s instead of DIRS...\n", + FormatPathName(DirDB->Name, *ppCurrentDirsFileName)); + } + + if (DEBUG_1) { + BuildMsg( + " Scanning file %s\n", + FormatPathName(DirDB->Name, *ppCurrentDirsFileName)); + } + + assert(cMacro == 0); + while ((TextLine = ReadLine(InFileHandle)) != NULL) { + if ((pValue = SplitMacro(&TextLine)) != NULL) { + SaveMacro(TextLine, pValue); + FreeString(&TextLine, MT_DIRSTRING); + } + } + CloseReadFile(NULL); + if ((pValue = FindMacro("DIRS")) != NULL) { + MarkDirNames(DirDB, pValue, TRUE); + } + if ((pValue = FindMacro("OPTIONAL_DIRS")) != NULL) { + MarkDirNames(DirDB, pValue, BuildAllOptionalDirs); + } + if ((FindMacro("SYNCHRONIZE_DRAIN")) != NULL) { + DirDB->DirFlags |= DIRDB_SYNCHRONIZE_DRAIN; + } + FreeMacros(); + return( TRUE ); +} + + +// +// Debugging and Utility Functions +// + +VOID +PrintDirSupData(DIRSUP *pds) +{ + int i; + + if (pds->LocalIncludePath != NULL) { + BuildMsgRaw(" LocalIncludePath: %s\n", pds->LocalIncludePath); + } + if (pds->TestType != NULL) { + BuildMsgRaw(" TestType: %s\n", pds->TestType); + } + if (pds->PchIncludeDir != NULL) { + BuildMsgRaw(" PchIncludeDir: %s\n", pds->PchIncludeDir); + } + if (pds->PchInclude != NULL) { + BuildMsgRaw(" PchInclude: %s\n", pds->PchInclude); + } + if (pds->PchTargetDir != NULL) { + BuildMsgRaw(" PchTargetDir: %s\n", pds->PchTargetDir); + } + if (pds->PchTarget != NULL) { + BuildMsgRaw(" PchTarget: %s\n", pds->PchTarget); + } + if (pds->ConditionalIncludes != NULL) { + BuildMsgRaw(" ConditionalIncludes: %s\n", pds->ConditionalIncludes); + } + for (i = 0; i < MAX_TARGET_MACHINES + 1; i++) { + if (pds->SourcesVariables[i] != NULL) { + BuildMsgRaw( + " SourcesVariables[%d]: %s\n", + i, + pds->SourcesVariables[i]); + } + if (pds->psrSourcesList[i] != NULL) { + BuildMsgRaw(" SourcesList[%d]:\n", i); + PrintSourceDBList(pds->psrSourcesList[i], i - 1); + } + } +} + + +VOID +FreeDirSupData(DIRSUP *pds) +{ + int i; + + if (pds->LocalIncludePath != NULL) { + FreeMem(&pds->LocalIncludePath, MT_DIRSTRING); + } + if (pds->TestType != NULL) { + FreeMem(&pds->TestType, MT_DIRSTRING); + } + if (pds->PchInclude != NULL) { + FreeMem(&pds->PchInclude, MT_DIRSTRING); + } + if (pds->PchIncludeDir != NULL) { + FreeMem(&pds->PchIncludeDir, MT_DIRSTRING); + } + if (pds->PchTargetDir != NULL) { + FreeMem(&pds->PchTargetDir, MT_DIRSTRING); + } + if (pds->PchTarget != NULL) { + FreeMem(&pds->PchTarget, MT_DIRSTRING); + } + if (pds->ConditionalIncludes != NULL) { + FreeMem(&pds->ConditionalIncludes, MT_DIRSTRING); + } + if (pds->PassZeroHdrDir != NULL) { + FreeMem(&pds->PassZeroHdrDir, MT_DIRSTRING); + } + if (pds->PassZeroSrcDir1 != NULL) { + FreeMem(&pds->PassZeroSrcDir1, MT_DIRSTRING); + } + if (pds->PassZeroSrcDir2 != NULL) { + FreeMem(&pds->PassZeroSrcDir2, MT_DIRSTRING); + } + for (i = 0; i < MAX_TARGET_MACHINES + 1; i++) { + if (pds->SourcesVariables[i] != NULL) { + FreeMem(&pds->SourcesVariables[i], MT_DIRSTRING); + } + while (pds->psrSourcesList[i] != NULL) { + FreeSourceDB(&pds->psrSourcesList[i]); + } + } +} + + +VOID +FreeDirData(DIRREC *pdr) +{ + if (pdr->TargetPath != NULL) { + FreeMem(&pdr->TargetPath, MT_DIRSTRING); + } + if (pdr->TargetPathLib != NULL) { + FreeMem(&pdr->TargetPathLib, MT_DIRSTRING); + } + if (pdr->TargetName != NULL) { + FreeMem(&pdr->TargetName, MT_DIRSTRING); + } + if (pdr->TargetExt != NULL) { + FreeMem(&pdr->TargetExt, MT_DIRSTRING); + } + if (pdr->KernelTest != NULL) { + FreeMem(&pdr->KernelTest, MT_DIRSTRING); + } + if (pdr->UserAppls != NULL) { + FreeMem(&pdr->UserAppls, MT_DIRSTRING); + } + if (pdr->UserTests != NULL) { + FreeMem(&pdr->UserTests, MT_DIRSTRING); + } + if (pdr->NTTargetFile0 != NULL) { + FreeMem(&pdr->NTTargetFile0, MT_DIRSTRING); + } + if (pdr->Pch != NULL) { + FreeMem(&pdr->Pch, MT_DIRSTRING); + } + if (pdr->PchObj != NULL) { + FreeMem(&pdr->PchObj, MT_DIRSTRING); + } + if (pdr->pds != NULL) { + FreeDirSupData(pdr->pds); + FreeMem(&pdr->pds, MT_DIRSUP); + pdr->pds = NULL; + } +} + +//+--------------------------------------------------------------------------- +// +// Function: MarkDirNames +// +// Synopsis: Parses a DIRS= or OPTIONAL_DIRS line and marks the directories +// appropriately. +// +// Arguments: [DirDB] -- Directory containing DIRS file +// [TextLine] -- DIRS= or OPTIONAL_DIRS= line +// [Required] -- Indicates if directories are optional or not. +// +//---------------------------------------------------------------------------- + +VOID +MarkDirNames(PDIRREC DirDB, LPSTR TextLine, BOOL Required) +{ + UINT i; + LPSTR p, token; + PFILEREC FileDB, *FileDBNext; + char dirbuf[DB_MAX_PATH_LENGTH]; + ULONG DirInclude; + + AssertPathString(TextLine); + while (SplitToken(dirbuf, '*', &TextLine)) { + // Assume all platforms are included for this dir. + DirInclude = DIR_INCLUDE_ALL; + for (p = dirbuf; *p != '\0'; p++) { + if ( dirbuf != p && *p == '{' ) { + // An explicit include path was listed. + DirInclude = DIR_INCLUDE_NONE; + *p = '\0'; + token = strtok(p+1, ",}"); + while (token) { + if (!_stricmp(token, "X86") || + !_stricmp(token, "I386") || + !_stricmp(token, "386")) + { + DirInclude |= DIR_INCLUDE_X86; + } else if (!_stricmp(token, "32") || + !_stricmp(token, "Win32")) + { + DirInclude |= DIR_INCLUDE_WIN32; + } else if (!_stricmp(token, "64") || + !_stricmp(token, "Win64")) + { + DirInclude |= DIR_INCLUDE_WIN64; + } else if (!_stricmp(token, "IA64")) { + DirInclude |= DIR_INCLUDE_IA64; + } else if (!_stricmp(token, "AMD64")) { + DirInclude |= DIR_INCLUDE_AMD64; + } else if (!_stricmp(token, "RISC")) { + DirInclude |= DIR_INCLUDE_RISC; + } + token = strtok(NULL, ",}"); + } + break; + } else { + if (!iscsym(*p) && *p != '.' && *p != '-' ) { + BuildError( + "%s: ignoring bad subdirectory: %s\n", + DirDB->Name, + dirbuf); + p = NULL; + break; + } + } + } + + if (!(DirInclude & TargetMachines[0]->DirIncludeMask)) { + continue; + } + + if (p != NULL) { + if (!Required) { + for (i = 0; i < CountOptionalDirs; i++) { + if (!strcmp(dirbuf, OptionalDirs[i])) { + OptionalDirsUsed[i] = TRUE; + break; + } + } + if (i >= CountOptionalDirs) { + p = NULL; + } + } + else { + for (i = 0; i < CountExcludeDirs; i++) { + if (!strcmp(dirbuf, ExcludeDirs[i])) { + ExcludeDirsUsed[i] = TRUE; + p = NULL; + break; + } + } + } + } + if (p != NULL) { + if ((fQuicky || fSemiQuicky) && (!fQuickZero)) { + FileDB = InsertFileDB( + DirDB, + dirbuf, + 0, + FILE_ATTRIBUTE_DIRECTORY, + 0); + if (FileDB != NULL) { + FileDB->SubDirIndex = ++DirDB->CountSubDirs; + } + } + else { + FileDBNext = &DirDB->Files; + while (FileDB = *FileDBNext) { + if (FileDB->FileFlags & FILEDB_DIR) { + if (!strcmp(dirbuf, FileDB->Name)) { + FileDB->SubDirIndex = ++DirDB->CountSubDirs; + break; + } + } + FileDBNext = &FileDB->Next; + } + if (FileDB == NULL) { + BuildError( + "%s found in %s, is not a subdirectory of %s\n", + dirbuf, + FormatPathName(DirDB->Name, *ppCurrentDirsFileName), + DirDB->Name); + } + } + + } + } +} + + +VOID +StartElapsedTime(VOID) +{ + if (fPrintElapsed && StartTime == 0) { + StartTime = GetTickCount(); + } +} + + +VOID +PrintElapsedTime(VOID) +{ + DWORD ElapsedTime; + DWORD ElapsedHours; + DWORD ElapsedMinutes; + DWORD ElapsedSeconds; + DWORD ElapsedMilliseconds; + + if (fPrintElapsed) { + ElapsedTime = GetTickCount() - StartTime; + ElapsedHours = ElapsedTime/(1000 * 60 * 60); + ElapsedTime = ElapsedTime % (1000 * 60 * 60); + ElapsedMinutes = ElapsedTime/(1000 * 60); + ElapsedTime = ElapsedTime % (1000 * 60); + ElapsedSeconds = ElapsedTime/1000; + ElapsedMilliseconds = ElapsedTime % 1000; + BuildMsg( + "Elapsed time [%d:%02d:%02d.%03d]\n", + ElapsedHours, + ElapsedMinutes, + ElapsedSeconds, + ElapsedMilliseconds); + LogMsg( + "Elapsed time [%d:%02d:%02d.%03d]%s\n", + ElapsedHours, + ElapsedMinutes, + ElapsedSeconds, + ElapsedMilliseconds, + szAsterisks); + } +} diff --git a/sdktools/buildutl.c b/sdktools/buildutl.c new file mode 100644 index 0000000..c928a3b --- /dev/null +++ b/sdktools/buildutl.c @@ -0,0 +1,1818 @@ +//+--------------------------------------------------------------------------- +// +// Microsoft Windows +// Copyright (C) Microsoft Corporation, 1989 - 1994 +// +// File: buildutl.c +// +// Contents: Utility functions for Build.exe +// +// History: 16-May-89 SteveWo Created +// ... See SLM log +// 26-Jul-94 LyleC Cleanup/Add pass0 support +// +//---------------------------------------------------------------------------- + +#include "build.h" + + +#if DBG +//+--------------------------------------------------------------------------- +// +// Memory Allocation/Deallocation functions +// +// These functions provide leak tracking on a debug build. +// +//---------------------------------------------------------------------------- + +typedef struct _MEMHEADER { + MemType mt; + ULONG cbRequest; + struct _MEMHEADER *pmhPrev; + struct _MEMHEADER *pmhNext; +} MEMHEADER; + +#define CBHEADER sizeof(MEMHEADER) +#define CBTAIL sizeof(ULONG) + +char patternFree[CBTAIL] = { 'M', 'E', 'M', 'D' }; +char patternBusy[CBTAIL] = { 'm', 'e', 'm', 'd' }; + +__inline MEMHEADER * +GetHeader(VOID *pvblock) +{ + return((MEMHEADER *) (pvblock) - 1); +} + +__inline VOID * +GetBlock(MEMHEADER *pmh) +{ + return((VOID *) (pmh + 1)); +} + +__inline VOID +FillTailBusy(LPSTR p) +{ + memcpy(p, patternBusy, sizeof(patternBusy)); +} + +__inline VOID +FillTailFree(LPSTR p) +{ + memcpy(p, patternFree, sizeof(patternFree)); +} + +__inline BOOL +CheckTail(LPSTR p) +{ + return(memcmp(p, patternBusy, sizeof(patternBusy)) == 0); +} + + +typedef struct _MEMTAB { + LPSTR pszType; + ULONG cbAlloc; + ULONG cAlloc; + ULONG cbAllocTotal; + ULONG cAllocTotal; + MEMHEADER mh; +} MEMTAB; + +ULONG cbAllocMax; +ULONG cAllocMax; + +MEMTAB MemTab[] = { + { "Totals", }, // MT_TOTALS + { "Unknown", }, // MT_UNKNOWN + + { "ChildData", }, // MT_CHILDDATA + { "CmdString", }, // MT_CMDSTRING + { "DirDB", }, // MT_DIRDB + { "DirSup", }, // MT_DIRSUP + { "DirPath", }, // MT_DIRPATH + { "DirString", }, // MT_DIRSTRING + { "EventHandles", }, // MT_EVENTHANDLES + { "FileDB", }, // MT_FILEDB + { "FileReadBuf", }, // MT_FILEREADBUF + { "FrbString", }, // MT_FRBSTRING + { "IncludeDB", }, // MT_INCLUDEDB + { "IoBuffer", }, // MT_IOBUFFER + { "Macro", }, // MT_MACRO + { "SourceDB", }, // MT_SOURCEDB + { "Target", }, // MT_TARGET + { "ThreadFilter", }, // MT_THREADFILTER + { "ThreadHandles", }, // MT_THREADHANDLES + { "ThreadState", }, // MT_THREADSTATE +}; +#define MT_MAX (sizeof(MemTab)/sizeof(MemTab[0])) + + +VOID +InitMem(VOID) +{ + MEMTAB *pmt; + for (pmt = MemTab; pmt < &MemTab[MT_MAX]; pmt++) { + assert(pmt->cAllocTotal == 0); + pmt->mh.mt = MT_INVALID; + pmt->mh.pmhNext = &pmt->mh; + pmt->mh.pmhPrev = &pmt->mh; + } +} + + +#else + +#define CBHEADER 0 +#define CBTAIL 0 + +#endif + + +//+--------------------------------------------------------------------------- +// +// Function: AllocMem +// +// Synopsis: Allocate memory +// +// Arguments: [cb] -- Requested Size +// [ppv] -- [out] allocated memory +// [mt] -- Type of memory being allocated (MT_XXX) +// +//---------------------------------------------------------------------------- + +VOID +AllocMem(UINT cb, VOID **ppv, MemType mt) +{ + *ppv = malloc(cb + CBHEADER + CBTAIL); + if (*ppv == NULL) { + BuildError("(Fatal Error) malloc(%u) failed\n", cb); + exit(16); + } +#if DBG + { + MEMTAB *pmt; + MEMHEADER *pmh; + + pmh = *ppv; + *ppv = GetBlock(pmh); + + if (mt >= MT_MAX) { + mt = MT_UNKNOWN; + } + pmt = &MemTab[MT_TOTALS]; + if (pmt->cAllocTotal == 0) { + InitMem(); + } + pmt->cAlloc++; + pmt->cAllocTotal++; + pmt->cbAlloc += cb; + pmt->cbAllocTotal += cb; + if (cbAllocMax < pmt->cbAlloc) { + cbAllocMax = pmt->cbAlloc; + } + if (cAllocMax < pmt->cAlloc) { + cAllocMax = pmt->cAlloc; + } + + pmt = &MemTab[mt]; + pmt->cAlloc++; + pmt->cAllocTotal++; + pmt->cbAlloc += cb; + pmt->cbAllocTotal += cb; + + pmh->mt = mt; + pmh->cbRequest = cb; + + pmh->pmhNext = pmt->mh.pmhNext; + pmt->mh.pmhNext = pmh; + pmh->pmhPrev = pmh->pmhNext->pmhPrev; + pmh->pmhNext->pmhPrev = pmh; + + FillTailBusy((char *) *ppv + cb); + + if (DEBUG_4 && DEBUG_1) { + BuildError("AllocMem(%d, mt=%s) -> %lx\n", cb, pmt->pszType, *ppv); + } + } +#endif +} + + + +//+--------------------------------------------------------------------------- +// +// Function: FreeMem +// +// Synopsis: Free memory allocated by AllocMem +// +// Arguments: [ppv] -- Memory pointer +// [mt] -- Type of memory (MT_XXX) +// +// Notes: Sets the memory pointer to null after freeing it. +// +//---------------------------------------------------------------------------- + +VOID +FreeMem(VOID **ppv, MemType mt) +{ + assert(*ppv != NULL); +#if DBG + { + MEMTAB *pmt; + MEMHEADER *pmh; + + pmh = GetHeader(*ppv); + if (mt == MT_DIRDB || + mt == MT_FILEDB || + mt == MT_INCLUDEDB || + mt == MT_SOURCEDB) { + + SigCheck(assert(((DIRREC *) (*ppv))->Sig == 0)); + } + if (mt >= MT_MAX) { + mt = MT_UNKNOWN; + } + pmt = &MemTab[MT_TOTALS]; + pmt->cAlloc--; + pmt->cbAlloc -= pmh->cbRequest; + pmt = &MemTab[mt]; + pmt->cAlloc--; + pmt->cbAlloc -= pmh->cbRequest; + + if (DEBUG_4 && DEBUG_1) { + BuildError( + "FreeMem(%d, mt=%s) <- %lx\n", + pmh->cbRequest, + pmt->pszType, + *ppv); + } + assert(CheckTail((char *) *ppv + pmh->cbRequest)); + FillTailFree((char *) *ppv + pmh->cbRequest); + assert(mt == pmh->mt); + + pmh->pmhNext->pmhPrev = pmh->pmhPrev; + pmh->pmhPrev->pmhNext = pmh->pmhNext; + pmh->pmhNext = pmh->pmhPrev = NULL; + + pmh->mt = MT_INVALID; + *ppv = pmh; + } +#endif + free(*ppv); + *ppv = NULL; +} + + +//+--------------------------------------------------------------------------- +// +// Function: ReportMemoryUsage +// +// Synopsis: Report current memory usage (if any) on a debug build. If +// called just before termination, memory leaks will be +// displayed. +// +// Arguments: (none) +// +//---------------------------------------------------------------------------- + +VOID +ReportMemoryUsage(VOID) +{ +#if DBG + MEMTAB *pmt; + UINT i; + + if (DEBUG_1) { + BuildErrorRaw( + "Maximum memory usage: %5lx bytes in %4lx blocks\n", + cbAllocMax, + cAllocMax); + for (pmt = MemTab; pmt < &MemTab[MT_MAX]; pmt++) { + BuildErrorRaw( + "%5lx bytes in %4lx blocks, %5lx bytes in %4lx blocks Total (%s)\n", + pmt->cbAlloc, + pmt->cAlloc, + pmt->cbAllocTotal, + pmt->cAllocTotal, + pmt->pszType); + } + } + FreeMem(&BigBuf, MT_IOBUFFER); + if (fDebug & 8) { + PrintAllDirs(); + } + FreeAllDirs(); + if (DEBUG_1 || MemTab[MT_TOTALS].cbAlloc != 0) { + BuildErrorRaw(szNewLine); + if (MemTab[MT_TOTALS].cbAlloc != 0) { + BuildError("Internal memory leaks detected:\n"); + } + for (pmt = MemTab; pmt < &MemTab[MT_MAX]; pmt++) { + BuildErrorRaw( + "%5lx bytes in %4lx blocks, %5lx bytes in %4lx blocks Total (%s)\n", + pmt->cbAlloc, + pmt->cAlloc, + pmt->cbAllocTotal, + pmt->cAllocTotal, + pmt->pszType); + } + } +#endif +} + + +//+--------------------------------------------------------------------------- +// +// Function: MyOpenFile +// +// Synopsis: Open a file +// +//---------------------------------------------------------------------------- + +BOOL +MyOpenFile( + LPSTR DirName, + LPSTR FileName, + LPSTR Access, + FILE **ppf, + BOOL BufferedIO) +{ + char path[ DB_MAX_PATH_LENGTH * 2 + 1]; // ensure we have enough space for "DirName" + "\\" + "FileName" + + strcpy(path, DirName); + if (path[0] != '\0') { + strcat(path, "\\"); + } + strcat(path, FileName); + *ppf = fopen( path, Access ); + if (*ppf == NULL) { + if (*Access == 'w') { + BuildError("%s: create file failed\n", path); + } + return(FALSE); + } + if (!BufferedIO) { + setvbuf(*ppf, NULL, _IONBF, 0); // Clear buffering on the stream. + } + return(TRUE); +} + + +typedef struct _FILEREADBUF { + struct _FILEREADBUF *pfrbNext; + LPSTR pszFile; + LPSTR pbBuffer; + LPSTR pbNext; + UINT cbBuf; + UINT cbBuffer; + UINT cbTotal; + UINT cbFile; + USHORT cLine; + USHORT cNull; + ULONG DateTime; + FILE *pf; + LPSTR pszCommentToEOL; + size_t cbCommentToEOL; + BOOLEAN fEof; + BOOLEAN fOpen; + BOOLEAN fMakefile; +} FILEREADBUF; + +static FILEREADBUF Frb; +char achzeros[16]; + + +//+--------------------------------------------------------------------------- +// +// Function: OpenFilePush +// +//---------------------------------------------------------------------------- + +BOOL +OpenFilePush( + LPSTR pszdir, + LPSTR pszfile, + LPSTR pszCommentToEOL, + FILE **ppf + ) +{ + FILEREADBUF *pfrb; + + if (Frb.fOpen) { + AllocMem(sizeof(*pfrb), &pfrb, MT_FILEREADBUF); + memcpy(pfrb, &Frb, sizeof(*pfrb)); + memset(&Frb, 0, sizeof(Frb)); + Frb.pfrbNext = pfrb; + } else { + pfrb = NULL; + } + + if (!SetupReadFile( + pszdir, + pszfile, + pszCommentToEOL, + ppf)) { + + if (pfrb != NULL) { + memcpy(&Frb, pfrb, sizeof(*pfrb)); + FreeMem(&pfrb, MT_FILEREADBUF); + } + + return FALSE; + } + + return TRUE; +} + + +//+--------------------------------------------------------------------------- +// +// Function: ReadFilePush +// +//---------------------------------------------------------------------------- + +LPSTR +ReadFilePush(LPSTR pszfile) +{ + FILE *pf; + + assert(Frb.fOpen); + OpenFilePush(IsFullPath(pszfile) ? "" : Frb.pszFile, pszfile, + Frb.pszCommentToEOL, &pf); + return(ReadLine(Frb.pf)); +} + + +//+--------------------------------------------------------------------------- +// +// Function: ReadFilePop +// +//---------------------------------------------------------------------------- + +LPSTR +ReadFilePop(VOID) +{ + if (Frb.pfrbNext == NULL) { + return(NULL); + } + CloseReadFile(NULL); + return(ReadLine(Frb.pf)); +} + + +//+--------------------------------------------------------------------------- +// +// Function: ReadBuf +// +//---------------------------------------------------------------------------- + +BOOL +ReadBuf(FILE *pf) +{ + LPSTR p, p2; + + assert(pf == Frb.pf); + assert(!Frb.fEof); + Frb.pbNext = Frb.pbBuffer; + Frb.cbBuf = fread(Frb.pbBuffer, 1, Frb.cbBuffer - 1, Frb.pf); + if (Frb.cbBuf == 0) { + Frb.fEof = TRUE; // no more to read + return(FALSE); + } + if (Frb.cbTotal == 0 && + Frb.cbBuf > sizeof(achzeros) && + memcmp(Frb.pbBuffer, achzeros, sizeof(achzeros)) == 0) { + + BuildError("ignoring binary file\n"); + Frb.fEof = TRUE; + return(FALSE); + } + p = &Frb.pbBuffer[Frb.cbBuf - 1]; + if (Frb.cbTotal + Frb.cbBuf < Frb.cbFile) { + do { + while (p > Frb.pbBuffer && *p != '\n') { + p--; + } + p2 = p; // save end of last complete line + if (p > Frb.pbBuffer && *p == '\n') { + p--; + if (p > Frb.pbBuffer && *p == '\r') { + p--; + } + while (p > Frb.pbBuffer && (*p == '\t' || *p == ' ')) { + p--; + } + } + } while (*p == '\\'); + if (p == Frb.pbBuffer) { + BuildError("(Fatal Error) too many continuation lines\n"); + exit(8); + } + p = p2; // restore end of last complete line + Frb.cbBuf = (UINT)(p - Frb.pbBuffer + 1); + } else { + Frb.fEof = TRUE; // no more to read + } + p[1] = '\0'; + Frb.cbTotal += Frb.cbBuf; + + return(TRUE); +} + + +//+--------------------------------------------------------------------------- +// +// Function: IsNmakeInclude +// +//---------------------------------------------------------------------------- + +LPSTR +IsNmakeInclude(LPSTR pinc) +{ + static char szInclude[] = "include"; + LPSTR pnew, p; + + while (*pinc == ' ') { + pinc++; + } + if (_strnicmp(pinc, szInclude, sizeof(szInclude) - 1) == 0 && + pinc[sizeof(szInclude) - 1] == ' ') { + + pnew = NULL; + pinc += sizeof(szInclude); + while (*pinc == ' ') { + pinc++; + } + + if (MakeMacroString(&pnew, pinc)) { + p = strchr(pnew, ' '); + if (p != NULL) { + *p = '\0'; + } + return(pnew); + } + } + return(NULL); +} + + +//+--------------------------------------------------------------------------- +// +// Function: ReadLine +// +// Synopsis: Read a line from the input file. +// +// Arguments: [pf] -- File to read from +// +// Returns: Line read from file +// +// Notes: ReadLine returns a canonical line from the input file. +// This involves: +// +// 1) Converting tab to spaces. Various editors/users change +// tabbing. +// 2) Uniformly terminate lines. Some editors drop CR in +// CRLF or add extras. +// 3) Handle file-type-specific continuations. +// +//---------------------------------------------------------------------------- + +LPSTR +ReadLine(FILE *pf) +{ + LPSTR p, pend, pline; + LPSTR pcont; + UCHAR chComment0 = Frb.pszCommentToEOL[0]; + BOOL fInComment, fWhiteSpace; + + assert(pf == Frb.pf || (pf != NULL && Frb.pfrbNext != NULL)); + if (Frb.cbBuf == 0) { + if (Frb.fEof) { + return(ReadFilePop()); + } + if (fseek(Frb.pf, Frb.cbTotal, SEEK_SET) == -1) { + return(ReadFilePop()); + } + if (!ReadBuf(Frb.pf)) { + return(ReadFilePop()); + } + } + pline = p = Frb.pbNext; + pend = &p[Frb.cbBuf]; + pcont = NULL; + + // scan through line forward + + fInComment = FALSE; + while (p < pend) { + switch (*p) { + case '\n': // Are we at an end of line? + if (*p == '\n') { + Frb.cLine++; + } + // FALL THROUGH + + case '\0': + if (pcont == NULL) { + goto eol; // bail out if single line + } // else combine multiple lines... + + *pcont = ' '; // remove continuation char + pcont = NULL; // eat only one line per continuation + + // We've seen a continuation char with whitespace following. + // If we're in a comment then we complain and break anyway. + + if (fInComment) { + if (DEBUG_1) { + BuildError ("continued line is commented out\n"); + } + goto eol; // bail out - ignore continuation + } + *p = ' '; // join the lines with blanks + break; + + case '\\': + pcont = p; // remember continuation character + break; + + case ' ': + break; + + case '\t': + case '\r': + *p = ' '; + break; + + default: + + // See if the character we're examining begins the + // comment-to-EOL string. + + if (*p == chComment0 && + !strncmp(p, Frb.pszCommentToEOL, Frb.cbCommentToEOL)) { + fInComment = TRUE; + } + pcont = NULL; // not a continuation character + break; + } + p++; + } +eol: + assert(Frb.cbBuf >= (UINT) (p - Frb.pbNext)); + Frb.cbBuf -= (UINT)(p - Frb.pbNext); + Frb.pbNext = p; + + if (pcont != NULL) { + *pcont = ' '; // file ended with backslash... + } + assert(*p == '\0' || *p == '\n'); + if (p < pend) { + if (*p == '\0') { + if (Frb.cNull++ == 0) { + BuildError("null byte at offset %lx\n", + Frb.cbTotal - Frb.cbBuf + p - Frb.pbNext); + } + } + *p = '\0'; // terminate line + assert(Frb.cbBuf >= 1); + Frb.cbBuf--; // account for newline (or null) + Frb.pbNext++; + } else { + assert(p == pend && *p == '\0'); + if (*pline == 'Z' - 64 && p == &pline[1] && Frb.cbBuf == 0) { + pline = NULL; // found CTL-Z at end of file + } else { +// BuildError( "last line incomplete\n"); + } + } + fWhiteSpace = FALSE; + if (pline != NULL) { + while (*pline == ' ') { + pline++; // skip leading whitespace + fWhiteSpace = TRUE; + } + if (*p != '\0') { + BuildError( "\"*p != '\\0'\" at offset %lx\n", + Frb.cbTotal - Frb.cbBuf + p - Frb.pbNext); + BuildError( + "pline=%x(%s) p=%x(%s)\n", + pline, + pline, + p, + p, + Frb.cbTotal - Frb.cbBuf + p - Frb.pbNext); + } + assert(*p == '\0'); + while (p > pline && *--p == ' ') { + *p = '\0'; // truncate trailing whitespace + } + } + if (pline == NULL) { + return(ReadFilePop()); + } + if (Frb.fMakefile && !fWhiteSpace && *pline == '!') { + p = IsNmakeInclude(pline + 1); + if (p != NULL) { + if (Frb.fMakefile && DEBUG_4) { + BuildError("!include(%s)\n", p); + } + pline = ReadFilePush(p); + FreeMem(&p, MT_DIRSTRING); + } + } + return(pline); +} + + +//+--------------------------------------------------------------------------- +// +// Function: SetupReadFile +// +// Synopsis: Open a file and prepare to read from it. +// +// Arguments: [pszdir] -- Directory name +// [pszfile] -- Filename +// [pszCommentToEOL] -- Comment to EOL string +// [ppf] -- [out] Open file handle +// +// Returns: TRUE if opened successfully +// +// Notes: This function, in order to minimize disk hits, reads the +// entire file into a buffer, which is then used by the ReadLine +// function. +// +//---------------------------------------------------------------------------- + +BOOL +SetupReadFile( + LPSTR pszdir, + LPSTR pszfile, + LPSTR pszCommentToEOL, + FILE **ppf + ) +{ + char path[DB_MAX_PATH_LENGTH]; + + assert(!Frb.fOpen); + assert(Frb.pf == NULL); + assert(Frb.pszFile == NULL); + Frb.fMakefile = strcmp(pszCommentToEOL, "#") == 0; + Frb.DateTime = 0; + + strcpy(path, pszdir); + if (Frb.pfrbNext != NULL) { // if a nested open + LPSTR p; + + if (Frb.fMakefile && !IsFullPath(pszfile)) { + + // nmake handles relative includes in makefiles by + // attempting to locate the file relative to each makefile + // in the complete include chain. + + FILEREADBUF *pfrb; + + for (pfrb = Frb.pfrbNext; pfrb != NULL; pfrb = pfrb->pfrbNext) { + assert(pfrb->pszFile != NULL); + + strcpy(path, pfrb->pszFile); + p = strrchr(path, '\\'); + if (p != NULL) { + *p = '\0'; + } + + if (ProbeFile(path, pszfile) != -1) { + break; + } + } + + if (pfrb == NULL) { + // Unable to find file anywhere along path. + return FALSE; + } + } else { + p = strrchr(path, '\\'); + if (p != NULL) { + *p = '\0'; + } + } + } + + if (!MyOpenFile(path, pszfile, "rb", ppf, TRUE)) { + *ppf = NULL; + return(FALSE); + } + if (Frb.fMakefile) { + Frb.DateTime = (*pDateTimeFile)(path, pszfile); + } + Frb.cLine = 0; + Frb.cNull = 0; + Frb.cbTotal = 0; + Frb.pf = *ppf; + Frb.fEof = FALSE; + Frb.pszCommentToEOL = pszCommentToEOL; + Frb.cbCommentToEOL = strlen(pszCommentToEOL); + + if (fseek(Frb.pf, 0L, SEEK_END) != -1) { + Frb.cbFile = ftell(Frb.pf); + if (fseek(Frb.pf, 0L, SEEK_SET) == -1) { + Frb.cbFile = 0; + } + } else { + Frb.cbFile = 0; + } + + Frb.cbBuffer = BigBufSize; + if (Frb.pfrbNext != NULL) { + if (Frb.cbBuffer > Frb.cbFile + 1) { + Frb.cbBuffer = Frb.cbFile + 1; + } + AllocMem(Frb.cbBuffer, &Frb.pbBuffer, MT_IOBUFFER); + } else { + Frb.pbBuffer = BigBuf; + } + if (!ReadBuf(Frb.pf)) { + fclose(Frb.pf); + Frb.pf = *ppf = NULL; + if (Frb.pfrbNext != NULL) { + FreeMem(&Frb.pbBuffer, MT_IOBUFFER); + } + return(FALSE); // zero byte file + } + if (path[0] != '\0') { + strcat(path, "\\"); + } + strcat(path, pszfile); + MakeString(&Frb.pszFile, path, TRUE, MT_FRBSTRING); + Frb.fOpen = TRUE; + if (Frb.fMakefile && DEBUG_4) { + BuildError( + "Opening file: cbFile=%lu cbBuf=%lu\n", + Frb.cbTotal, + Frb.cbBuffer); + } + return(TRUE); +} + + +//+--------------------------------------------------------------------------- +// +// Function: CloseReadFile +// +// Synopsis: Close the open file buffer. +// +// Arguments: [pcline] -- [out] Count of lines in file. +// +// Returns: Timestamp of file +// +//---------------------------------------------------------------------------- + +ULONG +CloseReadFile( + UINT *pcline + ) +{ + assert(Frb.fOpen); + assert(Frb.pf != NULL); + assert(Frb.pszFile != NULL); + + if (Frb.fMakefile && DEBUG_4) { + BuildError("Closing file\n"); + } + if (Frb.cNull > 1) { + BuildError("%hu null bytes in file\n", Frb.cNull); + } + fclose(Frb.pf); + Frb.fOpen = FALSE; + Frb.pf = NULL; + FreeString(&Frb.pszFile, MT_FRBSTRING); + if (Frb.pfrbNext != NULL) { + FILEREADBUF *pfrb; + + FreeMem(&Frb.pbBuffer, MT_IOBUFFER); + pfrb = Frb.pfrbNext; + if (pfrb->DateTime < Frb.DateTime) { + pfrb->DateTime = Frb.DateTime; // propagate subordinate timestamp + } + memcpy(&Frb, pfrb, sizeof(*pfrb)); + FreeMem(&pfrb, MT_FILEREADBUF); + } + if (pcline != NULL) { + *pcline = Frb.cLine; + } + return(Frb.DateTime); +} + + +//+--------------------------------------------------------------------------- +// +// Function: ProbeFile +// +// Synopsis: Determine if a file exists +// +//---------------------------------------------------------------------------- + +UINT +ProbeFile( + LPSTR DirName, + LPSTR FileName + ) +{ + char path[ DB_MAX_PATH_LENGTH ]; + + if (DirName != NULL) { + sprintf(path, "%s\\%s", DirName, FileName); + FileName = path; + } + return(GetFileAttributes(FileName)); +} + +//+--------------------------------------------------------------------------- +// +// Function: EnsureDirectoriesExist +// +// Synopsis: Ensures the given directory exists. If the path contains +// an asterisk, it will be expanded into all current machine +// target names. +// +// Arguments: [DirName] -- Name of directory to create if necessary +// +// Returns: FALSE if the directory could not be created, TRUE if it +// already exists or it could be created. +// +//---------------------------------------------------------------------------- + +BOOL +EnsureDirectoriesExist( + LPSTR DirName + ) +{ + char path[ DB_MAX_PATH_LENGTH ]; + char *p; + UINT i; + + if (!DirName || DirName[0] == '\0') + return FALSE; + + for (i = 0; i < CountTargetMachines; i++) { + + // Replace '*' with appropriate name + + ExpandObjAsterisk( + path, + DirName, + TargetMachines[i]->ObjectDirectory); + + if (ProbeFile(NULL, path) != -1) { + continue; + } + p = path; + while (TRUE) { + p = strchr(p, '\\'); + if (p != NULL) { + *p = '\0'; + } + if (!CreateBuildDirectory(path)) { + return FALSE; + } + if (p == NULL) { + break; + } + *p++ = '\\'; + } + } + + return TRUE; +} + +//+--------------------------------------------------------------------------- +// +// Function: DateTimeFile +// +// Synopsis: Get the timestamp on a file +// +//---------------------------------------------------------------------------- + +ULONG +DateTimeFile( + LPSTR DirName, + LPSTR FileName + ) +{ + char path[ DB_MAX_PATH_LENGTH ]; + WIN32_FIND_DATA FindFileData; + HDIR FindHandle; + ULONG FileDateTime; + + if (DirName == NULL || DirName[0] == '\0') { + FindHandle = FindFirstFile( FileName, &FindFileData ); + } else { + sprintf( path, "%s\\%s", DirName, FileName ); + FindHandle = FindFirstFile( path, &FindFileData ); + } + + if (FindHandle == (HDIR)INVALID_HANDLE_VALUE) { + return( 0L ); + } else { + FindClose( FindHandle ); + FileDateTime = 0L; + FileTimeToDosDateTime( &FindFileData.ftLastWriteTime, + ((LPWORD)&FileDateTime)+1, + (LPWORD)&FileDateTime + ); + + return( FileDateTime ); + } +} + +//+--------------------------------------------------------------------------- +// +// Function: DateTimeFile2 +// +// Synopsis: Get the timestamp on a file using the new GetFileAttributesExA +// +//---------------------------------------------------------------------------- + +ULONG +DateTimeFile2( + LPSTR DirName, + LPSTR FileName + ) +{ + char path[ DB_MAX_PATH_LENGTH ]; + WIN32_FILE_ATTRIBUTE_DATA FileData; + ULONG FileDateTime; + BOOL rc; + + if (DirName == NULL || DirName[0] == '\0') { + strcpy( path, FileName ); + } else { + sprintf( path, "%s\\%s", DirName, FileName ); + } + + rc = (*pGetFileAttributesExA) (path, GetFileExInfoStandard, (LPVOID)&FileData); + + if (!rc) { + return( 0L ); + } else { + FILETIME ftSystemTime; + SYSTEMTIME stSystemTime; + unsigned __int64 ui64Local, ui64File; + GetSystemTime(&stSystemTime); + SystemTimeToFileTime(&stSystemTime, &ftSystemTime); + + ui64Local = (((unsigned __int64) ftSystemTime.dwHighDateTime) << 32) + + (unsigned __int64) ftSystemTime.dwLowDateTime; + + ui64File = (((unsigned __int64) FileData.ftLastWriteTime.dwHighDateTime) << 32) + + (unsigned __int64) FileData.ftLastWriteTime.dwLowDateTime; + + // Take into account that file times may have two second intervals (0x989680 = 1 second) + // for FAT drives. + if (ui64File > (ui64Local + (0x989680*2))) { + BuildError("ERROR - \"%s\" file time is in the future.\n", path); + } + + FileDateTime = 0L; + FileTimeToDosDateTime( &FileData.ftLastWriteTime, + ((LPWORD)&FileDateTime)+1, + (LPWORD)&FileDateTime + ); + return( FileDateTime ); + } +} + +//+--------------------------------------------------------------------------- +// +// Function: DeleteSingleFile +// +// Synopsis: Delete the given file +// +//---------------------------------------------------------------------------- + +BOOL +DeleteSingleFile( + LPSTR DirName, + LPSTR FileName, + BOOL QuietFlag + ) +{ + char path[ DB_MAX_PATH_LENGTH * 2 + 1]; // ensure we have enough space for "DirName" + "\\" + "FileName" + + if (DirName) { + sprintf( path, "%s\\%s", DirName, FileName ); + } + else { + strcpy( path, FileName ); + } + if (!QuietFlag && fQuery) { + BuildMsgRaw("'erase %s'\n", path); + return( TRUE ); + } + + return( DeleteFile( path ) ); +} + + +//+--------------------------------------------------------------------------- +// +// Function: DeleteMultipleFiles +// +// Synopsis: Delete one or more files matching a pattern. +// +//---------------------------------------------------------------------------- + +BOOL +DeleteMultipleFiles( + LPSTR DirName, + LPSTR FilePattern + ) +{ + char path[ DB_MAX_PATH_LENGTH ]; + WIN32_FIND_DATA FindFileData; + HDIR FindHandle; + + sprintf( path, "%s\\%s", DirName, FilePattern ); + + if (fQuery) { + BuildMsgRaw("'erase %s'\n", path); + return( TRUE ); + } + + FindHandle = FindFirstFile( path, &FindFileData ); + if (FindHandle == (HDIR)INVALID_HANDLE_VALUE) { + return( FALSE ); + } + + do { + if (!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + DeleteSingleFile( DirName, FindFileData.cFileName, TRUE ); + } + } + while (FindNextFile( FindHandle, &FindFileData )); + + FindClose( FindHandle ); + return( TRUE ); +} + + +//+--------------------------------------------------------------------------- +// +// Function: CloseOrDeleteFile +// +//---------------------------------------------------------------------------- + +BOOL +CloseOrDeleteFile( + FILE **ppf, + LPSTR DirName, + LPSTR FileName, + ULONG SizeThreshold + ) +{ + ULONG Temp; + + if (*ppf == NULL) { + return TRUE; + } + + Temp = ftell( *ppf ); + fclose( *ppf ); + *ppf = NULL; + if (Temp <= SizeThreshold) { + return( DeleteSingleFile( DirName, FileName, TRUE ) ); + } + else { + CreatedBuildFile(DirName, FileName); + return( TRUE ); + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: PushCurrentDirectory +// +//---------------------------------------------------------------------------- + +LPSTR +PushCurrentDirectory( + LPSTR NewCurrentDirectory + ) +{ + LPSTR OldCurrentDirectory; + char path[DB_MAX_PATH_LENGTH]; + + GetCurrentDirectory(sizeof(path), path); + AllocMem(strlen(path) + 1, &OldCurrentDirectory, MT_DIRPATH); + strcpy(OldCurrentDirectory, path); + SetCurrentDirectory(NewCurrentDirectory); + return(OldCurrentDirectory); +} + + +//+--------------------------------------------------------------------------- +// +// Function: PopCurrentDirectory +// +//---------------------------------------------------------------------------- + +VOID +PopCurrentDirectory( + LPSTR OldCurrentDirectory + ) +{ + if (OldCurrentDirectory) { + SetCurrentDirectory(OldCurrentDirectory); + FreeMem(&OldCurrentDirectory, MT_DIRPATH); + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: CanonicalizePathName +// +// Synopsis: Take the given relative pathname and the current directory +// and obtain the full absolute path of the file. +// +// Arguments: [SourcePath] -- Relative path +// [Action] -- Canonicalizing flags +// [FullPath] -- [out] Full path of file or directory +// +// Returns: TRUE if canonicalization succeeded. +// +// Notes: [Action] indicates whether the function will fail if the +// resulting path is not of the correct type. CANONICALIZE_ONLY +// never fails, and CANON..._FILE or CANON..._DIR will fail if +// the resulting path is not of the specified type. +// +//---------------------------------------------------------------------------- + +BOOL +CanonicalizePathName( + LPSTR SourcePath, + UINT Action, + LPSTR FullPath + ) +{ + char PathBuffer[DB_MAX_PATH_LENGTH] = {0}, + *FilePart; + char *psz; + DWORD attr; + + if (!GetFullPathName( + SourcePath, + sizeof(PathBuffer), + PathBuffer, + &FilePart)) { + BuildError( + "CanonicalizePathName: GetFullPathName(%s) failed - rc = %d.\n", + SourcePath, + GetLastError()); + return( FALSE ); + } + CopyString(FullPath, PathBuffer, TRUE); + + if (Action == CANONICALIZE_ONLY) { + return( TRUE ); + } + + if ((attr = GetFileAttributes( PathBuffer )) == -1) { + UINT rc = GetLastError(); + + if (DEBUG_1 || + (rc != ERROR_FILE_NOT_FOUND && rc != ERROR_PATH_NOT_FOUND)) { + BuildError( + "CanonicalizePathName: GetFileAttributes(%s --> %s) failed - rc = %d.\n", + SourcePath, + PathBuffer, + rc); + } + return( FALSE ); + } + + if (Action == CANONICALIZE_DIR) { + if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) { + return(TRUE); + } + psz = "directory"; + } + else { + if ((attr & FILE_ATTRIBUTE_DIRECTORY) == 0) { + return(TRUE); + } + psz = "file"; + } + BuildError( + "CanonicalizePathName: %s --> %s is not a %s\n", + SourcePath, + PathBuffer, + psz); + return(FALSE); +} + +static char FormatPathBuffer[ DB_MAX_PATH_LENGTH ]; + +//+--------------------------------------------------------------------------- +// +// Function: FormatPathName +// +// Synopsis: Take a directory name and relative pathname and merges the +// two into a correctly formatted path. If the resulting path +// has the current directory as a component, the current +// directory part is removed. +// +// Arguments: [DirName] -- Directory +// [FileName] -- Pathname relative to [DirName] +// +// Returns: Resulting string (should not be freed). +// +// Notes: Example: DirName="f:\nt\private\foo\subdir1\subdir2" +// FileName="..\..\bar.c" +// CurrentDirectory="f:\nt\private" +// Result="foo\bar.c" +// +//---------------------------------------------------------------------------- + +LPSTR +FormatPathName( + LPSTR DirName, + LPSTR FileName + ) +{ + UINT cb; + LPSTR p; + + CopyString(FormatPathBuffer, CurrentDirectory, TRUE); + if (DirName && *DirName) { + if (DirName[1] == ':') { + p = FormatPathBuffer; + } + else + if (DirName[0] == '\\') { + p = FormatPathBuffer + 2; + } + else { + p = FormatPathBuffer + strlen(FormatPathBuffer); + *p++ = '\\'; + } + CopyString(p, DirName, TRUE); + } + p = FormatPathBuffer + strlen(FormatPathBuffer); + if (p[-1] != '\\') { + *p++ = '\\'; + *p = '\0'; + } + + if (FileName[1] == ':') { + p = FormatPathBuffer; + } + else + if (FileName[0] == '\\') { + p = FormatPathBuffer + 2; + } + else + if (!strncmp(FileName, ".\\", 2)) { + FileName += 2; + } + else + if (!strncmp(FileName, "..\\", 3)) { + do + { + p--; + while (*--p != '\\') { + if (p <= FormatPathBuffer) { + p = FormatPathBuffer; + break; + } + } + p++; + FileName += 3; + + } + while (!strncmp(FileName, "..\\", 3) && (p != FormatPathBuffer)); + } + CopyString(p, FileName, TRUE); + + cb = strlen(CurrentDirectory); + p = FormatPathBuffer + cb; + if (!fAlwaysPrintFullPath) { + if (!_strnicmp(CurrentDirectory, FormatPathBuffer, cb) && *p == '\\') { + return(p + 1); + } + } + return(FormatPathBuffer); +} + +//+--------------------------------------------------------------------------- +// +// Function: AppendString +// +//---------------------------------------------------------------------------- + +LPSTR +AppendString( + LPSTR Destination, + LPSTR Source, + BOOL PrefixWithSpace + ) +{ + if (Source != NULL) { + while (*Destination) { + Destination++; + } + if (PrefixWithSpace) { + *Destination++ = ' '; + } + while (*Destination = *Source++) { + Destination++; + } + } + return(Destination); +} + + +#if DBG +//+--------------------------------------------------------------------------- +// +// Function: AssertPathString +// +//---------------------------------------------------------------------------- + +VOID +AssertPathString(LPSTR pszPath) +{ + LPSTR p = pszPath; + + while (*p != '\0') { + if ((*p >= 'A' && *p <= 'Z') || *p == '/') { + BuildError("Bad Path string: '%s'\n", pszPath); + assert(FALSE); + } + p++; + } +} +#endif + + +//+--------------------------------------------------------------------------- +// +// Function: CopyString +// +//---------------------------------------------------------------------------- + +LPSTR +CopyString( + LPSTR Destination, + LPSTR Source, + BOOL fPath) +{ + UCHAR ch; + LPSTR Result; + + Result = Destination; + while ((ch = *Source++) != '\0') { + if (fPath) { + if (ch >= 'A' && ch <= 'Z') { + ch -= (UCHAR) ('A' - 'a'); + } else if (ch == '/') { + ch = '\\'; + } + } + *Destination++ = ch; + } + *Destination = ch; + return(Result); +} + + +//+--------------------------------------------------------------------------- +// +// Function: MakeString +// +//---------------------------------------------------------------------------- + +VOID +MakeString( + LPSTR *Destination, + LPSTR Source, + BOOL fPath, + MemType mt + ) +{ + if (Source == NULL) { + Source = ""; + } + AllocMem(strlen(Source) + 1, Destination, mt); + *Destination = CopyString(*Destination, Source, fPath); +} + + +//+--------------------------------------------------------------------------- +// +// Function: MakeExpandedString +// +//---------------------------------------------------------------------------- + +VOID +MakeExpandedString( + LPSTR *Destination, + LPSTR Source + ) +{ + AllocMem(strlen(Source) + strlen(NtRoot) + 1, Destination, MT_DIRSTRING); + sprintf(*Destination, "%s%s", NtRoot, Source); +} + + +//+--------------------------------------------------------------------------- +// +// Function: FreeString +// +//---------------------------------------------------------------------------- + +VOID +FreeString(LPSTR *ppsz, MemType mt) +{ + if (*ppsz != NULL) { + FreeMem(ppsz, mt); + } +} + + +//+--------------------------------------------------------------------------- +// +// Function: FormatNumber +// +//---------------------------------------------------------------------------- + +LPSTR +FormatNumber( + ULONG Number + ) +{ + USHORT i; + LPSTR p; + static char FormatNumberBuffer[16]; + + p = FormatNumberBuffer + sizeof( FormatNumberBuffer ) - 1; + *p = '\0'; + i = 0; + do { + if (i != 0 && (i % 3) == 0) { + *--p = ','; + } + i++; + *--p = (UCHAR) ((Number % 10) + '0'); + Number /= 10; + } while (Number != 0); + return( p ); +} + + +//+--------------------------------------------------------------------------- +// +// Function: FormatTime +// +//---------------------------------------------------------------------------- + +LPSTR +FormatTime( + ULONG Seconds + ) +{ + ULONG Hours, Minutes; + static char FormatTimeBuffer[16]; + + Hours = Seconds / 3600; + Seconds = Seconds % 3600; + Minutes = Seconds / 60; + Seconds = Seconds % 60; + + sprintf( FormatTimeBuffer, + "%2ld:%02ld:%02ld", + Hours, + Minutes, + Seconds + ); + + return( FormatTimeBuffer ); +} + + +//+--------------------------------------------------------------------------- +// +// Function: AToX +// +// Synopsis: Hex atoi with pointer bumping and success flag +// +// Arguments: [pp] -- String to convert +// [pul] -- [out] Result +// +// Returns: TRUE if success +// +//---------------------------------------------------------------------------- + +BOOL +AToX(LPSTR *pp, ULONG *pul) +{ + LPSTR p = *pp; + int digit; + ULONG r; + BOOL fRet = FALSE; + + while (*p == ' ') { + p++; + } + for (r = 0; isxdigit(digit = *p); p++) { + fRet = TRUE; + if (isdigit(digit)) { + digit -= '0'; + } else if (isupper(digit)) { + digit -= 'A' - 10; + } else { + digit -= 'a' - 10; + } + r = (r << 4) + digit; + } + *pp = p; + *pul = r; + return(fRet); +} + + +//+--------------------------------------------------------------------------- +// +// Function: AToD +// +// Synopsis: Decimal atoi with pointer bumping and success flag +// +// Arguments: [pp] -- String to convert +// [pul] -- [out] Result +// +// Returns: TRUE if success +// +//---------------------------------------------------------------------------- + +BOOL +AToD(LPSTR *pp, ULONG *pul) +{ + LPSTR p = *pp; + int digit; + ULONG r; + BOOL fRet = FALSE; + + while (*p == ' ') { + p++; + } + for (r = 0; isdigit(digit = *p); p++) { + fRet = TRUE; + r = (r * 10) + digit - '0'; + } + *pp = p; + *pul = r; + return(fRet); +} + +//+--------------------------------------------------------------------------- +// +// Logging and Display Functions +// +//---------------------------------------------------------------------------- + +VOID +__cdecl +LogMsg(const char *pszfmt, ...) +{ + va_list va; + + if (LogFile != NULL) { + va_start(va, pszfmt); + vfprintf(LogFile, pszfmt, va); + va_end(va); + } +} + + +VOID +EnterMessageMode(VOID) +{ + EnterCriticalSection(&TTYCriticalSection); + if (fConsoleInitialized && + (NewConsoleMode & ENABLE_WRAP_AT_EOL_OUTPUT) == 0) { + + SetConsoleMode( + GetStdHandle(STD_ERROR_HANDLE), + NewConsoleMode | ENABLE_WRAP_AT_EOL_OUTPUT); + } +} + + +VOID +LeaveMessageMode(VOID) +{ + if (fConsoleInitialized && + (NewConsoleMode & ENABLE_WRAP_AT_EOL_OUTPUT) == 0) { + + SetConsoleMode(GetStdHandle(STD_ERROR_HANDLE), NewConsoleMode); + } + LeaveCriticalSection(&TTYCriticalSection); +} + + +VOID +__cdecl +BuildMsg(const char *pszfmt, ...) +{ + va_list va; + + EnterMessageMode(); + + ClearLine(); + va_start(va, pszfmt); + fprintf(stderr, "BUILD: "); + vfprintf(stderr, pszfmt, va); + va_end(va); + fflush(stderr); + + LeaveMessageMode(); +} + + +VOID +__cdecl +BuildMsgRaw(const char *pszfmt, ...) +{ + va_list va; + + EnterMessageMode(); + + va_start(va, pszfmt); + vfprintf(stderr, pszfmt, va); + va_end(va); + fflush(stderr); + + LeaveMessageMode(); +} + + +VOID +__cdecl +BuildError(const char *pszfmt, ...) +{ + va_list va; + + EnterMessageMode(); + + ClearLine(); + va_start(va, pszfmt); + fprintf(stderr, "BUILD: "); + + if (Frb.fOpen) { + fprintf (stderr, "%s(%hu): ", Frb.pszFile, Frb.cLine); + } + + vfprintf(stderr, pszfmt, va); + va_end(va); + fflush(stderr); + + LeaveMessageMode(); + + if (LogFile != NULL) { + va_start(va, pszfmt); + fprintf(LogFile, "BUILD: "); + + if (Frb.fOpen) { + fprintf (LogFile, "%s(%hu): ", Frb.pszFile, Frb.cLine); + } + + vfprintf(LogFile, pszfmt, va); + va_end(va); + fflush(LogFile); + } +} + + +VOID +__cdecl +BuildErrorRaw(const char *pszfmt, ...) +{ + va_list va; + + EnterMessageMode(); + + va_start(va, pszfmt); + vfprintf(stderr, pszfmt, va); + va_end(va); + fflush(stderr); + + LeaveMessageMode(); + + if (LogFile != NULL) { + va_start(va, pszfmt); + vfprintf(LogFile, pszfmt, va); + va_end(va); + fflush(LogFile); + } +} diff --git a/sdktools/docs/build.cnt b/sdktools/docs/build.cnt new file mode 100644 index 0000000..e69de29 diff --git a/sdktools/docs/build.doc b/sdktools/docs/build.doc new file mode 100644 index 0000000000000000000000000000000000000000..d6eea84f66bbb168e90b6ef24761113411356b59 GIT binary patch literal 220672 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 z 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

=|ATQAarQGu& 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

$ZJzwbZY77J;maVMm$ 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 X`1{JTr&@3%ME&h2mGS=o-HPMf literal 0 HcmV?d00001 diff --git a/sdktools/docs/build.hpj b/sdktools/docs/build.hpj new file mode 100644 index 0000000..8d68f82 --- /dev/null +++ b/sdktools/docs/build.hpj @@ -0,0 +1,93 @@ +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; Help Project File for BUILD +; +; This file is maintained by RoboHELP. Do not modify this file directly. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + +[OPTIONS] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Options section contains the following information: +; +; The optional BMROOT= entry sets the directories in which the Help Compiler +; will look for graphics. +; +; The CONTENTS= tells WinHelp which topic contains the contents. +; +; The TITLE= is displayed in the Title Bar of WINHELP.EXE +; +; The BUILD= setting allows you to create different Help systems from +; the same source file. +; +; The COMPRESS= option tells the Help Compiler how much to compress +; the Help file. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +;BMROOT=C:\ROBOHELP +TITLE=Build Process +BUILD=WINDOWS +NOTES=1 + + +OLDKEYPHRASE=NO +OPTCDROM=0 +REPORT=YES +ERRORLOG=D:\builddocs\Build.ERR +CONTENTS=Contents +COMPRESS=12 +[BUILDTAGS] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Build Tags section specifies to the Help Compiler the names +; of all the valid build tags used in this Help project. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +WINDOWS + + +[CONFIG] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Config section defines macros which will run at startup. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + + + +[FILES] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Files section specifies the RTF files for a project. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + +BUILD.RTF +[ALIAS] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Alias section sets up aliases for Topic IDs in your Help system. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + +[MAP] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Map section specifies the project HH files. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + +[BITMAPS] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Bitmaps section specifies the referenced bitmaps used in +; your help system. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + + +[WINDOWS] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Windows section contains all of the information about the windows +; in a Help project. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +;Gloss = "Glossary",(100,100,350,350),0,(255,255,255),(255,255,255) + + +(w95sec)=,,20740,(r14745599),(r14745599),f2 +main="",,28164,(255,255,224),(128,255,255),f0 +[BAGGAGE] +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +; The Baggage section specifies any additional files. +;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + diff --git a/sdktools/docs/build.rbh b/sdktools/docs/build.rbh new file mode 100644 index 0000000..d823d51 --- /dev/null +++ b/sdktools/docs/build.rbh @@ -0,0 +1,27 @@ +[Project] +Help Compiler=HCW.EXE +Remove Unused=0 +Version=512 +ConvertedFromV1=0 +HasGlossary=0 +Automatic Map Files=0 +NextFile=2 +IncludeRTF=0 +Extra Language=0 +[Document Files] +BUILD.DOC=1 +[File Properties] +HasProperties=1 +BrowseType=0 +AutoMapFile=0 +StartingWith=0 +IncrementBy=20 +NextTopicNumber=0 +StartingNumber=1 +BrowseString=BUILD:0 +DefaultBuildTag= +[.RBH] +CopyTo=0 +PreBatch= +PostBatch= +AutoFixRTF=0 diff --git a/sdktools/docs/build.rta b/sdktools/docs/build.rta new file mode 100644 index 0000000000000000000000000000000000000000..60658803c5c9c05831bba5da4aca18aca908ae2c GIT binary patch literal 59 vcmWFvaWwD`H!#p=U|;~zPCy#OW@Q2ra1a#Y=It68?jPg=6gttP2$lc<{|yLH literal 0 HcmV?d00001 diff --git a/sdktools/docs/build.rtf b/sdktools/docs/build.rtf new file mode 100644 index 0000000..31a6172 --- /dev/null +++ b/sdktools/docs/build.rtf @@ -0,0 +1,1846 @@ +{\rtf1\ansi \deff7\deflang1033{\fonttbl{\f0\froman\fcharset0\fprq2 Tms Rmn;}{\f1\froman\fcharset2\fprq2 Symbol;}{\f2\fswiss\fcharset0\fprq2 Helv{\*\falt Arial};}{\f3\fmodern\fcharset0\fprq1 Courier;} +{\f4\froman\fcharset0\fprq2 Times New Roman;}{\f5\fswiss\fcharset0\fprq2 Arial;}{\f6\froman\fcharset0\fprq2 MS Serif;}{\f7\fswiss\fcharset0\fprq2 MS Sans Serif;}{\f8\froman\fcharset0\fprq2 Times;}{\f9\fswiss\fcharset0\fprq2 Helvetica;} +{\f10\fswiss\fcharset0\fprq2 System;}{\f11\fmodern\fcharset0\fprq1 Courier New;}{\f12\froman\fcharset0\fprq2 New York;}{\f13\fswiss\fcharset0\fprq2 Geneva;}{\f14\fswiss\fcharset0\fprq2 AvantGarde;}{\f15\froman\fcharset0\fprq2 ITC Bookman;} +{\f16\fswiss\fcharset0\fprq2 Helvetica-Narrow;}{\f17\froman\fcharset0\fprq2 NewCenturySchlbk;}{\f18\froman\fcharset0\fprq2 Palatino;}{\f19\froman\fcharset0\fprq2 ZapfChancery;}{\f20\fdecor\fcharset2\fprq2 ZapfDingbats;}{\f21\fnil\fcharset2\fprq2 Marlett;} +{\f22\fmodern\fcharset0\fprq1 Lucida Console;}{\f23\fnil\fcharset2\fprq2 Wingdings;}{\f24\fswiss\fcharset0\fprq2 Lucida Sans Unicode;}{\f25\fnil\fcharset0\fprq2 Bodoni-DTC;}{\f26\fnil\fcharset0\fprq2 Dom Casual;} +{\f27\fnil\fcharset0\fprq2 Fette Engschrift;}{\f28\fswiss\fcharset0\fprq2 Franklin Cond. Gothic;}{\f29\fswiss\fcharset0\fprq2 Franklin Gothic;}{\f30\fswiss\fcharset0\fprq2 Garrison Cond. Sans;}{\f31\fswiss\fcharset0\fprq2 Garrison ExtraBold Sans;} +{\f32\fswiss\fcharset0\fprq2 Garrison ExtraCond. Sans;}{\f33\fswiss\fcharset0\fprq2 Garrison Light Sans;}{\f34\fswiss\fcharset0\fprq2 Garrison Sans;}{\f35\froman\fcharset0\fprq2 Goudy Old Style;}{\f36\fdecor\fcharset0\fprq2 Kauflinn;} +{\f37\fnil\fcharset0\fprq2 Optimum;}{\f38\fdecor\fcharset0\fprq2 VAG Round;}{\f39\froman\fcharset0\fprq2 Village Square;}{\f40\fdecor\fcharset0\fprq2 Windsor;}{\f41\fswiss\fcharset0\fprq2 Arial Rounded MT Bold;}{\f42\fswiss\fcharset0\fprq2 Arial Narrow;} +{\f43\fswiss\fcharset0\fprq2 Arial Black;}{\f44\froman\fcharset0\fprq2 Book Antiqua;}{\f45\froman\fcharset0\fprq2 Bookman Old Style;}{\f46\fswiss\fcharset0\fprq2 Century Gothic;}{\f47\froman\fcharset0\fprq2 Century Schoolbook;} +{\f48\fnil\fcharset2\fprq2 Monotype Sorts;}{\f49\fswiss\fcharset0\fprq2 Haettenschweiler;}{\f50\fdecor\fcharset0\fprq2 Algerian;}{\f51\fdecor\fcharset0\fprq2 Braggadocio;}{\f52\fswiss\fcharset0\fprq2 Britannic Bold;} +{\f53\fscript\fcharset0\fprq2 Brush Script MT;}{\f54\fdecor\fcharset0\fprq2 Colonna MT;}{\f55\fdecor\fcharset0\fprq2 Desdemona;}{\f56\froman\fcharset0\fprq2 Footlight MT Light;}{\f57\froman\fcharset0\fprq2 Garamond;}{\f58\fswiss\fcharset0\fprq2 Impact;} +{\f59\fdecor\fcharset0\fprq2 Kino MT;}{\f60\froman\fcharset0\fprq2 Wide Latin;}{\f61\fscript\fcharset0\fprq2 Matura MT Script Capitals;}{\f62\fdecor\fcharset0\fprq2 Playbill;}{\f63\fmodern\fcharset2\fprq1 MS LineDraw;} +{\f64\froman\fcharset255\fprq2 Roman;}{\f65\fscript\fcharset255\fprq2 Script;}{\f66\fmodern\fcharset255\fprq2 Modern;}{\f67\fswiss\fcharset0\fprq1 MS Dialog;}{\f68\fswiss\fcharset0\fprq2 MS Shell Dlg;}{\f69\froman\fcharset0\fprq2 CG Times (WN);} +{\f70\fscript\fcharset238\fprq2 Phyllis ATT;}{\f71\fnil\fcharset0\fprq2 EmpireBuilder;}{\f72\fscript\fcharset0\fprq2 Comic Sans MS;}{\f73\froman\fcharset0\fprq2 Lucida Bright;}{\f74\fscript\fcharset0\fprq2 Lucida Calligraphy;} +{\f75\fscript\fcharset0\fprq2 Lucida Blackletter;}{\f76\fscript\fcharset0\fprq2 Monotype Corsiva;}{\f77\fswiss\fcharset0\fprq2 News Gothic MT;}{\f78\froman\fcharset2\fprq0 MT Symbol;}{\f79\froman\fcharset2\fprq2 Times New Roman Special G1;} +{\f80\fswiss\fcharset0\fprq0 Tahoma;}{\f81\fswiss\fcharset0\fprq2 Copperplate Gothic Bold;}{\f82\fscript\fcharset0\fprq2 Lucida Handwriting;}{\f83\fscript\fcharset0\fprq2 Mistral;}{\f84\froman\fcharset0\fprq2 Century;} +{\f85\fswiss\fcharset0\fprq2 Albertus Medium;}{\f86\fmodern\fcharset128\fprq2 \'82l\'82r \'82o\'83S\'83V\'83b\'83N;}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255; +\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;} +{\stylesheet{\ri130\sa240\widctlpar \f7\fs20 \snext0 Normal;}{\s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \sbasedon0\snext0 heading 1;}{\s2\li360\ri360\sb120\sa48\widctlpar \b\f7 \sbasedon0\snext0 heading 2;}{ +\s3\li115\ri130\sb240\sa60\keepn\widctlpar \b\f7 \sbasedon0\snext0 heading 3;}{\s4\li360\ri130\sa48\widctlpar \f7 \sbasedon0\snext0 heading 4;}{\s5\li115\ri130\sb240\sa60\widctlpar \f7\fs22 \sbasedon0\snext0 heading 5;}{ +\s6\li115\ri130\sb240\sa60\widctlpar \i\f7\fs22 \sbasedon0\snext0 heading 6;}{\s7\li115\ri130\sb240\sa60\widctlpar \f7\fs16 \sbasedon0\snext0 heading 7;}{\s8\li115\ri130\sb240\sa60\widctlpar \i\f7\fs16 \sbasedon0\snext0 heading 8;}{ +\s9\li115\ri130\sb240\sa60\widctlpar \i\f7\fs18 \sbasedon0\snext0 heading 9;}{\*\cs10 \additive Default Paragraph Font;}{\s15\ri130\sa240\widctlpar \f7\fs20 \sbasedon0\snext15 footnote text;}{\*\cs16 \additive\super \sbasedon10 footnote reference;}{ +\s17\qr\sb50\keep\keepn\widctlpar\noline\pvpara\phpg\posy0\absw540\dxfrtext180\dfrmtxtx180\dfrmtxty0{\*\pn \pnlvl10\pnstart1\pnhang}\hyphpar0 \f4\fs20\kerning20 \sbasedon0\snext0 Art Button,ab;}{\s18\ri130\sa240\widctlpar\tqc\tx4320\tqr\tx8640 \f7\fs20 +\sbasedon0\snext18 header;}{\s19\li302\ri130\sa240\widctlpar \f7\fs20 \sbasedon0\snext19 Topic Text Indent;}{\s20\li720\ri130\sa240\widctlpar \f7\fs20 \sbasedon0\snext20 Normal Indent;}{\s21\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 +\sbasedon1\snext0 Tip/Note Heading;}{\s22\li302\ri130\sa240\widctlpar \f7\fs20 \sbasedon0\snext22 Tip/Note Text;}{\s23\fi-187\li302\ri130\sa240\widctlpar\tx302{\*\pn \pnlvl11\pnf23\pnfs10\pnstart1\pnindent187\pnhang{\pntxtb n}}\f7\fs20 +\sbasedon22\snext23 Tip/Note Text Bulleted;}{\s24\fi-187\li302\ri130\sa240\widctlpar\tx302{\*\pn \pnlvl11\pnf23\pnfs10\pnstart1\pnindent187\pnhang{\pntxtb n}}\f7\fs20 \sbasedon0\snext24 Topic Text Bulleted;}{ +\s25\fi-187\li302\ri130\sa240\widctlpar\tx302{\*\pn \pnlvl10\pndec\pnb0\pni0\pnf5\pnfs16\pnstart1\pnindent187\pnhang}\f7\fs20 \sbasedon0\snext25 Topic Text Numbered;}{\s26\ri130\sa240\widctlpar\tqc\tx4320\tqr\tx8640 \f7\fs20 \sbasedon0\snext26 footer;}}{\*\revtbl {Unknown;}{Dee Christian (EDP) +;}{Don Goldberg (Wasser);}}{\info{\title Help Project generated with RoboHELP\'ae 95.}{\author Test}{\operator Test}{\creatim\yr1996\mo4\dy12\hr15\min25}{\revtim\yr1996\mo4\dy12\hr15\min55}{\printim\yr1996\mo4\dy5\hr10\min18}{\version3}{\edmins1}{\nofpages174}{\nofwords16322} +{\nofchars93037}{\*\company test}{\vern57443}}\widowctrl\ftnbj\aenddoc\noextrasprl\prcolbl\cvmme\sprsspbf\brkfrm\swpbdr\hyphcaps0\fracwidth \fet0{\*\template C:\\MSOffice\\Templates\\Robohelp.dot}\sectd \linex0\endnhere {\*\pnseclvl1 +\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta )}}{\*\pnseclvl5 +\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang +{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}\pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} + Contents}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super $} Contents}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Contents}} {\cs16\super +{\footnote \pard\plain +\s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} BUILD:0}} Contents +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Click on a topic formatted in green to view more information about that topic. +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}\pard \fi-360\li360\ri130\sa60\widctlpar\tx360{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}{\uldb\cf11 Getting Started}{\v Getting_Started} +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}{\uldb\cf11 Windows}{\f1\fs24\uldb\cf11 \'e2}{\uldb\cf11 NT}{\f1\fs24\uldb\cf11 \'e2}{\uldb\cf11 Directory Structure}{\v Directory_Structure} +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}{\uldb\cf11 Using the Build Utility}{\v Using_the_Build_Utility} +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}{\uldb\cf11 Building Multiple Targets from One Subdirectory}{\v Building_Multiple_Targets_from_One_Subdirectory} +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}{\uldb\cf11 Multi-processor Build Issues}{\v Multi_processor_Build_Issues} +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}{\uldb\cf11 Specifying Libraries}{\v Specifying_Libraries} +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}{\uldb\cf11 Precompiled Headers}{\v Precompiled_Headers} +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}{\uldb\cf11 Environment Variables}{\v Environment_Variables} +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}{\uldb\cf11 Macro Definitions}{\v Macro_Definitions} +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}{\uldb\cf11 Rules}{\v Rules} +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}{\uldb\cf11 Debugging}{\v Debugging} +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}{\uldb\cf11 Building Windows NT Software}{\v Building_NT_Software} +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}{\uldb\cf11 Building Chicago Software}{\v Building_Chicago_Software} +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}{\uldb\cf11 Building Win32 Subsystem Software}{\v Building_Win32_Subsystem_Software} +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}{\uldb\cf11 Frequently Asked Questions}{\v Frequently_Asked_Questions} +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}{\uldb\cf11 Glossary}{\v Glossary} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Getting_Started}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Getting Started}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Getting Started}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} BEGIN:0}} Getting Started + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 The Build Utility, {\i build.exe}, was created by{\i }{\uldb\cf11 Steve Wood}{\v Steve_Wood} it to build Windows\~ +NT. The Build Utility provides a structured way of building things. This is the default build process for Windows\~NT. Groups who use it enable the Windows\~NT group to be able to build with their group and to make changes to the group\rquote +s source files when needed. Other groups, such as the VC team, use the Build Utility for precisely this reason. Even though the VC team did not need the same multi-platform support for their build process as the build process for Windows\~ +NT needed, the Build Utility enabled them to override all the default settings for build.exe and still take advantage of Windows\~NT. +\par {\b See Also}\line {\uldb\cf11 Features}{\v Features}\line {\uldb\cf11 Why Use the Build Utility}{\v Why_use_the_Build_Utility}\line {\uldb\cf11 Where is the Build Utility Located}{\v Where_is_the_build_utility_located}\line {\uldb\cf11 Quick Start}{\v +Quick_Start} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Steve_Wood}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Steve Wood}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Steve Wood}} Steve Wood +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Steve Wood was one of the initial ten people working on Windows\~NT. They knew that t +hey were going to build something really, really big. Steve came from OS/2 where everyone used individual procedures for building products. In OS/2, there were the UI people, the base kernel people, and the net people, who all had their own way of doing t +hings. The build was tremendously difficult to coordinate. If you went to one subdirectory, you built a certain way, but if you went to another subdirectory, you built a different way. There were people in different geographic locations, all of them makin +g changes and none of them compatible with each other or working together. So Steve came from that environment and realized there was a need for something better. That\rquote s how the Build Utility came into being. +\par The question Steve asked was how could he abstract out all of this complicated gobbeldy-gook and put it in a master file? Steve noticed that nmake itself does not have some of the functions needed to build Windows\~ +NT: the ability to occasionally exclude directories or only build certain directories. He also wanted to have a way to have a global look at the whole tree for Windows\~ +NT. If a file changed anywhere in the tree, the developers could easily answer the question: \ldblquote What do we have to rebuild as a result of that change?\rdblquote +\par One of the things the Build Utility does is create a master database of all the inter-dependencies in the tree. This means you can go to any subdirectory, make a change to a file, and check it in. Then you can go to the top of the build tree for Windows\~ +NT, run build.exe, and anything in the tree that needs to be rebuilt, {\ul will} be rebuilt. You don\rquote t have to worry if you did the right thing. There would have been no way to build Windows\~NT without this type of structure and methodology. + +\par The Build Utility eliminates the requirement of testing every single release against every single platform. This requirement is not needed for Windows\~NT because Windows\~NT performs the same way on all platforms: Intel, Alpha, MIPS, and PowerPC. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Features}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Features}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Features}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} BEGIN:0}} Features +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 The Build Utility: +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}\pard \fi-360\li360\ri130\sa240\widctlpar\tx360{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}Automatically establishes file dependencies. +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}Provides tools to build products for multiple hardware platforms without specifying any target-specific information. +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}Shields you from the details of the various compilers and machine architectures. +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}Is multiprocessor aware for speedier compilation. +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}Provides feedback during compilation, including: \line \line * How much longer before the build will finish \line * How many lines are compiling\line * How fast it\rquote s compiling them\line +* How many files you have to link\line * How many targets you are creating +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}Provides detailed information about the build process. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Why_use_the_Build_Utility}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar +\f7\fs20 {\cs16\super $} Why use the Build Utility? }} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Why use the Build Utility? }} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super +} BEGIN:0}} Why Use the Build Utility? +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 The great benefit to using this Build Utility, rather than creating your own make or nmake files, is because: +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}\pard \fi-360\li360\ri130\sa240\widctlpar\tx360{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}} +The Build Utility isolates all target-dependent information in a centralized location (including header and library include paths, compiler names and switches, and linker switches). +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}You can build products for multiple hardware platforms without specifying any target-specific information. +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}The Build Utility ensures that everyone builds consistently. \line \line +This is important when you have multiple files to build, many .exe files that you are generating, and multiple developers working on a project, You never have to be specific places. Once you are set up in one subdirectory in Windows\~ +NT, you can build all your subdirectories using build.exe. For this reason, the Build Utility has been used successfully by the following groups: Exchange, VC, Media Foundation, and MSN. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Where_is_the_build_utility_located}} {\cs16\super ${\footnote \pard\plain +\s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super $} Where is the build utility located?}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Where is the build utility located?}} {\cs16\super +{\footnote \pard\plain +\s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} BEGIN:0}} Where Is the Build Utility Located? +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Every drop of Windows\~ +NT includes build.exe in the Internal Development Workstation (IDW) subdirectory. It also ships in the DDK as a tool for people who are writing device drivers. You can copy build.exe from the most recent build drop of Windows\~NT. {\f5 +The X86 version runs on Windows}{\f1\fs24 \'e2}{\f5 \~95}{\f1\fs24 \'e2}{\f5 as well as Windows\~NT. +\par }\pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Quick_Start}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Quick Start}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Quick Start}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} BEGIN:0}} Quick Start +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 The sources.tpl file is contained in this topic. It is a template that specifies the target component that you want to build and the list of sources files needed to build it. It also specif +ies optional compiler switches and libraries that are unique for the component being built. Follow the instructions in this topic to copy and edit this template so you can use it to run the Build Utility. +\par {\uldb\cf11 Steve Wood}{\v Steve_Wood} (stevewo) wrote sources.tpl in April of 1990, and it was later modified. There is a commented description of this file is in \\nt\\bak\\bin\\sources.tpl. For more detailed information, see {\uldb\cf11 +Getting Started. }{\v Getting_Started} +\par \pard\plain \s2\li360\ri360\sb120\sa48\widctlpar \b\f7 Instructions +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Here is what you need to do to get started using the Build Utility: +\par {\pntext\pard\plain\f7\fs20 1.\tab}\pard \fi-360\li475\ri130\sa240\widctlpar\tx475{\*\pn \pnlvlbody\pndec\pnstart1\pnindent360\pnhang{\pntxta .}}Choose {\b Edit, Copy} from the menu bar to copy this topic to the Clipboard. +\par {\pntext\pard\plain\f7\fs20 2.\tab}Paste this topic into a file using a text editor. +\par {\pntext\pard\plain\f7\fs20 3.\tab}Replace the xxxxx in the {\ul\cf11 MAJORCOMP}{\v MAJORCOMP} and {\ul\cf11 MINORCOMP}{\v MINORCOMP} macros below with your component's major and minor component name for example:\line \line MAJORCOMP=ntos, MINORCOMP=ke +\line \line {\b Note}: Do not type spaces surrounding the equal sign. +\par {\pntext\pard\plain\f7\fs20 4.\tab}Replace the xxxxx in the {\ul\cf11 TARGETNAME}{\v TARGETNAME} macro with your target name, for example:\line \line TARGETNAME={\i myprogram} +\par {\pntext\pard\plain\f7\fs20 5.\tab}Edit the {\ul\cf11 TARGETPATH}{\v TARGETPATH} and {\uldb\cf11 TARGETTYPE}{\v TARGETTYPE} macros to specify the location and type of the target. +\par {\pntext\pard\plain\f7\fs20 6.\tab}Edit the {\uldb\cf11 INCLUDES}{\v INCLUDES} macro if you have a private include directory to search. +\par {\pntext\pard\plain\f7\fs20 7.\tab}Carefully edit the {\ul\cf11 SOURCES}{\v SOURCES} macro so that it defines all the source files for the component that you are building. +\par {\pntext\pard\plain\f7\fs20 8.\tab}Remove these instructions and all comments. +\par {\pntext\pard\plain\f7\fs20 9.\tab}Save this file, naming it sources.tpl, and quit your text editor. +\par {\pntext\pard\plain\f7\fs20 10.\tab}Run the Build Utility from the command line by typing \ldblquote build\rdblquote and pressing{\b Enter}.\line From now on, you can run either build or nmake to build the component. +\par \pard \ri130\widctlpar # +\par # The MAJORCOMP and MINORCOMP variables are defined +\par # so that $(MAJORCOMP)$(MINORCOMP)filename can be used in +\par # cross compiling to provide unique filenames in a flat namespace. +\par # +\par MAJORCOMP=xxxxx +\par MINORCOMP=xxxxx +\par # +\par # The developer defines the TARGETNAME variable. It is the name of +\par # the target (component) that is being built by this makefile. +\par # It should {\ul not} include any path or filename extension. +\par # +\par TARGETNAME=xxxxx +\par # +\par # The developer defines the TARGETPATH and TARGETTYPE variables. +\par # The first variable specifies where the target will be built. The second specifies +\par # the type of target (either PROGRAM, DYNLINK, LIBRARY, UMAPPL_NOLIB or +\par # BOOTPGM). Use UMAPPL_NOLIB when you are only building user-mode +\par # programs and do not need to build a library. +\par # +\par TARGETPATH=obj +\par # Select one of the following, and delete the others: +\par TARGETTYPE=PROGRAM +\par TARGETTYPE=DYNLINK +\par TARGETTYPE=LIBRARY +\par TARGETTYPE=UMAPPL_NOLIB +\par TARGETTYPE=BOOTPGM +\par # +\par # The {\uldb\cf11 TARGETLIBS}{\v TARGETLIBS} macro specifies additional libraries to link against your target +\par # image. Each library path specification should contain an asterisk (*) +\par # where the machine-specific subdirectory name should go. +\par # +\par TARGETLIBS= +\par # +\par # The {\uldb\cf11 INCLUDES}{\v INCLUDES} variable specifies any include paths that are specific to +\par # this source directory. Separate multiple paths with single +\par # semicolons. Relative path specifications are okay. +\par # +\par INCLUDES=..\\inc +\par # +\par # The developer defines the {\ul\cf11 SOURCES}{\v SOURCES} macro. It contains a list of all the +\par # source files for this component. Specify each source file on a separate +\par # line using the line-continuation character. This minimizes merge +\par # conflicts if two developers are adding source files to the same component. +\par # +\par +\par SOURCES=source1.c \\ +\par source2.c \\ +\par source3.c \\ +\par source4.c +\par i386_SOURCES=i386\\source1.asm +\par ALPHA_SOURCES=alpha\\source1.s +\par MIPS_SOURCES=mips\\source1.s +\par PPC_SOURCES=ppc\\source1.s +\par # +\par # Next, specify options for the compiler using {\ul\cf11 C_DEFINES. }{\v CDEFINES} +\par # +\par C_DEFINES= +\par # +\par # Next, specify one or more user-mode test programs and their type. +\par # Use {\ul\cf11 UMTEST}{\v UMTEST} for optional test programs. Use {\uldb\cf11 UMAPPL}{\v UMAPPL} for +\par # programs that are always built when the directory is built. See also +\par # {\uldb\cf11 UMTYPE, }{\v UMTYPE} {\ul\cf11 UMBASE, }{\v UMBASE} and {\ul\cf11 UMLIBS. }{\v UMLIBS} +\par # +\par UMTYPE=nt +\par UMTEST=bunny*baz +\par UMAPPL=bunny*baz +\par UMBASE=0x1000000 +\par UMLIBS=obj\\*\\bunny.lib +\par # +\par # Defining either (or both) the variables {\uldb\cf11 NTTARGETFILE0}{\v NTTARGETFILE0} and/or {\ul\cf11 NTTARGETFILES}{\v NT_TARGETFILES} +\par # causes makefile.def to include .\\{\uldb\cf11 makefile.inc}{\v mk_inc} immediately after it +\par # specifies the top level targets (all, clean and loc) and their dependencies. +\par # The makefile.def file expands NTTARGETFILE0 as the first dependent for the +\par # "all" target and NTTARGETFILES as the last dependent for the "all" target. +\par # This is useful for specifying additional targets and dependencies that do not fit the +\par # general case covered by makefile.def. +\par # +\par # NTTARGETFILE0= +\par # NTTARGETFILES= +\par # For more information about the macros in this file, see {\uldb\cf11 Macro Definitions. }{\v Macro_Definitions} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Building_Multiple_Targets_from_One_Subdirectory}} {\cs16\super ${\footnote \pard\plain +\s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super $} Building Multiple Targets from One Subdirectory}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Building Multiple Targets from One Subdirectory}} {\cs16\super + +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} BEGIN:0}} Building Multiple Targets from One Subdirectory +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +In a typical build model, every subdirectory builds one target. The Build Utility gives you the advantage of having a single subdirectory where you can build multiple executable output files. The Build Utility supports a library-linked-to-main model, whic +h enables you to have one subdirectory that builds multiple targets that are very similar. This eliminates the need to move recursively through 10 different subdirectories to build 10 different .exe files when they are all pretty much the same except for +one source file that\rquote s different between them. +\par In a single subdirectory you can have a number of files that share some common subset of code. Each of them will have a single source file that will have the unique code for that product. If your build product consists of several source files, you can spe +cify all but the main source file as components of a library. The Build Utility links this library with the file containing main. +\par This model is especially useful in situations like in the tree for Windows\~NT tr +ee where you have a subdirectory or in which you are building UNIX tools that all have a common file I/O code, memory code, and registry code. Then they also have a little wrapper around it that implements the name, which is the thing specific to that too +l. What the Build Utility enables you to do is set up a target type of library in that subdirectory and use the use remote applications macro (UMAPPL) to specify the target names. +\par Consider, for example the simple UNIX commands tar, cat and grep: +\par \pard \li720\ri130\sa240\widctlpar UMAPPL=tar*cat*grep +\par \pard \ri130\sa240\widctlpar +Put all your common source files in the SOURCES macro. The Build Utility compiles all of those into a library, then compiles each one of the individual source files for tar.c, cat.c, and grep.c and links each of those against the common library that you b +uilt to produce tar.exe, cat.exe, and grep.exe. +\par {\b See Also}\line {\uldb\cf11 UMAPPL}{\v UMAPPL}\line {\uldb\cf11 SOURCES}{\v SOURCES} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} SOURCES_File}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} SOURCES File}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} SOURCES File}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} FILES:0}} sources File +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 You describe build products in a file named \ldblquote sources\rdblquote that resides in each source code subdirectory. The sources file contains a series of {\uldb\cf11 macro definitions}{\v Macro_Definitions} + that are recognized by the Build Utility. A sample of this file is contained in {\uldb\cf11 Quick Start. }{\v Quick_Start} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} binplace_exe}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} binplace.exe}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} binplace.exe}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} FILES:0}} binplace.exe +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Binplace.exe is the utility that the Build Utility uses to create the installable share point for the product. When you build an image, the Binplace Utility determines where that image will reside. +\par {\f5 The Build Utility only calls binplace.exe if }_NTTREE is defined before building. When enabled, the build process will run binplace.exe after building every{\f5 + image. If there are extra files you want distributed, use the MISCFILES macro to specify them in your sources file. +\par }BINPLACE_PLACEFILE is something you define when you do not want to have a public directory. The Build Utility expects to find this file in public, but if you do not want it there, you can override it with your own name. +\par The platform determines whether or not the Build Utility should run binplace. Binplace will be run if _NTTREE is defined, for example: +\par \pard \li720\ri130\sa240\widctlpar _NTMIPSTREE={\i root_of_the_ mips_release_tree}\line _NTALPHATREE={\i root_of_the_alpha_release_tree} \line _NT386TREE={\i root_of_the_x86_release_tree}\line _NTPPCTREE={\i root_of_the_ppc_release_tree} +\par \pard \ri130\sa240\widctlpar {\b See Also}\line {\ul\cf11 BINPLACE_FLAGS}{\v BINPLACE_FLAGS}\line {\uldb\cf11 NTDBGFILES}{\v NTDBGFILES}\line {\uldb\cf11 BINPLACE_PLACEFILE}{\v BINPLACE_PLACEFILE}\line +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} build_dat}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} build.dat}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} build.dat}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} FILES:0}} build.dat +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +When you use the Build Utility, it looks for a sources file and a dirs file. It processes the dependencies and builds a file called build.dat, which it puts in the NT subdirectory by default. Build.dat is basically a dump from build.exe o +f what the dependency graph looks like. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} DIRS_File}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} DIRS File}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} DIRS File}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} FILES:0}} dirs File +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 You can instruct the Build Utility to recursively build an entire source tree by using the {\i dirs} + file. The dirs file resides in a directory that contains subdirectories (that is, at the root of a source code tree or subtree). Each subdirectory can be a source directory or another source tree. You should place a dirs file at the root of each source c +ode subtree. Then go to the leaf node in each source code subdirectory and specify your build products in a {\i sources} file. To view a sample of a sources file, see {\uldb\cf11 Quick Start. }{\v Quick_Start} +\par You should define the following macros in your dirs file: +\par \trowd \trgaph108\trleft-108 \cellx1980\cellx8748 \pard \ri130\sa240\widctlpar\intbl DIRS\cell +This macro lists the directories that the Build Utility should always go into. Specify a list of subdirectories to be built unconditionally. Separate the entries in this list with spaces or tabs\line \cell \pard \widctlpar\intbl \row \trowd +\trgaph108\trleft-108 \cellx1980\cellx8748 \pard \ri130\sa240\widctlpar\intbl OPTIONAL_DIRS\cell This macro lists the directories that the Build Utility does not have to go into, and by default will not go into. Specify a list of subdirectories to be + built only if they are explicitly specified on the original build command line.\line \cell \pard \widctlpar\intbl \row \pard \ri130\sa240\widctlpar {\b\f5 Example}{\f5 : +\par }\pard \li720\ri130\sa240\widctlpar {\f5 DIRS=dir1 dir2 dir3\line OPTIONAL_DIRS=dir4 dir5 +\par }\pard \ri130\sa240\widctlpar {\f5 Build <}{\i\f5 currentdir}{\f5 >\\dir1 <}{\i\f5 currentdir}{\f5 >\\dir2 <}{\i\f5 currentdir}{\f5 >\\dir3 in that order, all the time. <}{\i\f5 currentdir}{\f5 >\\dir4 and <}{\i\f5 currentdir}{\f5 >\\ +dir5 will only be built if you specify them to build on the command line or in the }{\ul\cf11 BUILD_OPTIONS}{\v BUILD_OPTIONS}{\f5 environment variable. +\par The Build Utility supports a 'not' switch (~) for removing a directory from the default build. Using the above example, +\par }\pard \li720\ri130\sa240\widctlpar {\f5 build ~dir1 ~dir3 dir4 +\par }\pard \ri130\sa240\widctlpar {\f5 +would build only dir2 and dir4. If you follow a distinct pattern when naming your directories, it's trivial to use this to build multiple versions of a product. List the current version in the DIRS macro, the new or previous versions in the OPTIONAL_DIRS + macro. On your build machine, you can then build whichever version you want. +\par }\pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} makefile_def}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} makefile.def}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} makefile.def}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} FILES:0}} makefile.def +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 The Build Utility makes use of a generic makefile called makefile.def, which contains all the {\uldb\cf11 macro definitions}{\v Macro_Definitions} tha +t the sources file uses. (For an example of a sources file, see {\uldb\cf11 Quick Start}{\v Quick_Start} +.) The Build Utility sets the appropriate header and library include paths, compiler names and switches, and linker switches that are defined in makefile.def, and invokes nmake.exe. +\par The current version of makefile.def resides on \\\\orville\\razzel\\src\\public\\oak\\bin. +\par {\b Note}: You must use nmake version 1.30 or greater because earlier versions do not understand the message command and the Build Utility depends on a number of features that are only in version 1.30 or greater. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} makefile_plt}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} makefile.plt}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} makefile.plt}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} FILES:0}} makefile.plt +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +The platform-specific information for the makefiles is contained in makefile.plt. You can include makefile.plt in your own makefiles to select the build target and set platform-specific variables. For an example of this, see {\uldb\cf11 makefile.def}{\v +makefile_def}. The latest {\v copy of makefile.def} is stored on \\\\orville\\razzel\\src\\public\\oak\\bin. +\par There are three very useful macros in this file: +\par {\uldb\cf11 TARGET_DIRECTORY}{\v TARGET_DIRECTORY}\line {\ul\cf11 FREEBUILD}{\v FREEBUILD}\line {\ul\cf11 TARGET_CPP}{\v TARGET_CPP} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} makefile_tpl}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} makefile.tpl}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} makefile.tpl}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} FILES:0}} makefile.tpl +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 This is the template makefile. Nothing has to be in the makefile except: +\par }\pard \li720\ri130\sa240\widctlpar {\f5 !include $(NTMAKEENV)\\makefile.def +\par }\pard \ri130\sa240\widctlpar The complete text of makefile.tpl is as follows: +\par \pard \ri130\widctlpar # +\par # DO NOT EDIT THIS FILE!!! Edit .\\sources. if you want to add a new source +\par # file to this component. This file merely indirects to the real makefile +\par # that is shared by all the components of Windows\~NT and OS/2 +\par # +\par !INCLUDE $(NTMAKEENV)\\makefile.def +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} verrc_tpl}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} verrc.tpl}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} verrc.tpl}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} FILES:0}} verrc.tpl +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 Use this template file to add a version resource to an image. The final name would be something like . }The following is the complete text of verrc.tpl: +\par \pard \ri130\widctlpar /* +\par ** Template for version resources. Place this in your .rc file, +\par ** editing the values for VER_FILETYPE, VER_FILESUBTYPE, +\par ** VER_FILEDESCRIPTION_STR and VER_INTERNALNAME_STR as needed. +\par ** See winver.h for possible values. +\par ** +\par ** Ntverp.h defines several global values that do not need to be +\par ** changed except for official releases such as betas, SDK updates, etc. +\par ** +\par ** Common.ver has the actual version resource structure that all these +\par ** #defines eventually initialize. +\par */ +\par +\par /* #include needed if this will be the .rc file */ +\par +\par #include +\par +\par /*-----------------------------------------------*/ +\par /* the following lines are specific to this file */ +\par /*-----------------------------------------------*/ +\par +\par /* VER_FILETYPE, VER_FILESUBTYPE, VER_FILEDESCRIPTION_STR +\par * and VER_INTERNALNAME_STR must be defined before including COMMON.VER +\par * The strings do not need a '\\0', because common.ver has them. +\par */ +\par #define\tab VER_FILETYPE\tab VFT_DLL +\par /* possible values:\tab \tab VFT_UNKNOWN +\par \tab \tab \tab \tab VFT_APP +\par \tab \tab \tab \tab VFT_DLL +\par \tab \tab \tab \tab VFT_DRV +\par \tab \tab \tab \tab VFT_FONT +\par \tab \tab \tab \tab VFT_VXD +\par \tab \tab \tab \tab VFT_STATIC_LIB +\par */ +\par #define\tab VER_FILESUBTYPE\tab VFT2_UNKNOWN +\par /* possible values\tab \tab VFT2_UNKNOWN +\par \tab \tab \tab \tab VFT2_DRV_PRINTER +\par \tab \tab \tab \tab VFT2_DRV_KEYBOARD +\par \tab \tab \tab \tab VFT2_DRV_LANGUAGE +\par \tab \tab \tab \tab VFT2_DRV_DISPLAY +\par \tab \tab \tab \tab VFT2_DRV_MOUSE +\par \tab \tab \tab \tab VFT2_DRV_NETWORK +\par \tab \tab \tab \tab VFT2_DRV_SYSTEM +\par \tab \tab \tab \tab VFT2_DRV_INSTALLABLE +\par \tab \tab \tab \tab VFT2_DRV_SOUND +\par \tab \tab \tab \tab VFT2_DRV_COMM +\par */ +\par #define VER_FILEDESCRIPTION_STR "Version Checking and File Installation Libraries" +\par #define VER_INTERNALNAME_STR "VERSION.DLL" +\par #define VER_ORIGINALFILENAME_STR "VERSION.DLL" +\par +\par #include "common.ver" +\par \pard \ri130\sa240\widctlpar +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} mk_inc}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +$} makefile.inc}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} makefile.inc;mipsmk.inc;alphamk.inc;ppcmk.inc;i386mk.inc}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} + FILES:0}} makefile.inc +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 For each platform, there is a special {\i makefile.inc}: +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}\pard \fi-360\li475\ri130\sa240\widctlpar\tx475{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}mipsmk.inc +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}alphamk.inc +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}ppcmk.inc +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}i386mk.inc +\par \pard \ri130\sa240\widctlpar The current version of these files reside on \\\\orville\\razzel\\src\\public\\oak\\ +bin. In these files, there are optimization rules or assembler instructions that are specific for that target. There may also be extra link flags, resource compiler flags, or C preprocessor rules that are needed to make it all work. The {\i makefile} +.inc files are not something you would usually edit because there are macros to override all the settings in makefile.inc in your sources file. If you want to change optimization, use{\uldb\cf11 MSC_OPTIMIZATION. }{\v MSC_OPTIMIZATION} + If you want to change linker flags, use{\ul\cf11 LINKER_FLAGS. }{\v LINKER_FLAGS} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} ntverp}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +$} ntverp.h}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} ntverp.h;Master Version File}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} FILES:0}} ntverp.h +\par \pard\plain \ri130\sa240\widctlpar\tx2718\tx8856 \f7\fs20 This is the master version file for Windows\~NT, from which all of version resources are built. It's located in {\f5 \\\\orville\\razzle\\src\\public\\sdk\\inc} + (more conventionally known as in the public project in the \\sdk\\inc subdirectory). Every image has a version resource on it. When they release a build from the Windows\~ +NT Build Lab, they increase that master version number. Anything they link or build after that will automatically get a new version resource attached to it with the correct build number. +\par You can either use ntverp or the MASTER_VERSION_FILE macro to specify a different master version file. You do not have to have \\\\public\\sdk\\inc\\ntverp +.h. The VC team uses a different master version file because they have a different version scheme than Windows\~NT does. +\par If you look on the very last line of {\uldb\cf11 makefile.def}{\v makefile_def}, you will see the one place where {\uldb\cf11 MASTER_VERSION_FILE}{\v MASTER_VERSION_FILE} is used as a dependency for the resources. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} objects_mac}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} _objects.mac}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} _objects.mac}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} FILES:0}} _objects.mac +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 The Build Utility puts a file in the obj subdirectory called _objects.mac which contains the object dependencies for each platform.} If you type that file out, all you see is something like: +\par \pard \li720\ri130\sa240\widctlpar i386objects=i386\\x.obj i386\\y.obj +\par mipsobjects=mips\\x.obj mips\\y.obj +\par ppcobjects=ppc\\x.obj ppc\\y.obj +\par \pard \ri130\sa240\widctlpar This is something that the Build Utility creates. It is not something you need to edit. Every time the sources file gets updated, this file is regenerated. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Directory_Structure}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 +{\cs16\super $} Directory Structure}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Directory Structure}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} DIRSTR:0}} + Directory Structure +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Windows{\f1\fs24 \'e2}\~NT{\f1\fs24 \'e2} has a fixed directory tree. {\f5 The root of the build process is usually \\NT (you can change this if you set the }{\ul\cf11 BASEDIR}{\v BASEDIR} {\f5 +environment variable). Underneath are two subdirectories. Public, and Private. Public contains all the headers, libraries, build rules, etc shared by the source projects. Private contains all the source code. Each subcomponent in Windows\~ +NT has its own directory under private. The major components are: +\par }\trowd \trgaph108\trleft-108 \cellx1094\cellx4839 \pard \ri130\sa240\widctlpar\intbl {\f5 ntos\cell The kernel, core OS, and most drivers\cell }\pard \widctlpar\intbl {\f5 \row }\trowd \trgaph108\trleft-108 \cellx1094\cellx4839 \pard +\ri130\sa240\widctlpar\intbl {\f5 windows\cell The shell\cell }\pard \widctlpar\intbl {\f5 \row }\pard \ri130\sa240\widctlpar\intbl {\f5 ole\cell The OLE source\cell }\pard \widctlpar\intbl {\f5 \row }\pard \ri130\sa240\widctlpar\intbl {\f5 rpc\cell +RPC-related tools and libraries\cell }\pard \widctlpar\intbl {\f5 \row }\trowd \trgaph108\trleft-108 \cellx1094\cellx4839 \pard \ri130\sa240\widctlpar\intbl {\f5 sdktools\cell The source to all the tools\cell }\pard \widctlpar\intbl {\f5 \row }\pard +\ri130\sa240\widctlpar {\f5 +\par }Here is an example of the Windows\~NT directory structure: +\par \pard \ri130\widctlpar {\f5 nt +\par +---private +\par \'a6 +---csr +\par \'a6 \'a6 +---inc +\par \'a6 \'a6 +---server +\par \'a6 \'a6 +---alpha +\par \'a6 \'a6 +---daytona +\par \'a6 \'a6 +---i386 +\par \'a6 \'a6 +---km +\par \'a6 \'a6 +---mips +\par \'a6 \'a6 +---ppc +\par \'a6 +---dcomidl +\par \'a6 +---developr +\par \'a6 +---dfs +\par |... +\par | +\par +---public +\par +---oak +\par \'a6 +---bin +\par \'a6 \'a6 +---alpha +\par \'a6 \'a6 +---i386 +\par \'a6 \'a6 +---mips +\par \'a6 \'a6 +---ppc +\par \'a6 +---inc +\par +---sdk +\par \'a6 +---bin +\par \'a6 +---inc +\par \'a6 \'a6 +---chicago +\par \'a6 \'a6 +---crt +\par \'a6 \'a6 \'a6 +---mrc +\par \'a6 \'a6 \'a6 +---sys +\par \'a6 \'a6 +---gl +\par \'a6 \'a6 +---mfc40 +\par \'a6 \'a6 \'a6 +---l.chs +\par \'a6 \'a6 \'a6 +---l.deu +\par \'a6 \'a6 \'a6 +---l.esp +\par \'a6 \'a6 \'a6 +---l.fra +\par \'a6 \'a6 \'a6 +---l.ita +\par \'a6 \'a6 \'a6 +---l.jpn +\par \'a6 \'a6 \'a6 +---l.kor +\par \'a6 \'a6 \'a6 +---res +\par \'a6 \'a6 +---posix +\par \'a6 \'a6 +---sys +\par \'a6 +---lib +\par \'a6 +---alpha +\par \'a6 +---i386 +\par \'a6 +---mips +\par \'a6 +---ppc +\par }\pard \ri130\sa240\widctlpar {\f5 +---tools +\par }You can follow the directory structure that Windows\~NT uses for your own build process or you can specify the following macros in your sources file. These macros enable you to specify alternate object directories: +\par \pard \ri130\sa240\widctlpar\tx2718\tx8856 {\f5\ul\cf11 BINPLACE_PLACEFILE}{\v\f5 BINPLACE_PLACEFILE}{\f5 \line }{\f5\ul\cf11 COFFBASE_TXT_FILE}{\v\f5 COFFBASE_TXT_FILE}{\f5 \line }{\f5\ul\cf11 COMPILER_WARNINGS}{\v\f5 COMPILER_WARNINGS}{\f5 \line }{ +\ul\cf11 SDK_INC_PATH}{\v SDK_INC_PATH}\line {\ul\cf11 SDK_LIB_PATH}{\v SDK_LIB_PATH}\line {\ul\cf11 CRT_INC_PATH}{\v CRT_INC_PATH}\line {\ul\cf11 CRT_LIB_PATH}{\v CRT_LIB_PATH}\line {\f5\uldb\cf11 MASTER_VERSION_FILE}{\v\f5 MASTER_VERSION_FILE}{\f5 +\line }{\ul\cf11 OAK_INC_PATH}{\v OAK_INC_PATH}\line +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Using_the_Build_Utility}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar +\f7\fs20 {\cs16\super $} Using the Build Utility}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Using the Build Utility}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} + USING:0}} Using the Build Utility +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 The Build Utility enables you to build multiple pieces of your product in a logical way and exactly the same. In a typical development environment, you have everybody doing + their own sequence of steps to build their .exe files. The Build Utility eliminates all those differences. +\par {\f5 The files used by build.exe are}: +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}\pard \fi-360\li360\ri130\sa240\widctlpar\tx360{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}{\uldb\cf11 sources}{\v SOURCES_File} - {\f5 +lists the rules and macros. needed to build a specific component subdirectory.} +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}{\uldb\cf11 dirs}{\v DIRS_File} - contains macros called DIRS and OPTIONAL_DIRS that {\f5 specify the directories to open recursively and the order in which they should be opened.} +\par \pard \ri130\sa240\widctlpar Build.exe looks into the dirs file for the macros DIRS and OPTIONAL_DIRS. It then recurses to each directory li +sted where it might find another dirs file (indicating more directories to recurse into) or a sources file (indicating something needs to be built). If the latter, it looks for the macros SOURCES, INCLUDES, TARGETNAME, and TARGETPATH. These are parsed to + determine the dependencies, the list of files to build, and the end result. Normally, this information is then kept in a file called build.dat that the build utility will create for future reference. Depending on the options you pass to build, it does +the appropriate action and then calls a make program (For more information, see {\ul\cf11 BUILD_MAKE_PROGRAM}{\v BUILD_MAKE_PROGRAM}) to build the component. There are files (makefil0 and {\uldb\cf11 makefile.inc}{\v mk_inc} +) that build will recognize in special circumstances (for instance, only on a clean build or only when NTTARGETFILES is specified in the sources file). When the entire directory tree is built, build terminates. For an introduction to the Build Utility, s +ee {\uldb\cf11 Getting Started. }{\v Getting_Started} +\par Invoke build.exe with the \ldblquote -?\rdblquote option to display the following syntax and command line options: +\par \trowd \trgaph108\trleft-108 \cellx1080\cellx8748 \pard \sa240\widctlpar\intbl -b\cell Displays full error message text without truncating anything.\cell \pard \widctlpar\intbl \row \trowd \trgaph108\trleft-108 \cellx1080\cellx8748 \pard +\sa240\widctlpar\intbl -c\cell Deletes all object files.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -C\cell Deletes all .lib files only.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -e\cell +Generates the build.log, build.err, and build.wrn files.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -E\cell Always keep the log files.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -f\cell +Forces rescan of all source and include files.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -i\cell Ignores extraneous compiler warning messages. \cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -j {\i filename}\cell Use { +\i filename} as the name for log files. The j switch changes the first field, so it produces {\i filename}.log, {\i filename} +.wrn, and filename.err. Some people have it set up on their machine where they share their source drive and then they connect with their x86 or Alpha or MIPS and in each of those they set the j switch so they can build all those machines at the same time +across the net and produce the log, warning and error files for each platform\rquote s build.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -k\cell Keep out-of-date targets (do not delete them).\cell \pard \widctlpar\intbl \row \pard +\sa240\widctlpar\intbl -l\cell Link only, no compiles.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -L\cell Compile only, no link phase.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -M\cell Multiprocessor\cell \pard +\widctlpar\intbl \row \pard \sa240\widctlpar\intbl -m\cell Background mode; run build in the idle priority class.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -o\cell Display out-of-date files.\cell \pard \widctlpar\intbl \row \pard +\sa240\widctlpar\intbl -O\cell Generate obj\\_objects.mac file for current directory.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -p\cell Pause before compile and link phases.\cell \pard \widctlpar\intbl \row \pard +\sa240\widctlpar\intbl -P\cell Print elapsed time after every directory.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -q\cell Query only; do not run nmake.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -r {\i dirpath} +\cell Restarts clean build at specified path.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -s\cell Display status line at top of display.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -S\cell +Display status line with include file line counts.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -t\cell Display the first level of the dependency tree\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -T\cell +Display the complete dependency tree.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -$\cell Display the complete dependency tree hierarchically.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -v\cell +Enable include file version checking.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -w\cell Show warnings on screen.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -z\cell +No dependency checking or scanning of source files; one pass compile and link.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -Z\cell No dependency checking or scanning of source files; two passes.\cell \pard \widctlpar\intbl \row \pard +\sa240\widctlpar\intbl -why\cell List reasons for building targets.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -all\cell Same as specifying -386 , -mips, -alpha and -ppc\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl +-alpha\cell Build targets for Alpha.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -mips\cell Build targets for MIPS.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -386\cell Build targets for i386.\cell \pard +\widctlpar\intbl \row \pard \sa240\widctlpar\intbl -ppc\cell Build targets for PowerPC.\cell \pard \widctlpar\intbl \row \pard \sa240\widctlpar\intbl -x{\i filename}\cell Exclude include file from dependency checks.\cell \pard \widctlpar\intbl \row +\trowd \trgaph108\trleft-108 \cellx1080\cellx8748 \pard \sa240\widctlpar\intbl -nmake {\i arg}\cell Argument to pass to nmake.\cell \pard \widctlpar\intbl \row \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super # +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Multi_processor_Build_Issues}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super $} Multi-processor Build Issues}} {\cs16\super K{\footnote +\pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Multi-processor Build Issues;SYNCHRONIZE_DRAIN;SYNCHRONIZE_BLOCK}} Multi-processor Build Issues +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 There are two important multi-processor directives: SYNCHRONIZE_DRAIN and SYNCHRONIZE_BLOCK. Their syntax and meaning are as follows: +\par \trowd \trgaph108\trleft-108 \cellx2610\cellx7424 \pard \sa240\widctlpar\intbl {\f5 SYNCHRONIZE_DRAIN=1\cell Do not build this subdirectory until all the prior subdirectories are done.\cell }\pard \widctlpar\intbl {\f5 \row }\trowd \trgaph108\trleft-108 +\cellx2610\cellx7424 \pard \sa240\widctlpar\intbl {\f5 SYNCHRONIZE_BLOCK=1\cell Do not continue building until this subdirectory is done.\cell }\pard \widctlpar\intbl {\f5 \row }\pard \ri130\sa240\widctlpar +Use SYNCHRONIZE_DRAIN when you have a subdirectory that needs the results from a prior subdirectory on the {\ul same} pa +ss. For example, when building a DLL, you may have several subdirectories with TARGETTYPE=LIBRARY where each builds some component. You have another subdirectory with TARGETTYPE=DYNLINK, and the Build Utility will build a DLL that exports functions from t +he component libraries. In such a case, set LINKLIBS to the component libraries, make sure the DLL subdirectory is the last in the parent DIRS file, and add SYNCHRONIZE_DRAIN=1 to the sources file for the DLL. +\par Use SYNCHRONIZE_BLOCK when you have a subdirect +ory that other subdirectories require the results from in order to build. The usual example is a global precompiled header. List the precompiled directory first in the DIRS list, add SYNCHRONIZE_BLOCK=1 to that sources file, and the subsequent directories + that use the PCH will not be built until the PCH is created. +\par {\b Note}: Use these directives very sparingly because they completely stall an MP build when they're encountered. In most cases, the problem is not with the MP nature of the build, but rather the mac +ros used in the sources file. A common mistake is using LINKLIBS to specify import libraries when building a DLL. You almost never want to do this. LINKLIBS {\ul mus} +t exist during pass 1 because they're used to build the import library for the DLL. TARGETLIBS do not need to exist until pass 2 because they are only used to link the image. Use LINKLIBS for component libraries only. Use TARGETLIBS for import libraries. + +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Specifying_Libraries}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar +\f7\fs20 {\cs16\super $} Specifying Libraries}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Specifying Libraries}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} LIBR:0 +}} Specifying Libraries +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 Unlike some other environments that use }the LIB environment variable, the Build Utility always requires the full path to eliminate any ambiguity. +\par For instance, s{\f5 ome build processes rely on the linker to "}{\i\f5 figure out"}{\f5 + the correct libraries by using paths stored in the LIB environment variable and a list of default libraries stored in the objects. However, there's an inherent (and undesirable) side-effect in this approach because you never really know what library you +'re using, and controlling this on a per-library basis is difficult. For consistency, the Built Utility requ +ires you specify the full path to the library(s) and it will disable any default library lookup the linker might perform. Additionally, when specifying the libraries, you should try to abstract any absolute dependencies in the path. The build process pro +vides an asterisk to take the place of the platform. You can use }{\ul\cf11 BASEDIR}{\v BASEDIR} {\f5 macro to take the place for the root of the source tree. You can use the}{\f5\ul\cf11 }{\ul\cf11 SDK_LIB_PATH}{\f5\ul\cf11 }{\v\f5 SDK_LIB_PATH}{\f5 + if you don't want to rely on the Windows\~NT} {\uldb\cf11 directory structure. }{\v Directory_Structure} +\par Additionally, you should use an asterisk to indicate the target platform in the path. For instance, assume you're building a typical Win32 Windows exe. Normally, this would require you to link against kernel32.lib, user32.lib, gdi32.lib, and maybe a compo +nent library you built called mylib.lib. Here's what the {\uldb\cf11 TARGETLIBS}{\v TARGETLIBS} macro would look like: +\par \pard \li360\ri130\widctlpar {\f5 TARGETLIBS = \\ +\par $(BASEDIR)\\public\\sdk\\lib\\*\\kernel32.lib \\ +\par $(BASEDIR)\\public\\sdk\\lib\\*\\user32.lib \\ +\par $(BASEDIR)\\public\\sdk\\lib\\*\\gdi32.lib \\ +\par }\pard \li360\ri130\sa240\widctlpar {\f5 ..\\mylib\\obj\\*\\mylib.lib +\par }\pard \ri130\sa240\widctlpar When building on X86, this would mean the same as: +\par \pard \li360\ri130\widctlpar {\f5 TARGETLIBS = \\ +\par $(BASEDIR)\\public\\sdk\\lib\\i386\\kernel32.lib \\ +\par $(BASEDIR)\\public\\sdk\\lib\\i386\\user32.lib \\ +\par $(BASEDIR)\\public\\sdk\\lib\\i386\\gdi32.lib \\ +\par }\pard \li360\ri130\sa240\widctlpar {\f5 ..\\mylib\\obj\\i386\\mylib.lib +\par }\pard \ri130\sa240\widctlpar\tx4428\tx8856 {\b See Also}\line {\uldb\cf11 LINKLIBS}{\v LINKLIBS}\line {\uldb\cf11 TARGETLIBS}{\v TARGETLIBS}\line {\uldb\cf11 TARGETPATH}{\v TARGETPATH}\line {\ul\cf11 UMLIBS}{\v UMLIBS} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Precompiled_Headers}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 +{\cs16\super $} Precompiled Headers}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Precompiled Headers;Headers}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} HEADERS:0 +}} Precompiled Headers +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 The easiest way to use precompiled headers is to state in your sources file: +\par PRECOMPILED_INCLUDE={\i some_header_file_that_every_source_file_include}s +\par If you are building C++ code you state: +\par PRECOMPILED_CXX=1 +\par Then you are done! +\par {\cf1 Precompiled headers are put into the obj\\platform subdirectory by default or $(O). Therefore, they should not collide with simultaneous compilations. +\par }{\b See Also}\line {\ul\cf11 PRECOMPILED_CXX}{\v PRECOMPILED_CXX}\line {\ul\cf11 PRECOMPILED_INCLUDE}{\v PRECOMPILED_INCLUDE}\line {\ul\cf11 PRECOMPILED_OBJ}{\v PRECOMPILED_OBJ}\line {\ul\cf11 PRECOMPILED_TARGET}{\v PRECOMPILED_TARGET} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Environment_Variables}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar +\f7\fs20 {\cs16\super $} Environment Variables}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Environment Variables;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super ++} ENVVAR:00}} Environment Variables +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 You can set the following variables in your environment: +\par \pard \ri130\widctlpar {\ul\cf11 BUILD_OPTIONS}{\v BUILD_OPTIONS}\line {\ul\cf11 BUILD_DEFAULTS}{\v BUILD_DEFAULTS}\line {\uldb\cf11 BUILD_MAKE_PROGRAM}{\v BUILD_MAKE_PROGRAM}\line {\uldb\cf11 BUILD_DEFAULT_TARGETS}{\v BUILD_DEFAULT_TARGETS}\line { +\uldb\cf11 BUILD_ALT_DIR}{\v BUILD_ALT_DIR} +\par \pard \ri130\sa240\widctlpar +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} BUILD_ALT_DIR}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} BUILD_ALT_DIR}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} BUILD_ALT_DIR;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} ENVVAR:05}} + BUILD_ALT_DIR +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +Use this to specify an alternate object directory name. It must be ten characters or less and contain no spaces. The value is added to the end of the .obj name and (if no -j switch is used for build.exe) the logfile name, for example: +\par \pard \li720\ri130\sa240\widctlpar c:\\> set BUILD_ALT_DIR=Debug\line c:\\> build -MIPS -e +\par \pard \ri130\sa240\widctlpar Would generate objects in the objDebug\\ +mips subdirectory and logfiles named "buildDebug.log/buildDebug.wrn/buildDebug.err". If you do not set this, the default is nothing. Use this macro when you want to build the same source in different windows using different language, optim +izations, or debugging information. +\par \pard \ri130\sa240\widctlpar\tx2718\tx8856 This Build Alternate Directory macro was added to the Build Utility so the VC group could use the same build process as the Windows\~ +NT group. They wanted to be able to build debug and retail versions from the same subdirectory at the same time on the same machine. This macro enabled them to specify the output directory. Instead of always being OBJ{\i machine_name} +, it would be OBJ plus whatever they tacked onto this BUILD_ALT_DIR macro. That enabled them to specify a "D" for where the debug files went. They had another screen group that did retail builds. +\par You could extend this logic and make it one screen group that does USA and one that does Korean, or one that does optimize and one that does not, The only limitations on BUILD +_ALT_DIR are that it be less than 10 characters and it cannot have embedded spaces or dots. +\par \pard \ri130\sa240\widctlpar If you do not want to build using the same {\uldb\cf11 directory structure}{\v Directory_Structure} as the Windows\~NT group, specify the following macros and you do not need it any more. +\par \pard \ri130\sa240\widctlpar\tx2718\tx8856 {\f5\ul\cf11 BINPLACE_PLACEFILE}{\v\f5 BINPLACE_PLACEFILE}{\f5 \line }{\f5\ul\cf11 COFFBASE_TXT_FILE}{\v\f5 COFFBASE_TXT_FILE}{\f5 \line }{\f5\ul\cf11 COMPILER_WARNINGS}{\v\f5 COMPILER_WARNINGS}{\f5 \line }{ +\ul\cf11 SDK_INC_PATH}{\v SDK_INC_PATH}\line {\ul\cf11 SDK_LIB_PATH}{\v SDK_LIB_PATH}\line {\ul\cf11 CRT_INC_PATH}{\v CRT_INC_PATH}\line {\ul\cf11 CRT_LIB_PATH}{\v CRT_LIB_PATH}\line {\f5\uldb\cf11 MASTER_VERSION_FILE}{\v\f5 MASTER_VERSION_FILE}{\f5 +\line }{\ul\cf11 OAK_INC_PATH}{\v OAK_INC_PATH}\line +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} BUILD_DEFAULT_TARGETS}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar +\f7\fs20 {\cs16\super $} BUILD_DEFAULT_TARGETS}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} BUILD_DEFAULT_TARGETS}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} + ENVVAR:10}} BUILD_DEFAULT_TARGETS +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +Use this to specify the default target platform for which you are building. Assuming cross compilers existed, you could set it to -MIPS on an X86 and build MIPS binaries. Usually, you can just set it to the platform you're hosted on, for example: +\par \pard \ri130\widctlpar c:\\> build -mips +\par +\par means the same as: +\par +\par c:\\> set BUILD_DEFAULT_TARGETS=-mips +\par c:\\> build +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} BUILD_DEFAULTS}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} BUILD_DEFAULT}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} BUILD_DEFAULT}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} ENVVAR:15}} BUILD_DEFAULT + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Used this to specify options to build, for example: +\par \pard \ri130\widctlpar c:\\> build -eswM -nmake -i +\par +\par means the same as: +\par +\par c:\\> set BUILD_DEFAULT=-eswM -nmake -i +\par c:\\> build +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} BUILD_MAKE_PROGRAM}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} BUILD_MAKE_PROGRAM}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} BUILD_MAKE_PROGRAM}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} ENVVAR:20}} + BUILD_MAKE_PROGRAM +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 +Use this to specify the make program to execute. The default is nmake.exe, but if you want to use some other make program, just set this variable. You can specify the full path name to the make program, if desired. +\par }\pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} BUILD_OPTIONS}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} BUILD_OPTIONS}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} BUILD_OPTIONS}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} ENVVAR:25}} BUILD_OPTIONS + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this to specify the OPTIONAL_DIRS to process, for example: +\par \pard \ri130\widctlpar // DIRS file: +\par DIRS=dir1 dir2 dir3 +\par OPTIONAL_DIRS=OptDir1 OptDir2 OptDir3 +\par +\par c:\\> build OptDir1 OptDir2 OptDir3 +\par +\par means the same as: +\par +\par c:\\> set BUILD_OPTIONS=OptDir1 OptDir2 OptDir3 +\par c:\\> build +\par \pard \ri130\sa240\widctlpar +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Macro_Definitions}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Macro Definitions}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Macro Definitions}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + Macro Definitions +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +You set the variables for most of the following macros in a sources file; a few are set in your environment (for a list of these, see Environment Variables): Except for DIRS and OPTIONAL_DIRS, which are used by build.exe, these macros are all used by nmak +e. All that build.exe does is open all the files, figure out the dependencies, and then calls nmake. The other macros us +ed in the build process are all used by nmake. Here are all the macro names, how they are used and why you would want to put them in your sources file. +\par \pard \ri130\widctlpar {\uldb\cf11 INCLUDES}{\v INCLUDES} +\par {\uldb\cf11 SOURCES}{\v SOURCES} +\par {\uldb\cf11 TARGETEXT}{\v TARGETEXT} +\par {\uldb\cf11 TARGETNAME}{\v TARGETNAME} +\par {\uldb\cf11 TARGETPATH}{\v TARGETPATH} +\par {\uldb\cf11 TARGETTYPE}{\v TARGETTYPE} +\par {\uldb\cf11 UMAPPL}{\v UMAPPL} +\par {\uldb\cf11 UMAPPLEXT}{\v UMAPPLEXT} +\par {\uldb\cf11 UMLIBS}{\v UMLIBS} +\par \pard \ri130\sa240\widctlpar +\par Optional macros that you may want to define in your sources file include: +\par \pard \ri130\widctlpar {\uldb\cf11 BASEDIR}{\v BASEDIR} +\par {\uldb\cf11 BINPLACE_FLAGS}{\v BINPLACE_FLAGS} +\par {\uldb\cf11 BINPLACE_PLACEFILE}{\v BINPLACE_PLACEFILE} +\par {\uldb\cf11 C_DEFINES}{\v CDEFINES}{\uldb\cf11 +\par COFFBASE}{\v COFFBASE} +\par {\uldb\cf11 COFFBASE_TXT_FILE}{\v COFFBASE_TXT_FILE} +\par {\uldb\cf11 COMPILER_WARNINGS}{\v COMPILER_WARNINGS} +\par {\uldb\cf11 CRT_INC_PATH}{\v CRT_INC_PATH} +\par {\uldb\cf11 CRT_LIB_PATH}{\v CRT_LIB_PATH} +\par {\uldb\cf11 DEBUG_CRTS}{\v DEBUG_CRTS} +\par {\uldb\cf11 DLLBASE}{\v DLLBASE} +\par {\uldb\cf11 DLLDEF}{\v DLLDEF} +\par {\uldb\cf11 DLLENTRY}{\v DLLENTRY} +\par {\uldb\cf11 DLLLIBOBJECTS}{\v DLLLIBOBJECTS} +\par {\uldb\cf11 DLLORDER}{\v DLLORDER} +\par {\uldb\cf11 DRIVERBASE}{\v DRIVERBASE} +\par {\uldb\cf11 EXEPROFILEINPUT}{\v EXEPROFILEINPUT} +\par {\uldb\cf11 FREEBUILD}{\v FREEBUILD} +\par {\uldb\cf11 GPSIZE}{\v GPSIZE} +\par {\uldb\cf11 HALBASE}{\v HALBASE} +\par {\uldb\cf11 IDL_RULES}{\v IDL_RULES} +\par {\uldb\cf11 IDL_TYPE}{\v IDL_TYPE} +\par {\uldb\cf11 LANGUAGE}{\v LANGUAGE} +\par {\uldb\cf11 LINKER_FLAGS}{\v LINKER_FLAGS} +\par {\uldb\cf11 LINKER_NOREF}{\v LINKER_NOREF} +\par {\uldb\cf11 LINKLIBS}{\v LINKLIBS} +\par {\uldb\cf11 MAJORCOMP}{\v MAJORCOMP} +\par {\uldb\cf11 MAKEDLL}{\v MAKEDLL} +\par {\uldb\cf11 MASTER_VERSION_FILE}{\v MASTER_VERSION_FILE} +\par {\uldb\cf11 MFC_FLAGS}{\v MFC_FLAGS} +\par {\uldb\cf11 MFC_INC_PATH}{\v MFC_INC_PATH} +\par {\uldb\cf11 MFC_INCLUDES}{\v MFC_INCLUDES} +\par {\ul\cf11 MFC_LIB_PATH}{\v MFC_LIB_PATH} +\par {\uldb\cf11 MFC_LIBS}{\v MFC_LIBS} +\par {\ul\cf11 MFC_VER}{\v MFC_VER} +\par {\uldb\cf11 MIDL_OPTIMIZATION}{\v MIDL_OPTIMIZATION} +\par {\uldb\cf11 MIDL_UUIDDIR}{\v MIDL_UUIDDIR} +\par {\uldb\cf11 MINORCOMP}{\v MINORCOMP} +\par {\uldb\cf11 MISCFILES}{\v MISCFILES} +\par {\uldb\cf11 MSC_OPTIMIZATION}{\v MSC_OPTIMIZATION} +\par {\uldb\cf11 MSC_WARNING_LEVEL}{\v MSC_WARNING_LEVEL} +\par {\uldb\cf11 NOLINK}{\v NOLINK} +\par {\uldb\cf11 NOMFCPDB}{\v NOMFCPDB} +\par {\f5\ul\cf11 NO_NTDLL}{\v\f5 NO_NTDLL}{\uldb\cf11 +\par NOT_LEAN_AND_MEAN}{\v NOT_LEAN_AND_MEAN} +\par {\uldb\cf11 NT_INST}{\v NT_INST} +\par {\uldb\cf11 NT_UP}{\v NT_UP} +\par {\uldb\cf11 NTDBGFILES}{\v NTDBGFILES} +\par {\uldb\cf11 NTDEBUG}{\v NTDEBUG} +\par {\uldb\cf11 NTDEBUGTYPE}{\v NTDEBUGTYPE} +\par {\uldb\cf11 NTKEEPRESOURCETMPFILES}{\v NTKEEPRESOURCETMPFILES} +\par {\uldb\cf11 NTNOFUZZYLOOKUP}{\v NTNOFUZZYLOOKUP} +\par {\uldb\cf11 NTNOPCH}{\v NTNOPCH} +\par {\uldb\cf11 NTPFROFILEINPUT}{\v NTPROFILEINPUT} +\par {\uldb\cf11 NTTARGETFILE0}{\v NTTARGETFILE0} +\par {\uldb\cf11 NTTARGETFILE1}{\v NTTARGTFILE1} +\par {\uldb\cf11 NTTARGETFILES}{\v NT_TARGETFILES} +\par {\uldb\cf11 O}{\v O} +\par {\uldb\cf11 OAK_INC_PATH}{\v OAK_INC_PATH} +\par {\uldb\cf11 PASS0_CLIENTDIR}{\v PASS0_CLIENTDIR} +\par {\uldb\cf11 PASS0_HEADERDIR}{\v PASS0_HEADERDIR} +\par {\uldb\cf11 PASS0_SERVERDIR}{\v PASS0_SERVERDIR} +\par {\uldb\cf11 PASS0_SOURCEDIR}{\v PASS0_SOURCEDIR} +\par {\uldb\cf11 PNP_POWER}{\v PNP_POWER} +\par {\uldb\cf11 PRECOMPILED_CXX}{\v PRECOMPILED_CXX} +\par {\uldb\cf11 PRECOMPILED_INCLUDE}{\v PRECOMPILED_INCLUDE} +\par {\uldb\cf11 PRECOMPILED_OBJ}{\v PRECOMPILED_OBJ} +\par {\uldb\cf11 PRECOMPILED_TARGET}{\v PRECOMPILED_TARGET} +\par {\uldb\cf11 RC_COMPILER}{\v RC_COMPILER} +\par {\uldb\cf11 SDK_INC_PATH}{\v SDK_INC_PATH} +\par {\uldb\cf11 SDK_LIB_PATH}{\v SDK_LIB_PATH} +\par {\uldb\cf11 SOURCES_USED}{\v SOURCES_USED} +\par {\uldb\cf11 SUBSYSTEM_VERSION}{\v SUBSYSTEM_VERSION} +\par {\uldb\cf11 TARGET_CPP}{\v TARGET_CPP} +\par {\uldb\cf11 TARGET_DIRECTORY}{\v TARGET_DIRECTORY} +\par {\uldb\cf11 TARGETLIBS}{\v TARGETLIBS} +\par {\uldb\cf11 TARGETPATHLIB}{\v TARGETPATHLIB} +\par {\uldb\cf11 UMBASE}{\v UMBASE} +\par {\uldb\cf11 UMENTRY}{\v UMENTRY} +\par {\uldb\cf11 UMENTRYABS}{\v UMENTRYABS} +\par {\uldb\cf11 UMTEST}{\v UMTEST} +\par {\uldb\cf11 UMTYPE}{\v UMTYPE} +\par {\uldb\cf11 USE_CRTDLL}{\v USE_CRTDLL} +\par {\uldb\cf11 USE_INCREMENTAL_LINKING}{\v USE_INCREMENTAL_LINKING} +\par {\uldb\cf11 USE_LIBCNTPR}{\v USE_LIBCNTPR} +\par {\uldb\cf11 USE_MFCUNICODE}{\v USE_MFCUNICODE} +\par {\uldb\cf11 USE_MFC}{\v USE_MFC} +\par {\ul\cf11 USE_MFC30}{\v\f5 USE_MFC30}{\uldb\cf11 +\par USE_MSVCRT}{\v USE_MSVCRT} +\par {\uldb\cf11 USE_NATIVE_EH}{\v USE_NATIVE_EH} +\par {\uldb\cf11 USE_NOLIBS}{\v USE_NOLIBS} +\par {\uldb\cf11 USE_NTDLL}{\v USE_NTDLL} +\par {\uldb\cf11 USE_PDB}{\v USE_PDB} +\par {\uldb\cf11 USE_STATIC_MFC}{\v USE_STATIC_MFC} +\par {\uldb\cf11 USECXX_FLAG}{\v USECXX_FLAG} +\par {\uldb\cf11 USER_C_FLAGS}{\v USER_C_FLAGS} +\par {\uldb\cf11 USE_LIBCMT}{\v USE_LIBCMT} +\par {\uldb\cf11 USER_INCLUDES}{\v USER_INCLUDES} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} BASEDIR}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} BASEDIR}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} BASEDIR;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} BASEDIR +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 Use the BASEDIR macro when referring to the base of the source tree. By default, the source tree starts at $(_NTDRIVE)\\ +nt, but it's not required. By using BASEDIR to refer to the base, you abstract out this dependency. +\par Example +\par Instead of this: +\par TARGETLIBS=d:\\nt\\public\\sdk\\lib\\*\\kernel32.lib +\par Use this: +\par } TARGETLIBS=$(BASEDIR)\\public\\sdk\\lib\\*\\kernel32.lib +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} BINPLACE_FLAGS}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} BINPLACE_FLAGS}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} BINPLACE_FLAGS;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + BINPLACE_FLAGS +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify arguments that you want to pass to {\uldb\cf11 binplace.exe. }{\v binplace_exe} Type binplace-? to display a list of these switches. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} BINPLACE_PLACEFILE}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} BINPLACE_PLACEFILE}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} BINPLACE_PLACEFILE;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + BINPLACE_PLACEFILE +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify the placefile used by binplace. If nothing is listed, +\par $({\ul\cf11 BASEDIR}{\v BASEDIR})\\public\\sdk\\lib\\placefil.txt is used by default. +\par For more information, see {\uldb\cf11 binplace.exe. }{\v binplace_exe} +\par Set this macro if you don't use the Windows\~NT {\uldb\cf11 directory structure. }{\v Directory_Structure} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} CDEFINES}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} C_DEFINES}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} C_DEFINES;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} C_DEFINES +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify switches you want passed to the compiler. Typically, they are compiler #defines. +\par You might specify: +\par \pard \li720\ri130\sa240\widctlpar C_DEFINES = /DDEBUG_BUILD +\par \pard \ri130\sa240\widctlpar +to define DEBUG_BUILD to the compiler. There's no limit to what this #define can be except that C_DEFINES gets passed to the compiler and it also gets passed to the resource compiler. Therefore, you cannot put compiler optimization or other machine- +or tool-specific switches in the C_DEFINES macro. Instead, use one of the following macros for this: +\par {\uldb\cf11 MSC_OPTIMIZATION}{\v MSC_OPTIMIZATION}\line {\uldb\cf11 MSC_WARNING_LEVEL}{\v MSC_WARNING_LEVEL}\line {\ul\cf11 USER_C_FLAGS}{\v USER_C_FLAGS} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} COFFBASE}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} COFFBASE}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} COFFBASE;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} COFFBASE +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 Use this macro to specify the name to look up in }{\ul\cf11 COFFBASE_TXT_FILE. }{\v COFFBASE_TXT_FILE} If you do not specify a name, it defaults to the value of {\ul\cf11 TARGETNAME}{\v TARGETNAME} + (if building a DYNLINK) or{\f5 usermode (if you are building a UMAPPL, PROGLIB, or PROGRAM). If you want to specify an absolute base address for your image and not use a global file for all, see }{\uldb\cf11 DLLBASE}{\v DLLBASE} or {\uldb\cf11 UMBASE. +}{\v UMBASE} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} COFFBASE_TXT_FILE}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} COFFBASE_TXT_FILE}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} COFFBASE_TXT_FILE;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + COFFBASE_TXT_FILE +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 The name of the file passed to the linker with the base addresses for the images you build. By default, this is $({\ul\cf11 BASEDIR}{\v BASEDIR})\\public\\sdk\\lib\\ +coffbase.txt. The file should have three columns. The first is the name of the image. The second is the starting address for the image. The last is the maximum size of the image. There should also be an entry with the name "usermode" +that will be the default value. Here's an example: +\par \tab usermode\tab 0x60000000\tab 0x20000000 +\par \tab MyDll1\tab \tab 0x70000000\tab 0x00010000 +\par \tab MyDll2\tab \tab 0x70010000\tab 0x00010000 +\par Set this macro if you don't use the Windows NT {\uldb\cf11 directory structure. }{\v Directory_Structure} +\par The Build Utility assumes that coffbase.txt will be in \\\\public\\sdk\\lib and will be called coffbase.txt. You can override this filename and call it anything you want by using COFFBASE_TXT_FILE. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} COMPILER_WARNINGS}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} COMPILER_WARNINGS}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} COMPILER_WARNINGS;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + COMPILER_WARNINGS +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 The name of the warning file passed to the compiler with the /FI switch. By default, this is $({\ul\cf11 BASEDIR}{\v BASEDIR})\\public\\sdk\\inc\\warning.h. The file contains a list of comp +iler pragmas used to disable, enable, or promote warnings for the entire build. +\par Set this macro if you don't use the Windows\~NT {\uldb\cf11 directory structure}{\v Directory_Structure}. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} CRT_INC_PATH}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} CRT_INC_PATH}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} CRT_INC_PATH;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} CRT_INC_PATH + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Specifies the path to the C Runtime headers. The default is $({\ul\cf11 BASEDIR}{\v BASEDIR})\\public\\sdk\\inc\\crt. +\par Set this macro if you don't use the Windows\~NT {\uldb\cf11 directory structure. }{\v Directory_Structure} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} CRT_LIB_PATH}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} CRT_LIB_PATH}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} CRT_LIB_PATH;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} CRT_LIB_PATH + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify {\f5 the path to the C Runtime libraries . The default is $(}{\ul\cf11 BASEDIR}{\v BASEDIR}{\f5 )\\public\\sdk\\lib\\* +\par }Set this macro if you don't use the Windows\~NT {\uldb\cf11 directory structure}{\v Directory_Structure}. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} DEBUG_CRTS}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} DEBUG_CRTS}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} DEBUG_CRTS;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} DEBUG_CRTS +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +Whether you build checked or free system, the Build Utility always links against the retail runtime libraries and the retail MFC. If you want to link against the debug MFC and the debug runtime libraries, specify the following in your sources file or set +it in your environment variables before you build: +\par \pard \li720\ri130\sa240\widctlpar DEBUG_CRTS=1 +\par \pard \ri130\sa240\widctlpar For example, the VC team sets DEBUT_CRT=1 in a batch file that sets up for a debug build of the VC product because the VC team builds differently than the Windows\~NT team, and do not use the debug runtime libraries. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} DLLBASE}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} DLLBASE}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} DLLBASE;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} DLLBASE +\par \pard\plain \ri130\sa240\widctlpar\tx2718\tx8856 \f7\fs20 You only need to use this macro when your {\uldb\cf11 TARGETTYPE}{\v TARGETTYPE} + macro is set to DYNLINK. Use it to set the base address for the DLL image you are creating. If you do not specify an address, the Build Utility will assume that the target name in coffbase.txt is the name of your image. You can override this default targ +et name by specifying a target name with the DL +LBASE macro. You can set DLLBASE to be the hard-coded base address, a hex address, or you can leave it blank. If you leave it blank, the Build Utility will always look up the target name specified in coffbase.txt. +\par Example: If you are building kernel32.dll, the Build Utility will look up kernel32 in coffbase.txt to find that base address. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} DLLDEF}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +$} DLLDEF}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} DLLDEF;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} DLLDEF +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify the name of the .def file that the Build Utility will pass to the librarian when building the export and import files. If you do + not set this, the Build Utility will assume it is the same name as the image you are building. The most common usage is: +\par \pard \li720\ri130\sa240\widctlpar {\f5 DLLDEF=mydll.def +\par }\pard \ri130\sa240\widctlpar {\f5 Additionally, there is a standard inference rule that will run the C preprocessor over the .def or .src file in the current directory to create build-specific .def files in the object subdirectory. The same compiler } +defines {\f5 you key off of in your source code can be used in the root .def or .src file to create the export list. To enable it, use something like: +\par }\pard \li720\ri130\sa240\widctlpar {\f5 DLLDEF=$O\\mydll.def +\par }\pard \ri130\sa240\widctlpar {\f5 Here's an example of what mydll.src might look like: +\par }\pard \ri130\widctlpar {\f5 ; mydll.src +\par LIBRARY mydll +\par EXPORTS +\par +\par #if defined(_M_IX86) +\par X86Routine +\par #elseif defined(_M_MRX000) +\par MipsRoutine +\par #elseif defined(_M_ALPHA) +\par AlphaRoutine +\par #elseif defined(_M_PPC) +\par PPCRoutine +\par #else +\par #error Unknown platform +\par #endif +\par // Grab some other exports from another file +\par }\pard \ri130\sa240\widctlpar {\f5 #include "master.src" +\par }\pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} DLLENTRY}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} DLLENTRY}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} DLLENTRY;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} DLLENTRY +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify the DLL entry point. {\f5 By default, no entry point is assumed. For example, when you bring over programs that were built in the VC build environment or use the C Run-time, } +you will probably set: +\par \pard \li720\ri130\sa240\widctlpar DLLENTRY=_DllMainCRTStartup +\par \pard \ri130\sa240\widctlpar Look up the documentation on DLL entry point in the Win32 SDK to find the values to use. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} DLLLIBOBJECTS}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} DLLLIBOBJECTS}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} DLLLIBOBJECTS;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + DLLLIBOBJECTS +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify extra objects to add to an import library. +\par Usually, when the TARGETTYPE is DYNLINK, the end result is a DLL and an import library. If you want to have different LIB objects for each platform, you + can override this to create different platform-specific DLL LIB objects. DLLLIBOBJECTS enables you to specify additional objects to add to the import library. For example, you{\f5 + might have an OLE custom control (with GUIDs used to identify this control) that also exports a non-OLE C interface via an import library. Rather than build two separate libraries (for example, mydll.lib and myuuid.lib), you can list the GUID data object +(s) in DLLLIBOBJECTS. The result is a single library that all your users will link against. +\par }\pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} DLLORDER}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} DLLORDER}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} DLLORDER;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} DLLORDER +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +When you are building a DLL, you can specify an order file that will be passed to the linker. The order file lists the functions and the order in which they should be linked together. By default, the Build Utility passes the name of the DLL as the name of + the order file. For example, if you are building kernel32.dll, the Build Utility expects kernel32.prf as the order file. +\par You can use the DLLORDER macro to specify another name. The Build Utility will use whatever name you give + it. It can be in a different subdirectory, have a different name, or a different an extension. You can set DLLORDER to whatever you want it to be, and you can give it a fully qualified path name. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} DRIVERBASE}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} DRIVERBASE}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} DRIVERBASE;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} DRIVERBASE +\par \pard\plain \ri130\sa240\widctlpar\tx2718\tx8856 \f7\fs20 Similar to DLLBASE and UMBASE, use this macro to specify the base address for a driver. It's generally not necessary to set this because it will be relocated at run time anyway. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} EXEPROFILEINPUT}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} EXEPROFILEINPUT}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} EXEPROFILEINPUT;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + EXEPROFILEINPUT +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 This macro has been changed and is now exactly the same as {\uldb\cf11 NTPROFILEINPUT. }{\v NTPROFILEINPUT} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} FREEBUILD}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} FREEBUILD}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} FREEBUILD}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} FREEBUILD +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify whether your build is checked (debug) or free (retail). You can say, \ldblquote If $FREEBUILD, do things for a retail build.\rdblquote + Maybe you want to set a different set of flags or put it in a different place or compile a different way from a checked (or debug) build. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} GPSIZE}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +$} GPSIZE}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} GPSIZE;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} GPSIZE +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Specify a value for this macro in your sources file to control the GPSIZE switch to the linker. The GPSIZE is an optimization used on RISC platforms (on MIPS and PowerPC only). The value used for Windows\~ +NT is 32. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} HALBASE}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} HALBASE}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} HALBASE;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} HALBASE +\par \pard\plain \ri130\sa240\widctlpar\tx2718\tx8856 \f7\fs20 Similar to {\ul\cf11 DLLBASE}{\v DLLBASE} and {\ul\cf11 UMBASE, }{\v UMBASE} + use this macro to specify the base address for a HAL. It's generally not necessary to set this because it will be relocated at run time anyway. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} IDL_RULES}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} IDL_RULES}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} IDL_RULES;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} IDL_RULES +\par \pard\plain \ri130\sa240\widctlpar\tx2718\tx8856 \f7\fs20 This macro is only used for Cairo and OLE builds. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} IDL_TYPE}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} IDL_TYPE}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} IDL_TYPE;Macros;IDL Files}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} IDL_TYPE + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 When you specify an IDL file in your sources rule, you have to specify whether this is an OLE IDL or an RPC IDL because their syntax differs. Based on the syntax, the Build Utility passes different c +ommands to MIDL. The default for IDL_TYPE is OLE. Both of the following commands specify OLE: +\par \pard \li720\ri130\sa240\widctlpar IDL-TYPE=" "\line IDL_TYPE=ole +\par \pard \ri130\sa240\widctlpar Otherwise, specify RPC: +\par \pard \li720\ri130\sa240\widctlpar IDL_TYPE=rpc +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} INCLUDES}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} INCLUDES}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} INCLUDES;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} INCLUDES +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +Use this macro in your sources file to indicate to the Build Utility where to find the headers that you are including in your build. Specify a list of the paths to be searched for include files during compilation. Separate the entries in this list with a +semicolon. Path names can be absolute or relative, for example: +\par \pard \li720\ri130\sa240\widctlpar INCLUDES=bunny;inc +\par INCLUDES=.\\ +\par INCLUDES=.\\inc +\par \pard \ri130\sa240\widctlpar +The INCLUDES macro is read by the Build Utility. It looks at the INCLUDES variable that you specify in your sources file to figure out where to find the header files that you are including in your source code so it can build the dependency tree. +\par You will usually use the INCLUDES macro in your sources file to indicate to the Build Utility where to find the headers that you are including in your build. But there are times when some header files may not exist. Maybe they are built +as part of the build process. Specify those header files in {\uldb\cf11 USER_INCLUDES}{\v USER_INCLUDES}. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} LANGUAGE}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} LANGUAGE}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} LANGUAGE;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} LANGUAGE +\par \pard\plain \ri130\sa240\widctlpar\tx2718\tx8856 \f7\fs20 +Use this macro to specify the language when you set up dependencies so that you can include country-specific parts in your build. If you are building a product for the USA, you may want to include a USA icon, but if you are building for Korea, you would w +ant to use a Korean one. \line \line For example, the Exchange team used this macro because their directory tree was set up so that \\LANG\\LANGUAGE\\USA\\mainscree +n.bmp was used for their main splash screen. So they could just override LANGUAGE to build their product for Korea, Japan or any other country. They set LANGUAGE to something that was unique for them: KOR for Korean, JPN for Japan and GER for German. But +there is no limitation on what this can be so long as it makes sense in your build environment.\line \line The default is LANGUAGE=USA. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} LINKER_FLAGS}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} LINKER_FLAGS}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} LINKER_FLAGS;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} LINKER_FLAGS + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use the LINKER_FLAGS macro to override any default linker switch that you want to pass to the linker. Type l +ink-? to view a list of all the linker switches. This macro just gives you a way to pass in flags that you cannot pass in another way. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} LINKER_NOREF}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} LINKER_NOREF}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} LINKER_NOREF;Macros;OPTICAL_AND_REF}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0} +} LINKER_NOREF +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +Use this macro to turn off switches to the linker. The Build Utility turns some switches on, by default. One of them is the OPTICAL_AND_REF switch, which says, "Throw out everything that's not referenced in this module." This is the right thing to do if y +ou want small modules, but if you've got some debug routines in there that you want to call from the + debugger, it's kind of annoying to have them all thrown away on you. To avoid this, set LINKER_NOREF in your environment, rebuild your product, load it up in the debugger, and then run these functions that are only used in the debug scenario. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} LINKLIBS}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} LINKLIBS}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} LINKLIBS;Macros;PERFLIBS;TARGETLIBS}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + LINKLIBS +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use the LINKLIBS macro to specify libraries that you need to link against. LINKLIBS enables you to specify a macro called PERFLIBS, which are extra libraries you use for a performance case. +\par Example: The Windows\~NT Performance Lab people do that when they build the system to generate the BBT ordering files. They set PERFLIBS equal to some extra libraries that they want linked in to get some instrumentation stuff. +\par The only difference between TARGETLIBS and LINKLIBS is the ordering on the command line. LINKLIBS usually gets passed first; TARGETLIBS gets passed second. If you order them in your TARGETLIBS macro correctly, that shouldn't be a problem EXCEPT when you a +re building a DLL. When you are building a DLL, you may have some objects that you've buil +t, but you also have some other libraries that you want to export some features from. Maybe you go to subdirectory one and compile a number of objects into a library. In subdirectory two, you compile some more into a library. In subdirectory three, you ac +tually build the DLL, but it exports functions that are defined in library one or library two. So put those libraries in your LINKLIBS macro. +\par {\pntext\tab}\pard\plain \s17\sb50\widctlpar\noline\pvpara\phpg\posy0\absw540\dxfrtext180\dfrmtxtx180\dfrmtxty0{\*\pn \pnlvlbody\pnstart1\pnhang}\hyphpar0 \f4\fs20\kerning20 {\pard\plain +\s17\sb50\widctlpar\noline\pvpara\phpg\posy0\absw540\dxfrtext180\dfrmtxtx180\dfrmtxty0{\*\pn \pnlvlbody\pnstart1\pnhang}\hyphpar0 \f4\fs20\kerning20 {\object\objlink\rsltmerge\rsltbmp\objw0\objh0{\*\objclass }{\*\objdata 010500000100000010000000576f72642e446f63756d656e742e360021000000433a5c47554944455c5052494e545c444f435c4d5350524553535c432e414d5300080000004d414561727438000000000000000000 +020000000105000000000000}{\result {{\pict\wmetafile8\picw846\pich846\picwgoal480\pichgoal480 \picbmp\picbpp4 +010009000003220800000400d903000000001400000026060f001e00ffffffff040014000000576f72640e004d6963726f736f667420576f7264050000000b0200000000050000000c02640064000d000000fb020000000000000000000000000000000000010044040000002d0100000400000002010100040000002d0100 +0015000000fb02d6ff0000000000009001000000000400001254696d6573204e657720526f6d616e000000040000002d01010005000000090200000000040000000201010004000000020101000400000002010100030000001e0007000000160465006500000000000400000002010100040000002d010100030000001e00 +0700000016046400640000000000030000001e000700000016046400640000000000030000001e000700000012046400640064006400050000000c0264006400050000000b0200000000050000000b0200000000050000000c0218001800050000000b0200000000060000002606260002000100050000000b020000000005 +0000000c0220002000050000000b020000000005000000090200000000050000000102ffffff00040000000701030042010000430fc600880000002000200000000000200020000000000028000000200000002000000001000400000000000002000000000000000000000000000000000000000000001111110022222200 +33333300444444005555550066666600777777008888880099999900aaaaaa00bbbbbb00cccccc00dddddd00eeeeee00ffffff00fffff7777777777777777777777777ffffff777777777777777777777777777fff700000000000000000000000077777f7ffffffffffffffffffffffffc077777fffffffffffffffffffff +fffffc07777fffffffffffffffffffffffffff07777ffffffffffffc00cfffffffffff077f7ffffffffffff0000ffffffffffc077ff7fffffffffff0000ffffffffff077fff7fffffffffffc00cfffffffffc077ffff7fffffffffffffffffffffff077fffff7fffffffffff0ffffffffffc077ffffff7fffffffffc0cffff +fffff077fffffff7fffffffff707ffffffffc077ffffffff7ffffffff000ffffffff077fffffffff7fffffffc000cffffffc077ffffffffff7ffffff70007ffffff077fffffffffff7ffffff00000fffffc077ffffffffffff7fffff00000fffff077fffffffffffff7fffff00000ffffc077ffffffffffffff7ffff00000f +fff077fffffffffffffff7ffff00000fffc077ffffffffffffffff7fffc000cfff077fffffffffffffffff7ffffffffffc077ffffffffffffffffff7fffffffff077fffffffffffffffffff7ffffffffc077ffffffffffffffffffff7fffffff077fffffffffffffffffffff7ffffffc077ffffffffffffffffffffff7ffff +f077fffffffffffffffffffffff7ffffc07fffffffffffffffffffffffff7ffc0ffffffffffffffffffffffffffff777fffffffffffffffff000000026062500d501d301254d5345505320507265616d626c6520302030203234203234203020302033322033320d092f70705f736176652073617665206465660d092f7368 +6f7770616765207b7d206465660d093430206469637420626567696e202f70705f636c69702066616c736520646566202f70705f62626f782066616c7365206465660d092f46207b20706f70207d20646566202f53207b7d206465660d092f42207b207b202f70705f647931206578636820646566202f70705f6478312065 +786368206465660d09092020202f70705f647932206578636820646566202f70705f647832206578636820646566207d0d090973746f70706564206e6f74207b202f70705f62626f78207472756520646566207d206966207d206465660d092f4342207b207b202f70705f6379206578636820646566202f70705f63782065 +786368206465660d0909202020202f70705f636874206578636820646566202f70705f637764206578636820646566207d0d090973746f70706564206e6f74207b202f70705f636c6970207472756520646566207d206966207d206465660d092f70705f627831203020646566202f70705f627931203020646566202f7070 +5f62783220323420646566202f70705f627932203234206465660d00060000002606260002000000030000001e0007000000fc020100000000000000040000002d01020008000000fa02000000000000feffff00040000002d0103000400000004010b00070000001b042000200000000000040000002701ffff0600000026 +06260002000100d500000026062500a0019e010970705f636c69700d097b2070705f63782070705f6379206d6f7665746f2070705f637764203020726c696e65746f20302070705f63687420726c696e65746f0d09202070705f637764206e6567203020726c696e65746f20636c6970206e657770617468207d2069660d09 +70705f62626f78207b0d092f70705f6479322070705f6479322070705f64793120616464206465660d092f70705f6478322070705f6478322070705f64783120616464206465660d092f70705f73782070705f6478322070705f647831207375622070705f6278322070705f6278312073756220646976206465660d092f70 +705f73792070705f6479322070705f647931207375622070705f6279312070705f6279322073756220646976206465660d092f70705f74782070705f6478312070705f73782070705f627831206d756c20737562206465660d092f70705f74792070705f6479312070705f73792070705f627932206d756c20737562206465 +660d0970705f74782070705f7479207472616e736c6174652070705f73782070705f7379207363616c65207d2069660d656e640dd903000026062500a807a607252150532d41646f62652d312e300d0a2525426f756e64696e67426f783a203020302032342032340d0a25255363616c696e673a203130300d0a2525424954 +4d4150494e464f4845414445523a203332203332203420323034380d0a252543726561746f723a20466c6173682028313631353736290d0a2525456e64436f6d6d656e74730d0a3020736574677261790d0a3130206469637420626567696e0d0a63757272656e7473637265656e20706f7020706f70206475702031323020 +6c74207b706f70203132307d2069662025206e657720636f64650d0a3435207b20616273206578636820616273203220636f7079206164642031206774207b2031207375620d0a647570206d756c206578636820312073756220647570206d756c20616464203120737562207d207b20647570206d756c2065786368206475 +700d0a6d756c206164642031206578636820737562207d206966656c7365207d2073657473637265656e0d0a2f77426d7020313620737472696e67206465660d0a3234203234207363616c650d0a33322033322034205b333220302030203332203020305d0d0a2f6368203120737472696e6720646566202f7262207b2063 +757272656e7466696c652063682072656164686578737472696e6720706f7020706f70206e207b2077426d70206c2063680a707574696e74657276616c202f6c206c20312061646420646566207d20726570656174207d20646566202f6e62207b202f6e206e203132372073756220646566206e207b2063757272656e7466 +696c650a63682072656164686578737472696e6720706f7020706f702077426d70206c20636820707574696e74657276616c202f6c206c20312061646420646566207d20726570656174207d20646566202f67730a7b202f6c203020646566207b202f6e2063757272656e7466696c6520746f6b656e20706f702064656620 +6e20313237206774207b6e627d207b72627d206966656c7365206c2031362065710a7b657869747d206966207d206c6f6f70207d20646566202f72203020646566202f63203020646566207b20632030206571207b202f722063757272656e7466696c6520746f6b656e20706f70206465660a6773207d206966202f632063 +2031206164642064656620632072206571207b2f632030206465667d2069662077426d70207d20696d6167650a31203133302046464646463720313220373720313238204646203120313239204646464620313320373720313238203746203120313239204646373020313120303020313330203037373737370a31203132 +38204637203132204646203133302043303737373720312031323820374620313220464620313330204643303737372031203132382037462031332046462031323920303737372031203132382037460a35204646203133302046433030434620352046462031323920303737462031203132382037462035204646203133 +3020463030303046203420464620313330204643303737462031203132382046370a35204646203133302046303030304620342046462031333020463037374646203120313238204637203520464620313330204643303043462034204646203133302043303737464620312031323920464637460a313120464620313330 +203037374646462031203132392046463746203520464620313238203046203420464620313331204643303737464646203120313239204646463720342046462031323920464330430a3420464620313331204630373746464646203120313239204646463720342046462031323920463730372034204646203133312043 +3037374646464620312031333520464646463746464646464646463030300a34204646203133312030373746464646462031203134332046464646374646464646464643303030434646464646464330373746464646462031203134332046464646463746464646464637303030374646464646463037374646464646460a +31203134332046464646463746464646464630303030304646464646433037374646464646462031203134332046464646464637464646464630303030304646464646303737464646464646460a31203134332046464646464637464646464630303030304646464643303737464646464646462031203133392046464646 +46464637464646463030303030464646463037370a342046462031203133392046464646464646374646464630303030304646464330373720342046462031203420464620313335203746464643303030434646463037374620342046460a3120342046462031323820374620342046462031333020464330373746203420 +464620312034204646203132382046372034204646203132392046303737203520464620312034204646203132382046370a342046462031323920433037372035204646203120352046462031333320374646464646464630373746203520464620312035204646203133332037464646464646433037374620352046460a +3120352046462031333220463746464646463037372036204646203120352046462031333220463746464646433037462036204646203120362046462031333020374646433046203720464620310a36204646203132392046373737203820464620656e640a2525456e64496d616765446174610a06000000260626000200 +0000160000002606250021001f00254d5345505320547261696c65720d70705f7361766520726573746f72650d00040000002701ffff040000002701ffff040000002701ffff0400000002010100040000002701ffff040000002d01000003000000000050436f6c6f724374726c0000002c00700014000800600200000050 +4300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff}}}}} +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\b\cf6 Caution!} The LINKLIB +S macro requires that the library has to be around in pass one of the build, because the Build Utility builds the import libraries during pass one. You must structure your build in such a manner that the libraries will be guaranteed to exist during pass o +ne. You should never specify an import library in your LINKLIBS macro, mainly because you can get into some real nasty cases where you export something that you've imported from somebody else instead of what you actually had, perhaps with typos or whateve +r. + You may not realize this until suddenly your program starts acting really weird. Stick with the rule that you use TARGETLIBS everywhere. There is TARGETLIBS and There is LINKLIBS; if you use TARGETLIBS for everything, life is good. (To avoid problems whe +n doing multi-processor builds, see {\uldb\cf11 Multi-processor Build Issues}{\v Multi_processor_Build_Issues}.) +\par Use LINKLIBS only for the case that meets the following conditions: +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}\pard \fi-360\li360\ri130\sa240\widctlpar\tx360{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}You are building a dynamic link. +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}You are exporting something that's defined in some other component library that you also build. +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}In your dirs file in the subdirectory above, you have ordered it so that the component libraries are around before you build the dynamic link. +\par \pard \ri130\sa240\widctlpar There is a similar macro called {\uldb\cf11 UMLIBS}{\v UMLIBS} that you can use if you are building UMAPPLs. +\par {\b See Also}\line {\uldb\cf11 TARGETLIBS}{\v TARGETEXT} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} MAJORCOMP}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} MAJORCOMP}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} MAJORCOMP;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} MAJORCOMP +\par \pard\plain \ri130\sa240\widctlpar\tx4428\tx8856 \f7\fs20 Use this major component macro to specify the first part of a filename you are building for use by the MIPS compiler. Use the MINORCOMP macro to specify the minor component filename. +\par For example, when you build the kernel for Windows\~NT, you specify: +\par \pard \li720\ri130\sa240\widctlpar MAJORCOMP=ntos\line MINORCOMP=drivers +\par \pard \ri130\sa240\widctlpar\tx4428\tx8856 You can use this if you have global sources file or a global rules file. You can state: +\par \pard \ri130\sa240\widctlpar \tab If MAJORCOMP={\i something} +\par \pard \ri130\sa240\widctlpar\tx4428\tx8856 Then do something you might do for all your NTOS things, but: +\par \pard \ri130\sa240\widctlpar \tab If MAJORCOMP=somethingelse +\par \pard \ri130\sa240\widctlpar\tx4428\tx8856 Then do something you might do for all your drivers. +\par {\b Note}: This macro is required for MIPS and ALPHA builds. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} MAKEDLL}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} MAKEDLL}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} MAKEDLL;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} MAKEDLL +\par \pard\plain \ri130\sa240\widctlpar\tx2718\tx8856 \f7\fs20 The build process is a two-pass build. In the first pass, the Build Utility compiles all th +e source files, and creates import libraries and component libraries. In the second pass, it links everything against those libraries. The default, which directs the Build Utility to make the second pass, is as follows: +\par \pard \li720\ri130\sa240\widctlpar MAKEDLL=1 +\par \pard \ri130\sa240\widctlpar\tx2718\tx8856 You typically would not set this for yourself. You might do a test in your makefile to say: +\par \pard \li720\ri130\sa240\widctlpar IF MAKEDLL=1\line {\i do things that you want to do on the second pass of the build} +\par \pard \ri130\sa240\widctlpar\tx2718\tx8856 A more frequent use of this macro is to run nmake from the command line to run the compile and link without having to run build.exe: +\par \pard \li720\ri130\sa240\widctlpar nmake MAKEDLL=1 +\par \pard \ri130\sa240\widctlpar\tx2718\tx8856 The Build Utility will then do the compile and the link all in one step without having to run build.exe. This works because all that build.exe does is figure out dependencies and call nmake. This works when: + +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}\pard \fi-360\li360\ri130\sa240\widctlpar\tx360{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}You know the dependencies. +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}The source file has changed and you do not care about the header file dependency generation. +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}You are in a leaf node subdirectory. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} MASTER_VERSION_FILE}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 +{\cs16\super $} MASTER_VERSION_FILE}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} MASTER_VERSION_FILE;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + MASTER_VERSION_FILE +\par \pard\plain \ri130\sa240\widctlpar\tx2718\tx8856 \f7\fs20 Every image has a version resource on it. When they release a built from the Windows\~ +NT Build Lab, they increase the master version number. Anything they link or build after that will automatically get a new version resource attached to it with the correct build number. +\par You can go into the File Manager or Windows Explorer or you can run filever.exe to view properties and see which version resource setup uses when it copies that image onto a new system. The system checks whether or not the version resource is newer than t +he one already on the system. If it is, it is copied onto the system, otherwise it is not. +\par There is a master version file for Windows\~NT, from which all version resources are built. The Master Version File for Windows\~NT is called ntverp and it's located in \\\\public\\sdk\\ +inc. You can either use ntverp or use the MASTER_VERSION_FILE macro to specify a different master version file. You do not have to have \\\\public\\sdk\\inc\\ +ntverp.h. The VC team uses a different master version file because they have a different version scheme than the Windows\~NT group does. +\par If you look on the very last line of {\uldb\cf11 makefile.def}{\v makefile_def} +, you will see the one place where MASTER_VERSION_FILE is used as a dependency for the resources. The TARGET_DIRECTORY macro is always dependent on the master version file to determine what the name of the resource is for your image. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} MFC_FLAGS}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} MFC_FLAGS}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} MFC_FLAGS;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} MFC_FLAGS +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +If you have extra command line options you want to pass to the compiler, you can put them in MFC_FLAGS. They will only affect programs that use MFC. That would be useful if you had a global project. You could set + MFC_FLAGS equal to some macro name or compiler #define that you want to add. There are other ways to handle that, however, for example by using the {\uldb\cf11 C_DEFINES}{\v CDEFINES} macro. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} MFC_INC_PATH}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} MFC_INC_PATH}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} MFC_INC_PATH;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} MFC_INC_PATH + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify {\f5 the path to the MFC headers. The default is: +\par }\pard \li720\ri130\sa240\widctlpar {\f5 $(}{\ul\cf11 BASEDIR}{\v BASEDIR}{\f5 )\\public\\sdk\\inc\\mfc$(}{\ul\cf11 MFC_VER}{\v MFC_VER}{\f5 ) +\par }\pard \ri130\sa240\widctlpar Set this macro if you don't use the Windows\~NT {\uldb\cf11 directory structure. }{\v Directory_Structure} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} MFC_INCLUDES}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} MFC_INCLUDES}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} MFC_INCLUDES;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} MFC_INCLUDES + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 If you have your own MFC include files, use this macro to specify where you put your MFC headers on your system. This is another macro you might use if you choose not to follow the same {\uldb\cf11 +directory structure. }{\v Directory_Structure} as{\v }Windows NT uses. +\par For example, the MSN group has their own MFC libraries. They do not use the ones from Windows\~NT. They do not use the public directory. So, they specify their MFC_INCLUDES to be wherever they put their MFC headers on their systems. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} MFC_LIB_PATH}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} MFC_LIB_PATH}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} MFC_LIB_PATH;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} MFC_LIB_PATH + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 Use this macro to specify the path to the MFC libraries. The default is $(}{\ul\cf11 BASEDIR}{\v BASEDIR}{\f5 )\\public\\sdk\\lib\\* +\par }Set this macro if you don't use the Windows\~NT {\uldb\cf11 directory structure. }{\v Directory_Structure} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} MFC_LIBS}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} MFC_LIBS}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} MFC_LIBS;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} MFC_LIBS +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to provide explicit MFC library names and override the default names that the Build Utility uses. This is another macro you might use if you choose not to follow the same {\uldb\cf11 +directory structure. }{\v Directory_Structure} as Windows\~NT. For example, the MSN group has their own MFC libraries. They do not use the ones from Windows\~NT. They do not use the public directory. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} MFC_VER}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} MFC_VER}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} MFC_VER;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} MFC_VER +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 Use this macro to specify the version of MFC to build with. By default, it is set to 40. Valid values must be 40 or greater. To use MFC 3.x, define }{\ul\cf11 USE_MFC30}{\f5\ul\cf11 . }{\v\f5 USE_MFC30} + +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} MIDL_OPTIMIZATION}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} MIDL_OPTIMIZATION}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} MIDL_OPTIMIZATION;Macros;IDL Files}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} + MACROS:0}} MIDL_OPTIMIZATION +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to override the default optimization that is passed to the MIDL compiler. The default is OI2. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} MIDL_UUIDDIR}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} MIDL_UUIDDIR}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} MIDL_UUIDDIR;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} MIDL_UUIDDIR + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify where the {\ul\cf11 GUID}{\v GUIDs} file goes when you generate an OLE IDL file (UUIDs and GUIDs are the same thing). By default everything built in pass zero goes to + wherever you set the TARGETPATH subdirectory. Use this macro to override that. +\par To create the GUIDs in the current subdirectory, set MIDL_UUIDDIR to be dot: +\par \pard \li720\ri130\sa240\widctlpar MIDL_UUIDDIR=. +\par \pard \ri130\sa240\widctlpar It does not matter where you put the GUIDs so long as whatever you set here, you set your #includes to get them from here. Otherwise the subsequent tools used by the Build Utility will not be able to find the GUIDs. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} MINORCOMP}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} MINORCOMP}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} MINORCOMPMacros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} MINORCOMP +\par \pard\plain \ri130\sa240\widctlpar\tx4428\tx8856 \f7\fs20 Use this macro to specify the second part of the filename constructed for use by the MIPS compiler. This is required only for MIPS and ALPHA builds. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} MISCFILES}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} MISCFILES}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} MISCFILES;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} MISCFILES +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use the MISCFILES macro to list items that you want to put into the appropriate installation point when the Build Utility runs {\uldb\cf11 binplace.exe. }{\v binplace_exe} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} MSC_OPTIMIZATION}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} MSC_OPTIMIZATION}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} MSC_OPTIMIZATION;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + MSC_OPTIMIZATION +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +Use this macro to override the default optimization the Build Utility uses on the compiler. By default, everything is optimized. If you want to turn off optimization to step through your code, you can set MSC_OPTIMIZATION to whatever is appropriate for yo +ur compiler. Most people in the Windows\~ +NT group use /Odi, which is unoptimize everything, for the code they want to hand debug. All of these flags also have platform-specific variants. If you know your code works great on all platforms except PowerPC, you can set the +MSC_WARNING_LEVEL to /W3/WX and then you can say PPC_WARNING_LEVEL=/W1. The same is true for optimization, you can specify PPC optimization or MIPS optimization or Alpha optimization or i386 optimization to override for each specific platform. If you do n +ot specify any of those, MSC optimization will be the default. If you do not specify MSC_OPTIMIZATION, the default is: +\par \pard \li720\ri130\sa240\widctlpar Oxs - Fully optimize, size overrules speed. +\par \pard \ri130\sa240\widctlpar {\f5 While performance testing Windows\~ +NT, it was determined that the overhead from handling page faults and cache misses usually outweighs any optimization the compiler might make that results in larger code. Therefore /Oxs is used by default. It directs the +compiler, "when presented with an optimization choice that is either bigger/faster or smaller/s +lower, choose the smaller case". This is also the reason why /G5 isn't used when compiling for X86. /G5 directs the compiler to break complex instructions into several more primitive instructions that the Pentium can run faster. Again, larger code typica +lly means more page faults and the net result is slower performance. +\par If, after testing for yourself, you find that this is not the case for your code, you can always override the generic MSC_OPTIMIZATION macro with platform-specific macros. They are: +\par MSC_OPTIMIZATION (all platforms)\line ALPHA_OPTIMIZATION (Alpha)\line 386_OPTIMIZATION (Intel)\line MIPS_OPTIMIZATION (Mips)\line PPC_OPTIMIZATION (Power PC) +\par }{\b See Also}\line {\uldb\cf11 MSC_WARNING_LEVEL}{\v MSC_WARNING_LEVEL} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} MSC_WARNING_LEVEL}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} MSC_WARNING_LEVEL}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} MSC_WARNING_LEVEL;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + MSC_WARNING_LEVEL +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +Use this macro to set the warning level to use on the compiler. The default is W3. After you have your code building without errors, you probably want to change MSC_WARNING_LEVEL to /W3/WX, which always makes any warnings an error. +\par MSC_WARNING_LEVEL is generic to all platforms. Platform-specific variants include: +\par \pard \li720\ri130\widctlpar i386_WARNING_LEVEL +\par MIPS_WARNING_LEVEL +\par ALPHA_WARNING_LEVEL +\par \pard \li720\ri130\sa240\widctlpar PPC_WARNING_LEVEL +\par \pard \ri130\sa240\widctlpar {\b See Also}\line {\uldb\cf11 MSC_OPTIMIZATION}{\v MSC_OPTIMIZATION} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} NOLINK}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +$} NOLINK}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} NOLINK;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} NOLINK +\par \pard\plain \ri130\sa240\widctlpar\tx2718\tx8856 \f7\fs20 {\f5 The NOLINK and MAKEDLL macros are primarily used in the master makefile (}{\f5\uldb\cf11 makefile.def}{\v\f5 makefile_def}{\f5 ) to indicate which rules to enable or disable } +when the Build Utility goes through two tools. {\f5 NOLINK=1 indicates a link isn't supposed to occur (most likely because this is pass one and build cannot guarantee the libraries needed are built yet). MAKEDLL=1 indicates a link +should occur and is used in pass two after all the libraries are built. If you run a one-pass build (by specifying -z on the command line to build), only MAKEDLL=1 is specified.} +\par You can test for this macro in your makefile. You can say, if NOLINK=1, then you know you are in pass one; if MAKEDLL=1, then you know you are in pass two because in the first pass you do not want to link and in the second pass you just want to make the D +LL. +\par {\b See Also}\line {\uldb\cf11 MAKEDLL}{\v MAKEDLL} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} NOMFCPDB}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} NOMFCPDB}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} NOMFCPDB;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} NOMFCPDB +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 By default whenever you are buil +ding an MFC program, the Build Utility generates the symbolic debugging information in a PDB file (a program database). MFC has so much stuff, the Build Utility puts it in the PDB. If you define NOMFCPDB, it won't. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} NOT_LEAN_AND_MEAN}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} NOT_LEAN_AND_MEAN}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} NOT_LEAN_AND_MEAN;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + NOT_LEAN_AND_MEAN +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 The windows.h file checks to see if WIN32_LEAN_AND_MEAN is defined. If it isn't, it includes every header file; if it is, it only includes the Windows headers. All of Windows\~NT builds that way. +\par So if you include windows.h, you get just Windows. If you want OLE and RPC and all the net stuff, you include those headers as you need them. +\par The SDK ships with this undefined. If you've got code that you brought over from the SDK or if you've built it in the VC build environment, you probably included windows.h and got all these things for free without realizing that it just made your build so + much slower. When you are bringing code over from that environment, define the following in your sources file: +\par \pard \li720\ri130\sa240\widctlpar NOT_LEAN_AND_MEAN=1 +\par \pard \ri130\sa240\widctlpar Then it will all continue to work the same way it worked in your old build environment. +\par The right thing to do, of course, would be to go through and get rid of unneeded headers, but sometimes that's more work than is necessary. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} NO_NTDLL}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} NO_NTDLL}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} NO_NTDLL;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} NO_NTDLL +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 Use this macro to indicate that NTDLL.LIB should not be automatically added to the library list. +\par }\pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} NT_INST}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} NT_INST}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} NT_INST;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} NT_INST +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 This macro is used internally by the Windows\~NT build group to specify instrumentation.{\f5 Some components for Windows\~ +NT use it to enable some special instrumentation when building. Whatever you set this value to will be passed to the compiler as is. For example: +\par }\pard \li720\ri130\sa240\widctlpar {\f5 NT_INST=1 +\par }\pard \ri130\sa240\widctlpar {\f5 Results in: +\par }\pard \li720\ri130\sa240\widctlpar {\f5 /DNT_INST=1 +\par }\pard \ri130\sa240\widctlpar {\f5 passed to the compiler. The default is /DNT_INST=0. +\par }\pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} NT_UP}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +$} NT_UP}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} NT_UP;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} NT_UP +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to indicate whether your driver will run on a uniprocessor machine or multiprocessor machine. The default is uniprocessor, as follows: +\par \pard \li720\ri130\sa240\widctlpar NT_UP=1 +\par \pard \ri130\sa240\widctlpar To specify multiprocessor, set\rdblquote +\par \pard \li720\ri130\sa240\widctlpar NT_UP=0 +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} NTDBGFILES}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} NTDBGFILES}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} NTDBGFILES;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} NTDBGFILES +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to control whether symbols should be stripped from final image files when the Binplace Utility is run by the Build Utility. +\par Binplace.exe is the utility that the Build Utility uses to create the final installation format for an image. When you build a CD, the Binplace Utility directs which images go in the root of the CD, which images go in different subdirectories, which .inf +files need to be in certain subdirectories with other files, and which symbols need to be split off. +\par As part of this process, the Build Utility enables you to split off the symbols that are used for debugging. This is because in the Windows\~NT build e +nvironment, everything built has symbols. But the final product is not shipped with symbols. Instead, the Build Utility directs binplace.exe to strip the symbols from all the images and put them in a symbols subdirectory. Then the Windows\~ +NT group ships the binary subdirectory. The symbols subdirectory goes out separately on the CD, the SDK, or the DDK. +\par What determines whether or not the Build Utility should split off symbols is based on whether NTDBGFILES is set. +\par You usually do this in your environment, not in your sources file. +\par You should do this on your build machine rather than on all of your developers' machines because they probably want the symbols there. It\rquote +s easier to track. The debugger does not have to do all this hand waving to find the debug symbolic files that match the images themselves. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} NTDEBUG}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} NTDEBUG}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} NTDEBUG;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} NTDEBUG +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 Use this macro to specify what type of symbolic information you want when building (and therefore which debugger you'll be using). It is rarely used in the sources file, instead it should +be set in the environment before building the project. +\par }To indicate a checked (or debug) build, specify: +\par \pard \li720\ri130\sa240\widctlpar NTDEBUG=ntsd +\par \pard \ri130\sa240\widctlpar To indicate a free (or retail) build, specify: +\par \pard \li720\ri130\sa240\widctlpar NTDEBUG= ntsdnodbg +\par \pard \ri130\sa240\widctlpar +The only difference between the two of them is that specifying ntsd causes the Build Utility to define DBG=1 and ntsdnodbg causes it to define DBG=0, so the Build Utility can direct the code to do or not do something based on the value of DBG. Some groups +, such as the VC group, define _DEBUG for their debug version and NDEBUG for their non-debug version. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} NTDEBUGTYPE}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} NTDEBUGTYPE}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} NTDEBUGTYPE;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} NTDEBUGTYPE + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 +The Blue text on the NTDEBUGTYPE page - Yes, ntsd does specify coff information... and it does make sense... :-) The paragraph at the bottom can be removed. Instead, for NTDEBUGTYPE=windbg, we should add: "specifies Codeview information in the final ima +ge. If you want to generate a program database (.PDB file) for the CV info, you'll need to set }{\ul\cf11 USE_PDB}{\v USE_PDB}{\f5 =1 also. +\par }Use this macro to specify the method of linking, which symbols are used. +\par \pard \li720\ri130\sa240\widctlpar NTDEBUGTYPE +=ntsd The ntsd information is only useful for debugging with NTSD, which is our character-mode debugger that ships with the system and Kernel Debugger (KD). The other debuggers understand CodeView, so most people want to stick with windbg for everything b +ecause every debugger understands it. +\par NTDEBUGTYPE=windbg (specifies CodeView information {\f5 in the final image. If you want to generate a program database (.pdb file) for the CV information, you'll need to set }USE_PDB{\f5 =1 also.}) +\par NTDEBUGTYPE=coff +\par NTDEBUGTYPE=both (Specifies both CodeView and ntsd information.) +\par \pard \ri130\sa240\widctlpar +Any of these settings used for NTDEBUGTYPE will compile with C7, which means put the CodeView information in every object. There is a C9 compiler from the VC group and a C10, C11, which enables you to put all the type information in a program database (PD +B). If you want to do that, you have to say USE_PDB=1 in your sources file or in your environment. This is not recommended, however. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} NTKEEPRESOURCETMPFILES}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar +\f7\fs20 {\cs16\super $} NTKEEPRESOURCETMPFILES}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} NTKEEPRESOURCETMPFILES;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super +} MACROS:0}} NTKEEPRESOURCETMPFILES +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 In the Windows\~NT build, the RC Compiler generates a binary file, but it cannot be linked into a final image because it hasn't been converted to the right format. When you do a Windows\~ +NT build, the Build Utility converts it as soon as the RC Compiler creates it. In most other build processes, +they convert it when they link it in. This means that, in our case if you build it once, it can be linked as many times as you want and it will never need to be reconverted. In their environment, every time you link it, you reconvert it. But in their envi +ronment, after you run it through our C, you can still bring it up in other tools that understand the RC output. In the Windows\~NT environment, it's been converted and it's not in the RC output any more. So, if it\rquote +s important to you that it stay in the RC output and not be converted, you have to set: +\par \pard \li720\ri130\sa240\widctlpar NTKEEPRESOURCETMPFILES=1 +\par \pard \ri130\sa240\widctlpar All that says is "Do not do the conversion after you build it. Hold off on converting it until you go to link it." Every time you link it, it will convert it. This makes your links a litt +le slower, but it means you can use other tools, such as the Visual C Resource Editor, to modify it before you link it. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} NTNOFUZZYLOOKUP}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} NTNOFUZZYLOOKUP}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} NTNOFUZZYLOOKUP;Macros;Fuzzy Matching}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} + MACROS:0}} NTNOFUZZYLOOKUP +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 This macro was added to help bring other projects into the build environment for Windows\~NT. +\par By default, in the method used by Windows\~ +NT, you have a .def file. You may have a DLL that you want to build. That DLL is going to export functions a, b, and c. But on x86, it may be _bunny@8; on MIPS, it may be bunny; on Alpha, it may be _bunny. So they all have unique +names, but you do not want to have a different .def file for each platform because then it becomes a maintenance nightmare. What you instead want to do is state in your .def file, "Export function a. Exporting function b." Then call the linker to say, "He +re is the .def file and here are all the .obj files. Go figure out what the right name is supposed to be." That's called fuzzy matching. +\par Some people have set up their build environments so that they specify the fully declared name in the .def file. So instead of saying \ldblquote Export function\~a\rdblquote or \ldblquote Export function\~b,\rdblquote + they say export_functionb@8. If they do that, they already have the declared name in there. They've just made it so that every time they do a new platform, they've got to go through and edit their +.def files and add in the new funky names. If you are bringing a project over that does that, you can prevent the extra step of passing in all the objects and directing the linker to figure out the right names by stating the following in your sources file +: +\par \pard \li720\ri130\sa240\widctlpar NTNOFUZZYLOOKUP=1 +\par \pard \ri130\sa240\widctlpar +Once you specify a declared name and you ship a product with the declared name in it, you've got to use that from now on. It makes it very hard, but sometimes it's too late. You cannot fix it. That's when you specify NTNOFUZZYLOOKUP. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} NTNOPCH}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} NTNOPCH}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} NTNOPCH;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} NTNOPCH +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to turn off precompiled headers for a single source file. +\par If you have precompiled headers on a subdirectory, the Build Utility expects you to build that subdirectory and then make subsequent changes as you go along. Whenever yo +u change one of the source files, you need to rebuild that file. The Build Utility will detect that you used precompiled headers there, and will compile that single source file without them. That enables you to build everything, then change a definition i +n a header file (for example, a #define {\i something} to {\i something else} +). Then you change the source file to use that new definition. You really do not want to regenerate the precompiled header and rebuild everything else. You just want to rebuild that one sour +ce file. But you do not want to use the old precompiled header because that information is not valid any more. So in that case, the Build Utility does a non-precompiled header build. For that one source file, it turns off precompiled headers. That makes i +t reread all the headers, and all the type information is then correct. That's only going to happen when you do a build with a -Z or -z switch when you are directing it to not scan dependencies and therefore do not regenerate the precompiled header. + +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} NTPROFILEINPUT}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} NTPROFILEINPUT}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} NTPROFILEINPUT;Macros;Profile}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + NTPROFILEINPUT +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +The linker lets you specify a profile, which is a list of all the functions or symbols in your image and the order you want them emitted in the final image. You can optimize page usage by listing the functions in the order they should be emitted in the fi +nal image. You can automate this list generation with the Working Set Tuner (wst.exe). +\par To use the profile, specify the following in your sources file:: +\par \pard \li720\ri130\sa240\widctlpar NTPROFILEINPUT=1 +\par \pard \ri130\sa240\widctlpar If you set that, the Build Utility expects to find the name of the thi +ng you are building with a .prf filename extension in the current subdirectory. If you are building kernel 32, it expects to find kernel32.prf in the current subdirectory. The Build Utility will use that to order the final image that it builds. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} NTTARGETFILE0}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} NTTARGETFILE0}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} NTTARGETFILE0}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} NTTARGETFILE0 + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 You can define NTTARGETFILE0 and/or NTTARGETFILES to cause makefile.def to include .\\ + makefile.inc immediately after it specifies the top level targets (all, clean and loc) and their dependencies. The makefile.def file expands NTTARGETFILE0 as +the first dependent for the "all" target and NTTARGETFILES as the last dependent for the "all" target. Use this to specify additional targets and dependencies that do not fit the general case covered by makefile.def. +\par \pard \li720\ri130\sa240\widctlpar NTTARGETFILE0= +\par \pard \ri130\sa240\widctlpar The fact that NTTARGETFILE0 exists, even if it is defined to nothing, means that the Build Utility should open makefile.inc in the same subdirectory as the sources file. If you set NTTARGETFILE0, what you are saying is, +\ldblquote Not only should you include makefile.inc, but you should also build the thing that the macro defines.\rdblquote So if: +\par \pard \li720\ri130\sa240\widctlpar NTTARGETFILE0=myfile.a +\par \pard \ri130\sa240\widctlpar Then, as part of pass zero, the Build Utility will build myfile.a. +\par If you do not set NTTARGETFILE0, the Build Utility will go down to the specified subdirectory on pass zero, include {\uldb\cf11 makefile.inc}{\v mk_inc}, and do any default rules that it contains. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} NTTARGTFILE1}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} NTTARGTFILE1}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} NTTARGTFILE1}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} NTTARGETFILE1 +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 NTTARGETFILE1 is exactly like {\uldb\cf11 NTTARGETFILE0, }{\v NTTARGETFILE0} except that it happens later in the build process. NTTARGETFILE0 happens on pass zero; NTTARGETFILE1 happens + on pass two. Both of these macros cause the Build Utility to change directories to a specified subdirectory and run nmake on pass zero or pass two where it might not ordinarily do that. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} NT_TARGETFILES}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} NT_TARGETFILES}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} NT_TARGETFILES}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} NTTARGETFILES + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 If you have unique rules in your subdirectory, you can set up this macro to key the build process to say that along with your sources file in the subdirectory, you also have a {\uldb\cf11 makefile.inc}{\v +mk_inc}, which can include extra dependencies, extra command line rules, anything you want to build. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} O}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super $} O} +} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} O;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} O +\par \pard\plain \ri130\sa240\widctlpar\tx2718\tx8856 \f7\fs20 Use this macro to specify the final objects subdirectory. Define this macro in your sources file or in {\uldb\cf11 makefile.inc}{\v mk_inc} + to be certain something goes into the object subdirectory. The benefit of using $(O) is that any files that you have built and placed in the objects subdirectory will be deleted on the next clean build. This guarantees that no collisions will occur betwe +en two builds running on the same machine at the same time. They will never override each other's files if you follow the convention that everything you build goes in $(O). +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} OAK_INC_PATH}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} OAK_INC_PATH }} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} OAK_INC_PATH }} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} OAK_INC_PATH + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify {\f5 the path to the OEM Adapter Kit headers. The default is: +\par }\pard \li720\ri130\sa240\widctlpar {\f5 $(}{\ul\cf11 BASEDIR}{\v BASEDIR})\\{\f5 public\\oak\\inc +\par }\pard \ri130\sa240\widctlpar Set this macro if you don't use the Windows\~NT {\uldb\cf11 directory structure. }{\v Directory_Structure} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} PASS0_CLIENTDIR}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} PASS0_CLIENTDIR}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} PASS0_CLIENTDIR;Macros;IDL Files}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0} +} PASS0_CLIENTDIR +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 PASS0_CLIENTDIR, PASS0_HEADERDIR, and PASS0_SERVERDIR are used when you have a SOURCES macro in your sources file. That macro can contain the following types of files: +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}\pard \fi-360\li360\ri130\widctlpar\tx360{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}C +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}C++ +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}RC +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}MC +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}\pard \fi-360\li360\ri130\sa240\widctlpar\tx360{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}IDL +\par \pard \ri130\sa240\widctlpar Use the PASS0_CLIENTDIR, PASS0_HEADERDIR, and PASS0_SERVERDIR macros to specify where to put the output from MC and MIDL. +\par When you have IDLs in your SOURCES macro and run MIDL, you generate a server part, a client part, a header, and a default source. You specify where you want to put that output in PASS0_SERVERDIR and PASS0_CLIENTDIR. +\par When you run MC, you create a header and a source file. You put that in PASS0_HEADERDIR and PASS0_SOURCEDIR to specify where you want to put that output. +\par When you are building a MIDL stub, it's RPC, so you have what runs on the client side and what runs on the server side. There are stub programs that communicate in RPC to each other. You can override those by default. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} PASS0_HEADERDIR}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} PASS0_HEADERDIR}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} PASS0_HEADERDIR;Macros;Headers}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + PASS0_HEADERDIR +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify where the headers generated by MC and MIDL go. By default everything built in pass zero goes to wherever you set the TARGETPATH subdirectory. Use this macro to override that. +\par To create the headers in the current subdirectory, set PASS0_HEADERDIR to be dot: +\par \pard \li720\ri130\sa240\widctlpar PASS0_HEADERDIR=. +\par \pard \ri130\sa240\widctlpar It does not matter where you put the headers so long as whatever you set here, you set your #includes to get them from here. Otherwise the subsequent tools used by the Build Utility will not be able to find the headers. +\par {\b See Also}\line {\uldb\cf11 PASSO_CLIENTDIR}{\v PASS0_CLIENTDIR} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} PASS0_SERVERDIR}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} PASS0_SERVERDIR}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} PASS0_SERVERDIR;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + PASS0_SERVERDIR +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify where the server part generated by MIDL goes. By default everything built in pass zero goes to wherever you set the TARGETPATH subdirectory. Use this macro to override that. +\par To create the server part in the current subdirectory, set PASS0_SERVERDIR to be dot: +\par \pard \li720\ri130\sa240\widctlpar PASS0_SERVERDIR=. +\par \pard \ri130\sa240\widctlpar +It does not matter where you put the server part so long as whatever you set here, you set your #includes to get them from here. Otherwise the subsequent tools used by the Build Utility will not be able to find the server part. +\par {\b See Also}\line {\uldb\cf11 TARGETPATH}{\v TARGETPATH}\line {\uldb\cf11 PASSO_CLIENTDIR}{\v PASS0_CLIENTDIR} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} PASS0_SOURCEDIR}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} PASS0_SOURCEDIR}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} PASS0_SOURCEDIR;Macros;IDL Files}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0} +} PASS0_SOURCEDIR +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify where the source code generated by MIDL and maketype.lib file goes. By default everything built in pass zero goes to w +herever you set the TARGETPATH subdirectory. Use this macro to override that. +\par To create the source code generated by MIDL and maketype.lib in the current subdirectory, set PASS0_SOURCEDIR to be dot: +\par \pard \li720\ri130\sa240\widctlpar PASS0_SOURCEDIR=. +\par \pard \ri130\sa240\widctlpar +It does not matter where you put the source code generated by MIDL and maketype.lib, so long as whatever you set here, you also set your #includes to get them from here. Otherwise the subsequent tools used by the Build Utility will not be able to find the + source code generated by MIDL and maketype.lib file. +\par {\b See Also}\line {\uldb\cf11 TARGETPATH}{\v TARGETPATH}\line {\uldb\cf11 PASSO_CLIENTDIR}{\v PASS0_CLIENTDIR} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} PNP_POWER}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} PNP_POWER}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} PNP_POWER;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} PNP_POWER +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 This macro is used internally by the Windows\~ +NT build group to specify plug-and-play power definition. This enables you to build a driver that understands plug and play. If it's not set, the Build Utility does not define a value; if it is, the Build Utility defines +\par \pard \li720\ri130\sa240\widctlpar PNP_POWER=1 +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} PRECOMPILED_CXX}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} PRECOMPILED_CXX}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} PRECOMPILED_CXX;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + PRECOMPILED_CXX +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to indicate whether the precompiled header you are building will be used with C files or with C++ fi +les. The default is to use precompiled headers with C. Therefore, to use the precompiled header with C, do not set PRECOMPILED_CXX at all. +\par To use the precompiled header with C++ files, specify +\par \pard \fi720\ri130\sa240\widctlpar PRECOMPILED_CXX=1 +\par \pard \ri130\sa240\widctlpar {\b See Also}\line {\uldb\cf11 Precompiled Headers}{\v Precompiled_Headers} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} PRECOMPILED_INCLUDE}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 +{\cs16\super $} PRECOMPILED_INCLUDE}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} PRECOMPILED_INCLUDE;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + PRECOMPILED_INCLUDE +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify the name of the precompiled header. For example, if you have precompiled headers that are a.c, b.c, and c.c as your source files, and all of them include precomp.h, specify: +\par \tab PRECOMPILED_INCLUDE=precomp.h +\par If you omit this, you will not be able to have precompiled headers. PRECOMPILED_INCLUDE is what triggers the build process to understand that you do have precompiled headers. +\par {\b See Also}\line {\uldb\cf11 Precompiled Headers}{\v Precompiled_Headers} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} PRECOMPILED_OBJ}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} PRECOMPILED_OBJ}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} PRECOMPILED_OBJ;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + PRECOMPILED_OBJ +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +By default, the Build Utility takes the precompiled header with the precompiled #include setting that you specify, for example precomp.h. Out of that, it creates precomp.obj for the precompiled object and precomp.pch for the precompiled target. You can ov +erride those names by setting the PRECOMPILED_OBJ and PRECOMPILED_TARGET macros. +\par {\b See Also}\line {\uldb\cf11 Precompiled Headers}{\v Precompiled_Headers} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} PRECOMPILED_TARGET}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} PRECOMPILED_TARGET}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} PRECOMPILED_TARGET;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + PRECOMPILED_TARGET +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +By default, the Build Utility takes the precompiled header with the precompiled #include setting that you specify, for example precomp.h. Out of that, it creates precomp.obj for the precompiled object and precomp.pch for the precompiled target. You can ov +erride those names by setting the{\ul\cf11 PRECOMPILED_OBJ }{\v PRECOMPILED_OBJ} and{\ul\cf11 PRECOMPILED_TARGET }{\v PRECOMPILED_TARGET} macros. +\par {\b See Also}\line {\uldb\cf11 Precompiled Headers}{\v Precompiled_Headers} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} RC_COMPILER}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} RC_COMPILER}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} RC_COMPILER;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} RC_COMPILER + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +The Exchange team uses this macro when they are compiling different builds for different countries. They set the RC code page equal to the code page for Korea, and set the Japanese one to the code page for Japan. That informs the RC Compiler about what to + expect from the input side so it can translate the correct code page. If you do set the code page, it will be passed as the -C switch to the Resource Compiler. You can override other switches to the Resource Compiler with RC_OPTIONS. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} SDK_INC_PATH}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} SDK_INC_PATH}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} SDK_INC_PATH;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} SDK_INC_PATH + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 Use this macro to specify the path to the SDK headers. The default is: +\par }\pard \li720\ri130\sa240\widctlpar {\f5 $(}{\ul\cf11 BASEDIR}{\v BASEDIR}{\f5 )\\public\\sdk\\inc +\par }\pard \ri130\sa240\widctlpar Set this macro if you don't use the Windows\~NT {\uldb\cf11 directory structure. }{\v Directory_Structure} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} SDK_LIB_PATH}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} SDK_LIB_PATH}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} SDK_LIB_PATH;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} SDK_LIB_PATH + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify {\f5 the path to the SDK libraries. The default is: +\par }\pard \li720\ri130\sa240\widctlpar {\f5 $(}{\ul\cf11 BASEDIR}{\v BASEDIR}{\f5 )\\public\\sdk\\lib\\* +\par }\pard \ri130\sa240\widctlpar Set this macro if you don't use the Windows\~NT {\uldb\cf11 directory structure. }{\v Directory_Structure} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} SOURCES}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} SOURCES}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} SOURCES;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} SOURCES +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +The SOURCES macro is the most important macro for the Build Utility. You must have this macro in your sources file. The SOURCES macro specifies which files are going to be compiled. The Build Utility will look at these files and generate a dependency list +. If any of those dependencies change, the Build Utility will rebuild this source file. +\par Use this macro to list your source filenames (except for the file containing main. Include the filename extension and separate the entries in this list with spaces or tabs. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} SOURCES_USED}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} SOURCES_USED}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} SOURCES_USED;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} SOURCES_USED + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to indicate that another sources file or makefile exists elsewhere in the tree when that file has things in it that your build is dependent upon. When you specify: +\par \pard \li720\ri130\sa240\widctlpar SOURCES_USED={\i filename_someplace_else} +\par \pard \ri130\sa240\widctlpar nmake will regenerate the objects file when your sources file in this directory changes and also when another sources file or makefile that you specified in SOURCES_USED changes. +\par For example, the first thing you do in your sources file is include some other file. Then, right underneath that, specify: +\par \pard \li720\ri130\sa240\widctlpar SOURCES_USED={\i that_filename} +\par \pard \ri130\sa240\widctlpar This establishes a link between that file and the sources file. When that other file changes, nmake will regenerate objects.mac. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} SUBSYSTEM_VERSION}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} SUBSYSTEM_VERSION}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} SUBSYSTEM_VERSION;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + SUBSYSTEM_VERSION +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 If your product has to run on Windows\~NT\~3.1 or 3.5 or 3.51, set your subsystem version to that version number. For example, in the current setup program of Windows\~NT: +\par \pard \li720\ri130\sa240\widctlpar SUBSYSTEM_VERSION=3.1 +\par \pard \ri130\sa240\widctlpar This is the most common usage. If you do not set SUBSYSTEM_VERSION, the default will be whatever the current build of Windows\~NT is. +\par You can also set individual subsystem versions. If you want to set the Windows version to 4.0, specify: +\par \pard \li720\ri130\sa240\widctlpar SUBSYSTEM_WINVER=4.0 +\par \pard \ri130\sa240\widctlpar Likewise, you can set: +\par \pard \li720\ri130\sa240\widctlpar SUBSYSTEM_CONVER\line SUBSYSTEM_OS2VER\line SUBSYSTEM_POSIX\line SUBSYSTEM_NATVER +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} TARGET_CPP}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} TARGET_CPP}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} TARGET_CPP}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} TARGET_CPP +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify name of the compiler. Instead of having to specify that on x86 it\rquote s CL386 and on MIPS, it\rquote s CLMIPS, and on PowerPC, it\rquote s CLPPC, you can simply specify: +\par \pard \li720\ri130\sa240\widctlpar TARGET_CPP={\i name_of_compiler} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} TARGET_DIRECTORY}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} TARGET_DIRECTORY}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} TARGET_DIRECTORY;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + TARGET_DIRECTORY +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro as follows to specify the target directory when you want some dependency file to always end up in the obj subdirectory: +\par \pard \li720\ri130\sa240\widctlpar TARGET_DIRECTORY={\i some_sourcefile:some_dependency_file} +\par \pard \ri130\sa240\widctlpar This enables you to do platform-specific builds from the same source tree at the same time and they won\rquote t override each other. You do not have to hard code the name of the platform. +\par For example, if you have a special build rule for some feature in your code or if you want to build a particular object from a particular C file, specify: +\par \pard \li720\ri130\sa240\widctlpar obj\\$(TARGET_DIRECTORY)\\{\i filename}.obj;{\i filename}.c +\par \pard \ri130\sa240\widctlpar By using the TARGET_DIRECTORY macro, you guarantee that it\rquote s going to end up in the correct platform subdirectory, such as \\obj\\{\i i386subdirectory}\\obj\\. +\par There are some default targets. One of them is .cod. If you go to a subdirectory where you've got source files and specify: +\par \pard \li720\ri130\sa240\widctlpar nmake SOURCE_FILE_NAME=.cod +\par \pard \ri130\sa240\widctlpar it will create an assembler listing for you that you can view to see where the compiler erred. +\par There is another default target called .pp file, a preprocessed listing. Preprocessing adds line numbers. You can look view to see where the Build Utility got your headers, and which #defines and what kinds of structures it added. +\par The other thing with a .pp file is that you can send it out to the compiler group if something goes wrong. It's all self-contained. They do not have to have any header files or anything like that in their environment You can just give it to them. They are + usually quite large, in the neighborhood of a meg or more, with several hundred thousand lines. You can send that to the compiler group. +\par You can, again, go to a subdirectory where you have a source file and say: +\par \pard \li720\ri130\sa240\widctlpar nmake SOURCE_FILE_NAME=.pp +\par \pard \ri130\sa240\widctlpar and it will preprocess it. +\par The .cod and .pp files are very useful for tracking bugs in the build process. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} TARGETEXT}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} TARGETEXT}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} TARGETEXT;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} TARGETEXT +\par \pard\plain \ri130\sa240\widctlpar\tx4428\tx8856 \f7\fs20 Use this macro to specify the extension name (such as .cpl) when you want the DLLs to have something other than .dll as the filename extension. +\par \pard \ri130\sa240\widctlpar If you specify something unexpected, you will see a message "Unexpected Target Ext." If you want an extension added to the Build Utility, contact Bryan Tuttle (bryant). +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} TARGETLIBS}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} TARGETLIBS}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} TARGETLIBS;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} TARGETLIBS +\par \pard\plain \ri130\sa240\widctlpar\tx4428\tx8856 \f7\fs20 +Use TARGETLIBS to specify other libraries that you want to link against when building your image. It should be your primary method for specifying libraries or objects you want to link against to build your image. +\par You can also use the {\uldb\cf11 LINKLIBS}{\v LINKLIBS} macro to specify libraries that you need to link against. The only difference is the ordering on the command line. LINKLIBS usually gets passed first; TARGETLIBS + gets passed second. If you order them in your TARGETLIBS macro correctly, that shouldn't be a problem EXCEPT when you are building a DLL. When you are building a DLL, you may have some objects that you've built, but you also have some other libraries tha +t you want to export some features from. Maybe you go to subdirectory one and compile a number of objects into a library. In subdirectory two, you compile some more into a library. In subdirectory three, you actually build the DLL, but it exports function +s that are defined in library one or library two. So put those libraries in your LINKLIBS macro. +\par {\pntext\tab}\pard\plain \s17\sb50\widctlpar\noline\pvpara\phpg\posy0\absw540\dxfrtext180\dfrmtxtx180\dfrmtxty0{\*\pn \pnlvlbody\pnstart1\pnhang}\hyphpar0 \f4\fs20\kerning20 {\pard\plain +\s17\sb50\widctlpar\noline\pvpara\phpg\posy0\absw540\dxfrtext180\dfrmtxtx180\dfrmtxty0{\*\pn \pnlvlbody\pnstart1\pnhang}\hyphpar0 \f4\fs20\kerning20 {\object\objlink\rsltmerge\rsltbmp\objw0\objh0{\*\objclass }{\*\objdata 010500000100000010000000576f72642e446f63756d656e742e360021000000433a5c47554944455c5052494e545c444f435c4d5350524553535c432e414d5300080000004d414561727438000000000000000000 +020000000105000000000000{\*\bkmkstart _865320947}{\*\bkmkend _865320947}}{\result {{\pict\wmetafile8\picw846\pich846\picwgoal480\pichgoal480 \picbmp\picbpp4 +010009000003220800000400d903000000001400000026060f001e00ffffffff040014000000576f72640e004d6963726f736f667420576f7264050000000b0200000000050000000c02640064000d000000fb020000000000000000000000000000000000010044040000002d0100000400000002010100040000002d0100 +0015000000fb02d6ff0000000000009001000000000400001254696d6573204e657720526f6d616e000000040000002d01010005000000090200000000040000000201010004000000020101000400000002010100030000001e0007000000160465006500000000000400000002010100040000002d010100030000001e00 +0700000016046400640000000000030000001e000700000016046400640000000000030000001e000700000012046400640064006400050000000c0264006400050000000b0200000000050000000b0200000000050000000c0218001800050000000b0200000000060000002606260002000100050000000b020000000005 +0000000c0220002000050000000b020000000005000000090200000000050000000102ffffff00040000000701030042010000430fc600880000002000200000000000200020000000000028000000200000002000000001000400000000000002000000000000000000000000000000000000000000001111110022222200 +33333300444444005555550066666600777777008888880099999900aaaaaa00bbbbbb00cccccc00dddddd00eeeeee00ffffff00fffff7777777777777777777777777ffffff777777777777777777777777777fff700000000000000000000000077777f7ffffffffffffffffffffffffc077777fffffffffffffffffffff +fffffc07777fffffffffffffffffffffffffff07777ffffffffffffc00cfffffffffff077f7ffffffffffff0000ffffffffffc077ff7fffffffffff0000ffffffffff077fff7fffffffffffc00cfffffffffc077ffff7fffffffffffffffffffffff077fffff7fffffffffff0ffffffffffc077ffffff7fffffffffc0cffff +fffff077fffffff7fffffffff707ffffffffc077ffffffff7ffffffff000ffffffff077fffffffff7fffffffc000cffffffc077ffffffffff7ffffff70007ffffff077fffffffffff7ffffff00000fffffc077ffffffffffff7fffff00000fffff077fffffffffffff7fffff00000ffffc077ffffffffffffff7ffff00000f +fff077fffffffffffffff7ffff00000fffc077ffffffffffffffff7fffc000cfff077fffffffffffffffff7ffffffffffc077ffffffffffffffffff7fffffffff077fffffffffffffffffff7ffffffffc077ffffffffffffffffffff7fffffff077fffffffffffffffffffff7ffffffc077ffffffffffffffffffffff7ffff +f077fffffffffffffffffffffff7ffffc07fffffffffffffffffffffffff7ffc0ffffffffffffffffffffffffffff777fffffffffffffffff000000026062500d501d301254d5345505320507265616d626c6520302030203234203234203020302033322033320d092f70705f736176652073617665206465660d092f7368 +6f7770616765207b7d206465660d093430206469637420626567696e202f70705f636c69702066616c736520646566202f70705f62626f782066616c7365206465660d092f46207b20706f70207d20646566202f53207b7d206465660d092f42207b207b202f70705f647931206578636820646566202f70705f6478312065 +786368206465660d09092020202f70705f647932206578636820646566202f70705f647832206578636820646566207d0d090973746f70706564206e6f74207b202f70705f62626f78207472756520646566207d206966207d206465660d092f4342207b207b202f70705f6379206578636820646566202f70705f63782065 +786368206465660d0909202020202f70705f636874206578636820646566202f70705f637764206578636820646566207d0d090973746f70706564206e6f74207b202f70705f636c6970207472756520646566207d206966207d206465660d092f70705f627831203020646566202f70705f627931203020646566202f7070 +5f62783220323420646566202f70705f627932203234206465660d00060000002606260002000000030000001e0007000000fc020100000000000000040000002d01020008000000fa02000000000000feffff00040000002d0103000400000004010b00070000001b042000200000000000040000002701ffff0600000026 +06260002000100d500000026062500a0019e010970705f636c69700d097b2070705f63782070705f6379206d6f7665746f2070705f637764203020726c696e65746f20302070705f63687420726c696e65746f0d09202070705f637764206e6567203020726c696e65746f20636c6970206e657770617468207d2069660d09 +70705f62626f78207b0d092f70705f6479322070705f6479322070705f64793120616464206465660d092f70705f6478322070705f6478322070705f64783120616464206465660d092f70705f73782070705f6478322070705f647831207375622070705f6278322070705f6278312073756220646976206465660d092f70 +705f73792070705f6479322070705f647931207375622070705f6279312070705f6279322073756220646976206465660d092f70705f74782070705f6478312070705f73782070705f627831206d756c20737562206465660d092f70705f74792070705f6479312070705f73792070705f627932206d756c20737562206465 +660d0970705f74782070705f7479207472616e736c6174652070705f73782070705f7379207363616c65207d2069660d656e640dd903000026062500a807a607252150532d41646f62652d312e300d0a2525426f756e64696e67426f783a203020302032342032340d0a25255363616c696e673a203130300d0a2525424954 +4d4150494e464f4845414445523a203332203332203420323034380d0a252543726561746f723a20466c6173682028313631353736290d0a2525456e64436f6d6d656e74730d0a3020736574677261790d0a3130206469637420626567696e0d0a63757272656e7473637265656e20706f7020706f70206475702031323020 +6c74207b706f70203132307d2069662025206e657720636f64650d0a3435207b20616273206578636820616273203220636f7079206164642031206774207b2031207375620d0a647570206d756c206578636820312073756220647570206d756c20616464203120737562207d207b20647570206d756c2065786368206475 +700d0a6d756c206164642031206578636820737562207d206966656c7365207d2073657473637265656e0d0a2f77426d7020313620737472696e67206465660d0a3234203234207363616c650d0a33322033322034205b333220302030203332203020305d0d0a2f6368203120737472696e6720646566202f7262207b2063 +757272656e7466696c652063682072656164686578737472696e6720706f7020706f70206e207b2077426d70206c2063680a707574696e74657276616c202f6c206c20312061646420646566207d20726570656174207d20646566202f6e62207b202f6e206e203132372073756220646566206e207b2063757272656e7466 +696c650a63682072656164686578737472696e6720706f7020706f702077426d70206c20636820707574696e74657276616c202f6c206c20312061646420646566207d20726570656174207d20646566202f67730a7b202f6c203020646566207b202f6e2063757272656e7466696c6520746f6b656e20706f702064656620 +6e20313237206774207b6e627d207b72627d206966656c7365206c2031362065710a7b657869747d206966207d206c6f6f70207d20646566202f72203020646566202f63203020646566207b20632030206571207b202f722063757272656e7466696c6520746f6b656e20706f70206465660a6773207d206966202f632063 +2031206164642064656620632072206571207b2f632030206465667d2069662077426d70207d20696d6167650a31203133302046464646463720313220373720313238204646203120313239204646464620313320373720313238203746203120313239204646373020313120303020313330203037373737370a31203132 +38204637203132204646203133302043303737373720312031323820374620313220464620313330204643303737372031203132382037462031332046462031323920303737372031203132382037460a35204646203133302046433030434620352046462031323920303737462031203132382037462035204646203133 +3020463030303046203420464620313330204643303737462031203132382046370a35204646203133302046303030304620342046462031333020463037374646203120313238204637203520464620313330204643303043462034204646203133302043303737464620312031323920464637460a313120464620313330 +203037374646462031203132392046463746203520464620313238203046203420464620313331204643303737464646203120313239204646463720342046462031323920464330430a3420464620313331204630373746464646203120313239204646463720342046462031323920463730372034204646203133312043 +3037374646464620312031333520464646463746464646464646463030300a34204646203133312030373746464646462031203134332046464646374646464646464643303030434646464646464330373746464646462031203134332046464646463746464646464637303030374646464646463037374646464646460a +31203134332046464646463746464646464630303030304646464646433037374646464646462031203134332046464646464637464646464630303030304646464646303737464646464646460a31203134332046464646464637464646464630303030304646464643303737464646464646462031203133392046464646 +46464637464646463030303030464646463037370a342046462031203133392046464646464646374646464630303030304646464330373720342046462031203420464620313335203746464643303030434646463037374620342046460a3120342046462031323820374620342046462031333020464330373746203420 +464620312034204646203132382046372034204646203132392046303737203520464620312034204646203132382046370a342046462031323920433037372035204646203120352046462031333320374646464646464630373746203520464620312035204646203133332037464646464646433037374620352046460a +3120352046462031333220463746464646463037372036204646203120352046462031333220463746464646433037462036204646203120362046462031333020374646433046203720464620310a36204646203132392046373737203820464620656e640a2525456e64496d616765446174610a06000000260626000200 +0000160000002606250021001f00254d5345505320547261696c65720d70705f7361766520726573746f72650d00040000002701ffff040000002701ffff040000002701ffff0400000002010100040000002701ffff040000002d01000003000000000050436f6c6f724374726c0000002c00700014000800600200000050 +4300ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff}}}}} +\par \pard\plain \ri130\sa240\widctlpar\tx4428\tx8856 \f7\fs20 {\cf6 Caution!} + The LINKLIBS macro requires that the library has to be around in pass one of the build, because the Build Utility builds the import libraries during pass one. You must structure your build in such a manner that the libraries will be guaranteed to exist d +uring pass one. You should never specify an import library +in your LINKLIBS macro, mainly because you can get into some real nasty cases where you export something that you've imported from somebody else instead of what you actually had, perhaps with typos or whatever. You may not realize this until suddenly your + program starts acting really weird. Stick with the rule that you use TARGETLIBS everywhere. There is TARGETLIBS and There is LINKLIBS; if you use TARGETLIBS for everything, life is good. (To avoid problems when doing multi-processor builds, see { +\uldb\cf11 Multi-processor Build Issues}{\v Multi_processor_Build_Issues}.) +\par Use LINKLIBS {\ul only} for the case that meets the following conditions: +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}\pard \fi-360\li360\ri130\sa240\widctlpar\tx360{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}You are building a dynamic link. +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}You are exporting something that's defined in some other component library that you also build. +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}In your dirs file in the subdirectory above, you have ordered it so that the component libraries are around before you build the dynamic link. +\par \pard \ri130\sa240\widctlpar There is a similar macro called {\uldb\cf11 UMLIBS}{\v UMLIBS} that you can use if you are building UMAPPLs. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} TARGETNAME}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} TARGETNAME}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} TARGETNAME;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} TARGETNAME +\par \pard\plain \ri130\sa240\widctlpar\tx4428\tx8856 \f7\fs20 Use this macro to specify the name of the library being built, excluding the filename extension. You must have this macro in your sources file. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} TARGETPATH}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} TARGETPATH}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} TARGETPATH;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} TARGETPATH +\par \pard\plain \ri130\sa240\widctlpar\tx4428\tx8856 \f7\fs20 +Use this macro to specify the target directory name that is the destination of all build products ( such as .exe, .dll, and .lib files). Notice that object files always end up in the obj subdirectory. You must have this macro in your sources file. For exa +mple: +\par \pard \li720\ri130\sa240\widctlpar TARGETPATH=obj +\par \pard \ri130\sa240\widctlpar\tx4428\tx8856 {\b See Also}\line {\uldb\cf11 Specifying Libraries}{\v Specifying_Libraries} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} TARGETPATHLIB}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} TARGETPATHLIB}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} TARGETPATHLIB;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + TARGETPATHLIB +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use the TARGETPATHLIB macro to specify where to put the import library when you are building a DLL. +\par When you are building a DLL, you create the DLL itself and you create an import library that other images can use that need to use your DLL. For example, a Windows\~ +NT developer built kernel32.dll and also kernel32.lib that users of kernel32.dll would link against. In the past, you would handle all that by specifying: +\par \pard \li720\ri130\sa240\widctlpar TARGETPATH=publicsdk.lib +\par \pard \ri130\sa240\widctlpar and it would put both the DLL and the import library in the public tree. By specifying TARGETPATHLIB, you can say, \ldblquote Put the library in the public tree.\rdblquote + Then you can set TARGETPATH=obj and we use the DLL in the obj subdirectory in the source tree and put the import library in the public tree where people might want to share it. +\par The VC team uses this because on their release point they have the root of the VC tree and then they have a bin subdirectory and a lib subdirectory. They put all their DLLs in the bin subdirectory and all their libraries in the lib subdirectory. So they w +ould specify: +\par \pard \li720\ri130\sa240\widctlpar TARGETPATH=bin\line TARGETPATHLIBS=vc\\lib +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} TARGETTYPE}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} TARGETTYPE}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} TARGETTYPE;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} TARGETTYPE +\par \pard\plain \ri130\sa240\widctlpar\tx4428\tx8856 \f7\fs20 +Use this macro to specify the type of product being built. This is typically LIBRARY or DYNLINK (for DLLs), but can take other values. This is a required field in the sources file. TARGETTYPE gives the Build Utility some clues about some of the input fil +es that it should be expecting. You must have this macro in your sources file. The valid values for TARGETYPE include: +\par \pard\plain \s20\li720\ri130\sa240\widctlpar \f7\fs20 PROGLIB is an executable that exports something. It's a program library. +\par PROGRAM - This is just a plain, program file that does not export anything. It just imports stuff in the default .exe on the command line. +\par DYNLINK - A DLL, a control panel applet, anything that can be dynamically loaded or that people can import from that has to have when its linked, it uses the DLL switch to the linker to indicate it's not a standalone .exe. It's actually something that's d +ynamically linked. When you build a dynamic link, you may also need to set the {\ul\cf11 TARGETEXT}{\v TARGETEXT} macro. +\par LIBRARY +- A component library. This is a library of objects, not an import library (an import library is built as a side effect of building a dynamic link. Anytime you build a dynamic link, you get a .lib file and a .dll file. When you build a library, you just g +et a .lib file.) +\par DRIVER - A system kernel driver. +\par EXPORT_DRIVER - An export driver is like a driver except it exports things. It provides services to other drivers. There are two of those in Windows\~NT. +\par HAL - {\ul\cf11 Hardware Abstraction Layer. }{\v Hardware_Abstraction_Layer} This is the kernel HAL for Windows\~NT. +\par BOOTPGM - A kernel driver. +\par MINIPORT - A kernel driver. +\par GDI_DRIVER - A kernel driver that is similar to a DLL, which is loaded in user and kernel space. This was added for Windows\~NT\~4.0. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} UMAPPL}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +$} UMAPPL}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} UMAPPL;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} UMAPPL +\par \pard\plain \ri130\sa240\widctlpar\tx4428\tx8856 \f7\fs20 This macro enables you to build multiple targets from a single subdirectory where every target is a source file and some other .lib files that you link against. +\par To use this macro, specify a list of source filenames containing a main function. Specify these filenames without filename extensions and separate them with an asterisk. For example: +\par \pard \li720\ri130\sa240\widctlpar UMAPPL=a*b*c*d +\par \pard \ri130\sa240\widctlpar\tx4428\tx8856 +The Build Utility will compile and link each file in this list after the main target in the sources file is built. The only restriction is that there can only be one source file and you must specify what it links with using the UMLIBS macro. +\par The Build Utility links against whatever things you list in the UMLIBS macro. Those things could be a .res file if you have a common resource, a library that you just buil +t in a subdirectory, a library or object from another subdirectory. There is no limit to what can be listed in UMLIBS. +\par The difference between UMTEST and UMAPPL is that if you use UMTEST, you need to specify the executable names that need to be built through the command line to build.exe. If you use UMAPPL, you need not specify anything on the command line, and build.exe w +ill automatically build all the program files. +\par {\b See Also}\line {\ul\cf11 UMLIBS}{\v UMLIBS}\line {\ul\cf11 UMTEST}{\v UMTEST} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} UMAPPLEXT}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} UMAPPLEXT}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} UMAPPLEXT;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} UMAPPLEXT +\par \pard\plain \ri130\sa240\widctlpar\tx4428\tx8856 \f7\fs20 Use this macro to specify the exten +sion name (for example .COM or .SCR) that will be appended when you want image files to have multiple filename extensions when you are building from a single source file. Use UMAPPLEXT when you want the extension to be something other than .exe. If you wa +nt the filename extension to be .exe, use UMAPPL. If you have questions about using UMAPPLEXT, see {\uldb\cf11 makefile.def}{\v makefile_def} or contact Bryan Tuttle or Wes Witt. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} UMBASE}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +$} UMBASE}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} UMBASEMacros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} UMBASE +\par \pard\plain \ri130\sa240\widctlpar\tx2718\tx8856 \f7\fs20 You only need to use this macro when you are building a dynamic link library (a +DLL). Use it to set the base address for the DLL image you are creating. If you do not specify an address, the Build Utility will assume that the target name in coffbase.txt is the name of your image. You can override this default target name by specifyin +g a target name with the DLLBASE macro. You can set DLLBASE to be the hard-coded base address, a hex address, or you can leave it blank. If you leave it blank, the Build Utility will always look up the target name specified in coffbase.txt. +\par Example: If you are building kernel32.dll, the Build Utility will look up kernel32 in coffbase.txt to find that base address. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} UMENTRY}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} UMENTRY}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} UMENTRY;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} UMENTRY +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +Use this macro to override the default entry point (mainCRTStartup) and specify the entry point depending on the UM Type. You can set this name to be anything you choose. If the UM Type is Windows or Console, the default entry point is main and you can ov +erride it with winmain, wmain, or wwinmain. +\par \pard \ri130\sa240\widctlpar\tx4428\tx8856 You can only use this macro if your UMTYPE is Windows or Console. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} UMENTRYABS}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} UMENTRYABS}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} UMENTRYABS;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} UMENTRYABS +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify an absolute entry point. For example, you might specify: +\par \pard \li720\ri130\sa240\widctlpar UMENTRY=main +\par \pard \ri130\sa240\widctlpar +but the real entry point is mainCRTStartup. If you do not want mainCRTStartup to be the entry point, specify UMENTRYABS to make main the absolute entry point. This prevents the Build Utility from going through the translation table that says if it\rquote +s main, make it mainCRTStartup. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} UMLIBS}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +$} UMLIBS}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} UMLIBS;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} UMLIBS +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to specify a list of library path names to be linked to the files specified in {\uldb\cf11 UMTEST}{\v UMTEST} or in{\uldb\cf11 UMAPPL. }{\v UMAPPL} + Include the library generated by the sources file. Separate the entries in this list with spaces or tabs. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} UMTEST}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +$} UMTEST}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} UMTEST;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} UMTEST +\par \pard\plain \ri130\sa240\widctlpar\tx4428\tx8856 \f7\fs20 Use this macro to list source filenames containing a main function. Type these filenames without filename extensions and separate them with an asterisk. +\par \pard \li720\ri130\sa240\widctlpar UMTEST=a*b*c*d +\par \pard \ri130\sa240\widctlpar\tx4428\tx8856 The Build Utility compiles and links each file in this list. +\par {\b See Also}\line {\uldb\cf11 UMAPPL}{\v UMAPPL} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} UMTYPE}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +$} UMTYPE}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} UMTYPE;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} UMTYPE +\par \pard\plain \ri130\sa240\widctlpar\tx4428\tx8856 \f7\fs20 Use this macro to specify the type of product being built: +\par \trowd \trgaph108\trleft-108 \cellx2250\cellx6750 \pard \ri130\sa240\widctlpar\intbl {\b Set UMTYPE to This:\cell To Specify This:}\cell \pard \widctlpar\intbl \row \trowd \trgaph108\trleft-108 \cellx2250\cellx6750 \pard \ri130\sa240\widctlpar\intbl {\b +windows\cell }A Win32 Program\cell \pard \widctlpar\intbl \row \pard \ri130\sa240\widctlpar\intbl {\b nt\cell }A Native Kernel-mode System Windows\~NT Program\cell \pard \widctlpar\intbl \row \pard \ri130\sa240\widctlpar\intbl {\b ntss\cell }A Windows\~ +NT Subsystem\cell \pard \widctlpar\intbl \row \pard \ri130\sa240\widctlpar\intbl {\b os2\cell }An OS/2 Program\cell \pard \widctlpar\intbl \row \pard \ri130\sa240\widctlpar\intbl {\b posix\cell }A POSIX Program\cell \pard \widctlpar\intbl \row \trowd +\trgaph108\trleft-108 \cellx2250\cellx6750 \pard \ri130\sa240\widctlpar\intbl {\b console\cell }A Win32 Console Program\cell \pard \widctlpar\intbl \row \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote +\pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} USE_CRTDLL}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super $} USE_CRTDLL}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super K} USE_CRTDLL;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} USE_CRTDLL +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Depending on how you want to link your image, you can link runtime libraries from the DLL for Windows\~NT or use: +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}\pard \fi-360\li360\ri130\sa240\widctlpar\tx360{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}The runtime libraries in a DLL +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}The multi-threaded runtime libraries +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}The single-threaded runtime libraries +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}The kernel runtime libraries +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}No runtime libraries at all +\par \pard \ri130\sa240\widctlpar Use this macro, or one of the following macros, to define the type of runtime library you are using. Which one of these macros you use will depend on the type of runtime libraries you want to have on your system. +\par \trowd \trgaph108\trleft-108 \cellx1687\cellx6115 \pard \ri130\sa240\widctlpar\intbl {\b This Marco:\cell Specifies This Runtime Library:\cell }\pard \widctlpar\intbl {\b \row }\trowd \trgaph108\trleft-108 \cellx1687\cellx6115 \pard +\ri130\sa240\widctlpar\intbl USE_CRTDLL\cell Multi-threaded runtime in a DLL\cell \pard \widctlpar\intbl \row \pard \ri130\sa240\widctlpar\intbl USE_MSVCRT\cell Multi-threaded runtime in a DLL\cell \pard \widctlpar\intbl \row \pard +\ri130\sa240\widctlpar\intbl USE_LIBCMT\cell Multi-threaded static\cell \pard \widctlpar\intbl \row \pard \ri130\sa240\widctlpar\intbl USE_LIBCNTPR\cell Kernel\cell \pard \widctlpar\intbl \row \pard \ri130\sa240\widctlpar\intbl USE_NTDLL\cell +The DLL for Windows\~NT\cell \pard \widctlpar\intbl \row \trowd \trgaph108\trleft-108 \cellx1687\cellx6115 \pard \ri130\sa240\widctlpar\intbl USE_NOLIBS\cell None\cell \pard \widctlpar\intbl \row \pard \ri130\sa240\widctlpar +The default is LIBC, statically linked in single-threaded runtime libraries. If you do not define any of these macros, you get LIBC. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} USE_INCREMENTAL_LINKING}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar +\f7\fs20 {\cs16\super $} USE_INCREMENTAL_LINKING}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} USE_INCREMENTAL_LINKING;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super +} MACROS:0}} USE_INCREMENTAL_LINKING +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro to direct the Build Utility to use incremental linking. +\par \pard \li720\ri130\sa240\widctlpar USE_INCREMENTAL_LINKING=1 +\par \pard \ri130\sa240\widctlpar If you are running on slower hardware, you may find that using incremental linking can speed up the build. +\par {\b See Also}\line {\uldb\cf11 USE_PDB}{\v USE_PDB}. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} USE_LIBCNTPR}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} USE_LIBCNTPR}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} USE_LIBCNTPR;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} USE_LIBCNTPR + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 See {\uldb\cf11 USE_CRTDLL. }{\v USE_CRTDLL} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} USE_MFC}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} USE_MFC}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} USE_MFC;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} USE_MFC +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro in your sources file to indicate you are using MFC. The syntax is: +\par \pard \li720\ri130\sa240\widctlpar USE_MFC=1 +\par \pard \ri130\sa240\widctlpar This will establish the correct build environment for a program that needs to use MFC. The Build Utility supports either MFC3 or MFC4. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} USE_MFC30}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} USE_MFC30}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} USE_MFC30;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} USE_MFC30 +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 Use this macro to direct the Build Utility to use MFC version 3.0 headers and libraries when building. You must list this with }{\ul\cf11 USE_MFC}{\v USE_MFC} or{\ul\cf11 USE_MFCUNICODE }{\v USE_MFCUNICODE +} to{\f5 be effective.} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} USE_MFCUNICODE}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} USE_MFCUNICODE}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} USE_MFCUNICODE;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + USE_MFCUNICODE +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Use this macro in your sources file to indicate you are using Unicode MFC. The syntax is: +\par \pard \li720\ri130\sa240\widctlpar USE_MFCUNICODE=1 +\par \pard \ri130\sa240\widctlpar This will establish the correct build environment for a program that needs to use Unicode MFC. The Build Utility supports either MFC3 or MFC4. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} USE_MSVCRT}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} USE_MSVCRT}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} USE_MSVCRT;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} USE_MSVCRT +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 See {\uldb\cf11 USE_CRTDLL. }{\v USE_CRTDLL} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} USE_NATIVE_EH}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} USE_NATIVE_EH}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} USE_NATIVE_EH;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + USE_NATIVE_EH +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 If you are using Try Catch and Throw, the standard C++ exception handling (C++EH), you must specify the following in your sources file: +\par \pard \li720\ri130\sa240\widctlpar USE_NATIVE_EH=1 +\par \pard \ri130\sa240\widctlpar This directs the Build Utility to turn on some needed switches to the compiler. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} USE_NOLIBS}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} USE_NOLIBS}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} USE_NOLIBS;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} USE_NOLIBS +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 See {\uldb\cf11 USE_CRTDLL. }{\v USE_CRTDLL} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} USE_NTDLL}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} USE_NTDLL}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} USE_NTDLL}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} USE_NTDLL +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 See {\uldb\cf11 USE_CRTDLL. }{\v USE_CRTDLL} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} USE_PDB}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} USE_PDB}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} USE_PDB;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} USE_PDB +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 If you want a VC4 PDB for your debug symbolic files, specify: +\par \pard \li720\ri130\sa240\widctlpar USE_PDB=1 +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} USE_STATIC_MFC}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} USE_STATIC_MFC}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} USE_STATIC_MFC;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + USE_STATIC_MFC +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +The Build Utility always uses MFC in a DLL, but there are a number of cases where that's not available. In those cases, specify USE_STATIC_MFC in your sources file. Then the Build Utility will link MFC into your program statically instead of dynamically l +oading it from a DLL. Your program will get bigger, but you can do more things. +\par If you need to redefine or change the MFC code, specify USE_STATIC_MFC because that enables you to make the changes you need, and whatever you do not change will be linked in for you. If you build a DLL, you must use what\rquote +s in the DLL. You cannot override classes. You cannot add new members. You cannot change arguments. +\par It\rquote s highly unlikely that you will ever need to use this macro. This macro was used in one case where the rich edit support was not correct for Windows\~NT. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} USECXX_FLAG}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} USECXX_FLAG}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} USECXX_FLAG;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} USECXX_FLAG + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 This macro enables you to go to a subdirectory that has all C files and compile them with the C++ compiler rather than the C compiler. One reason for + doing that might be switching to C++. Rather than change all your filenames to be a.cpp, b.cpp, which is a lot of work for no real gain, you can just specify: +\par \pard \li720\ri130\sa240\widctlpar USECXX_FLAG=/Tp +\par \pard \ri130\sa240\widctlpar That switch directs the compiler to compile this subdirectory using the C++ compiler instead of the C compiler. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} USER_C_FLAGS}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} USER_C_FLAGS}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} USER_C_FLAGS;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} USER_C_FLAGS + +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 Use this macro to specify flags that only go to the C/C++ compiler. Unlike }{\f5\uldb\cf11 C_DEFINES, }{\v\f5 CDEFINES}{\f5 USER_C_FLAGS doesn't go to the RC compiler.} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} USER_INCLUDES}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} USER_INCLUDES}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} USER_INCLUDES;Macros}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} MACROS:0}} + USER_INCLUDES +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 You will usually use the {\uldb\cf11 INCLUDES}{\v INCLUDES} + macro in your sources file to indicate to the Build Utility where to find the headers that you are including in your build. But there are times when some header files may not exist. Maybe they are built as part of the build process. Specify those header +files in USER_INCLUDES to notify the Build Utility, \ldblquote Here\rquote s another place to go, but do not worry if you cannot find these header files because there may not be anything there.\rdblquote +\par The reason you put things in USER_INCLUDES is because you {\ul do not} want the Build Utility to do dependency checking on them. They either will be there or they won\rquote t, but it\rquote s not up to the Build Utility to figure out if they\rquote +re not found. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} USE_LIBCMT}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} USE_LIBCMT}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} USE_LIBCMT;Macros}} USE_LIBCMT +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 See {\uldb\cf11 USE_CRTDLL. }{\v USE_CRTDLL} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Building_NT_Software}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar +\f7\fs20 {\cs16\super $} Building NT Software}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Building NT Software}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} + BUILDNT:0}} Building Windows NT Software +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 The Build Utility assumes you are building the current version of Windows NT (current meaning what Windows\~ +NT is currently working on, not what has already shipped). If you are building something that needs to run on a future version of Windows\~NT, there are other settings available. +\par If you have a single set of source files that build for Chicago, Windows\~NT, or future versions of Windows\~NT, there are some macros that you can specify in your source code to do that. They are: +\par \pard \li720\ri130\sa240\widctlpar WIN_32_WINNT for Windows\~NT +\par WIN32_WINDOWS for Chicago or Win95 +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Building_Chicago_Software}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar +\f7\fs20 {\cs16\super $} Building Chicago Software}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Building Chicago Software;Chicago}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super +} CHICAGO:0}} Building Chicago Software +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 The Build Utility assumes you are building the current version of Windows\~NT (current meaning what Windows\~NT is currently working on, not what has already shipped). If you want to build a Chicago bin +ary, specify the following in your sources file: +\par \pard \li720\ri130\sa240\widctlpar CHICAGO_PRODUCT=1 +\par \pard \ri130\sa240\widctlpar This defines some variables to indicate to the Build Utility that you are building a Chicago product. It defines Chicago to be equal to 200. It does not use any of the system DLLs for Windows\~ +NT. It always uses just kernel 32 DLLs. If you specify this in your sources file, when you are all done building, you should have an .exe that will run fine on Win95 and on Windows\~NT at the same time. +\par This macro was used by the OLE team. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Building_Win32_Subsystem_Software}} {\cs16\super ${\footnote \pard\plain +\s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super $} Building Win32 Subsystem Software}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Building Win32 Subsystem Software}} {\cs16\super +{\footnote \pard\plain +\s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} WIN:0}} Building Win32 Subsystem Software +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 In the sources file describing a Win32 build product, set UMTPYE to windows: +\par \pard \li720\ri130\sa240\widctlpar UMTYPE=windows +\par \pard \ri130\sa240\widctlpar This selects the appropriate libraries and entry point for the build product(s). +\par For an example of a sources file that builds a Win32 program, see \\\\rastaman\\ntwin\\src\\shell\\accessory\\calc\\sources. +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Rules}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super $ +} Rules}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Rules}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} RULES:0}} Rules +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}\pard\plain \fi-360\li360\ri130\sa240\widctlpar{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}\f7\fs20 There are a number of limitations and rules associated with the Build Utility. +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}\pard \fi-360\li360\ri130\sa240\widctlpar\tx360{\*\pn \pnlvlblt\pnf1\pnstart1\pnindent360\pnhang{\pntxtb \'b7}}Only one DLL or library may be built in a given source directory. The equivalent of an import libr +ary will be generated automatically when you build a DLL. +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}Any number of .exe files can be generated, as long as each one consists of a single source file (containing main) that is to be linked to the library or DLL being generated. +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}If your DLL needs to link with other libraries, these libraries must be specified in the {\uldb\cf11 TARGETLIBS}{\v TARGETLIBS} + statement within your sources file. These libraries must be specified with the same * notation as described for {\ul\cf11 UMLIBS. }{\v UMLIBS} +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}Build.exe does not understand NMAKE macros or conditional syntax. So the value of a BUILD keyword in a sources file must be textual; it cannot contain references to NMAKE macros. +\par {\pntext\pard\plain\f1\fs20 \'b7\tab}{\f5 Only files in the current subdirectory, one directory above, and in the platform subdirectory can be listed in the }{\f5\ul\cf11 SOURCES}{\v\f5 SOURCES}{\f5 macro.} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Debugging}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Debugging}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Debugging}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} DEBUG:0}} Debugging +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 In the build environment for Windows\~NT, you can {\ul always} + debug what you build. No matter how you build using the Build Utility, you get debug symbolic files. This is different from other build processes. In the VC build e +nvironment, when you are building debug you get debug symbolic files; when you are building retail, you get nothing{\f5 You control the type and amount of symbolic information with the }{\uldb\cf11 NTDEBUG, }{\v NTDEBUG}{\f5 }{\uldb\cf11 NTDEBUGTYPE, }{ +\v NTDEBUGTYPE}{\f5 and }{\uldb\cf11 MSC_OPTIMIZATION}{\v MSC_OPTIMIZATION} {\f5 +variables. For example, NTDEBUG=ntsd, NTDEBUGTYPE=both, MSC_OPTIMIZATION=/Odi will allow you to single step through your code with windbg and the VC ide or you can asm debug with ntsd or the kernel debuggers.} +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Frequently_Asked_Questions}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar +\f7\fs20 {\cs16\super $} Frequently Asked Questions}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Frequently Asked Questions}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super +} FAQ:0}} Frequently Asked Questions +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\ul\cf11 Question #1: }{\v Answer_1} I{\f5 have a new }multi-processor{\f5 machine. How do I take advantage of it with build?} +\par {\ul\cf11 Question #2: }{\v Answer_2}{\v\f5 }{\f5\cf1 I've read the help file. I've tried the quick start. I still have more questions. Is there anyone I can ask for help?}{\f5 } +\par {\uldb\cf11 Question #3: }{\v Answer_3} {\f5\cf1 What about Win16 or OS/2? I have legacy code I need to maintain and the build process I use works. Can I integrate it into the build utility? +\par }{\f5\uldb\cf11 Question #4: }{\v\f5 Answer_4}{\f5 What's the best way to convert a p}roject to use the Build Utility? +\par {\ul\cf11 Question #5: }{\v Answer_5} {\f5 How do I generate debugging information? +\par }{\uldb\cf11 Question #6: }{\v Answer_6} {\f5 {\*\bkmkstart ROBOHELP}{\*\bkmkend ROBOHELP}What's the difference between free and checked builds?} +\par {\ul\cf11 Question #7: }{\v Answer_8} What happened to all the makefiles? +\par {\ul\cf11 Question #8: }{\v Answer_9} Where is my .def file? +\par {\uldb\cf11 Question #9: }{\v Answer_10} Do I have to edit the dirs files to customize which components I build? +\par {\ul\cf11 Question #10: }{\v Answer_11} I get a return code of 4b from binplace - why? +\par {\ul\cf11 Question #11: }{\v Answer_12} I am getting a load of undefined symbols which I know are exported from a DLL (often the shell DLL msvcshl$(D)). Why? +\par {\ul\cf11 Question #12: }{\v Answer_13} Where do the build errors go? I need to know what failed. +\par {\ul\cf11 Question #13: }{\v Answer_14} How do I get browse information? +\par {\ul\cf11 Question #14: }{\v Answer_15} I have a number of small tools that have a subset of common code. There is just one source file between them that\rquote +s different. Can I avoid having a different subdirectory for each one of these little baby tools? +\par {\ul\cf11 Question #15: }{\v Answer_16} I've got five subdirectories and they all use all the same headers. I want to put one precompiled header someplace and have all of them use it. +\par {\ul\cf11 Question #16: }{\v Answer_17} I do not like the idea of having a public folder on my machine. Do I have to follow the build model for Windows\~NT that uses this directory structure? +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Glossary}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Glossary}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Glossary}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} GLOSS:0}} Glossary +\par \pard\plain \ri130\widctlpar \f7\fs20 {\ul\cf11 GDI}{\v GDI} +\par {\ul\cf11 GUIDs}{\v GUIDs} +\par {\ul\cf11 Hardware Abstraction Layer (HAL) }{\v Hardware_Abstraction_Layer} +\par {\ul\cf11 IDL}{\v IDL} +\par {\ul\cf11 MIDL}{\v MIDL} +\par +\par +\par +\par +\par +\par +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} GUIDs}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super $ +} GUIDs}} GUIDs +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Global Unique Identifiers. A GUID is a 16-byte structure that you use to identify classes in OLE. +\par +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} GDI}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super $} + GDI}} GDI +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Graphics Device Interface +\par +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Hardware_Abstraction_Layer}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar +\f7\fs20 {\cs16\super $} Hardware Abstraction Layer}} Hardware Abstraction Layer +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 It is a dynamic link library (DLL) that protects the Windows\~ +NT Executive from variations in different vendors' hardware platforms to maximize the operating system's portability. The HAL implements functions that abstract I/O interfaces, the interrupt con +troller, hardware caches, multiprocessor communication mechanisms, and so forth. +\par +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} IDL}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super $} + IDL}} IDL +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Interface Description Language. This is used for RPC code to handle stubs that specify how to marshal arguments between the client and server. +\par +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Answer_1}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Answer #1}} Answer +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 Usually, it is very simple. Just add -M to the command line when you start the build utility. If you want this as the default, add it to your }{\ul\cf11 BUILD_DEFAULT}{\v BUILD_DEFAULTS} {\f5 +environment variable. For more information, see }{\uldb\cf11 Multi-processor Build Issues. }{\v Multi_processor_Build_Issues} +\par +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Answer_2}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Answer #2}} Answer +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5\cf1 Send mail to BryanT or the NT build lab.} +\par +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Answer_3}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Answer #3}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Answer #3}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} BUILD:0}} Answer +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5\cf1 There are several ways to do this. The easiest is to create a}{\f5\ul\cf11 }{\i\f5\ul\cf11 sources}{\f5\ul\cf11 file }{\v\f5 SOURCES_File}{\f5 }{\f5\cf1 +which builds no target. It can then call your existing build process. In this case, the Build Utility is used strictly to spawn nmake. Here's an example: +\par }\pard \ri130\widctlpar {\f5\cf1 +\par ======== Sources file ======== +\par +\par }{\ul\cf11 TARGETNAME}{\v TARGETNAME}{\f5\cf1 = +\par }{\uldb\cf11 TARGETTYPE}{\v TARGETTYPE}={\f5\cf1 NOTARGET +\par }{\ul\cf11 TARGETPATH}{\v TARGETPATH}{\f5\cf1 = +\par }{\ul\cf11 SOURCES}{\v SOURCES}{\f5\cf1 = +\par }{\ul\cf11 NTTARGETFILES}{\v NT_TARGETFILES}{\f5\cf1 =MyOldBuild +\par }{\ul\cf11 MISCFILES}{\v MISCFILES}{\f5\cf1 = +\par +\par ======== makefile.inc ======== +\par MyOldBuild: +\par nmake +\par +\par Another option is to create a }{\ul\cf11 makefil0}{\v makefile0}. {\f5\cf1 It has the added advantage in that the build utility will execute the all rule for a regular build and the clean rule when the -c switch is used. Here's an example: +\par }{\f5 +\par ======== dirs ========= +\par DIRS= Win32Dir1 Win32Dir2 Win32Dir3 +\par +\par ======== makefil0 ======== +\par all: +\par nmake +\par +\par clean: +\par nmake +\par }\pard \ri130\sa240\widctlpar +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Answer_4}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Answer #4}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Answer #4}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} BUILD:0}} Answer #4 +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 1. Generate a full build of the project with your existing build. Make sure you can find all the switches passed to the compiler, include paths, linker options, resource compiler usage, ext +ra utilities you use, directory processing order, etc. Most builds try to hide all of this, but it's important for this purpose. +\par 2. Take a look at the extra tools you use. If they aren't available for all platforms (X86, Mips, Alpha, PPC, etc.), find the source code and start building it first. If you can't get the tools for all platforms, don't waste your time converting more co +de. +\par 3. Look over the output from Step1. Many non-trivial builds will have common code. Build library(s) with this code. If you want to do dual builds while you're converting, your existing makefiles can have a wrapper added. Here's an example: +\par }\pard \ri130\widctlpar {\f5 +\par ======= Existing makefile ========= +\par !ifdef NTMAKEENV +\par !include $(NTMAKEENV)\\makefile.def +\par !else +\par # The current makefile go here +\par !endif +\par +\par }\pard \ri130\sa240\widctlpar {\f5 Now by defining NTMAKEENV, the subdir will use the build utility. Otherwise, your existing build will still work. +\par 4. Build the core DLLs next. This will also generate import libraries. +\par 5. Build the .exes and ancillary DLLs next. These will probably use the common libraries you built in Step 3 and the import libraries from Step 4. +\par 6. Add dirs files as needed to these together. By using DIRS for projects you're sure build and OPTIONAL_DIRS to projects that you're converting, you can keep the build working for other users at the same time. Try to list the directories that build lib +raries and DLL's first as it reduces the chance you'll need Multiprocessor synchronization. +\par 7. Make sure you have someone else build on an alternate platform just to make sure you didn't introduce a platform dependency. Continue working until done. +\par } +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Answer_5}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Answer #5}} Answer #5 +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 The debugging information is controlled with the {\ul\cf11 NTDEBUGTYPE}{\v NTDEBUGTYPE} + environment variable which you set before you build the project. Usually, windbg or both is appropriate. All builds have debug symbolic information which is later stripped out into a .dbg file with the {\uldb\cf11 Binplace}{\v binplace_exe} + Utility as part of the build. If you want to generate PDBs for the Codeview information, set USE_PDB=1 in the sources file or in the environment when you build. +\par +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Answer_6}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Answer #6}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Answer #6}} {\cs16\super +{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super +} BUILD:0}} Answer #6 +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 {\f5 +Think of them as Retail and Debug except the ONLY difference is whether DBG is defined or not. Checked defines DBG, Free doesn't. Optimizations are enabled all the time. You're welcome to change these based on the }FREEBUILD{\f5 + setting in your sources file. For instance: +\par }\pard \ri130\widctlpar {\f5 ====== sources file ======== +\par ... +\par !if !$(FREEBUILD) +\par C_DEFINES = $(C_DEFINES) /D_DEBUG +\par MSC_OPTIMIZATION=-Odi +\par !else +\par C_DEFINES = $(C_DEFINES) /DNDEBUG +\par !endif +\par }\pard \ri130\sa240\widctlpar {\f5 ... +\par The Free/Check setting is controlled by the }{\uldb\cf11 NTDEBUG}{\v NTDEBUG} {\f5 environment variable. Set it to ntsd for a checked build, ntsdnodbg for a free build. +\par }{\f5\cf10 Note:}{\f5 on the NTDEBUG page, all the blue text can be removed. Also the last sentence ("Some groups, such as the VC group, define _DEBUG... version") can be deleted also. A comment should be added that: +\par It is rarely used in the sources file, instead it should be set in the environment before building the project. +\par }\pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Answer_8}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Answer #8}} Answer +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 All directories still contain a makefile, but it just includes the standard makefile.def file. This makefile should not be edited. Instead look in the corresponding sources and {\uldb\cf11 makefile.inc}{\v +mk_inc} + files when you need to make local changes to how a component builds, or the sources.inc and makefile.inc files in directories above your component to make more global changes. When adding a new component, it will need at least a sources and the standard +makefile, and may need a makefile.inc as well. +\par +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Answer_9}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Answer #9}} Answer +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 The .def files that need preprocessing have been renamed as .src files so the preprocessing happens automatically. +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Answer_10}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Answer #10}} {\cs16\super K{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super K} Answer #10}} Answer +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 No. You can give directions to build on the command line, or in the environment variable BUILD_OPTIONS. So with the following dirs file: +\par \pard \li720\ri130\widctlpar DIRS=dir1 +\par \pard \ri130\widctlpar \tab OPTIONAL_DIRS=dir2 +\par +\par \tab build +\par \tab -or- +\par \tab build ~dir2 +\par \tab builds dir1 +\par +\par \tab build dir2 +\par \tab builds dir1 and dir2 +\par +\par \tab build dir2 ~dir1 +\par \tab builds dir2 only +\par +\par Or you can set BUILD_OPTIONS=dir2 ~dir1. +\par +\par \pard \ri130\sa240\widctlpar +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Answer_13}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Answer #13}} Answer +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 If you use the -e flag, you get BUILD.LOG, BUILD.ERR and BUILD.WRN in the directory in which you invoked build.exe. +\par +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Answer_14}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Answer #14}} Answer +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Set BROWSER_INFO=1. +\par +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Answer_15}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Answer #15}} Answer +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 Yes. For more information, see {\uldb\cf11 Building Multiple Targets from One Subdirectory. }{\v Building_Multiple_Targets_from_One_Subdirectory} +\par +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Answer_16}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Answer #16}} Answer +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 +This may be more problematic than it's worth because you then get into issues where if the precompiled header changes, you've got to rebuild five subdirectories instead of just one. If you really want to do this, read {\uldb\cf11 makefile.def}{\v +makefile_def} or send email to Bryan Tuttle to answer questions about how to do it. +\par +\par +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} Answer_17}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} Answer #17}} Answer +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 No. You do not need to follow the same directory structure as Windows\~NT in which s{\f5 ource code is in project directories under $(}{\ul\cf11 BASEDIR}{\v BASEDIR}{\f5 )\\ +private and shared libraries and headers are under $(}BASEDIR)\\{\f5 public}. You can specify the following macros in your sources file{\f5 . These macros enable you to eliminate the reliance on public}: +\par \pard \ri130\widctlpar {\f5\ul\cf11 BINPLACE_PLACEFILE}{\v\f5 BINPLACE_PLACEFILE}{\f5 \line }{\f5\uldb\cf11 COFFBASE_TXT_FILE}{\v\f5 COFFBASE_TXT_FILE}{\f5 \line }{\f5\ul\cf11 COMPILER_WARNINGS}{\v\f5 COMPILER_WARNINGS}{\f5 \line }{\ul\cf11 CRT_INC_PATH}{ +\v CRT_INC_PATH} +\par {\ul\cf11 CRT_LIB_PATH}{\v CRT_LIB_PATH} +\par {\f5\uldb\cf11 MASTER_VERSION_FILE}{\v\f5 MASTER_VERSION_FILE}{\f5 \line }{\f5\ul\cf11 MFC_INC_PATH}{\v\f5 MFC_INC_PATH}{\f5 \line }{\f5\ul\cf11 MFC_LIB_PATH}{\v\f5 MFC_LIB_PATH}{\ul\cf11 \line OAK_INC_PATH}{\v OAK_INC_PATH}\line {\ul\cf11 SDK_INC_PATH}{ +\v SDK_INC_PATH} +\par {\ul\cf11 SDK_LIB_PATH}{\v SDK_LIB_PATH} +\par \pard \ri130\sa240\widctlpar +\par \pard\plain \s1\li115\ri130\sb80\sa120\widctlpar \b\f7\kerning28 \page {\cs16\super #{\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 {\cs16\super #} makefile0}} {\cs16\super ${\footnote \pard\plain \s15\ri130\sa240\widctlpar \f7\fs20 { +\cs16\super $} makefile0}} makefile0 +\par \pard\plain \ri130\sa240\widctlpar \f7\fs20 This is a makefile you write that exists in the same subdirectory as a {\uldb\cf11 dirs file. }{\v DIRS_File} + It is typically used to build header files needed in the subdirectories. The Build utility will spawn nmake to execute this file before traversing the directory list in the dirs file. +\par +\par } \ No newline at end of file diff --git a/sdktools/docs/build.rtk b/sdktools/docs/build.rtk new file mode 100644 index 0000000000000000000000000000000000000000..e370f89dacee583829a9d0f9747947e67f272cf8 GIT binary patch literal 9365 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 version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __scrproc_h__ +#define __scrproc_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __IScriptedProcess_FWD_DEFINED__ +#define __IScriptedProcess_FWD_DEFINED__ +typedef interface IScriptedProcess IScriptedProcess; +#endif /* __IScriptedProcess_FWD_DEFINED__ */ + + +#ifndef __IScriptedProcessSink_FWD_DEFINED__ +#define __IScriptedProcessSink_FWD_DEFINED__ +typedef interface IScriptedProcessSink IScriptedProcessSink; +#endif /* __IScriptedProcessSink_FWD_DEFINED__ */ + + +#ifndef __LocalScriptedProcess_FWD_DEFINED__ +#define __LocalScriptedProcess_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class LocalScriptedProcess LocalScriptedProcess; +#else +typedef struct LocalScriptedProcess LocalScriptedProcess; +#endif /* __cplusplus */ + +#endif /* __LocalScriptedProcess_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "oleidl.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +void * __RPC_USER MIDL_user_allocate(size_t); +void __RPC_USER MIDL_user_free( void * ); + +/* interface __MIDL_itf_scrproc_0000 */ +/* [local] */ + + + + +extern RPC_IF_HANDLE __MIDL_itf_scrproc_0000_v0_0_c_ifspec; +extern RPC_IF_HANDLE __MIDL_itf_scrproc_0000_v0_0_s_ifspec; + +#ifndef __IScriptedProcess_INTERFACE_DEFINED__ +#define __IScriptedProcess_INTERFACE_DEFINED__ + +/* interface IScriptedProcess */ +/* [uuid][object] */ + + +EXTERN_C const IID IID_IScriptedProcess; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("854c3171-c854-4a77-b189-606859e4391b") + IScriptedProcess : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE SetProcessID( + /* [in] */ long lProcessID, + /* [string][in] */ wchar_t *pszEnvID) = 0; + + virtual HRESULT STDMETHODCALLTYPE SendData( + /* [string][in] */ wchar_t *pszType, + /* [string][in] */ wchar_t *pszData, + /* [out] */ long *plReturn) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetExitCode( + /* [in] */ long lExitCode) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetProcessSink( + /* [in] */ IScriptedProcessSink *pSPS) = 0; + + }; + +#else /* C style interface */ + + typedef struct IScriptedProcessVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IScriptedProcess * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IScriptedProcess * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IScriptedProcess * This); + + HRESULT ( STDMETHODCALLTYPE *SetProcessID )( + IScriptedProcess * This, + /* [in] */ long lProcessID, + /* [string][in] */ wchar_t *pszEnvID); + + HRESULT ( STDMETHODCALLTYPE *SendData )( + IScriptedProcess * This, + /* [string][in] */ wchar_t *pszType, + /* [string][in] */ wchar_t *pszData, + /* [out] */ long *plReturn); + + HRESULT ( STDMETHODCALLTYPE *SetExitCode )( + IScriptedProcess * This, + /* [in] */ long lExitCode); + + HRESULT ( STDMETHODCALLTYPE *SetProcessSink )( + IScriptedProcess * This, + /* [in] */ IScriptedProcessSink *pSPS); + + END_INTERFACE + } IScriptedProcessVtbl; + + interface IScriptedProcess + { + CONST_VTBL struct IScriptedProcessVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IScriptedProcess_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IScriptedProcess_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IScriptedProcess_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IScriptedProcess_SetProcessID(This,lProcessID,pszEnvID) \ + (This)->lpVtbl -> SetProcessID(This,lProcessID,pszEnvID) + +#define IScriptedProcess_SendData(This,pszType,pszData,plReturn) \ + (This)->lpVtbl -> SendData(This,pszType,pszData,plReturn) + +#define IScriptedProcess_SetExitCode(This,lExitCode) \ + (This)->lpVtbl -> SetExitCode(This,lExitCode) + +#define IScriptedProcess_SetProcessSink(This,pSPS) \ + (This)->lpVtbl -> SetProcessSink(This,pSPS) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IScriptedProcess_SetProcessID_Proxy( + IScriptedProcess * This, + /* [in] */ long lProcessID, + /* [string][in] */ wchar_t *pszEnvID); + + +void __RPC_STUB IScriptedProcess_SetProcessID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IScriptedProcess_SendData_Proxy( + IScriptedProcess * This, + /* [string][in] */ wchar_t *pszType, + /* [string][in] */ wchar_t *pszData, + /* [out] */ long *plReturn); + + +void __RPC_STUB IScriptedProcess_SendData_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IScriptedProcess_SetExitCode_Proxy( + IScriptedProcess * This, + /* [in] */ long lExitCode); + + +void __RPC_STUB IScriptedProcess_SetExitCode_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IScriptedProcess_SetProcessSink_Proxy( + IScriptedProcess * This, + /* [in] */ IScriptedProcessSink *pSPS); + + +void __RPC_STUB IScriptedProcess_SetProcessSink_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IScriptedProcess_INTERFACE_DEFINED__ */ + + +#ifndef __IScriptedProcessSink_INTERFACE_DEFINED__ +#define __IScriptedProcessSink_INTERFACE_DEFINED__ + +/* interface IScriptedProcessSink */ +/* [uuid][object] */ + + +EXTERN_C const IID IID_IScriptedProcessSink; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("854c3172-c854-4a77-b189-606859e4391b") + IScriptedProcessSink : public IUnknown + { + public: + virtual HRESULT STDMETHODCALLTYPE RequestExit( void) = 0; + + virtual HRESULT STDMETHODCALLTYPE ReceiveData( + /* [string][in] */ wchar_t *pszType, + /* [string][in] */ wchar_t *pszData, + /* [out] */ long *plReturn) = 0; + + }; + +#else /* C style interface */ + + typedef struct IScriptedProcessSinkVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IScriptedProcessSink * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IScriptedProcessSink * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IScriptedProcessSink * This); + + HRESULT ( STDMETHODCALLTYPE *RequestExit )( + IScriptedProcessSink * This); + + HRESULT ( STDMETHODCALLTYPE *ReceiveData )( + IScriptedProcessSink * This, + /* [string][in] */ wchar_t *pszType, + /* [string][in] */ wchar_t *pszData, + /* [out] */ long *plReturn); + + END_INTERFACE + } IScriptedProcessSinkVtbl; + + interface IScriptedProcessSink + { + CONST_VTBL struct IScriptedProcessSinkVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IScriptedProcessSink_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IScriptedProcessSink_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IScriptedProcessSink_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IScriptedProcessSink_RequestExit(This) \ + (This)->lpVtbl -> RequestExit(This) + +#define IScriptedProcessSink_ReceiveData(This,pszType,pszData,plReturn) \ + (This)->lpVtbl -> ReceiveData(This,pszType,pszData,plReturn) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +HRESULT STDMETHODCALLTYPE IScriptedProcessSink_RequestExit_Proxy( + IScriptedProcessSink * This); + + +void __RPC_STUB IScriptedProcessSink_RequestExit_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +HRESULT STDMETHODCALLTYPE IScriptedProcessSink_ReceiveData_Proxy( + IScriptedProcessSink * This, + /* [string][in] */ wchar_t *pszType, + /* [string][in] */ wchar_t *pszData, + /* [out] */ long *plReturn); + + +void __RPC_STUB IScriptedProcessSink_ReceiveData_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IScriptedProcessSink_INTERFACE_DEFINED__ */ + + + +#ifndef __MTScriptedProcessLib_LIBRARY_DEFINED__ +#define __MTScriptedProcessLib_LIBRARY_DEFINED__ + +/* library MTScriptedProcessLib */ +/* [uuid] */ + + +EXTERN_C const IID LIBID_MTScriptedProcessLib; + +EXTERN_C const CLSID CLSID_LocalScriptedProcess; + +#ifdef __cplusplus + +class DECLSPEC_UUID("854c316f-c854-4a77-b189-606859e4391b") +LocalScriptedProcess; +#endif +#endif /* __MTScriptedProcessLib_LIBRARY_DEFINED__ */ + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 6.00.0338 */ +/* Compiler settings for od.idl: + Oicf, W1, Zp8, env=Win32 (32b run) + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +//@@MIDL_FILE_HEADING( ) + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + +#ifndef COM_NO_WINDOWS_H +#include "windows.h" +#include "ole2.h" +#endif /*COM_NO_WINDOWS_H*/ + +#ifndef __od_h__ +#define __od_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __IObjectDaemon_FWD_DEFINED__ +#define __IObjectDaemon_FWD_DEFINED__ +typedef interface IObjectDaemon IObjectDaemon; +#endif /* __IObjectDaemon_FWD_DEFINED__ */ + + +#ifndef __ObjectDaemon_FWD_DEFINED__ +#define __ObjectDaemon_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class ObjectDaemon ObjectDaemon; +#else +typedef struct ObjectDaemon ObjectDaemon; +#endif /* __cplusplus */ + +#endif /* __ObjectDaemon_FWD_DEFINED__ */ + + +/* header files for imported files */ +#include "unknwn.h" +#include "oaidl.h" + +#ifdef __cplusplus +extern "C"{ +#endif + +void * __RPC_USER MIDL_user_allocate(size_t); +void __RPC_USER MIDL_user_free( void * ); + +#ifndef __IObjectDaemon_INTERFACE_DEFINED__ +#define __IObjectDaemon_INTERFACE_DEFINED__ + +/* interface IObjectDaemon */ +/* [object][dual][uuid] */ + + +EXTERN_C const IID IID_IObjectDaemon; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("854c3183-c854-4a77-b189-606859e4391b") + IObjectDaemon : public IDispatch + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetMaximumIndex( + /* [retval][out] */ DWORD *dwMaxIndex) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetIdentity( + /* [in] */ DWORD dwIndex, + /* [retval][out] */ BSTR *pbstrIdentity) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetProgID( + /* [in] */ DWORD dwIndex, + /* [retval][out] */ BSTR *pbstrProgId) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OpenInterface( + /* [in] */ BSTR bstrIdentity, + /* [in] */ BSTR bstrProgId, + /* [in] */ BOOL fCreate, + /* [retval][out] */ IDispatch **ppDisp) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RemoveInterface( + /* [in] */ BSTR bstrIdentity, + /* [in] */ BSTR bstrProgId) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE IdentifyInterface( + /* [in] */ IDispatch *pDisp, + /* [out] */ BSTR *pbstrIdentity, + /* [retval][out] */ BSTR *pbstrProgId) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE IdentifyInterfaceIndex( + /* [in] */ IDispatch *pDisp, + /* [retval][out] */ DWORD *pdwIndex) = 0; + + }; + +#else /* C style interface */ + + typedef struct IObjectDaemonVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IObjectDaemon * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IObjectDaemon * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IObjectDaemon * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IObjectDaemon * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IObjectDaemon * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IObjectDaemon * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IObjectDaemon * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetMaximumIndex )( + IObjectDaemon * This, + /* [retval][out] */ DWORD *dwMaxIndex); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetIdentity )( + IObjectDaemon * This, + /* [in] */ DWORD dwIndex, + /* [retval][out] */ BSTR *pbstrIdentity); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetProgID )( + IObjectDaemon * This, + /* [in] */ DWORD dwIndex, + /* [retval][out] */ BSTR *pbstrProgId); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *OpenInterface )( + IObjectDaemon * This, + /* [in] */ BSTR bstrIdentity, + /* [in] */ BSTR bstrProgId, + /* [in] */ BOOL fCreate, + /* [retval][out] */ IDispatch **ppDisp); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *RemoveInterface )( + IObjectDaemon * This, + /* [in] */ BSTR bstrIdentity, + /* [in] */ BSTR bstrProgId); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *IdentifyInterface )( + IObjectDaemon * This, + /* [in] */ IDispatch *pDisp, + /* [out] */ BSTR *pbstrIdentity, + /* [retval][out] */ BSTR *pbstrProgId); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *IdentifyInterfaceIndex )( + IObjectDaemon * This, + /* [in] */ IDispatch *pDisp, + /* [retval][out] */ DWORD *pdwIndex); + + END_INTERFACE + } IObjectDaemonVtbl; + + interface IObjectDaemon + { + CONST_VTBL struct IObjectDaemonVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IObjectDaemon_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IObjectDaemon_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IObjectDaemon_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IObjectDaemon_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IObjectDaemon_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IObjectDaemon_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IObjectDaemon_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IObjectDaemon_GetMaximumIndex(This,dwMaxIndex) \ + (This)->lpVtbl -> GetMaximumIndex(This,dwMaxIndex) + +#define IObjectDaemon_GetIdentity(This,dwIndex,pbstrIdentity) \ + (This)->lpVtbl -> GetIdentity(This,dwIndex,pbstrIdentity) + +#define IObjectDaemon_GetProgID(This,dwIndex,pbstrProgId) \ + (This)->lpVtbl -> GetProgID(This,dwIndex,pbstrProgId) + +#define IObjectDaemon_OpenInterface(This,bstrIdentity,bstrProgId,fCreate,ppDisp) \ + (This)->lpVtbl -> OpenInterface(This,bstrIdentity,bstrProgId,fCreate,ppDisp) + +#define IObjectDaemon_RemoveInterface(This,bstrIdentity,bstrProgId) \ + (This)->lpVtbl -> RemoveInterface(This,bstrIdentity,bstrProgId) + +#define IObjectDaemon_IdentifyInterface(This,pDisp,pbstrIdentity,pbstrProgId) \ + (This)->lpVtbl -> IdentifyInterface(This,pDisp,pbstrIdentity,pbstrProgId) + +#define IObjectDaemon_IdentifyInterfaceIndex(This,pDisp,pdwIndex) \ + (This)->lpVtbl -> IdentifyInterfaceIndex(This,pDisp,pdwIndex) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IObjectDaemon_GetMaximumIndex_Proxy( + IObjectDaemon * This, + /* [retval][out] */ DWORD *dwMaxIndex); + + +void __RPC_STUB IObjectDaemon_GetMaximumIndex_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IObjectDaemon_GetIdentity_Proxy( + IObjectDaemon * This, + /* [in] */ DWORD dwIndex, + /* [retval][out] */ BSTR *pbstrIdentity); + + +void __RPC_STUB IObjectDaemon_GetIdentity_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IObjectDaemon_GetProgID_Proxy( + IObjectDaemon * This, + /* [in] */ DWORD dwIndex, + /* [retval][out] */ BSTR *pbstrProgId); + + +void __RPC_STUB IObjectDaemon_GetProgID_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IObjectDaemon_OpenInterface_Proxy( + IObjectDaemon * This, + /* [in] */ BSTR bstrIdentity, + /* [in] */ BSTR bstrProgId, + /* [in] */ BOOL fCreate, + /* [retval][out] */ IDispatch **ppDisp); + + +void __RPC_STUB IObjectDaemon_OpenInterface_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IObjectDaemon_RemoveInterface_Proxy( + IObjectDaemon * This, + /* [in] */ BSTR bstrIdentity, + /* [in] */ BSTR bstrProgId); + + +void __RPC_STUB IObjectDaemon_RemoveInterface_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IObjectDaemon_IdentifyInterface_Proxy( + IObjectDaemon * This, + /* [in] */ IDispatch *pDisp, + /* [out] */ BSTR *pbstrIdentity, + /* [retval][out] */ BSTR *pbstrProgId); + + +void __RPC_STUB IObjectDaemon_IdentifyInterface_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IObjectDaemon_IdentifyInterfaceIndex_Proxy( + IObjectDaemon * This, + /* [in] */ IDispatch *pDisp, + /* [retval][out] */ DWORD *pdwIndex); + + +void __RPC_STUB IObjectDaemon_IdentifyInterfaceIndex_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IObjectDaemon_INTERFACE_DEFINED__ */ + + + +#ifndef __ObjectDaemonLib_LIBRARY_DEFINED__ +#define __ObjectDaemonLib_LIBRARY_DEFINED__ + +/* library ObjectDaemonLib */ +/* [uuid] */ + + +EXTERN_C const IID LIBID_ObjectDaemonLib; + +EXTERN_C const CLSID CLSID_ObjectDaemon; + +#ifdef __cplusplus + +class DECLSPEC_UUID("854c3184-c854-4a77-b189-606859e4391b") +ObjectDaemon; +#endif +#endif /* __ObjectDaemonLib_LIBRARY_DEFINED__ */ + +/* Additional Prototypes for ALL interfaces */ + +unsigned long __RPC_USER BSTR_UserSize( unsigned long *, unsigned long , BSTR * ); +unsigned char * __RPC_USER BSTR_UserMarshal( unsigned long *, unsigned char *, BSTR * ); +unsigned char * __RPC_USER BSTR_UserUnmarshal(unsigned long *, unsigned char *, BSTR * ); +void __RPC_USER BSTR_UserFree( unsigned long *, BSTR * ); + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + +/* this ALWAYS GENERATED file contains the definitions for the interfaces */ + + + /* File created by MIDL compiler version 6.00.0338 */ +/* Compiler settings for mtscript.idl: + Oicf, W1, Zp8, env=Win32 (32b run) + protocol : dce , ms_ext, c_ext, robust + error checks: allocation ref bounds_check enum stub_data + VC __declspec() decoration level: + __declspec(uuid()), __declspec(selectany), __declspec(novtable) + DECLSPEC_UUID(), MIDL_INTERFACE() +*/ +//@@MIDL_FILE_HEADING( ) + + +/* verify that the version is high enough to compile this file*/ +#ifndef __REQUIRED_RPCNDR_H_VERSION__ +#define __REQUIRED_RPCNDR_H_VERSION__ 475 +#endif + +#include "rpc.h" +#include "rpcndr.h" + +#ifndef __RPCNDR_H_VERSION__ +#error this stub requires an updated version of +#endif // __RPCNDR_H_VERSION__ + + +#ifndef __mtscript_h__ +#define __mtscript_h__ + +#if defined(_MSC_VER) && (_MSC_VER >= 1020) +#pragma once +#endif + +/* Forward Declarations */ + +#ifndef __IRemoteMTScriptProxy_FWD_DEFINED__ +#define __IRemoteMTScriptProxy_FWD_DEFINED__ +typedef interface IRemoteMTScriptProxy IRemoteMTScriptProxy; +#endif /* __IRemoteMTScriptProxy_FWD_DEFINED__ */ + + +#ifndef __IConnectedMachine_FWD_DEFINED__ +#define __IConnectedMachine_FWD_DEFINED__ +typedef interface IConnectedMachine IConnectedMachine; +#endif /* __IConnectedMachine_FWD_DEFINED__ */ + + +#ifndef __IGlobalMTScript_FWD_DEFINED__ +#define __IGlobalMTScript_FWD_DEFINED__ +typedef interface IGlobalMTScript IGlobalMTScript; +#endif /* __IGlobalMTScript_FWD_DEFINED__ */ + + +#ifndef __DLocalMTScriptEvents_FWD_DEFINED__ +#define __DLocalMTScriptEvents_FWD_DEFINED__ +typedef interface DLocalMTScriptEvents DLocalMTScriptEvents; +#endif /* __DLocalMTScriptEvents_FWD_DEFINED__ */ + + +#ifndef __DRemoteMTScriptEvents_FWD_DEFINED__ +#define __DRemoteMTScriptEvents_FWD_DEFINED__ +typedef interface DRemoteMTScriptEvents DRemoteMTScriptEvents; +#endif /* __DRemoteMTScriptEvents_FWD_DEFINED__ */ + + +#ifndef __LocalMTScript_FWD_DEFINED__ +#define __LocalMTScript_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class LocalMTScript LocalMTScript; +#else +typedef struct LocalMTScript LocalMTScript; +#endif /* __cplusplus */ + +#endif /* __LocalMTScript_FWD_DEFINED__ */ + + +#ifndef __RemoteMTScript_FWD_DEFINED__ +#define __RemoteMTScript_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class RemoteMTScript RemoteMTScript; +#else +typedef struct RemoteMTScript RemoteMTScript; +#endif /* __cplusplus */ + +#endif /* __RemoteMTScript_FWD_DEFINED__ */ + + +#ifndef __RemoteMTScriptProxy_FWD_DEFINED__ +#define __RemoteMTScriptProxy_FWD_DEFINED__ + +#ifdef __cplusplus +typedef class RemoteMTScriptProxy RemoteMTScriptProxy; +#else +typedef struct RemoteMTScriptProxy RemoteMTScriptProxy; +#endif /* __cplusplus */ + +#endif /* __RemoteMTScriptProxy_FWD_DEFINED__ */ + + +/* header files for imported files */ + +#ifdef __cplusplus +extern "C"{ +#endif + +void * __RPC_USER MIDL_user_allocate(size_t); +void __RPC_USER MIDL_user_free( void * ); + + +#ifndef __MTScriptEngine_LIBRARY_DEFINED__ +#define __MTScriptEngine_LIBRARY_DEFINED__ + +/* library MTScriptEngine */ +/* [version][uuid] */ + +#define IConnectedMachine_lVersionMajor ( 0 ) + +#define IConnectedMachine_lVersionMinor ( 0 ) + + +EXTERN_C const IID LIBID_MTScriptEngine; + +#ifndef __IRemoteMTScriptProxy_INTERFACE_DEFINED__ +#define __IRemoteMTScriptProxy_INTERFACE_DEFINED__ + +/* interface IRemoteMTScriptProxy */ +/* [object][dual][uuid] */ + + +EXTERN_C const IID IID_IRemoteMTScriptProxy; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("854c3181-c854-4a77-b189-606859e4391b") + IRemoteMTScriptProxy : public IDispatch + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Connect( + /* [defaultvalue][in] */ BSTR bstrMachine = L"") = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConnectToMTScript( + /* [defaultvalue][in] */ BSTR bstrMachine = L"", + /* [defaultvalue][in] */ BSTR bstrIdentity = L"Build", + /* [defaultvalue][in] */ BOOL fCreate = FALSE) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ConnectToObjectDaemon( + /* [defaultvalue][in] */ BSTR bstrMachine, + /* [retval][out] */ IObjectDaemon **ppIOD) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Disconnect( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE DownloadFile( + /* [in] */ BSTR bstrUrl, + /* [retval][out] */ BSTR *bstrFile) = 0; + + }; + +#else /* C style interface */ + + typedef struct IRemoteMTScriptProxyVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IRemoteMTScriptProxy * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IRemoteMTScriptProxy * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IRemoteMTScriptProxy * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IRemoteMTScriptProxy * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IRemoteMTScriptProxy * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IRemoteMTScriptProxy * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IRemoteMTScriptProxy * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Connect )( + IRemoteMTScriptProxy * This, + /* [defaultvalue][in] */ BSTR bstrMachine); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConnectToMTScript )( + IRemoteMTScriptProxy * This, + /* [defaultvalue][in] */ BSTR bstrMachine, + /* [defaultvalue][in] */ BSTR bstrIdentity, + /* [defaultvalue][in] */ BOOL fCreate); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ConnectToObjectDaemon )( + IRemoteMTScriptProxy * This, + /* [defaultvalue][in] */ BSTR bstrMachine, + /* [retval][out] */ IObjectDaemon **ppIOD); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Disconnect )( + IRemoteMTScriptProxy * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *DownloadFile )( + IRemoteMTScriptProxy * This, + /* [in] */ BSTR bstrUrl, + /* [retval][out] */ BSTR *bstrFile); + + END_INTERFACE + } IRemoteMTScriptProxyVtbl; + + interface IRemoteMTScriptProxy + { + CONST_VTBL struct IRemoteMTScriptProxyVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IRemoteMTScriptProxy_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IRemoteMTScriptProxy_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IRemoteMTScriptProxy_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IRemoteMTScriptProxy_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IRemoteMTScriptProxy_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IRemoteMTScriptProxy_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IRemoteMTScriptProxy_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IRemoteMTScriptProxy_Connect(This,bstrMachine) \ + (This)->lpVtbl -> Connect(This,bstrMachine) + +#define IRemoteMTScriptProxy_ConnectToMTScript(This,bstrMachine,bstrIdentity,fCreate) \ + (This)->lpVtbl -> ConnectToMTScript(This,bstrMachine,bstrIdentity,fCreate) + +#define IRemoteMTScriptProxy_ConnectToObjectDaemon(This,bstrMachine,ppIOD) \ + (This)->lpVtbl -> ConnectToObjectDaemon(This,bstrMachine,ppIOD) + +#define IRemoteMTScriptProxy_Disconnect(This) \ + (This)->lpVtbl -> Disconnect(This) + +#define IRemoteMTScriptProxy_DownloadFile(This,bstrUrl,bstrFile) \ + (This)->lpVtbl -> DownloadFile(This,bstrUrl,bstrFile) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IRemoteMTScriptProxy_Connect_Proxy( + IRemoteMTScriptProxy * This, + /* [defaultvalue][in] */ BSTR bstrMachine); + + +void __RPC_STUB IRemoteMTScriptProxy_Connect_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IRemoteMTScriptProxy_ConnectToMTScript_Proxy( + IRemoteMTScriptProxy * This, + /* [defaultvalue][in] */ BSTR bstrMachine, + /* [defaultvalue][in] */ BSTR bstrIdentity, + /* [defaultvalue][in] */ BOOL fCreate); + + +void __RPC_STUB IRemoteMTScriptProxy_ConnectToMTScript_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IRemoteMTScriptProxy_ConnectToObjectDaemon_Proxy( + IRemoteMTScriptProxy * This, + /* [defaultvalue][in] */ BSTR bstrMachine, + /* [retval][out] */ IObjectDaemon **ppIOD); + + +void __RPC_STUB IRemoteMTScriptProxy_ConnectToObjectDaemon_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IRemoteMTScriptProxy_Disconnect_Proxy( + IRemoteMTScriptProxy * This); + + +void __RPC_STUB IRemoteMTScriptProxy_Disconnect_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IRemoteMTScriptProxy_DownloadFile_Proxy( + IRemoteMTScriptProxy * This, + /* [in] */ BSTR bstrUrl, + /* [retval][out] */ BSTR *bstrFile); + + +void __RPC_STUB IRemoteMTScriptProxy_DownloadFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IRemoteMTScriptProxy_INTERFACE_DEFINED__ */ + + +#ifndef __IConnectedMachine_INTERFACE_DEFINED__ +#define __IConnectedMachine_INTERFACE_DEFINED__ + +/* interface IConnectedMachine */ +/* [object][version][dual][uuid] */ + + +EXTERN_C const IID IID_IConnectedMachine; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("854c316c-c854-4a77-b189-606859e4391b") + IConnectedMachine : public IDispatch + { + public: + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Exec( + /* [in] */ BSTR bstrCmd, + /* [in] */ BSTR bstrParams, + /* [retval][out] */ VARIANT *pvData) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PublicData( + /* [retval][out] */ VARIANT *pvData) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Name( + /* [retval][out] */ BSTR *name) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Platform( + /* [retval][out] */ BSTR *platform) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_OS( + /* [retval][out] */ BSTR *os) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_MajorVer( + /* [retval][out] */ long *majorver) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_MinorVer( + /* [retval][out] */ long *minorver) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_BuildNum( + /* [retval][out] */ long *buildnum) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PlatformIsNT( + /* [retval][out] */ VARIANT_BOOL *pfIsNT) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ServicePack( + /* [retval][out] */ BSTR *servicepack) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_HostMajorVer( + /* [retval][out] */ long *majorver) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_HostMinorVer( + /* [retval][out] */ long *minorver) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_StatusValue( + /* [in] */ long nIndex, + /* [retval][out] */ long *pnStatus) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CreateIScriptedProcess( + /* [in] */ long lProcessID, + /* [string][in] */ wchar_t *pszEnvID, + /* [retval][out] */ IScriptedProcess **pISP) = 0; + + }; + +#else /* C style interface */ + + typedef struct IConnectedMachineVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IConnectedMachine * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IConnectedMachine * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IConnectedMachine * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IConnectedMachine * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IConnectedMachine * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IConnectedMachine * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IConnectedMachine * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Exec )( + IConnectedMachine * This, + /* [in] */ BSTR bstrCmd, + /* [in] */ BSTR bstrParams, + /* [retval][out] */ VARIANT *pvData); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PublicData )( + IConnectedMachine * This, + /* [retval][out] */ VARIANT *pvData); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Name )( + IConnectedMachine * This, + /* [retval][out] */ BSTR *name); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Platform )( + IConnectedMachine * This, + /* [retval][out] */ BSTR *platform); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_OS )( + IConnectedMachine * This, + /* [retval][out] */ BSTR *os); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MajorVer )( + IConnectedMachine * This, + /* [retval][out] */ long *majorver); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_MinorVer )( + IConnectedMachine * This, + /* [retval][out] */ long *minorver); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_BuildNum )( + IConnectedMachine * This, + /* [retval][out] */ long *buildnum); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PlatformIsNT )( + IConnectedMachine * This, + /* [retval][out] */ VARIANT_BOOL *pfIsNT); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ServicePack )( + IConnectedMachine * This, + /* [retval][out] */ BSTR *servicepack); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_HostMajorVer )( + IConnectedMachine * This, + /* [retval][out] */ long *majorver); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_HostMinorVer )( + IConnectedMachine * This, + /* [retval][out] */ long *minorver); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_StatusValue )( + IConnectedMachine * This, + /* [in] */ long nIndex, + /* [retval][out] */ long *pnStatus); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CreateIScriptedProcess )( + IConnectedMachine * This, + /* [in] */ long lProcessID, + /* [string][in] */ wchar_t *pszEnvID, + /* [retval][out] */ IScriptedProcess **pISP); + + END_INTERFACE + } IConnectedMachineVtbl; + + interface IConnectedMachine + { + CONST_VTBL struct IConnectedMachineVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IConnectedMachine_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IConnectedMachine_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IConnectedMachine_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IConnectedMachine_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IConnectedMachine_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IConnectedMachine_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IConnectedMachine_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IConnectedMachine_Exec(This,bstrCmd,bstrParams,pvData) \ + (This)->lpVtbl -> Exec(This,bstrCmd,bstrParams,pvData) + +#define IConnectedMachine_get_PublicData(This,pvData) \ + (This)->lpVtbl -> get_PublicData(This,pvData) + +#define IConnectedMachine_get_Name(This,name) \ + (This)->lpVtbl -> get_Name(This,name) + +#define IConnectedMachine_get_Platform(This,platform) \ + (This)->lpVtbl -> get_Platform(This,platform) + +#define IConnectedMachine_get_OS(This,os) \ + (This)->lpVtbl -> get_OS(This,os) + +#define IConnectedMachine_get_MajorVer(This,majorver) \ + (This)->lpVtbl -> get_MajorVer(This,majorver) + +#define IConnectedMachine_get_MinorVer(This,minorver) \ + (This)->lpVtbl -> get_MinorVer(This,minorver) + +#define IConnectedMachine_get_BuildNum(This,buildnum) \ + (This)->lpVtbl -> get_BuildNum(This,buildnum) + +#define IConnectedMachine_get_PlatformIsNT(This,pfIsNT) \ + (This)->lpVtbl -> get_PlatformIsNT(This,pfIsNT) + +#define IConnectedMachine_get_ServicePack(This,servicepack) \ + (This)->lpVtbl -> get_ServicePack(This,servicepack) + +#define IConnectedMachine_get_HostMajorVer(This,majorver) \ + (This)->lpVtbl -> get_HostMajorVer(This,majorver) + +#define IConnectedMachine_get_HostMinorVer(This,minorver) \ + (This)->lpVtbl -> get_HostMinorVer(This,minorver) + +#define IConnectedMachine_get_StatusValue(This,nIndex,pnStatus) \ + (This)->lpVtbl -> get_StatusValue(This,nIndex,pnStatus) + +#define IConnectedMachine_CreateIScriptedProcess(This,lProcessID,pszEnvID,pISP) \ + (This)->lpVtbl -> CreateIScriptedProcess(This,lProcessID,pszEnvID,pISP) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IConnectedMachine_Exec_Proxy( + IConnectedMachine * This, + /* [in] */ BSTR bstrCmd, + /* [in] */ BSTR bstrParams, + /* [retval][out] */ VARIANT *pvData); + + +void __RPC_STUB IConnectedMachine_Exec_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IConnectedMachine_get_PublicData_Proxy( + IConnectedMachine * This, + /* [retval][out] */ VARIANT *pvData); + + +void __RPC_STUB IConnectedMachine_get_PublicData_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IConnectedMachine_get_Name_Proxy( + IConnectedMachine * This, + /* [retval][out] */ BSTR *name); + + +void __RPC_STUB IConnectedMachine_get_Name_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IConnectedMachine_get_Platform_Proxy( + IConnectedMachine * This, + /* [retval][out] */ BSTR *platform); + + +void __RPC_STUB IConnectedMachine_get_Platform_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IConnectedMachine_get_OS_Proxy( + IConnectedMachine * This, + /* [retval][out] */ BSTR *os); + + +void __RPC_STUB IConnectedMachine_get_OS_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IConnectedMachine_get_MajorVer_Proxy( + IConnectedMachine * This, + /* [retval][out] */ long *majorver); + + +void __RPC_STUB IConnectedMachine_get_MajorVer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IConnectedMachine_get_MinorVer_Proxy( + IConnectedMachine * This, + /* [retval][out] */ long *minorver); + + +void __RPC_STUB IConnectedMachine_get_MinorVer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IConnectedMachine_get_BuildNum_Proxy( + IConnectedMachine * This, + /* [retval][out] */ long *buildnum); + + +void __RPC_STUB IConnectedMachine_get_BuildNum_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IConnectedMachine_get_PlatformIsNT_Proxy( + IConnectedMachine * This, + /* [retval][out] */ VARIANT_BOOL *pfIsNT); + + +void __RPC_STUB IConnectedMachine_get_PlatformIsNT_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IConnectedMachine_get_ServicePack_Proxy( + IConnectedMachine * This, + /* [retval][out] */ BSTR *servicepack); + + +void __RPC_STUB IConnectedMachine_get_ServicePack_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IConnectedMachine_get_HostMajorVer_Proxy( + IConnectedMachine * This, + /* [retval][out] */ long *majorver); + + +void __RPC_STUB IConnectedMachine_get_HostMajorVer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IConnectedMachine_get_HostMinorVer_Proxy( + IConnectedMachine * This, + /* [retval][out] */ long *minorver); + + +void __RPC_STUB IConnectedMachine_get_HostMinorVer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IConnectedMachine_get_StatusValue_Proxy( + IConnectedMachine * This, + /* [in] */ long nIndex, + /* [retval][out] */ long *pnStatus); + + +void __RPC_STUB IConnectedMachine_get_StatusValue_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IConnectedMachine_CreateIScriptedProcess_Proxy( + IConnectedMachine * This, + /* [in] */ long lProcessID, + /* [string][in] */ wchar_t *pszEnvID, + /* [retval][out] */ IScriptedProcess **pISP); + + +void __RPC_STUB IConnectedMachine_CreateIScriptedProcess_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IConnectedMachine_INTERFACE_DEFINED__ */ + + +#ifndef __IGlobalMTScript_INTERFACE_DEFINED__ +#define __IGlobalMTScript_INTERFACE_DEFINED__ + +/* interface IGlobalMTScript */ +/* [object][local][dual][uuid] */ + + +EXTERN_C const IID IID_IGlobalMTScript; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("854c316b-c854-4a77-b189-606859e4391b") + IGlobalMTScript : public IDispatch + { + public: + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_HostMajorVer( + /* [retval][out] */ long *majorver) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_HostMinorVer( + /* [retval][out] */ long *minorver) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PublicData( + /* [retval][out] */ VARIANT *pvData) = 0; + + virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_PublicData( + /* [in] */ VARIANT vData) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_PrivateData( + /* [retval][out] */ VARIANT *pvData) = 0; + + virtual /* [propput] */ HRESULT STDMETHODCALLTYPE put_PrivateData( + /* [in] */ VARIANT vData) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ExitProcess( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Restart( void) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_LocalMachine( + /* [retval][out] */ BSTR *pbstrName) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_Identity( + /* [retval][out] */ BSTR *pbstrIdentity) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Include( + BSTR bstrPath) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CallScript( + /* [in] */ BSTR Path, + /* [in][optional] */ VARIANT *Param) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SpawnScript( + /* [in] */ BSTR Path, + /* [in][optional] */ VARIANT *Param) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ScriptParam( + /* [retval][out] */ VARIANT *Param) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_ScriptPath( + /* [retval][out] */ BSTR *pbstrPath) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CallExternal( + /* [in] */ BSTR bstrDLLName, + /* [in] */ BSTR bstrFunctionName, + /* [optional][in] */ VARIANT *pParam, + /* [retval][out] */ long *pdwRetVal) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ResetSync( + /* [in] */ const BSTR bstrName) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE WaitForSync( + /* [in] */ BSTR bstrName, + /* [in] */ long nTimeout, + /* [retval][out] */ VARIANT_BOOL *pfSignaled) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE WaitForMultipleSyncs( + /* [in] */ const BSTR bstrNameList, + /* [in] */ VARIANT_BOOL fWaitForAll, + /* [in] */ long nTimeout, + /* [retval][out] */ long *plSignal) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SignalThreadSync( + /* [in] */ BSTR bstrName) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE TakeThreadLock( + /* [in] */ BSTR bstrName) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ReleaseThreadLock( + /* [in] */ BSTR bstrName) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE DoEvents( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE MessageBoxTimeout( + /* [in] */ BSTR bstrMessage, + /* [in] */ long cButtons, + /* [in] */ BSTR bstrButtonText, + /* [in] */ long lTimeout, + /* [in] */ long lEventInterval, + /* [in] */ VARIANT_BOOL fCanCancel, + /* [in] */ VARIANT_BOOL fConfirm, + /* [retval][out] */ long *plSelected) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RunLocalCommand( + /* [in] */ BSTR bstrCommand, + /* [in] */ BSTR bstrDir, + /* [defaultvalue][in] */ BSTR bstrTitle, + /* [defaultvalue][in] */ VARIANT_BOOL fMinimize, + /* [defaultvalue][in] */ VARIANT_BOOL fGetOutput, + /* [defaultvalue][in] */ VARIANT_BOOL fWait, + /* [defaultvalue][in] */ VARIANT_BOOL fNoCrashPopup, + /* [defaultvalue][in] */ VARIANT_BOOL fNoEnviron, + /* [retval][out] */ long *plProcessID) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetLastRunLocalError( + /* [retval][out] */ long *plErrorCode) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetProcessOutput( + /* [in] */ long lProcessID, + /* [retval][out] */ BSTR *pbstrData) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE GetProcessExitCode( + /* [in] */ long lProcessID, + /* [retval][out] */ long *plExitCode) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE TerminateProcess( + /* [in] */ long lProcessID) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SendToProcess( + /* [in] */ long lProcessID, + /* [in] */ BSTR bstrType, + /* [in] */ BSTR bstrData, + /* [retval][out] */ long *plReturn) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SendMail( + /* [in] */ BSTR bstrTo, + /* [in] */ BSTR bstrCC, + /* [in] */ BSTR bstrBCC, + /* [in] */ BSTR bstrSubject, + /* [in] */ BSTR bstrMessage, + /* [defaultvalue][in] */ BSTR bstrAttachmentPath, + /* [defaultvalue][in] */ BSTR bstrUsername, + /* [defaultvalue][in] */ BSTR bstrPassword, + /* [retval][out] */ long *plErrorCode) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE SendSMTPMail( + /* [in] */ BSTR bstrFrom, + /* [in] */ BSTR bstrTo, + /* [in] */ BSTR bstrCC, + /* [in] */ BSTR bstrSubject, + /* [in] */ BSTR bstrMessage, + /* [in] */ BSTR bstrSMTPHost, + /* [retval][out] */ long *plErrorCode) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE ASSERT( + /* [in] */ VARIANT_BOOL Assertion, + /* [in] */ BSTR Message) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE OUTPUTDEBUGSTRING( + /* [in] */ BSTR Message) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UnevalString( + /* [in] */ BSTR bstrIn, + /* [retval][out] */ BSTR *bstrOut) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE CopyOrAppendFile( + /* [in] */ BSTR bstrSrc, + /* [in] */ BSTR bstrDst, + /* [in] */ long nSrcOffset, + /* [in] */ long nSrcLength, + /* [in] */ VARIANT_BOOL fAppend, + /* [retval][out] */ long *nSrcFilePosition) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Sleep( + /* [in] */ int nTimeout) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE Reboot( void) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE NotifyScript( + BSTR bstrEvent, + VARIANT vData) = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE RegisterEventSource( + /* [in] */ IDispatch *pDisp, + /* [defaultvalue][in] */ BSTR bstrProgID = L"") = 0; + + virtual /* [helpstring] */ HRESULT STDMETHODCALLTYPE UnregisterEventSource( + /* [in] */ IDispatch *pDisp) = 0; + + virtual /* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE get_StatusValue( + /* [in] */ long nIndex, + /* [retval][out] */ long *pnStatus) = 0; + + virtual /* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE put_StatusValue( + /* [in] */ long nIndex, + /* [in] */ long nStatus) = 0; + + }; + +#else /* C style interface */ + + typedef struct IGlobalMTScriptVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + IGlobalMTScript * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + IGlobalMTScript * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + IGlobalMTScript * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + IGlobalMTScript * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + IGlobalMTScript * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + IGlobalMTScript * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + IGlobalMTScript * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_HostMajorVer )( + IGlobalMTScript * This, + /* [retval][out] */ long *majorver); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_HostMinorVer )( + IGlobalMTScript * This, + /* [retval][out] */ long *minorver); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PublicData )( + IGlobalMTScript * This, + /* [retval][out] */ VARIANT *pvData); + + /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_PublicData )( + IGlobalMTScript * This, + /* [in] */ VARIANT vData); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_PrivateData )( + IGlobalMTScript * This, + /* [retval][out] */ VARIANT *pvData); + + /* [propput] */ HRESULT ( STDMETHODCALLTYPE *put_PrivateData )( + IGlobalMTScript * This, + /* [in] */ VARIANT vData); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ExitProcess )( + IGlobalMTScript * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Restart )( + IGlobalMTScript * This); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_LocalMachine )( + IGlobalMTScript * This, + /* [retval][out] */ BSTR *pbstrName); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_Identity )( + IGlobalMTScript * This, + /* [retval][out] */ BSTR *pbstrIdentity); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Include )( + IGlobalMTScript * This, + BSTR bstrPath); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CallScript )( + IGlobalMTScript * This, + /* [in] */ BSTR Path, + /* [in][optional] */ VARIANT *Param); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SpawnScript )( + IGlobalMTScript * This, + /* [in] */ BSTR Path, + /* [in][optional] */ VARIANT *Param); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ScriptParam )( + IGlobalMTScript * This, + /* [retval][out] */ VARIANT *Param); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_ScriptPath )( + IGlobalMTScript * This, + /* [retval][out] */ BSTR *pbstrPath); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CallExternal )( + IGlobalMTScript * This, + /* [in] */ BSTR bstrDLLName, + /* [in] */ BSTR bstrFunctionName, + /* [optional][in] */ VARIANT *pParam, + /* [retval][out] */ long *pdwRetVal); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ResetSync )( + IGlobalMTScript * This, + /* [in] */ const BSTR bstrName); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *WaitForSync )( + IGlobalMTScript * This, + /* [in] */ BSTR bstrName, + /* [in] */ long nTimeout, + /* [retval][out] */ VARIANT_BOOL *pfSignaled); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *WaitForMultipleSyncs )( + IGlobalMTScript * This, + /* [in] */ const BSTR bstrNameList, + /* [in] */ VARIANT_BOOL fWaitForAll, + /* [in] */ long nTimeout, + /* [retval][out] */ long *plSignal); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SignalThreadSync )( + IGlobalMTScript * This, + /* [in] */ BSTR bstrName); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *TakeThreadLock )( + IGlobalMTScript * This, + /* [in] */ BSTR bstrName); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ReleaseThreadLock )( + IGlobalMTScript * This, + /* [in] */ BSTR bstrName); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *DoEvents )( + IGlobalMTScript * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *MessageBoxTimeout )( + IGlobalMTScript * This, + /* [in] */ BSTR bstrMessage, + /* [in] */ long cButtons, + /* [in] */ BSTR bstrButtonText, + /* [in] */ long lTimeout, + /* [in] */ long lEventInterval, + /* [in] */ VARIANT_BOOL fCanCancel, + /* [in] */ VARIANT_BOOL fConfirm, + /* [retval][out] */ long *plSelected); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *RunLocalCommand )( + IGlobalMTScript * This, + /* [in] */ BSTR bstrCommand, + /* [in] */ BSTR bstrDir, + /* [defaultvalue][in] */ BSTR bstrTitle, + /* [defaultvalue][in] */ VARIANT_BOOL fMinimize, + /* [defaultvalue][in] */ VARIANT_BOOL fGetOutput, + /* [defaultvalue][in] */ VARIANT_BOOL fWait, + /* [defaultvalue][in] */ VARIANT_BOOL fNoCrashPopup, + /* [defaultvalue][in] */ VARIANT_BOOL fNoEnviron, + /* [retval][out] */ long *plProcessID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetLastRunLocalError )( + IGlobalMTScript * This, + /* [retval][out] */ long *plErrorCode); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetProcessOutput )( + IGlobalMTScript * This, + /* [in] */ long lProcessID, + /* [retval][out] */ BSTR *pbstrData); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *GetProcessExitCode )( + IGlobalMTScript * This, + /* [in] */ long lProcessID, + /* [retval][out] */ long *plExitCode); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *TerminateProcess )( + IGlobalMTScript * This, + /* [in] */ long lProcessID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SendToProcess )( + IGlobalMTScript * This, + /* [in] */ long lProcessID, + /* [in] */ BSTR bstrType, + /* [in] */ BSTR bstrData, + /* [retval][out] */ long *plReturn); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SendMail )( + IGlobalMTScript * This, + /* [in] */ BSTR bstrTo, + /* [in] */ BSTR bstrCC, + /* [in] */ BSTR bstrBCC, + /* [in] */ BSTR bstrSubject, + /* [in] */ BSTR bstrMessage, + /* [defaultvalue][in] */ BSTR bstrAttachmentPath, + /* [defaultvalue][in] */ BSTR bstrUsername, + /* [defaultvalue][in] */ BSTR bstrPassword, + /* [retval][out] */ long *plErrorCode); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *SendSMTPMail )( + IGlobalMTScript * This, + /* [in] */ BSTR bstrFrom, + /* [in] */ BSTR bstrTo, + /* [in] */ BSTR bstrCC, + /* [in] */ BSTR bstrSubject, + /* [in] */ BSTR bstrMessage, + /* [in] */ BSTR bstrSMTPHost, + /* [retval][out] */ long *plErrorCode); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *ASSERT )( + IGlobalMTScript * This, + /* [in] */ VARIANT_BOOL Assertion, + /* [in] */ BSTR Message); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *OUTPUTDEBUGSTRING )( + IGlobalMTScript * This, + /* [in] */ BSTR Message); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UnevalString )( + IGlobalMTScript * This, + /* [in] */ BSTR bstrIn, + /* [retval][out] */ BSTR *bstrOut); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *CopyOrAppendFile )( + IGlobalMTScript * This, + /* [in] */ BSTR bstrSrc, + /* [in] */ BSTR bstrDst, + /* [in] */ long nSrcOffset, + /* [in] */ long nSrcLength, + /* [in] */ VARIANT_BOOL fAppend, + /* [retval][out] */ long *nSrcFilePosition); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Sleep )( + IGlobalMTScript * This, + /* [in] */ int nTimeout); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *Reboot )( + IGlobalMTScript * This); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *NotifyScript )( + IGlobalMTScript * This, + BSTR bstrEvent, + VARIANT vData); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *RegisterEventSource )( + IGlobalMTScript * This, + /* [in] */ IDispatch *pDisp, + /* [defaultvalue][in] */ BSTR bstrProgID); + + /* [helpstring] */ HRESULT ( STDMETHODCALLTYPE *UnregisterEventSource )( + IGlobalMTScript * This, + /* [in] */ IDispatch *pDisp); + + /* [helpstring][propget] */ HRESULT ( STDMETHODCALLTYPE *get_StatusValue )( + IGlobalMTScript * This, + /* [in] */ long nIndex, + /* [retval][out] */ long *pnStatus); + + /* [helpstring][propput] */ HRESULT ( STDMETHODCALLTYPE *put_StatusValue )( + IGlobalMTScript * This, + /* [in] */ long nIndex, + /* [in] */ long nStatus); + + END_INTERFACE + } IGlobalMTScriptVtbl; + + interface IGlobalMTScript + { + CONST_VTBL struct IGlobalMTScriptVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define IGlobalMTScript_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define IGlobalMTScript_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define IGlobalMTScript_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define IGlobalMTScript_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define IGlobalMTScript_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define IGlobalMTScript_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define IGlobalMTScript_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + + +#define IGlobalMTScript_get_HostMajorVer(This,majorver) \ + (This)->lpVtbl -> get_HostMajorVer(This,majorver) + +#define IGlobalMTScript_get_HostMinorVer(This,minorver) \ + (This)->lpVtbl -> get_HostMinorVer(This,minorver) + +#define IGlobalMTScript_get_PublicData(This,pvData) \ + (This)->lpVtbl -> get_PublicData(This,pvData) + +#define IGlobalMTScript_put_PublicData(This,vData) \ + (This)->lpVtbl -> put_PublicData(This,vData) + +#define IGlobalMTScript_get_PrivateData(This,pvData) \ + (This)->lpVtbl -> get_PrivateData(This,pvData) + +#define IGlobalMTScript_put_PrivateData(This,vData) \ + (This)->lpVtbl -> put_PrivateData(This,vData) + +#define IGlobalMTScript_ExitProcess(This) \ + (This)->lpVtbl -> ExitProcess(This) + +#define IGlobalMTScript_Restart(This) \ + (This)->lpVtbl -> Restart(This) + +#define IGlobalMTScript_get_LocalMachine(This,pbstrName) \ + (This)->lpVtbl -> get_LocalMachine(This,pbstrName) + +#define IGlobalMTScript_get_Identity(This,pbstrIdentity) \ + (This)->lpVtbl -> get_Identity(This,pbstrIdentity) + +#define IGlobalMTScript_Include(This,bstrPath) \ + (This)->lpVtbl -> Include(This,bstrPath) + +#define IGlobalMTScript_CallScript(This,Path,Param) \ + (This)->lpVtbl -> CallScript(This,Path,Param) + +#define IGlobalMTScript_SpawnScript(This,Path,Param) \ + (This)->lpVtbl -> SpawnScript(This,Path,Param) + +#define IGlobalMTScript_get_ScriptParam(This,Param) \ + (This)->lpVtbl -> get_ScriptParam(This,Param) + +#define IGlobalMTScript_get_ScriptPath(This,pbstrPath) \ + (This)->lpVtbl -> get_ScriptPath(This,pbstrPath) + +#define IGlobalMTScript_CallExternal(This,bstrDLLName,bstrFunctionName,pParam,pdwRetVal) \ + (This)->lpVtbl -> CallExternal(This,bstrDLLName,bstrFunctionName,pParam,pdwRetVal) + +#define IGlobalMTScript_ResetSync(This,bstrName) \ + (This)->lpVtbl -> ResetSync(This,bstrName) + +#define IGlobalMTScript_WaitForSync(This,bstrName,nTimeout,pfSignaled) \ + (This)->lpVtbl -> WaitForSync(This,bstrName,nTimeout,pfSignaled) + +#define IGlobalMTScript_WaitForMultipleSyncs(This,bstrNameList,fWaitForAll,nTimeout,plSignal) \ + (This)->lpVtbl -> WaitForMultipleSyncs(This,bstrNameList,fWaitForAll,nTimeout,plSignal) + +#define IGlobalMTScript_SignalThreadSync(This,bstrName) \ + (This)->lpVtbl -> SignalThreadSync(This,bstrName) + +#define IGlobalMTScript_TakeThreadLock(This,bstrName) \ + (This)->lpVtbl -> TakeThreadLock(This,bstrName) + +#define IGlobalMTScript_ReleaseThreadLock(This,bstrName) \ + (This)->lpVtbl -> ReleaseThreadLock(This,bstrName) + +#define IGlobalMTScript_DoEvents(This) \ + (This)->lpVtbl -> DoEvents(This) + +#define IGlobalMTScript_MessageBoxTimeout(This,bstrMessage,cButtons,bstrButtonText,lTimeout,lEventInterval,fCanCancel,fConfirm,plSelected) \ + (This)->lpVtbl -> MessageBoxTimeout(This,bstrMessage,cButtons,bstrButtonText,lTimeout,lEventInterval,fCanCancel,fConfirm,plSelected) + +#define IGlobalMTScript_RunLocalCommand(This,bstrCommand,bstrDir,bstrTitle,fMinimize,fGetOutput,fWait,fNoCrashPopup,fNoEnviron,plProcessID) \ + (This)->lpVtbl -> RunLocalCommand(This,bstrCommand,bstrDir,bstrTitle,fMinimize,fGetOutput,fWait,fNoCrashPopup,fNoEnviron,plProcessID) + +#define IGlobalMTScript_GetLastRunLocalError(This,plErrorCode) \ + (This)->lpVtbl -> GetLastRunLocalError(This,plErrorCode) + +#define IGlobalMTScript_GetProcessOutput(This,lProcessID,pbstrData) \ + (This)->lpVtbl -> GetProcessOutput(This,lProcessID,pbstrData) + +#define IGlobalMTScript_GetProcessExitCode(This,lProcessID,plExitCode) \ + (This)->lpVtbl -> GetProcessExitCode(This,lProcessID,plExitCode) + +#define IGlobalMTScript_TerminateProcess(This,lProcessID) \ + (This)->lpVtbl -> TerminateProcess(This,lProcessID) + +#define IGlobalMTScript_SendToProcess(This,lProcessID,bstrType,bstrData,plReturn) \ + (This)->lpVtbl -> SendToProcess(This,lProcessID,bstrType,bstrData,plReturn) + +#define IGlobalMTScript_SendMail(This,bstrTo,bstrCC,bstrBCC,bstrSubject,bstrMessage,bstrAttachmentPath,bstrUsername,bstrPassword,plErrorCode) \ + (This)->lpVtbl -> SendMail(This,bstrTo,bstrCC,bstrBCC,bstrSubject,bstrMessage,bstrAttachmentPath,bstrUsername,bstrPassword,plErrorCode) + +#define IGlobalMTScript_SendSMTPMail(This,bstrFrom,bstrTo,bstrCC,bstrSubject,bstrMessage,bstrSMTPHost,plErrorCode) \ + (This)->lpVtbl -> SendSMTPMail(This,bstrFrom,bstrTo,bstrCC,bstrSubject,bstrMessage,bstrSMTPHost,plErrorCode) + +#define IGlobalMTScript_ASSERT(This,Assertion,Message) \ + (This)->lpVtbl -> ASSERT(This,Assertion,Message) + +#define IGlobalMTScript_OUTPUTDEBUGSTRING(This,Message) \ + (This)->lpVtbl -> OUTPUTDEBUGSTRING(This,Message) + +#define IGlobalMTScript_UnevalString(This,bstrIn,bstrOut) \ + (This)->lpVtbl -> UnevalString(This,bstrIn,bstrOut) + +#define IGlobalMTScript_CopyOrAppendFile(This,bstrSrc,bstrDst,nSrcOffset,nSrcLength,fAppend,nSrcFilePosition) \ + (This)->lpVtbl -> CopyOrAppendFile(This,bstrSrc,bstrDst,nSrcOffset,nSrcLength,fAppend,nSrcFilePosition) + +#define IGlobalMTScript_Sleep(This,nTimeout) \ + (This)->lpVtbl -> Sleep(This,nTimeout) + +#define IGlobalMTScript_Reboot(This) \ + (This)->lpVtbl -> Reboot(This) + +#define IGlobalMTScript_NotifyScript(This,bstrEvent,vData) \ + (This)->lpVtbl -> NotifyScript(This,bstrEvent,vData) + +#define IGlobalMTScript_RegisterEventSource(This,pDisp,bstrProgID) \ + (This)->lpVtbl -> RegisterEventSource(This,pDisp,bstrProgID) + +#define IGlobalMTScript_UnregisterEventSource(This,pDisp) \ + (This)->lpVtbl -> UnregisterEventSource(This,pDisp) + +#define IGlobalMTScript_get_StatusValue(This,nIndex,pnStatus) \ + (This)->lpVtbl -> get_StatusValue(This,nIndex,pnStatus) + +#define IGlobalMTScript_put_StatusValue(This,nIndex,nStatus) \ + (This)->lpVtbl -> put_StatusValue(This,nIndex,nStatus) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_get_HostMajorVer_Proxy( + IGlobalMTScript * This, + /* [retval][out] */ long *majorver); + + +void __RPC_STUB IGlobalMTScript_get_HostMajorVer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_get_HostMinorVer_Proxy( + IGlobalMTScript * This, + /* [retval][out] */ long *minorver); + + +void __RPC_STUB IGlobalMTScript_get_HostMinorVer_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_get_PublicData_Proxy( + IGlobalMTScript * This, + /* [retval][out] */ VARIANT *pvData); + + +void __RPC_STUB IGlobalMTScript_get_PublicData_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [propput] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_put_PublicData_Proxy( + IGlobalMTScript * This, + /* [in] */ VARIANT vData); + + +void __RPC_STUB IGlobalMTScript_put_PublicData_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_get_PrivateData_Proxy( + IGlobalMTScript * This, + /* [retval][out] */ VARIANT *pvData); + + +void __RPC_STUB IGlobalMTScript_get_PrivateData_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [propput] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_put_PrivateData_Proxy( + IGlobalMTScript * This, + /* [in] */ VARIANT vData); + + +void __RPC_STUB IGlobalMTScript_put_PrivateData_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_ExitProcess_Proxy( + IGlobalMTScript * This); + + +void __RPC_STUB IGlobalMTScript_ExitProcess_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_Restart_Proxy( + IGlobalMTScript * This); + + +void __RPC_STUB IGlobalMTScript_Restart_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_get_LocalMachine_Proxy( + IGlobalMTScript * This, + /* [retval][out] */ BSTR *pbstrName); + + +void __RPC_STUB IGlobalMTScript_get_LocalMachine_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_get_Identity_Proxy( + IGlobalMTScript * This, + /* [retval][out] */ BSTR *pbstrIdentity); + + +void __RPC_STUB IGlobalMTScript_get_Identity_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_Include_Proxy( + IGlobalMTScript * This, + BSTR bstrPath); + + +void __RPC_STUB IGlobalMTScript_Include_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_CallScript_Proxy( + IGlobalMTScript * This, + /* [in] */ BSTR Path, + /* [in][optional] */ VARIANT *Param); + + +void __RPC_STUB IGlobalMTScript_CallScript_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_SpawnScript_Proxy( + IGlobalMTScript * This, + /* [in] */ BSTR Path, + /* [in][optional] */ VARIANT *Param); + + +void __RPC_STUB IGlobalMTScript_SpawnScript_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_get_ScriptParam_Proxy( + IGlobalMTScript * This, + /* [retval][out] */ VARIANT *Param); + + +void __RPC_STUB IGlobalMTScript_get_ScriptParam_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_get_ScriptPath_Proxy( + IGlobalMTScript * This, + /* [retval][out] */ BSTR *pbstrPath); + + +void __RPC_STUB IGlobalMTScript_get_ScriptPath_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_CallExternal_Proxy( + IGlobalMTScript * This, + /* [in] */ BSTR bstrDLLName, + /* [in] */ BSTR bstrFunctionName, + /* [optional][in] */ VARIANT *pParam, + /* [retval][out] */ long *pdwRetVal); + + +void __RPC_STUB IGlobalMTScript_CallExternal_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_ResetSync_Proxy( + IGlobalMTScript * This, + /* [in] */ const BSTR bstrName); + + +void __RPC_STUB IGlobalMTScript_ResetSync_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_WaitForSync_Proxy( + IGlobalMTScript * This, + /* [in] */ BSTR bstrName, + /* [in] */ long nTimeout, + /* [retval][out] */ VARIANT_BOOL *pfSignaled); + + +void __RPC_STUB IGlobalMTScript_WaitForSync_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_WaitForMultipleSyncs_Proxy( + IGlobalMTScript * This, + /* [in] */ const BSTR bstrNameList, + /* [in] */ VARIANT_BOOL fWaitForAll, + /* [in] */ long nTimeout, + /* [retval][out] */ long *plSignal); + + +void __RPC_STUB IGlobalMTScript_WaitForMultipleSyncs_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_SignalThreadSync_Proxy( + IGlobalMTScript * This, + /* [in] */ BSTR bstrName); + + +void __RPC_STUB IGlobalMTScript_SignalThreadSync_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_TakeThreadLock_Proxy( + IGlobalMTScript * This, + /* [in] */ BSTR bstrName); + + +void __RPC_STUB IGlobalMTScript_TakeThreadLock_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_ReleaseThreadLock_Proxy( + IGlobalMTScript * This, + /* [in] */ BSTR bstrName); + + +void __RPC_STUB IGlobalMTScript_ReleaseThreadLock_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_DoEvents_Proxy( + IGlobalMTScript * This); + + +void __RPC_STUB IGlobalMTScript_DoEvents_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_MessageBoxTimeout_Proxy( + IGlobalMTScript * This, + /* [in] */ BSTR bstrMessage, + /* [in] */ long cButtons, + /* [in] */ BSTR bstrButtonText, + /* [in] */ long lTimeout, + /* [in] */ long lEventInterval, + /* [in] */ VARIANT_BOOL fCanCancel, + /* [in] */ VARIANT_BOOL fConfirm, + /* [retval][out] */ long *plSelected); + + +void __RPC_STUB IGlobalMTScript_MessageBoxTimeout_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_RunLocalCommand_Proxy( + IGlobalMTScript * This, + /* [in] */ BSTR bstrCommand, + /* [in] */ BSTR bstrDir, + /* [defaultvalue][in] */ BSTR bstrTitle, + /* [defaultvalue][in] */ VARIANT_BOOL fMinimize, + /* [defaultvalue][in] */ VARIANT_BOOL fGetOutput, + /* [defaultvalue][in] */ VARIANT_BOOL fWait, + /* [defaultvalue][in] */ VARIANT_BOOL fNoCrashPopup, + /* [defaultvalue][in] */ VARIANT_BOOL fNoEnviron, + /* [retval][out] */ long *plProcessID); + + +void __RPC_STUB IGlobalMTScript_RunLocalCommand_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_GetLastRunLocalError_Proxy( + IGlobalMTScript * This, + /* [retval][out] */ long *plErrorCode); + + +void __RPC_STUB IGlobalMTScript_GetLastRunLocalError_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_GetProcessOutput_Proxy( + IGlobalMTScript * This, + /* [in] */ long lProcessID, + /* [retval][out] */ BSTR *pbstrData); + + +void __RPC_STUB IGlobalMTScript_GetProcessOutput_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_GetProcessExitCode_Proxy( + IGlobalMTScript * This, + /* [in] */ long lProcessID, + /* [retval][out] */ long *plExitCode); + + +void __RPC_STUB IGlobalMTScript_GetProcessExitCode_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_TerminateProcess_Proxy( + IGlobalMTScript * This, + /* [in] */ long lProcessID); + + +void __RPC_STUB IGlobalMTScript_TerminateProcess_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_SendToProcess_Proxy( + IGlobalMTScript * This, + /* [in] */ long lProcessID, + /* [in] */ BSTR bstrType, + /* [in] */ BSTR bstrData, + /* [retval][out] */ long *plReturn); + + +void __RPC_STUB IGlobalMTScript_SendToProcess_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_SendMail_Proxy( + IGlobalMTScript * This, + /* [in] */ BSTR bstrTo, + /* [in] */ BSTR bstrCC, + /* [in] */ BSTR bstrBCC, + /* [in] */ BSTR bstrSubject, + /* [in] */ BSTR bstrMessage, + /* [defaultvalue][in] */ BSTR bstrAttachmentPath, + /* [defaultvalue][in] */ BSTR bstrUsername, + /* [defaultvalue][in] */ BSTR bstrPassword, + /* [retval][out] */ long *plErrorCode); + + +void __RPC_STUB IGlobalMTScript_SendMail_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_SendSMTPMail_Proxy( + IGlobalMTScript * This, + /* [in] */ BSTR bstrFrom, + /* [in] */ BSTR bstrTo, + /* [in] */ BSTR bstrCC, + /* [in] */ BSTR bstrSubject, + /* [in] */ BSTR bstrMessage, + /* [in] */ BSTR bstrSMTPHost, + /* [retval][out] */ long *plErrorCode); + + +void __RPC_STUB IGlobalMTScript_SendSMTPMail_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_ASSERT_Proxy( + IGlobalMTScript * This, + /* [in] */ VARIANT_BOOL Assertion, + /* [in] */ BSTR Message); + + +void __RPC_STUB IGlobalMTScript_ASSERT_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_OUTPUTDEBUGSTRING_Proxy( + IGlobalMTScript * This, + /* [in] */ BSTR Message); + + +void __RPC_STUB IGlobalMTScript_OUTPUTDEBUGSTRING_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_UnevalString_Proxy( + IGlobalMTScript * This, + /* [in] */ BSTR bstrIn, + /* [retval][out] */ BSTR *bstrOut); + + +void __RPC_STUB IGlobalMTScript_UnevalString_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_CopyOrAppendFile_Proxy( + IGlobalMTScript * This, + /* [in] */ BSTR bstrSrc, + /* [in] */ BSTR bstrDst, + /* [in] */ long nSrcOffset, + /* [in] */ long nSrcLength, + /* [in] */ VARIANT_BOOL fAppend, + /* [retval][out] */ long *nSrcFilePosition); + + +void __RPC_STUB IGlobalMTScript_CopyOrAppendFile_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_Sleep_Proxy( + IGlobalMTScript * This, + /* [in] */ int nTimeout); + + +void __RPC_STUB IGlobalMTScript_Sleep_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_Reboot_Proxy( + IGlobalMTScript * This); + + +void __RPC_STUB IGlobalMTScript_Reboot_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_NotifyScript_Proxy( + IGlobalMTScript * This, + BSTR bstrEvent, + VARIANT vData); + + +void __RPC_STUB IGlobalMTScript_NotifyScript_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_RegisterEventSource_Proxy( + IGlobalMTScript * This, + /* [in] */ IDispatch *pDisp, + /* [defaultvalue][in] */ BSTR bstrProgID); + + +void __RPC_STUB IGlobalMTScript_RegisterEventSource_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_UnregisterEventSource_Proxy( + IGlobalMTScript * This, + /* [in] */ IDispatch *pDisp); + + +void __RPC_STUB IGlobalMTScript_UnregisterEventSource_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propget] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_get_StatusValue_Proxy( + IGlobalMTScript * This, + /* [in] */ long nIndex, + /* [retval][out] */ long *pnStatus); + + +void __RPC_STUB IGlobalMTScript_get_StatusValue_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + +/* [helpstring][propput] */ HRESULT STDMETHODCALLTYPE IGlobalMTScript_put_StatusValue_Proxy( + IGlobalMTScript * This, + /* [in] */ long nIndex, + /* [in] */ long nStatus); + + +void __RPC_STUB IGlobalMTScript_put_StatusValue_Stub( + IRpcStubBuffer *This, + IRpcChannelBuffer *_pRpcChannelBuffer, + PRPC_MESSAGE _pRpcMessage, + DWORD *_pdwStubPhase); + + + +#endif /* __IGlobalMTScript_INTERFACE_DEFINED__ */ + + +#ifndef __DLocalMTScriptEvents_DISPINTERFACE_DEFINED__ +#define __DLocalMTScriptEvents_DISPINTERFACE_DEFINED__ + +/* dispinterface DLocalMTScriptEvents */ +/* [uuid] */ + + +EXTERN_C const IID DIID_DLocalMTScriptEvents; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("854c316a-c854-4a77-b189-606859e4391b") + DLocalMTScriptEvents : public IDispatch + { + }; + +#else /* C style interface */ + + typedef struct DLocalMTScriptEventsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + DLocalMTScriptEvents * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + DLocalMTScriptEvents * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + DLocalMTScriptEvents * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + DLocalMTScriptEvents * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + DLocalMTScriptEvents * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + DLocalMTScriptEvents * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + DLocalMTScriptEvents * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + END_INTERFACE + } DLocalMTScriptEventsVtbl; + + interface DLocalMTScriptEvents + { + CONST_VTBL struct DLocalMTScriptEventsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define DLocalMTScriptEvents_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define DLocalMTScriptEvents_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define DLocalMTScriptEvents_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define DLocalMTScriptEvents_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define DLocalMTScriptEvents_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define DLocalMTScriptEvents_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define DLocalMTScriptEvents_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + +#endif /* __DLocalMTScriptEvents_DISPINTERFACE_DEFINED__ */ + + +#ifndef __DRemoteMTScriptEvents_DISPINTERFACE_DEFINED__ +#define __DRemoteMTScriptEvents_DISPINTERFACE_DEFINED__ + +/* dispinterface DRemoteMTScriptEvents */ +/* [uuid] */ + + +EXTERN_C const IID DIID_DRemoteMTScriptEvents; + +#if defined(__cplusplus) && !defined(CINTERFACE) + + MIDL_INTERFACE("854c3170-c854-4a77-b189-606859e4391b") + DRemoteMTScriptEvents : public IDispatch + { + }; + +#else /* C style interface */ + + typedef struct DRemoteMTScriptEventsVtbl + { + BEGIN_INTERFACE + + HRESULT ( STDMETHODCALLTYPE *QueryInterface )( + DRemoteMTScriptEvents * This, + /* [in] */ REFIID riid, + /* [iid_is][out] */ void **ppvObject); + + ULONG ( STDMETHODCALLTYPE *AddRef )( + DRemoteMTScriptEvents * This); + + ULONG ( STDMETHODCALLTYPE *Release )( + DRemoteMTScriptEvents * This); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfoCount )( + DRemoteMTScriptEvents * This, + /* [out] */ UINT *pctinfo); + + HRESULT ( STDMETHODCALLTYPE *GetTypeInfo )( + DRemoteMTScriptEvents * This, + /* [in] */ UINT iTInfo, + /* [in] */ LCID lcid, + /* [out] */ ITypeInfo **ppTInfo); + + HRESULT ( STDMETHODCALLTYPE *GetIDsOfNames )( + DRemoteMTScriptEvents * This, + /* [in] */ REFIID riid, + /* [size_is][in] */ LPOLESTR *rgszNames, + /* [in] */ UINT cNames, + /* [in] */ LCID lcid, + /* [size_is][out] */ DISPID *rgDispId); + + /* [local] */ HRESULT ( STDMETHODCALLTYPE *Invoke )( + DRemoteMTScriptEvents * This, + /* [in] */ DISPID dispIdMember, + /* [in] */ REFIID riid, + /* [in] */ LCID lcid, + /* [in] */ WORD wFlags, + /* [out][in] */ DISPPARAMS *pDispParams, + /* [out] */ VARIANT *pVarResult, + /* [out] */ EXCEPINFO *pExcepInfo, + /* [out] */ UINT *puArgErr); + + END_INTERFACE + } DRemoteMTScriptEventsVtbl; + + interface DRemoteMTScriptEvents + { + CONST_VTBL struct DRemoteMTScriptEventsVtbl *lpVtbl; + }; + + + +#ifdef COBJMACROS + + +#define DRemoteMTScriptEvents_QueryInterface(This,riid,ppvObject) \ + (This)->lpVtbl -> QueryInterface(This,riid,ppvObject) + +#define DRemoteMTScriptEvents_AddRef(This) \ + (This)->lpVtbl -> AddRef(This) + +#define DRemoteMTScriptEvents_Release(This) \ + (This)->lpVtbl -> Release(This) + + +#define DRemoteMTScriptEvents_GetTypeInfoCount(This,pctinfo) \ + (This)->lpVtbl -> GetTypeInfoCount(This,pctinfo) + +#define DRemoteMTScriptEvents_GetTypeInfo(This,iTInfo,lcid,ppTInfo) \ + (This)->lpVtbl -> GetTypeInfo(This,iTInfo,lcid,ppTInfo) + +#define DRemoteMTScriptEvents_GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) \ + (This)->lpVtbl -> GetIDsOfNames(This,riid,rgszNames,cNames,lcid,rgDispId) + +#define DRemoteMTScriptEvents_Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) \ + (This)->lpVtbl -> Invoke(This,dispIdMember,riid,lcid,wFlags,pDispParams,pVarResult,pExcepInfo,puArgErr) + +#endif /* COBJMACROS */ + + +#endif /* C style interface */ + + +#endif /* __DRemoteMTScriptEvents_DISPINTERFACE_DEFINED__ */ + + +EXTERN_C const CLSID CLSID_LocalMTScript; + +#ifdef __cplusplus + +class DECLSPEC_UUID("854c316e-c854-4a77-b189-606859e4391b") +LocalMTScript; +#endif + +EXTERN_C const CLSID CLSID_RemoteMTScript; + +#ifdef __cplusplus + +class DECLSPEC_UUID("854c316d-c854-4a77-b189-606859e4391b") +RemoteMTScript; +#endif + +EXTERN_C const CLSID CLSID_RemoteMTScriptProxy; + +#ifdef __cplusplus + +class DECLSPEC_UUID("854c3182-c854-4a77-b189-606859e4391b") +RemoteMTScriptProxy; +#endif +#endif /* __MTScriptEngine_LIBRARY_DEFINED__ */ + +/* Additional Prototypes for ALL interfaces */ + +/* end of Additional Prototypes */ + +#ifdef __cplusplus +} +#endif + +#endif + + diff --git a/sdktools/watch.c b/sdktools/watch.c new file mode 100644 index 0000000..426cb3f --- /dev/null +++ b/sdktools/watch.c @@ -0,0 +1,191 @@ +/* Small external watch supervisor. Each build runs in a fresh child process. */ +#define WIN32_LEAN_AND_MEAN +#include +#include +#include +#include +#include +#include + +struct WatchState { + HANDLE directory; + HANDLE changed; + volatile LONG generation; +}; + +/* Exclude generated object directories, caches and build logs. */ +static int IgnoreChange(const WCHAR *name, DWORD length) +{ + WCHAR component[260]; + DWORD i = 0; + while (i < length) { + DWORD j = 0; + while (i < length && (name[i] == L'\\' || name[i] == L'/')) ++i; + while (i < length && name[i] != L'\\' && name[i] != L'/') { + if (j + 1 < 260) component[j++] = towlower(name[i]); + ++i; + } + component[j] = 0; + if (!wcscmp(component, L"obj") || !wcscmp(component, L"objd") || + !wcscmp(component, L"out") || !wcscmp(component, L".git") || + !wcscmp(component, L".vs")) return 1; + if (i >= length) { + if (!wcscmp(component, L"build.dat") || + !wcscmp(component, L"build.log") || + !wcscmp(component, L"build.err") || + !wcscmp(component, L"build.wrn") || + !wcscmp(component, L"build.inc")) return 1; + } + } + return 0; +} + +static DWORD WINAPI WatchThread(void *param) +{ + struct WatchState *state = (struct WatchState *)param; + BYTE buffer[32768]; + DWORD bytes; + for (;;) { + if (!ReadDirectoryChangesW(state->directory, buffer, sizeof(buffer), TRUE, + FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME | + FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_CREATION, + &bytes, NULL, NULL)) return 1; + if (bytes) { + BYTE *cursor = buffer; + for (;;) { + FILE_NOTIFY_INFORMATION *info = (FILE_NOTIFY_INFORMATION *)cursor; + if (!IgnoreChange(info->FileName, info->FileNameLength / sizeof(WCHAR))) { + InterlockedIncrement(&state->generation); + SetEvent(state->changed); + break; + } + if (!info->NextEntryOffset) break; + cursor += info->NextEntryOffset; + } + } + } +} + +/* Quote an individual argument according to the Win32 CRT argv rules. */ +static void AddQuoted(WCHAR *dst, const WCHAR *src, size_t *position) +{ + size_t slash = 0; + dst[(*position)++] = L'"'; + while (*src) { + if (*src == L'\\') { ++slash; ++src; continue; } + if (*src == L'"') { + while (slash--) dst[(*position)++] = L'\\'; + dst[(*position)++] = L'\\'; + dst[(*position)++] = L'"'; + slash = 0; + ++src; + continue; + } + while (slash) { dst[(*position)++] = L'\\'; --slash; } + dst[(*position)++] = *src++; + } + while (slash--) { dst[(*position)++] = L'\\'; dst[(*position)++] = L'\\'; } + dst[(*position)++] = L'"'; + dst[*position] = 0; +} + +static WCHAR *MakeChildCommand(int argc, WCHAR **argv) +{ + size_t capacity = 4, pos = 0; + WCHAR *command; + int i; + for (i = 0; i < argc; ++i) capacity += wcslen(argv[i]) * 2 + 5; + command = (WCHAR *)calloc(capacity, sizeof(WCHAR)); + if (!command) return NULL; + for (i = 0; i < argc; ++i) { + if (!argv[i] || !argv[i][0]) continue; + if (pos) command[pos++] = L' '; + AddQuoted(command, argv[i], &pos); + } + return command; +} + +static int RunChild(WCHAR *command) +{ + PROCESS_INFORMATION pi = {0}; + STARTUPINFOW si = {0}; + DWORD status = 1; + si.cb = sizeof(si); + if (!CreateProcessW(NULL, command, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) { + fwprintf(stderr, L"BUILD: error: cannot launch build (%lu)\n", GetLastError()); + return 1; + } + WaitForSingleObject(pi.hProcess, INFINITE); + GetExitCodeProcess(pi.hProcess, &status); + CloseHandle(pi.hThread); + CloseHandle(pi.hProcess); + return (int)status; +} + +/* Return -1 for a normal build; otherwise supervise -w until Ctrl+C. */ +int TryWatchMode(void) +{ + int argc, i, watch = 0; + WCHAR **argv = CommandLineToArgvW(GetCommandLineW(), &argc); + WCHAR *command; + struct WatchState state = {0}; + HANDLE worker; + DWORD threadId; + if (!argv) return -1; + for (i = 1; i < argc; ++i) { + WCHAR *arg = argv[i]; + size_t j, k; + if (arg[0] != L'-' && arg[0] != L'/') continue; + if (!_wcsicmp(arg + 1, L"why")) continue; + /* Keep whole-word and target switches unchanged. */ + if (wcslen(arg) > 1 && wcschr(L"aAcCnN", arg[1]) && + (wcslen(arg) > 3)) continue; + for (j = 1, k = 1; arg[j]; ++j) { + if (arg[j] == L'w' || arg[j] == L'W') { + watch = 1; + } else { + arg[k++] = arg[j]; + } + } + arg[k] = 0; + if (k == 1) argv[i][0] = 0; + } + if (!watch) { LocalFree(argv); return -1; } + command = MakeChildCommand(argc, argv); + LocalFree(argv); + if (!command) return 1; + state.changed = CreateEventW(NULL, FALSE, FALSE, NULL); + state.directory = CreateFileW(L".", FILE_LIST_DIRECTORY, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); + if (!state.changed || state.directory == INVALID_HANDLE_VALUE) { + fprintf(stderr, "BUILD: error: unable to watch project directory\n"); + free(command); + return 1; + } + worker = CreateThread(NULL, 0, WatchThread, &state, 0, &threadId); + if (!worker) { + fprintf(stderr, "BUILD: error: unable to start watcher\n"); + free(command); + return 1; + } + for (;;) { + LONG before = InterlockedCompareExchange(&state.generation, 0, 0); + RunChild(command); + if (before == InterlockedCompareExchange(&state.generation, 0, 0)) { + printf("BUILD: Watching...\n"); + fflush(stdout); + { + HANDLE signals[2] = { state.changed, worker }; + if (WaitForMultipleObjects(2, signals, FALSE, INFINITE) != WAIT_OBJECT_0) { + fprintf(stderr, "BUILD: error: watcher stopped\n"); + free(command); + return 1; + } + } + } + Sleep(200); + /* Drain coalesced notifications before next build. */ + ResetEvent(state.changed); + } +}