From f215e02bf85f68d3a6106c2a1f4f7f063f819064 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 11 Apr 2024 10:17:27 +0200 Subject: Adding upstream version 7.0.14-dfsg. Signed-off-by: Daniel Baumann --- .../Source/C/BrotliCompress/BrotliCompress.c | 587 ++ .../BaseTools/Source/C/BrotliCompress/GNUmakefile | 41 + .../BaseTools/Source/C/BrotliCompress/Makefile | 48 + .../BaseTools/Source/C/Common/BasePeCoff.c | 1469 +++++ .../BaseTools/Source/C/Common/BinderFuncs.c | 74 + .../BaseTools/Source/C/Common/BinderFuncs.h | 61 + .../Firmware/BaseTools/Source/C/Common/CommonLib.c | 2191 ++++++++ .../Firmware/BaseTools/Source/C/Common/CommonLib.h | 469 ++ .../Firmware/BaseTools/Source/C/Common/Compress.h | 82 + .../EFI/Firmware/BaseTools/Source/C/Common/Crc32.c | 313 ++ .../EFI/Firmware/BaseTools/Source/C/Common/Crc32.h | 41 + .../BaseTools/Source/C/Common/Decompress.c | 1014 ++++ .../BaseTools/Source/C/Common/Decompress.h | 159 + .../BaseTools/Source/C/Common/EfiCompress.c | 1591 ++++++ .../BaseTools/Source/C/Common/EfiUtilityMsgs.c | 902 +++ .../BaseTools/Source/C/Common/EfiUtilityMsgs.h | 164 + .../Source/C/Common/FirmwareVolumeBuffer.c | 1775 ++++++ .../Source/C/Common/FirmwareVolumeBufferLib.h | 163 + .../EFI/Firmware/BaseTools/Source/C/Common/FvLib.c | 927 ++++ .../EFI/Firmware/BaseTools/Source/C/Common/FvLib.h | 189 + .../Firmware/BaseTools/Source/C/Common/GNUmakefile | 33 + .../Firmware/BaseTools/Source/C/Common/Makefile | 36 + .../BaseTools/Source/C/Common/Makefile.kmk | 63 + .../BaseTools/Source/C/Common/MemoryFile.c | 251 + .../BaseTools/Source/C/Common/MemoryFile.h | 105 + .../Firmware/BaseTools/Source/C/Common/MyAlloc.c | 548 ++ .../Firmware/BaseTools/Source/C/Common/MyAlloc.h | 209 + .../Firmware/BaseTools/Source/C/Common/OsPath.c | 295 + .../Firmware/BaseTools/Source/C/Common/OsPath.h | 133 + .../Source/C/Common/ParseGuidedSectionTools.c | 205 + .../Source/C/Common/ParseGuidedSectionTools.h | 120 + .../Firmware/BaseTools/Source/C/Common/ParseInf.c | 695 +++ .../Firmware/BaseTools/Source/C/Common/ParseInf.h | 220 + .../BaseTools/Source/C/Common/PcdValueCommon.c | 779 +++ .../BaseTools/Source/C/Common/PcdValueCommon.h | 185 + .../Firmware/BaseTools/Source/C/Common/PeCoffLib.h | 213 + .../BaseTools/Source/C/Common/PeCoffLoaderEx.c | 334 ++ .../BaseTools/Source/C/Common/SimpleFileParsing.c | 1429 +++++ .../BaseTools/Source/C/Common/SimpleFileParsing.h | 104 + .../BaseTools/Source/C/Common/StringFuncs.c | 413 ++ .../BaseTools/Source/C/Common/StringFuncs.h | 244 + .../BaseTools/Source/C/Common/TianoCompress.c | 1746 ++++++ .../BaseTools/Source/C/Common/WinNtInclude.h | 78 + .../BaseTools/Source/C/DevicePath/DevicePath.c | 194 + .../Source/C/DevicePath/DevicePathFromText.c | 3524 ++++++++++++ .../Source/C/DevicePath/DevicePathUtilities.c | 868 +++ .../BaseTools/Source/C/DevicePath/GNUmakefile | 24 + .../BaseTools/Source/C/DevicePath/Makefile | 18 + .../Source/C/DevicePath/UefiDevicePathLib.c | 292 + .../Source/C/DevicePath/UefiDevicePathLib.h | 439 ++ .../Firmware/BaseTools/Source/C/EfiRom/EfiRom.c | 1712 ++++++ .../Firmware/BaseTools/Source/C/EfiRom/EfiRom.h | 353 ++ .../Firmware/BaseTools/Source/C/EfiRom/GNUmakefile | 15 + .../Firmware/BaseTools/Source/C/EfiRom/Makefile | 16 + .../BaseTools/Source/C/EfiRom/Makefile.kmk | 45 + .../EFI/Firmware/BaseTools/Source/C/GNUmakefile | 93 + .../BaseTools/Source/C/GenCrc32/GNUmakefile | 15 + .../BaseTools/Source/C/GenCrc32/GenCrc32.c | 361 ++ .../Firmware/BaseTools/Source/C/GenCrc32/Makefile | 16 + .../BaseTools/Source/C/GenCrc32/Makefile.kmk | 45 + .../Firmware/BaseTools/Source/C/GenFfs/GNUmakefile | 16 + .../Firmware/BaseTools/Source/C/GenFfs/GenFfs.c | 1120 ++++ .../Firmware/BaseTools/Source/C/GenFfs/Makefile | 16 + .../BaseTools/Source/C/GenFfs/Makefile.kmk | 45 + .../Firmware/BaseTools/Source/C/GenFv/GNUmakefile | 23 + .../EFI/Firmware/BaseTools/Source/C/GenFv/GenFv.c | 696 +++ .../BaseTools/Source/C/GenFv/GenFvInternalLib.c | 4432 +++++++++++++++ .../BaseTools/Source/C/GenFv/GenFvInternalLib.h | 402 ++ .../EFI/Firmware/BaseTools/Source/C/GenFv/Makefile | 16 + .../Firmware/BaseTools/Source/C/GenFv/Makefile.kmk | 45 + .../BaseTools/Source/C/GenFw/Elf32Convert.c | 1177 ++++ .../BaseTools/Source/C/GenFw/Elf32Convert.h | 19 + .../BaseTools/Source/C/GenFw/Elf64Convert.c | 1668 ++++++ .../BaseTools/Source/C/GenFw/Elf64Convert.h | 19 + .../Firmware/BaseTools/Source/C/GenFw/ElfConvert.c | 245 + .../Firmware/BaseTools/Source/C/GenFw/ElfConvert.h | 81 + .../Firmware/BaseTools/Source/C/GenFw/GNUmakefile | 23 + .../EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.c | 3255 +++++++++++ .../EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.h | 50 + .../EFI/Firmware/BaseTools/Source/C/GenFw/Makefile | 18 + .../Firmware/BaseTools/Source/C/GenFw/Makefile.kmk | 49 + .../EFI/Firmware/BaseTools/Source/C/GenFw/elf32.h | 252 + .../EFI/Firmware/BaseTools/Source/C/GenFw/elf64.h | 254 + .../Firmware/BaseTools/Source/C/GenFw/elf_common.h | 1045 ++++ .../Firmware/BaseTools/Source/C/GenSec/GNUmakefile | 23 + .../Firmware/BaseTools/Source/C/GenSec/GenSec.c | 1818 +++++++ .../Firmware/BaseTools/Source/C/GenSec/Makefile | 18 + .../BaseTools/Source/C/GenSec/Makefile.kmk | 45 + .../Source/C/Include/AArch64/ProcessorBind.h | 148 + .../BaseTools/Source/C/Include/Arm/ProcessorBind.h | 147 + .../BaseTools/Source/C/Include/Common/BaseTypes.h | 318 ++ .../Source/C/Include/Common/BuildVersion.h | 9 + .../Source/C/Include/Common/MdeModuleHii.h | 233 + .../Source/C/Include/Common/PiFirmwareFile.h | 350 ++ .../Source/C/Include/Common/PiFirmwareVolume.h | 157 + .../Source/C/Include/Common/UefiBaseTypes.h | 168 + .../Source/C/Include/Common/UefiCapsule.h | 26 + .../Common/UefiInternalFormRepresentation.h | 1680 ++++++ .../Source/C/Include/Common/UefiMultiPhase.h | 226 + .../Source/C/Include/Common/VariableFormat.h | 44 + .../Source/C/Include/Common/WorkingBlockHeader.h | 35 + .../C/Include/Guid/FfsSectionAlignmentPadding.h | 16 + .../BaseTools/Source/C/Include/Guid/PcAnsi.h | 52 + .../Source/C/Include/Guid/PiFirmwareFileSystem.h | 39 + .../Source/C/Include/Ia32/ProcessorBind.h | 155 + .../Source/C/Include/IndustryStandard/Acpi.h | 117 + .../Source/C/Include/IndustryStandard/Acpi1_0.h | 285 + .../Source/C/Include/IndustryStandard/Acpi2_0.h | 520 ++ .../Source/C/Include/IndustryStandard/Acpi3_0.h | 668 +++ .../Source/C/Include/IndustryStandard/Bluetooth.h | 56 + .../Source/C/Include/IndustryStandard/EfiPci.h | 51 + .../MemoryMappedConfigurationSpaceAccessTable.h | 39 + .../Source/C/Include/IndustryStandard/PeImage.h | 768 +++ .../Source/C/Include/IndustryStandard/pci22.h | 536 ++ .../Source/C/Include/IndustryStandard/pci23.h | 18 + .../Source/C/Include/IndustryStandard/pci30.h | 38 + .../Source/C/Include/Protocol/DevicePath.h | 1404 +++++ .../C/Include/Protocol/DevicePathUtilities.h | 288 + .../Source/C/Include/Protocol/GraphicsOutput.h | 187 + .../C/Include/Protocol/GuidedSectionExtraction.h | 145 + .../Source/C/Include/Protocol/HiiFramework.h | 944 ++++ .../BaseTools/Source/C/Include/Protocol/UgaDraw.h | 161 + .../Source/C/Include/RiscV64/ProcessorBind.h | 85 + .../BaseTools/Source/C/Include/X64/ProcessorBind.h | 185 + .../BaseTools/Source/C/LzmaCompress/GNUmakefile | 27 + .../Source/C/LzmaCompress/LZMA-SDK-README.txt | 3 + .../BaseTools/Source/C/LzmaCompress/LzmaCompress.c | 406 ++ .../Source/C/LzmaCompress/LzmaF86Compress.bat | 26 + .../BaseTools/Source/C/LzmaCompress/Makefile | 37 + .../BaseTools/Source/C/LzmaCompress/Makefile.kmk | 58 + .../BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.c | 286 + .../BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.h | 87 + .../Source/C/LzmaCompress/Sdk/C/7zStream.c | 176 + .../Source/C/LzmaCompress/Sdk/C/7zTypes.h | 375 ++ .../Source/C/LzmaCompress/Sdk/C/7zVersion.h | 27 + .../BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.c | 460 ++ .../BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.h | 51 + .../BaseTools/Source/C/LzmaCompress/Sdk/C/Bra.h | 64 + .../BaseTools/Source/C/LzmaCompress/Sdk/C/Bra86.c | 82 + .../Source/C/LzmaCompress/Sdk/C/Compiler.h | 33 + .../Source/C/LzmaCompress/Sdk/C/CpuArch.h | 336 ++ .../BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.c | 1127 ++++ .../BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.h | 121 + .../Source/C/LzmaCompress/Sdk/C/LzFindMt.c | 853 +++ .../Source/C/LzmaCompress/Sdk/C/LzFindMt.h | 101 + .../BaseTools/Source/C/LzmaCompress/Sdk/C/LzHash.h | 57 + .../Source/C/LzmaCompress/Sdk/C/LzmaDec.c | 1185 ++++ .../Source/C/LzmaCompress/Sdk/C/LzmaDec.h | 234 + .../Source/C/LzmaCompress/Sdk/C/LzmaEnc.c | 2976 ++++++++++ .../Source/C/LzmaCompress/Sdk/C/LzmaEnc.h | 76 + .../Source/C/LzmaCompress/Sdk/C/Precomp.h | 10 + .../Source/C/LzmaCompress/Sdk/C/Threads.c | 95 + .../Source/C/LzmaCompress/Sdk/C/Threads.h | 72 + .../Source/C/LzmaCompress/Sdk/DOC/lzma-history.txt | 446 ++ .../Source/C/LzmaCompress/Sdk/DOC/lzma-sdk.txt | 357 ++ .../EFI/Firmware/BaseTools/Source/C/Makefile | 69 + .../EFI/Firmware/BaseTools/Source/C/Makefile.kmk | 54 + .../BaseTools/Source/C/Makefiles/NmakeSubdirs.bat | 40 + .../BaseTools/Source/C/Makefiles/NmakeSubdirs.py | 166 + .../BaseTools/Source/C/Makefiles/app.makefile | 22 + .../BaseTools/Source/C/Makefiles/footer.makefile | 30 + .../BaseTools/Source/C/Makefiles/header.makefile | 137 + .../BaseTools/Source/C/Makefiles/lib.makefile | 14 + .../Firmware/BaseTools/Source/C/Makefiles/ms.app | 28 + .../BaseTools/Source/C/Makefiles/ms.common | 62 + .../Firmware/BaseTools/Source/C/Makefiles/ms.lib | 25 + .../Firmware/BaseTools/Source/C/Makefiles/ms.rule | 20 + .../Source/C/PyEfiCompressor/EfiCompressor.c | 206 + .../BaseTools/Source/C/PyEfiCompressor/Makefile | 18 + .../BaseTools/Source/C/PyEfiCompressor/setup.py | 37 + .../BaseTools/Source/C/TianoCompress/GNUmakefile | 15 + .../BaseTools/Source/C/TianoCompress/Makefile | 16 + .../BaseTools/Source/C/TianoCompress/Makefile.kmk | 45 + .../Source/C/TianoCompress/TianoCompress.c | 2795 ++++++++++ .../Source/C/TianoCompress/TianoCompress.h | 431 ++ .../BaseTools/Source/C/VfrCompile/EfiVfr.h | 44 + .../BaseTools/Source/C/VfrCompile/GNUmakefile | 80 + .../BaseTools/Source/C/VfrCompile/Makefile | 50 + .../BaseTools/Source/C/VfrCompile/Makefile.kmk | 155 + .../Source/C/VfrCompile/Pccts/CHANGES_FROM_131.txt | 522 ++ .../Source/C/VfrCompile/Pccts/CHANGES_FROM_133.txt | 2448 +++++++++ .../Pccts/CHANGES_FROM_133_BEFORE_MR13.txt | 3666 +++++++++++++ .../Source/C/VfrCompile/Pccts/CHANGES_SUMMARY.txt | 2049 +++++++ .../Source/C/VfrCompile/Pccts/KNOWN_PROBLEMS.txt | 241 + .../Source/C/VfrCompile/Pccts/MPW_Read_Me | 21 + .../BaseTools/Source/C/VfrCompile/Pccts/Makefile | 15 + .../BaseTools/Source/C/VfrCompile/Pccts/NOTES.bcc | 184 + .../BaseTools/Source/C/VfrCompile/Pccts/NOTES.msvc | 189 + .../BaseTools/Source/C/VfrCompile/Pccts/README | 159 + .../BaseTools/Source/C/VfrCompile/Pccts/RIGHTS | 26 + .../Source/C/VfrCompile/Pccts/antlr/AntlrDDK.mak | 233 + .../Source/C/VfrCompile/Pccts/antlr/AntlrMS.mak | 239 + .../Source/C/VfrCompile/Pccts/antlr/AntlrPPC.mak | 101 + .../Source/C/VfrCompile/Pccts/antlr/README | 19 + .../Source/C/VfrCompile/Pccts/antlr/antlr.1 | 209 + .../Source/C/VfrCompile/Pccts/antlr/antlr.c | 3574 ++++++++++++ .../Source/C/VfrCompile/Pccts/antlr/antlr.g | 2587 +++++++++ .../Source/C/VfrCompile/Pccts/antlr/antlr.r | 787 +++ .../Source/C/VfrCompile/Pccts/antlr/antlr1.txt | 264 + .../Source/C/VfrCompile/Pccts/antlr/bits.c | 1025 ++++ .../Source/C/VfrCompile/Pccts/antlr/build.c | 813 +++ .../Source/C/VfrCompile/Pccts/antlr/dumpcycles.c | 67 + .../Source/C/VfrCompile/Pccts/antlr/dumpnode.c | 423 ++ .../Source/C/VfrCompile/Pccts/antlr/egman.c | 328 ++ .../Source/C/VfrCompile/Pccts/antlr/err.c | 538 ++ .../Source/C/VfrCompile/Pccts/antlr/fcache.c | 123 + .../Source/C/VfrCompile/Pccts/antlr/fset.c | 1555 ++++++ .../Source/C/VfrCompile/Pccts/antlr/fset2.c | 2250 ++++++++ .../Source/C/VfrCompile/Pccts/antlr/gen.c | 4797 ++++++++++++++++ .../Source/C/VfrCompile/Pccts/antlr/generic.h | 286 + .../Source/C/VfrCompile/Pccts/antlr/globals.c | 484 ++ .../Source/C/VfrCompile/Pccts/antlr/hash.c | 224 + .../Source/C/VfrCompile/Pccts/antlr/hash.h | 73 + .../Source/C/VfrCompile/Pccts/antlr/lex.c | 878 +++ .../Source/C/VfrCompile/Pccts/antlr/main.c | 1747 ++++++ .../Source/C/VfrCompile/Pccts/antlr/makefile | 225 + .../C/VfrCompile/Pccts/antlr/makefile.cygwin | 219 + .../Source/C/VfrCompile/Pccts/antlr/makefile1 | 96 + .../Source/C/VfrCompile/Pccts/antlr/misc.c | 1864 +++++++ .../Source/C/VfrCompile/Pccts/antlr/mode.h | 12 + .../Source/C/VfrCompile/Pccts/antlr/mrhoist.c | 3030 +++++++++++ .../Source/C/VfrCompile/Pccts/antlr/parser.dlg | 1387 +++++ .../Source/C/VfrCompile/Pccts/antlr/pred.c | 821 +++ .../Source/C/VfrCompile/Pccts/antlr/proto.h | 857 +++ .../Source/C/VfrCompile/Pccts/antlr/scan.c | 5735 ++++++++++++++++++++ .../Source/C/VfrCompile/Pccts/antlr/stdpccts.h | 31 + .../Source/C/VfrCompile/Pccts/antlr/syn.h | 390 ++ .../Source/C/VfrCompile/Pccts/antlr/tokens.h | 246 + .../Source/C/VfrCompile/Pccts/dlg/DlgDDK.mak | 121 + .../Source/C/VfrCompile/Pccts/dlg/DlgMS.mak | 126 + .../Source/C/VfrCompile/Pccts/dlg/DlgPPC.mak | 84 + .../Source/C/VfrCompile/Pccts/dlg/automata.c | 353 ++ .../BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.1 | 79 + .../BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.h | 250 + .../BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.r | 270 + .../Source/C/VfrCompile/Pccts/dlg/dlg1.txt | 132 + .../Source/C/VfrCompile/Pccts/dlg/dlg_a.c | 1414 +++++ .../Source/C/VfrCompile/Pccts/dlg/dlg_p.c | 970 ++++ .../Source/C/VfrCompile/Pccts/dlg/dlg_p.g | 616 +++ .../BaseTools/Source/C/VfrCompile/Pccts/dlg/err.c | 99 + .../BaseTools/Source/C/VfrCompile/Pccts/dlg/main.c | 281 + .../Source/C/VfrCompile/Pccts/dlg/makefile | 164 + .../Source/C/VfrCompile/Pccts/dlg/makefile.cygwin | 157 + .../Source/C/VfrCompile/Pccts/dlg/makefile1 | 63 + .../BaseTools/Source/C/VfrCompile/Pccts/dlg/mode.h | 4 + .../Source/C/VfrCompile/Pccts/dlg/output.c | 865 +++ .../Source/C/VfrCompile/Pccts/dlg/parser.dlg | 398 ++ .../Source/C/VfrCompile/Pccts/dlg/relabel.c | 217 + .../Source/C/VfrCompile/Pccts/dlg/stdpccts.h | 26 + .../Source/C/VfrCompile/Pccts/dlg/support.c | 240 + .../Source/C/VfrCompile/Pccts/dlg/tokens.h | 133 + .../Source/C/VfrCompile/Pccts/h/AParser.cpp | 871 +++ .../Source/C/VfrCompile/Pccts/h/AParser.h | 376 ++ .../Source/C/VfrCompile/Pccts/h/ASTBase.cpp | 256 + .../Source/C/VfrCompile/Pccts/h/ASTBase.h | 122 + .../Source/C/VfrCompile/Pccts/h/ATokPtr.h | 88 + .../Source/C/VfrCompile/Pccts/h/ATokPtrImpl.h | 90 + .../BaseTools/Source/C/VfrCompile/Pccts/h/AToken.h | 325 ++ .../Source/C/VfrCompile/Pccts/h/ATokenBuffer.cpp | 374 ++ .../Source/C/VfrCompile/Pccts/h/ATokenBuffer.h | 109 + .../Source/C/VfrCompile/Pccts/h/ATokenStream.h | 51 + .../Source/C/VfrCompile/Pccts/h/BufFileInput.cpp | 100 + .../Source/C/VfrCompile/Pccts/h/BufFileInput.h | 53 + .../Source/C/VfrCompile/Pccts/h/DLG_stream_input.h | 98 + .../BaseTools/Source/C/VfrCompile/Pccts/h/DLexer.h | 194 + .../Source/C/VfrCompile/Pccts/h/DLexerBase.cpp | 302 ++ .../Source/C/VfrCompile/Pccts/h/DLexerBase.h | 202 + .../Source/C/VfrCompile/Pccts/h/PBlackBox.h | 134 + .../Source/C/VfrCompile/Pccts/h/PCCTSAST.cpp | 684 +++ .../Source/C/VfrCompile/Pccts/h/PCCTSAST.h | 143 + .../BaseTools/Source/C/VfrCompile/Pccts/h/SList.h | 72 + .../BaseTools/Source/C/VfrCompile/Pccts/h/antlr.h | 807 +++ .../BaseTools/Source/C/VfrCompile/Pccts/h/ast.c | 345 ++ .../BaseTools/Source/C/VfrCompile/Pccts/h/ast.h | 121 + .../Source/C/VfrCompile/Pccts/h/charbuf.h | 46 + .../Source/C/VfrCompile/Pccts/h/charptr.c | 58 + .../Source/C/VfrCompile/Pccts/h/charptr.h | 48 + .../BaseTools/Source/C/VfrCompile/Pccts/h/config.h | 1 + .../Source/C/VfrCompile/Pccts/h/dlgauto.h | 504 ++ .../BaseTools/Source/C/VfrCompile/Pccts/h/dlgdef.h | 128 + .../BaseTools/Source/C/VfrCompile/Pccts/h/err.h | 1173 ++++ .../BaseTools/Source/C/VfrCompile/Pccts/h/int.h | 37 + .../Source/C/VfrCompile/Pccts/h/pccts_assert.h | 10 + .../Source/C/VfrCompile/Pccts/h/pccts_iostream.h | 10 + .../Source/C/VfrCompile/Pccts/h/pccts_istream.h | 10 + .../Source/C/VfrCompile/Pccts/h/pccts_setjmp.h | 10 + .../Source/C/VfrCompile/Pccts/h/pccts_stdarg.h | 10 + .../Source/C/VfrCompile/Pccts/h/pccts_stdio.h | 10 + .../Source/C/VfrCompile/Pccts/h/pccts_stdlib.h | 10 + .../Source/C/VfrCompile/Pccts/h/pccts_string.h | 10 + .../Source/C/VfrCompile/Pccts/h/pcctscfg.h | 359 ++ .../Source/C/VfrCompile/Pccts/h/pcnames.bat | 11 + .../Source/C/VfrCompile/Pccts/h/slist.cpp | 116 + .../BaseTools/Source/C/VfrCompile/Pccts/history.ps | 473 ++ .../Source/C/VfrCompile/Pccts/history.txt | 186 + .../Source/C/VfrCompile/Pccts/makefile.old | 66 + .../C/VfrCompile/Pccts/support/genmk/genmk.c | 1063 ++++ .../C/VfrCompile/Pccts/support/genmk/genmk_old.c | 762 +++ .../C/VfrCompile/Pccts/support/genmk/makefile | 29 + .../C/VfrCompile/Pccts/support/rexpr/makefile | 19 + .../C/VfrCompile/Pccts/support/rexpr/rexpr.c | 586 ++ .../C/VfrCompile/Pccts/support/rexpr/rexpr.h | 30 + .../Source/C/VfrCompile/Pccts/support/rexpr/test.c | 19 + .../Source/C/VfrCompile/Pccts/support/set/set.c | 816 +++ .../Source/C/VfrCompile/Pccts/support/set/set.h | 121 + .../Source/C/VfrCompile/Pccts/support/sym/sym.c | 402 ++ .../C/VfrCompile/Pccts/support/sym/template.h | 41 + .../BaseTools/Source/C/VfrCompile/VfrCompiler.cpp | 941 ++++ .../BaseTools/Source/C/VfrCompile/VfrCompiler.h | 108 + .../BaseTools/Source/C/VfrCompile/VfrError.cpp | 297 + .../BaseTools/Source/C/VfrCompile/VfrError.h | 107 + .../BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp | 2457 +++++++++ .../BaseTools/Source/C/VfrCompile/VfrFormPkg.h | 2776 ++++++++++ .../BaseTools/Source/C/VfrCompile/VfrSyntax.g | 5708 +++++++++++++++++++ .../Source/C/VfrCompile/VfrUtilityLib.cpp | 3921 +++++++++++++ .../BaseTools/Source/C/VfrCompile/VfrUtilityLib.h | 538 ++ .../BaseTools/Source/C/VolInfo/GNUmakefile | 17 + .../Firmware/BaseTools/Source/C/VolInfo/Makefile | 16 + .../BaseTools/Source/C/VolInfo/Makefile.kmk | 45 + .../Firmware/BaseTools/Source/C/VolInfo/VolInfo.c | 2440 +++++++++ .../Firmware/BaseTools/Source/C/VolInfo/VolInfo.h | 31 + 321 files changed, 158311 insertions(+) create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/BrotliCompress.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/GNUmakefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/Makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BasePeCoff.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BinderFuncs.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BinderFuncs.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Compress.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Crc32.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Crc32.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Decompress.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Decompress.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiCompress.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiUtilityMsgs.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiUtilityMsgs.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FirmwareVolumeBuffer.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FirmwareVolumeBufferLib.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FvLib.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FvLib.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/GNUmakefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Makefile.kmk create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MemoryFile.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MemoryFile.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MyAlloc.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MyAlloc.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/OsPath.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/OsPath.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseGuidedSectionTools.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseGuidedSectionTools.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseInf.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseInf.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLib.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLoaderEx.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/SimpleFileParsing.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/SimpleFileParsing.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/StringFuncs.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/StringFuncs.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/TianoCompress.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/WinNtInclude.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/DevicePath.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/DevicePathFromText.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/DevicePathUtilities.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/GNUmakefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/Makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/UefiDevicePathLib.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/UefiDevicePathLib.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/GNUmakefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/Makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/Makefile.kmk create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GNUmakefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenCrc32/GNUmakefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenCrc32/GenCrc32.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenCrc32/Makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenCrc32/Makefile.kmk create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/GNUmakefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/GenFfs.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/Makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/Makefile.kmk create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GNUmakefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GenFv.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GenFvInternalLib.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GenFvInternalLib.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/Makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/Makefile.kmk create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/ElfConvert.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/ElfConvert.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GNUmakefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Makefile.kmk create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf32.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf64.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf_common.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/GNUmakefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/GenSec.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/Makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/Makefile.kmk create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/AArch64/ProcessorBind.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Arm/ProcessorBind.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/BaseTypes.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/BuildVersion.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/MdeModuleHii.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/PiFirmwareFile.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/PiFirmwareVolume.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/UefiBaseTypes.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/UefiCapsule.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/UefiInternalFormRepresentation.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/UefiMultiPhase.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/VariableFormat.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/WorkingBlockHeader.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Guid/FfsSectionAlignmentPadding.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Guid/PcAnsi.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Guid/PiFirmwareFileSystem.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Ia32/ProcessorBind.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Acpi.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Acpi1_0.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Acpi2_0.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Acpi3_0.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Bluetooth.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/EfiPci.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/PeImage.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/pci22.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/pci23.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/pci30.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/DevicePath.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/DevicePathUtilities.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/GraphicsOutput.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/GuidedSectionExtraction.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/HiiFramework.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/UgaDraw.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/RiscV64/ProcessorBind.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/X64/ProcessorBind.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/GNUmakefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LZMA-SDK-README.txt create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LzmaCompress.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LzmaF86Compress.bat create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Makefile.kmk create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zStream.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zTypes.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zVersion.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Bra.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Bra86.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Compiler.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/CpuArch.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzHash.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Precomp.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-history.txt create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-sdk.txt create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile.kmk create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/NmakeSubdirs.bat create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/NmakeSubdirs.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/app.makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/footer.makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/header.makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/lib.makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.app create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.common create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.lib create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.rule create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/PyEfiCompressor/EfiCompressor.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/PyEfiCompressor/Makefile create mode 100755 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/PyEfiCompressor/setup.py create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/GNUmakefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/Makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/Makefile.kmk create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/TianoCompress.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/TianoCompress.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/EfiVfr.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/GNUmakefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Makefile.kmk create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_131.txt create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_133.txt create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_133_BEFORE_MR13.txt create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_SUMMARY.txt create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/KNOWN_PROBLEMS.txt create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/MPW_Read_Me create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/Makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/NOTES.bcc create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/NOTES.msvc create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/README create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/RIGHTS create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrDDK.mak create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrMS.mak create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrPPC.mak create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/README create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.1 create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.g create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.r create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr1.txt create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/bits.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/build.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/dumpcycles.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/dumpnode.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/egman.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/err.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/fcache.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/fset.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/fset2.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/gen.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/generic.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/globals.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/hash.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/hash.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/lex.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/main.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile.cygwin create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile1 create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/misc.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/mode.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/mrhoist.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/parser.dlg create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/pred.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/proto.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/scan.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/stdpccts.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/syn.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/tokens.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgDDK.mak create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgMS.mak create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgPPC.mak create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/automata.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.1 create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.r create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg1.txt create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_a.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_p.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_p.g create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/err.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/main.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/makefile.cygwin create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/makefile1 create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/mode.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/output.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/parser.dlg create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/relabel.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/stdpccts.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/support.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/tokens.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/AParser.cpp create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/AParser.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ASTBase.cpp create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ASTBase.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokPtr.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokPtrImpl.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/AToken.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenBuffer.cpp create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenBuffer.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenStream.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/BufFileInput.cpp create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/BufFileInput.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/DLG_stream_input.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/DLexer.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/DLexerBase.cpp create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/DLexerBase.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/PBlackBox.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/PCCTSAST.cpp create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/PCCTSAST.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/SList.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/antlr.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ast.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ast.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/charbuf.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/charptr.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/charptr.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/config.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/dlgauto.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/dlgdef.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/err.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/int.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_assert.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_iostream.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_istream.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_setjmp.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdarg.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdio.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdlib.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_string.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pcctscfg.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pcnames.bat create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/slist.cpp create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/history.ps create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/history.txt create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/makefile.old create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/genmk.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/genmk_old.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/rexpr.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/rexpr.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/test.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/set/set.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/set/set.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/sym/sym.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/sym/template.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrCompiler.cpp create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrCompiler.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrError.cpp create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrError.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrFormPkg.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrSyntax.g create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrUtilityLib.h create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/GNUmakefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/Makefile create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/Makefile.kmk create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/VolInfo.c create mode 100644 src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/VolInfo.h (limited to 'src/VBox/Devices/EFI/Firmware/BaseTools/Source/C') diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/BrotliCompress.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/BrotliCompress.c new file mode 100644 index 00000000..e32b0c6b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/BrotliCompress.c @@ -0,0 +1,587 @@ +/** @file + BrotliCompress Compress/Decompress tool (BrotliCompress) + + Copyright (c) 2020, ByoSoft Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +/* Command line interface for Brotli library. */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "./brotli/c/common/constants.h" +#include "./brotli/c/common/version.h" +#include +#include + +#if !defined(_WIN32) +#include +#include +#else +#include +#include +#include + +#if !defined(__MINGW32__) +#define STDIN_FILENO _fileno(stdin) +#define STDOUT_FILENO _fileno(stdout) +#define S_IRUSR S_IREAD +#define S_IWUSR S_IWRITE +#endif + +#define fopen ms_fopen +#define open ms_open + +#if defined(_MSC_VER) && (_MSC_VER >= 1400) +#define fseek _fseeki64 +#define ftell _ftelli64 +#endif + +static FILE* ms_fopen(const char* FileName, const char* Mode) { + FILE* Result; + Result = NULL; + fopen_s(&Result, FileName, Mode); + return Result; +} + +static int ms_open(const char* FileName, int Oflag, int Pmode) { + int Result; + Result = -1; + _sopen_s(&Result, FileName, Oflag | O_BINARY, _SH_DENYNO, Pmode); + return Result; +} +#endif /* WIN32 */ + + +#ifndef _MAX_PATH +#define _MAX_PATH 500 +#endif + +#define DEFAULT_LGWIN 22 +#define DECODE_HEADER_SIZE 0x10 +#define GAP_MEM_BLOCK 0x1000 +size_t ScratchBufferSize = 0; +static const size_t kFileBufferSize = 1 << 19; + +static void Version(void) { + int Major; + int Minor; + int Patch; + Major = BROTLI_VERSION >> 24; + Minor = (BROTLI_VERSION >> 12) & 0xFFF; + Patch = BROTLI_VERSION & 0xFFF; + printf("BrotliCompress %d.%d.%d\n", Major, Minor, Patch); +} + +static void Usage() { + printf("Usage: %s [OPTION]... [FILE]...\n", __FILE__); + printf( +"Options:\n" +" -e, --compress compress\n" +" -d, --decompress decompress\n" +" -h, --help display this help and exit\n"); + printf( +" -o FILE, --output=FILE output file (only if 1 input file)\n"); + printf( +" -g NUM, --gap=NUM scratch memory gap level (1-16)\n"); + printf( +" -q NUM, --quality=NUM compression level (%d-%d)\n", + BROTLI_MIN_QUALITY, BROTLI_MAX_QUALITY); + printf( +" -v, --version display version and exit\n"); +} + +static int64_t FileSize(const char* Path) { + FILE *FileHandle; + int64_t RetVal; + FileHandle = fopen(Path, "rb"); + + if (FileHandle == NULL) { + printf ("Failed to open file [%s]\n", Path); + return -1; + } + if (fseek(FileHandle, 0L, SEEK_END) != 0) { + printf ("Failed to seek file [%s]\n", Path); + fclose(FileHandle); + return -1; + } + RetVal = ftell(FileHandle); + if (fclose(FileHandle) != 0) { + printf ("Failed to close file [%s]\n", Path); + return -1; + } + return RetVal; +} + +static BROTLI_BOOL HasMoreInput(FILE *FileHandle) { + return feof(FileHandle) ? BROTLI_FALSE : BROTLI_TRUE; +} + +int OpenFiles(char *InputFile, FILE **InHandle, char *OutputFile, FILE **OutHandle) { + *InHandle = NULL; + *OutHandle = NULL; + *InHandle = fopen(InputFile, "rb"); + if (*InHandle == NULL) { + printf("Failed to open input file [%s]\n", InputFile); + return BROTLI_FALSE; + } + + *OutHandle = fopen(OutputFile, "wb+"); + if (*OutHandle == NULL) { + printf("Failed to open output file [%s]\n", OutputFile); + fclose(*InHandle); + return BROTLI_FALSE; + } + return BROTLI_TRUE; +} + +int CompressFile(char *InputFile, uint8_t *InputBuffer, char *OutputFile, uint8_t *OutputBuffer, int Quality, int Gap) { + int64_t InputFileSize; + FILE *InputFileHandle; + FILE *OutputFileHandle; + BrotliEncoderState *EncodeState; + uint32_t LgWin; + BROTLI_BOOL IsEof; + size_t AvailableIn; + const uint8_t *NextIn; + size_t AvailableOut; + uint8_t *NextOut; + uint8_t *Input; + uint8_t *Output; + size_t TotalOut; + size_t OutSize; + uint32_t SizeHint; + BROTLI_BOOL IsOk; + AvailableIn = 0; + IsEof = BROTLI_FALSE; + Input = InputBuffer; + Output = OutputBuffer; + IsOk = BROTLI_TRUE; + LgWin = DEFAULT_LGWIN; + + InputFileSize = FileSize(InputFile); + + IsOk = OpenFiles(InputFile, &InputFileHandle, OutputFile, &OutputFileHandle); + if (!IsOk) { + return IsOk; + } + + fseek (OutputFileHandle, DECODE_HEADER_SIZE, SEEK_SET); + + EncodeState = BrotliEncoderCreateInstance(NULL, NULL, NULL); + if (!EncodeState) { + printf("Out of memory\n"); + IsOk = BROTLI_FALSE; + goto Finish; + } + BrotliEncoderSetParameter(EncodeState, BROTLI_PARAM_QUALITY, (uint32_t)Quality); + + if (InputFileSize >= 0) { + LgWin = BROTLI_MIN_WINDOW_BITS; + while (BROTLI_MAX_BACKWARD_LIMIT(LgWin) < InputFileSize) { + LgWin++; + if (LgWin == BROTLI_MAX_WINDOW_BITS) { + break; + } + } + } + BrotliEncoderSetParameter(EncodeState, BROTLI_PARAM_LGWIN, LgWin); + if (InputFileSize > 0) { + SizeHint = InputFileSize < (1 << 30)? (uint32_t)InputFileSize : (1u << 30); + BrotliEncoderSetParameter(EncodeState, BROTLI_PARAM_SIZE_HINT, SizeHint); + } + + AvailableIn = 0; + NextIn = NULL; + AvailableOut = kFileBufferSize; + NextOut = Output; + for (;;) { + if (AvailableIn == 0 && !IsEof) { + AvailableIn = fread(Input, 1, kFileBufferSize, InputFileHandle); + NextIn = Input; + if (ferror(InputFileHandle)) { + printf("Failed to read input [%s]\n", InputFile); + IsOk = BROTLI_FALSE; + goto Finish; + } + IsEof = !HasMoreInput(InputFileHandle); + } + + if (!IsEof){ + do{ + if (!BrotliEncoderCompressStream(EncodeState, + BROTLI_OPERATION_FLUSH, + &AvailableIn, &NextIn, &AvailableOut, &NextOut, &TotalOut)) { + printf("Failed to compress data [%s]\n", InputFile); + IsOk = BROTLI_FALSE; + goto Finish; + } + OutSize = (size_t)(NextOut - Output); + if (OutSize > 0) { + fwrite(Output, 1, OutSize, OutputFileHandle); + if (ferror(OutputFileHandle)) { + printf("Failed to write output [%s]\n", OutputFile); + IsOk = BROTLI_FALSE; + goto Finish; + } + } + NextOut = Output; + AvailableOut = kFileBufferSize; + } + while (AvailableIn > 0 || BrotliEncoderHasMoreOutput(EncodeState)); + } + else{ + do{ + if (!BrotliEncoderCompressStream(EncodeState, + BROTLI_OPERATION_FINISH, + &AvailableIn, &NextIn, &AvailableOut, &NextOut, &TotalOut)) { + printf("Failed to compress data [%s]\n", InputFile); + IsOk = BROTLI_FALSE; + goto Finish; + } + OutSize = (size_t)(NextOut - Output); + if (OutSize > 0) { + fwrite(Output, 1, OutSize, OutputFileHandle); + if (ferror(OutputFileHandle)) { + printf("Failed to write output [%s]\n", OutputFile); + IsOk = BROTLI_FALSE; + goto Finish; + } + } + NextOut = Output; + AvailableOut = kFileBufferSize; + } + while (AvailableIn > 0 || BrotliEncoderHasMoreOutput(EncodeState)); + } + if (BrotliEncoderIsFinished(EncodeState)){ + break; + } + } + +Finish: + if (EncodeState) { + BrotliEncoderDestroyInstance(EncodeState); + } + if (InputFileHandle) { + fclose(InputFileHandle); + } + if (OutputFileHandle) { + fclose(OutputFileHandle); + } + return IsOk; +} + +/* Default BrotliAllocFunc */ +void* BrotliAllocFunc(void* Opaque, size_t Size) { + *(size_t *)Opaque = *(size_t *) Opaque + Size; + return malloc(Size); +} + +/* Default BrotliFreeFunc */ +void BrotliFreeFunc(void* Opaque, void* Address) { + free(Address); +} + +int DecompressFile(char *InputFile, uint8_t *InputBuffer, char *OutputFile, uint8_t *OutputBuffer, int Quality, int Gap) { + FILE *InputFileHandle; + FILE *OutputFileHandle; + BrotliDecoderState *DecoderState; + BrotliDecoderResult Result; + size_t AvailableIn; + const uint8_t *NextIn; + size_t AvailableOut; + uint8_t *NextOut; + uint8_t *Input; + uint8_t *Output; + size_t OutSize; + BROTLI_BOOL IsOk; + AvailableIn = 0; + Input = InputBuffer; + Output = OutputBuffer; + IsOk = BROTLI_TRUE; + + IsOk = OpenFiles(InputFile, &InputFileHandle, OutputFile, &OutputFileHandle); + if (!IsOk) { + return IsOk; + } + fseek(InputFileHandle, DECODE_HEADER_SIZE, SEEK_SET); + + DecoderState = BrotliDecoderCreateInstance(BrotliAllocFunc, BrotliFreeFunc, &ScratchBufferSize); + if (!DecoderState) { + printf("Out of memory\n"); + IsOk = BROTLI_FALSE; + goto Finish; + } + /* This allows decoding "large-window" streams. Though it creates + fragmentation (new builds decode streams that old builds don't), + it is better from used experience perspective. */ + BrotliDecoderSetParameter(DecoderState, BROTLI_DECODER_PARAM_LARGE_WINDOW, 1u); + + AvailableIn = 0; + NextIn = NULL; + AvailableOut = kFileBufferSize; + NextOut = Output; + Result = BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT; + for (;;) { + if (Result == BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT) { + if (!HasMoreInput(InputFileHandle)) { + printf("Corrupt input [%s]\n", InputFile); + IsOk = BROTLI_FALSE; + goto Finish; + } + AvailableIn = fread(Input, 1, kFileBufferSize, InputFileHandle); + NextIn = Input; + if (ferror(InputFileHandle)) { + printf("Failed to read input [%s]\n", InputFile); + IsOk = BROTLI_FALSE; + goto Finish; + } + } else if (Result == BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT) { + OutSize = (size_t) (NextOut - Output); + if (OutSize > 0) { + fwrite(Output, 1, OutSize, OutputFileHandle); + if (ferror(OutputFileHandle)) { + printf("Failed to write output [%s]\n", OutputFile); + IsOk = BROTLI_FALSE; + goto Finish; + } + } + AvailableOut = kFileBufferSize; + NextOut = Output; + } else if (Result == BROTLI_DECODER_RESULT_SUCCESS) { + OutSize = (size_t) (NextOut - Output); + if (OutSize > 0) { + fwrite(Output, 1, OutSize, OutputFileHandle); + if (ferror(OutputFileHandle)) { + printf("Failed to write output [%s]\n", OutputFile); + IsOk = BROTLI_FALSE; + goto Finish; + } + } + AvailableOut = 0; + if (AvailableIn != 0 || HasMoreInput(InputFileHandle)) { + printf("Corrupt input [%s]\n", InputFile); + IsOk = BROTLI_FALSE; + goto Finish; + } + } else { + printf("Corrupt input [%s]\n", InputFile); + IsOk = BROTLI_FALSE; + goto Finish; + } + if (!HasMoreInput(InputFileHandle) && Result == BROTLI_DECODER_RESULT_SUCCESS ) { + break; + } + Result = BrotliDecoderDecompressStream(DecoderState, &AvailableIn, &NextIn, &AvailableOut, &NextOut, 0); + } +Finish: + if (DecoderState) { + BrotliDecoderDestroyInstance(DecoderState); + } + if (InputFileHandle) { + fclose(InputFileHandle); + } + if (OutputFileHandle) { + fclose(OutputFileHandle); + } + return IsOk; +} + +int main(int argc, char** argv) { + BROTLI_BOOL CompressBool; + BROTLI_BOOL DecompressBool; + char *OutputFile; + char *InputFile; + char OutputTmpFile[_MAX_PATH]; + FILE *OutputHandle; + int Quality; + int Gap; + int OutputFileLength; + int InputFileLength; + int Ret; + size_t InputFileSize; + uint8_t *Buffer; + uint8_t *InputBuffer; + uint8_t *OutputBuffer; + int64_t Size; + + InputFile = NULL; + OutputFile = NULL; + CompressBool = BROTLI_FALSE; + DecompressBool = BROTLI_FALSE; + // + //Set default Quality and Gap + // + Quality = 9; + Gap = 1; + InputFileSize = 0; + Ret = 0; + + if (argc < 2) { + Usage(); + return 1; + } + if (strcmp(argv[1], "-h") == 0 || strcmp (argv[1], "--help") == 0 ) { + Usage(); + return 0; + } + if (strcmp(argv[1], "-v") == 0 || strcmp (argv[1], "--version") == 0 ) { + Version(); + return 0; + } + while (argc > 1) { + if (strcmp(argv[1], "-e") == 0 || strcmp(argv[1], "--compress") == 0 ) { + CompressBool = BROTLI_TRUE; + if (DecompressBool) { + printf("Can't use -e/--compress with -d/--decompess on the same time\n"); + return 1; + } + argc--; + argv++; + continue; + } + if (strcmp(argv[1], "-d") == 0 || strcmp(argv[1], "--decompress") == 0 ) { + DecompressBool = BROTLI_TRUE; + if (CompressBool) { + printf("Can't use -e/--compress with -d/--decompess on the same time\n"); + return 1; + } + argc--; + argv++; + continue; + } + if (strcmp(argv[1], "-o") == 0 || strncmp(argv[1], "--output", 8) == 0) { + if (strcmp(argv[1], "-o") == 0) { + OutputFileLength = strlen(argv[2]); + if (OutputFileLength > _MAX_PATH) { + printf ("The file path %s is too long\n", argv[2]); + return 1; + } + OutputFile = argv[2]; + if (OutputFile == NULL) { + fprintf(stderr, "Input file can't be null\n"); + return 1; + } + argc--; + argv++; + } else { + OutputFileLength = strlen(argv[1] - 9); + OutputFile = (char *)argv[1] + 9; + } + argc--; + argv++; + continue; + } + if (strcmp(argv[1], "-q") == 0 || strncmp(argv[1], "--quality", 9) == 0) { + if (strcmp(argv[1], "-q") == 0) { + Quality = strtol(argv[2], NULL, 16); + argc--; + argv++; + } else { + Quality = strtol((char *)argv[1] + 10, NULL, 16); + } + argc--; + argv++; + continue; + } + if (strcmp(argv[1], "-g") == 0 || strncmp(argv[1], "--gap", 5) == 0) { + if (strcmp(argv[1], "-g") == 0) { + Gap = strtol(argv[2], NULL, 16); + argc--; + argv++; + } else { + Gap = strtol((char *)argv[1] + 6, NULL, 16); + } + argc--; + argv++; + continue; + } + if (argc > 1) { + InputFileLength = strlen(argv[1]); + if (InputFileLength > _MAX_PATH - 1) { + printf ("The file path %s is too long\n", argv[2]); + return 1; + } + InputFile = argv[1]; + if (InputFile == NULL) { + printf("Input file can't be null\n"); + return 1; + } + argc--; + argv++; + } + } + + Buffer = (uint8_t*)malloc(kFileBufferSize * 2); + if (!Buffer) { + printf("Out of memory\n"); + goto Finish; + } + memset(Buffer, 0, kFileBufferSize*2); + InputBuffer = Buffer; + OutputBuffer = Buffer + kFileBufferSize; + if (CompressBool) { + // + // Compress file + // + Ret = CompressFile(InputFile, InputBuffer, OutputFile, OutputBuffer, Quality, Gap); + if (!Ret) { + printf ("Failed to compress file [%s]\n", InputFile); + goto Finish; + } + // + // Decompress file for get Outputfile size + // + strcpy (OutputTmpFile, OutputFile); + if (strlen(InputFile) + strlen(".tmp") < _MAX_PATH) { + strcat(OutputTmpFile, ".tmp"); + } else { + printf ("Output file path is too long[%s]\n", OutputFile); + Ret = BROTLI_FALSE; + goto Finish; + } + memset(Buffer, 0, kFileBufferSize*2); + Ret = DecompressFile(OutputFile, InputBuffer, OutputTmpFile, OutputBuffer, Quality, Gap); + if (!Ret) { + printf ("Failed to decompress file [%s]\n", OutputFile); + goto Finish; + } + remove (OutputTmpFile); + + // + // fill decoder header + // + InputFileSize = FileSize(InputFile); + Size = (int64_t)InputFileSize; + OutputHandle = fopen(OutputFile, "rb+"); /* open output_path file and add in head info */ + fwrite(&Size, 1, sizeof(int64_t), OutputHandle); + ScratchBufferSize += Gap * GAP_MEM_BLOCK; /* there is a memory gap between IA32 and X64 environment*/ + ScratchBufferSize += kFileBufferSize * 2; + Size = (int64_t) ScratchBufferSize; + fwrite(&Size, 1, sizeof(int64_t), OutputHandle); + if (fclose(OutputHandle) != 0) { + printf("Failed to close output file [%s]\n", OutputFile); + Ret = BROTLI_FALSE; + goto Finish; + } + } else { + Ret = DecompressFile(InputFile, InputBuffer, OutputFile, OutputBuffer, Quality, Gap); + if (!Ret) { + printf ("Failed to decompress file [%s]\n", InputFile); + goto Finish; + } + } + Finish: + if (Buffer != NULL) { + free (Buffer); + } + return !Ret; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/GNUmakefile new file mode 100644 index 00000000..1a1c1bb6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/GNUmakefile @@ -0,0 +1,41 @@ +## @file +# GNU/Linux makefile for 'Brotli' module build. +# +# Copyright (c) 2017 - 2020, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +MAKEROOT ?= .. + +APPNAME = BrotliCompress + +OBJECTS = \ + BrotliCompress.o \ + brotli/c/common/dictionary.o \ + brotli/c/common/transform.o \ + brotli/c/dec/bit_reader.o \ + brotli/c/dec/decode.o \ + brotli/c/dec/huffman.o \ + brotli/c/dec/state.o \ + brotli/c/enc/backward_references.o \ + brotli/c/enc/backward_references_hq.o \ + brotli/c/enc/bit_cost.o \ + brotli/c/enc/block_splitter.o \ + brotli/c/enc/brotli_bit_stream.o \ + brotli/c/enc/cluster.o \ + brotli/c/enc/compress_fragment.o \ + brotli/c/enc/compress_fragment_two_pass.o \ + brotli/c/enc/dictionary_hash.o \ + brotli/c/enc/encode.o \ + brotli/c/enc/encoder_dict.o \ + brotli/c/enc/entropy_encode.o \ + brotli/c/enc/histogram.o \ + brotli/c/enc/literal_cost.o \ + brotli/c/enc/memory.o \ + brotli/c/enc/metablock.o \ + brotli/c/enc/static_dict.o \ + brotli/c/enc/utf8_util.o + +include $(MAKEROOT)/Makefiles/app.makefile + +TOOL_INCLUDE = -I ./brotli/c/include +LIBS += -lm diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/Makefile new file mode 100644 index 00000000..30d329b6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/BrotliCompress/Makefile @@ -0,0 +1,48 @@ +## @file +# Windows makefile for 'Brotli' module build. +# +# Copyright (c) 2017 - 2020, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +!INCLUDE ..\Makefiles\ms.common + +INC = -I .\brotli\c\include $(INC) +CFLAGS = $(CFLAGS) /W2 + +APPNAME = BrotliCompress + +#LIBS = $(LIB_PATH)\Common.lib + +COMMON_OBJ = brotli\c\common\dictionary.obj brotli\c\common\transform.obj +DEC_OBJ = \ + brotli\c\dec\bit_reader.obj \ + brotli\c\dec\decode.obj \ + brotli\c\dec\huffman.obj \ + brotli\c\dec\state.obj +ENC_OBJ = \ + brotli\c\enc\backward_references.obj \ + brotli\c\enc\backward_references_hq.obj \ + brotli\c\enc\bit_cost.obj \ + brotli\c\enc\block_splitter.obj \ + brotli\c\enc\brotli_bit_stream.obj \ + brotli\c\enc\cluster.obj \ + brotli\c\enc\compress_fragment.obj \ + brotli\c\enc\compress_fragment_two_pass.obj \ + brotli\c\enc\dictionary_hash.obj \ + brotli\c\enc\encode.obj \ + brotli\c\enc\encoder_dict.obj \ + brotli\c\enc\entropy_encode.obj \ + brotli\c\enc\histogram.obj \ + brotli\c\enc\literal_cost.obj \ + brotli\c\enc\memory.obj \ + brotli\c\enc\metablock.obj \ + brotli\c\enc\static_dict.obj \ + brotli\c\enc\utf8_util.obj + +OBJECTS = \ + BrotliCompress.obj \ + $(COMMON_OBJ) \ + $(DEC_OBJ) \ + $(ENC_OBJ) + +!INCLUDE ..\Makefiles\ms.app diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BasePeCoff.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BasePeCoff.c new file mode 100644 index 00000000..154f737f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BasePeCoff.c @@ -0,0 +1,1469 @@ +/** @file + + Functions to get info and load PE/COFF image. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include "PeCoffLib.h" + +typedef union { + VOID *Header; + EFI_IMAGE_OPTIONAL_HEADER32 *Optional32; + EFI_IMAGE_OPTIONAL_HEADER64 *Optional64; +} EFI_IMAGE_OPTIONAL_HEADER_POINTER; + +STATIC +RETURN_STATUS +PeCoffLoaderGetPeHeader ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_IMAGE_OPTIONAL_HEADER_UNION **PeHdr, + OUT EFI_TE_IMAGE_HEADER **TeHdr + ); + +STATIC +RETURN_STATUS +PeCoffLoaderCheckImageType ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr, + IN EFI_TE_IMAGE_HEADER *TeHdr + ); + +STATIC +VOID * +PeCoffLoaderImageAddress ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN UINTN Address + ); + +RETURN_STATUS +PeCoffLoaderRelocateIa32Image ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ); + + +RETURN_STATUS +PeCoffLoaderRelocateArmImage ( + IN UINT16 **Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ); + +RETURN_STATUS +PeCoffLoaderRelocateRiscVImage ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ); + +STATIC +RETURN_STATUS +PeCoffLoaderGetPeHeader ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + OUT EFI_IMAGE_OPTIONAL_HEADER_UNION **PeHdr, + OUT EFI_TE_IMAGE_HEADER **TeHdr + ) +/*++ + +Routine Description: + + Retrieves the PE or TE Header from a PE/COFF or TE image + +Arguments: + + ImageContext - The context of the image being loaded + + PeHdr - The buffer in which to return the PE header + + TeHdr - The buffer in which to return the TE header + +Returns: + + RETURN_SUCCESS if the PE or TE Header is read, + Otherwise, the error status from reading the PE/COFF or TE image using the ImageRead function. + +--*/ +{ + RETURN_STATUS Status; + EFI_IMAGE_DOS_HEADER DosHdr; + UINTN Size; + + ImageContext->IsTeImage = FALSE; + // + // Read the DOS image headers + // + Size = sizeof (EFI_IMAGE_DOS_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &Size, + &DosHdr + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + ImageContext->PeCoffHeaderOffset = 0; + if (DosHdr.e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header + // + ImageContext->PeCoffHeaderOffset = DosHdr.e_lfanew; + } + // + // Get the PE/COFF Header pointer + // + *PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINTN)ImageContext->Handle + ImageContext->PeCoffHeaderOffset); + if ((*PeHdr)->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + // + // Check the PE/COFF Header Signature. If not, then try to get a TE header + // + *TeHdr = (EFI_TE_IMAGE_HEADER *)*PeHdr; + if ((*TeHdr)->Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) { + return RETURN_UNSUPPORTED; + } + ImageContext->IsTeImage = TRUE; + } + + return RETURN_SUCCESS; +} + +STATIC +RETURN_STATUS +PeCoffLoaderCheckImageType ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr, + IN EFI_TE_IMAGE_HEADER *TeHdr + ) +/*++ + +Routine Description: + + Checks the PE or TE header of a PE/COFF or TE image to determine if it supported + +Arguments: + + ImageContext - The context of the image being loaded + + PeHdr - The buffer in which to return the PE header + + TeHdr - The buffer in which to return the TE header + +Returns: + + RETURN_SUCCESS if the PE/COFF or TE image is supported + RETURN_UNSUPPORTED of the PE/COFF or TE image is not supported. + +--*/ +{ + // + // See if the machine type is supported. + // We support a native machine type (IA-32/Itanium-based) + // + if (ImageContext->IsTeImage == FALSE) { + ImageContext->Machine = PeHdr->Pe32.FileHeader.Machine; + } else { + ImageContext->Machine = TeHdr->Machine; + } + + if (ImageContext->Machine != EFI_IMAGE_MACHINE_IA32 && \ + ImageContext->Machine != EFI_IMAGE_MACHINE_X64 && \ + ImageContext->Machine != EFI_IMAGE_MACHINE_ARMT && \ + ImageContext->Machine != EFI_IMAGE_MACHINE_EBC && \ + ImageContext->Machine != EFI_IMAGE_MACHINE_AARCH64 && \ + ImageContext->Machine != EFI_IMAGE_MACHINE_RISCV64) { + if (ImageContext->Machine == IMAGE_FILE_MACHINE_ARM) { + // + // There are two types of ARM images. Pure ARM and ARM/Thumb. + // If we see the ARM say it is the ARM/Thumb so there is only + // a single machine type we need to check for ARM. + // + ImageContext->Machine = EFI_IMAGE_MACHINE_ARMT; + if (ImageContext->IsTeImage == FALSE) { + PeHdr->Pe32.FileHeader.Machine = ImageContext->Machine; + } else { + TeHdr->Machine = ImageContext->Machine; + } + + } else { + // + // unsupported PeImage machine type + // + return RETURN_UNSUPPORTED; + } + } + + // + // See if the image type is supported. We support EFI Applications, + // EFI Boot Service Drivers, EFI Runtime Drivers and EFI SAL Drivers. + // + if (ImageContext->IsTeImage == FALSE) { + ImageContext->ImageType = PeHdr->Pe32.OptionalHeader.Subsystem; + } else { + ImageContext->ImageType = (UINT16) (TeHdr->Subsystem); + } + + if (ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION && \ + ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER && \ + ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER && \ + ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER) { + // + // unsupported PeImage subsystem type + // + return RETURN_UNSUPPORTED; + } + + return RETURN_SUCCESS; +} + +RETURN_STATUS +EFIAPI +PeCoffLoaderGetImageInfo ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Retrieves information on a PE/COFF image + +Arguments: + + This - Calling context + ImageContext - The context of the image being loaded + +Returns: + + RETURN_SUCCESS - The information on the PE/COFF image was collected. + RETURN_INVALID_PARAMETER - ImageContext is NULL. + RETURN_UNSUPPORTED - The PE/COFF image is not supported. + Otherwise - The error status from reading the PE/COFF image using the + ImageContext->ImageRead() function + +--*/ +{ + RETURN_STATUS Status; + EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr; + EFI_TE_IMAGE_HEADER *TeHdr; + EFI_IMAGE_DATA_DIRECTORY *DebugDirectoryEntry; + UINTN Size; + UINTN Index; + UINTN DebugDirectoryEntryRva; + UINTN DebugDirectoryEntryFileOffset; + UINTN SectionHeaderOffset; + EFI_IMAGE_SECTION_HEADER SectionHeader; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry; + EFI_IMAGE_OPTIONAL_HEADER_POINTER OptionHeader; + + PeHdr = NULL; + TeHdr = NULL; + DebugDirectoryEntry = NULL; + DebugDirectoryEntryRva = 0; + + if (NULL == ImageContext) { + return RETURN_INVALID_PARAMETER; + } + // + // Assume success + // + ImageContext->ImageError = IMAGE_ERROR_SUCCESS; + + Status = PeCoffLoaderGetPeHeader (ImageContext, &PeHdr, &TeHdr); + if (RETURN_ERROR (Status)) { + return Status; + } + + // + // Verify machine type + // + Status = PeCoffLoaderCheckImageType (ImageContext, PeHdr, TeHdr); + if (RETURN_ERROR (Status)) { + return Status; + } + OptionHeader.Header = (VOID *) &(PeHdr->Pe32.OptionalHeader); + + // + // Retrieve the base address of the image + // + if (!(ImageContext->IsTeImage)) { + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + ImageContext->ImageAddress = (PHYSICAL_ADDRESS) OptionHeader.Optional32->ImageBase; + } else { + ImageContext->ImageAddress = (PHYSICAL_ADDRESS) OptionHeader.Optional64->ImageBase; + } + } else { + ImageContext->ImageAddress = (PHYSICAL_ADDRESS) (TeHdr->ImageBase + TeHdr->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER)); + } + // + // Initialize the alternate destination address to 0 indicating that it + // should not be used. + // + ImageContext->DestinationAddress = 0; + + // + // Initialize the codeview pointer. + // + ImageContext->CodeView = NULL; + ImageContext->PdbPointer = NULL; + + // + // Three cases with regards to relocations: + // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable + // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable + // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but + // has no base relocs to apply + // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid. + // + // Look at the file header to determine if relocations have been stripped, and + // save this info in the image context for later use. + // + if ((!(ImageContext->IsTeImage)) && ((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) { + ImageContext->RelocationsStripped = TRUE; + } else if ((ImageContext->IsTeImage) && (TeHdr->DataDirectory[0].Size == 0) && (TeHdr->DataDirectory[0].VirtualAddress == 0)) { + ImageContext->RelocationsStripped = TRUE; + } else { + ImageContext->RelocationsStripped = FALSE; + } + + if (!(ImageContext->IsTeImage)) { + + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + ImageContext->ImageSize = (UINT64) OptionHeader.Optional32->SizeOfImage; + ImageContext->SectionAlignment = OptionHeader.Optional32->SectionAlignment; + ImageContext->SizeOfHeaders = OptionHeader.Optional32->SizeOfHeaders; + + // + // Modify ImageSize to contain .PDB file name if required and initialize + // PdbRVA field... + // + if (OptionHeader.Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionHeader.Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress; + } + } else { + ImageContext->ImageSize = (UINT64) OptionHeader.Optional64->SizeOfImage; + ImageContext->SectionAlignment = OptionHeader.Optional64->SectionAlignment; + ImageContext->SizeOfHeaders = OptionHeader.Optional64->SizeOfHeaders; + + // + // Modify ImageSize to contain .PDB file name if required and initialize + // PdbRVA field... + // + if (OptionHeader.Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + DebugDirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) &(OptionHeader.Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress; + } + } + + if (DebugDirectoryEntryRva != 0) { + // + // Determine the file offset of the debug directory... This means we walk + // the sections to find which section contains the RVA of the debug + // directory + // + DebugDirectoryEntryFileOffset = 0; + + SectionHeaderOffset = (UINTN)( + ImageContext->PeCoffHeaderOffset + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader + ); + + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) { + // + // Read section header from file + // + Size = sizeof (EFI_IMAGE_SECTION_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeaderOffset, + &Size, + &SectionHeader + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress && + DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) { + DebugDirectoryEntryFileOffset = + DebugDirectoryEntryRva - SectionHeader.VirtualAddress + SectionHeader.PointerToRawData; + break; + } + + SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); + } + + if (DebugDirectoryEntryFileOffset != 0) { + for (Index = 0; Index < DebugDirectoryEntry->Size; Index += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) { + // + // Read next debug directory entry + // + Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugDirectoryEntryFileOffset + Index, + &Size, + &DebugEntry + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index); + if (DebugEntry.RVA == 0 && DebugEntry.FileOffset != 0) { + ImageContext->ImageSize += DebugEntry.SizeOfData; + } + + return RETURN_SUCCESS; + } + } + } + } + } else { + ImageContext->ImageSize = 0; + ImageContext->SectionAlignment = 4096; + ImageContext->SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN) TeHdr->BaseOfCode - (UINTN) TeHdr->StrippedSize; + + DebugDirectoryEntry = &TeHdr->DataDirectory[1]; + DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress; + SectionHeaderOffset = (UINTN) (sizeof (EFI_TE_IMAGE_HEADER)); + + DebugDirectoryEntryFileOffset = 0; + + for (Index = 0; Index < TeHdr->NumberOfSections;) { + // + // Read section header from file + // + Size = sizeof (EFI_IMAGE_SECTION_HEADER); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + SectionHeaderOffset, + &Size, + &SectionHeader + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugDirectoryEntryRva >= SectionHeader.VirtualAddress && + DebugDirectoryEntryRva < SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize) { + DebugDirectoryEntryFileOffset = DebugDirectoryEntryRva - + SectionHeader.VirtualAddress + + SectionHeader.PointerToRawData + + sizeof (EFI_TE_IMAGE_HEADER) - + TeHdr->StrippedSize; + + // + // File offset of the debug directory was found, if this is not the last + // section, then skip to the last section for calculating the image size. + // + if (Index < (UINTN) TeHdr->NumberOfSections - 1) { + SectionHeaderOffset += (TeHdr->NumberOfSections - 1 - Index) * sizeof (EFI_IMAGE_SECTION_HEADER); + Index = TeHdr->NumberOfSections - 1; + continue; + } + } + + // + // In Te image header there is not a field to describe the ImageSize. + // Actually, the ImageSize equals the RVA plus the VirtualSize of + // the last section mapped into memory (Must be rounded up to + // a multiple of Section Alignment). Per the PE/COFF specification, the + // section headers in the Section Table must appear in order of the RVA + // values for the corresponding sections. So the ImageSize can be determined + // by the RVA and the VirtualSize of the last section header in the + // Section Table. + // + if ((++Index) == (UINTN) TeHdr->NumberOfSections) { + ImageContext->ImageSize = (SectionHeader.VirtualAddress + SectionHeader.Misc.VirtualSize + + ImageContext->SectionAlignment - 1) & ~(ImageContext->SectionAlignment - 1); + } + + SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); + } + + if (DebugDirectoryEntryFileOffset != 0) { + for (Index = 0; Index < DebugDirectoryEntry->Size; Index += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) { + // + // Read next debug directory entry + // + Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugDirectoryEntryFileOffset, + &Size, + &DebugEntry + ); + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + + if (DebugEntry.Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + ImageContext->DebugDirectoryEntryRva = (UINT32) (DebugDirectoryEntryRva + Index); + return RETURN_SUCCESS; + } + } + } + } + + return RETURN_SUCCESS; +} + +STATIC +VOID * +PeCoffLoaderImageAddress ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext, + IN UINTN Address + ) +/*++ + +Routine Description: + + Converts an image address to the loaded address + +Arguments: + + ImageContext - The context of the image being loaded + + Address - The address to be converted to the loaded address + +Returns: + + NULL if the address can not be converted, otherwise, the converted address + +--*/ +{ + if (Address >= ImageContext->ImageSize) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS; + return NULL; + } + + return (UINT8 *) ((UINTN) ImageContext->ImageAddress + Address); +} + +RETURN_STATUS +EFIAPI +PeCoffLoaderRelocateImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Relocates a PE/COFF image in memory + +Arguments: + + This - Calling context + + ImageContext - Contains information on the loaded image to relocate + +Returns: + + RETURN_SUCCESS if the PE/COFF image was relocated + RETURN_LOAD_ERROR if the image is not a valid PE/COFF image + RETURN_UNSUPPORTED not support + +--*/ +{ + RETURN_STATUS Status; + EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr; + EFI_TE_IMAGE_HEADER *TeHdr; + EFI_IMAGE_DATA_DIRECTORY *RelocDir; + UINT64 Adjust; + EFI_IMAGE_BASE_RELOCATION *RelocBase; + EFI_IMAGE_BASE_RELOCATION *RelocBaseEnd; + UINT16 *Reloc; + UINT16 *RelocEnd; + CHAR8 *Fixup; + CHAR8 *FixupBase; + UINT16 *F16; + UINT32 *F32; + UINT64 *F64; + CHAR8 *FixupData; + PHYSICAL_ADDRESS BaseAddress; + UINT16 MachineType; + EFI_IMAGE_OPTIONAL_HEADER_POINTER OptionHeader; + + PeHdr = NULL; + TeHdr = NULL; + // + // Assume success + // + ImageContext->ImageError = IMAGE_ERROR_SUCCESS; + + // + // If there are no relocation entries, then we are done + // + if (ImageContext->RelocationsStripped) { + return RETURN_SUCCESS; + } + + // + // Use DestinationAddress field of ImageContext as the relocation address even if it is 0. + // + BaseAddress = ImageContext->DestinationAddress; + + if (!(ImageContext->IsTeImage)) { + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN)ImageContext->ImageAddress + + ImageContext->PeCoffHeaderOffset); + OptionHeader.Header = (VOID *) &(PeHdr->Pe32.OptionalHeader); + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Adjust = (UINT64) BaseAddress - OptionHeader.Optional32->ImageBase; + OptionHeader.Optional32->ImageBase = (UINT32) BaseAddress; + MachineType = ImageContext->Machine; + // + // Find the relocation block + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + if (OptionHeader.Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + RelocDir = &OptionHeader.Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + if ((RelocDir != NULL) && (RelocDir->Size > 0)) { + RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress); + RelocBaseEnd = PeCoffLoaderImageAddress ( + ImageContext, + RelocDir->VirtualAddress + RelocDir->Size - 1 + ); + if (RelocBase == NULL || RelocBaseEnd == NULL || RelocBaseEnd < RelocBase) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return RETURN_LOAD_ERROR; + } + } else { + // + // Set base and end to bypass processing below. + // + RelocBase = RelocBaseEnd = 0; + } + } else { + // + // Set base and end to bypass processing below. + // + RelocBase = RelocBaseEnd = 0; + } + } else { + Adjust = (UINT64) BaseAddress - OptionHeader.Optional64->ImageBase; + OptionHeader.Optional64->ImageBase = BaseAddress; + MachineType = ImageContext->Machine; + // + // Find the relocation block + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + if (OptionHeader.Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + RelocDir = &OptionHeader.Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + if ((RelocDir != NULL) && (RelocDir->Size > 0)) { + RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress); + RelocBaseEnd = PeCoffLoaderImageAddress ( + ImageContext, + RelocDir->VirtualAddress + RelocDir->Size - 1 + ); + if (RelocBase == NULL || RelocBaseEnd == NULL || RelocBaseEnd < RelocBase) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return RETURN_LOAD_ERROR; + } + } else { + // + // Set base and end to bypass processing below. + // + RelocBase = RelocBaseEnd = 0; + } + } else { + // + // Set base and end to bypass processing below. + // + RelocBase = RelocBaseEnd = 0; + } + } + } else { + TeHdr = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress); + Adjust = (UINT64) (BaseAddress - TeHdr->ImageBase); + TeHdr->ImageBase = (UINT64) (BaseAddress); + MachineType = TeHdr->Machine; + + // + // Find the relocation block + // + RelocDir = &TeHdr->DataDirectory[0]; + RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)( + ImageContext->ImageAddress + + RelocDir->VirtualAddress + + sizeof(EFI_TE_IMAGE_HEADER) - + TeHdr->StrippedSize + ); + RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1); + } + + // + // Run the relocation information and apply the fixups + // + FixupData = ImageContext->FixupData; + while (RelocBase < RelocBaseEnd) { + + Reloc = (UINT16 *) ((CHAR8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION)); + RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock); + if (!(ImageContext->IsTeImage)) { + FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress); + if (FixupBase == NULL) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return RETURN_LOAD_ERROR; + } + } else { + FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress + + RelocBase->VirtualAddress + + sizeof(EFI_TE_IMAGE_HEADER) - + TeHdr->StrippedSize + ); + } + + if ((CHAR8 *) RelocEnd < (CHAR8 *) ((UINTN) ImageContext->ImageAddress) || + (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress + + (UINTN)ImageContext->ImageSize)) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return RETURN_LOAD_ERROR; + } + + // + // Run this relocation record + // + while (Reloc < RelocEnd) { + + Fixup = FixupBase + (*Reloc & 0xFFF); + switch ((*Reloc) >> 12) { + case EFI_IMAGE_REL_BASED_ABSOLUTE: + break; + + case EFI_IMAGE_REL_BASED_HIGH: + F16 = (UINT16 *) Fixup; + *F16 = (UINT16) (*F16 + ((UINT16) ((UINT32) Adjust >> 16))); + if (FixupData != NULL) { + *(UINT16 *) FixupData = *F16; + FixupData = FixupData + sizeof (UINT16); + } + break; + + case EFI_IMAGE_REL_BASED_LOW: + F16 = (UINT16 *) Fixup; + *F16 = (UINT16) (*F16 + (UINT16) Adjust); + if (FixupData != NULL) { + *(UINT16 *) FixupData = *F16; + FixupData = FixupData + sizeof (UINT16); + } + break; + + case EFI_IMAGE_REL_BASED_HIGHLOW: + F32 = (UINT32 *) Fixup; + *F32 = *F32 + (UINT32) Adjust; + if (FixupData != NULL) { + FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32)); + *(UINT32 *) FixupData = *F32; + FixupData = FixupData + sizeof (UINT32); + } + break; + + case EFI_IMAGE_REL_BASED_DIR64: + F64 = (UINT64 *) Fixup; + *F64 = *F64 + (UINT64) Adjust; + if (FixupData != NULL) { + FixupData = ALIGN_POINTER (FixupData, sizeof (UINT64)); + *(UINT64 *) FixupData = *F64; + FixupData = FixupData + sizeof (UINT64); + } + break; + + case EFI_IMAGE_REL_BASED_HIGHADJ: + // + // Return the same EFI_UNSUPPORTED return code as + // PeCoffLoaderRelocateImageEx() returns if it does not recognize + // the relocation type. + // + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return RETURN_UNSUPPORTED; + + default: + switch (MachineType) { + case EFI_IMAGE_MACHINE_IA32: + Status = PeCoffLoaderRelocateIa32Image (Reloc, Fixup, &FixupData, Adjust); + break; + case EFI_IMAGE_MACHINE_ARMT: + Status = PeCoffLoaderRelocateArmImage (&Reloc, Fixup, &FixupData, Adjust); + break; + case EFI_IMAGE_MACHINE_RISCV64: + Status = PeCoffLoaderRelocateRiscVImage (Reloc, Fixup, &FixupData, Adjust); + break; + default: + Status = RETURN_UNSUPPORTED; + break; + } + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION; + return Status; + } + } + + // + // Next relocation record + // + Reloc += 1; + } + + // + // Next reloc block + // + RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd; + } + + return RETURN_SUCCESS; +} + +RETURN_STATUS +EFIAPI +PeCoffLoaderLoadImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +/*++ + +Routine Description: + + Loads a PE/COFF image into memory + +Arguments: + + This - Calling context + + ImageContext - Contains information on image to load into memory + +Returns: + + RETURN_SUCCESS if the PE/COFF image was loaded + RETURN_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer + RETURN_LOAD_ERROR if the image is a runtime driver with no relocations + RETURN_INVALID_PARAMETER if the image address is invalid + +--*/ +{ + RETURN_STATUS Status; + EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr; + EFI_TE_IMAGE_HEADER *TeHdr; + PE_COFF_LOADER_IMAGE_CONTEXT CheckContext; + EFI_IMAGE_SECTION_HEADER *FirstSection; + EFI_IMAGE_SECTION_HEADER *Section; + UINTN NumberOfSections; + UINTN Index; + CHAR8 *Base; + CHAR8 *End; + CHAR8 *MaxEnd; + EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + UINTN Size; + UINT32 TempDebugEntryRva; + EFI_IMAGE_OPTIONAL_HEADER_POINTER OptionHeader; + + PeHdr = NULL; + TeHdr = NULL; + OptionHeader.Header = NULL; + // + // Assume success + // + ImageContext->ImageError = IMAGE_ERROR_SUCCESS; + + // + // Copy the provided context info into our local version, get what we + // can from the original image, and then use that to make sure everything + // is legit. + // + CopyMem (&CheckContext, ImageContext, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT)); + + Status = PeCoffLoaderGetImageInfo (&CheckContext); + if (RETURN_ERROR (Status)) { + return Status; + } + + // + // Make sure there is enough allocated space for the image being loaded + // + if (ImageContext->ImageSize < CheckContext.ImageSize) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_SIZE; + return RETURN_BUFFER_TOO_SMALL; + } + + // + // If there's no relocations, then make sure it's not a runtime driver, + // and that it's being loaded at the linked address. + // + if (CheckContext.RelocationsStripped) { + // + // If the image does not contain relocations and it is a runtime driver + // then return an error. + // + if (CheckContext.ImageType == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_SUBSYSTEM; + return RETURN_LOAD_ERROR; + } + // + // If the image does not contain relocations, and the requested load address + // is not the linked address, then return an error. + // + if (CheckContext.ImageAddress != ImageContext->ImageAddress) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_IMAGE_ADDRESS; + return RETURN_INVALID_PARAMETER; + } + } + // + // Make sure the allocated space has the proper section alignment + // + if (!(ImageContext->IsTeImage)) { + if ((ImageContext->ImageAddress & (CheckContext.SectionAlignment - 1)) != 0) { + ImageContext->ImageError = IMAGE_ERROR_INVALID_SECTION_ALIGNMENT; + return RETURN_INVALID_PARAMETER; + } + } + // + // Read the entire PE/COFF or TE header into memory + // + if (!(ImageContext->IsTeImage)) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &ImageContext->SizeOfHeaders, + (VOID *) (UINTN) ImageContext->ImageAddress + ); + + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) + ((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset); + + OptionHeader.Header = (VOID *) &(PeHdr->Pe32.OptionalHeader); + + FirstSection = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN)ImageContext->ImageAddress + + ImageContext->PeCoffHeaderOffset + + sizeof(UINT32) + + sizeof(EFI_IMAGE_FILE_HEADER) + + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader + ); + NumberOfSections = (UINTN) (PeHdr->Pe32.FileHeader.NumberOfSections); + } else { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + 0, + &ImageContext->SizeOfHeaders, + (VOID *) (UINTN) ImageContext->ImageAddress + ); + + TeHdr = (EFI_TE_IMAGE_HEADER *) (UINTN) (ImageContext->ImageAddress); + + FirstSection = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN)ImageContext->ImageAddress + + sizeof(EFI_TE_IMAGE_HEADER) + ); + NumberOfSections = (UINTN) (TeHdr->NumberOfSections); + + } + + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return RETURN_LOAD_ERROR; + } + + // + // Load each section of the image + // + Section = FirstSection; + for (Index = 0, MaxEnd = NULL; Index < NumberOfSections; Index++) { + + // + // Compute sections address + // + Base = PeCoffLoaderImageAddress (ImageContext, Section->VirtualAddress); + End = PeCoffLoaderImageAddress ( + ImageContext, + Section->VirtualAddress + Section->Misc.VirtualSize - 1 + ); + + // + // If the base start or end address resolved to 0, then fail. + // + if ((Base == NULL) || (End == NULL)) { + ImageContext->ImageError = IMAGE_ERROR_SECTION_NOT_LOADED; + return RETURN_LOAD_ERROR; + } + + + if (ImageContext->IsTeImage) { + Base = (CHAR8 *) ((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize); + End = (CHAR8 *) ((UINTN) End + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize); + } + + if (End > MaxEnd) { + MaxEnd = End; + } + + // + // Read the section + // + Size = (UINTN) Section->Misc.VirtualSize; + if ((Size == 0) || (Size > Section->SizeOfRawData)) { + Size = (UINTN) Section->SizeOfRawData; + } + + if (Section->SizeOfRawData) { + if (!(ImageContext->IsTeImage)) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + Section->PointerToRawData, + &Size, + Base + ); + } else { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + Section->PointerToRawData + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize, + &Size, + Base + ); + } + + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return Status; + } + } + + // + // If raw size is less then virt size, zero fill the remaining + // + + if (Size < Section->Misc.VirtualSize) { + ZeroMem (Base + Size, Section->Misc.VirtualSize - Size); + } + + // + // Next Section + // + Section += 1; + } + + // + // Get image's entry point + // + if (!(ImageContext->IsTeImage)) { + ImageContext->EntryPoint = (PHYSICAL_ADDRESS) (UINTN) PeCoffLoaderImageAddress ( + ImageContext, + PeHdr->Pe32.OptionalHeader.AddressOfEntryPoint + ); + } else { + ImageContext->EntryPoint = (UINTN)ImageContext->ImageAddress + + (UINTN)TeHdr->AddressOfEntryPoint + + (UINTN)sizeof(EFI_TE_IMAGE_HEADER) - + (UINTN) TeHdr->StrippedSize; + } + + // + // Determine the size of the fixup data + // + // Per the PE/COFF spec, you can't assume that a given data directory + // is present in the image. You have to check the NumberOfRvaAndSizes in + // the optional header to verify a desired directory entry is there. + // + if (!(ImageContext->IsTeImage)) { + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + if (OptionHeader.Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) + &OptionHeader.Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN); + } else { + ImageContext->FixupDataSize = 0; + } + } else { + if (OptionHeader.Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *) + &OptionHeader.Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN); + } else { + ImageContext->FixupDataSize = 0; + } + } + } else { + DirectoryEntry = &TeHdr->DataDirectory[0]; + ImageContext->FixupDataSize = DirectoryEntry->Size / sizeof (UINT16) * sizeof (UINTN); + } + // + // Consumer must allocate a buffer for the relocation fixup log. + // Only used for runtime drivers. + // + ImageContext->FixupData = NULL; + + // + // Load the Codeview info if present + // + if (ImageContext->DebugDirectoryEntryRva != 0) { + if (!(ImageContext->IsTeImage)) { + DebugEntry = PeCoffLoaderImageAddress ( + ImageContext, + ImageContext->DebugDirectoryEntryRva + ); + } else { + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)(UINTN)( + ImageContext->ImageAddress + + ImageContext->DebugDirectoryEntryRva + + sizeof(EFI_TE_IMAGE_HEADER) - + TeHdr->StrippedSize + ); + } + + if (DebugEntry != NULL) { + TempDebugEntryRva = DebugEntry->RVA; + if (DebugEntry->RVA == 0 && DebugEntry->FileOffset != 0) { + Section--; + if ((UINTN) Section->SizeOfRawData < Section->Misc.VirtualSize) { + TempDebugEntryRva = Section->VirtualAddress + Section->Misc.VirtualSize; + } else { + TempDebugEntryRva = Section->VirtualAddress + Section->SizeOfRawData; + } + } + + if (TempDebugEntryRva != 0) { + if (!(ImageContext->IsTeImage)) { + ImageContext->CodeView = PeCoffLoaderImageAddress (ImageContext, TempDebugEntryRva); + } else { + ImageContext->CodeView = (VOID *)( + (UINTN)ImageContext->ImageAddress + + (UINTN)TempDebugEntryRva + + (UINTN)sizeof(EFI_TE_IMAGE_HEADER) - + (UINTN) TeHdr->StrippedSize + ); + } + + if (ImageContext->CodeView == NULL) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return RETURN_LOAD_ERROR; + } + + if (DebugEntry->RVA == 0) { + Size = DebugEntry->SizeOfData; + if (!(ImageContext->IsTeImage)) { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugEntry->FileOffset, + &Size, + ImageContext->CodeView + ); + } else { + Status = ImageContext->ImageRead ( + ImageContext->Handle, + DebugEntry->FileOffset + sizeof (EFI_TE_IMAGE_HEADER) - TeHdr->StrippedSize, + &Size, + ImageContext->CodeView + ); + // + // Should we apply fix up to this field according to the size difference between PE and TE? + // Because now we maintain TE header fields unfixed, this field will also remain as they are + // in original PE image. + // + } + + if (RETURN_ERROR (Status)) { + ImageContext->ImageError = IMAGE_ERROR_IMAGE_READ; + return RETURN_LOAD_ERROR; + } + + DebugEntry->RVA = TempDebugEntryRva; + } + + switch (*(UINT32 *) ImageContext->CodeView) { + case CODEVIEW_SIGNATURE_NB10: + ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY); + break; + + case CODEVIEW_SIGNATURE_RSDS: + ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY); + break; + + case CODEVIEW_SIGNATURE_MTOC: + ImageContext->PdbPointer = (CHAR8 *) ImageContext->CodeView + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY); + + default: + break; + } + } + } + } + + return Status; +} + +/** + Returns a pointer to the PDB file name for a raw PE/COFF image that is not + loaded into system memory with the PE/COFF Loader Library functions. + + Returns the PDB file name for the PE/COFF image specified by Pe32Data. If + the PE/COFF image specified by Pe32Data is not a valid, then NULL is + returned. If the PE/COFF image specified by Pe32Data does not contain a + debug directory entry, then NULL is returned. If the debug directory entry + in the PE/COFF image specified by Pe32Data does not contain a PDB file name, + then NULL is returned. + If Pe32Data is NULL, then return NULL. + + @param Pe32Data Pointer to the PE/COFF image that is loaded in system + memory. + + @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL + if it cannot be retrieved. + +**/ +VOID * +EFIAPI +PeCoffLoaderGetPdbPointer ( + IN VOID *Pe32Data + ) +{ + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + UINTN DirCount; + VOID *CodeViewEntryPointer; + INTN TEImageAdjust; + UINT32 NumberOfRvaAndSizes; + UINT16 Magic; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + UINT32 Index, Index1; + + if (Pe32Data == NULL) { + return NULL; + } + + TEImageAdjust = 0; + DirectoryEntry = NULL; + DebugEntry = NULL; + NumberOfRvaAndSizes = 0; + Index = 0; + Index1 = 0; + SectionHeader = NULL; + + DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (EFI_IMAGE_DOS_SIGNATURE == DosHdr->e_magic) { + // + // DOS image header is present, so read the PE header after the DOS image header. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data; + } + + if (EFI_TE_IMAGE_HEADER_SIGNATURE == Hdr.Te->Signature) { + if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) { + DirectoryEntry = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG]; + TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize; + + // + // Get the DebugEntry offset in the raw data image. + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (Hdr.Te + 1); + Index = Hdr.Te->NumberOfSections; + for (Index1 = 0; Index1 < Index; Index1 ++) { + if ((DirectoryEntry->VirtualAddress >= SectionHeader[Index1].VirtualAddress) && + (DirectoryEntry->VirtualAddress < (SectionHeader[Index1].VirtualAddress + SectionHeader[Index1].Misc.VirtualSize))) { + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) Hdr.Te + + DirectoryEntry->VirtualAddress - + SectionHeader [Index1].VirtualAddress + + SectionHeader [Index1].PointerToRawData + + TEImageAdjust); + break; + } + } + } + } else if (EFI_IMAGE_NT_SIGNATURE == Hdr.Pe32->Signature) { + // + // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic. + // It is due to backward-compatibility, for some system might + // generate PE32+ image with PE32 Magic. + // + switch (Hdr.Pe32->FileHeader.Machine) { + case EFI_IMAGE_MACHINE_IA32: + case EFI_IMAGE_MACHINE_ARMT: + // + // Assume PE32 image with IA32 Machine field. + // + Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + break; + case EFI_IMAGE_MACHINE_X64: + // + // Assume PE32+ image with X64 Machine field + // + Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + break; + default: + // + // For unknown Machine field, use Magic in optional Header + // + Magic = Hdr.Pe32->OptionalHeader.Magic; + } + + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ( + (UINT8 *) Hdr.Pe32 + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + Hdr.Pe32->FileHeader.SizeOfOptionalHeader + ); + Index = Hdr.Pe32->FileHeader.NumberOfSections; + + if (EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC == Magic) { + // + // Use PE32 offset get Debug Directory Entry + // + NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + // + // Use PE32+ offset get Debug Directory Entry + // + NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes; + DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]); + } + + if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG || DirectoryEntry->VirtualAddress == 0) { + DirectoryEntry = NULL; + DebugEntry = NULL; + } else { + // + // Get the DebugEntry offset in the raw data image. + // + for (Index1 = 0; Index1 < Index; Index1 ++) { + if ((DirectoryEntry->VirtualAddress >= SectionHeader[Index1].VirtualAddress) && + (DirectoryEntry->VirtualAddress < (SectionHeader[Index1].VirtualAddress + SectionHeader[Index1].Misc.VirtualSize))) { + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ( + (UINTN) Pe32Data + + DirectoryEntry->VirtualAddress - + SectionHeader[Index1].VirtualAddress + + SectionHeader[Index1].PointerToRawData); + break; + } + } + } + } else { + return NULL; + } + + if (NULL == DebugEntry || NULL == DirectoryEntry) { + return NULL; + } + + // + // Scan the directory to find the debug entry. + // + for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) { + if (EFI_IMAGE_DEBUG_TYPE_CODEVIEW == DebugEntry->Type) { + if (DebugEntry->SizeOfData > 0) { + // + // Get the DebugEntry offset in the raw data image. + // + CodeViewEntryPointer = NULL; + for (Index1 = 0; Index1 < Index; Index1 ++) { + if ((DebugEntry->RVA >= SectionHeader[Index1].VirtualAddress) && + (DebugEntry->RVA < (SectionHeader[Index1].VirtualAddress + SectionHeader[Index1].Misc.VirtualSize))) { + CodeViewEntryPointer = (VOID *) ( + ((UINTN)Pe32Data) + + (UINTN) DebugEntry->RVA - + SectionHeader[Index1].VirtualAddress + + SectionHeader[Index1].PointerToRawData + + (UINTN)TEImageAdjust); + break; + } + } + if (Index1 >= Index) { + // + // Can't find CodeViewEntryPointer in raw PE/COFF image. + // + continue; + } + switch (* (UINT32 *) CodeViewEntryPointer) { + case CODEVIEW_SIGNATURE_NB10: + return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY)); + case CODEVIEW_SIGNATURE_RSDS: + return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY)); + case CODEVIEW_SIGNATURE_MTOC: + return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY)); + default: + break; + } + } + } + } + + return NULL; +} + + +RETURN_STATUS +EFIAPI +PeCoffLoaderGetEntryPoint ( + IN VOID *Pe32Data, + OUT VOID **EntryPoint, + OUT VOID **BaseOfImage + ) +{ + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr; + + DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data; + if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) { + // + // DOS image header is present, so read the PE header after the DOS image header. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff)); + } else { + // + // DOS image header is not present, so PE header is at the image base. + // + Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data; + } + + // + // Calculate the entry point relative to the start of the image. + // AddressOfEntryPoint is common for PE32 & PE32+ + // + if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + *BaseOfImage = (VOID *)(UINTN)(Hdr.Te->ImageBase + Hdr.Te->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER)); + *EntryPoint = (VOID *)((UINTN)*BaseOfImage + (Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof(EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize); + return RETURN_SUCCESS; + } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) { + *EntryPoint = (VOID *)(UINTN)Hdr.Pe32->OptionalHeader.AddressOfEntryPoint; + if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + *BaseOfImage = (VOID *)(UINTN)Hdr.Pe32->OptionalHeader.ImageBase; + } else { + *BaseOfImage = (VOID *)(UINTN)Hdr.Pe32Plus->OptionalHeader.ImageBase; + } + *EntryPoint = (VOID *)(UINTN)((UINTN)*EntryPoint + (UINTN)*BaseOfImage); + return RETURN_SUCCESS; + } + + return RETURN_UNSUPPORTED; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BinderFuncs.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BinderFuncs.c new file mode 100644 index 00000000..507b70aa --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BinderFuncs.c @@ -0,0 +1,74 @@ +/** @file +Binder function implementations for ANSI C libraries. + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "BinderFuncs.h" +#include "CommonLib.h" +#include +#include + +// +// Binder Function Implementations +// + +VOID * +CommonLibBinderAllocate ( + IN UINTN Size + ) +{ + return (VOID *) malloc (Size); +} + +VOID +CommonLibBinderFree ( + IN VOID *Pointer + ) +{ + free (Pointer); +} + +VOID +CommonLibBinderCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +{ + memmove (Destination, Source, Length); +} + +VOID +CommonLibBinderSetMem ( + IN VOID *Destination, + IN UINTN Length, + IN UINT8 Value + ) +{ + memset (Destination, Value, Length); +} + +INTN +CommonLibBinderCompareMem ( + IN VOID *MemOne, + IN VOID *MemTwo, + IN UINTN Length + ) +{ + return memcmp (MemOne, MemTwo, Length); +} + +BOOLEAN +CommonLibBinderCompareGuid ( + IN EFI_GUID *Guid1, + IN EFI_GUID *Guid2 + ) +{ + return CompareGuid (Guid1, Guid2) ? FALSE : TRUE; +} + + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BinderFuncs.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BinderFuncs.h new file mode 100644 index 00000000..accd22d1 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/BinderFuncs.h @@ -0,0 +1,61 @@ +/** @file +Prototypes for binder functions that allow common code to be written which then +links to implementation of these functions which is appropriate for the specific +environment that they are running under. + +Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef BinderFuncs_h_INCLUDED +#define BinderFuncs_h_INCLUDED + +#include "Common/UefiBaseTypes.h" + +// +// Binder Function Prototypes +// +// These binding functions must be implemented externally as appropriate for +// the environment that the code will be running under. +// + +VOID * +CommonLibBinderAllocate ( + IN UINTN Size + ); + +VOID +CommonLibBinderFree ( + IN VOID *Pointer + ); + +VOID +CommonLibBinderCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ); + +VOID +CommonLibBinderSetMem ( + IN VOID *Destination, + IN UINTN Length, + IN UINT8 Value + ); + +INTN +CommonLibBinderCompareMem ( + IN VOID *MemOne, + IN VOID *MemTwo, + IN UINTN Length + ); + +BOOLEAN +CommonLibBinderCompareGuid ( + IN EFI_GUID *Guid1, + IN EFI_GUID *Guid2 + ); + +#endif // #ifndef CommonLibs_h_INCLUDED + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.c new file mode 100644 index 00000000..ecda9d70 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.c @@ -0,0 +1,2191 @@ +/** @file +Common basic Library Functions + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#ifdef __GNUC__ +#include +#else +#include +#endif +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" + +#define SAFE_STRING_CONSTRAINT_CHECK(Expression, Status) \ + do { \ + ASSERT (Expression); \ + if (!(Expression)) { \ + return Status; \ + } \ + } while (FALSE) + +VOID +PeiZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +/*++ + +Routine Description: + + Set Buffer to zero for Size bytes. + +Arguments: + + Buffer - Memory to set. + + Size - Number of bytes to set + +Returns: + + None + +--*/ +{ + INT8 *Ptr; + + Ptr = Buffer; + while (Size--) { + *(Ptr++) = 0; + } +} + +VOID +PeiCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +/*++ + +Routine Description: + + Copy Length bytes from Source to Destination. + +Arguments: + + Destination - Target of copy + + Source - Place to copy from + + Length - Number of bytes to copy + +Returns: + + None + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + + Destination8 = Destination; + Source8 = Source; + while (Length--) { + *(Destination8++) = *(Source8++); + } +} + +VOID +ZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +{ + PeiZeroMem (Buffer, Size); +} + +VOID +CopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +{ + PeiCopyMem (Destination, Source, Length); +} + +INTN +CompareGuid ( + IN EFI_GUID *Guid1, + IN EFI_GUID *Guid2 + ) +/*++ + +Routine Description: + + Compares to GUIDs + +Arguments: + + Guid1 - guid to compare + Guid2 - guid to compare + +Returns: + = 0 if Guid1 == Guid2 + != 0 if Guid1 != Guid2 + +--*/ +{ + INT32 *g1; + INT32 *g2; + INT32 r; + + // + // Compare 32 bits at a time + // + g1 = (INT32 *) Guid1; + g2 = (INT32 *) Guid2; + + r = g1[0] - g2[0]; + r |= g1[1] - g2[1]; + r |= g1[2] - g2[2]; + r |= g1[3] - g2[3]; + + return r; +} + + +EFI_STATUS +GetFileImage ( + IN CHAR8 *InputFileName, + OUT CHAR8 **InputFileImage, + OUT UINT32 *BytesRead + ) +/*++ + +Routine Description: + + This function opens a file and reads it into a memory buffer. The function + will allocate the memory buffer and returns the size of the buffer. + +Arguments: + + InputFileName The name of the file to read. + InputFileImage A pointer to the memory buffer. + BytesRead The size of the memory buffer. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED An error occurred. + EFI_OUT_OF_RESOURCES No resource to complete operations. + +--*/ +{ + FILE *InputFile; + UINT32 FileSize; + + // + // Verify input parameters. + // + if (InputFileName == NULL || strlen (InputFileName) == 0 || InputFileImage == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Open the file and copy contents into a memory buffer. + // + // + // Open the file + // + InputFile = fopen (LongFilePath (InputFileName), "rb"); + if (InputFile == NULL) { + Error (NULL, 0, 0001, "Error opening the input file", InputFileName); + return EFI_ABORTED; + } + // + // Go to the end so that we can determine the file size + // + if (fseek (InputFile, 0, SEEK_END)) { + Error (NULL, 0, 0004, "Error reading the input file", InputFileName); + fclose (InputFile); + return EFI_ABORTED; + } + // + // Get the file size + // + FileSize = ftell (InputFile); + if (FileSize == -1) { + Error (NULL, 0, 0003, "Error parsing the input file", InputFileName); + fclose (InputFile); + return EFI_ABORTED; + } + // + // Allocate a buffer + // + *InputFileImage = malloc (FileSize); + if (*InputFileImage == NULL) { + fclose (InputFile); + return EFI_OUT_OF_RESOURCES; + } + // + // Reset to the beginning of the file + // + if (fseek (InputFile, 0, SEEK_SET)) { + Error (NULL, 0, 0004, "Error reading the input file", InputFileName); + fclose (InputFile); + free (*InputFileImage); + *InputFileImage = NULL; + return EFI_ABORTED; + } + // + // Read all of the file contents. + // + *BytesRead = fread (*InputFileImage, sizeof (UINT8), FileSize, InputFile); + if (*BytesRead != sizeof (UINT8) * FileSize) { + Error (NULL, 0, 0004, "Error reading the input file", InputFileName); + fclose (InputFile); + free (*InputFileImage); + *InputFileImage = NULL; + return EFI_ABORTED; + } + // + // Close the file + // + fclose (InputFile); + + return EFI_SUCCESS; +} + +EFI_STATUS +PutFileImage ( + IN CHAR8 *OutputFileName, + IN CHAR8 *OutputFileImage, + IN UINT32 BytesToWrite + ) +/*++ + +Routine Description: + + This function opens a file and writes OutputFileImage into the file. + +Arguments: + + OutputFileName The name of the file to write. + OutputFileImage A pointer to the memory buffer. + BytesToWrite The size of the memory buffer. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED An error occurred. + EFI_OUT_OF_RESOURCES No resource to complete operations. + +--*/ +{ + FILE *OutputFile; + UINT32 BytesWrote; + + // + // Verify input parameters. + // + if (OutputFileName == NULL || strlen (OutputFileName) == 0 || OutputFileImage == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Open the file and copy contents into a memory buffer. + // + // + // Open the file + // + OutputFile = fopen (LongFilePath (OutputFileName), "wb"); + if (OutputFile == NULL) { + Error (NULL, 0, 0001, "Error opening the output file", OutputFileName); + return EFI_ABORTED; + } + + // + // Write all of the file contents. + // + BytesWrote = fwrite (OutputFileImage, sizeof (UINT8), BytesToWrite, OutputFile); + if (BytesWrote != sizeof (UINT8) * BytesToWrite) { + Error (NULL, 0, 0002, "Error writing the output file", OutputFileName); + fclose (OutputFile); + return EFI_ABORTED; + } + // + // Close the file + // + fclose (OutputFile); + + return EFI_SUCCESS; +} + +UINT8 +CalculateChecksum8 ( + IN UINT8 *Buffer, + IN UINTN Size + ) +/*++ + +Routine Description: + + This function calculates the value needed for a valid UINT8 checksum + +Arguments: + + Buffer Pointer to buffer containing byte data of component. + Size Size of the buffer + +Returns: + + The 8 bit checksum value needed. + +--*/ +{ + return (UINT8) (0x100 - CalculateSum8 (Buffer, Size)); +} + +UINT8 +CalculateSum8 ( + IN UINT8 *Buffer, + IN UINTN Size + ) +/*++ + +Routine Description:: + + This function calculates the UINT8 sum for the requested region. + +Arguments: + + Buffer Pointer to buffer containing byte data of component. + Size Size of the buffer + +Returns: + + The 8 bit checksum value needed. + +--*/ +{ + UINTN Index; + UINT8 Sum; + + Sum = 0; + + // + // Perform the byte sum for buffer + // + for (Index = 0; Index < Size; Index++) { + Sum = (UINT8) (Sum + Buffer[Index]); + } + + return Sum; +} + +UINT16 +CalculateChecksum16 ( + IN UINT16 *Buffer, + IN UINTN Size + ) +/*++ + +Routine Description:: + + This function calculates the value needed for a valid UINT16 checksum + +Arguments: + + Buffer Pointer to buffer containing byte data of component. + Size Size of the buffer + +Returns: + + The 16 bit checksum value needed. + +--*/ +{ + return (UINT16) (0x10000 - CalculateSum16 (Buffer, Size)); +} + +UINT16 +CalculateSum16 ( + IN UINT16 *Buffer, + IN UINTN Size + ) +/*++ + +Routine Description: + + This function calculates the UINT16 sum for the requested region. + +Arguments: + + Buffer Pointer to buffer containing byte data of component. + Size Size of the buffer + +Returns: + + The 16 bit checksum + +--*/ +{ + UINTN Index; + UINT16 Sum; + + Sum = 0; + + // + // Perform the word sum for buffer + // + for (Index = 0; Index < Size; Index++) { + Sum = (UINT16) (Sum + Buffer[Index]); + } + + return (UINT16) Sum; +} + +EFI_STATUS +PrintGuid ( + IN EFI_GUID *Guid + ) +/*++ + +Routine Description: + + This function prints a GUID to STDOUT. + +Arguments: + + Guid Pointer to a GUID to print. + +Returns: + + EFI_SUCCESS The GUID was printed. + EFI_INVALID_PARAMETER The input was NULL. + +--*/ +{ + if (Guid == NULL) { + Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value"); + return EFI_INVALID_PARAMETER; + } + + printf ( + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", + (unsigned) Guid->Data1, + Guid->Data2, + Guid->Data3, + Guid->Data4[0], + Guid->Data4[1], + Guid->Data4[2], + Guid->Data4[3], + Guid->Data4[4], + Guid->Data4[5], + Guid->Data4[6], + Guid->Data4[7] + ); + return EFI_SUCCESS; +} + +EFI_STATUS +PrintGuidToBuffer ( + IN EFI_GUID *Guid, + IN OUT UINT8 *Buffer, + IN UINT32 BufferLen, + IN BOOLEAN Uppercase + ) +/*++ + +Routine Description: + + This function prints a GUID to a buffer + +Arguments: + + Guid - Pointer to a GUID to print. + Buffer - Pointer to a user-provided buffer to print to + BufferLen - Size of the Buffer + Uppercase - If use upper case. + +Returns: + + EFI_SUCCESS The GUID was printed. + EFI_INVALID_PARAMETER The input was NULL. + EFI_BUFFER_TOO_SMALL The input buffer was not big enough + +--*/ +{ + if (Guid == NULL) { + Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with a NULL value"); + return EFI_INVALID_PARAMETER; + } + + if (BufferLen < PRINTED_GUID_BUFFER_SIZE) { + Error (NULL, 0, 2000, "Invalid parameter", "PrintGuidToBuffer() called with invalid buffer size"); + return EFI_BUFFER_TOO_SMALL; + } + + if (Uppercase) { + sprintf ( + (CHAR8 *)Buffer, + "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + (unsigned) Guid->Data1, + Guid->Data2, + Guid->Data3, + Guid->Data4[0], + Guid->Data4[1], + Guid->Data4[2], + Guid->Data4[3], + Guid->Data4[4], + Guid->Data4[5], + Guid->Data4[6], + Guid->Data4[7] + ); + } else { + sprintf ( + (CHAR8 *)Buffer, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + (unsigned) Guid->Data1, + Guid->Data2, + Guid->Data3, + Guid->Data4[0], + Guid->Data4[1], + Guid->Data4[2], + Guid->Data4[3], + Guid->Data4[4], + Guid->Data4[5], + Guid->Data4[6], + Guid->Data4[7] + ); + } + + return EFI_SUCCESS; +} + +#ifdef __GNUC__ + +size_t _filelength(int fd) +{ + struct stat stat_buf; + fstat(fd, &stat_buf); + return stat_buf.st_size; +} + +#ifndef __CYGWIN__ +char *strlwr(char *s) +{ + char *p = s; + for(;*s;s++) { + *s = tolower(*s); + } + return p; +} +#endif +#endif + +#define WINDOWS_EXTENSION_PATH "\\\\?\\" +#define WINDOWS_UNC_EXTENSION_PATH "\\\\?\\UNC" + +// +// Global data to store full file path. It is not required to be free. +// +CHAR8 mCommonLibFullPath[MAX_LONG_FILE_PATH]; + +CHAR8 * +LongFilePath ( + IN CHAR8 *FileName + ) +/*++ + +Routine Description: + Convert FileName to the long file path, which can support larger than 260 length. + +Arguments: + FileName - FileName. + +Returns: + LongFilePath A pointer to the converted long file path. + +--*/ +{ +#ifdef __GNUC__ + // + // __GNUC__ may not be good way to differentiate unix and windows. Need more investigation here. + // unix has no limitation on file path. Just return FileName. + // + return FileName; +#else + CHAR8 *RootPath; + CHAR8 *PathPointer; + CHAR8 *NextPointer; + + PathPointer = (CHAR8 *) FileName; + + if (FileName != NULL) { + // + // Add the extension string first to support long file path. + // + mCommonLibFullPath[0] = 0; + strcpy (mCommonLibFullPath, WINDOWS_EXTENSION_PATH); + + if (strlen (FileName) > 1 && FileName[0] == '\\' && FileName[1] == '\\') { + // + // network path like \\server\share to \\?\UNC\server\share + // + strcpy (mCommonLibFullPath, WINDOWS_UNC_EXTENSION_PATH); + FileName ++; + } else if (strlen (FileName) < 3 || FileName[1] != ':' || (FileName[2] != '\\' && FileName[2] != '/')) { + // + // Relative file path. Convert it to absolute path. + // + RootPath = getcwd (NULL, 0); + if (RootPath != NULL) { + if (strlen (mCommonLibFullPath) + strlen (RootPath) > MAX_LONG_FILE_PATH - 1) { + Error (NULL, 0, 2000, "Invalid parameter", "RootPath is too long!"); + free (RootPath); + return NULL; + } + strncat (mCommonLibFullPath, RootPath, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1); + if (FileName[0] != '\\' && FileName[0] != '/') { + if (strlen (mCommonLibFullPath) + 1 > MAX_LONG_FILE_PATH - 1) { + Error (NULL, 0, 2000, "Invalid parameter", "RootPath is too long!"); + free (RootPath); + return NULL; + } + // + // Attach directory separator + // + strncat (mCommonLibFullPath, "\\", MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1); + } + free (RootPath); + } + } + + // + // Construct the full file path + // + if (strlen (mCommonLibFullPath) + strlen (FileName) > MAX_LONG_FILE_PATH - 1) { + Error (NULL, 0, 2000, "Invalid parameter", "FileName %s is too long!", FileName); + return NULL; + } + strncat (mCommonLibFullPath, FileName, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1); + + // + // Convert directory separator '/' to '\\' + // + PathPointer = (CHAR8 *) mCommonLibFullPath; + do { + if (*PathPointer == '/') { + *PathPointer = '\\'; + } + } while (*PathPointer ++ != '\0'); + + // + // Convert ":\\\\" to ":\\", because it doesn't work with WINDOWS_EXTENSION_PATH. + // + if ((PathPointer = strstr (mCommonLibFullPath, ":\\\\")) != NULL) { + *(PathPointer + 2) = '\0'; + strncat (mCommonLibFullPath, PathPointer + 3, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1); + } + + // + // Convert ".\\" to "", because it doesn't work with WINDOWS_EXTENSION_PATH. + // + while ((PathPointer = strstr (mCommonLibFullPath, ".\\")) != NULL) { + *PathPointer = '\0'; + strncat (mCommonLibFullPath, PathPointer + 2, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1); + } + + // + // Convert "\\.\\" to "\\", because it doesn't work with WINDOWS_EXTENSION_PATH. + // + while ((PathPointer = strstr (mCommonLibFullPath, "\\.\\")) != NULL) { + *PathPointer = '\0'; + strncat (mCommonLibFullPath, PathPointer + 2, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1); + } + + // + // Convert "\\..\\" to last directory, because it doesn't work with WINDOWS_EXTENSION_PATH. + // + while ((PathPointer = strstr (mCommonLibFullPath, "\\..\\")) != NULL) { + NextPointer = PathPointer + 3; + do { + PathPointer --; + } while (PathPointer > mCommonLibFullPath && *PathPointer != ':' && *PathPointer != '\\'); + + if (*PathPointer == '\\') { + // + // Skip one directory + // + *PathPointer = '\0'; + strncat (mCommonLibFullPath, NextPointer, MAX_LONG_FILE_PATH - strlen (mCommonLibFullPath) - 1); + } else { + // + // No directory is found. Just break. + // + break; + } + } + + PathPointer = mCommonLibFullPath; + } + + return PathPointer; +#endif +} + +CHAR16 +InternalCharToUpper ( + CHAR16 Char + ) +{ + if (Char >= L'a' && Char <= L'z') { + return (CHAR16) (Char - (L'a' - L'A')); + } + + return Char; +} + +UINTN +StrnLenS ( + CONST CHAR16 *String, + UINTN MaxSize + ) +{ + UINTN Length; + + ASSERT (((UINTN) String & BIT0) == 0); + + // + // If String is a null pointer or MaxSize is 0, then the StrnLenS function returns zero. + // + if ((String == NULL) || (MaxSize == 0)) { + return 0; + } + + Length = 0; + while (String[Length] != 0) { + if (Length >= MaxSize - 1) { + return MaxSize; + } + Length++; + } + return Length; +} + + +VOID * +InternalAllocatePool ( + UINTN AllocationSize + ) +{ + VOID * Memory; + + Memory = malloc(AllocationSize); + ASSERT(Memory != NULL); + return Memory; +} + + +VOID * +InternalReallocatePool ( + UINTN OldSize, + UINTN NewSize, + VOID *OldBuffer OPTIONAL + ) +{ + VOID *NewBuffer; + + NewBuffer = AllocateZeroPool (NewSize); + if (NewBuffer != NULL && OldBuffer != NULL) { + memcpy (NewBuffer, OldBuffer, MIN (OldSize, NewSize)); + free(OldBuffer); + } + return NewBuffer; +} + +VOID * +ReallocatePool ( + UINTN OldSize, + UINTN NewSize, + VOID *OldBuffer OPTIONAL + ) +{ + return InternalReallocatePool (OldSize, NewSize, OldBuffer); +} + +/** + Returns the length of a Null-terminated Unicode string. + + This function returns the number of Unicode characters in the Null-terminated + Unicode string specified by String. + + If String is NULL, then ASSERT(). + If String is not aligned on a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + @param String A pointer to a Null-terminated Unicode string. + + @return The length of String. + +**/ +UINTN +StrLen ( + CONST CHAR16 *String + ) +{ + UINTN Length; + + ASSERT (String != NULL); + ASSERT (((UINTN) String & BIT0) == 0); + + for (Length = 0; *String != L'\0'; String++, Length++) { + // + // If PcdMaximumUnicodeStringLength is not zero, + // length should not more than PcdMaximumUnicodeStringLength + // + } + return Length; +} + +BOOLEAN +InternalSafeStringIsOverlap ( + IN VOID *Base1, + IN UINTN Size1, + IN VOID *Base2, + IN UINTN Size2 + ) +{ + if ((((UINTN)Base1 >= (UINTN)Base2) && ((UINTN)Base1 < (UINTN)Base2 + Size2)) || + (((UINTN)Base2 >= (UINTN)Base1) && ((UINTN)Base2 < (UINTN)Base1 + Size1))) { + return TRUE; + } + return FALSE; +} + +BOOLEAN +InternalSafeStringNoStrOverlap ( + IN CHAR16 *Str1, + IN UINTN Size1, + IN CHAR16 *Str2, + IN UINTN Size2 + ) +{ + return !InternalSafeStringIsOverlap (Str1, Size1 * sizeof(CHAR16), Str2, Size2 * sizeof(CHAR16)); +} + +/** + Convert a Null-terminated Unicode decimal string to a value of type UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Unicode string specified by String as a decimal number. The format of the + input Unicode string String is: + + [spaces] [decimal digits]. + + The valid decimal digit character is in the range [0-9]. The function will + ignore the pad space, which includes spaces or tab characters, before + [decimal digits]. The running zero in the beginning of [decimal digits] will + be ignored. Then, the function stops at the first character that is a not a + valid decimal character or a Null-terminator, whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid decimal digits in the above format, then 0 is stored + at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + decimal digits right after the optional pad spaces, the value of String is + stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +StrDecimalToUint64S ( + CONST CHAR16 *String, + CHAR16 **EndPointer, OPTIONAL + UINT64 *Data + ) +{ + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == L' ') || (*String == L'\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == L'0') { + String++; + } + + *Data = 0; + + while (InternalIsDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINT64, then MAX_UINT64 is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > ((MAX_UINT64 - (*String - L'0'))/10)) { + *Data = MAX_UINT64; + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = (*Data) * 10 + (*String - L'0'); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode hexadecimal string to a value of type + UINT64. + + This function outputs a value of type UINT64 by interpreting the contents of + the Unicode string specified by String as a hexadecimal number. The format of + the input Unicode string String is: + + [spaces][zeros][x][hexadecimal digits]. + + The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F]. + The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix. + If "x" appears in the input string, it must be prefixed with at least one 0. + The function will ignore the pad space, which includes spaces or tab + characters, before [zeros], [x] or [hexadecimal digit]. The running zero + before [x] or [hexadecimal digit] will be ignored. Then, the decoding starts + after [x] or the first valid hexadecimal digit. Then, the function stops at + the first character that is a not a valid hexadecimal character or NULL, + whichever one comes first. + + If String is NULL, then ASSERT(). + If Data is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the + Null-terminator, then ASSERT(). + + If String has no valid hexadecimal digits in the above format, then 0 is + stored at the location pointed to by Data. + If the number represented by String exceeds the range defined by UINT64, then + MAX_UINT64 is stored at the location pointed to by Data. + + If EndPointer is not NULL, a pointer to the character that stopped the scan + is stored at the location pointed to by EndPointer. If String has no valid + hexadecimal digits right after the optional pad spaces, the value of String + is stored at the location pointed to by EndPointer. + + @param String Pointer to a Null-terminated Unicode string. + @param EndPointer Pointer to character that stops scan. + @param Data Pointer to the converted value. + + @retval RETURN_SUCCESS Value is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If PcdMaximumUnicodeStringLength is not + zero, and String contains more than + PcdMaximumUnicodeStringLength Unicode + characters, not including the + Null-terminator. + @retval RETURN_UNSUPPORTED If the number represented by String exceeds + the range defined by UINT64. + +**/ +RETURN_STATUS +StrHexToUint64S ( + CONST CHAR16 *String, + CHAR16 **EndPointer, OPTIONAL + UINT64 *Data + ) +{ + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. Neither String nor Data shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Data != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. The length of String shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((StrnLenS (String, RSIZE_MAX + 1) <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + + // + // Ignore the pad spaces (space or tab) + // + while ((*String == L' ') || (*String == L'\t')) { + String++; + } + + // + // Ignore leading Zeros after the spaces + // + while (*String == L'0') { + String++; + } + + if (InternalCharToUpper (*String) == L'X') { + if (*(String - 1) != L'0') { + *Data = 0; + return RETURN_SUCCESS; + } + // + // Skip the 'X' + // + String++; + } + + *Data = 0; + + while (InternalIsHexaDecimalDigitCharacter (*String)) { + // + // If the number represented by String overflows according to the range + // defined by UINT64, then MAX_UINT64 is stored in *Data and + // RETURN_UNSUPPORTED is returned. + // + if (*Data > ((MAX_UINT64 - InternalHexCharToUintn (*String))>>4)) { + *Data = MAX_UINT64; + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_UNSUPPORTED; + } + + *Data = ((*Data) << 4) + InternalHexCharToUintn (*String); + String++; + } + + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) String; + } + return RETURN_SUCCESS; +} + +UINT64 +StrDecimalToUint64 ( + CONST CHAR16 *String + ) +{ + UINT64 Result; + + StrDecimalToUint64S (String, (CHAR16 **) NULL, &Result); + return Result; +} + + +UINT64 +StrHexToUint64 ( + CONST CHAR16 *String + ) +{ + UINT64 Result; + + StrHexToUint64S (String, (CHAR16 **) NULL, &Result); + return Result; +} + +UINTN +StrSize ( + CONST CHAR16 *String + ) +{ + return (StrLen (String) + 1) * sizeof (*String); +} + + +UINT64 +ReadUnaligned64 ( + CONST UINT64 *Buffer + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer; +} + +UINT64 +WriteUnaligned64 ( + UINT64 *Buffer, + UINT64 Value + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer = Value; +} + + +EFI_GUID * +CopyGuid ( + EFI_GUID *DestinationGuid, + CONST EFI_GUID *SourceGuid + ) +{ + WriteUnaligned64 ( + (UINT64*)DestinationGuid, + ReadUnaligned64 ((CONST UINT64*)SourceGuid) + ); + WriteUnaligned64 ( + (UINT64*)DestinationGuid + 1, + ReadUnaligned64 ((CONST UINT64*)SourceGuid + 1) + ); + return DestinationGuid; +} + +UINT16 +SwapBytes16 ( + UINT16 Value + ) +{ + return (UINT16) ((Value<< 8) | (Value>> 8)); +} + + +UINT32 +SwapBytes32 ( + UINT32 Value + ) +{ + UINT32 LowerBytes; + UINT32 HigherBytes; + + LowerBytes = (UINT32) SwapBytes16 ((UINT16) Value); + HigherBytes = (UINT32) SwapBytes16 ((UINT16) (Value >> 16)); + return (LowerBytes << 16 | HigherBytes); +} + +BOOLEAN +InternalIsDecimalDigitCharacter ( + CHAR16 Char + ) +{ + return (BOOLEAN) (Char >= L'0' && Char <= L'9'); +} + +VOID * +InternalAllocateCopyPool ( + UINTN AllocationSize, + CONST VOID *Buffer + ) +{ + VOID *Memory; + + ASSERT (Buffer != NULL); + + Memory = malloc (AllocationSize); + if (Memory != NULL) { + Memory = memcpy (Memory, Buffer, AllocationSize); + } + return Memory; +} + +BOOLEAN +InternalIsHexaDecimalDigitCharacter ( + CHAR16 Char + ) +{ + + return (BOOLEAN) (InternalIsDecimalDigitCharacter (Char) || + (Char >= L'A' && Char <= L'F') || + (Char >= L'a' && Char <= L'f')); +} + +UINTN +InternalHexCharToUintn ( + CHAR16 Char + ) +{ + if (InternalIsDecimalDigitCharacter (Char)) { + return Char - L'0'; + } + + return (10 + InternalCharToUpper (Char) - L'A'); +} + + +/** + Convert a Null-terminated Unicode hexadecimal string to a byte array. + + This function outputs a byte array by interpreting the contents of + the Unicode string specified by String in hexadecimal format. The format of + the input Unicode string String is: + + [XX]* + + X is a hexadecimal digit character in the range [0-9], [a-f] and [A-F]. + The function decodes every two hexadecimal digit characters as one byte. The + decoding stops after Length of characters and outputs Buffer containing + (Length / 2) bytes. + + If String is not aligned in a 16-bit boundary, then ASSERT(). + + If String is NULL, then ASSERT(). + + If Buffer is NULL, then ASSERT(). + + If Length is not multiple of 2, then ASSERT(). + + If PcdMaximumUnicodeStringLength is not zero and Length is greater than + PcdMaximumUnicodeStringLength, then ASSERT(). + + If MaxBufferSize is less than (Length / 2), then ASSERT(). + + @param String Pointer to a Null-terminated Unicode string. + @param Length The number of Unicode characters to decode. + @param Buffer Pointer to the converted bytes array. + @param MaxBufferSize The maximum size of Buffer. + + @retval RETURN_SUCCESS Buffer is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + If Length is not multiple of 2. + If PcdMaximumUnicodeStringLength is not zero, + and Length is greater than + PcdMaximumUnicodeStringLength. + @retval RETURN_UNSUPPORTED If Length of characters from String contain + a character that is not valid hexadecimal + digit characters, or a Null-terminator. + @retval RETURN_BUFFER_TOO_SMALL If MaxBufferSize is less than (Length / 2). +**/ +RETURN_STATUS +StrHexToBytes ( + CONST CHAR16 *String, + UINTN Length, + UINT8 *Buffer, + UINTN MaxBufferSize + ) +{ + UINTN Index; + + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. None of String or Buffer shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Buffer != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. Length shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((Length <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. Length shall not be odd. + // + SAFE_STRING_CONSTRAINT_CHECK (((Length & BIT0) == 0), RETURN_INVALID_PARAMETER); + + // + // 4. MaxBufferSize shall equal to or greater than Length / 2. + // + SAFE_STRING_CONSTRAINT_CHECK ((MaxBufferSize >= Length / 2), RETURN_BUFFER_TOO_SMALL); + + // + // 5. String shall not contains invalid hexadecimal digits. + // + for (Index = 0; Index < Length; Index++) { + if (!InternalIsHexaDecimalDigitCharacter (String[Index])) { + break; + } + } + if (Index != Length) { + return RETURN_UNSUPPORTED; + } + + // + // Convert the hex string to bytes. + // + for(Index = 0; Index < Length; Index++) { + + // + // For even characters, write the upper nibble for each buffer byte, + // and for even characters, the lower nibble. + // + if ((Index & BIT0) == 0) { + Buffer[Index / 2] = (UINT8) InternalHexCharToUintn (String[Index]) << 4; + } else { + Buffer[Index / 2] |= (UINT8) InternalHexCharToUintn (String[Index]); + } + } + return RETURN_SUCCESS; +} + +/** + Convert a Null-terminated Unicode GUID string to a value of type + EFI_GUID. + + This function outputs a GUID value by interpreting the contents of + the Unicode string specified by String. The format of the input + Unicode string String consists of 36 characters, as follows: + + aabbccdd-eeff-gghh-iijj-kkllmmnnoopp + + The pairs aa - pp are two characters in the range [0-9], [a-f] and + [A-F], with each pair representing a single byte hexadecimal value. + + The mapping between String and the EFI_GUID structure is as follows: + aa Data1[24:31] + bb Data1[16:23] + cc Data1[8:15] + dd Data1[0:7] + ee Data2[8:15] + ff Data2[0:7] + gg Data3[8:15] + hh Data3[0:7] + ii Data4[0:7] + jj Data4[8:15] + kk Data4[16:23] + ll Data4[24:31] + mm Data4[32:39] + nn Data4[40:47] + oo Data4[48:55] + pp Data4[56:63] + + If String is NULL, then ASSERT(). + If Guid is NULL, then ASSERT(). + If String is not aligned in a 16-bit boundary, then ASSERT(). + + @param String Pointer to a Null-terminated Unicode string. + @param Guid Pointer to the converted GUID. + + @retval RETURN_SUCCESS Guid is translated from String. + @retval RETURN_INVALID_PARAMETER If String is NULL. + If Data is NULL. + @retval RETURN_UNSUPPORTED If String is not as the above format. + +**/ +RETURN_STATUS +StrToGuid ( + CONST CHAR16 *String, + EFI_GUID *Guid + ) +{ + RETURN_STATUS Status; + EFI_GUID LocalGuid; + + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. None of String or Guid shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Guid != NULL), RETURN_INVALID_PARAMETER); + + // + // Get aabbccdd in big-endian. + // + Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data1), (UINT8 *) &LocalGuid.Data1, sizeof (LocalGuid.Data1)); + if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data1)] != L'-') { + return RETURN_UNSUPPORTED; + } + // + // Convert big-endian to little-endian. + // + LocalGuid.Data1 = SwapBytes32 (LocalGuid.Data1); + String += 2 * sizeof (LocalGuid.Data1) + 1; + + // + // Get eeff in big-endian. + // + Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data2), (UINT8 *) &LocalGuid.Data2, sizeof (LocalGuid.Data2)); + if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data2)] != L'-') { + return RETURN_UNSUPPORTED; + } + // + // Convert big-endian to little-endian. + // + LocalGuid.Data2 = SwapBytes16 (LocalGuid.Data2); + String += 2 * sizeof (LocalGuid.Data2) + 1; + + // + // Get gghh in big-endian. + // + Status = StrHexToBytes (String, 2 * sizeof (LocalGuid.Data3), (UINT8 *) &LocalGuid.Data3, sizeof (LocalGuid.Data3)); + if (RETURN_ERROR (Status) || String[2 * sizeof (LocalGuid.Data3)] != L'-') { + return RETURN_UNSUPPORTED; + } + // + // Convert big-endian to little-endian. + // + LocalGuid.Data3 = SwapBytes16 (LocalGuid.Data3); + String += 2 * sizeof (LocalGuid.Data3) + 1; + + // + // Get iijj. + // + Status = StrHexToBytes (String, 2 * 2, &LocalGuid.Data4[0], 2); + if (RETURN_ERROR (Status) || String[2 * 2] != L'-') { + return RETURN_UNSUPPORTED; + } + String += 2 * 2 + 1; + + // + // Get kkllmmnnoopp. + // + Status = StrHexToBytes (String, 2 * 6, &LocalGuid.Data4[2], 6); + if (RETURN_ERROR (Status)) { + return RETURN_UNSUPPORTED; + } + + CopyGuid (Guid, &LocalGuid); + return RETURN_SUCCESS; +} + +/** + Compares up to a specified length the contents of two Null-terminated Unicode strings, + and returns the difference between the first mismatched Unicode characters. + + This function compares the Null-terminated Unicode string FirstString to the + Null-terminated Unicode string SecondString. At most, Length Unicode + characters will be compared. If Length is 0, then 0 is returned. If + FirstString is identical to SecondString, then 0 is returned. Otherwise, the + value returned is the first mismatched Unicode character in SecondString + subtracted from the first mismatched Unicode character in FirstString. + + If Length > 0 and FirstString is NULL, then ASSERT(). + If Length > 0 and FirstString is not aligned on a 16-bit boundary, then ASSERT(). + If Length > 0 and SecondString is NULL, then ASSERT(). + If Length > 0 and SecondString is not aligned on a 16-bit boundary, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and Length is greater than + PcdMaximumUnicodeStringLength, then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and FirstString contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, + then ASSERT(). + If PcdMaximumUnicodeStringLength is not zero, and SecondString contains more than + PcdMaximumUnicodeStringLength Unicode characters, not including the Null-terminator, + then ASSERT(). + + @param FirstString A pointer to a Null-terminated Unicode string. + @param SecondString A pointer to a Null-terminated Unicode string. + @param Length The maximum number of Unicode characters to compare. + + @retval 0 FirstString is identical to SecondString. + @return others FirstString is not identical to SecondString. + +**/ +INTN +StrnCmp ( + CONST CHAR16 *FirstString, + CONST CHAR16 *SecondString, + UINTN Length + ) +{ + if (Length == 0) { + return 0; + } + + // + // ASSERT both strings are less long than PcdMaximumUnicodeStringLength. + // Length tests are performed inside StrLen(). + // + ASSERT (StrSize (FirstString) != 0); + ASSERT (StrSize (SecondString) != 0); + + while ((*FirstString != L'\0') && + (*SecondString != L'\0') && + (*FirstString == *SecondString) && + (Length > 1)) { + FirstString++; + SecondString++; + Length--; + } + + return *FirstString - *SecondString; +} + +VOID * +AllocateCopyPool ( + UINTN AllocationSize, + CONST VOID *Buffer + ) +{ + return InternalAllocateCopyPool (AllocationSize, Buffer); +} + +INTN +StrCmp ( + CONST CHAR16 *FirstString, + CONST CHAR16 *SecondString + ) +{ + // + // ASSERT both strings are less long than PcdMaximumUnicodeStringLength + // + ASSERT (StrSize (FirstString) != 0); + ASSERT (StrSize (SecondString) != 0); + + while ((*FirstString != L'\0') && (*FirstString == *SecondString)) { + FirstString++; + SecondString++; + } + return *FirstString - *SecondString; +} + +UINT64 +SwapBytes64 ( + UINT64 Value + ) +{ + return InternalMathSwapBytes64 (Value); +} + +UINT64 +InternalMathSwapBytes64 ( + UINT64 Operand + ) +{ + UINT64 LowerBytes; + UINT64 HigherBytes; + + LowerBytes = (UINT64) SwapBytes32 ((UINT32) Operand); + HigherBytes = (UINT64) SwapBytes32 ((UINT32) (Operand >> 32)); + + return (LowerBytes << 32 | HigherBytes); +} + +RETURN_STATUS +StrToIpv4Address ( + CONST CHAR16 *String, + CHAR16 **EndPointer, + EFI_IPv4_ADDRESS *Address, + UINT8 *PrefixLength + ) +{ + RETURN_STATUS Status; + UINTN AddressIndex; + UINT64 Uint64; + EFI_IPv4_ADDRESS LocalAddress; + UINT8 LocalPrefixLength; + CHAR16 *Pointer; + + LocalPrefixLength = MAX_UINT8; + LocalAddress.Addr[0] = 0; + + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. None of String or Guid shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER); + + for (Pointer = (CHAR16 *) String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) { + if (!InternalIsDecimalDigitCharacter (*Pointer)) { + // + // D or P contains invalid characters. + // + break; + } + + // + // Get D or P. + // + Status = StrDecimalToUint64S ((CONST CHAR16 *) Pointer, &Pointer, &Uint64); + if (RETURN_ERROR (Status)) { + return RETURN_UNSUPPORTED; + } + if (AddressIndex == ARRAY_SIZE (Address->Addr)) { + // + // It's P. + // + if (Uint64 > 32) { + return RETURN_UNSUPPORTED; + } + LocalPrefixLength = (UINT8) Uint64; + } else { + // + // It's D. + // + if (Uint64 > MAX_UINT8) { + return RETURN_UNSUPPORTED; + } + LocalAddress.Addr[AddressIndex] = (UINT8) Uint64; + AddressIndex++; + } + + // + // Check the '.' or '/', depending on the AddressIndex. + // + if (AddressIndex == ARRAY_SIZE (Address->Addr)) { + if (*Pointer == L'/') { + // + // '/P' is in the String. + // Skip "/" and get P in next loop. + // + Pointer++; + } else { + // + // '/P' is not in the String. + // + break; + } + } else if (AddressIndex < ARRAY_SIZE (Address->Addr)) { + if (*Pointer == L'.') { + // + // D should be followed by '.' + // + Pointer++; + } else { + return RETURN_UNSUPPORTED; + } + } + } + + if (AddressIndex < ARRAY_SIZE (Address->Addr)) { + return RETURN_UNSUPPORTED; + } + + memcpy (Address, &LocalAddress, sizeof (*Address)); + if (PrefixLength != NULL) { + *PrefixLength = LocalPrefixLength; + } + if (EndPointer != NULL) { + *EndPointer = Pointer; + } + + return RETURN_SUCCESS; +} + +RETURN_STATUS +StrToIpv6Address ( + CONST CHAR16 *String, + CHAR16 **EndPointer, + EFI_IPv6_ADDRESS *Address, + UINT8 *PrefixLength + ) +{ + RETURN_STATUS Status; + UINTN AddressIndex; + UINT64 Uint64; + EFI_IPv6_ADDRESS LocalAddress; + UINT8 LocalPrefixLength; + CONST CHAR16 *Pointer; + CHAR16 *End; + UINTN CompressStart; + BOOLEAN ExpectPrefix; + + LocalPrefixLength = MAX_UINT8; + CompressStart = ARRAY_SIZE (Address->Addr); + ExpectPrefix = FALSE; + + ASSERT (((UINTN) String & BIT0) == 0); + + // + // 1. None of String or Guid shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((String != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Address != NULL), RETURN_INVALID_PARAMETER); + + for (Pointer = String, AddressIndex = 0; AddressIndex < ARRAY_SIZE (Address->Addr) + 1;) { + if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) { + if (*Pointer != L':') { + // + // ":" or "/" should be followed by digit characters. + // + return RETURN_UNSUPPORTED; + } + + // + // Meet second ":" after previous ":" or "/" + // or meet first ":" in the beginning of String. + // + if (ExpectPrefix) { + // + // ":" shall not be after "/" + // + return RETURN_UNSUPPORTED; + } + + if (CompressStart != ARRAY_SIZE (Address->Addr) || AddressIndex == ARRAY_SIZE (Address->Addr)) { + // + // "::" can only appear once. + // "::" can only appear when address is not full length. + // + return RETURN_UNSUPPORTED; + } else { + // + // Remember the start of zero compressing. + // + CompressStart = AddressIndex; + Pointer++; + + if (CompressStart == 0) { + if (*Pointer != L':') { + // + // Single ":" shall not be in the beginning of String. + // + return RETURN_UNSUPPORTED; + } + Pointer++; + } + } + } + + if (!InternalIsHexaDecimalDigitCharacter (*Pointer)) { + if (*Pointer == L'/') { + // + // Might be optional "/P" after "::". + // + if (CompressStart != AddressIndex) { + return RETURN_UNSUPPORTED; + } + } else { + break; + } + } else { + if (!ExpectPrefix) { + // + // Get X. + // + Status = StrHexToUint64S (Pointer, &End, &Uint64); + if (RETURN_ERROR (Status) || End - Pointer > 4) { + // + // Number of hexadecimal digit characters is no more than 4. + // + return RETURN_UNSUPPORTED; + } + Pointer = End; + // + // Uint64 won't exceed MAX_UINT16 if number of hexadecimal digit characters is no more than 4. + // + ASSERT (AddressIndex + 1 < ARRAY_SIZE (Address->Addr)); + LocalAddress.Addr[AddressIndex] = (UINT8) ((UINT16) Uint64 >> 8); + LocalAddress.Addr[AddressIndex + 1] = (UINT8) Uint64; + AddressIndex += 2; + } else { + // + // Get P, then exit the loop. + // + Status = StrDecimalToUint64S (Pointer, &End, &Uint64); + if (RETURN_ERROR (Status) || End == Pointer || Uint64 > 128) { + // + // Prefix length should not exceed 128. + // + return RETURN_UNSUPPORTED; + } + LocalPrefixLength = (UINT8) Uint64; + Pointer = End; + break; + } + } + + // + // Skip ':' or "/" + // + if (*Pointer == L'/') { + ExpectPrefix = TRUE; + } else if (*Pointer == L':') { + if (AddressIndex == ARRAY_SIZE (Address->Addr)) { + // + // Meet additional ":" after all 8 16-bit address + // + break; + } + } else { + // + // Meet other character that is not "/" or ":" after all 8 16-bit address + // + break; + } + Pointer++; + } + + if ((AddressIndex == ARRAY_SIZE (Address->Addr) && CompressStart != ARRAY_SIZE (Address->Addr)) || + (AddressIndex != ARRAY_SIZE (Address->Addr) && CompressStart == ARRAY_SIZE (Address->Addr)) + ) { + // + // Full length of address shall not have compressing zeros. + // Non-full length of address shall have compressing zeros. + // + return RETURN_UNSUPPORTED; + } + memcpy (&Address->Addr[0], &LocalAddress.Addr[0], CompressStart); + if (AddressIndex > CompressStart) { + memset (&Address->Addr[CompressStart], 0, ARRAY_SIZE (Address->Addr) - AddressIndex); + memcpy ( + &Address->Addr[CompressStart + ARRAY_SIZE (Address->Addr) - AddressIndex], + &LocalAddress.Addr[CompressStart], + AddressIndex - CompressStart + ); + } + + if (PrefixLength != NULL) { + *PrefixLength = LocalPrefixLength; + } + if (EndPointer != NULL) { + *EndPointer = (CHAR16 *) Pointer; + } + + return RETURN_SUCCESS; +} + + +RETURN_STATUS +UnicodeStrToAsciiStrS ( + CONST CHAR16 *Source, + CHAR8 *Destination, + UINTN DestMax + ) +{ + UINTN SourceLen; + + ASSERT (((UINTN) Source & BIT0) == 0); + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. DestMax shall not be greater than ASCII_RSIZE_MAX or RSIZE_MAX. + // + if (ASCII_RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= ASCII_RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. DestMax shall be greater than StrnLenS (Source, DestMax). + // + SourceLen = StrnLenS (Source, DestMax); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + + // + // 5. Copying shall not take place between objects that overlap. + // + SAFE_STRING_CONSTRAINT_CHECK (!InternalSafeStringIsOverlap (Destination, DestMax, (VOID *)Source, (SourceLen + 1) * sizeof(CHAR16)), RETURN_ACCESS_DENIED); + + // + // convert string + // + while (*Source != '\0') { + // + // If any Unicode characters in Source contain + // non-zero value in the upper 8 bits, then ASSERT(). + // + ASSERT (*Source < 0x100); + *(Destination++) = (CHAR8) *(Source++); + } + *Destination = '\0'; + + return RETURN_SUCCESS; +} + +RETURN_STATUS +StrCpyS ( + CHAR16 *Destination, + UINTN DestMax, + CONST CHAR16 *Source + ) +{ + UINTN SourceLen; + + ASSERT (((UINTN) Destination & BIT0) == 0); + ASSERT (((UINTN) Source & BIT0) == 0); + + // + // 1. Neither Destination nor Source shall be a null pointer. + // + SAFE_STRING_CONSTRAINT_CHECK ((Destination != NULL), RETURN_INVALID_PARAMETER); + SAFE_STRING_CONSTRAINT_CHECK ((Source != NULL), RETURN_INVALID_PARAMETER); + + // + // 2. DestMax shall not be greater than RSIZE_MAX. + // + if (RSIZE_MAX != 0) { + SAFE_STRING_CONSTRAINT_CHECK ((DestMax <= RSIZE_MAX), RETURN_INVALID_PARAMETER); + } + + // + // 3. DestMax shall not equal zero. + // + SAFE_STRING_CONSTRAINT_CHECK ((DestMax != 0), RETURN_INVALID_PARAMETER); + + // + // 4. DestMax shall be greater than StrnLenS(Source, DestMax). + // + SourceLen = StrnLenS (Source, DestMax); + SAFE_STRING_CONSTRAINT_CHECK ((DestMax > SourceLen), RETURN_BUFFER_TOO_SMALL); + + // + // 5. Copying shall not take place between objects that overlap. + // + SAFE_STRING_CONSTRAINT_CHECK (InternalSafeStringNoStrOverlap (Destination, DestMax, (CHAR16 *)Source, SourceLen + 1), RETURN_ACCESS_DENIED); + + // + // The StrCpyS function copies the string pointed to by Source (including the terminating + // null character) into the array pointed to by Destination. + // + while (*Source != 0) { + *(Destination++) = *(Source++); + } + *Destination = 0; + + return RETURN_SUCCESS; +} + +VOID * +AllocateZeroPool ( + UINTN AllocationSize + ) +{ + VOID * Memory; + Memory = malloc(AllocationSize); + ASSERT (Memory != NULL); + if (Memory == NULL) { + fprintf(stderr, "Not memory for malloc\n"); + } + memset(Memory, 0, AllocationSize); + return Memory; +} + +VOID * +AllocatePool ( + UINTN AllocationSize + ) +{ + return InternalAllocatePool (AllocationSize); +} + +UINT16 +WriteUnaligned16 ( + UINT16 *Buffer, + UINT16 Value + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer = Value; +} + +UINT16 +ReadUnaligned16 ( + CONST UINT16 *Buffer + ) +{ + ASSERT (Buffer != NULL); + + return *Buffer; +} +/** + Return whether the integer string is a hex string. + + @param Str The integer string + + @retval TRUE Hex string + @retval FALSE Decimal string + +**/ +BOOLEAN +IsHexStr ( + CHAR16 *Str + ) +{ + // + // skip preceding white space + // + while ((*Str != 0) && *Str == L' ') { + Str ++; + } + // + // skip preceding zeros + // + while ((*Str != 0) && *Str == L'0') { + Str ++; + } + + return (BOOLEAN) (*Str == L'x' || *Str == L'X'); +} + +/** + + Convert integer string to uint. + + @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal. + + @return A UINTN value represented by Str + +**/ +UINTN +Strtoi ( + CHAR16 *Str + ) +{ + if (IsHexStr (Str)) { + return (UINTN)StrHexToUint64 (Str); + } else { + return (UINTN)StrDecimalToUint64 (Str); + } +} + +/** + + Convert integer string to 64 bit data. + + @param Str The integer string. If leading with "0x" or "0X", it's hexadecimal. + @param Data A pointer to the UINT64 value represented by Str + +**/ +VOID +Strtoi64 ( + CHAR16 *Str, + UINT64 *Data + ) +{ + if (IsHexStr (Str)) { + *Data = StrHexToUint64 (Str); + } else { + *Data = StrDecimalToUint64 (Str); + } +} + +/** + Converts a Unicode string to ASCII string. + + @param Str The equivalent Unicode string + @param AsciiStr On input, it points to destination ASCII string buffer; on output, it points + to the next ASCII string next to it + +**/ +VOID +StrToAscii ( + CHAR16 *Str, + CHAR8 **AsciiStr + ) +{ + CHAR8 *Dest; + + Dest = *AsciiStr; + while (!IS_NULL (*Str)) { + *(Dest++) = (CHAR8) *(Str++); + } + *Dest = 0; + + // + // Return the string next to it + // + *AsciiStr = Dest + 1; +} + +/** + Gets current sub-string from a string list, before return + the list header is moved to next sub-string. The sub-string is separated + by the specified character. For example, the separator is ',', the string + list is "2,0,3", it returns "2", the remain list move to "0,3" + + @param List A string list separated by the specified separator + @param Separator The separator character + + @return A pointer to the current sub-string + +**/ +CHAR16 * +SplitStr ( + CHAR16 **List, + CHAR16 Separator + ) +{ + CHAR16 *Str; + CHAR16 *ReturnStr; + + Str = *List; + ReturnStr = Str; + + if (IS_NULL (*Str)) { + return ReturnStr; + } + + // + // Find first occurrence of the separator + // + while (!IS_NULL (*Str)) { + if (*Str == Separator) { + break; + } + Str++; + } + + if (*Str == Separator) { + // + // Find a sub-string, terminate it + // + *Str = L'\0'; + Str++; + } + + // + // Move to next sub-string + // + *List = Str; + return ReturnStr; +} + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.h new file mode 100644 index 00000000..2fa4b576 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/CommonLib.h @@ -0,0 +1,469 @@ +/** @file +Common library assistance routines. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_COMMON_LIB_H +#define _EFI_COMMON_LIB_H + +#include +#include +#include +#ifndef _WIN32 +#include +#endif + +#define PRINTED_GUID_BUFFER_SIZE 37 // including null-termination + +#ifdef PATH_MAX +#define MAX_LONG_FILE_PATH PATH_MAX +#else +#define MAX_LONG_FILE_PATH 500 +#endif + +#define MAX_UINT64 ((UINT64)0xFFFFFFFFFFFFFFFFULL) +#define MAX_UINT32 ((UINT32)0xFFFFFFFF) +#define MAX_UINT16 ((UINT16)0xFFFF) +#define MAX_UINT8 ((UINT8)0xFF) +#define ARRAY_SIZE(Array) (sizeof (Array) / sizeof ((Array)[0])) +#define ASCII_RSIZE_MAX 1000000 +#undef RSIZE_MAX +#define RSIZE_MAX 1000000 + +#define IS_COMMA(a) ((a) == L',') +#define IS_HYPHEN(a) ((a) == L'-') +#define IS_DOT(a) ((a) == L'.') +#define IS_LEFT_PARENTH(a) ((a) == L'(') +#define IS_RIGHT_PARENTH(a) ((a) == L')') +#define IS_SLASH(a) ((a) == L'/') +#define IS_NULL(a) ((a) == L'\0') + +#define ASSERT(x) assert(x) + +#ifdef __cplusplus +extern "C" { +#endif + +// +// Function declarations +// +VOID +PeiZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +; + +VOID +PeiCopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +; + +VOID +ZeroMem ( + IN VOID *Buffer, + IN UINTN Size + ) +; + +VOID +CopyMem ( + IN VOID *Destination, + IN VOID *Source, + IN UINTN Length + ) +; + +INTN +CompareGuid ( + IN EFI_GUID *Guid1, + IN EFI_GUID *Guid2 + ) +; + +EFI_STATUS +GetFileImage ( + IN CHAR8 *InputFileName, + OUT CHAR8 **InputFileImage, + OUT UINT32 *BytesRead + ) +; + +EFI_STATUS +PutFileImage ( + IN CHAR8 *OutputFileName, + IN CHAR8 *OutputFileImage, + IN UINT32 BytesToWrite + ) +; +/*++ + +Routine Description: + + This function opens a file and writes OutputFileImage into the file. + +Arguments: + + OutputFileName The name of the file to write. + OutputFileImage A pointer to the memory buffer. + BytesToWrite The size of the memory buffer. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED An error occurred. + EFI_OUT_OF_RESOURCES No resource to complete operations. + +**/ + +UINT8 +CalculateChecksum8 ( + IN UINT8 *Buffer, + IN UINTN Size + ) +; + +UINT8 +CalculateSum8 ( + IN UINT8 *Buffer, + IN UINTN Size + ) +; + +UINT16 +CalculateChecksum16 ( + IN UINT16 *Buffer, + IN UINTN Size + ) +; + +UINT16 +CalculateSum16 ( + IN UINT16 *Buffer, + IN UINTN Size + ) +; + +EFI_STATUS +PrintGuid ( + IN EFI_GUID *Guid + ) +; + +#define PRINTED_GUID_BUFFER_SIZE 37 // including null-termination +EFI_STATUS +PrintGuidToBuffer ( + IN EFI_GUID *Guid, + IN OUT UINT8 *Buffer, + IN UINT32 BufferLen, + IN BOOLEAN Uppercase + ) +; + +CHAR8 * +LongFilePath ( + IN CHAR8 *FileName +); + +UINTN +StrLen ( + CONST CHAR16 *String + ); + +VOID * +AllocateCopyPool ( + UINTN AllocationSize, + CONST VOID *Buffer + ); + +INTN +StrnCmp ( + CONST CHAR16 *FirstString, + CONST CHAR16 *SecondString, + UINTN Length + ); + +RETURN_STATUS +StrToGuid ( + CONST CHAR16 *String, + EFI_GUID *Guid + ); + +RETURN_STATUS +StrHexToBytes ( + CONST CHAR16 *String, + UINTN Length, + UINT8 *Buffer, + UINTN MaxBufferSize + ); + +UINTN +InternalHexCharToUintn ( + CHAR16 Char + ); + +VOID * +InternalAllocateCopyPool ( + UINTN AllocationSize, + CONST VOID *Buffer + ); + +BOOLEAN +InternalIsDecimalDigitCharacter ( + CHAR16 Char + ); + +UINT32 +SwapBytes32 ( + UINT32 Value + ); + +UINT16 +SwapBytes16 ( + UINT16 Value + ); + +EFI_GUID * +CopyGuid ( + EFI_GUID *DestinationGuid, + CONST EFI_GUID *SourceGuid + ); + +UINT64 +WriteUnaligned64 ( + UINT64 *Buffer, + UINT64 Value + ); + +UINT64 +ReadUnaligned64 ( + CONST UINT64 *Buffer + ); + +UINTN +StrSize ( + CONST CHAR16 *String + ); + +UINT64 +StrHexToUint64 ( + CONST CHAR16 *String + ); + +UINT64 +StrDecimalToUint64 ( + CONST CHAR16 *String + ); + +RETURN_STATUS +StrHexToUint64S ( + CONST CHAR16 *String, + CHAR16 **EndPointer, + UINT64 *Data + ); + +RETURN_STATUS +StrDecimalToUint64S ( + CONST CHAR16 *String, + CHAR16 **EndPointer, OPTIONAL + UINT64 *Data + ); + +VOID * +ReallocatePool ( + UINTN OldSize, + UINTN NewSize, + VOID *OldBuffer OPTIONAL + ); + +VOID * +InternalReallocatePool ( + UINTN OldSize, + UINTN NewSize, + VOID *OldBuffer OPTIONAL + ); + +VOID * +InternalAllocateZeroPool ( + UINTN AllocationSize + ) ; + +VOID * +InternalAllocatePool ( + UINTN AllocationSize + ); + +UINTN +StrnLenS ( + CONST CHAR16 *String, + UINTN MaxSize + ); + +CHAR16 +InternalCharToUpper ( + CHAR16 Char + ); + +INTN +StrCmp ( + CONST CHAR16 *FirstString, + CONST CHAR16 *SecondString + ); + +UINT64 +SwapBytes64 ( + UINT64 Value + ); + +UINT64 +InternalMathSwapBytes64 ( + UINT64 Operand + ); + +RETURN_STATUS +StrToIpv4Address ( + CONST CHAR16 *String, + CHAR16 **EndPointer, + EFI_IPv4_ADDRESS *Address, + UINT8 *PrefixLength + ); + +RETURN_STATUS +StrToIpv6Address ( + CONST CHAR16 *String, + CHAR16 **EndPointer, + EFI_IPv6_ADDRESS *Address, + UINT8 *PrefixLength + ); + +RETURN_STATUS +StrCpyS ( + CHAR16 *Destination, + UINTN DestMax, + CONST CHAR16 *Source + ); + +RETURN_STATUS +UnicodeStrToAsciiStrS ( + CONST CHAR16 *Source, + CHAR8 *Destination, + UINTN DestMax + ); +VOID * +AllocatePool ( + UINTN AllocationSize + ); + +UINT16 +WriteUnaligned16 ( + UINT16 *Buffer, + UINT16 Value + ); + +UINT16 +ReadUnaligned16 ( + CONST UINT16 *Buffer + ); + +VOID * +AllocateZeroPool ( + UINTN AllocationSize + ); + +BOOLEAN +InternalIsHexaDecimalDigitCharacter ( + CHAR16 Char + ); + +BOOLEAN +InternalSafeStringIsOverlap ( + IN VOID *Base1, + IN UINTN Size1, + IN VOID *Base2, + IN UINTN Size2 + ); + +BOOLEAN +InternalSafeStringNoStrOverlap ( + IN CHAR16 *Str1, + IN UINTN Size1, + IN CHAR16 *Str2, + IN UINTN Size2 + ); + +BOOLEAN +IsHexStr ( + CHAR16 *Str + ); + +UINTN +Strtoi ( + CHAR16 *Str + ); + +VOID +Strtoi64 ( + CHAR16 *Str, + UINT64 *Data + ); + +VOID +StrToAscii ( + CHAR16 *Str, + CHAR8 **AsciiStr + ); + +CHAR16 * +SplitStr ( + CHAR16 **List, + CHAR16 Separator + ); + +/*++ + +Routine Description: + Convert FileName to the long file path, which can support larger than 260 length. + +Arguments: + FileName - FileName. + +Returns: + LongFilePath A pointer to the converted long file path. + +--*/ + +#ifdef __cplusplus +} +#endif + +#ifdef __GNUC__ +#include +#include +#define stricmp strcasecmp +#define _stricmp strcasecmp +#define strnicmp strncasecmp +#define strcmpi strcasecmp +size_t _filelength(int fd); +#ifndef __CYGWIN__ +char *strlwr(char *s); +#endif +#endif + +// +// On windows, mkdir only has one parameter. +// On unix, it has two parameters +// +#if defined(__GNUC__) +#define mkdir(dir, perm) mkdir(dir, perm) +#else +#define mkdir(dir, perm) mkdir(dir) +#endif + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Compress.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Compress.h new file mode 100644 index 00000000..bacc8183 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Compress.h @@ -0,0 +1,82 @@ +/** @file +Header file for compression routine. +Providing both EFI and Tiano Compress algorithms. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _COMPRESS_H_ +#define _COMPRESS_H_ + +#include +#include + +#include "CommonLib.h" +#include +/*++ + +Routine Description: + + Tiano compression routine. + +--*/ +EFI_STATUS +TianoCompress ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ) +; + +/*++ + +Routine Description: + + Efi compression routine. + +--*/ +EFI_STATUS +EfiCompress ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ) +; + +/*++ + +Routine Description: + + The compression routine. + +Arguments: + + SrcBuffer - The buffer storing the source data + SrcSize - The size of source data + DstBuffer - The buffer to store the compressed data + DstSize - On input, the size of DstBuffer; On output, + the size of the actual compressed data. + +Returns: + + EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case, + DstSize contains the size needed. + EFI_SUCCESS - Compression is successful. + EFI_OUT_OF_RESOURCES - No resource to complete function. + EFI_INVALID_PARAMETER - Parameter supplied is wrong. + +--*/ +typedef +EFI_STATUS +(*COMPRESS_FUNCTION) ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Crc32.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Crc32.c new file mode 100644 index 00000000..df823283 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Crc32.c @@ -0,0 +1,313 @@ +/** @file +CalculateCrc32 routine. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include "Crc32.h" + +UINT32 mCrcTable[256] = { + 0x00000000, + 0x77073096, + 0xEE0E612C, + 0x990951BA, + 0x076DC419, + 0x706AF48F, + 0xE963A535, + 0x9E6495A3, + 0x0EDB8832, + 0x79DCB8A4, + 0xE0D5E91E, + 0x97D2D988, + 0x09B64C2B, + 0x7EB17CBD, + 0xE7B82D07, + 0x90BF1D91, + 0x1DB71064, + 0x6AB020F2, + 0xF3B97148, + 0x84BE41DE, + 0x1ADAD47D, + 0x6DDDE4EB, + 0xF4D4B551, + 0x83D385C7, + 0x136C9856, + 0x646BA8C0, + 0xFD62F97A, + 0x8A65C9EC, + 0x14015C4F, + 0x63066CD9, + 0xFA0F3D63, + 0x8D080DF5, + 0x3B6E20C8, + 0x4C69105E, + 0xD56041E4, + 0xA2677172, + 0x3C03E4D1, + 0x4B04D447, + 0xD20D85FD, + 0xA50AB56B, + 0x35B5A8FA, + 0x42B2986C, + 0xDBBBC9D6, + 0xACBCF940, + 0x32D86CE3, + 0x45DF5C75, + 0xDCD60DCF, + 0xABD13D59, + 0x26D930AC, + 0x51DE003A, + 0xC8D75180, + 0xBFD06116, + 0x21B4F4B5, + 0x56B3C423, + 0xCFBA9599, + 0xB8BDA50F, + 0x2802B89E, + 0x5F058808, + 0xC60CD9B2, + 0xB10BE924, + 0x2F6F7C87, + 0x58684C11, + 0xC1611DAB, + 0xB6662D3D, + 0x76DC4190, + 0x01DB7106, + 0x98D220BC, + 0xEFD5102A, + 0x71B18589, + 0x06B6B51F, + 0x9FBFE4A5, + 0xE8B8D433, + 0x7807C9A2, + 0x0F00F934, + 0x9609A88E, + 0xE10E9818, + 0x7F6A0DBB, + 0x086D3D2D, + 0x91646C97, + 0xE6635C01, + 0x6B6B51F4, + 0x1C6C6162, + 0x856530D8, + 0xF262004E, + 0x6C0695ED, + 0x1B01A57B, + 0x8208F4C1, + 0xF50FC457, + 0x65B0D9C6, + 0x12B7E950, + 0x8BBEB8EA, + 0xFCB9887C, + 0x62DD1DDF, + 0x15DA2D49, + 0x8CD37CF3, + 0xFBD44C65, + 0x4DB26158, + 0x3AB551CE, + 0xA3BC0074, + 0xD4BB30E2, + 0x4ADFA541, + 0x3DD895D7, + 0xA4D1C46D, + 0xD3D6F4FB, + 0x4369E96A, + 0x346ED9FC, + 0xAD678846, + 0xDA60B8D0, + 0x44042D73, + 0x33031DE5, + 0xAA0A4C5F, + 0xDD0D7CC9, + 0x5005713C, + 0x270241AA, + 0xBE0B1010, + 0xC90C2086, + 0x5768B525, + 0x206F85B3, + 0xB966D409, + 0xCE61E49F, + 0x5EDEF90E, + 0x29D9C998, + 0xB0D09822, + 0xC7D7A8B4, + 0x59B33D17, + 0x2EB40D81, + 0xB7BD5C3B, + 0xC0BA6CAD, + 0xEDB88320, + 0x9ABFB3B6, + 0x03B6E20C, + 0x74B1D29A, + 0xEAD54739, + 0x9DD277AF, + 0x04DB2615, + 0x73DC1683, + 0xE3630B12, + 0x94643B84, + 0x0D6D6A3E, + 0x7A6A5AA8, + 0xE40ECF0B, + 0x9309FF9D, + 0x0A00AE27, + 0x7D079EB1, + 0xF00F9344, + 0x8708A3D2, + 0x1E01F268, + 0x6906C2FE, + 0xF762575D, + 0x806567CB, + 0x196C3671, + 0x6E6B06E7, + 0xFED41B76, + 0x89D32BE0, + 0x10DA7A5A, + 0x67DD4ACC, + 0xF9B9DF6F, + 0x8EBEEFF9, + 0x17B7BE43, + 0x60B08ED5, + 0xD6D6A3E8, + 0xA1D1937E, + 0x38D8C2C4, + 0x4FDFF252, + 0xD1BB67F1, + 0xA6BC5767, + 0x3FB506DD, + 0x48B2364B, + 0xD80D2BDA, + 0xAF0A1B4C, + 0x36034AF6, + 0x41047A60, + 0xDF60EFC3, + 0xA867DF55, + 0x316E8EEF, + 0x4669BE79, + 0xCB61B38C, + 0xBC66831A, + 0x256FD2A0, + 0x5268E236, + 0xCC0C7795, + 0xBB0B4703, + 0x220216B9, + 0x5505262F, + 0xC5BA3BBE, + 0xB2BD0B28, + 0x2BB45A92, + 0x5CB36A04, + 0xC2D7FFA7, + 0xB5D0CF31, + 0x2CD99E8B, + 0x5BDEAE1D, + 0x9B64C2B0, + 0xEC63F226, + 0x756AA39C, + 0x026D930A, + 0x9C0906A9, + 0xEB0E363F, + 0x72076785, + 0x05005713, + 0x95BF4A82, + 0xE2B87A14, + 0x7BB12BAE, + 0x0CB61B38, + 0x92D28E9B, + 0xE5D5BE0D, + 0x7CDCEFB7, + 0x0BDBDF21, + 0x86D3D2D4, + 0xF1D4E242, + 0x68DDB3F8, + 0x1FDA836E, + 0x81BE16CD, + 0xF6B9265B, + 0x6FB077E1, + 0x18B74777, + 0x88085AE6, + 0xFF0F6A70, + 0x66063BCA, + 0x11010B5C, + 0x8F659EFF, + 0xF862AE69, + 0x616BFFD3, + 0x166CCF45, + 0xA00AE278, + 0xD70DD2EE, + 0x4E048354, + 0x3903B3C2, + 0xA7672661, + 0xD06016F7, + 0x4969474D, + 0x3E6E77DB, + 0xAED16A4A, + 0xD9D65ADC, + 0x40DF0B66, + 0x37D83BF0, + 0xA9BCAE53, + 0xDEBB9EC5, + 0x47B2CF7F, + 0x30B5FFE9, + 0xBDBDF21C, + 0xCABAC28A, + 0x53B39330, + 0x24B4A3A6, + 0xBAD03605, + 0xCDD70693, + 0x54DE5729, + 0x23D967BF, + 0xB3667A2E, + 0xC4614AB8, + 0x5D681B02, + 0x2A6F2B94, + 0xB40BBE37, + 0xC30C8EA1, + 0x5A05DF1B, + 0x2D02EF8D +}; + +EFI_STATUS +CalculateCrc32 ( + IN UINT8 *Data, + IN UINTN DataSize, + IN OUT UINT32 *CrcOut + ) +/*++ + +Routine Description: + + The CalculateCrc32 routine. + +Arguments: + + Data - The buffer containing the data to be processed + DataSize - The size of data to be processed + CrcOut - A pointer to the caller allocated UINT32 that on + contains the CRC32 checksum of Data + +Returns: + + EFI_SUCCESS - Calculation is successful. + EFI_INVALID_PARAMETER - Data / CrcOut = NULL, or DataSize = 0 + +--*/ +{ + UINT32 Crc; + UINTN Index; + UINT8 *Ptr; + + if ((DataSize == 0) || (Data == NULL) || (CrcOut == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Crc = 0xffffffff; + for (Index = 0, Ptr = Data; Index < DataSize; Index++, Ptr++) { + Crc = (Crc >> 8) ^ mCrcTable[(UINT8) Crc ^ *Ptr]; + } + + *CrcOut = Crc ^ 0xffffffff; + + return EFI_SUCCESS; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Crc32.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Crc32.h new file mode 100644 index 00000000..a8c855c4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Crc32.h @@ -0,0 +1,41 @@ +/** @file +Header file for CalculateCrc32 routine + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _CRC32_H +#define _CRC32_H + +#include + +EFI_STATUS +CalculateCrc32 ( + IN UINT8 *Data, + IN UINTN DataSize, + IN OUT UINT32 *CrcOut + ) +/*++ + +Routine Description: + + The CalculateCrc32 routine. + +Arguments: + + Data - The buffer containing the data to be processed + DataSize - The size of data to be processed + CrcOut - A pointer to the caller allocated UINT32 that on + contains the CRC32 checksum of Data + +Returns: + + EFI_SUCCESS - Calculation is successful. + EFI_INVALID_PARAMETER - Data / CrcOut = NULL, or DataSize = 0 + +--*/ +; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Decompress.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Decompress.c new file mode 100644 index 00000000..e494437a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Decompress.c @@ -0,0 +1,1014 @@ +/** @file +Decompressor. Algorithm Ported from OPSD code (Decomp.asm) for Efi and Tiano +compress algorithm. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +--*/ + +#include +#include +#include +#include "Decompress.h" + +// +// Decompression algorithm begins here +// +#define BITBUFSIZ 32 +#define MAXMATCH 256 +#define THRESHOLD 3 +#define CODE_BIT 16 +#define BAD_TABLE - 1 + +// +// C: Char&Len Set; P: Position Set; T: exTra Set +// +#define NC (0xff + MAXMATCH + 2 - THRESHOLD) +#define CBIT 9 +#define EFIPBIT 4 +#define MAXPBIT 5 +#define TBIT 5 +#define MAXNP ((1U << MAXPBIT) - 1) +#define NT (CODE_BIT + 3) +#if NT > MAXNP +#define NPT NT +#else +#define NPT MAXNP +#endif + +typedef struct { + UINT8 *mSrcBase; // Starting address of compressed data + UINT8 *mDstBase; // Starting address of decompressed data + UINT32 mOutBuf; + UINT32 mInBuf; + + UINT16 mBitCount; + UINT32 mBitBuf; + UINT32 mSubBitBuf; + UINT16 mBlockSize; + UINT32 mCompSize; + UINT32 mOrigSize; + + UINT16 mBadTableFlag; + + UINT16 mLeft[2 * NC - 1]; + UINT16 mRight[2 * NC - 1]; + UINT8 mCLen[NC]; + UINT8 mPTLen[NPT]; + UINT16 mCTable[4096]; + UINT16 mPTTable[256]; +} SCRATCH_DATA; + +STATIC UINT16 mPbit = EFIPBIT; + +STATIC +VOID +FillBuf ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +/*++ + +Routine Description: + + Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source. + +Arguments: + + Sd - The global scratch data + NumOfBit - The number of bits to shift and read. + +Returns: (VOID) + +--*/ +{ + Sd->mBitBuf = (UINT32) (((UINT64)Sd->mBitBuf) << NumOfBits); + + while (NumOfBits > Sd->mBitCount) { + + Sd->mBitBuf |= (UINT32) (((UINT64)Sd->mSubBitBuf) << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount))); + + if (Sd->mCompSize > 0) { + // + // Get 1 byte into SubBitBuf + // + Sd->mCompSize--; + Sd->mSubBitBuf = 0; + Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++]; + Sd->mBitCount = 8; + + } else { + // + // No more bits from the source, just pad zero bit. + // + Sd->mSubBitBuf = 0; + Sd->mBitCount = 8; + + } + } + + Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits); + Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; +} + +STATIC +UINT32 +GetBits ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +/*++ + +Routine Description: + + Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent + NumOfBits of bits from source. Returns NumOfBits of bits that are + popped out. + +Arguments: + + Sd - The global scratch data. + NumOfBits - The number of bits to pop and read. + +Returns: + + The bits that are popped out. + +--*/ +{ + UINT32 OutBits; + + OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); + + FillBuf (Sd, NumOfBits); + + return OutBits; +} + +STATIC +UINT16 +MakeTable ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfChar, + IN UINT8 *BitLen, + IN UINT16 TableBits, + OUT UINT16 *Table + ) +/*++ + +Routine Description: + + Creates Huffman Code mapping table according to code length array. + +Arguments: + + Sd - The global scratch data + NumOfChar - Number of symbols in the symbol set + BitLen - Code length array + TableBits - The width of the mapping table + Table - The table + +Returns: + + 0 - OK. + BAD_TABLE - The table is corrupted. + +--*/ +{ + UINT16 Count[17]; + UINT16 Weight[17]; + UINT16 Start[18]; + UINT16 *Pointer; + UINT16 Index3; + UINT16 Index; + UINT16 Len; + UINT16 Char; + UINT16 JuBits; + UINT16 Avail; + UINT16 NextCode; + UINT16 Mask; + UINT16 MaxTableLength; + + for (Index = 1; Index <= 16; Index++) { + Count[Index] = 0; + } + + for (Index = 0; Index < NumOfChar; Index++) { + if (BitLen[Index] > 16) { + return (UINT16) BAD_TABLE; + } + Count[BitLen[Index]]++; + } + + Start[1] = 0; + + for (Index = 1; Index <= 16; Index++) { + Start[Index + 1] = (UINT16) (Start[Index] + (Count[Index] << (16 - Index))); + } + + if (Start[17] != 0) { + /*(1U << 16)*/ + return (UINT16) BAD_TABLE; + } + + JuBits = (UINT16) (16 - TableBits); + + for (Index = 1; Index <= TableBits; Index++) { + Start[Index] >>= JuBits; + Weight[Index] = (UINT16) (1U << (TableBits - Index)); + } + + while (Index <= 16) { + Weight[Index] = (UINT16) (1U << (16 - Index)); + Index++; + } + + Index = (UINT16) (Start[TableBits + 1] >> JuBits); + + if (Index != 0) { + Index3 = (UINT16) (1U << TableBits); + while (Index != Index3) { + Table[Index++] = 0; + } + } + + Avail = NumOfChar; + Mask = (UINT16) (1U << (15 - TableBits)); + MaxTableLength = (UINT16) (1U << TableBits); + + for (Char = 0; Char < NumOfChar; Char++) { + + Len = BitLen[Char]; + if (Len == 0 || Len >= 17) { + continue; + } + + NextCode = (UINT16) (Start[Len] + Weight[Len]); + + if (Len <= TableBits) { + + if (Start[Len] >= NextCode || NextCode > MaxTableLength){ + return (UINT16) BAD_TABLE; + } + + for (Index = Start[Len]; Index < NextCode; Index++) { + Table[Index] = Char; + } + + } else { + + Index3 = Start[Len]; + Pointer = &Table[Index3 >> JuBits]; + Index = (UINT16) (Len - TableBits); + + while (Index != 0) { + if (*Pointer == 0) { + Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; + *Pointer = Avail++; + } + + if (Index3 & Mask) { + Pointer = &Sd->mRight[*Pointer]; + } else { + Pointer = &Sd->mLeft[*Pointer]; + } + + Index3 <<= 1; + Index--; + } + + *Pointer = Char; + + } + + Start[Len] = NextCode; + } + // + // Succeeds + // + return 0; +} + +STATIC +UINT32 +DecodeP ( + IN SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decodes a position value. + +Arguments: + + Sd - the global scratch data + +Returns: + + The position value decoded. + +--*/ +{ + UINT16 Val; + UINT32 Mask; + UINT32 Pos; + + Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + + if (Val >= MAXNP) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if (Sd->mBitBuf & Mask) { + Val = Sd->mRight[Val]; + } else { + Val = Sd->mLeft[Val]; + } + + Mask >>= 1; + } while (Val >= MAXNP); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[Val]); + + Pos = Val; + if (Val > 1) { + Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1))); + } + + return Pos; +} + +STATIC +UINT16 +ReadPTLen ( + IN SCRATCH_DATA *Sd, + IN UINT16 nn, + IN UINT16 nbit, + IN UINT16 Special + ) +/*++ + +Routine Description: + + Reads code lengths for the Extra Set or the Position Set + +Arguments: + + Sd - The global scratch data + nn - Number of symbols + nbit - Number of bits needed to represent nn + Special - The special symbol that needs to be taken care of + +Returns: + + 0 - OK. + BAD_TABLE - Table is corrupted. + +--*/ +{ + UINT16 Number; + UINT16 CharC; + UINT16 Index; + UINT32 Mask; + + assert (nn <= NPT); + + Number = (UINT16) GetBits (Sd, nbit); + + if (Number == 0) { + CharC = (UINT16) GetBits (Sd, nbit); + + for (Index = 0; Index < 256; Index++) { + Sd->mPTTable[Index] = CharC; + } + + for (Index = 0; Index < nn; Index++) { + Sd->mPTLen[Index] = 0; + } + + return 0; + } + + Index = 0; + + while (Index < Number && Index < NPT) { + + CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3)); + + if (CharC == 7) { + Mask = 1U << (BITBUFSIZ - 1 - 3); + while (Mask & Sd->mBitBuf) { + Mask >>= 1; + CharC += 1; + } + } + + FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3)); + + Sd->mPTLen[Index++] = (UINT8) CharC; + + if (Index == Special) { + CharC = (UINT16) GetBits (Sd, 2); + CharC--; + while ((INT16) (CharC) >= 0 && Index < NPT) { + Sd->mPTLen[Index++] = 0; + CharC--; + } + } + } + + while (Index < nn && Index < NPT) { + Sd->mPTLen[Index++] = 0; + } + + return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); +} + +STATIC +VOID +ReadCLen ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Reads code lengths for Char&Len Set. + +Arguments: + + Sd - the global scratch data + +Returns: (VOID) + +--*/ +{ + UINT16 Number; + UINT16 CharC; + UINT16 Index; + UINT32 Mask; + + Number = (UINT16) GetBits (Sd, CBIT); + + if (Number == 0) { + CharC = (UINT16) GetBits (Sd, CBIT); + + for (Index = 0; Index < NC; Index++) { + Sd->mCLen[Index] = 0; + } + + for (Index = 0; Index < 4096; Index++) { + Sd->mCTable[Index] = CharC; + } + + return ; + } + + Index = 0; + while (Index < Number) { + + CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + if (CharC >= NT) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if (Mask & Sd->mBitBuf) { + CharC = Sd->mRight[CharC]; + } else { + CharC = Sd->mLeft[CharC]; + } + + Mask >>= 1; + + } while (CharC >= NT); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[CharC]); + + if (CharC <= 2) { + + if (CharC == 0) { + CharC = 1; + } else if (CharC == 1) { + CharC = (UINT16) (GetBits (Sd, 4) + 3); + } else if (CharC == 2) { + CharC = (UINT16) (GetBits (Sd, CBIT) + 20); + } + + CharC--; + while ((INT16) (CharC) >= 0) { + Sd->mCLen[Index++] = 0; + CharC--; + } + + } else { + + Sd->mCLen[Index++] = (UINT8) (CharC - 2); + + } + } + + while (Index < NC) { + Sd->mCLen[Index++] = 0; + } + + MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable); + + return ; +} + +STATIC +UINT16 +DecodeC ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decode a character/length value. + +Arguments: + + Sd - The global scratch data. + +Returns: + + The value decoded. + +--*/ +{ + UINT16 Index2; + UINT32 Mask; + + if (Sd->mBlockSize == 0) { + // + // Starting a new block + // + Sd->mBlockSize = (UINT16) GetBits (Sd, 16); + Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3); + if (Sd->mBadTableFlag != 0) { + return 0; + } + + ReadCLen (Sd); + + Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, mPbit, (UINT16) (-1)); + if (Sd->mBadTableFlag != 0) { + return 0; + } + } + + Sd->mBlockSize--; + Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; + + if (Index2 >= NC) { + Mask = 1U << (BITBUFSIZ - 1 - 12); + + do { + if (Sd->mBitBuf & Mask) { + Index2 = Sd->mRight[Index2]; + } else { + Index2 = Sd->mLeft[Index2]; + } + + Mask >>= 1; + } while (Index2 >= NC); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mCLen[Index2]); + + return Index2; +} + +STATIC +VOID +Decode ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decode the source data and put the resulting data into the destination buffer. + +Arguments: + + Sd - The global scratch data + +Returns: (VOID) + + --*/ +{ + UINT16 BytesRemain; + UINT32 DataIdx; + UINT16 CharC; + + BytesRemain = (UINT16) (-1); + + DataIdx = 0; + + for (;;) { + CharC = DecodeC (Sd); + if (Sd->mBadTableFlag != 0) { + return ; + } + + if (CharC < 256) { + // + // Process an Original character + // + Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC; + if (Sd->mOutBuf >= Sd->mOrigSize) { + return ; + } + + } else { + // + // Process a Pointer + // + CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD)); + + BytesRemain = CharC; + + DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1; + + BytesRemain--; + while ((INT16) (BytesRemain) >= 0) { + if (Sd->mOutBuf >= Sd->mOrigSize) { + return ; + } + if (DataIdx >= Sd->mOrigSize) { + Sd->mBadTableFlag = (UINT16) BAD_TABLE; + return ; + } + Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; + + BytesRemain--; + } + // + // Once mOutBuf is fully filled, directly return + // + if (Sd->mOutBuf >= Sd->mOrigSize) { + return ; + } + } + } + + return ; +} + +EFI_STATUS +GetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The implementation of EFI_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + DstSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successfully retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + UINT8 *Src; + UINT32 CompSize; + + *ScratchSize = sizeof (SCRATCH_DATA); + + Src = Source; + if (SrcSize < 8) { + return EFI_INVALID_PARAMETER; + } + + CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); + *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + + if (SrcSize < CompSize + 8 || (CompSize + 8) < 8) { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +Decompress ( + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) +/*++ + +Routine Description: + + The implementation Efi and Tiano Decompress(). + +Arguments: + + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + Destination - The destination buffer to store the decompressed data + DstSize - The size of destination buffer. + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - Decompression is successful + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + UINT32 Index; + UINT32 CompSize; + UINT32 OrigSize; + EFI_STATUS Status; + SCRATCH_DATA *Sd; + UINT8 *Src; + UINT8 *Dst; + + Status = EFI_SUCCESS; + Src = Source; + Dst = Destination; + + if (ScratchSize < sizeof (SCRATCH_DATA)) { + return EFI_INVALID_PARAMETER; + } + + Sd = (SCRATCH_DATA *) Scratch; + + if (SrcSize < 8) { + return EFI_INVALID_PARAMETER; + } + + CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); + OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + + if (SrcSize < CompSize + 8 || (CompSize + 8) < 8) { + return EFI_INVALID_PARAMETER; + } + + if (DstSize != OrigSize) { + return EFI_INVALID_PARAMETER; + } + + Src = Src + 8; + + for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) { + ((UINT8 *) Sd)[Index] = 0; + } + + Sd->mSrcBase = Src; + Sd->mDstBase = Dst; + Sd->mCompSize = CompSize; + Sd->mOrigSize = OrigSize; + + // + // Fill the first BITBUFSIZ bits + // + FillBuf (Sd, BITBUFSIZ); + + // + // Decompress it + // + Decode (Sd); + + if (Sd->mBadTableFlag != 0) { + // + // Something wrong with the source + // + Status = EFI_INVALID_PARAMETER; + } + + return Status; +} + +EFI_STATUS +EfiGetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The implementation Efi Decompress GetInfo(). + +Arguments: + + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + DstSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successfully retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return GetInfo (Source, SrcSize, DstSize, ScratchSize); +} + +EFI_STATUS +TianoGetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The implementation Tiano Decompress GetInfo(). + +Arguments: + + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + DstSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successfully retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return GetInfo (Source, SrcSize, DstSize, ScratchSize); +} + +EFI_STATUS +EfiDecompress ( + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) +/*++ + +Routine Description: + + The implementation of Efi Decompress(). + +Arguments: + + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + Destination - The destination buffer to store the decompressed data + DstSize - The size of destination buffer. + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - Decompression is successful + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + mPbit = EFIPBIT; + return Decompress (Source, SrcSize, Destination, DstSize, Scratch, ScratchSize); +} + +EFI_STATUS +TianoDecompress ( + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ) +/*++ + +Routine Description: + + The implementation of Tiano Decompress(). + +Arguments: + + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + Destination - The destination buffer to store the decompressed data + DstSize - The size of destination buffer. + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - Decompression is successful + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + mPbit = MAXPBIT; + return Decompress (Source, SrcSize, Destination, DstSize, Scratch, ScratchSize); +} + +EFI_STATUS +Extract ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT VOID **Destination, + OUT UINT32 *DstSize, + IN UINTN Algorithm + ) +{ + VOID *Scratch; + UINT32 ScratchSize; + EFI_STATUS Status; + + Scratch = NULL; + Status = EFI_SUCCESS; + + switch (Algorithm) { + case 0: + *Destination = (VOID *)malloc(SrcSize); + if (*Destination != NULL) { + memcpy(*Destination, Source, SrcSize); + } else { + Status = EFI_OUT_OF_RESOURCES; + } + break; + case 1: + Status = EfiGetInfo(Source, SrcSize, DstSize, &ScratchSize); + if (Status == EFI_SUCCESS) { + Scratch = (VOID *)malloc(ScratchSize); + if (Scratch == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + *Destination = (VOID *)malloc(*DstSize); + if (*Destination == NULL) { + free (Scratch); + return EFI_OUT_OF_RESOURCES; + } + + Status = EfiDecompress(Source, SrcSize, *Destination, *DstSize, Scratch, ScratchSize); + } + break; + case 2: + Status = TianoGetInfo(Source, SrcSize, DstSize, &ScratchSize); + if (Status == EFI_SUCCESS) { + Scratch = (VOID *)malloc(ScratchSize); + if (Scratch == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + *Destination = (VOID *)malloc(*DstSize); + if (*Destination == NULL) { + free (Scratch); + return EFI_OUT_OF_RESOURCES; + } + + Status = TianoDecompress(Source, SrcSize, *Destination, *DstSize, Scratch, ScratchSize); + } + break; + default: + Status = EFI_INVALID_PARAMETER; + } + + if (Scratch != NULL) { + free (Scratch); + } + + return Status; +} + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Decompress.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Decompress.h new file mode 100644 index 00000000..2df9a14b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Decompress.h @@ -0,0 +1,159 @@ +/** @file +Header file for compression routine + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_DECOMPRESS_H +#define _EFI_DECOMPRESS_H + +#include + +EFI_STATUS +EfiGetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ); +/** + +Routine Description: + + The implementation Efi Decompress GetInfo(). + +Arguments: + + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + DstSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successfully retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +**/ + +EFI_STATUS +EfiDecompress ( + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ); +/** + +Routine Description: + + The implementation of Efi Decompress(). + +Arguments: + + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + Destination - The destination buffer to store the decompressed data + DstSize - The size of destination buffer. + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - Decompression is successful + EFI_INVALID_PARAMETER - The source data is corrupted + +**/ + +EFI_STATUS +TianoGetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ); +/** + +Routine Description: + + The implementation Tiano Decompress GetInfo(). + +Arguments: + + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + DstSize - The size of destination buffer. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - The size of destination buffer and the size of scratch buffer are successfully retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +**/ + +EFI_STATUS +TianoDecompress ( + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ); +/** + +Routine Description: + + The implementation of Tiano Decompress(). + +Arguments: + + Source - The source buffer containing the compressed data. + SrcSize - The size of source buffer + Destination - The destination buffer to store the decompressed data + DstSize - The size of destination buffer. + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + ScratchSize - The size of scratch buffer. + +Returns: + + EFI_SUCCESS - Decompression is successful + EFI_INVALID_PARAMETER - The source data is corrupted + +**/ + +typedef +EFI_STATUS +(*GETINFO_FUNCTION) ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ); + +typedef +EFI_STATUS +(*DECOMPRESS_FUNCTION) ( + IN VOID *Source, + IN UINT32 SrcSize, + IN OUT VOID *Destination, + IN UINT32 DstSize, + IN OUT VOID *Scratch, + IN UINT32 ScratchSize + ); + +EFI_STATUS +Extract ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT VOID **Destination, + OUT UINT32 *DstSize, + IN UINTN Algorithm + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiCompress.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiCompress.c new file mode 100644 index 00000000..4cbd49b5 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiCompress.c @@ -0,0 +1,1591 @@ +/** @file +Compression routine. The compression algorithm is a mixture of LZ77 and Huffman +coding. LZ77 transforms the source data into a sequence of Original Characters +and Pointers to repeated strings. This sequence is further divided into Blocks +and Huffman codings are applied to each Block. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Compress.h" + + +// +// Macro Definitions +// + +#undef UINT8_MAX +typedef INT16 NODE; +#define UINT8_MAX 0xff +#define UINT8_BIT 8 +#define THRESHOLD 3 +#define INIT_CRC 0 +#define WNDBIT 13 +#define WNDSIZ (1U << WNDBIT) +#define MAXMATCH 256 +#define PERC_FLAG 0x8000U +#define CODE_BIT 16 +#define NIL 0 +#define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX) +#define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2) +#define CRCPOLY 0xA001 +#define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT) + +// +// C: the Char&Len Set; P: the Position Set; T: the exTra Set +// + +#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD) +#define CBIT 9 +#define NP (WNDBIT + 1) +#define PBIT 4 +#define NT (CODE_BIT + 3) +#define TBIT 5 +#if NT > NP + #define NPT NT +#else + #define NPT NP +#endif + +// +// Function Prototypes +// + +STATIC +VOID +PutDword( + IN UINT32 Data + ); + +STATIC +EFI_STATUS +AllocateMemory ( + ); + +STATIC +VOID +FreeMemory ( + ); + +STATIC +VOID +InitSlide ( + ); + +STATIC +NODE +Child ( + IN NODE q, + IN UINT8 c + ); + +STATIC +VOID +MakeChild ( + IN NODE q, + IN UINT8 c, + IN NODE r + ); + +STATIC +VOID +Split ( + IN NODE Old + ); + +STATIC +VOID +InsertNode ( + ); + +STATIC +VOID +DeleteNode ( + ); + +STATIC +VOID +GetNextMatch ( + ); + +STATIC +EFI_STATUS +Encode ( + ); + +STATIC +VOID +CountTFreq ( + ); + +STATIC +VOID +WritePTLen ( + IN INT32 n, + IN INT32 nbit, + IN INT32 Special + ); + +STATIC +VOID +WriteCLen ( + ); + +STATIC +VOID +EncodeC ( + IN INT32 c + ); + +STATIC +VOID +EncodeP ( + IN UINT32 p + ); + +STATIC +VOID +SendBlock ( + ); + +STATIC +VOID +Output ( + IN UINT32 c, + IN UINT32 p + ); + +STATIC +VOID +HufEncodeStart ( + ); + +STATIC +VOID +HufEncodeEnd ( + ); + +STATIC +VOID +MakeCrcTable ( + ); + +STATIC +VOID +PutBits ( + IN INT32 n, + IN UINT32 x + ); + +STATIC +INT32 +FreadCrc ( + OUT UINT8 *p, + IN INT32 n + ); + +STATIC +VOID +InitPutBits ( + ); + +STATIC +VOID +CountLen ( + IN INT32 i + ); + +STATIC +VOID +MakeLen ( + IN INT32 Root + ); + +STATIC +VOID +DownHeap ( + IN INT32 i + ); + +STATIC +VOID +MakeCode ( + IN INT32 n, + IN UINT8 Len[], + OUT UINT16 Code[] + ); + +STATIC +INT32 +MakeTree ( + IN INT32 NParm, + IN UINT16 FreqParm[], + OUT UINT8 LenParm[], + OUT UINT16 CodeParm[] + ); + + +// +// Global Variables +// + +STATIC UINT8 *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit; + +STATIC UINT8 *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen; +STATIC INT16 mHeap[NC + 1]; +STATIC INT32 mRemainder, mMatchLen, mBitCount, mHeapSize, mN; +STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc; +STATIC UINT32 mCompSize, mOrigSize; + +STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], + mCrcTable[UINT8_MAX + 1], mCFreq[2 * NC - 1],mCCode[NC], + mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1]; + +STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL; + + +// +// functions +// + +EFI_STATUS +EfiCompress ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ) +/*++ + +Routine Description: + + The main compression routine. + +Arguments: + + SrcBuffer - The buffer storing the source data + SrcSize - The size of source data + DstBuffer - The buffer to store the compressed data + DstSize - On input, the size of DstBuffer; On output, + the size of the actual compressed data. + +Returns: + + EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case, + DstSize contains the size needed. + EFI_SUCCESS - Compression is successful. + +--*/ +{ + EFI_STATUS Status = EFI_SUCCESS; + + // + // Initializations + // + mBufSiz = 0; + mBuf = NULL; + mText = NULL; + mLevel = NULL; + mChildCount = NULL; + mPosition = NULL; + mParent = NULL; + mPrev = NULL; + mNext = NULL; + + + mSrc = SrcBuffer; + mSrcUpperLimit = mSrc + SrcSize; + mDst = DstBuffer; + mDstUpperLimit = mDst + *DstSize; + + PutDword(0L); + PutDword(0L); + + MakeCrcTable (); + + mOrigSize = mCompSize = 0; + mCrc = INIT_CRC; + + // + // Compress it + // + + Status = Encode(); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Null terminate the compressed data + // + if (mDst < mDstUpperLimit) { + *mDst++ = 0; + } + + // + // Fill in compressed size and original size + // + mDst = DstBuffer; + PutDword(mCompSize+1); + PutDword(mOrigSize); + + // + // Return + // + + if (mCompSize + 1 + 8 > *DstSize) { + *DstSize = mCompSize + 1 + 8; + return EFI_BUFFER_TOO_SMALL; + } else { + *DstSize = mCompSize + 1 + 8; + return EFI_SUCCESS; + } + +} + +STATIC +VOID +PutDword( + IN UINT32 Data + ) +/*++ + +Routine Description: + + Put a dword to output stream + +Arguments: + + Data - the dword to put + +Returns: (VOID) + +--*/ +{ + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8)(((UINT8)(Data )) & 0xff); + } + + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8)(((UINT8)(Data >> 0x08)) & 0xff); + } + + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8)(((UINT8)(Data >> 0x10)) & 0xff); + } + + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8)(((UINT8)(Data >> 0x18)) & 0xff); + } +} + +STATIC +EFI_STATUS +AllocateMemory () +/*++ + +Routine Description: + + Allocate memory spaces for data structures used in compression process + +Arguments: (VOID) + +Returns: + + EFI_SUCCESS - Memory is allocated successfully + EFI_OUT_OF_RESOURCES - Allocation fails + +--*/ +{ + UINT32 i; + + mText = malloc (WNDSIZ * 2 + MAXMATCH); + if (mText == NULL) { + return EFI_OUT_OF_RESOURCES; + } + for (i = 0 ; i < WNDSIZ * 2 + MAXMATCH; i ++) { + mText[i] = 0; + } + + mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mLevel)); + mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mChildCount)); + mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof(*mPosition)); + mParent = malloc (WNDSIZ * 2 * sizeof(*mParent)); + mPrev = malloc (WNDSIZ * 2 * sizeof(*mPrev)); + mNext = malloc ((MAX_HASH_VAL + 1) * sizeof(*mNext)); + if (mLevel == NULL || mChildCount == NULL || mPosition == NULL || + mParent == NULL || mPrev == NULL || mNext == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + mBufSiz = 16 * 1024U; + while ((mBuf = malloc(mBufSiz)) == NULL) { + mBufSiz = (mBufSiz / 10U) * 9U; + if (mBufSiz < 4 * 1024U) { + return EFI_OUT_OF_RESOURCES; + } + } + mBuf[0] = 0; + + return EFI_SUCCESS; +} + +VOID +FreeMemory () +/*++ + +Routine Description: + + Called when compression is completed to free memory previously allocated. + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + if (mText) { + free (mText); + } + + if (mLevel) { + free (mLevel); + } + + if (mChildCount) { + free (mChildCount); + } + + if (mPosition) { + free (mPosition); + } + + if (mParent) { + free (mParent); + } + + if (mPrev) { + free (mPrev); + } + + if (mNext) { + free (mNext); + } + + if (mBuf) { + free (mBuf); + } + + return; +} + + +STATIC +VOID +InitSlide () +/*++ + +Routine Description: + + Initialize String Info Log data structures + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + NODE i; + + for (i = WNDSIZ; i <= WNDSIZ + UINT8_MAX; i++) { + mLevel[i] = 1; + mPosition[i] = NIL; /* sentinel */ + } + for (i = WNDSIZ; i < WNDSIZ * 2; i++) { + mParent[i] = NIL; + } + mAvail = 1; + for (i = 1; i < WNDSIZ - 1; i++) { + mNext[i] = (NODE)(i + 1); + } + + mNext[WNDSIZ - 1] = NIL; + for (i = WNDSIZ * 2; i <= MAX_HASH_VAL; i++) { + mNext[i] = NIL; + } +} + + +STATIC +NODE +Child ( + IN NODE q, + IN UINT8 c + ) +/*++ + +Routine Description: + + Find child node given the parent node and the edge character + +Arguments: + + q - the parent node + c - the edge character + +Returns: + + The child node (NIL if not found) + +--*/ +{ + NODE r; + + r = mNext[HASH(q, c)]; + mParent[NIL] = q; /* sentinel */ + while (mParent[r] != q) { + r = mNext[r]; + } + + return r; +} + +STATIC +VOID +MakeChild ( + IN NODE q, + IN UINT8 c, + IN NODE r + ) +/*++ + +Routine Description: + + Create a new child for a given parent node. + +Arguments: + + q - the parent node + c - the edge character + r - the child node + +Returns: (VOID) + +--*/ +{ + NODE h, t; + + h = (NODE)HASH(q, c); + t = mNext[h]; + mNext[h] = r; + mNext[r] = t; + mPrev[t] = r; + mPrev[r] = h; + mParent[r] = q; + mChildCount[q]++; +} + +STATIC +VOID +Split ( + NODE Old + ) +/*++ + +Routine Description: + + Split a node. + +Arguments: + + Old - the node to split + +Returns: (VOID) + +--*/ +{ + NODE New, t; + + New = mAvail; + mAvail = mNext[New]; + mChildCount[New] = 0; + t = mPrev[Old]; + mPrev[New] = t; + mNext[t] = New; + t = mNext[Old]; + mNext[New] = t; + mPrev[t] = New; + mParent[New] = mParent[Old]; + mLevel[New] = (UINT8)mMatchLen; + mPosition[New] = mPos; + MakeChild(New, mText[mMatchPos + mMatchLen], Old); + MakeChild(New, mText[mPos + mMatchLen], mPos); +} + +STATIC +VOID +InsertNode () +/*++ + +Routine Description: + + Insert string info for current position into the String Info Log + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + NODE q, r, j, t; + UINT8 c, *t1, *t2; + + if (mMatchLen >= 4) { + + // + // We have just got a long match, the target tree + // can be located by MatchPos + 1. Traverse the tree + // from bottom up to get to a proper starting point. + // The usage of PERC_FLAG ensures proper node deletion + // in DeleteNode() later. + // + + mMatchLen--; + r = (INT16)((mMatchPos + 1) | WNDSIZ); + while ((q = mParent[r]) == NIL) { + r = mNext[r]; + } + while (mLevel[q] >= mMatchLen) { + r = q; q = mParent[q]; + } + t = q; + while (mPosition[t] < 0) { + mPosition[t] = mPos; + t = mParent[t]; + } + if (t < WNDSIZ) { + mPosition[t] = (NODE)(mPos | PERC_FLAG); + } + } else { + + // + // Locate the target tree + // + + q = (INT16)(mText[mPos] + WNDSIZ); + c = mText[mPos + 1]; + if ((r = Child(q, c)) == NIL) { + MakeChild(q, c, mPos); + mMatchLen = 1; + return; + } + mMatchLen = 2; + } + + // + // Traverse down the tree to find a match. + // Update Position value along the route. + // Node split or creation is involved. + // + + for ( ; ; ) { + if (r >= WNDSIZ) { + j = MAXMATCH; + mMatchPos = r; + } else { + j = mLevel[r]; + mMatchPos = (NODE)(mPosition[r] & ~PERC_FLAG); + } + if (mMatchPos >= mPos) { + mMatchPos -= WNDSIZ; + } + t1 = &mText[mPos + mMatchLen]; + t2 = &mText[mMatchPos + mMatchLen]; + while (mMatchLen < j) { + if (*t1 != *t2) { + Split(r); + return; + } + mMatchLen++; + t1++; + t2++; + } + if (mMatchLen >= MAXMATCH) { + break; + } + mPosition[r] = mPos; + q = r; + if ((r = Child(q, *t1)) == NIL) { + MakeChild(q, *t1, mPos); + return; + } + mMatchLen++; + } + t = mPrev[r]; + mPrev[mPos] = t; + mNext[t] = mPos; + t = mNext[r]; + mNext[mPos] = t; + mPrev[t] = mPos; + mParent[mPos] = q; + mParent[r] = NIL; + + // + // Special usage of 'next' + // + mNext[r] = mPos; + +} + +STATIC +VOID +DeleteNode () +/*++ + +Routine Description: + + Delete outdated string info. (The Usage of PERC_FLAG + ensures a clean deletion) + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + NODE q, r, s, t, u; + + if (mParent[mPos] == NIL) { + return; + } + + r = mPrev[mPos]; + s = mNext[mPos]; + mNext[r] = s; + mPrev[s] = r; + r = mParent[mPos]; + mParent[mPos] = NIL; + if (r >= WNDSIZ || --mChildCount[r] > 1) { + return; + } + t = (NODE)(mPosition[r] & ~PERC_FLAG); + if (t >= mPos) { + t -= WNDSIZ; + } + s = t; + q = mParent[r]; + while ((u = mPosition[q]) & PERC_FLAG) { + u &= ~PERC_FLAG; + if (u >= mPos) { + u -= WNDSIZ; + } + if (u > s) { + s = u; + } + mPosition[q] = (INT16)(s | WNDSIZ); + q = mParent[q]; + } + if (q < WNDSIZ) { + if (u >= mPos) { + u -= WNDSIZ; + } + if (u > s) { + s = u; + } + mPosition[q] = (INT16)(s | WNDSIZ | PERC_FLAG); + } + s = Child(r, mText[t + mLevel[r]]); + t = mPrev[s]; + u = mNext[s]; + mNext[t] = u; + mPrev[u] = t; + t = mPrev[r]; + mNext[t] = s; + mPrev[s] = t; + t = mNext[r]; + mPrev[t] = s; + mNext[s] = t; + mParent[s] = mParent[r]; + mParent[r] = NIL; + mNext[r] = mAvail; + mAvail = r; +} + +STATIC +VOID +GetNextMatch () +/*++ + +Routine Description: + + Advance the current position (read in new data if needed). + Delete outdated string info. Find a match string for current position. + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + INT32 n; + + mRemainder--; + if (++mPos == WNDSIZ * 2) { + memmove(&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); + n = FreadCrc(&mText[WNDSIZ + MAXMATCH], WNDSIZ); + mRemainder += n; + mPos = WNDSIZ; + } + DeleteNode(); + InsertNode(); +} + +STATIC +EFI_STATUS +Encode () +/*++ + +Routine Description: + + The main controlling routine for compression process. + +Arguments: (VOID) + +Returns: + + EFI_SUCCESS - The compression is successful + EFI_OUT_0F_RESOURCES - Not enough memory for compression process + +--*/ +{ + EFI_STATUS Status; + INT32 LastMatchLen; + NODE LastMatchPos; + + Status = AllocateMemory(); + if (EFI_ERROR(Status)) { + FreeMemory(); + return Status; + } + + InitSlide(); + + HufEncodeStart(); + + mRemainder = FreadCrc(&mText[WNDSIZ], WNDSIZ + MAXMATCH); + + mMatchLen = 0; + mPos = WNDSIZ; + InsertNode(); + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + while (mRemainder > 0) { + LastMatchLen = mMatchLen; + LastMatchPos = mMatchPos; + GetNextMatch(); + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + + if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { + + // + // Not enough benefits are gained by outputting a pointer, + // so just output the original character + // + + Output(mText[mPos - 1], 0); + } else { + + // + // Outputting a pointer is beneficial enough, do it. + // + + Output(LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), + (mPos - LastMatchPos - 2) & (WNDSIZ - 1)); + while (--LastMatchLen > 0) { + GetNextMatch(); + } + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + } + } + + HufEncodeEnd(); + FreeMemory(); + return EFI_SUCCESS; +} + +STATIC +VOID +CountTFreq () +/*++ + +Routine Description: + + Count the frequencies for the Extra Set + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + INT32 i, k, n, Count; + + for (i = 0; i < NT; i++) { + mTFreq[i] = 0; + } + n = NC; + while (n > 0 && mCLen[n - 1] == 0) { + n--; + } + i = 0; + while (i < n) { + k = mCLen[i++]; + if (k == 0) { + Count = 1; + while (i < n && mCLen[i] == 0) { + i++; + Count++; + } + if (Count <= 2) { + mTFreq[0] = (UINT16)(mTFreq[0] + Count); + } else if (Count <= 18) { + mTFreq[1]++; + } else if (Count == 19) { + mTFreq[0]++; + mTFreq[1]++; + } else { + mTFreq[2]++; + } + } else { + mTFreq[k + 2]++; + } + } +} + +STATIC +VOID +WritePTLen ( + IN INT32 n, + IN INT32 nbit, + IN INT32 Special + ) +/*++ + +Routine Description: + + Outputs the code length array for the Extra Set or the Position Set. + +Arguments: + + n - the number of symbols + nbit - the number of bits needed to represent 'n' + Special - the special symbol that needs to be take care of + +Returns: (VOID) + +--*/ +{ + INT32 i, k; + + while (n > 0 && mPTLen[n - 1] == 0) { + n--; + } + PutBits(nbit, n); + i = 0; + while (i < n) { + k = mPTLen[i++]; + if (k <= 6) { + PutBits(3, k); + } else { + PutBits(k - 3, (1U << (k - 3)) - 2); + } + if (i == Special) { + while (i < 6 && mPTLen[i] == 0) { + i++; + } + PutBits(2, (i - 3) & 3); + } + } +} + +STATIC +VOID +WriteCLen () +/*++ + +Routine Description: + + Outputs the code length array for Char&Length Set + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + INT32 i, k, n, Count; + + n = NC; + while (n > 0 && mCLen[n - 1] == 0) { + n--; + } + PutBits(CBIT, n); + i = 0; + while (i < n) { + k = mCLen[i++]; + if (k == 0) { + Count = 1; + while (i < n && mCLen[i] == 0) { + i++; + Count++; + } + if (Count <= 2) { + for (k = 0; k < Count; k++) { + PutBits(mPTLen[0], mPTCode[0]); + } + } else if (Count <= 18) { + PutBits(mPTLen[1], mPTCode[1]); + PutBits(4, Count - 3); + } else if (Count == 19) { + PutBits(mPTLen[0], mPTCode[0]); + PutBits(mPTLen[1], mPTCode[1]); + PutBits(4, 15); + } else { + PutBits(mPTLen[2], mPTCode[2]); + PutBits(CBIT, Count - 20); + } + } else { + PutBits(mPTLen[k + 2], mPTCode[k + 2]); + } + } +} + +STATIC +VOID +EncodeC ( + IN INT32 c + ) +{ + PutBits(mCLen[c], mCCode[c]); +} + +STATIC +VOID +EncodeP ( + IN UINT32 p + ) +{ + UINT32 c, q; + + c = 0; + q = p; + while (q) { + q >>= 1; + c++; + } + PutBits(mPTLen[c], mPTCode[c]); + if (c > 1) { + PutBits(c - 1, p & (0xFFFFU >> (17 - c))); + } +} + +STATIC +VOID +SendBlock () +/*++ + +Routine Description: + + Huffman code the block and output it. + +Argument: (VOID) + +Returns: (VOID) + +--*/ +{ + UINT32 i, k, Flags, Root, Pos, Size; + Flags = 0; + + Root = MakeTree(NC, mCFreq, mCLen, mCCode); + Size = mCFreq[Root]; + PutBits(16, Size); + if (Root >= NC) { + CountTFreq(); + Root = MakeTree(NT, mTFreq, mPTLen, mPTCode); + if (Root >= NT) { + WritePTLen(NT, TBIT, 3); + } else { + PutBits(TBIT, 0); + PutBits(TBIT, Root); + } + WriteCLen(); + } else { + PutBits(TBIT, 0); + PutBits(TBIT, 0); + PutBits(CBIT, 0); + PutBits(CBIT, Root); + } + Root = MakeTree(NP, mPFreq, mPTLen, mPTCode); + if (Root >= NP) { + WritePTLen(NP, PBIT, -1); + } else { + PutBits(PBIT, 0); + PutBits(PBIT, Root); + } + Pos = 0; + for (i = 0; i < Size; i++) { + if (i % UINT8_BIT == 0) { + Flags = mBuf[Pos++]; + } else { + Flags <<= 1; + } + if (Flags & (1U << (UINT8_BIT - 1))) { + EncodeC(mBuf[Pos++] + (1U << UINT8_BIT)); + k = mBuf[Pos++] << UINT8_BIT; + k += mBuf[Pos++]; + EncodeP(k); + } else { + EncodeC(mBuf[Pos++]); + } + } + for (i = 0; i < NC; i++) { + mCFreq[i] = 0; + } + for (i = 0; i < NP; i++) { + mPFreq[i] = 0; + } +} + + +STATIC +VOID +Output ( + IN UINT32 c, + IN UINT32 p + ) +/*++ + +Routine Description: + + Outputs an Original Character or a Pointer + +Arguments: + + c - The original character or the 'String Length' element of a Pointer + p - The 'Position' field of a Pointer + +Returns: (VOID) + +--*/ +{ + STATIC UINT32 CPos; + + if ((mOutputMask >>= 1) == 0) { + mOutputMask = 1U << (UINT8_BIT - 1); + if (mOutputPos >= mBufSiz - 3 * UINT8_BIT) { + SendBlock(); + mOutputPos = 0; + } + CPos = mOutputPos++; + mBuf[CPos] = 0; + } + mBuf[mOutputPos++] = (UINT8) c; + mCFreq[c]++; + if (c >= (1U << UINT8_BIT)) { + mBuf[CPos] |= mOutputMask; + mBuf[mOutputPos++] = (UINT8)(p >> UINT8_BIT); + mBuf[mOutputPos++] = (UINT8) p; + c = 0; + while (p) { + p >>= 1; + c++; + } + mPFreq[c]++; + } +} + +STATIC +VOID +HufEncodeStart () +{ + INT32 i; + + for (i = 0; i < NC; i++) { + mCFreq[i] = 0; + } + for (i = 0; i < NP; i++) { + mPFreq[i] = 0; + } + mOutputPos = mOutputMask = 0; + InitPutBits(); + return; +} + +STATIC +VOID +HufEncodeEnd () +{ + SendBlock(); + + // + // Flush remaining bits + // + PutBits(UINT8_BIT - 1, 0); + + return; +} + + +STATIC +VOID +MakeCrcTable () +{ + UINT32 i, j, r; + + for (i = 0; i <= UINT8_MAX; i++) { + r = i; + for (j = 0; j < UINT8_BIT; j++) { + if (r & 1) { + r = (r >> 1) ^ CRCPOLY; + } else { + r >>= 1; + } + } + mCrcTable[i] = (UINT16)r; + } +} + +STATIC +VOID +PutBits ( + IN INT32 n, + IN UINT32 x + ) +/*++ + +Routine Description: + + Outputs rightmost n bits of x + +Arguments: + + n - the rightmost n bits of the data is used + x - the data + +Returns: (VOID) + +--*/ +{ + UINT8 Temp; + + if (n < mBitCount) { + mSubBitBuf |= x << (mBitCount -= n); + } else { + + Temp = (UINT8)(mSubBitBuf | (x >> (n -= mBitCount))); + if (mDst < mDstUpperLimit) { + *mDst++ = Temp; + } + mCompSize++; + + if (n < UINT8_BIT) { + mSubBitBuf = x << (mBitCount = UINT8_BIT - n); + } else { + + Temp = (UINT8)(x >> (n - UINT8_BIT)); + if (mDst < mDstUpperLimit) { + *mDst++ = Temp; + } + mCompSize++; + + mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - n); + } + } +} + +STATIC +INT32 +FreadCrc ( + OUT UINT8 *p, + IN INT32 n + ) +/*++ + +Routine Description: + + Read in source data + +Arguments: + + p - the buffer to hold the data + n - number of bytes to read + +Returns: + + number of bytes actually read + +--*/ +{ + INT32 i; + + for (i = 0; mSrc < mSrcUpperLimit && i < n; i++) { + *p++ = *mSrc++; + } + n = i; + + p -= n; + mOrigSize += n; + while (--i >= 0) { + UPDATE_CRC(*p++); + } + return n; +} + + +STATIC +VOID +InitPutBits () +{ + mBitCount = UINT8_BIT; + mSubBitBuf = 0; +} + +STATIC +VOID +CountLen ( + IN INT32 i + ) +/*++ + +Routine Description: + + Count the number of each code length for a Huffman tree. + +Arguments: + + i - the top node + +Returns: (VOID) + +--*/ +{ + STATIC INT32 Depth = 0; + + if (i < mN) { + mLenCnt[(Depth < 16) ? Depth : 16]++; + } else { + Depth++; + CountLen(mLeft [i]); + CountLen(mRight[i]); + Depth--; + } +} + +STATIC +VOID +MakeLen ( + IN INT32 Root + ) +/*++ + +Routine Description: + + Create code length array for a Huffman tree + +Arguments: + + Root - the root of the tree + +--*/ +{ + INT32 i, k; + UINT32 Cum; + + for (i = 0; i <= 16; i++) { + mLenCnt[i] = 0; + } + CountLen(Root); + + // + // Adjust the length count array so that + // no code will be generated longer than its designated length + // + + Cum = 0; + for (i = 16; i > 0; i--) { + Cum += mLenCnt[i] << (16 - i); + } + while (Cum != (1U << 16)) { + mLenCnt[16]--; + for (i = 15; i > 0; i--) { + if (mLenCnt[i] != 0) { + mLenCnt[i]--; + mLenCnt[i+1] += 2; + break; + } + } + Cum--; + } + for (i = 16; i > 0; i--) { + k = mLenCnt[i]; + while (--k >= 0) { + mLen[*mSortPtr++] = (UINT8)i; + } + } +} + +STATIC +VOID +DownHeap ( + IN INT32 i + ) +{ + INT32 j, k; + + // + // priority queue: send i-th entry down heap + // + + k = mHeap[i]; + while ((j = 2 * i) <= mHeapSize) { + if (j < mHeapSize && mFreq[mHeap[j]] > mFreq[mHeap[j + 1]]) { + j++; + } + if (mFreq[k] <= mFreq[mHeap[j]]) { + break; + } + mHeap[i] = mHeap[j]; + i = j; + } + mHeap[i] = (INT16)k; +} + +STATIC +VOID +MakeCode ( + IN INT32 n, + IN UINT8 Len[], + OUT UINT16 Code[] + ) +/*++ + +Routine Description: + + Assign code to each symbol based on the code length array + +Arguments: + + n - number of symbols + Len - the code length array + Code - stores codes for each symbol + +Returns: (VOID) + +--*/ +{ + INT32 i; + UINT16 Start[18]; + + Start[1] = 0; + for (i = 1; i <= 16; i++) { + Start[i + 1] = (UINT16)((Start[i] + mLenCnt[i]) << 1); + } + for (i = 0; i < n; i++) { + Code[i] = Start[Len[i]]++; + } +} + +STATIC +INT32 +MakeTree ( + IN INT32 NParm, + IN UINT16 FreqParm[], + OUT UINT8 LenParm[], + OUT UINT16 CodeParm[] + ) +/*++ + +Routine Description: + + Generates Huffman codes given a frequency distribution of symbols + +Arguments: + + NParm - number of symbols + FreqParm - frequency of each symbol + LenParm - code length for each symbol + CodeParm - code for each symbol + +Returns: + + Root of the Huffman tree. + +--*/ +{ + INT32 i, j, k, Avail; + + // + // make tree, calculate len[], return root + // + + mN = NParm; + mFreq = FreqParm; + mLen = LenParm; + Avail = mN; + mHeapSize = 0; + mHeap[1] = 0; + for (i = 0; i < mN; i++) { + mLen[i] = 0; + if (mFreq[i]) { + mHeap[++mHeapSize] = (INT16)i; + } + } + if (mHeapSize < 2) { + CodeParm[mHeap[1]] = 0; + return mHeap[1]; + } + for (i = mHeapSize / 2; i >= 1; i--) { + + // + // make priority queue + // + DownHeap(i); + } + mSortPtr = CodeParm; + do { + i = mHeap[1]; + if (i < mN) { + *mSortPtr++ = (UINT16)i; + } + mHeap[1] = mHeap[mHeapSize--]; + DownHeap(1); + j = mHeap[1]; + if (j < mN) { + *mSortPtr++ = (UINT16)j; + } + k = Avail++; + mFreq[k] = (UINT16)(mFreq[i] + mFreq[j]); + mHeap[1] = (INT16)k; + DownHeap(1); + mLeft[k] = (UINT16)i; + mRight[k] = (UINT16)j; + } while (mHeapSize > 1); + + mSortPtr = CodeParm; + MakeLen(k); + MakeCode(NParm, LenParm, CodeParm); + + // + // return root + // + return k; +} + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiUtilityMsgs.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiUtilityMsgs.c new file mode 100644 index 00000000..69b9f899 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiUtilityMsgs.c @@ -0,0 +1,902 @@ +/** @file +EFI tools utility functions to display warning, error, and informational messages + +Copyright (c) 2004 - 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +--*/ + +#include +#include +#include +#include +#include + +#include "EfiUtilityMsgs.h" + +// +// Declare module globals for keeping track of the utility's +// name and other settings. +// +STATIC STATUS mStatus = STATUS_SUCCESS; +STATIC CHAR8 mUtilityName[50] = { 0 }; +STATIC UINT64 mPrintLogLevel = INFO_LOG_LEVEL; +STATIC CHAR8 *mSourceFileName = NULL; +STATIC UINT32 mSourceFileLineNum = 0; +STATIC UINT32 mErrorCount = 0; +STATIC UINT32 mWarningCount = 0; +STATIC UINT32 mMaxErrors = 0; +STATIC UINT32 mMaxWarnings = 0; +STATIC UINT32 mMaxWarningsPlusErrors = 0; +STATIC INT8 mPrintLimitsSet = 0; + +STATIC +VOID +PrintLimitExceeded ( + VOID + ); + +VOID +Error ( + CHAR8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + CHAR8 *Text, + CHAR8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Prints an error message. + +Arguments: + All arguments are optional, though the printed message may be useless if + at least something valid is not specified. + + FileName - name of the file or application. If not specified, then the + utility name (as set by the utility calling SetUtilityName() + earlier) is used. Otherwise "Unknown utility" is used. + + LineNumber - the line number of error, typically used by parsers. If the + utility is not a parser, then 0 should be specified. Otherwise + the FileName and LineNumber info can be used to cause + MS Visual Studio to jump to the error. + + MessageCode - an application-specific error code that can be referenced in + other documentation. + + Text - the text in question, typically used by parsers. + + MsgFmt - the format string for the error message. Can contain formatting + controls for use with the varargs. + +Returns: + None. + +Notes: + We print the following (similar to the Warn() and Debug() + W + Typical error/warning message format: + + bin\VfrCompile.cpp(330) : error C2660: 'AddVfrDataStructField' : function does not take 2 parameters + + BUGBUG -- these three utility functions are almost identical, and + should be modified to share code. + + Visual Studio does not find error messages with: + + " error :" + " error 1:" + " error c1:" + " error 1000:" + " error c100:" + + It does find: + " error c1000:" +--*/ +{ + va_list List; + // + // If limits have been set, then check that we have not exceeded them + // + if (mPrintLimitsSet) { + // + // See if we've exceeded our total count + // + if (mMaxWarningsPlusErrors != 0) { + if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) { + PrintLimitExceeded (); + return ; + } + } + // + // See if we've exceeded our error count + // + if (mMaxErrors != 0) { + if (mErrorCount > mMaxErrors) { + PrintLimitExceeded (); + return ; + } + } + } + + mErrorCount++; + va_start (List, MsgFmt); + PrintMessage ("ERROR", FileName, LineNumber, MessageCode, Text, MsgFmt, List); + va_end (List); +} + +VOID +ParserError ( + UINT32 MessageCode, + CHAR8 *Text, + CHAR8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a parser error, using the source file name and line number + set by a previous call to SetParserPosition(). + +Arguments: + MessageCode - application-specific error code + Text - text to print in the error message + MsgFmt - format string to print at the end of the error message + +Returns: + NA + +--*/ +{ + va_list List; + // + // If limits have been set, then check them + // + if (mPrintLimitsSet) { + // + // See if we've exceeded our total count + // + if (mMaxWarningsPlusErrors != 0) { + if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) { + PrintLimitExceeded (); + return ; + } + } + // + // See if we've exceeded our error count + // + if (mMaxErrors != 0) { + if (mErrorCount > mMaxErrors) { + PrintLimitExceeded (); + return ; + } + } + } + + mErrorCount++; + va_start (List, MsgFmt); + PrintMessage ("ERROR", mSourceFileName, mSourceFileLineNum, MessageCode, Text, MsgFmt, List); + va_end (List); +} + +VOID +ParserWarning ( + UINT32 ErrorCode, + CHAR8 *OffendingText, + CHAR8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a parser warning, using the source file name and line number + set by a previous call to SetParserPosition(). + +Arguments: + ErrorCode - application-specific error code + OffendingText - text to print in the warning message + MsgFmt - format string to print at the end of the warning message + +Returns: + NA + +--*/ +{ + va_list List; + // + // If limits have been set, then check them + // + if (mPrintLimitsSet) { + // + // See if we've exceeded our total count + // + if (mMaxWarningsPlusErrors != 0) { + if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) { + PrintLimitExceeded (); + return ; + } + } + // + // See if we've exceeded our warning count + // + if (mMaxWarnings != 0) { + if (mWarningCount > mMaxWarnings) { + PrintLimitExceeded (); + return ; + } + } + } + + mWarningCount++; + va_start (List, MsgFmt); + PrintMessage ("WARNING", mSourceFileName, mSourceFileLineNum, ErrorCode, OffendingText, MsgFmt, List); + va_end (List); + // + // Don't set warning status accordingly + // + // if (mStatus < STATUS_WARNING) { + // mStatus = STATUS_WARNING; + // } +} + +VOID +Warning ( + CHAR8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + CHAR8 *Text, + CHAR8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a warning message. + +Arguments: + FileName - name of the file where the warning was detected, or the name + of the application that detected the warning + + LineNumber - the line number where the warning was detected (parsers). + 0 should be specified if the utility is not a parser. + + MessageCode - an application-specific warning code that can be referenced in + other documentation. + + Text - the text in question (parsers) + + MsgFmt - the format string for the warning message. Can contain formatting + controls for use with varargs. + +Returns: + None. + +--*/ +{ + va_list List; + + // + // Current Print Level not output warning information. + // + if (WARNING_LOG_LEVEL < mPrintLogLevel) { + return; + } + // + // If limits have been set, then check them + // + if (mPrintLimitsSet) { + // + // See if we've exceeded our total count + // + if (mMaxWarningsPlusErrors != 0) { + if (mErrorCount + mWarningCount > mMaxWarningsPlusErrors) { + PrintLimitExceeded (); + return ; + } + } + // + // See if we've exceeded our warning count + // + if (mMaxWarnings != 0) { + if (mWarningCount > mMaxWarnings) { + PrintLimitExceeded (); + return ; + } + } + } + + mWarningCount++; + va_start (List, MsgFmt); + PrintMessage ("WARNING", FileName, LineNumber, MessageCode, Text, MsgFmt, List); + va_end (List); +} + +VOID +DebugMsg ( + CHAR8 *FileName, + UINT32 LineNumber, + UINT64 MsgLevel, + CHAR8 *Text, + CHAR8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a Debug message. + +Arguments: + FileName - typically the name of the utility printing the debug message, but + can be the name of a file being parsed. + + LineNumber - the line number in FileName (parsers) + + MsgLevel - Debug message print level (0~9) + + Text - the text in question (parsers) + + MsgFmt - the format string for the debug message. Can contain formatting + controls for use with varargs. + +Returns: + None. + +--*/ +{ + va_list List; + // + // If the debug level is less than current print level, then do nothing. + // + if (MsgLevel < mPrintLogLevel) { + return ; + } + + va_start (List, MsgFmt); + PrintMessage ("DEBUG", FileName, LineNumber, 0, Text, MsgFmt, List); + va_end (List); +} + +VOID +PrintMessage ( + CHAR8 *Type, + CHAR8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + CHAR8 *Text, + CHAR8 *MsgFmt, + va_list List + ) +/*++ + +Routine Description: + Worker routine for all the utility printing services. Prints the message in + a format that Visual Studio will find when scanning build outputs for + errors or warnings. + +Arguments: + Type - "warning" or "error" string to insert into the message to be + printed. The first character of this string (converted to uppercase) + is used to precede the MessageCode value in the output string. + + FileName - name of the file where the warning was detected, or the name + of the application that detected the warning + + LineNumber - the line number where the warning was detected (parsers). + 0 should be specified if the utility is not a parser. + + MessageCode - an application-specific warning code that can be referenced in + other documentation. + + Text - part of the message to print + + MsgFmt - the format string for the message. Can contain formatting + controls for use with varargs. + List - the variable list. + +Returns: + None. + +Notes: + If FileName == NULL then this utility will use the string passed into SetUtilityName(). + + LineNumber is only used if the caller is a parser, in which case FileName refers to the + file being parsed. + + Text and MsgFmt are both optional, though it would be of little use calling this function with + them both NULL. + + Output will typically be of the form: + () : : : + + Parser (LineNumber != 0) + VfrCompile.cpp(330) : error E2660: AddVfrDataStructField : function does not take 2 parameters + Generic utility (LineNumber == 0) + UtilityName : error E1234 : Text string : MsgFmt string and args + +--*/ +{ + CHAR8 Line[MAX_LINE_LEN]; + CHAR8 Line2[MAX_LINE_LEN]; + CHAR8 *Cptr; + struct tm *NewTime; + time_t CurrentTime; + + // + // init local variable + // + Line[0] = '\0'; + Line2[0] = '\0'; + + // + // If given a filename, then add it (and the line number) to the string. + // If there's no filename, then use the program name if provided. + // + if (FileName != NULL) { + Cptr = FileName; + } else { + Cptr = NULL; + } + + if (strcmp (Type, "DEBUG") == 0) { + // + // Debug Message requires current time. + // + time (&CurrentTime); + NewTime = localtime (&CurrentTime); + if (NewTime != NULL) { + fprintf (stdout, "%04d-%02d-%02d %02d:%02d:%02d", + NewTime->tm_year + 1900, + NewTime->tm_mon + 1, + NewTime->tm_mday, + NewTime->tm_hour, + NewTime->tm_min, + NewTime->tm_sec + ); + } + if (Cptr != NULL) { + strcpy (Line, ": "); + strncat (Line, Cptr, MAX_LINE_LEN - strlen (Line) - 1); + if (LineNumber != 0) { + sprintf (Line2, "(%u)", (unsigned) LineNumber); + strncat (Line, Line2, MAX_LINE_LEN - strlen (Line) - 1); + } + } + } else { + // + // Error and Warning Information. + // + if (Cptr != NULL) { + if (mUtilityName[0] != '\0') { + fprintf (stdout, "%s...\n", mUtilityName); + } + strncpy (Line, Cptr, MAX_LINE_LEN - 1); + Line[MAX_LINE_LEN - 1] = 0; + if (LineNumber != 0) { + sprintf (Line2, "(%u)", (unsigned) LineNumber); + strncat (Line, Line2, MAX_LINE_LEN - strlen (Line) - 1); + } + } else { + if (mUtilityName[0] != '\0') { + strncpy (Line, mUtilityName, MAX_LINE_LEN - 1); + Line[MAX_LINE_LEN - 1] = 0; + } + } + + if (strcmp (Type, "ERROR") == 0) { + // + // Set status accordingly for ERROR information. + // + if (mStatus < STATUS_ERROR) { + mStatus = STATUS_ERROR; + } + } + } + + // + // Have to print an error code or Visual Studio won't find the + // message for you. It has to be decimal digits too. + // + strncat (Line, ": ", MAX_LINE_LEN - strlen (Line) - 1); + strncat (Line, Type, MAX_LINE_LEN - strlen (Line) - 1); + if (MessageCode != 0) { + sprintf (Line2, " %04u", (unsigned) MessageCode); + strncat (Line, Line2, MAX_LINE_LEN - strlen (Line) - 1); + } + fprintf (stdout, "%s", Line); + // + // If offending text was provided, then print it + // + if (Text != NULL) { + fprintf (stdout, ": %s", Text); + } + fprintf (stdout, "\n"); + + // + // Print formatted message if provided + // + if (MsgFmt != NULL) { + vsprintf (Line2, MsgFmt, List); + fprintf (stdout, " %s\n", Line2); + } + +} + +STATIC +VOID +PrintSimpleMessage ( + CHAR8 *MsgFmt, + va_list List + ) +/*++ +Routine Description: + Print message into stdout. + +Arguments: + MsgFmt - the format string for the message. Can contain formatting + controls for use with varargs. + List - the variable list. + +Returns: + None. +--*/ +{ + CHAR8 Line[MAX_LINE_LEN]; + // + // Print formatted message if provided + // + if (MsgFmt != NULL) { + vsprintf (Line, MsgFmt, List); + fprintf (stdout, "%s\n", Line); + } +} + +VOID +ParserSetPosition ( + CHAR8 *SourceFileName, + UINT32 LineNum + ) +/*++ + +Routine Description: + Set the position in a file being parsed. This can be used to + print error messages deeper down in a parser. + +Arguments: + SourceFileName - name of the source file being parsed + LineNum - line number of the source file being parsed + +Returns: + NA + +--*/ +{ + mSourceFileName = SourceFileName; + mSourceFileLineNum = LineNum; +} + +VOID +SetUtilityName ( + CHAR8 *UtilityName + ) +/*++ + +Routine Description: + All printed error/warning/debug messages follow the same format, and + typically will print a filename or utility name followed by the error + text. However if a filename is not passed to the print routines, then + they'll print the utility name if you call this function early in your + app to set the utility name. + +Arguments: + UtilityName - name of the utility, which will be printed with all + error/warning/debug messages. + +Returns: + NA + +--*/ +{ + // + // Save the name of the utility in our local variable. Make sure its + // length does not exceed our buffer. + // + if (UtilityName != NULL) { + if (strlen (UtilityName) >= sizeof (mUtilityName)) { + Error (UtilityName, 0, 0, "application error", "utility name length exceeds internal buffer size"); + } + strncpy (mUtilityName, UtilityName, sizeof (mUtilityName) - 1); + mUtilityName[sizeof (mUtilityName) - 1] = 0; + } else { + Error (NULL, 0, 0, "application error", "SetUtilityName() called with NULL utility name"); + } +} + +STATUS +GetUtilityStatus ( + VOID + ) +/*++ + +Routine Description: + When you call Error() or Warning(), this module keeps track of it and + sets a local mStatus to STATUS_ERROR or STATUS_WARNING. When the utility + exits, it can call this function to get the status and use it as a return + value. + +Arguments: + None. + +Returns: + Worst-case status reported, as defined by which print function was called. + +--*/ +{ + return mStatus; +} + +VOID +SetPrintLevel ( + UINT64 LogLevel + ) +/*++ + +Routine Description: + Set the printing message Level. This is used by the PrintMsg() function + to determine when/if a message should be printed. + +Arguments: + LogLevel - 0~50 to specify the different level message. + +Returns: + NA + +--*/ +{ + mPrintLogLevel = LogLevel; +} + +VOID +VerboseMsg ( + CHAR8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a verbose level message. + +Arguments: + MsgFmt - the format string for the message. Can contain formatting + controls for use with varargs. + List - the variable list. + +Returns: + NA + +--*/ +{ + va_list List; + // + // If the debug level is less than current print level, then do nothing. + // + if (VERBOSE_LOG_LEVEL < mPrintLogLevel) { + return ; + } + + va_start (List, MsgFmt); + PrintSimpleMessage (MsgFmt, List); + va_end (List); +} + +VOID +NormalMsg ( + CHAR8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a default level message. + +Arguments: + MsgFmt - the format string for the message. Can contain formatting + controls for use with varargs. + List - the variable list. + +Returns: + NA + +--*/ +{ + va_list List; + // + // If the debug level is less than current print level, then do nothing. + // + if (INFO_LOG_LEVEL < mPrintLogLevel) { + return ; + } + + va_start (List, MsgFmt); + PrintSimpleMessage (MsgFmt, List); + va_end (List); +} + +VOID +KeyMsg ( + CHAR8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a key level message. + +Arguments: + MsgFmt - the format string for the message. Can contain formatting + controls for use with varargs. + List - the variable list. + +Returns: + NA + +--*/ +{ + va_list List; + // + // If the debug level is less than current print level, then do nothing. + // + if (KEY_LOG_LEVEL < mPrintLogLevel) { + return ; + } + + va_start (List, MsgFmt); + PrintSimpleMessage (MsgFmt, List); + va_end (List); +} + +VOID +SetPrintLimits ( + UINT32 MaxErrors, + UINT32 MaxWarnings, + UINT32 MaxWarningsPlusErrors + ) +/*++ + +Routine Description: + Set the limits of how many errors, warnings, and errors+warnings + we will print. + +Arguments: + MaxErrors - maximum number of error messages to print + MaxWarnings - maximum number of warning messages to print + MaxWarningsPlusErrors + - maximum number of errors+warnings to print + +Returns: + NA + +--*/ +{ + mMaxErrors = MaxErrors; + mMaxWarnings = MaxWarnings; + mMaxWarningsPlusErrors = MaxWarningsPlusErrors; + mPrintLimitsSet = 1; +} + +STATIC +VOID +PrintLimitExceeded ( + VOID + ) +{ + STATIC INT8 mPrintLimitExceeded = 0; + // + // If we've already printed the message, do nothing. Otherwise + // temporarily increase our print limits so we can pass one + // more message through. + // + if (mPrintLimitExceeded == 0) { + mPrintLimitExceeded++; + mMaxErrors++; + mMaxWarnings++; + mMaxWarningsPlusErrors++; + Error (NULL, 0, 0, "error/warning print limit exceeded", NULL); + mMaxErrors--; + mMaxWarnings--; + mMaxWarningsPlusErrors--; + } +} + +#if 0 +VOID +TestUtilityMessages ( + VOID + ) +{ + CHAR8 *ArgStr = "ArgString"; + int ArgInt; + + ArgInt = 0x12345678; + // + // Test without setting utility name + // + fprintf (stdout, "* Testing without setting utility name\n"); + fprintf (stdout, "** Test debug message not printed\n"); + DebugMsg (NULL, 0, 0x00000001, NULL, NULL); + fprintf (stdout, "** Test warning with two strings and two args\n"); + Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); + fprintf (stdout, "** Test error with two strings and two args\n"); + Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); + fprintf (stdout, "** Test parser warning with nothing\n"); + ParserWarning (0, NULL, NULL); + fprintf (stdout, "** Test parser error with nothing\n"); + ParserError (0, NULL, NULL); + // + // Test with utility name set now + // + fprintf (stdout, "** Testingin with utility name set\n"); + SetUtilityName ("MyUtilityName"); + // + // Test debug prints + // + SetDebugMsgMask (2); + fprintf (stdout, "** Test debug message with one string\n"); + DebugMsg (NULL, 0, 0x00000002, "Text1", NULL); + fprintf (stdout, "** Test debug message with one string\n"); + DebugMsg (NULL, 0, 0x00000002, NULL, "Text2"); + fprintf (stdout, "** Test debug message with two strings\n"); + DebugMsg (NULL, 0, 0x00000002, "Text1", "Text2"); + fprintf (stdout, "** Test debug message with two strings and two args\n"); + DebugMsg (NULL, 0, 0x00000002, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); + // + // Test warning prints + // + fprintf (stdout, "** Test warning with no strings\n"); + Warning (NULL, 0, 1234, NULL, NULL); + fprintf (stdout, "** Test warning with one string\n"); + Warning (NULL, 0, 1234, "Text1", NULL); + fprintf (stdout, "** Test warning with one string\n"); + Warning (NULL, 0, 1234, NULL, "Text2"); + fprintf (stdout, "** Test warning with two strings and two args\n"); + Warning (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); + // + // Test error prints + // + fprintf (stdout, "** Test error with no strings\n"); + Error (NULL, 0, 1234, NULL, NULL); + fprintf (stdout, "** Test error with one string\n"); + Error (NULL, 0, 1234, "Text1", NULL); + fprintf (stdout, "** Test error with one string\n"); + Error (NULL, 0, 1234, NULL, "Text2"); + fprintf (stdout, "** Test error with two strings and two args\n"); + Error (NULL, 0, 1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); + // + // Test parser prints + // + fprintf (stdout, "** Test parser errors\n"); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserError (1234, NULL, NULL); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserError (1234, "Text1", NULL); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserError (1234, NULL, "Text2"); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserError (1234, "Text1", "Text2"); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserError (1234, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); + + fprintf (stdout, "** Test parser warnings\n"); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserWarning (4321, NULL, NULL); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserWarning (4321, "Text1", NULL); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserWarning (4321, NULL, "Text2"); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserWarning (4321, "Text1", "Text2"); + ParserSetPosition (__FILE__, __LINE__ + 1); + ParserWarning (4321, "Text1", "Text2 %s 0x%X", ArgStr, ArgInt); +} +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiUtilityMsgs.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiUtilityMsgs.h new file mode 100644 index 00000000..406cc70e --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/EfiUtilityMsgs.h @@ -0,0 +1,164 @@ +/** @file +Defines and prototypes for common EFI utility error and debug messages. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_UTILITY_MSGS_H_ +#define _EFI_UTILITY_MSGS_H_ + +#include + +// +// Log message print Level +// +#define VERBOSE_LOG_LEVEL 15 +#define WARNING_LOG_LEVEL 15 +#define INFO_LOG_LEVEL 20 +#define KEY_LOG_LEVEL 40 +#define ERROR_LOG_LEVLE 50 + +// +// Status codes returned by EFI utility programs and functions +// +#define STATUS_SUCCESS 0 +#define STATUS_WARNING 1 +#define STATUS_ERROR 2 +#define VOID void + +typedef int STATUS; + +#define MAX_LINE_LEN 0x200 +#define MAXIMUM_INPUT_FILE_NUM 10 + +#ifdef __cplusplus +extern "C" { +#endif +// +// When we call Error() or Warning(), the module keeps track of the worst +// case reported. GetUtilityStatus() will get the worst-case results, which +// can be used as the return value from the app. +// +STATUS +GetUtilityStatus ( + VOID + ); + +// +// If someone prints an error message and didn't specify a source file name, +// then we print the utility name instead. However they must tell us the +// utility name early on via this function. +// +VOID +SetUtilityName ( + CHAR8 *ProgramName + ) +; + +VOID +PrintMessage ( + CHAR8 *Type, + CHAR8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + CHAR8 *Text, + CHAR8 *MsgFmt, + va_list List + ); + +VOID +Error ( + CHAR8 *FileName, + UINT32 LineNumber, + UINT32 ErrorCode, + CHAR8 *OffendingText, + CHAR8 *MsgFmt, + ... + ) +; + +VOID +Warning ( + CHAR8 *FileName, + UINT32 LineNumber, + UINT32 WarningCode, + CHAR8 *OffendingText, + CHAR8 *MsgFmt, + ... + ) +; + +VOID +DebugMsg ( + CHAR8 *FileName, + UINT32 LineNumber, + UINT64 MsgLevel, + CHAR8 *OffendingText, + CHAR8 *MsgFmt, + ... + ) +; + +VOID +VerboseMsg ( + CHAR8 *MsgFmt, + ... + ); + +VOID +NormalMsg ( + CHAR8 *MsgFmt, + ... + ); + +VOID +KeyMsg ( + CHAR8 *MsgFmt, + ... + ); + +VOID +SetPrintLevel ( + UINT64 LogLevel + ); + +VOID +ParserSetPosition ( + CHAR8 *SourceFileName, + UINT32 LineNum + ) +; + +VOID +ParserError ( + UINT32 ErrorCode, + CHAR8 *OffendingText, + CHAR8 *MsgFmt, + ... + ) +; + +VOID +ParserWarning ( + UINT32 ErrorCode, + CHAR8 *OffendingText, + CHAR8 *MsgFmt, + ... + ) +; + +VOID +SetPrintLimits ( + UINT32 NumErrors, + UINT32 NumWarnings, + UINT32 NumWarningsPlusErrors + ) +; + +#ifdef __cplusplus +} +#endif + +#endif // #ifndef _EFI_UTILITY_MSGS_H_ diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FirmwareVolumeBuffer.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FirmwareVolumeBuffer.c new file mode 100644 index 00000000..fcf62e70 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FirmwareVolumeBuffer.c @@ -0,0 +1,1775 @@ +/** @file +EFI Firmware Volume routines which work on a Fv image in buffers. + +Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "FirmwareVolumeBufferLib.h" +#include "BinderFuncs.h" + +// +// Local macros +// +#define EFI_TEST_FFS_ATTRIBUTES_BIT(FvbAttributes, TestAttributes, Bit) \ + ( \ + (BOOLEAN) ( \ + (FvbAttributes & EFI_FVB2_ERASE_POLARITY) ? (((~TestAttributes) & Bit) == Bit) : ((TestAttributes & Bit) == Bit) \ + ) \ + ) + + +// +// Local prototypes +// + +STATIC +UINT32 +FvBufGetSecHdrLen( + IN EFI_COMMON_SECTION_HEADER *SectionHeader + ) +{ + if (SectionHeader == NULL) { + return 0; + } + if (FvBufExpand3ByteSize(SectionHeader->Size) == 0xffffff) { + return sizeof(EFI_COMMON_SECTION_HEADER2); + } + return sizeof(EFI_COMMON_SECTION_HEADER); +} + +STATIC +UINT32 +FvBufGetSecFileLen ( + IN EFI_COMMON_SECTION_HEADER *SectionHeader + ) +{ + UINT32 Length; + if (SectionHeader == NULL) { + return 0; + } + Length = FvBufExpand3ByteSize(SectionHeader->Size); + if (Length == 0xffffff) { + Length = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize; + } + return Length; +} + +// +// Local prototypes +// + +STATIC +UINT16 +FvBufCalculateChecksum16 ( + IN UINT16 *Buffer, + IN UINTN Size + ); + +STATIC +UINT8 +FvBufCalculateChecksum8 ( + IN UINT8 *Buffer, + IN UINTN Size + ); + +// +// Procedures start +// + +EFI_STATUS +FvBufRemoveFileNew ( + IN OUT VOID *Fv, + IN EFI_GUID *Name + ) +/*++ + +Routine Description: + + Clears out all files from the Fv buffer in memory + +Arguments: + + SourceFv - Address of the Fv in memory, this firmware volume volume will + be modified, if SourceFfsFile exists + SourceFfsFile - Input FFS file to replace + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + +--*/ +{ + EFI_STATUS Status; + EFI_FFS_FILE_HEADER* FileToRm; + UINTN FileToRmLength; + + Status = FvBufFindFileByName( + Fv, + Name, + (VOID **)&FileToRm + ); + if (EFI_ERROR (Status)) { + return Status; + } + + FileToRmLength = FvBufGetFfsFileSize (FileToRm); + + CommonLibBinderSetMem ( + FileToRm, + FileToRmLength, + (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_FVB2_ERASE_POLARITY) + ? 0xFF : 0 + ); + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufRemoveFile ( + IN OUT VOID *Fv, + IN EFI_GUID *Name + ) +/*++ + +Routine Description: + + Clears out all files from the Fv buffer in memory + +Arguments: + + SourceFv - Address of the Fv in memory, this firmware volume volume will + be modified, if SourceFfsFile exists + SourceFfsFile - Input FFS file to replace + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + +--*/ +{ + EFI_STATUS Status; + EFI_FFS_FILE_HEADER *NextFile; + EFI_FIRMWARE_VOLUME_HEADER *TempFv; + UINTN FileKey; + UINTN FvLength; + + Status = FvBufFindFileByName( + Fv, + Name, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = FvBufGetSize (Fv, &FvLength); + if (EFI_ERROR (Status)) { + return Status; + } + + TempFv = NULL; + Status = FvBufDuplicate (Fv, (VOID **)&TempFv); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = FvBufClearAllFiles (TempFv); + if (EFI_ERROR (Status)) { + CommonLibBinderFree (TempFv); + return Status; + } + + // TempFv has been allocated. It must now be freed + // before returning. + + FileKey = 0; + while (TRUE) { + + Status = FvBufFindNextFile (Fv, &FileKey, (VOID **)&NextFile); + if (Status == EFI_NOT_FOUND) { + break; + } else if (EFI_ERROR (Status)) { + CommonLibBinderFree (TempFv); + return Status; + } + + if (CommonLibBinderCompareGuid (Name, &NextFile->Name)) { + continue; + } + else { + Status = FvBufAddFile (TempFv, NextFile); + if (EFI_ERROR (Status)) { + CommonLibBinderFree (TempFv); + return Status; + } + } + } + + CommonLibBinderCopyMem (Fv, TempFv, FvLength); + CommonLibBinderFree (TempFv); + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufChecksumFile ( + IN OUT VOID *FfsFile + ) +/*++ + +Routine Description: + + Clears out all files from the Fv buffer in memory + +Arguments: + + SourceFfsFile - Input FFS file to update the checksum for + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + +--*/ +{ + EFI_FFS_FILE_HEADER* File = (EFI_FFS_FILE_HEADER*)FfsFile; + EFI_FFS_FILE_STATE StateBackup; + UINT32 FileSize; + + FileSize = FvBufGetFfsFileSize (File); + + // + // Fill in checksums and state, they must be 0 for checksumming. + // + File->IntegrityCheck.Checksum.Header = 0; + File->IntegrityCheck.Checksum.File = 0; + StateBackup = File->State; + File->State = 0; + + File->IntegrityCheck.Checksum.Header = + FvBufCalculateChecksum8 ( + (UINT8 *) File, + FvBufGetFfsHeaderSize (File) + ); + + if (File->Attributes & FFS_ATTRIB_CHECKSUM) { + File->IntegrityCheck.Checksum.File = FvBufCalculateChecksum8 ( + (VOID*)((UINT8 *)File + FvBufGetFfsHeaderSize (File)), + FileSize - FvBufGetFfsHeaderSize (File) + ); + } else { + File->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + + File->State = StateBackup; + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufChecksumHeader ( + IN OUT VOID *Fv + ) +/*++ + +Routine Description: + + Clears out all files from the Fv buffer in memory + +Arguments: + + SourceFv - Address of the Fv in memory, this firmware volume volume will + be modified, if SourceFfsFile exists + SourceFfsFile - Input FFS file to replace + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER* FvHeader = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + + FvHeader->Checksum = 0; + FvHeader->Checksum = + FvBufCalculateChecksum16 ( + (UINT16*) FvHeader, + FvHeader->HeaderLength / sizeof (UINT16) + ); + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufDuplicate ( + IN VOID *SourceFv, + IN OUT VOID **DestinationFv + ) +/*++ + +Routine Description: + + Clears out all files from the Fv buffer in memory + +Arguments: + + SourceFv - Address of the Fv in memory + DestinationFv - Output for destination Fv + DestinationFv == NULL - invalid parameter + *DestinationFv == NULL - memory will be allocated + *DestinationFv != NULL - this address will be the destination + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + UINTN size; + + if (DestinationFv == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = FvBufGetSize (SourceFv, &size); + if (EFI_ERROR (Status)) { + return Status; + } + + if (*DestinationFv == NULL) { + *DestinationFv = CommonLibBinderAllocate (size); + if (*DestinationFv == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } + + CommonLibBinderCopyMem (*DestinationFv, SourceFv, size); + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufExtend ( + IN VOID **Fv, + IN UINTN Size + ) +/*++ + +Routine Description: + + Extends a firmware volume by the given number of bytes. + + BUGBUG: Does not handle the case where the firmware volume has a + VTF (Volume Top File). The VTF will not be moved to the + end of the extended FV. + +Arguments: + + Fv - Source and destination firmware volume. + Note: The original firmware volume buffer is freed! + + Size - The minimum size that the firmware volume is to be extended by. + The FV may be extended more than this size. + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + UINTN OldSize; + UINTN NewSize; + UINTN BlockCount; + VOID* NewFv; + + EFI_FIRMWARE_VOLUME_HEADER* hdr; + EFI_FV_BLOCK_MAP_ENTRY* blk; + + Status = FvBufGetSize (*Fv, &OldSize); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Locate the block map in the fv header + // + hdr = (EFI_FIRMWARE_VOLUME_HEADER*)*Fv; + blk = hdr->BlockMap; + + // + // Calculate the number of blocks needed to achieve the requested + // size extension + // + BlockCount = ((Size + (blk->Length - 1)) / blk->Length); + + // + // Calculate the new size from the number of blocks that will be added + // + NewSize = OldSize + (BlockCount * blk->Length); + + NewFv = CommonLibBinderAllocate (NewSize); + if (NewFv == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Copy the old data + // + CommonLibBinderCopyMem (NewFv, *Fv, OldSize); + + // + // Free the old fv buffer + // + CommonLibBinderFree (*Fv); + + // + // Locate the block map in the new fv header + // + hdr = (EFI_FIRMWARE_VOLUME_HEADER*)NewFv; + hdr->FvLength = NewSize; + blk = hdr->BlockMap; + + // + // Update the block map for the new fv + // + blk->NumBlocks += (UINT32)BlockCount; + + // + // Update the FV header checksum + // + FvBufChecksumHeader (NewFv); + + // + // Clear out the new area of the FV + // + CommonLibBinderSetMem ( + (UINT8*)NewFv + OldSize, + (NewSize - OldSize), + (hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0 + ); + + // + // Set output with new fv that was created + // + *Fv = NewFv; + + return EFI_SUCCESS; + +} + + +EFI_STATUS +FvBufClearAllFiles ( + IN OUT VOID *Fv + ) +/*++ + +Routine Description: + + Clears out all files from the Fv buffer in memory + +Arguments: + + Fv - Address of the Fv in memory + +Returns: + + EFI_SUCCESS + +--*/ + +{ + EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + EFI_STATUS Status; + UINTN size = 0; + + Status = FvBufGetSize (Fv, &size); + if (EFI_ERROR (Status)) { + return Status; + } + + CommonLibBinderSetMem( + (UINT8*)hdr + hdr->HeaderLength, + size - hdr->HeaderLength, + (hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0 + ); + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufGetSize ( + IN VOID *Fv, + OUT UINTN *Size + ) +/*++ + +Routine Description: + + Clears out all files from the Fv buffer in memory + +Arguments: + + Fv - Address of the Fv in memory + +Returns: + + EFI_SUCCESS + +--*/ + +{ + EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + EFI_FV_BLOCK_MAP_ENTRY *blk = hdr->BlockMap; + + *Size = 0; + + while (blk->Length != 0 || blk->NumBlocks != 0) { + *Size = *Size + (blk->Length * blk->NumBlocks); + if (*Size >= 0x40000000) { + // If size is greater than 1GB, then assume it is corrupted + return EFI_VOLUME_CORRUPTED; + } + blk++; + } + + if (*Size == 0) { + // If size is 0, then assume the volume is corrupted + return EFI_VOLUME_CORRUPTED; + } + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufAddFile ( + IN OUT VOID *Fv, + IN VOID *File + ) +/*++ + +Routine Description: + + Adds a new FFS file + +Arguments: + + Fv - Address of the Fv in memory + File - FFS file to add to Fv + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + + EFI_FFS_FILE_HEADER *fhdr = NULL; + EFI_FVB_ATTRIBUTES_2 FvbAttributes; + UINTN offset; + UINTN fsize; + UINTN newSize; + UINTN clearLoop; + + EFI_STATUS Status; + UINTN fvSize; + + Status = FvBufGetSize (Fv, &fvSize); + if (EFI_ERROR (Status)) { + return Status; + } + + FvbAttributes = hdr->Attributes; + newSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File); + + for( + offset = (UINTN)ALIGN_POINTER (hdr->HeaderLength, 8); + offset + newSize <= fvSize; + offset = (UINTN)ALIGN_POINTER (offset, 8) + ) { + + fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + offset); + + if (EFI_TEST_FFS_ATTRIBUTES_BIT( + FvbAttributes, + fhdr->State, + EFI_FILE_HEADER_VALID + ) + ) { + // BUGBUG: Need to make sure that the new file does not already + // exist. + + fsize = FvBufGetFfsFileSize (fhdr); + if (fsize == 0 || (offset + fsize > fvSize)) { + return EFI_VOLUME_CORRUPTED; + } + + offset = offset + fsize; + continue; + } + + clearLoop = 0; + while ((clearLoop < newSize) && + (((UINT8*)fhdr)[clearLoop] == + (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0) + ) + ) { + clearLoop++; + } + + // + // We found a place in the FV which is empty and big enough for + // the new file + // + if (clearLoop >= newSize) { + break; + } + + offset = offset + 1; // Make some forward progress + } + + if (offset + newSize > fvSize) { + return EFI_OUT_OF_RESOURCES; + } + + CommonLibBinderCopyMem (fhdr, File, newSize); + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufAddFileWithExtend ( + IN OUT VOID **Fv, + IN VOID *File + ) +/*++ + +Routine Description: + + Adds a new FFS file. Extends the firmware volume if needed. + +Arguments: + + Fv - Source and destination firmware volume. + Note: If the FV is extended, then the original firmware volume + buffer is freed! + + Size - The minimum size that the firmware volume is to be extended by. + The FV may be extended more than this size. + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + EFI_FFS_FILE_HEADER* NewFile; + + NewFile = (EFI_FFS_FILE_HEADER*)File; + + // + // Try to add to the capsule volume + // + Status = FvBufAddFile (*Fv, NewFile); + if (Status == EFI_OUT_OF_RESOURCES) { + // + // Try to extend the capsule volume by the size of the file + // + Status = FvBufExtend (Fv, FvBufExpand3ByteSize (NewFile->Size)); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Now, try to add the file again + // + Status = FvBufAddFile (*Fv, NewFile); + } + + return Status; +} + + +EFI_STATUS +FvBufAddVtfFile ( + IN OUT VOID *Fv, + IN VOID *File + ) +/*++ + +Routine Description: + + Adds a new FFS VFT (Volume Top File) file. In other words, adds the + file to the end of the firmware volume. + +Arguments: + + Fv - Address of the Fv in memory + File - FFS file to add to Fv + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + + EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + + EFI_FFS_FILE_HEADER* NewFile; + UINTN NewFileSize; + + UINT8 erasedUint8; + UINTN clearLoop; + + EFI_FFS_FILE_HEADER *LastFile; + UINTN LastFileSize; + + UINTN fvSize; + UINTN Key; + + Status = FvBufGetSize (Fv, &fvSize); + if (EFI_ERROR (Status)) { + return Status; + } + + erasedUint8 = (UINT8)((hdr->Attributes & EFI_FVB2_ERASE_POLARITY) ? 0xFF : 0); + NewFileSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File); + + if (NewFileSize != (UINTN)ALIGN_POINTER (NewFileSize, 8)) { + return EFI_INVALID_PARAMETER; + } + + // + // Find the last file in the FV + // + Key = 0; + LastFile = NULL; + LastFileSize = 0; + do { + Status = FvBufFindNextFile (Fv, &Key, (VOID **)&LastFile); + LastFileSize = FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)File); + } while (!EFI_ERROR (Status)); + + // + // If no files were found, then we start at the beginning of the FV + // + if (LastFile == NULL) { + LastFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + hdr->HeaderLength); + } + + // + // We want to put the new file (VTF) at the end of the FV + // + NewFile = (EFI_FFS_FILE_HEADER*)((UINT8*)hdr + (fvSize - NewFileSize)); + + // + // Check to see if there is enough room for the VTF after the last file + // found in the FV + // + if ((UINT8*)NewFile < ((UINT8*)LastFile + LastFileSize)) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Loop to determine if the end of the FV is empty + // + clearLoop = 0; + while ((clearLoop < NewFileSize) && + (((UINT8*)NewFile)[clearLoop] == erasedUint8) + ) { + clearLoop++; + } + + // + // Check to see if there was not enough room for the file + // + if (clearLoop < NewFileSize) { + return EFI_OUT_OF_RESOURCES; + } + + CommonLibBinderCopyMem (NewFile, File, NewFileSize); + + return EFI_SUCCESS; +} + + +VOID +FvBufCompact3ByteSize ( + OUT VOID* SizeDest, + IN UINT32 Size + ) +/*++ + +Routine Description: + + Expands the 3 byte size commonly used in Firmware Volume data structures + +Arguments: + + Size - Address of the 3 byte array representing the size + +Returns: + + UINT32 + +--*/ +{ + ((UINT8*)SizeDest)[0] = (UINT8)Size; + ((UINT8*)SizeDest)[1] = (UINT8)(Size >> 8); + ((UINT8*)SizeDest)[2] = (UINT8)(Size >> 16); +} + +UINT32 +FvBufGetFfsFileSize ( + IN EFI_FFS_FILE_HEADER *Ffs + ) +/*++ + +Routine Description: + + Get the FFS file size. + +Arguments: + + Ffs - Pointer to FFS header + +Returns: + + UINT32 + +--*/ +{ + if (Ffs == NULL) { + return 0; + } + if (Ffs->Attributes & FFS_ATTRIB_LARGE_FILE) { + return (UINT32) ((EFI_FFS_FILE_HEADER2 *)Ffs)->ExtendedSize; + } + return FvBufExpand3ByteSize(Ffs->Size); +} + +UINT32 +FvBufGetFfsHeaderSize ( + IN EFI_FFS_FILE_HEADER *Ffs + ) +/*++ + +Routine Description: + + Get the FFS header size. + +Arguments: + + Ffs - Pointer to FFS header + +Returns: + + UINT32 + +--*/ +{ + if (Ffs == NULL) { + return 0; + } + if (Ffs->Attributes & FFS_ATTRIB_LARGE_FILE) { + return sizeof(EFI_FFS_FILE_HEADER2); + } + return sizeof(EFI_FFS_FILE_HEADER); +} + +UINT32 +FvBufExpand3ByteSize ( + IN VOID* Size + ) +/*++ + +Routine Description: + + Expands the 3 byte size commonly used in Firmware Volume data structures + +Arguments: + + Size - Address of the 3 byte array representing the size + +Returns: + + UINT32 + +--*/ +{ + return (((UINT8*)Size)[2] << 16) + + (((UINT8*)Size)[1] << 8) + + ((UINT8*)Size)[0]; +} + +EFI_STATUS +FvBufFindNextFile ( + IN VOID *Fv, + IN OUT UINTN *Key, + OUT VOID **File + ) +/*++ + +Routine Description: + + Iterates through the files contained within the firmware volume + +Arguments: + + Fv - Address of the Fv in memory + Key - Should be 0 to get the first file. After that, it should be + passed back in without modifying its contents to retrieve + subsequent files. + File - Output file pointer + File == NULL - invalid parameter + otherwise - *File will be update to the location of the file + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + EFI_VOLUME_CORRUPTED + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + + EFI_FFS_FILE_HEADER *fhdr = NULL; + EFI_FVB_ATTRIBUTES_2 FvbAttributes; + UINTN fsize; + + EFI_STATUS Status; + UINTN fvSize; + + if (Fv == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = FvBufGetSize (Fv, &fvSize); + if (EFI_ERROR (Status)) { + return Status; + } + + if (*Key == 0) { + *Key = hdr->HeaderLength; + } + + FvbAttributes = hdr->Attributes; + + for( + *Key = (UINTN)ALIGN_POINTER (*Key, 8); + (*Key + sizeof (*fhdr)) < fvSize; + *Key = (UINTN)ALIGN_POINTER (*Key, 8) + ) { + + fhdr = (EFI_FFS_FILE_HEADER*) ((UINT8*)hdr + *Key); + fsize = FvBufGetFfsFileSize (fhdr); + + if (!EFI_TEST_FFS_ATTRIBUTES_BIT( + FvbAttributes, + fhdr->State, + EFI_FILE_HEADER_VALID + ) || + EFI_TEST_FFS_ATTRIBUTES_BIT( + FvbAttributes, + fhdr->State, + EFI_FILE_HEADER_INVALID + ) + ) { + *Key = *Key + 1; // Make some forward progress + continue; + } else if( + EFI_TEST_FFS_ATTRIBUTES_BIT( + FvbAttributes, + fhdr->State, + EFI_FILE_MARKED_FOR_UPDATE + ) || + EFI_TEST_FFS_ATTRIBUTES_BIT( + FvbAttributes, + fhdr->State, + EFI_FILE_DELETED + ) + ) { + *Key = *Key + fsize; + continue; + } else if (EFI_TEST_FFS_ATTRIBUTES_BIT( + FvbAttributes, + fhdr->State, + EFI_FILE_DATA_VALID + ) + ) { + *File = (UINT8*)hdr + *Key; + *Key = *Key + fsize; + return EFI_SUCCESS; + } + + *Key = *Key + 1; // Make some forward progress + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +FvBufFindFileByName ( + IN VOID *Fv, + IN EFI_GUID *Name, + OUT VOID **File + ) +/*++ + +Routine Description: + + Searches the Fv for a file by its name + +Arguments: + + Fv - Address of the Fv in memory + Name - Guid filename to search for in the firmware volume + File - Output file pointer + File == NULL - Only determine if the file exists, based on return + value from the function call. + otherwise - *File will be update to the location of the file + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + EFI_VOLUME_CORRUPTED + +--*/ +{ + EFI_STATUS Status; + UINTN Key; + EFI_FFS_FILE_HEADER *NextFile; + + Key = 0; + while (TRUE) { + Status = FvBufFindNextFile (Fv, &Key, (VOID **)&NextFile); + if (EFI_ERROR (Status)) { + return Status; + } + + if (CommonLibBinderCompareGuid (Name, &NextFile->Name)) { + if (File != NULL) { + *File = NextFile; + } + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +FvBufFindFileByType ( + IN VOID *Fv, + IN EFI_FV_FILETYPE Type, + OUT VOID **File + ) +/*++ + +Routine Description: + + Searches the Fv for a file by its type + +Arguments: + + Fv - Address of the Fv in memory + Type - FFS FILE type to search for + File - Output file pointer + (File == NULL) -> Only determine if the file exists, based on return + value from the function call. + otherwise -> *File will be update to the location of the file + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + EFI_VOLUME_CORRUPTED + +--*/ +{ + EFI_STATUS Status; + UINTN Key; + EFI_FFS_FILE_HEADER *NextFile; + + Key = 0; + while (TRUE) { + Status = FvBufFindNextFile (Fv, &Key, (VOID **)&NextFile); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Type == NextFile->Type) { + if (File != NULL) { + *File = NextFile; + } + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +FvBufGetFileRawData ( + IN VOID* FfsFile, + OUT VOID** RawData, + OUT UINTN* RawDataSize + ) +/*++ + +Routine Description: + + Searches the requested file for raw data. + + This routine either returns all the payload of a EFI_FV_FILETYPE_RAW file, + or finds the EFI_SECTION_RAW section within the file and returns its data. + +Arguments: + + FfsFile - Address of the FFS file in memory + RawData - Pointer to the raw data within the file + (This is NOT allocated. It is within the file.) + RawDataSize - Size of the raw data within the file + +Returns: + + EFI_STATUS + +--*/ +{ + EFI_STATUS Status; + EFI_FFS_FILE_HEADER* File; + EFI_RAW_SECTION* Section; + + File = (EFI_FFS_FILE_HEADER*)FfsFile; + + // + // Is the file type == EFI_FV_FILETYPE_RAW? + // + if (File->Type == EFI_FV_FILETYPE_RAW) { + // + // Raw filetypes don't have sections, so we just return the raw data + // + *RawData = (VOID*)((UINT8 *)File + FvBufGetFfsHeaderSize (File)); + *RawDataSize = FvBufGetFfsFileSize (File) - FvBufGetFfsHeaderSize (File); + return EFI_SUCCESS; + } + + // + // Within the file, we now need to find the EFI_SECTION_RAW section. + // + Status = FvBufFindSectionByType (File, EFI_SECTION_RAW, (VOID **)&Section); + if (EFI_ERROR (Status)) { + return Status; + } + + *RawData = (VOID*)((UINT8 *)Section + FvBufGetSecHdrLen(Section)); + *RawDataSize = + FvBufGetSecFileLen (Section) - FvBufGetSecHdrLen(Section); + + return EFI_SUCCESS; + +} + + +EFI_STATUS +FvBufPackageFreeformRawFile ( + IN EFI_GUID* Filename, + IN VOID* RawData, + IN UINTN RawDataSize, + OUT VOID** FfsFile + ) +/*++ + +Routine Description: + + Packages up a FFS file containing the input raw data. + + The file created will have a type of EFI_FV_FILETYPE_FREEFORM, and will + contain one EFI_FV_FILETYPE_RAW section. + +Arguments: + + RawData - Pointer to the raw data to be packed + RawDataSize - Size of the raw data to be packed + FfsFile - Address of the packaged FFS file. + Note: The called must deallocate this memory! + +Returns: + + EFI_STATUS + +--*/ +{ + EFI_FFS_FILE_HEADER* NewFile; + UINT32 NewFileSize; + EFI_RAW_SECTION* NewSection; + UINT32 NewSectionSize; + UINT32 FfsHdrLen; + UINT32 SecHdrLen; + + // + // The section size is the DataSize + the size of the section header + // + NewSectionSize = (UINT32)sizeof (EFI_RAW_SECTION) + (UINT32)RawDataSize; + SecHdrLen = sizeof (EFI_RAW_SECTION); + if (NewSectionSize >= MAX_SECTION_SIZE) { + NewSectionSize = (UINT32)sizeof (EFI_RAW_SECTION2) + (UINT32)RawDataSize; + SecHdrLen = sizeof (EFI_RAW_SECTION2); + } + + // + // The file size is the size of the file header + the section size + // + NewFileSize = sizeof (EFI_FFS_FILE_HEADER) + NewSectionSize; + FfsHdrLen = sizeof (EFI_FFS_FILE_HEADER); + if (NewFileSize >= MAX_FFS_SIZE) { + NewFileSize = sizeof (EFI_FFS_FILE_HEADER2) + NewSectionSize; + FfsHdrLen = sizeof (EFI_FFS_FILE_HEADER2); + } + + // + // Try to allocate a buffer to build the new FFS file in + // + NewFile = CommonLibBinderAllocate (NewFileSize); + if (NewFile == NULL) { + return EFI_OUT_OF_RESOURCES; + } + CommonLibBinderSetMem (NewFile, NewFileSize, 0); + + // + // The NewSection follow right after the FFS file header + // + NewSection = (EFI_RAW_SECTION*)((UINT8*)NewFile + FfsHdrLen); + if (NewSectionSize >= MAX_SECTION_SIZE) { + FvBufCompact3ByteSize (NewSection->Size, 0xffffff); + ((EFI_RAW_SECTION2 *)NewSection)->ExtendedSize = NewSectionSize; + } else { + FvBufCompact3ByteSize (NewSection->Size, NewSectionSize); + } + NewSection->Type = EFI_SECTION_RAW; + + // + // Copy the actual file data into the buffer + // + CommonLibBinderCopyMem ((UINT8 *)NewSection + SecHdrLen, RawData, RawDataSize); + + // + // Initialize the FFS file header + // + CommonLibBinderCopyMem (&NewFile->Name, Filename, sizeof (EFI_GUID)); + NewFile->Attributes = 0; + if (NewFileSize >= MAX_FFS_SIZE) { + FvBufCompact3ByteSize (NewFile->Size, 0x0); + ((EFI_FFS_FILE_HEADER2 *)NewFile)->ExtendedSize = NewFileSize; + NewFile->Attributes |= FFS_ATTRIB_LARGE_FILE; + } else { + FvBufCompact3ByteSize (NewFile->Size, NewFileSize); + } + NewFile->Type = EFI_FV_FILETYPE_FREEFORM; + NewFile->IntegrityCheck.Checksum.Header = + FvBufCalculateChecksum8 ((UINT8*)NewFile, FfsHdrLen); + NewFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + NewFile->State = (UINT8)~( EFI_FILE_HEADER_CONSTRUCTION | + EFI_FILE_HEADER_VALID | + EFI_FILE_DATA_VALID + ); + + *FfsFile = NewFile; + + return EFI_SUCCESS; +} + + +EFI_STATUS +FvBufFindNextSection ( + IN VOID *SectionsStart, + IN UINTN TotalSectionsSize, + IN OUT UINTN *Key, + OUT VOID **Section + ) +/*++ + +Routine Description: + + Iterates through the sections contained within a given array of sections + +Arguments: + + SectionsStart - Address of the start of the FFS sections array + TotalSectionsSize - Total size of all the sections + Key - Should be 0 to get the first section. After that, it should be + passed back in without modifying its contents to retrieve + subsequent files. + Section - Output section pointer + (Section == NULL) -> invalid parameter + otherwise -> *Section will be update to the location of the file + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + EFI_VOLUME_CORRUPTED + +--*/ +{ + EFI_COMMON_SECTION_HEADER *sectionHdr; + UINTN sectionSize; + + *Key = (UINTN)ALIGN_POINTER (*Key, 4); // Sections are DWORD aligned + + if ((*Key + sizeof (*sectionHdr)) > TotalSectionsSize) { + return EFI_NOT_FOUND; + } + + sectionHdr = (EFI_COMMON_SECTION_HEADER*)((UINT8*)SectionsStart + *Key); + sectionSize = FvBufGetSecFileLen (sectionHdr); + + if (sectionSize < sizeof (EFI_COMMON_SECTION_HEADER)) { + return EFI_NOT_FOUND; + } + + if ((*Key + sectionSize) > TotalSectionsSize) { + return EFI_NOT_FOUND; + } + + *Section = (UINT8*)sectionHdr; + *Key = *Key + sectionSize; + return EFI_SUCCESS; + +} + + +EFI_STATUS +FvBufCountSections ( + IN VOID* FfsFile, + IN UINTN* Count + ) +/*++ + +Routine Description: + + Searches the FFS file and counts the number of sections found. + The sections are NOT recursed. + +Arguments: + + FfsFile - Address of the FFS file in memory + Count - The location to store the section count in + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + EFI_VOLUME_CORRUPTED + +--*/ +{ + EFI_STATUS Status; + UINTN Key; + VOID* SectionStart; + UINTN TotalSectionsSize; + EFI_COMMON_SECTION_HEADER* NextSection; + + SectionStart = (VOID*)((UINTN)FfsFile + FvBufGetFfsHeaderSize(FfsFile)); + TotalSectionsSize = + FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)FfsFile) - + FvBufGetFfsHeaderSize(FfsFile); + Key = 0; + *Count = 0; + while (TRUE) { + Status = FvBufFindNextSection ( + SectionStart, + TotalSectionsSize, + &Key, + (VOID **)&NextSection + ); + if (Status == EFI_NOT_FOUND) { + return EFI_SUCCESS; + } else if (EFI_ERROR (Status)) { + return Status; + } + + // + // Increment the section counter + // + *Count += 1; + + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +FvBufFindSectionByType ( + IN VOID *FfsFile, + IN UINT8 Type, + OUT VOID **Section + ) +/*++ + +Routine Description: + + Searches the FFS file for a section by its type + +Arguments: + + FfsFile - Address of the FFS file in memory + Type - FFS FILE section type to search for + Section - Output section pointer + (Section == NULL) -> Only determine if the section exists, based on return + value from the function call. + otherwise -> *Section will be update to the location of the file + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + EFI_VOLUME_CORRUPTED + +--*/ +{ + EFI_STATUS Status; + UINTN Key; + VOID* SectionStart; + UINTN TotalSectionsSize; + EFI_COMMON_SECTION_HEADER* NextSection; + + SectionStart = (VOID*)((UINTN)FfsFile + FvBufGetFfsHeaderSize(FfsFile)); + TotalSectionsSize = + FvBufGetFfsFileSize ((EFI_FFS_FILE_HEADER*)FfsFile) - + FvBufGetFfsHeaderSize(FfsFile); + Key = 0; + while (TRUE) { + Status = FvBufFindNextSection ( + SectionStart, + TotalSectionsSize, + &Key, + (VOID **)&NextSection + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (Type == NextSection->Type) { + if (Section != NULL) { + *Section = NextSection; + } + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + + +EFI_STATUS +FvBufShrinkWrap ( + IN VOID *Fv + ) +/*++ + +Routine Description: + + Shrinks a firmware volume (in place) to provide a minimal FV. + + BUGBUG: Does not handle the case where the firmware volume has a + VTF (Volume Top File). The VTF will not be moved to the + end of the extended FV. + +Arguments: + + Fv - Firmware volume. + +Returns: + + EFI_SUCCESS + +--*/ +{ + EFI_STATUS Status; + UINTN OldSize; + UINT32 BlockCount; + UINT32 NewBlockSize = 128; + UINTN Key; + EFI_FFS_FILE_HEADER* FileIt; + VOID* EndOfLastFile; + + EFI_FIRMWARE_VOLUME_HEADER* FvHdr; + + Status = FvBufGetSize (Fv, &OldSize); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = FvBufUnifyBlockSizes (Fv, NewBlockSize); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Locate the block map in the fv header + // + FvHdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + + // + // Find the end of the last file + // + Key = 0; + EndOfLastFile = (UINT8*)FvHdr + FvHdr->FvLength; + while (!EFI_ERROR (FvBufFindNextFile (Fv, &Key, (VOID **)&FileIt))) { + EndOfLastFile = + (VOID*)((UINT8*)FileIt + FvBufGetFfsFileSize (FileIt)); + } + + // + // Set the BlockCount to have the minimal number of blocks for the Fv. + // + BlockCount = (UINT32)((UINTN)EndOfLastFile - (UINTN)Fv); + BlockCount = BlockCount + NewBlockSize - 1; + BlockCount = BlockCount / NewBlockSize; + + // + // Adjust the block count to shrink the Fv in place. + // + FvHdr->BlockMap[0].NumBlocks = BlockCount; + FvHdr->FvLength = BlockCount * NewBlockSize; + + // + // Update the FV header checksum + // + FvBufChecksumHeader (Fv); + + return EFI_SUCCESS; + +} + + +EFI_STATUS +FvBufUnifyBlockSizes ( + IN OUT VOID *Fv, + IN UINTN BlockSize + ) +/*++ + +Routine Description: + + Searches the FFS file for a section by its type + +Arguments: + + Fv - Address of the Fv in memory + BlockSize - The size of the blocks to convert the Fv to. If the total size + of the Fv is not evenly divisible by this size, then + EFI_INVALID_PARAMETER will be returned. + +Returns: + + EFI_SUCCESS + EFI_NOT_FOUND + EFI_VOLUME_CORRUPTED + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER *hdr = (EFI_FIRMWARE_VOLUME_HEADER*)Fv; + EFI_FV_BLOCK_MAP_ENTRY *blk = hdr->BlockMap; + UINT32 Size; + + Size = 0; + + // + // Scan through the block map list, performing error checking, and adding + // up the total Fv size. + // + while( blk->Length != 0 || + blk->NumBlocks != 0 + ) { + Size = Size + (blk->Length * blk->NumBlocks); + blk++; + if ((UINT8*)blk > ((UINT8*)hdr + hdr->HeaderLength)) { + return EFI_VOLUME_CORRUPTED; + } + } + + // + // Make sure that the Fv size is a multiple of the new block size. + // + if ((Size % BlockSize) != 0) { + return EFI_INVALID_PARAMETER; + } + + // + // Zero out the entire block map. + // + CommonLibBinderSetMem ( + &hdr->BlockMap, + (UINTN)blk - (UINTN)&hdr->BlockMap, + 0 + ); + + // + // Write out the single block map entry. + // + hdr->BlockMap[0].Length = (UINT32)BlockSize; + hdr->BlockMap[0].NumBlocks = Size / (UINT32)BlockSize; + + return EFI_SUCCESS; +} + +STATIC +UINT16 +FvBufCalculateSum16 ( + IN UINT16 *Buffer, + IN UINTN Size + ) +/*++ + +Routine Description: + + This function calculates the UINT16 sum for the requested region. + +Arguments: + + Buffer Pointer to buffer containing byte data of component. + Size Size of the buffer + +Returns: + + The 16 bit checksum + +--*/ +{ + UINTN Index; + UINT16 Sum; + + Sum = 0; + + // + // Perform the word sum for buffer + // + for (Index = 0; Index < Size; Index++) { + Sum = (UINT16) (Sum + Buffer[Index]); + } + + return (UINT16) Sum; +} + + +STATIC +UINT16 +FvBufCalculateChecksum16 ( + IN UINT16 *Buffer, + IN UINTN Size + ) +/*++ + +Routine Description:: + + This function calculates the value needed for a valid UINT16 checksum + +Arguments: + + Buffer Pointer to buffer containing byte data of component. + Size Size of the buffer + +Returns: + + The 16 bit checksum value needed. + +--*/ +{ + return (UINT16)(0x10000 - FvBufCalculateSum16 (Buffer, Size)); +} + + +STATIC +UINT8 +FvBufCalculateSum8 ( + IN UINT8 *Buffer, + IN UINTN Size + ) +/*++ + +Description: + + This function calculates the UINT8 sum for the requested region. + +Input: + + Buffer Pointer to buffer containing byte data of component. + Size Size of the buffer + +Return: + + The 8 bit checksum value needed. + +--*/ +{ + UINTN Index; + UINT8 Sum; + + Sum = 0; + + // + // Perform the byte sum for buffer + // + for (Index = 0; Index < Size; Index++) { + Sum = (UINT8) (Sum + Buffer[Index]); + } + + return Sum; +} + + +STATIC +UINT8 +FvBufCalculateChecksum8 ( + IN UINT8 *Buffer, + IN UINTN Size + ) +/*++ + +Description: + + This function calculates the value needed for a valid UINT8 checksum + +Input: + + Buffer Pointer to buffer containing byte data of component. + Size Size of the buffer + +Return: + + The 8 bit checksum value needed. + +--*/ +{ + return (UINT8)(0x100 - FvBufCalculateSum8 (Buffer, Size)); +} + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FirmwareVolumeBufferLib.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FirmwareVolumeBufferLib.h new file mode 100644 index 00000000..6ba9e80e --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FirmwareVolumeBufferLib.h @@ -0,0 +1,163 @@ +/** @file +EFI Firmware Volume routines which work on a Fv image in buffers. + +Copyright (c) 1999 - 2014, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef FirmwareVolumeBuffer_h_INCLUDED +#define FirmwareVolumeBuffer_h_INCLUDED + +#include "Common/UefiBaseTypes.h" +#include "Common/PiFirmwareFile.h" +#include "Common/PiFirmwareVolume.h" + +EFI_STATUS +FvBufAddFile ( + IN OUT VOID *Fv, + IN VOID *File + ); + +EFI_STATUS +FvBufAddFileWithExtend ( + IN OUT VOID **Fv, + IN VOID *File + ); + +EFI_STATUS +FvBufAddVtfFile ( + IN OUT VOID *Fv, + IN VOID *File + ); + +EFI_STATUS +FvBufChecksumFile ( + IN OUT VOID *FfsFile + ); + +EFI_STATUS +FvBufChecksumHeader ( + IN OUT VOID *Fv + ); + +EFI_STATUS +FvBufClearAllFiles ( + IN OUT VOID *Fv + ); + +VOID +FvBufCompact3ByteSize ( + OUT VOID* SizeDest, + IN UINT32 Size + ); + +EFI_STATUS +FvBufCountSections ( + IN VOID* FfsFile, + IN UINTN* Count + ); + +EFI_STATUS +FvBufDuplicate ( + IN VOID *SourceFv, + IN OUT VOID **DestinationFv + ); + +UINT32 +FvBufExpand3ByteSize ( + IN VOID* Size + ); + +UINT32 +FvBufGetFfsFileSize ( + IN EFI_FFS_FILE_HEADER *Ffs + ); + +UINT32 +FvBufGetFfsHeaderSize ( + IN EFI_FFS_FILE_HEADER *Ffs + ); + +EFI_STATUS +FvBufExtend ( + IN VOID **Fv, + IN UINTN Size + ); + +EFI_STATUS +FvBufFindFileByName ( + IN VOID *Fv, + IN EFI_GUID *Name, + OUT VOID **File + ); + +EFI_STATUS +FvBufFindFileByType ( + IN VOID *Fv, + IN EFI_FV_FILETYPE Type, + OUT VOID **File + ); + +EFI_STATUS +FvBufFindNextFile ( + IN VOID *Fv, + IN OUT UINTN *Key, + OUT VOID **File + ); + +EFI_STATUS +FvBufFindNextSection ( + IN VOID *SectionsStart, + IN UINTN TotalSectionsSize, + IN OUT UINTN *Key, + OUT VOID **Section + ); + +EFI_STATUS +FvBufFindSectionByType ( + IN VOID *FfsFile, + IN UINT8 Type, + OUT VOID **Section + ); + +EFI_STATUS +FvBufGetFileRawData ( + IN VOID* FfsFile, + OUT VOID** RawData, + OUT UINTN* RawDataSize + ); + +EFI_STATUS +FvBufGetSize ( + IN VOID *Fv, + OUT UINTN *Size + ); + +EFI_STATUS +FvBufPackageFreeformRawFile ( + IN EFI_GUID* Filename, + IN VOID* RawData, + IN UINTN RawDataSize, + OUT VOID** FfsFile + ); + +EFI_STATUS +FvBufRemoveFile ( + IN OUT VOID *Fv, + IN EFI_GUID *Name + ); + +EFI_STATUS +FvBufUnifyBlockSizes ( + IN OUT VOID *Fv, + IN UINTN BlockSize + ); + +EFI_STATUS +FvBufShrinkWrap ( + IN VOID *Fv + ); + +#endif // #ifndef FirmwareVolumeBuffer_h_INCLUDED + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FvLib.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FvLib.c new file mode 100644 index 00000000..d9f45930 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FvLib.c @@ -0,0 +1,927 @@ +/** @file +These functions assist in parsing and manipulating a Firmware Volume. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +// +// Include files +// +#include "FvLib.h" +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" + +// +// Module global variables +// +EFI_FIRMWARE_VOLUME_HEADER *mFvHeader = NULL; +UINT32 mFvLength = 0; + +// +// External function implementations +// +EFI_STATUS +InitializeFvLib ( + IN VOID *Fv, + IN UINT32 FvLength + ) +/*++ + +Routine Description: + + This initializes the FV lib with a pointer to the FV and length. It does not + verify the FV in any way. + +Arguments: + + Fv Buffer containing the FV. + FvLength Length of the FV + +Returns: + + EFI_SUCCESS Function Completed successfully. + EFI_INVALID_PARAMETER A required parameter was NULL. + +--*/ +{ + // + // Verify input arguments + // + if (Fv == NULL) { + return EFI_INVALID_PARAMETER; + } + + mFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) Fv; + mFvLength = FvLength; + + return EFI_SUCCESS; +} + +EFI_STATUS +GetFvHeader ( + OUT EFI_FIRMWARE_VOLUME_HEADER **FvHeader, + OUT UINT32 *FvLength + ) +/*++ + +Routine Description: + + This function returns a pointer to the current FV and the size. + +Arguments: + + FvHeader Pointer to the FV buffer. + FvLength Length of the FV + +Returns: + + EFI_SUCCESS Function Completed successfully. + EFI_INVALID_PARAMETER A required parameter was NULL. + EFI_ABORTED The library needs to be initialized. + +--*/ +{ + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify input arguments + // + if (FvHeader == NULL) { + return EFI_INVALID_PARAMETER; + } + + *FvHeader = mFvHeader; + *FvLength = mFvLength; + return EFI_SUCCESS; +} + +EFI_STATUS +GetNextFile ( + IN EFI_FFS_FILE_HEADER *CurrentFile, + OUT EFI_FFS_FILE_HEADER **NextFile + ) +/*++ + +Routine Description: + + This function returns the next file. If the current file is NULL, it returns + the first file in the FV. If the function returns EFI_SUCCESS and the file + pointer is NULL, then there are no more files in the FV. + +Arguments: + + CurrentFile Pointer to the current file, must be within the current FV. + NextFile Pointer to the next file in the FV. + +Returns: + + EFI_SUCCESS Function completed successfully. + EFI_INVALID_PARAMETER A required parameter was NULL or is out of range. + EFI_ABORTED The library needs to be initialized. + +--*/ +{ + EFI_STATUS Status; + + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify input arguments + // + if (NextFile == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Verify FV header + // + Status = VerifyFv (mFvHeader); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Get first file + // + if (CurrentFile == NULL) { + CurrentFile = (EFI_FFS_FILE_HEADER *) ((UINTN) mFvHeader + mFvHeader->HeaderLength); + + // + // Verify file is valid + // + Status = VerifyFfsFile (CurrentFile); + if (EFI_ERROR (Status)) { + // + // no files in this FV + // + *NextFile = NULL; + return EFI_SUCCESS; + } else { + // + // Verify file is in this FV. + // + if ((UINTN) CurrentFile + GetFfsFileLength(CurrentFile) > (UINTN) mFvHeader + mFvLength) { + *NextFile = NULL; + return EFI_SUCCESS; + } + + *NextFile = CurrentFile; + return EFI_SUCCESS; + } + } + // + // Verify current file is in range + // + if (((UINTN) CurrentFile < (UINTN) mFvHeader + mFvHeader->HeaderLength) || + ((UINTN) CurrentFile + GetFfsFileLength(CurrentFile) > (UINTN) mFvHeader + mFvLength) + ) { + return EFI_INVALID_PARAMETER; + } + // + // Get next file, compensate for 8 byte alignment if necessary. + // + *NextFile = (EFI_FFS_FILE_HEADER *) ((((UINTN) CurrentFile - (UINTN) mFvHeader + GetFfsFileLength(CurrentFile) + 0x07) & (~(UINTN) 7)) + (UINT8 *) mFvHeader); + + // + // Verify file is in this FV. + // + if (((UINTN) *NextFile + GetFfsHeaderLength(*NextFile) >= (UINTN) mFvHeader + mFvLength) || + ((UINTN) *NextFile + GetFfsFileLength (*NextFile) > (UINTN) mFvHeader + mFvLength) + ) { + *NextFile = NULL; + return EFI_SUCCESS; + } + // + // Verify file is valid + // + Status = VerifyFfsFile (*NextFile); + if (EFI_ERROR (Status)) { + // + // no more files in this FV + // + *NextFile = NULL; + return EFI_SUCCESS; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetFileByName ( + IN EFI_GUID *FileName, + OUT EFI_FFS_FILE_HEADER **File + ) +/*++ + +Routine Description: + + Find a file by name. The function will return NULL if the file is not found. + +Arguments: + + FileName The GUID file name of the file to search for. + File Return pointer. In the case of an error, contents are undefined. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_ABORTED An error was encountered. + EFI_INVALID_PARAMETER One of the parameters was NULL. + +--*/ +{ + EFI_FFS_FILE_HEADER *CurrentFile; + EFI_STATUS Status; + CHAR8 FileGuidString[80]; + + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify input parameters + // + if (FileName == NULL || File == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // File Guid String Name + // + PrintGuidToBuffer (FileName, (UINT8 *)FileGuidString, sizeof (FileGuidString), TRUE); + // + // Verify FV header + // + Status = VerifyFv (mFvHeader); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Get the first file + // + Status = GetNextFile (NULL, &CurrentFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "error parsing FV image", "FFS file with Guid %s can't be found", FileGuidString); + return EFI_ABORTED; + } + // + // Loop as long as we have a valid file + // + while (CurrentFile) { + if (!CompareGuid (&CurrentFile->Name, FileName)) { + *File = CurrentFile; + return EFI_SUCCESS; + } + + Status = GetNextFile (CurrentFile, &CurrentFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "error parsing FV image", "FFS file with Guid %s can't be found", FileGuidString); + return EFI_ABORTED; + } + } + // + // File not found in this FV. + // + *File = NULL; + return EFI_SUCCESS; +} + +EFI_STATUS +GetFileByType ( + IN EFI_FV_FILETYPE FileType, + IN UINTN Instance, + OUT EFI_FFS_FILE_HEADER **File + ) +/*++ + +Routine Description: + + Find a file by type and instance. An instance of 1 is the first instance. + The function will return NULL if a matching file cannot be found. + File type EFI_FV_FILETYPE_ALL means any file type is valid. + +Arguments: + + FileType Type of file to search for. + Instance Instance of the file type to return. + File Return pointer. In the case of an error, contents are undefined. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_ABORTED An error was encountered. + EFI_INVALID_PARAMETER One of the parameters was NULL. + +--*/ +{ + EFI_FFS_FILE_HEADER *CurrentFile; + EFI_STATUS Status; + UINTN FileCount; + + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify input parameters + // + if (File == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Verify FV header + // + Status = VerifyFv (mFvHeader); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Initialize the number of matching files found. + // + FileCount = 0; + + // + // Get the first file + // + Status = GetNextFile (NULL, &CurrentFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "error parsing FV image", "FFS file with FileType 0x%x can't be found", FileType); + return EFI_ABORTED; + } + // + // Loop as long as we have a valid file + // + while (CurrentFile) { + if (FileType == EFI_FV_FILETYPE_ALL || CurrentFile->Type == FileType) { + FileCount++; + } + + if (FileCount == Instance) { + *File = CurrentFile; + return EFI_SUCCESS; + } + + Status = GetNextFile (CurrentFile, &CurrentFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "error parsing FV image", "FFS file with FileType 0x%x can't be found", FileType); + return EFI_ABORTED; + } + } + + *File = NULL; + return EFI_SUCCESS; +} + +EFI_STATUS +SearchSectionByType ( + IN EFI_FILE_SECTION_POINTER FirstSection, + IN UINT8 *SearchEnd, + IN EFI_SECTION_TYPE SectionType, + IN OUT UINTN *StartIndex, + IN UINTN Instance, + OUT EFI_FILE_SECTION_POINTER *Section + ) +/*++ + +Routine Description: + + Helper function to search a sequence of sections from the section pointed + by FirstSection to SearchEnd for the Instance-th section of type SectionType. + The current counter is saved in StartIndex and when the section is found, it's + saved in Section. GUID-defined sections, if special processing is not required, + are searched recursively in a depth-first manner. + +Arguments: + + FirstSection The first section to start searching from. + SearchEnd The end address to stop search. + SectionType The type of section to search. + StartIndex The current counter is saved. + Instance The requested n-th section number. + Section The found section returned. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_NOT_FOUND The section is not found. +--*/ +{ + EFI_FILE_SECTION_POINTER CurrentSection; + EFI_FILE_SECTION_POINTER InnerSection; + EFI_STATUS Status; + UINTN SectionSize; + UINT16 GuidSecAttr; + UINT16 GuidDataOffset; + + GuidSecAttr = 0; + GuidDataOffset = 0; + CurrentSection = FirstSection; + + while ((UINTN) CurrentSection.CommonHeader < (UINTN) SearchEnd) { + if (CurrentSection.CommonHeader->Type == SectionType) { + (*StartIndex)++; + } + + if (*StartIndex == Instance) { + *Section = CurrentSection; + return EFI_SUCCESS; + } + // + // If the requesting section is not GUID-defined and + // we find a GUID-defined section that doesn't need + // special processing, go ahead to search the requesting + // section inside the GUID-defined section. + // + if (CurrentSection.CommonHeader->Type == EFI_SECTION_GUID_DEFINED) { + if (GetLength(CurrentSection.CommonHeader->Size) == 0xffffff) { + GuidSecAttr = CurrentSection.GuidDefinedSection2->Attributes; + GuidDataOffset = CurrentSection.GuidDefinedSection2->DataOffset; + } else { + GuidSecAttr = CurrentSection.GuidDefinedSection->Attributes; + GuidDataOffset = CurrentSection.GuidDefinedSection->DataOffset; + } + } + if (SectionType != EFI_SECTION_GUID_DEFINED && + CurrentSection.CommonHeader->Type == EFI_SECTION_GUID_DEFINED && + !(GuidSecAttr & EFI_GUIDED_SECTION_PROCESSING_REQUIRED)) { + InnerSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) + ((UINTN) CurrentSection.CommonHeader + GuidDataOffset); + SectionSize = GetSectionFileLength(CurrentSection.CommonHeader); + Status = SearchSectionByType ( + InnerSection, + (UINT8 *) ((UINTN) CurrentSection.CommonHeader + SectionSize), + SectionType, + StartIndex, + Instance, + Section + ); + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + } + // + // Find next section (including compensating for alignment issues. + // + CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((((UINTN) CurrentSection.CommonHeader) + GetSectionFileLength(CurrentSection.CommonHeader) + 0x03) & (~(UINTN) 3)); + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +GetSectionByType ( + IN EFI_FFS_FILE_HEADER *File, + IN EFI_SECTION_TYPE SectionType, + IN UINTN Instance, + OUT EFI_FILE_SECTION_POINTER *Section + ) +/*++ + +Routine Description: + + Find a section in a file by type and instance. An instance of 1 is the first + instance. The function will return NULL if a matching section cannot be found. + GUID-defined sections, if special processing is not needed, are handled in a + depth-first manner. + +Arguments: + + File The file to search. + SectionType Type of file to search for. + Instance Instance of the section to return. + Section Return pointer. In the case of an error, contents are undefined. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_ABORTED An error was encountered. + EFI_INVALID_PARAMETER One of the parameters was NULL. + EFI_NOT_FOUND No found. +--*/ +{ + EFI_FILE_SECTION_POINTER CurrentSection; + EFI_STATUS Status; + UINTN SectionCount; + + // + // Verify input parameters + // + if (File == NULL || Instance == 0) { + return EFI_INVALID_PARAMETER; + } + // + // Verify FFS header + // + Status = VerifyFfsFile (File); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0006, "invalid FFS file", NULL); + return EFI_ABORTED; + } + // + // Initialize the number of matching sections found. + // + SectionCount = 0; + + // + // Get the first section + // + CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) File + GetFfsHeaderLength(File)); + + // + // Depth-first manner to find section file. + // + Status = SearchSectionByType ( + CurrentSection, + (UINT8 *) ((UINTN) File + GetFfsFileLength (File)), + SectionType, + &SectionCount, + Instance, + Section + ); + + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } else { + // + // Section not found + // + (*Section).Code16Section = NULL; + return EFI_NOT_FOUND; + } +} +// +// will not parse compressed sections +// +EFI_STATUS +VerifyFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader + ) +/*++ + +Routine Description: + + Verify the current pointer points to a valid FV header. + +Arguments: + + FvHeader Pointer to an alleged FV file. + +Returns: + + EFI_SUCCESS The FV header is valid. + EFI_VOLUME_CORRUPTED The FV header is not valid. + EFI_INVALID_PARAMETER A required parameter was NULL. + EFI_ABORTED Operation aborted. + +--*/ +{ + UINT16 Checksum; + + // + // Verify input parameters + // + if (FvHeader == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (FvHeader->Signature != EFI_FVH_SIGNATURE) { + Error (NULL, 0, 0006, "invalid FV header signature", NULL); + return EFI_VOLUME_CORRUPTED; + } + // + // Verify header checksum + // + Checksum = CalculateSum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + + if (Checksum != 0) { + Error (NULL, 0, 0006, "invalid FV header checksum", NULL); + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +VerifyFfsFile ( + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + + Verify the current pointer points to a FFS file header. + +Arguments: + + FfsHeader Pointer to an alleged FFS file. + +Returns: + + EFI_SUCCESS The Ffs header is valid. + EFI_NOT_FOUND This "file" is the beginning of free space. + EFI_VOLUME_CORRUPTED The Ffs header is not valid. + EFI_ABORTED The erase polarity is not known. + +--*/ +{ + BOOLEAN ErasePolarity; + EFI_STATUS Status; + EFI_FFS_FILE_HEADER2 BlankHeader; + UINT8 Checksum; + UINT32 FileLength; + UINT8 SavedChecksum; + UINT8 SavedState; + UINT8 FileGuidString[80]; + UINT32 FfsHeaderSize; + + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify FV header + // + Status = VerifyFv (mFvHeader); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Get the erase polarity. + // + Status = GetErasePolarity (&ErasePolarity); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + + FfsHeaderSize = GetFfsHeaderLength(FfsHeader); + // + // Check if we have free space + // + if (ErasePolarity) { + memset (&BlankHeader, -1, FfsHeaderSize); + } else { + memset (&BlankHeader, 0, FfsHeaderSize); + } + + if (memcmp (&BlankHeader, FfsHeader, FfsHeaderSize) == 0) { + return EFI_NOT_FOUND; + } + // + // Convert the GUID to a string so we can at least report which file + // if we find an error. + // + PrintGuidToBuffer (&FfsHeader->Name, FileGuidString, sizeof (FileGuidString), TRUE); + // + // Verify file header checksum + // + SavedState = FfsHeader->State; + FfsHeader->State = 0; + SavedChecksum = FfsHeader->IntegrityCheck.Checksum.File; + FfsHeader->IntegrityCheck.Checksum.File = 0; + Checksum = CalculateSum8 ((UINT8 *) FfsHeader, FfsHeaderSize); + FfsHeader->State = SavedState; + FfsHeader->IntegrityCheck.Checksum.File = SavedChecksum; + if (Checksum != 0) { + Error (NULL, 0, 0006, "invalid FFS file header checksum", "Ffs file with Guid %s", FileGuidString); + return EFI_ABORTED; + } + // + // Verify file checksum + // + if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) { + // + // Verify file data checksum + // + FileLength = GetFfsFileLength (FfsHeader); + Checksum = CalculateSum8 ((UINT8 *) ((UINT8 *)FfsHeader + FfsHeaderSize), FileLength - FfsHeaderSize); + Checksum = Checksum + FfsHeader->IntegrityCheck.Checksum.File; + if (Checksum != 0) { + Error (NULL, 0, 0006, "invalid FFS file checksum", "Ffs file with Guid %s", FileGuidString); + return EFI_ABORTED; + } + } else { + // + // File does not have a checksum + // Verify contents are 0xAA as spec'd + // + if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) { + Error (NULL, 0, 0006, "invalid fixed FFS file header checksum", "Ffs file with Guid %s", FileGuidString); + return EFI_ABORTED; + } + } + + return EFI_SUCCESS; +} + +UINT32 +GetFfsHeaderLength( + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +{ + if (FfsHeader == NULL) { + return 0; + } + if (FfsHeader->Attributes & FFS_ATTRIB_LARGE_FILE) { + return sizeof(EFI_FFS_FILE_HEADER2); + } + return sizeof(EFI_FFS_FILE_HEADER); +} + +UINT32 +GetSectionHeaderLength( + IN EFI_COMMON_SECTION_HEADER *SectionHeader + ) +{ + if (SectionHeader == NULL) { + return 0; + } + if (GetLength(SectionHeader->Size) == 0xffffff) { + return sizeof(EFI_COMMON_SECTION_HEADER2); + } + return sizeof(EFI_COMMON_SECTION_HEADER); +} + +UINT32 +GetFfsFileLength ( + EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + + Get FFS file length including FFS header. + +Arguments: + + FfsHeader Pointer to EFI_FFS_FILE_HEADER. + +Returns: + + UINT32 Length of FFS file header. + +--*/ +{ + if (FfsHeader == NULL) { + return 0; + } + if (FfsHeader->Attributes & FFS_ATTRIB_LARGE_FILE) { + return (UINT32) ((EFI_FFS_FILE_HEADER2 *)FfsHeader)->ExtendedSize; + } else { + return GetLength(FfsHeader->Size); + } +} + +UINT32 +GetSectionFileLength ( + EFI_COMMON_SECTION_HEADER *SectionHeader + ) +{ + UINT32 Length; + if (SectionHeader == NULL) { + return 0; + } + Length = GetLength(SectionHeader->Size); + if (Length == 0xffffff) { + Length = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize; + } + return Length; +} + +UINT32 +GetLength ( + UINT8 *ThreeByteLength + ) +/*++ + +Routine Description: + + Converts a three byte length value into a UINT32. + +Arguments: + + ThreeByteLength Pointer to the first of the 3 byte length. + +Returns: + + UINT32 Size of the section + +--*/ +{ + UINT32 Length; + + if (ThreeByteLength == NULL) { + return 0; + } + + Length = *((UINT32 *) ThreeByteLength); + Length = Length & 0x00FFFFFF; + + return Length; +} + +EFI_STATUS +GetErasePolarity ( + OUT BOOLEAN *ErasePolarity + ) +/*++ + +Routine Description: + + This function returns with the FV erase polarity. If the erase polarity + for a bit is 1, the function return TRUE. + +Arguments: + + ErasePolarity A pointer to the erase polarity. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED Operation aborted. + +--*/ +{ + EFI_STATUS Status; + + // + // Verify library has been initialized. + // + if (mFvHeader == NULL || mFvLength == 0) { + return EFI_ABORTED; + } + // + // Verify FV header + // + Status = VerifyFv (mFvHeader); + if (EFI_ERROR (Status)) { + return EFI_ABORTED; + } + // + // Verify input parameters. + // + if (ErasePolarity == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (mFvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) { + *ErasePolarity = TRUE; + } else { + *ErasePolarity = FALSE; + } + + return EFI_SUCCESS; +} + +UINT8 +GetFileState ( + IN BOOLEAN ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +/*++ + +Routine Description: + + This function returns a the highest state bit in the FFS that is set. + It in no way validate the FFS file. + +Arguments: + + ErasePolarity The erase polarity for the file state bits. + FfsHeader Pointer to a FFS file. + +Returns: + + UINT8 The hightest set state of the file. + +--*/ +{ + UINT8 FileState; + UINT8 HighestBit; + + FileState = FfsHeader->State; + + if (ErasePolarity) { + FileState = (UINT8)~FileState; + } + + HighestBit = 0x80; + while (HighestBit != 0 && (HighestBit & FileState) == 0) { + HighestBit >>= 1; + } + + return HighestBit; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FvLib.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FvLib.h new file mode 100644 index 00000000..0128779e --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/FvLib.h @@ -0,0 +1,189 @@ +/** @file +These functions assist in parsing and manipulating a Firmware Volume. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_FV_LIB_H +#define _EFI_FV_LIB_H + +// +// Include files +// +#include + +#include +#include +#include + +EFI_STATUS +InitializeFvLib ( + IN VOID *Fv, + IN UINT32 FvLength + ) +; + +EFI_STATUS +GetFvHeader ( + OUT EFI_FIRMWARE_VOLUME_HEADER **FvHeader, + OUT UINT32 *FvLength + ) +; + +EFI_STATUS +GetNextFile ( + IN EFI_FFS_FILE_HEADER *CurrentFile, + OUT EFI_FFS_FILE_HEADER **NextFile + ) +; + +EFI_STATUS +GetFileByName ( + IN EFI_GUID *FileName, + OUT EFI_FFS_FILE_HEADER **File + ) +; + +EFI_STATUS +GetFileByType ( + IN EFI_FV_FILETYPE FileType, + IN UINTN Instance, + OUT EFI_FFS_FILE_HEADER **File + ) +; + +EFI_STATUS +GetSectionByType ( + IN EFI_FFS_FILE_HEADER *File, + IN EFI_SECTION_TYPE SectionType, + IN UINTN Instance, + OUT EFI_FILE_SECTION_POINTER *Section + ) +; +// +// will not parse compressed sections +// +EFI_STATUS +VerifyFv ( + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader + ) +; + +EFI_STATUS +VerifyFfsFile ( + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +; + +UINT32 +GetFfsFileLength ( + EFI_FFS_FILE_HEADER *FfsHeader + ) +; + +UINT32 +GetSectionFileLength ( + EFI_COMMON_SECTION_HEADER *SectionHeader + ) +; + +UINT32 +GetFfsHeaderLength( + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +; + +UINT32 +GetSectionHeaderLength( + IN EFI_COMMON_SECTION_HEADER *SectionHeader + ) +; + +/*++ + +Routine Description: + + Verify the current pointer points to a FFS file header. + +Arguments: + + FfsHeader Pointer to an alleged FFS file. + +Returns: + + EFI_SUCCESS The Ffs header is valid. + EFI_NOT_FOUND This "file" is the beginning of free space. + EFI_VOLUME_CORRUPTED The Ffs header is not valid. + +--*/ +UINT32 +GetLength ( + UINT8 *ThreeByteLength + ) +; + +/*++ + +Routine Description: + + Converts a three byte length value into a UINT32. + +Arguments: + + ThreeByteLength Pointer to the first of the 3 byte length. + +Returns: + + UINT32 Size of the section + +--*/ +EFI_STATUS +GetErasePolarity ( + OUT BOOLEAN *ErasePolarity + ) +; + +/*++ + +Routine Description: + + This function returns with the FV erase polarity. If the erase polarity + for a bit is 1, the function return TRUE. + +Arguments: + + ErasePolarity A pointer to the erase polarity. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + +--*/ +UINT8 +GetFileState ( + IN BOOLEAN ErasePolarity, + IN EFI_FFS_FILE_HEADER *FfsHeader + ) +; + +/*++ + +Routine Description: + + This function returns a the highest state bit in the FFS that is set. + It in no way validate the FFS file. + +Arguments: + + ErasePolarity The erase polarity for the file state bits. + FfsHeader Pointer to a FFS file. + +Returns: + + UINT8 The hightest set state of the file. + +--*/ +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/GNUmakefile new file mode 100644 index 00000000..a2ff48f3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/GNUmakefile @@ -0,0 +1,33 @@ +## @file +# GNU/Linux makefile for 'Common' module build. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +MAKEROOT ?= .. + +# VPATH = .. + +LIBNAME = Common + +OBJECTS = \ + BasePeCoff.o \ + BinderFuncs.o \ + CommonLib.o \ + Crc32.o \ + Decompress.o \ + EfiCompress.o \ + EfiUtilityMsgs.o \ + FirmwareVolumeBuffer.o \ + FvLib.o \ + MemoryFile.o \ + MyAlloc.o \ + OsPath.o \ + ParseGuidedSectionTools.o \ + ParseInf.o \ + PeCoffLoaderEx.o \ + SimpleFileParsing.o \ + StringFuncs.o \ + TianoCompress.o + +include $(MAKEROOT)/Makefiles/lib.makefile diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Makefile new file mode 100644 index 00000000..971025f6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Makefile @@ -0,0 +1,36 @@ +## @file +# Windows makefile for 'Common' module build. +# +# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +!INCLUDE ..\Makefiles\ms.common + +# VPATH = .. + +LIBNAME = Common + +OBJECTS = \ + BasePeCoff.obj \ + BinderFuncs.obj \ + CommonLib.obj \ + Crc32.obj \ + Decompress.obj \ + EfiCompress.obj \ + EfiUtilityMsgs.obj \ + FirmwareVolumeBuffer.obj \ + FvLib.obj \ + MemoryFile.obj \ + MyAlloc.obj \ + OsPath.obj \ + ParseGuidedSectionTools.obj \ + ParseInf.obj \ + PeCoffLoaderEx.obj \ + SimpleFileParsing.obj \ + StringFuncs.obj \ + TianoCompress.obj + +!INCLUDE ..\Makefiles\ms.lib + + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Makefile.kmk new file mode 100644 index 00000000..aab8f640 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/Makefile.kmk @@ -0,0 +1,63 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-makefile for the EFI build tool common library. +# + +# +# Copyright (C) 2013-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# 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, in version 3 of the +# License. +# +# 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 . +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +SUB_DEPTH = ../../../../../../../../.. +include $(KBUILD_PATH)/subheader.kmk + +LIBRARIES += EfiBldCommonLib +EfiBldCommonLib_TEMPLATE = VBoxEfiBldLib +EfiBldCommonLib_SOURCES = \ + BasePeCoff.c \ + BinderFuncs.c \ + CommonLib.c \ + Crc32.c \ + Decompress.c \ + EfiCompress.c \ + EfiUtilityMsgs.c \ + FirmwareVolumeBuffer.c \ + FvLib.c \ + MemoryFile.c \ + MyAlloc.c \ + OsPath.c \ + ParseGuidedSectionTools.c \ + ParseInf.c \ + PeCoffLoaderEx.c \ + SimpleFileParsing.c \ + StringFuncs.c \ + TianoCompress.c + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MemoryFile.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MemoryFile.c new file mode 100644 index 00000000..68277e98 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MemoryFile.c @@ -0,0 +1,251 @@ +/** @file +This contains some useful functions for accessing files. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include "CommonLib.h" +#include "MemoryFile.h" + + +// +// Local (static) function prototypes +// +STATIC +VOID +CheckMemoryFileState ( + IN EFI_HANDLE InputMemoryFile + ); + +// +// Function implementations +// + +EFI_STATUS +GetMemoryFile ( + IN CHAR8 *InputFileName, + OUT EFI_HANDLE *OutputMemoryFile + ) +/*++ + +Routine Description: + + This opens a file, reads it into memory and returns a memory file + object. + +Arguments: + + InputFile Memory file image. + OutputMemoryFile Handle to memory file + +Returns: + + EFI_STATUS + OutputMemoryFile is valid if !EFI_ERROR + +--*/ +{ + EFI_STATUS Status; + CHAR8 *InputFileImage; + UINT32 BytesRead; + MEMORY_FILE *NewMemoryFile; + + Status = GetFileImage (InputFileName, &InputFileImage, &BytesRead); + if (EFI_ERROR (Status)) { + return Status; + } + + NewMemoryFile = malloc (sizeof (*NewMemoryFile)); + if (NewMemoryFile == NULL) { + free (InputFileImage); + return EFI_OUT_OF_RESOURCES; + } + + NewMemoryFile->FileImage = InputFileImage; + NewMemoryFile->CurrentFilePointer = InputFileImage; + NewMemoryFile->Eof = InputFileImage + BytesRead; + + *OutputMemoryFile = (EFI_HANDLE)NewMemoryFile; + + CheckMemoryFileState (*OutputMemoryFile); + + return EFI_SUCCESS; +} + + +EFI_STATUS +FreeMemoryFile ( + IN EFI_HANDLE InputMemoryFile + ) +/*++ + +Routine Description: + + Frees all memory associated with the input memory file. + +Arguments: + + InputMemoryFile Handle to memory file + +Returns: + + EFI_STATUS + +--*/ +{ + MEMORY_FILE *MemoryFile; + + CheckMemoryFileState (InputMemoryFile); + + MemoryFile = (MEMORY_FILE*)InputMemoryFile; + + free (MemoryFile->FileImage); + + // + // Invalidate state of MEMORY_FILE structure to catch invalid usage. + // + memset (MemoryFile, 0xcc, sizeof (*MemoryFile)); + MemoryFile->Eof -= 1; + + free (MemoryFile); + + return EFI_SUCCESS; +} + + +CHAR8 * +ReadMemoryFileLine ( + IN EFI_HANDLE InputMemoryFile + ) +/*++ + +Routine Description: + + This function reads a line from the memory file. The newline characters + are stripped and a null terminated string is returned. + + If the string pointer returned is non-NULL, then the caller must free the + memory associated with this string. + +Arguments: + + InputMemoryFile Handle to memory file + +Returns: + + NULL if error or EOF + NULL character termincated string otherwise (MUST BE FREED BY CALLER) + +--*/ +{ + CHAR8 *EndOfLine; + UINTN CharsToCopy; + MEMORY_FILE *InputFile; + UINTN BytesToEof; + CHAR8 *OutputString; + + // + // Verify input parameters are not null + // + CheckMemoryFileState (InputMemoryFile); + + InputFile = (MEMORY_FILE*)InputMemoryFile; + + // + // Check for end of file condition + // + if (InputFile->CurrentFilePointer >= InputFile->Eof) { + return NULL; + } + + // + // Determine the number of bytes remaining until the EOF + // + BytesToEof = InputFile->Eof - InputFile->CurrentFilePointer; + + // + // Find the next newline char + // + EndOfLine = memchr (InputFile->CurrentFilePointer, '\n', BytesToEof); + + // + // Determine the number of characters to copy. + // + if (EndOfLine == 0) { + // + // If no newline found, copy to the end of the file. + // + CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer; + } else { + // + // Newline found in the file. + // + CharsToCopy = EndOfLine - InputFile->CurrentFilePointer; + } + + OutputString = malloc (CharsToCopy + 1); + if (OutputString == NULL) { + return NULL; + } + + // + // Copy the line. + // + memcpy (OutputString, InputFile->CurrentFilePointer, CharsToCopy); + + // + // Add the null termination over the 0x0D + // + if (OutputString[CharsToCopy - 1] == '\r') { + + OutputString[CharsToCopy - 1] = '\0'; + + } else { + + OutputString[CharsToCopy] = '\0'; + + } + + // + // Increment the current file pointer (include the 0x0A) + // + InputFile->CurrentFilePointer += CharsToCopy + 1; + if (InputFile->CurrentFilePointer > InputFile->Eof) { + InputFile->CurrentFilePointer = InputFile->Eof; + } + CheckMemoryFileState (InputMemoryFile); + + // + // Return the string + // + return OutputString; +} + + +STATIC +VOID +CheckMemoryFileState ( + IN EFI_HANDLE InputMemoryFile + ) +{ + MEMORY_FILE *MemoryFile; + + assert (InputMemoryFile != NULL); + + MemoryFile = (MEMORY_FILE*)InputMemoryFile; + + assert (MemoryFile->FileImage != NULL); + assert (MemoryFile->CurrentFilePointer != NULL); + assert (MemoryFile->Eof != NULL); + assert (MemoryFile->Eof >= MemoryFile->FileImage); + assert (MemoryFile->CurrentFilePointer >= MemoryFile->FileImage); + assert (MemoryFile->CurrentFilePointer <= MemoryFile->Eof); +} + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MemoryFile.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MemoryFile.h new file mode 100644 index 00000000..56a11d89 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MemoryFile.h @@ -0,0 +1,105 @@ +/** @file +Header file for helper functions useful for accessing files. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_MEMORY_FILE_H +#define _EFI_MEMORY_FILE_H + +#include +#include +#include + +// +// Common data structures +// +typedef struct { + CHAR8 *FileImage; + CHAR8 *Eof; + CHAR8 *CurrentFilePointer; +} MEMORY_FILE; + + +// +// Functions declarations +// + +EFI_STATUS +GetMemoryFile ( + IN CHAR8 *InputFileName, + OUT EFI_HANDLE *OutputMemoryFile + ) +; +/** + +Routine Description: + + This opens a file, reads it into memory and returns a memory file + object. + +Arguments: + + InputFile Memory file image. + OutputMemoryFile Handle to memory file + +Returns: + + EFI_STATUS + OutputMemoryFile is valid if !EFI_ERROR + +**/ + + +EFI_STATUS +FreeMemoryFile ( + IN EFI_HANDLE InputMemoryFile + ) +; +/** + +Routine Description: + + Frees all memory associated with the input memory file. + +Arguments: + + InputMemoryFile Handle to memory file + +Returns: + + EFI_STATUS + +**/ + + +CHAR8 * +ReadMemoryFileLine ( + IN EFI_HANDLE InputMemoryFile + ) +; +/** + +Routine Description: + + This function reads a line from the memory file. The newline characters + are stripped and a null terminated string is returned. + + If the string pointer returned is non-NULL, then the caller must free the + memory associated with this string. + +Arguments: + + InputMemoryFile Handle to memory file + +Returns: + + NULL if error or EOF + NULL character termincated string otherwise (MUST BE FREED BY CALLER) + +**/ + + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MyAlloc.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MyAlloc.c new file mode 100644 index 00000000..dacb07ec --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MyAlloc.c @@ -0,0 +1,548 @@ +/** @file +File for memory allocation tracking functions. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "MyAlloc.h" + +#if USE_MYALLOC +// +// Get back to original alloc/free calls. +// +#undef malloc +#undef calloc +#undef realloc +#undef free +// +// Start of allocation list. +// +STATIC MY_ALLOC_STRUCT *MyAllocData = NULL; + +// +// +// +STATIC UINT32 MyAllocHeadMagik = MYALLOC_HEAD_MAGIK; +STATIC UINT32 MyAllocTailMagik = MYALLOC_TAIL_MAGIK; + +// +// //////////////////////////////////////////////////////////////////////////// +// +// +VOID +MyCheck ( + BOOLEAN Final, + UINT8 File[], + UINTN Line + ) +// *++ +// Description: +// +// Check for corruptions in the allocated memory chain. If a corruption +// is detection program operation stops w/ an exit(1) call. +// +// Parameters: +// +// Final := When FALSE, MyCheck() returns if the allocated memory chain +// has not been corrupted. When TRUE, MyCheck() returns if there +// are no un-freed allocations. If there are un-freed allocations, +// they are displayed and exit(1) is called. +// +// +// File := Set to __FILE__ by macro expansion. +// +// Line := Set to __LINE__ by macro expansion. +// +// Returns: +// +// n/a +// +// --*/ +// +{ + MY_ALLOC_STRUCT *Tmp; + + // + // Check parameters. + // + if (File == NULL) { + printf ( + "\nMyCheck(Final=%u, File=NULL, Line=%u)" + "Invalid parameter(s).\n", + Final, + (unsigned)Line + ); + + exit (1); + } + + if (Line == 0) { + printf ( + "\nMyCheck(Final=%u, File=%s, Line=%u)" + "Invalid parameter(s).\n", + Final, + File, + (unsigned)Line + ); + + exit (1); + } + + if (strlen ((CHAR8 *)File) == 0) { + printf ( + "\nMyCheck(Final=%u, File=%s, Line=%u)" + "Invalid parameter.\n", + Final, + File, + (unsigned)Line + ); + + exit (1); + } + // + // Check structure contents. + // + for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) { + if (memcmp(Tmp->Buffer, &MyAllocHeadMagik, sizeof MyAllocHeadMagik) || + memcmp(&Tmp->Buffer[Tmp->Size + sizeof(UINT32)], &MyAllocTailMagik, sizeof MyAllocTailMagik)) { + break; + } + } + // + // If Tmp is not NULL, the structure is corrupt. + // + if (Tmp != NULL) { + printf ( + "\nMyCheck(Final=%u, File=%s, Line=%u)""\nStructure corrupted!" + "\nFile=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n", + Final, + File, + (unsigned)Line, + Tmp->File, + (unsigned) Tmp->Line, + (unsigned) Tmp->Size, + (unsigned) *(UINT32 *) (Tmp->Buffer), + (unsigned) *(UINT32 *) (&Tmp->Buffer[Tmp->Size + sizeof (UINT32)]) + ); + + exit (1); + } + // + // If Final is TRUE, display the state of the structure chain. + // + if (Final) { + if (MyAllocData != NULL) { + printf ( + "\nMyCheck(Final=%u, File=%s, Line=%u)" + "\nSome allocated items have not been freed.\n", + Final, + File, + (unsigned)Line + ); + + for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) { + printf ( + "File=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n", + Tmp->File, + (unsigned) Tmp->Line, + (unsigned) Tmp->Size, + (unsigned) *(UINT32 *) (Tmp->Buffer), + (unsigned) *(UINT32 *) (&Tmp->Buffer[Tmp->Size + sizeof (UINT32)]) + ); + } + } + } +} +// +// //////////////////////////////////////////////////////////////////////////// +// +// +VOID * +MyAlloc ( + UINTN Size, + UINT8 File[], + UINTN Line + ) +// *++ +// Description: +// +// Allocate a new link in the allocation chain along with enough storage +// for the File[] string, requested Size and alignment overhead. If +// memory cannot be allocated or the allocation chain has been corrupted, +// exit(1) will be called. +// +// Parameters: +// +// Size := Number of bytes (UINT8) requested by the called. +// Size cannot be zero. +// +// File := Set to __FILE__ by macro expansion. +// +// Line := Set to __LINE__ by macro expansion. +// +// Returns: +// +// Pointer to the caller's buffer. +// +// --*/ +// +{ + MY_ALLOC_STRUCT *Tmp; + UINTN Len; + + // + // Check for invalid parameters. + // + if (File == NULL) { + printf ( + "\nMyAlloc(Size=%u, File=NULL, Line=%u)" + "\nInvalid parameter(s).\n", + (unsigned)Size, + (unsigned)Line + ); + + exit (1); + } + + if (Size == 0 || Line == 0) { + printf ( + "\nMyAlloc(Size=%u, File=%s, Line=%u)" + "\nInvalid parameter(s).\n", + (unsigned)Size, + File, + (unsigned)Line + ); + + exit (1); + } + + Len = strlen ((CHAR8 *)File); + if (Len == 0) { + printf ( + "\nMyAlloc(Size=%u, File=%s, Line=%u)" + "\nInvalid parameter.\n", + (unsigned)Size, + File, + (unsigned)Line + ); + + exit (1); + } + // + // Check the allocation list for corruption. + // + MyCheck (0, (UINT8 *)__FILE__, __LINE__); + + // + // Allocate a new entry. + // + Tmp = calloc ( + 1, + sizeof (MY_ALLOC_STRUCT) + Len + 1 + sizeof (UINT64) + Size + (sizeof MyAllocHeadMagik) + (sizeof MyAllocTailMagik) + ); + + if (Tmp == NULL) { + printf ( + "\nMyAlloc(Size=%u, File=%s, Line=%u)" + "\nOut of memory.\n", + (unsigned)Size, + File, + (unsigned)Line + ); + + exit (1); + } + // + // Fill in the new entry. + // + Tmp->File = ((UINT8 *) Tmp) + sizeof (MY_ALLOC_STRUCT); + strcpy ((CHAR8 *)Tmp->File, (CHAR8 *)File); + Tmp->Line = Line; + Tmp->Size = Size; + Tmp->Buffer = (UINT8 *) (((UINTN) Tmp + Len + 9) &~7); + + memcpy (Tmp->Buffer, &MyAllocHeadMagik, sizeof MyAllocHeadMagik); + + memcpy ( + &Tmp->Buffer[Size + sizeof (UINT32)], + &MyAllocTailMagik, + sizeof MyAllocTailMagik + ); + + Tmp->Next = MyAllocData; + Tmp->Cksum = (UINTN) Tmp + (UINTN) (Tmp->Next) + Tmp->Line + Tmp->Size + (UINTN) (Tmp->File) + (UINTN) (Tmp->Buffer); + + MyAllocData = Tmp; + + return Tmp->Buffer + sizeof (UINT32); +} +// +// //////////////////////////////////////////////////////////////////////////// +// +// +VOID * +MyRealloc ( + VOID *Ptr, + UINTN Size, + UINT8 File[], + UINTN Line + ) +// *++ +// Description: +// +// This does a MyAlloc(), memcpy() and MyFree(). There is no optimization +// for shrinking or expanding buffers. An invalid parameter will cause +// MyRealloc() to fail with a call to exit(1). +// +// Parameters: +// +// Ptr := Pointer to the caller's buffer to be re-allocated. +// +// Size := Size of new buffer. Size cannot be zero. +// +// File := Set to __FILE__ by macro expansion. +// +// Line := Set to __LINE__ by macro expansion. +// +// Returns: +// +// Pointer to new caller's buffer. +// +// --*/ +// +{ + MY_ALLOC_STRUCT *Tmp; + VOID *Buffer; + + // + // Check for invalid parameter(s). + // + if (File == NULL) { + printf ( + "\nMyRealloc(Ptr=%p, Size=%u, File=NULL, Line=%u)" + "\nInvalid parameter(s).\n", + Ptr, + (unsigned)Size, + (unsigned)Line + ); + + exit (1); + } + + if (Size == 0 || Line == 0) { + printf ( + "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)" + "\nInvalid parameter(s).\n", + Ptr, + (unsigned)Size, + File, + (unsigned)Line + ); + + exit (1); + } + + if (strlen ((CHAR8 *)File) == 0) { + printf ( + "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)" + "\nInvalid parameter.\n", + Ptr, + (unsigned)Size, + File, + (unsigned)Line + ); + + exit (1); + } + // + // Find existing buffer in allocation list. + // + if (Ptr == NULL) { + Tmp = NULL; + } else if (&MyAllocData->Buffer[sizeof (UINT32)] == Ptr) { + Tmp = MyAllocData; + } else { + for (Tmp = MyAllocData;; Tmp = Tmp->Next) { + if (Tmp->Next == NULL) { + printf ( + "\nMyRealloc(Ptr=%p, Size=%u, File=%s, Line=%u)" + "\nCould not find buffer.\n", + Ptr, + (unsigned)Size, + File, + (unsigned)Line + ); + + exit (1); + } + + Tmp = Tmp->Next; + } + } + // + // Allocate new buffer, copy old data, free old buffer. + // + Buffer = MyAlloc (Size, File, Line); + + if (Buffer != NULL && Tmp != NULL) { + memcpy ( + Buffer, + &Tmp->Buffer[sizeof (UINT32)], + ((Size <= Tmp->Size) ? Size : Tmp->Size) + ); + + MyFree (Ptr, (UINT8 *)__FILE__, __LINE__); + } + + return Buffer; +} +// +// //////////////////////////////////////////////////////////////////////////// +// +// +VOID +MyFree ( + VOID *Ptr, + UINT8 File[], + UINTN Line + ) +// *++ +// Description: +// +// Release a previously allocated buffer. Invalid parameters will cause +// MyFree() to fail with an exit(1) call. +// +// Parameters: +// +// Ptr := Pointer to the caller's buffer to be freed. +// A NULL pointer will be ignored. +// +// File := Set to __FILE__ by macro expansion. +// +// Line := Set to __LINE__ by macro expansion. +// +// Returns: +// +// n/a +// +// --*/ +// +{ + MY_ALLOC_STRUCT *Tmp; + MY_ALLOC_STRUCT *Tmp2; + + // + // Check for invalid parameter(s). + // + if (File == NULL) { + printf ( + "\nMyFree(Ptr=%p, File=NULL, Line=%u)" + "\nInvalid parameter(s).\n", + Ptr, + (unsigned)Line + ); + + exit (1); + } + + if (Line == 0) { + printf ( + "\nMyFree(Ptr=%p, File=%s, Line=%u)" + "\nInvalid parameter(s).\n", + Ptr, + File, + (unsigned)Line + ); + + exit (1); + } + + if (strlen ((CHAR8 *)File) == 0) { + printf ( + "\nMyFree(Ptr=%p, File=%s, Line=%u)" + "\nInvalid parameter.\n", + Ptr, + File, + (unsigned)Line + ); + + exit (1); + } + // + // Freeing NULL is always valid. + // + if (Ptr == NULL) { + return ; + } + // + // Fail if nothing is allocated. + // + if (MyAllocData == NULL) { + printf ( + "\nMyFree(Ptr=%p, File=%s, Line=%u)" + "\nCalled before memory allocated.\n", + Ptr, + File, + (unsigned)Line + ); + + exit (1); + } + // + // Check for corrupted allocation list. + // + MyCheck (0, (UINT8 *)__FILE__, __LINE__); + + // + // Need special check for first item in list. + // + if (&MyAllocData->Buffer[sizeof (UINT32)] == Ptr) { + // + // Unlink first item in list. + // + Tmp = MyAllocData; + MyAllocData = MyAllocData->Next; + } else { + // + // Walk list looking for matching item. + // + for (Tmp = MyAllocData;; Tmp = Tmp->Next) { + // + // Fail if end of list is reached. + // + if (Tmp->Next == NULL) { + printf ( + "\nMyFree(Ptr=%p, File=%s, Line=%u)\n" + "\nNot found.\n", + Ptr, + File, + (unsigned)Line + ); + + exit (1); + } + // + // Leave loop when match is found. + // + if (&Tmp->Next->Buffer[sizeof (UINT32)] == Ptr) { + break; + } + } + // + // Unlink item from list. + // + Tmp2 = Tmp->Next; + Tmp->Next = Tmp->Next->Next; + Tmp = Tmp2; + } + // + // Release item. + // + free (Tmp); +} + +#endif /* USE_MYALLOC */ + +/* eof - MyAlloc.c */ diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MyAlloc.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MyAlloc.h new file mode 100644 index 00000000..005f477b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/MyAlloc.h @@ -0,0 +1,209 @@ +/** @file +Header file for memory allocation tracking functions. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _MYALLOC_H_ +#define _MYALLOC_H_ + +#include +#include +#include + +#include + +// +// Default operation is to use the memory allocation tracking functions. +// To over-ride add "#define USE_MYALLOC 0" to your program header and/or +// source files as needed. Or, just do not include this header file in +// your project. +// +#ifndef USE_MYALLOC +#define USE_MYALLOC 1 +#endif + +#if USE_MYALLOC +// +// Replace C library allocation routines with MyAlloc routines. +// +#define malloc(size) MyAlloc ((size), __FILE__, __LINE__) +#define calloc(count, size) MyAlloc ((count) * (size), __FILE__, __LINE__) +#define realloc(ptr, size) MyRealloc ((ptr), (size), __FILE__, __LINE__) +#define free(ptr) MyFree ((ptr), __FILE__, __LINE__) +#define alloc_check(final) MyCheck ((final), __FILE__, __LINE__) + +// +// Structure for checking/tracking memory allocations. +// +typedef struct MyAllocStruct { + UINTN Cksum; + struct MyAllocStruct *Next; + UINTN Line; + UINTN Size; + UINT8 *File; + UINT8 *Buffer; +} MY_ALLOC_STRUCT; +// +// Cksum := (UINTN)This + (UINTN)Next + Line + Size + (UINTN)File + +// (UINTN)Buffer; +// +// Next := Pointer to next allocation structure in the list. +// +// Line := __LINE__ +// +// Size := Size of allocation request. +// +// File := Pointer to __FILE__ string stored immediately following +// MY_ALLOC_STRUCT in memory. +// +// Buffer := Pointer to UINT32 aligned storage immediately following +// the NULL terminated __FILE__ string. This is UINT32 +// aligned because the underflow signature is 32-bits and +// this will place the first caller address on a 64-bit +// boundary. +// +// +// Signatures used to check for buffer overflow/underflow conditions. +// +#define MYALLOC_HEAD_MAGIK 0xBADFACED +#define MYALLOC_TAIL_MAGIK 0xDEADBEEF + +VOID +MyCheck ( + BOOLEAN Final, + UINT8 File[], + UINTN Line + ) +; +// +// *++ +// Description: +// +// Check for corruptions in the allocated memory chain. If a corruption +// is detection program operation stops w/ an exit(1) call. +// +// Parameters: +// +// Final := When FALSE, MyCheck() returns if the allocated memory chain +// has not been corrupted. When TRUE, MyCheck() returns if there +// are no un-freed allocations. If there are un-freed allocations, +// they are displayed and exit(1) is called. +// +// +// File := Set to __FILE__ by macro expansion. +// +// Line := Set to __LINE__ by macro expansion. +// +// Returns: +// +// n/a +// +// --*/ +// +VOID * +MyAlloc ( + UINTN Size, + UINT8 File[], + UINTN Line + ) +; +// +// *++ +// Description: +// +// Allocate a new link in the allocation chain along with enough storage +// for the File[] string, requested Size and alignment overhead. If +// memory cannot be allocated or the allocation chain has been corrupted, +// exit(1) will be called. +// +// Parameters: +// +// Size := Number of bytes (UINT8) requested by the called. +// Size cannot be zero. +// +// File := Set to __FILE__ by macro expansion. +// +// Line := Set to __LINE__ by macro expansion. +// +// Returns: +// +// Pointer to the caller's buffer. +// +// --*/ +// +VOID * +MyRealloc ( + VOID *Ptr, + UINTN Size, + UINT8 File[], + UINTN Line + ) +; +// +// *++ +// Description: +// +// This does a MyAlloc(), memcpy() and MyFree(). There is no optimization +// for shrinking or expanding buffers. An invalid parameter will cause +// MyRealloc() to fail with a call to exit(1). +// +// Parameters: +// +// Ptr := Pointer to the caller's buffer to be re-allocated. +// Ptr cannot be NULL. +// +// Size := Size of new buffer. Size cannot be zero. +// +// File := Set to __FILE__ by macro expansion. +// +// Line := Set to __LINE__ by macro expansion. +// +// Returns: +// +// Pointer to new caller's buffer. +// +// --*/ +// +VOID +MyFree ( + VOID *Ptr, + UINT8 File[], + UINTN Line + ) +; +// +// *++ +// Description: +// +// Release a previously allocated buffer. Invalid parameters will cause +// MyFree() to fail with an exit(1) call. +// +// Parameters: +// +// Ptr := Pointer to the caller's buffer to be freed. +// A NULL pointer will be ignored. +// +// File := Set to __FILE__ by macro expansion. +// +// Line := Set to __LINE__ by macro expansion. +// +// Returns: +// +// n/a +// +// --*/ +// +#else /* USE_MYALLOC */ + +// +// Nothing to do when USE_MYALLOC is zero. +// +#define alloc_check(final) + +#endif /* USE_MYALLOC */ +#endif /* _MYALLOC_H_ */ + +/* eof - MyAlloc.h */ diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/OsPath.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/OsPath.c new file mode 100644 index 00000000..04e1557d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/OsPath.c @@ -0,0 +1,295 @@ +/** @file +Functions useful to operate file directories by parsing file path. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include "CommonLib.h" +#include "OsPath.h" + +// +// Functions implementations +// + +#if 0 + // + // BUGBUG: Not fully implemented yet. + // +CHAR8* +OsPathDirName ( + IN CHAR8 *FilePath + ) +/*++ + +Routine Description: + + This function returns the directory path which contains the particular path. + Some examples: + "a/b/c" -> "a/b" + "a/b/c/" -> "a/b" + "a" -> "." + "." -> ".." + "/" -> NULL + + This function does not check for the existence of the file. + + The caller must free the string returned. + +Arguments: + + FilePath Path name of file to get the parent directory for. + +Returns: + + NULL if error + +--*/ +{ + CHAR8 *Return; + CHAR8 *Pos; + CHAR8 Char; + UINTN Length; + INTN Offset; + + Length = strlen (FilePath); + + if (Length == 0) { + return NULL; + } + + // + // Check for the root directory case + // + if ( + (Length == 3 && isalpha (FilePath[0]) && (strcmp(FilePath + 1, ":\\") == 0)) || + (strcmp(FilePath, "/") == 0) + ) { + return NULL; + } + + // + // If the path ends with a path separator, then just append ".." + // + Char = FilePath[Length - 1]; + if (Char == '/' || Char == '\\') { + return OsPathJoin (FilePath, ".."); + } + + // + // + // + for (Offset = Length; Offset > 0; Offset--) { + if ((Return[Offset] == '/') || (Return[Offset] == '\\')) { + Return[Offset] = '\0'; + return Return; + } + } +} +#endif + + +#if 0 + // + // BUGBUG: Not fully implemented yet. + // +VOID +OsPathNormPathInPlace ( + IN CHAR8 *Path + ) +/*++ + +Routine Description: + + This function returns the directory path which contains the particular path. + Some examples: + "a/b/../c" -> "a/c" + "a/b//c" -> "a/b/c" + "a/./b" -> "a/b" + + This function does not check for the existence of the file. + +Arguments: + + Path Path name of file to normalize + +Returns: + + The string is altered in place. + +--*/ +{ + CHAR8 *Pos; + INTN Offset; + BOOLEAN TryAgain; + UINTN Length; + UINTN Remaining; + UINTN SubLength; + + do { + TryAgain = FALSE; + Length = strlen (Path); + + for (Offset = 0; Offset < Length; Offset++) { + Remaining = Length - Offset; + + // + // Collapse '//' -> '/' + // + if ( + (Remaining >= 2) && + ((Offset > 0) || (Path[0] != '\\')) && + IsDirSep (Path[Offset]) && IsDirSep (Path[Offset + 1]) + ) { + memmove (&Path[Offset], &Path[Offset + 1], Remaining); + TryAgain = TRUE; + break; + } + + // + // Collapse '/./' -> '/' + // + if ((Remaining >= 3) && IsDirSep (Path[Offset]) && + (Path[Offset + 1] == '.') && IsDirSep (Path[Offset + 2]) + ) { + memmove (&Path[Offset], &Path[Offset + 1], Remaining); + TryAgain = TRUE; + break; + } + + // + // Collapse 'a/../b' -> 'b' + // + // BUGBUG: Not implemented yet + + } + + } while (TryAgain); + + Return = CloneString (FilePath); + if (Return == NULL) { + return NULL; + } + + Length = strlen (Return); + + // + // Check for the root directory case + // + if ( + (Length == 3 && isalpha (Return[0]) && (strcmp(Return + 1, ":\\") == 0)) || + (strcmp(Return, "/") == 0) + ) { + free (Return); + return NULL; + } + + // + // + // + for (Offset = Length; Offset > 0; Offset--) { + if ((Return[Offset] == '/') || (Return[Offset] == '\\')) { + Return[Offset] = '\0'; + return Return; + } + } +} +#endif + + +CHAR8* +OsPathPeerFilePath ( + IN CHAR8 *OldPath, + IN CHAR8 *Peer + ) +/*++ + +Routine Description: + + This function replaces the final portion of a path with an alternative + 'peer' filename. For example: + "a/b/../c", "peer" -> "a/b/../peer" + "a/b/", "peer" -> "a/b/peer" + "/a", "peer" -> "/peer" + "a", "peer" -> "peer" + + This function does not check for the existence of the file. + +Arguments: + + OldPath Path name of replace the final segment + Peer The new path name to concatenate to become the peer path + +Returns: + + A CHAR8* string, which must be freed by the caller + +--*/ +{ + CHAR8 *Result; + INTN Offset; + + Result = (CHAR8 *) malloc (strlen (OldPath) + strlen (Peer) + 1); + if (Result == NULL) { + return NULL; + } + + strcpy (Result, OldPath); + + // + // Search for the last '/' or '\' in the string. If found, replace + // everything following it with Peer + // + for (Offset = strlen (Result); Offset >= 0; Offset--) { + if ((Result[Offset] == '/') || (Result[Offset] == '\\')) { + Result[Offset + 1] = '\0'; + strcat (Result, Peer); + return Result; + } + } + + // + // Neither a '/' nor a '\' was found. Therefore, we simply return Peer. + // + strcpy (Result, Peer); + return Result; +} + + +BOOLEAN +OsPathExists ( + IN CHAR8 *InputFileName + ) +/*++ + +Routine Description: + + Checks if a file exists + +Arguments: + + InputFileName The name of the file to check for existence + +Returns: + + TRUE The file exists + FALSE The file does not exist + +--*/ +{ + FILE *InputFile; + InputFile = fopen (LongFilePath (InputFileName), "rb"); + if (InputFile == NULL) { + return FALSE; + } else { + fclose (InputFile); + return TRUE; + } +} + + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/OsPath.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/OsPath.h new file mode 100644 index 00000000..1b0640bd --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/OsPath.h @@ -0,0 +1,133 @@ +/** @file +Header file for helper functions useful to operate file directories by parsing +file path. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_OS_PATH_H +#define _EFI_OS_PATH_H + +#include + +// +// Functions declarations +// + +CHAR8* +OsPathDirName ( + IN CHAR8 *FilePath + ) +; +/** + +Routine Description: + + This function returns the directory path which contains the particular path. + Some examples: + "a/b/c" -> "a/b" + "a/b/c/" -> "a/b" + "a" -> "." + "." -> ".." + "/" -> NULL + + This function does not check for the existence of the file. + + The caller must free the string returned. + +Arguments: + + FilePath Path name of file to get the parent directory for. + +Returns: + + NULL if error + +**/ + + +VOID +OsPathNormPathInPlace ( + IN CHAR8 *Path + ) +; +/** + +Routine Description: + + This function returns the directory path which contains the particular path. + Some examples: + "a/b/../c" -> "a/c" + "a/b//c" -> "a/b/c" + "a/./b" -> "a/b" + + This function does not check for the existence of the file. + +Arguments: + + Path Path name of file to normalize + +Returns: + + The string is altered in place. + +**/ + + +CHAR8* +OsPathPeerFilePath ( + IN CHAR8 *OldPath, + IN CHAR8 *Peer + ) +; +/** + +Routine Description: + + This function replaces the final portion of a path with an alternative + 'peer' filename. For example: + "a/b/../c", "peer" -> "a/b/../peer" + "a/b/", "peer" -> "a/b/peer" + "/a", "peer" -> "/peer" + "a", "peer" -> "peer" + + This function does not check for the existence of the file. + +Arguments: + + OldPath Path name of replace the final segment + Peer The new path name to concatenate to become the peer path + +Returns: + + A CHAR8* string, which must be freed by the caller + +**/ + + +BOOLEAN +OsPathExists ( + IN CHAR8 *InputFileName + ) +; +/** + +Routine Description: + + Checks if a file exists + +Arguments: + + InputFileName The name of the file to check for existence + +Returns: + + TRUE The file exists + FALSE The file does not exist + +**/ + + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseGuidedSectionTools.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseGuidedSectionTools.c new file mode 100644 index 00000000..f8b8f061 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseGuidedSectionTools.c @@ -0,0 +1,205 @@ +/** @file +Helper functions for parsing GuidedSectionTools.txt + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include "MemoryFile.h" +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" +#include "ParseInf.h" +#include "ParseGuidedSectionTools.h" +#include "StringFuncs.h" + + +// +// Local types / structures +// + +typedef struct _GUID_SEC_TOOL_ENTRY { + EFI_GUID Guid; + CHAR8* Name; + CHAR8* Path; + struct _GUID_SEC_TOOL_ENTRY *Next; +} GUID_SEC_TOOL_ENTRY; + +// +// Function Implementation +// + +EFI_HANDLE +ParseGuidedSectionToolsFile ( + IN CHAR8 *InputFile + ) +/*++ + +Routine Description: + + This function parses the tools_def.txt file. It returns a + EFI_HANDLE object which can be used for the other library + functions and should be passed to FreeParsedGuidedSectionToolsHandle + to free resources when the tools_def.txt information is no + longer needed. + +Arguments: + + InputFile Path name of file to read + +Returns: + + NULL if error parsing + A non-NULL EFI_HANDLE otherwise + +--*/ +{ + EFI_STATUS Status; + EFI_HANDLE MemoryFile; + EFI_HANDLE ParsedGuidedSectionTools; + + Status = GetMemoryFile (InputFile, &MemoryFile); + if (EFI_ERROR (Status)) { + return NULL; + } + + ParsedGuidedSectionTools = ParseGuidedSectionToolsMemoryFile (MemoryFile); + + FreeMemoryFile (MemoryFile); + + return ParsedGuidedSectionTools; +} + + +EFI_HANDLE +ParseGuidedSectionToolsMemoryFile ( + IN EFI_HANDLE InputFile + ) +/*++ + +Routine Description: + + This function parses the tools_def.txt file. It returns a + EFI_HANDLE object which can be used for the other library + functions and should be passed to FreeParsedGuidedSectionToolsHandle + to free resources when the tools_def.txt information is no + longer needed. + +Arguments: + + InputFile Memory file image. + +Returns: + + NULL if error or EOF + InputBuffer otherwise + +--*/ +{ + EFI_STATUS Status; + CHAR8 *NextLine; + STRING_LIST *Tool; + EFI_GUID Guid; + GUID_SEC_TOOL_ENTRY *FirstGuidTool; + GUID_SEC_TOOL_ENTRY *LastGuidTool; + GUID_SEC_TOOL_ENTRY *NewGuidTool; + + FirstGuidTool = NULL; + LastGuidTool = NULL; + + while (TRUE) { + NextLine = ReadMemoryFileLine (InputFile); + if (NextLine == NULL) { + break; + } + + Status = StripInfDscStringInPlace (NextLine); + if (EFI_ERROR (Status)) { + free (NextLine); + break; + } + + if (NextLine[0] == '\0') { + free (NextLine); + continue; + } + + Tool = SplitStringByWhitespace (NextLine); + if ((Tool != NULL) && + (Tool->Count == 3) + ) { + Status = StringToGuid (Tool->Strings[0], &Guid); + if (!EFI_ERROR (Status)) { + NewGuidTool = malloc (sizeof (GUID_SEC_TOOL_ENTRY)); + if (NewGuidTool != NULL) { + memcpy (&(NewGuidTool->Guid), &Guid, sizeof (Guid)); + NewGuidTool->Name = CloneString(Tool->Strings[1]); + NewGuidTool->Path = CloneString(Tool->Strings[2]); + NewGuidTool->Next = NULL; + + if (FirstGuidTool == NULL) { + FirstGuidTool = NewGuidTool; + } else { + LastGuidTool->Next = NewGuidTool; + } + LastGuidTool = NewGuidTool; + } + } + } + + if (Tool != NULL) { + FreeStringList (Tool); + } + free (NextLine); + } + + return FirstGuidTool; +} + + +CHAR8* +LookupGuidedSectionToolPath ( + IN EFI_HANDLE ParsedGuidedSectionToolsHandle, + IN EFI_GUID *SectionGuid + ) +/*++ + +Routine Description: + + This function looks up the appropriate tool to use for extracting + a GUID defined FV section. + +Arguments: + + ParsedGuidedSectionToolsHandle A parsed GUID section tools handle. + SectionGuid The GUID for the section. + +Returns: + + NULL - if no tool is found or there is another error + Non-NULL - The tool to use to access the section contents. (The caller + must free the memory associated with this string.) + +--*/ +{ + GUID_SEC_TOOL_ENTRY *GuidTool; + + GuidTool = (GUID_SEC_TOOL_ENTRY*)ParsedGuidedSectionToolsHandle; + if (GuidTool == NULL) { + return NULL; + } + + for ( ; GuidTool != NULL; GuidTool = GuidTool->Next) { + if (CompareGuid (&(GuidTool->Guid), SectionGuid) == 0) { + return CloneString (GuidTool->Path); + } + } + + return NULL; +} + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseGuidedSectionTools.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseGuidedSectionTools.h new file mode 100644 index 00000000..6b7bf1a7 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseGuidedSectionTools.h @@ -0,0 +1,120 @@ +/** @file +Header file for helper functions for parsing GuidedSectionTools.txt + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_PARSE_GUIDED_SECTION_TOOLS_H +#define _EFI_PARSE_GUIDED_SECTION_TOOLS_H + +#include + +// +// Functions declarations +// + +EFI_HANDLE +ParseGuidedSectionToolsFile ( + IN CHAR8 *InputFile + ) +; +/** + +Routine Description: + + This function parses the tools_def.txt file. It returns a + EFI_HANDLE object which can be used for the other library + functions and should be passed to FreeParsedToolsDefHandle + to free resources when the tools_def.txt information is no + longer needed. + +Arguments: + + InputFile Path name of file to read + +Returns: + + NULL if error parsing + A non-NULL EFI_HANDLE otherwise + +**/ + + +EFI_HANDLE +ParseGuidedSectionToolsMemoryFile ( + IN EFI_HANDLE InputFile + ) +; +/** + +Routine Description: + + This function parses the tools_def.txt file. It returns a + EFI_HANDLE object which can be used for the other library + functions and should be passed to FreeParsedToolsDefHandle + to free resources when the tools_def.txt information is no + longer needed. + +Arguments: + + InputFile Memory file image. + +Returns: + + NULL if error parsing + A non-NULL EFI_HANDLE otherwise + +**/ + +CHAR8* +LookupGuidedSectionToolPath ( + IN EFI_HANDLE ParsedGuidedSectionToolsHandle, + IN EFI_GUID *SectionGuid + ) +; +/** + +Routine Description: + + This function looks up the appropriate tool to use for extracting + a GUID defined FV section. + +Arguments: + + ParsedGuidedSectionToolsHandle A parsed GUID section tools handle. + SectionGuid The GUID for the section. + +Returns: + + NULL - if no tool is found or there is another error + Non-NULL - The tool to use to access the section contents. (The caller + must free the memory associated with this string.) + +**/ + +EFI_STATUS +FreeParsedGuidedSectionToolsHandle ( + IN EFI_HANDLE ParsedGuidedSectionToolsHandle + ) +; +/** + +Routine Description: + + Frees resources that were allocated by ParseGuidedSectionToolsFile. + After freeing these resources, the information that was parsed + is no longer accessible. + +Arguments: + + ParsedToolDefHandle Handle returned from ParseGuidedSectionToolsFile + +Returns: + + EFI_STATUS + +**/ + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseInf.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseInf.c new file mode 100644 index 00000000..cc0b04ad --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseInf.c @@ -0,0 +1,695 @@ +/** @file +This contains some useful functions for parsing INF files. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include "EfiUtilityMsgs.h" +#include "ParseInf.h" +#include "CommonLib.h" + +CHAR8 * +ReadLine ( + IN MEMORY_FILE *InputFile, + IN OUT CHAR8 *InputBuffer, + IN UINTN MaxLength + ) +/*++ + +Routine Description: + + This function reads a line, stripping any comments. + The function reads a string from the input stream argument and stores it in + the input string. ReadLine reads characters from the current file position + to and including the first newline character, to the end of the stream, or + until the number of characters read is equal to MaxLength - 1, whichever + comes first. The newline character, if read, is replaced with a \0. + +Arguments: + + InputFile Memory file image. + InputBuffer Buffer to read into, must be MaxLength size. + MaxLength The maximum size of the input buffer. + +Returns: + + NULL if error or EOF + InputBuffer otherwise + +--*/ +{ + CHAR8 *CharPtr; + CHAR8 *EndOfLine; + UINTN CharsToCopy; + + // + // Verify input parameters are not null + // + assert (InputBuffer); + assert (InputFile->FileImage); + assert (InputFile->Eof); + assert (InputFile->CurrentFilePointer); + + // + // Check for end of file condition + // + if (InputFile->CurrentFilePointer >= InputFile->Eof) { + return NULL; + } + // + // Find the next newline char + // + EndOfLine = strchr (InputFile->CurrentFilePointer, '\n'); + + // + // Determine the number of characters to copy. + // + if (EndOfLine == 0) { + // + // If no newline found, copy to the end of the file. + // + CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer; + } else if (EndOfLine >= InputFile->Eof) { + // + // If the newline found was beyond the end of file, copy to the eof. + // + CharsToCopy = InputFile->Eof - InputFile->CurrentFilePointer; + } else { + // + // Newline found in the file. + // + CharsToCopy = EndOfLine - InputFile->CurrentFilePointer; + } + // + // If the end of line is too big for the current buffer, set it to the max + // size of the buffer (leaving room for the \0. + // + if (CharsToCopy > MaxLength - 1) { + CharsToCopy = MaxLength - 1; + } + // + // Copy the line. + // + memcpy (InputBuffer, InputFile->CurrentFilePointer, CharsToCopy); + + // + // Add the null termination over the 0x0D + // + if (InputBuffer[CharsToCopy - 1] == '\r') { + + InputBuffer[CharsToCopy - 1] = '\0'; + + } else { + + InputBuffer[CharsToCopy] = '\0'; + + } + + // + // Increment the current file pointer (include the 0x0A) + // + InputFile->CurrentFilePointer += CharsToCopy + 1; + + // + // Strip any comments + // + CharPtr = strstr (InputBuffer, "//"); + if (CharPtr != 0) { + CharPtr[0] = 0; + } + // + // Return the string + // + return InputBuffer; +} + +BOOLEAN +FindSection ( + IN MEMORY_FILE *InputFile, + IN CHAR8 *Section + ) +/*++ + +Routine Description: + + This function parses a file from the beginning to find a section. + The section string may be anywhere within a line. + +Arguments: + + InputFile Memory file image. + Section Section to search for + +Returns: + + FALSE if error or EOF + TRUE if section found + +--*/ +{ + CHAR8 InputBuffer[MAX_LONG_FILE_PATH]; + CHAR8 *CurrentToken; + + // + // Verify input is not NULL + // + assert (InputFile->FileImage); + assert (InputFile->Eof); + assert (InputFile->CurrentFilePointer); + assert (Section); + + // + // Rewind to beginning of file + // + InputFile->CurrentFilePointer = InputFile->FileImage; + + // + // Read lines until the section is found + // + while (InputFile->CurrentFilePointer < InputFile->Eof) { + // + // Read a line + // + ReadLine (InputFile, InputBuffer, MAX_LONG_FILE_PATH); + + // + // Check if the section is found + // + CurrentToken = strstr (InputBuffer, Section); + if (CurrentToken != NULL) { + return TRUE; + } + } + + return FALSE; +} + +EFI_STATUS +FindToken ( + IN MEMORY_FILE *InputFile, + IN CHAR8 *Section, + IN CHAR8 *Token, + IN UINTN Instance, + OUT CHAR8 *Value + ) +/*++ + +Routine Description: + + Finds a token value given the section and token to search for. + +Arguments: + + InputFile Memory file image. + Section The section to search for, a string within []. + Token The token to search for, e.g. EFI_PEIM_RECOVERY, followed by an = in the INF file. + Instance The instance of the token to search for. Zero is the first instance. + Value The string that holds the value following the =. Must be MAX_LONG_FILE_PATH in size. + +Returns: + + EFI_SUCCESS Value found. + EFI_ABORTED Format error detected in INF file. + EFI_INVALID_PARAMETER Input argument was null. + EFI_LOAD_ERROR Error reading from the file. + EFI_NOT_FOUND Section/Token/Value not found. + +--*/ +{ + CHAR8 InputBuffer[MAX_LONG_FILE_PATH]; + CHAR8 *CurrentToken; + CHAR8 *Delimiter; + BOOLEAN ParseError; + BOOLEAN ReadError; + UINTN Occurrence; + + // + // Check input parameters + // + if (InputFile->FileImage == NULL || + InputFile->Eof == NULL || + InputFile->CurrentFilePointer == NULL || + Section == NULL || + strlen (Section) == 0 || + Token == NULL || + strlen (Token) == 0 || + Value == NULL + ) { + return EFI_INVALID_PARAMETER; + } + // + // Initialize error codes + // + ParseError = FALSE; + ReadError = FALSE; + + // + // Initialize our instance counter for the search token + // + Occurrence = 0; + + if (FindSection (InputFile, Section)) { + // + // Found the desired section, find and read the desired token + // + do { + // + // Read a line from the file + // + if (ReadLine (InputFile, InputBuffer, MAX_LONG_FILE_PATH) == NULL) { + // + // Error reading from input file + // + ReadError = TRUE; + break; + } + // + // Get the first non-whitespace string + // + Delimiter = strchr (InputBuffer, '='); + if (Delimiter != NULL) { + *Delimiter = 0; + } + + CurrentToken = strtok (InputBuffer, " \t\n"); + if (CurrentToken == NULL || Delimiter == NULL) { + // + // Whitespace line found (or comment) so continue + // + CurrentToken = InputBuffer; + continue; + } + // + // Make sure we have not reached the end of the current section + // + if (CurrentToken[0] == '[') { + break; + } + // + // Compare the current token with the desired token + // + if (strcmp (CurrentToken, Token) == 0) { + // + // Found it + // + // + // Check if it is the correct instance + // + if (Instance == Occurrence) { + // + // Copy the contents following the = + // + CurrentToken = Delimiter + 1; + if (*CurrentToken == 0) { + // + // Nothing found, parsing error + // + ParseError = TRUE; + } else { + // + // Strip leading white space + // + while (*CurrentToken == ' ' || *CurrentToken == '\t') { + CurrentToken++; + } + // + // Copy the current token to the output value + // + strcpy (Value, CurrentToken); + // + // Strip trailing white space + // + while (strlen(Value) > 0 && (*(Value + strlen(Value) - 1) == ' ' || *(Value + strlen(Value) - 1) == '\t')) { + *(Value + strlen(Value) - 1) = 0; + } + return EFI_SUCCESS; + } + } else { + // + // Increment the occurrence found + // + Occurrence++; + } + } + } while ( + !ParseError && + !ReadError && + InputFile->CurrentFilePointer < InputFile->Eof && + CurrentToken[0] != '[' && + Occurrence <= Instance + ); + } + // + // Distinguish between read errors and INF file format errors. + // + if (ReadError) { + return EFI_LOAD_ERROR; + } + + if (ParseError) { + return EFI_ABORTED; + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +StringToGuid ( + IN CHAR8 *AsciiGuidBuffer, + OUT EFI_GUID *GuidBuffer + ) +/*++ + +Routine Description: + + Converts a string to an EFI_GUID. The string must be in the + xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format. + +Arguments: + + AsciiGuidBuffer - pointer to ascii string + GuidBuffer - pointer to destination Guid + +Returns: + + EFI_ABORTED Could not convert the string + EFI_SUCCESS The string was successfully converted + EFI_INVALID_PARAMETER Input parameter is invalid. + +--*/ +{ + INT32 Index; + int Data1; + int Data2; + int Data3; + int Data4[8]; + + if (AsciiGuidBuffer == NULL || GuidBuffer == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Check Guid Format strictly xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx + // + for (Index = 0; AsciiGuidBuffer[Index] != '\0' && Index < 37; Index ++) { + if (Index == 8 || Index == 13 || Index == 18 || Index == 23) { + if (AsciiGuidBuffer[Index] != '-') { + break; + } + } else { + if (((AsciiGuidBuffer[Index] >= '0') && (AsciiGuidBuffer[Index] <= '9')) || + ((AsciiGuidBuffer[Index] >= 'a') && (AsciiGuidBuffer[Index] <= 'f')) || + ((AsciiGuidBuffer[Index] >= 'A') && (AsciiGuidBuffer[Index] <= 'F'))) { + continue; + } else { + break; + } + } + } + + if (Index < 36 || AsciiGuidBuffer[36] != '\0') { + Error (NULL, 0, 1003, "Invalid option value", "Incorrect GUID \"%s\"\n Correct Format \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"", AsciiGuidBuffer); + return EFI_ABORTED; + } + + // + // Scan the guid string into the buffer + // + Index = sscanf ( + AsciiGuidBuffer, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + &Data1, + &Data2, + &Data3, + &Data4[0], + &Data4[1], + &Data4[2], + &Data4[3], + &Data4[4], + &Data4[5], + &Data4[6], + &Data4[7] + ); + + // + // Verify the correct number of items were scanned. + // + if (Index != 11) { + Error (NULL, 0, 1003, "Invalid option value", "Incorrect GUID \"%s\"\n Correct Format \"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\"", AsciiGuidBuffer); + return EFI_ABORTED; + } + // + // Copy the data into our GUID. + // + GuidBuffer->Data1 = (UINT32) Data1; + GuidBuffer->Data2 = (UINT16) Data2; + GuidBuffer->Data3 = (UINT16) Data3; + GuidBuffer->Data4[0] = (UINT8) Data4[0]; + GuidBuffer->Data4[1] = (UINT8) Data4[1]; + GuidBuffer->Data4[2] = (UINT8) Data4[2]; + GuidBuffer->Data4[3] = (UINT8) Data4[3]; + GuidBuffer->Data4[4] = (UINT8) Data4[4]; + GuidBuffer->Data4[5] = (UINT8) Data4[5]; + GuidBuffer->Data4[6] = (UINT8) Data4[6]; + GuidBuffer->Data4[7] = (UINT8) Data4[7]; + + return EFI_SUCCESS; +} + +EFI_STATUS +AsciiStringToUint64 ( + IN CONST CHAR8 *AsciiString, + IN BOOLEAN IsHex, + OUT UINT64 *ReturnValue + ) +/*++ + +Routine Description: + + Converts a null terminated ascii string that represents a number into a + UINT64 value. A hex number may be preceded by a 0x, but may not be + succeeded by an h. A number without 0x or 0X is considered to be base 10 + unless the IsHex input is true. + +Arguments: + + AsciiString The string to convert. + IsHex Force the string to be treated as a hex number. + ReturnValue The return value. + +Returns: + + EFI_SUCCESS Number successfully converted. + EFI_ABORTED Invalid character encountered. + +--*/ +{ + UINT8 Index; + UINT64 Value; + CHAR8 CurrentChar; + + // + // Initialize the result + // + Value = 0; + Index = 0; + + // + // Check input parameter + // + if (AsciiString == NULL || ReturnValue == NULL || strlen(AsciiString) > 0xFF) { + return EFI_INVALID_PARAMETER; + } + while (AsciiString[Index] == ' ') { + Index ++; + } + + // + // Add each character to the result + // + + // + // Skip first two chars only if the string starts with '0x' or '0X' + // + if (AsciiString[Index] == '0' && (AsciiString[Index + 1] == 'x' || AsciiString[Index + 1] == 'X')) { + IsHex = TRUE; + Index += 2; + } + if (IsHex) { + // + // Convert the hex string. + // + for (; AsciiString[Index] != '\0'; Index++) { + CurrentChar = AsciiString[Index]; + if (CurrentChar == ' ') { + break; + } + // + // Verify Hex string + // + if (isxdigit ((int)CurrentChar) == 0) { + return EFI_ABORTED; + } + // + // Add hex value + // + Value *= 16; + if (CurrentChar >= '0' && CurrentChar <= '9') { + Value += CurrentChar - '0'; + } else if (CurrentChar >= 'a' && CurrentChar <= 'f') { + Value += CurrentChar - 'a' + 10; + } else if (CurrentChar >= 'A' && CurrentChar <= 'F') { + Value += CurrentChar - 'A' + 10; + } + } + + *ReturnValue = Value; + } else { + // + // Convert dec string is a number + // + for (; Index < strlen (AsciiString); Index++) { + CurrentChar = AsciiString[Index]; + if (CurrentChar == ' ') { + break; + } + // + // Verify Dec string + // + if (isdigit ((int)CurrentChar) == 0) { + return EFI_ABORTED; + } + // + // Add dec value + // + Value = Value * 10; + Value += CurrentChar - '0'; + } + + *ReturnValue = Value; + } + + return EFI_SUCCESS; +} + +CHAR8 * +ReadLineInStream ( + IN FILE *InputFile, + IN OUT CHAR8 *InputBuffer + ) +/*++ + +Routine Description: + + This function reads a line, stripping any comments. + // BUGBUG: This is obsolete once genmake goes away... + +Arguments: + + InputFile Stream pointer. + InputBuffer Buffer to read into, must be MAX_LONG_FILE_PATH size. + +Returns: + + NULL if error or EOF + InputBuffer otherwise + +--*/ +{ + CHAR8 *CharPtr; + + // + // Verify input parameters are not null + // + assert (InputFile); + assert (InputBuffer); + + // + // Read a line + // + if (fgets (InputBuffer, MAX_LONG_FILE_PATH, InputFile) == NULL) { + return NULL; + } + // + // Strip any comments + // + CharPtr = strstr (InputBuffer, "//"); + if (CharPtr != 0) { + CharPtr[0] = 0; + } + + CharPtr = strstr (InputBuffer, "#"); + if (CharPtr != 0) { + CharPtr[0] = 0; + } + // + // Return the string + // + return InputBuffer; +} + +BOOLEAN +FindSectionInStream ( + IN FILE *InputFile, + IN CHAR8 *Section + ) +/*++ + +Routine Description: + + This function parses a stream file from the beginning to find a section. + The section string may be anywhere within a line. + // BUGBUG: This is obsolete once genmake goes away... + +Arguments: + + InputFile Stream pointer. + Section Section to search for + +Returns: + + FALSE if error or EOF + TRUE if section found + +--*/ +{ + CHAR8 InputBuffer[MAX_LONG_FILE_PATH]; + CHAR8 *CurrentToken; + + // + // Verify input is not NULL + // + assert (InputFile); + assert (Section); + + // + // Rewind to beginning of file + // + if (fseek (InputFile, 0, SEEK_SET) != 0) { + return FALSE; + } + // + // Read lines until the section is found + // + while (feof (InputFile) == 0) { + // + // Read a line + // + ReadLineInStream (InputFile, InputBuffer); + + // + // Check if the section is found + // + CurrentToken = strstr (InputBuffer, Section); + if (CurrentToken != NULL) { + return TRUE; + } + } + + return FALSE; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseInf.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseInf.h new file mode 100644 index 00000000..69c92cc1 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/ParseInf.h @@ -0,0 +1,220 @@ +/** @file +Header file for helper functions useful for parsing INF files. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_PARSE_INF_H +#define _EFI_PARSE_INF_H + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +// +// Functions declarations +// +CHAR8 * +ReadLine ( + IN MEMORY_FILE *InputFile, + IN OUT CHAR8 *InputBuffer, + IN UINTN MaxLength + ) +; + +/*++ + +Routine Description: + + This function reads a line, stripping any comments. + The function reads a string from the input stream argument and stores it in + the input string. ReadLine reads characters from the current file position + to and including the first newline character, to the end of the stream, or + until the number of characters read is equal to MaxLength - 1, whichever + comes first. The newline character, if read, is replaced with a \0. + +Arguments: + + InputFile Memory file image. + InputBuffer Buffer to read into, must be MaxLength size. + MaxLength The maximum size of the input buffer. + +Returns: + + NULL if error or EOF + InputBuffer otherwise + +--*/ +BOOLEAN +FindSection ( + IN MEMORY_FILE *InputFile, + IN CHAR8 *Section + ) +; + +/*++ + +Routine Description: + + This function parses a file from the beginning to find a section. + The section string may be anywhere within a line. + +Arguments: + + InputFile Memory file image. + Section Section to search for + +Returns: + + FALSE if error or EOF + TRUE if section found + +--*/ +EFI_STATUS +FindToken ( + IN MEMORY_FILE *InputFile, + IN CHAR8 *Section, + IN CHAR8 *Token, + IN UINTN Instance, + OUT CHAR8 *Value + ) +; + +/*++ + +Routine Description: + + Finds a token value given the section and token to search for. + +Arguments: + + InputFile Memory file image. + Section The section to search for, a string within []. + Token The token to search for, e.g. EFI_PEIM_RECOVERY, followed by an = in the INF file. + Instance The instance of the token to search for. Zero is the first instance. + Value The string that holds the value following the =. Must be MAX_LONG_FILE_PATH in size. + +Returns: + + EFI_SUCCESS Value found. + EFI_ABORTED Format error detected in INF file. + EFI_INVALID_PARAMETER Input argument was null. + EFI_LOAD_ERROR Error reading from the file. + EFI_NOT_FOUND Section/Token/Value not found. + +--*/ +EFI_STATUS +StringToGuid ( + IN CHAR8 *AsciiGuidBuffer, + OUT EFI_GUID *GuidBuffer + ) +; + +/*++ + +Routine Description: + + Converts a string to an EFI_GUID. The string must be in the + xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format. + +Arguments: + + GuidBuffer - pointer to destination Guid + AsciiGuidBuffer - pointer to ascii string + +Returns: + + EFI_ABORTED Could not convert the string + EFI_SUCCESS The string was successfully converted + +--*/ +EFI_STATUS +AsciiStringToUint64 ( + IN CONST CHAR8 *AsciiString, + IN BOOLEAN IsHex, + OUT UINT64 *ReturnValue + ) +; + +/*++ + +Routine Description: + + Converts a null terminated ascii string that represents a number into a + UINT64 value. A hex number may be preceded by a 0x, but may not be + succeeded by an h. A number without 0x or 0X is considered to be base 10 + unless the IsHex input is true. + +Arguments: + + AsciiString The string to convert. + IsHex Force the string to be treated as a hex number. + ReturnValue The return value. + +Returns: + + EFI_SUCCESS Number successfully converted. + EFI_ABORTED Invalid character encountered. + +--*/ +CHAR8 * +ReadLineInStream ( + IN FILE *InputFile, + IN OUT CHAR8 *InputBuffer + ) +; + +/*++ + +Routine Description: + + This function reads a line, stripping any comments. + +Arguments: + + InputFile Stream pointer. + InputBuffer Buffer to read into, must be MAX_LONG_FILE_PATH size. + +Returns: + + NULL if error or EOF + InputBuffer otherwise + +--*/ +BOOLEAN +FindSectionInStream ( + IN FILE *InputFile, + IN CHAR8 *Section + ) +; + +/*++ + +Routine Description: + + This function parses a stream file from the beginning to find a section. + The section string may be anywhere within a line. + +Arguments: + + InputFile Stream pointer. + Section Section to search for + +Returns: + + FALSE if error or EOF + TRUE if section found + +--*/ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.c new file mode 100644 index 00000000..de3b7446 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.c @@ -0,0 +1,779 @@ +/** @file +This file contains the PcdValue structure definition. + +Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include "CommonLib.h" +#include "PcdValueCommon.h" + +typedef enum { + PcdDataTypeBoolean, + PcdDataTypeUint8, + PcdDataTypeUint16, + PcdDataTypeUint32, + PcdDataTypeUint64, + PcdDataTypePointer +} PCD_DATA_TYPE; + +typedef struct { + CHAR8 *SkuName; + CHAR8 *DefaultValueName; + CHAR8 *TokenSpaceGuidName; + CHAR8 *TokenName; + CHAR8 *DataType; + CHAR8 *Value; + PCD_DATA_TYPE PcdDataType; +} PCD_ENTRY; + +PCD_ENTRY *PcdList; +UINT32 PcdListLength; + +VOID +STATIC +RecordToken ( + UINT8 *FileBuffer, + UINT32 PcdIndex, + UINT32 TokenIndex, + UINT32 TokenStart, + UINT32 TokenEnd + ) +/*++ + +Routine Description: + + Record new token information + +Arguments: + + FileBuffer File Buffer to be record + PcdIndex Index of PCD in database + TokenIndex Index of Token + TokenStart Start of Token + TokenEnd End of Token + +Returns: + + None +--*/ +{ + CHAR8 *Token; + + Token = malloc (TokenEnd - TokenStart + 1); + if (Token == NULL) { + return; + } + memcpy (Token, &FileBuffer[TokenStart], TokenEnd - TokenStart); + Token[TokenEnd - TokenStart] = 0; + switch (TokenIndex) { + case 0: + PcdList[PcdIndex].SkuName = Token; + break; + case 1: + PcdList[PcdIndex].DefaultValueName = Token; + break; + case 2: + PcdList[PcdIndex].TokenSpaceGuidName = Token; + break; + case 3: + PcdList[PcdIndex].TokenName = Token; + break; + case 4: + PcdList[PcdIndex].DataType = Token; + if (strcmp (Token, "BOOLEAN") == 0) { + PcdList[PcdIndex].PcdDataType = PcdDataTypeBoolean; + } else if (strcmp (Token, "UINT8") == 0) { + PcdList[PcdIndex].PcdDataType = PcdDataTypeUint8; + } else if (strcmp (Token, "UINT16") == 0) { + PcdList[PcdIndex].PcdDataType = PcdDataTypeUint16; + } else if (strcmp (Token, "UINT32") == 0) { + PcdList[PcdIndex].PcdDataType = PcdDataTypeUint32; + } else if (strcmp (Token, "UINT64") == 0) { + PcdList[PcdIndex].PcdDataType = PcdDataTypeUint64; + } else { + PcdList[PcdIndex].PcdDataType = PcdDataTypePointer; + } + break; + case 5: + PcdList[PcdIndex].Value = Token; + break; + default: + free (Token); + break; + } +} + +int +STATIC +LookupPcdIndex ( + CHAR8 *SkuName OPTIONAL, + CHAR8 *DefaultValueName OPTIONAL, + CHAR8 *TokenSpaceGuidName, + CHAR8 *TokenName + ) +/*++ + +Routine Description: + + Get PCD index in Pcd database + +Arguments: + + SkuName SkuName String + DefaultValueName DefaultValueName String + TokenSpaceGuidName TokenSpaceGuidName String + TokenName TokenName String + +Returns: + + Index of PCD in Pcd database +--*/ +{ + UINT32 Index; + + if (SkuName == NULL) { + SkuName = "DEFAULT"; + } + if (DefaultValueName == NULL) { + DefaultValueName = "DEFAULT"; + } + for (Index = 0; Index < PcdListLength; Index++) { + if (strcmp(PcdList[Index].TokenSpaceGuidName, TokenSpaceGuidName) != 0) { + continue; + } + if (strcmp(PcdList[Index].TokenName, TokenName) != 0) { + continue; + } + if (strcmp(PcdList[Index].SkuName, SkuName) != 0) { + continue; + } + if (strcmp(PcdList[Index].DefaultValueName, DefaultValueName) != 0) { + continue; + } + return Index; + } + return -1; +} + +UINT64 +__PcdGet ( + CHAR8 *SkuName OPTIONAL, + CHAR8 *DefaultValueName OPTIONAL, + CHAR8 *TokenSpaceGuidName, + CHAR8 *TokenName + ) +/*++ + +Routine Description: + + Get PCD value + +Arguments: + + SkuName SkuName String + DefaultValueName DefaultValueName String + TokenSpaceGuidName TokenSpaceGuidName String + TokenName TokenName String + +Returns: + + PCD value +--*/ +{ + int Index; + CHAR8 *End; + + Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName); + if (Index < 0) { + fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName); + exit (EXIT_FAILURE); + } + switch (PcdList[Index].PcdDataType) { + case PcdDataTypeBoolean: + case PcdDataTypeUint8: + case PcdDataTypeUint16: + case PcdDataTypeUint32: + return (UINT64)strtoul(PcdList[Index].Value, &End, 16); + break; + case PcdDataTypeUint64: + return (UINT64)strtoul(PcdList[Index].Value, &End, 16); + break; + case PcdDataTypePointer: + fprintf (stderr, "PCD %s.%s.%s.%s is structure. Use PcdGetPtr()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName); + exit (EXIT_FAILURE); + break; + } + return 0; +} + +VOID +__PcdSet ( + CHAR8 *SkuName OPTIONAL, + CHAR8 *DefaultValueName OPTIONAL, + CHAR8 *TokenSpaceGuidName, + CHAR8 *TokenName, + UINT64 Value + ) +/*++ + +Routine Description: + + Set PCD value + +Arguments: + + SkuName SkuName String + DefaultValueName DefaultValueName String + TokenSpaceGuidName TokenSpaceGuidName String + TokenName TokenName String + Value PCD value to be set + +Returns: + + None +--*/ +{ + int Index; + + Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName); + if (Index < 0) { + fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName); + exit (EXIT_FAILURE); + } + free(PcdList[Index].Value); + PcdList[Index].Value = malloc(20); + switch (PcdList[Index].PcdDataType) { + case PcdDataTypeBoolean: + if (Value == 0) { + strcpy (PcdList[Index].Value, "0x00"); + } else { + strcpy (PcdList[Index].Value, "0x01"); + } + break; + case PcdDataTypeUint8: + sprintf(PcdList[Index].Value, "0x%02x", (UINT8)(Value & 0xff)); + break; + case PcdDataTypeUint16: + sprintf(PcdList[Index].Value, "0x%04x", (UINT16)(Value & 0xffff)); + break; + case PcdDataTypeUint32: + sprintf(PcdList[Index].Value, "0x%08x", (UINT32)(Value & 0xffffffff)); + break; + case PcdDataTypeUint64: + sprintf(PcdList[Index].Value, "0x%016llx", (unsigned long long)Value); + break; + case PcdDataTypePointer: + fprintf (stderr, "PCD %s.%s.%s.%s is structure. Use PcdSetPtr()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName); + exit (EXIT_FAILURE); + break; + } +} + +VOID * +__PcdGetPtr ( + CHAR8 *SkuName OPTIONAL, + CHAR8 *DefaultValueName OPTIONAL, + CHAR8 *TokenSpaceGuidName, + CHAR8 *TokenName, + UINT32 *Size + ) +/*++ + +Routine Description: + + Get PCD value buffer + +Arguments: + + SkuName SkuName String + DefaultValueName DefaultValueName String + TokenSpaceGuidName TokenSpaceGuidName String + TokenName TokenName String + Size Size of PCD value buffer + +Returns: + + PCD value buffer +--*/ +{ + int Index; + CHAR8 *Value; + UINT8 *Buffer; + CHAR8 *End; + + Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName); + if (Index < 0) { + fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName); + exit (EXIT_FAILURE); + } + switch (PcdList[Index].PcdDataType) { + case PcdDataTypeBoolean: + case PcdDataTypeUint8: + case PcdDataTypeUint16: + case PcdDataTypeUint32: + case PcdDataTypeUint64: + fprintf (stderr, "PCD %s.%s.%s.%s is a value. Use PcdGet()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName); + exit (EXIT_FAILURE); + break; + case PcdDataTypePointer: + Value = &PcdList[Index].Value[1]; + for (*Size = 0, strtoul(Value, &End, 16); Value != End; strtoul(Value, &End, 16), *Size = *Size + 1) { + Value = End + 1; + } + Buffer = malloc(*Size + 1); + if (Buffer == NULL) { + *Size = 0; + return NULL; + } + Value = &PcdList[Index].Value[1]; + for (*Size = 0, Buffer[*Size] = (UINT8) strtoul(Value, &End, 16); Value != End; *Size = *Size + 1, Buffer[*Size] = (UINT8) strtoul(Value, &End, 16)) { + Value = End + 1; + } + return Buffer; + } + *Size = 0; + return 0; +} + +VOID +__PcdSetPtr ( + CHAR8 *SkuName OPTIONAL, + CHAR8 *DefaultValueName OPTIONAL, + CHAR8 *TokenSpaceGuidName, + CHAR8 *TokenName, + UINT32 Size, + UINT8 *Value + ) +/*++ + +Routine Description: + + Set PCD value buffer + +Arguments: + + SkuName SkuName String + DefaultValueName DefaultValueName String + TokenSpaceGuidName TokenSpaceGuidName String + TokenName TokenName String + Size Size of PCD value + Value Pointer to the updated PCD value buffer + +Returns: + + None +--*/ +{ + int Index; + UINT32 ValueIndex; + + Index = LookupPcdIndex (SkuName, DefaultValueName, TokenSpaceGuidName, TokenName); + if (Index < 0) { + fprintf (stderr, "PCD %s.%s.%s.%s is not in database\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName); + exit (EXIT_FAILURE); + } + switch (PcdList[Index].PcdDataType) { + case PcdDataTypeBoolean: + case PcdDataTypeUint8: + case PcdDataTypeUint16: + case PcdDataTypeUint32: + case PcdDataTypeUint64: + fprintf (stderr, "PCD %s.%s.%s.%s is a value. Use PcdGet()\n", SkuName, DefaultValueName, TokenSpaceGuidName, TokenName); + exit (EXIT_FAILURE); + break; + case PcdDataTypePointer: + free(PcdList[Index].Value); + PcdList[Index].Value = malloc(Size * 5 + 3); + PcdList[Index].Value[0] = '{'; + for (ValueIndex = 0; ValueIndex < Size; ValueIndex++) { + sprintf(&PcdList[Index].Value[1 + ValueIndex * 5], "0x%02x,", Value[ValueIndex]); + } + PcdList[Index].Value[1 + Size * 5 - 1] = '}'; + PcdList[Index].Value[1 + Size * 5 ] = 0; + break; + } +} + +VOID +STATIC +ReadInputFile ( + CHAR8 *InputFileName, + UINT8 **FileBuffer, + UINT32 *FileSize + ) +/*++ + +Routine Description: + + Read the file buffer from the input file. + +Arguments: + + InputFileName Point to the input file name. + FileBuffer Point to the input file buffer. + FileSize Size of the file buffer. + +Returns: + + None +--*/ +{ + FILE *InputFile; + UINT32 BytesRead; + + // + // Open Input file and read file data. + // + InputFile = fopen (InputFileName, "rb"); + if (InputFile == NULL) { + fprintf (stderr, "Error opening file %s\n", InputFileName); + exit (EXIT_FAILURE); + } + + // + // Go to the end so that we can determine the file size + // + if (fseek (InputFile, 0, SEEK_END)) { + fprintf (stderr, "Error reading input file %s\n", InputFileName); + fclose (InputFile); + exit (EXIT_FAILURE); + } + + // + // Get the file size + // + *FileSize = ftell (InputFile); + if (*FileSize == -1) { + fprintf (stderr, "Error parsing the input file %s\n", InputFileName); + fclose (InputFile); + exit (EXIT_FAILURE); + } + + // + // Allocate a buffer + // + *FileBuffer = malloc (*FileSize); + if (*FileBuffer == NULL) { + fprintf (stderr, "Can not allocate buffer for input input file %s\n", InputFileName); + fclose (InputFile); + exit (EXIT_FAILURE); + } + + // + // Reset to the beginning of the file + // + if (fseek (InputFile, 0, SEEK_SET)) { + fprintf (stderr, "Error reading the input file %s\n", InputFileName); + fclose (InputFile); + free (*FileBuffer); + exit (EXIT_FAILURE); + } + + // + // Read all of the file contents. + // + BytesRead = (UINT32)fread (*FileBuffer, sizeof (UINT8), *FileSize, InputFile); + if (BytesRead != *FileSize * sizeof (UINT8)) { + fprintf (stderr, "Error reading the input file %s\n", InputFileName); + fclose (InputFile); + free (*FileBuffer); + exit (EXIT_FAILURE); + } + + // + // Close the file + // + fclose (InputFile); +} + +VOID +STATIC +ParseFile ( + UINT8 *FileBuffer, + UINT32 FileSize + ) +/*++ + +Routine Description: + + Read the initial PCD value from the input file buffer. + +Arguments: + + FileBuffer Point to the input file buffer. + FileSize Size of the file buffer. + +Returns: + + None +--*/ +{ + UINT32 Index; + UINT32 NumLines; + UINT32 TokenIndex; + UINT32 TokenStart; + + for (Index = 0, NumLines = 0; Index < FileSize; Index++) { + if (FileBuffer[Index] == '\n') { + NumLines++; + } + } + PcdList = malloc((NumLines + 1) * sizeof(PcdList[0])); + + for (Index = 0, TokenIndex = 0, PcdListLength = 0, TokenStart = 0; Index < FileSize; Index++) { + if (FileBuffer[Index] == ' ') { + continue; + } + if (FileBuffer[Index] == '|' || FileBuffer[Index] == '.' || FileBuffer[Index] == '\n' || FileBuffer[Index] == '\r') { + RecordToken (FileBuffer, PcdListLength, TokenIndex, TokenStart, Index); + if (FileBuffer[Index] == '\n' || FileBuffer[Index] == '\r') { + if (TokenIndex != 0) { + PcdListLength++; + TokenIndex = 0; + } + } else { + TokenIndex++; + } + TokenStart = Index + 1; + continue; + } + } + if (Index > TokenStart) { + RecordToken (FileBuffer, PcdListLength, TokenIndex, TokenStart, Index); + if (TokenIndex != 0) { + PcdListLength++; + } + } +} + +VOID +STATIC +WriteOutputFile ( + CHAR8 *OutputFileName + ) +/*++ + +Routine Description: + + Write the updated PCD value into the output file name. + +Arguments: + + OutputFileName Point to the output file name. + +Returns: + + None +--*/ +{ + FILE *OutputFile; + UINT32 Index; + + // + // Open output file + // + OutputFile = fopen (OutputFileName, "wb"); + if (OutputFile == NULL) { + fprintf (stderr, "Error opening file %s\n", OutputFileName); + exit (EXIT_FAILURE); + } + + for (Index = 0; Index < PcdListLength; Index++) { + fprintf ( + OutputFile, + "%s.%s.%s.%s|%s|%s\n", + PcdList[Index].SkuName, + PcdList[Index].DefaultValueName, + PcdList[Index].TokenSpaceGuidName, + PcdList[Index].TokenName, + PcdList[Index].DataType, + PcdList[Index].Value + ); + } + + // + // Done, write output file. + // + if (OutputFile != NULL) { + fclose (OutputFile); + } +} + +VOID +STATIC +Usage ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + fprintf (stdout, "Usage: -i -o \n\n"); + fprintf (stdout, "optional arguments:\n"); + fprintf (stdout, " -h, --help Show this help message and exit\n"); + fprintf (stdout, " -i INPUT_FILENAME, --input INPUT_FILENAME\n\ + PCD Database Input file name\n"); + fprintf (stdout, " -o OUTPUT_FILENAME, --output OUTPUT_FILENAME\n\ + PCD Database Output file name\n"); +} + +VOID +STATIC +ParseArguments ( + int argc, + char *argv[], + CHAR8 **InputFileName, + CHAR8 **OutputFileName + ) +/*++ + +Routine Description: + + Parse the input parameters to get the input/output file name. + +Arguments: + + argc Number of command line parameters. + argv Array of pointers to parameter strings. + InputFileName Point to the input file name. + OutputFileName Point to the output file name. + +Returns: + + None +--*/ +{ + if (argc == 1) { + fprintf (stderr, "Missing options\n"); + exit (EXIT_FAILURE); + } + + // + // Parse command line + // + argc--; + argv++; + + if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) { + Usage (); + exit (EXIT_SUCCESS); + } + + while (argc > 0) { + if ((stricmp (argv[0], "-i") == 0) || (stricmp (argv[0], "--input") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + fprintf (stderr, "Invalid option value. Input File name is missing for -i option\n"); + exit (EXIT_FAILURE); + } + *InputFileName = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + fprintf (stderr, "Invalid option value. Output File name is missing for -i option\n"); + exit (EXIT_FAILURE); + } + *OutputFileName = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if (argv[0][0] == '-') { + fprintf (stderr, "Unknown option %s\n", argv[0]); + exit (EXIT_FAILURE); + } + argc --; + argv ++; + } + + // + // Check Input parameters + // + if (*InputFileName == NULL) { + fprintf (stderr, "Missing option. Input files is not specified\n"); + exit (EXIT_FAILURE); + } + + if (*OutputFileName == NULL) { + fprintf (stderr, "Missing option. Output file is not specified\n"); + exit (EXIT_FAILURE); + } +} + +int +PcdValueMain ( + int argc, + char *argv[] + ) +/*++ + +Routine Description: + + Main function updates PCD values. + +Arguments: + + argc Number of command line parameters. + argv Array of pointers to parameter strings. + +Returns: + EXIT_SUCCESS +--*/ +{ + CHAR8 *InputFileName; + CHAR8 *OutputFileName; + UINT8 *FileBuffer; + UINT32 FileSize; + + InputFileName = NULL; + OutputFileName = NULL; + + // + // Parse the input arguments + // + ParseArguments (argc, argv, &InputFileName, &OutputFileName); + + // + // Open Input file and read file data. + // + ReadInputFile (InputFileName, &FileBuffer, &FileSize); + + // + // Read the initial Pcd value + // + ParseFile (FileBuffer, FileSize); + + // + // Customize PCD values in the PCD Database + // + PcdEntryPoint (); + + // + // Save the updated PCD value + // + WriteOutputFile (OutputFileName); + + exit (EXIT_SUCCESS); +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.h new file mode 100644 index 00000000..f53d8a4b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PcdValueCommon.h @@ -0,0 +1,185 @@ +/** @file +Header file for PcdValue structure definition. + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _PCD_VALUE_COMMON_H +#define _PCD_VALUE_COMMON_H + +#include +#include + +#define __FIELD_SIZE(TYPE, Field) (sizeof((TYPE *)0)->Field) +#define __ARRAY_ELEMENT_SIZE(TYPE, Field) (sizeof((TYPE *)0)->Field[0]) +#define __OFFSET_OF(TYPE, Field) ((UINT32)(size_t) &(((TYPE *)0)->Field)) +#define __FLEXIBLE_SIZE(Size, TYPE, Field, MaxIndex) if (__FIELD_SIZE(TYPE, Field) == 0) Size = MAX((__OFFSET_OF(TYPE, Field) + __ARRAY_ELEMENT_SIZE(TYPE, Field) * (MaxIndex)), Size) +#define __ARRAY_SIZE(Array) (sizeof(Array)/sizeof(Array[0])) + +#if defined(_MSC_EXTENSIONS) +#define __STATIC_ASSERT static_assert +#else +#define __STATIC_ASSERT _Static_assert +#endif + +VOID +PcdEntryPoint ( + VOID + ) +/*++ + +Routine Description: + + Main function updates PCD values. It is auto generated by Build + +Arguments: + + None + +Returns: + None +--*/ +; + +int +PcdValueMain ( + int argc, + char *argv[] + ) +/*++ + +Routine Description: + + Main function updates PCD values. + +Arguments: + + argc Number of command line parameters. + argv Array of pointers to parameter strings. + +Returns: + EXIT_SUCCESS +--*/ +; + +VOID +__PcdSet ( + CHAR8 *SkuName OPTIONAL, + CHAR8 *DefaultValueName OPTIONAL, + CHAR8 *TokenSpaceGuidName, + CHAR8 *TokenName, + UINT64 Value + ) +/*++ + +Routine Description: + + Get PCD value + +Arguments: + + SkuName SkuName String + DefaultValueName DefaultValueName String + TokenSpaceGuidName TokenSpaceGuidName String + TokenName TokenName String + +Returns: + + PCD value +--*/ +; + +VOID +__PcdSet ( + CHAR8 *SkuName OPTIONAL, + CHAR8 *DefaultValueName OPTIONAL, + CHAR8 *TokenSpaceGuidName, + CHAR8 *TokenName, + UINT64 Value + ) +/*++ + +Routine Description: + + Set PCD value + +Arguments: + + SkuName SkuName String + DefaultValueName DefaultValueName String + TokenSpaceGuidName TokenSpaceGuidName String + TokenName TokenName String + Value PCD value to be set + +Returns: + + None +--*/ +; + +VOID * +__PcdGetPtr ( + CHAR8 *SkuName OPTIONAL, + CHAR8 *DefaultValueName OPTIONAL, + CHAR8 *TokenSpaceGuidName, + CHAR8 *TokenName, + UINT32 *Size + ) +/*++ + +Routine Description: + + Get PCD value buffer + +Arguments: + + SkuName SkuName String + DefaultValueName DefaultValueName String + TokenSpaceGuidName TokenSpaceGuidName String + TokenName TokenName String + Size Size of PCD value buffer + +Returns: + + PCD value buffer +--*/ +; + +VOID +__PcdSetPtr ( + CHAR8 *SkuName OPTIONAL, + CHAR8 *DefaultValueName OPTIONAL, + CHAR8 *TokenSpaceGuidName, + CHAR8 *TokenName, + UINT32 Size, + UINT8 *Value + ) +/*++ + +Routine Description: + + Set PCD value buffer + +Arguments: + + SkuName SkuName String + DefaultValueName DefaultValueName String + TokenSpaceGuidName TokenSpaceGuidName String + TokenName TokenName String + Size Size of PCD value + Value Pointer to the updated PCD value buffer + +Returns: + + None +--*/ +; + +#define PcdGet(A, B, C, D) __PcdGet(#A, #B, #C, #D) +#define PcdSet(A, B, C, D, Value) __PcdSet(#A, #B, #C, #D, Value) +#define PcdGetPtr(A, B, C, D, Size) __PcdGetPtr(#A, #B, #C, #D, Size) +#define PcdSetPtr(A, B, C, D, Size, Value) __PcdSetPtr(#A, #B, #C, #D, Size, Value) + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLib.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLib.h new file mode 100644 index 00000000..b625f6ac --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLib.h @@ -0,0 +1,213 @@ +/** @file + Function prototypes and defines on Memory Only PE COFF loader + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portion Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __BASE_PE_COFF_LIB_H__ +#define __BASE_PE_COFF_LIB_H__ + +// +// Return status codes from the PE/COFF Loader services +// BUGBUG: Find where used and see if can be replaced by RETURN_STATUS codes +// +#define IMAGE_ERROR_SUCCESS 0 +#define IMAGE_ERROR_IMAGE_READ 1 +#define IMAGE_ERROR_INVALID_PE_HEADER_SIGNATURE 2 +#define IMAGE_ERROR_INVALID_MACHINE_TYPE 3 +#define IMAGE_ERROR_INVALID_SUBSYSTEM 4 +#define IMAGE_ERROR_INVALID_IMAGE_ADDRESS 5 +#define IMAGE_ERROR_INVALID_IMAGE_SIZE 6 +#define IMAGE_ERROR_INVALID_SECTION_ALIGNMENT 7 +#define IMAGE_ERROR_SECTION_NOT_LOADED 8 +#define IMAGE_ERROR_FAILED_RELOCATION 9 +#define IMAGE_ERROR_FAILED_ICACHE_FLUSH 10 + +// +// Macro definitions for RISC-V architecture. +// +#define RV_X(x, s, n) (((x) >> (s)) & ((1<<(n))-1)) +#define RISCV_IMM_BITS 12 +#define RISCV_IMM_REACH (1LL<ImageRead() function + +**/ +RETURN_STATUS +EFIAPI +PeCoffLoaderGetImageInfo ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +; + +/** + Relocates a PE/COFF image in memory + + @param ImageContext Contains information on the loaded image to relocate + + @retval EFI_SUCCESS if the PE/COFF image was relocated + @retval EFI_LOAD_ERROR if the image is not a valid PE/COFF image + @retval EFI_UNSUPPORTED not support + +**/ +RETURN_STATUS +EFIAPI +PeCoffLoaderRelocateImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +; + +/** + Loads a PE/COFF image into memory + + @param ImageContext Contains information on image to load into memory + + @retval EFI_SUCCESS if the PE/COFF image was loaded + @retval EFI_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer + @retval EFI_LOAD_ERROR if the image is a runtime driver with no relocations + @retval EFI_INVALID_PARAMETER if the image address is invalid + +**/ +RETURN_STATUS +EFIAPI +PeCoffLoaderLoadImage ( + IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext + ) +; + +VOID * +EFIAPI +PeCoffLoaderGetPdbPointer ( + IN VOID *Pe32Data + ) +; + +RETURN_STATUS +EFIAPI +PeCoffLoaderGetEntryPoint ( + IN VOID *Pe32Data, + OUT VOID **EntryPoint, + OUT VOID **BaseOfImage + ) +; + +// +// These functions are used by the ARM PE/COFF relocation code and by +// the ELF to PE/COFF converter so that is why they are public +// + +/** + Pass in a pointer to an ARM MOVT or MOVW immediate instruction and + return the immediate data encoded in the instruction + + @param Instruction Pointer to ARM MOVT or MOVW immediate instruction + + @return Immediate address encoded in the instruction + +**/ +UINT16 +EFIAPI +ThumbMovtImmediateAddress ( + IN UINT16 *Instruction + ); + +/** + Update an ARM MOVT or MOVW immediate instruction immediate data. + + @param Instruction Pointer to ARM MOVT or MOVW immediate instruction + @param Address New address to patch into the instruction + +**/ +VOID +EFIAPI +ThumbMovtImmediatePatch ( + IN OUT UINT16 *Instruction, + IN UINT16 Address + ); + + +/** + Pass in a pointer to an ARM MOVW/MOVT instruction pair and + return the immediate data encoded in the two` instruction + + @param Instructions Pointer to ARM MOVW/MOVT instruction pair + + @return Immediate address encoded in the instructions + +**/ +UINT32 +EFIAPI +ThumbMovwMovtImmediateAddress ( + IN UINT16 *Instructions + ); + +/** + Update an ARM MOVW/MOVT immediate instruction instruction pair. + + @param Instructions Pointer to ARM MOVW/MOVT instruction pair + @param Address New address to patch into the instructions +**/ +VOID +EFIAPI +ThumbMovwMovtImmediatePatch ( + IN OUT UINT16 *Instructions, + IN UINT32 Address + ); + + + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLoaderEx.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLoaderEx.c new file mode 100644 index 00000000..b7492998 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/PeCoffLoaderEx.c @@ -0,0 +1,334 @@ +/** @file +IA32 and X64 Specific relocation fixups + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +--*/ + +#include +#include +#include "PeCoffLib.h" +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" + + +#define EXT_IMM64(Value, Address, Size, InstPos, ValPos) \ + Value |= (((UINT64)((*(Address) >> InstPos) & (((UINT64)1 << Size) - 1))) << ValPos) + +#define INS_IMM64(Value, Address, Size, InstPos, ValPos) \ + *(UINT32*)Address = (*(UINT32*)Address & ~(((1 << Size) - 1) << InstPos)) | \ + ((UINT32)((((UINT64)Value >> ValPos) & (((UINT64)1 << Size) - 1))) << InstPos) + +#define IMM64_IMM7B_INST_WORD_X 3 +#define IMM64_IMM7B_SIZE_X 7 +#define IMM64_IMM7B_INST_WORD_POS_X 4 +#define IMM64_IMM7B_VAL_POS_X 0 + +#define IMM64_IMM9D_INST_WORD_X 3 +#define IMM64_IMM9D_SIZE_X 9 +#define IMM64_IMM9D_INST_WORD_POS_X 18 +#define IMM64_IMM9D_VAL_POS_X 7 + +#define IMM64_IMM5C_INST_WORD_X 3 +#define IMM64_IMM5C_SIZE_X 5 +#define IMM64_IMM5C_INST_WORD_POS_X 13 +#define IMM64_IMM5C_VAL_POS_X 16 + +#define IMM64_IC_INST_WORD_X 3 +#define IMM64_IC_SIZE_X 1 +#define IMM64_IC_INST_WORD_POS_X 12 +#define IMM64_IC_VAL_POS_X 21 + +#define IMM64_IMM41a_INST_WORD_X 1 +#define IMM64_IMM41a_SIZE_X 10 +#define IMM64_IMM41a_INST_WORD_POS_X 14 +#define IMM64_IMM41a_VAL_POS_X 22 + +#define IMM64_IMM41b_INST_WORD_X 1 +#define IMM64_IMM41b_SIZE_X 8 +#define IMM64_IMM41b_INST_WORD_POS_X 24 +#define IMM64_IMM41b_VAL_POS_X 32 + +#define IMM64_IMM41c_INST_WORD_X 2 +#define IMM64_IMM41c_SIZE_X 23 +#define IMM64_IMM41c_INST_WORD_POS_X 0 +#define IMM64_IMM41c_VAL_POS_X 40 + +#define IMM64_SIGN_INST_WORD_X 3 +#define IMM64_SIGN_SIZE_X 1 +#define IMM64_SIGN_INST_WORD_POS_X 27 +#define IMM64_SIGN_VAL_POS_X 63 + +UINT32 *RiscVHi20Fixup = NULL; + +RETURN_STATUS +PeCoffLoaderRelocateIa32Image ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +/*++ + +Routine Description: + + Performs an IA-32 specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + EFI_UNSUPPORTED - Unsupported now + +--*/ +{ + return RETURN_UNSUPPORTED; +} + +/*++ + +Routine Description: + + Performs an RISC-V specific relocation fixup + +Arguments: + + Reloc - Pointer to the relocation record + + Fixup - Pointer to the address to fix up + + FixupData - Pointer to a buffer to log the fixups + + Adjust - The offset to adjust the fixup + +Returns: + + Status code + +--*/ +RETURN_STATUS +PeCoffLoaderRelocateRiscVImage ( + IN UINT16 *Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +{ + UINT32 Value; + UINT32 Value2; + + switch ((*Reloc) >> 12) { + case EFI_IMAGE_REL_BASED_RISCV_HI20: + RiscVHi20Fixup = (UINT32 *) Fixup; + break; + + case EFI_IMAGE_REL_BASED_RISCV_LOW12I: + if (RiscVHi20Fixup != NULL) { + Value = (UINT32)(RV_X(*RiscVHi20Fixup, 12, 20) << 12); + Value2 = (UINT32)(RV_X(*(UINT32 *)Fixup, 20, 12)); + if (Value2 & (RISCV_IMM_REACH/2)) { + Value2 |= ~(RISCV_IMM_REACH-1); + } + Value += Value2; + Value += (UINT32)Adjust; + Value2 = RISCV_CONST_HIGH_PART (Value); + *(UINT32 *)RiscVHi20Fixup = (RV_X (Value2, 12, 20) << 12) | \ + (RV_X (*(UINT32 *)RiscVHi20Fixup, 0, 12)); + *(UINT32 *)Fixup = (RV_X (Value, 0, 12) << 20) | \ + (RV_X (*(UINT32 *)Fixup, 0, 20)); + } + RiscVHi20Fixup = NULL; + break; + + case EFI_IMAGE_REL_BASED_RISCV_LOW12S: + if (RiscVHi20Fixup != NULL) { + Value = (UINT32)(RV_X(*RiscVHi20Fixup, 12, 20) << 12); + Value2 = (UINT32)(RV_X(*(UINT32 *)Fixup, 7, 5) | (RV_X(*(UINT32 *)Fixup, 25, 7) << 5)); + if (Value2 & (RISCV_IMM_REACH/2)) { + Value2 |= ~(RISCV_IMM_REACH-1); + } + Value += Value2; + Value += (UINT32)Adjust; + Value2 = RISCV_CONST_HIGH_PART (Value); + *(UINT32 *)RiscVHi20Fixup = (RV_X (Value2, 12, 20) << 12) | \ + (RV_X (*(UINT32 *)RiscVHi20Fixup, 0, 12)); + Value2 = *(UINT32 *)Fixup & 0x01fff07f; + Value &= RISCV_IMM_REACH - 1; + *(UINT32 *)Fixup = Value2 | (UINT32)(((RV_X(Value, 0, 5) << 7) | (RV_X(Value, 5, 7) << 25))); + } + RiscVHi20Fixup = NULL; + break; + + default: + return EFI_UNSUPPORTED; + + } + return RETURN_SUCCESS; +} + +/** + Pass in a pointer to an ARM MOVT or MOVW immediate instruction and + return the immediate data encoded in the instruction + + @param Instruction Pointer to ARM MOVT or MOVW immediate instruction + + @return Immediate address encoded in the instruction + +**/ +UINT16 +ThumbMovtImmediateAddress ( + IN UINT16 *Instruction + ) +{ + UINT32 Movt; + UINT16 Address; + + // Thumb2 is two 16-bit instructions working together. Not a single 32-bit instruction + // Example MOVT R0, #0 is 0x0000f2c0 or 0xf2c0 0x0000 + Movt = (*Instruction << 16) | (*(Instruction + 1)); + + // imm16 = imm4:i:imm3:imm8 + // imm4 -> Bit19:Bit16 + // i -> Bit26 + // imm3 -> Bit14:Bit12 + // imm8 -> Bit7:Bit0 + Address = (UINT16)(Movt & 0x000000ff); // imm8 + Address |= (UINT16)((Movt >> 4) & 0x0000f700); // imm4 imm3 + Address |= (((Movt & BIT26) != 0) ? BIT11 : 0); // i + return Address; +} + + +/** + Update an ARM MOVT or MOVW immediate instruction immediate data. + + @param Instruction Pointer to ARM MOVT or MOVW immediate instruction + @param Address New address to patch into the instruction +**/ +VOID +ThumbMovtImmediatePatch ( + IN OUT UINT16 *Instruction, + IN UINT16 Address + ) +{ + UINT16 Patch; + + // First 16-bit chunk of instruction + Patch = ((Address >> 12) & 0x000f); // imm4 + Patch |= (((Address & BIT11) != 0) ? BIT10 : 0); // i + *Instruction = (*Instruction & ~0x040f) | Patch; + + // Second 16-bit chunk of instruction + Patch = Address & 0x000000ff; // imm8 + Patch |= ((Address << 4) & 0x00007000); // imm3 + Instruction++; + *Instruction = (*Instruction & ~0x70ff) | Patch; +} + +/** + Pass in a pointer to an ARM MOVW/MOVT instruction pair and + return the immediate data encoded in the two` instruction + + @param Instructions Pointer to ARM MOVW/MOVT instruction pair + + @return Immediate address encoded in the instructions + +**/ +UINT32 +EFIAPI +ThumbMovwMovtImmediateAddress ( + IN UINT16 *Instructions + ) +{ + UINT16 *Word; + UINT16 *Top; + + Word = Instructions; // MOVW + Top = Word + 2; // MOVT + + return (ThumbMovtImmediateAddress (Top) << 16) + ThumbMovtImmediateAddress (Word); +} + + +/** + Update an ARM MOVW/MOVT immediate instruction instruction pair. + + @param Instructions Pointer to ARM MOVW/MOVT instruction pair + @param Address New address to patch into the instructions +**/ +VOID +EFIAPI +ThumbMovwMovtImmediatePatch ( + IN OUT UINT16 *Instructions, + IN UINT32 Address + ) +{ + UINT16 *Word; + UINT16 *Top; + + Word = (UINT16 *)Instructions; // MOVW + Top = Word + 2; // MOVT + + ThumbMovtImmediatePatch (Word, (UINT16)(Address & 0xffff)); + ThumbMovtImmediatePatch (Top, (UINT16)(Address >> 16)); +} + + +/** + Performs an ARM-based specific relocation fixup and is a no-op on other + instruction sets. + + @param Reloc Pointer to the relocation record. + @param Fixup Pointer to the address to fix up. + @param FixupData Pointer to a buffer to log the fixups. + @param Adjust The offset to adjust the fixup. + + @return Status code. + +**/ +RETURN_STATUS +PeCoffLoaderRelocateArmImage ( + IN UINT16 **Reloc, + IN OUT CHAR8 *Fixup, + IN OUT CHAR8 **FixupData, + IN UINT64 Adjust + ) +{ + UINT16 *Fixup16; + UINT32 FixupVal; + + Fixup16 = (UINT16 *) Fixup; + + switch ((**Reloc) >> 12) { + + case EFI_IMAGE_REL_BASED_ARM_MOV32T: + FixupVal = ThumbMovwMovtImmediateAddress (Fixup16) + (UINT32)Adjust; + ThumbMovwMovtImmediatePatch (Fixup16, FixupVal); + + + if (*FixupData != NULL) { + *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64)); + CopyMem (*FixupData, Fixup16, sizeof (UINT64)); + *FixupData = *FixupData + sizeof(UINT64); + } + break; + + case EFI_IMAGE_REL_BASED_ARM_MOV32A: + // break omitted - ARM instruction encoding not implemented + default: + return RETURN_UNSUPPORTED; + } + + return RETURN_SUCCESS; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/SimpleFileParsing.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/SimpleFileParsing.c new file mode 100644 index 00000000..337899ed --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/SimpleFileParsing.c @@ -0,0 +1,1429 @@ +/** @file +Generic but simple file parsing routines. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +--*/ + +#include +#include +#include +#include + +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" +#include "SimpleFileParsing.h" + +#ifndef MAX_PATH +#define MAX_PATH 255 +#endif +// +// just in case we get in an endless loop. +// +#define MAX_NEST_DEPTH 20 +// +// number of wchars +// +#define MAX_STRING_IDENTIFIER_NAME 100 + +#define T_CHAR_SPACE ' ' +#define T_CHAR_NULL 0 +#define T_CHAR_CR '\r' +#define T_CHAR_TAB '\t' +#define T_CHAR_LF '\n' +#define T_CHAR_SLASH '/' +#define T_CHAR_BACKSLASH '\\' +#define T_CHAR_DOUBLE_QUOTE '"' +#define T_CHAR_LC_X 'x' +#define T_CHAR_0 '0' +#define T_CHAR_STAR '*' + +// +// We keep a linked list of these for the source files we process +// +typedef struct _SOURCE_FILE { + FILE *Fptr; + CHAR8 *FileBuffer; + CHAR8 *FileBufferPtr; + UINTN FileSize; + CHAR8 FileName[MAX_PATH]; + UINTN LineNum; + BOOLEAN EndOfFile; + BOOLEAN SkipToHash; + struct _SOURCE_FILE *Previous; + struct _SOURCE_FILE *Next; + CHAR8 ControlCharacter; +} SOURCE_FILE; + +typedef struct { + CHAR8 *FileBufferPtr; +} FILE_POSITION; + +// +// Keep all our module globals in this structure +// +STATIC struct { + SOURCE_FILE SourceFile; + BOOLEAN VerboseFile; + BOOLEAN VerboseToken; +} mGlobals; + +STATIC +UINTN +t_strcmp ( + CHAR8 *Buffer, + CHAR8 *Str + ); + +STATIC +UINTN +t_strncmp ( + CHAR8 *Str1, + CHAR8 *Str2, + INTN Len + ); + +STATIC +UINTN +t_strlen ( + CHAR8 *Str + ); + +STATIC +VOID +RewindFile ( + SOURCE_FILE *SourceFile + ); + +STATIC +BOOLEAN +IsWhiteSpace ( + SOURCE_FILE *SourceFile + ); + +STATIC +UINTN +SkipWhiteSpace ( + SOURCE_FILE *SourceFile + ); + +STATIC +BOOLEAN +EndOfFile ( + SOURCE_FILE *SourceFile + ); + +STATIC +VOID +PreprocessFile ( + SOURCE_FILE *SourceFile + ); + +STATIC +CHAR8 * +t_strcpy ( + CHAR8 *Dest, + CHAR8 *Src + ); + +STATIC +STATUS +ProcessIncludeFile ( + SOURCE_FILE *SourceFile, + SOURCE_FILE *ParentSourceFile + ); + +STATIC +STATUS +ProcessFile ( + SOURCE_FILE *SourceFile + ); + +STATIC +STATUS +GetFilePosition ( + FILE_POSITION *Fpos + ); + +STATIC +STATUS +SetFilePosition ( + FILE_POSITION *Fpos + ); + +STATUS +SFPInit ( + VOID + ) +/*++ + +Routine Description: + +Arguments: + None. + +Returns: + STATUS_SUCCESS always + +--*/ +{ + memset ((VOID *) &mGlobals, 0, sizeof (mGlobals)); + return STATUS_SUCCESS; +} + +UINTN +SFPGetLineNumber ( + VOID + ) +/*++ + +Routine Description: + Return the line number of the file we're parsing. Used + for error reporting purposes. + +Arguments: + None. + +Returns: + The line number, or 0 if no file is being processed + +--*/ +{ + return mGlobals.SourceFile.LineNum; +} + +CHAR8 * +SFPGetFileName ( + VOID + ) +/*++ + +Routine Description: + Return the name of the file we're parsing. Used + for error reporting purposes. + +Arguments: + None. + +Returns: + A pointer to the file name. Null if no file is being + processed. + +--*/ +{ + if (mGlobals.SourceFile.FileName[0]) { + return mGlobals.SourceFile.FileName; + } + + return NULL; +} + +STATUS +SFPOpenFile ( + CHAR8 *FileName + ) +/*++ + +Routine Description: + Open a file for parsing. + +Arguments: + FileName - name of the file to parse + +Returns: + + +--*/ +{ + STATUS Status; + t_strcpy (mGlobals.SourceFile.FileName, FileName); + Status = ProcessIncludeFile (&mGlobals.SourceFile, NULL); + return Status; +} + +BOOLEAN +SFPIsToken ( + CHAR8 *Str + ) +/*++ + +Routine Description: + Check to see if the specified token is found at + the current position in the input file. + +Arguments: + Str - the token to look for + +Returns: + TRUE - the token is next + FALSE - the token is not next + +Notes: + We do a simple string comparison on this function. It is + the responsibility of the caller to ensure that the token + is not a subset of some other token. + + The file pointer is advanced past the token in the input file. + +--*/ +{ + UINTN Len; + SkipWhiteSpace (&mGlobals.SourceFile); + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + + if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) { + mGlobals.SourceFile.FileBufferPtr += Len; + if (mGlobals.VerboseToken) { + printf ("Token: '%s'\n", Str); + } + + return TRUE; + } + + return FALSE; +} + +BOOLEAN +SFPIsKeyword ( + CHAR8 *Str + ) +/*++ + +Routine Description: + Check to see if the specified keyword is found at + the current position in the input file. + +Arguments: + Str - keyword to look for + +Returns: + TRUE - the keyword is next + FALSE - the keyword is not next + +Notes: + A keyword is defined as a "special" string that has a non-alphanumeric + character following it. + +--*/ +{ + UINTN Len; + SkipWhiteSpace (&mGlobals.SourceFile); + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + + if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) { + if (isalnum ((int)mGlobals.SourceFile.FileBufferPtr[Len])) { + return FALSE; + } + + mGlobals.SourceFile.FileBufferPtr += Len; + if (mGlobals.VerboseToken) { + printf ("Token: '%s'\n", Str); + } + + return TRUE; + } + + return FALSE; +} + +BOOLEAN +SFPGetNextToken ( + CHAR8 *Str, + UINTN Len + ) +/*++ + +Routine Description: + Get the next token from the input stream. + +Arguments: + Str - pointer to a copy of the next token + Len - size of buffer pointed to by Str + +Returns: + TRUE - next token successfully returned + FALSE - otherwise + +Notes: + Preceding white space is ignored. + The parser's buffer pointer is advanced past the end of the + token. + +--*/ +{ + UINTN Index; + CHAR8 TempChar; + + SkipWhiteSpace (&mGlobals.SourceFile); + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + // + // Have to have enough string for at least one char and a null-terminator + // + if (Len < 2) { + return FALSE; + } + // + // Look at the first character. If it's an identifier, then treat it + // as such + // + TempChar = mGlobals.SourceFile.FileBufferPtr[0]; + if (((TempChar >= 'a') && (TempChar <= 'z')) || ((TempChar >= 'A') && (TempChar <= 'Z')) || (TempChar == '_')) { + Str[0] = TempChar; + mGlobals.SourceFile.FileBufferPtr++; + Index = 1; + while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) { + TempChar = mGlobals.SourceFile.FileBufferPtr[0]; + if (((TempChar >= 'a') && (TempChar <= 'z')) || + ((TempChar >= 'A') && (TempChar <= 'Z')) || + ((TempChar >= '0') && (TempChar <= '9')) || + (TempChar == '_') + ) { + Str[Index] = mGlobals.SourceFile.FileBufferPtr[0]; + mGlobals.SourceFile.FileBufferPtr++; + Index++; + } else { + // + // Invalid character for symbol name, so break out + // + break; + } + } + // + // Null terminate and return success + // + Str[Index] = 0; + return TRUE; + } else if ((TempChar == ')') || (TempChar == '(') || (TempChar == '*')) { + Str[0] = mGlobals.SourceFile.FileBufferPtr[0]; + mGlobals.SourceFile.FileBufferPtr++; + Str[1] = 0; + return TRUE; + } else { + // + // Everything else is white-space (or EOF) separated + // + Index = 0; + while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) { + if (IsWhiteSpace (&mGlobals.SourceFile)) { + if (Index > 0) { + Str[Index] = 0; + return TRUE; + } + + return FALSE; + } else { + Str[Index] = mGlobals.SourceFile.FileBufferPtr[0]; + mGlobals.SourceFile.FileBufferPtr++; + Index++; + } + } + // + // See if we just ran out of file contents, but did find a token + // + if ((Index > 0) && EndOfFile (&mGlobals.SourceFile)) { + Str[Index] = 0; + return TRUE; + } + } + + return FALSE; +} + +BOOLEAN +SFPGetGuidToken ( + CHAR8 *Str, + UINT32 Len + ) +/*++ + +Routine Description: + Parse a GUID from the input stream. Stop when you discover white space. + +Arguments: + Str - pointer to a copy of the next token + Len - size of buffer pointed to by Str + +Returns: + TRUE - GUID string returned successfully + FALSE - otherwise + +--*/ +{ + UINT32 Index; + SkipWhiteSpace (&mGlobals.SourceFile); + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + + Index = 0; + while (!EndOfFile (&mGlobals.SourceFile) && (Index < Len)) { + if (IsWhiteSpace (&mGlobals.SourceFile)) { + if (Index > 0) { + Str[Index] = 0; + return TRUE; + } + + return FALSE; + } else { + Str[Index] = mGlobals.SourceFile.FileBufferPtr[0]; + mGlobals.SourceFile.FileBufferPtr++; + Index++; + } + } + + return FALSE; +} + +BOOLEAN +SFPSkipToToken ( + CHAR8 *Str + ) +{ + UINTN Len; + CHAR8 *SavePos; + Len = t_strlen (Str); + SavePos = mGlobals.SourceFile.FileBufferPtr; + SkipWhiteSpace (&mGlobals.SourceFile); + while (!EndOfFile (&mGlobals.SourceFile)) { + if (t_strncmp (Str, mGlobals.SourceFile.FileBufferPtr, Len) == 0) { + mGlobals.SourceFile.FileBufferPtr += Len; + return TRUE; + } + + mGlobals.SourceFile.FileBufferPtr++; + SkipWhiteSpace (&mGlobals.SourceFile); + } + + mGlobals.SourceFile.FileBufferPtr = SavePos; + return FALSE; +} + +BOOLEAN +SFPGetNumber ( + UINTN *Value + ) +/*++ + +Routine Description: + Check the token at the current file position for a numeric value. + May be either decimal or hex. + +Arguments: + Value - pointer where to store the value + +Returns: + FALSE - current token is not a number + TRUE - current token is a number + +--*/ +{ + int Val; + + SkipWhiteSpace (&mGlobals.SourceFile); + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + + if (isdigit ((int)mGlobals.SourceFile.FileBufferPtr[0])) { + // + // Check for hex value + // + if ((mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_0) && (mGlobals.SourceFile.FileBufferPtr[1] == T_CHAR_LC_X)) { + if (!isxdigit ((int)mGlobals.SourceFile.FileBufferPtr[2])) { + return FALSE; + } + + mGlobals.SourceFile.FileBufferPtr += 2; + sscanf (mGlobals.SourceFile.FileBufferPtr, "%x", &Val); + *Value = (UINT32) Val; + while (isxdigit ((int)mGlobals.SourceFile.FileBufferPtr[0])) { + mGlobals.SourceFile.FileBufferPtr++; + } + + return TRUE; + } else { + *Value = atoi (mGlobals.SourceFile.FileBufferPtr); + while (isdigit ((int)mGlobals.SourceFile.FileBufferPtr[0])) { + mGlobals.SourceFile.FileBufferPtr++; + } + + return TRUE; + } + } else { + return FALSE; + } +} + +STATUS +SFPCloseFile ( + VOID + ) +/*++ + +Routine Description: + Close the file being parsed. + +Arguments: + None. + +Returns: + STATUS_SUCCESS - the file was closed + STATUS_ERROR - no file is currently open + +--*/ +{ + if (mGlobals.SourceFile.FileBuffer != NULL) { + free (mGlobals.SourceFile.FileBuffer); + memset (&mGlobals.SourceFile, 0, sizeof (mGlobals.SourceFile)); + return STATUS_SUCCESS; + } + + return STATUS_ERROR; +} + +STATIC +STATUS +ProcessIncludeFile ( + SOURCE_FILE *SourceFile, + SOURCE_FILE *ParentSourceFile + ) +/*++ + +Routine Description: + + Given a source file, open the file and parse it + +Arguments: + + SourceFile - name of file to parse + ParentSourceFile - for error reporting purposes, the file that #included SourceFile. + +Returns: + + Standard status. + +--*/ +{ + STATIC UINTN NestDepth = 0; + CHAR8 FoundFileName[MAX_PATH]; + STATUS Status; + + Status = STATUS_SUCCESS; + NestDepth++; + // + // Print the file being processed. Indent so you can tell the include nesting + // depth. + // + if (mGlobals.VerboseFile) { + fprintf (stdout, "%*cProcessing file '%s'\n", (int)NestDepth * 2, ' ', SourceFile->FileName); + fprintf (stdout, "Parent source file = '%s'\n", ParentSourceFile->FileName); + } + + // + // Make sure we didn't exceed our maximum nesting depth + // + if (NestDepth > MAX_NEST_DEPTH) { + Error (NULL, 0, 3001, "Not Supported", "%s exceeds max nesting depth (%u)", SourceFile->FileName, (unsigned) NestDepth); + Status = STATUS_ERROR; + goto Finish; + } + // + // Try to open the file locally, and if that fails try along our include paths. + // + strcpy (FoundFileName, SourceFile->FileName); + if ((SourceFile->Fptr = fopen (LongFilePath (FoundFileName), "rb")) == NULL) { + return STATUS_ERROR; + } + // + // Process the file found + // + ProcessFile (SourceFile); +Finish: + // + // Close open files and return status + // + if (SourceFile->Fptr != NULL) { + fclose (SourceFile->Fptr); + SourceFile->Fptr = NULL; + } + + return Status; +} + +STATIC +STATUS +ProcessFile ( + SOURCE_FILE *SourceFile + ) +/*++ + +Routine Description: + + Given a source file that's been opened, read the contents into an internal + buffer and pre-process it to remove comments. + +Arguments: + + SourceFile - structure containing info on the file to process + +Returns: + + Standard status. + +--*/ +{ + // + // Get the file size, and then read the entire thing into memory. + // Allocate extra space for a terminator character. + // + fseek (SourceFile->Fptr, 0, SEEK_END); + SourceFile->FileSize = ftell (SourceFile->Fptr); + if (mGlobals.VerboseFile) { + printf ("FileSize = %u (0x%X)\n", (unsigned) SourceFile->FileSize, (unsigned) SourceFile->FileSize); + } + + fseek (SourceFile->Fptr, 0, SEEK_SET); + SourceFile->FileBuffer = (CHAR8 *) malloc (SourceFile->FileSize + sizeof (CHAR8 )); + if (SourceFile->FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource: memory cannot be allocated", NULL); + return STATUS_ERROR; + } + + fread ((VOID *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr); + SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (CHAR8 ))] = T_CHAR_NULL; + // + // Pre-process the file to replace comments with spaces + // + PreprocessFile (SourceFile); + SourceFile->LineNum = 1; + return STATUS_SUCCESS; +} + +STATIC +VOID +PreprocessFile ( + SOURCE_FILE *SourceFile + ) +/*++ + +Routine Description: + Preprocess a file to replace all carriage returns with NULLs so + we can print lines (as part of error messages) from the file to the screen. + +Arguments: + SourceFile - structure that we use to keep track of an input file. + +Returns: + Nothing. + +--*/ +{ + BOOLEAN InComment; + BOOLEAN SlashSlashComment; + int LineNum; + + RewindFile (SourceFile); + InComment = FALSE; + SlashSlashComment = FALSE; + while (!EndOfFile (SourceFile)) { + // + // If a line-feed, then no longer in a comment if we're in a // comment + // + if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) { + SourceFile->FileBufferPtr++; + SourceFile->LineNum++; + if (InComment && SlashSlashComment) { + InComment = FALSE; + SlashSlashComment = FALSE; + } + } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) { + // + // Replace all carriage returns with a NULL so we can print stuff + // + SourceFile->FileBufferPtr[0] = 0; + SourceFile->FileBufferPtr++; + // + // Check for */ comment end + // + } else if (InComment && + !SlashSlashComment && + (SourceFile->FileBufferPtr[0] == T_CHAR_STAR) && + (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH) + ) { + SourceFile->FileBufferPtr[0] = T_CHAR_SPACE; + SourceFile->FileBufferPtr++; + SourceFile->FileBufferPtr[0] = T_CHAR_SPACE; + SourceFile->FileBufferPtr++; + InComment = FALSE; + } else if (InComment) { + SourceFile->FileBufferPtr[0] = T_CHAR_SPACE; + SourceFile->FileBufferPtr++; + // + // Check for // comments + // + } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_SLASH)) { + InComment = TRUE; + SlashSlashComment = TRUE; + // + // Check for /* comment start + // + } else if ((SourceFile->FileBufferPtr[0] == T_CHAR_SLASH) && (SourceFile->FileBufferPtr[1] == T_CHAR_STAR)) { + SourceFile->FileBufferPtr[0] = T_CHAR_SPACE; + SourceFile->FileBufferPtr++; + SourceFile->FileBufferPtr[0] = T_CHAR_SPACE; + SourceFile->FileBufferPtr++; + SlashSlashComment = FALSE; + InComment = TRUE; + } else { + SourceFile->FileBufferPtr++; + } + } + // + // Could check for end-of-file and still in a comment, but + // should not be necessary. So just restore the file pointers. + // + RewindFile (SourceFile); + // + // Dump the reformatted file if verbose mode + // + if (mGlobals.VerboseFile) { + LineNum = 1; + printf ("%04d: ", LineNum); + while (!EndOfFile (SourceFile)) { + if (SourceFile->FileBufferPtr[0] == T_CHAR_LF) { + printf ("'\n%04d: '", ++LineNum); + } else { + printf ("%c", SourceFile->FileBufferPtr[0]); + } + + SourceFile->FileBufferPtr++; + } + + printf ("'\n"); + printf ("FileSize = %u (0x%X)\n", (unsigned)SourceFile->FileSize, (unsigned)SourceFile->FileSize); + RewindFile (SourceFile); + } +} + +BOOLEAN +SFPGetQuotedString ( + CHAR8 *Str, + INTN Length + ) +/*++ + +Routine Description: + Retrieve a quoted-string from the input file. + +Arguments: + Str - pointer to a copy of the quoted string parsed + Length - size of buffer pointed to by Str + +Returns: + TRUE - next token in input stream was a quoted string, and + the string value was returned in Str + FALSE - otherwise + +--*/ +{ + SkipWhiteSpace (&mGlobals.SourceFile); + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + + if (mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) { + mGlobals.SourceFile.FileBufferPtr++; + while (Length > 0) { + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + // + // Check for closing quote + // + if (mGlobals.SourceFile.FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) { + mGlobals.SourceFile.FileBufferPtr++; + *Str = 0; + return TRUE; + } + + *Str = mGlobals.SourceFile.FileBufferPtr[0]; + Str++; + Length--; + mGlobals.SourceFile.FileBufferPtr++; + } + } + // + // First character was not a quote, or the input string length was + // insufficient to contain the quoted string, so return failure code. + // + return FALSE; +} + +BOOLEAN +SFPIsEOF ( + VOID + ) +/*++ + +Routine Description: + Return TRUE of FALSE to indicate whether or not we've reached the end of the + file we're parsing. + +Arguments: + NA + +Returns: + TRUE - EOF reached + FALSE - otherwise + +--*/ +{ + SkipWhiteSpace (&mGlobals.SourceFile); + return EndOfFile (&mGlobals.SourceFile); +} + +#if 0 +STATIC +CHAR8 * +GetQuotedString ( + SOURCE_FILE *SourceFile, + BOOLEAN Optional + ) +{ + CHAR8 *String; + CHAR8 *Start; + CHAR8 *Ptr; + UINTN Len; + BOOLEAN PreviousBackslash; + + if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) { + if (Optional == FALSE) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted string", "%S", SourceFile->FileBufferPtr); + } + + return NULL; + } + + Len = 0; + SourceFile->FileBufferPtr++; + Start = Ptr = SourceFile->FileBufferPtr; + PreviousBackslash = FALSE; + while (!EndOfFile (SourceFile)) { + if ((SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) && (PreviousBackslash == FALSE)) { + break; + } else if (SourceFile->FileBufferPtr[0] == T_CHAR_CR) { + Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start); + PreviousBackslash = FALSE; + } else if (SourceFile->FileBufferPtr[0] == T_CHAR_BACKSLASH) { + PreviousBackslash = TRUE; + } else { + PreviousBackslash = FALSE; + } + + SourceFile->FileBufferPtr++; + Len++; + } + + if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) { + Warning (SourceFile->FileName, SourceFile->LineNum, 0, "missing closing quote on string", "%S", Start); + } else { + SourceFile->FileBufferPtr++; + } + // + // Now allocate memory for the string and save it off + // + String = (CHAR8 *) malloc ((Len + 1) * sizeof (CHAR8 )); + if (String == NULL) { + Error (NULL, 0, 4001, "Resource: memory cannot be allocated", NULL); + return NULL; + } + // + // Copy the string from the file buffer to the local copy. + // We do no reformatting of it whatsoever at this point. + // + Ptr = String; + while (Len > 0) { + *Ptr = *Start; + Start++; + Ptr++; + Len--; + } + + *Ptr = 0; + return String; +} +#endif +STATIC +BOOLEAN +EndOfFile ( + SOURCE_FILE *SourceFile + ) +{ + // + // The file buffer pointer will typically get updated before the End-of-file flag in the + // source file structure, so check it first. + // + if (SourceFile->FileBufferPtr >= SourceFile->FileBuffer + SourceFile->FileSize / sizeof (CHAR8 )) { + SourceFile->EndOfFile = TRUE; + return TRUE; + } + + if (SourceFile->EndOfFile) { + return TRUE; + } + + return FALSE; +} + +#if 0 +STATIC +VOID +ProcessTokenInclude ( + SOURCE_FILE *SourceFile + ) +{ + CHAR8 IncludeFileName[MAX_PATH]; + CHAR8 *To; + UINTN Len; + BOOLEAN ReportedError; + SOURCE_FILE IncludedSourceFile; + + ReportedError = FALSE; + if (SkipWhiteSpace (SourceFile) == 0) { + Warning (SourceFile->FileName, SourceFile->LineNum, 0, "expected whitespace following #include keyword", NULL); + } + // + // Should be quoted file name + // + if (SourceFile->FileBufferPtr[0] != T_CHAR_DOUBLE_QUOTE) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "expected quoted include file name", NULL); + goto FailDone; + } + + SourceFile->FileBufferPtr++; + // + // Copy the filename as ascii to our local string + // + To = IncludeFileName; + Len = 0; + while (!EndOfFile (SourceFile)) { + if ((SourceFile->FileBufferPtr[0] == T_CHAR_CR) || (SourceFile->FileBufferPtr[0] == T_CHAR_LF)) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-line found in quoted include file name", NULL); + goto FailDone; + } + + if (SourceFile->FileBufferPtr[0] == T_CHAR_DOUBLE_QUOTE) { + SourceFile->FileBufferPtr++; + break; + } + // + // If too long, then report the error once and process until the closing quote + // + Len++; + if (!ReportedError && (Len >= sizeof (IncludeFileName))) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "length of include file name exceeds limit", NULL); + ReportedError = TRUE; + } + + if (!ReportedError) { + *To = (CHAR8 ) SourceFile->FileBufferPtr[0]; + To++; + } + + SourceFile->FileBufferPtr++; + } + + if (!ReportedError) { + *To = 0; + memset ((CHAR8 *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE)); + strcpy (IncludedSourceFile.FileName, IncludeFileName); + ProcessIncludeFile (&IncludedSourceFile, SourceFile); + } + + return ; +FailDone: + // + // Error recovery -- skip to next # + // + SourceFile->SkipToHash = TRUE; +} +#endif +STATIC +BOOLEAN +IsWhiteSpace ( + SOURCE_FILE *SourceFile + ) +{ + switch (*SourceFile->FileBufferPtr) { + case T_CHAR_NULL: + case T_CHAR_CR: + case T_CHAR_SPACE: + case T_CHAR_TAB: + case T_CHAR_LF: + return TRUE; + + default: + return FALSE; + } +} + +UINTN +SkipWhiteSpace ( + SOURCE_FILE *SourceFile + ) +{ + UINTN Count; + + Count = 0; + while (!EndOfFile (SourceFile)) { + Count++; + switch (*SourceFile->FileBufferPtr) { + case T_CHAR_NULL: + case T_CHAR_CR: + case T_CHAR_SPACE: + case T_CHAR_TAB: + SourceFile->FileBufferPtr++; + break; + + case T_CHAR_LF: + SourceFile->FileBufferPtr++; + SourceFile->LineNum++; + break; + + default: + return Count - 1; + } + } + // + // Some tokens require trailing whitespace. If we're at the end of the + // file, then we count that as well. + // + if ((Count == 0) && (EndOfFile (SourceFile))) { + Count++; + } + + return Count; +} + +STATIC +UINTN +t_strcmp ( + CHAR8 *Buffer, + CHAR8 *Str + ) +/*++ + +Routine Description: + Compare two strings for equality. The string pointed to by 'Buffer' may or may not be null-terminated, + so only compare up to the length of Str. + +Arguments: + Buffer - pointer to first (possibly not null-terminated) string + Str - pointer to null-terminated string to compare to Buffer + +Returns: + Number of bytes matched if exact match + 0 if Buffer does not start with Str + +--*/ +{ + UINTN Len; + + Len = 0; + while (*Str && (*Str == *Buffer)) { + Buffer++; + Str++; + Len++; + } + + if (*Str) { + return 0; + } + + return Len; +} + +STATIC +UINTN +t_strlen ( + CHAR8 *Str + ) +{ + UINTN Len; + Len = 0; + while (*Str) { + Len++; + Str++; + } + + return Len; +} + +STATIC +UINTN +t_strncmp ( + CHAR8 *Str1, + CHAR8 *Str2, + INTN Len + ) +{ + while (Len > 0) { + if (*Str1 != *Str2) { + return Len; + } + + Len--; + Str1++; + Str2++; + } + + return 0; +} + +STATIC +CHAR8 * +t_strcpy ( + CHAR8 *Dest, + CHAR8 *Src + ) +{ + CHAR8 *SaveDest; + SaveDest = Dest; + while (*Src) { + *Dest = *Src; + Dest++; + Src++; + } + + *Dest = 0; + return SaveDest; +} + +STATIC +VOID +RewindFile ( + SOURCE_FILE *SourceFile + ) +{ + SourceFile->LineNum = 1; + SourceFile->FileBufferPtr = SourceFile->FileBuffer; + SourceFile->EndOfFile = 0; +} + +STATIC +UINT32 +GetHexChars ( + CHAR8 *Buffer, + UINT32 BufferLen + ) +{ + UINT32 Len; + Len = 0; + while (!EndOfFile (&mGlobals.SourceFile) && (Len < BufferLen)) { + if (isxdigit ((int)mGlobals.SourceFile.FileBufferPtr[0])) { + Buffer[Len] = mGlobals.SourceFile.FileBufferPtr[0]; + Len++; + mGlobals.SourceFile.FileBufferPtr++; + } else { + break; + } + } + // + // Null terminate if we can + // + if ((Len > 0) && (Len < BufferLen)) { + Buffer[Len] = 0; + } + + return Len; +} + +BOOLEAN +SFPGetGuid ( + INTN GuidStyle, + EFI_GUID *Value + ) +/*++ + +Routine Description: + Parse a GUID from the input stream. Stop when you discover white space. + +Arguments: + GuidStyle - Style of the following GUID token + Value - pointer to EFI_GUID struct for output + +Returns: + TRUE - GUID string parsed successfully + FALSE - otherwise + + GUID styles + Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD + +--*/ +{ + INT32 Value32; + UINT32 Index; + FILE_POSITION FPos; + CHAR8 TempString[20]; + CHAR8 TempString2[3]; + CHAR8 *From; + CHAR8 *To; + UINT32 Len; + BOOLEAN Status; + + Status = FALSE; + // + // Skip white space, then start parsing + // + SkipWhiteSpace (&mGlobals.SourceFile); + GetFilePosition (&FPos); + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + + if (GuidStyle == PARSE_GUID_STYLE_5_FIELDS) { + // + // Style[0] 12345678-1234-5678-AAAA-BBBBCCCCDDDD + // + Len = GetHexChars (TempString, sizeof (TempString)); + if ((Len == 0) || (Len > 8)) { + goto Done; + } + + sscanf (TempString, "%x", &Value32); + Value->Data1 = Value32; + // + // Next two UINT16 fields + // + if (mGlobals.SourceFile.FileBufferPtr[0] != '-') { + goto Done; + } + + mGlobals.SourceFile.FileBufferPtr++; + Len = GetHexChars (TempString, sizeof (TempString)); + if ((Len == 0) || (Len > 4)) { + goto Done; + } + + sscanf (TempString, "%x", &Value32); + Value->Data2 = (UINT16) Value32; + + if (mGlobals.SourceFile.FileBufferPtr[0] != '-') { + goto Done; + } + + mGlobals.SourceFile.FileBufferPtr++; + Len = GetHexChars (TempString, sizeof (TempString)); + if ((Len == 0) || (Len > 4)) { + goto Done; + } + + sscanf (TempString, "%x", &Value32); + Value->Data3 = (UINT16) Value32; + // + // Parse the "AAAA" as two bytes + // + if (mGlobals.SourceFile.FileBufferPtr[0] != '-') { + goto Done; + } + + mGlobals.SourceFile.FileBufferPtr++; + Len = GetHexChars (TempString, sizeof (TempString)); + if ((Len == 0) || (Len > 4)) { + goto Done; + } + + sscanf (TempString, "%x", &Value32); + Value->Data4[0] = (UINT8) (Value32 >> 8); + Value->Data4[1] = (UINT8) Value32; + if (mGlobals.SourceFile.FileBufferPtr[0] != '-') { + goto Done; + } + + mGlobals.SourceFile.FileBufferPtr++; + // + // Read the last 6 bytes of the GUID + // + // + Len = GetHexChars (TempString, sizeof (TempString)); + if ((Len == 0) || (Len > 12)) { + goto Done; + } + // + // Insert leading 0's to make life easier + // + if (Len != 12) { + From = TempString + Len - 1; + To = TempString + 11; + TempString[12] = 0; + while (From >= TempString) { + *To = *From; + To--; + From--; + } + + while (To >= TempString) { + *To = '0'; + To--; + } + } + // + // Now parse each byte + // + TempString2[2] = 0; + for (Index = 0; Index < 6; Index++) { + // + // Copy the two characters from the input string to something + // we can parse. + // + TempString2[0] = TempString[Index * 2]; + TempString2[1] = TempString[Index * 2 + 1]; + sscanf (TempString2, "%x", &Value32); + Value->Data4[Index + 2] = (UINT8) Value32; + } + + Status = TRUE; + } else { + // + // Unsupported GUID style + // + return FALSE; + } + +Done: + if (Status == FALSE) { + SetFilePosition (&FPos); + } + + return Status; +} + +STATIC +STATUS +GetFilePosition ( + FILE_POSITION *Fpos + ) +{ + Fpos->FileBufferPtr = mGlobals.SourceFile.FileBufferPtr; + return STATUS_SUCCESS; +} + +STATIC +STATUS +SetFilePosition ( + FILE_POSITION *Fpos + ) +{ + // + // Should check range of pointer + // + mGlobals.SourceFile.FileBufferPtr = Fpos->FileBufferPtr; + return STATUS_SUCCESS; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/SimpleFileParsing.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/SimpleFileParsing.h new file mode 100644 index 00000000..e699f050 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/SimpleFileParsing.h @@ -0,0 +1,104 @@ +/** @file +Function prototypes and defines for the simple file parsing routines. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _SIMPLE_FILE_PARSING_H_ +#define _SIMPLE_FILE_PARSING_H_ + +#include + +STATUS +SFPInit ( + VOID + ) +; + +STATUS +SFPOpenFile ( + CHAR8 *FileName + ) +; + +BOOLEAN +SFPIsKeyword ( + CHAR8 *Str + ) +; + +BOOLEAN +SFPIsToken ( + CHAR8 *Str + ) +; + +BOOLEAN +SFPGetNextToken ( + CHAR8 *Str, + UINTN Len + ) +; + +BOOLEAN +SFPGetGuidToken ( + CHAR8 *Str, + UINT32 Len + ) +; + +#define PARSE_GUID_STYLE_5_FIELDS 0 + +BOOLEAN +SFPGetGuid ( + INTN GuidStyle, + EFI_GUID *Value + ) +; + +BOOLEAN +SFPSkipToToken ( + CHAR8 *Str + ) +; + +BOOLEAN +SFPGetNumber ( + UINTN *Value + ) +; + +BOOLEAN +SFPGetQuotedString ( + CHAR8 *Str, + INTN Length + ) +; + +BOOLEAN +SFPIsEOF ( + VOID + ) +; + +STATUS +SFPCloseFile ( + VOID + ) +; + +UINTN +SFPGetLineNumber ( + VOID + ) +; + +CHAR8 * +SFPGetFileName ( + VOID + ) +; + +#endif // #ifndef _SIMPLE_FILE_PARSING_H_ diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/StringFuncs.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/StringFuncs.c new file mode 100644 index 00000000..2d092869 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/StringFuncs.c @@ -0,0 +1,413 @@ +/** @file +Function prototypes and defines for string routines. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include "StringFuncs.h" + +// +// Functions implementations +// + +CHAR8* +CloneString ( + IN CHAR8 *String + ) +/*++ + +Routine Description: + + Allocates a new string and copies 'String' to clone it + +Arguments: + + String The string to clone + +Returns: + + CHAR8* - NULL if there are not enough resources + +--*/ +{ + CHAR8* NewString; + + NewString = malloc (strlen (String) + 1); + if (NewString != NULL) { + strcpy (NewString, String); + } + + return NewString; +} + + +EFI_STATUS +StripInfDscStringInPlace ( + IN CHAR8 *String + ) +/*++ + +Routine Description: + + Remove all comments, leading and trailing whitespace from the string. + +Arguments: + + String The string to 'strip' + +Returns: + + EFI_STATUS + +--*/ +{ + CHAR8 *Pos; + + if (String == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Remove leading whitespace + // + for (Pos = String; isspace ((int)*Pos); Pos++) { + } + if (Pos != String) { + memmove (String, Pos, strlen (Pos) + 1); + } + + // + // Comment BUGBUGs! + // + // What about strings? Comment characters are okay in strings. + // What about multiline comments? + // + + Pos = (CHAR8 *) strstr (String, "//"); + if (Pos != NULL) { + *Pos = '\0'; + } + + Pos = (CHAR8 *) strchr (String, '#'); + if (Pos != NULL) { + *Pos = '\0'; + } + + // + // Remove trailing whitespace + // + for (Pos = String + strlen (String); + ((Pos - 1) >= String) && (isspace ((int)*(Pos - 1))); + Pos-- + ) { + } + *Pos = '\0'; + + return EFI_SUCCESS; +} + + +STRING_LIST* +SplitStringByWhitespace ( + IN CHAR8 *String + ) +/*++ + +Routine Description: + + Creates and returns a 'split' STRING_LIST by splitting the string + on whitespace boundaries. + +Arguments: + + String The string to 'split' + +Returns: + + EFI_STATUS + +--*/ +{ + CHAR8 *Pos; + CHAR8 *EndOfSubString; + CHAR8 *EndOfString; + STRING_LIST *Output; + UINTN Item; + + String = CloneString (String); + if (String == NULL) { + return NULL; + } + EndOfString = String + strlen (String); + + Output = NewStringList (); + + for (Pos = String, Item = 0; Pos < EndOfString; Item++) { + while (isspace ((int)*Pos)) { + Pos++; + } + + for (EndOfSubString=Pos; + (*EndOfSubString != '\0') && !isspace ((int)*EndOfSubString); + EndOfSubString++ + ) { + } + + if (EndOfSubString == Pos) { + break; + } + + *EndOfSubString = '\0'; + + AppendCopyOfStringToList (&Output, Pos); + + Pos = EndOfSubString + 1; + } + + free (String); + return Output; +} + + +STRING_LIST* +NewStringList ( + ) +/*++ + +Routine Description: + + Creates a new STRING_LIST with 0 strings. + +Returns: + + STRING_LIST* - Null if there is not enough resources to create the object. + +--*/ +{ + STRING_LIST *NewList; + NewList = AllocateStringListStruct (0); + if (NewList != NULL) { + NewList->Count = 0; + } + return NewList; +} + + +EFI_STATUS +AppendCopyOfStringToList ( + IN OUT STRING_LIST **StringList, + IN CHAR8 *String + ) +/*++ + +Routine Description: + + Adds String to StringList. A new copy of String is made before it is + added to StringList. + +Returns: + + EFI_STATUS + +--*/ +{ + STRING_LIST *OldList; + STRING_LIST *NewList; + CHAR8 *NewString; + + OldList = *StringList; + NewList = AllocateStringListStruct (OldList->Count + 1); + if (NewList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + NewString = CloneString (String); + if (NewString == NULL) { + free (NewList); + return EFI_OUT_OF_RESOURCES; + } + + memcpy ( + NewList->Strings, + OldList->Strings, + sizeof (OldList->Strings[0]) * OldList->Count + ); + NewList->Count = OldList->Count + 1; + NewList->Strings[OldList->Count] = NewString; + + *StringList = NewList; + free (OldList); + + return EFI_SUCCESS; +} + + +EFI_STATUS +RemoveLastStringFromList ( + IN STRING_LIST *StringList + ) +/*++ + +Routine Description: + + Removes the last string from StringList and frees the memory associated + with it. + +Arguments: + + StringList The string list to remove the string from + +Returns: + + EFI_STATUS + +--*/ +{ + if (StringList->Count == 0) { + return EFI_INVALID_PARAMETER; + } + + free (StringList->Strings[StringList->Count - 1]); + StringList->Count--; + return EFI_SUCCESS; +} + + +STRING_LIST* +AllocateStringListStruct ( + IN UINTN StringCount + ) +/*++ + +Routine Description: + + Allocates a STRING_LIST structure that can store StringCount strings. + +Arguments: + + StringCount The number of strings that need to be stored + +Returns: + + EFI_STATUS + +--*/ +{ + return malloc (OFFSET_OF(STRING_LIST, Strings[StringCount + 1])); +} + + +VOID +FreeStringList ( + IN STRING_LIST *StringList + ) +/*++ + +Routine Description: + + Frees all memory associated with StringList. + +Arguments: + + StringList The string list to free + +Returns: + + VOID +--*/ +{ + while (StringList->Count > 0) { + RemoveLastStringFromList (StringList); + } + + free (StringList); +} + + +CHAR8* +StringListToString ( + IN STRING_LIST *StringList + ) +/*++ + +Routine Description: + + Generates a string that represents the STRING_LIST + +Arguments: + + StringList The string list to convert to a string + +Returns: + + CHAR8* - The string list represented with a single string. The returned + string must be freed by the caller. + +--*/ +{ + UINTN Count; + UINTN Length; + CHAR8 *NewString; + + Length = 2; + for (Count = 0; Count < StringList->Count; Count++) { + if (Count > 0) { + Length += 2; + } + Length += strlen (StringList->Strings[Count]) + 2; + } + + NewString = malloc (Length + 1); + if (NewString == NULL) { + return NewString; + } + NewString[0] = '\0'; + + strcat (NewString, "["); + for (Count = 0; Count < StringList->Count; Count++) { + if (Count > 0) { + strcat (NewString, ", "); + } + strcat (NewString, "\""); + strcat (NewString, StringList->Strings[Count]); + strcat (NewString, "\""); + } + strcat (NewString, "]"); + + return NewString; +} + + +VOID +PrintStringList ( + IN STRING_LIST *StringList + ) +/*++ + +Routine Description: + + Prints out the string list + +Arguments: + + StringList The string list to print + +Returns: + + EFI_STATUS + +--*/ +{ + CHAR8* String; + String = StringListToString (StringList); + if (String != NULL) { + printf ("%s", String); + free (String); + } +} + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/StringFuncs.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/StringFuncs.h new file mode 100644 index 00000000..937abcd9 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/StringFuncs.h @@ -0,0 +1,244 @@ +/** @file +String routines implementation + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_STRING_FUNCS_H +#define _EFI_STRING_FUNCS_H + +#include +#include +#include + +// +// Common data structures +// +typedef struct { + UINTN Count; + // + // Actually this array can be 0 or more items (based on Count) + // + CHAR8* Strings[1]; +} STRING_LIST; + + +// +// Functions declarations +// + +CHAR8* +CloneString ( + IN CHAR8 *String + ) +; +/** + +Routine Description: + + Allocates a new string and copies 'String' to clone it + +Arguments: + + String The string to clone + +Returns: + + CHAR8* - NULL if there are not enough resources + +**/ + + +EFI_STATUS +StripInfDscStringInPlace ( + IN CHAR8 *String + ) +; +/** + +Routine Description: + + Remove all comments, leading and trailing whitespace from the string. + +Arguments: + + String The string to 'strip' + +Returns: + + EFI_STATUS + +**/ + + +STRING_LIST* +SplitStringByWhitespace ( + IN CHAR8 *String + ) +; +/** + +Routine Description: + + Creates and returns a 'split' STRING_LIST by splitting the string + on whitespace boundaries. + +Arguments: + + String The string to 'split' + +Returns: + + EFI_STATUS + +**/ + + +STRING_LIST* +NewStringList ( + ) +; +/** + +Routine Description: + + Creates a new STRING_LIST with 0 strings. + +Returns: + + STRING_LIST* - Null if there is not enough resources to create the object. + +**/ + + +EFI_STATUS +AppendCopyOfStringToList ( + IN OUT STRING_LIST **StringList, + IN CHAR8 *String + ) +; +/** + +Routine Description: + + Adds String to StringList. A new copy of String is made before it is + added to StringList. + +Returns: + + EFI_STATUS + +**/ + + +EFI_STATUS +RemoveLastStringFromList ( + IN STRING_LIST *StringList + ) +; +/** + +Routine Description: + + Removes the last string from StringList and frees the memory associated + with it. + +Arguments: + + StringList The string list to remove the string from + +Returns: + + EFI_STATUS + +**/ + + +STRING_LIST* +AllocateStringListStruct ( + IN UINTN StringCount + ) +; +/** + +Routine Description: + + Allocates a STRING_LIST structure that can store StringCount strings. + +Arguments: + + StringCount The number of strings that need to be stored + +Returns: + + EFI_STATUS + +**/ + + +VOID +FreeStringList ( + IN STRING_LIST *StringList + ) +; +/** + +Routine Description: + + Frees all memory associated with StringList. + +Arguments: + + StringList The string list to free + +Returns: + + EFI_STATUS + +**/ + + +CHAR8* +StringListToString ( + IN STRING_LIST *StringList + ) +; +/** + +Routine Description: + + Generates a string that represents the STRING_LIST + +Arguments: + + StringList The string list to convert to a string + +Returns: + + CHAR8* - The string list represented with a single string. The returned + string must be freed by the caller. + +**/ + + +VOID +PrintStringList ( + IN STRING_LIST *StringList + ) +; +/** + +Routine Description: + + Prints out the string list + +Arguments: + + StringList The string list to print + +**/ + + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/TianoCompress.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/TianoCompress.c new file mode 100644 index 00000000..b5aea760 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/TianoCompress.c @@ -0,0 +1,1746 @@ +/** @file +Compression routine. The compression algorithm is a mixture of LZ77 and Huffman +coding. LZ77 transforms the source data into a sequence of Original Characters +and Pointers to repeated strings. This sequence is further divided into Blocks +and Huffman codings are applied to each Block. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Compress.h" + +// +// Macro Definitions +// +#undef UINT8_MAX +typedef INT32 NODE; +#define UINT8_MAX 0xff +#define UINT8_BIT 8 +#define THRESHOLD 3 +#define INIT_CRC 0 +#define WNDBIT 19 +#define WNDSIZ (1U << WNDBIT) +#define MAXMATCH 256 +#define BLKSIZ (1U << 14) // 16 * 1024U +#define PERC_FLAG 0x80000000U +#define CODE_BIT 16 +#define NIL 0 +#define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX) +#define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2) +#define CRCPOLY 0xA001 +#define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT) + +// +// C: the Char&Len Set; P: the Position Set; T: the exTra Set +// +#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD) +#define CBIT 9 +#define NP (WNDBIT + 1) +#define PBIT 5 +#define NT (CODE_BIT + 3) +#define TBIT 5 +#if NT > NP +#define NPT NT +#else +#define NPT NP +#endif +// +// Function Prototypes +// + +STATIC +VOID +PutDword( + IN UINT32 Data + ); + +STATIC +EFI_STATUS +AllocateMemory ( + VOID + ); + +STATIC +VOID +FreeMemory ( + VOID + ); + +STATIC +VOID +InitSlide ( + VOID + ); + +STATIC +NODE +Child ( + IN NODE NodeQ, + IN UINT8 CharC + ); + +STATIC +VOID +MakeChild ( + IN NODE NodeQ, + IN UINT8 CharC, + IN NODE NodeR + ); + +STATIC +VOID +Split ( + IN NODE Old + ); + +STATIC +VOID +InsertNode ( + VOID + ); + +STATIC +VOID +DeleteNode ( + VOID + ); + +STATIC +VOID +GetNextMatch ( + VOID + ); + +STATIC +EFI_STATUS +Encode ( + VOID + ); + +STATIC +VOID +CountTFreq ( + VOID + ); + +STATIC +VOID +WritePTLen ( + IN INT32 Number, + IN INT32 nbit, + IN INT32 Special + ); + +STATIC +VOID +WriteCLen ( + VOID + ); + +STATIC +VOID +EncodeC ( + IN INT32 Value + ); + +STATIC +VOID +EncodeP ( + IN UINT32 Value + ); + +STATIC +VOID +SendBlock ( + VOID + ); + +STATIC +VOID +Output ( + IN UINT32 c, + IN UINT32 p + ); + +STATIC +VOID +HufEncodeStart ( + VOID + ); + +STATIC +VOID +HufEncodeEnd ( + VOID + ); + +STATIC +VOID +MakeCrcTable ( + VOID + ); + +STATIC +VOID +PutBits ( + IN INT32 Number, + IN UINT32 Value + ); + +STATIC +INT32 +FreadCrc ( + OUT UINT8 *Pointer, + IN INT32 Number + ); + +STATIC +VOID +InitPutBits ( + VOID + ); + +STATIC +VOID +CountLen ( + IN INT32 Index + ); + +STATIC +VOID +MakeLen ( + IN INT32 Root + ); + +STATIC +VOID +DownHeap ( + IN INT32 Index + ); + +STATIC +VOID +MakeCode ( + IN INT32 Number, + IN UINT8 Len[ ], + OUT UINT16 Code[] + ); + +STATIC +INT32 +MakeTree ( + IN INT32 NParm, + IN UINT16 FreqParm[], + OUT UINT8 LenParm[ ], + OUT UINT16 CodeParm[] + ); + +// +// Global Variables +// +STATIC UINT8 *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit; + +STATIC UINT8 *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen; +STATIC INT16 mHeap[NC + 1]; +STATIC INT32 mRemainder, mMatchLen, mBitCount, mHeapSize, mN; +STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc; +STATIC UINT32 mCompSize, mOrigSize; + +STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], mCrcTable[UINT8_MAX + 1], + mCFreq[2 * NC - 1], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1]; + +STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL; + +// +// functions +// +EFI_STATUS +TianoCompress ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ) +/*++ + +Routine Description: + + The internal implementation of [Efi/Tiano]Compress(). + +Arguments: + + SrcBuffer - The buffer storing the source data + SrcSize - The size of source data + DstBuffer - The buffer to store the compressed data + DstSize - On input, the size of DstBuffer; On output, + the size of the actual compressed data. + Version - The version of de/compression algorithm. + Version 1 for UEFI 2.0 de/compression algorithm. + Version 2 for Tiano de/compression algorithm. + +Returns: + + EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case, + DstSize contains the size needed. + EFI_SUCCESS - Compression is successful. + EFI_OUT_OF_RESOURCES - No resource to complete function. + EFI_INVALID_PARAMETER - Parameter supplied is wrong. + +--*/ +{ + EFI_STATUS Status; + + // + // Initializations + // + mBufSiz = 0; + mBuf = NULL; + mText = NULL; + mLevel = NULL; + mChildCount = NULL; + mPosition = NULL; + mParent = NULL; + mPrev = NULL; + mNext = NULL; + + mSrc = SrcBuffer; + mSrcUpperLimit = mSrc + SrcSize; + mDst = DstBuffer; + mDstUpperLimit = mDst +*DstSize; + + PutDword (0L); + PutDword (0L); + + MakeCrcTable (); + + mOrigSize = mCompSize = 0; + mCrc = INIT_CRC; + + // + // Compress it + // + Status = Encode (); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + // + // Null terminate the compressed data + // + if (mDst < mDstUpperLimit) { + *mDst++ = 0; + } + // + // Fill in compressed size and original size + // + mDst = DstBuffer; + PutDword (mCompSize + 1); + PutDword (mOrigSize); + + // + // Return + // + if (mCompSize + 1 + 8 > *DstSize) { + *DstSize = mCompSize + 1 + 8; + return EFI_BUFFER_TOO_SMALL; + } else { + *DstSize = mCompSize + 1 + 8; + return EFI_SUCCESS; + } + +} + +STATIC +VOID +PutDword ( + IN UINT32 Data + ) +/*++ + +Routine Description: + + Put a dword to output stream + +Arguments: + + Data - the dword to put + +Returns: (VOID) + +--*/ +{ + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff); + } + + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff); + } + + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff); + } + + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff); + } +} + +STATIC +EFI_STATUS +AllocateMemory ( + VOID + ) +/*++ + +Routine Description: + + Allocate memory spaces for data structures used in compression process + +Arguments: + VOID + +Returns: + + EFI_SUCCESS - Memory is allocated successfully + EFI_OUT_OF_RESOURCES - Allocation fails + +--*/ +{ + UINT32 Index; + + mText = malloc (WNDSIZ * 2 + MAXMATCH); + if (mText == NULL) { + return EFI_OUT_OF_RESOURCES; + } + for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) { + mText[Index] = 0; + } + + mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel)); + mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount)); + mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition)); + mParent = malloc (WNDSIZ * 2 * sizeof (*mParent)); + mPrev = malloc (WNDSIZ * 2 * sizeof (*mPrev)); + mNext = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext)); + if (mLevel == NULL || mChildCount == NULL || mPosition == NULL || + mParent == NULL || mPrev == NULL || mNext == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + mBufSiz = BLKSIZ; + mBuf = malloc (mBufSiz); + while (mBuf == NULL) { + mBufSiz = (mBufSiz / 10U) * 9U; + if (mBufSiz < 4 * 1024U) { + return EFI_OUT_OF_RESOURCES; + } + + mBuf = malloc (mBufSiz); + } + + mBuf[0] = 0; + + return EFI_SUCCESS; +} + +VOID +FreeMemory ( + VOID + ) +/*++ + +Routine Description: + + Called when compression is completed to free memory previously allocated. + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + if (mText != NULL) { + free (mText); + } + + if (mLevel != NULL) { + free (mLevel); + } + + if (mChildCount != NULL) { + free (mChildCount); + } + + if (mPosition != NULL) { + free (mPosition); + } + + if (mParent != NULL) { + free (mParent); + } + + if (mPrev != NULL) { + free (mPrev); + } + + if (mNext != NULL) { + free (mNext); + } + + if (mBuf != NULL) { + free (mBuf); + } + + return ; +} + +STATIC +VOID +InitSlide ( + VOID + ) +/*++ + +Routine Description: + + Initialize String Info Log data structures + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + NODE Index; + + for (Index = WNDSIZ; Index <= WNDSIZ + UINT8_MAX; Index++) { + mLevel[Index] = 1; + mPosition[Index] = NIL; /* sentinel */ + } + + for (Index = WNDSIZ; Index < WNDSIZ * 2; Index++) { + mParent[Index] = NIL; + } + + mAvail = 1; + for (Index = 1; Index < WNDSIZ - 1; Index++) { + mNext[Index] = (NODE) (Index + 1); + } + + mNext[WNDSIZ - 1] = NIL; + for (Index = WNDSIZ * 2; Index <= MAX_HASH_VAL; Index++) { + mNext[Index] = NIL; + } +} + +STATIC +NODE +Child ( + IN NODE NodeQ, + IN UINT8 CharC + ) +/*++ + +Routine Description: + + Find child node given the parent node and the edge character + +Arguments: + + NodeQ - the parent node + CharC - the edge character + +Returns: + + The child node (NIL if not found) + +--*/ +{ + NODE NodeR; + + NodeR = mNext[HASH (NodeQ, CharC)]; + // + // sentinel + // + mParent[NIL] = NodeQ; + while (mParent[NodeR] != NodeQ) { + NodeR = mNext[NodeR]; + } + + return NodeR; +} + +STATIC +VOID +MakeChild ( + IN NODE Parent, + IN UINT8 CharC, + IN NODE Child + ) +/*++ + +Routine Description: + + Create a new child for a given parent node. + +Arguments: + + Parent - the parent node + CharC - the edge character + Child - the child node + +Returns: (VOID) + +--*/ +{ + NODE Node1; + NODE Node2; + + Node1 = (NODE) HASH (Parent, CharC); + Node2 = mNext[Node1]; + mNext[Node1] = Child; + mNext[Child] = Node2; + mPrev[Node2] = Child; + mPrev[Child] = Node1; + mParent[Child] = Parent; + mChildCount[Parent]++; +} + +STATIC +VOID +Split ( + NODE Old + ) +/*++ + +Routine Description: + + Split a node. + +Arguments: + + Old - the node to split + +Returns: (VOID) + +--*/ +{ + NODE New; + NODE TempNode; + + New = mAvail; + mAvail = mNext[New]; + mChildCount[New] = 0; + TempNode = mPrev[Old]; + mPrev[New] = TempNode; + mNext[TempNode] = New; + TempNode = mNext[Old]; + mNext[New] = TempNode; + mPrev[TempNode] = New; + mParent[New] = mParent[Old]; + mLevel[New] = (UINT8) mMatchLen; + mPosition[New] = mPos; + MakeChild (New, mText[mMatchPos + mMatchLen], Old); + MakeChild (New, mText[mPos + mMatchLen], mPos); +} + +STATIC +VOID +InsertNode ( + VOID + ) +/*++ + +Routine Description: + + Insert string info for current position into the String Info Log + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + NODE NodeQ; + NODE NodeR; + NODE Index2; + NODE NodeT; + UINT8 CharC; + UINT8 *t1; + UINT8 *t2; + + if (mMatchLen >= 4) { + // + // We have just got a long match, the target tree + // can be located by MatchPos + 1. Traverse the tree + // from bottom up to get to a proper starting point. + // The usage of PERC_FLAG ensures proper node deletion + // in DeleteNode() later. + // + mMatchLen--; + NodeR = (NODE) ((mMatchPos + 1) | WNDSIZ); + NodeQ = mParent[NodeR]; + while (NodeQ == NIL) { + NodeR = mNext[NodeR]; + NodeQ = mParent[NodeR]; + } + + while (mLevel[NodeQ] >= mMatchLen) { + NodeR = NodeQ; + NodeQ = mParent[NodeQ]; + } + + NodeT = NodeQ; + while (mPosition[NodeT] < 0) { + mPosition[NodeT] = mPos; + NodeT = mParent[NodeT]; + } + + if (NodeT < WNDSIZ) { + mPosition[NodeT] = (NODE) (mPos | (UINT32) PERC_FLAG); + } + } else { + // + // Locate the target tree + // + NodeQ = (NODE) (mText[mPos] + WNDSIZ); + CharC = mText[mPos + 1]; + NodeR = Child (NodeQ, CharC); + if (NodeR == NIL) { + MakeChild (NodeQ, CharC, mPos); + mMatchLen = 1; + return ; + } + + mMatchLen = 2; + } + // + // Traverse down the tree to find a match. + // Update Position value along the route. + // Node split or creation is involved. + // + for (;;) { + if (NodeR >= WNDSIZ) { + Index2 = MAXMATCH; + mMatchPos = NodeR; + } else { + Index2 = mLevel[NodeR]; + mMatchPos = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); + } + + if (mMatchPos >= mPos) { + mMatchPos -= WNDSIZ; + } + + t1 = &mText[mPos + mMatchLen]; + t2 = &mText[mMatchPos + mMatchLen]; + while (mMatchLen < Index2) { + if (*t1 != *t2) { + Split (NodeR); + return ; + } + + mMatchLen++; + t1++; + t2++; + } + + if (mMatchLen >= MAXMATCH) { + break; + } + + mPosition[NodeR] = mPos; + NodeQ = NodeR; + NodeR = Child (NodeQ, *t1); + if (NodeR == NIL) { + MakeChild (NodeQ, *t1, mPos); + return ; + } + + mMatchLen++; + } + + NodeT = mPrev[NodeR]; + mPrev[mPos] = NodeT; + mNext[NodeT] = mPos; + NodeT = mNext[NodeR]; + mNext[mPos] = NodeT; + mPrev[NodeT] = mPos; + mParent[mPos] = NodeQ; + mParent[NodeR] = NIL; + + // + // Special usage of 'next' + // + mNext[NodeR] = mPos; + +} + +STATIC +VOID +DeleteNode ( + VOID + ) +/*++ + +Routine Description: + + Delete outdated string info. (The Usage of PERC_FLAG + ensures a clean deletion) + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + NODE NodeQ; + NODE NodeR; + NODE NodeS; + NODE NodeT; + NODE NodeU; + + if (mParent[mPos] == NIL) { + return ; + } + + NodeR = mPrev[mPos]; + NodeS = mNext[mPos]; + mNext[NodeR] = NodeS; + mPrev[NodeS] = NodeR; + NodeR = mParent[mPos]; + mParent[mPos] = NIL; + if (NodeR >= WNDSIZ) { + return ; + } + + mChildCount[NodeR]--; + if (mChildCount[NodeR] > 1) { + return ; + } + + NodeT = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); + if (NodeT >= mPos) { + NodeT -= WNDSIZ; + } + + NodeS = NodeT; + NodeQ = mParent[NodeR]; + NodeU = mPosition[NodeQ]; + while (NodeU & (UINT32) PERC_FLAG) { + NodeU &= (UINT32)~PERC_FLAG; + if (NodeU >= mPos) { + NodeU -= WNDSIZ; + } + + if (NodeU > NodeS) { + NodeS = NodeU; + } + + mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ); + NodeQ = mParent[NodeQ]; + NodeU = mPosition[NodeQ]; + } + + if (NodeQ < WNDSIZ) { + if (NodeU >= mPos) { + NodeU -= WNDSIZ; + } + + if (NodeU > NodeS) { + NodeS = NodeU; + } + + mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ | (UINT32) PERC_FLAG); + } + + NodeS = Child (NodeR, mText[NodeT + mLevel[NodeR]]); + NodeT = mPrev[NodeS]; + NodeU = mNext[NodeS]; + mNext[NodeT] = NodeU; + mPrev[NodeU] = NodeT; + NodeT = mPrev[NodeR]; + mNext[NodeT] = NodeS; + mPrev[NodeS] = NodeT; + NodeT = mNext[NodeR]; + mPrev[NodeT] = NodeS; + mNext[NodeS] = NodeT; + mParent[NodeS] = mParent[NodeR]; + mParent[NodeR] = NIL; + mNext[NodeR] = mAvail; + mAvail = NodeR; +} + +STATIC +VOID +GetNextMatch ( + VOID + ) +/*++ + +Routine Description: + + Advance the current position (read in new data if needed). + Delete outdated string info. Find a match string for current position. + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + INT32 Number; + + mRemainder--; + mPos++; + if (mPos == WNDSIZ * 2) { + memmove (&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); + Number = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ); + mRemainder += Number; + mPos = WNDSIZ; + } + + DeleteNode (); + InsertNode (); +} + +STATIC +EFI_STATUS +Encode ( + VOID + ) +/*++ + +Routine Description: + + The main controlling routine for compression process. + +Arguments: (VOID) + +Returns: + + EFI_SUCCESS - The compression is successful + EFI_OUT_0F_RESOURCES - Not enough memory for compression process + +--*/ +{ + EFI_STATUS Status; + INT32 LastMatchLen; + NODE LastMatchPos; + + Status = AllocateMemory (); + if (EFI_ERROR (Status)) { + FreeMemory (); + return Status; + } + + InitSlide (); + + HufEncodeStart (); + + mRemainder = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH); + + mMatchLen = 0; + mPos = WNDSIZ; + InsertNode (); + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + + while (mRemainder > 0) { + LastMatchLen = mMatchLen; + LastMatchPos = mMatchPos; + GetNextMatch (); + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + + if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { + // + // Not enough benefits are gained by outputting a pointer, + // so just output the original character + // + Output (mText[mPos - 1], 0); + + } else { + + if (LastMatchLen == THRESHOLD) { + if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) { + Output (mText[mPos - 1], 0); + continue; + } + } + // + // Outputting a pointer is beneficial enough, do it. + // + Output ( + LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), + (mPos - LastMatchPos - 2) & (WNDSIZ - 1) + ); + LastMatchLen--; + while (LastMatchLen > 0) { + GetNextMatch (); + LastMatchLen--; + } + + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + } + } + + HufEncodeEnd (); + FreeMemory (); + return EFI_SUCCESS; +} + +STATIC +VOID +CountTFreq ( + VOID + ) +/*++ + +Routine Description: + + Count the frequencies for the Extra Set + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + INT32 Index; + INT32 Index3; + INT32 Number; + INT32 Count; + + for (Index = 0; Index < NT; Index++) { + mTFreq[Index] = 0; + } + + Number = NC; + while (Number > 0 && mCLen[Number - 1] == 0) { + Number--; + } + + Index = 0; + while (Index < Number) { + Index3 = mCLen[Index++]; + if (Index3 == 0) { + Count = 1; + while (Index < Number && mCLen[Index] == 0) { + Index++; + Count++; + } + + if (Count <= 2) { + mTFreq[0] = (UINT16) (mTFreq[0] + Count); + } else if (Count <= 18) { + mTFreq[1]++; + } else if (Count == 19) { + mTFreq[0]++; + mTFreq[1]++; + } else { + mTFreq[2]++; + } + } else { + mTFreq[Index3 + 2]++; + } + } +} + +STATIC +VOID +WritePTLen ( + IN INT32 Number, + IN INT32 nbit, + IN INT32 Special + ) +/*++ + +Routine Description: + + Outputs the code length array for the Extra Set or the Position Set. + +Arguments: + + Number - the number of symbols + nbit - the number of bits needed to represent 'n' + Special - the special symbol that needs to be take care of + +Returns: (VOID) + +--*/ +{ + INT32 Index; + INT32 Index3; + + while (Number > 0 && mPTLen[Number - 1] == 0) { + Number--; + } + + PutBits (nbit, Number); + Index = 0; + while (Index < Number) { + Index3 = mPTLen[Index++]; + if (Index3 <= 6) { + PutBits (3, Index3); + } else { + PutBits (Index3 - 3, (1U << (Index3 - 3)) - 2); + } + + if (Index == Special) { + while (Index < 6 && mPTLen[Index] == 0) { + Index++; + } + + PutBits (2, (Index - 3) & 3); + } + } +} + +STATIC +VOID +WriteCLen ( + VOID + ) +/*++ + +Routine Description: + + Outputs the code length array for Char&Length Set + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + INT32 Index; + INT32 Index3; + INT32 Number; + INT32 Count; + + Number = NC; + while (Number > 0 && mCLen[Number - 1] == 0) { + Number--; + } + + PutBits (CBIT, Number); + Index = 0; + while (Index < Number) { + Index3 = mCLen[Index++]; + if (Index3 == 0) { + Count = 1; + while (Index < Number && mCLen[Index] == 0) { + Index++; + Count++; + } + + if (Count <= 2) { + for (Index3 = 0; Index3 < Count; Index3++) { + PutBits (mPTLen[0], mPTCode[0]); + } + } else if (Count <= 18) { + PutBits (mPTLen[1], mPTCode[1]); + PutBits (4, Count - 3); + } else if (Count == 19) { + PutBits (mPTLen[0], mPTCode[0]); + PutBits (mPTLen[1], mPTCode[1]); + PutBits (4, 15); + } else { + PutBits (mPTLen[2], mPTCode[2]); + PutBits (CBIT, Count - 20); + } + } else { + PutBits (mPTLen[Index3 + 2], mPTCode[Index3 + 2]); + } + } +} + +STATIC +VOID +EncodeC ( + IN INT32 Value + ) +{ + PutBits (mCLen[Value], mCCode[Value]); +} + +STATIC +VOID +EncodeP ( + IN UINT32 Value + ) +{ + UINT32 Index; + UINT32 NodeQ; + + Index = 0; + NodeQ = Value; + while (NodeQ) { + NodeQ >>= 1; + Index++; + } + + PutBits (mPTLen[Index], mPTCode[Index]); + if (Index > 1) { + PutBits (Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1))); + } +} + +STATIC +VOID +SendBlock ( + VOID + ) +/*++ + +Routine Description: + + Huffman code the block and output it. + +Arguments: + (VOID) + +Returns: + (VOID) + +--*/ +{ + UINT32 Index; + UINT32 Index2; + UINT32 Index3; + UINT32 Flags; + UINT32 Root; + UINT32 Pos; + UINT32 Size; + Flags = 0; + + Root = MakeTree (NC, mCFreq, mCLen, mCCode); + Size = mCFreq[Root]; + PutBits (16, Size); + if (Root >= NC) { + CountTFreq (); + Root = MakeTree (NT, mTFreq, mPTLen, mPTCode); + if (Root >= NT) { + WritePTLen (NT, TBIT, 3); + } else { + PutBits (TBIT, 0); + PutBits (TBIT, Root); + } + + WriteCLen (); + } else { + PutBits (TBIT, 0); + PutBits (TBIT, 0); + PutBits (CBIT, 0); + PutBits (CBIT, Root); + } + + Root = MakeTree (NP, mPFreq, mPTLen, mPTCode); + if (Root >= NP) { + WritePTLen (NP, PBIT, -1); + } else { + PutBits (PBIT, 0); + PutBits (PBIT, Root); + } + + Pos = 0; + for (Index = 0; Index < Size; Index++) { + if (Index % UINT8_BIT == 0) { + Flags = mBuf[Pos++]; + } else { + Flags <<= 1; + } + + if (Flags & (1U << (UINT8_BIT - 1))) { + EncodeC (mBuf[Pos++] + (1U << UINT8_BIT)); + Index3 = mBuf[Pos++]; + for (Index2 = 0; Index2 < 3; Index2++) { + Index3 <<= UINT8_BIT; + Index3 += mBuf[Pos++]; + } + + EncodeP (Index3); + } else { + EncodeC (mBuf[Pos++]); + } + } + + for (Index = 0; Index < NC; Index++) { + mCFreq[Index] = 0; + } + + for (Index = 0; Index < NP; Index++) { + mPFreq[Index] = 0; + } +} + +STATIC +VOID +Output ( + IN UINT32 CharC, + IN UINT32 Pos + ) +/*++ + +Routine Description: + + Outputs an Original Character or a Pointer + +Arguments: + + CharC - The original character or the 'String Length' element of a Pointer + Pos - The 'Position' field of a Pointer + +Returns: (VOID) + +--*/ +{ + STATIC UINT32 CPos; + + if ((mOutputMask >>= 1) == 0) { + mOutputMask = 1U << (UINT8_BIT - 1); + // + // Check the buffer overflow per outputing UINT8_BIT symbols + // which is an Original Character or a Pointer. The biggest + // symbol is a Pointer which occupies 5 bytes. + // + if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) { + SendBlock (); + mOutputPos = 0; + } + + CPos = mOutputPos++; + mBuf[CPos] = 0; + } + + mBuf[mOutputPos++] = (UINT8) CharC; + mCFreq[CharC]++; + if (CharC >= (1U << UINT8_BIT)) { + mBuf[CPos] |= mOutputMask; + mBuf[mOutputPos++] = (UINT8) (Pos >> 24); + mBuf[mOutputPos++] = (UINT8) (Pos >> 16); + mBuf[mOutputPos++] = (UINT8) (Pos >> (UINT8_BIT)); + mBuf[mOutputPos++] = (UINT8) Pos; + CharC = 0; + while (Pos) { + Pos >>= 1; + CharC++; + } + + mPFreq[CharC]++; + } +} + +STATIC +VOID +HufEncodeStart ( + VOID + ) +{ + INT32 Index; + + for (Index = 0; Index < NC; Index++) { + mCFreq[Index] = 0; + } + + for (Index = 0; Index < NP; Index++) { + mPFreq[Index] = 0; + } + + mOutputPos = mOutputMask = 0; + InitPutBits (); + return ; +} + +STATIC +VOID +HufEncodeEnd ( + VOID + ) +{ + SendBlock (); + + // + // Flush remaining bits + // + PutBits (UINT8_BIT - 1, 0); + + return ; +} + +STATIC +VOID +MakeCrcTable ( + VOID + ) +{ + UINT32 Index; + UINT32 Index2; + UINT32 Temp; + + for (Index = 0; Index <= UINT8_MAX; Index++) { + Temp = Index; + for (Index2 = 0; Index2 < UINT8_BIT; Index2++) { + if (Temp & 1) { + Temp = (Temp >> 1) ^ CRCPOLY; + } else { + Temp >>= 1; + } + } + + mCrcTable[Index] = (UINT16) Temp; + } +} + +STATIC +VOID +PutBits ( + IN INT32 Number, + IN UINT32 Value + ) +/*++ + +Routine Description: + + Outputs rightmost n bits of x + +Arguments: + + Number - the rightmost n bits of the data is used + x - the data + +Returns: (VOID) + +--*/ +{ + UINT8 Temp; + + while (Number >= mBitCount) { + // + // Number -= mBitCount should never equal to 32 + // + Temp = (UINT8) (mSubBitBuf | (Value >> (Number -= mBitCount))); + if (mDst < mDstUpperLimit) { + *mDst++ = Temp; + } + + mCompSize++; + mSubBitBuf = 0; + mBitCount = UINT8_BIT; + } + + mSubBitBuf |= Value << (mBitCount -= Number); +} + +STATIC +INT32 +FreadCrc ( + OUT UINT8 *Pointer, + IN INT32 Number + ) +/*++ + +Routine Description: + + Read in source data + +Arguments: + + Pointer - the buffer to hold the data + Number - number of bytes to read + +Returns: + + number of bytes actually read + +--*/ +{ + INT32 Index; + + for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) { + *Pointer++ = *mSrc++; + } + + Number = Index; + + Pointer -= Number; + mOrigSize += Number; + Index--; + while (Index >= 0) { + UPDATE_CRC (*Pointer++); + Index--; + } + + return Number; +} + +STATIC +VOID +InitPutBits ( + VOID + ) +{ + mBitCount = UINT8_BIT; + mSubBitBuf = 0; +} + +STATIC +VOID +CountLen ( + IN INT32 Index + ) +/*++ + +Routine Description: + + Count the number of each code length for a Huffman tree. + +Arguments: + + Index - the top node + +Returns: (VOID) + +--*/ +{ + STATIC INT32 Depth = 0; + + if (Index < mN) { + mLenCnt[(Depth < 16) ? Depth : 16]++; + } else { + Depth++; + CountLen (mLeft[Index]); + CountLen (mRight[Index]); + Depth--; + } +} + +STATIC +VOID +MakeLen ( + IN INT32 Root + ) +/*++ + +Routine Description: + + Create code length array for a Huffman tree + +Arguments: + + Root - the root of the tree + +Returns: + + VOID + +--*/ +{ + INT32 Index; + INT32 Index3; + UINT32 Cum; + + for (Index = 0; Index <= 16; Index++) { + mLenCnt[Index] = 0; + } + + CountLen (Root); + + // + // Adjust the length count array so that + // no code will be generated longer than its designated length + // + Cum = 0; + for (Index = 16; Index > 0; Index--) { + Cum += mLenCnt[Index] << (16 - Index); + } + + while (Cum != (1U << 16)) { + mLenCnt[16]--; + for (Index = 15; Index > 0; Index--) { + if (mLenCnt[Index] != 0) { + mLenCnt[Index]--; + mLenCnt[Index + 1] += 2; + break; + } + } + + Cum--; + } + + for (Index = 16; Index > 0; Index--) { + Index3 = mLenCnt[Index]; + Index3--; + while (Index3 >= 0) { + mLen[*mSortPtr++] = (UINT8) Index; + Index3--; + } + } +} + +STATIC +VOID +DownHeap ( + IN INT32 Index + ) +{ + INT32 Index2; + INT32 Index3; + + // + // priority queue: send Index-th entry down heap + // + Index3 = mHeap[Index]; + Index2 = 2 * Index; + while (Index2 <= mHeapSize) { + if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) { + Index2++; + } + + if (mFreq[Index3] <= mFreq[mHeap[Index2]]) { + break; + } + + mHeap[Index] = mHeap[Index2]; + Index = Index2; + Index2 = 2 * Index; + } + + mHeap[Index] = (INT16) Index3; +} + +STATIC +VOID +MakeCode ( + IN INT32 Number, + IN UINT8 Len[ ], + OUT UINT16 Code[] + ) +/*++ + +Routine Description: + + Assign code to each symbol based on the code length array + +Arguments: + + Number - number of symbols + Len - the code length array + Code - stores codes for each symbol + +Returns: (VOID) + +--*/ +{ + INT32 Index; + UINT16 Start[18]; + + Start[1] = 0; + for (Index = 1; Index <= 16; Index++) { + Start[Index + 1] = (UINT16) ((Start[Index] + mLenCnt[Index]) << 1); + } + + for (Index = 0; Index < Number; Index++) { + Code[Index] = Start[Len[Index]]++; + } +} + +STATIC +INT32 +MakeTree ( + IN INT32 NParm, + IN UINT16 FreqParm[], + OUT UINT8 LenParm[ ], + OUT UINT16 CodeParm[] + ) +/*++ + +Routine Description: + + Generates Huffman codes given a frequency distribution of symbols + +Arguments: + + NParm - number of symbols + FreqParm - frequency of each symbol + LenParm - code length for each symbol + CodeParm - code for each symbol + +Returns: + + Root of the Huffman tree. + +--*/ +{ + INT32 Index; + INT32 Index2; + INT32 Index3; + INT32 Avail; + + // + // make tree, calculate len[], return root + // + mN = NParm; + mFreq = FreqParm; + mLen = LenParm; + Avail = mN; + mHeapSize = 0; + mHeap[1] = 0; + for (Index = 0; Index < mN; Index++) { + mLen[Index] = 0; + if (mFreq[Index]) { + mHeapSize++; + mHeap[mHeapSize] = (INT16) Index; + } + } + + if (mHeapSize < 2) { + CodeParm[mHeap[1]] = 0; + return mHeap[1]; + } + + for (Index = mHeapSize / 2; Index >= 1; Index--) { + // + // make priority queue + // + DownHeap (Index); + } + + mSortPtr = CodeParm; + do { + Index = mHeap[1]; + if (Index < mN) { + *mSortPtr++ = (UINT16) Index; + } + + mHeap[1] = mHeap[mHeapSize--]; + DownHeap (1); + Index2 = mHeap[1]; + if (Index2 < mN) { + *mSortPtr++ = (UINT16) Index2; + } + + Index3 = Avail++; + mFreq[Index3] = (UINT16) (mFreq[Index] + mFreq[Index2]); + mHeap[1] = (INT16) Index3; + DownHeap (1); + mLeft[Index3] = (UINT16) Index; + mRight[Index3] = (UINT16) Index2; + } while (mHeapSize > 1); + + mSortPtr = CodeParm; + MakeLen (Index3); + MakeCode (NParm, LenParm, CodeParm); + + // + // return root + // + return Index3; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/WinNtInclude.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/WinNtInclude.h new file mode 100644 index 00000000..b3c58497 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Common/WinNtInclude.h @@ -0,0 +1,78 @@ +/** @file +Include file for the WinNt Library + +Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __WIN_NT_INCLUDE_H__ +#define __WIN_NT_INCLUDE_H__ + +#define GUID _WINNT_DUP_GUID_____ +#define _LIST_ENTRY _WINNT_DUP_LIST_ENTRY_FORWARD +#define LIST_ENTRY _WINNT_DUP_LIST_ENTRY + +#ifndef VBOX +#if (_MSC_VER < 1800) +#define InterlockedIncrement _WINNT_DUP_InterlockedIncrement +#define InterlockedDecrement _WINNT_DUP_InterlockedDecrement +#define InterlockedCompareExchange64 _WINNT_DUP_InterlockedCompareExchange64 +#endif +#endif + +#undef UNALIGNED +#undef CONST +#undef VOID + +#ifndef __GNUC__ +# ifdef VBOX +# define RUNTIME_FUNCTION _WINNT_DUP_RUNTIME_FUNCTION +# endif +#ifdef VBOX +#include +#else +#include "windows.h" +#endif + +// +// Win32 include files do not compile clean with /W4, so we use the warning +// pragma to suppress the warnings for Win32 only. This way our code can still +// compile at /W4 (highest warning level) with /WX (warnings cause build +// errors). +// +#pragma warning(disable : 4115) +#pragma warning(disable : 4201) +#pragma warning(disable : 4214) +#pragma warning(disable : 4028) +#pragma warning(disable : 4133) + +// +// Set the warnings back on as the EFI code must be /W4. +// +#pragma warning(default : 4115) +#pragma warning(default : 4201) +#pragma warning(default : 4214) + +# ifdef VBOX +# undef RUNTIME_FUNCTION +# endif +#endif + +#undef GUID +#undef _LIST_ENTRY +#undef LIST_ENTRY +#undef InterlockedIncrement +#undef InterlockedDecrement +#undef InterlockedCompareExchange64 +#undef InterlockedCompareExchangePointer + +#define VOID void + +// +// Prevent collisions with Windows API name macros that deal with Unicode/Not issues +// +#undef LoadImage +#undef CreateEvent + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/DevicePath.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/DevicePath.c new file mode 100644 index 00000000..7c45b367 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/DevicePath.c @@ -0,0 +1,194 @@ +/** @file + Definition for Device Path Tool. + +Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UefiDevicePathLib.h" + +// +// Utility Name +// +#define UTILITY_NAME "DevicePath" + +// +// Utility version information +// +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +EFI_GUID gEfiDebugPortProtocolGuid = DEVICE_PATH_MESSAGING_DEBUGPORT; +EFI_GUID gEfiPcAnsiGuid = EFI_PC_ANSI_GUID; +EFI_GUID gEfiVT100Guid = EFI_VT_100_GUID; +EFI_GUID gEfiVT100PlusGuid = EFI_VT_100_PLUS_GUID; +EFI_GUID gEfiVTUTF8Guid = EFI_VT_UTF8_GUID; +EFI_GUID gEfiUartDevicePathGuid = EFI_UART_DEVICE_PATH_GUID; +EFI_GUID gEfiSasDevicePathGuid = EFI_SAS_DEVICE_PATH_GUID; +EFI_GUID gEfiVirtualDiskGuid = EFI_VIRTUAL_DISK_GUID; +EFI_GUID gEfiVirtualCdGuid = EFI_VIRTUAL_CD_GUID; +EFI_GUID gEfiPersistentVirtualDiskGuid = EFI_PERSISTENT_VIRTUAL_DISK_GUID; +EFI_GUID gEfiPersistentVirtualCdGuid = EFI_PERSISTENT_VIRTUAL_CD_GUID; + +STATIC +VOID +Version ( + VOID +) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION); +} + +STATIC +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "\nUsage: %s [options]\n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2017, Intel Corporation. All rights reserved.\n\n"); + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " DevicePathString Device Path string is specified, no space character.\n" + " Example: \"PciRoot(0)/Pci(0,0)\"\n"); + + fprintf (stdout, " --version Show program's version number and exit.\n"); + fprintf (stdout, " -h, --help Show this help message and exit.\n"); +} + + +STATIC +VOID +PrintMem ( + CONST VOID *Buffer, + UINTN Count + ) +{ + CONST UINT8 *Bytes; + UINTN Idx; + + Bytes = Buffer; + for (Idx = 0; Idx < Count; Idx++) { + printf("0x%02x ", Bytes[Idx]); + } +} + +VOID +Ascii2UnicodeString ( + CHAR8 *String, + CHAR16 *UniString + ) +/*++ + +Routine Description: + + Write ascii string as unicode string format to FILE + +Arguments: + + String - Pointer to string that is written to FILE. + UniString - Pointer to unicode string + +Returns: + + NULL + +--*/ +{ + while (*String != '\0') { + *(UniString++) = (CHAR16) *(String++); + } + // + // End the UniString with a NULL. + // + *UniString = '\0'; +} + +int main(int argc, CHAR8 *argv[]) +{ + CHAR8 * Str; + CHAR16* Str16; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + if (argc == 1) { + Error (NULL, 0, 1001, "Missing options", "No input options specified."); + Usage (); + return STATUS_ERROR; + } + if ((stricmp (argv[1], "-h") == 0) || (stricmp (argv[1], "--help") == 0)) { + Version (); + Usage (); + return STATUS_SUCCESS; + } + + if (stricmp (argv[1], "--version") == 0) { + Version (); + return STATUS_SUCCESS; + } + Str = argv[1]; + if (Str == NULL) { + fprintf(stderr, "Invalid option value, Device Path can't be NULL"); + return STATUS_ERROR; + } + Str16 = (CHAR16 *)malloc(1024); + if (Str16 == NULL) { + fprintf(stderr, "Resource, memory cannot be allocated"); + return STATUS_ERROR; + } + Ascii2UnicodeString(Str, Str16); + DevicePath = UefiDevicePathLibConvertTextToDevicePath(Str16); + if (DevicePath == NULL) { + fprintf(stderr, "Convert fail, Cannot convert text to a device path"); + free(Str16); + return STATUS_ERROR; + } + while (!((DevicePath->Type == END_DEVICE_PATH_TYPE) && (DevicePath->SubType == END_ENTIRE_DEVICE_PATH_SUBTYPE)) ) + { + PrintMem (DevicePath, DevicePath->Length[0] | DevicePath->Length[1] << 8); + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)DevicePath + (DevicePath->Length[0] | DevicePath->Length[1] << 8)); + } + PrintMem (DevicePath, DevicePath->Length[0] | DevicePath->Length[1] << 8); + putchar('\n'); + free(Str16); + return STATUS_SUCCESS; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/DevicePathFromText.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/DevicePathFromText.c new file mode 100644 index 00000000..dc49998d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/DevicePathFromText.c @@ -0,0 +1,3524 @@ +/** @file + DevicePathFromText protocol as defined in the UEFI 2.0 specification. + +Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UefiDevicePathLib.h" + +/** + + Duplicates a string. + + @param Src Source string. + + @return The duplicated string. + +**/ +CHAR16 * +UefiDevicePathLibStrDuplicate ( + CONST CHAR16 *Src + ) +{ + return AllocateCopyPool (StrSize (Src), Src); +} + +/** + + Get parameter in a pair of parentheses follow the given node name. + For example, given the "Pci(0,1)" and NodeName "Pci", it returns "0,1". + + @param Str Device Path Text. + @param NodeName Name of the node. + + @return Parameter text for the node. + +**/ +CHAR16 * +GetParamByNodeName ( + CHAR16 *Str, + CHAR16 *NodeName + ) +{ + CHAR16 *ParamStr; + CHAR16 *StrPointer; + UINTN NodeNameLength; + UINTN ParameterLength; + + // + // Check whether the node name matchs + // + NodeNameLength = StrLen (NodeName); + if (StrnCmp (Str, NodeName, NodeNameLength) != 0) { + return NULL; + } + + ParamStr = Str + NodeNameLength; + if (!IS_LEFT_PARENTH (*ParamStr)) { + return NULL; + } + + // + // Skip the found '(' and find first occurrence of ')' + // + ParamStr++; + ParameterLength = 0; + StrPointer = ParamStr; + while (!IS_NULL (*StrPointer)) { + if (IS_RIGHT_PARENTH (*StrPointer)) { + break; + } + StrPointer++; + ParameterLength++; + } + if (IS_NULL (*StrPointer)) { + // + // ')' not found + // + return NULL; + } + + ParamStr = AllocateCopyPool ((ParameterLength + 1) * sizeof (CHAR16), ParamStr); + if (ParamStr == NULL) { + return NULL; + } + // + // Terminate the parameter string + // + ParamStr[ParameterLength] = L'\0'; + + return ParamStr; +} + +/** + Gets the next parameter string from the list. + + @param List A string list separated by the specified separator + + @return A pointer to the current sub-string + +**/ +CHAR16 * +GetNextParamStr ( + CHAR16 **List + ) +{ + // + // The separator is comma + // + return SplitStr (List, L','); +} + +/** + Get one device node from entire device path text. + + @param DevicePath On input, the current Device Path node; on output, the next device path node + @param IsInstanceEnd This node is the end of a device path instance + + @return A device node text or NULL if no more device node available + +**/ +CHAR16 * +GetNextDeviceNodeStr ( + CHAR16 **DevicePath, + BOOLEAN *IsInstanceEnd + ) +{ + CHAR16 *Str; + CHAR16 *ReturnStr; + UINTN ParenthesesStack; + + Str = *DevicePath; + if (IS_NULL (*Str)) { + return NULL; + } + + // + // Skip the leading '/', '(', ')' and ',' + // + while (!IS_NULL (*Str)) { + if (!IS_SLASH (*Str) && + !IS_COMMA (*Str) && + !IS_LEFT_PARENTH (*Str) && + !IS_RIGHT_PARENTH (*Str)) { + break; + } + Str++; + } + + ReturnStr = Str; + + // + // Scan for the separator of this device node, '/' or ',' + // + ParenthesesStack = 0; + while (!IS_NULL (*Str)) { + if ((IS_COMMA (*Str) || IS_SLASH (*Str)) && (ParenthesesStack == 0)) { + break; + } + + if (IS_LEFT_PARENTH (*Str)) { + ParenthesesStack++; + } else if (IS_RIGHT_PARENTH (*Str)) { + ParenthesesStack--; + } + + Str++; + } + + if (ParenthesesStack != 0) { + // + // The '(' doesn't pair with ')', invalid device path text + // + return NULL; + } + + if (IS_COMMA (*Str)) { + *IsInstanceEnd = TRUE; + *Str = L'\0'; + Str++; + } else { + *IsInstanceEnd = FALSE; + if (!IS_NULL (*Str)) { + *Str = L'\0'; + Str++; + } + } + + *DevicePath = Str; + + return ReturnStr; +} + +/** + Converts a generic text device path node to device path structure. + + @param Type The type of the device path node. + @param TextDeviceNode The input text device path node. + + @return A pointer to device path structure. +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextGenericPath ( + UINT8 Type, + CHAR16 *TextDeviceNode + ) +{ + EFI_DEVICE_PATH_PROTOCOL *Node; + CHAR16 *SubtypeStr; + CHAR16 *DataStr; + UINTN DataLength; + + SubtypeStr = GetNextParamStr (&TextDeviceNode); + DataStr = GetNextParamStr (&TextDeviceNode); + + if (DataStr == NULL) { + DataLength = 0; + } else { + DataLength = StrLen (DataStr) / 2; + } + Node = CreateDeviceNode ( + Type, + (UINT8) Strtoi (SubtypeStr), + (UINT16) (sizeof (EFI_DEVICE_PATH_PROTOCOL) + DataLength) + ); + + StrHexToBytes (DataStr, DataLength * 2, (UINT8 *) (Node + 1), DataLength); + return Node; +} + +/** + Converts a generic text device path node to device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPath ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *TypeStr; + + TypeStr = GetNextParamStr (&TextDeviceNode); + + return DevPathFromTextGenericPath ((UINT8) Strtoi (TypeStr), TextDeviceNode); +} + +/** + Converts a generic hardware text device path node to Hardware device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to Hardware device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextHardwarePath ( + CHAR16 *TextDeviceNode + ) +{ + return DevPathFromTextGenericPath (HARDWARE_DEVICE_PATH, TextDeviceNode); +} + +/** + Converts a text device path node to Hardware PCI device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to Hardware PCI device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPci ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *FunctionStr; + CHAR16 *DeviceStr; + PCI_DEVICE_PATH *Pci; + + DeviceStr = GetNextParamStr (&TextDeviceNode); + FunctionStr = GetNextParamStr (&TextDeviceNode); + Pci = (PCI_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_PCI_DP, + (UINT16) sizeof (PCI_DEVICE_PATH) + ); + + Pci->Function = (UINT8) Strtoi (FunctionStr); + Pci->Device = (UINT8) Strtoi (DeviceStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Pci; +} + +/** + Converts a text device path node to Hardware PC card device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to Hardware PC card device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPcCard ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *FunctionNumberStr; + PCCARD_DEVICE_PATH *Pccard; + + FunctionNumberStr = GetNextParamStr (&TextDeviceNode); + Pccard = (PCCARD_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_PCCARD_DP, + (UINT16) sizeof (PCCARD_DEVICE_PATH) + ); + + Pccard->FunctionNumber = (UINT8) Strtoi (FunctionNumberStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Pccard; +} + +/** + Converts a text device path node to Hardware memory map device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to Hardware memory map device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextMemoryMapped ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *MemoryTypeStr; + CHAR16 *StartingAddressStr; + CHAR16 *EndingAddressStr; + MEMMAP_DEVICE_PATH *MemMap; + + MemoryTypeStr = GetNextParamStr (&TextDeviceNode); + StartingAddressStr = GetNextParamStr (&TextDeviceNode); + EndingAddressStr = GetNextParamStr (&TextDeviceNode); + MemMap = (MEMMAP_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_MEMMAP_DP, + (UINT16) sizeof (MEMMAP_DEVICE_PATH) + ); + + MemMap->MemoryType = (UINT32) Strtoi (MemoryTypeStr); + Strtoi64 (StartingAddressStr, &MemMap->StartingAddress); + Strtoi64 (EndingAddressStr, &MemMap->EndingAddress); + + return (EFI_DEVICE_PATH_PROTOCOL *) MemMap; +} + +/** + Converts a text device path node to Vendor device path structure based on the input Type + and SubType. + + @param TextDeviceNode The input Text device path node. + @param Type The type of device path node. + @param SubType The subtype of device path node. + + @return A pointer to the newly-created Vendor device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +ConvertFromTextVendor ( + CHAR16 *TextDeviceNode, + UINT8 Type, + UINT8 SubType + ) +{ + CHAR16 *GuidStr; + CHAR16 *DataStr; + UINTN Length; + VENDOR_DEVICE_PATH *Vendor; + + GuidStr = GetNextParamStr (&TextDeviceNode); + + DataStr = GetNextParamStr (&TextDeviceNode); + Length = StrLen (DataStr); + // + // Two hex characters make up 1 buffer byte + // + Length = (Length + 1) / 2; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + Type, + SubType, + (UINT16) (sizeof (VENDOR_DEVICE_PATH) + Length) + ); + + StrToGuid (GuidStr, &Vendor->Guid); + StrHexToBytes (DataStr, Length * 2, (UINT8 *) (Vendor + 1), Length); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +/** + Converts a text device path node to Vendor Hardware device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Vendor Hardware device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenHw ( + CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextVendor ( + TextDeviceNode, + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP + ); +} + +/** + Converts a text device path node to Hardware Controller device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Hardware Controller device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextCtrl ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *ControllerStr; + CONTROLLER_DEVICE_PATH *Controller; + + ControllerStr = GetNextParamStr (&TextDeviceNode); + Controller = (CONTROLLER_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_CONTROLLER_DP, + (UINT16) sizeof (CONTROLLER_DEVICE_PATH) + ); + Controller->ControllerNumber = (UINT32) Strtoi (ControllerStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Controller; +} + +/** + Converts a text device path node to BMC device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created BMC device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextBmc ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *InterfaceTypeStr; + CHAR16 *BaseAddressStr; + BMC_DEVICE_PATH *BmcDp; + + InterfaceTypeStr = GetNextParamStr (&TextDeviceNode); + BaseAddressStr = GetNextParamStr (&TextDeviceNode); + BmcDp = (BMC_DEVICE_PATH *) CreateDeviceNode ( + HARDWARE_DEVICE_PATH, + HW_BMC_DP, + (UINT16) sizeof (BMC_DEVICE_PATH) + ); + + BmcDp->InterfaceType = (UINT8) Strtoi (InterfaceTypeStr); + WriteUnaligned64 ( + (UINT64 *) (&BmcDp->BaseAddress), + StrHexToUint64 (BaseAddressStr) + ); + + return (EFI_DEVICE_PATH_PROTOCOL *) BmcDp; +} + +/** + Converts a generic ACPI text device path node to ACPI device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to ACPI device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAcpiPath ( + CHAR16 *TextDeviceNode + ) +{ + return DevPathFromTextGenericPath (ACPI_DEVICE_PATH, TextDeviceNode); +} + +/** + Converts a string to EisaId. + + @param Text The input string. + + @return UINT32 EISA ID. +**/ +UINT32 +EisaIdFromText ( + CHAR16 *Text + ) +{ + return (((Text[0] - 'A' + 1) & 0x1f) << 10) + + (((Text[1] - 'A' + 1) & 0x1f) << 5) + + (((Text[2] - 'A' + 1) & 0x1f) << 0) + + (UINT32) (StrHexToUint64 (&Text[3]) << 16) + ; +} + +/** + Converts a text device path node to ACPI HID device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created ACPI HID device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAcpi ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *HIDStr; + CHAR16 *UIDStr; + ACPI_HID_DEVICE_PATH *Acpi; + + HIDStr = GetNextParamStr (&TextDeviceNode); + UIDStr = GetNextParamStr (&TextDeviceNode); + Acpi = (ACPI_HID_DEVICE_PATH *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_DP, + (UINT16) sizeof (ACPI_HID_DEVICE_PATH) + ); + + Acpi->HID = EisaIdFromText (HIDStr); + Acpi->UID = (UINT32) Strtoi (UIDStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Acpi; +} + +/** + Converts a text device path node to ACPI HID device path structure. + + @param TextDeviceNode The input Text device path node. + @param PnPId The input plug and play identification. + + @return A pointer to the newly-created ACPI HID device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +ConvertFromTextAcpi ( + CHAR16 *TextDeviceNode, + UINT32 PnPId + ) +{ + CHAR16 *UIDStr; + ACPI_HID_DEVICE_PATH *Acpi; + + UIDStr = GetNextParamStr (&TextDeviceNode); + Acpi = (ACPI_HID_DEVICE_PATH *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_DP, + (UINT16) sizeof (ACPI_HID_DEVICE_PATH) + ); + + Acpi->HID = EFI_PNP_ID (PnPId); + Acpi->UID = (UINT32) Strtoi (UIDStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Acpi; +} + +/** + Converts a text device path node to PCI root device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created PCI root device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPciRoot ( + CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x0a03); +} + +/** + Converts a text device path node to PCIE root device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created PCIE root device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPcieRoot ( + CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x0a08); +} + +/** + Converts a text device path node to Floppy device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Floppy device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFloppy ( + CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x0604); +} + +/** + Converts a text device path node to Keyboard device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Keyboard device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextKeyboard ( + CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x0301); +} + +/** + Converts a text device path node to Serial device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Serial device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextSerial ( + CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x0501); +} + +/** + Converts a text device path node to Parallel Port device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Parallel Port device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextParallelPort ( + CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextAcpi (TextDeviceNode, 0x0401); +} + +/** + Converts a text device path node to ACPI extension device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created ACPI extension device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAcpiEx ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *HIDStr; + CHAR16 *CIDStr; + CHAR16 *UIDStr; + CHAR16 *HIDSTRStr; + CHAR16 *CIDSTRStr; + CHAR16 *UIDSTRStr; + CHAR8 *AsciiStr; + UINT16 Length; + ACPI_EXTENDED_HID_DEVICE_PATH *AcpiEx; + + HIDStr = GetNextParamStr (&TextDeviceNode); + CIDStr = GetNextParamStr (&TextDeviceNode); + UIDStr = GetNextParamStr (&TextDeviceNode); + HIDSTRStr = GetNextParamStr (&TextDeviceNode); + CIDSTRStr = GetNextParamStr (&TextDeviceNode); + UIDSTRStr = GetNextParamStr (&TextDeviceNode); + + Length = (UINT16) (sizeof (ACPI_EXTENDED_HID_DEVICE_PATH) + StrLen (HIDSTRStr) + 1); + Length = (UINT16) (Length + StrLen (UIDSTRStr) + 1); + Length = (UINT16) (Length + StrLen (CIDSTRStr) + 1); + AcpiEx = (ACPI_EXTENDED_HID_DEVICE_PATH *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_EXTENDED_DP, + Length + ); + + AcpiEx->HID = EisaIdFromText (HIDStr); + AcpiEx->CID = EisaIdFromText (CIDStr); + AcpiEx->UID = (UINT32) Strtoi (UIDStr); + + AsciiStr = (CHAR8 *) ((UINT8 *)AcpiEx + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH)); + StrToAscii (HIDSTRStr, &AsciiStr); + StrToAscii (UIDSTRStr, &AsciiStr); + StrToAscii (CIDSTRStr, &AsciiStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) AcpiEx; +} + +/** + Converts a text device path node to ACPI extension device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created ACPI extension device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAcpiExp ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *HIDStr; + CHAR16 *CIDStr; + CHAR16 *UIDSTRStr; + CHAR8 *AsciiStr; + UINT16 Length; + ACPI_EXTENDED_HID_DEVICE_PATH *AcpiEx; + + HIDStr = GetNextParamStr (&TextDeviceNode); + CIDStr = GetNextParamStr (&TextDeviceNode); + UIDSTRStr = GetNextParamStr (&TextDeviceNode); + Length = (UINT16) (sizeof (ACPI_EXTENDED_HID_DEVICE_PATH) + StrLen (UIDSTRStr) + 3); + AcpiEx = (ACPI_EXTENDED_HID_DEVICE_PATH *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_EXTENDED_DP, + Length + ); + + AcpiEx->HID = EisaIdFromText (HIDStr); + // + // According to UEFI spec, the CID parametr is optional and has a default value of 0. + // So when the CID parametr is not specified or specified as 0 in the text device node. + // Set the CID to 0 in the ACPI extension device path structure. + // + if (*CIDStr == L'\0' || *CIDStr == L'0') { + AcpiEx->CID = 0; + } else { + AcpiEx->CID = EisaIdFromText (CIDStr); + } + AcpiEx->UID = 0; + + AsciiStr = (CHAR8 *) ((UINT8 *)AcpiEx + sizeof (ACPI_EXTENDED_HID_DEVICE_PATH)); + // + // HID string is NULL + // + *AsciiStr = '\0'; + // + // Convert UID string + // + AsciiStr++; + StrToAscii (UIDSTRStr, &AsciiStr); + // + // CID string is NULL + // + *AsciiStr = '\0'; + + return (EFI_DEVICE_PATH_PROTOCOL *) AcpiEx; +} + +/** + Converts a text device path node to ACPI _ADR device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created ACPI _ADR device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAcpiAdr ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *DisplayDeviceStr; + ACPI_ADR_DEVICE_PATH *AcpiAdr; + UINTN Index; + UINTN Length; + + AcpiAdr = (ACPI_ADR_DEVICE_PATH *) CreateDeviceNode ( + ACPI_DEVICE_PATH, + ACPI_ADR_DP, + (UINT16) sizeof (ACPI_ADR_DEVICE_PATH) + ); + ASSERT (AcpiAdr != NULL); + + for (Index = 0; ; Index++) { + DisplayDeviceStr = GetNextParamStr (&TextDeviceNode); + if (IS_NULL (*DisplayDeviceStr)) { + break; + } + if (Index > 0) { + Length = DevicePathNodeLength (AcpiAdr); + AcpiAdr = ReallocatePool ( + Length, + Length + sizeof (UINT32), + AcpiAdr + ); + ASSERT (AcpiAdr != NULL); + SetDevicePathNodeLength (AcpiAdr, Length + sizeof (UINT32)); + } + + (&AcpiAdr->ADR)[Index] = (UINT32) Strtoi (DisplayDeviceStr); + } + + return (EFI_DEVICE_PATH_PROTOCOL *) AcpiAdr; +} + +/** + Converts a generic messaging text device path node to messaging device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to messaging device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextMsg ( + CHAR16 *TextDeviceNode + ) +{ + return DevPathFromTextGenericPath (MESSAGING_DEVICE_PATH, TextDeviceNode); +} + +/** + Converts a text device path node to Parallel Port device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Parallel Port device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextAta ( + CHAR16 *TextDeviceNode +) +{ + CHAR16 *PrimarySecondaryStr; + CHAR16 *SlaveMasterStr; + CHAR16 *LunStr; + ATAPI_DEVICE_PATH *Atapi; + + Atapi = (ATAPI_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_ATAPI_DP, + (UINT16) sizeof (ATAPI_DEVICE_PATH) + ); + + PrimarySecondaryStr = GetNextParamStr (&TextDeviceNode); + SlaveMasterStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + + if (StrCmp (PrimarySecondaryStr, L"Primary") == 0) { + Atapi->PrimarySecondary = 0; + } else if (StrCmp (PrimarySecondaryStr, L"Secondary") == 0) { + Atapi->PrimarySecondary = 1; + } else { + Atapi->PrimarySecondary = (UINT8) Strtoi (PrimarySecondaryStr); + } + if (StrCmp (SlaveMasterStr, L"Master") == 0) { + Atapi->SlaveMaster = 0; + } else if (StrCmp (SlaveMasterStr, L"Slave") == 0) { + Atapi->SlaveMaster = 1; + } else { + Atapi->SlaveMaster = (UINT8) Strtoi (SlaveMasterStr); + } + + Atapi->Lun = (UINT16) Strtoi (LunStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Atapi; +} + +/** + Converts a text device path node to SCSI device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created SCSI device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextScsi ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *PunStr; + CHAR16 *LunStr; + SCSI_DEVICE_PATH *Scsi; + + PunStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + Scsi = (SCSI_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_SCSI_DP, + (UINT16) sizeof (SCSI_DEVICE_PATH) + ); + + Scsi->Pun = (UINT16) Strtoi (PunStr); + Scsi->Lun = (UINT16) Strtoi (LunStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Scsi; +} + +/** + Converts a text device path node to Fibre device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Fibre device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFibre ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *WWNStr; + CHAR16 *LunStr; + FIBRECHANNEL_DEVICE_PATH *Fibre; + + WWNStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + Fibre = (FIBRECHANNEL_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_FIBRECHANNEL_DP, + (UINT16) sizeof (FIBRECHANNEL_DEVICE_PATH) + ); + + Fibre->Reserved = 0; + Strtoi64 (WWNStr, &Fibre->WWN); + Strtoi64 (LunStr, &Fibre->Lun); + + return (EFI_DEVICE_PATH_PROTOCOL *) Fibre; +} + +/** + Converts a text device path node to FibreEx device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created FibreEx device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFibreEx ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *WWNStr; + CHAR16 *LunStr; + FIBRECHANNELEX_DEVICE_PATH *FibreEx; + + WWNStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + FibreEx = (FIBRECHANNELEX_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_FIBRECHANNELEX_DP, + (UINT16) sizeof (FIBRECHANNELEX_DEVICE_PATH) + ); + + FibreEx->Reserved = 0; + Strtoi64 (WWNStr, (UINT64 *) (&FibreEx->WWN)); + Strtoi64 (LunStr, (UINT64 *) (&FibreEx->Lun)); + + *(UINT64 *) (&FibreEx->WWN) = SwapBytes64 (*(UINT64 *) (&FibreEx->WWN)); + *(UINT64 *) (&FibreEx->Lun) = SwapBytes64 (*(UINT64 *) (&FibreEx->Lun)); + + return (EFI_DEVICE_PATH_PROTOCOL *) FibreEx; +} + +/** + Converts a text device path node to 1394 device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created 1394 device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromText1394 ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *GuidStr; + F1394_DEVICE_PATH *F1394DevPath; + + GuidStr = GetNextParamStr (&TextDeviceNode); + F1394DevPath = (F1394_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_1394_DP, + (UINT16) sizeof (F1394_DEVICE_PATH) + ); + + F1394DevPath->Reserved = 0; + F1394DevPath->Guid = StrHexToUint64 (GuidStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) F1394DevPath; +} + +/** + Converts a text device path node to USB device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsb ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *PortStr; + CHAR16 *InterfaceStr; + USB_DEVICE_PATH *Usb; + + PortStr = GetNextParamStr (&TextDeviceNode); + InterfaceStr = GetNextParamStr (&TextDeviceNode); + Usb = (USB_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_USB_DP, + (UINT16) sizeof (USB_DEVICE_PATH) + ); + + Usb->ParentPortNumber = (UINT8) Strtoi (PortStr); + Usb->InterfaceNumber = (UINT8) Strtoi (InterfaceStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Usb; +} + +/** + Converts a text device path node to I20 device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created I20 device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextI2O ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *TIDStr; + I2O_DEVICE_PATH *I2ODevPath; + + TIDStr = GetNextParamStr (&TextDeviceNode); + I2ODevPath = (I2O_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_I2O_DP, + (UINT16) sizeof (I2O_DEVICE_PATH) + ); + + I2ODevPath->Tid = (UINT32) Strtoi (TIDStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) I2ODevPath; +} + +/** + Converts a text device path node to Infini Band device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Infini Band device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextInfiniband ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *FlagsStr; + CHAR16 *GuidStr; + CHAR16 *SidStr; + CHAR16 *TidStr; + CHAR16 *DidStr; + INFINIBAND_DEVICE_PATH *InfiniBand; + + FlagsStr = GetNextParamStr (&TextDeviceNode); + GuidStr = GetNextParamStr (&TextDeviceNode); + SidStr = GetNextParamStr (&TextDeviceNode); + TidStr = GetNextParamStr (&TextDeviceNode); + DidStr = GetNextParamStr (&TextDeviceNode); + InfiniBand = (INFINIBAND_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_INFINIBAND_DP, + (UINT16) sizeof (INFINIBAND_DEVICE_PATH) + ); + + InfiniBand->ResourceFlags = (UINT32) Strtoi (FlagsStr); + StrToGuid (GuidStr, (EFI_GUID *) InfiniBand->PortGid); + Strtoi64 (SidStr, &InfiniBand->ServiceId); + Strtoi64 (TidStr, &InfiniBand->TargetPortId); + Strtoi64 (DidStr, &InfiniBand->DeviceId); + + return (EFI_DEVICE_PATH_PROTOCOL *) InfiniBand; +} + +/** + Converts a text device path node to Vendor-Defined Messaging device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Vendor-Defined Messaging device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenMsg ( + CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextVendor ( + TextDeviceNode, + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP + ); +} + +/** + Converts a text device path node to Vendor defined PC-ANSI device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Vendor defined PC-ANSI device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenPcAnsi ( + CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vendor; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + (UINT16) sizeof (VENDOR_DEVICE_PATH)); + CopyGuid (&Vendor->Guid, &gEfiPcAnsiGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +/** + Converts a text device path node to Vendor defined VT100 device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Vendor defined VT100 device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenVt100 ( + CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vendor; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + (UINT16) sizeof (VENDOR_DEVICE_PATH)); + CopyGuid (&Vendor->Guid, &gEfiVT100Guid); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +/** + Converts a text device path node to Vendor defined VT100 Plus device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Vendor defined VT100 Plus device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenVt100Plus ( + CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vendor; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + (UINT16) sizeof (VENDOR_DEVICE_PATH)); + CopyGuid (&Vendor->Guid, &gEfiVT100PlusGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +/** + Converts a text device path node to Vendor defined UTF8 device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Vendor defined UTF8 device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenUtf8 ( + CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vendor; + + Vendor = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + (UINT16) sizeof (VENDOR_DEVICE_PATH)); + CopyGuid (&Vendor->Guid, &gEfiVTUTF8Guid); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vendor; +} + +/** + Converts a text device path node to UART Flow Control device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created UART Flow Control device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUartFlowCtrl ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *ValueStr; + UART_FLOW_CONTROL_DEVICE_PATH *UartFlowControl; + + ValueStr = GetNextParamStr (&TextDeviceNode); + UartFlowControl = (UART_FLOW_CONTROL_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + (UINT16) sizeof (UART_FLOW_CONTROL_DEVICE_PATH) + ); + + CopyGuid (&UartFlowControl->Guid, &gEfiUartDevicePathGuid); + if (StrCmp (ValueStr, L"XonXoff") == 0) { + UartFlowControl->FlowControlMap = 2; + } else if (StrCmp (ValueStr, L"Hardware") == 0) { + UartFlowControl->FlowControlMap = 1; + } else { + UartFlowControl->FlowControlMap = 0; + } + + return (EFI_DEVICE_PATH_PROTOCOL *) UartFlowControl; +} + +/** + Converts a text device path node to Serial Attached SCSI device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Serial Attached SCSI device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextSAS ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *AddressStr; + CHAR16 *LunStr; + CHAR16 *RTPStr; + CHAR16 *SASSATAStr; + CHAR16 *LocationStr; + CHAR16 *ConnectStr; + CHAR16 *DriveBayStr; + CHAR16 *ReservedStr; + UINT16 Info; + UINT16 Uint16; + SAS_DEVICE_PATH *Sas; + + AddressStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + RTPStr = GetNextParamStr (&TextDeviceNode); + SASSATAStr = GetNextParamStr (&TextDeviceNode); + LocationStr = GetNextParamStr (&TextDeviceNode); + ConnectStr = GetNextParamStr (&TextDeviceNode); + DriveBayStr = GetNextParamStr (&TextDeviceNode); + ReservedStr = GetNextParamStr (&TextDeviceNode); + Sas = (SAS_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + (UINT16) sizeof (SAS_DEVICE_PATH) + ); + + CopyGuid (&Sas->Guid, &gEfiSasDevicePathGuid); + Strtoi64 (AddressStr, &Sas->SasAddress); + Strtoi64 (LunStr, &Sas->Lun); + Sas->RelativeTargetPort = (UINT16) Strtoi (RTPStr); + + if (StrCmp (SASSATAStr, L"NoTopology") == 0) { + Info = 0x0; + + } else if ((StrCmp (SASSATAStr, L"SATA") == 0) || (StrCmp (SASSATAStr, L"SAS") == 0)) { + + Uint16 = (UINT16) Strtoi (DriveBayStr); + if (Uint16 == 0) { + Info = 0x1; + } else { + Info = (UINT16) (0x2 | ((Uint16 - 1) << 8)); + } + + if (StrCmp (SASSATAStr, L"SATA") == 0) { + Info |= BIT4; + } + + // + // Location is an integer between 0 and 1 or else + // the keyword Internal (0) or External (1). + // + if (StrCmp (LocationStr, L"External") == 0) { + Uint16 = 1; + } else if (StrCmp (LocationStr, L"Internal") == 0) { + Uint16 = 0; + } else { + Uint16 = ((UINT16) Strtoi (LocationStr) & BIT0); + } + Info |= (Uint16 << 5); + + // + // Connect is an integer between 0 and 3 or else + // the keyword Direct (0) or Expanded (1). + // + if (StrCmp (ConnectStr, L"Expanded") == 0) { + Uint16 = 1; + } else if (StrCmp (ConnectStr, L"Direct") == 0) { + Uint16 = 0; + } else { + Uint16 = ((UINT16) Strtoi (ConnectStr) & (BIT0 | BIT1)); + } + Info |= (Uint16 << 6); + + } else { + Info = (UINT16) Strtoi (SASSATAStr); + } + + Sas->DeviceTopology = Info; + Sas->Reserved = (UINT32) Strtoi (ReservedStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Sas; +} + +/** + Converts a text device path node to Serial Attached SCSI Ex device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Serial Attached SCSI Ex device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextSasEx ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *AddressStr; + CHAR16 *LunStr; + CHAR16 *RTPStr; + CHAR16 *SASSATAStr; + CHAR16 *LocationStr; + CHAR16 *ConnectStr; + CHAR16 *DriveBayStr; + UINT16 Info; + UINT16 Uint16; + UINT64 SasAddress; + UINT64 Lun; + SASEX_DEVICE_PATH *SasEx; + + AddressStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + RTPStr = GetNextParamStr (&TextDeviceNode); + SASSATAStr = GetNextParamStr (&TextDeviceNode); + LocationStr = GetNextParamStr (&TextDeviceNode); + ConnectStr = GetNextParamStr (&TextDeviceNode); + DriveBayStr = GetNextParamStr (&TextDeviceNode); + SasEx = (SASEX_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_SASEX_DP, + (UINT16) sizeof (SASEX_DEVICE_PATH) + ); + + Strtoi64 (AddressStr, &SasAddress); + Strtoi64 (LunStr, &Lun); + WriteUnaligned64 ((UINT64 *) &SasEx->SasAddress, SwapBytes64 (SasAddress)); + WriteUnaligned64 ((UINT64 *) &SasEx->Lun, SwapBytes64 (Lun)); + SasEx->RelativeTargetPort = (UINT16) Strtoi (RTPStr); + + if (StrCmp (SASSATAStr, L"NoTopology") == 0) { + Info = 0x0; + + } else if ((StrCmp (SASSATAStr, L"SATA") == 0) || (StrCmp (SASSATAStr, L"SAS") == 0)) { + + Uint16 = (UINT16) Strtoi (DriveBayStr); + if (Uint16 == 0) { + Info = 0x1; + } else { + Info = (UINT16) (0x2 | ((Uint16 - 1) << 8)); + } + + if (StrCmp (SASSATAStr, L"SATA") == 0) { + Info |= BIT4; + } + + // + // Location is an integer between 0 and 1 or else + // the keyword Internal (0) or External (1). + // + if (StrCmp (LocationStr, L"External") == 0) { + Uint16 = 1; + } else if (StrCmp (LocationStr, L"Internal") == 0) { + Uint16 = 0; + } else { + Uint16 = ((UINT16) Strtoi (LocationStr) & BIT0); + } + Info |= (Uint16 << 5); + + // + // Connect is an integer between 0 and 3 or else + // the keyword Direct (0) or Expanded (1). + // + if (StrCmp (ConnectStr, L"Expanded") == 0) { + Uint16 = 1; + } else if (StrCmp (ConnectStr, L"Direct") == 0) { + Uint16 = 0; + } else { + Uint16 = ((UINT16) Strtoi (ConnectStr) & (BIT0 | BIT1)); + } + Info |= (Uint16 << 6); + + } else { + Info = (UINT16) Strtoi (SASSATAStr); + } + + SasEx->DeviceTopology = Info; + + return (EFI_DEVICE_PATH_PROTOCOL *) SasEx; +} + +/** + Converts a text device path node to NVM Express Namespace device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created NVM Express Namespace device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextNVMe ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *NamespaceIdStr; + CHAR16 *NamespaceUuidStr; + NVME_NAMESPACE_DEVICE_PATH *Nvme; + UINT8 *Uuid; + UINTN Index; + + NamespaceIdStr = GetNextParamStr (&TextDeviceNode); + NamespaceUuidStr = GetNextParamStr (&TextDeviceNode); + Nvme = (NVME_NAMESPACE_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_NVME_NAMESPACE_DP, + (UINT16) sizeof (NVME_NAMESPACE_DEVICE_PATH) + ); + + Nvme->NamespaceId = (UINT32) Strtoi (NamespaceIdStr); + Uuid = (UINT8 *) &Nvme->NamespaceUuid; + + Index = sizeof (Nvme->NamespaceUuid) / sizeof (UINT8); + while (Index-- != 0) { + Uuid[Index] = (UINT8) StrHexToUint64 (SplitStr (&NamespaceUuidStr, L'-')); + } + + return (EFI_DEVICE_PATH_PROTOCOL *) Nvme; +} + +/** + Converts a text device path node to UFS device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created UFS device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUfs ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *PunStr; + CHAR16 *LunStr; + UFS_DEVICE_PATH *Ufs; + + PunStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + Ufs = (UFS_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_UFS_DP, + (UINT16) sizeof (UFS_DEVICE_PATH) + ); + + Ufs->Pun = (UINT8) Strtoi (PunStr); + Ufs->Lun = (UINT8) Strtoi (LunStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Ufs; +} + +/** + Converts a text device path node to SD (Secure Digital) device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created SD device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextSd ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *SlotNumberStr; + SD_DEVICE_PATH *Sd; + + SlotNumberStr = GetNextParamStr (&TextDeviceNode); + Sd = (SD_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_SD_DP, + (UINT16) sizeof (SD_DEVICE_PATH) + ); + + Sd->SlotNumber = (UINT8) Strtoi (SlotNumberStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Sd; +} + +/** + Converts a text device path node to EMMC (Embedded MMC) device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created EMMC device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextEmmc ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *SlotNumberStr; + EMMC_DEVICE_PATH *Emmc; + + SlotNumberStr = GetNextParamStr (&TextDeviceNode); + Emmc = (EMMC_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_EMMC_DP, + (UINT16) sizeof (EMMC_DEVICE_PATH) + ); + + Emmc->SlotNumber = (UINT8) Strtoi (SlotNumberStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Emmc; +} + +/** + Converts a text device path node to Debug Port device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Debug Port device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextDebugPort ( + CHAR16 *TextDeviceNode + ) +{ + VENDOR_DEVICE_PATH *Vend; + + Vend = (VENDOR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VENDOR_DP, + (UINT16) sizeof (VENDOR_DEVICE_PATH) + ); + + CopyGuid (&Vend->Guid, &gEfiDebugPortProtocolGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vend; +} + +/** + Converts a text device path node to MAC device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created MAC device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextMAC ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *AddressStr; + CHAR16 *IfTypeStr; + UINTN Length; + MAC_ADDR_DEVICE_PATH *MACDevPath; + + AddressStr = GetNextParamStr (&TextDeviceNode); + IfTypeStr = GetNextParamStr (&TextDeviceNode); + MACDevPath = (MAC_ADDR_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_MAC_ADDR_DP, + (UINT16) sizeof (MAC_ADDR_DEVICE_PATH) + ); + + MACDevPath->IfType = (UINT8) Strtoi (IfTypeStr); + + Length = sizeof (EFI_MAC_ADDRESS); + if (MACDevPath->IfType == 0x01 || MACDevPath->IfType == 0x00) { + Length = 6; + } + + StrHexToBytes (AddressStr, Length * 2, MACDevPath->MacAddress.Addr, Length); + + return (EFI_DEVICE_PATH_PROTOCOL *) MACDevPath; +} + + +/** + Converts a text format to the network protocol ID. + + @param Text String of protocol field. + + @return Network protocol ID . + +**/ +UINTN +NetworkProtocolFromText ( + CHAR16 *Text + ) +{ + if (StrCmp (Text, L"UDP") == 0) { + return RFC_1700_UDP_PROTOCOL; + } + + if (StrCmp (Text, L"TCP") == 0) { + return RFC_1700_TCP_PROTOCOL; + } + + return Strtoi (Text); +} + + +/** + Converts a text device path node to IPV4 device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created IPV4 device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextIPv4 ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *RemoteIPStr; + CHAR16 *ProtocolStr; + CHAR16 *TypeStr; + CHAR16 *LocalIPStr; + CHAR16 *GatewayIPStr; + CHAR16 *SubnetMaskStr; + IPv4_DEVICE_PATH *IPv4; + + RemoteIPStr = GetNextParamStr (&TextDeviceNode); + ProtocolStr = GetNextParamStr (&TextDeviceNode); + TypeStr = GetNextParamStr (&TextDeviceNode); + LocalIPStr = GetNextParamStr (&TextDeviceNode); + GatewayIPStr = GetNextParamStr (&TextDeviceNode); + SubnetMaskStr = GetNextParamStr (&TextDeviceNode); + IPv4 = (IPv4_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_IPv4_DP, + (UINT16) sizeof (IPv4_DEVICE_PATH) + ); + + StrToIpv4Address (RemoteIPStr, NULL, &IPv4->RemoteIpAddress, NULL); + IPv4->Protocol = (UINT16) NetworkProtocolFromText (ProtocolStr); + if (StrCmp (TypeStr, L"Static") == 0) { + IPv4->StaticIpAddress = TRUE; + } else { + IPv4->StaticIpAddress = FALSE; + } + + StrToIpv4Address (LocalIPStr, NULL, &IPv4->LocalIpAddress, NULL); + if (!IS_NULL (*GatewayIPStr) && !IS_NULL (*SubnetMaskStr)) { + StrToIpv4Address (GatewayIPStr, NULL, &IPv4->GatewayIpAddress, NULL); + StrToIpv4Address (SubnetMaskStr, NULL, &IPv4->SubnetMask, NULL); + } else { + ZeroMem (&IPv4->GatewayIpAddress, sizeof (IPv4->GatewayIpAddress)); + ZeroMem (&IPv4->SubnetMask, sizeof (IPv4->SubnetMask)); + } + + IPv4->LocalPort = 0; + IPv4->RemotePort = 0; + + return (EFI_DEVICE_PATH_PROTOCOL *) IPv4; +} + +/** + Converts a text device path node to IPV6 device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created IPV6 device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextIPv6 ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *RemoteIPStr; + CHAR16 *ProtocolStr; + CHAR16 *TypeStr; + CHAR16 *LocalIPStr; + CHAR16 *GatewayIPStr; + CHAR16 *PrefixLengthStr; + IPv6_DEVICE_PATH *IPv6; + + RemoteIPStr = GetNextParamStr (&TextDeviceNode); + ProtocolStr = GetNextParamStr (&TextDeviceNode); + TypeStr = GetNextParamStr (&TextDeviceNode); + LocalIPStr = GetNextParamStr (&TextDeviceNode); + PrefixLengthStr = GetNextParamStr (&TextDeviceNode); + GatewayIPStr = GetNextParamStr (&TextDeviceNode); + IPv6 = (IPv6_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_IPv6_DP, + (UINT16) sizeof (IPv6_DEVICE_PATH) + ); + + StrToIpv6Address (RemoteIPStr, NULL, &IPv6->RemoteIpAddress, NULL); + IPv6->Protocol = (UINT16) NetworkProtocolFromText (ProtocolStr); + if (StrCmp (TypeStr, L"Static") == 0) { + IPv6->IpAddressOrigin = 0; + } else if (StrCmp (TypeStr, L"StatelessAutoConfigure") == 0) { + IPv6->IpAddressOrigin = 1; + } else { + IPv6->IpAddressOrigin = 2; + } + + StrToIpv6Address (LocalIPStr, NULL, &IPv6->LocalIpAddress, NULL); + if (!IS_NULL (*GatewayIPStr) && !IS_NULL (*PrefixLengthStr)) { + StrToIpv6Address (GatewayIPStr, NULL, &IPv6->GatewayIpAddress, NULL); + IPv6->PrefixLength = (UINT8) Strtoi (PrefixLengthStr); + } else { + ZeroMem (&IPv6->GatewayIpAddress, sizeof (IPv6->GatewayIpAddress)); + IPv6->PrefixLength = 0; + } + + IPv6->LocalPort = 0; + IPv6->RemotePort = 0; + + return (EFI_DEVICE_PATH_PROTOCOL *) IPv6; +} + +/** + Converts a text device path node to UART device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created UART device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUart ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *BaudStr; + CHAR16 *DataBitsStr; + CHAR16 *ParityStr; + CHAR16 *StopBitsStr; + UART_DEVICE_PATH *Uart; + + BaudStr = GetNextParamStr (&TextDeviceNode); + DataBitsStr = GetNextParamStr (&TextDeviceNode); + ParityStr = GetNextParamStr (&TextDeviceNode); + StopBitsStr = GetNextParamStr (&TextDeviceNode); + Uart = (UART_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_UART_DP, + (UINT16) sizeof (UART_DEVICE_PATH) + ); + + if (StrCmp (BaudStr, L"DEFAULT") == 0) { + Uart->BaudRate = 115200; + } else { + Strtoi64 (BaudStr, &Uart->BaudRate); + } + Uart->DataBits = (UINT8) ((StrCmp (DataBitsStr, L"DEFAULT") == 0) ? 8 : Strtoi (DataBitsStr)); + switch (*ParityStr) { + case L'D': + Uart->Parity = 0; + break; + + case L'N': + Uart->Parity = 1; + break; + + case L'E': + Uart->Parity = 2; + break; + + case L'O': + Uart->Parity = 3; + break; + + case L'M': + Uart->Parity = 4; + break; + + case L'S': + Uart->Parity = 5; + break; + + default: + Uart->Parity = (UINT8) Strtoi (ParityStr); + break; + } + + if (StrCmp (StopBitsStr, L"D") == 0) { + Uart->StopBits = (UINT8) 0; + } else if (StrCmp (StopBitsStr, L"1") == 0) { + Uart->StopBits = (UINT8) 1; + } else if (StrCmp (StopBitsStr, L"1.5") == 0) { + Uart->StopBits = (UINT8) 2; + } else if (StrCmp (StopBitsStr, L"2") == 0) { + Uart->StopBits = (UINT8) 3; + } else { + Uart->StopBits = (UINT8) Strtoi (StopBitsStr); + } + + return (EFI_DEVICE_PATH_PROTOCOL *) Uart; +} + +/** + Converts a text device path node to USB class device path structure. + + @param TextDeviceNode The input Text device path node. + @param UsbClassText A pointer to USB_CLASS_TEXT structure to be integrated to USB Class Text. + + @return A pointer to the newly-created USB class device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +ConvertFromTextUsbClass ( + CHAR16 *TextDeviceNode, + USB_CLASS_TEXT *UsbClassText + ) +{ + CHAR16 *VIDStr; + CHAR16 *PIDStr; + CHAR16 *ClassStr; + CHAR16 *SubClassStr; + CHAR16 *ProtocolStr; + USB_CLASS_DEVICE_PATH *UsbClass; + + UsbClass = (USB_CLASS_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_USB_CLASS_DP, + (UINT16) sizeof (USB_CLASS_DEVICE_PATH) + ); + + VIDStr = GetNextParamStr (&TextDeviceNode); + PIDStr = GetNextParamStr (&TextDeviceNode); + if (UsbClassText->ClassExist) { + ClassStr = GetNextParamStr (&TextDeviceNode); + if (*ClassStr == L'\0') { + UsbClass->DeviceClass = 0xFF; + } else { + UsbClass->DeviceClass = (UINT8) Strtoi (ClassStr); + } + } else { + UsbClass->DeviceClass = UsbClassText->Class; + } + if (UsbClassText->SubClassExist) { + SubClassStr = GetNextParamStr (&TextDeviceNode); + if (*SubClassStr == L'\0') { + UsbClass->DeviceSubClass = 0xFF; + } else { + UsbClass->DeviceSubClass = (UINT8) Strtoi (SubClassStr); + } + } else { + UsbClass->DeviceSubClass = UsbClassText->SubClass; + } + + ProtocolStr = GetNextParamStr (&TextDeviceNode); + + if (*VIDStr == L'\0') { + UsbClass->VendorId = 0xFFFF; + } else { + UsbClass->VendorId = (UINT16) Strtoi (VIDStr); + } + if (*PIDStr == L'\0') { + UsbClass->ProductId = 0xFFFF; + } else { + UsbClass->ProductId = (UINT16) Strtoi (PIDStr); + } + if (*ProtocolStr == L'\0') { + UsbClass->DeviceProtocol = 0xFF; + } else { + UsbClass->DeviceProtocol = (UINT8) Strtoi (ProtocolStr); + } + + return (EFI_DEVICE_PATH_PROTOCOL *) UsbClass; +} + + +/** + Converts a text device path node to USB class device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB class device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbClass ( + CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = TRUE; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB audio device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB audio device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbAudio ( + CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_AUDIO; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB CDC Control device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB CDC Control device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbCDCControl ( + CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_CDCCONTROL; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB HID device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB HID device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbHID ( + CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_HID; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB Image device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB Image device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbImage ( + CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_IMAGE; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB Print device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB Print device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbPrinter ( + CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_PRINTER; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB mass storage device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB mass storage device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbMassStorage ( + CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_MASS_STORAGE; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB HUB device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB HUB device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbHub ( + CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_HUB; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB CDC data device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB CDC data device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbCDCData ( + CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_CDCDATA; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB smart card device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB smart card device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbSmartCard ( + CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_SMART_CARD; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB video device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB video device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbVideo ( + CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_VIDEO; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB diagnostic device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB diagnostic device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbDiagnostic ( + CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_DIAGNOSTIC; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB wireless device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB wireless device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbWireless ( + CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_WIRELESS; + UsbClassText.SubClassExist = TRUE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB device firmware update device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB device firmware update device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbDeviceFirmwareUpdate ( + CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_RESERVE; + UsbClassText.SubClassExist = FALSE; + UsbClassText.SubClass = USB_SUBCLASS_FW_UPDATE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB IRDA bridge device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB IRDA bridge device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbIrdaBridge ( + CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_RESERVE; + UsbClassText.SubClassExist = FALSE; + UsbClassText.SubClass = USB_SUBCLASS_IRDA_BRIDGE; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB text and measurement device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB text and measurement device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbTestAndMeasurement ( + CHAR16 *TextDeviceNode + ) +{ + USB_CLASS_TEXT UsbClassText; + + UsbClassText.ClassExist = FALSE; + UsbClassText.Class = USB_CLASS_RESERVE; + UsbClassText.SubClassExist = FALSE; + UsbClassText.SubClass = USB_SUBCLASS_TEST; + + return ConvertFromTextUsbClass (TextDeviceNode, &UsbClassText); +} + +/** + Converts a text device path node to USB WWID device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created USB WWID device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUsbWwid ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *VIDStr; + CHAR16 *PIDStr; + CHAR16 *InterfaceNumStr; + CHAR16 *SerialNumberStr; + USB_WWID_DEVICE_PATH *UsbWwid; + UINTN SerialNumberStrLen; + + VIDStr = GetNextParamStr (&TextDeviceNode); + PIDStr = GetNextParamStr (&TextDeviceNode); + InterfaceNumStr = GetNextParamStr (&TextDeviceNode); + SerialNumberStr = GetNextParamStr (&TextDeviceNode); + SerialNumberStrLen = StrLen (SerialNumberStr); + if (SerialNumberStrLen >= 2 && + SerialNumberStr[0] == L'\"' && + SerialNumberStr[SerialNumberStrLen - 1] == L'\"' + ) { + SerialNumberStr[SerialNumberStrLen - 1] = L'\0'; + SerialNumberStr++; + SerialNumberStrLen -= 2; + } + UsbWwid = (USB_WWID_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_USB_WWID_DP, + (UINT16) (sizeof (USB_WWID_DEVICE_PATH) + SerialNumberStrLen * sizeof (CHAR16)) + ); + UsbWwid->VendorId = (UINT16) Strtoi (VIDStr); + UsbWwid->ProductId = (UINT16) Strtoi (PIDStr); + UsbWwid->InterfaceNumber = (UINT16) Strtoi (InterfaceNumStr); + + // + // There is no memory allocated in UsbWwid for the '\0' in SerialNumberStr. + // Therefore, the '\0' will not be copied. + // + memcpy ( + (UINT8 *) UsbWwid + sizeof (USB_WWID_DEVICE_PATH), + SerialNumberStr, + SerialNumberStrLen * sizeof (CHAR16) + ); + + return (EFI_DEVICE_PATH_PROTOCOL *) UsbWwid; +} + +/** + Converts a text device path node to Logic Unit device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Logic Unit device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUnit ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *LunStr; + DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicalUnit; + + LunStr = GetNextParamStr (&TextDeviceNode); + LogicalUnit = (DEVICE_LOGICAL_UNIT_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_DEVICE_LOGICAL_UNIT_DP, + (UINT16) sizeof (DEVICE_LOGICAL_UNIT_DEVICE_PATH) + ); + + LogicalUnit->Lun = (UINT8) Strtoi (LunStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) LogicalUnit; +} + +/** + Converts a text device path node to iSCSI device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created iSCSI device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextiSCSI ( + CHAR16 *TextDeviceNode + ) +{ + UINT16 Options; + CHAR16 *NameStr; + CHAR16 *PortalGroupStr; + CHAR16 *LunStr; + CHAR16 *HeaderDigestStr; + CHAR16 *DataDigestStr; + CHAR16 *AuthenticationStr; + CHAR16 *ProtocolStr; + CHAR8 *AsciiStr; + ISCSI_DEVICE_PATH_WITH_NAME *ISCSIDevPath; + UINT64 Lun; + + NameStr = GetNextParamStr (&TextDeviceNode); + PortalGroupStr = GetNextParamStr (&TextDeviceNode); + LunStr = GetNextParamStr (&TextDeviceNode); + HeaderDigestStr = GetNextParamStr (&TextDeviceNode); + DataDigestStr = GetNextParamStr (&TextDeviceNode); + AuthenticationStr = GetNextParamStr (&TextDeviceNode); + ProtocolStr = GetNextParamStr (&TextDeviceNode); + ISCSIDevPath = (ISCSI_DEVICE_PATH_WITH_NAME *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_ISCSI_DP, + (UINT16) (sizeof (ISCSI_DEVICE_PATH_WITH_NAME) + StrLen (NameStr)) + ); + + AsciiStr = ISCSIDevPath->TargetName; + StrToAscii (NameStr, &AsciiStr); + + ISCSIDevPath->TargetPortalGroupTag = (UINT16) Strtoi (PortalGroupStr); + Strtoi64 (LunStr, &Lun); + WriteUnaligned64 ((UINT64 *) &ISCSIDevPath->Lun, SwapBytes64 (Lun)); + + Options = 0x0000; + if (StrCmp (HeaderDigestStr, L"CRC32C") == 0) { + Options |= 0x0002; + } + + if (StrCmp (DataDigestStr, L"CRC32C") == 0) { + Options |= 0x0008; + } + + if (StrCmp (AuthenticationStr, L"None") == 0) { + Options |= 0x0800; + } + + if (StrCmp (AuthenticationStr, L"CHAP_UNI") == 0) { + Options |= 0x1000; + } + + ISCSIDevPath->LoginOption = (UINT16) Options; + + if (IS_NULL (*ProtocolStr) || (StrCmp (ProtocolStr, L"TCP") == 0)) { + ISCSIDevPath->NetworkProtocol = 0; + } else { + // + // Undefined and reserved. + // + ISCSIDevPath->NetworkProtocol = 1; + } + + return (EFI_DEVICE_PATH_PROTOCOL *) ISCSIDevPath; +} + +/** + Converts a text device path node to VLAN device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created VLAN device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVlan ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *VlanStr; + VLAN_DEVICE_PATH *Vlan; + + VlanStr = GetNextParamStr (&TextDeviceNode); + Vlan = (VLAN_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_VLAN_DP, + (UINT16) sizeof (VLAN_DEVICE_PATH) + ); + + Vlan->VlanId = (UINT16) Strtoi (VlanStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Vlan; +} + +/** + Converts a text device path node to Bluetooth device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Bluetooth device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextBluetooth ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *BluetoothStr; + BLUETOOTH_DEVICE_PATH *BluetoothDp; + + BluetoothStr = GetNextParamStr (&TextDeviceNode); + BluetoothDp = (BLUETOOTH_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_BLUETOOTH_DP, + (UINT16) sizeof (BLUETOOTH_DEVICE_PATH) + ); + StrHexToBytes ( + BluetoothStr, + sizeof (BLUETOOTH_ADDRESS) * 2, + BluetoothDp->BD_ADDR.Address, + sizeof (BLUETOOTH_ADDRESS) + ); + return (EFI_DEVICE_PATH_PROTOCOL *) BluetoothDp; +} + +/** + Converts a text device path node to Wi-Fi device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Wi-Fi device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextWiFi ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *SSIdStr; + CHAR8 AsciiStr[33]; + UINTN DataLen; + WIFI_DEVICE_PATH *WiFiDp; + + SSIdStr = GetNextParamStr (&TextDeviceNode); + WiFiDp = (WIFI_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_WIFI_DP, + (UINT16) sizeof (WIFI_DEVICE_PATH) + ); + + if (NULL != SSIdStr) { + DataLen = StrLen (SSIdStr); + if (StrLen (SSIdStr) > 32) { + SSIdStr[32] = L'\0'; + DataLen = 32; + } + + UnicodeStrToAsciiStrS (SSIdStr, AsciiStr, sizeof (AsciiStr)); + memcpy (WiFiDp->SSId, AsciiStr, DataLen); + } + + return (EFI_DEVICE_PATH_PROTOCOL *) WiFiDp; +} + +/** + Converts a text device path node to Bluetooth LE device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Bluetooth LE device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextBluetoothLE ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *BluetoothLeAddrStr; + CHAR16 *BluetoothLeAddrTypeStr; + BLUETOOTH_LE_DEVICE_PATH *BluetoothLeDp; + + BluetoothLeAddrStr = GetNextParamStr (&TextDeviceNode); + BluetoothLeAddrTypeStr = GetNextParamStr (&TextDeviceNode); + BluetoothLeDp = (BLUETOOTH_LE_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_BLUETOOTH_LE_DP, + (UINT16) sizeof (BLUETOOTH_LE_DEVICE_PATH) + ); + + BluetoothLeDp->Address.Type = (UINT8) Strtoi (BluetoothLeAddrTypeStr); + StrHexToBytes ( + BluetoothLeAddrStr, sizeof (BluetoothLeDp->Address.Address) * 2, + BluetoothLeDp->Address.Address, sizeof (BluetoothLeDp->Address.Address) + ); + return (EFI_DEVICE_PATH_PROTOCOL *) BluetoothLeDp; +} + +/** + Converts a text device path node to DNS device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created DNS device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextDns ( + IN CHAR16 *TextDeviceNode + ) +{ + CHAR16 *DeviceNodeStr; + CHAR16 *DeviceNodeStrPtr; + UINT32 DnsServerIpCount; + UINT16 DnsDeviceNodeLength; + DNS_DEVICE_PATH *DnsDeviceNode; + UINT32 DnsServerIpIndex; + CHAR16 *DnsServerIp; + + + // + // Count the DNS server address number. + // + DeviceNodeStr = UefiDevicePathLibStrDuplicate (TextDeviceNode); + if (DeviceNodeStr == NULL) { + return NULL; + } + + DeviceNodeStrPtr = DeviceNodeStr; + + DnsServerIpCount = 0; + while (DeviceNodeStrPtr != NULL && *DeviceNodeStrPtr != L'\0') { + GetNextParamStr (&DeviceNodeStrPtr); + DnsServerIpCount ++; + } + + free (DeviceNodeStr); + DeviceNodeStr = NULL; + + // + // One or more instances of the DNS server address in EFI_IP_ADDRESS, + // otherwise, NULL will be returned. + // + if (DnsServerIpCount == 0) { + return NULL; + } + + // + // Create the DNS DeviceNode. + // + DnsDeviceNodeLength = (UINT16) (sizeof (EFI_DEVICE_PATH_PROTOCOL) + sizeof (UINT8) + DnsServerIpCount * sizeof (EFI_IP_ADDRESS)); + DnsDeviceNode = (DNS_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_DNS_DP, + DnsDeviceNodeLength + ); + if (DnsDeviceNode == NULL) { + return NULL; + } + + // + // Confirm the DNS server address is IPv4 or IPv6 type. + // + DeviceNodeStrPtr = TextDeviceNode; + while (!IS_NULL (*DeviceNodeStrPtr)) { + if (*DeviceNodeStrPtr == L'.') { + DnsDeviceNode->IsIPv6 = 0x00; + break; + } + + if (*DeviceNodeStrPtr == L':') { + DnsDeviceNode->IsIPv6 = 0x01; + break; + } + + DeviceNodeStrPtr++; + } + + for (DnsServerIpIndex = 0; DnsServerIpIndex < DnsServerIpCount; DnsServerIpIndex++) { + DnsServerIp = GetNextParamStr (&TextDeviceNode); + if (DnsDeviceNode->IsIPv6 == 0x00) { + StrToIpv4Address (DnsServerIp, NULL, &(DnsDeviceNode->DnsServerIp[DnsServerIpIndex].v4), NULL); + } else { + StrToIpv6Address (DnsServerIp, NULL, &(DnsDeviceNode->DnsServerIp[DnsServerIpIndex].v6), NULL); + } + } + + return (EFI_DEVICE_PATH_PROTOCOL *) DnsDeviceNode; +} + +/** + Converts a text device path node to URI device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created URI device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextUri ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *UriStr; + UINTN UriLength; + URI_DEVICE_PATH *Uri; + + UriStr = GetNextParamStr (&TextDeviceNode); + UriLength = StrnLenS (UriStr, MAX_UINT16 - sizeof (URI_DEVICE_PATH)); + Uri = (URI_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_URI_DP, + (UINT16) (sizeof (URI_DEVICE_PATH) + UriLength) + ); + + while (UriLength-- != 0) { + Uri->Uri[UriLength] = (CHAR8) UriStr[UriLength]; + } + + return (EFI_DEVICE_PATH_PROTOCOL *) Uri; +} + +/** + Converts a media text device path node to media device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to media device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextMediaPath ( + CHAR16 *TextDeviceNode + ) +{ + return DevPathFromTextGenericPath (MEDIA_DEVICE_PATH, TextDeviceNode); +} + +/** + Converts a text device path node to HD device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created HD device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextHD ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *PartitionStr; + CHAR16 *TypeStr; + CHAR16 *SignatureStr; + CHAR16 *StartStr; + CHAR16 *SizeStr; + UINT32 Signature32; + HARDDRIVE_DEVICE_PATH *Hd; + + PartitionStr = GetNextParamStr (&TextDeviceNode); + TypeStr = GetNextParamStr (&TextDeviceNode); + SignatureStr = GetNextParamStr (&TextDeviceNode); + StartStr = GetNextParamStr (&TextDeviceNode); + SizeStr = GetNextParamStr (&TextDeviceNode); + Hd = (HARDDRIVE_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_HARDDRIVE_DP, + (UINT16) sizeof (HARDDRIVE_DEVICE_PATH) + ); + + Hd->PartitionNumber = (UINT32) Strtoi (PartitionStr); + + ZeroMem (Hd->Signature, 16); + Hd->MBRType = (UINT8) 0; + + if (StrCmp (TypeStr, L"MBR") == 0) { + Hd->SignatureType = SIGNATURE_TYPE_MBR; + Hd->MBRType = 0x01; + + Signature32 = (UINT32) Strtoi (SignatureStr); + memcpy (Hd->Signature, &Signature32, sizeof (UINT32)); + } else if (StrCmp (TypeStr, L"GPT") == 0) { + Hd->SignatureType = SIGNATURE_TYPE_GUID; + Hd->MBRType = 0x02; + + StrToGuid (SignatureStr, (EFI_GUID *) Hd->Signature); + } else { + Hd->SignatureType = (UINT8) Strtoi (TypeStr); + } + + Strtoi64 (StartStr, &Hd->PartitionStart); + Strtoi64 (SizeStr, &Hd->PartitionSize); + + return (EFI_DEVICE_PATH_PROTOCOL *) Hd; +} + +/** + Converts a text device path node to CDROM device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created CDROM device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextCDROM ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *EntryStr; + CHAR16 *StartStr; + CHAR16 *SizeStr; + CDROM_DEVICE_PATH *CDROMDevPath; + + EntryStr = GetNextParamStr (&TextDeviceNode); + StartStr = GetNextParamStr (&TextDeviceNode); + SizeStr = GetNextParamStr (&TextDeviceNode); + CDROMDevPath = (CDROM_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_CDROM_DP, + (UINT16) sizeof (CDROM_DEVICE_PATH) + ); + + CDROMDevPath->BootEntry = (UINT32) Strtoi (EntryStr); + Strtoi64 (StartStr, &CDROMDevPath->PartitionStart); + Strtoi64 (SizeStr, &CDROMDevPath->PartitionSize); + + return (EFI_DEVICE_PATH_PROTOCOL *) CDROMDevPath; +} + +/** + Converts a text device path node to Vendor-defined media device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Vendor-defined media device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVenMedia ( + CHAR16 *TextDeviceNode + ) +{ + return ConvertFromTextVendor ( + TextDeviceNode, + MEDIA_DEVICE_PATH, + MEDIA_VENDOR_DP + ); +} + +/** + Converts a text device path node to File device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created File device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFilePath ( + CHAR16 *TextDeviceNode + ) +{ + FILEPATH_DEVICE_PATH *File; + + File = (FILEPATH_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_FILEPATH_DP, + (UINT16) (sizeof (FILEPATH_DEVICE_PATH) + StrLen (TextDeviceNode) * 2) + ); + + StrCpyS (File->PathName, StrLen (TextDeviceNode) + 1, TextDeviceNode); + + return (EFI_DEVICE_PATH_PROTOCOL *) File; +} + +/** + Converts a text device path node to Media protocol device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Media protocol device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextMedia ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *GuidStr; + MEDIA_PROTOCOL_DEVICE_PATH *Media; + + GuidStr = GetNextParamStr (&TextDeviceNode); + Media = (MEDIA_PROTOCOL_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_PROTOCOL_DP, + (UINT16) sizeof (MEDIA_PROTOCOL_DEVICE_PATH) + ); + + StrToGuid (GuidStr, &Media->Protocol); + + return (EFI_DEVICE_PATH_PROTOCOL *) Media; +} + +/** + Converts a text device path node to firmware volume device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created firmware volume device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFv ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *GuidStr; + MEDIA_FW_VOL_DEVICE_PATH *Fv; + + GuidStr = GetNextParamStr (&TextDeviceNode); + Fv = (MEDIA_FW_VOL_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_PIWG_FW_VOL_DP, + (UINT16) sizeof (MEDIA_FW_VOL_DEVICE_PATH) + ); + + StrToGuid (GuidStr, &Fv->FvName); + + return (EFI_DEVICE_PATH_PROTOCOL *) Fv; +} + +/** + Converts a text device path node to firmware file device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created firmware file device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextFvFile ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *GuidStr; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFile; + + GuidStr = GetNextParamStr (&TextDeviceNode); + FvFile = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_PIWG_FW_FILE_DP, + (UINT16) sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + ); + + StrToGuid (GuidStr, &FvFile->FvFileName); + + return (EFI_DEVICE_PATH_PROTOCOL *) FvFile; +} + +/** + Converts a text device path node to text relative offset device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Text device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextRelativeOffsetRange ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *StartingOffsetStr; + CHAR16 *EndingOffsetStr; + MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset; + + StartingOffsetStr = GetNextParamStr (&TextDeviceNode); + EndingOffsetStr = GetNextParamStr (&TextDeviceNode); + Offset = (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_RELATIVE_OFFSET_RANGE_DP, + (UINT16) sizeof (MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH) + ); + + Strtoi64 (StartingOffsetStr, &Offset->StartingOffset); + Strtoi64 (EndingOffsetStr, &Offset->EndingOffset); + + return (EFI_DEVICE_PATH_PROTOCOL *) Offset; +} + +/** + Converts a text device path node to text ram disk device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Text device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextRamDisk ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *StartingAddrStr; + CHAR16 *EndingAddrStr; + CHAR16 *TypeGuidStr; + CHAR16 *InstanceStr; + MEDIA_RAM_DISK_DEVICE_PATH *RamDisk; + UINT64 StartingAddr; + UINT64 EndingAddr; + + StartingAddrStr = GetNextParamStr (&TextDeviceNode); + EndingAddrStr = GetNextParamStr (&TextDeviceNode); + InstanceStr = GetNextParamStr (&TextDeviceNode); + TypeGuidStr = GetNextParamStr (&TextDeviceNode); + RamDisk = (MEDIA_RAM_DISK_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_RAM_DISK_DP, + (UINT16) sizeof (MEDIA_RAM_DISK_DEVICE_PATH) + ); + + Strtoi64 (StartingAddrStr, &StartingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->StartingAddr[0]), StartingAddr); + Strtoi64 (EndingAddrStr, &EndingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->EndingAddr[0]), EndingAddr); + RamDisk->Instance = (UINT16) Strtoi (InstanceStr); + StrToGuid (TypeGuidStr, &RamDisk->TypeGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) RamDisk; +} + +/** + Converts a text device path node to text virtual disk device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Text device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVirtualDisk ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *StartingAddrStr; + CHAR16 *EndingAddrStr; + CHAR16 *InstanceStr; + MEDIA_RAM_DISK_DEVICE_PATH *RamDisk; + UINT64 StartingAddr; + UINT64 EndingAddr; + + StartingAddrStr = GetNextParamStr (&TextDeviceNode); + EndingAddrStr = GetNextParamStr (&TextDeviceNode); + InstanceStr = GetNextParamStr (&TextDeviceNode); + + RamDisk = (MEDIA_RAM_DISK_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_RAM_DISK_DP, + (UINT16) sizeof (MEDIA_RAM_DISK_DEVICE_PATH) + ); + + Strtoi64 (StartingAddrStr, &StartingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->StartingAddr[0]), StartingAddr); + Strtoi64 (EndingAddrStr, &EndingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->EndingAddr[0]), EndingAddr); + RamDisk->Instance = (UINT16) Strtoi (InstanceStr); + CopyGuid (&RamDisk->TypeGuid, &gEfiVirtualDiskGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) RamDisk; +} + +/** + Converts a text device path node to text virtual cd device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Text device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextVirtualCd ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *StartingAddrStr; + CHAR16 *EndingAddrStr; + CHAR16 *InstanceStr; + MEDIA_RAM_DISK_DEVICE_PATH *RamDisk; + UINT64 StartingAddr; + UINT64 EndingAddr; + + StartingAddrStr = GetNextParamStr (&TextDeviceNode); + EndingAddrStr = GetNextParamStr (&TextDeviceNode); + InstanceStr = GetNextParamStr (&TextDeviceNode); + + RamDisk = (MEDIA_RAM_DISK_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_RAM_DISK_DP, + (UINT16) sizeof (MEDIA_RAM_DISK_DEVICE_PATH) + ); + + Strtoi64 (StartingAddrStr, &StartingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->StartingAddr[0]), StartingAddr); + Strtoi64 (EndingAddrStr, &EndingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->EndingAddr[0]), EndingAddr); + RamDisk->Instance = (UINT16) Strtoi (InstanceStr); + CopyGuid (&RamDisk->TypeGuid, &gEfiVirtualCdGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) RamDisk; +} + +/** + Converts a text device path node to text persistent virtual disk device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Text device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPersistentVirtualDisk ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *StartingAddrStr; + CHAR16 *EndingAddrStr; + CHAR16 *InstanceStr; + MEDIA_RAM_DISK_DEVICE_PATH *RamDisk; + UINT64 StartingAddr; + UINT64 EndingAddr; + + StartingAddrStr = GetNextParamStr (&TextDeviceNode); + EndingAddrStr = GetNextParamStr (&TextDeviceNode); + InstanceStr = GetNextParamStr (&TextDeviceNode); + + RamDisk = (MEDIA_RAM_DISK_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_RAM_DISK_DP, + (UINT16) sizeof (MEDIA_RAM_DISK_DEVICE_PATH) + ); + + Strtoi64 (StartingAddrStr, &StartingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->StartingAddr[0]), StartingAddr); + Strtoi64 (EndingAddrStr, &EndingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->EndingAddr[0]), EndingAddr); + RamDisk->Instance = (UINT16) Strtoi (InstanceStr); + CopyGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualDiskGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) RamDisk; +} + +/** + Converts a text device path node to text persistent virtual cd device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created Text device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextPersistentVirtualCd ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *StartingAddrStr; + CHAR16 *EndingAddrStr; + CHAR16 *InstanceStr; + MEDIA_RAM_DISK_DEVICE_PATH *RamDisk; + UINT64 StartingAddr; + UINT64 EndingAddr; + + StartingAddrStr = GetNextParamStr (&TextDeviceNode); + EndingAddrStr = GetNextParamStr (&TextDeviceNode); + InstanceStr = GetNextParamStr (&TextDeviceNode); + + RamDisk = (MEDIA_RAM_DISK_DEVICE_PATH *) CreateDeviceNode ( + MEDIA_DEVICE_PATH, + MEDIA_RAM_DISK_DP, + (UINT16) sizeof (MEDIA_RAM_DISK_DEVICE_PATH) + ); + + Strtoi64 (StartingAddrStr, &StartingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->StartingAddr[0]), StartingAddr); + Strtoi64 (EndingAddrStr, &EndingAddr); + WriteUnaligned64 ((UINT64 *) &(RamDisk->EndingAddr[0]), EndingAddr); + RamDisk->Instance = (UINT16) Strtoi (InstanceStr); + CopyGuid (&RamDisk->TypeGuid, &gEfiPersistentVirtualCdGuid); + + return (EFI_DEVICE_PATH_PROTOCOL *) RamDisk; +} + +/** + Converts a BBS text device path node to BBS device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to BBS device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextBbsPath ( + CHAR16 *TextDeviceNode + ) +{ + return DevPathFromTextGenericPath (BBS_DEVICE_PATH, TextDeviceNode); +} + +/** + Converts a text device path node to BIOS Boot Specification device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created BIOS Boot Specification device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextBBS ( + CHAR16 *TextDeviceNode + ) +{ + CHAR16 *TypeStr; + CHAR16 *IdStr; + CHAR16 *FlagsStr; + CHAR8 *AsciiStr; + BBS_BBS_DEVICE_PATH *Bbs; + + TypeStr = GetNextParamStr (&TextDeviceNode); + IdStr = GetNextParamStr (&TextDeviceNode); + FlagsStr = GetNextParamStr (&TextDeviceNode); + Bbs = (BBS_BBS_DEVICE_PATH *) CreateDeviceNode ( + BBS_DEVICE_PATH, + BBS_BBS_DP, + (UINT16) (sizeof (BBS_BBS_DEVICE_PATH) + StrLen (IdStr)) + ); + + if (StrCmp (TypeStr, L"Floppy") == 0) { + Bbs->DeviceType = BBS_TYPE_FLOPPY; + } else if (StrCmp (TypeStr, L"HD") == 0) { + Bbs->DeviceType = BBS_TYPE_HARDDRIVE; + } else if (StrCmp (TypeStr, L"CDROM") == 0) { + Bbs->DeviceType = BBS_TYPE_CDROM; + } else if (StrCmp (TypeStr, L"PCMCIA") == 0) { + Bbs->DeviceType = BBS_TYPE_PCMCIA; + } else if (StrCmp (TypeStr, L"USB") == 0) { + Bbs->DeviceType = BBS_TYPE_USB; + } else if (StrCmp (TypeStr, L"Network") == 0) { + Bbs->DeviceType = BBS_TYPE_EMBEDDED_NETWORK; + } else { + Bbs->DeviceType = (UINT16) Strtoi (TypeStr); + } + + AsciiStr = Bbs->String; + StrToAscii (IdStr, &AsciiStr); + + Bbs->StatusFlag = (UINT16) Strtoi (FlagsStr); + + return (EFI_DEVICE_PATH_PROTOCOL *) Bbs; +} + +/** + Converts a text device path node to SATA device path structure. + + @param TextDeviceNode The input Text device path node. + + @return A pointer to the newly-created SATA device path structure. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DevPathFromTextSata ( + CHAR16 *TextDeviceNode + ) +{ + SATA_DEVICE_PATH *Sata; + CHAR16 *Param1; + CHAR16 *Param2; + CHAR16 *Param3; + + Param1 = GetNextParamStr (&TextDeviceNode); + Param2 = GetNextParamStr (&TextDeviceNode); + Param3 = GetNextParamStr (&TextDeviceNode); + + Sata = (SATA_DEVICE_PATH *) CreateDeviceNode ( + MESSAGING_DEVICE_PATH, + MSG_SATA_DP, + (UINT16) sizeof (SATA_DEVICE_PATH) + ); + Sata->HBAPortNumber = (UINT16) Strtoi (Param1); + + // + // According to UEFI spec, if PMPN is not provided, the default is 0xFFFF + // + if (*Param2 == L'\0' ) { + Sata->PortMultiplierPortNumber = 0xFFFF; + } else { + Sata->PortMultiplierPortNumber = (UINT16) Strtoi (Param2); + } + Sata->Lun = (UINT16) Strtoi (Param3); + + return (EFI_DEVICE_PATH_PROTOCOL *) Sata; +} + +DEVICE_PATH_FROM_TEXT_TABLE mUefiDevicePathLibDevPathFromTextTable[] = { + {L"Path", DevPathFromTextPath }, + + {L"HardwarePath", DevPathFromTextHardwarePath }, + {L"Pci", DevPathFromTextPci }, + {L"PcCard", DevPathFromTextPcCard }, + {L"MemoryMapped", DevPathFromTextMemoryMapped }, + {L"VenHw", DevPathFromTextVenHw }, + {L"Ctrl", DevPathFromTextCtrl }, + {L"BMC", DevPathFromTextBmc }, + + {L"AcpiPath", DevPathFromTextAcpiPath }, + {L"Acpi", DevPathFromTextAcpi }, + {L"PciRoot", DevPathFromTextPciRoot }, + {L"PcieRoot", DevPathFromTextPcieRoot }, + {L"Floppy", DevPathFromTextFloppy }, + {L"Keyboard", DevPathFromTextKeyboard }, + {L"Serial", DevPathFromTextSerial }, + {L"ParallelPort", DevPathFromTextParallelPort }, + {L"AcpiEx", DevPathFromTextAcpiEx }, + {L"AcpiExp", DevPathFromTextAcpiExp }, + {L"AcpiAdr", DevPathFromTextAcpiAdr }, + + {L"Msg", DevPathFromTextMsg }, + {L"Ata", DevPathFromTextAta }, + {L"Scsi", DevPathFromTextScsi }, + {L"Fibre", DevPathFromTextFibre }, + {L"FibreEx", DevPathFromTextFibreEx }, + {L"I1394", DevPathFromText1394 }, + {L"USB", DevPathFromTextUsb }, + {L"I2O", DevPathFromTextI2O }, + {L"Infiniband", DevPathFromTextInfiniband }, + {L"VenMsg", DevPathFromTextVenMsg }, + {L"VenPcAnsi", DevPathFromTextVenPcAnsi }, + {L"VenVt100", DevPathFromTextVenVt100 }, + {L"VenVt100Plus", DevPathFromTextVenVt100Plus }, + {L"VenUtf8", DevPathFromTextVenUtf8 }, + {L"UartFlowCtrl", DevPathFromTextUartFlowCtrl }, + {L"SAS", DevPathFromTextSAS }, +#ifndef VBOX + {L"SasEx", DevPathFromTextSasEx }, +#else + {L"NVMe", DevPathFromTextNVMe }, +#endif + {L"NVMe", DevPathFromTextNVMe }, + {L"UFS", DevPathFromTextUfs }, + {L"SD", DevPathFromTextSd }, + {L"eMMC", DevPathFromTextEmmc }, + {L"DebugPort", DevPathFromTextDebugPort }, + {L"MAC", DevPathFromTextMAC }, + {L"IPv4", DevPathFromTextIPv4 }, + {L"IPv6", DevPathFromTextIPv6 }, + {L"Uart", DevPathFromTextUart }, + {L"UsbClass", DevPathFromTextUsbClass }, + {L"UsbAudio", DevPathFromTextUsbAudio }, + {L"UsbCDCControl", DevPathFromTextUsbCDCControl }, + {L"UsbHID", DevPathFromTextUsbHID }, + {L"UsbImage", DevPathFromTextUsbImage }, + {L"UsbPrinter", DevPathFromTextUsbPrinter }, + {L"UsbMassStorage", DevPathFromTextUsbMassStorage }, + {L"UsbHub", DevPathFromTextUsbHub }, + {L"UsbCDCData", DevPathFromTextUsbCDCData }, + {L"UsbSmartCard", DevPathFromTextUsbSmartCard }, + {L"UsbVideo", DevPathFromTextUsbVideo }, + {L"UsbDiagnostic", DevPathFromTextUsbDiagnostic }, + {L"UsbWireless", DevPathFromTextUsbWireless }, + {L"UsbDeviceFirmwareUpdate", DevPathFromTextUsbDeviceFirmwareUpdate }, + {L"UsbIrdaBridge", DevPathFromTextUsbIrdaBridge }, + {L"UsbTestAndMeasurement", DevPathFromTextUsbTestAndMeasurement }, + {L"UsbWwid", DevPathFromTextUsbWwid }, + {L"Unit", DevPathFromTextUnit }, + {L"iSCSI", DevPathFromTextiSCSI }, + {L"Vlan", DevPathFromTextVlan }, + {L"Dns", DevPathFromTextDns }, + {L"Uri", DevPathFromTextUri }, + {L"Bluetooth", DevPathFromTextBluetooth }, + {L"Wi-Fi", DevPathFromTextWiFi }, + {L"BluetoothLE", DevPathFromTextBluetoothLE }, + {L"MediaPath", DevPathFromTextMediaPath }, + {L"HD", DevPathFromTextHD }, + {L"CDROM", DevPathFromTextCDROM }, + {L"VenMedia", DevPathFromTextVenMedia }, + {L"Media", DevPathFromTextMedia }, + {L"Fv", DevPathFromTextFv }, + {L"FvFile", DevPathFromTextFvFile }, + {L"Offset", DevPathFromTextRelativeOffsetRange }, + {L"RamDisk", DevPathFromTextRamDisk }, + {L"VirtualDisk", DevPathFromTextVirtualDisk }, + {L"VirtualCD", DevPathFromTextVirtualCd }, + {L"PersistentVirtualDisk", DevPathFromTextPersistentVirtualDisk }, + {L"PersistentVirtualCD", DevPathFromTextPersistentVirtualCd }, + + {L"BbsPath", DevPathFromTextBbsPath }, + {L"BBS", DevPathFromTextBBS }, + {L"Sata", DevPathFromTextSata }, + {NULL, NULL} +}; + +/** + Convert text to the binary representation of a device node. + + @param TextDeviceNode TextDeviceNode points to the text representation of a device + node. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was + insufficient memory or text unsupported. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibConvertTextToDeviceNode ( + CONST CHAR16 *TextDeviceNode + ) +{ + DEVICE_PATH_FROM_TEXT FromText; + CHAR16 *ParamStr; + EFI_DEVICE_PATH_PROTOCOL *DeviceNode; + CHAR16 *DeviceNodeStr; + UINTN Index; + + if ((TextDeviceNode == NULL) || (IS_NULL (*TextDeviceNode))) { + return NULL; + } + + ParamStr = NULL; + FromText = NULL; + DeviceNodeStr = UefiDevicePathLibStrDuplicate (TextDeviceNode); + ASSERT (DeviceNodeStr != NULL); + + for (Index = 0; mUefiDevicePathLibDevPathFromTextTable[Index].Function != NULL; Index++) { + ParamStr = GetParamByNodeName (DeviceNodeStr, mUefiDevicePathLibDevPathFromTextTable[Index].DevicePathNodeText); + if (ParamStr != NULL) { + FromText = mUefiDevicePathLibDevPathFromTextTable[Index].Function; + break; + } + } + + if (FromText == NULL) { + // + // A file path + // + FromText = DevPathFromTextFilePath; + DeviceNode = FromText (DeviceNodeStr); + // + // According to above logic, if 'FromText' is NULL in the 'if' statement, + // then 'ParamStr' must be NULL as well. No memory allocation has been made + // in this case. + // + // The below check is for addressing a false positive potential memory leak + // issue raised from static analysis. + // + if (ParamStr != NULL) { + free (ParamStr); + } + } else { + DeviceNode = FromText (ParamStr); + free (ParamStr); + } + + free (DeviceNodeStr); + + return DeviceNode; +} + +/** + Convert text to the binary representation of a device path. + + + @param TextDevicePath TextDevicePath points to the text representation of a device + path. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or + there was insufficient memory. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibConvertTextToDevicePath ( + CONST CHAR16 *TextDevicePath + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DeviceNode; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + CHAR16 *DevicePathStr; + CHAR16 *Str; + CHAR16 *DeviceNodeStr; + BOOLEAN IsInstanceEnd; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + if ((TextDevicePath == NULL) || (IS_NULL (*TextDevicePath))) { + return NULL; + } + + DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH); + ASSERT (DevicePath != NULL); + SetDevicePathEndNode (DevicePath); + + DevicePathStr = UefiDevicePathLibStrDuplicate (TextDevicePath); + + Str = DevicePathStr; + while ((DeviceNodeStr = GetNextDeviceNodeStr (&Str, &IsInstanceEnd)) != NULL) { + DeviceNode = UefiDevicePathLibConvertTextToDeviceNode (DeviceNodeStr); + + NewDevicePath = AppendDevicePathNode (DevicePath, DeviceNode); + free (DevicePath); + free (DeviceNode); + DevicePath = NewDevicePath; + + if (IsInstanceEnd) { + DeviceNode = (EFI_DEVICE_PATH_PROTOCOL *) AllocatePool (END_DEVICE_PATH_LENGTH); + ASSERT (DeviceNode != NULL); + SetDevicePathEndNode (DeviceNode); + DeviceNode->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; + + NewDevicePath = AppendDevicePathNode (DevicePath, DeviceNode); + free (DevicePath); + free (DeviceNode); + DevicePath = NewDevicePath; + } + } + + free (DevicePathStr); + return DevicePath; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/DevicePathUtilities.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/DevicePathUtilities.c new file mode 100644 index 00000000..d4b63271 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/DevicePathUtilities.c @@ -0,0 +1,868 @@ +/** @file + Device Path services. The thing to remember is device paths are built out of + nodes. The device path is terminated by an end node that is length + sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL) + all over this file. + + The only place where multi-instance device paths are supported is in + environment variables. Multi-instance device paths should never be placed + on a Handle. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "UefiDevicePathLib.h" +#include + +// +// Template for an end-of-device path node. +// +CONST EFI_DEVICE_PATH_PROTOCOL mUefiDevicePathLibEndDevicePath = { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + END_DEVICE_PATH_LENGTH, + 0 + } +}; + +/** + Determine whether a given device path is valid. + + @param DevicePath A pointer to a device path data structure. + @param MaxSize The maximum size of the device path data structure. + + @retval TRUE DevicePath is valid. + @retval FALSE DevicePath is NULL. + @retval FALSE Maxsize is less than sizeof(EFI_DEVICE_PATH_PROTOCOL). + @retval FALSE The length of any node node in the DevicePath is less + than sizeof (EFI_DEVICE_PATH_PROTOCOL). + @retval FALSE If MaxSize is not zero, the size of the DevicePath + exceeds MaxSize. + @retval FALSE If PcdMaximumDevicePathNodeCount is not zero, the node + count of the DevicePath exceeds PcdMaximumDevicePathNodeCount. +**/ +BOOLEAN +IsDevicePathValid ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + UINTN MaxSize + ) +{ + UINTN Count; + UINTN Size; + UINTN NodeLength; + + // + // Validate the input whether exists and its size big enough to touch the first node + // + if (DevicePath == NULL || (MaxSize > 0 && MaxSize < END_DEVICE_PATH_LENGTH)) { + return FALSE; + } + + if (MaxSize == 0) { + MaxSize = MAX_UINT32; + } + + for (Count = 0, Size = 0; !IsDevicePathEnd (DevicePath); DevicePath = NextDevicePathNode (DevicePath)) { + NodeLength = DevicePathNodeLength (DevicePath); + if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { + return FALSE; + } + + if (NodeLength > MAX_UINT32 - Size) { + return FALSE; + } + Size += NodeLength; + + // + // Validate next node before touch it. + // + if (Size > MaxSize - END_DEVICE_PATH_LENGTH ) { + return FALSE; + } + + Count++; + if (Count >= MAX_DEVICE_PATH_NODE_COUNT) { + return FALSE; + } + + } + + // + // Only return TRUE when the End Device Path node is valid. + // + return (BOOLEAN) (DevicePathNodeLength (DevicePath) == END_DEVICE_PATH_LENGTH); +} + + +/** + Returns the Type field of a device path node. + + Returns the Type field of the device path node specified by Node. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return The Type field of the device path node specified by Node. + +**/ +UINT8 +DevicePathType ( + CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return ((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Type; +} + +/** + Returns the SubType field of a device path node. + + Returns the SubType field of the device path node specified by Node. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return The SubType field of the device path node specified by Node. + +**/ +UINT8 +DevicePathSubType ( + CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return ((EFI_DEVICE_PATH_PROTOCOL *)(Node))->SubType; +} + +/** + Returns the 16-bit Length field of a device path node. + + Returns the 16-bit Length field of the device path node specified by Node. + Node is not required to be aligned on a 16-bit boundary, so it is recommended + that a function such as ReadUnaligned16() be used to extract the contents of + the Length field. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return The 16-bit Length field of the device path node specified by Node. + +**/ +UINTN +DevicePathNodeLength ( + CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return ReadUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0]); +} + +/** + Returns a pointer to the next node in a device path. + + Returns a pointer to the device path node that follows the device path node + specified by Node. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @return a pointer to the device path node that follows the device path node + specified by Node. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +NextDevicePathNode ( + CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return (EFI_DEVICE_PATH_PROTOCOL *)((UINT8 *)(Node) + DevicePathNodeLength(Node)); +} + +/** + Determines if a device path node is an end node of a device path. + This includes nodes that are the end of a device path instance and nodes that + are the end of an entire device path. + + Determines if the device path node specified by Node is an end node of a device path. + This includes nodes that are the end of a device path instance and nodes that are the + end of an entire device path. If Node represents an end node of a device path, + then TRUE is returned. Otherwise, FALSE is returned. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @retval TRUE The device path node specified by Node is an end node of a + device path. + @retval FALSE The device path node specified by Node is not an end node of + a device path. + +**/ +BOOLEAN +IsDevicePathEndType ( + CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return (BOOLEAN) (DevicePathType (Node) == END_DEVICE_PATH_TYPE); +} + +/** + Determines if a device path node is an end node of an entire device path. + + Determines if a device path node specified by Node is an end node of an entire + device path. If Node represents the end of an entire device path, then TRUE is + returned. Otherwise, FALSE is returned. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @retval TRUE The device path node specified by Node is the end of an entire + device path. + @retval FALSE The device path node specified by Node is not the end of an + entire device path. + +**/ +BOOLEAN +IsDevicePathEnd ( + CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_ENTIRE_DEVICE_PATH_SUBTYPE); +} + +/** + Determines if a device path node is an end node of a device path instance. + + Determines if a device path node specified by Node is an end node of a device + path instance. If Node represents the end of a device path instance, then TRUE + is returned. Otherwise, FALSE is returned. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + + @retval TRUE The device path node specified by Node is the end of a device + path instance. + @retval FALSE The device path node specified by Node is not the end of a + device path instance. + +**/ +BOOLEAN +IsDevicePathEndInstance ( + CONST VOID *Node + ) +{ + ASSERT (Node != NULL); + return (BOOLEAN) (IsDevicePathEndType (Node) && DevicePathSubType(Node) == END_INSTANCE_DEVICE_PATH_SUBTYPE); +} + +/** + Sets the length, in bytes, of a device path node. + + Sets the length of the device path node specified by Node to the value specified + by NodeLength. NodeLength is returned. Node is not required to be aligned on + a 16-bit boundary, so it is recommended that a function such as WriteUnaligned16() + be used to set the contents of the Length field. + + If Node is NULL, then ASSERT(). + If NodeLength >= SIZE_64KB, then ASSERT(). + If NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL), then ASSERT(). + + @param Node A pointer to a device path node data structure. + @param Length The length, in bytes, of the device path node. + + @return Length + +**/ +UINT16 +SetDevicePathNodeLength ( + VOID *Node, + UINTN Length + ) +{ + ASSERT (Node != NULL); + ASSERT ((Length >= sizeof (EFI_DEVICE_PATH_PROTOCOL)) && (Length < SIZE_64KB)); + return WriteUnaligned16 ((UINT16 *)&((EFI_DEVICE_PATH_PROTOCOL *)(Node))->Length[0], (UINT16)(Length)); +} + +/** + Fills in all the fields of a device path node that is the end of an entire device path. + + Fills in all the fields of a device path node specified by Node so Node represents + the end of an entire device path. The Type field of Node is set to + END_DEVICE_PATH_TYPE, the SubType field of Node is set to + END_ENTIRE_DEVICE_PATH_SUBTYPE, and the Length field of Node is set to + END_DEVICE_PATH_LENGTH. Node is not required to be aligned on a 16-bit boundary, + so it is recommended that a function such as WriteUnaligned16() be used to set + the contents of the Length field. + + If Node is NULL, then ASSERT(). + + @param Node A pointer to a device path node data structure. + +**/ +VOID +SetDevicePathEndNode ( + VOID *Node + ) +{ + ASSERT (Node != NULL); + memcpy (Node, &mUefiDevicePathLibEndDevicePath, sizeof (mUefiDevicePathLibEndDevicePath)); +} + +/** + Returns the size of a device path in bytes. + + This function returns the size, in bytes, of the device path data structure + specified by DevicePath including the end of device path node. + If DevicePath is NULL or invalid, then 0 is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval 0 If DevicePath is NULL or invalid. + @retval Others The size of a device path in bytes. + +**/ +UINTN +UefiDevicePathLibGetDevicePathSize ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + CONST EFI_DEVICE_PATH_PROTOCOL *Start; + + if (DevicePath == NULL) { + return 0; + } + + if (!IsDevicePathValid (DevicePath, 0)) { + return 0; + } + + // + // Search for the end of the device path structure + // + Start = DevicePath; + while (!IsDevicePathEnd (DevicePath)) { + DevicePath = NextDevicePathNode (DevicePath); + } + + // + // Compute the size and add back in the size of the end device path structure + // + return ((UINTN) DevicePath - (UINTN) Start) + DevicePathNodeLength (DevicePath); +} + +/** + Creates a new copy of an existing device path. + + This function allocates space for a new copy of the device path specified by DevicePath. + If DevicePath is NULL, then NULL is returned. If the memory is successfully + allocated, then the contents of DevicePath are copied to the newly allocated + buffer, and a pointer to that buffer is returned. Otherwise, NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + + @retval NULL DevicePath is NULL or invalid. + @retval Others A pointer to the duplicated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibDuplicateDevicePath ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + UINTN Size; + + // + // Compute the size + // + Size = GetDevicePathSize (DevicePath); + if (Size == 0) { + return NULL; + } + + // + // Allocate space for duplicate device path + // + + return AllocateCopyPool (Size, DevicePath); +} + +/** + Creates a new device path by appending a second device path to a first device path. + + This function creates a new device path by appending a copy of SecondDevicePath + to a copy of FirstDevicePath in a newly allocated buffer. Only the end-of-device-path + device node from SecondDevicePath is retained. The newly created device path is + returned. If FirstDevicePath is NULL, then it is ignored, and a duplicate of + SecondDevicePath is returned. If SecondDevicePath is NULL, then it is ignored, + and a duplicate of FirstDevicePath is returned. If both FirstDevicePath and + SecondDevicePath are NULL, then a copy of an end-of-device-path is returned. + + If there is not enough memory for the newly allocated buffer, then NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param FirstDevicePath A pointer to a device path data structure. + @param SecondDevicePath A pointer to a device path data structure. + + @retval NULL If there is not enough memory for the newly allocated buffer. + @retval NULL If FirstDevicePath or SecondDevicePath is invalid. + @retval Others A pointer to the new device path if success. + Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibAppendDevicePath ( + CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, + CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath + ) +{ + UINTN Size; + UINTN Size1; + UINTN Size2; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath2; + + // + // If there's only 1 path, just duplicate it. + // + if (FirstDevicePath == NULL) { + return DuplicateDevicePath ((SecondDevicePath != NULL) ? SecondDevicePath : &mUefiDevicePathLibEndDevicePath); + } + + if (SecondDevicePath == NULL) { + return DuplicateDevicePath (FirstDevicePath); + } + + if (!IsDevicePathValid (FirstDevicePath, 0) || !IsDevicePathValid (SecondDevicePath, 0)) { + return NULL; + } + + // + // Allocate space for the combined device path. It only has one end node of + // length EFI_DEVICE_PATH_PROTOCOL. + // + Size1 = GetDevicePathSize (FirstDevicePath); + Size2 = GetDevicePathSize (SecondDevicePath); + Size = Size1 + Size2 - END_DEVICE_PATH_LENGTH; + + NewDevicePath = AllocatePool (Size); + + if (NewDevicePath != NULL) { + NewDevicePath = memcpy (NewDevicePath, FirstDevicePath, Size1); + // + // Over write FirstDevicePath EndNode and do the copy + // + DevicePath2 = (EFI_DEVICE_PATH_PROTOCOL *) ((CHAR8 *) NewDevicePath + + (Size1 - END_DEVICE_PATH_LENGTH)); + memcpy (DevicePath2, SecondDevicePath, Size2); + } + + return NewDevicePath; +} + +/** + Creates a new path by appending the device node to the device path. + + This function creates a new device path by appending a copy of the device node + specified by DevicePathNode to a copy of the device path specified by DevicePath + in an allocated buffer. The end-of-device-path device node is moved after the + end of the appended device node. + If DevicePathNode is NULL then a copy of DevicePath is returned. + If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device + path device node is returned. + If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path + device node is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathNode A pointer to a single device path node. + + @retval NULL If there is not enough memory for the new device path. + @retval Others A pointer to the new device path if success. + A copy of DevicePathNode followed by an end-of-device-path node + if both FirstDevicePath and SecondDevicePath are NULL. + A copy of an end-of-device-path node if both FirstDevicePath + and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibAppendDevicePathNode ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode + ) +{ + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + EFI_DEVICE_PATH_PROTOCOL *NextNode; + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + UINTN NodeLength; + + if (DevicePathNode == NULL) { + return DuplicateDevicePath ((DevicePath != NULL) ? DevicePath : &mUefiDevicePathLibEndDevicePath); + } + // + // Build a Node that has a terminator on it + // + NodeLength = DevicePathNodeLength (DevicePathNode); + + TempDevicePath = AllocatePool (NodeLength + END_DEVICE_PATH_LENGTH); + if (TempDevicePath == NULL) { + return NULL; + } + TempDevicePath = memcpy (TempDevicePath, DevicePathNode, NodeLength); + // + // Add and end device path node to convert Node to device path + // + NextNode = NextDevicePathNode (TempDevicePath); + SetDevicePathEndNode (NextNode); + // + // Append device paths + // + NewDevicePath = AppendDevicePath (DevicePath, TempDevicePath); + + free (TempDevicePath); + + return NewDevicePath; +} + +/** + Creates a new device path by appending the specified device path instance to the specified device + path. + + This function creates a new device path by appending a copy of the device path + instance specified by DevicePathInstance to a copy of the device path specified + by DevicePath in a allocated buffer. + The end-of-device-path device node is moved after the end of the appended device + path instance and a new end-of-device-path-instance node is inserted between. + If DevicePath is NULL, then a copy if DevicePathInstance is returned. + If DevicePathInstance is NULL, then NULL is returned. + If DevicePath or DevicePathInstance is invalid, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathInstance A pointer to a device path instance. + + @return A pointer to the new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibAppendDevicePathInstance ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance + ) +{ + EFI_DEVICE_PATH_PROTOCOL *NewDevicePath; + EFI_DEVICE_PATH_PROTOCOL *TempDevicePath; + UINTN SrcSize; + UINTN InstanceSize; + + if (DevicePath == NULL) { + return DuplicateDevicePath (DevicePathInstance); + } + + if (DevicePathInstance == NULL) { + return NULL; + } + + if (!IsDevicePathValid (DevicePath, 0) || !IsDevicePathValid (DevicePathInstance, 0)) { + return NULL; + } + + SrcSize = GetDevicePathSize (DevicePath); + InstanceSize = GetDevicePathSize (DevicePathInstance); + + NewDevicePath = AllocatePool (SrcSize + InstanceSize); + if (NewDevicePath != NULL) { + + TempDevicePath = memcpy (NewDevicePath, DevicePath, SrcSize);; + + while (!IsDevicePathEnd (TempDevicePath)) { + TempDevicePath = NextDevicePathNode (TempDevicePath); + } + + TempDevicePath->SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE; + TempDevicePath = NextDevicePathNode (TempDevicePath); + memcpy (TempDevicePath, DevicePathInstance, InstanceSize); + } + + return NewDevicePath; +} + +/** + Creates a copy of the current device path instance and returns a pointer to the next device path + instance. + + This function creates a copy of the current device path instance. It also updates + DevicePath to point to the next device path instance in the device path (or NULL + if no more) and updates Size to hold the size of the device path instance copy. + If DevicePath is NULL, then NULL is returned. + If DevicePath points to a invalid device path, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + If Size is NULL, then ASSERT(). + + @param DevicePath On input, this holds the pointer to the current + device path instance. On output, this holds + the pointer to the next device path instance + or NULL if there are no more device path + instances in the device path pointer to a + device path data structure. + @param Size On output, this holds the size of the device + path instance, in bytes or zero, if DevicePath + is NULL. + + @return A pointer to the current device path instance. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibGetNextDevicePathInstance ( + EFI_DEVICE_PATH_PROTOCOL **DevicePath, + UINTN *Size + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevPath; + EFI_DEVICE_PATH_PROTOCOL *ReturnValue; + UINT8 Temp; + + ASSERT (Size != NULL); + + if (DevicePath == NULL || *DevicePath == NULL) { + *Size = 0; + return NULL; + } + + if (!IsDevicePathValid (*DevicePath, 0)) { + return NULL; + } + + // + // Find the end of the device path instance + // + DevPath = *DevicePath; + while (!IsDevicePathEndType (DevPath)) { + DevPath = NextDevicePathNode (DevPath); + } + + // + // Compute the size of the device path instance + // + *Size = ((UINTN) DevPath - (UINTN) (*DevicePath)) + sizeof (EFI_DEVICE_PATH_PROTOCOL); + + // + // Make a copy and return the device path instance + // + Temp = DevPath->SubType; + DevPath->SubType = END_ENTIRE_DEVICE_PATH_SUBTYPE; + ReturnValue = DuplicateDevicePath (*DevicePath); + DevPath->SubType = Temp; + + // + // If DevPath is the end of an entire device path, then another instance + // does not follow, so *DevicePath is set to NULL. + // + if (DevicePathSubType (DevPath) == END_ENTIRE_DEVICE_PATH_SUBTYPE) { + *DevicePath = NULL; + } else { + *DevicePath = NextDevicePathNode (DevPath); + } + + return ReturnValue; +} + +/** + Creates a device node. + + This function creates a new device node in a newly allocated buffer of size + NodeLength and initializes the device path node header with NodeType and NodeSubType. + The new device path node is returned. + If NodeLength is smaller than a device path header, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param NodeType The device node type for the new device node. + @param NodeSubType The device node sub-type for the new device node. + @param NodeLength The length of the new device node. + + @return The new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibCreateDeviceNode ( + UINT8 NodeType, + UINT8 NodeSubType, + UINT16 NodeLength + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + if (NodeLength < sizeof (EFI_DEVICE_PATH_PROTOCOL)) { + // + // NodeLength is less than the size of the header. + // + return NULL; + } + + DevicePath = AllocateZeroPool (NodeLength); + if (DevicePath != NULL) { + DevicePath->Type = NodeType; + DevicePath->SubType = NodeSubType; + SetDevicePathNodeLength (DevicePath, NodeLength); + } + + return DevicePath; +} + +/** + Determines if a device path is single or multi-instance. + + This function returns TRUE if the device path specified by DevicePath is + multi-instance. + Otherwise, FALSE is returned. + If DevicePath is NULL or invalid, then FALSE is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval TRUE DevicePath is multi-instance. + @retval FALSE DevicePath is not multi-instance, or DevicePath + is NULL or invalid. + +**/ +BOOLEAN +UefiDevicePathLibIsDevicePathMultiInstance ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + CONST EFI_DEVICE_PATH_PROTOCOL *Node; + + if (DevicePath == NULL) { + return FALSE; + } + + if (!IsDevicePathValid (DevicePath, 0)) { + return FALSE; + } + + Node = DevicePath; + while (!IsDevicePathEnd (Node)) { + if (IsDevicePathEndInstance (Node)) { + return TRUE; + } + + Node = NextDevicePathNode (Node); + } + + return FALSE; +} + + +/** + Retrieves the device path protocol from a handle. + + This function returns the device path protocol from the handle specified by Handle. + If Handle is NULL or Handle does not contain a device path protocol, then NULL + is returned. + + @param Handle The handle from which to retrieve the device + path protocol. + + @return The device path protocol from the handle specified by Handle. + +**/ +/* +EFI_DEVICE_PATH_PROTOCOL * +DevicePathFromHandle ( + EFI_HANDLE Handle + ) +{ + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_STATUS Status; + + Status = gBS->HandleProtocol ( + Handle, + &gEfiDevicePathProtocolGuid, + (VOID *) &DevicePath + ); + if (EFI_ERROR (Status)) { + DevicePath = NULL; + } + return DevicePath; +} +*/ +/** + Allocates a device path for a file and appends it to an existing device path. + + If Device is a valid device handle that contains a device path protocol, then a device path for + the file specified by FileName is allocated and appended to the device path associated with the + handle Device. The allocated device path is returned. If Device is NULL or Device is a handle + that does not support the device path protocol, then a device path containing a single device + path node for the file specified by FileName is allocated and returned. + The memory for the new device path is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + If FileName is NULL, then ASSERT(). + If FileName is not aligned on a 16-bit boundary, then ASSERT(). + + @param Device A pointer to a device handle. This parameter + is optional and may be NULL. + @param FileName A pointer to a Null-terminated Unicode string. + + @return The allocated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +FileDevicePath ( + EFI_HANDLE Device, OPTIONAL + CONST CHAR16 *FileName + ) +{ + UINTN Size; + FILEPATH_DEVICE_PATH *FilePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *FileDevicePath; + + DevicePath = NULL; + + Size = StrSize (FileName); + FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH); + if (FileDevicePath != NULL) { + FilePath = (FILEPATH_DEVICE_PATH *) FileDevicePath; + FilePath->Header.Type = MEDIA_DEVICE_PATH; + FilePath->Header.SubType = MEDIA_FILEPATH_DP; + memcpy (&FilePath->PathName, FileName, Size); + SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH); + SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header)); + + //if (Device != NULL) { + // DevicePath = DevicePathFromHandle (Device); + //} + + DevicePath = AppendDevicePath (DevicePath, FileDevicePath); + free (FileDevicePath); + } + + return DevicePath; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/GNUmakefile new file mode 100644 index 00000000..693eed53 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/GNUmakefile @@ -0,0 +1,24 @@ +## @file +# GNU/Linux makefile for 'DevicePath' module build. +# +# Copyright (c) 2017, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +ARCH ?= IA32 +MAKEROOT ?= .. + +APPNAME = DevicePath + +OBJECTS = DevicePath.o UefiDevicePathLib.o DevicePathFromText.o DevicePathUtilities.o + +include $(MAKEROOT)/Makefiles/app.makefile + +LIBS = -lCommon +ifeq ($(CYGWIN), CYGWIN) + LIBS += -L/lib/e2fsprogs -luuid +endif + +ifeq ($(LINUX), Linux) + LIBS += -luuid +endif + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/Makefile new file mode 100644 index 00000000..47c99140 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/Makefile @@ -0,0 +1,18 @@ +## @file +# Windows makefile for 'DevicePath' module build. +# +# Copyright (c) 2017, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +!INCLUDE ..\Makefiles\ms.common + +APPNAME = DevicePath + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = DevicePath.obj UefiDevicePathLib.obj DevicePathFromText.obj DevicePathUtilities.obj + +#CFLAGS = $(CFLAGS) /nodefaultlib:libc.lib + +!INCLUDE ..\Makefiles\ms.app + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/UefiDevicePathLib.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/UefiDevicePathLib.c new file mode 100644 index 00000000..3ee51bb3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/UefiDevicePathLib.c @@ -0,0 +1,292 @@ +/** @file + Device Path services. The thing to remember is device paths are built out of + nodes. The device path is terminated by an end node that is length + sizeof(EFI_DEVICE_PATH_PROTOCOL). That would be why there is sizeof(EFI_DEVICE_PATH_PROTOCOL) + all over this file. + + The only place where multi-instance device paths are supported is in + environment variables. Multi-instance device paths should never be placed + on a Handle. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + + +#include "UefiDevicePathLib.h" + +/** + Returns the size of a device path in bytes. + + This function returns the size, in bytes, of the device path data structure + specified by DevicePath including the end of device path node. + If DevicePath is NULL or invalid, then 0 is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval 0 If DevicePath is NULL or invalid. + @retval Others The size of a device path in bytes. + +**/ +UINTN +GetDevicePathSize ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + return UefiDevicePathLibGetDevicePathSize (DevicePath); +} + +/** + Creates a new copy of an existing device path. + + This function allocates space for a new copy of the device path specified by DevicePath. + If DevicePath is NULL, then NULL is returned. If the memory is successfully + allocated, then the contents of DevicePath are copied to the newly allocated + buffer, and a pointer to that buffer is returned. Otherwise, NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + + @retval NULL DevicePath is NULL or invalid. + @retval Others A pointer to the duplicated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +DuplicateDevicePath ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + return UefiDevicePathLibDuplicateDevicePath (DevicePath); +} + +/** + Creates a new device path by appending a second device path to a first device path. + + This function creates a new device path by appending a copy of SecondDevicePath + to a copy of FirstDevicePath in a newly allocated buffer. Only the end-of-device-path + device node from SecondDevicePath is retained. The newly created device path is + returned. If FirstDevicePath is NULL, then it is ignored, and a duplicate of + SecondDevicePath is returned. If SecondDevicePath is NULL, then it is ignored, + and a duplicate of FirstDevicePath is returned. If both FirstDevicePath and + SecondDevicePath are NULL, then a copy of an end-of-device-path is returned. + + If there is not enough memory for the newly allocated buffer, then NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param FirstDevicePath A pointer to a device path data structure. + @param SecondDevicePath A pointer to a device path data structure. + + @retval NULL If there is not enough memory for the newly allocated buffer. + @retval NULL If FirstDevicePath or SecondDevicePath is invalid. + @retval Others A pointer to the new device path if success. + Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +AppendDevicePath ( + CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, OPTIONAL + CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL + ) +{ + return UefiDevicePathLibAppendDevicePath (FirstDevicePath, SecondDevicePath); +} + +/** + Creates a new path by appending the device node to the device path. + + This function creates a new device path by appending a copy of the device node + specified by DevicePathNode to a copy of the device path specified by DevicePath + in an allocated buffer. The end-of-device-path device node is moved after the + end of the appended device node. + If DevicePathNode is NULL then a copy of DevicePath is returned. + If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device + path device node is returned. + If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path + device node is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathNode A pointer to a single device path node. + + @retval NULL If there is not enough memory for the new device path. + @retval Others A pointer to the new device path if success. + A copy of DevicePathNode followed by an end-of-device-path node + if both FirstDevicePath and SecondDevicePath are NULL. + A copy of an end-of-device-path node if both FirstDevicePath + and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +AppendDevicePathNode ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL + ) +{ + return UefiDevicePathLibAppendDevicePathNode (DevicePath, DevicePathNode); +} + +/** + Creates a new device path by appending the specified device path instance to the specified device + path. + + This function creates a new device path by appending a copy of the device path + instance specified by DevicePathInstance to a copy of the device path specified + by DevicePath in a allocated buffer. + The end-of-device-path device node is moved after the end of the appended device + path instance and a new end-of-device-path-instance node is inserted between. + If DevicePath is NULL, then a copy if DevicePathInstance is returned. + If DevicePathInstance is NULL, then NULL is returned. + If DevicePath or DevicePathInstance is invalid, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathInstance A pointer to a device path instance. + + @return A pointer to the new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +AppendDevicePathInstance ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL + ) +{ + return UefiDevicePathLibAppendDevicePathInstance (DevicePath, DevicePathInstance); +} + +/** + Creates a copy of the current device path instance and returns a pointer to the next device path + instance. + + This function creates a copy of the current device path instance. It also updates + DevicePath to point to the next device path instance in the device path (or NULL + if no more) and updates Size to hold the size of the device path instance copy. + If DevicePath is NULL, then NULL is returned. + If DevicePath points to a invalid device path, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + If Size is NULL, then ASSERT(). + + @param DevicePath On input, this holds the pointer to the current + device path instance. On output, this holds + the pointer to the next device path instance + or NULL if there are no more device path + instances in the device path pointer to a + device path data structure. + @param Size On output, this holds the size of the device + path instance, in bytes or zero, if DevicePath + is NULL. + + @return A pointer to the current device path instance. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +GetNextDevicePathInstance ( + EFI_DEVICE_PATH_PROTOCOL **DevicePath, + UINTN *Size + ) +{ + return UefiDevicePathLibGetNextDevicePathInstance (DevicePath, Size); +} + +/** + Creates a device node. + + This function creates a new device node in a newly allocated buffer of size + NodeLength and initializes the device path node header with NodeType and NodeSubType. + The new device path node is returned. + If NodeLength is smaller than a device path header, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param NodeType The device node type for the new device node. + @param NodeSubType The device node sub-type for the new device node. + @param NodeLength The length of the new device node. + + @return The new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +CreateDeviceNode ( + UINT8 NodeType, + UINT8 NodeSubType, + UINT16 NodeLength + ) +{ + return UefiDevicePathLibCreateDeviceNode (NodeType, NodeSubType, NodeLength); +} + +/** + Determines if a device path is single or multi-instance. + + This function returns TRUE if the device path specified by DevicePath is + multi-instance. + Otherwise, FALSE is returned. + If DevicePath is NULL or invalid, then FALSE is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval TRUE DevicePath is multi-instance. + @retval FALSE DevicePath is not multi-instance, or DevicePath + is NULL or invalid. + +**/ +BOOLEAN +IsDevicePathMultiInstance ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + return UefiDevicePathLibIsDevicePathMultiInstance (DevicePath); +} + +/** + Convert text to the binary representation of a device node. + + @param TextDeviceNode TextDeviceNode points to the text representation of a device + node. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was + insufficient memory or text unsupported. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +ConvertTextToDeviceNode ( + CONST CHAR16 *TextDeviceNode + ) +{ + return UefiDevicePathLibConvertTextToDeviceNode (TextDeviceNode); +} + +/** + Convert text to the binary representation of a device path. + + + @param TextDevicePath TextDevicePath points to the text representation of a device + path. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or + there was insufficient memory. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +ConvertTextToDevicePath ( + CONST CHAR16 *TextDevicePath + ) +{ + return UefiDevicePathLibConvertTextToDevicePath (TextDevicePath); +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/UefiDevicePathLib.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/UefiDevicePathLib.h new file mode 100644 index 00000000..4e855acc --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/DevicePath/UefiDevicePathLib.h @@ -0,0 +1,439 @@ +/** @file + Definition for Device Path library. + +Copyright (c) 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#ifndef _UEFI_DEVICE_PATH_LIB_H_ +#define _UEFI_DEVICE_PATH_LIB_H_ + +#include +#include +#include +#include +#include +#ifdef __GNUC__ +#include +#else +#include +#endif +#include +#include +#include +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" + +#define END_DEVICE_PATH_LENGTH (sizeof (EFI_DEVICE_PATH_PROTOCOL)) +#define MAX_DEVICE_PATH_NODE_COUNT 1024 +#define SIZE_64KB 0x00010000 + +// +// Private Data structure +// +typedef +EFI_DEVICE_PATH_PROTOCOL * +(*DEVICE_PATH_FROM_TEXT) ( + IN CHAR16 *Str + ); + +typedef struct { + CHAR16 *Str; + UINTN Count; + UINTN Capacity; +} POOL_PRINT; + + +typedef struct { + CHAR16 *DevicePathNodeText; + DEVICE_PATH_FROM_TEXT Function; +} DEVICE_PATH_FROM_TEXT_TABLE; + +typedef struct { + BOOLEAN ClassExist; + UINT8 Class; + BOOLEAN SubClassExist; + UINT8 SubClass; +} USB_CLASS_TEXT; + +#define USB_CLASS_AUDIO 1 +#define USB_CLASS_CDCCONTROL 2 +#define USB_CLASS_HID 3 +#define USB_CLASS_IMAGE 6 +#define USB_CLASS_PRINTER 7 +#define USB_CLASS_MASS_STORAGE 8 +#define USB_CLASS_HUB 9 +#define USB_CLASS_CDCDATA 10 +#define USB_CLASS_SMART_CARD 11 +#define USB_CLASS_VIDEO 14 +#define USB_CLASS_DIAGNOSTIC 220 +#define USB_CLASS_WIRELESS 224 + +#define USB_CLASS_RESERVE 254 +#define USB_SUBCLASS_FW_UPDATE 1 +#define USB_SUBCLASS_IRDA_BRIDGE 2 +#define USB_SUBCLASS_TEST 3 + +#define RFC_1700_UDP_PROTOCOL 17 +#define RFC_1700_TCP_PROTOCOL 6 + +#pragma pack(1) + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEFINED_HARDWARE_DEVICE_PATH; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEFINED_MESSAGING_DEVICE_PATH; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEFINED_MEDIA_DEVICE_PATH; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Hid; + UINT32 Uid; + UINT32 Cid; + CHAR8 HidUidCidStr[3]; +} ACPI_EXTENDED_HID_DEVICE_PATH_WITH_STR; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT16 NetworkProtocol; + UINT16 LoginOption; + UINT64 Lun; + UINT16 TargetPortalGroupTag; + CHAR8 TargetName[1]; +} ISCSI_DEVICE_PATH_WITH_NAME; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; + UINT8 VendorDefinedData[1]; +} VENDOR_DEVICE_PATH_WITH_DATA; + +#pragma pack() + +/** + Returns the size of a device path in bytes. + + This function returns the size, in bytes, of the device path data structure + specified by DevicePath including the end of device path node. + If DevicePath is NULL or invalid, then 0 is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval 0 If DevicePath is NULL or invalid. + @retval Others The size of a device path in bytes. + +**/ +UINTN +UefiDevicePathLibGetDevicePathSize ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/** + Creates a new copy of an existing device path. + + This function allocates space for a new copy of the device path specified by DevicePath. + If DevicePath is NULL, then NULL is returned. If the memory is successfully + allocated, then the contents of DevicePath are copied to the newly allocated + buffer, and a pointer to that buffer is returned. Otherwise, NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + + @retval NULL DevicePath is NULL or invalid. + @retval Others A pointer to the duplicated device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibDuplicateDevicePath ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/** + Creates a new device path by appending a second device path to a first device path. + + This function creates a new device path by appending a copy of SecondDevicePath + to a copy of FirstDevicePath in a newly allocated buffer. Only the end-of-device-path + device node from SecondDevicePath is retained. The newly created device path is + returned. If FirstDevicePath is NULL, then it is ignored, and a duplicate of + SecondDevicePath is returned. If SecondDevicePath is NULL, then it is ignored, + and a duplicate of FirstDevicePath is returned. If both FirstDevicePath and + SecondDevicePath are NULL, then a copy of an end-of-device-path is returned. + + If there is not enough memory for the newly allocated buffer, then NULL is returned. + The memory for the new device path is allocated from EFI boot services memory. + It is the responsibility of the caller to free the memory allocated. + + @param FirstDevicePath A pointer to a device path data structure. + @param SecondDevicePath A pointer to a device path data structure. + + @retval NULL If there is not enough memory for the newly allocated buffer. + @retval NULL If FirstDevicePath or SecondDevicePath is invalid. + @retval Others A pointer to the new device path if success. + Or a copy an end-of-device-path if both FirstDevicePath and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibAppendDevicePath ( + CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, OPTIONAL + CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL + ); + +/** + Creates a new path by appending the device node to the device path. + + This function creates a new device path by appending a copy of the device node + specified by DevicePathNode to a copy of the device path specified by DevicePath + in an allocated buffer. The end-of-device-path device node is moved after the + end of the appended device node. + If DevicePathNode is NULL then a copy of DevicePath is returned. + If DevicePath is NULL then a copy of DevicePathNode, followed by an end-of-device + path device node is returned. + If both DevicePathNode and DevicePath are NULL then a copy of an end-of-device-path + device node is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathNode A pointer to a single device path node. + + @retval NULL If there is not enough memory for the new device path. + @retval Others A pointer to the new device path if success. + A copy of DevicePathNode followed by an end-of-device-path node + if both FirstDevicePath and SecondDevicePath are NULL. + A copy of an end-of-device-path node if both FirstDevicePath + and SecondDevicePath are NULL. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibAppendDevicePathNode ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL + ); + +/** + Creates a new device path by appending the specified device path instance to the specified device + path. + + This function creates a new device path by appending a copy of the device path + instance specified by DevicePathInstance to a copy of the device path specified + by DevicePath in a allocated buffer. + The end-of-device-path device node is moved after the end of the appended device + path instance and a new end-of-device-path-instance node is inserted between. + If DevicePath is NULL, then a copy if DevicePathInstance is returned. + If DevicePathInstance is NULL, then NULL is returned. + If DevicePath or DevicePathInstance is invalid, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param DevicePath A pointer to a device path data structure. + @param DevicePathInstance A pointer to a device path instance. + + @return A pointer to the new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibAppendDevicePathInstance ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL + ); + +/** + Creates a copy of the current device path instance and returns a pointer to the next device path + instance. + + This function creates a copy of the current device path instance. It also updates + DevicePath to point to the next device path instance in the device path (or NULL + if no more) and updates Size to hold the size of the device path instance copy. + If DevicePath is NULL, then NULL is returned. + If DevicePath points to a invalid device path, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + If Size is NULL, then ASSERT(). + + @param DevicePath On input, this holds the pointer to the current + device path instance. On output, this holds + the pointer to the next device path instance + or NULL if there are no more device path + instances in the device path pointer to a + device path data structure. + @param Size On output, this holds the size of the device + path instance, in bytes or zero, if DevicePath + is NULL. + + @return A pointer to the current device path instance. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibGetNextDevicePathInstance ( + EFI_DEVICE_PATH_PROTOCOL **DevicePath, + UINTN *Size + ); + +/** + Creates a device node. + + This function creates a new device node in a newly allocated buffer of size + NodeLength and initializes the device path node header with NodeType and NodeSubType. + The new device path node is returned. + If NodeLength is smaller than a device path header, then NULL is returned. + If there is not enough memory to allocate space for the new device path, then + NULL is returned. + The memory is allocated from EFI boot services memory. It is the responsibility + of the caller to free the memory allocated. + + @param NodeType The device node type for the new device node. + @param NodeSubType The device node sub-type for the new device node. + @param NodeLength The length of the new device node. + + @return The new device path. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibCreateDeviceNode ( + UINT8 NodeType, + UINT8 NodeSubType, + UINT16 NodeLength + ); + +/** + Determines if a device path is single or multi-instance. + + This function returns TRUE if the device path specified by DevicePath is + multi-instance. + Otherwise, FALSE is returned. + If DevicePath is NULL or invalid, then FALSE is returned. + + @param DevicePath A pointer to a device path data structure. + + @retval TRUE DevicePath is multi-instance. + @retval FALSE DevicePath is not multi-instance, or DevicePath + is NULL or invalid. + +**/ +BOOLEAN +UefiDevicePathLibIsDevicePathMultiInstance ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/** + Convert text to the binary representation of a device node. + + @param TextDeviceNode TextDeviceNode points to the text representation of a device + node. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the EFI device node or NULL if TextDeviceNode is NULL or there was + insufficient memory or text unsupported. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibConvertTextToDeviceNode ( + CONST CHAR16 *TextDeviceNode + ); + +/** + Convert text to the binary representation of a device path. + + + @param TextDevicePath TextDevicePath points to the text representation of a device + path. Conversion starts with the first character and continues + until the first non-device node character. + + @return A pointer to the allocated device path or NULL if TextDeviceNode is NULL or + there was insufficient memory. + +**/ +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibConvertTextToDevicePath ( + CONST CHAR16 *TextDevicePath + ); + +EFI_DEVICE_PATH_PROTOCOL * +CreateDeviceNode ( + UINT8 NodeType, + UINT8 NodeSubType, + UINT16 NodeLength + ); + +BOOLEAN +IsDevicePathMultiInstance ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +EFI_DEVICE_PATH_PROTOCOL * +GetNextDevicePathInstance ( + EFI_DEVICE_PATH_PROTOCOL **DevicePath, + UINTN *Size + ); + +EFI_DEVICE_PATH_PROTOCOL * +AppendDevicePathInstance ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance OPTIONAL + ); + +EFI_DEVICE_PATH_PROTOCOL * +AppendDevicePathNode ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, OPTIONAL + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode OPTIONAL + ); +EFI_DEVICE_PATH_PROTOCOL * +AppendDevicePath ( + CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, OPTIONAL + CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath OPTIONAL + ); + +EFI_DEVICE_PATH_PROTOCOL * +DuplicateDevicePath ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +UINTN +GetDevicePathSize ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +CHAR16 * +ConvertDeviceNodeToText ( + CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode, + BOOLEAN DisplayOnly, + BOOLEAN AllowShortcuts + ); + +CHAR16 * +ConvertDevicePathToText ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + BOOLEAN DisplayOnly, + BOOLEAN AllowShortcuts + ); + +EFI_DEVICE_PATH_PROTOCOL * +ConvertTextToDeviceNode ( + CONST CHAR16 *TextDeviceNode + ); + +EFI_DEVICE_PATH_PROTOCOL * +ConvertTextToDevicePath ( + CONST CHAR16 *TextDevicePath + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.c new file mode 100644 index 00000000..61e47a6a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.c @@ -0,0 +1,1712 @@ +/** @file +Utility program to create an EFI option ROM image from binary and EFI PE32 files. + +Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "EfiUtilityMsgs.h" +#include "ParseInf.h" +#include "EfiRom.h" + +UINT64 DebugLevel = 0; + +int +main ( + int Argc, + char *Argv[] + ) +/*++ + +Routine Description: + + Given an EFI image filename, create a ROM-able image by creating an option + ROM header and PCI data structure, filling them in, and then writing the + option ROM header + PCI data structure + EFI image out to the output file. + +Arguments: + + Argc - standard C main() argument count + + Argv - standard C main() argument list + +Returns: + + 0 success + non-zero otherwise + +--*/ +{ + CHAR8 *Ext; + FILE *FptrOut; + UINT32 Status; + FILE_LIST *FList; + UINT32 TotalSize; + UINT32 Size; + CHAR8 *Ptr0; + + SetUtilityName(UTILITY_NAME); + + Status = STATUS_SUCCESS; + FptrOut = NULL; + + // + // Parse the command line arguments + // + if (ParseCommandLine (Argc, Argv, &mOptions)) { + return STATUS_ERROR; + } + + if (mOptions.Quiet) { + SetPrintLevel(40); + } else if (mOptions.Verbose) { + SetPrintLevel(15); + } else if (mOptions.Debug) { + SetPrintLevel(DebugLevel); + } + + if (mOptions.Verbose) { + VerboseMsg("%s tool start.\n", UTILITY_NAME); + } + + // + // If dumping an image, then do that and quit + // + if (mOptions.DumpOption == 1) { + if (mOptions.FileList != NULL) { + if ((Ptr0 = strstr ((CONST CHAR8 *) mOptions.FileList->FileName, DEFAULT_OUTPUT_EXTENSION)) != NULL) { + DumpImage (mOptions.FileList); + goto BailOut; + } else { + Error (NULL, 0, 1002, "No PciRom input file", "No *.rom input file"); + goto BailOut; + } + } + } + // + // Determine the output filename. Either what they specified on + // the command line, or the first input filename with a different extension. + // + if (!mOptions.OutFileName[0]) { + if (mOptions.FileList != NULL) { + if (strlen (mOptions.FileList->FileName) >= MAX_PATH) { + Status = STATUS_ERROR; + Error (NULL, 0, 2000, "Invalid parameter", "Input file name is too long - %s.", mOptions.FileList->FileName); + goto BailOut; + } + strncpy (mOptions.OutFileName, mOptions.FileList->FileName, MAX_PATH - 1); + mOptions.OutFileName[MAX_PATH - 1] = 0; + // + // Find the last . on the line and replace the filename extension with + // the default + // + Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1; + while (Ext >= mOptions.OutFileName) { + if ((*Ext == '.') || (*Ext == '\\')) { + break; + } + Ext--; + } + // + // If dot here, then insert extension here, otherwise append + // + if (*Ext != '.') { + Ext = mOptions.OutFileName + strlen (mOptions.OutFileName); + } + + strcpy (Ext, DEFAULT_OUTPUT_EXTENSION); + } + } + // + // Make sure we don't have the same filename for input and output files + // + for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) { + if (stricmp (mOptions.OutFileName, FList->FileName) == 0) { + Status = STATUS_ERROR; + Error (NULL, 0, 1002, "Invalid input parameter", "Input and output file names must be different - %s = %s.", FList->FileName, mOptions.OutFileName); + goto BailOut; + } + } + // + // Now open our output file + // + if ((FptrOut = fopen (LongFilePath (mOptions.OutFileName), "wb")) == NULL) { + Error (NULL, 0, 0001, "Error opening file", "Error opening file %s", mOptions.OutFileName); + goto BailOut; + } + // + // Process all our files + // + TotalSize = 0; + for (FList = mOptions.FileList; FList != NULL; FList = FList->Next) { + Size = 0; + if ((FList->FileFlags & FILE_FLAG_EFI) != 0) { + if (mOptions.Verbose) { + VerboseMsg("Processing EFI file %s\n", FList->FileName); + } + + Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevIdList[0], &Size); + } else if ((FList->FileFlags & FILE_FLAG_BINARY) !=0 ) { + if (mOptions.Verbose) { + VerboseMsg("Processing binary file %s\n", FList->FileName); + } + + Status = ProcessBinFile (FptrOut, FList, &Size); + } else { + Error (NULL, 0, 2000, "Invalid parameter", "File type not specified, it must be either an EFI or binary file: %s.", FList->FileName); + Status = STATUS_ERROR; + } + + if (mOptions.Verbose) { + VerboseMsg(" Output size = 0x%X\n", (unsigned) Size); + } + + if (Status != STATUS_SUCCESS) { + break; + } + + TotalSize += Size; + } + // + // Check total size + // + if (TotalSize > MAX_OPTION_ROM_SIZE) { + Error (NULL, 0, 2000, "Invalid parameter", "Option ROM image size exceeds limit of 0x%X bytes.", MAX_OPTION_ROM_SIZE); + Status = STATUS_ERROR; + } + +BailOut: + if (Status == STATUS_SUCCESS) { + // + // Clean up our file list + // + while (mOptions.FileList != NULL) { + FList = mOptions.FileList->Next; + free (mOptions.FileList); + mOptions.FileList = FList; + } + + // + // Clean up device ID list + // + if (mOptions.DevIdList != NULL) { + free (mOptions.DevIdList); + } + } + if (FptrOut != NULL) { + fclose (FptrOut); + } + + if (mOptions.Verbose) { + VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ()); + } + + return GetUtilityStatus (); +} + +static +int +ProcessBinFile ( + FILE *OutFptr, + FILE_LIST *InFile, + UINT32 *Size + ) +/*++ + +Routine Description: + + Process a binary input file. + +Arguments: + + OutFptr - file pointer to output binary ROM image file we're creating + InFile - structure contains information on the binary file to process + Size - pointer to where to return the size added to the output file + +Returns: + + 0 - successful + +--*/ +{ + FILE *InFptr; + UINT32 TotalSize; + UINT32 FileSize; + UINT8 *Buffer; + UINT32 Status; + PCI_EXPANSION_ROM_HEADER *RomHdr; + PCI_DATA_STRUCTURE *PciDs23; + PCI_3_0_DATA_STRUCTURE *PciDs30; + UINT32 Index; + UINT8 ByteCheckSum; + UINT16 CodeType; + + PciDs23 = NULL; + PciDs30 = NULL; + Status = STATUS_SUCCESS; + + // + // Try to open the input file + // + if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) { + Error (NULL, 0, 0001, "Error opening file", "%s", InFile->FileName); + return STATUS_ERROR; + } + // + // Seek to the end of the input file and get the file size. Then allocate + // a buffer to read it in to. + // + fseek (InFptr, 0, SEEK_END); + FileSize = ftell (InFptr); + if (mOptions.Verbose) { + VerboseMsg(" File size = 0x%X\n", (unsigned) FileSize); + } + + fseek (InFptr, 0, SEEK_SET); + Buffer = (UINT8 *) malloc (FileSize); + if (Buffer == NULL) { + Error (NULL, 0, 4003, "Resource", "memory cannot be allocated!"); + Status = STATUS_ERROR; + goto BailOut; + } + + if (fread (Buffer, FileSize, 1, InFptr) != 1) { + Error (NULL, 0, 2000, "Invalid", "Failed to read all bytes from input file."); + Status = STATUS_ERROR; + goto BailOut; + } + // + // Total size must be an even multiple of 512 bytes, and can't exceed + // the option ROM image size. + // + TotalSize = FileSize; + if (TotalSize & 0x1FF) { + TotalSize = (TotalSize + 0x200) &~0x1ff; + } + + if (TotalSize > MAX_OPTION_ROM_SIZE) { + Error (NULL, 0, 3001, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", InFile->FileName, MAX_OPTION_ROM_SIZE); + Status = STATUS_ERROR; + goto BailOut; + } + // + // Return the size to the caller so they can keep track of the running total. + // + *Size = TotalSize; + + // + // Crude check to make sure it's a legitimate ROM image + // + RomHdr = (PCI_EXPANSION_ROM_HEADER *) Buffer; + if (RomHdr->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) { + Error (NULL, 0, 2000, "Invalid parameter", "ROM image file has an invalid ROM signature."); + Status = STATUS_ERROR; + goto BailOut; + } + // + // Make sure the pointer to the PCI data structure is within the size of the image. + // Then check it for valid signature. + // + if ((RomHdr->PcirOffset > FileSize) || (RomHdr->PcirOffset == 0)) { + Error (NULL, 0, 2000, "Invalid parameter", "Invalid PCI data structure offset."); + Status = STATUS_ERROR; + goto BailOut; + } + + // + // Check the header is conform to PCI2.3 or PCI3.0 + // + if (mOptions.Pci23 == 1) { + PciDs23 = (PCI_DATA_STRUCTURE *) (Buffer + RomHdr->PcirOffset); + if (PciDs23->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { + Error (NULL, 0, 2000, "Invalid parameter", "PCI data structure has an invalid signature."); + Status = STATUS_ERROR; + goto BailOut; + } + } else { + // + // Default setting is PCI3.0 header + // + PciDs30 = (PCI_3_0_DATA_STRUCTURE *)(Buffer + RomHdr->PcirOffset); + if (PciDs30->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { + Error (NULL, 0, 2000, "Invalid parameter", "PCI data structure has an invalid signature."); + Status = STATUS_ERROR; + goto BailOut; + } + } + + // + // ReSet Option Rom size + // + if (mOptions.Pci23 == 1) { + PciDs23->ImageLength = (UINT16) (TotalSize / 512); + CodeType = PciDs23->CodeType; + } else { + PciDs30->ImageLength = (UINT16) (TotalSize / 512); + CodeType = PciDs30->CodeType; + } + + // + // If this is the last image, then set the LAST bit unless requested not + // to via the command-line -n argument. Otherwise, make sure you clear it. + // + if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) { + if (mOptions.Pci23 == 1) { + PciDs23->Indicator = INDICATOR_LAST; + } else { + PciDs30->Indicator = INDICATOR_LAST; + } + } else { + if (mOptions.Pci23 == 1) { + PciDs23->Indicator = 0; + } else { + PciDs30->Indicator = 0; + } + } + + if (CodeType != PCI_CODE_TYPE_EFI_IMAGE) { + ByteCheckSum = 0; + for (Index = 0; Index < FileSize - 1; Index++) { + ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]); + } + + Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1); + if (mOptions.Verbose) { + VerboseMsg(" Checksum = %02x\n\n", Buffer[FileSize - 1]); + } + } + + // + // Now copy the input file contents out to the output file + // + if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) { + Error (NULL, 0, 0005, "Failed to write all file bytes to output file.", NULL); + Status = STATUS_ERROR; + goto BailOut; + } + + TotalSize -= FileSize; + // + // Pad the rest of the image to make it a multiple of 512 bytes + // + while (TotalSize > 0) { + putc (~0, OutFptr); + TotalSize--; + } + +BailOut: + if (InFptr != NULL) { + fclose (InFptr); + } + + if (Buffer != NULL) { + free (Buffer); + } + // + // Print the file name if errors occurred + // + if (Status != STATUS_SUCCESS) { + Error (NULL, 0, 0003, "Error", "Error parsing file: %s", InFile->FileName); + } + + return Status; +} + +static +int +ProcessEfiFile ( + FILE *OutFptr, + FILE_LIST *InFile, + UINT16 VendId, + UINT16 DevId, + UINT32 *Size + ) +/*++ + +Routine Description: + + Process a PE32 EFI file. + +Arguments: + + OutFptr - file pointer to output binary ROM image file we're creating + InFile - structure contains information on the PE32 file to process + VendId - vendor ID as required in the option ROM header + DevId - device ID as required in the option ROM header + Size - pointer to where to return the size added to the output file + +Returns: + + 0 - successful + +--*/ +{ + UINT32 Status; + FILE *InFptr; + EFI_PCI_EXPANSION_ROM_HEADER RomHdr; + PCI_DATA_STRUCTURE PciDs23; + PCI_3_0_DATA_STRUCTURE PciDs30; + UINT32 FileSize; + UINT32 CompressedFileSize; + UINT8 *Buffer; + UINT8 *CompressedBuffer; + UINT8 *TempBufferPtr; + UINT32 TotalSize; + UINT32 HeaderSize; + UINT16 MachineType; + UINT16 SubSystem; + UINT32 HeaderPadBytes; + UINT32 PadBytesBeforeImage; + UINT32 PadBytesAfterImage; + UINT32 DevIdListSize; + + // + // Try to open the input file + // + if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) { + Error (NULL, 0, 0001, "Open file error", "Error opening file: %s", InFile->FileName); + return STATUS_ERROR; + } + // + // Initialize our buffer pointers to null. + // + Buffer = NULL; + CompressedBuffer = NULL; + + // + // Double-check the file to make sure it's what we expect it to be + // + Status = CheckPE32File (InFptr, &MachineType, &SubSystem); + if (Status != STATUS_SUCCESS) { + goto BailOut; + } + // + // Seek to the end of the input file and get the file size + // + fseek (InFptr, 0, SEEK_END); + FileSize = ftell (InFptr); + + // + // Get the size of the headers we're going to put in front of the image. The + // EFI header must be aligned on a 4-byte boundary, so pad accordingly. + // + if (sizeof (RomHdr) & 0x03) { + HeaderPadBytes = 4 - (sizeof (RomHdr) & 0x03); + } else { + HeaderPadBytes = 0; + } + + // + // For Pci3.0 to use the different data structure. + // + if (mOptions.Pci23 == 1) { + HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER); + } else { + if (mOptions.DevIdCount > 1) { + // + // Write device ID list when more than one device ID is specified. + // Leave space for list plus terminator. + // + DevIdListSize = (mOptions.DevIdCount + 1) * sizeof (UINT16); + } else { + DevIdListSize = 0; + } + HeaderSize = sizeof (PCI_3_0_DATA_STRUCTURE) + HeaderPadBytes + DevIdListSize + sizeof (EFI_PCI_EXPANSION_ROM_HEADER); + } + + if (mOptions.Verbose) { + VerboseMsg(" File size = 0x%X\n", (unsigned) FileSize); + } + // + // Allocate memory for the entire file (in case we have to compress), then + // seek back to the beginning of the file and read it into our buffer. + // + Buffer = (UINT8 *) malloc (FileSize); + if (Buffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + Status = STATUS_ERROR; + goto BailOut; + } + + fseek (InFptr, 0, SEEK_SET); + if (fread (Buffer, FileSize, 1, InFptr) != 1) { + Error (NULL, 0, 0004, "Error reading file", "File %s", InFile->FileName); + Status = STATUS_ERROR; + goto BailOut; + } + // + // Now determine the size of the final output file. It's either the header size + // plus the file's size, or the header size plus the compressed file size. + // + if ((InFile->FileFlags & FILE_FLAG_COMPRESS) != 0) { + // + // Allocate a buffer into which we can compress the image, compress it, + // and use that size as the new size. + // + CompressedBuffer = (UINT8 *) malloc (FileSize); + if (CompressedBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + Status = STATUS_ERROR; + goto BailOut; + } + + CompressedFileSize = FileSize; + Status = EfiCompress (Buffer, FileSize, CompressedBuffer, &CompressedFileSize); + if (Status != STATUS_SUCCESS) { + Error (NULL, 0, 0007, "Error compressing file!", NULL); + goto BailOut; + } + // + // Now compute the size, then swap buffer pointers. + // + if (mOptions.Verbose) { + VerboseMsg(" Comp size = 0x%X\n", (unsigned) CompressedFileSize); + } + + TotalSize = CompressedFileSize + HeaderSize; + FileSize = CompressedFileSize; + TempBufferPtr = Buffer; + Buffer = CompressedBuffer; + CompressedBuffer = TempBufferPtr; + } else { + TotalSize = FileSize + HeaderSize; + } + // + // Total size must be an even multiple of 512 bytes + // + if (TotalSize & 0x1FF) { + TotalSize = (TotalSize + 0x200) &~0x1ff; + } + // + // Workaround: + // If compressed, put the pad bytes after the image, + // else put the pad bytes before the image. + // + if ((InFile->FileFlags & FILE_FLAG_COMPRESS) != 0) { + PadBytesBeforeImage = 0; + PadBytesAfterImage = TotalSize - (FileSize + HeaderSize); + } else { + PadBytesBeforeImage = TotalSize - (FileSize + HeaderSize); + PadBytesAfterImage = 0; + } + // + // Check size + // + if (TotalSize > MAX_OPTION_ROM_SIZE) { + Error (NULL, 0, 2000, "Invalid", "Option ROM image %s size exceeds limit of 0x%X bytes.", InFile->FileName, MAX_OPTION_ROM_SIZE); + Status = STATUS_ERROR; + goto BailOut; + } + // + // Return the size to the caller so they can keep track of the running total. + // + *Size = TotalSize; + + // + // Now fill in the ROM header. These values come from chapter 18 of the + // EFI 1.02 specification. + // + memset (&RomHdr, 0, sizeof (RomHdr)); + RomHdr.Signature = PCI_EXPANSION_ROM_HEADER_SIGNATURE; + RomHdr.InitializationSize = (UINT16) (TotalSize / 512); + RomHdr.EfiSignature = EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE; + RomHdr.EfiSubsystem = SubSystem; + RomHdr.EfiMachineType = MachineType; + RomHdr.EfiImageHeaderOffset = (UINT16) (HeaderSize + PadBytesBeforeImage); + RomHdr.PcirOffset = (UINT16) (sizeof (RomHdr) + HeaderPadBytes); + // + // Set image as compressed or not + // + if (InFile->FileFlags & FILE_FLAG_COMPRESS) { + RomHdr.CompressionType = EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED; + } + // + // Fill in the PCI data structure + // + if (mOptions.Pci23 == 1) { + memset (&PciDs23, 0, sizeof (PCI_DATA_STRUCTURE)); + } else { + memset (&PciDs30, 0, sizeof (PCI_3_0_DATA_STRUCTURE)); + } + + if (mOptions.Pci23 == 1) { + PciDs23.Signature = PCI_DATA_STRUCTURE_SIGNATURE; + PciDs23.VendorId = VendId; + PciDs23.DeviceId = DevId; + PciDs23.Length = (UINT16) sizeof (PCI_DATA_STRUCTURE); + PciDs23.Revision = 0; + // + // Class code and code revision from the command line (optional) + // + PciDs23.ClassCode[0] = (UINT8) InFile->ClassCode; + PciDs23.ClassCode[1] = (UINT8) (InFile->ClassCode >> 8); + PciDs23.ClassCode[2] = (UINT8) (InFile->ClassCode >> 16); + PciDs23.ImageLength = RomHdr.InitializationSize; + PciDs23.CodeRevision = InFile->CodeRevision; + PciDs23.CodeType = PCI_CODE_TYPE_EFI_IMAGE; + } else { + PciDs30.Signature = PCI_DATA_STRUCTURE_SIGNATURE; + PciDs30.VendorId = VendId; + PciDs30.DeviceId = DevId; + if (mOptions.DevIdCount > 1) { + // + // Place device list immediately after PCI structure + // + PciDs30.DeviceListOffset = (UINT16) sizeof (PCI_3_0_DATA_STRUCTURE); + } else { + PciDs30.DeviceListOffset = 0; + } + PciDs30.Length = (UINT16) sizeof (PCI_3_0_DATA_STRUCTURE); + PciDs30.Revision = 0x3; + // + // Class code and code revision from the command line (optional) + // + PciDs30.ClassCode[0] = (UINT8) InFile->ClassCode; + PciDs30.ClassCode[1] = (UINT8) (InFile->ClassCode >> 8); + PciDs30.ClassCode[2] = (UINT8) (InFile->ClassCode >> 16); + PciDs30.ImageLength = RomHdr.InitializationSize; + PciDs30.CodeRevision = InFile->CodeRevision; + PciDs30.CodeType = PCI_CODE_TYPE_EFI_IMAGE; + PciDs30.MaxRuntimeImageLength = 0; // to be fixed + PciDs30.ConfigUtilityCodeHeaderOffset = 0; // to be fixed + PciDs30.DMTFCLPEntryPointOffset = 0; // to be fixed + } + // + // If this is the last image, then set the LAST bit unless requested not + // to via the command-line -n argument. + // + if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) { + if (mOptions.Pci23 == 1) { + PciDs23.Indicator = INDICATOR_LAST; + } else { + PciDs30.Indicator = INDICATOR_LAST;} + } else { + if (mOptions.Pci23 == 1) { + PciDs23.Indicator = 0; + } else { + PciDs30.Indicator = 0; + } + } + // + // Write the ROM header to the output file + // + if (fwrite (&RomHdr, sizeof (RomHdr), 1, OutFptr) != 1) { + Error (NULL, 0, 0002, "Failed to write ROM header to output file!", NULL); + Status = STATUS_ERROR; + goto BailOut; + } + + // + // Write pad bytes to align the PciDs + // + while (HeaderPadBytes > 0) { + if (putc (0, OutFptr) == EOF) { + Error (NULL, 0, 0002, "Failed to write ROM header pad bytes to output file!", NULL); + Status = STATUS_ERROR; + goto BailOut; + } + + HeaderPadBytes--; + } + // + // Write the PCI data structure header to the output file + // + if (mOptions.Pci23 == 1) { + if (fwrite (&PciDs23, sizeof (PciDs23), 1, OutFptr) != 1) { + Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL); + Status = STATUS_ERROR; + goto BailOut; + } + } else { + if (fwrite (&PciDs30, sizeof (PciDs30), 1, OutFptr) != 1) { + Error (NULL, 0, 0002, "Failed to write PCI ROM header to output file!", NULL); + Status = STATUS_ERROR; + goto BailOut; + } + } + + // + // Write the Device ID list to the output file + // + if (mOptions.DevIdCount > 1) { + if (fwrite (mOptions.DevIdList, sizeof (UINT16), mOptions.DevIdCount, OutFptr) != mOptions.DevIdCount) { + Error (NULL, 0, 0002, "Failed to write PCI device list to output file!", NULL); + Status = STATUS_ERROR; + goto BailOut; + } + // + // Write two-byte terminating 0 at the end of the device list + // + if (putc (0, OutFptr) == EOF || putc (0, OutFptr) == EOF) { + Error (NULL, 0, 0002, "Failed to write PCI device list to output file!", NULL); + Status = STATUS_ERROR; + goto BailOut; + } + } + + + // + // Pad head to make it a multiple of 512 bytes + // + while (PadBytesBeforeImage > 0) { + if (putc (~0, OutFptr) == EOF) { + Error (NULL, 0, 2000, "Failed to write trailing pad bytes output file!", NULL); + Status = STATUS_ERROR; + goto BailOut; + } + PadBytesBeforeImage--; + } + // + // Now dump the input file's contents to the output file + // + if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) { + Error (NULL, 0, 0002, "Failed to write all file bytes to output file!", NULL); + Status = STATUS_ERROR; + goto BailOut; + } + + // + // Pad the rest of the image to make it a multiple of 512 bytes + // + while (PadBytesAfterImage > 0) { + if (putc (~0, OutFptr) == EOF) { + Error (NULL, 0, 2000, "Failed to write trailing pad bytes output file!", NULL); + Status = STATUS_ERROR; + goto BailOut; + } + + PadBytesAfterImage--; + } + +BailOut: + if (InFptr != NULL) { + fclose (InFptr); + } + // + // Free up our buffers + // + if (Buffer != NULL) { + free (Buffer); + } + + if (CompressedBuffer != NULL) { + free (CompressedBuffer); + } + // + // Print the file name if errors occurred + // + if (Status != STATUS_SUCCESS) { + Error (NULL, 0, 0003, "Error parsing", "Error parsing file: %s", InFile->FileName); + } + + return Status; +} + +static +int +CheckPE32File ( + FILE *Fptr, + UINT16 *MachineType, + UINT16 *SubSystem + ) +/*++ + +Routine Description: + + Given a file pointer to a supposed PE32 image file, verify that it is indeed a + PE32 image file, and then return the machine type in the supplied pointer. + +Arguments: + + Fptr File pointer to the already-opened PE32 file + MachineType Location to stuff the machine type of the PE32 file. This is needed + because the image may be Itanium-based, IA32, or EBC. + +Returns: + + 0 success + non-zero otherwise + +--*/ +{ + EFI_IMAGE_DOS_HEADER DosHeader; + EFI_IMAGE_OPTIONAL_HEADER_UNION PeHdr; + + // + // Position to the start of the file + // + fseek (Fptr, 0, SEEK_SET); + + // + // Read the DOS header + // + if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) { + Error (NULL, 0, 0004, "Failed to read the DOS stub from the input file!", NULL); + return STATUS_ERROR; + } + // + // Check the magic number (0x5A4D) + // + if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) { + Error (NULL, 0, 2000, "Invalid parameter", "Input file does not appear to be a PE32 image (magic number)!"); + return STATUS_ERROR; + } + // + // Position into the file and check the PE signature + // + fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET); + + // + // Read PE headers + // + if (fread (&PeHdr, sizeof (PeHdr), 1, Fptr) != 1) { + Error (NULL, 0, 0004, "Failed to read PE/COFF headers from input file!", NULL); + return STATUS_ERROR; + } + + + // + // Check the PE signature in the header "PE\0\0" + // + if (PeHdr.Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 2000, "Invalid parameter", "Input file does not appear to be a PE32 image (signature)!"); + return STATUS_ERROR; + } + + memcpy ((char *) MachineType, &PeHdr.Pe32.FileHeader.Machine, 2); + + if (PeHdr.Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + *SubSystem = PeHdr.Pe32.OptionalHeader.Subsystem; + } else if (PeHdr.Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + *SubSystem = PeHdr.Pe32Plus.OptionalHeader.Subsystem; + } else { + Error (NULL, 0, 2000, "Invalid parameter", "Unable to find subsystem type!"); + return STATUS_ERROR; + } + + if (mOptions.Verbose) { + VerboseMsg(" Got subsystem = 0x%X from image\n", *SubSystem); + } + + // + // File was successfully identified as a PE32 + // + return STATUS_SUCCESS; +} + +static +int +ParseCommandLine ( + int Argc, + char *Argv[], + OPTIONS *Options + ) +/*++ + +Routine Description: + + Given the Argc/Argv program arguments, and a pointer to an options structure, + parse the command-line options and check their validity. + + +Arguments: + + Argc - standard C main() argument count + Argv[] - standard C main() argument list + Options - pointer to a structure to store the options in + +Returns: + + STATUS_SUCCESS success + non-zero otherwise + +--*/ +{ + FILE_LIST *FileList; + FILE_LIST *PrevFileList; + UINT32 FileFlags; + UINT32 ClassCode; + UINT32 CodeRevision; + EFI_STATUS Status; + INTN ReturnStatus; + BOOLEAN EfiRomFlag; + UINT64 TempValue; + char *OptionName; + UINT16 *DevIdList; + + ReturnStatus = 0; + FileFlags = 0; + EfiRomFlag = FALSE; + + // + // Clear out the options + // + memset ((char *) Options, 0, sizeof (OPTIONS)); + + // + // To avoid compile warnings + // + FileList = PrevFileList = NULL; + + Options->DevIdList = NULL; + Options->DevIdCount = 0; + + ClassCode = 0; + CodeRevision = 0; + // + // Skip over the program name + // + Argc--; + Argv++; + + // + // If no arguments, assume they want usage info + // + if (Argc == 0) { + Usage (); + return STATUS_ERROR; + } + + if ((stricmp(Argv[0], "-h") == 0) || (stricmp(Argv[0], "--help") == 0)) { + Usage(); + return STATUS_ERROR; + } + + if ((stricmp(Argv[0], "--version") == 0)) { + Version(); + return STATUS_ERROR; + } + + // + // Process until no more arguments + // + while (Argc > 0) { + if (Argv[0][0] == '-') { + // + // Vendor ID specified with -f + // + if (stricmp (Argv[0], "-f") == 0) { + // + // Make sure there's another parameter + // + Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]); + ReturnStatus = 1; + goto Done; + } + if (TempValue >= 0x10000) { + Error (NULL, 0, 2000, "Invalid option value", "Vendor Id %s out of range!", Argv[1]); + ReturnStatus = 1; + goto Done; + } + Options->VendId = (UINT16) TempValue; + Options->VendIdValid = 1; + + Argv++; + Argc--; + } else if (stricmp (Argv[0], "-i") == 0) { + + OptionName = Argv[0]; + + // + // Device IDs specified with -i + // Make sure there's at least one more parameter + // + if (Argc == 1) { + Error (NULL, 0, 2000, "Invalid parameter", "Missing Device Id with %s option!", OptionName); + ReturnStatus = 1; + goto Done; + } + + // + // Process until another dash-argument parameter or the end of the list + // + while (Argc > 1 && Argv[1][0] != '-') { + Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid option value", "%s = %s", OptionName, Argv[1]); + ReturnStatus = 1; + goto Done; + } + // + // Don't allow device IDs greater than 16 bits + // Don't allow 0, since it is used as a list terminator + // + if (TempValue >= 0x10000 || TempValue == 0) { + Error (NULL, 0, 2000, "Invalid option value", "Device Id %s out of range!", Argv[1]); + ReturnStatus = 1; + goto Done; + } + + DevIdList = (UINT16*) realloc (Options->DevIdList, (Options->DevIdCount + 1) * sizeof (UINT16)); + if (DevIdList == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!", NULL); + ReturnStatus = 1; + goto Done; + } + Options->DevIdList = DevIdList; + + Options->DevIdList[Options->DevIdCount++] = (UINT16) TempValue; + + Argv++; + Argc--; + } + + } else if ((stricmp (Argv[0], "-o") == 0) || (stricmp (Argv[0], "--output") == 0)) { + // + // Output filename specified with -o + // Make sure there's another parameter + // + if (Argv[1] == NULL || Argv[1][0] == '-') { + Error (NULL, 0, 2000, "Invalid parameter", "Missing output file name with %s option!", Argv[0]); + ReturnStatus = STATUS_ERROR; + goto Done; + } + if (strlen (Argv[1]) > MAX_PATH - 1) { + Error (NULL, 0, 2000, "Invalid parameter", "Output file name %s is too long!", Argv[1]); + ReturnStatus = STATUS_ERROR; + goto Done; + } + strncpy (Options->OutFileName, Argv[1], MAX_PATH - 1); + Options->OutFileName[MAX_PATH - 1] = 0; + + Argv++; + Argc--; + } else if ((stricmp (Argv[0], "-h") == 0) || (stricmp (Argv[0], "--help") == 0)) { + // + // Help option + // + Usage (); + ReturnStatus = STATUS_ERROR; + goto Done; + } else if (stricmp (Argv[0], "-b") == 0) { + // + // Specify binary files with -b + // + FileFlags = FILE_FLAG_BINARY; + } else if ((stricmp (Argv[0], "-e") == 0) || (stricmp (Argv[0], "-ec") == 0)) { + // + // Specify EFI files with -e. Specify EFI-compressed with -c. + // + FileFlags = FILE_FLAG_EFI; + if ((Argv[0][2] == 'c') || (Argv[0][2] == 'C')) { + FileFlags |= FILE_FLAG_COMPRESS; + } + // + // Specify not to set the LAST bit in the last file with -n + // + } else if (stricmp (Argv[0], "-n") == 0) { + Options->NoLast = 1; + } else if (((stricmp (Argv[0], "-v") == 0)) || ((stricmp (Argv[0], "--verbose") == 0))) { + // + // -v for verbose + // + Options->Verbose = 1; + } else if (stricmp (Argv[0], "--debug") == 0) { + Status = AsciiStringToUint64(Argv[1], FALSE, &DebugLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]); + ReturnStatus = 1; + goto Done; + } + if (DebugLevel > 9) { + Error (NULL, 0, 2000, "Invalid option value", "Debug Level range is 0-9, current input level is %d", Argv[1]); + ReturnStatus = 1; + goto Done; + } + if (DebugLevel>=5 && DebugLevel<=9) { + Options->Debug = TRUE; + } else { + Options->Debug = FALSE; + } + Argv++; + Argc--; + } else if ((stricmp (Argv[0], "--quiet") == 0) || (stricmp (Argv[0], "-q") == 0)) { + Options->Quiet = TRUE; + } else if ((stricmp (Argv[0], "--dump") == 0) || (stricmp (Argv[0], "-d") == 0)) { + // + // -dump for dumping a ROM image. In this case, say that the device id + // and vendor id are valid so we don't have to specify bogus ones on the + // command line. + // + Options->DumpOption = 1; + + Options->VendIdValid = 1; + Options->DevIdCount = 1; + FileFlags = FILE_FLAG_BINARY; + } else if ((stricmp (Argv[0], "-l") == 0) || (stricmp (Argv[0], "--class-code") == 0)) { + // + // Class code value for the next file in the list. + // Make sure there's another parameter + // + Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]); + ReturnStatus = 1; + goto Done; + } + ClassCode = (UINT32) TempValue; + if (ClassCode & 0xFF000000) { + Error (NULL, 0, 2000, "Invalid parameter", "Class code %s out of range!", Argv[1]); + ReturnStatus = STATUS_ERROR; + goto Done; + } + if (FileList != NULL && FileList->ClassCode == 0) { + FileList->ClassCode = ClassCode; + } + Argv++; + Argc--; + } else if ((stricmp (Argv[0], "-r") == 0) || (stricmp (Argv[0], "--Revision") == 0)) { + // + // Code revision in the PCI data structure. The value is for the next + // file in the list. + // Make sure there's another parameter + // + Status = AsciiStringToUint64(Argv[1], FALSE, &TempValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid option value", "%s = %s", Argv[0], Argv[1]); + ReturnStatus = 1; + goto Done; + } + CodeRevision = (UINT32) TempValue; + if (CodeRevision & 0xFFFF0000) { + Error (NULL, 0, 2000, "Invalid parameter", "Code revision %s out of range!", Argv[1]); + ReturnStatus = STATUS_ERROR; + goto Done; + } + if (FileList != NULL && FileList->CodeRevision == 0) { + FileList->CodeRevision = (UINT16) CodeRevision; + } + Argv++; + Argc--; + } else if ((stricmp (Argv[0], "-p") == 0) || (stricmp (Argv[0], "--pci23") == 0)) { + // + // Default layout meets PCI 3.0 specifications, specifying this flag will for a PCI 2.3 layout. + // + mOptions.Pci23 = 1; + } else { + Error (NULL, 0, 2000, "Invalid parameter", "Invalid option specified: %s", Argv[0]); + ReturnStatus = STATUS_ERROR; + goto Done; + } + } else { + // + // Not a slash-option argument. Must be a file name. Make sure they've specified + // -e or -b already. + // + if ((FileFlags & (FILE_FLAG_BINARY | FILE_FLAG_EFI)) == 0) { + Error (NULL, 0, 2000, "Invalid parameter", "Missing -e or -b with input file %s!", Argv[0]); + ReturnStatus = STATUS_ERROR; + goto Done; + } + // + // Check Efi Option RomImage + // + if ((FileFlags & FILE_FLAG_EFI) == FILE_FLAG_EFI) { + EfiRomFlag = TRUE; + } + // + // Create a new file structure + // + FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST)); + if (FileList == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!", NULL); + ReturnStatus = STATUS_ERROR; + goto Done; + } + + // + // set flag and class code for this image. + // + memset ((char *) FileList, 0, sizeof (FILE_LIST)); + FileList->FileName = Argv[0]; + FileList->FileFlags = FileFlags; + FileList->ClassCode = ClassCode; + FileList->CodeRevision = (UINT16) CodeRevision; + ClassCode = 0; + CodeRevision = 0; + + if (Options->FileList == NULL) { + Options->FileList = FileList; + } else { + if (PrevFileList == NULL) { + PrevFileList = FileList; + } else { + PrevFileList->Next = FileList; + } + } + + PrevFileList = FileList; + } + // + // Next argument + // + Argv++; + Argc--; + } + + // + // Must have specified some files + // + if (Options->FileList == NULL) { + Error (NULL, 0, 2000, "Invalid parameter", "Missing input file name!"); + // + // No memory allocation, return directly. + // + return STATUS_ERROR; + } + + // + // For EFI OptionRom image, Make sure a device ID and vendor ID are both specified. + // + if (EfiRomFlag) { + if (!Options->VendIdValid) { + Error (NULL, 0, 2000, "Missing Vendor ID in command line", NULL); + ReturnStatus = STATUS_ERROR; + goto Done; + } + + if (!Options->DevIdCount) { + Error (NULL, 0, 2000, "Missing Device ID in command line", NULL); + ReturnStatus = STATUS_ERROR; + goto Done; + } + } + + if (Options->DevIdCount > 1 && Options->Pci23) { + Error (NULL, 0, 2000, "Invalid parameter", "PCI 3.0 is required when specifying multiple Device IDs"); + ReturnStatus = STATUS_ERROR; + goto Done; + } + +Done: + if (ReturnStatus != 0) { + while (Options->FileList != NULL) { + FileList = Options->FileList->Next; + free (Options->FileList); + Options->FileList = FileList; + } + } + + return ReturnStatus; +} + +static +void +Version ( + VOID + ) +/*++ + +Routine Description: + + Print version information for this utility. + +Arguments: + + None. + +Returns: + + Nothing. +--*/ +{ + fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION); +} + +static +void +Usage ( + VOID + ) +/*++ + +Routine Description: + + Print usage information for this utility. + +Arguments: + + None. + +Returns: + + Nothing. + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "Usage: %s -f VendorId -i DeviceId [options] [file name] \n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n"); + + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " -o FileName, --output FileName\n\ + File will be created to store the output content.\n"); + fprintf (stdout, " -e EfiFileName\n\ + EFI PE32 image files.\n"); + fprintf (stdout, " -ec EfiFileName\n\ + EFI PE32 image files and will be compressed.\n"); + fprintf (stdout, " -b BinFileName\n\ + Legacy binary files.\n"); + fprintf (stdout, " -l ClassCode\n\ + Hex ClassCode in the PCI data structure header.\n"); + fprintf (stdout, " -r Rev Hex Revision in the PCI data structure header.\n"); + fprintf (stdout, " -n Not to automatically set the LAST bit in the last file.\n"); + fprintf (stdout, " -f VendorId\n\ + Hex PCI Vendor ID for the device OpROM, must be specified\n"); + fprintf (stdout, " -i DeviceId\n\ + One or more hex PCI Device IDs for the device OpROM, must be specified\n"); + fprintf (stdout, " -p, --pci23\n\ + Default layout meets PCI 3.0 specifications\n\ + specifying this flag will for a PCI 2.3 layout.\n"); + fprintf (stdout, " -d, --dump\n\ + Dump the headers of an existing option ROM image.\n"); + fprintf (stdout, " -v, --verbose\n\ + Turn on verbose output with informational messages.\n"); + fprintf (stdout, " --version Show program's version number and exit.\n"); + fprintf (stdout, " -h, --help\n\ + Show this help message and exit.\n"); + fprintf (stdout, " -q, --quiet\n\ + Disable all messages except FATAL ERRORS.\n"); + fprintf (stdout, " --debug [#,0-9]\n\ + Enable debug messages at level #.\n"); +} + +static +void +DumpImage ( + FILE_LIST *InFile + ) +/*++ + +Routine Description: + + Dump the headers of an existing option ROM image + +Arguments: + + InFile - the file name of an existing option ROM image + +Returns: + + none + +--*/ +{ + PCI_EXPANSION_ROM_HEADER PciRomHdr; + FILE *InFptr; + UINT32 ImageStart; + UINT32 ImageCount; + EFI_PCI_EXPANSION_ROM_HEADER EfiRomHdr; + PCI_DATA_STRUCTURE PciDs23; + PCI_3_0_DATA_STRUCTURE PciDs30; + UINT16 DevId; + + // + // Open the input file + // + if ((InFptr = fopen (LongFilePath (InFile->FileName), "rb")) == NULL) { + Error (NULL, 0, 0001, "Error opening file", InFile->FileName); + return ; + } + // + // Go through the image and dump the header stuff for each + // + ImageCount = 0; + for (;;) { + // + // Save our position in the file, since offsets in the headers + // are relative to the particular image. + // + ImageStart = ftell (InFptr); + ImageCount++; + + // + // Read the option ROM header. Have to assume a raw binary image for now. + // + if (fread (&PciRomHdr, sizeof (PciRomHdr), 1, InFptr) != 1) { + Error (NULL, 0, 3001, "Not supported", "Failed to read PCI ROM header from file!"); + goto BailOut; + } + + // + // Dump the contents of the header + // + fprintf (stdout, "Image %u -- Offset 0x%X\n", (unsigned) ImageCount, (unsigned) ImageStart); + fprintf (stdout, " ROM header contents\n"); + fprintf (stdout, " Signature 0x%04X\n", PciRomHdr.Signature); + fprintf (stdout, " PCIR offset 0x%04X\n", PciRomHdr.PcirOffset); + // + // Find PCI data structure + // + if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset, SEEK_SET)) { + Error (NULL, 0, 3001, "Not supported", "Failed to seek to PCI data structure!"); + goto BailOut; + } + // + // Read and dump the PCI data structure + // + memset (&PciDs23, 0, sizeof (PciDs23)); + memset (&PciDs30, 0, sizeof (PciDs30)); + if (mOptions.Pci23 == 1) { + if (fread (&PciDs23, sizeof (PciDs23), 1, InFptr) != 1) { + Error (NULL, 0, 3001, "Not supported", "Failed to read PCI data structure from file %s!", InFile->FileName); + goto BailOut; + } + } else { + if (fread (&PciDs30, sizeof (PciDs30), 1, InFptr) != 1) { + Error (NULL, 0, 3001, "Not supported", "Failed to read PCI data structure from file %s!", InFile->FileName); + goto BailOut; + } + } + if (mOptions.Verbose) { + VerboseMsg("Read PCI data structure from file %s", InFile->FileName); + } + + //fprintf (stdout, " PCI Data Structure\n"); + if (mOptions.Pci23 == 1) { + fprintf ( + stdout, + " Signature %c%c%c%c\n", + (char) PciDs23.Signature, + (char) (PciDs23.Signature >> 8), + (char) (PciDs23.Signature >> 16), + (char) (PciDs23.Signature >> 24) + ); + fprintf (stdout, " Vendor ID 0x%04X\n", PciDs23.VendorId); + fprintf (stdout, " Device ID 0x%04X\n", PciDs23.DeviceId); + fprintf (stdout, " Length 0x%04X\n", PciDs23.Length); + fprintf (stdout, " Revision 0x%04X\n", PciDs23.Revision); + fprintf ( + stdout, + " Class Code 0x%06X\n", + (unsigned) (PciDs23.ClassCode[0] | (PciDs23.ClassCode[1] << 8) | (PciDs23.ClassCode[2] << 16)) + ); + fprintf (stdout, " Image size 0x%X\n", (unsigned) PciDs23.ImageLength * 512); + fprintf (stdout, " Code revision: 0x%04X\n", PciDs23.CodeRevision); + fprintf (stdout, " Indicator 0x%02X", PciDs23.Indicator); + } else { + fprintf ( + stdout, + " Signature %c%c%c%c\n", + (char) PciDs30.Signature, + (char) (PciDs30.Signature >> 8), + (char) (PciDs30.Signature >> 16), + (char) (PciDs30.Signature >> 24) + ); + fprintf (stdout, " Vendor ID 0x%04X\n", PciDs30.VendorId); + fprintf (stdout, " Device ID 0x%04X\n", PciDs30.DeviceId); + fprintf (stdout, " Length 0x%04X\n", PciDs30.Length); + fprintf (stdout, " Revision 0x%04X\n", PciDs30.Revision); + fprintf (stdout, " DeviceListOffset 0x%02X\n", PciDs30.DeviceListOffset); + if (PciDs30.DeviceListOffset) { + // + // Print device ID list + // + fprintf (stdout, " Device list contents\n"); + if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset + PciDs30.DeviceListOffset, SEEK_SET)) { + Error (NULL, 0, 3001, "Not supported", "Failed to seek to PCI device ID list!"); + goto BailOut; + } + + // + // Loop until terminating 0 + // + do { + if (fread (&DevId, sizeof (DevId), 1, InFptr) != 1) { + Error (NULL, 0, 3001, "Not supported", "Failed to read PCI device ID list from file %s!", InFile->FileName); + goto BailOut; + } + if (DevId) { + fprintf (stdout, " 0x%04X\n", DevId); + } + } while (DevId); + + } + fprintf ( + stdout, + " Class Code 0x%06X\n", + (unsigned) (PciDs30.ClassCode[0] | (PciDs30.ClassCode[1] << 8) | (PciDs30.ClassCode[2] << 16)) + ); + fprintf (stdout, " Image size 0x%X\n", (unsigned) PciDs30.ImageLength * 512); + fprintf (stdout, " Code revision: 0x%04X\n", PciDs30.CodeRevision); + fprintf (stdout, " MaxRuntimeImageLength 0x%02X\n", PciDs30.MaxRuntimeImageLength); + fprintf (stdout, " ConfigUtilityCodeHeaderOffset 0x%02X\n", PciDs30.ConfigUtilityCodeHeaderOffset); + fprintf (stdout, " DMTFCLPEntryPointOffset 0x%02X\n", PciDs30.DMTFCLPEntryPointOffset); + fprintf (stdout, " Indicator 0x%02X", PciDs30.Indicator); + } + // + // Print the indicator, used to flag the last image + // + if (PciDs23.Indicator == INDICATOR_LAST || PciDs30.Indicator == INDICATOR_LAST) { + fprintf (stdout, " (last image)\n"); + } else { + fprintf (stdout, "\n"); + } + // + // Print the code type. If EFI code, then we can provide more info. + // + if (mOptions.Pci23 == 1) { + fprintf (stdout, " Code type 0x%02X", PciDs23.CodeType); + } else { + fprintf (stdout, " Code type 0x%02X", PciDs30.CodeType); + } + if (PciDs23.CodeType == PCI_CODE_TYPE_EFI_IMAGE || PciDs30.CodeType == PCI_CODE_TYPE_EFI_IMAGE) { + fprintf (stdout, " (EFI image)\n"); + // + // Re-read the header as an EFI ROM header, then dump more info + // + fprintf (stdout, " EFI ROM header contents\n"); + if (fseek (InFptr, ImageStart, SEEK_SET)) { + Error (NULL, 0, 5001, "Failed to re-seek to ROM header structure!", NULL); + goto BailOut; + } + + if (fread (&EfiRomHdr, sizeof (EfiRomHdr), 1, InFptr) != 1) { + Error (NULL, 0, 5001, "Failed to read EFI PCI ROM header from file!", NULL); + goto BailOut; + } + // + // Now dump more info + // + fprintf (stdout, " EFI Signature 0x%04X\n", (unsigned) EfiRomHdr.EfiSignature); + fprintf ( + stdout, + " Compression Type 0x%04X ", + EfiRomHdr.CompressionType + ); + if (EfiRomHdr.CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) { + fprintf (stdout, "(compressed)\n"); + } else { + fprintf (stdout, "(not compressed)\n"); + } + + fprintf ( + stdout, + " Machine type 0x%04X (%s)\n", + EfiRomHdr.EfiMachineType, + GetMachineTypeStr (EfiRomHdr.EfiMachineType) + ); + fprintf ( + stdout, + " Subsystem 0x%04X (%s)\n", + EfiRomHdr.EfiSubsystem, + GetSubsystemTypeStr (EfiRomHdr.EfiSubsystem) + ); + fprintf ( + stdout, + " EFI image offset 0x%04X (@0x%X)\n", + EfiRomHdr.EfiImageHeaderOffset, + EfiRomHdr.EfiImageHeaderOffset + (unsigned) ImageStart + ); + + } else { + // + // Not an EFI image + // + fprintf (stdout, "\n"); + } + // + // If code type is EFI image, then dump it as well? + // + // if (PciDs.CodeType == PCI_CODE_TYPE_EFI_IMAGE) { + // } + // + // If last image, then we're done + // + if (PciDs23.Indicator == INDICATOR_LAST || PciDs30.Indicator == INDICATOR_LAST) { + goto BailOut; + } + // + // Seek to the start of the next image + // + if (mOptions.Pci23 == 1) { + if (fseek (InFptr, ImageStart + (PciDs23.ImageLength * 512), SEEK_SET)) { + Error (NULL, 0, 3001, "Not supported", "Failed to seek to next image!"); + goto BailOut; + } + } else { + if (fseek (InFptr, ImageStart + (PciDs30.ImageLength * 512), SEEK_SET)) { + Error (NULL, 0, 3001, "Not supported", "Failed to seek to next image!"); + goto BailOut; + } + } + } + +BailOut: + fclose (InFptr); +} + +char * +GetMachineTypeStr ( + UINT16 MachineType + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + MachineType - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + int Index; + + for (Index = 0; mMachineTypes[Index].Name != NULL; Index++) { + if (mMachineTypes[Index].Value == MachineType) { + return mMachineTypes[Index].Name; + } + } + + return "unknown"; +} + +static +char * +GetSubsystemTypeStr ( + UINT16 SubsystemType + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + SubsystemType - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + int Index; + + for (Index = 0; mSubsystemTypes[Index].Name != NULL; Index++) { + if (mSubsystemTypes[Index].Value == SubsystemType) { + return mSubsystemTypes[Index].Name; + } + } + + return "unknown"; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.h new file mode 100644 index 00000000..0a04e605 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/EfiRom.h @@ -0,0 +1,353 @@ +/** @file +This file contains the relevant declarations required to generate Option Rom File + +Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __EFI_ROM_H__ +#define __EFI_ROM_H__ + +#include +#include +#include + +#include +#include // for PE32 structure definitions + +#include // for option ROM header structures +#include + +#include "Compress.h" +#include "CommonLib.h" + +// +// Version of this utility +// +#define UTILITY_NAME "EfiRom" +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +// +// Define the max length of a filename +// +#define MAX_PATH 200 + +// +// Define the default file extension name +// +#define DEFAULT_OUTPUT_EXTENSION ".rom" + +// +// Max size for an option ROM image +// +#define MAX_OPTION_ROM_SIZE (1024 * 1024 * 16) // 16MB + +// +// Values for the indicator field in the PCI data structure +// +#define INDICATOR_LAST 0x80 // last file in series of files + +// +// Masks for the FILE_LIST.FileFlags field +// +#define FILE_FLAG_BINARY 0x01 +#define FILE_FLAG_EFI 0x02 +#define FILE_FLAG_COMPRESS 0x04 + +// +// Use this linked list structure to keep track of all the filenames +// specified on the command line. +// +typedef struct _FILE_LIST { + struct _FILE_LIST *Next; + CHAR8 *FileName; + UINT32 FileFlags; + UINT32 ClassCode; + UINT16 CodeRevision; +} FILE_LIST; + +// +// Use this to track our command-line options +// +typedef struct { + CHAR8 OutFileName[MAX_PATH]; + INT8 NoLast; + UINT16 ClassCode; + UINT16 PciRevision; + UINT16 VendId; + UINT16 *DevIdList; + UINT32 DevIdCount; + UINT8 VendIdValid; + INT8 Verbose; + INT8 Quiet; + INT8 Debug; + INT8 Pci23; + INT8 Pci30; + INT8 DumpOption; +// INT8 Help; +// INT8 Version; + FILE_LIST *FileList; +} OPTIONS; + +// +// Make a global structure to keep track of command-line options +// +static OPTIONS mOptions; + +// +// Use these to convert from machine type value to a named type +// +typedef struct { + UINT16 Value; + CHAR8 *Name; +} STRING_LOOKUP; + +// +// Machine Types +// +static STRING_LOOKUP mMachineTypes[] = { + { EFI_IMAGE_MACHINE_IA32, "IA32" }, + { EFI_IMAGE_MACHINE_X64, "X64" }, + { EFI_IMAGE_MACHINE_EBC, "EBC" }, + { EFI_IMAGE_MACHINE_ARMT, "ARM" }, + { EFI_IMAGE_MACHINE_AARCH64, "AA64" }, + { 0, NULL } +}; + +// +// Subsystem Types +// +static STRING_LOOKUP mSubsystemTypes[] = { + { EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION, "EFI application" }, + { EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER, "EFI boot service driver" }, + { EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER, "EFI runtime driver" }, + { 0, NULL } +}; + +// +// Function prototypes +// +static +void +Version ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility version to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +; + +static +void +Usage ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +; + +static +int +ParseCommandLine ( + int Argc, + char *Argv[], + OPTIONS *Options + ) +/*++ + +Routine Description: + + Given the Argc/Argv program arguments, and a pointer to an options structure, + parse the command-line options and check their validity. + +Arguments: + + Argc - standard C main() argument count + Argv[] - standard C main() argument list + Options - pointer to a structure to store the options in + +Returns: + + STATUS_SUCCESS success + non-zero otherwise + +--*/ +; + +static +int +CheckPE32File ( + FILE *Fptr, + UINT16 *MachineType, + UINT16 *SubSystem + ) +/*++ + +Routine Description: + + Given the Argc/Argv program arguments, and a pointer to an options structure, + parse the command-line options and check their validity. + +Arguments: + + Argc - standard C main() argument count + Argv[] - standard C main() argument list + Options - pointer to a structure to store the options in + +Returns: + + STATUS_SUCCESS success + non-zero otherwise + +--*/ +; + +static +int +ProcessEfiFile ( + FILE *OutFptr, + FILE_LIST *InFile, + UINT16 VendId, + UINT16 DevId, + UINT32 *Size + ) +/*++ + +Routine Description: + + Process a PE32 EFI file. + +Arguments: + + OutFptr - file pointer to output binary ROM image file we're creating + InFile - structure contains information on the PE32 file to process + VendId - vendor ID as required in the option ROM header + DevId - device ID as required in the option ROM header + Size - pointer to where to return the size added to the output file + +Returns: + + 0 - successful + +--*/ +; + +static +int +ProcessBinFile ( + FILE *OutFptr, + FILE_LIST *InFile, + UINT32 *Size + ) +/*++ + +Routine Description: + + Process a binary input file. + +Arguments: + + OutFptr - file pointer to output binary ROM image file we're creating + InFile - structure contains information on the binary file to process + Size - pointer to where to return the size added to the output file + +Returns: + + 0 - successful + +--*/ +; + +static +void +DumpImage ( + FILE_LIST *InFile + ) +/*++ + +Routine Description: + + Dump the headers of an existing option ROM image + +Arguments: + + InFile - the file name of an existing option ROM image + +Returns: + + none + +--*/ +; + +char * +GetMachineTypeStr ( + UINT16 MachineType + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + MachineType - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +static +char * +GetSubsystemTypeStr ( + UINT16 SubsystemType + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + SubsystemType - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/GNUmakefile new file mode 100644 index 00000000..8b0e2c27 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/GNUmakefile @@ -0,0 +1,15 @@ +## @file +# GNU/Linux makefile for 'EfiRom' module build. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +MAKEROOT ?= .. + +APPNAME = EfiRom + +LIBS = -lCommon + +OBJECTS = EfiRom.o + +include $(MAKEROOT)/Makefiles/app.makefile diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/Makefile new file mode 100644 index 00000000..ab64084c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/Makefile @@ -0,0 +1,16 @@ +## @file +# Windows makefile for 'EfiRom' module build. +# +# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +!INCLUDE ..\Makefiles\ms.common + +APPNAME = EfiRom + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = EfiRom.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/Makefile.kmk new file mode 100644 index 00000000..29dd6c16 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/EfiRom/Makefile.kmk @@ -0,0 +1,45 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-makefile for the EFI EfiRom build tool. +# + +# +# Copyright (C) 2013-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# 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, in version 3 of the +# License. +# +# 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 . +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +SUB_DEPTH = ../../../../../../../../.. +include $(KBUILD_PATH)/subheader.kmk + +BLDPROGS += EfiRom +EfiRom_TEMPLATE = VBoxEfiBldProg +EfiRom_SOURCES = EfiRom.c + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GNUmakefile new file mode 100644 index 00000000..34031a4b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GNUmakefile @@ -0,0 +1,93 @@ +## @file +# GNU/Linux makefile for C tools build. +# +# Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +ifndef HOST_ARCH + # + # If HOST_ARCH is not defined, then we use 'uname -m' to attempt + # try to figure out the appropriate HOST_ARCH. + # + uname_m = $(shell uname -m) + $(info Attempting to detect HOST_ARCH from 'uname -m': $(uname_m)) + ifneq (,$(strip $(filter $(uname_m), x86_64 amd64))) + HOST_ARCH=X64 + endif + ifeq ($(patsubst i%86,IA32,$(uname_m)),IA32) + HOST_ARCH=IA32 + endif + ifneq (,$(findstring aarch64,$(uname_m))) + HOST_ARCH=AARCH64 + else ifneq (,$(findstring arm64,$(uname_m))) + HOST_ARCH=AARCH64 + else ifneq (,$(findstring arm,$(uname_m))) + HOST_ARCH=ARM + endif + ifneq (,$(findstring riscv64,$(uname_m))) + HOST_ARCH=RISCV64 + endif + ifndef HOST_ARCH + $(info Could not detected HOST_ARCH from uname results) + $(error HOST_ARCH is not defined!) + endif + $(info Detected HOST_ARCH of $(HOST_ARCH) using uname.) +endif + +export HOST_ARCH + +MAKEROOT = . + +include Makefiles/header.makefile + +all: makerootdir subdirs + @echo Finished building BaseTools C Tools with HOST_ARCH=$(HOST_ARCH) + +LIBRARIES = Common +VFRAUTOGEN = VfrCompile/VfrLexer.h +APPLICATIONS = \ + BrotliCompress \ + VfrCompile \ + EfiRom \ + GenFfs \ + GenFv \ + GenFw \ + GenSec \ + GenCrc32 \ + LzmaCompress \ + TianoCompress \ + VolInfo \ + DevicePath + +SUBDIRS := $(LIBRARIES) $(APPLICATIONS) + +$(LIBRARIES): $(MAKEROOT)/libs +$(APPLICATIONS): $(LIBRARIES) $(MAKEROOT)/bin $(VFRAUTOGEN) + +.PHONY: outputdirs +makerootdir: + -mkdir -p $(MAKEROOT) + +.PHONY: subdirs $(SUBDIRS) +subdirs: $(SUBDIRS) +$(SUBDIRS): + $(MAKE) -C $@ + +.PHONY: $(patsubst %,%-clean,$(sort $(SUBDIRS))) +$(patsubst %,%-clean,$(sort $(SUBDIRS))): + -$(MAKE) -C $(@:-clean=) clean + +$(VFRAUTOGEN): VfrCompile/VfrSyntax.g + $(MAKE) -C VfrCompile VfrLexer.h + +clean: $(patsubst %,%-clean,$(sort $(SUBDIRS))) + +clean: localClean + +localClean: + rm -f $(MAKEROOT)/bin/* + -rmdir $(MAKEROOT)/libs $(MAKEROOT)/bin + +include Makefiles/footer.makefile diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenCrc32/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenCrc32/GNUmakefile new file mode 100644 index 00000000..5c007d85 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenCrc32/GNUmakefile @@ -0,0 +1,15 @@ +## @file +# GNU/Linux makefile for 'GenCrc32' module build. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +MAKEROOT ?= .. + +APPNAME = GenCrc32 + +LIBS = -lCommon + +OBJECTS = GenCrc32.o + +include $(MAKEROOT)/Makefiles/app.makefile diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenCrc32/GenCrc32.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenCrc32/GenCrc32.c new file mode 100644 index 00000000..a33bd3d8 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenCrc32/GenCrc32.c @@ -0,0 +1,361 @@ +/** @file +Calculate Crc32 value and Verify Crc32 value for input data. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include + +#include "ParseInf.h" +#include "EfiUtilityMsgs.h" +#include "CommonLib.h" +#include "Crc32.h" + +#define UTILITY_NAME "GenCrc32" +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 2 + +#define CRC32_NULL 0 +#define CRC32_ENCODE 1 +#define CRC32_DECODE 2 + +VOID +Version ( + VOID + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION); +} + +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "Usage: GenCrc32 -e|-d [options] \n\n"); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n"); + + // + // Details Option + // + fprintf (stdout, "optional arguments:\n"); + fprintf (stdout, " -h, --help Show this help message and exit\n"); + fprintf (stdout, " --version Show program's version number and exit\n"); + fprintf (stdout, " --debug [DEBUG] Output DEBUG statements, where DEBUG_LEVEL is 0 (min)\n\ + - 9 (max)\n"); + fprintf (stdout, " -v, --verbose Print informational statements\n"); + fprintf (stdout, " -q, --quiet Returns the exit code, error messages will be\n\ + displayed\n"); + fprintf (stdout, " -s, --silent Returns only the exit code; informational and error\n\ + messages are not displayed\n"); + fprintf (stdout, " -e, --encode Calculate CRC32 value for the input file\n"); + fprintf (stdout, " -d, --decode Verify CRC32 value for the input file\n"); + fprintf (stdout, " -o OUTPUT_FILENAME, --output OUTPUT_FILENAME\n\ + Output file name\n"); + fprintf (stdout, " --sfo Reserved for future use\n"); + +} + +int +main ( + int argc, + CHAR8 *argv[] + ) +/*++ + +Routine Description: + + Main function. + +Arguments: + + argc - Number of command line parameters. + argv - Array of pointers to parameter strings. + +Returns: + STATUS_SUCCESS - Utility exits successfully. + STATUS_ERROR - Some error occurred during execution. + +--*/ +{ + EFI_STATUS Status; + CHAR8 *OutputFileName; + CHAR8 *InputFileName; + UINT8 *FileBuffer; + UINT32 FileSize; + UINT64 LogLevel; + UINT8 FileAction; + UINT32 Crc32Value; + FILE *InFile; + FILE *OutFile; + + // + // Init local variables + // + LogLevel = 0; + Status = EFI_SUCCESS; + InputFileName = NULL; + OutputFileName = NULL; + FileAction = CRC32_NULL; + InFile = NULL; + OutFile = NULL; + Crc32Value = 0; + FileBuffer = NULL; + + SetUtilityName (UTILITY_NAME); + + if (argc == 1) { + Error (NULL, 0, 1001, "Missing options", "no options input"); + Usage (); + return STATUS_ERROR; + } + + // + // Parse command line + // + argc --; + argv ++; + + if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) { + Usage (); + return STATUS_SUCCESS; + } + + if (stricmp (argv[0], "--version") == 0) { + Version (); + return STATUS_SUCCESS; + } + + while (argc > 0) { + if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Output File name is missing for -o option"); + goto Finish; + } + OutputFileName = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-e") == 0) || (stricmp (argv[0], "--encode") == 0)) { + FileAction = CRC32_ENCODE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--decode") == 0)) { + FileAction = CRC32_DECODE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) { + SetPrintLevel (VERBOSE_LOG_LEVEL); + VerboseMsg ("Verbose output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + SetPrintLevel (KEY_LOG_LEVEL); + KeyMsg ("Quiet output Mode Set!"); + argc --; + argv ++; + continue; + } + + if (stricmp (argv[0], "--debug") == 0) { + Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + if (LogLevel > 9) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel); + goto Finish; + } + SetPrintLevel (LogLevel); + DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]); + argc -= 2; + argv += 2; + continue; + } + + if (argv[0][0] == '-') { + Error (NULL, 0, 1000, "Unknown option", argv[0]); + goto Finish; + } + + // + // Get Input file file name. + // + InputFileName = argv[0]; + argc --; + argv ++; + } + + VerboseMsg ("%s tool start.", UTILITY_NAME); + + // + // Check Input parameters + // + if (FileAction == CRC32_NULL) { + Error (NULL, 0, 1001, "Missing option", "either the encode or the decode option must be specified!"); + return STATUS_ERROR; + } else if (FileAction == CRC32_ENCODE) { + VerboseMsg ("File will be encoded by Crc32"); + } else if (FileAction == CRC32_DECODE) { + VerboseMsg ("File will be decoded by Crc32"); + } + + if (InputFileName == NULL) { + Error (NULL, 0, 1001, "Missing option", "Input files are not specified"); + goto Finish; + } else { + VerboseMsg ("Input file name is %s", InputFileName); + } + + if (OutputFileName == NULL) { + Error (NULL, 0, 1001, "Missing option", "Output file are not specified"); + goto Finish; + } else { + VerboseMsg ("Output file name is %s", OutputFileName); + } + + // + // Open Input file and read file data. + // + InFile = fopen (LongFilePath (InputFileName), "rb"); + if (InFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", InputFileName); + return STATUS_ERROR; + } + + fseek (InFile, 0, SEEK_END); + FileSize = ftell (InFile); + fseek (InFile, 0, SEEK_SET); + + FileBuffer = (UINT8 *) malloc (FileSize); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + fclose (InFile); + goto Finish; + } + + fread (FileBuffer, 1, FileSize, InFile); + fclose (InFile); + VerboseMsg ("the size of the input file is %u bytes", (unsigned) FileSize); + + // + // Open output file + // + OutFile = fopen (LongFilePath (OutputFileName), "wb"); + if (OutFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", OutputFileName); + goto Finish; + } + + // + // Calculate Crc32 value + // + if (FileAction == CRC32_ENCODE) { + Status = CalculateCrc32 (FileBuffer, FileSize, &Crc32Value); + if (Status != EFI_SUCCESS) { + Error (NULL, 0, 3000, "Invalid", "Calculate CRC32 value failed!"); + goto Finish; + } + // + // Done, write output file. + // + fwrite (&Crc32Value, 1, sizeof (Crc32Value), OutFile); + VerboseMsg ("The calculated CRC32 value is 0x%08x", (unsigned) Crc32Value); + fwrite (FileBuffer, 1, FileSize, OutFile); + VerboseMsg ("the size of the encoded file is %u bytes", (unsigned) FileSize + sizeof (UINT32)); + } else { + // + // Verify Crc32 Value + // + if (FileSize < sizeof (UINT32)) { + Error (NULL, 0, 3000, "Invalid", "Input file is invalid!"); + goto Finish; + } + Status = CalculateCrc32 (FileBuffer + sizeof (UINT32), FileSize - sizeof (UINT32), &Crc32Value); + if (Status != EFI_SUCCESS) { + Error (NULL, 0, 3000, "Invalid", "Calculate CRC32 value failed!"); + goto Finish; + } + VerboseMsg ("The calculated CRC32 value is 0x%08x and File Crc32 value is 0x%08x", (unsigned) Crc32Value, (unsigned) (*(UINT32 *)FileBuffer)); + if (Crc32Value != *(UINT32 *)FileBuffer) { + Error (NULL, 0, 3000, "Invalid", "CRC32 value of input file is not correct!"); + Status = STATUS_ERROR; + goto Finish; + } + // + // Done, write output file. + // + fwrite (FileBuffer + sizeof (UINT32), 1, FileSize - sizeof (UINT32), OutFile); + VerboseMsg ("the size of the decoded file is %u bytes", (unsigned) FileSize - sizeof (UINT32)); + } + +Finish: + if (FileBuffer != NULL) { + free (FileBuffer); + } + + if (OutFile != NULL) { + fclose (OutFile); + } + + VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ()); + + return GetUtilityStatus (); +} + + + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenCrc32/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenCrc32/Makefile new file mode 100644 index 00000000..e3b6bcd7 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenCrc32/Makefile @@ -0,0 +1,16 @@ +## @file +# Windows makefile for 'GenCrc32' module build. +# +# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenCrc32 + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = GenCrc32.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenCrc32/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenCrc32/Makefile.kmk new file mode 100644 index 00000000..51243288 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenCrc32/Makefile.kmk @@ -0,0 +1,45 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-makefile for the EFI GenCrc32 build tool. +# + +# +# Copyright (C) 2013-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# 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, in version 3 of the +# License. +# +# 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 . +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +SUB_DEPTH = ../../../../../../../../.. +include $(KBUILD_PATH)/subheader.kmk + +BLDPROGS += GenCrc32 +GenCrc32_TEMPLATE = VBoxEfiBldProg +GenCrc32_SOURCES = GenCrc32.c + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/GNUmakefile new file mode 100644 index 00000000..804d8540 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/GNUmakefile @@ -0,0 +1,16 @@ +## @file +# GNU/Linux makefile for 'GenFfs' module build. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +MAKEROOT ?= .. + +APPNAME = GenFfs + +OBJECTS = GenFfs.o + +include $(MAKEROOT)/Makefiles/app.makefile + +LIBS = -lCommon + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/GenFfs.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/GenFfs.c new file mode 100644 index 00000000..28066c2b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/GenFfs.c @@ -0,0 +1,1120 @@ +/** @file +This file contains functions required to generate a Firmware File System file. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __GNUC__ +# ifdef VBOX +// RUNTIME_FUNCTION typedef conflicts; just use EFI headers +# else +#include +# endif +#include +#include +#include +#endif + +#ifdef __GNUC__ +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include + +#include "CommonLib.h" +#include "ParseInf.h" +#include "EfiUtilityMsgs.h" +#include "FvLib.h" +#include "PeCoffLib.h" + +#define UTILITY_NAME "GenFfs" +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +STATIC CHAR8 *mFfsFileType[] = { + NULL, // 0x00 + "EFI_FV_FILETYPE_RAW", // 0x01 + "EFI_FV_FILETYPE_FREEFORM", // 0x02 + "EFI_FV_FILETYPE_SECURITY_CORE", // 0x03 + "EFI_FV_FILETYPE_PEI_CORE", // 0x04 + "EFI_FV_FILETYPE_DXE_CORE", // 0x05 + "EFI_FV_FILETYPE_PEIM", // 0x06 + "EFI_FV_FILETYPE_DRIVER", // 0x07 + "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER", // 0x08 + "EFI_FV_FILETYPE_APPLICATION", // 0x09 + "EFI_FV_FILETYPE_SMM", // 0x0A + "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE",// 0x0B + "EFI_FV_FILETYPE_COMBINED_SMM_DXE", // 0x0C + "EFI_FV_FILETYPE_SMM_CORE", // 0x0D + "EFI_FV_FILETYPE_MM_STANDALONE", // 0x0E + "EFI_FV_FILETYPE_MM_CORE_STANDALONE" // 0x0F +}; + +STATIC CHAR8 *mAlignName[] = { + "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", + "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", + "512K", "1M", "2M", "4M", "8M", "16M" + }; + +STATIC CHAR8 *mFfsValidAlignName[] = { + "8", "16", "128", "512", "1K", "4K", "32K", "64K", "128K","256K", + "512K", "1M", "2M", "4M", "8M", "16M" + }; + +STATIC UINT32 mFfsValidAlign[] = {0, 8, 16, 128, 512, 1024, 4096, 32768, 65536, 131072, 262144, + 524288, 1048576, 2097152, 4194304, 8388608, 16777216}; + +STATIC EFI_GUID mZeroGuid = {0}; + +STATIC EFI_GUID mEfiFfsSectionAlignmentPaddingGuid = EFI_FFS_SECTION_ALIGNMENT_PADDING_GUID; + +STATIC +VOID +Version ( + VOID + ) +/*++ + +Routine Description: + + Print out version information for this utility. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION); +} + +STATIC +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Print Error / Help message. + +Arguments: + + VOID + +Returns: + + None + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "\nUsage: %s [options]\n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n"); + + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " -o FileName, --outputfile FileName\n\ + File is FFS file to be created.\n"); + fprintf (stdout, " -t Type, --filetype Type\n\ + Type is one FV file type defined in PI spec, which is\n\ + EFI_FV_FILETYPE_RAW, EFI_FV_FILETYPE_FREEFORM,\n\ + EFI_FV_FILETYPE_SECURITY_CORE, EFI_FV_FILETYPE_PEIM,\n\ + EFI_FV_FILETYPE_PEI_CORE, EFI_FV_FILETYPE_DXE_CORE,\n\ + EFI_FV_FILETYPE_DRIVER, EFI_FV_FILETYPE_APPLICATION,\n\ + EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER,\n\ + EFI_FV_FILETYPE_SMM, EFI_FV_FILETYPE_SMM_CORE,\n\ + EFI_FV_FILETYPE_MM_STANDALONE,\n\ + EFI_FV_FILETYPE_MM_CORE_STANDALONE,\n\ + EFI_FV_FILETYPE_COMBINED_SMM_DXE, \n\ + EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE.\n"); + fprintf (stdout, " -g FileGuid, --fileguid FileGuid\n\ + FileGuid is one module guid.\n\ + Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"); + fprintf (stdout, " -x, --fixed Indicates that the file may not be moved\n\ + from its present location.\n"); + fprintf (stdout, " -s, --checksum Indicates to calculate file checksum.\n"); + fprintf (stdout, " -a FileAlign, --align FileAlign\n\ + FileAlign points to file alignment, which only support\n\ + the following align: 1,2,4,8,16,128,512,1K,4K,32K,64K\n\ + 128K,256K,512K,1M,2M,4M,8M,16M\n"); + fprintf (stdout, " -i SectionFile, --sectionfile SectionFile\n\ + Section file will be contained in this FFS file.\n"); + fprintf (stdout, " -oi SectionFile, --optionalsectionfile SectionFile\n\ + If the Section file exists, it will be contained in this FFS file, otherwise, it will be ignored.\n"); + fprintf (stdout, " -n SectionAlign, --sectionalign SectionAlign\n\ + SectionAlign points to section alignment, which support\n\ + the alignment scope 0~16M. If SectionAlign is specified\n\ + as 0, tool get alignment value from SectionFile. It is\n\ + specified together with sectionfile to point its\n\ + alignment in FFS file.\n"); + fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n"); + fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n"); + fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n"); + fprintf (stdout, " --version Show program's version number and exit.\n"); + fprintf (stdout, " -h, --help Show this help message and exit.\n"); +} + +STATIC +EFI_STATUS +StringtoAlignment ( + IN CHAR8 *AlignBuffer, + OUT UINT32 *AlignNumber + ) +/*++ + +Routine Description: + + Converts Align String to align value (1~16M). + +Arguments: + + AlignBuffer - Pointer to Align string. + AlignNumber - Pointer to Align value. + +Returns: + + EFI_SUCCESS Successfully convert align string to align value. + EFI_INVALID_PARAMETER Align string is invalid or align value is not in scope. + +--*/ +{ + UINT32 Index = 0; + // + // Check AlignBuffer + // + if (AlignBuffer == NULL) { + return EFI_INVALID_PARAMETER; + } + for (Index = 0; Index < sizeof (mAlignName) / sizeof (CHAR8 *); Index ++) { + if (stricmp (AlignBuffer, mAlignName [Index]) == 0) { + *AlignNumber = 1 << Index; + return EFI_SUCCESS; + } + } + return EFI_INVALID_PARAMETER; +} + +STATIC +UINT8 +StringToType ( + IN CHAR8 *String + ) +/*++ + +Routine Description: + + Converts File Type String to value. EFI_FV_FILETYPE_ALL indicates that an + unrecognized file type was specified. + +Arguments: + + String - File type string + +Returns: + + File Type Value + +--*/ +{ + UINT8 Index = 0; + + if (String == NULL) { + return EFI_FV_FILETYPE_ALL; + } + + for (Index = 0; Index < sizeof (mFfsFileType) / sizeof (CHAR8 *); Index ++) { + if (mFfsFileType [Index] != NULL && (stricmp (String, mFfsFileType [Index]) == 0)) { + return Index; + } + } + return EFI_FV_FILETYPE_ALL; +} + +STATIC +EFI_STATUS +GetSectionContents ( + IN CHAR8 **InputFileName, + IN UINT32 *InputFileAlign, + IN UINT32 InputFileNum, + IN EFI_FFS_FILE_ATTRIBUTES FfsAttrib, + OUT UINT8 *FileBuffer, + OUT UINT32 *BufferLength, + OUT UINT32 *MaxAlignment, + OUT UINT8 *PESectionNum + ) +/*++ + +Routine Description: + + Get the contents of all section files specified in InputFileName + into FileBuffer. + +Arguments: + + InputFileName - Name of the input file. + + InputFileAlign - Alignment required by the input file data. + + InputFileNum - Number of input files. Should be at least 1. + + FileBuffer - Output buffer to contain data + + BufferLength - On input, this is size of the FileBuffer. + On output, this is the actual length of the data. + + MaxAlignment - The max alignment required by all the input file datas. + + PeSectionNum - Calculate the number of Pe/Te Section in this FFS file. + +Returns: + + EFI_SUCCESS on successful return + EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL. + EFI_ABORTED if unable to open input file. + EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data. +--*/ +{ + UINT32 Size; + UINT32 Offset; + UINT32 FileSize; + UINT32 Index; + FILE *InFile; + EFI_FREEFORM_SUBTYPE_GUID_SECTION *SectHeader; + EFI_COMMON_SECTION_HEADER2 TempSectHeader; + EFI_TE_IMAGE_HEADER TeHeader; + UINT32 TeOffset; + EFI_GUID_DEFINED_SECTION GuidSectHeader; + EFI_GUID_DEFINED_SECTION2 GuidSectHeader2; + UINT32 HeaderSize; + UINT32 MaxEncounteredAlignment; + + Size = 0; + Offset = 0; + TeOffset = 0; + MaxEncounteredAlignment = 1; + + // + // Go through our array of file names and copy their contents + // to the output buffer. + // + for (Index = 0; Index < InputFileNum; Index++) { + // + // make sure section ends on a DWORD boundary + // + while ((Size & 0x03) != 0) { + Size++; + } + + // + // Open file and read contents + // + InFile = fopen (LongFilePath (InputFileName[Index]), "rb"); + if (InFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", InputFileName[Index]); + return EFI_ABORTED; + } + + fseek (InFile, 0, SEEK_END); + FileSize = ftell (InFile); + fseek (InFile, 0, SEEK_SET); + DebugMsg (NULL, 0, 9, "Input section files", + "the input section name is %s and the size is %u bytes", InputFileName[Index], (unsigned) FileSize); + + // + // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section. + // + TeOffset = 0; + if (FileSize >= MAX_FFS_SIZE) { + HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2); + } else { + HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER); + } + fread (&TempSectHeader, 1, HeaderSize, InFile); + if (TempSectHeader.Type == EFI_SECTION_TE) { + (*PESectionNum) ++; + fread (&TeHeader, 1, sizeof (TeHeader), InFile); + if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + TeOffset = TeHeader.StrippedSize - sizeof (TeHeader); + } + } else if (TempSectHeader.Type == EFI_SECTION_PE32) { + (*PESectionNum) ++; + } else if (TempSectHeader.Type == EFI_SECTION_GUID_DEFINED) { + fseek (InFile, 0, SEEK_SET); + if (FileSize >= MAX_SECTION_SIZE) { + fread (&GuidSectHeader2, 1, sizeof (GuidSectHeader2), InFile); + if ((GuidSectHeader2.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) { + HeaderSize = GuidSectHeader2.DataOffset; + } + } else { + fread (&GuidSectHeader, 1, sizeof (GuidSectHeader), InFile); + if ((GuidSectHeader.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) { + HeaderSize = GuidSectHeader.DataOffset; + } + } + (*PESectionNum) ++; + } else if (TempSectHeader.Type == EFI_SECTION_COMPRESSION || + TempSectHeader.Type == EFI_SECTION_FIRMWARE_VOLUME_IMAGE) { + // + // for the encapsulated section, assume it contains Pe/Te section + // + (*PESectionNum) ++; + } + + fseek (InFile, 0, SEEK_SET); + + // + // Revert TeOffset to the converse value relative to Alignment + // This is to assure the original PeImage Header at Alignment. + // + if ((TeOffset != 0) && (InputFileAlign [Index] != 0)) { + TeOffset = InputFileAlign [Index] - (TeOffset % InputFileAlign [Index]); + TeOffset = TeOffset % InputFileAlign [Index]; + } + + // + // make sure section data meet its alignment requirement by adding one pad section. + // But the different sections have the different section header. Necessary or not? + // Based on section type to adjust offset? Todo + // + if ((InputFileAlign [Index] != 0) && (((Size + HeaderSize + TeOffset) % InputFileAlign [Index]) != 0)) { + Offset = (Size + sizeof (EFI_COMMON_SECTION_HEADER) + HeaderSize + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1); + Offset = Offset - Size - HeaderSize - TeOffset; + + if (FileBuffer != NULL && ((Size + Offset) < *BufferLength)) { + // + // The maximal alignment is 64K, the raw section size must be less than 0xffffff + // + memset (FileBuffer + Size, 0, Offset); + SectHeader = (EFI_FREEFORM_SUBTYPE_GUID_SECTION *) (FileBuffer + Size); + SectHeader->CommonHeader.Size[0] = (UINT8) (Offset & 0xff); + SectHeader->CommonHeader.Size[1] = (UINT8) ((Offset & 0xff00) >> 8); + SectHeader->CommonHeader.Size[2] = (UINT8) ((Offset & 0xff0000) >> 16); + + // + // Only add a special reducible padding section if + // - this FFS has the FFS_ATTRIB_FIXED attribute, + // - none of the preceding sections have alignment requirements, + // - the size of the padding is sufficient for the + // EFI_SECTION_FREEFORM_SUBTYPE_GUID header. + // + if ((FfsAttrib & FFS_ATTRIB_FIXED) != 0 && + MaxEncounteredAlignment <= 1 && + Offset >= sizeof (EFI_FREEFORM_SUBTYPE_GUID_SECTION)) { + SectHeader->CommonHeader.Type = EFI_SECTION_FREEFORM_SUBTYPE_GUID; + SectHeader->SubTypeGuid = mEfiFfsSectionAlignmentPaddingGuid; + } else { + SectHeader->CommonHeader.Type = EFI_SECTION_RAW; + } + } + DebugMsg (NULL, 0, 9, "Pad raw section for section data alignment", + "Pad Raw section size is %u", (unsigned) Offset); + + Size = Size + Offset; + } + + // + // Get the Max alignment of all input file datas + // + if (MaxEncounteredAlignment < InputFileAlign [Index]) { + MaxEncounteredAlignment = InputFileAlign [Index]; + } + + // + // Now read the contents of the file into the buffer + // Buffer must be enough to contain the file content. + // + if ((FileSize > 0) && (FileBuffer != NULL) && ((Size + FileSize) <= *BufferLength)) { + if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) { + Error (NULL, 0, 0004, "Error reading file", InputFileName[Index]); + fclose (InFile); + return EFI_ABORTED; + } + } + + fclose (InFile); + Size += FileSize; + } + + *MaxAlignment = MaxEncounteredAlignment; + + // + // Set the actual length of the data. + // + if (Size > *BufferLength) { + *BufferLength = Size; + return EFI_BUFFER_TOO_SMALL; + } else { + *BufferLength = Size; + return EFI_SUCCESS; + } +} + +EFI_STATUS +FfsRebaseImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINT32 *ReadSize, + OUT VOID *Buffer + ) + /*++ + + Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + + Arguments: + + FileHandle - The handle to the PE/COFF file + + FileOffset - The offset, in bytes, into the file to read + + ReadSize - The number of bytes to read from the file starting at FileOffset + + Buffer - A pointer to the buffer to read the data into. + + Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + + --*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + UINT32 Length; + + Destination8 = Buffer; + Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); + Length = *ReadSize; + while (Length--) { + *(Destination8++) = *(Source8++); + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +GetAlignmentFromFile(char *InFile, UINT32 *Alignment) + /*++ + InFile is input file for getting alignment + return the alignment + --*/ +{ + FILE *InFileHandle; + UINT8 *PeFileBuffer; + UINTN PeFileSize; + UINT32 CurSecHdrSize; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + EFI_COMMON_SECTION_HEADER *CommonHeader; + EFI_STATUS Status; + + InFileHandle = NULL; + PeFileBuffer = NULL; + *Alignment = 0; + + memset (&ImageContext, 0, sizeof (ImageContext)); + + InFileHandle = fopen(LongFilePath(InFile), "rb"); + if (InFileHandle == NULL){ + Error (NULL, 0, 0001, "Error opening file", InFile); + return EFI_ABORTED; + } + PeFileSize = _filelength (fileno(InFileHandle)); + PeFileBuffer = (UINT8 *) malloc (PeFileSize); + if (PeFileBuffer == NULL) { + fclose (InFileHandle); + Error(NULL, 0, 4001, "Resource", "memory cannot be allocated of %s", InFileHandle); + return EFI_OUT_OF_RESOURCES; + } + fread (PeFileBuffer, sizeof (UINT8), PeFileSize, InFileHandle); + fclose (InFileHandle); + CommonHeader = (EFI_COMMON_SECTION_HEADER *) PeFileBuffer; + CurSecHdrSize = GetSectionHeaderLength(CommonHeader); + ImageContext.Handle = (VOID *) ((UINTN)PeFileBuffer + CurSecHdrSize); + ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)FfsRebaseImageRead; + Status = PeCoffLoaderGetImageInfo(&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and return status is %x", InFile, (int) Status); + return Status; + } + *Alignment = ImageContext.SectionAlignment; + // Free the allocated memory resource + if (PeFileBuffer != NULL) { + free (PeFileBuffer); + PeFileBuffer = NULL; + } + return EFI_SUCCESS; +} + +int +main ( + int argc, + CHAR8 *argv[] + ) +/*++ + +Routine Description: + + Main function. + +Arguments: + + argc - Number of command line parameters. + argv - Array of pointers to parameter strings. + +Returns: + STATUS_SUCCESS - Utility exits successfully. + STATUS_ERROR - Some error occurred during execution. + +--*/ +{ + EFI_STATUS Status; + EFI_FFS_FILE_ATTRIBUTES FfsAttrib; + UINT32 FfsAlign; + EFI_FV_FILETYPE FfsFiletype; + CHAR8 *OutputFileName; + EFI_GUID FileGuid = {0}; + UINT32 InputFileNum; + UINT32 *InputFileAlign; + CHAR8 **InputFileName; + UINT8 *FileBuffer; + UINT32 FileSize; + UINT32 MaxAlignment; + EFI_FFS_FILE_HEADER2 FfsFileHeader; + FILE *FfsFile; + UINT32 Index; + UINT64 LogLevel; + UINT8 PeSectionNum; + UINT32 HeaderSize; + UINT32 Alignment; + // + // Workaround for static code checkers. + // Ensures the size of 'AlignmentBuffer' can hold all the digits of an + // unsigned 32-bit integer plus the size unit character. + // + CHAR8 AlignmentBuffer[16]; + + // + // Init local variables + // + LogLevel = 0; + Index = 0; + FfsAttrib = 0; + FfsAlign = 0; + FfsFiletype = EFI_FV_FILETYPE_ALL; + OutputFileName = NULL; + InputFileNum = 0; + InputFileName = NULL; + InputFileAlign = NULL; + FileBuffer = NULL; + FileSize = 0; + MaxAlignment = 1; + FfsFile = NULL; + Status = EFI_SUCCESS; + PeSectionNum = 0; + + SetUtilityName (UTILITY_NAME); + + if (argc == 1) { + Error (NULL, 0, 1001, "Missing options", "no options input"); + Usage (); + return STATUS_ERROR; + } + + // + // Parse command line + // + argc --; + argv ++; + + if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) { + Version (); + Usage (); + return STATUS_SUCCESS; + } + + if (stricmp (argv[0], "--version") == 0) { + Version (); + return STATUS_SUCCESS; + } + + while (argc > 0) { + if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--filetype") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "file type is missing for -t option"); + goto Finish; + } + FfsFiletype = StringToType (argv[1]); + if (FfsFiletype == EFI_FV_FILETYPE_ALL) { + Error (NULL, 0, 1003, "Invalid option value", "%s is not a valid file type", argv[1]); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Output file is missing for -o option"); + goto Finish; + } + OutputFileName = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--fileguid") == 0)) { + Status = StringToGuid (argv[1], &FileGuid); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-x") == 0) || (stricmp (argv[0], "--fixed") == 0)) { + FfsAttrib |= FFS_ATTRIB_FIXED; + argc -= 1; + argv += 1; + continue; + } + + if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--checksum") == 0)) { + FfsAttrib |= FFS_ATTRIB_CHECKSUM; + argc -= 1; + argv += 1; + continue; + } + + if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--align") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Align value is missing for -a option"); + goto Finish; + } + for (Index = 0; Index < sizeof (mFfsValidAlignName) / sizeof (CHAR8 *); Index ++) { + if (stricmp (argv[1], mFfsValidAlignName[Index]) == 0) { + break; + } + } + if (Index == sizeof (mFfsValidAlignName) / sizeof (CHAR8 *)) { + if ((stricmp (argv[1], "1") == 0) || (stricmp (argv[1], "2") == 0) || (stricmp (argv[1], "4") == 0)) { + // + // 1, 2, 4 byte alignment same to 8 byte alignment + // + Index = 0; + } else { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + } + FfsAlign = Index; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-oi") == 0) || (stricmp (argv[0], "--optionalsectionfile") == 0) || (stricmp (argv[0], "-i") == 0) || (stricmp (argv[0], "--sectionfile") == 0)) { + // + // Get Input file name and its alignment + // + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "input section file is missing for -i option"); + goto Finish; + } + if ((stricmp (argv[0], "-oi") == 0) || (stricmp (argv[0], "--optionalsectionfile") == 0) ){ + if (-1 == access(argv[1] , 0)){ + Warning(NULL, 0, 0001, "File is not found.", argv[1]); + argc -= 2; + argv += 2; + continue; + } + } + // + // Allocate Input file name buffer and its alignment buffer. + // + if ((InputFileNum == 0) && (InputFileName == NULL)) { + InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)); + if (InputFileName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return STATUS_ERROR; + } + memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *))); + + InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)); + if (InputFileAlign == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + free (InputFileName); + return STATUS_ERROR; + } + memset (InputFileAlign, 0, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)); + } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) { + // + // InputFileName and alignment buffer too small, need to realloc + // + InputFileName = (CHAR8 **) realloc ( + InputFileName, + (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *) + ); + + if (InputFileName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + free (InputFileAlign); + return STATUS_ERROR; + } + memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *))); + + InputFileAlign = (UINT32 *) realloc ( + InputFileAlign, + (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32) + ); + + if (InputFileAlign == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + free (InputFileName); + return STATUS_ERROR; + } + memset (&(InputFileAlign[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32))); + } + + InputFileName[InputFileNum] = argv[1]; + argc -= 2; + argv += 2; + + if (argc <= 0) { + InputFileNum ++; + break; + } + + // + // Section File alignment requirement + // + if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--sectionalign") == 0)) { + if ((argv[1] != NULL) && (stricmp("0", argv[1]) == 0)) { + Status = GetAlignmentFromFile(InputFileName[InputFileNum], &Alignment); + if (EFI_ERROR(Status)) { + Error (NULL, 0, 1003, "Fail to get Alignment from %s", InputFileName[InputFileNum]); + goto Finish; + } + if (Alignment < 0x400){ + sprintf (AlignmentBuffer, "%d", Alignment); + } + else if (Alignment >= 0x100000) { + sprintf (AlignmentBuffer, "%dM", Alignment/0x100000); + } + else { + sprintf (AlignmentBuffer, "%dK", Alignment/0x400); + } + Status = StringtoAlignment (AlignmentBuffer, &(InputFileAlign[InputFileNum])); + } + else { + Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileNum])); + } + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + argc -= 2; + argv += 2; + } + InputFileNum ++; + continue; + } + + if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--sectionalign") == 0)) { + Error (NULL, 0, 1000, "Unknown option", "SectionAlign option must be specified with section file."); + goto Finish; + } + + if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) { + SetPrintLevel (VERBOSE_LOG_LEVEL); + VerboseMsg ("Verbose output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + SetPrintLevel (KEY_LOG_LEVEL); + KeyMsg ("Quiet output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + if (LogLevel > 9) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel); + goto Finish; + } + SetPrintLevel (LogLevel); + DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]); + argc -= 2; + argv += 2; + continue; + } + + Error (NULL, 0, 1000, "Unknown option", "%s", argv[0]); + goto Finish; + } + + VerboseMsg ("%s tool start.", UTILITY_NAME); + + // + // Check the complete input parameters. + // + if (FfsFiletype == EFI_FV_FILETYPE_ALL) { + Error (NULL, 0, 1001, "Missing option", "filetype"); + goto Finish; + } + + if (CompareGuid (&FileGuid, &mZeroGuid) == 0) { + Error (NULL, 0, 1001, "Missing option", "fileguid"); + goto Finish; + } + + if (InputFileNum == 0) { + Error (NULL, 0, 1001, "Missing option", "Input files"); + goto Finish; + } + + // + // Output input parameter information + // + VerboseMsg ("Fv File type is %s", mFfsFileType [FfsFiletype]); + VerboseMsg ("Output file name is %s", OutputFileName); + VerboseMsg ("FFS File Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + (unsigned) FileGuid.Data1, + FileGuid.Data2, + FileGuid.Data3, + FileGuid.Data4[0], + FileGuid.Data4[1], + FileGuid.Data4[2], + FileGuid.Data4[3], + FileGuid.Data4[4], + FileGuid.Data4[5], + FileGuid.Data4[6], + FileGuid.Data4[7]); + if ((FfsAttrib & FFS_ATTRIB_FIXED) != 0) { + VerboseMsg ("FFS File has the fixed file attribute"); + } + if ((FfsAttrib & FFS_ATTRIB_CHECKSUM) != 0) { + VerboseMsg ("FFS File requires the checksum of the whole file"); + } + VerboseMsg ("FFS file alignment is %s", mFfsValidAlignName[FfsAlign]); + for (Index = 0; Index < InputFileNum; Index ++) { + if (InputFileAlign[Index] == 0) { + // + // Minimum alignment is 1 byte. + // + InputFileAlign[Index] = 1; + } + VerboseMsg ("the %dth input section name is %s and section alignment is %u", Index, InputFileName[Index], (unsigned) InputFileAlign[Index]); + } + + // + // Calculate the size of all input section files. + // + Status = GetSectionContents ( + InputFileName, + InputFileAlign, + InputFileNum, + FfsAttrib, + FileBuffer, + &FileSize, + &MaxAlignment, + &PeSectionNum + ); + + if ((FfsFiletype == EFI_FV_FILETYPE_SECURITY_CORE || + FfsFiletype == EFI_FV_FILETYPE_PEI_CORE || + FfsFiletype == EFI_FV_FILETYPE_DXE_CORE) && (PeSectionNum != 1)) { + Error (NULL, 0, 2000, "Invalid parameter", "Fv File type %s must have one and only one Pe or Te section, but %u Pe/Te section are input", mFfsFileType [FfsFiletype], PeSectionNum); + goto Finish; + } + + if ((FfsFiletype == EFI_FV_FILETYPE_PEIM || + FfsFiletype == EFI_FV_FILETYPE_DRIVER || + FfsFiletype == EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER || + FfsFiletype == EFI_FV_FILETYPE_APPLICATION) && (PeSectionNum < 1)) { + Error (NULL, 0, 2000, "Invalid parameter", "Fv File type %s must have at least one Pe or Te section, but no Pe/Te section is input", mFfsFileType [FfsFiletype]); + goto Finish; + } + + if (Status == EFI_BUFFER_TOO_SMALL) { + FileBuffer = (UINT8 *) malloc (FileSize); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + goto Finish; + } + memset (FileBuffer, 0, FileSize); + + // + // read all input file contents into a buffer + // + Status = GetSectionContents ( + InputFileName, + InputFileAlign, + InputFileNum, + FfsAttrib, + FileBuffer, + &FileSize, + &MaxAlignment, + &PeSectionNum + ); + } + + if (EFI_ERROR (Status)) { + goto Finish; + } + + if (FileBuffer == NULL && FileSize != 0) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + goto Finish; + } + + // + // Create Ffs file header. + // + memset (&FfsFileHeader, 0, sizeof (EFI_FFS_FILE_HEADER2)); + memcpy (&FfsFileHeader.Name, &FileGuid, sizeof (EFI_GUID)); + FfsFileHeader.Type = FfsFiletype; + // + // Update FFS Alignment based on the max alignment required by input section files + // + VerboseMsg ("the max alignment of all input sections is %u", (unsigned) MaxAlignment); + for (Index = 0; Index < sizeof (mFfsValidAlign) / sizeof (UINT32) - 1; Index ++) { + if ((MaxAlignment > mFfsValidAlign [Index]) && (MaxAlignment <= mFfsValidAlign [Index + 1])) { + break; + } + } + if (FfsAlign < Index) { + FfsAlign = Index; + } + VerboseMsg ("the alignment of the generated FFS file is %u", (unsigned) mFfsValidAlign [FfsAlign + 1]); + + // + // Now FileSize includes the EFI_FFS_FILE_HEADER + // + if (FileSize + sizeof (EFI_FFS_FILE_HEADER) >= MAX_FFS_SIZE) { + HeaderSize = sizeof (EFI_FFS_FILE_HEADER2); + FileSize += sizeof (EFI_FFS_FILE_HEADER2); + FfsFileHeader.ExtendedSize = FileSize; + memset(FfsFileHeader.Size, 0, sizeof (UINT8) * 3); + FfsAttrib |= FFS_ATTRIB_LARGE_FILE; + } else { + HeaderSize = sizeof (EFI_FFS_FILE_HEADER); + FileSize += sizeof (EFI_FFS_FILE_HEADER); + FfsFileHeader.Size[0] = (UINT8) (FileSize & 0xFF); + FfsFileHeader.Size[1] = (UINT8) ((FileSize & 0xFF00) >> 8); + FfsFileHeader.Size[2] = (UINT8) ((FileSize & 0xFF0000) >> 16); + } + VerboseMsg ("the size of the generated FFS file is %u bytes", (unsigned) FileSize); + + //FfsAlign larger than 7, set FFS_ATTRIB_DATA_ALIGNMENT2 + if (FfsAlign < 8) { + FfsFileHeader.Attributes = (EFI_FFS_FILE_ATTRIBUTES) (FfsAttrib | (FfsAlign << 3)); + } else { + FfsFileHeader.Attributes = (EFI_FFS_FILE_ATTRIBUTES) (FfsAttrib | ((FfsAlign & 0x7) << 3) | FFS_ATTRIB_DATA_ALIGNMENT2); + } + + // + // Fill in checksums and state, these must be zero for checksumming + // + // FileHeader.IntegrityCheck.Checksum.Header = 0; + // FileHeader.IntegrityCheck.Checksum.File = 0; + // FileHeader.State = 0; + // + FfsFileHeader.IntegrityCheck.Checksum.Header = CalculateChecksum8 ( + (UINT8 *) &FfsFileHeader, + HeaderSize + ); + + if (FfsFileHeader.Attributes & FFS_ATTRIB_CHECKSUM) { + // + // Ffs header checksum = zero, so only need to calculate ffs body. + // + FfsFileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 ( + FileBuffer, + FileSize - HeaderSize + ); + } else { + FfsFileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + + FfsFileHeader.State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID; + + // + // Open output file to write ffs data. + // + if (OutputFileName != NULL) { + remove(OutputFileName); + FfsFile = fopen (LongFilePath (OutputFileName), "wb"); + if (FfsFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", OutputFileName); + goto Finish; + } + // + // write header + // + fwrite (&FfsFileHeader, 1, HeaderSize, FfsFile); + // + // write data + // + if (FileBuffer != NULL) { + fwrite (FileBuffer, 1, FileSize - HeaderSize, FfsFile); + } + + fclose (FfsFile); + } + +Finish: + if (InputFileName != NULL) { + free (InputFileName); + } + if (InputFileAlign != NULL) { + free (InputFileAlign); + } + if (FileBuffer != NULL) { + free (FileBuffer); + } + // + // If any errors were reported via the standard error reporting + // routines, then the status has been saved. Get the value and + // return it to the caller. + // + VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ()); + + return GetUtilityStatus (); +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/Makefile new file mode 100644 index 00000000..1f805241 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/Makefile @@ -0,0 +1,16 @@ +## @file +# Windows makefile for 'GenFfs' module build. +# +# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenFfs + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = GenFfs.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/Makefile.kmk new file mode 100644 index 00000000..8a200b35 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFfs/Makefile.kmk @@ -0,0 +1,45 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-makefile for the EFI GenFfs build tool. +# + +# +# Copyright (C) 2013-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# 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, in version 3 of the +# License. +# +# 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 . +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +SUB_DEPTH = ../../../../../../../../.. +include $(KBUILD_PATH)/subheader.kmk + +BLDPROGS += GenFfs +GenFfs_TEMPLATE = VBoxEfiBldProg +GenFfs_SOURCES = GenFfs.c + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GNUmakefile new file mode 100644 index 00000000..608d9b48 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GNUmakefile @@ -0,0 +1,23 @@ +## @file +# GNU/Linux makefile for 'GenFv' module build. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +MAKEROOT ?= .. + +APPNAME = GenFv + +OBJECTS = GenFv.o GenFvInternalLib.o + +include $(MAKEROOT)/Makefiles/app.makefile + +LIBS = -lCommon +ifeq ($(CYGWIN), CYGWIN) + LIBS += -L/lib/e2fsprogs -luuid +endif + +ifeq ($(LINUX), Linux) + LIBS += -luuid +endif + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GenFv.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GenFv.c new file mode 100644 index 00000000..21b0a392 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GenFv.c @@ -0,0 +1,696 @@ +/** @file + This contains all code necessary to build the GenFvImage.exe utility. + This utility relies heavily on the GenFvImage Lib. Definitions for both + can be found in the Tiano Firmware Volume Generation Utility + Specification, review draft. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +// +// File included in build +// +#include +#include +#include +#include "GenFvInternalLib.h" + +// +// Utility Name +// +#define UTILITY_NAME "GenFv" + +// +// Utility version information +// +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +EFI_GUID mEfiFirmwareFileSystem2Guid = EFI_FIRMWARE_FILE_SYSTEM2_GUID; +EFI_GUID mEfiFirmwareFileSystem3Guid = EFI_FIRMWARE_FILE_SYSTEM3_GUID; + +STATIC +VOID +Version ( + VOID +) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION); +} + +STATIC +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "\nUsage: %s [options]\n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n"); + + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " -o FileName, --outputfile FileName\n\ + File is the FvImage or CapImage to be created.\n"); + fprintf (stdout, " -i FileName, --inputfile FileName\n\ + File is the input FV.inf or Cap.inf to specify\n\ + how to construct FvImage or CapImage.\n"); + fprintf (stdout, " -b BlockSize, --blocksize BlockSize\n\ + BlockSize is one HEX or DEC format value\n\ + BlockSize is required by Fv Image.\n"); + fprintf (stdout, " -n NumberBlock, --numberblock NumberBlock\n\ + NumberBlock is one HEX or DEC format value\n\ + NumberBlock is one optional parameter.\n"); + fprintf (stdout, " -f FfsFile, --ffsfile FfsFile\n\ + FfsFile is placed into Fv Image\n\ + multi files can input one by one\n"); + fprintf (stdout, " -s FileTakenSize, --filetakensize FileTakenSize\n\ + FileTakenSize specifies the size of the required\n\ + space that the input file is placed in Fvimage.\n\ + It is specified together with the input file.\n"); + fprintf (stdout, " -r Address, --baseaddr Address\n\ + Address is the rebase start address for drivers that\n\ + run in Flash. It supports DEC or HEX digital format.\n\ + If it is set to zero, no rebase action will be taken\n"); + fprintf (stdout, " -F ForceRebase, --force-rebase ForceRebase\n\ + If value is TRUE, will always take rebase action\n\ + If value is FALSE, will always not take reabse action\n\ + If not specified, will take rebase action if rebase address greater than zero, \n\ + will not take rebase action if rebase address is zero.\n"); + fprintf (stdout, " -a AddressFile, --addrfile AddressFile\n\ + AddressFile is one file used to record the child\n\ + FV base address when current FV base address is set.\n"); + fprintf (stdout, " -m logfile, --map logfile\n\ + Logfile is the output fv map file name. if it is not\n\ + given, the FvName.map will be the default map file name\n"); + fprintf (stdout, " -g Guid, --guid Guid\n\ + GuidValue is one specific capsule guid value\n\ + or fv file system guid value.\n\ + Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"); + fprintf (stdout, " --FvNameGuid Guid Guid is used to specify Fv Name.\n\ + Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"); + fprintf (stdout, " --capflag CapFlag Capsule Reset Flag can be PersistAcrossReset,\n\ + or PopulateSystemTable or InitiateReset or not set\n"); + fprintf (stdout, " --capoemflag CapOEMFlag\n\ + Capsule OEM Flag is an integer between 0x0000 and 0xffff\n"); + fprintf (stdout, " --capheadsize HeadSize\n\ + HeadSize is one HEX or DEC format value\n\ + HeadSize is required by Capsule Image.\n"); + fprintf (stdout, " -c, --capsule Create Capsule Image.\n"); + fprintf (stdout, " -p, --dump Dump Capsule Image header.\n"); + fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n"); + fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n"); + fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n"); + fprintf (stdout, " --version Show program's version number and exit.\n"); + fprintf (stdout, " -h, --help Show this help message and exit.\n"); +} + +UINT32 mFvTotalSize; +UINT32 mFvTakenSize; + +int +main ( + IN int argc, + IN char **argv + ) +/*++ + +Routine Description: + + This utility uses GenFvImage.Lib to build a firmware volume image. + +Arguments: + + FvInfFileName The name of an FV image description file or Capsule Image. + + Arguments come in pair in any order. + -I FvInfFileName + +Returns: + + EFI_SUCCESS No error conditions detected. + EFI_INVALID_PARAMETER One or more of the input parameters is invalid. + EFI_OUT_OF_RESOURCES A resource required by the utility was unavailable. + Most commonly this will be memory allocation + or file creation. + EFI_LOAD_ERROR GenFvImage.lib could not be loaded. + EFI_ABORTED Error executing the GenFvImage lib. + +--*/ +{ + EFI_STATUS Status; + CHAR8 *InfFileName; + CHAR8 *AddrFileName; + CHAR8 *MapFileName; + CHAR8 *InfFileImage; + UINT32 InfFileSize; + CHAR8 *OutFileName; + BOOLEAN CapsuleFlag; + BOOLEAN DumpCapsule; + FILE *FpFile; + EFI_CAPSULE_HEADER *CapsuleHeader; + UINT64 LogLevel, TempNumber; + UINT32 Index; + + InfFileName = NULL; + AddrFileName = NULL; + InfFileImage = NULL; + OutFileName = NULL; + MapFileName = NULL; + InfFileSize = 0; + CapsuleFlag = FALSE; + DumpCapsule = FALSE; + FpFile = NULL; + CapsuleHeader = NULL; + LogLevel = 0; + TempNumber = 0; + Index = 0; + mFvTotalSize = 0; + mFvTakenSize = 0; + Status = EFI_SUCCESS; + + SetUtilityName (UTILITY_NAME); + + if (argc == 1) { + Error (NULL, 0, 1001, "Missing options", "No input options specified."); + Usage (); + return STATUS_ERROR; + } + + // + // Init global data to Zero + // + memset (&mFvDataInfo, 0, sizeof (FV_INFO)); + memset (&mCapDataInfo, 0, sizeof (CAP_INFO)); + // + // Set the default FvGuid + // + memcpy (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem2Guid, sizeof (EFI_GUID)); + mFvDataInfo.ForceRebase = -1; + + // + // Parse command line + // + argc --; + argv ++; + + if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) { + Version (); + Usage (); + return STATUS_SUCCESS; + } + + if (stricmp (argv[0], "--version") == 0) { + Version (); + return STATUS_SUCCESS; + } + + while (argc > 0) { + if ((stricmp (argv[0], "-i") == 0) || (stricmp (argv[0], "--inputfile") == 0)) { + InfFileName = argv[1]; + if (InfFileName == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Input file can't be null"); + return STATUS_ERROR; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--addrfile") == 0)) { + AddrFileName = argv[1]; + if (AddrFileName == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Address file can't be null"); + return STATUS_ERROR; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) { + OutFileName = argv[1]; + if (OutFileName == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Output file can't be null"); + return STATUS_ERROR; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--baseaddr") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &TempNumber); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + return STATUS_ERROR; + } + mFvDataInfo.BaseAddress = TempNumber; + mFvDataInfo.BaseAddressSet = TRUE; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--blocksize") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &TempNumber); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + return STATUS_ERROR; + } + if (TempNumber == 0) { + Error (NULL, 0, 1003, "Invalid option value", "Fv block size can't be be set to zero"); + return STATUS_ERROR; + } + mFvDataInfo.FvBlocks[0].Length = (UINT32) TempNumber; + DebugMsg (NULL, 0, 9, "FV Block Size", "%s = 0x%llx", EFI_BLOCK_SIZE_STRING, (unsigned long long) TempNumber); + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--numberblock") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &TempNumber); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + return STATUS_ERROR; + } + if (TempNumber == 0) { + Error (NULL, 0, 1003, "Invalid option value", "Fv block number can't be set to zero"); + return STATUS_ERROR; + } + mFvDataInfo.FvBlocks[0].NumBlocks = (UINT32) TempNumber; + DebugMsg (NULL, 0, 9, "FV Number Block", "%s = 0x%llx", EFI_NUM_BLOCKS_STRING, (unsigned long long) TempNumber); + argc -= 2; + argv += 2; + continue; + } + + if ((strcmp (argv[0], "-f") == 0) || (stricmp (argv[0], "--ffsfile") == 0)) { + if (argv[1] == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Input Ffsfile can't be null"); + return STATUS_ERROR; + } + if (strlen (argv[1]) > MAX_LONG_FILE_PATH - 1) { + Error (NULL, 0, 1003, "Invalid option value", "Input Ffsfile name %s is too long!", argv[1]); + return STATUS_ERROR; + } + strncpy (mFvDataInfo.FvFiles[Index], argv[1], MAX_LONG_FILE_PATH - 1); + mFvDataInfo.FvFiles[Index][MAX_LONG_FILE_PATH - 1] = 0; + DebugMsg (NULL, 0, 9, "FV component file", "the %uth name is %s", (unsigned) Index + 1, argv[1]); + argc -= 2; + argv += 2; + + if (argc > 0) { + if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--filetakensize") == 0)) { + if (argv[1] == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Ffsfile Size can't be null"); + return STATUS_ERROR; + } + Status = AsciiStringToUint64 (argv[1], FALSE, &TempNumber); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + return STATUS_ERROR; + } + mFvDataInfo.SizeofFvFiles[Index] = (UINT32) TempNumber; + DebugMsg (NULL, 0, 9, "FV component file size", "the %uth size is %s", (unsigned) Index + 1, argv[1]); + argc -= 2; + argv += 2; + } + } + Index ++; + continue; + } + + if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--filetakensize") == 0)) { + Error (NULL, 0, 1003, "Invalid option", "It must be specified together with -f option to specify the file size."); + return STATUS_ERROR; + } + + if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--capsule") == 0)) { + CapsuleFlag = TRUE; + argc --; + argv ++; + continue; + } + + if ((strcmp (argv[0], "-F") == 0) || (stricmp (argv[0], "--force-rebase") == 0)) { + if (argv[1] == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Froce rebase flag can't be null"); + return STATUS_ERROR; + } + + if (stricmp (argv[1], "TRUE") == 0) { + mFvDataInfo.ForceRebase = 1; + } else if (stricmp (argv[1], "FALSE") == 0) { + mFvDataInfo.ForceRebase = 0; + } else { + Error (NULL, 0, 1003, "Invalid option value", "froce rebase flag value must be \"TRUE\" or \"FALSE\""); + return STATUS_ERROR; + } + + argc -= 2; + argv += 2; + continue; + } + + if (stricmp (argv[0], "--capheadsize") == 0) { + // + // Get Capsule Image Header Size + // + Status = AsciiStringToUint64 (argv[1], FALSE, &TempNumber); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + return STATUS_ERROR; + } + mCapDataInfo.HeaderSize = (UINT32) TempNumber; + DebugMsg (NULL, 0, 9, "Capsule Header size", "%s = 0x%llx", EFI_CAPSULE_HEADER_SIZE_STRING, (unsigned long long) TempNumber); + argc -= 2; + argv += 2; + continue; + } + + if (stricmp (argv[0], "--capflag") == 0) { + // + // Get Capsule Header + // + if (argv[1] == NULL) { + Error (NULL, 0, 1003, "Option value is not set", "%s = %s", argv[0], argv[1]); + return STATUS_ERROR; + } + if (strcmp (argv[1], "PopulateSystemTable") == 0) { + mCapDataInfo.Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE; + } else if (strcmp (argv[1], "PersistAcrossReset") == 0) { + mCapDataInfo.Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET; + } else if (strcmp (argv[1], "InitiateReset") == 0) { + mCapDataInfo.Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_INITIATE_RESET; + } else { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + return STATUS_ERROR; + } + DebugMsg (NULL, 0, 9, "Capsule Flag", argv[1]); + argc -= 2; + argv += 2; + continue; + } + + if (stricmp (argv[0], "--capoemflag") == 0) { + if (argv[1] == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Capsule OEM flag can't be null"); + } + Status = AsciiStringToUint64(argv[1], FALSE, &TempNumber); + if (EFI_ERROR (Status) || TempNumber > 0xffff) { + Error (NULL, 0, 1003, "Invalid option value", "Capsule OEM flag value must be integer value between 0x0000 and 0xffff"); + return STATUS_ERROR; + } + mCapDataInfo.Flags |= TempNumber; + DebugMsg( NULL, 0, 9, "Capsule OEM Flags", argv[1]); + argc -= 2; + argv += 2; + continue; + } + + if (stricmp (argv[0], "--capguid") == 0) { + // + // Get the Capsule Guid + // + Status = StringToGuid (argv[1], &mCapDataInfo.CapGuid); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", EFI_CAPSULE_GUID_STRING, argv[1]); + return STATUS_ERROR; + } + DebugMsg (NULL, 0, 9, "Capsule Guid", "%s = %s", EFI_CAPSULE_GUID_STRING, argv[1]); + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--guid") == 0)) { + // + // Get the Capsule or Fv Guid + // + Status = StringToGuid (argv[1], &mCapDataInfo.CapGuid); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", EFI_GUID_STRING, argv[1]); + return STATUS_ERROR; + } + memcpy (&mFvDataInfo.FvFileSystemGuid, &mCapDataInfo.CapGuid, sizeof (EFI_GUID)); + mFvDataInfo.FvFileSystemGuidSet = TRUE; + DebugMsg (NULL, 0, 9, "Capsule Guid", "%s = %s", EFI_CAPSULE_GUID_STRING, argv[1]); + DebugMsg (NULL, 0, 9, "FV Guid", "%s = %s", EFI_FV_FILESYSTEMGUID_STRING, argv[1]); + argc -= 2; + argv += 2; + continue; + } + + if (stricmp (argv[0], "--FvNameGuid") == 0) { + // + // Get Fv Name Guid + // + Status = StringToGuid (argv[1], &mFvDataInfo.FvNameGuid); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", EFI_GUID_STRING, argv[1]); + return STATUS_ERROR; + } + mFvDataInfo.FvNameGuidSet = TRUE; + DebugMsg (NULL, 0, 9, "FV Name Guid", "%s = %s", EFI_FV_NAMEGUID_STRING, argv[1]); + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--dump") == 0)) { + DumpCapsule = TRUE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--map") == 0)) { + MapFileName = argv[1]; + if (MapFileName == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Map file can't be null"); + return STATUS_ERROR; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) { + SetPrintLevel (VERBOSE_LOG_LEVEL); + VerboseMsg ("Verbose output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + SetPrintLevel (KEY_LOG_LEVEL); + KeyMsg ("Quiet output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + return STATUS_ERROR; + } + if (LogLevel > 9) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel); + return STATUS_ERROR; + } + SetPrintLevel (LogLevel); + DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]); + argc -= 2; + argv += 2; + continue; + } + + // + // Don't recognize the parameter. + // + Error (NULL, 0, 1000, "Unknown option", "%s", argv[0]); + return STATUS_ERROR; + } + + VerboseMsg ("%s tool start.", UTILITY_NAME); + + // + // check input parameter, InfFileName can be NULL + // + if (InfFileName == NULL && DumpCapsule) { + Error (NULL, 0, 1001, "Missing option", "Input Capsule Image"); + return STATUS_ERROR; + } + VerboseMsg ("the input FvInf or CapInf file name is %s", InfFileName); + + if (!DumpCapsule && OutFileName == NULL) { + Error (NULL, 0, 1001, "Missing option", "Output File"); + return STATUS_ERROR; + } + if (OutFileName != NULL) { + VerboseMsg ("the output file name is %s", OutFileName); + } + + // + // Read the INF file image + // + if (InfFileName != NULL) { + Status = GetFileImage (InfFileName, &InfFileImage, &InfFileSize); + if (EFI_ERROR (Status)) { + return STATUS_ERROR; + } + } + + if (DumpCapsule) { + VerboseMsg ("Dump the capsule header information for the input capsule image %s", InfFileName); + // + // Dump Capsule Image Header Information + // + CapsuleHeader = (EFI_CAPSULE_HEADER *) InfFileImage; + if (OutFileName == NULL) { + FpFile = stdout; + } else { + FpFile = fopen (LongFilePath (OutFileName), "w"); + if (FpFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", OutFileName); + return STATUS_ERROR; + } + } + if (FpFile != NULL) { + fprintf (FpFile, "Capsule %s Image Header Information\n", InfFileName); + fprintf (FpFile, " GUID %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X\n", + (unsigned) CapsuleHeader->CapsuleGuid.Data1, + (unsigned) CapsuleHeader->CapsuleGuid.Data2, + (unsigned) CapsuleHeader->CapsuleGuid.Data3, + (unsigned) CapsuleHeader->CapsuleGuid.Data4[0], + (unsigned) CapsuleHeader->CapsuleGuid.Data4[1], + (unsigned) CapsuleHeader->CapsuleGuid.Data4[2], + (unsigned) CapsuleHeader->CapsuleGuid.Data4[3], + (unsigned) CapsuleHeader->CapsuleGuid.Data4[4], + (unsigned) CapsuleHeader->CapsuleGuid.Data4[5], + (unsigned) CapsuleHeader->CapsuleGuid.Data4[6], + (unsigned) CapsuleHeader->CapsuleGuid.Data4[7]); + fprintf (FpFile, " Header size 0x%08X\n", (unsigned) CapsuleHeader->HeaderSize); + fprintf (FpFile, " Flags 0x%08X\n", (unsigned) CapsuleHeader->Flags); + fprintf (FpFile, " Capsule image size 0x%08X\n", (unsigned) CapsuleHeader->CapsuleImageSize); + fclose (FpFile); + } + } else if (CapsuleFlag) { + VerboseMsg ("Create capsule image"); + // + // Call the GenerateCapImage to generate Capsule Image + // + for (Index = 0; mFvDataInfo.FvFiles[Index][0] != '\0'; Index ++) { + strcpy (mCapDataInfo.CapFiles[Index], mFvDataInfo.FvFiles[Index]); + } + + Status = GenerateCapImage ( + InfFileImage, + InfFileSize, + OutFileName + ); + } else { + VerboseMsg ("Create Fv image and its map file"); + // + // Will take rebase action at below situation: + // 1. ForceRebase Flag specified to TRUE; + // 2. ForceRebase Flag not specified, BaseAddress greater than zero. + // + if (((mFvDataInfo.BaseAddress > 0) && (mFvDataInfo.ForceRebase == -1)) || (mFvDataInfo.ForceRebase == 1)) { + VerboseMsg ("FvImage Rebase Address is 0x%llX", (unsigned long long) mFvDataInfo.BaseAddress); + } + // + // Call the GenerateFvImage to generate Fv Image + // + Status = GenerateFvImage ( + InfFileImage, + InfFileSize, + OutFileName, + MapFileName + ); + } + + // + // free InfFileImage memory + // + if (InfFileImage != NULL) { + free (InfFileImage); + } + + // + // update boot driver address and runtime driver address in address file + // + if (Status == EFI_SUCCESS && AddrFileName != NULL && mFvBaseAddressNumber > 0) { + FpFile = fopen (LongFilePath (AddrFileName), "w"); + if (FpFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", AddrFileName); + return STATUS_ERROR; + } + fprintf (FpFile, FV_BASE_ADDRESS_STRING); + fprintf (FpFile, "\n"); + for (Index = 0; Index < mFvBaseAddressNumber; Index ++) { + fprintf ( + FpFile, + "0x%llx\n", + (unsigned long long)mFvBaseAddress[Index] + ); + } + fflush (FpFile); + fclose (FpFile); + } + + if (Status == EFI_SUCCESS) { + DebugMsg (NULL, 0, 9, "The Total Fv Size", "%s = 0x%x", EFI_FV_TOTAL_SIZE_STRING, (unsigned) mFvTotalSize); + DebugMsg (NULL, 0, 9, "The used Fv Size", "%s = 0x%x", EFI_FV_TAKEN_SIZE_STRING, (unsigned) mFvTakenSize); + DebugMsg (NULL, 0, 9, "The space Fv size", "%s = 0x%x", EFI_FV_SPACE_SIZE_STRING, (unsigned) (mFvTotalSize - mFvTakenSize)); + } + + VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ()); + + return GetUtilityStatus (); +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GenFvInternalLib.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GenFvInternalLib.c new file mode 100644 index 00000000..85ea51eb --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GenFvInternalLib.c @@ -0,0 +1,4432 @@ +/** @file +This file contains the internal functions required to generate a Firmware Volume. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+Portions Copyright (c) 2016 HP Development Company, L.P.
+Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +// +// Include files +// + +#if defined(__FreeBSD__) +#include +#elif defined(__GNUC__) +#include +#endif +#ifdef __GNUC__ +#include +#endif +#include +#ifndef __GNUC__ +#include +#endif +#include + +#include + +#include "WinNtInclude.h" +#include "GenFvInternalLib.h" +#include "FvLib.h" +#include "PeCoffLib.h" + +#define ARMT_UNCONDITIONAL_JUMP_INSTRUCTION 0xEB000000 +#define ARM64_UNCONDITIONAL_JUMP_INSTRUCTION 0x14000000 + +BOOLEAN mArm = FALSE; +BOOLEAN mRiscV = FALSE; +STATIC UINT32 MaxFfsAlignment = 0; +BOOLEAN VtfFileFlag = FALSE; + +EFI_GUID mEfiFirmwareVolumeTopFileGuid = EFI_FFS_VOLUME_TOP_FILE_GUID; +EFI_GUID mFileGuidArray [MAX_NUMBER_OF_FILES_IN_FV]; +EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; +EFI_GUID mDefaultCapsuleGuid = {0x3B6686BD, 0x0D76, 0x4030, { 0xB7, 0x0E, 0xB5, 0x51, 0x9E, 0x2F, 0xC5, 0xA0 }}; +EFI_GUID mEfiFfsSectionAlignmentPaddingGuid = EFI_FFS_SECTION_ALIGNMENT_PADDING_GUID; + +CHAR8 *mFvbAttributeName[] = { + EFI_FVB2_READ_DISABLED_CAP_STRING, + EFI_FVB2_READ_ENABLED_CAP_STRING, + EFI_FVB2_READ_STATUS_STRING, + EFI_FVB2_WRITE_DISABLED_CAP_STRING, + EFI_FVB2_WRITE_ENABLED_CAP_STRING, + EFI_FVB2_WRITE_STATUS_STRING, + EFI_FVB2_LOCK_CAP_STRING, + EFI_FVB2_LOCK_STATUS_STRING, + NULL, + EFI_FVB2_STICKY_WRITE_STRING, + EFI_FVB2_MEMORY_MAPPED_STRING, + EFI_FVB2_ERASE_POLARITY_STRING, + EFI_FVB2_READ_LOCK_CAP_STRING, + EFI_FVB2_READ_LOCK_STATUS_STRING, + EFI_FVB2_WRITE_LOCK_CAP_STRING, + EFI_FVB2_WRITE_LOCK_STATUS_STRING +}; + +CHAR8 *mFvbAlignmentName[] = { + EFI_FVB2_ALIGNMENT_1_STRING, + EFI_FVB2_ALIGNMENT_2_STRING, + EFI_FVB2_ALIGNMENT_4_STRING, + EFI_FVB2_ALIGNMENT_8_STRING, + EFI_FVB2_ALIGNMENT_16_STRING, + EFI_FVB2_ALIGNMENT_32_STRING, + EFI_FVB2_ALIGNMENT_64_STRING, + EFI_FVB2_ALIGNMENT_128_STRING, + EFI_FVB2_ALIGNMENT_256_STRING, + EFI_FVB2_ALIGNMENT_512_STRING, + EFI_FVB2_ALIGNMENT_1K_STRING, + EFI_FVB2_ALIGNMENT_2K_STRING, + EFI_FVB2_ALIGNMENT_4K_STRING, + EFI_FVB2_ALIGNMENT_8K_STRING, + EFI_FVB2_ALIGNMENT_16K_STRING, + EFI_FVB2_ALIGNMENT_32K_STRING, + EFI_FVB2_ALIGNMENT_64K_STRING, + EFI_FVB2_ALIGNMENT_128K_STRING, + EFI_FVB2_ALIGNMENT_256K_STRING, + EFI_FVB2_ALIGNMENT_512K_STRING, + EFI_FVB2_ALIGNMENT_1M_STRING, + EFI_FVB2_ALIGNMENT_2M_STRING, + EFI_FVB2_ALIGNMENT_4M_STRING, + EFI_FVB2_ALIGNMENT_8M_STRING, + EFI_FVB2_ALIGNMENT_16M_STRING, + EFI_FVB2_ALIGNMENT_32M_STRING, + EFI_FVB2_ALIGNMENT_64M_STRING, + EFI_FVB2_ALIGNMENT_128M_STRING, + EFI_FVB2_ALIGNMENT_256M_STRING, + EFI_FVB2_ALIGNMENT_512M_STRING, + EFI_FVB2_ALIGNMENT_1G_STRING, + EFI_FVB2_ALIGNMENT_2G_STRING +}; + +// +// This data array will be located at the base of the Firmware Volume Header (FVH) +// in the boot block. It must not exceed 14 bytes of code. The last 2 bytes +// will be used to keep the FVH checksum consistent. +// This code will be run in response to a startup IPI for HT-enabled systems. +// +#define SIZEOF_STARTUP_DATA_ARRAY 0x10 + +UINT8 m128kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = { + // + // EA D0 FF 00 F0 ; far jmp F000:FFD0 + // 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes + // 0, 0 ; Checksum Padding + // + 0xEA, + 0xD0, + 0xFF, + 0x0, + 0xF0, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; + +UINT8 m64kRecoveryStartupApDataArray[SIZEOF_STARTUP_DATA_ARRAY] = { + // + // EB CE ; jmp short ($-0x30) + // ; (from offset 0x0 to offset 0xFFD0) + // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ; Reserved bytes + // 0, 0 ; Checksum Padding + // + 0xEB, + 0xCE, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 +}; + +FV_INFO mFvDataInfo; +CAP_INFO mCapDataInfo; +BOOLEAN mIsLargeFfs = FALSE; + +EFI_PHYSICAL_ADDRESS mFvBaseAddress[0x10]; +UINT32 mFvBaseAddressNumber = 0; + +EFI_STATUS +ParseFvInf ( + IN MEMORY_FILE *InfFile, + OUT FV_INFO *FvInfo + ) +/*++ + +Routine Description: + + This function parses a FV.INF file and copies info into a FV_INFO structure. + +Arguments: + + InfFile Memory file image. + FvInfo Information read from INF file. + +Returns: + + EFI_SUCCESS INF file information successfully retrieved. + EFI_ABORTED INF file has an invalid format. + EFI_NOT_FOUND A required string was not found in the INF file. +--*/ +{ + CHAR8 Value[MAX_LONG_FILE_PATH]; + UINT64 Value64; + UINTN Index; + UINTN Number; + EFI_STATUS Status; + EFI_GUID GuidValue; + + // + // Read the FV base address + // + if (!mFvDataInfo.BaseAddressSet) { + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_BASE_ADDRESS_STRING, 0, Value); + if (Status == EFI_SUCCESS) { + // + // Get the base address + // + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_BASE_ADDRESS_STRING, Value); + return EFI_ABORTED; + } + DebugMsg (NULL, 0, 9, "rebase address", "%s = %s", EFI_FV_BASE_ADDRESS_STRING, Value); + + FvInfo->BaseAddress = Value64; + FvInfo->BaseAddressSet = TRUE; + } + } + + // + // Read the FV File System Guid + // + if (!FvInfo->FvFileSystemGuidSet) { + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILESYSTEMGUID_STRING, 0, Value); + if (Status == EFI_SUCCESS) { + // + // Get the guid value + // + Status = StringToGuid (Value, &GuidValue); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_FV_FILESYSTEMGUID_STRING, Value); + return EFI_ABORTED; + } + memcpy (&FvInfo->FvFileSystemGuid, &GuidValue, sizeof (EFI_GUID)); + FvInfo->FvFileSystemGuidSet = TRUE; + } + } + + // + // Read the FV Extension Header File Name + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FV_EXT_HEADER_FILE_NAME, 0, Value); + if (Status == EFI_SUCCESS) { + strcpy (FvInfo->FvExtHeaderFile, Value); + } + + // + // Read the FV file name + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_FILE_NAME_STRING, 0, Value); + if (Status == EFI_SUCCESS) { + // + // copy the file name + // + strcpy (FvInfo->FvName, Value); + } + + // + // Read Fv Attribute + // + for (Index = 0; Index < sizeof (mFvbAttributeName)/sizeof (CHAR8 *); Index ++) { + if ((mFvbAttributeName [Index] != NULL) && \ + (FindToken (InfFile, ATTRIBUTES_SECTION_STRING, mFvbAttributeName [Index], 0, Value) == EFI_SUCCESS)) { + if ((strcmp (Value, TRUE_STRING) == 0) || (strcmp (Value, ONE_STRING) == 0)) { + FvInfo->FvAttributes |= 1 << Index; + } else if ((strcmp (Value, FALSE_STRING) != 0) && (strcmp (Value, ZERO_STRING) != 0)) { + Error (NULL, 0, 2000, "Invalid parameter", "%s expected %s | %s", mFvbAttributeName [Index], TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } + } + + // + // Read Fv Alignment + // + for (Index = 0; Index < sizeof (mFvbAlignmentName)/sizeof (CHAR8 *); Index ++) { + if (FindToken (InfFile, ATTRIBUTES_SECTION_STRING, mFvbAlignmentName [Index], 0, Value) == EFI_SUCCESS) { + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= Index << 16; + DebugMsg (NULL, 0, 9, "FV file alignment", "Align = %s", mFvbAlignmentName [Index]); + break; + } + } + } + + // + // Read weak alignment flag + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FV_WEAK_ALIGNMENT_STRING, 0, Value); + if (Status == EFI_SUCCESS) { + if ((strcmp (Value, TRUE_STRING) == 0) || (strcmp (Value, ONE_STRING) == 0)) { + FvInfo->FvAttributes |= EFI_FVB2_WEAK_ALIGNMENT; + } else if ((strcmp (Value, FALSE_STRING) != 0) && (strcmp (Value, ZERO_STRING) != 0)) { + Error (NULL, 0, 2000, "Invalid parameter", "Weak alignment value expected one of TRUE, FALSE, 1 or 0."); + return EFI_ABORTED; + } + } + + // + // Read block maps + // + for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) { + if (FvInfo->FvBlocks[Index].Length == 0) { + // + // Read block size + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the size of block + // + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_BLOCK_SIZE_STRING, Value); + return EFI_ABORTED; + } + + FvInfo->FvBlocks[Index].Length = (UINT32) Value64; + DebugMsg (NULL, 0, 9, "FV Block Size", "%s = %s", EFI_BLOCK_SIZE_STRING, Value); + } else { + // + // If there is no blocks size, but there is the number of block, then we have a mismatched pair + // and should return an error. + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value); + if (!EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid parameter", "both %s and %s must be specified.", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING); + return EFI_ABORTED; + } else { + // + // We are done + // + break; + } + } + + // + // Read blocks number + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_NUM_BLOCKS_STRING, Index, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the number of blocks + // + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_NUM_BLOCKS_STRING, Value); + return EFI_ABORTED; + } + + FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64; + DebugMsg (NULL, 0, 9, "FV Block Number", "%s = %s", EFI_NUM_BLOCKS_STRING, Value); + } + } + } + + if (Index == 0) { + Error (NULL, 0, 2001, "Missing required argument", "block size."); + return EFI_ABORTED; + } + + // + // Read files + // + Number = 0; + for (Number = 0; Number < MAX_NUMBER_OF_FILES_IN_FV; Number ++) { + if (FvInfo->FvFiles[Number][0] == '\0') { + break; + } + } + + for (Index = 0; Number + Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) { + // + // Read the FFS file list + // + Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the file + // + strcpy (FvInfo->FvFiles[Number + Index], Value); + DebugMsg (NULL, 0, 9, "FV component file", "the %uth name is %s", (unsigned) Index, Value); + } else { + break; + } + } + + if ((Index + Number) == 0) { + Warning (NULL, 0, 0, "FV components are not specified.", NULL); + } + + return EFI_SUCCESS; +} + +VOID +UpdateFfsFileState ( + IN EFI_FFS_FILE_HEADER *FfsFile, + IN EFI_FIRMWARE_VOLUME_HEADER *FvHeader + ) +/*++ + +Routine Description: + + This function changes the FFS file attributes based on the erase polarity + of the FV. Update the reserved bits of State to EFI_FVB2_ERASE_POLARITY. + +Arguments: + + FfsFile File header. + FvHeader FV header. + +Returns: + + None + +--*/ +{ + if (FvHeader->Attributes & EFI_FVB2_ERASE_POLARITY) { + FfsFile->State = (UINT8)~(FfsFile->State); + // FfsFile->State |= ~(UINT8) EFI_FILE_ALL_STATE_BITS; + } +} + +EFI_STATUS +ReadFfsAlignment ( + IN EFI_FFS_FILE_HEADER *FfsFile, + IN OUT UINT32 *Alignment + ) +/*++ + +Routine Description: + + This function determines the alignment of the FFS input file from the file + attributes. + +Arguments: + + FfsFile FFS file to parse + Alignment The minimum required alignment offset of the FFS file + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED An error occurred. + +--*/ +{ + // + // Verify input parameters. + // + if (FfsFile == NULL || Alignment == NULL) { + return EFI_INVALID_PARAMETER; + } + + switch ((FfsFile->Attributes >> 3) & 0x07) { + + case 0: + // + // 1 byte alignment + //if bit 1 have set, 128K byte alignment + // + if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) { + *Alignment = 17; + } else { + *Alignment = 0; + } + break; + + case 1: + // + // 16 byte alignment + //if bit 1 have set, 256K byte alignment + // + if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) { + *Alignment = 18; + } else { + *Alignment = 4; + } + break; + + case 2: + // + // 128 byte alignment + //if bit 1 have set, 512K byte alignment + // + if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) { + *Alignment = 19; + } else { + *Alignment = 7; + } + break; + + case 3: + // + // 512 byte alignment + //if bit 1 have set, 1M byte alignment + // + if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) { + *Alignment = 20; + } else { + *Alignment = 9; + } + break; + + case 4: + // + // 1K byte alignment + //if bit 1 have set, 2M byte alignment + // + if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) { + *Alignment = 21; + } else { + *Alignment = 10; + } + break; + + case 5: + // + // 4K byte alignment + //if bit 1 have set, 4M byte alignment + // + if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) { + *Alignment = 22; + } else { + *Alignment = 12; + } + break; + + case 6: + // + // 32K byte alignment + //if bit 1 have set , 8M byte alignment + // + if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) { + *Alignment = 23; + } else { + *Alignment = 15; + } + break; + + case 7: + // + // 64K byte alignment + //if bit 1 have set, 16M alignment + // + if (FfsFile->Attributes & FFS_ATTRIB_DATA_ALIGNMENT2) { + *Alignment = 24; + } else { + *Alignment = 16; + } + break; + + default: + break; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AddPadFile ( + IN OUT MEMORY_FILE *FvImage, + IN UINT32 DataAlignment, + IN VOID *FvEnd, + IN EFI_FIRMWARE_VOLUME_EXT_HEADER *ExtHeader, + IN UINT32 NextFfsSize + ) +/*++ + +Routine Description: + + This function adds a pad file to the FV image if it required to align the + data of the next file. + +Arguments: + + FvImage The memory image of the FV to add it to. + The current offset must be valid. + DataAlignment The data alignment of the next FFS file. + FvEnd End of the empty data in FvImage. + ExtHeader PI FvExtHeader Optional + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_OUT_OF_RESOURCES Insufficient resources exist in the FV to complete + the pad file add. + +--*/ +{ + EFI_FFS_FILE_HEADER *PadFile; + UINTN PadFileSize; + UINT32 NextFfsHeaderSize; + UINT32 CurFfsHeaderSize; + UINT32 Index; + + Index = 0; + CurFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER); + // + // Verify input parameters. + // + if (FvImage == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Calculate the pad file size + // + + // + // Append extension header size + // + if (ExtHeader != NULL) { + PadFileSize = ExtHeader->ExtHeaderSize; + if (PadFileSize + sizeof (EFI_FFS_FILE_HEADER) >= MAX_FFS_SIZE) { + CurFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER2); + } + PadFileSize += CurFfsHeaderSize; + } else { + NextFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER); + if (NextFfsSize >= MAX_FFS_SIZE) { + NextFfsHeaderSize = sizeof (EFI_FFS_FILE_HEADER2); + } + // + // Check if a pad file is necessary + // + if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + NextFfsHeaderSize) % DataAlignment == 0) { + return EFI_SUCCESS; + } + PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER) + NextFfsHeaderSize; + // + // Add whatever it takes to get to the next aligned address + // + while ((PadFileSize % DataAlignment) != 0) { + PadFileSize++; + } + // + // Subtract the next file header size + // + PadFileSize -= NextFfsHeaderSize; + // + // Subtract the starting offset to get size + // + PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage; + } + + // + // Verify that we have enough space for the file header + // + if (((UINTN) FvImage->CurrentFilePointer + PadFileSize) > (UINTN) FvEnd) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Write pad file header + // + PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer; + + // + // Write PadFile FFS header with PadType, don't need to set PAD file guid in its header. + // + PadFile->Type = EFI_FV_FILETYPE_FFS_PAD; + PadFile->Attributes = 0; + + // + // Write pad file size (calculated size minus next file header size) + // + if (PadFileSize >= MAX_FFS_SIZE) { + memset(PadFile->Size, 0, sizeof(UINT8) * 3); + ((EFI_FFS_FILE_HEADER2 *)PadFile)->ExtendedSize = PadFileSize; + PadFile->Attributes |= FFS_ATTRIB_LARGE_FILE; + } else { + PadFile->Size[0] = (UINT8) (PadFileSize & 0xFF); + PadFile->Size[1] = (UINT8) ((PadFileSize >> 8) & 0xFF); + PadFile->Size[2] = (UINT8) ((PadFileSize >> 16) & 0xFF); + } + + // + // Fill in checksums and state, they must be 0 for checksumming. + // + PadFile->IntegrityCheck.Checksum.Header = 0; + PadFile->IntegrityCheck.Checksum.File = 0; + PadFile->State = 0; + PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, CurFfsHeaderSize); + PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + + PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID; + UpdateFfsFileState ( + (EFI_FFS_FILE_HEADER *) PadFile, + (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage + ); + + // + // Update the current FV pointer + // + FvImage->CurrentFilePointer += PadFileSize; + + if (ExtHeader != NULL) { + // + // Copy Fv Extension Header and Set Fv Extension header offset + // + if (ExtHeader->ExtHeaderSize > sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER)) { + for (Index = sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER); Index < ExtHeader->ExtHeaderSize;) { + if (((EFI_FIRMWARE_VOLUME_EXT_ENTRY *)((UINT8 *)ExtHeader + Index))-> ExtEntryType == EFI_FV_EXT_TYPE_USED_SIZE_TYPE) { + if (VtfFileFlag) { + ((EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *)((UINT8 *)ExtHeader + Index))->UsedSize = mFvTotalSize; + } else { + ((EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE *)((UINT8 *)ExtHeader + Index))->UsedSize = mFvTakenSize; + } + break; + } + Index += ((EFI_FIRMWARE_VOLUME_EXT_ENTRY *)((UINT8 *)ExtHeader + Index))-> ExtEntrySize; + } + } + memcpy ((UINT8 *)PadFile + CurFfsHeaderSize, ExtHeader, ExtHeader->ExtHeaderSize); + ((EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage)->ExtHeaderOffset = (UINT16) ((UINTN) ((UINT8 *)PadFile + CurFfsHeaderSize) - (UINTN) FvImage->FileImage); + // + // Make next file start at QWord Boundary + // + while (((UINTN) FvImage->CurrentFilePointer & (EFI_FFS_FILE_HEADER_ALIGNMENT - 1)) != 0) { + FvImage->CurrentFilePointer++; + } + } + + return EFI_SUCCESS; +} + +BOOLEAN +IsVtfFile ( + IN EFI_FFS_FILE_HEADER *FileBuffer + ) +/*++ + +Routine Description: + + This function checks the header to validate if it is a VTF file + +Arguments: + + FileBuffer Buffer in which content of a file has been read. + +Returns: + + TRUE If this is a VTF file + FALSE If this is not a VTF file + +--*/ +{ + if (!memcmp (&FileBuffer->Name, &mEfiFirmwareVolumeTopFileGuid, sizeof (EFI_GUID))) { + return TRUE; + } else { + return FALSE; + } +} + +EFI_STATUS +WriteMapFile ( + IN OUT FILE *FvMapFile, + IN CHAR8 *FileName, + IN EFI_FFS_FILE_HEADER *FfsFile, + IN EFI_PHYSICAL_ADDRESS ImageBaseAddress, + IN PE_COFF_LOADER_IMAGE_CONTEXT *pImageContext + ) +/*++ + +Routine Description: + + This function gets the basic debug information (entrypoint, baseaddress, .text, .data section base address) + from PE/COFF image and abstracts Pe Map file information and add them into FvMap file for Debug. + +Arguments: + + FvMapFile A pointer to FvMap File + FileName Ffs File PathName + FfsFile A pointer to Ffs file image. + ImageBaseAddress PeImage Base Address. + pImageContext Image Context Information. + +Returns: + + EFI_SUCCESS Added required map information. + +--*/ +{ + CHAR8 PeMapFileName [MAX_LONG_FILE_PATH]; + CHAR8 *Cptr, *Cptr2; + CHAR8 FileGuidName [MAX_LINE_LEN]; + FILE *PeMapFile; + CHAR8 Line [MAX_LINE_LEN]; + CHAR8 KeyWord [MAX_LINE_LEN]; + CHAR8 KeyWord2 [MAX_LINE_LEN]; + CHAR8 FunctionName [MAX_LINE_LEN]; + EFI_PHYSICAL_ADDRESS FunctionAddress; + UINT32 FunctionType; + CHAR8 FunctionTypeName [MAX_LINE_LEN]; + UINT32 Index; + UINT32 AddressOfEntryPoint; + UINT32 Offset; + EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; + EFI_TE_IMAGE_HEADER *TEImageHeader; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + long long TempLongAddress; + UINT32 TextVirtualAddress; + UINT32 DataVirtualAddress; + EFI_PHYSICAL_ADDRESS LinkTimeBaseAddress; + BOOLEAN IsUseClang; + + // + // Init local variable + // + FunctionType = 0; + // + // Print FileGuid to string buffer. + // + PrintGuidToBuffer (&FfsFile->Name, (UINT8 *)FileGuidName, MAX_LINE_LEN, TRUE); + + // + // Construct Map file Name + // + if (strlen (FileName) >= MAX_LONG_FILE_PATH) { + return EFI_ABORTED; + } + strncpy (PeMapFileName, FileName, MAX_LONG_FILE_PATH - 1); + PeMapFileName[MAX_LONG_FILE_PATH - 1] = 0; + + // + // Change '\\' to '/', unified path format. + // + Cptr = PeMapFileName; + while (*Cptr != '\0') { + if (*Cptr == '\\') { + *Cptr = FILE_SEP_CHAR; + } + Cptr ++; + } + + // + // Get Map file + // + Cptr = PeMapFileName + strlen (PeMapFileName); + while ((*Cptr != '.') && (Cptr >= PeMapFileName)) { + Cptr --; + } + if (Cptr < PeMapFileName) { + return EFI_NOT_FOUND; + } else { + *(Cptr + 1) = 'm'; + *(Cptr + 2) = 'a'; + *(Cptr + 3) = 'p'; + *(Cptr + 4) = '\0'; + } + + // + // Get module Name + // + Cptr2 = Cptr; + while ((*Cptr != FILE_SEP_CHAR) && (Cptr >= PeMapFileName)) { + Cptr --; + } + *Cptr2 = '\0'; + if (strlen (Cptr + 1) >= MAX_LINE_LEN) { + return EFI_ABORTED; + } + strncpy (KeyWord, Cptr + 1, MAX_LINE_LEN - 1); + KeyWord[MAX_LINE_LEN - 1] = 0; + *Cptr2 = '.'; + + // + // AddressOfEntryPoint and Offset in Image + // + if (!pImageContext->IsTeImage) { + ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINT8 *) pImageContext->Handle + pImageContext->PeCoffHeaderOffset); + AddressOfEntryPoint = ImgHdr->Pe32.OptionalHeader.AddressOfEntryPoint; + Offset = 0; + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ( + (UINT8 *) ImgHdr + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader + ); + Index = ImgHdr->Pe32.FileHeader.NumberOfSections; + } else { + TEImageHeader = (EFI_TE_IMAGE_HEADER *) pImageContext->Handle; + AddressOfEntryPoint = TEImageHeader->AddressOfEntryPoint; + Offset = TEImageHeader->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER); + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TEImageHeader + 1); + Index = TEImageHeader->NumberOfSections; + } + + // + // module information output + // + if (ImageBaseAddress == 0) { + fprintf (FvMapFile, "%s (dummy) (", KeyWord); + fprintf (FvMapFile, "BaseAddress=%010llx, ", (unsigned long long) ImageBaseAddress); + } else { + fprintf (FvMapFile, "%s (Fixed Flash Address, ", KeyWord); + fprintf (FvMapFile, "BaseAddress=0x%010llx, ", (unsigned long long) (ImageBaseAddress + Offset)); + } + + fprintf (FvMapFile, "EntryPoint=0x%010llx, ", (unsigned long long) (ImageBaseAddress + AddressOfEntryPoint)); + if (!pImageContext->IsTeImage) { + fprintf (FvMapFile, "Type=PE"); + } else { + fprintf (FvMapFile, "Type=TE"); + } + fprintf (FvMapFile, ")\n"); + + fprintf (FvMapFile, "(GUID=%s", FileGuidName); + TextVirtualAddress = 0; + DataVirtualAddress = 0; + for (; Index > 0; Index --, SectionHeader ++) { + if (stricmp ((CHAR8 *)SectionHeader->Name, ".text") == 0) { + TextVirtualAddress = SectionHeader->VirtualAddress; + } else if (stricmp ((CHAR8 *)SectionHeader->Name, ".data") == 0) { + DataVirtualAddress = SectionHeader->VirtualAddress; + } else if (stricmp ((CHAR8 *)SectionHeader->Name, ".sdata") == 0) { + DataVirtualAddress = SectionHeader->VirtualAddress; + } + } + fprintf (FvMapFile, " .textbaseaddress=0x%010llx", (unsigned long long) (ImageBaseAddress + TextVirtualAddress)); + fprintf (FvMapFile, " .databaseaddress=0x%010llx", (unsigned long long) (ImageBaseAddress + DataVirtualAddress)); + fprintf (FvMapFile, ")\n\n"); + + // + // Open PeMapFile + // + PeMapFile = fopen (LongFilePath (PeMapFileName), "r"); + if (PeMapFile == NULL) { + // fprintf (stdout, "can't open %s file to reading\n", PeMapFileName); + return EFI_ABORTED; + } + VerboseMsg ("The map file is %s", PeMapFileName); + + // + // Output Functions information into Fv Map file + // + LinkTimeBaseAddress = 0; + IsUseClang = FALSE; + while (fgets (Line, MAX_LINE_LEN, PeMapFile) != NULL) { + // + // Skip blank line + // + if (Line[0] == 0x0a) { + FunctionType = 0; + continue; + } + // + // By Address and Static keyword + // + if (FunctionType == 0) { + sscanf (Line, "%s", KeyWord); + if (stricmp (KeyWord, "Address") == 0) { + sscanf (Line, "%s %s", KeyWord, KeyWord2); + if (stricmp (KeyWord2, "Size") == 0) { + IsUseClang = TRUE; + FunctionType = 1; + continue; + } + // + // function list + // + FunctionType = 1; + fgets (Line, MAX_LINE_LEN, PeMapFile); + } else if (stricmp (KeyWord, "Static") == 0) { + // + // static function list + // + FunctionType = 2; + fgets (Line, MAX_LINE_LEN, PeMapFile); + } else if (stricmp (KeyWord, "Preferred") ==0) { + sscanf (Line + strlen (" Preferred load address is"), "%llx", &TempLongAddress); + LinkTimeBaseAddress = (UINT64) TempLongAddress; + } + continue; + } + // + // Printf Function Information + // + if (FunctionType == 1) { + if (IsUseClang) { + sscanf (Line, "%llx %s %s %s", &TempLongAddress, KeyWord, KeyWord2, FunctionTypeName); + FunctionAddress = (UINT64) TempLongAddress; + if (FunctionTypeName [0] == '_' ) { + fprintf (FvMapFile, " 0x%010llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress - LinkTimeBaseAddress)); + fprintf (FvMapFile, "%s\n", FunctionTypeName); + } + } else { + sscanf (Line, "%s %s %llx %s", KeyWord, FunctionName, &TempLongAddress, FunctionTypeName); + FunctionAddress = (UINT64) TempLongAddress; + if (FunctionTypeName [1] == '\0' && (FunctionTypeName [0] == 'f' || FunctionTypeName [0] == 'F')) { + fprintf (FvMapFile, " 0x%010llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress - LinkTimeBaseAddress)); + fprintf (FvMapFile, "%s\n", FunctionName); + } + } + } else if (FunctionType == 2) { + sscanf (Line, "%s %s %llx %s", KeyWord, FunctionName, &TempLongAddress, FunctionTypeName); + FunctionAddress = (UINT64) TempLongAddress; + if (FunctionTypeName [1] == '\0' && (FunctionTypeName [0] == 'f' || FunctionTypeName [0] == 'F')) { + fprintf (FvMapFile, " 0x%010llx ", (unsigned long long) (ImageBaseAddress + FunctionAddress - LinkTimeBaseAddress)); + fprintf (FvMapFile, "%s\n", FunctionName); + } + } + } + // + // Close PeMap file + // + fprintf (FvMapFile, "\n\n"); + fclose (PeMapFile); + + return EFI_SUCCESS; +} + +STATIC +BOOLEAN +AdjustInternalFfsPadding ( + IN OUT EFI_FFS_FILE_HEADER *FfsFile, + IN OUT MEMORY_FILE *FvImage, + IN UINTN Alignment, + IN OUT UINTN *FileSize + ) +/*++ + +Routine Description: + + This function looks for a dedicated alignment padding section in the FFS, and + shrinks it to the size required to line up subsequent sections correctly. + +Arguments: + + FfsFile A pointer to Ffs file image. + FvImage The memory image of the FV to adjust it to. + Alignment Current file alignment + FileSize Reference to a variable holding the size of the FFS file + +Returns: + + TRUE Padding section was found and updated successfully + FALSE Otherwise + +--*/ +{ + EFI_FILE_SECTION_POINTER PadSection; + UINT8 *Remainder; + EFI_STATUS Status; + UINT32 FfsHeaderLength; + UINT32 FfsFileLength; + UINT32 PadSize; + UINTN Misalignment; + EFI_FFS_INTEGRITY_CHECK *IntegrityCheck; + + // + // Figure out the misalignment: all FFS sections are aligned relative to the + // start of the FFS payload, so use that as the base of the misalignment + // computation. + // + FfsHeaderLength = GetFfsHeaderLength(FfsFile); + Misalignment = (UINTN) FvImage->CurrentFilePointer - + (UINTN) FvImage->FileImage + FfsHeaderLength; + Misalignment &= Alignment - 1; + if (Misalignment == 0) { + // Nothing to do, return success + return TRUE; + } + + // + // We only apply this optimization to FFS files with the FIXED attribute set, + // since the FFS will not be loadable at arbitrary offsets anymore after + // we adjust the size of the padding section. + // + if ((FfsFile->Attributes & FFS_ATTRIB_FIXED) == 0) { + return FALSE; + } + + // + // Look for a dedicated padding section that we can adjust to compensate + // for the misalignment. If such a padding section exists, it precedes all + // sections with alignment requirements, and so the adjustment will correct + // all of them. + // + Status = GetSectionByType (FfsFile, EFI_SECTION_FREEFORM_SUBTYPE_GUID, 1, + &PadSection); + if (EFI_ERROR (Status) || + CompareGuid (&PadSection.FreeformSubtypeSection->SubTypeGuid, + &mEfiFfsSectionAlignmentPaddingGuid) != 0) { + return FALSE; + } + + // + // Find out if the size of the padding section is sufficient to compensate + // for the misalignment. + // + PadSize = GetSectionFileLength (PadSection.CommonHeader); + if (Misalignment > PadSize - sizeof (EFI_FREEFORM_SUBTYPE_GUID_SECTION)) { + return FALSE; + } + + // + // Move the remainder of the FFS file towards the front, and adjust the + // file size output parameter. + // + Remainder = (UINT8 *) PadSection.CommonHeader + PadSize; + memmove (Remainder - Misalignment, Remainder, + *FileSize - (UINTN) (Remainder - (UINTN) FfsFile)); + *FileSize -= Misalignment; + + // + // Update the padding section's length with the new values. Note that the + // padding is always < 64 KB, so we can ignore EFI_COMMON_SECTION_HEADER2 + // ExtendedSize. + // + PadSize -= Misalignment; + PadSection.CommonHeader->Size[0] = (UINT8) (PadSize & 0xff); + PadSection.CommonHeader->Size[1] = (UINT8) ((PadSize & 0xff00) >> 8); + PadSection.CommonHeader->Size[2] = (UINT8) ((PadSize & 0xff0000) >> 16); + + // + // Update the FFS header with the new overall length + // + FfsFileLength = GetFfsFileLength (FfsFile) - Misalignment; + if (FfsHeaderLength > sizeof(EFI_FFS_FILE_HEADER)) { + ((EFI_FFS_FILE_HEADER2 *)FfsFile)->ExtendedSize = FfsFileLength; + } else { + FfsFile->Size[0] = (UINT8) (FfsFileLength & 0x000000FF); + FfsFile->Size[1] = (UINT8) ((FfsFileLength & 0x0000FF00) >> 8); + FfsFile->Size[2] = (UINT8) ((FfsFileLength & 0x00FF0000) >> 16); + } + + // + // Clear the alignment bits: these have become meaningless now that we have + // adjusted the padding section. + // + FfsFile->Attributes &= ~(FFS_ATTRIB_DATA_ALIGNMENT | FFS_ATTRIB_DATA_ALIGNMENT2); + + // + // Recalculate the FFS header checksum. Instead of setting Header and State + // both to zero, set Header to (UINT8)(-State) so State preserves its original + // value + // + IntegrityCheck = &FfsFile->IntegrityCheck; + IntegrityCheck->Checksum.Header = (UINT8) (0x100 - FfsFile->State); + IntegrityCheck->Checksum.File = 0; + + IntegrityCheck->Checksum.Header = CalculateChecksum8 ( + (UINT8 *) FfsFile, FfsHeaderLength); + + if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) { + // + // Ffs header checksum = zero, so only need to calculate ffs body. + // + IntegrityCheck->Checksum.File = CalculateChecksum8 ( + (UINT8 *) FfsFile + FfsHeaderLength, + FfsFileLength - FfsHeaderLength); + } else { + IntegrityCheck->Checksum.File = FFS_FIXED_CHECKSUM; + } + + return TRUE; +} + +EFI_STATUS +AddFile ( + IN OUT MEMORY_FILE *FvImage, + IN FV_INFO *FvInfo, + IN UINTN Index, + IN OUT EFI_FFS_FILE_HEADER **VtfFileImage, + IN FILE *FvMapFile, + IN FILE *FvReportFile + ) +/*++ + +Routine Description: + + This function adds a file to the FV image. The file will pad to the + appropriate alignment if required. + +Arguments: + + FvImage The memory image of the FV to add it to. The current offset + must be valid. + FvInfo Pointer to information about the FV. + Index The file in the FvInfo file list to add. + VtfFileImage A pointer to the VTF file within the FvImage. If this is equal + to the end of the FvImage then no VTF previously found. + FvMapFile Pointer to FvMap File + FvReportFile Pointer to FvReport File + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED An error occurred. + EFI_OUT_OF_RESOURCES Insufficient resources exist to complete the add. + +--*/ +{ + FILE *NewFile; + UINTN FileSize; + UINT8 *FileBuffer; + UINTN NumBytesRead; + UINT32 CurrentFileAlignment; + EFI_STATUS Status; + UINTN Index1; + UINT8 FileGuidString[PRINTED_GUID_BUFFER_SIZE]; + + Index1 = 0; + // + // Verify input parameters. + // + if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Read the file to add + // + NewFile = fopen (LongFilePath (FvInfo->FvFiles[Index]), "rb"); + + if (NewFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", FvInfo->FvFiles[Index]); + return EFI_ABORTED; + } + + // + // Get the file size + // + FileSize = _filelength (fileno (NewFile)); + + // + // Read the file into a buffer + // + FileBuffer = malloc (FileSize); + if (FileBuffer == NULL) { + fclose (NewFile); + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return EFI_OUT_OF_RESOURCES; + } + + NumBytesRead = fread (FileBuffer, sizeof (UINT8), FileSize, NewFile); + + // + // Done with the file, from this point on we will just use the buffer read. + // + fclose (NewFile); + + // + // Verify read successful + // + if (NumBytesRead != sizeof (UINT8) * FileSize) { + free (FileBuffer); + Error (NULL, 0, 0004, "Error reading file", FvInfo->FvFiles[Index]); + return EFI_ABORTED; + } + + // + // For None PI Ffs file, directly add them into FvImage. + // + if (!FvInfo->IsPiFvImage) { + memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize); + if (FvInfo->SizeofFvFiles[Index] > FileSize) { + FvImage->CurrentFilePointer += FvInfo->SizeofFvFiles[Index]; + } else { + FvImage->CurrentFilePointer += FileSize; + } + goto Done; + } + + // + // Verify Ffs file + // + Status = VerifyFfsFile ((EFI_FFS_FILE_HEADER *)FileBuffer); + if (EFI_ERROR (Status)) { + free (FileBuffer); + Error (NULL, 0, 3000, "Invalid", "%s is not a valid FFS file.", FvInfo->FvFiles[Index]); + return EFI_INVALID_PARAMETER; + } + + // + // Verify space exists to add the file + // + if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) { + free (FileBuffer); + Error (NULL, 0, 4002, "Resource", "FV space is full, not enough room to add file %s.", FvInfo->FvFiles[Index]); + return EFI_OUT_OF_RESOURCES; + } + + // + // Verify the input file is the duplicated file in this Fv image + // + for (Index1 = 0; Index1 < Index; Index1 ++) { + if (CompareGuid ((EFI_GUID *) FileBuffer, &mFileGuidArray [Index1]) == 0) { + Error (NULL, 0, 2000, "Invalid parameter", "the %dth file and %uth file have the same file GUID.", (unsigned) Index1 + 1, (unsigned) Index + 1); + PrintGuid ((EFI_GUID *) FileBuffer); + free (FileBuffer); + return EFI_INVALID_PARAMETER; + } + } + CopyMem (&mFileGuidArray [Index], FileBuffer, sizeof (EFI_GUID)); + + // + // Update the file state based on polarity of the FV. + // + UpdateFfsFileState ( + (EFI_FFS_FILE_HEADER *) FileBuffer, + (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage + ); + + // + // Check if alignment is required + // + ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment); + + // + // Find the largest alignment of all the FFS files in the FV + // + if (CurrentFileAlignment > MaxFfsAlignment) { + MaxFfsAlignment = CurrentFileAlignment; + } + // + // If we have a VTF file, add it at the top. + // + if (IsVtfFile ((EFI_FFS_FILE_HEADER *) FileBuffer)) { + if ((UINTN) *VtfFileImage == (UINTN) FvImage->Eof) { + // + // No previous VTF, add this one. + // + *VtfFileImage = (EFI_FFS_FILE_HEADER *) (UINTN) ((UINTN) FvImage->FileImage + FvInfo->Size - FileSize); + // + // Sanity check. The file MUST align appropriately + // + if (((UINTN) *VtfFileImage + GetFfsHeaderLength((EFI_FFS_FILE_HEADER *)FileBuffer) - (UINTN) FvImage->FileImage) % (1 << CurrentFileAlignment)) { + Error (NULL, 0, 3000, "Invalid", "VTF file cannot be aligned on a %u-byte boundary.", (unsigned) (1 << CurrentFileAlignment)); + free (FileBuffer); + return EFI_ABORTED; + } + // + // Rebase the PE or TE image in FileBuffer of FFS file for XIP + // Rebase for the debug genfvmap tool + // + Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) *VtfFileImage - (UINTN) FvImage->FileImage, FvMapFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "Could not rebase %s.", FvInfo->FvFiles[Index]); + return Status; + } + // + // copy VTF File + // + memcpy (*VtfFileImage, FileBuffer, FileSize); + + PrintGuidToBuffer ((EFI_GUID *) FileBuffer, FileGuidString, sizeof (FileGuidString), TRUE); + fprintf (FvReportFile, "0x%08X %s\n", (unsigned)(UINTN) (((UINT8 *)*VtfFileImage) - (UINTN)FvImage->FileImage), FileGuidString); + + free (FileBuffer); + DebugMsg (NULL, 0, 9, "Add VTF FFS file in FV image", NULL); + return EFI_SUCCESS; + } else { + // + // Already found a VTF file. + // + Error (NULL, 0, 3000, "Invalid", "multiple VTF files are not permitted within a single FV."); + free (FileBuffer); + return EFI_ABORTED; + } + } + + // + // Add pad file if necessary + // + if (!AdjustInternalFfsPadding ((EFI_FFS_FILE_HEADER *) FileBuffer, FvImage, + 1 << CurrentFileAlignment, &FileSize)) { + Status = AddPadFile (FvImage, 1 << CurrentFileAlignment, *VtfFileImage, NULL, FileSize); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 4002, "Resource", "FV space is full, could not add pad file for data alignment property."); + free (FileBuffer); + return EFI_ABORTED; + } + } + // + // Add file + // + if ((UINTN) (FvImage->CurrentFilePointer + FileSize) <= (UINTN) (*VtfFileImage)) { + // + // Rebase the PE or TE image in FileBuffer of FFS file for XIP. + // Rebase Bs and Rt drivers for the debug genfvmap tool. + // + Status = FfsRebase (FvInfo, FvInfo->FvFiles[Index], (EFI_FFS_FILE_HEADER *) FileBuffer, (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage, FvMapFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "Could not rebase %s.", FvInfo->FvFiles[Index]); + return Status; + } + // + // Copy the file + // + memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize); + PrintGuidToBuffer ((EFI_GUID *) FileBuffer, FileGuidString, sizeof (FileGuidString), TRUE); + fprintf (FvReportFile, "0x%08X %s\n", (unsigned) (FvImage->CurrentFilePointer - FvImage->FileImage), FileGuidString); + FvImage->CurrentFilePointer += FileSize; + } else { + Error (NULL, 0, 4002, "Resource", "FV space is full, cannot add file %s.", FvInfo->FvFiles[Index]); + free (FileBuffer); + return EFI_ABORTED; + } + // + // Make next file start at QWord Boundary + // + while (((UINTN) FvImage->CurrentFilePointer & (EFI_FFS_FILE_HEADER_ALIGNMENT - 1)) != 0) { + FvImage->CurrentFilePointer++; + } + +Done: + // + // Free allocated memory. + // + free (FileBuffer); + + return EFI_SUCCESS; +} + +EFI_STATUS +PadFvImage ( + IN MEMORY_FILE *FvImage, + IN EFI_FFS_FILE_HEADER *VtfFileImage + ) +/*++ + +Routine Description: + + This function places a pad file between the last file in the FV and the VTF + file if the VTF file exists. + +Arguments: + + FvImage Memory file for the FV memory image + VtfFileImage The address of the VTF file. If this is the end of the FV + image, no VTF exists and no pad file is needed. + +Returns: + + EFI_SUCCESS Completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was NULL. + +--*/ +{ + EFI_FFS_FILE_HEADER *PadFile; + UINTN FileSize; + UINT32 FfsHeaderSize; + + // + // If there is no VTF or the VTF naturally follows the previous file without a + // pad file, then there's nothing to do + // + if ((UINTN) VtfFileImage == (UINTN) FvImage->Eof || \ + ((UINTN) VtfFileImage == (UINTN) FvImage->CurrentFilePointer)) { + return EFI_SUCCESS; + } + + if ((UINTN) VtfFileImage < (UINTN) FvImage->CurrentFilePointer) { + return EFI_INVALID_PARAMETER; + } + + // + // Pad file starts at beginning of free space + // + PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer; + + // + // write PadFile FFS header with PadType, don't need to set PAD file guid in its header. + // + PadFile->Type = EFI_FV_FILETYPE_FFS_PAD; + PadFile->Attributes = 0; + + // + // FileSize includes the EFI_FFS_FILE_HEADER + // + FileSize = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer; + if (FileSize >= MAX_FFS_SIZE) { + PadFile->Attributes |= FFS_ATTRIB_LARGE_FILE; + memset(PadFile->Size, 0, sizeof(UINT8) * 3); + ((EFI_FFS_FILE_HEADER2 *)PadFile)->ExtendedSize = FileSize; + FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER2); + mIsLargeFfs = TRUE; + } else { + PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF); + PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8); + PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16); + FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER); + } + + // + // Fill in checksums and state, must be zero during checksum calculation. + // + PadFile->IntegrityCheck.Checksum.Header = 0; + PadFile->IntegrityCheck.Checksum.File = 0; + PadFile->State = 0; + PadFile->IntegrityCheck.Checksum.Header = CalculateChecksum8 ((UINT8 *) PadFile, FfsHeaderSize); + PadFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + + PadFile->State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID; + + UpdateFfsFileState ( + (EFI_FFS_FILE_HEADER *) PadFile, + (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage + ); + // + // Update the current FV pointer + // + FvImage->CurrentFilePointer = FvImage->Eof; + + return EFI_SUCCESS; +} + +EFI_STATUS +UpdateResetVector ( + IN MEMORY_FILE *FvImage, + IN FV_INFO *FvInfo, + IN EFI_FFS_FILE_HEADER *VtfFile + ) +/*++ + +Routine Description: + + This parses the FV looking for the PEI core and then plugs the address into + the SALE_ENTRY point of the BSF/VTF for IPF and does BUGBUG TBD action to + complete an IA32 Bootstrap FV. + +Arguments: + + FvImage Memory file for the FV memory image + FvInfo Information read from INF file. + VtfFile Pointer to the VTF file in the FV image. + +Returns: + + EFI_SUCCESS Function Completed successfully. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + EFI_NOT_FOUND PEI Core file not found. + +--*/ +{ + EFI_FFS_FILE_HEADER *PeiCoreFile; + EFI_FFS_FILE_HEADER *SecCoreFile; + EFI_STATUS Status; + EFI_FILE_SECTION_POINTER Pe32Section; + UINT32 EntryPoint; + UINT32 BaseOfCode; + UINT16 MachineType; + EFI_PHYSICAL_ADDRESS PeiCorePhysicalAddress; + EFI_PHYSICAL_ADDRESS SecCorePhysicalAddress; + INT32 Ia32SecEntryOffset; + UINT32 *Ia32ResetAddressPtr; + UINT8 *BytePointer; + UINT8 *BytePointer2; + UINT16 *WordPointer; + UINT16 CheckSum; + UINT32 IpiVector; + UINTN Index; + EFI_FFS_FILE_STATE SavedState; + BOOLEAN Vtf0Detected; + UINT32 FfsHeaderSize; + UINT32 SecHeaderSize; + + // + // Verify input parameters + // + if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Initialize FV library + // + InitializeFvLib (FvImage->FileImage, FvInfo->Size); + + // + // Verify VTF file + // + Status = VerifyFfsFile (VtfFile); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + + if ( + (((UINTN)FvImage->Eof - (UINTN)FvImage->FileImage) >= + IA32_X64_VTF_SIGNATURE_OFFSET) && + (*(UINT32 *)(VOID*)((UINTN) FvImage->Eof - + IA32_X64_VTF_SIGNATURE_OFFSET) == + IA32_X64_VTF0_SIGNATURE) + ) { + Vtf0Detected = TRUE; + } else { + Vtf0Detected = FALSE; + } + + // + // Find the Sec Core + // + Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile); + if (EFI_ERROR (Status) || SecCoreFile == NULL) { + if (Vtf0Detected) { + // + // If the SEC core file is not found, but the VTF-0 signature + // is found, we'll treat it as a VTF-0 'Volume Top File'. + // This means no modifications are required to the VTF. + // + return EFI_SUCCESS; + } + + Error (NULL, 0, 3000, "Invalid", "could not find the SEC core file in the FV."); + return EFI_ABORTED; + } + // + // Sec Core found, now find PE32 section + // + Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section); + if (Status == EFI_NOT_FOUND) { + Status = GetSectionByType (SecCoreFile, EFI_SECTION_TE, 1, &Pe32Section); + } + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "could not find a PE32 section in the SEC core file."); + return EFI_ABORTED; + } + + SecHeaderSize = GetSectionHeaderLength(Pe32Section.CommonHeader); + Status = GetPe32Info ( + (VOID *) ((UINTN) Pe32Section.Pe32Section + SecHeaderSize), + &EntryPoint, + &BaseOfCode, + &MachineType + ); + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the SEC core."); + return EFI_ABORTED; + } + + if ( + Vtf0Detected && + (MachineType == EFI_IMAGE_MACHINE_IA32 || + MachineType == EFI_IMAGE_MACHINE_X64) + ) { + // + // If the SEC core code is IA32 or X64 and the VTF-0 signature + // is found, we'll treat it as a VTF-0 'Volume Top File'. + // This means no modifications are required to the VTF. + // + return EFI_SUCCESS; + } + + // + // Physical address is FV base + offset of PE32 + offset of the entry point + // + SecCorePhysicalAddress = FvInfo->BaseAddress; + SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + SecHeaderSize - (UINTN) FvImage->FileImage; + SecCorePhysicalAddress += EntryPoint; + DebugMsg (NULL, 0, 9, "SecCore physical entry point address", "Address = 0x%llX", (unsigned long long) SecCorePhysicalAddress); + + // + // Find the PEI Core + // + PeiCorePhysicalAddress = 0; + Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile); + if (!EFI_ERROR (Status) && (PeiCoreFile != NULL)) { + // + // PEI Core found, now find PE32 or TE section + // + Status = GetSectionByType (PeiCoreFile, EFI_SECTION_PE32, 1, &Pe32Section); + if (Status == EFI_NOT_FOUND) { + Status = GetSectionByType (PeiCoreFile, EFI_SECTION_TE, 1, &Pe32Section); + } + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "could not find either a PE32 or a TE section in PEI core file."); + return EFI_ABORTED; + } + + SecHeaderSize = GetSectionHeaderLength(Pe32Section.CommonHeader); + Status = GetPe32Info ( + (VOID *) ((UINTN) Pe32Section.Pe32Section + SecHeaderSize), + &EntryPoint, + &BaseOfCode, + &MachineType + ); + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the PEI core."); + return EFI_ABORTED; + } + // + // Physical address is FV base + offset of PE32 + offset of the entry point + // + PeiCorePhysicalAddress = FvInfo->BaseAddress; + PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + SecHeaderSize - (UINTN) FvImage->FileImage; + PeiCorePhysicalAddress += EntryPoint; + DebugMsg (NULL, 0, 9, "PeiCore physical entry point address", "Address = 0x%llX", (unsigned long long) PeiCorePhysicalAddress); + } + +if (MachineType == EFI_IMAGE_MACHINE_IA32 || MachineType == EFI_IMAGE_MACHINE_X64) { + if (PeiCorePhysicalAddress != 0) { + // + // Get the location to update + // + Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET); + + // + // Write lower 32 bits of physical address for Pei Core entry + // + *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress; + } + // + // Write SecCore Entry point relative address into the jmp instruction in reset vector. + // + Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_SEC_CORE_ENTRY_OFFSET); + + Ia32SecEntryOffset = (INT32) (SecCorePhysicalAddress - (FV_IMAGES_TOP_ADDRESS - IA32_SEC_CORE_ENTRY_OFFSET + 2)); + if (Ia32SecEntryOffset <= -65536) { + Error (NULL, 0, 3000, "Invalid", "The SEC EXE file size is too large, it must be less than 64K."); + return STATUS_ERROR; + } + + *(UINT16 *) Ia32ResetAddressPtr = (UINT16) Ia32SecEntryOffset; + + // + // Update the BFV base address + // + Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4); + *Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress); + DebugMsg (NULL, 0, 9, "update BFV base address in the top FV image", "BFV base address = 0x%llX.", (unsigned long long) FvInfo->BaseAddress); + + // + // Update the Startup AP in the FVH header block ZeroVector region. + // + BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage); + if (FvInfo->Size <= 0x10000) { + BytePointer2 = m64kRecoveryStartupApDataArray; + } else if (FvInfo->Size <= 0x20000) { + BytePointer2 = m128kRecoveryStartupApDataArray; + } else { + BytePointer2 = m128kRecoveryStartupApDataArray; + // + // Find the position to place Ap reset vector, the offset + // between the position and the end of Fvrecovery.fv file + // should not exceed 128kB to prevent Ap reset vector from + // outside legacy E and F segment + // + Status = FindApResetVectorPosition (FvImage, &BytePointer); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "FV image does not have enough space to place AP reset vector. The FV image needs to reserve at least 4KB of unused space."); + return EFI_ABORTED; + } + } + + for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) { + BytePointer[Index] = BytePointer2[Index]; + } + // + // Calculate the checksum + // + CheckSum = 0x0000; + WordPointer = (UINT16 *) (BytePointer); + for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) { + CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer)); + WordPointer++; + } + // + // Update the checksum field + // + WordPointer = (UINT16 *) (BytePointer + SIZEOF_STARTUP_DATA_ARRAY - 2); + *WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum); + + // + // IpiVector at the 4k aligned address in the top 2 blocks in the PEI FV. + // + IpiVector = (UINT32) (FV_IMAGES_TOP_ADDRESS - ((UINTN) FvImage->Eof - (UINTN) BytePointer)); + DebugMsg (NULL, 0, 9, "Startup AP Vector address", "IpiVector at 0x%X", (unsigned) IpiVector); + if ((IpiVector & 0xFFF) != 0) { + Error (NULL, 0, 3000, "Invalid", "Startup AP Vector address are not 4K aligned, because the FV size is not 4K aligned"); + return EFI_ABORTED; + } + IpiVector = IpiVector >> 12; + IpiVector = IpiVector & 0xFF; + + // + // Write IPI Vector at Offset FvrecoveryFileSize - 8 + // + Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 8); + *Ia32ResetAddressPtr = IpiVector; + } else if (MachineType == EFI_IMAGE_MACHINE_ARMT) { + // + // Since the ARM reset vector is in the FV Header you really don't need a + // Volume Top File, but if you have one for some reason don't crash... + // + } else if (MachineType == EFI_IMAGE_MACHINE_AARCH64) { + // + // Since the AArch64 reset vector is in the FV Header you really don't need a + // Volume Top File, but if you have one for some reason don't crash... + // + } else { + Error (NULL, 0, 3000, "Invalid", "machine type=0x%X in PEI core.", MachineType); + return EFI_ABORTED; + } + + // + // Now update file checksum + // + SavedState = VtfFile->State; + VtfFile->IntegrityCheck.Checksum.File = 0; + VtfFile->State = 0; + if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) { + FfsHeaderSize = GetFfsHeaderLength(VtfFile); + VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ( + (UINT8 *) ((UINT8 *)VtfFile + FfsHeaderSize), + GetFfsFileLength (VtfFile) - FfsHeaderSize + ); + } else { + VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + + VtfFile->State = SavedState; + + return EFI_SUCCESS; +} + +EFI_STATUS +FindCorePeSection( + IN VOID *FvImageBuffer, + IN UINT64 FvSize, + IN EFI_FV_FILETYPE FileType, + OUT EFI_FILE_SECTION_POINTER *Pe32Section + ) +/*++ + +Routine Description: + + Recursively searches the FV for the FFS file of specified type (typically + SEC or PEI core) and extracts the PE32 section for further processing. + +Arguments: + + FvImageBuffer Buffer containing FV data + FvSize Size of the FV + FileType Type of FFS file to search for + Pe32Section PE32 section pointer when FFS file is found. + +Returns: + + EFI_SUCCESS Function Completed successfully. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + EFI_NOT_FOUND Core file not found. + +--*/ +{ + EFI_STATUS Status; + EFI_FIRMWARE_VOLUME_HEADER *OrigFvHeader; + UINT32 OrigFvLength; + EFI_FFS_FILE_HEADER *CoreFfsFile; + UINTN FvImageFileCount; + EFI_FFS_FILE_HEADER *FvImageFile; + UINTN EncapFvSectionCount; + EFI_FILE_SECTION_POINTER EncapFvSection; + EFI_FIRMWARE_VOLUME_HEADER *EncapsulatedFvHeader; + + if (Pe32Section == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Initialize FV library, saving previous values + // + OrigFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)NULL; + GetFvHeader (&OrigFvHeader, &OrigFvLength); + InitializeFvLib(FvImageBuffer, (UINT32)FvSize); + + // + // First see if we can obtain the file directly in outer FV + // + Status = GetFileByType(FileType, 1, &CoreFfsFile); + if (!EFI_ERROR(Status) && (CoreFfsFile != NULL) ) { + + // + // Core found, now find PE32 or TE section + // + Status = GetSectionByType(CoreFfsFile, EFI_SECTION_PE32, 1, Pe32Section); + if (EFI_ERROR(Status)) { + Status = GetSectionByType(CoreFfsFile, EFI_SECTION_TE, 1, Pe32Section); + } + + if (EFI_ERROR(Status)) { + Error(NULL, 0, 3000, "Invalid", "could not find a PE32 section in the core file."); + return EFI_ABORTED; + } + + // + // Core PE/TE section, found, return + // + Status = EFI_SUCCESS; + goto EarlyExit; + } + + // + // File was not found, look for FV Image file + // + + // iterate through all FV image files in outer FV + for (FvImageFileCount = 1;; FvImageFileCount++) { + + Status = GetFileByType(EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE, FvImageFileCount, &FvImageFile); + + if (EFI_ERROR(Status) || (FvImageFile == NULL) ) { + // exit FV image file loop, no more found + break; + } + + // Found an fv image file, look for an FV image section. The PI spec does not + // preclude multiple FV image sections so we loop accordingly. + for (EncapFvSectionCount = 1;; EncapFvSectionCount++) { + + // Look for the next FV image section. The section search code will + // iterate into encapsulation sections. For example, it will iterate + // into an EFI_SECTION_GUID_DEFINED encapsulation section to find the + // EFI_SECTION_FIRMWARE_VOLUME_IMAGE sections contained therein. + Status = GetSectionByType(FvImageFile, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EncapFvSectionCount, &EncapFvSection); + + if (EFI_ERROR(Status)) { + // exit section inner loop, no more found + break; + } + + EncapsulatedFvHeader = (EFI_FIRMWARE_VOLUME_HEADER *)((UINT8 *)EncapFvSection.FVImageSection + GetSectionHeaderLength(EncapFvSection.FVImageSection)); + + // recurse to search the encapsulated FV for this core file type + Status = FindCorePeSection(EncapsulatedFvHeader, EncapsulatedFvHeader->FvLength, FileType, Pe32Section); + + if (!EFI_ERROR(Status)) { + // we found the core in the capsulated image, success + goto EarlyExit; + } + + } // end encapsulated fv image section loop + } // end fv image file loop + + // core was not found + Status = EFI_NOT_FOUND; + +EarlyExit: + + // restore FV lib values + if(OrigFvHeader != NULL) { + InitializeFvLib(OrigFvHeader, OrigFvLength); + } + + return Status; +} + +EFI_STATUS +GetCoreMachineType( + IN EFI_FILE_SECTION_POINTER Pe32Section, + OUT UINT16 *CoreMachineType + ) +/*++ + +Routine Description: + + Returns the machine type of a P32 image, typically SEC or PEI core. + +Arguments: + + Pe32Section PE32 section data + CoreMachineType The extracted machine type + +Returns: + + EFI_SUCCESS Function Completed successfully. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + +--*/ +{ + EFI_STATUS Status; + UINT32 EntryPoint; + UINT32 BaseOfCode; + + if (CoreMachineType == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = GetPe32Info( + (VOID *)((UINTN)Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader)), + &EntryPoint, + &BaseOfCode, + CoreMachineType + ); + if (EFI_ERROR(Status)) { + Error(NULL, 0, 3000, "Invalid", "could not get the PE32 machine type for the core."); + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetCoreEntryPointAddress( + IN VOID *FvImageBuffer, + IN FV_INFO *FvInfo, + IN EFI_FILE_SECTION_POINTER Pe32Section, + OUT EFI_PHYSICAL_ADDRESS *CoreEntryAddress +) +/*++ + +Routine Description: + + Returns the physical address of the core (SEC or PEI) entry point. + +Arguments: + + FvImageBuffer Pointer to buffer containing FV data + FvInfo Info for the parent FV + Pe32Section PE32 section data + CoreEntryAddress The extracted core entry physical address + +Returns: + + EFI_SUCCESS Function Completed successfully. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + +--*/ +{ + EFI_STATUS Status; + UINT32 EntryPoint; + UINT32 BaseOfCode; + UINT16 MachineType; + EFI_PHYSICAL_ADDRESS EntryPhysicalAddress; + + if (CoreEntryAddress == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = GetPe32Info( + (VOID *)((UINTN)Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader)), + &EntryPoint, + &BaseOfCode, + &MachineType + ); + if (EFI_ERROR(Status)) { + Error(NULL, 0, 3000, "Invalid", "could not get the PE32 entry point for the core."); + return EFI_ABORTED; + } + + // + // Physical address is FV base + offset of PE32 + offset of the entry point + // + EntryPhysicalAddress = FvInfo->BaseAddress; + EntryPhysicalAddress += (UINTN)Pe32Section.Pe32Section + GetSectionHeaderLength(Pe32Section.CommonHeader) - (UINTN)FvImageBuffer; + EntryPhysicalAddress += EntryPoint; + + *CoreEntryAddress = EntryPhysicalAddress; + + return EFI_SUCCESS; +} + +EFI_STATUS +UpdateArmResetVectorIfNeeded ( + IN MEMORY_FILE *FvImage, + IN FV_INFO *FvInfo + ) +/*++ + +Routine Description: + This parses the FV looking for SEC and patches that address into the + beginning of the FV header. + + For ARM32 the reset vector is at 0x00000000 or 0xFFFF0000. + For AArch64 the reset vector is at 0x00000000. + + This would commonly map to the first entry in the ROM. + ARM32 Exceptions: + Reset +0 + Undefined +4 + SWI +8 + Prefetch Abort +12 + Data Abort +16 + IRQ +20 + FIQ +24 + + We support two schemes on ARM. + 1) Beginning of the FV is the reset vector + 2) Reset vector is data bytes FDF file and that code branches to reset vector + in the beginning of the FV (fixed size offset). + + Need to have the jump for the reset vector at location zero. + We also need to store the address or PEI (if it exists). + We stub out a return from interrupt in case the debugger + is using SWI (not done for AArch64, not enough space in struct). + The optional entry to the common exception handler is + to support full featured exception handling from ROM and is currently + not support by this tool. + +Arguments: + FvImage Memory file for the FV memory image + FvInfo Information read from INF file. + +Returns: + + EFI_SUCCESS Function Completed successfully. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + EFI_NOT_FOUND PEI Core file not found. + +--*/ +{ + EFI_STATUS Status; + EFI_FILE_SECTION_POINTER SecPe32; + EFI_FILE_SECTION_POINTER PeiPe32; + BOOLEAN UpdateVectorSec = FALSE; + BOOLEAN UpdateVectorPei = FALSE; + UINT16 MachineType = 0; + EFI_PHYSICAL_ADDRESS SecCoreEntryAddress = 0; + UINT16 PeiMachineType = 0; + EFI_PHYSICAL_ADDRESS PeiCoreEntryAddress = 0; + + // + // Verify input parameters + // + if (FvImage == NULL || FvInfo == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // Locate an SEC Core instance and if found extract the machine type and entry point address + // + Status = FindCorePeSection(FvImage->FileImage, FvInfo->Size, EFI_FV_FILETYPE_SECURITY_CORE, &SecPe32); + if (!EFI_ERROR(Status)) { + + Status = GetCoreMachineType(SecPe32, &MachineType); + if (EFI_ERROR(Status)) { + Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for SEC Core."); + return EFI_ABORTED; + } + + Status = GetCoreEntryPointAddress(FvImage->FileImage, FvInfo, SecPe32, &SecCoreEntryAddress); + if (EFI_ERROR(Status)) { + Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 entry point address for SEC Core."); + return EFI_ABORTED; + } + + VerboseMsg("UpdateArmResetVectorIfNeeded found SEC core entry at 0x%llx", (unsigned long long)SecCoreEntryAddress); + UpdateVectorSec = TRUE; + } + + // + // Locate a PEI Core instance and if found extract the machine type and entry point address + // + Status = FindCorePeSection(FvImage->FileImage, FvInfo->Size, EFI_FV_FILETYPE_PEI_CORE, &PeiPe32); + if (!EFI_ERROR(Status)) { + + Status = GetCoreMachineType(PeiPe32, &PeiMachineType); + if (EFI_ERROR(Status)) { + Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for PEI Core."); + return EFI_ABORTED; + } + + Status = GetCoreEntryPointAddress(FvImage->FileImage, FvInfo, PeiPe32, &PeiCoreEntryAddress); + if (EFI_ERROR(Status)) { + Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 entry point address for PEI Core."); + return EFI_ABORTED; + } + + VerboseMsg("UpdateArmResetVectorIfNeeded found PEI core entry at 0x%llx", (unsigned long long)PeiCoreEntryAddress); + + // if we previously found an SEC Core make sure machine types match + if (UpdateVectorSec && (MachineType != PeiMachineType)) { + Error(NULL, 0, 3000, "Invalid", "SEC and PEI machine types do not match, can't update reset vector"); + return EFI_ABORTED; + } + else { + MachineType = PeiMachineType; + } + + UpdateVectorPei = TRUE; + } + + if (!UpdateVectorSec && !UpdateVectorPei) { + return EFI_SUCCESS; + } + + if (MachineType == EFI_IMAGE_MACHINE_ARMT) { + // ARM: Array of 4 UINT32s: + // 0 - is branch relative to SEC entry point + // 1 - PEI Entry Point + // 2 - movs pc,lr for a SWI handler + // 3 - Place holder for Common Exception Handler + UINT32 ResetVector[4]; + + memset(ResetVector, 0, sizeof (ResetVector)); + + // if we found an SEC core entry point then generate a branch instruction + // to it and populate a debugger SWI entry as well + if (UpdateVectorSec) { + + VerboseMsg("UpdateArmResetVectorIfNeeded updating ARM SEC vector"); + + // B SecEntryPoint - signed_immed_24 part +/-32MB offset + // on ARM, the PC is always 8 ahead, so we're not really jumping from the base address, but from base address + 8 + ResetVector[0] = (INT32)(SecCoreEntryAddress - FvInfo->BaseAddress - 8) >> 2; + + if (ResetVector[0] > 0x00FFFFFF) { + Error(NULL, 0, 3000, "Invalid", "SEC Entry point must be within 32MB of the start of the FV"); + return EFI_ABORTED; + } + + // Add opcode for an unconditional branch with no link. i.e.: " B SecEntryPoint" + ResetVector[0] |= ARMT_UNCONDITIONAL_JUMP_INSTRUCTION; + + // SWI handler movs pc,lr. Just in case a debugger uses SWI + ResetVector[2] = 0xE1B0F07E; + + // Place holder to support a common interrupt handler from ROM. + // Currently not supported. For this to be used the reset vector would not be in this FV + // and the exception vectors would be hard coded in the ROM and just through this address + // to find a common handler in the a module in the FV. + ResetVector[3] = 0; + } + + // if a PEI core entry was found place its address in the vector area + if (UpdateVectorPei) { + + VerboseMsg("UpdateArmResetVectorIfNeeded updating ARM PEI address"); + + // Address of PEI Core, if we have one + ResetVector[1] = (UINT32)PeiCoreEntryAddress; + } + + // + // Copy to the beginning of the FV + // + memcpy(FvImage->FileImage, ResetVector, sizeof (ResetVector)); + + } else if (MachineType == EFI_IMAGE_MACHINE_AARCH64) { + // AArch64: Used as UINT64 ResetVector[2] + // 0 - is branch relative to SEC entry point + // 1 - PEI Entry Point + UINT64 ResetVector[2]; + + memset(ResetVector, 0, sizeof (ResetVector)); + + /* NOTE: + ARMT above has an entry in ResetVector[2] for SWI. The way we are using the ResetVector + array at the moment, for AArch64, does not allow us space for this as the header only + allows for a fixed amount of bytes at the start. If we are sure that UEFI will live + within the first 4GB of addressable RAM we could potentially adopt the same ResetVector + layout as above. But for the moment we replace the four 32bit vectors with two 64bit + vectors in the same area of the Image heasder. This allows UEFI to start from a 64bit + base. + */ + + // if we found an SEC core entry point then generate a branch instruction to it + if (UpdateVectorSec) { + + VerboseMsg("UpdateArmResetVectorIfNeeded updating AArch64 SEC vector"); + + ResetVector[0] = (UINT64)(SecCoreEntryAddress - FvInfo->BaseAddress) >> 2; + + // B SecEntryPoint - signed_immed_26 part +/-128MB offset + if (ResetVector[0] > 0x03FFFFFF) { + Error(NULL, 0, 3000, "Invalid", "SEC Entry point must be within 128MB of the start of the FV"); + return EFI_ABORTED; + } + // Add opcode for an unconditional branch with no link. i.e.: " B SecEntryPoint" + ResetVector[0] |= ARM64_UNCONDITIONAL_JUMP_INSTRUCTION; + } + + // if a PEI core entry was found place its address in the vector area + if (UpdateVectorPei) { + + VerboseMsg("UpdateArmResetVectorIfNeeded updating AArch64 PEI address"); + + // Address of PEI Core, if we have one + ResetVector[1] = (UINT64)PeiCoreEntryAddress; + } + + // + // Copy to the beginning of the FV + // + memcpy(FvImage->FileImage, ResetVector, sizeof (ResetVector)); + + } else { + Error(NULL, 0, 3000, "Invalid", "Unknown machine type"); + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +UpdateRiscvResetVectorIfNeeded ( + MEMORY_FILE *FvImage, + FV_INFO *FvInfo + ) +/*++ + +Routine Description: + This parses the FV looking for SEC and patches that address into the + beginning of the FV header. + + For RISC-V ISA, the reset vector is at 0xfff~ff00h or 200h + +Arguments: + FvImage Memory file for the FV memory image/ + FvInfo Information read from INF file. + +Returns: + + EFI_SUCCESS Function Completed successfully. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + EFI_NOT_FOUND PEI Core file not found. + +--*/ +{ + EFI_STATUS Status; + UINT16 MachineType; + EFI_FILE_SECTION_POINTER SecPe32; + EFI_PHYSICAL_ADDRESS SecCoreEntryAddress; + + UINT32 bSecCore; + UINT32 tmp; + + + // + // Verify input parameters + // + if (FvImage == NULL || FvInfo == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Initialize FV library + // + InitializeFvLib (FvImage->FileImage, FvInfo->Size); + + // + // Find the Sec Core + // + Status = FindCorePeSection(FvImage->FileImage, FvInfo->Size, EFI_FV_FILETYPE_SECURITY_CORE, &SecPe32); + if(EFI_ERROR(Status)) { + printf("skip because Secutiry Core not found\n"); + return EFI_SUCCESS; + } + + DebugMsg (NULL, 0, 9, "Update SEC core in FV Header", NULL); + + Status = GetCoreMachineType(SecPe32, &MachineType); + if(EFI_ERROR(Status)) { + Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for SEC core."); + return EFI_ABORTED; + } + + if (MachineType != EFI_IMAGE_MACHINE_RISCV64) { + Error(NULL, 0, 3000, "Invalid", "Could not update SEC core because Machine type is not RiscV."); + return EFI_ABORTED; + } + + Status = GetCoreEntryPointAddress(FvImage->FileImage, FvInfo, SecPe32, &SecCoreEntryAddress); + if(EFI_ERROR(Status)) { + Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 entry point address for SEC Core."); + return EFI_ABORTED; + } + + VerboseMsg("SecCore entry point Address = 0x%llX", (unsigned long long) SecCoreEntryAddress); + VerboseMsg("BaseAddress = 0x%llX", (unsigned long long) FvInfo->BaseAddress); + bSecCore = (UINT32)(SecCoreEntryAddress - FvInfo->BaseAddress); + VerboseMsg("offset = 0x%llX", bSecCore); + + if(bSecCore > 0x0fffff) { + Error(NULL, 0, 3000, "Invalid", "SEC Entry point must be within 1MB of start of the FV"); + return EFI_ABORTED; + } + + tmp = bSecCore; + bSecCore = 0; + //J-type + bSecCore = (tmp&0x100000)<<11; //imm[20] at bit[31] + bSecCore |= (tmp&0x0007FE)<<20; //imm[10:1] at bit[30:21] + bSecCore |= (tmp&0x000800)<<9; //imm[11] at bit[20] + bSecCore |= (tmp&0x0FF000); //imm[19:12] at bit[19:12] + bSecCore |= 0x6F; //JAL opcode + + memcpy(FvImage->FileImage, &bSecCore, sizeof(bSecCore)); + + return EFI_SUCCESS; +} + +EFI_STATUS +GetPe32Info ( + IN UINT8 *Pe32, + OUT UINT32 *EntryPoint, + OUT UINT32 *BaseOfCode, + OUT UINT16 *MachineType + ) +/*++ + +Routine Description: + + Retrieves the PE32 entry point offset and machine type from PE image or TeImage. + See EfiImage.h for machine types. The entry point offset is from the beginning + of the PE32 buffer passed in. + +Arguments: + + Pe32 Beginning of the PE32. + EntryPoint Offset from the beginning of the PE32 to the image entry point. + BaseOfCode Base address of code. + MachineType Magic number for the machine type. + +Returns: + + EFI_SUCCESS Function completed successfully. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + EFI_UNSUPPORTED The operation is unsupported. + +--*/ +{ + EFI_IMAGE_DOS_HEADER *DosHeader; + EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; + EFI_TE_IMAGE_HEADER *TeHeader; + + // + // Verify input parameters + // + if (Pe32 == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // First check whether it is one TE Image. + // + TeHeader = (EFI_TE_IMAGE_HEADER *) Pe32; + if (TeHeader->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + // + // By TeImage Header to get output + // + *EntryPoint = TeHeader->AddressOfEntryPoint + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize; + *BaseOfCode = TeHeader->BaseOfCode + sizeof (EFI_TE_IMAGE_HEADER) - TeHeader->StrippedSize; + *MachineType = TeHeader->Machine; + } else { + + // + // Then check whether + // First is the DOS header + // + DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32; + + // + // Verify DOS header is expected + // + if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "Unknown magic number in the DOS header, 0x%04X.", DosHeader->e_magic); + return EFI_UNSUPPORTED; + } + // + // Immediately following is the NT header. + // + ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *) ((UINTN) Pe32 + DosHeader->e_lfanew); + + // + // Verify NT header is expected + // + if (ImgHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "Unrecognized image signature 0x%08X.", (unsigned) ImgHdr->Pe32.Signature); + return EFI_UNSUPPORTED; + } + // + // Get output + // + *EntryPoint = ImgHdr->Pe32.OptionalHeader.AddressOfEntryPoint; + *BaseOfCode = ImgHdr->Pe32.OptionalHeader.BaseOfCode; + *MachineType = ImgHdr->Pe32.FileHeader.Machine; + } + + // + // Verify machine type is supported + // + if ((*MachineType != EFI_IMAGE_MACHINE_IA32) && (*MachineType != EFI_IMAGE_MACHINE_X64) && (*MachineType != EFI_IMAGE_MACHINE_EBC) && + (*MachineType != EFI_IMAGE_MACHINE_ARMT) && (*MachineType != EFI_IMAGE_MACHINE_AARCH64) && + (*MachineType != EFI_IMAGE_MACHINE_RISCV64)) { + Error (NULL, 0, 3000, "Invalid", "Unrecognized machine type in the PE32 file."); + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GenerateFvImage ( + IN CHAR8 *InfFileImage, + IN UINTN InfFileSize, + IN CHAR8 *FvFileName, + IN CHAR8 *MapFileName + ) +/*++ + +Routine Description: + + This is the main function which will be called from application. + +Arguments: + + InfFileImage Buffer containing the INF file contents. + InfFileSize Size of the contents of the InfFileImage buffer. + FvFileName Requested name for the FV file. + MapFileName Fv map file to log fv driver information. + +Returns: + + EFI_SUCCESS Function completed successfully. + EFI_OUT_OF_RESOURCES Could not allocate required resources. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + +--*/ +{ + EFI_STATUS Status; + MEMORY_FILE InfMemoryFile; + MEMORY_FILE FvImageMemoryFile; + UINTN Index; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_FFS_FILE_HEADER *VtfFileImage; + UINT8 *FvBufferHeader; // to make sure fvimage header 8 type alignment. + UINT8 *FvImage; + UINTN FvImageSize; + FILE *FvFile; + CHAR8 *FvMapName; + FILE *FvMapFile; + EFI_FIRMWARE_VOLUME_EXT_HEADER *FvExtHeader; + FILE *FvExtHeaderFile; + UINTN FileSize; + CHAR8 *FvReportName; + FILE *FvReportFile; + + FvBufferHeader = NULL; + FvFile = NULL; + FvMapName = NULL; + FvMapFile = NULL; + FvReportName = NULL; + FvReportFile = NULL; + + if (InfFileImage != NULL) { + // + // Initialize file structures + // + InfMemoryFile.FileImage = InfFileImage; + InfMemoryFile.CurrentFilePointer = InfFileImage; + InfMemoryFile.Eof = InfFileImage + InfFileSize; + + // + // Parse the FV inf file for header information + // + Status = ParseFvInf (&InfMemoryFile, &mFvDataInfo); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "Error parsing file", "the input FV INF file."); + return Status; + } + } + + // + // Update the file name return values + // + if (FvFileName == NULL && mFvDataInfo.FvName[0] != '\0') { + FvFileName = mFvDataInfo.FvName; + } + + if (FvFileName == NULL) { + Error (NULL, 0, 1001, "Missing option", "Output file name"); + return EFI_ABORTED; + } + + if (mFvDataInfo.FvBlocks[0].Length == 0) { + Error (NULL, 0, 1001, "Missing required argument", "Block Size"); + return EFI_ABORTED; + } + + // + // Debug message Fv File System Guid + // + if (mFvDataInfo.FvFileSystemGuidSet) { + DebugMsg (NULL, 0, 9, "FV File System Guid", "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + (unsigned) mFvDataInfo.FvFileSystemGuid.Data1, + mFvDataInfo.FvFileSystemGuid.Data2, + mFvDataInfo.FvFileSystemGuid.Data3, + mFvDataInfo.FvFileSystemGuid.Data4[0], + mFvDataInfo.FvFileSystemGuid.Data4[1], + mFvDataInfo.FvFileSystemGuid.Data4[2], + mFvDataInfo.FvFileSystemGuid.Data4[3], + mFvDataInfo.FvFileSystemGuid.Data4[4], + mFvDataInfo.FvFileSystemGuid.Data4[5], + mFvDataInfo.FvFileSystemGuid.Data4[6], + mFvDataInfo.FvFileSystemGuid.Data4[7]); + } + + // + // Add PI FV extension header + // + FvExtHeader = NULL; + FvExtHeaderFile = NULL; + if (mFvDataInfo.FvExtHeaderFile[0] != 0) { + // + // Open the FV Extension Header file + // + FvExtHeaderFile = fopen (LongFilePath (mFvDataInfo.FvExtHeaderFile), "rb"); + if (FvExtHeaderFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", mFvDataInfo.FvExtHeaderFile); + return EFI_ABORTED; + } + + // + // Get the file size + // + FileSize = _filelength (fileno (FvExtHeaderFile)); + + // + // Allocate a buffer for the FV Extension Header + // + FvExtHeader = malloc(FileSize); + if (FvExtHeader == NULL) { + fclose (FvExtHeaderFile); + return EFI_OUT_OF_RESOURCES; + } + + // + // Read the FV Extension Header + // + fread (FvExtHeader, sizeof (UINT8), FileSize, FvExtHeaderFile); + fclose (FvExtHeaderFile); + + // + // See if there is an override for the FV Name GUID + // + if (mFvDataInfo.FvNameGuidSet) { + memcpy (&FvExtHeader->FvName, &mFvDataInfo.FvNameGuid, sizeof (EFI_GUID)); + } + memcpy (&mFvDataInfo.FvNameGuid, &FvExtHeader->FvName, sizeof (EFI_GUID)); + mFvDataInfo.FvNameGuidSet = TRUE; + } else if (mFvDataInfo.FvNameGuidSet) { + // + // Allocate a buffer for the FV Extension Header + // + FvExtHeader = malloc(sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER)); + if (FvExtHeader == NULL) { + return EFI_OUT_OF_RESOURCES; + } + memcpy (&FvExtHeader->FvName, &mFvDataInfo.FvNameGuid, sizeof (EFI_GUID)); + FvExtHeader->ExtHeaderSize = sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER); + } + + // + // Debug message Fv Name Guid + // + if (mFvDataInfo.FvNameGuidSet) { + DebugMsg (NULL, 0, 9, "FV Name Guid", "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + (unsigned) mFvDataInfo.FvNameGuid.Data1, + mFvDataInfo.FvNameGuid.Data2, + mFvDataInfo.FvNameGuid.Data3, + mFvDataInfo.FvNameGuid.Data4[0], + mFvDataInfo.FvNameGuid.Data4[1], + mFvDataInfo.FvNameGuid.Data4[2], + mFvDataInfo.FvNameGuid.Data4[3], + mFvDataInfo.FvNameGuid.Data4[4], + mFvDataInfo.FvNameGuid.Data4[5], + mFvDataInfo.FvNameGuid.Data4[6], + mFvDataInfo.FvNameGuid.Data4[7]); + } + + if (CompareGuid (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem2Guid) == 0 || + CompareGuid (&mFvDataInfo.FvFileSystemGuid, &mEfiFirmwareFileSystem3Guid) == 0) { + mFvDataInfo.IsPiFvImage = TRUE; + } + + // + // FvMap file to log the function address of all modules in one Fvimage + // + if (MapFileName != NULL) { + if (strlen (MapFileName) > MAX_LONG_FILE_PATH - 1) { + Error (NULL, 0, 1003, "Invalid option value", "MapFileName %s is too long!", MapFileName); + Status = EFI_ABORTED; + goto Finish; + } + + FvMapName = malloc (strlen (MapFileName) + 1); + if (FvMapName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + Status = EFI_OUT_OF_RESOURCES; + goto Finish; + } + + strcpy (FvMapName, MapFileName); + } else { + if (strlen (FvFileName) + strlen (".map") > MAX_LONG_FILE_PATH - 1) { + Error (NULL, 0, 1003, "Invalid option value", "FvFileName %s is too long!", FvFileName); + Status = EFI_ABORTED; + goto Finish; + } + + FvMapName = malloc (strlen (FvFileName) + strlen (".map") + 1); + if (FvMapName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + Status = EFI_OUT_OF_RESOURCES; + goto Finish; + } + + strcpy (FvMapName, FvFileName); + strcat (FvMapName, ".map"); + } + VerboseMsg ("FV Map file name is %s", FvMapName); + + // + // FvReport file to log the FV information in one Fvimage + // + if (strlen (FvFileName) + strlen (".txt") > MAX_LONG_FILE_PATH - 1) { + Error (NULL, 0, 1003, "Invalid option value", "FvFileName %s is too long!", FvFileName); + Status = EFI_ABORTED; + goto Finish; + } + + FvReportName = malloc (strlen (FvFileName) + strlen (".txt") + 1); + if (FvReportName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + Status = EFI_OUT_OF_RESOURCES; + goto Finish; + } + + strcpy (FvReportName, FvFileName); + strcat (FvReportName, ".txt"); + + // + // Calculate the FV size and Update Fv Size based on the actual FFS files. + // And Update mFvDataInfo data. + // + Status = CalculateFvSize (&mFvDataInfo); + if (EFI_ERROR (Status)) { + goto Finish; + } + VerboseMsg ("the generated FV image size is %u bytes", (unsigned) mFvDataInfo.Size); + + // + // support fv image and empty fv image + // + FvImageSize = mFvDataInfo.Size; + + // + // Allocate the FV, assure FvImage Header 8 byte alignment + // + FvBufferHeader = malloc (FvImageSize + sizeof (UINT64)); + if (FvBufferHeader == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Finish; + } + FvImage = (UINT8 *) (((UINTN) FvBufferHeader + 7) & ~7); + + // + // Initialize the FV to the erase polarity + // + if (mFvDataInfo.FvAttributes == 0) { + // + // Set Default Fv Attribute + // + mFvDataInfo.FvAttributes = FV_DEFAULT_ATTRIBUTE; + } + if (mFvDataInfo.FvAttributes & EFI_FVB2_ERASE_POLARITY) { + memset (FvImage, -1, FvImageSize); + } else { + memset (FvImage, 0, FvImageSize); + } + + // + // Initialize FV header + // + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage; + + // + // Initialize the zero vector to all zeros. + // + memset (FvHeader->ZeroVector, 0, 16); + + // + // Copy the Fv file system GUID + // + memcpy (&FvHeader->FileSystemGuid, &mFvDataInfo.FvFileSystemGuid, sizeof (EFI_GUID)); + + FvHeader->FvLength = FvImageSize; + FvHeader->Signature = EFI_FVH_SIGNATURE; + FvHeader->Attributes = mFvDataInfo.FvAttributes; + FvHeader->Revision = EFI_FVH_REVISION; + FvHeader->ExtHeaderOffset = 0; + FvHeader->Reserved[0] = 0; + + // + // Copy firmware block map + // + for (Index = 0; mFvDataInfo.FvBlocks[Index].Length != 0; Index++) { + FvHeader->BlockMap[Index].NumBlocks = mFvDataInfo.FvBlocks[Index].NumBlocks; + FvHeader->BlockMap[Index].Length = mFvDataInfo.FvBlocks[Index].Length; + } + + // + // Add block map terminator + // + FvHeader->BlockMap[Index].NumBlocks = 0; + FvHeader->BlockMap[Index].Length = 0; + + // + // Complete the header + // + FvHeader->HeaderLength = (UINT16) (((UINTN) &(FvHeader->BlockMap[Index + 1])) - (UINTN) FvImage); + FvHeader->Checksum = 0; + FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + + // + // If there is no FFS file, generate one empty FV + // + if (mFvDataInfo.FvFiles[0][0] == 0 && !mFvDataInfo.FvNameGuidSet) { + goto WriteFile; + } + + // + // Initialize our "file" view of the buffer + // + FvImageMemoryFile.FileImage = (CHAR8 *)FvImage; + FvImageMemoryFile.CurrentFilePointer = (CHAR8 *)FvImage + FvHeader->HeaderLength; + FvImageMemoryFile.Eof = (CHAR8 *)FvImage + FvImageSize; + + // + // Initialize the FV library. + // + InitializeFvLib (FvImageMemoryFile.FileImage, FvImageSize); + + // + // Initialize the VTF file address. + // + VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof; + + // + // Open FvMap file + // + FvMapFile = fopen (LongFilePath (FvMapName), "w"); + if (FvMapFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", FvMapName); + Status = EFI_ABORTED; + goto Finish; + } + + // + // Open FvReport file + // + FvReportFile = fopen (LongFilePath (FvReportName), "w"); + if (FvReportFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", FvReportName); + Status = EFI_ABORTED; + goto Finish; + } + // + // record FV size information into FvMap file. + // + if (mFvTotalSize != 0) { + fprintf (FvMapFile, EFI_FV_TOTAL_SIZE_STRING); + fprintf (FvMapFile, " = 0x%x\n", (unsigned) mFvTotalSize); + } + if (mFvTakenSize != 0) { + fprintf (FvMapFile, EFI_FV_TAKEN_SIZE_STRING); + fprintf (FvMapFile, " = 0x%x\n", (unsigned) mFvTakenSize); + } + if (mFvTotalSize != 0 && mFvTakenSize != 0) { + fprintf (FvMapFile, EFI_FV_SPACE_SIZE_STRING); + fprintf (FvMapFile, " = 0x%x\n\n", (unsigned) (mFvTotalSize - mFvTakenSize)); + } + + // + // record FV size information to FvReportFile. + // + fprintf (FvReportFile, "%s = 0x%x\n", EFI_FV_TOTAL_SIZE_STRING, (unsigned) mFvTotalSize); + fprintf (FvReportFile, "%s = 0x%x\n", EFI_FV_TAKEN_SIZE_STRING, (unsigned) mFvTakenSize); + + // + // Add PI FV extension header + // + if (FvExtHeader != NULL) { + // + // Add FV Extended Header contents to the FV as a PAD file + // + AddPadFile (&FvImageMemoryFile, 4, VtfFileImage, FvExtHeader, 0); + + // + // Fv Extension header change update Fv Header Check sum + // + FvHeader->Checksum = 0; + FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + } + + // + // Add files to FV + // + for (Index = 0; mFvDataInfo.FvFiles[Index][0] != 0; Index++) { + // + // Add the file + // + Status = AddFile (&FvImageMemoryFile, &mFvDataInfo, Index, &VtfFileImage, FvMapFile, FvReportFile); + + // + // Exit if error detected while adding the file + // + if (EFI_ERROR (Status)) { + goto Finish; + } + } + + // + // If there is a VTF file, some special actions need to occur. + // + if ((UINTN) VtfFileImage != (UINTN) FvImageMemoryFile.Eof) { + // + // Pad from the end of the last file to the beginning of the VTF file. + // If the left space is less than sizeof (EFI_FFS_FILE_HEADER)? + // + Status = PadFvImage (&FvImageMemoryFile, VtfFileImage); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 4002, "Resource", "FV space is full, cannot add pad file between the last file and the VTF file."); + goto Finish; + } + + if (!mArm && !mRiscV) { + // + // Update reset vector (SALE_ENTRY for IPF) + // Now for IA32 and IA64 platform, the fv which has bsf file must have the + // EndAddress of 0xFFFFFFFF (unless the section was rebased). + // Thus, only this type fv needs to update the reset vector. + // If the PEI Core is found, the VTF file will probably get + // corrupted by updating the entry point. + // + if (mFvDataInfo.ForceRebase == 1 || + (mFvDataInfo.BaseAddress + mFvDataInfo.Size) == FV_IMAGES_TOP_ADDRESS) { + Status = UpdateResetVector (&FvImageMemoryFile, &mFvDataInfo, VtfFileImage); + if (EFI_ERROR(Status)) { + Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector."); + goto Finish; + } + DebugMsg (NULL, 0, 9, "Update Reset vector in VTF file", NULL); + } + } + } + + if (mArm) { + Status = UpdateArmResetVectorIfNeeded (&FvImageMemoryFile, &mFvDataInfo); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector."); + goto Finish; + } + + // + // Update Checksum for FvHeader + // + FvHeader->Checksum = 0; + FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + } + + if (mRiscV) { + // + // Update RISCV reset vector. + // + Status = UpdateRiscvResetVectorIfNeeded (&FvImageMemoryFile, &mFvDataInfo); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "Could not update the reset vector for RISC-V."); + goto Finish; + } + // + // Update Checksum for FvHeader + // + FvHeader->Checksum = 0; + FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + } + + // + // Update FV Alignment attribute to the largest alignment of all the FFS files in the FV + // + if (((FvHeader->Attributes & EFI_FVB2_WEAK_ALIGNMENT) != EFI_FVB2_WEAK_ALIGNMENT) && + (((FvHeader->Attributes & EFI_FVB2_ALIGNMENT) >> 16)) < MaxFfsAlignment) { + FvHeader->Attributes = ((MaxFfsAlignment << 16) | (FvHeader->Attributes & 0xFFFF)); + // + // Update Checksum for FvHeader + // + FvHeader->Checksum = 0; + FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + } + + // + // If there are large FFS in FV, the file system GUID should set to system 3 GUID. + // + if (mIsLargeFfs && CompareGuid (&FvHeader->FileSystemGuid, &mEfiFirmwareFileSystem2Guid) == 0) { + memcpy (&FvHeader->FileSystemGuid, &mEfiFirmwareFileSystem3Guid, sizeof (EFI_GUID)); + FvHeader->Checksum = 0; + FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + } + +WriteFile: + // + // Write fv file + // + FvFile = fopen (LongFilePath (FvFileName), "wb"); + if (FvFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", FvFileName); + Status = EFI_ABORTED; + goto Finish; + } + + if (fwrite (FvImage, 1, FvImageSize, FvFile) != FvImageSize) { + Error (NULL, 0, 0002, "Error writing file", FvFileName); + Status = EFI_ABORTED; + goto Finish; + } + +Finish: + if (FvBufferHeader != NULL) { + free (FvBufferHeader); + } + + if (FvExtHeader != NULL) { + free (FvExtHeader); + } + + if (FvMapName != NULL) { + free (FvMapName); + } + + if (FvReportName != NULL) { + free (FvReportName); + } + + if (FvFile != NULL) { + fflush (FvFile); + fclose (FvFile); + } + + if (FvMapFile != NULL) { + fflush (FvMapFile); + fclose (FvMapFile); + } + + if (FvReportFile != NULL) { + fflush (FvReportFile); + fclose (FvReportFile); + } + return Status; +} + +EFI_STATUS +UpdatePeiCoreEntryInFit ( + IN FIT_TABLE *FitTablePtr, + IN UINT64 PeiCorePhysicalAddress + ) +/*++ + +Routine Description: + + This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from + Sec to Pei Core + +Arguments: + + FitTablePtr - The pointer of FIT_TABLE. + PeiCorePhysicalAddress - The address of Pei Core entry. + +Returns: + + EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully. + EFI_NOT_FOUND - Not found the PEI_CORE FIT entry. + +--*/ +{ + FIT_TABLE *TmpFitPtr; + UINTN Index; + UINTN NumFitComponents; + + TmpFitPtr = FitTablePtr; + NumFitComponents = TmpFitPtr->CompSize; + + for (Index = 0; Index < NumFitComponents; Index++) { + if ((TmpFitPtr->CvAndType & FIT_TYPE_MASK) == COMP_TYPE_FIT_PEICORE) { + TmpFitPtr->CompAddress = PeiCorePhysicalAddress; + return EFI_SUCCESS; + } + + TmpFitPtr++; + } + + return EFI_NOT_FOUND; +} + +VOID +UpdateFitCheckSum ( + IN FIT_TABLE *FitTablePtr + ) +/*++ + +Routine Description: + + This function is used to update the checksum for FIT. + + +Arguments: + + FitTablePtr - The pointer of FIT_TABLE. + +Returns: + + None. + +--*/ +{ + if ((FitTablePtr->CvAndType & CHECKSUM_BIT_MASK) >> 7) { + FitTablePtr->CheckSum = 0; + FitTablePtr->CheckSum = CalculateChecksum8 ((UINT8 *) FitTablePtr, FitTablePtr->CompSize * 16); + } +} + +EFI_STATUS +CalculateFvSize ( + FV_INFO *FvInfoPtr + ) +/*++ +Routine Description: + Calculate the FV size and Update Fv Size based on the actual FFS files. + And Update FvInfo data. + +Arguments: + FvInfoPtr - The pointer to FV_INFO structure. + +Returns: + EFI_ABORTED - Ffs Image Error + EFI_SUCCESS - Successfully update FvSize +--*/ +{ + UINTN CurrentOffset; + UINTN OrigOffset; + UINTN Index; + FILE *fpin; + UINTN FfsFileSize; + UINTN FvExtendHeaderSize; + UINT32 FfsAlignment; + UINT32 FfsHeaderSize; + EFI_FFS_FILE_HEADER FfsHeader; + UINTN VtfFileSize; + UINTN MaxPadFileSize; + + FvExtendHeaderSize = 0; + MaxPadFileSize = 0; + VtfFileSize = 0; + fpin = NULL; + Index = 0; + + // + // Compute size for easy access later + // + FvInfoPtr->Size = 0; + for (Index = 0; FvInfoPtr->FvBlocks[Index].NumBlocks > 0 && FvInfoPtr->FvBlocks[Index].Length > 0; Index++) { + FvInfoPtr->Size += FvInfoPtr->FvBlocks[Index].NumBlocks * FvInfoPtr->FvBlocks[Index].Length; + } + + // + // Calculate the required sizes for all FFS files. + // + CurrentOffset = sizeof (EFI_FIRMWARE_VOLUME_HEADER); + + for (Index = 1;; Index ++) { + CurrentOffset += sizeof (EFI_FV_BLOCK_MAP_ENTRY); + if (FvInfoPtr->FvBlocks[Index].NumBlocks == 0 || FvInfoPtr->FvBlocks[Index].Length == 0) { + break; + } + } + + // + // Calculate PI extension header + // + if (mFvDataInfo.FvExtHeaderFile[0] != '\0') { + fpin = fopen (LongFilePath (mFvDataInfo.FvExtHeaderFile), "rb"); + if (fpin == NULL) { + Error (NULL, 0, 0001, "Error opening file", mFvDataInfo.FvExtHeaderFile); + return EFI_ABORTED; + } + FvExtendHeaderSize = _filelength (fileno (fpin)); + fclose (fpin); + if (sizeof (EFI_FFS_FILE_HEADER) + FvExtendHeaderSize >= MAX_FFS_SIZE) { + CurrentOffset += sizeof (EFI_FFS_FILE_HEADER2) + FvExtendHeaderSize; + mIsLargeFfs = TRUE; + } else { + CurrentOffset += sizeof (EFI_FFS_FILE_HEADER) + FvExtendHeaderSize; + } + CurrentOffset = (CurrentOffset + 7) & (~7); + } else if (mFvDataInfo.FvNameGuidSet) { + CurrentOffset += sizeof (EFI_FFS_FILE_HEADER) + sizeof (EFI_FIRMWARE_VOLUME_EXT_HEADER); + CurrentOffset = (CurrentOffset + 7) & (~7); + } + + // + // Accumulate every FFS file size. + // + for (Index = 0; FvInfoPtr->FvFiles[Index][0] != 0; Index++) { + // + // Open FFS file + // + fpin = NULL; + fpin = fopen (LongFilePath (FvInfoPtr->FvFiles[Index]), "rb"); + if (fpin == NULL) { + Error (NULL, 0, 0001, "Error opening file", FvInfoPtr->FvFiles[Index]); + return EFI_ABORTED; + } + // + // Get the file size + // + FfsFileSize = _filelength (fileno (fpin)); + if (FfsFileSize >= MAX_FFS_SIZE) { + FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER2); + mIsLargeFfs = TRUE; + } else { + FfsHeaderSize = sizeof(EFI_FFS_FILE_HEADER); + } + // + // Read Ffs File header + // + fread (&FfsHeader, sizeof (UINT8), sizeof (EFI_FFS_FILE_HEADER), fpin); + // + // close file + // + fclose (fpin); + + if (FvInfoPtr->IsPiFvImage) { + // + // Check whether this ffs file is vtf file + // + if (IsVtfFile (&FfsHeader)) { + if (VtfFileFlag) { + // + // One Fv image can't have two vtf files. + // + Error (NULL, 0, 3000,"Invalid", "One Fv image can't have two vtf files."); + return EFI_ABORTED; + } + VtfFileFlag = TRUE; + VtfFileSize = FfsFileSize; + continue; + } + + // + // Get the alignment of FFS file + // + ReadFfsAlignment (&FfsHeader, &FfsAlignment); + FfsAlignment = 1 << FfsAlignment; + // + // Add Pad file + // + if (((CurrentOffset + FfsHeaderSize) % FfsAlignment) != 0) { + // + // Only EFI_FFS_FILE_HEADER is needed for a pad section. + // + OrigOffset = CurrentOffset; + CurrentOffset = (CurrentOffset + FfsHeaderSize + sizeof(EFI_FFS_FILE_HEADER) + FfsAlignment - 1) & ~(FfsAlignment - 1); + CurrentOffset -= FfsHeaderSize; + if ((CurrentOffset - OrigOffset) > MaxPadFileSize) { + MaxPadFileSize = CurrentOffset - OrigOffset; + } + } + } + + // + // Add ffs file size + // + if (FvInfoPtr->SizeofFvFiles[Index] > FfsFileSize) { + CurrentOffset += FvInfoPtr->SizeofFvFiles[Index]; + } else { + CurrentOffset += FfsFileSize; + } + + // + // Make next ffs file start at QWord Boundary + // + if (FvInfoPtr->IsPiFvImage) { + CurrentOffset = (CurrentOffset + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1); + } + } + CurrentOffset += VtfFileSize; + DebugMsg (NULL, 0, 9, "FvImage size", "The calculated fv image size is 0x%x and the current set fv image size is 0x%x", (unsigned) CurrentOffset, (unsigned) FvInfoPtr->Size); + + if (FvInfoPtr->Size == 0) { + // + // Update FvInfo data + // + FvInfoPtr->FvBlocks[0].NumBlocks = CurrentOffset / FvInfoPtr->FvBlocks[0].Length + ((CurrentOffset % FvInfoPtr->FvBlocks[0].Length)?1:0); + FvInfoPtr->Size = FvInfoPtr->FvBlocks[0].NumBlocks * FvInfoPtr->FvBlocks[0].Length; + FvInfoPtr->FvBlocks[1].NumBlocks = 0; + FvInfoPtr->FvBlocks[1].Length = 0; + } else if (FvInfoPtr->Size < CurrentOffset) { + // + // Not invalid + // + Error (NULL, 0, 3000, "Invalid", "the required fv image size 0x%x exceeds the set fv image size 0x%x", (unsigned) CurrentOffset, (unsigned) FvInfoPtr->Size); + return EFI_INVALID_PARAMETER; + } + + // + // Set Fv Size Information + // + mFvTotalSize = FvInfoPtr->Size; + mFvTakenSize = CurrentOffset; + if ((mFvTakenSize == mFvTotalSize) && (MaxPadFileSize > 0)) { + // + // This FV means TOP FFS has been taken. Then, check whether there is padding data for use. + // + mFvTakenSize = mFvTakenSize - MaxPadFileSize; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +FfsRebaseImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINT32 *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + + FileHandle - The handle to the PE/COFF file + + FileOffset - The offset, in bytes, into the file to read + + ReadSize - The number of bytes to read from the file starting at FileOffset + + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + UINT32 Length; + + Destination8 = Buffer; + Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); + Length = *ReadSize; + while (Length--) { + *(Destination8++) = *(Source8++); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GetChildFvFromFfs ( + IN FV_INFO *FvInfo, + IN EFI_FFS_FILE_HEADER *FfsFile, + IN UINTN XipOffset + ) +/*++ + +Routine Description: + + This function gets all child FvImages in the input FfsFile, and records + their base address to the parent image. + +Arguments: + FvInfo A pointer to FV_INFO structure. + FfsFile A pointer to Ffs file image that may contain FvImage. + XipOffset The offset address to the parent FvImage base. + +Returns: + + EFI_SUCCESS Base address of child Fv image is recorded. +--*/ +{ + EFI_STATUS Status; + UINTN Index; + EFI_FILE_SECTION_POINTER SubFvSection; + EFI_FIRMWARE_VOLUME_HEADER *SubFvImageHeader; + EFI_PHYSICAL_ADDRESS SubFvBaseAddress; + EFI_FILE_SECTION_POINTER CorePe32; + UINT16 MachineType; + + for (Index = 1;; Index++) { + // + // Find FV section + // + Status = GetSectionByType (FfsFile, EFI_SECTION_FIRMWARE_VOLUME_IMAGE, Index, &SubFvSection); + if (EFI_ERROR (Status)) { + break; + } + SubFvImageHeader = (EFI_FIRMWARE_VOLUME_HEADER *) ((UINT8 *) SubFvSection.FVImageSection + GetSectionHeaderLength(SubFvSection.FVImageSection)); + + // + // See if there's an SEC core in the child FV + Status = FindCorePeSection(SubFvImageHeader, SubFvImageHeader->FvLength, EFI_FV_FILETYPE_SECURITY_CORE, &CorePe32); + + // if we couldn't find the SEC core, look for a PEI core + if (EFI_ERROR(Status)) { + Status = FindCorePeSection(SubFvImageHeader, SubFvImageHeader->FvLength, EFI_FV_FILETYPE_PEI_CORE, &CorePe32); + } + + if (!EFI_ERROR(Status)) { + Status = GetCoreMachineType(CorePe32, &MachineType); + if (EFI_ERROR(Status)) { + Error(NULL, 0, 3000, "Invalid", "Could not get the PE32 machine type for SEC/PEI Core."); + return EFI_ABORTED; + } + + // machine type is ARM, set a flag so ARM reset vector processing occurs + if ((MachineType == EFI_IMAGE_MACHINE_ARMT) || (MachineType == EFI_IMAGE_MACHINE_AARCH64)) { + VerboseMsg("Located ARM/AArch64 SEC/PEI core in child FV"); + mArm = TRUE; + } + } + + // + // Rebase on Flash + // + SubFvBaseAddress = FvInfo->BaseAddress + (UINTN) SubFvImageHeader - (UINTN) FfsFile + XipOffset; + mFvBaseAddress[mFvBaseAddressNumber ++ ] = SubFvBaseAddress; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +FfsRebase ( + IN OUT FV_INFO *FvInfo, + IN CHAR8 *FileName, + IN OUT EFI_FFS_FILE_HEADER *FfsFile, + IN UINTN XipOffset, + IN FILE *FvMapFile + ) +/*++ + +Routine Description: + + This function determines if a file is XIP and should be rebased. It will + rebase any PE32 sections found in the file using the base address. + +Arguments: + + FvInfo A pointer to FV_INFO structure. + FileName Ffs File PathName + FfsFile A pointer to Ffs file image. + XipOffset The offset address to use for rebasing the XIP file image. + FvMapFile FvMapFile to record the function address in one Fvimage + +Returns: + + EFI_SUCCESS The image was properly rebased. + EFI_INVALID_PARAMETER An input parameter is invalid. + EFI_ABORTED An error occurred while rebasing the input file image. + EFI_OUT_OF_RESOURCES Could not allocate a required resource. + EFI_NOT_FOUND No compressed sections could be found. + +--*/ +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + PE_COFF_LOADER_IMAGE_CONTEXT OrigImageContext; + EFI_PHYSICAL_ADDRESS XipBase; + EFI_PHYSICAL_ADDRESS NewPe32BaseAddress; + UINTN Index; + EFI_FILE_SECTION_POINTER CurrentPe32Section; + EFI_FFS_FILE_STATE SavedState; + EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; + EFI_TE_IMAGE_HEADER *TEImageHeader; + UINT8 *MemoryImagePointer; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + CHAR8 PeFileName [MAX_LONG_FILE_PATH]; + CHAR8 *Cptr; + FILE *PeFile; + UINT8 *PeFileBuffer; + UINT32 PeFileSize; + CHAR8 *PdbPointer; + UINT32 FfsHeaderSize; + UINT32 CurSecHdrSize; + + Index = 0; + MemoryImagePointer = NULL; + TEImageHeader = NULL; + ImgHdr = NULL; + SectionHeader = NULL; + Cptr = NULL; + PeFile = NULL; + PeFileBuffer = NULL; + + // + // Don't need to relocate image when BaseAddress is zero and no ForceRebase Flag specified. + // + if ((FvInfo->BaseAddress == 0) && (FvInfo->ForceRebase == -1)) { + return EFI_SUCCESS; + } + + // + // If ForceRebase Flag specified to FALSE, will always not take rebase action. + // + if (FvInfo->ForceRebase == 0) { + return EFI_SUCCESS; + } + + + XipBase = FvInfo->BaseAddress + XipOffset; + + // + // We only process files potentially containing PE32 sections. + // + switch (FfsFile->Type) { + case EFI_FV_FILETYPE_SECURITY_CORE: + case EFI_FV_FILETYPE_PEI_CORE: + case EFI_FV_FILETYPE_PEIM: + case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: + case EFI_FV_FILETYPE_DRIVER: + case EFI_FV_FILETYPE_DXE_CORE: + break; + case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: + // + // Rebase the inside FvImage. + // + GetChildFvFromFfs (FvInfo, FfsFile, XipOffset); + + // + // Search PE/TE section in FV sectin. + // + break; + default: + return EFI_SUCCESS; + } + + FfsHeaderSize = GetFfsHeaderLength(FfsFile); + // + // Rebase each PE32 section + // + Status = EFI_SUCCESS; + for (Index = 1;; Index++) { + // + // Init Value + // + NewPe32BaseAddress = 0; + + // + // Find Pe Image + // + Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section); + if (EFI_ERROR (Status)) { + break; + } + CurSecHdrSize = GetSectionHeaderLength(CurrentPe32Section.CommonHeader); + + // + // Initialize context + // + memset (&ImageContext, 0, sizeof (ImageContext)); + ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize); + ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead; + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and the return status is %x", FileName, (int) Status); + return Status; + } + + if ( (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) || + (ImageContext.Machine == EFI_IMAGE_MACHINE_AARCH64) ) { + mArm = TRUE; + } + + if (ImageContext.Machine == EFI_IMAGE_MACHINE_RISCV64) { + mRiscV = TRUE; + } + + // + // Keep Image Context for PE image in FV + // + memcpy (&OrigImageContext, &ImageContext, sizeof (ImageContext)); + + // + // Get File PdbPointer + // + PdbPointer = PeCoffLoaderGetPdbPointer (ImageContext.Handle); + + // + // Get PeHeader pointer + // + ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize + ImageContext.PeCoffHeaderOffset); + + // + // Calculate the PE32 base address, based on file type + // + switch (FfsFile->Type) { + case EFI_FV_FILETYPE_SECURITY_CORE: + case EFI_FV_FILETYPE_PEI_CORE: + case EFI_FV_FILETYPE_PEIM: + case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: + // + // Check if section-alignment and file-alignment match or not + // + if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) { + // + // Xip module has the same section alignment and file alignment. + // + Error (NULL, 0, 3000, "Invalid", "PE image Section-Alignment and File-Alignment do not match : %s.", FileName); + return EFI_ABORTED; + } + // + // PeImage has no reloc section. It will try to get reloc data from the original EFI image. + // + if (ImageContext.RelocationsStripped) { + // + // Construct the original efi file Name + // + if (strlen (FileName) >= MAX_LONG_FILE_PATH) { + Error (NULL, 0, 2000, "Invalid", "The file name %s is too long.", FileName); + return EFI_ABORTED; + } + strncpy (PeFileName, FileName, MAX_LONG_FILE_PATH - 1); + PeFileName[MAX_LONG_FILE_PATH - 1] = 0; + Cptr = PeFileName + strlen (PeFileName); + while (*Cptr != '.') { + Cptr --; + } + if (*Cptr != '.') { + Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName); + return EFI_ABORTED; + } else { + *(Cptr + 1) = 'e'; + *(Cptr + 2) = 'f'; + *(Cptr + 3) = 'i'; + *(Cptr + 4) = '\0'; + } + PeFile = fopen (LongFilePath (PeFileName), "rb"); + if (PeFile == NULL) { + Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName); + //Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName); + //return EFI_ABORTED; + break; + } + // + // Get the file size + // + PeFileSize = _filelength (fileno (PeFile)); + PeFileBuffer = (UINT8 *) malloc (PeFileSize); + if (PeFileBuffer == NULL) { + fclose (PeFile); + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName); + return EFI_OUT_OF_RESOURCES; + } + // + // Read Pe File + // + fread (PeFileBuffer, sizeof (UINT8), PeFileSize, PeFile); + // + // close file + // + fclose (PeFile); + // + // Handle pointer to the original efi image. + // + ImageContext.Handle = PeFileBuffer; + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and the return status is %x", FileName, (int) Status); + return Status; + } + ImageContext.RelocationsStripped = FALSE; + } + + NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize - (UINTN)FfsFile; + break; + + case EFI_FV_FILETYPE_DRIVER: + case EFI_FV_FILETYPE_DXE_CORE: + // + // Check if section-alignment and file-alignment match or not + // + if ((ImgHdr->Pe32.OptionalHeader.SectionAlignment != ImgHdr->Pe32.OptionalHeader.FileAlignment)) { + // + // Xip module has the same section alignment and file alignment. + // + Error (NULL, 0, 3000, "Invalid", "PE image Section-Alignment and File-Alignment do not match : %s.", FileName); + return EFI_ABORTED; + } + NewPe32BaseAddress = XipBase + (UINTN) CurrentPe32Section.Pe32Section + CurSecHdrSize - (UINTN)FfsFile; + break; + + default: + // + // Not supported file type + // + return EFI_SUCCESS; + } + + // + // Relocation doesn't exist + // + if (ImageContext.RelocationsStripped) { + Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName); + continue; + } + + // + // Relocation exist and rebase + // + // + // Load and Relocate Image Data + // + MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment); + if (MemoryImagePointer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName); + return EFI_OUT_OF_RESOURCES; + } + memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment); + ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((UINTN) ImageContext.SectionAlignment - 1)); + + Status = PeCoffLoaderLoadImage (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName); + free ((VOID *) MemoryImagePointer); + return Status; + } + + ImageContext.DestinationAddress = NewPe32BaseAddress; + Status = PeCoffLoaderRelocateImage (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s Status=%d", FileName, Status); + free ((VOID *) MemoryImagePointer); + return Status; + } + + // + // Copy Relocated data to raw image file. + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN) ImgHdr + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader + ); + + for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + CopyMem ( + (UINT8 *) CurrentPe32Section.Pe32Section + CurSecHdrSize + SectionHeader->PointerToRawData, + (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress), + SectionHeader->SizeOfRawData + ); + } + + free ((VOID *) MemoryImagePointer); + MemoryImagePointer = NULL; + if (PeFileBuffer != NULL) { + free (PeFileBuffer); + PeFileBuffer = NULL; + } + + // + // Update Image Base Address + // + if (ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress; + } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress; + } else { + Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s", + ImgHdr->Pe32.OptionalHeader.Magic, + FileName + ); + return EFI_ABORTED; + } + + // + // Now update file checksum + // + if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) { + SavedState = FfsFile->State; + FfsFile->IntegrityCheck.Checksum.File = 0; + FfsFile->State = 0; + FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ( + (UINT8 *) ((UINT8 *)FfsFile + FfsHeaderSize), + GetFfsFileLength (FfsFile) - FfsHeaderSize + ); + FfsFile->State = SavedState; + } + + // + // Get this module function address from ModulePeMapFile and add them into FvMap file + // + + // + // Default use FileName as map file path + // + if (PdbPointer == NULL) { + PdbPointer = FileName; + } + + WriteMapFile (FvMapFile, PdbPointer, FfsFile, NewPe32BaseAddress, &OrigImageContext); + } + + if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE && + FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE && + FfsFile->Type != EFI_FV_FILETYPE_PEIM && + FfsFile->Type != EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER && + FfsFile->Type != EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE + ) { + // + // Only Peim code may have a TE section + // + return EFI_SUCCESS; + } + + // + // Now process TE sections + // + for (Index = 1;; Index++) { + NewPe32BaseAddress = 0; + + // + // Find Te Image + // + Status = GetSectionByType (FfsFile, EFI_SECTION_TE, Index, &CurrentPe32Section); + if (EFI_ERROR (Status)) { + break; + } + + CurSecHdrSize = GetSectionHeaderLength(CurrentPe32Section.CommonHeader); + + // + // Calculate the TE base address, the FFS file base plus the offset of the TE section less the size stripped off + // by GenTEImage + // + TEImageHeader = (EFI_TE_IMAGE_HEADER *) ((UINT8 *) CurrentPe32Section.Pe32Section + CurSecHdrSize); + + // + // Initialize context, load image info. + // + memset (&ImageContext, 0, sizeof (ImageContext)); + ImageContext.Handle = (VOID *) TEImageHeader; + ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead; + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid TeImage", "The input file is %s and the return status is %x", FileName, (int) Status); + return Status; + } + + if ( (ImageContext.Machine == EFI_IMAGE_MACHINE_ARMT) || + (ImageContext.Machine == EFI_IMAGE_MACHINE_AARCH64) ) { + mArm = TRUE; + } + + // + // Keep Image Context for TE image in FV + // + memcpy (&OrigImageContext, &ImageContext, sizeof (ImageContext)); + + // + // Get File PdbPointer + // + PdbPointer = PeCoffLoaderGetPdbPointer (ImageContext.Handle); + + // + // Set new rebased address. + // + NewPe32BaseAddress = XipBase + (UINTN) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) \ + - TEImageHeader->StrippedSize - (UINTN) FfsFile; + + // + // if reloc is stripped, try to get the original efi image to get reloc info. + // + if (ImageContext.RelocationsStripped) { + // + // Construct the original efi file name + // + if (strlen (FileName) >= MAX_LONG_FILE_PATH) { + Error (NULL, 0, 2000, "Invalid", "The file name %s is too long.", FileName); + return EFI_ABORTED; + } + strncpy (PeFileName, FileName, MAX_LONG_FILE_PATH - 1); + PeFileName[MAX_LONG_FILE_PATH - 1] = 0; + Cptr = PeFileName + strlen (PeFileName); + while (*Cptr != '.') { + Cptr --; + } + + if (*Cptr != '.') { + Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName); + return EFI_ABORTED; + } else { + *(Cptr + 1) = 'e'; + *(Cptr + 2) = 'f'; + *(Cptr + 3) = 'i'; + *(Cptr + 4) = '\0'; + } + + PeFile = fopen (LongFilePath (PeFileName), "rb"); + if (PeFile == NULL) { + Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName); + //Error (NULL, 0, 3000, "Invalid", "The file %s has no .reloc section.", FileName); + //return EFI_ABORTED; + } else { + // + // Get the file size + // + PeFileSize = _filelength (fileno (PeFile)); + PeFileBuffer = (UINT8 *) malloc (PeFileSize); + if (PeFileBuffer == NULL) { + fclose (PeFile); + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName); + return EFI_OUT_OF_RESOURCES; + } + // + // Read Pe File + // + fread (PeFileBuffer, sizeof (UINT8), PeFileSize, PeFile); + // + // close file + // + fclose (PeFile); + // + // Append reloc section into TeImage + // + ImageContext.Handle = PeFileBuffer; + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid TeImage", "The input file is %s and the return status is %x", FileName, (int) Status); + return Status; + } + ImageContext.RelocationsStripped = FALSE; + } + } + // + // Relocation doesn't exist + // + if (ImageContext.RelocationsStripped) { + Warning (NULL, 0, 0, "Invalid", "The file %s has no .reloc section.", FileName); + continue; + } + + // + // Relocation exist and rebase + // + // + // Load and Relocate Image Data + // + MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment); + if (MemoryImagePointer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName); + return EFI_OUT_OF_RESOURCES; + } + memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment); + ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((UINTN) ImageContext.SectionAlignment - 1)); + + Status = PeCoffLoaderLoadImage (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName); + free ((VOID *) MemoryImagePointer); + return Status; + } + // + // Reloacate TeImage + // + ImageContext.DestinationAddress = NewPe32BaseAddress; + Status = PeCoffLoaderRelocateImage (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of TE image %s", FileName); + free ((VOID *) MemoryImagePointer); + return Status; + } + + // + // Copy the relocated image into raw image file. + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TEImageHeader + 1); + for (Index = 0; Index < TEImageHeader->NumberOfSections; Index ++, SectionHeader ++) { + if (!ImageContext.IsTeImage) { + CopyMem ( + (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData, + (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress), + SectionHeader->SizeOfRawData + ); + } else { + CopyMem ( + (UINT8 *) TEImageHeader + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->PointerToRawData, + (VOID*) (UINTN) (ImageContext.ImageAddress + sizeof (EFI_TE_IMAGE_HEADER) - TEImageHeader->StrippedSize + SectionHeader->VirtualAddress), + SectionHeader->SizeOfRawData + ); + } + } + + // + // Free the allocated memory resource + // + free ((VOID *) MemoryImagePointer); + MemoryImagePointer = NULL; + if (PeFileBuffer != NULL) { + free (PeFileBuffer); + PeFileBuffer = NULL; + } + + // + // Update Image Base Address + // + TEImageHeader->ImageBase = NewPe32BaseAddress; + + // + // Now update file checksum + // + if (FfsFile->Attributes & FFS_ATTRIB_CHECKSUM) { + SavedState = FfsFile->State; + FfsFile->IntegrityCheck.Checksum.File = 0; + FfsFile->State = 0; + FfsFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ( + (UINT8 *)((UINT8 *)FfsFile + FfsHeaderSize), + GetFfsFileLength (FfsFile) - FfsHeaderSize + ); + FfsFile->State = SavedState; + } + // + // Get this module function address from ModulePeMapFile and add them into FvMap file + // + + // + // Default use FileName as map file path + // + if (PdbPointer == NULL) { + PdbPointer = FileName; + } + + WriteMapFile ( + FvMapFile, + PdbPointer, + FfsFile, + NewPe32BaseAddress, + &OrigImageContext + ); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +FindApResetVectorPosition ( + IN MEMORY_FILE *FvImage, + OUT UINT8 **Pointer + ) +/*++ + +Routine Description: + + Find the position in this FvImage to place Ap reset vector. + +Arguments: + + FvImage Memory file for the FV memory image. + Pointer Pointer to pointer to position. + +Returns: + + EFI_NOT_FOUND - No satisfied position is found. + EFI_SUCCESS - The suitable position is return. + +--*/ +{ + EFI_FFS_FILE_HEADER *PadFile; + UINT32 Index; + EFI_STATUS Status; + UINT8 *FixPoint; + UINT32 FileLength; + + for (Index = 1; ;Index ++) { + // + // Find Pad File to add ApResetVector info + // + Status = GetFileByType (EFI_FV_FILETYPE_FFS_PAD, Index, &PadFile); + if (EFI_ERROR (Status) || (PadFile == NULL)) { + // + // No Pad file to be found. + // + break; + } + // + // Get Pad file size. + // + FileLength = GetFfsFileLength(PadFile); + FileLength = (FileLength + EFI_FFS_FILE_HEADER_ALIGNMENT - 1) & ~(EFI_FFS_FILE_HEADER_ALIGNMENT - 1); + // + // FixPoint must be align on 0x1000 relative to FvImage Header + // + FixPoint = (UINT8*) PadFile + GetFfsHeaderLength(PadFile); + FixPoint = FixPoint + 0x1000 - (((UINTN) FixPoint - (UINTN) FvImage->FileImage) & 0xFFF); + // + // FixPoint be larger at the last place of one fv image. + // + while (((UINTN) FixPoint + SIZEOF_STARTUP_DATA_ARRAY - (UINTN) PadFile) <= FileLength) { + FixPoint += 0x1000; + } + FixPoint -= 0x1000; + + if ((UINTN) FixPoint < ((UINTN) PadFile + GetFfsHeaderLength(PadFile))) { + // + // No alignment FixPoint in this Pad File. + // + continue; + } + + if ((UINTN) FvImage->Eof - (UINTN)FixPoint <= 0x20000) { + // + // Find the position to place ApResetVector + // + *Pointer = FixPoint; + return EFI_SUCCESS; + } + } + + return EFI_NOT_FOUND; +} + +EFI_STATUS +ParseCapInf ( + IN MEMORY_FILE *InfFile, + OUT CAP_INFO *CapInfo + ) +/*++ + +Routine Description: + + This function parses a Cap.INF file and copies info into a CAP_INFO structure. + +Arguments: + + InfFile Memory file image. + CapInfo Information read from INF file. + +Returns: + + EFI_SUCCESS INF file information successfully retrieved. + EFI_ABORTED INF file has an invalid format. + EFI_NOT_FOUND A required string was not found in the INF file. +--*/ +{ + CHAR8 Value[MAX_LONG_FILE_PATH]; + UINT64 Value64; + UINTN Index, Number; + EFI_STATUS Status; + + // + // Initialize Cap info + // + // memset (CapInfo, 0, sizeof (CAP_INFO)); + // + + // + // Read the Capsule Guid + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_CAPSULE_GUID_STRING, 0, Value); + if (Status == EFI_SUCCESS) { + // + // Get the Capsule Guid + // + Status = StringToGuid (Value, &CapInfo->CapGuid); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_CAPSULE_GUID_STRING, Value); + return EFI_ABORTED; + } + DebugMsg (NULL, 0, 9, "Capsule Guid", "%s = %s", EFI_CAPSULE_GUID_STRING, Value); + } + + // + // Read the Capsule Header Size + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_CAPSULE_HEADER_SIZE_STRING, 0, Value); + if (Status == EFI_SUCCESS) { + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 2000, "Invalid parameter", "%s = %s", EFI_CAPSULE_HEADER_SIZE_STRING, Value); + return EFI_ABORTED; + } + CapInfo->HeaderSize = (UINT32) Value64; + DebugMsg (NULL, 0, 9, "Capsule Header size", "%s = %s", EFI_CAPSULE_HEADER_SIZE_STRING, Value); + } + + // + // Read the Capsule Flag + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_CAPSULE_FLAGS_STRING, 0, Value); + if (Status == EFI_SUCCESS) { + if (strstr (Value, "PopulateSystemTable") != NULL) { + CapInfo->Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET | CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE; + if (strstr (Value, "InitiateReset") != NULL) { + CapInfo->Flags |= CAPSULE_FLAGS_INITIATE_RESET; + } + } else if (strstr (Value, "PersistAcrossReset") != NULL) { + CapInfo->Flags |= CAPSULE_FLAGS_PERSIST_ACROSS_RESET; + if (strstr (Value, "InitiateReset") != NULL) { + CapInfo->Flags |= CAPSULE_FLAGS_INITIATE_RESET; + } + } else { + Error (NULL, 0, 2000, "Invalid parameter", "invalid Flag setting for %s.", EFI_CAPSULE_FLAGS_STRING); + return EFI_ABORTED; + } + DebugMsg (NULL, 0, 9, "Capsule Flag", Value); + } + + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_OEM_CAPSULE_FLAGS_STRING, 0, Value); + if (Status == EFI_SUCCESS) { + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status) || Value64 > 0xffff) { + Error (NULL, 0, 2000, "Invalid parameter", + "invalid Flag setting for %s. Must be integer value between 0x0000 and 0xffff.", + EFI_OEM_CAPSULE_FLAGS_STRING); + return EFI_ABORTED; + } + CapInfo->Flags |= Value64; + DebugMsg (NULL, 0, 9, "Capsule Extend Flag", Value); + } + + // + // Read Capsule File name + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FILE_NAME_STRING, 0, Value); + if (Status == EFI_SUCCESS) { + // + // Get output file name + // + strcpy (CapInfo->CapName, Value); + } + + // + // Read the Capsule FileImage + // + Number = 0; + for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_CAP; Index++) { + if (CapInfo->CapFiles[Index][0] != '\0') { + continue; + } + // + // Read the capsule file name + // + Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Number++, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the file + // + strcpy (CapInfo->CapFiles[Index], Value); + DebugMsg (NULL, 0, 9, "Capsule component file", "the %uth file name is %s", (unsigned) Index, CapInfo->CapFiles[Index]); + } else { + break; + } + } + + if (Index == 0) { + Warning (NULL, 0, 0, "Capsule components are not specified.", NULL); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +GenerateCapImage ( + IN CHAR8 *InfFileImage, + IN UINTN InfFileSize, + IN CHAR8 *CapFileName + ) +/*++ + +Routine Description: + + This is the main function which will be called from application to create UEFI Capsule image. + +Arguments: + + InfFileImage Buffer containing the INF file contents. + InfFileSize Size of the contents of the InfFileImage buffer. + CapFileName Requested name for the Cap file. + +Returns: + + EFI_SUCCESS Function completed successfully. + EFI_OUT_OF_RESOURCES Could not allocate required resources. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + +--*/ +{ + UINT32 CapSize; + UINT8 *CapBuffer; + EFI_CAPSULE_HEADER *CapsuleHeader; + MEMORY_FILE InfMemoryFile; + UINT32 FileSize; + UINT32 Index; + FILE *fpin, *fpout; + EFI_STATUS Status; + + if (InfFileImage != NULL) { + // + // Initialize file structures + // + InfMemoryFile.FileImage = InfFileImage; + InfMemoryFile.CurrentFilePointer = InfFileImage; + InfMemoryFile.Eof = InfFileImage + InfFileSize; + + // + // Parse the Cap inf file for header information + // + Status = ParseCapInf (&InfMemoryFile, &mCapDataInfo); + if (Status != EFI_SUCCESS) { + return Status; + } + } + + if (mCapDataInfo.HeaderSize == 0) { + // + // make header size align 16 bytes. + // + mCapDataInfo.HeaderSize = sizeof (EFI_CAPSULE_HEADER); + mCapDataInfo.HeaderSize = (mCapDataInfo.HeaderSize + 0xF) & ~0xF; + } + + if (mCapDataInfo.HeaderSize < sizeof (EFI_CAPSULE_HEADER)) { + Error (NULL, 0, 2000, "Invalid parameter", "The specified HeaderSize cannot be less than the size of EFI_CAPSULE_HEADER."); + return EFI_INVALID_PARAMETER; + } + + if (CapFileName == NULL && mCapDataInfo.CapName[0] != '\0') { + CapFileName = mCapDataInfo.CapName; + } + + if (CapFileName == NULL) { + Error (NULL, 0, 2001, "Missing required argument", "Output Capsule file name"); + return EFI_INVALID_PARAMETER; + } + + // + // Set Default Capsule Guid value + // + if (CompareGuid (&mCapDataInfo.CapGuid, &mZeroGuid) == 0) { + memcpy (&mCapDataInfo.CapGuid, &mDefaultCapsuleGuid, sizeof (EFI_GUID)); + } + // + // Calculate the size of capsule image. + // + Index = 0; + FileSize = 0; + CapSize = mCapDataInfo.HeaderSize; + while (mCapDataInfo.CapFiles [Index][0] != '\0') { + fpin = fopen (LongFilePath (mCapDataInfo.CapFiles[Index]), "rb"); + if (fpin == NULL) { + Error (NULL, 0, 0001, "Error opening file", mCapDataInfo.CapFiles[Index]); + return EFI_ABORTED; + } + FileSize = _filelength (fileno (fpin)); + CapSize += FileSize; + fclose (fpin); + Index ++; + } + + // + // Allocate buffer for capsule image. + // + CapBuffer = (UINT8 *) malloc (CapSize); + if (CapBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated for creating the capsule."); + return EFI_OUT_OF_RESOURCES; + } + + // + // Initialize the capsule header to zero + // + memset (CapBuffer, 0, mCapDataInfo.HeaderSize); + + // + // create capsule header and get capsule body + // + CapsuleHeader = (EFI_CAPSULE_HEADER *) CapBuffer; + memcpy (&CapsuleHeader->CapsuleGuid, &mCapDataInfo.CapGuid, sizeof (EFI_GUID)); + CapsuleHeader->HeaderSize = mCapDataInfo.HeaderSize; + CapsuleHeader->Flags = mCapDataInfo.Flags; + CapsuleHeader->CapsuleImageSize = CapSize; + + Index = 0; + FileSize = 0; + CapSize = CapsuleHeader->HeaderSize; + while (mCapDataInfo.CapFiles [Index][0] != '\0') { + fpin = fopen (LongFilePath (mCapDataInfo.CapFiles[Index]), "rb"); + if (fpin == NULL) { + Error (NULL, 0, 0001, "Error opening file", mCapDataInfo.CapFiles[Index]); + free (CapBuffer); + return EFI_ABORTED; + } + FileSize = _filelength (fileno (fpin)); + fread (CapBuffer + CapSize, 1, FileSize, fpin); + fclose (fpin); + Index ++; + CapSize += FileSize; + } + + // + // write capsule data into the output file + // + fpout = fopen (LongFilePath (CapFileName), "wb"); + if (fpout == NULL) { + Error (NULL, 0, 0001, "Error opening file", CapFileName); + free (CapBuffer); + return EFI_ABORTED; + } + + fwrite (CapBuffer, 1, CapSize, fpout); + fclose (fpout); + free (CapBuffer); + + VerboseMsg ("The size of the generated capsule image is %u bytes", (unsigned) CapSize); + + return EFI_SUCCESS; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GenFvInternalLib.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GenFvInternalLib.h new file mode 100644 index 00000000..acbebef5 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/GenFvInternalLib.h @@ -0,0 +1,402 @@ +/** @file +This file contains describes the public interfaces to the GenFvImage Library. +The basic purpose of the library is to create Firmware Volume images. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_GEN_FV_INTERNAL_LIB_H +#define _EFI_GEN_FV_INTERNAL_LIB_H + +// +// Include files +// +#include + +#include +#include + +#include +#include +#include +#include + +#include "CommonLib.h" +#include "ParseInf.h" +#include "EfiUtilityMsgs.h" + +// +// Different file separator for Linux and Windows +// +#define FILE_SEP_CHAR '/' + +// +// The maximum number of Pad file guid entries. +// +#define MAX_NUMBER_OF_PAD_FILE_GUIDS 1024 + +// +// The maximum number of block map entries supported by the library +// +#define MAX_NUMBER_OF_FV_BLOCKS 100 + +// +// The maximum number of files in the FV supported by the library +// +#define MAX_NUMBER_OF_FILES_IN_FV 1000 +#define MAX_NUMBER_OF_FILES_IN_CAP 1000 +#define EFI_FFS_FILE_HEADER_ALIGNMENT 8 +// +// INF file strings +// +#define OPTIONS_SECTION_STRING "[options]" +#define ATTRIBUTES_SECTION_STRING "[attributes]" +#define FILES_SECTION_STRING "[files]" +#define FV_BASE_ADDRESS_STRING "[FV_BASE_ADDRESS]" + +// +// Options section +// +#define EFI_FV_BASE_ADDRESS_STRING "EFI_BASE_ADDRESS" +#define EFI_FV_FILE_NAME_STRING "EFI_FILE_NAME" +#define EFI_NUM_BLOCKS_STRING "EFI_NUM_BLOCKS" +#define EFI_BLOCK_SIZE_STRING "EFI_BLOCK_SIZE" +#define EFI_GUID_STRING "EFI_GUID" +#define EFI_FV_FILESYSTEMGUID_STRING "EFI_FV_GUID" +#define EFI_FV_NAMEGUID_STRING "EFI_FVNAME_GUID" +#define EFI_CAPSULE_GUID_STRING "EFI_CAPSULE_GUID" +#define EFI_CAPSULE_HEADER_SIZE_STRING "EFI_CAPSULE_HEADER_SIZE" +#define EFI_CAPSULE_FLAGS_STRING "EFI_CAPSULE_FLAGS" +#define EFI_OEM_CAPSULE_FLAGS_STRING "EFI_OEM_CAPSULE_FLAGS" +#define EFI_CAPSULE_VERSION_STRING "EFI_CAPSULE_VERSION" + +#define EFI_FV_TOTAL_SIZE_STRING "EFI_FV_TOTAL_SIZE" +#define EFI_FV_TAKEN_SIZE_STRING "EFI_FV_TAKEN_SIZE" +#define EFI_FV_SPACE_SIZE_STRING "EFI_FV_SPACE_SIZE" + +// +// Attributes section +// +#define EFI_FVB2_READ_DISABLED_CAP_STRING "EFI_READ_DISABLED_CAP" +#define EFI_FVB2_READ_ENABLED_CAP_STRING "EFI_READ_ENABLED_CAP" +#define EFI_FVB2_READ_STATUS_STRING "EFI_READ_STATUS" + +#define EFI_FVB2_WRITE_DISABLED_CAP_STRING "EFI_WRITE_DISABLED_CAP" +#define EFI_FVB2_WRITE_ENABLED_CAP_STRING "EFI_WRITE_ENABLED_CAP" +#define EFI_FVB2_WRITE_STATUS_STRING "EFI_WRITE_STATUS" + +#define EFI_FVB2_LOCK_CAP_STRING "EFI_LOCK_CAP" +#define EFI_FVB2_LOCK_STATUS_STRING "EFI_LOCK_STATUS" + +#define EFI_FVB2_STICKY_WRITE_STRING "EFI_STICKY_WRITE" +#define EFI_FVB2_MEMORY_MAPPED_STRING "EFI_MEMORY_MAPPED" +#define EFI_FVB2_ERASE_POLARITY_STRING "EFI_ERASE_POLARITY" + +#define EFI_FVB2_READ_LOCK_CAP_STRING "EFI_READ_LOCK_CAP" +#define EFI_FVB2_READ_LOCK_STATUS_STRING "EFI_READ_LOCK_STATUS" +#define EFI_FVB2_WRITE_LOCK_CAP_STRING "EFI_WRITE_LOCK_CAP" +#define EFI_FVB2_WRITE_LOCK_STATUS_STRING "EFI_WRITE_LOCK_STATUS" + +#define EFI_FVB2_ALIGNMENT_1_STRING "EFI_FVB2_ALIGNMENT_1" +#define EFI_FVB2_ALIGNMENT_2_STRING "EFI_FVB2_ALIGNMENT_2" +#define EFI_FVB2_ALIGNMENT_4_STRING "EFI_FVB2_ALIGNMENT_4" +#define EFI_FVB2_ALIGNMENT_8_STRING "EFI_FVB2_ALIGNMENT_8" +#define EFI_FVB2_ALIGNMENT_16_STRING "EFI_FVB2_ALIGNMENT_16" +#define EFI_FVB2_ALIGNMENT_32_STRING "EFI_FVB2_ALIGNMENT_32" +#define EFI_FVB2_ALIGNMENT_64_STRING "EFI_FVB2_ALIGNMENT_64" +#define EFI_FVB2_ALIGNMENT_128_STRING "EFI_FVB2_ALIGNMENT_128" +#define EFI_FVB2_ALIGNMENT_256_STRING "EFI_FVB2_ALIGNMENT_256" +#define EFI_FVB2_ALIGNMENT_512_STRING "EFI_FVB2_ALIGNMENT_512" +#define EFI_FVB2_ALIGNMENT_1K_STRING "EFI_FVB2_ALIGNMENT_1K" +#define EFI_FVB2_ALIGNMENT_2K_STRING "EFI_FVB2_ALIGNMENT_2K" +#define EFI_FVB2_ALIGNMENT_4K_STRING "EFI_FVB2_ALIGNMENT_4K" +#define EFI_FVB2_ALIGNMENT_8K_STRING "EFI_FVB2_ALIGNMENT_8K" +#define EFI_FVB2_ALIGNMENT_16K_STRING "EFI_FVB2_ALIGNMENT_16K" +#define EFI_FVB2_ALIGNMENT_32K_STRING "EFI_FVB2_ALIGNMENT_32K" +#define EFI_FVB2_ALIGNMENT_64K_STRING "EFI_FVB2_ALIGNMENT_64K" +#define EFI_FVB2_ALIGNMENT_128K_STRING "EFI_FVB2_ALIGNMENT_128K" +#define EFI_FVB2_ALIGNMENT_256K_STRING "EFI_FVB2_ALIGNMENT_256K" +#define EFI_FVB2_ALIGNMENT_512K_STRING "EFI_FVB2_ALIGNMENT_512K" +#define EFI_FVB2_ALIGNMENT_1M_STRING "EFI_FVB2_ALIGNMENT_1M" +#define EFI_FVB2_ALIGNMENT_2M_STRING "EFI_FVB2_ALIGNMENT_2M" +#define EFI_FVB2_ALIGNMENT_4M_STRING "EFI_FVB2_ALIGNMENT_4M" +#define EFI_FVB2_ALIGNMENT_8M_STRING "EFI_FVB2_ALIGNMENT_8M" +#define EFI_FVB2_ALIGNMENT_16M_STRING "EFI_FVB2_ALIGNMENT_16M" +#define EFI_FVB2_ALIGNMENT_32M_STRING "EFI_FVB2_ALIGNMENT_32M" +#define EFI_FVB2_ALIGNMENT_64M_STRING "EFI_FVB2_ALIGNMENT_64M" +#define EFI_FVB2_ALIGNMENT_128M_STRING "EFI_FVB2_ALIGNMENT_128M" +#define EFI_FVB2_ALIGNMENT_256M_STRING "EFI_FVB2_ALIGNMENT_256M" +#define EFI_FVB2_ALIGNMENT_512M_STRING "EFI_FVB2_ALIGNMENT_512M" +#define EFI_FVB2_ALIGNMENT_1G_STRING "EFI_FVB2_ALIGNMENT_1G" +#define EFI_FVB2_ALIGNMENT_2G_STRING "EFI_FVB2_ALIGNMENT_2G" + +#define EFI_FV_WEAK_ALIGNMENT_STRING "EFI_WEAK_ALIGNMENT" + +// +// File sections +// +#define EFI_FILE_NAME_STRING "EFI_FILE_NAME" + +#define ONE_STRING "1" +#define ZERO_STRING "0" +#define TRUE_STRING "TRUE" +#define FALSE_STRING "FALSE" +#define NULL_STRING "NULL" + +// +// +// +#define EFI_FV_EXT_HEADER_FILE_NAME "EFI_FV_EXT_HEADER_FILE_NAME" + + +// +// VTF (Firmware Volume Top File) signatures +// +#define IA32_X64_VTF_SIGNATURE_OFFSET 0x14 +#define IA32_X64_VTF0_SIGNATURE SIGNATURE_32('V','T','F',0) + +// +// Defines to calculate the offset for PEI CORE entry points +// +#define IA32_PEI_CORE_ENTRY_OFFSET 0x20 + +// +// Defines to calculate the offset for IA32 SEC CORE entry point +// +#define IA32_SEC_CORE_ENTRY_OFFSET 0xD + +// +// Symbol file definitions, current max size if 512K +// +#define SYMBOL_FILE_SIZE 0x80000 + +#define FV_IMAGES_TOP_ADDRESS 0x100000000ULL + +// +// Following definition is used for FIT in IPF +// +#define COMP_TYPE_FIT_PEICORE 0x10 +#define COMP_TYPE_FIT_UNUSED 0x7F + +#define FIT_TYPE_MASK 0x7F +#define CHECKSUM_BIT_MASK 0x80 + +// +// Private data types +// +// +// Component information +// +typedef struct { + UINTN Size; + CHAR8 ComponentName[MAX_LONG_FILE_PATH]; +} COMPONENT_INFO; + +// +// FV and capsule information holder +// +typedef struct { + BOOLEAN BaseAddressSet; + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_GUID FvFileSystemGuid; + BOOLEAN FvFileSystemGuidSet; + EFI_GUID FvNameGuid; + BOOLEAN FvNameGuidSet; + CHAR8 FvExtHeaderFile[MAX_LONG_FILE_PATH]; + UINTN Size; + EFI_FVB_ATTRIBUTES_2 FvAttributes; + CHAR8 FvName[MAX_LONG_FILE_PATH]; + EFI_FV_BLOCK_MAP_ENTRY FvBlocks[MAX_NUMBER_OF_FV_BLOCKS]; + CHAR8 FvFiles[MAX_NUMBER_OF_FILES_IN_FV][MAX_LONG_FILE_PATH]; + UINT32 SizeofFvFiles[MAX_NUMBER_OF_FILES_IN_FV]; + BOOLEAN IsPiFvImage; + INT8 ForceRebase; +} FV_INFO; + +typedef struct { + EFI_GUID CapGuid; + UINT32 HeaderSize; + UINT32 Flags; + CHAR8 CapName[MAX_LONG_FILE_PATH]; + CHAR8 CapFiles[MAX_NUMBER_OF_FILES_IN_CAP][MAX_LONG_FILE_PATH]; +} CAP_INFO; + +#pragma pack(1) + +typedef struct { + UINT64 CompAddress; + UINT32 CompSize; + UINT16 CompVersion; + UINT8 CvAndType; + UINT8 CheckSum; +} FIT_TABLE; + +#pragma pack() + +#define FV_DEFAULT_ATTRIBUTE 0x0004FEFF +extern FV_INFO mFvDataInfo; +extern CAP_INFO mCapDataInfo; +extern EFI_GUID mEfiFirmwareFileSystem2Guid; +extern EFI_GUID mEfiFirmwareFileSystem3Guid; +extern UINT32 mFvTotalSize; +extern UINT32 mFvTakenSize; + +extern EFI_PHYSICAL_ADDRESS mFvBaseAddress[]; +extern UINT32 mFvBaseAddressNumber; +// +// Local function prototypes +// +EFI_STATUS +ParseFvInf ( + IN MEMORY_FILE *InfFile, + OUT FV_INFO *FvInfo + ) +; + +EFI_STATUS +UpdatePeiCoreEntryInFit ( + IN FIT_TABLE *FitTablePtr, + IN UINT64 PeiCorePhysicalAddress + ) +/*++ + +Routine Description: + + This function is used to update the Pei Core address in FIT, this can be used by Sec core to pass control from + Sec to Pei Core + +Arguments: + + FitTablePtr - The pointer of FIT_TABLE. + PeiCorePhysicalAddress - The address of Pei Core entry. + +Returns: + + EFI_SUCCESS - The PEI_CORE FIT entry was updated successfully. + EFI_NOT_FOUND - Not found the PEI_CORE FIT entry. + +--*/ +; + +VOID +UpdateFitCheckSum ( + IN FIT_TABLE *FitTablePtr + ) +/*++ + +Routine Description: + + This function is used to update the checksum for FIT. + + +Arguments: + + FitTablePtr - The pointer of FIT_TABLE. + +Returns: + + None. + +--*/ +; + +EFI_STATUS +GetPe32Info ( + IN UINT8 *Pe32, + OUT UINT32 *EntryPoint, + OUT UINT32 *BaseOfCode, + OUT UINT16 *MachineType + ); + +EFI_STATUS +ParseCapInf ( + IN MEMORY_FILE *InfFile, + OUT CAP_INFO *CapInfo + ); + +EFI_STATUS +FindApResetVectorPosition ( + IN MEMORY_FILE *FvImage, + OUT UINT8 **Pointer + ); + +EFI_STATUS +CalculateFvSize ( + FV_INFO *FvInfoPtr + ); + +EFI_STATUS +FfsRebase ( + IN OUT FV_INFO *FvInfo, + IN CHAR8 *FileName, + IN OUT EFI_FFS_FILE_HEADER *FfsFile, + IN UINTN XipOffset, + IN FILE *FvMapFile + ); + +// +// Exported function prototypes +// +EFI_STATUS +GenerateCapImage ( + IN CHAR8 *InfFileImage, + IN UINTN InfFileSize, + IN CHAR8 *CapFileName + ) +/*++ + +Routine Description: + + This is the main function which will be called from application to + generate UEFI Capsule image. + +Arguments: + + InfFileImage Buffer containing the INF file contents. + InfFileSize Size of the contents of the InfFileImage buffer. + CapFileName Requested name for the Cap file. + +Returns: + + EFI_SUCCESS Function completed successfully. + EFI_OUT_OF_RESOURCES Could not allocate required resources. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + +--*/ +; + +EFI_STATUS +GenerateFvImage ( + IN CHAR8 *InfFileImage, + IN UINTN InfFileSize, + IN CHAR8 *FvFileName, + IN CHAR8 *MapFileName + ) +/*++ + +Routine Description: + + This is the main function which will be called from application to + generate Firmware Image conforms to PI spec. + +Arguments: + + InfFileImage Buffer containing the INF file contents. + InfFileSize Size of the contents of the InfFileImage buffer. + FvFileName Requested name for the FV file. + MapFileName Fv map file to log fv driver information. + +Returns: + + EFI_SUCCESS Function completed successfully. + EFI_OUT_OF_RESOURCES Could not allocate required resources. + EFI_ABORTED Error encountered. + EFI_INVALID_PARAMETER A required parameter was NULL. + +--*/ +; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/Makefile new file mode 100644 index 00000000..e4550afd --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/Makefile @@ -0,0 +1,16 @@ +## @file +# Windows makefile for 'GenFv' module build. +# +# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenFv + +LIBS = $(LIB_PATH)\Common.lib RpcRT4.lib + +OBJECTS = GenFv.obj GenFvInternalLib.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/Makefile.kmk new file mode 100644 index 00000000..1da959c6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFv/Makefile.kmk @@ -0,0 +1,45 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-makefile for the EFI GenFv build tool. +# + +# +# Copyright (C) 2013-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# 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, in version 3 of the +# License. +# +# 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 . +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +SUB_DEPTH = ../../../../../../../../.. +include $(KBUILD_PATH)/subheader.kmk + +BLDPROGS += GenFv +GenFv_TEMPLATE = VBoxEfiBldProg +GenFv_SOURCES = GenFv.c GenFvInternalLib.c + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.c new file mode 100644 index 00000000..f93eeb47 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.c @@ -0,0 +1,1177 @@ +/** @file +Elf32 Convert solution + +Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.
+Portions copyright (c) 2013, ARM Ltd. All rights reserved.
+Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "WinNtInclude.h" + +#ifndef __GNUC__ +#include +#include +#endif +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "PeCoffLib.h" +#include "EfiUtilityMsgs.h" + +#include "GenFw.h" +#include "ElfConvert.h" +#include "Elf32Convert.h" + +STATIC +VOID +ScanSections32 ( + VOID + ); + +STATIC +BOOLEAN +WriteSections32 ( + SECTION_FILTER_TYPES FilterType + ); + +STATIC +VOID +WriteRelocations32 ( + VOID + ); + +STATIC +VOID +WriteDebug32 ( + VOID + ); + +STATIC +VOID +SetImageSize32 ( + VOID + ); + +STATIC +VOID +CleanUp32 ( + VOID + ); + +// +// Rename ELF32 structures to common names to help when porting to ELF64. +// +typedef Elf32_Shdr Elf_Shdr; +typedef Elf32_Ehdr Elf_Ehdr; +typedef Elf32_Rel Elf_Rel; +typedef Elf32_Sym Elf_Sym; +typedef Elf32_Phdr Elf_Phdr; +typedef Elf32_Dyn Elf_Dyn; +#define ELFCLASS ELFCLASS32 +#define ELF_R_TYPE(r) ELF32_R_TYPE(r) +#define ELF_R_SYM(r) ELF32_R_SYM(r) + +// +// Well known ELF structures. +// +STATIC Elf_Ehdr *mEhdr; +STATIC Elf_Shdr *mShdrBase; +STATIC Elf_Phdr *mPhdrBase; + +// +// Coff information +// +STATIC UINT32 mCoffAlignment = 0x20; + +// +// PE section alignment. +// +STATIC const UINT16 mCoffNbrSections = 4; + +// +// ELF sections to offset in Coff file. +// +STATIC UINT32 *mCoffSectionsOffset = NULL; + +// +// Offsets in COFF file +// +STATIC UINT32 mNtHdrOffset; +STATIC UINT32 mTextOffset; +STATIC UINT32 mDataOffset; +STATIC UINT32 mHiiRsrcOffset; +STATIC UINT32 mRelocOffset; +STATIC UINT32 mDebugOffset; + +// +// Initialization Function +// +BOOLEAN +InitializeElf32 ( + UINT8 *FileBuffer, + ELF_FUNCTION_TABLE *ElfFunctions + ) +{ + // + // Initialize data pointer and structures. + // + mEhdr = (Elf_Ehdr*) FileBuffer; + + // + // Check the ELF32 specific header information. + // + if (mEhdr->e_ident[EI_CLASS] != ELFCLASS32) { + Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFCLASS32"); + return FALSE; + } + if (mEhdr->e_ident[EI_DATA] != ELFDATA2LSB) { + Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB"); + return FALSE; + } + if ((mEhdr->e_type != ET_EXEC) && (mEhdr->e_type != ET_DYN)) { + Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN"); + return FALSE; + } + if (!((mEhdr->e_machine == EM_386) || (mEhdr->e_machine == EM_ARM) || (mEhdr->e_machine == EM_RISCV))) { + Warning (NULL, 0, 3000, "Unsupported", "ELF e_machine is not Elf32 machine."); + } + if (mEhdr->e_version != EV_CURRENT) { + Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) mEhdr->e_version, EV_CURRENT); + return FALSE; + } + + // + // Update section header pointers + // + mShdrBase = (Elf_Shdr *)((UINT8 *)mEhdr + mEhdr->e_shoff); + mPhdrBase = (Elf_Phdr *)((UINT8 *)mEhdr + mEhdr->e_phoff); + + // + // Create COFF Section offset buffer and zero. + // + mCoffSectionsOffset = (UINT32 *)malloc(mEhdr->e_shnum * sizeof (UINT32)); + if (mCoffSectionsOffset == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return FALSE; + } + memset(mCoffSectionsOffset, 0, mEhdr->e_shnum * sizeof(UINT32)); + + // + // Fill in function pointers. + // + ElfFunctions->ScanSections = ScanSections32; + ElfFunctions->WriteSections = WriteSections32; + ElfFunctions->WriteRelocations = WriteRelocations32; + ElfFunctions->WriteDebug = WriteDebug32; + ElfFunctions->SetImageSize = SetImageSize32; + ElfFunctions->CleanUp = CleanUp32; + + return TRUE; +} + + +// +// Header by Index functions +// +STATIC +Elf_Shdr* +GetShdrByIndex ( + UINT32 Num + ) +{ + if (Num >= mEhdr->e_shnum) { + Error (NULL, 0, 3000, "Invalid", "GetShdrByIndex: Index %u is too high.", Num); + exit(EXIT_FAILURE); + } + + return (Elf_Shdr*)((UINT8*)mShdrBase + Num * mEhdr->e_shentsize); +} + +STATIC +Elf_Phdr* +GetPhdrByIndex ( + UINT32 num + ) +{ + if (num >= mEhdr->e_phnum) { + Error (NULL, 0, 3000, "Invalid", "GetPhdrByIndex: Index %u is too high.", num); + exit(EXIT_FAILURE); + } + + return (Elf_Phdr *)((UINT8*)mPhdrBase + num * mEhdr->e_phentsize); +} + +STATIC +UINT32 +CoffAlign ( + UINT32 Offset + ) +{ + return (Offset + mCoffAlignment - 1) & ~(mCoffAlignment - 1); +} + +STATIC +UINT32 +DebugRvaAlign ( + UINT32 Offset + ) +{ + return (Offset + 3) & ~3; +} + +// +// filter functions +// +STATIC +BOOLEAN +IsTextShdr ( + Elf_Shdr *Shdr + ) +{ + return (BOOLEAN) ((Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC); +} + +STATIC +BOOLEAN +IsHiiRsrcShdr ( + Elf_Shdr *Shdr + ) +{ + Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx); + + return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0); +} + +STATIC +BOOLEAN +IsDataShdr ( + Elf_Shdr *Shdr + ) +{ + if (IsHiiRsrcShdr(Shdr)) { + return FALSE; + } + return (BOOLEAN) (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE); +} + +STATIC +BOOLEAN +IsStrtabShdr ( + Elf_Shdr *Shdr + ) +{ + Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx); + + return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_STRTAB_SECTION_NAME) == 0); +} + +STATIC +Elf_Shdr * +FindStrtabShdr ( + VOID + ) +{ + UINT32 i; + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (IsStrtabShdr(shdr)) { + return shdr; + } + } + return NULL; +} + +STATIC +const UINT8 * +GetSymName ( + Elf_Sym *Sym + ) +{ + Elf_Shdr *StrtabShdr; + UINT8 *StrtabContents; + BOOLEAN foundEnd; + UINT32 i; + + if (Sym->st_name == 0) { + return NULL; + } + + StrtabShdr = FindStrtabShdr(); + if (StrtabShdr == NULL) { + return NULL; + } + + assert(Sym->st_name < StrtabShdr->sh_size); + + StrtabContents = (UINT8*)mEhdr + StrtabShdr->sh_offset; + + foundEnd = FALSE; + for (i = Sym->st_name; (i < StrtabShdr->sh_size) && !foundEnd; i++) { + foundEnd = (BOOLEAN)(StrtabContents[i] == 0); + } + assert(foundEnd); + + return StrtabContents + Sym->st_name; +} + +// +// Elf functions interface implementation +// + +STATIC +VOID +ScanSections32 ( + VOID + ) +{ + UINT32 i; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; + UINT32 CoffEntry; + UINT32 SectionCount; + BOOLEAN FoundSection; + + CoffEntry = 0; + mCoffOffset = 0; + + // + // Coff file start with a DOS header. + // + mCoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40; + mNtHdrOffset = mCoffOffset; + switch (mEhdr->e_machine) { + case EM_386: + case EM_ARM: + mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32); + break; + default: + VerboseMsg ("%s unknown e_machine type. Assume IA-32", (UINTN)mEhdr->e_machine); + mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS32); + break; + } + + mTableOffset = mCoffOffset; + mCoffOffset += mCoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER); + + // + // Set mCoffAlignment to the maximum alignment of the input sections + // we care about + // + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (shdr->sh_addralign <= mCoffAlignment) { + continue; + } + if (IsTextShdr(shdr) || IsDataShdr(shdr) || IsHiiRsrcShdr(shdr)) { + mCoffAlignment = (UINT32)shdr->sh_addralign; + } + } + + // + // Check if mCoffAlignment is larger than MAX_COFF_ALIGNMENT + // + if (mCoffAlignment > MAX_COFF_ALIGNMENT) { + Error (NULL, 0, 3000, "Invalid", "Section alignment is larger than MAX_COFF_ALIGNMENT."); + assert (FALSE); + } + + // + // Move the PE/COFF header right before the first section. This will help us + // save space when converting to TE. + // + if (mCoffAlignment > mCoffOffset) { + mNtHdrOffset += mCoffAlignment - mCoffOffset; + mTableOffset += mCoffAlignment - mCoffOffset; + mCoffOffset = mCoffAlignment; + } + + // + // First text sections. + // + mCoffOffset = CoffAlign(mCoffOffset); + mTextOffset = mCoffOffset; + FoundSection = FALSE; + SectionCount = 0; + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (IsTextShdr(shdr)) { + if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) { + // the alignment field is valid + if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) { + // if the section address is aligned we must align PE/COFF + mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1); + } else { + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment."); + } + } + + /* Relocate entry. */ + if ((mEhdr->e_entry >= shdr->sh_addr) && + (mEhdr->e_entry < shdr->sh_addr + shdr->sh_size)) { + CoffEntry = mCoffOffset + mEhdr->e_entry - shdr->sh_addr; + } + + // + // Set mTextOffset with the offset of the first '.text' section + // + if (!FoundSection) { + mTextOffset = mCoffOffset; + FoundSection = TRUE; + } + + mCoffSectionsOffset[i] = mCoffOffset; + mCoffOffset += shdr->sh_size; + SectionCount ++; + } + } + + if (!FoundSection) { + Error (NULL, 0, 3000, "Invalid", "Did not find any '.text' section."); + assert (FALSE); + } + + mDebugOffset = DebugRvaAlign(mCoffOffset); + mCoffOffset = CoffAlign(mCoffOffset); + + if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) { + Warning (NULL, 0, 0, NULL, "Multiple sections in %s are merged into 1 text section. Source level debug might not work correctly.", mInImageName); + } + + // + // Then data sections. + // + mDataOffset = mCoffOffset; + FoundSection = FALSE; + SectionCount = 0; + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (IsDataShdr(shdr)) { + if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) { + // the alignment field is valid + if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) { + // if the section address is aligned we must align PE/COFF + mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1); + } else { + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment."); + } + } + + // + // Set mDataOffset with the offset of the first '.data' section + // + if (!FoundSection) { + mDataOffset = mCoffOffset; + FoundSection = TRUE; + } + + mCoffSectionsOffset[i] = mCoffOffset; + mCoffOffset += shdr->sh_size; + SectionCount ++; + } + } + + if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) { + Warning (NULL, 0, 0, NULL, "Multiple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName); + } + + // + // Make room for .debug data in .data (or .text if .data is empty) instead of + // putting it in a section of its own. This is explicitly allowed by the + // PE/COFF spec, and prevents bloat in the binary when using large values for + // section alignment. + // + if (SectionCount > 0) { + mDebugOffset = DebugRvaAlign(mCoffOffset); + } + mCoffOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) + + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + + strlen(mInImageName) + 1; + + mCoffOffset = CoffAlign(mCoffOffset); + if (SectionCount == 0) { + mDataOffset = mCoffOffset; + } + + // + // The HII resource sections. + // + mHiiRsrcOffset = mCoffOffset; + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (IsHiiRsrcShdr(shdr)) { + if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) { + // the alignment field is valid + if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) { + // if the section address is aligned we must align PE/COFF + mCoffOffset = (mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1); + } else { + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment."); + } + } + if (shdr->sh_size != 0) { + mHiiRsrcOffset = mCoffOffset; + mCoffSectionsOffset[i] = mCoffOffset; + mCoffOffset += shdr->sh_size; + mCoffOffset = CoffAlign(mCoffOffset); + SetHiiResourceHeader ((UINT8*) mEhdr + shdr->sh_offset, mHiiRsrcOffset); + } + break; + } + } + + mRelocOffset = mCoffOffset; + + // + // Allocate base Coff file. Will be expanded later for relocations. + // + mCoffFile = (UINT8 *)malloc(mCoffOffset); + if (mCoffFile == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + } + assert (mCoffFile != NULL); + memset(mCoffFile, 0, mCoffOffset); + + // + // Fill headers. + // + DosHdr = (EFI_IMAGE_DOS_HEADER *)mCoffFile; + DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE; + DosHdr->e_lfanew = mNtHdrOffset; + + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(mCoffFile + mNtHdrOffset); + + NtHdr->Pe32.Signature = EFI_IMAGE_NT_SIGNATURE; + + switch (mEhdr->e_machine) { + case EM_386: + NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32; + NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + break; + case EM_ARM: + NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_ARMT; + NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + break; + default: + VerboseMsg ("%s unknown e_machine type %hu. Assume IA-32", mInImageName, mEhdr->e_machine); + NtHdr->Pe32.FileHeader.Machine = EFI_IMAGE_MACHINE_IA32; + NtHdr->Pe32.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC; + } + + NtHdr->Pe32.FileHeader.NumberOfSections = mCoffNbrSections; + NtHdr->Pe32.FileHeader.TimeDateStamp = (UINT32) time(NULL); + mImageTimeStamp = NtHdr->Pe32.FileHeader.TimeDateStamp; + NtHdr->Pe32.FileHeader.PointerToSymbolTable = 0; + NtHdr->Pe32.FileHeader.NumberOfSymbols = 0; + NtHdr->Pe32.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32.OptionalHeader); + NtHdr->Pe32.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE + | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED + | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED + | EFI_IMAGE_FILE_32BIT_MACHINE; + + NtHdr->Pe32.OptionalHeader.SizeOfCode = mDataOffset - mTextOffset; + NtHdr->Pe32.OptionalHeader.SizeOfInitializedData = mRelocOffset - mDataOffset; + NtHdr->Pe32.OptionalHeader.SizeOfUninitializedData = 0; + NtHdr->Pe32.OptionalHeader.AddressOfEntryPoint = CoffEntry; + + NtHdr->Pe32.OptionalHeader.BaseOfCode = mTextOffset; + + NtHdr->Pe32.OptionalHeader.BaseOfData = mDataOffset; + NtHdr->Pe32.OptionalHeader.ImageBase = 0; + NtHdr->Pe32.OptionalHeader.SectionAlignment = mCoffAlignment; + NtHdr->Pe32.OptionalHeader.FileAlignment = mCoffAlignment; + NtHdr->Pe32.OptionalHeader.SizeOfImage = 0; + + NtHdr->Pe32.OptionalHeader.SizeOfHeaders = mTextOffset; + NtHdr->Pe32.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES; + + // + // Section headers. + // + if ((mDataOffset - mTextOffset) > 0) { + CreateSectionHeader (".text", mTextOffset, mDataOffset - mTextOffset, + EFI_IMAGE_SCN_CNT_CODE + | EFI_IMAGE_SCN_MEM_EXECUTE + | EFI_IMAGE_SCN_MEM_READ); + } else { + // Don't make a section of size 0. + NtHdr->Pe32.FileHeader.NumberOfSections--; + } + + if ((mHiiRsrcOffset - mDataOffset) > 0) { + CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset, + EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + | EFI_IMAGE_SCN_MEM_WRITE + | EFI_IMAGE_SCN_MEM_READ); + } else { + // Don't make a section of size 0. + NtHdr->Pe32.FileHeader.NumberOfSections--; + } + + if ((mRelocOffset - mHiiRsrcOffset) > 0) { + CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset, + EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + | EFI_IMAGE_SCN_MEM_READ); + + NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = mRelocOffset - mHiiRsrcOffset; + NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = mHiiRsrcOffset; + } else { + // Don't make a section of size 0. + NtHdr->Pe32.FileHeader.NumberOfSections--; + } + +} + +STATIC +BOOLEAN +WriteSections32 ( + SECTION_FILTER_TYPES FilterType + ) +{ + UINT32 Idx; + Elf_Shdr *SecShdr; + UINT32 SecOffset; + BOOLEAN (*Filter)(Elf_Shdr *); + + // + // Initialize filter pointer + // + switch (FilterType) { + case SECTION_TEXT: + Filter = IsTextShdr; + break; + case SECTION_HII: + Filter = IsHiiRsrcShdr; + break; + case SECTION_DATA: + Filter = IsDataShdr; + break; + default: + return FALSE; + } + + // + // First: copy sections. + // + for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) { + Elf_Shdr *Shdr = GetShdrByIndex(Idx); + if ((*Filter)(Shdr)) { + switch (Shdr->sh_type) { + case SHT_PROGBITS: + /* Copy. */ + if (Shdr->sh_offset + Shdr->sh_size > mFileBufferSize) { + return FALSE; + } + memcpy(mCoffFile + mCoffSectionsOffset[Idx], + (UINT8*)mEhdr + Shdr->sh_offset, + Shdr->sh_size); + break; + + case SHT_NOBITS: + memset(mCoffFile + mCoffSectionsOffset[Idx], 0, Shdr->sh_size); + break; + + default: + // + // Ignore for unknown section type. + // + VerboseMsg ("%s unknown section type %x. We ignore this unknown section type.", mInImageName, (unsigned)Shdr->sh_type); + break; + } + } + } + + // + // Second: apply relocations. + // + for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) { + // + // Determine if this is a relocation section. + // + Elf_Shdr *RelShdr = GetShdrByIndex(Idx); + if ((RelShdr->sh_type != SHT_REL) && (RelShdr->sh_type != SHT_RELA)) { + continue; + } + + // + // Relocation section found. Now extract section information that the relocations + // apply to in the ELF data and the new COFF data. + // + SecShdr = GetShdrByIndex(RelShdr->sh_info); + SecOffset = mCoffSectionsOffset[RelShdr->sh_info]; + + // + // Only process relocations for the current filter type. + // + if (RelShdr->sh_type == SHT_REL && (*Filter)(SecShdr)) { + UINT32 RelOffset; + + // + // Determine the symbol table referenced by the relocation data. + // + Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link); + UINT8 *Symtab = (UINT8*)mEhdr + SymtabShdr->sh_offset; + + // + // Process all relocation entries for this section. + // + for (RelOffset = 0; RelOffset < RelShdr->sh_size; RelOffset += RelShdr->sh_entsize) { + // + // Set pointer to relocation entry + // + Elf_Rel *Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelOffset); + + // + // Set pointer to symbol table entry associated with the relocation entry. + // + Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize); + + Elf_Shdr *SymShdr; + UINT8 *Targ; + UINT16 Address; + + // + // Check section header index found in symbol table and get the section + // header location. + // + if (Sym->st_shndx == SHN_UNDEF + || Sym->st_shndx >= mEhdr->e_shnum) { + const UINT8 *SymName = GetSymName(Sym); + if (SymName == NULL) { + SymName = (const UINT8 *)""; + } + + Error (NULL, 0, 3000, "Invalid", + "%s: Bad definition for symbol '%s'@%#x or unsupported symbol type. " + "For example, absolute and undefined symbols are not supported.", + mInImageName, SymName, Sym->st_value); + + exit(EXIT_FAILURE); + } + SymShdr = GetShdrByIndex(Sym->st_shndx); + + // + // Convert the relocation data to a pointer into the coff file. + // + // Note: + // r_offset is the virtual address of the storage unit to be relocated. + // sh_addr is the virtual address for the base of the section. + // + Targ = mCoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr); + + // + // Determine how to handle each relocation type based on the machine type. + // + if (mEhdr->e_machine == EM_386) { + switch (ELF_R_TYPE(Rel->r_info)) { + case R_386_NONE: + break; + case R_386_32: + // + // Absolute relocation. + // Converts Targ from a absolute virtual address to the absolute + // COFF address. + // + *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + + mCoffSectionsOffset[Sym->st_shndx]; + break; + case R_386_PC32: + // + // Relative relocation: Symbol - Ip + Addend + // + *(UINT32 *)Targ = *(UINT32 *)Targ + + (mCoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr) + - (SecOffset - SecShdr->sh_addr); + break; + default: + Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } + } else if (mEhdr->e_machine == EM_ARM) { + switch (ELF32_R_TYPE(Rel->r_info)) { + case R_ARM_RBASE: + // No relocation - no action required + // break skipped + + case R_ARM_PC24: + case R_ARM_REL32: + case R_ARM_XPC25: + case R_ARM_THM_PC22: + case R_ARM_THM_JUMP19: + case R_ARM_CALL: + case R_ARM_JMP24: + case R_ARM_THM_JUMP24: + case R_ARM_PREL31: + case R_ARM_MOVW_PREL_NC: + case R_ARM_MOVT_PREL: + case R_ARM_THM_MOVW_PREL_NC: + case R_ARM_THM_MOVT_PREL: + case R_ARM_THM_JMP6: + case R_ARM_THM_ALU_PREL_11_0: + case R_ARM_THM_PC12: + case R_ARM_REL32_NOI: + case R_ARM_ALU_PC_G0_NC: + case R_ARM_ALU_PC_G0: + case R_ARM_ALU_PC_G1_NC: + case R_ARM_ALU_PC_G1: + case R_ARM_ALU_PC_G2: + case R_ARM_LDR_PC_G1: + case R_ARM_LDR_PC_G2: + case R_ARM_LDRS_PC_G0: + case R_ARM_LDRS_PC_G1: + case R_ARM_LDRS_PC_G2: + case R_ARM_LDC_PC_G0: + case R_ARM_LDC_PC_G1: + case R_ARM_LDC_PC_G2: + case R_ARM_THM_JUMP11: + case R_ARM_THM_JUMP8: + case R_ARM_TLS_GD32: + case R_ARM_TLS_LDM32: + case R_ARM_TLS_IE32: + // Thease are all PC-relative relocations and don't require modification + // GCC does not seem to have the concept of a application that just needs to get relocated. + break; + + case R_ARM_THM_MOVW_ABS_NC: + // MOVW is only lower 16-bits of the addres + Address = (UINT16)(Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]); + ThumbMovtImmediatePatch ((UINT16 *)Targ, Address); + break; + + case R_ARM_THM_MOVT_ABS: + // MOVT is only upper 16-bits of the addres + Address = (UINT16)((Sym->st_value - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]) >> 16); + ThumbMovtImmediatePatch ((UINT16 *)Targ, Address); + break; + + case R_ARM_ABS32: + case R_ARM_RABS32: + // + // Absolute relocation. + // + *(UINT32 *)Targ = *(UINT32 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + break; + + default: + Error (NULL, 0, 3000, "Invalid", "WriteSections (): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info)); + } + } + } + } + } + + return TRUE; +} + +UINTN gMovwOffset = 0; + +STATIC +VOID +WriteRelocations32 ( + VOID + ) +{ + UINT32 Index; + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; + EFI_IMAGE_DATA_DIRECTORY *Dir; + BOOLEAN FoundRelocations; + Elf_Dyn *Dyn; + Elf_Rel *Rel; + UINTN RelElementSize; + UINTN RelSize; + UINTN RelOffset; + UINTN K; + Elf32_Phdr *DynamicSegment; + + for (Index = 0, FoundRelocations = FALSE; Index < mEhdr->e_shnum; Index++) { + Elf_Shdr *RelShdr = GetShdrByIndex(Index); + if ((RelShdr->sh_type == SHT_REL) || (RelShdr->sh_type == SHT_RELA)) { + Elf_Shdr *SecShdr = GetShdrByIndex (RelShdr->sh_info); + if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) { + UINT32 RelIdx; + + FoundRelocations = TRUE; + for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) { + Rel = (Elf_Rel *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx); + + if (mEhdr->e_machine == EM_386) { + switch (ELF_R_TYPE(Rel->r_info)) { + case R_386_NONE: + case R_386_PC32: + // + // No fixup entry required. + // + break; + case R_386_32: + // + // Creates a relative relocation entry from the absolute entry. + // + CoffAddFixup(mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr), + EFI_IMAGE_REL_BASED_HIGHLOW); + break; + default: + Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_386 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } + } else if (mEhdr->e_machine == EM_ARM) { + switch (ELF32_R_TYPE(Rel->r_info)) { + case R_ARM_RBASE: + // No relocation - no action required + // break skipped + + case R_ARM_PC24: + case R_ARM_REL32: + case R_ARM_XPC25: + case R_ARM_THM_PC22: + case R_ARM_THM_JUMP19: + case R_ARM_CALL: + case R_ARM_JMP24: + case R_ARM_THM_JUMP24: + case R_ARM_PREL31: + case R_ARM_MOVW_PREL_NC: + case R_ARM_MOVT_PREL: + case R_ARM_THM_MOVW_PREL_NC: + case R_ARM_THM_MOVT_PREL: + case R_ARM_THM_JMP6: + case R_ARM_THM_ALU_PREL_11_0: + case R_ARM_THM_PC12: + case R_ARM_REL32_NOI: + case R_ARM_ALU_PC_G0_NC: + case R_ARM_ALU_PC_G0: + case R_ARM_ALU_PC_G1_NC: + case R_ARM_ALU_PC_G1: + case R_ARM_ALU_PC_G2: + case R_ARM_LDR_PC_G1: + case R_ARM_LDR_PC_G2: + case R_ARM_LDRS_PC_G0: + case R_ARM_LDRS_PC_G1: + case R_ARM_LDRS_PC_G2: + case R_ARM_LDC_PC_G0: + case R_ARM_LDC_PC_G1: + case R_ARM_LDC_PC_G2: + case R_ARM_THM_JUMP11: + case R_ARM_THM_JUMP8: + case R_ARM_TLS_GD32: + case R_ARM_TLS_LDM32: + case R_ARM_TLS_IE32: + // Thease are all PC-relative relocations and don't require modification + break; + + case R_ARM_THM_MOVW_ABS_NC: + CoffAddFixup ( + mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr), + EFI_IMAGE_REL_BASED_ARM_MOV32T + ); + + // PE/COFF treats MOVW/MOVT relocation as single 64-bit instruction + // Track this address so we can log an error for unsupported sequence of MOVW/MOVT + gMovwOffset = mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr); + break; + + case R_ARM_THM_MOVT_ABS: + if ((gMovwOffset + 4) != (mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr))) { + Error (NULL, 0, 3000, "Not Supported", "PE/COFF requires MOVW+MOVT instruction sequence %x +4 != %x.", gMovwOffset, mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr)); + } + break; + + case R_ARM_ABS32: + case R_ARM_RABS32: + CoffAddFixup ( + mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr), + EFI_IMAGE_REL_BASED_HIGHLOW + ); + break; + + default: + Error (NULL, 0, 3000, "Invalid", "WriteRelocations(): %s unsupported ELF EM_ARM relocation 0x%x.", mInImageName, (unsigned) ELF32_R_TYPE(Rel->r_info)); + } + } else { + Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) mEhdr->e_machine); + } + } + } + } + } + + if (!FoundRelocations && (mEhdr->e_machine == EM_ARM)) { + /* Try again, but look for PT_DYNAMIC instead of SHT_REL */ + + for (Index = 0; Index < mEhdr->e_phnum; Index++) { + RelElementSize = 0; + RelSize = 0; + RelOffset = 0; + + DynamicSegment = GetPhdrByIndex (Index); + + if (DynamicSegment->p_type == PT_DYNAMIC) { + Dyn = (Elf32_Dyn *) ((UINT8 *)mEhdr + DynamicSegment->p_offset); + + while (Dyn->d_tag != DT_NULL) { + switch (Dyn->d_tag) { + case DT_REL: + RelOffset = Dyn->d_un.d_val; + break; + + case DT_RELSZ: + RelSize = Dyn->d_un.d_val; + break; + + case DT_RELENT: + RelElementSize = Dyn->d_un.d_val; + break; + + default: + break; + } + Dyn++; + } + if (( RelOffset == 0 ) || ( RelSize == 0 ) || ( RelElementSize == 0 )) { + Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations.", mInImageName); + } + + for (Index = 0; Index < mEhdr->e_shnum; Index++) { + Elf_Shdr *shdr = GetShdrByIndex(Index); + + // + // The PT_DYNAMIC section contains DT_REL relocations whose r_offset + // field is relative to the base of a segment (or the entire image), + // and not to the base of an ELF input section as is the case for + // SHT_REL sections. This means that we cannot fix up such relocations + // unless we cross-reference ELF sections and segments, considering + // that the output placement recorded in mCoffSectionsOffset[] is + // section based, not segment based. + // + // Fortunately, there is a simple way around this: we require that the + // in-memory layout of the ELF and PE/COFF versions of the binary is + // identical. That way, r_offset will retain its validity as a PE/COFF + // image offset, and we can record it in the COFF fixup table + // unmodified. + // + if (shdr->sh_addr != mCoffSectionsOffset[Index]) { + Error (NULL, 0, 3000, + "Invalid", "%s: PT_DYNAMIC relocations require identical ELF and PE/COFF section offsets.", + mInImageName); + } + } + + for (K = 0; K < RelSize; K += RelElementSize) { + + if (DynamicSegment->p_paddr == 0) { + // Older versions of the ARM ELF (SWS ESPC 0003 B-02) specification define DT_REL + // as an offset in the dynamic segment. p_paddr is defined to be zero for ARM tools + Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + DynamicSegment->p_offset + RelOffset + K); + } else { + // This is how it reads in the generic ELF specification + Rel = (Elf32_Rel *) ((UINT8 *) mEhdr + RelOffset + K); + } + + switch (ELF32_R_TYPE (Rel->r_info)) { + case R_ARM_RBASE: + break; + + case R_ARM_RABS32: + CoffAddFixup (Rel->r_offset, EFI_IMAGE_REL_BASED_HIGHLOW); + break; + + default: + Error (NULL, 0, 3000, "Invalid", "%s bad ARM dynamic relocations, unknown type %d.", mInImageName, ELF32_R_TYPE (Rel->r_info)); + break; + } + } + break; + } + } + } + + // + // Pad by adding empty entries. + // + while (mCoffOffset & (mCoffAlignment - 1)) { + CoffAddFixupEntry(0); + } + + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset); + Dir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + Dir->Size = mCoffOffset - mRelocOffset; + if (Dir->Size == 0) { + // If no relocations, null out the directory entry and don't add the .reloc section + Dir->VirtualAddress = 0; + NtHdr->Pe32.FileHeader.NumberOfSections--; + } else { + Dir->VirtualAddress = mRelocOffset; + CreateSectionHeader (".reloc", mRelocOffset, mCoffOffset - mRelocOffset, + EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + | EFI_IMAGE_SCN_MEM_DISCARDABLE + | EFI_IMAGE_SCN_MEM_READ); + } + +} + +STATIC +VOID +WriteDebug32 ( + VOID + ) +{ + UINT32 Len; + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; + EFI_IMAGE_DATA_DIRECTORY *DataDir; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir; + EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10; + + Len = strlen(mInImageName) + 1; + + Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(mCoffFile + mDebugOffset); + Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW; + Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len; + Dir->RVA = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + Dir->FileOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + + Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1); + Nb10->Signature = CODEVIEW_SIGNATURE_NB10; + strcpy ((char *)(Nb10 + 1), mInImageName); + + + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset); + DataDir = &NtHdr->Pe32.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]; + DataDir->VirtualAddress = mDebugOffset; + DataDir->Size = sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); +} + +STATIC +VOID +SetImageSize32 ( + VOID + ) +{ + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; + + // + // Set image size + // + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset); + NtHdr->Pe32.OptionalHeader.SizeOfImage = mCoffOffset; +} + +STATIC +VOID +CleanUp32 ( + VOID + ) +{ + if (mCoffSectionsOffset != NULL) { + free (mCoffSectionsOffset); + } +} + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.h new file mode 100644 index 00000000..d1b15123 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf32Convert.h @@ -0,0 +1,19 @@ +/** @file +Header file for Elf32 Convert solution + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _ELF_32_CONVERT_ +#define _ELF_32_CONVERT_ + +BOOLEAN +InitializeElf32 ( + UINT8 *FileBuffer, + ELF_FUNCTION_TABLE *ElfFunctions + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.c new file mode 100644 index 00000000..989c1fa8 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.c @@ -0,0 +1,1668 @@ +/** @file +Elf64 convert solution + +Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.
+Portions copyright (c) 2013-2014, ARM Ltd. All rights reserved.
+Portions Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "WinNtInclude.h" + +#ifndef __GNUC__ +#include +#include +#endif +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "PeCoffLib.h" +#include "EfiUtilityMsgs.h" + +#include "GenFw.h" +#include "ElfConvert.h" +#include "Elf64Convert.h" + +STATIC +VOID +ScanSections64 ( + VOID + ); + +STATIC +BOOLEAN +WriteSections64 ( + SECTION_FILTER_TYPES FilterType + ); + +STATIC +VOID +WriteRelocations64 ( + VOID + ); + +STATIC +VOID +WriteDebug64 ( + VOID + ); + +STATIC +VOID +SetImageSize64 ( + VOID + ); + +STATIC +VOID +CleanUp64 ( + VOID + ); + +// +// Rename ELF32 structures to common names to help when porting to ELF64. +// +typedef Elf64_Shdr Elf_Shdr; +typedef Elf64_Ehdr Elf_Ehdr; +typedef Elf64_Rel Elf_Rel; +typedef Elf64_Rela Elf_Rela; +typedef Elf64_Sym Elf_Sym; +typedef Elf64_Phdr Elf_Phdr; +typedef Elf64_Dyn Elf_Dyn; +#define ELFCLASS ELFCLASS64 +#define ELF_R_TYPE(r) ELF64_R_TYPE(r) +#define ELF_R_SYM(r) ELF64_R_SYM(r) + +// +// Well known ELF structures. +// +STATIC Elf_Ehdr *mEhdr; +STATIC Elf_Shdr *mShdrBase; +STATIC Elf_Phdr *mPhdrBase; + +// +// GOT information +// +STATIC Elf_Shdr *mGOTShdr = NULL; +STATIC UINT32 mGOTShindex = 0; +STATIC UINT32 *mGOTCoffEntries = NULL; +STATIC UINT32 mGOTMaxCoffEntries = 0; +STATIC UINT32 mGOTNumCoffEntries = 0; + +// +// Coff information +// +STATIC UINT32 mCoffAlignment = 0x20; + +// +// PE section alignment. +// +STATIC const UINT16 mCoffNbrSections = 4; + +// +// ELF sections to offset in Coff file. +// +STATIC UINT32 *mCoffSectionsOffset = NULL; + +// +// Offsets in COFF file +// +STATIC UINT32 mNtHdrOffset; +STATIC UINT32 mTextOffset; +STATIC UINT32 mDataOffset; +STATIC UINT32 mHiiRsrcOffset; +STATIC UINT32 mRelocOffset; +STATIC UINT32 mDebugOffset; + +// +// Used for RISC-V relocations. +// +STATIC UINT8 *mRiscVPass1Targ = NULL; +STATIC Elf_Shdr *mRiscVPass1Sym = NULL; +STATIC Elf64_Half mRiscVPass1SymSecIndex = 0; + +// +// Initialization Function +// +BOOLEAN +InitializeElf64 ( + UINT8 *FileBuffer, + ELF_FUNCTION_TABLE *ElfFunctions + ) +{ + // + // Initialize data pointer and structures. + // + VerboseMsg ("Set EHDR"); + mEhdr = (Elf_Ehdr*) FileBuffer; + + // + // Check the ELF64 specific header information. + // + VerboseMsg ("Check ELF64 Header Information"); + if (mEhdr->e_ident[EI_CLASS] != ELFCLASS64) { + Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFCLASS64"); + return FALSE; + } + if (mEhdr->e_ident[EI_DATA] != ELFDATA2LSB) { + Error (NULL, 0, 3000, "Unsupported", "ELF EI_DATA not ELFDATA2LSB"); + return FALSE; + } + if ((mEhdr->e_type != ET_EXEC) && (mEhdr->e_type != ET_DYN)) { + Error (NULL, 0, 3000, "Unsupported", "ELF e_type not ET_EXEC or ET_DYN"); + return FALSE; + } + if (!((mEhdr->e_machine == EM_X86_64) || (mEhdr->e_machine == EM_AARCH64) || (mEhdr->e_machine == EM_RISCV64))) { + Warning (NULL, 0, 3000, "Unsupported", "ELF e_machine is not Elf64 machine."); + } + if (mEhdr->e_version != EV_CURRENT) { + Error (NULL, 0, 3000, "Unsupported", "ELF e_version (%u) not EV_CURRENT (%d)", (unsigned) mEhdr->e_version, EV_CURRENT); + return FALSE; + } + + // + // Update section header pointers + // + VerboseMsg ("Update Header Pointers"); + mShdrBase = (Elf_Shdr *)((UINT8 *)mEhdr + mEhdr->e_shoff); + mPhdrBase = (Elf_Phdr *)((UINT8 *)mEhdr + mEhdr->e_phoff); + + // + // Create COFF Section offset buffer and zero. + // + VerboseMsg ("Create COFF Section Offset Buffer"); + mCoffSectionsOffset = (UINT32 *)malloc(mEhdr->e_shnum * sizeof (UINT32)); + if (mCoffSectionsOffset == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return FALSE; + } + memset(mCoffSectionsOffset, 0, mEhdr->e_shnum * sizeof(UINT32)); + + // + // Fill in function pointers. + // + VerboseMsg ("Fill in Function Pointers"); + ElfFunctions->ScanSections = ScanSections64; + ElfFunctions->WriteSections = WriteSections64; + ElfFunctions->WriteRelocations = WriteRelocations64; + ElfFunctions->WriteDebug = WriteDebug64; + ElfFunctions->SetImageSize = SetImageSize64; + ElfFunctions->CleanUp = CleanUp64; + + return TRUE; +} + + +// +// Header by Index functions +// +STATIC +Elf_Shdr* +GetShdrByIndex ( + UINT32 Num + ) +{ + if (Num >= mEhdr->e_shnum) { + Error (NULL, 0, 3000, "Invalid", "GetShdrByIndex: Index %u is too high.", Num); + exit(EXIT_FAILURE); + } + + return (Elf_Shdr*)((UINT8*)mShdrBase + Num * mEhdr->e_shentsize); +} + +STATIC +UINT32 +CoffAlign ( + UINT32 Offset + ) +{ + return (Offset + mCoffAlignment - 1) & ~(mCoffAlignment - 1); +} + +STATIC +UINT32 +DebugRvaAlign ( + UINT32 Offset + ) +{ + return (Offset + 3) & ~3; +} + +// +// filter functions +// +STATIC +BOOLEAN +IsTextShdr ( + Elf_Shdr *Shdr + ) +{ + return (BOOLEAN) ((Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC); +} + +STATIC +BOOLEAN +IsHiiRsrcShdr ( + Elf_Shdr *Shdr + ) +{ + Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx); + + return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_HII_SECTION_NAME) == 0); +} + +STATIC +BOOLEAN +IsDataShdr ( + Elf_Shdr *Shdr + ) +{ + if (IsHiiRsrcShdr(Shdr)) { + return FALSE; + } + return (BOOLEAN) (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE); +} + +STATIC +BOOLEAN +IsStrtabShdr ( + Elf_Shdr *Shdr + ) +{ + Elf_Shdr *Namedr = GetShdrByIndex(mEhdr->e_shstrndx); + + return (BOOLEAN) (strcmp((CHAR8*)mEhdr + Namedr->sh_offset + Shdr->sh_name, ELF_STRTAB_SECTION_NAME) == 0); +} + +STATIC +Elf_Shdr * +FindStrtabShdr ( + VOID + ) +{ + UINT32 i; + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (IsStrtabShdr(shdr)) { + return shdr; + } + } + return NULL; +} + +STATIC +const UINT8 * +GetSymName ( + Elf_Sym *Sym + ) +{ + Elf_Shdr *StrtabShdr; + UINT8 *StrtabContents; + BOOLEAN foundEnd; + UINT32 i; + + if (Sym->st_name == 0) { + return NULL; + } + + StrtabShdr = FindStrtabShdr(); + if (StrtabShdr == NULL) { + return NULL; + } + + assert(Sym->st_name < StrtabShdr->sh_size); + + StrtabContents = (UINT8*)mEhdr + StrtabShdr->sh_offset; + + foundEnd = FALSE; + for (i= Sym->st_name; (i < StrtabShdr->sh_size) && !foundEnd; i++) { + foundEnd = (BOOLEAN)(StrtabContents[i] == 0); + } + assert(foundEnd); + + return StrtabContents + Sym->st_name; +} + +// +// Find the ELF section hosting the GOT from an ELF Rva +// of a single GOT entry. Normally, GOT is placed in +// ELF .text section, so assume once we find in which +// section the GOT is, all GOT entries are there, and +// just verify this. +// +STATIC +VOID +FindElfGOTSectionFromGOTEntryElfRva ( + Elf64_Addr GOTEntryElfRva + ) +{ + UINT32 i; + if (mGOTShdr != NULL) { + if (GOTEntryElfRva >= mGOTShdr->sh_addr && + GOTEntryElfRva < mGOTShdr->sh_addr + mGOTShdr->sh_size) { + return; + } + Error (NULL, 0, 3000, "Unsupported", "FindElfGOTSectionFromGOTEntryElfRva: GOT entries found in multiple sections."); + exit(EXIT_FAILURE); + } + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (GOTEntryElfRva >= shdr->sh_addr && + GOTEntryElfRva < shdr->sh_addr + shdr->sh_size) { + mGOTShdr = shdr; + mGOTShindex = i; + return; + } + } + Error (NULL, 0, 3000, "Invalid", "FindElfGOTSectionFromGOTEntryElfRva: ElfRva 0x%016LX for GOT entry not found in any section.", GOTEntryElfRva); + exit(EXIT_FAILURE); +} + +// +// Stores locations of GOT entries in COFF image. +// Returns TRUE if GOT entry is new. +// Simple implementation as number of GOT +// entries is expected to be low. +// + +STATIC +BOOLEAN +AccumulateCoffGOTEntries ( + UINT32 GOTCoffEntry + ) +{ + UINT32 i; + if (mGOTCoffEntries != NULL) { + for (i = 0; i < mGOTNumCoffEntries; i++) { + if (mGOTCoffEntries[i] == GOTCoffEntry) { + return FALSE; + } + } + } + if (mGOTCoffEntries == NULL) { + mGOTCoffEntries = (UINT32*)malloc(5 * sizeof *mGOTCoffEntries); + if (mGOTCoffEntries == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + } + assert (mGOTCoffEntries != NULL); + mGOTMaxCoffEntries = 5; + mGOTNumCoffEntries = 0; + } else if (mGOTNumCoffEntries == mGOTMaxCoffEntries) { + mGOTCoffEntries = (UINT32*)realloc(mGOTCoffEntries, 2 * mGOTMaxCoffEntries * sizeof *mGOTCoffEntries); + if (mGOTCoffEntries == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + } + assert (mGOTCoffEntries != NULL); + mGOTMaxCoffEntries += mGOTMaxCoffEntries; + } + mGOTCoffEntries[mGOTNumCoffEntries++] = GOTCoffEntry; + return TRUE; +} + +// +// 32-bit Unsigned integer comparator for qsort. +// +STATIC +int +UINT32Comparator ( + const void* lhs, + const void* rhs + ) +{ + if (*(const UINT32*)lhs < *(const UINT32*)rhs) { + return -1; + } + return *(const UINT32*)lhs > *(const UINT32*)rhs; +} + +// +// Emit accumulated Coff GOT entry relocations into +// Coff image. This function performs its job +// once and then releases the entry list, so +// it can safely be called multiple times. +// +STATIC +VOID +EmitGOTRelocations ( + VOID + ) +{ + UINT32 i; + if (mGOTCoffEntries == NULL) { + return; + } + // + // Emit Coff relocations with Rvas ordered. + // + qsort( + mGOTCoffEntries, + mGOTNumCoffEntries, + sizeof *mGOTCoffEntries, + UINT32Comparator); + for (i = 0; i < mGOTNumCoffEntries; i++) { + VerboseMsg ("EFI_IMAGE_REL_BASED_DIR64 Offset: 0x%08X", mGOTCoffEntries[i]); + CoffAddFixup( + mGOTCoffEntries[i], + EFI_IMAGE_REL_BASED_DIR64); + } + free(mGOTCoffEntries); + mGOTCoffEntries = NULL; + mGOTMaxCoffEntries = 0; + mGOTNumCoffEntries = 0; +} +// +// RISC-V 64 specific Elf WriteSection function. +// +STATIC +VOID +WriteSectionRiscV64 ( + Elf_Rela *Rel, + UINT8 *Targ, + Elf_Shdr *SymShdr, + Elf_Sym *Sym + ) +{ + UINT32 Value; + UINT32 Value2; + + switch (ELF_R_TYPE(Rel->r_info)) { + case R_RISCV_NONE: + break; + + case R_RISCV_32: + *(UINT32 *)Targ = (UINT32)((UINT64)(*(UINT32 *)Targ) - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]); + break; + + case R_RISCV_64: + *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + break; + + case R_RISCV_HI20: + mRiscVPass1Targ = Targ; + mRiscVPass1Sym = SymShdr; + mRiscVPass1SymSecIndex = Sym->st_shndx; + break; + + case R_RISCV_LO12_I: + if (mRiscVPass1Sym == SymShdr && mRiscVPass1Targ != NULL && mRiscVPass1SymSecIndex == Sym->st_shndx && mRiscVPass1SymSecIndex != 0) { + Value = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20) << 12); + Value2 = (UINT32)(RV_X(*(UINT32 *)Targ, 20, 12)); + if (Value2 & (RISCV_IMM_REACH/2)) { + Value2 |= ~(RISCV_IMM_REACH-1); + } + Value += Value2; + Value = Value - (UINT32)SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + Value2 = RISCV_CONST_HIGH_PART (Value); + *(UINT32 *)mRiscVPass1Targ = (RV_X (Value2, 12, 20) << 12) | \ + (RV_X (*(UINT32 *)mRiscVPass1Targ, 0, 12)); + *(UINT32 *)Targ = (RV_X (Value, 0, 12) << 20) | \ + (RV_X (*(UINT32 *)Targ, 0, 20)); + } + mRiscVPass1Sym = NULL; + mRiscVPass1Targ = NULL; + mRiscVPass1SymSecIndex = 0; + break; + + case R_RISCV_LO12_S: + if (mRiscVPass1Sym == SymShdr && mRiscVPass1Targ != NULL && mRiscVPass1SymSecIndex == Sym->st_shndx && mRiscVPass1SymSecIndex != 0) { + Value = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20) << 12); + Value2 = (UINT32)(RV_X(*(UINT32 *)Targ, 7, 5) | (RV_X(*(UINT32 *)Targ, 25, 7) << 5)); + if (Value2 & (RISCV_IMM_REACH/2)) { + Value2 |= ~(RISCV_IMM_REACH-1); + } + Value += Value2; + Value = Value - (UINT32)SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + Value2 = RISCV_CONST_HIGH_PART (Value); + *(UINT32 *)mRiscVPass1Targ = (RV_X (Value2, 12, 20) << 12) | \ + (RV_X (*(UINT32 *)mRiscVPass1Targ, 0, 12)); + Value2 = *(UINT32 *)Targ & 0x01fff07f; + Value &= RISCV_IMM_REACH - 1; + *(UINT32 *)Targ = Value2 | (UINT32)(((RV_X(Value, 0, 5) << 7) | (RV_X(Value, 5, 7) << 25))); + } + mRiscVPass1Sym = NULL; + mRiscVPass1Targ = NULL; + mRiscVPass1SymSecIndex = 0; + break; + + case R_RISCV_PCREL_HI20: + mRiscVPass1Targ = Targ; + mRiscVPass1Sym = SymShdr; + mRiscVPass1SymSecIndex = Sym->st_shndx; + + Value = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20)); + break; + + case R_RISCV_PCREL_LO12_I: + if (mRiscVPass1Targ != NULL && mRiscVPass1Sym != NULL && mRiscVPass1SymSecIndex != 0) { + int i; + Value2 = (UINT32)(RV_X(*(UINT32 *)mRiscVPass1Targ, 12, 20)); + Value = (UINT32)(RV_X(*(UINT32 *)Targ, 20, 12)); + if(Value & (RISCV_IMM_REACH/2)) { + Value |= ~(RISCV_IMM_REACH-1); + } + Value = Value - (UINT32)mRiscVPass1Sym->sh_addr + mCoffSectionsOffset[mRiscVPass1SymSecIndex]; + if(-2048 > (INT32)Value) { + i = (((INT32)Value * -1) / 4096); + Value2 -= i; + Value += 4096 * i; + if(-2048 > (INT32)Value) { + Value2 -= 1; + Value += 4096; + } + } + else if( 2047 < (INT32)Value) { + i = (Value / 4096); + Value2 += i; + Value -= 4096 * i; + if(2047 < (INT32)Value) { + Value2 += 1; + Value -= 4096; + } + } + + *(UINT32 *)Targ = (RV_X(Value, 0, 12) << 20) | (RV_X(*(UINT32*)Targ, 0, 20)); + *(UINT32 *)mRiscVPass1Targ = (RV_X(Value2, 0, 20)<<12) | (RV_X(*(UINT32 *)mRiscVPass1Targ, 0, 12)); + } + mRiscVPass1Sym = NULL; + mRiscVPass1Targ = NULL; + mRiscVPass1SymSecIndex = 0; + break; + + case R_RISCV_ADD64: + case R_RISCV_SUB64: + case R_RISCV_ADD32: + case R_RISCV_SUB32: + case R_RISCV_BRANCH: + case R_RISCV_JAL: + case R_RISCV_GPREL_I: + case R_RISCV_GPREL_S: + case R_RISCV_CALL: + case R_RISCV_RVC_BRANCH: + case R_RISCV_RVC_JUMP: + case R_RISCV_RELAX: + case R_RISCV_SUB6: + case R_RISCV_SET6: + case R_RISCV_SET8: + case R_RISCV_SET16: + case R_RISCV_SET32: + break; + + default: + Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s unsupported ELF EM_RISCV64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } +} + +// +// Elf functions interface implementation +// + +STATIC +VOID +ScanSections64 ( + VOID + ) +{ + UINT32 i; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; + UINT32 CoffEntry; + UINT32 SectionCount; + BOOLEAN FoundSection; + + CoffEntry = 0; + mCoffOffset = 0; + + // + // Coff file start with a DOS header. + // + mCoffOffset = sizeof(EFI_IMAGE_DOS_HEADER) + 0x40; + mNtHdrOffset = mCoffOffset; + switch (mEhdr->e_machine) { + case EM_X86_64: + case EM_AARCH64: + case EM_RISCV64: + mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS64); + break; + default: + VerboseMsg ("%s unknown e_machine type %hu. Assume X64", mInImageName, mEhdr->e_machine); + mCoffOffset += sizeof (EFI_IMAGE_NT_HEADERS64); + break; + } + + mTableOffset = mCoffOffset; + mCoffOffset += mCoffNbrSections * sizeof(EFI_IMAGE_SECTION_HEADER); + + // + // Set mCoffAlignment to the maximum alignment of the input sections + // we care about + // + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (shdr->sh_addralign <= mCoffAlignment) { + continue; + } + if (IsTextShdr(shdr) || IsDataShdr(shdr) || IsHiiRsrcShdr(shdr)) { + mCoffAlignment = (UINT32)shdr->sh_addralign; + } + } + + // + // Check if mCoffAlignment is larger than MAX_COFF_ALIGNMENT + // + if (mCoffAlignment > MAX_COFF_ALIGNMENT) { + Error (NULL, 0, 3000, "Invalid", "Section alignment is larger than MAX_COFF_ALIGNMENT."); + assert (FALSE); + } + + + // + // Move the PE/COFF header right before the first section. This will help us + // save space when converting to TE. + // + if (mCoffAlignment > mCoffOffset) { + mNtHdrOffset += mCoffAlignment - mCoffOffset; + mTableOffset += mCoffAlignment - mCoffOffset; + mCoffOffset = mCoffAlignment; + } + + // + // First text sections. + // + mCoffOffset = CoffAlign(mCoffOffset); + mTextOffset = mCoffOffset; + FoundSection = FALSE; + SectionCount = 0; + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (IsTextShdr(shdr)) { + if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) { + // the alignment field is valid + if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) { + // if the section address is aligned we must align PE/COFF + mCoffOffset = (UINT32) ((mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1)); + } else { +#ifdef VBOX + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment. sec#%i addr=%#llx align=%#llx", i, shdr->sh_addr, shdr->sh_addralign); +#else + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment."); +#endif + } + } + + /* Relocate entry. */ + if ((mEhdr->e_entry >= shdr->sh_addr) && + (mEhdr->e_entry < shdr->sh_addr + shdr->sh_size)) { + CoffEntry = (UINT32) (mCoffOffset + mEhdr->e_entry - shdr->sh_addr); + } + + // + // Set mTextOffset with the offset of the first '.text' section + // + if (!FoundSection) { + mTextOffset = mCoffOffset; + FoundSection = TRUE; + } + + mCoffSectionsOffset[i] = mCoffOffset; + mCoffOffset += (UINT32) shdr->sh_size; + SectionCount ++; + } + } + + if (!FoundSection) { + Error (NULL, 0, 3000, "Invalid", "Did not find any '.text' section."); + assert (FALSE); + } + + mDebugOffset = DebugRvaAlign(mCoffOffset); + mCoffOffset = CoffAlign(mCoffOffset); + + if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) { + Warning (NULL, 0, 0, NULL, "Multiple sections in %s are merged into 1 text section. Source level debug might not work correctly.", mInImageName); + } + + // + // Then data sections. + // + mDataOffset = mCoffOffset; + FoundSection = FALSE; + SectionCount = 0; + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (IsDataShdr(shdr)) { + if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) { + // the alignment field is valid + if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) { + // if the section address is aligned we must align PE/COFF + mCoffOffset = (UINT32) ((mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1)); + } else { +#ifdef VBOX + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment. sec#%i addr=%#llx align=%#llx", i, shdr->sh_addr, shdr->sh_addralign); +#else + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment."); +#endif + } + } + + // + // Set mDataOffset with the offset of the first '.data' section + // + if (!FoundSection) { + mDataOffset = mCoffOffset; + FoundSection = TRUE; + } + mCoffSectionsOffset[i] = mCoffOffset; + mCoffOffset += (UINT32) shdr->sh_size; + SectionCount ++; + } + } + + // + // Make room for .debug data in .data (or .text if .data is empty) instead of + // putting it in a section of its own. This is explicitly allowed by the + // PE/COFF spec, and prevents bloat in the binary when using large values for + // section alignment. + // + if (SectionCount > 0) { + mDebugOffset = DebugRvaAlign(mCoffOffset); + } + mCoffOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY) + + sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + + strlen(mInImageName) + 1; + + mCoffOffset = CoffAlign(mCoffOffset); + if (SectionCount == 0) { + mDataOffset = mCoffOffset; + } + + if (SectionCount > 1 && mOutImageType == FW_EFI_IMAGE) { + Warning (NULL, 0, 0, NULL, "Multiple sections in %s are merged into 1 data section. Source level debug might not work correctly.", mInImageName); + } + + // + // The HII resource sections. + // + mHiiRsrcOffset = mCoffOffset; + for (i = 0; i < mEhdr->e_shnum; i++) { + Elf_Shdr *shdr = GetShdrByIndex(i); + if (IsHiiRsrcShdr(shdr)) { + if ((shdr->sh_addralign != 0) && (shdr->sh_addralign != 1)) { + // the alignment field is valid + if ((shdr->sh_addr & (shdr->sh_addralign - 1)) == 0) { + // if the section address is aligned we must align PE/COFF + mCoffOffset = (UINT32) ((mCoffOffset + shdr->sh_addralign - 1) & ~(shdr->sh_addralign - 1)); + } else { +#ifdef VBOX + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment. sec#%i addr=%#llx align=%#llx", i, shdr->sh_addr, shdr->sh_addralign); +#else + Error (NULL, 0, 3000, "Invalid", "Section address not aligned to its own alignment."); +#endif + } + } + if (shdr->sh_size != 0) { + mHiiRsrcOffset = mCoffOffset; + mCoffSectionsOffset[i] = mCoffOffset; + mCoffOffset += (UINT32) shdr->sh_size; + mCoffOffset = CoffAlign(mCoffOffset); + SetHiiResourceHeader ((UINT8*) mEhdr + shdr->sh_offset, mHiiRsrcOffset); + } + break; + } + } + + mRelocOffset = mCoffOffset; + + // + // Allocate base Coff file. Will be expanded later for relocations. + // + mCoffFile = (UINT8 *)malloc(mCoffOffset); + if (mCoffFile == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + } + assert (mCoffFile != NULL); + memset(mCoffFile, 0, mCoffOffset); + + // + // Fill headers. + // + DosHdr = (EFI_IMAGE_DOS_HEADER *)mCoffFile; + DosHdr->e_magic = EFI_IMAGE_DOS_SIGNATURE; + DosHdr->e_lfanew = mNtHdrOffset; + + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION*)(mCoffFile + mNtHdrOffset); + + NtHdr->Pe32Plus.Signature = EFI_IMAGE_NT_SIGNATURE; + + switch (mEhdr->e_machine) { + case EM_X86_64: + NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_X64; + NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + break; + case EM_AARCH64: + NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_AARCH64; + NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + break; + case EM_RISCV64: + NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_RISCV64; + NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + break; + + default: + VerboseMsg ("%s unknown e_machine type. Assume X64", (UINTN)mEhdr->e_machine); + NtHdr->Pe32Plus.FileHeader.Machine = EFI_IMAGE_MACHINE_X64; + NtHdr->Pe32Plus.OptionalHeader.Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; + } + + NtHdr->Pe32Plus.FileHeader.NumberOfSections = mCoffNbrSections; + NtHdr->Pe32Plus.FileHeader.TimeDateStamp = (UINT32) time(NULL); + mImageTimeStamp = NtHdr->Pe32Plus.FileHeader.TimeDateStamp; + NtHdr->Pe32Plus.FileHeader.PointerToSymbolTable = 0; + NtHdr->Pe32Plus.FileHeader.NumberOfSymbols = 0; + NtHdr->Pe32Plus.FileHeader.SizeOfOptionalHeader = sizeof(NtHdr->Pe32Plus.OptionalHeader); + NtHdr->Pe32Plus.FileHeader.Characteristics = EFI_IMAGE_FILE_EXECUTABLE_IMAGE + | EFI_IMAGE_FILE_LINE_NUMS_STRIPPED + | EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED + | EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE; + + NtHdr->Pe32Plus.OptionalHeader.SizeOfCode = mDataOffset - mTextOffset; + NtHdr->Pe32Plus.OptionalHeader.SizeOfInitializedData = mRelocOffset - mDataOffset; + NtHdr->Pe32Plus.OptionalHeader.SizeOfUninitializedData = 0; + NtHdr->Pe32Plus.OptionalHeader.AddressOfEntryPoint = CoffEntry; + + NtHdr->Pe32Plus.OptionalHeader.BaseOfCode = mTextOffset; + + NtHdr->Pe32Plus.OptionalHeader.ImageBase = 0; + NtHdr->Pe32Plus.OptionalHeader.SectionAlignment = mCoffAlignment; + NtHdr->Pe32Plus.OptionalHeader.FileAlignment = mCoffAlignment; + NtHdr->Pe32Plus.OptionalHeader.SizeOfImage = 0; + + NtHdr->Pe32Plus.OptionalHeader.SizeOfHeaders = mTextOffset; + NtHdr->Pe32Plus.OptionalHeader.NumberOfRvaAndSizes = EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES; + + // + // Section headers. + // + if ((mDataOffset - mTextOffset) > 0) { + CreateSectionHeader (".text", mTextOffset, mDataOffset - mTextOffset, + EFI_IMAGE_SCN_CNT_CODE + | EFI_IMAGE_SCN_MEM_EXECUTE + | EFI_IMAGE_SCN_MEM_READ); + } else { + // Don't make a section of size 0. + NtHdr->Pe32Plus.FileHeader.NumberOfSections--; + } + + if ((mHiiRsrcOffset - mDataOffset) > 0) { + CreateSectionHeader (".data", mDataOffset, mHiiRsrcOffset - mDataOffset, + EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + | EFI_IMAGE_SCN_MEM_WRITE + | EFI_IMAGE_SCN_MEM_READ); + } else { + // Don't make a section of size 0. + NtHdr->Pe32Plus.FileHeader.NumberOfSections--; + } + + if ((mRelocOffset - mHiiRsrcOffset) > 0) { + CreateSectionHeader (".rsrc", mHiiRsrcOffset, mRelocOffset - mHiiRsrcOffset, + EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + | EFI_IMAGE_SCN_MEM_READ); + + NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = mRelocOffset - mHiiRsrcOffset; + NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = mHiiRsrcOffset; + } else { + // Don't make a section of size 0. + NtHdr->Pe32Plus.FileHeader.NumberOfSections--; + } + +} + +STATIC +BOOLEAN +WriteSections64 ( + SECTION_FILTER_TYPES FilterType + ) +{ + UINT32 Idx; + Elf_Shdr *SecShdr; + UINT32 SecOffset; + BOOLEAN (*Filter)(Elf_Shdr *); + Elf64_Addr GOTEntryRva; + + // + // Initialize filter pointer + // + switch (FilterType) { + case SECTION_TEXT: + Filter = IsTextShdr; + break; + case SECTION_HII: + Filter = IsHiiRsrcShdr; + break; + case SECTION_DATA: + Filter = IsDataShdr; + break; + default: + return FALSE; + } + + // + // First: copy sections. + // + for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) { + Elf_Shdr *Shdr = GetShdrByIndex(Idx); + if ((*Filter)(Shdr)) { + switch (Shdr->sh_type) { + case SHT_PROGBITS: + /* Copy. */ + if (Shdr->sh_offset + Shdr->sh_size > mFileBufferSize) { + return FALSE; + } + memcpy(mCoffFile + mCoffSectionsOffset[Idx], + (UINT8*)mEhdr + Shdr->sh_offset, + (size_t) Shdr->sh_size); + break; + + case SHT_NOBITS: + memset(mCoffFile + mCoffSectionsOffset[Idx], 0, (size_t) Shdr->sh_size); + break; + + default: + // + // Ignore for unknown section type. + // + VerboseMsg ("%s unknown section type %x. We ignore this unknown section type.", mInImageName, (unsigned)Shdr->sh_type); + break; + } + } + } + + // + // Second: apply relocations. + // + VerboseMsg ("Applying Relocations..."); + for (Idx = 0; Idx < mEhdr->e_shnum; Idx++) { + // + // Determine if this is a relocation section. + // + Elf_Shdr *RelShdr = GetShdrByIndex(Idx); + if ((RelShdr->sh_type != SHT_REL) && (RelShdr->sh_type != SHT_RELA)) { + continue; + } + + // + // If this is a ET_DYN (PIE) executable, we will encounter a dynamic SHT_RELA + // section that applies to the entire binary, and which will have its section + // index set to #0 (which is a NULL section with the SHF_ALLOC bit cleared). + // + // In the absence of GOT based relocations, + // this RELA section will contain redundant R_xxx_RELATIVE relocations, one + // for every R_xxx_xx64 relocation appearing in the per-section RELA sections. + // (i.e., .rela.text and .rela.data) + // + if (RelShdr->sh_info == 0) { + continue; + } + + // + // Relocation section found. Now extract section information that the relocations + // apply to in the ELF data and the new COFF data. + // + SecShdr = GetShdrByIndex(RelShdr->sh_info); + SecOffset = mCoffSectionsOffset[RelShdr->sh_info]; + + // + // Only process relocations for the current filter type. + // + if (RelShdr->sh_type == SHT_RELA && (*Filter)(SecShdr)) { + UINT64 RelIdx; + + // + // Determine the symbol table referenced by the relocation data. + // + Elf_Shdr *SymtabShdr = GetShdrByIndex(RelShdr->sh_link); + UINT8 *Symtab = (UINT8*)mEhdr + SymtabShdr->sh_offset; + + // + // Process all relocation entries for this section. + // + for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += (UINT32) RelShdr->sh_entsize) { + + // + // Set pointer to relocation entry + // + Elf_Rela *Rel = (Elf_Rela *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx); + + // + // Set pointer to symbol table entry associated with the relocation entry. + // + Elf_Sym *Sym = (Elf_Sym *)(Symtab + ELF_R_SYM(Rel->r_info) * SymtabShdr->sh_entsize); + + Elf_Shdr *SymShdr; + UINT8 *Targ; + + // + // Check section header index found in symbol table and get the section + // header location. + // + if (Sym->st_shndx == SHN_UNDEF + || Sym->st_shndx >= mEhdr->e_shnum) { + const UINT8 *SymName = GetSymName(Sym); + if (SymName == NULL) { + SymName = (const UINT8 *)""; + } + + // + // Skip error on EM_RISCV64 becasue no symble name is built + // from RISC-V toolchain. + // + if (mEhdr->e_machine != EM_RISCV64) { + Error (NULL, 0, 3000, "Invalid", + "%s: Bad definition for symbol '%s'@%#llx or unsupported symbol type. " + "For example, absolute and undefined symbols are not supported.", + mInImageName, SymName, Sym->st_value); + + exit(EXIT_FAILURE); + } + } + SymShdr = GetShdrByIndex(Sym->st_shndx); + + // + // Convert the relocation data to a pointer into the coff file. + // + // Note: + // r_offset is the virtual address of the storage unit to be relocated. + // sh_addr is the virtual address for the base of the section. + // + // r_offset in a memory address. + // Convert it to a pointer in the coff file. + // + Targ = mCoffFile + SecOffset + (Rel->r_offset - SecShdr->sh_addr); + + // + // Determine how to handle each relocation type based on the machine type. + // + if (mEhdr->e_machine == EM_X86_64) { + switch (ELF_R_TYPE(Rel->r_info)) { + case R_X86_64_NONE: + break; + case R_X86_64_64: + // + // Absolute relocation. + // + VerboseMsg ("R_X86_64_64"); + VerboseMsg ("Offset: 0x%08X, Addend: 0x%016LX", + (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), + *(UINT64 *)Targ); + *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + VerboseMsg ("Relocation: 0x%016LX", *(UINT64*)Targ); + break; + case R_X86_64_32: + VerboseMsg ("R_X86_64_32"); + VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", + (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), + *(UINT32 *)Targ); + *(UINT32 *)Targ = (UINT32)((UINT64)(*(UINT32 *)Targ) - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]); + VerboseMsg ("Relocation: 0x%08X", *(UINT32*)Targ); + break; + case R_X86_64_32S: + VerboseMsg ("R_X86_64_32S"); + VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", + (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), + *(UINT32 *)Targ); + *(INT32 *)Targ = (INT32)((INT64)(*(INT32 *)Targ) - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]); + VerboseMsg ("Relocation: 0x%08X", *(UINT32*)Targ); + break; + + case R_X86_64_PLT32: + // + // Treat R_X86_64_PLT32 relocations as R_X86_64_PC32: this is + // possible since we know all code symbol references resolve to + // definitions in the same module (UEFI has no shared libraries), + // and so there is never a reason to jump via a PLT entry, + // allowing us to resolve the reference using the symbol directly. + // + VerboseMsg ("Treating R_X86_64_PLT32 as R_X86_64_PC32 ..."); + /* fall through */ + case R_X86_64_PC32: + // + // Relative relocation: Symbol - Ip + Addend + // + VerboseMsg ("R_X86_64_PC32"); + VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", + (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), + *(UINT32 *)Targ); + *(UINT32 *)Targ = (UINT32) (*(UINT32 *)Targ + + (mCoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr) + - (SecOffset - SecShdr->sh_addr)); + VerboseMsg ("Relocation: 0x%08X", *(UINT32 *)Targ); + break; + case R_X86_64_GOTPCREL: + case R_X86_64_GOTPCRELX: + case R_X86_64_REX_GOTPCRELX: + VerboseMsg ("R_X86_64_GOTPCREL family"); + VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", + (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), + *(UINT32 *)Targ); + GOTEntryRva = Rel->r_offset - Rel->r_addend + *(INT32 *)Targ; + FindElfGOTSectionFromGOTEntryElfRva(GOTEntryRva); + *(UINT32 *)Targ = (UINT32) (*(UINT32 *)Targ + + (mCoffSectionsOffset[mGOTShindex] - mGOTShdr->sh_addr) + - (SecOffset - SecShdr->sh_addr)); + VerboseMsg ("Relocation: 0x%08X", *(UINT32 *)Targ); + GOTEntryRva += (mCoffSectionsOffset[mGOTShindex] - mGOTShdr->sh_addr); // ELF Rva -> COFF Rva + if (AccumulateCoffGOTEntries((UINT32)GOTEntryRva)) { + // + // Relocate GOT entry if it's the first time we run into it + // + Targ = mCoffFile + GOTEntryRva; + // + // Limitation: The following three statements assume memory + // at *Targ is valid because the section containing the GOT + // has already been copied from the ELF image to the Coff image. + // This pre-condition presently holds because the GOT is placed + // in section .text, and the ELF text sections are all copied + // prior to reaching this point. + // If the pre-condition is violated in the future, this fixup + // either needs to be deferred after the GOT section is copied + // to the Coff image, or the fixup should be performed on the + // source Elf image instead of the destination Coff image. + // + VerboseMsg ("Offset: 0x%08X, Addend: 0x%016LX", + (UINT32)GOTEntryRva, + *(UINT64 *)Targ); + *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + VerboseMsg ("Relocation: 0x%016LX", *(UINT64*)Targ); + } + break; + default: + Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_X86_64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } + } else if (mEhdr->e_machine == EM_AARCH64) { + + switch (ELF_R_TYPE(Rel->r_info)) { + INT64 Offset; + + case R_AARCH64_LD64_GOT_LO12_NC: + // + // Convert into an ADD instruction - see R_AARCH64_ADR_GOT_PAGE below. + // + *(UINT32 *)Targ &= 0x3ff; + *(UINT32 *)Targ |= 0x91000000 | ((Sym->st_value & 0xfff) << 10); + break; + + case R_AARCH64_ADR_GOT_PAGE: + // + // This relocation points to the GOT entry that contains the absolute + // address of the symbol we are referring to. Since EDK2 only uses + // fully linked binaries, we can avoid the indirection, and simply + // refer to the symbol directly. This implies having to patch the + // subsequent LDR instruction (covered by a R_AARCH64_LD64_GOT_LO12_NC + // relocation) into an ADD instruction - this is handled above. + // + Offset = (Sym->st_value - (Rel->r_offset & ~0xfff)) >> 12; + + *(UINT32 *)Targ &= 0x9000001f; + *(UINT32 *)Targ |= ((Offset & 0x1ffffc) << (5 - 2)) | ((Offset & 0x3) << 29); + + /* fall through */ + + case R_AARCH64_ADR_PREL_PG_HI21: + // + // In order to handle Cortex-A53 erratum #843419, the LD linker may + // convert ADRP instructions into ADR instructions, but without + // updating the static relocation type, and so we may end up here + // while the instruction in question is actually ADR. So let's + // just disregard it: the section offset check we apply below to + // ADR instructions will trigger for its R_AARCH64_xxx_ABS_LO12_NC + // companion instruction as well, so it is safe to omit it here. + // + if ((*(UINT32 *)Targ & BIT31) == 0) { + break; + } + + // + // AArch64 PG_H21 relocations are typically paired with ABS_LO12 + // relocations, where a PC-relative reference with +/- 4 GB range is + // split into a relative high part and an absolute low part. Since + // the absolute low part represents the offset into a 4 KB page, we + // either have to convert the ADRP into an ADR instruction, or we + // need to use a section alignment of at least 4 KB, so that the + // binary appears at a correct offset at runtime. In any case, we + // have to make sure that the 4 KB relative offsets of both the + // section containing the reference as well as the section to which + // it refers have not been changed during PE/COFF conversion (i.e., + // in ScanSections64() above). + // + if (mCoffAlignment < 0x1000) { + // + // Attempt to convert the ADRP into an ADR instruction. + // This is only possible if the symbol is within +/- 1 MB. + // + + // Decode the ADRP instruction + Offset = (INT32)((*(UINT32 *)Targ & 0xffffe0) << 8); + Offset = (Offset << (6 - 5)) | ((*(UINT32 *)Targ & 0x60000000) >> (29 - 12)); + + // + // ADRP offset is relative to the previous page boundary, + // whereas ADR offset is relative to the instruction itself. + // So fix up the offset so it points to the page containing + // the symbol. + // + Offset -= (UINTN)(Targ - mCoffFile) & 0xfff; + + if (Offset < -0x100000 || Offset > 0xfffff) { + Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s due to its size (> 1 MB), this module requires 4 KB section alignment.", + mInImageName); + break; + } + + // Re-encode the offset as an ADR instruction + *(UINT32 *)Targ &= 0x1000001f; + *(UINT32 *)Targ |= ((Offset & 0x1ffffc) << (5 - 2)) | ((Offset & 0x3) << 29); + } + /* fall through */ + + case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_LDST8_ABS_LO12_NC: + case R_AARCH64_LDST16_ABS_LO12_NC: + case R_AARCH64_LDST32_ABS_LO12_NC: + case R_AARCH64_LDST64_ABS_LO12_NC: + case R_AARCH64_LDST128_ABS_LO12_NC: + if (((SecShdr->sh_addr ^ SecOffset) & 0xfff) != 0 || + ((SymShdr->sh_addr ^ mCoffSectionsOffset[Sym->st_shndx]) & 0xfff) != 0) { + Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s AARCH64 small code model requires identical ELF and PE/COFF section offsets modulo 4 KB.", + mInImageName); + break; + } + /* fall through */ + + case R_AARCH64_ADR_PREL_LO21: + case R_AARCH64_CONDBR19: + case R_AARCH64_LD_PREL_LO19: + case R_AARCH64_CALL26: + case R_AARCH64_JUMP26: + case R_AARCH64_PREL64: + case R_AARCH64_PREL32: + case R_AARCH64_PREL16: + // + // The GCC toolchains (i.e., binutils) may corrupt section relative + // relocations when emitting relocation sections into fully linked + // binaries. More specifically, they tend to fail to take into + // account the fact that a '.rodata + XXX' relocation needs to have + // its addend recalculated once .rodata is merged into the .text + // section, and the relocation emitted into the .rela.text section. + // + // We cannot really recover from this loss of information, so the + // only workaround is to prevent having to recalculate any relative + // relocations at all, by using a linker script that ensures that + // the offset between the Place and the Symbol is the same in both + // the ELF and the PE/COFF versions of the binary. + // + if ((SymShdr->sh_addr - SecShdr->sh_addr) != + (mCoffSectionsOffset[Sym->st_shndx] - SecOffset)) { + Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s AARCH64 relative relocations require identical ELF and PE/COFF section offsets", + mInImageName); + } + break; + + // Absolute relocations. + case R_AARCH64_ABS64: + *(UINT64 *)Targ = *(UINT64 *)Targ - SymShdr->sh_addr + mCoffSectionsOffset[Sym->st_shndx]; + break; + + default: + Error (NULL, 0, 3000, "Invalid", "WriteSections64(): %s unsupported ELF EM_AARCH64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } + } else if (mEhdr->e_machine == EM_RISCV64) { + // + // Write section for RISC-V 64 architecture. + // + WriteSectionRiscV64 (Rel, Targ, SymShdr, Sym); + } else { + Error (NULL, 0, 3000, "Invalid", "Not a supported machine type"); + } + } + } + } + + return TRUE; +} + +STATIC +VOID +WriteRelocations64 ( + VOID + ) +{ + UINT32 Index; + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; + EFI_IMAGE_DATA_DIRECTORY *Dir; + UINT32 RiscVRelType; + + for (Index = 0; Index < mEhdr->e_shnum; Index++) { + Elf_Shdr *RelShdr = GetShdrByIndex(Index); + if ((RelShdr->sh_type == SHT_REL) || (RelShdr->sh_type == SHT_RELA)) { + Elf_Shdr *SecShdr = GetShdrByIndex (RelShdr->sh_info); + if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) { + UINT64 RelIdx; + + for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) { + Elf_Rela *Rel = (Elf_Rela *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx); + + if (mEhdr->e_machine == EM_X86_64) { + switch (ELF_R_TYPE(Rel->r_info)) { + case R_X86_64_NONE: + case R_X86_64_PC32: + case R_X86_64_PLT32: + case R_X86_64_GOTPCREL: + case R_X86_64_GOTPCRELX: + case R_X86_64_REX_GOTPCRELX: + break; + case R_X86_64_64: + VerboseMsg ("EFI_IMAGE_REL_BASED_DIR64 Offset: 0x%08X", + mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr)); + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_DIR64); + break; + // + // R_X86_64_32 and R_X86_64_32S are ELF64 relocations emitted when using + // the SYSV X64 ABI small non-position-independent code model. + // R_X86_64_32 is used for unsigned 32-bit immediates with a 32-bit operand + // size. The value is either not extended, or zero-extended to 64 bits. + // R_X86_64_32S is used for either signed 32-bit non-rip-relative displacements + // or signed 32-bit immediates with a 64-bit operand size. The value is + // sign-extended to 64 bits. + // EFI_IMAGE_REL_BASED_HIGHLOW is a PE relocation that uses 32-bit arithmetic + // for rebasing an image. + // EFI PE binaries declare themselves EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE and + // may load above 2GB. If an EFI PE binary with a converted R_X86_64_32S + // relocation is loaded above 2GB, the value will get sign-extended to the + // negative part of the 64-bit address space. The negative part of the 64-bit + // address space is unmapped, so accessing such an address page-faults. + // In order to support R_X86_64_32S, it is necessary to unset + // EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE, and the EFI PE loader must implement + // this flag and abstain from loading such a PE binary above 2GB. + // Since this feature is not supported, support for R_X86_64_32S (and hence + // the small non-position-independent code model) is disabled. + // + // case R_X86_64_32S: + case R_X86_64_32: + VerboseMsg ("EFI_IMAGE_REL_BASED_HIGHLOW Offset: 0x%08X", + mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr)); + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_HIGHLOW); + break; + default: + Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_X86_64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } + } else if (mEhdr->e_machine == EM_AARCH64) { + + switch (ELF_R_TYPE(Rel->r_info)) { + case R_AARCH64_ADR_PREL_LO21: + case R_AARCH64_CONDBR19: + case R_AARCH64_LD_PREL_LO19: + case R_AARCH64_CALL26: + case R_AARCH64_JUMP26: + case R_AARCH64_PREL64: + case R_AARCH64_PREL32: + case R_AARCH64_PREL16: + case R_AARCH64_ADR_PREL_PG_HI21: + case R_AARCH64_ADD_ABS_LO12_NC: + case R_AARCH64_LDST8_ABS_LO12_NC: + case R_AARCH64_LDST16_ABS_LO12_NC: + case R_AARCH64_LDST32_ABS_LO12_NC: + case R_AARCH64_LDST64_ABS_LO12_NC: + case R_AARCH64_LDST128_ABS_LO12_NC: + case R_AARCH64_ADR_GOT_PAGE: + case R_AARCH64_LD64_GOT_LO12_NC: + // + // No fixups are required for relative relocations, provided that + // the relative offsets between sections have been preserved in + // the ELF to PE/COFF conversion. We have already asserted that + // this is the case in WriteSections64 (). + // + break; + + case R_AARCH64_ABS64: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_DIR64); + break; + + case R_AARCH64_ABS32: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_HIGHLOW); + break; + + default: + Error (NULL, 0, 3000, "Invalid", "WriteRelocations64(): %s unsupported ELF EM_AARCH64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } + } else if (mEhdr->e_machine == EM_RISCV64) { + RiscVRelType = ELF_R_TYPE(Rel->r_info); + switch (RiscVRelType) { + case R_RISCV_NONE: + break; + + case R_RISCV_32: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_HIGHLOW); + break; + + case R_RISCV_64: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_DIR64); + break; + + case R_RISCV_HI20: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_RISCV_HI20); + break; + + case R_RISCV_LO12_I: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_RISCV_LOW12I); + break; + + case R_RISCV_LO12_S: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_RISCV_LOW12S); + break; + + case R_RISCV_ADD64: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_SUB64: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_ADD32: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_SUB32: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_BRANCH: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_JAL: + CoffAddFixup( + (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + + (Rel->r_offset - SecShdr->sh_addr)), + EFI_IMAGE_REL_BASED_ABSOLUTE); + break; + + case R_RISCV_GPREL_I: + case R_RISCV_GPREL_S: + case R_RISCV_CALL: + case R_RISCV_RVC_BRANCH: + case R_RISCV_RVC_JUMP: + case R_RISCV_RELAX: + case R_RISCV_SUB6: + case R_RISCV_SET6: + case R_RISCV_SET8: + case R_RISCV_SET16: + case R_RISCV_SET32: + case R_RISCV_PCREL_HI20: + case R_RISCV_PCREL_LO12_I: + break; + + default: + Error (NULL, 0, 3000, "Invalid", "WriteRelocations64(): %s unsupported ELF EM_RISCV64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); + } + } else { + Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) mEhdr->e_machine); + } + } + if (mEhdr->e_machine == EM_X86_64 && RelShdr->sh_info == mGOTShindex) { + // + // Tack relocations for GOT entries after other relocations for + // the section the GOT is in, as it's usually found at the end + // of the section. This is done in order to maintain Rva order + // of Coff relocations. + // + EmitGOTRelocations(); + } + } + } + } + + if (mEhdr->e_machine == EM_X86_64) { + // + // This is a safety net just in case the GOT is in a section + // with no other relocations and the first invocation of + // EmitGOTRelocations() above was skipped. This invocation + // does not maintain Rva order of Coff relocations. + // At present, with a single text section, all references to + // the GOT and the GOT itself reside in section .text, so + // if there's a GOT at all, the first invocation above + // is executed. + // + EmitGOTRelocations(); + } + // + // Pad by adding empty entries. + // + while (mCoffOffset & (mCoffAlignment - 1)) { + CoffAddFixupEntry(0); + } + + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset); + Dir = &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; + Dir->Size = mCoffOffset - mRelocOffset; + if (Dir->Size == 0) { + // If no relocations, null out the directory entry and don't add the .reloc section + Dir->VirtualAddress = 0; + NtHdr->Pe32Plus.FileHeader.NumberOfSections--; + } else { + Dir->VirtualAddress = mRelocOffset; + CreateSectionHeader (".reloc", mRelocOffset, mCoffOffset - mRelocOffset, + EFI_IMAGE_SCN_CNT_INITIALIZED_DATA + | EFI_IMAGE_SCN_MEM_DISCARDABLE + | EFI_IMAGE_SCN_MEM_READ); + } +} + +STATIC +VOID +WriteDebug64 ( + VOID + ) +{ + UINT32 Len; + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; + EFI_IMAGE_DATA_DIRECTORY *DataDir; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *Dir; + EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY *Nb10; + + Len = strlen(mInImageName) + 1; + + Dir = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY*)(mCoffFile + mDebugOffset); + Dir->Type = EFI_IMAGE_DEBUG_TYPE_CODEVIEW; + Dir->SizeOfData = sizeof(EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY) + Len; + Dir->RVA = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + Dir->FileOffset = mDebugOffset + sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + + Nb10 = (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY*)(Dir + 1); + Nb10->Signature = CODEVIEW_SIGNATURE_NB10; + strcpy ((char *)(Nb10 + 1), mInImageName); + + + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset); + DataDir = &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]; + DataDir->VirtualAddress = mDebugOffset; + DataDir->Size = sizeof(EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); +} + +STATIC +VOID +SetImageSize64 ( + VOID + ) +{ + EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; + + // + // Set image size + // + NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset); + NtHdr->Pe32Plus.OptionalHeader.SizeOfImage = mCoffOffset; +} + +STATIC +VOID +CleanUp64 ( + VOID + ) +{ + if (mCoffSectionsOffset != NULL) { + free (mCoffSectionsOffset); + } +} + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.h new file mode 100644 index 00000000..69746f4e --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Elf64Convert.h @@ -0,0 +1,19 @@ +/** @file +Header file for Elf64 convert solution + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _ELF_64_CONVERT_ +#define _ELF_64_CONVERT_ + +BOOLEAN +InitializeElf64 ( + UINT8 *FileBuffer, + ELF_FUNCTION_TABLE *ElfFunctions + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/ElfConvert.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/ElfConvert.c new file mode 100644 index 00000000..1dfc947f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/ElfConvert.c @@ -0,0 +1,245 @@ +/** @file +Elf convert solution + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "WinNtInclude.h" + +#ifndef __GNUC__ +#include +#include +#endif +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "EfiUtilityMsgs.h" + +#include "GenFw.h" +#include "ElfConvert.h" +#include "Elf32Convert.h" +#include "Elf64Convert.h" + +// +// Result Coff file in memory. +// +UINT8 *mCoffFile = NULL; + +// +// COFF relocation data +// +EFI_IMAGE_BASE_RELOCATION *mCoffBaseRel; +UINT16 *mCoffEntryRel; + +// +// Current offset in coff file. +// +UINT32 mCoffOffset; + +// +// Offset in Coff file of headers and sections. +// +UINT32 mTableOffset; + +// +//mFileBufferSize +// +UINT32 mFileBufferSize; + +// +//***************************************************************************** +// Common ELF Functions +//***************************************************************************** +// + +VOID +CoffAddFixupEntry( + UINT16 Val + ) +{ + *mCoffEntryRel = Val; + mCoffEntryRel++; + mCoffBaseRel->SizeOfBlock += 2; + mCoffOffset += 2; +} + +VOID +CoffAddFixup( + UINT32 Offset, + UINT8 Type + ) +{ + if (mCoffBaseRel == NULL + || mCoffBaseRel->VirtualAddress != (Offset & ~0xfff)) { + if (mCoffBaseRel != NULL) { + // + // Add a null entry (is it required ?) + // + CoffAddFixupEntry (0); + + // + // Pad for alignment. + // + if (mCoffOffset % 4 != 0) + CoffAddFixupEntry (0); + } + + mCoffFile = realloc ( + mCoffFile, + mCoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2 * MAX_COFF_ALIGNMENT + ); + if (mCoffFile == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + } + assert (mCoffFile != NULL); + memset ( + mCoffFile + mCoffOffset, 0, + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2 * MAX_COFF_ALIGNMENT + ); + + mCoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(mCoffFile + mCoffOffset); + mCoffBaseRel->VirtualAddress = Offset & ~0xfff; + mCoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION); + + mCoffEntryRel = (UINT16 *)(mCoffBaseRel + 1); + mCoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION); + } + + // + // Fill the entry. + // + CoffAddFixupEntry((UINT16) ((Type << 12) | (Offset & 0xfff))); +} + +VOID +CreateSectionHeader ( + const CHAR8 *Name, + UINT32 Offset, + UINT32 Size, + UINT32 Flags + ) +{ + EFI_IMAGE_SECTION_HEADER *Hdr; + Hdr = (EFI_IMAGE_SECTION_HEADER*)(mCoffFile + mTableOffset); + + strcpy((char *)Hdr->Name, Name); + Hdr->Misc.VirtualSize = Size; + Hdr->VirtualAddress = Offset; + Hdr->SizeOfRawData = Size; + Hdr->PointerToRawData = Offset; + Hdr->PointerToRelocations = 0; + Hdr->PointerToLinenumbers = 0; + Hdr->NumberOfRelocations = 0; + Hdr->NumberOfLinenumbers = 0; + Hdr->Characteristics = Flags; + + mTableOffset += sizeof (EFI_IMAGE_SECTION_HEADER); +} + +// +//***************************************************************************** +// Functions called from GenFw main code. +//***************************************************************************** +// + +INTN +IsElfHeader ( + UINT8 *FileBuffer +) +{ + return (FileBuffer[EI_MAG0] == ELFMAG0 && + FileBuffer[EI_MAG1] == ELFMAG1 && + FileBuffer[EI_MAG2] == ELFMAG2 && + FileBuffer[EI_MAG3] == ELFMAG3); +} + +BOOLEAN +ConvertElf ( + UINT8 **FileBuffer, + UINT32 *FileLength + ) +{ + ELF_FUNCTION_TABLE ElfFunctions; + UINT8 EiClass; + + mFileBufferSize = *FileLength; + // + // Determine ELF type and set function table pointer correctly. + // + VerboseMsg ("Check Elf Image Header"); + EiClass = (*FileBuffer)[EI_CLASS]; + if (EiClass == ELFCLASS32) { + if (!InitializeElf32 (*FileBuffer, &ElfFunctions)) { + return FALSE; + } + } else if (EiClass == ELFCLASS64) { + if (!InitializeElf64 (*FileBuffer, &ElfFunctions)) { + return FALSE; + } + } else { + Error (NULL, 0, 3000, "Unsupported", "ELF EI_CLASS not supported."); + return FALSE; + } + + // + // Compute sections new address. + // + VerboseMsg ("Compute sections new address."); + ElfFunctions.ScanSections (); + + // + // Write and relocate sections. + // + VerboseMsg ("Write and relocate sections."); + if (!ElfFunctions.WriteSections (SECTION_TEXT)) { + return FALSE; + } + if (!ElfFunctions.WriteSections (SECTION_DATA)) { + return FALSE; + } + if (!ElfFunctions.WriteSections (SECTION_HII)) { + return FALSE; + } + + // + // Translate and write relocations. + // + VerboseMsg ("Translate and write relocations."); + ElfFunctions.WriteRelocations (); + + // + // Write debug info. + // + VerboseMsg ("Write debug info."); + ElfFunctions.WriteDebug (); + + // + // Make sure image size is correct before returning the new image. + // + VerboseMsg ("Set image size."); + ElfFunctions.SetImageSize (); + + // + // Replace. + // + free (*FileBuffer); + *FileBuffer = mCoffFile; + *FileLength = mCoffOffset; + + // + // Free resources used by ELF functions. + // + ElfFunctions.CleanUp (); + + return TRUE; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/ElfConvert.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/ElfConvert.h new file mode 100644 index 00000000..27917942 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/ElfConvert.h @@ -0,0 +1,81 @@ +/** @file +Header file for Elf convert solution + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _ELF_CONVERT_H_ +#define _ELF_CONVERT_H_ + +#include "elf_common.h" +#include "elf32.h" +#include "elf64.h" + +// +// Externally defined variables +// +extern UINT32 mCoffOffset; +extern CHAR8 *mInImageName; +extern UINT32 mImageTimeStamp; +extern UINT8 *mCoffFile; +extern UINT32 mTableOffset; +extern UINT32 mOutImageType; +extern UINT32 mFileBufferSize; + +// +// Common EFI specific data. +// +#define ELF_HII_SECTION_NAME ".hii" +#define ELF_STRTAB_SECTION_NAME ".strtab" +#define MAX_COFF_ALIGNMENT 0x10000 + +// +// Filter Types +// +typedef enum { + SECTION_TEXT, + SECTION_HII, + SECTION_DATA + +} SECTION_FILTER_TYPES; + +// +// FunctionTable +// +typedef struct { + VOID (*ScanSections) (); + BOOLEAN (*WriteSections) (SECTION_FILTER_TYPES FilterType); + VOID (*WriteRelocations) (); + VOID (*WriteDebug) (); + VOID (*SetImageSize) (); + VOID (*CleanUp) (); + +} ELF_FUNCTION_TABLE; + +// +// Common functions +// +VOID +CoffAddFixup ( + UINT32 Offset, + UINT8 Type + ); + +VOID +CoffAddFixupEntry ( + UINT16 Val + ); + + +VOID +CreateSectionHeader ( + const CHAR8 *Name, + UINT32 Offset, + UINT32 Size, + UINT32 Flags + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GNUmakefile new file mode 100644 index 00000000..79916b4f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GNUmakefile @@ -0,0 +1,23 @@ +## @file +# GNU/Linux makefile for 'GenFw' module build. +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +MAKEROOT ?= .. + +APPNAME = GenFw + +OBJECTS = GenFw.o ElfConvert.o Elf32Convert.o Elf64Convert.o + +include $(MAKEROOT)/Makefiles/app.makefile + +LIBS = -lCommon +ifeq ($(CYGWIN), CYGWIN) + LIBS += -L/lib/e2fsprogs -luuid +endif + +ifeq ($(LINUX), Linux) + LIBS += -luuid +endif + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.c new file mode 100644 index 00000000..4faf329b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.c @@ -0,0 +1,3255 @@ +/** @file +Converts a pe32+ image to an FW, Te image type, or other specific image. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "WinNtInclude.h" + +#ifndef __GNUC__ +#include +#include +#include +#include +#endif +#include +#include +#include +#include +#include + +#include +#include +#include + +// +// Acpi Table definition +// +#include +#include +#include +#include +#include + +#include "CommonLib.h" +#include "PeCoffLib.h" +#include "ParseInf.h" +#include "EfiUtilityMsgs.h" + +#include "GenFw.h" + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wlogical-op" +#endif + +// +// Version of this utility +// +#define UTILITY_NAME "GenFw" +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 2 + +#define HII_RESOURCE_SECTION_INDEX 1 +#define HII_RESOURCE_SECTION_NAME "HII" + +#define DEFAULT_MC_PAD_BYTE_VALUE 0xFF +#define DEFAULT_MC_ALIGNMENT 16 + +#define STATUS_IGNORE 0xA +// +// Structure definition for a microcode header +// +typedef struct { + UINT32 HeaderVersion; + UINT32 PatchId; + UINT32 Date; + UINT32 CpuId; + UINT32 Checksum; + UINT32 LoaderVersion; + UINT32 PlatformId; + UINT32 DataSize; // if 0, then TotalSize = 2048, and TotalSize field is invalid + UINT32 TotalSize; // number of bytes + UINT32 Reserved[3]; +} MICROCODE_IMAGE_HEADER; + +static EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; + +static const char *gHiiPackageRCFileHeader[] = { + "//", + "// DO NOT EDIT -- auto-generated file", + "//", + NULL +}; + +// +// Module image information +// +CHAR8 *mInImageName; +UINT32 mImageTimeStamp = 0; +UINT32 mImageSize = 0; +UINT32 mOutImageType = FW_DUMMY_IMAGE; +BOOLEAN mIsConvertXip = FALSE; + + +STATIC +EFI_STATUS +ZeroDebugData ( + IN OUT UINT8 *FileBuffer, + BOOLEAN ZeroDebug + ); + +STATIC +EFI_STATUS +SetStamp ( + IN OUT UINT8 *FileBuffer, + IN CHAR8 *TimeStamp + ); + +STATIC +STATUS +MicrocodeReadData ( + FILE *InFptr, + UINT32 *Data + ); + +STATIC +VOID +Version ( + VOID + ) +/*++ + +Routine Description: + + Print out version information for this utility. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION); +} + +STATIC +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Print Help message. + +Arguments: + + VOID + +Returns: + + None + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "\nUsage: %s [options] \n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n"); + + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " -o FileName, --outputfile FileName\n\ + File will be created to store the output content.\n"); + fprintf (stdout, " -e EFI_FILETYPE, --efiImage EFI_FILETYPE\n\ + Create Efi Image. EFI_FILETYPE is one of BASE,SMM_CORE,\n\ + PEI_CORE, PEIM, DXE_CORE, DXE_DRIVER, UEFI_APPLICATION,\n\ + SEC, DXE_SAL_DRIVER, UEFI_DRIVER, DXE_RUNTIME_DRIVER,\n\ + DXE_SMM_DRIVER, SECURITY_CORE, COMBINED_PEIM_DRIVER,\n\ + MM_STANDALONE, MM_CORE_STANDALONE,\n\ + PIC_PEIM, RELOCATABLE_PEIM, BS_DRIVER, RT_DRIVER,\n\ + APPLICATION, SAL_RT_DRIVER to support all module types\n\ + It can only be used together with --keepexceptiontable,\n\ + --keepzeropending, --keepoptionalheader, -r, -o option.\n\ + It is a action option. If it is combined with other action options,\n\ + the later input action option will override the previous one.\n"); + fprintf (stdout, " -c, --acpi Create Acpi table.\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -t, --terse Create Te Image.\n\ + It can only be used together with --keepexceptiontable,\n\ + --keepzeropending, --keepoptionalheader, -r, -o option.\n\ + It is a action option. If it is combined with other action options,\n\ + the later input action option will override the previous one.\n"); + fprintf (stdout, " -u, --dump Dump TeImage Header.\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -z, --zero Zero the Debug Data Fields in the PE input image file.\n\ + It also zeros the time stamp fields.\n\ + This option can be used to compare the binary efi image.\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -b, --exe2bin Convert the input EXE to the output BIN file.\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n");; + fprintf (stdout, " -l, --stripped Strip off the relocation info from PE or TE image.\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -s timedate, --stamp timedate\n\ + timedate format is \"yyyy-mm-dd 00:00:00\". if timedata \n\ + is set to NOW, current system time is used. The support\n\ + date scope is 1970-01-01 00+timezone:00:00\n\ + ~ 2038-01-19 03+timezone:14:07\n\ + The scope is adjusted according to the different zones.\n\ + It can't be combined with other action options\n\ + except for -o, -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -m, --mcifile Convert input microcode txt file to microcode bin file.\n\ + It can't be combined with other action options\n\ + except for -o option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -j, --join Combine multi microcode bin files to one file.\n\ + It can be specified with -a, -p, -o option.\n\ + No other options can be combined with it.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -a NUM, --align NUM NUM is one HEX or DEC format alignment value.\n\ + This option is only used together with -j option.\n"); + fprintf (stdout, " -p NUM, --pad NUM NUM is one HEX or DEC format padding value.\n\ + This option is only used together with -j option.\n"); + fprintf (stdout, " --keepexceptiontable Don't clear exception table.\n\ + This option can be used together with -e or -t.\n\ + It doesn't work for other options.\n"); + fprintf (stdout, " --keepoptionalheader Don't zero PE/COFF optional header fields.\n\ + This option can be used together with -e or -t.\n\ + It doesn't work for other options.\n"); + fprintf (stdout, " --keepzeropending Don't strip zero pending of .reloc.\n\ + This option can be used together with -e or -t.\n\ + It doesn't work for other options.\n"); + fprintf (stdout, " -r, --replace Overwrite the input file with the output content.\n\ + If more input files are specified,\n\ + the last input file will be as the output file.\n"); + fprintf (stdout, " -g HiiPackageListGuid, --hiiguid HiiPackageListGuid\n\ + Guid is used to specify hii package list guid.\n\ + Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n\ + If not specified, the first Form FormSet guid is used.\n"); + fprintf (stdout, " --hiipackage Combine all input binary hii packages into \n\ + a single package list as the text resource data(RC).\n\ + It can't be combined with other action options\n\ + except for -o option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " --hiibinpackage Combine all input binary hii packages into \n\ + a single package list as the binary resource section.\n\ + It can't be combined with other action options\n\ + except for -o option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " --rebase NewAddress Rebase image to new base address. New address \n\ + is also set to the first none code section header.\n\ + It can't be combined with other action options\n\ + except for -o or -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " --address NewAddress Set new address into the first none code \n\ + section header of the input image.\n\ + It can't be combined with other action options\n\ + except for -o or -r option. It is a action option.\n\ + If it is combined with other action options, the later\n\ + input action option will override the previous one.\n"); + fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n"); + fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n"); + fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n"); + fprintf (stdout, " --version Show program's version number and exit\n"); + fprintf (stdout, " -h, --help Show this help message and exit\n"); +} + +STATIC +STATUS +CheckAcpiTable ( + VOID *AcpiTable, + UINT32 Length + ) +/*++ + +Routine Description: + + Check Acpi Table + +Arguments: + + AcpiTable Buffer for AcpiSection + Length AcpiSection Length + +Returns: + + 0 success + non-zero otherwise + +--*/ +{ + EFI_ACPI_DESCRIPTION_HEADER *AcpiHeader; + EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *Facs; + UINT32 ExpectedLength; + + AcpiHeader = (EFI_ACPI_DESCRIPTION_HEADER *)AcpiTable; + + // + // Generic check for AcpiTable length. + // + if (AcpiHeader->Length > Length) { + Error (NULL, 0, 3000, "Invalid", "AcpiTable length check failed.", NULL); + return STATUS_ERROR; + } + + // + // Currently, we only check must-have tables: FADT, FACS, DSDT, + // and some important tables: MADT, MCFG. + // + switch (AcpiHeader->Signature) { + + // + // "FACP" Fixed ACPI Description Table + // + case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE: + switch (AcpiHeader->Revision) { + case EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION: + ExpectedLength = sizeof(EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE); + break; + case EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION: + ExpectedLength = sizeof(EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE); + break; + case EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION: + ExpectedLength = sizeof(EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE); + break; + default: + if (AcpiHeader->Revision > EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION) { + ExpectedLength = AcpiHeader->Length; + break; + } + Error (NULL, 0, 3000, "Invalid", "FACP revision check failed."); + return STATUS_ERROR; + } + if (ExpectedLength != AcpiHeader->Length) { + Error (NULL, 0, 3000, "Invalid", "FACP length check failed."); + return STATUS_ERROR; + } + break; + + // + // "FACS" Firmware ACPI Control Structure + // + case EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE: + Facs = (EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE *)AcpiTable; + if (Facs->Version > EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) { + break; + } + if ((Facs->Version != EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) && + (Facs->Version != EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION) && + (Facs->Version != EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION)){ + Error (NULL, 0, 3000, "Invalid", "FACS version check failed."); + return STATUS_ERROR; + } + if ((Facs->Length != sizeof(EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) && + (Facs->Length != sizeof(EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE)) && + (Facs->Length != sizeof(EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE))) { + Error (NULL, 0, 3000, "Invalid", "FACS length check failed."); + return STATUS_ERROR; + } + break; + + // + // "DSDT" Differentiated System Description Table + // + case EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE: + if (AcpiHeader->Revision > EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION) { + break; + } + if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER)) { + Error (NULL, 0, 3000, "Invalid", "DSDT length check failed."); + return STATUS_ERROR; + } + break; + + // + // "APIC" Multiple APIC Description Table + // + case EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE: + if (AcpiHeader->Revision > EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) { + break; + } + if ((AcpiHeader->Revision != EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) && + (AcpiHeader->Revision != EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION) && + (AcpiHeader->Revision != EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION)) { + Error (NULL, 0, 3000, "Invalid", "APIC revision check failed."); + return STATUS_ERROR; + } + if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT32) + sizeof(UINT32)) { + Error (NULL, 0, 3000, "Invalid", "APIC length check failed."); + return STATUS_ERROR; + } + break; + + // + // "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table + // + case EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE: + if (AcpiHeader->Revision > EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) { + break; + } + if (AcpiHeader->Revision != EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION) { + Error (NULL, 0, 3000, "Invalid", "MCFG revision check failed."); + return STATUS_ERROR; + } + if (AcpiHeader->Length <= sizeof(EFI_ACPI_DESCRIPTION_HEADER) + sizeof(UINT64)) { + Error (NULL, 0, 3000, "Invalid", "MCFG length check failed."); + return STATUS_ERROR; + } + break; + + // + // Other table pass check + // + default: + break; + } + + return STATUS_SUCCESS; +} + +VOID +SetHiiResourceHeader ( + UINT8 *HiiBinData, + UINT32 OffsetToFile + ) +{ + UINT32 Index; + EFI_IMAGE_RESOURCE_DIRECTORY *ResourceDirectory; + EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *ResourceDirectoryEntry; + EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString; + EFI_IMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry; + + // + // Fill Resource section entry + // + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData); + ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1); + for (Index = 0; Index < ResourceDirectory->NumberOfNamedEntries; Index ++) { + if (ResourceDirectoryEntry->u1.s.NameIsString) { + ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiBinData + ResourceDirectoryEntry->u1.s.NameOffset); + + if (ResourceDirectoryString->Length == 3 && + ResourceDirectoryString->String[0] == L'H' && + ResourceDirectoryString->String[1] == L'I' && + ResourceDirectoryString->String[2] == L'I') { + // + // Resource Type "HII" found + // + if (ResourceDirectoryEntry->u2.s.DataIsDirectory) { + // + // Move to next level - resource Name + // + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData + ResourceDirectoryEntry->u2.s.OffsetToDirectory); + ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1); + + if (ResourceDirectoryEntry->u2.s.DataIsDirectory) { + // + // Move to next level - resource Language + // + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiBinData + ResourceDirectoryEntry->u2.s.OffsetToDirectory); + ResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (ResourceDirectory + 1); + } + } + + // + // Now it ought to be resource Data and update its OffsetToData value + // + if (!ResourceDirectoryEntry->u2.s.DataIsDirectory) { + ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (HiiBinData + ResourceDirectoryEntry->u2.OffsetToData); + ResourceDataEntry->OffsetToData = ResourceDataEntry->OffsetToData + OffsetToFile; + break; + } + } + } + ResourceDirectoryEntry++; + } + + return; +} + +EFI_IMAGE_OPTIONAL_HEADER_UNION * +GetPeCoffHeader ( + void *Data + ) +{ + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr; + + // + // Read the dos & pe hdrs of the image + // + DosHdr = (EFI_IMAGE_DOS_HEADER *)Data; + if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + // NO DOS header, check for PE/COFF header + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(Data); + if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + return NULL; + } + } else { + + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(((UINT8 *)Data) + DosHdr->e_lfanew); + if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + return NULL; + } + } + + return PeHdr; +} + +void +PeCoffConvertImageToXip ( + UINT8 **FileBuffer, + UINT32 *FileLength + ) +{ + EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr; + EFI_IMAGE_OPTIONAL_HEADER_UNION *NewPeHdr; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + UINTN TotalNecessaryFileSize; + UINTN SectionSize; + UINT8 *XipFile; + UINT32 XipLength; + UINTN Index; + UINTN FirstSectionOffset; + BOOLEAN ConversionNeeded; + + PeHdr = GetPeCoffHeader ((void *) *FileBuffer); + if (PeHdr == NULL) { + return; + } + + if (PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment) { + // + // The only reason to expand zero fill sections is to make them compatible with XIP images. + // If SectionAlignment is not equal to FileAlignment then it is not an XIP type image. + // + return; + } + + // + // Calculate size of XIP file, and determine if the conversion is needed. + // + ConversionNeeded = FALSE; + XipLength = 0; + FirstSectionOffset = *FileLength; + TotalNecessaryFileSize = 0; + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + SectionSize = MAX (SectionHeader->Misc.VirtualSize, SectionHeader->SizeOfRawData); + TotalNecessaryFileSize += SectionSize; + if (SectionSize > 0) { + FirstSectionOffset = MIN (FirstSectionOffset, SectionHeader->VirtualAddress); + XipLength = MAX (XipLength, SectionHeader->VirtualAddress + SectionSize); + if (SectionHeader->VirtualAddress != SectionHeader->PointerToRawData) { + ConversionNeeded = TRUE; + } + } + if (SectionHeader->Misc.VirtualSize > SectionHeader->SizeOfRawData) { + ConversionNeeded = TRUE; + } + } + + if (FirstSectionOffset < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) { + // + // If one of the sections should be loaded to an offset overlapping with + // the executable header, then it cannot be made into an XIP image. + // + VerboseMsg ("PE/COFF conversion to XIP is impossible due to overlap"); + VerboseMsg ("of section data with the executable header."); + return; + } + + if (FirstSectionOffset == *FileLength) { + // + // If we never found a section with a non-zero size, then we + // skip the conversion. + // + return; + } + + TotalNecessaryFileSize += FirstSectionOffset; + + if (!ConversionNeeded) { + return; + } + + if (XipLength > (2 * TotalNecessaryFileSize)) { + VerboseMsg ("PE/COFF conversion to XIP appears to be larger than necessary."); + VerboseMsg ("The image linking process may have left unused memory ranges."); + } + + if (PeHdr->Pe32.FileHeader.PointerToSymbolTable != 0) { + // + // This field is obsolete and should be zero + // + PeHdr->Pe32.FileHeader.PointerToSymbolTable = 0; + } + + // + // Allocate the extra space that we need to grow the image + // + XipFile = malloc (XipLength); + if (XipFile == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return; + } + memset (XipFile, 0, XipLength); + + // + // Copy the file headers + // + memcpy (XipFile, *FileBuffer, PeHdr->Pe32.OptionalHeader.SizeOfHeaders); + + NewPeHdr = GetPeCoffHeader ((void *)XipFile); + if (NewPeHdr == NULL) { + free (XipFile); + return; + } + + // + // Copy the section data over to the appropriate XIP offsets + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(NewPeHdr->Pe32.OptionalHeader) + NewPeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + if (SectionHeader->SizeOfRawData > 0) { + memcpy ( + XipFile + SectionHeader->VirtualAddress, + *FileBuffer + SectionHeader->PointerToRawData, + SectionHeader->SizeOfRawData + ); + } + // + // Make the size of raw data in section header alignment. + // + SectionSize = (SectionHeader->Misc.VirtualSize + PeHdr->Pe32.OptionalHeader.FileAlignment - 1) & (~(PeHdr->Pe32.OptionalHeader.FileAlignment - 1)); + if (SectionSize < SectionHeader->SizeOfRawData) { + SectionHeader->SizeOfRawData = SectionSize; + } + + SectionHeader->PointerToRawData = SectionHeader->VirtualAddress; + } + + free (*FileBuffer); + *FileLength = XipLength; + *FileBuffer = XipFile; + + mIsConvertXip = TRUE; +} + +UINT8 * +CreateHiiResouceSectionHeader ( + UINT32 *pSectionHeaderSize, + UINT32 HiiDataSize + ) +/*++ + +Routine Description: + + Create COFF resource section header + +Arguments: + + pSectionHeaderSize - Pointer to section header size. + HiiDataSize - Size of the total HII data in section. + +Returns: + The created section header buffer. + +--*/ +{ + UINT32 HiiSectionHeaderSize; + UINT32 HiiSectionOffset; + UINT8 *HiiSectionHeader; + EFI_IMAGE_RESOURCE_DIRECTORY *ResourceDirectory; + EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *TypeResourceDirectoryEntry; + EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *NameResourceDirectoryEntry; + EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *LanguageResourceDirectoryEntry; + EFI_IMAGE_RESOURCE_DIRECTORY_STRING *ResourceDirectoryString; + EFI_IMAGE_RESOURCE_DATA_ENTRY *ResourceDataEntry; + + // + // Calculate the total size for the resource header (include Type, Name and Language) + // then allocate memory for the resource header. + // + HiiSectionHeaderSize = 3 * (sizeof (EFI_IMAGE_RESOURCE_DIRECTORY) + sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY)) + + 3 * (sizeof (UINT16) + 3 * sizeof (CHAR16)) + + sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY); + HiiSectionHeader = malloc (HiiSectionHeaderSize); + if (HiiSectionHeader == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return NULL; + } + memset (HiiSectionHeader, 0, HiiSectionHeaderSize); + + HiiSectionOffset = 0; + // + // Create Type entry + // + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset); + HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY); + ResourceDirectory->NumberOfNamedEntries = 1; + TypeResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset); + HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY); + TypeResourceDirectoryEntry->u1.s.NameIsString = 1; + TypeResourceDirectoryEntry->u2.s.DataIsDirectory = 1; + TypeResourceDirectoryEntry->u2.s.OffsetToDirectory = HiiSectionOffset; + // + // Create Name entry + // + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset); + HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY); + ResourceDirectory->NumberOfNamedEntries = 1; + NameResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset); + HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY); + NameResourceDirectoryEntry->u1.s.NameIsString = 1; + NameResourceDirectoryEntry->u2.s.DataIsDirectory = 1; + NameResourceDirectoryEntry->u2.s.OffsetToDirectory = HiiSectionOffset; + // + // Create Language entry + // + ResourceDirectory = (EFI_IMAGE_RESOURCE_DIRECTORY *) (HiiSectionHeader + HiiSectionOffset); + HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY); + ResourceDirectory->NumberOfNamedEntries = 1; + LanguageResourceDirectoryEntry = (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY *) (HiiSectionHeader + HiiSectionOffset); + HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY); + LanguageResourceDirectoryEntry->u1.s.NameIsString = 1; + // + // Create string entry for Type + // + TypeResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset; + ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset); + ResourceDirectoryString->Length = 3; + ResourceDirectoryString->String[0] = L'H'; + ResourceDirectoryString->String[1] = L'I'; + ResourceDirectoryString->String[2] = L'I'; + HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]); + // + // Create string entry for Name + // + NameResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset; + ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset); + ResourceDirectoryString->Length = 3; + ResourceDirectoryString->String[0] = L'E'; + ResourceDirectoryString->String[1] = L'F'; + ResourceDirectoryString->String[2] = L'I'; + HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]); + // + // Create string entry for Language + // + LanguageResourceDirectoryEntry->u1.s.NameOffset = HiiSectionOffset; + ResourceDirectoryString = (EFI_IMAGE_RESOURCE_DIRECTORY_STRING *) (HiiSectionHeader + HiiSectionOffset); + ResourceDirectoryString->Length = 3; + ResourceDirectoryString->String[0] = L'B'; + ResourceDirectoryString->String[1] = L'I'; + ResourceDirectoryString->String[2] = L'N'; + HiiSectionOffset = HiiSectionOffset + sizeof (ResourceDirectoryString->Length) + ResourceDirectoryString->Length * sizeof (ResourceDirectoryString->String[0]); + // + // Create Leaf data + // + LanguageResourceDirectoryEntry->u2.OffsetToData = HiiSectionOffset; + ResourceDataEntry = (EFI_IMAGE_RESOURCE_DATA_ENTRY *) (HiiSectionHeader + HiiSectionOffset); + HiiSectionOffset += sizeof (EFI_IMAGE_RESOURCE_DATA_ENTRY); + ResourceDataEntry->OffsetToData = HiiSectionOffset; + ResourceDataEntry->Size = HiiDataSize; + + *pSectionHeaderSize = HiiSectionHeaderSize; + return HiiSectionHeader; +} + +EFI_STATUS +RebaseImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINT32 *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + + FileHandle - The handle to the PE/COFF file + + FileOffset - The offset, in bytes, into the file to read + + ReadSize - The number of bytes to read from the file starting at FileOffset + + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + UINT32 Length; + + Destination8 = Buffer; + Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); + Length = *ReadSize; + while (Length--) { + *(Destination8++) = *(Source8++); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +SetAddressToSectionHeader ( + IN CHAR8 *FileName, + IN OUT UINT8 *FileBuffer, + IN UINT64 NewPe32BaseAddress + ) +/*++ + +Routine Description: + + Set new base address into the section header of PeImage + +Arguments: + + FileName - Name of file + FileBuffer - Pointer to PeImage. + NewPe32BaseAddress - New Base Address for PE image. + +Returns: + + EFI_SUCCESS Set new base address into this image successfully. + +--*/ +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + UINTN Index; + EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + + // + // Initialize context + // + memset (&ImageContext, 0, sizeof (ImageContext)); + ImageContext.Handle = (VOID *) FileBuffer; + ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead; + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName); + return Status; + } + + if (ImageContext.RelocationsStripped) { + Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName); + return Status; + } + + // + // Get PeHeader pointer + // + ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset); + + // + // Get section header list + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN) ImgHdr + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader + ); + + // + // Set base address into the first section header that doesn't point to code section. + // + for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + if ((SectionHeader->Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) { + *(UINT64 *) &SectionHeader->PointerToRelocations = NewPe32BaseAddress; + break; + } + } + + // + // BaseAddress is set to section header. + // + return EFI_SUCCESS; +} + +EFI_STATUS +RebaseImage ( + IN CHAR8 *FileName, + IN OUT UINT8 *FileBuffer, + IN UINT64 NewPe32BaseAddress + ) +/*++ + +Routine Description: + + Set new base address into PeImage, and fix up PeImage based on new address. + +Arguments: + + FileName - Name of file + FileBuffer - Pointer to PeImage. + NewPe32BaseAddress - New Base Address for PE image. + +Returns: + + EFI_INVALID_PARAMETER - BaseAddress is not valid. + EFI_SUCCESS - Update PeImage is correctly. + +--*/ +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + UINTN Index; + EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; + UINT8 *MemoryImagePointer; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + + // + // Initialize context + // + memset (&ImageContext, 0, sizeof (ImageContext)); + ImageContext.Handle = (VOID *) FileBuffer; + ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead; + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName); + return Status; + } + + if (ImageContext.RelocationsStripped) { + Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName); + return Status; + } + + // + // Get PeHeader pointer + // + ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset); + + // + // Load and Relocate Image Data + // + MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment); + if (MemoryImagePointer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName); + return EFI_OUT_OF_RESOURCES; + } + memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment); + ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((INT64)ImageContext.SectionAlignment - 1)); + + Status = PeCoffLoaderLoadImage (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName); + free ((VOID *) MemoryImagePointer); + return Status; + } + + ImageContext.DestinationAddress = NewPe32BaseAddress; + Status = PeCoffLoaderRelocateImage (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName); + free ((VOID *) MemoryImagePointer); + return Status; + } + + // + // Copy Relocated data to raw image file. + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN) ImgHdr + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader + ); + + for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + CopyMem ( + FileBuffer + SectionHeader->PointerToRawData, + (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress), + SectionHeader->SizeOfRawData < SectionHeader->Misc.VirtualSize ? SectionHeader->SizeOfRawData : SectionHeader->Misc.VirtualSize + ); + } + + free ((VOID *) MemoryImagePointer); + + // + // Update Image Base Address + // + if (ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress; + } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress; + } else { + Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s", + ImgHdr->Pe32.OptionalHeader.Magic, + FileName + ); + return EFI_ABORTED; + } + + // + // Set new base address into section header + // + Status = SetAddressToSectionHeader (FileName, FileBuffer, NewPe32BaseAddress); + + return Status; +} + +int +main ( + int argc, + char *argv[] + ) +/*++ + +Routine Description: + + Main function. + +Arguments: + + argc - Number of command line parameters. + argv - Array of pointers to command line parameter strings. + +Returns: + STATUS_SUCCESS - Utility exits successfully. + STATUS_ERROR - Some error occurred during execution. + +--*/ +{ + UINT32 Type; + UINT32 InputFileNum; + CHAR8 **InputFileName; + char *OutImageName; + char *ModuleType; + CHAR8 *TimeStamp; + FILE *fpIn; + FILE *fpOut; + FILE *fpInOut; + UINT32 Data; + UINT32 *DataPointer; + UINT32 *OldDataPointer; + UINT32 CheckSum; + UINT32 Index; + UINT32 Index1; + UINT32 Index2; + UINT64 Temp64; + UINT32 MciAlignment; + UINT8 MciPadValue; + UINT32 AllignedRelocSize; + UINT8 *FileBuffer; + UINT32 FileLength; + UINT8 *OutputFileBuffer; + UINT32 OutputFileLength; + UINT8 *InputFileBuffer; + UINT32 InputFileLength; + RUNTIME_FUNCTION *RuntimeFunction; + UNWIND_INFO *UnwindInfo; + STATUS Status; + BOOLEAN ReplaceFlag; + BOOLEAN KeepExceptionTableFlag; + BOOLEAN KeepOptionalHeaderFlag; + BOOLEAN KeepZeroPendingFlag; + UINT64 LogLevel; + EFI_TE_IMAGE_HEADER TEImageHeader; + EFI_TE_IMAGE_HEADER *TeHdr; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_OPTIONAL_HEADER_UNION *PeHdr; + EFI_IMAGE_OPTIONAL_HEADER32 *Optional32; + EFI_IMAGE_OPTIONAL_HEADER64 *Optional64; + EFI_IMAGE_DOS_HEADER BackupDosHdr; + MICROCODE_IMAGE_HEADER *MciHeader; + UINT8 *HiiPackageListBuffer; + UINT8 *HiiPackageDataPointer; + EFI_GUID HiiPackageListGuid; + EFI_HII_PACKAGE_LIST_HEADER HiiPackageListHeader; + EFI_HII_PACKAGE_HEADER HiiPackageHeader; + EFI_IFR_FORM_SET IfrFormSet; + UINT8 NumberOfFormPackage; + EFI_HII_PACKAGE_HEADER EndPackage; + UINT32 HiiSectionHeaderSize; + UINT8 *HiiSectionHeader; + UINT64 NewBaseAddress; + BOOLEAN NegativeAddr; + FILE *ReportFile; + CHAR8 *ReportFileName; + UINTN FileLen; + time_t InputFileTime; + time_t OutputFileTime; + struct stat Stat_Buf; + BOOLEAN ZeroDebugFlag; + + SetUtilityName (UTILITY_NAME); + + // + // Assign to fix compile warning + // + FileLen = 0; + InputFileNum = 0; + InputFileName = NULL; + mInImageName = NULL; + OutImageName = NULL; + ModuleType = NULL; + Type = 0; + Status = STATUS_SUCCESS; + FileBuffer = NULL; + fpIn = NULL; + fpOut = NULL; + fpInOut = NULL; + TimeStamp = NULL; + MciAlignment = DEFAULT_MC_ALIGNMENT; + MciPadValue = DEFAULT_MC_PAD_BYTE_VALUE; + FileLength = 0; + MciHeader = NULL; + CheckSum = 0; + ReplaceFlag = FALSE; + LogLevel = 0; + OutputFileBuffer = NULL; + OutputFileLength = 0; + InputFileBuffer = NULL; + InputFileLength = 0; + Optional32 = NULL; + Optional64 = NULL; + KeepExceptionTableFlag = FALSE; + KeepOptionalHeaderFlag = FALSE; + KeepZeroPendingFlag = FALSE; + NumberOfFormPackage = 0; + HiiPackageListBuffer = NULL; + HiiPackageDataPointer = NULL; + EndPackage.Length = sizeof (EFI_HII_PACKAGE_HEADER); + EndPackage.Type = EFI_HII_PACKAGE_END; + memset (&HiiPackageListGuid, 0, sizeof (HiiPackageListGuid)); + HiiSectionHeaderSize = 0; + HiiSectionHeader = NULL; + NewBaseAddress = 0; + NegativeAddr = FALSE; + InputFileTime = 0; + OutputFileTime = 0; + ZeroDebugFlag = FALSE; + + if (argc == 1) { + Error (NULL, 0, 1001, "Missing options", "No input options."); + Usage (); + return STATUS_ERROR; + } + + argc --; + argv ++; + + if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) { + Version (); + Usage (); + return STATUS_SUCCESS; + } + + if (stricmp (argv[0], "--version") == 0) { + Version (); + return STATUS_SUCCESS; + } + + while (argc > 0) { + if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Output file name is missing for -o option"); + goto Finish; + } + OutImageName = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-e") == 0) || (stricmp (argv[0], "--efiImage") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Module Type is missing for -o option"); + goto Finish; + } + ModuleType = argv[1]; + if (mOutImageType == FW_ZERO_DEBUG_IMAGE) { + ZeroDebugFlag = TRUE; + } + if (mOutImageType != FW_TE_IMAGE) { + mOutImageType = FW_EFI_IMAGE; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--stripped") == 0)) { + mOutImageType = FW_RELOC_STRIPEED_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--acpi") == 0)) { + mOutImageType = FW_ACPI_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-t") == 0) || (stricmp (argv[0], "--terse") == 0)) { + if (mOutImageType == FW_ZERO_DEBUG_IMAGE) { + ZeroDebugFlag = TRUE; + } + mOutImageType = FW_TE_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-u") == 0) || (stricmp (argv[0], "--dump") == 0)) { + mOutImageType = DUMP_TE_HEADER; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-b") == 0) || (stricmp (argv[0], "--exe2bin") == 0)) { + mOutImageType = FW_BIN_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-z") == 0) || (stricmp (argv[0], "--zero") == 0)) { + if (mOutImageType == FW_DUMMY_IMAGE) { + mOutImageType = FW_ZERO_DEBUG_IMAGE; + } + if (mOutImageType == FW_TE_IMAGE || mOutImageType == FW_EFI_IMAGE) { + ZeroDebugFlag = TRUE; + } + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--stamp") == 0)) { + mOutImageType = FW_SET_STAMP_IMAGE; + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "time stamp is missing for -s option"); + goto Finish; + } + TimeStamp = argv[1]; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--replace") == 0)) { + ReplaceFlag = TRUE; + argc --; + argv ++; + continue; + } + + if (stricmp (argv[0], "--keepexceptiontable") == 0) { + KeepExceptionTableFlag = TRUE; + argc --; + argv ++; + continue; + } + + if (stricmp(argv[0], "--keepoptionalheader") == 0) { + KeepOptionalHeaderFlag = TRUE; + argc--; + argv++; + continue; + } + + if (stricmp (argv[0], "--keepzeropending") == 0) { + KeepZeroPendingFlag = TRUE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-m") == 0) || (stricmp (argv[0], "--mcifile") == 0)) { + mOutImageType = FW_MCI_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--join") == 0)) { + mOutImageType = FW_MERGE_IMAGE; + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-a") == 0) || (stricmp (argv[0], "--align") == 0)) { + if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + MciAlignment = (UINT32) Temp64; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "--rebase") == 0)) { + if (argv[1][0] == '-') { + NegativeAddr = TRUE; + Status = AsciiStringToUint64 (argv[1] + 1, FALSE, &Temp64); + } else { + NegativeAddr = FALSE; + Status = AsciiStringToUint64 (argv[1], FALSE, &Temp64); + } + if (Status != EFI_SUCCESS) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + mOutImageType = FW_REBASE_IMAGE; + NewBaseAddress = (UINT64) Temp64; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "--address") == 0)) { + if (argv[1][0] == '-') { + NegativeAddr = TRUE; + Status = AsciiStringToUint64 (argv[1] + 1, FALSE, &Temp64); + } else { + NegativeAddr = FALSE; + Status = AsciiStringToUint64 (argv[1], FALSE, &Temp64); + } + if (Status != EFI_SUCCESS) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + mOutImageType = FW_SET_ADDRESS_IMAGE; + NewBaseAddress = (UINT64) Temp64; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-p") == 0) || (stricmp (argv[0], "--pad") == 0)) { + if (AsciiStringToUint64 (argv[1], FALSE, &Temp64) != EFI_SUCCESS) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + MciPadValue = (UINT8) Temp64; + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) { + SetPrintLevel (VERBOSE_LOG_LEVEL); + VerboseMsg ("Verbose output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + SetPrintLevel (KEY_LOG_LEVEL); + KeyMsg ("Quiet output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + if (LogLevel > 9) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel); + goto Finish; + } + SetPrintLevel (LogLevel); + DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]); + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--hiiguid") == 0)) { + Status = StringToGuid (argv[1], &HiiPackageListGuid); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if (stricmp (argv[0], "--hiipackage") == 0) { + mOutImageType = FW_HII_PACKAGE_LIST_RCIMAGE; + argc --; + argv ++; + continue; + } + + if (stricmp (argv[0], "--hiibinpackage") == 0) { + mOutImageType = FW_HII_PACKAGE_LIST_BINIMAGE; + argc --; + argv ++; + continue; + } + + if (argv[0][0] == '-') { + Error (NULL, 0, 1000, "Unknown option", argv[0]); + goto Finish; + } + // + // Get Input file name + // + if ((InputFileNum == 0) && (InputFileName == NULL)) { + InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)); + if (InputFileName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + goto Finish; + } + + memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *))); + } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) { + // + // InputFileName buffer too small, need to realloc + // + InputFileName = (CHAR8 **) realloc ( + InputFileName, + (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *) + ); + + if (InputFileName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + goto Finish; + } + + memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *))); + } + + InputFileName [InputFileNum ++] = argv[0]; + argc --; + argv ++; + } + + VerboseMsg ("%s tool start.", UTILITY_NAME); + + if (mOutImageType == FW_DUMMY_IMAGE) { + Error (NULL, 0, 1001, "Missing option", "No create file action specified; pls specify -e, -c or -t option to create efi image, or acpi table or TeImage!"); + if (ReplaceFlag) { + Error (NULL, 0, 1001, "Missing option", "-r option is not supported as the independent option. It can be used together with other create file option specified at the above."); + } + goto Finish; + } + + // + // check input files + // + if (InputFileNum == 0) { + Error (NULL, 0, 1001, "Missing option", "Input files"); + goto Finish; + } + + // + // Combine MciBinary files to one file + // + if ((mOutImageType == FW_MERGE_IMAGE) && ReplaceFlag) { + Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with -j merge files option."); + goto Finish; + } + + // + // Combine HiiBinary packages to a single package list + // + if ((mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) && ReplaceFlag) { + Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiipackage merge files option."); + goto Finish; + } + + if ((mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) && ReplaceFlag) { + Error (NULL, 0, 1002, "Conflicting option", "-r replace option cannot be used with --hiibinpackage merge files option."); + goto Finish; + } + + // + // Input image file + // + mInImageName = InputFileName [InputFileNum - 1]; + VerboseMsg ("the input file name is %s", mInImageName); + + // + // Action will be taken for the input file. + // + switch (mOutImageType) { + case FW_EFI_IMAGE: + VerboseMsg ("Create efi image on module type %s based on the input PE image.", ModuleType); + break; + case FW_TE_IMAGE: + VerboseMsg ("Create Te Image based on the input PE image."); + break; + case FW_ACPI_IMAGE: + VerboseMsg ("Get acpi table data from the input PE image."); + break; + case FW_RELOC_STRIPEED_IMAGE: + VerboseMsg ("Remove relocation section from Pe or Te image."); + break; + case FW_BIN_IMAGE: + VerboseMsg ("Convert the input EXE to the output BIN file."); + break; + case FW_ZERO_DEBUG_IMAGE: + VerboseMsg ("Zero the Debug Data Fields and Time Stamp in input PE image."); + break; + case FW_SET_STAMP_IMAGE: + VerboseMsg ("Set new time stamp %s in the input PE image.", TimeStamp); + break; + case DUMP_TE_HEADER: + VerboseMsg ("Dump the TE header information of the input TE image."); + break; + case FW_MCI_IMAGE: + VerboseMsg ("Convert input MicroCode.txt file to MicroCode.bin file."); + break; + case FW_MERGE_IMAGE: + VerboseMsg ("Combine the input multi microcode bin files to one bin file."); + break; + case FW_HII_PACKAGE_LIST_RCIMAGE: + VerboseMsg ("Combine the input multi hii bin packages to one text package list RC file."); + break; + case FW_HII_PACKAGE_LIST_BINIMAGE: + VerboseMsg ("Combine the input multi hii bin packages to one binary package list file."); + break; + case FW_REBASE_IMAGE: + VerboseMsg ("Rebase the input image to new base address."); + break; + case FW_SET_ADDRESS_IMAGE: + VerboseMsg ("Set the preferred address into the section header of the input image"); + break; + default: + break; + } + + if (ReplaceFlag) { + VerboseMsg ("Overwrite the input file with the output content."); + } + + // + // Open output file and Write image into the output file. + // + if (OutImageName != NULL) { + fpOut = fopen (LongFilePath (OutImageName), "rb"); + if (fpOut != NULL) { + // + // Get Output file time stamp + // + fstat(fileno (fpOut), &Stat_Buf); + OutputFileTime = Stat_Buf.st_mtime; + // + // Get Output file data + // + OutputFileLength = _filelength (fileno (fpOut)); + OutputFileBuffer = malloc (OutputFileLength); + if (OutputFileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + fclose (fpOut); + fpOut = NULL; + goto Finish; + } + fread (OutputFileBuffer, 1, OutputFileLength, fpOut); + fclose (fpOut); + fpOut = NULL; + } + VerboseMsg ("Output file name is %s", OutImageName); + } else if (!ReplaceFlag && mOutImageType != DUMP_TE_HEADER) { + Error (NULL, 0, 1001, "Missing option", "output file"); + goto Finish; + } + + // + // Open input file and read file data into file buffer. + // + fpIn = fopen (LongFilePath (mInImageName), "rb"); + if (fpIn == NULL) { + Error (NULL, 0, 0001, "Error opening file", mInImageName); + goto Finish; + } + // + // Get Iutput file time stamp + // + fstat(fileno (fpIn), &Stat_Buf); + InputFileTime = Stat_Buf.st_mtime; + // + // Get Input file data + // + InputFileLength = _filelength (fileno (fpIn)); + InputFileBuffer = malloc (InputFileLength); + if (InputFileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + fclose (fpIn); + goto Finish; + } + fread (InputFileBuffer, 1, InputFileLength, fpIn); + fclose (fpIn); + DebugMsg (NULL, 0, 9, "input file info", "the input file size is %u bytes", (unsigned) InputFileLength); + + // + // Combine multi binary HII package files. + // + if (mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE || mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) { + // + // Open output file handle. + // + fpOut = fopen (LongFilePath (OutImageName), "wb"); + if (!fpOut) { + Error (NULL, 0, 0001, "Error opening output file", OutImageName); + goto Finish; + } + // + // Get hii package list length + // + HiiPackageListHeader.PackageLength = sizeof (EFI_HII_PACKAGE_LIST_HEADER); + for (Index = 0; Index < InputFileNum; Index ++) { + fpIn = fopen (LongFilePath (InputFileName [Index]), "rb"); + if (fpIn == NULL) { + Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]); + goto Finish; + } + FileLength = _filelength (fileno (fpIn)); + fread (&HiiPackageHeader, 1, sizeof (HiiPackageHeader), fpIn); + if (HiiPackageHeader.Type == EFI_HII_PACKAGE_FORM) { + if (HiiPackageHeader.Length != FileLength) { + Error (NULL, 0, 3000, "Invalid", "The wrong package size is in HII package file %s", InputFileName [Index]); + fclose (fpIn); + goto Finish; + } + if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) { + fread (&IfrFormSet, 1, sizeof (IfrFormSet), fpIn); + memcpy (&HiiPackageListGuid, &IfrFormSet.Guid, sizeof (EFI_GUID)); + } + NumberOfFormPackage ++; + } + HiiPackageListHeader.PackageLength += FileLength; + fclose (fpIn); + } + HiiPackageListHeader.PackageLength += sizeof (EndPackage); + // + // Check whether hii packages are valid + // + if (NumberOfFormPackage > 1) { + Error (NULL, 0, 3000, "Invalid", "The input hii packages contains more than one hii form package"); + goto Finish; + } + if (memcmp (&HiiPackageListGuid, &mZeroGuid, sizeof (EFI_GUID)) == 0) { + Error (NULL, 0, 3000, "Invalid", "HII package list guid is not specified!"); + goto Finish; + } + memcpy (&HiiPackageListHeader.PackageListGuid, &HiiPackageListGuid, sizeof (EFI_GUID)); + // + // read hii packages + // + HiiPackageListBuffer = malloc (HiiPackageListHeader.PackageLength); + if (HiiPackageListBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + goto Finish; + } + memcpy (HiiPackageListBuffer, &HiiPackageListHeader, sizeof (HiiPackageListHeader)); + HiiPackageDataPointer = HiiPackageListBuffer + sizeof (HiiPackageListHeader); + for (Index = 0; Index < InputFileNum; Index ++) { + fpIn = fopen (LongFilePath (InputFileName [Index]), "rb"); + if (fpIn == NULL) { + Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]); + free (HiiPackageListBuffer); + goto Finish; + } + + FileLength = _filelength (fileno (fpIn)); + fread (HiiPackageDataPointer, 1, FileLength, fpIn); + fclose (fpIn); + HiiPackageDataPointer = HiiPackageDataPointer + FileLength; + } + memcpy (HiiPackageDataPointer, &EndPackage, sizeof (EndPackage)); + + // + // write the hii package into the binary package list file with the resource section header + // + if (mOutImageType == FW_HII_PACKAGE_LIST_BINIMAGE) { + // + // Create the resource section header + // + HiiSectionHeader = CreateHiiResouceSectionHeader (&HiiSectionHeaderSize, HiiPackageListHeader.PackageLength); + if (HiiSectionHeader == NULL) { + free (HiiPackageListBuffer); + goto Finish; + } + // + // Wrtie section header and HiiData into File. + // + fwrite (HiiSectionHeader, 1, HiiSectionHeaderSize, fpOut); + fwrite (HiiPackageListBuffer, 1, HiiPackageListHeader.PackageLength, fpOut); + // + // Free allocated resources. + // + free (HiiSectionHeader); + free (HiiPackageListBuffer); + // + // Done successfully + // + goto Finish; + } + + // + // write the hii package into the text package list rc file. + // + if (mOutImageType == FW_HII_PACKAGE_LIST_RCIMAGE) { + for (Index = 0; gHiiPackageRCFileHeader[Index] != NULL; Index++) { + fprintf (fpOut, "%s\n", gHiiPackageRCFileHeader[Index]); + } + fprintf (fpOut, "\n%d %s\n{", HII_RESOURCE_SECTION_INDEX, HII_RESOURCE_SECTION_NAME); + + HiiPackageDataPointer = HiiPackageListBuffer; + for (Index = 0; Index + 2 < HiiPackageListHeader.PackageLength; Index += 2) { + if (Index % 16 == 0) { + fprintf (fpOut, "\n "); + } + fprintf (fpOut, " 0x%04X,", *(UINT16 *) HiiPackageDataPointer); + HiiPackageDataPointer += 2; + } + + if (Index % 16 == 0) { + fprintf (fpOut, "\n "); + } + if ((Index + 2) == HiiPackageListHeader.PackageLength) { + fprintf (fpOut, " 0x%04X\n}\n", *(UINT16 *) HiiPackageDataPointer); + } + if ((Index + 1) == HiiPackageListHeader.PackageLength) { + fprintf (fpOut, " 0x%04X\n}\n", *(UINT8 *) HiiPackageDataPointer); + } + free (HiiPackageListBuffer); + // + // Done successfully + // + goto Finish; + } + } + + // + // Combine MciBinary files to one file + // + if (mOutImageType == FW_MERGE_IMAGE) { + // + // Open output file handle. + // + fpOut = fopen (LongFilePath (OutImageName), "wb"); + if (!fpOut) { + Error (NULL, 0, 0001, "Error opening output file", OutImageName); + goto Finish; + } + for (Index = 0; Index < InputFileNum; Index ++) { + fpIn = fopen (LongFilePath (InputFileName [Index]), "rb"); + if (!fpIn) { + Error (NULL, 0, 0001, "Error opening file", InputFileName [Index]); + goto Finish; + } + + FileLength = _filelength (fileno (fpIn)); + FileBuffer = malloc (FileLength); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + fclose (fpIn); + goto Finish; + } + + fread (FileBuffer, 1, FileLength, fpIn); + fclose (fpIn); + // + // write input file to out file + // + fwrite (FileBuffer, 1, FileLength, fpOut); + // + // write pad value to out file. + // + while (FileLength ++ % MciAlignment != 0) { + fwrite (&MciPadValue, 1, 1, fpOut); + } + // + // free allocated memory space + // + free (FileBuffer); + FileBuffer = NULL; + } + // + // Done successfully + // + goto Finish; + } + + // + // Convert MicroCode.txt file to MicroCode.bin file + // + if (mOutImageType == FW_MCI_IMAGE) { + fpIn = fopen (LongFilePath (mInImageName), "r"); + if (fpIn == NULL) { + Error (NULL, 0, 0001, "Error opening file", mInImageName); + goto Finish; + } + + // + // The first pass is to determine + // how much data is in the file so we can allocate a working buffer. + // + FileLength = 0; + do { + Status = MicrocodeReadData (fpIn, &Data); + if (Status == STATUS_SUCCESS) { + FileLength += sizeof (Data); + } + if (Status == STATUS_IGNORE) { + Status = STATUS_SUCCESS; + } + } while (Status == STATUS_SUCCESS); + // + // Error if no data. + // + if (FileLength == 0) { + Error (NULL, 0, 3000, "Invalid", "no parseable data found in file %s", mInImageName); + goto Finish; + } + if (FileLength < sizeof (MICROCODE_IMAGE_HEADER)) { + Error (NULL, 0, 3000, "Invalid", "amount of parseable data in %s is insufficient to contain a microcode header", mInImageName); + goto Finish; + } + + // + // Allocate a buffer for the data + // + FileBuffer = malloc (FileLength); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + goto Finish; + } + // + // Re-read the file, storing the data into our buffer + // + fseek (fpIn, 0, SEEK_SET); + DataPointer = (UINT32 *) FileBuffer; + OldDataPointer = DataPointer; + do { + OldDataPointer = DataPointer; + Status = MicrocodeReadData (fpIn, DataPointer++); + if (Status == STATUS_IGNORE) { + DataPointer = OldDataPointer; + Status = STATUS_SUCCESS; + } + } while (Status == STATUS_SUCCESS); + // + // close input file after read data + // + fclose (fpIn); + + // + // Can't do much checking on the header because, per the spec, the + // DataSize field may be 0, which means DataSize = 2000 and TotalSize = 2K, + // and the TotalSize field is invalid (actually missing). Thus we can't + // even verify the Reserved fields are 0. + // + MciHeader = (MICROCODE_IMAGE_HEADER *) FileBuffer; + if (MciHeader->DataSize == 0) { + Index = 2048; + } else { + Index = MciHeader->TotalSize; + } + + if (Index != FileLength) { + Error (NULL, 0, 3000, "Invalid", "file length of %s (0x%x) does not equal expected TotalSize: 0x%04X.", mInImageName, (unsigned) FileLength, (unsigned) Index); + goto Finish; + } + + // + // Checksum the contents + // + DataPointer = (UINT32 *) FileBuffer; + CheckSum = 0; + Index = 0; + while (Index < FileLength) { + CheckSum += *DataPointer; + DataPointer ++; + Index += sizeof (*DataPointer); + } + if (CheckSum != 0) { + Error (NULL, 0, 3000, "Invalid", "checksum (0x%x) failed on file %s.", (unsigned) CheckSum, mInImageName); + goto Finish; + } + // + // Open the output file and write the buffer contents + // + VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength); + goto WriteFile; + } + + // + // Open input file and read file data into file buffer. + // + FileLength = InputFileLength; + FileBuffer = malloc (FileLength); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + goto Finish; + } + memcpy (FileBuffer, InputFileBuffer, InputFileLength); + + // + // Dump TeImage Header into output file. + // + if (mOutImageType == DUMP_TE_HEADER) { + memcpy (&TEImageHeader, FileBuffer, sizeof (TEImageHeader)); + if (TEImageHeader.Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "TE header signature of file %s is not correct.", mInImageName); + goto Finish; + } + // + // Open the output file handle. + // + if (ReplaceFlag) { + fpInOut = fopen (LongFilePath (mInImageName), "wb"); + if (fpInOut == NULL) { + Error (NULL, 0, 0001, "Error opening file", mInImageName); + goto Finish; + } + } else { + if (OutImageName != NULL) { + fpOut = fopen (LongFilePath (OutImageName), "wb"); + } else { + fpOut = stdout; + } + if (fpOut == NULL) { + Error (NULL, 0, 0001, "Error opening output file", OutImageName); + goto Finish; + } + } + if (fpInOut != NULL) { + fprintf (fpInOut, "Dump of file %s\n\n", mInImageName); + fprintf (fpInOut, "TE IMAGE HEADER VALUES\n"); + fprintf (fpInOut, "%17X machine\n", TEImageHeader.Machine); + fprintf (fpInOut, "%17X number of sections\n", TEImageHeader.NumberOfSections); + fprintf (fpInOut, "%17X subsystems\n", TEImageHeader.Subsystem); + fprintf (fpInOut, "%17X stripped size\n", TEImageHeader.StrippedSize); + fprintf (fpInOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint); + fprintf (fpInOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode); + fprintf (fpInOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase); + fprintf (fpInOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size); + fprintf (fpInOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size); + } + if (fpOut != NULL) { + fprintf (fpOut, "Dump of file %s\n\n", mInImageName); + fprintf (fpOut, "TE IMAGE HEADER VALUES\n"); + fprintf (fpOut, "%17X machine\n", TEImageHeader.Machine); + fprintf (fpOut, "%17X number of sections\n", TEImageHeader.NumberOfSections); + fprintf (fpOut, "%17X subsystems\n", TEImageHeader.Subsystem); + fprintf (fpOut, "%17X stripped size\n", TEImageHeader.StrippedSize); + fprintf (fpOut, "%17X entry point\n", (unsigned) TEImageHeader.AddressOfEntryPoint); + fprintf (fpOut, "%17X base of code\n", (unsigned) TEImageHeader.BaseOfCode); + fprintf (fpOut, "%17llX image base\n", (unsigned long long)TEImageHeader.ImageBase); + fprintf (fpOut, "%17X [%8X] RVA [size] of Base Relocation Directory\n", (unsigned) TEImageHeader.DataDirectory[0].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[0].Size); + fprintf (fpOut, "%17X [%8X] RVA [size] of Debug Directory\n", (unsigned) TEImageHeader.DataDirectory[1].VirtualAddress, (unsigned) TEImageHeader.DataDirectory[1].Size); + } + goto Finish; + } + + // + // Following code to convert dll to efi image or te image. + // Get new image type + // + if ((mOutImageType == FW_EFI_IMAGE) || (mOutImageType == FW_TE_IMAGE)) { + if (ModuleType == NULL) { + if (mOutImageType == FW_EFI_IMAGE) { + Error (NULL, 0, 1001, "Missing option", "EFI_FILETYPE"); + goto Finish; + } else if (mOutImageType == FW_TE_IMAGE) { + // + // Default TE Image Type is Boot service driver + // + Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; + VerboseMsg ("Efi Image subsystem type is efi boot service driver."); + } + } else { + if (stricmp (ModuleType, "BASE") == 0 || + stricmp (ModuleType, "SEC") == 0 || + stricmp (ModuleType, "SECURITY_CORE") == 0 || + stricmp (ModuleType, "PEI_CORE") == 0 || + stricmp (ModuleType, "PEIM") == 0 || + stricmp (ModuleType, "COMBINED_PEIM_DRIVER") == 0 || + stricmp (ModuleType, "PIC_PEIM") == 0 || + stricmp (ModuleType, "RELOCATABLE_PEIM") == 0 || + stricmp (ModuleType, "DXE_CORE") == 0 || + stricmp (ModuleType, "BS_DRIVER") == 0 || + stricmp (ModuleType, "DXE_DRIVER") == 0 || + stricmp (ModuleType, "DXE_SMM_DRIVER") == 0 || + stricmp (ModuleType, "UEFI_DRIVER") == 0 || + stricmp (ModuleType, "SMM_CORE") == 0 || + stricmp (ModuleType, "MM_STANDALONE") == 0 || + stricmp (ModuleType, "MM_CORE_STANDALONE") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; + VerboseMsg ("Efi Image subsystem type is efi boot service driver."); + + } else if (stricmp (ModuleType, "UEFI_APPLICATION") == 0 || + stricmp (ModuleType, "APPLICATION") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION; + VerboseMsg ("Efi Image subsystem type is efi application."); + + } else if (stricmp (ModuleType, "DXE_RUNTIME_DRIVER") == 0 || + stricmp (ModuleType, "RT_DRIVER") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER; + VerboseMsg ("Efi Image subsystem type is efi runtime driver."); + + } else if (stricmp (ModuleType, "DXE_SAL_DRIVER") == 0 || + stricmp (ModuleType, "SAL_RT_DRIVER") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER; + VerboseMsg ("Efi Image subsystem type is efi sal runtime driver."); + + } else { + Error (NULL, 0, 1003, "Invalid option value", "EFI_FILETYPE = %s", ModuleType); + goto Finish; + } + } + } + + // + // Convert ELF image to PeImage + // + if (IsElfHeader(FileBuffer)) { + VerboseMsg ("Convert %s from ELF to PE/COFF.", mInImageName); + if (!ConvertElf(&FileBuffer, &FileLength)) { + Error (NULL, 0, 3000, "Invalid", "Unable to convert %s from ELF to PE/COFF.", mInImageName); + goto Finish; + } + } + + // + // Make sure File Offsets and Virtual Offsets are the same in the image so it is XIP + // XIP == eXecute In Place + // + PeCoffConvertImageToXip (&FileBuffer, &FileLength); + + // + // Remove reloc section from PE or TE image + // + if (mOutImageType == FW_RELOC_STRIPEED_IMAGE) { + // + // Check TeImage + // + TeHdr = (EFI_TE_IMAGE_HEADER *) FileBuffer; + if (TeHdr->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (TeHdr + 1); + for (Index = 0; Index < TeHdr->NumberOfSections; Index ++, SectionHeader ++) { + if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) { + // + // Check the reloc section is in the end of image. + // + if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == + (FileLength + TeHdr->StrippedSize - sizeof (EFI_TE_IMAGE_HEADER))) { + // + // Remove .reloc section and update TeImage Header + // + FileLength = FileLength - SectionHeader->SizeOfRawData; + SectionHeader->SizeOfRawData = 0; + SectionHeader->Misc.VirtualSize = 0; + TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0; + TeHdr->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0; + break; + } + } + } + } else { + // + // Check PE Image + // + DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer; + if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer); + if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "TE and DOS header signatures were not found in %s image.", mInImageName); + goto Finish; + } + DosHdr = NULL; + } else { + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew); + if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName); + goto Finish; + } + } + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + if (strcmp ((char *)SectionHeader->Name, ".reloc") == 0) { + // + // Check the reloc section is in the end of image. + // + if ((SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData) == FileLength) { + // + // Remove .reloc section and update PeImage Header + // + FileLength = FileLength - SectionHeader->SizeOfRawData; + + PeHdr->Pe32.FileHeader.Characteristics |= EFI_IMAGE_FILE_RELOCS_STRIPPED; + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader; + Optional32->SizeOfImage -= SectionHeader->SizeOfRawData; + Optional32->SizeOfInitializedData -= SectionHeader->SizeOfRawData; + if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0; + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0; + } + } + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader; + Optional64->SizeOfImage -= SectionHeader->SizeOfRawData; + Optional64->SizeOfInitializedData -= SectionHeader->SizeOfRawData; + if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = 0; + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = 0; + } + } + SectionHeader->Misc.VirtualSize = 0; + SectionHeader->SizeOfRawData = 0; + break; + } + } + } + } + // + // Write file + // + goto WriteFile; + } + // + // Read the dos & pe hdrs of the image + // + DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer; + if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + // NO DOS header, check for PE/COFF header + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer); + if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "DOS header signature was not found in %s image.", mInImageName); + goto Finish; + } + DosHdr = NULL; + } else { + + PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + DosHdr->e_lfanew); + if (PeHdr->Pe32.Signature != EFI_IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 3000, "Invalid", "PE header signature was not found in %s image.", mInImageName); + goto Finish; + } + } + + if (PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_ARM) { + // Some tools kick out IMAGE_FILE_MACHINE_ARM (0x1c0) vs IMAGE_FILE_MACHINE_ARMT (0x1c2) + // so patch back to the official UEFI value. + PeHdr->Pe32.FileHeader.Machine = IMAGE_FILE_MACHINE_ARMT; + } + + // + // Set new base address into image + // + if (mOutImageType == FW_REBASE_IMAGE || mOutImageType == FW_SET_ADDRESS_IMAGE) { + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + if (NewBaseAddress >= 0x100000000ULL) { + Error (NULL, 0, 3000, "Invalid", "New base address is larger than 4G for 32bit PE image"); + goto Finish; + } + } + + if (NegativeAddr) { + // + // Set Base Address to a negative value. + // + NewBaseAddress = (UINT64) (0 - NewBaseAddress); + } + if (mOutImageType == FW_REBASE_IMAGE) { + Status = RebaseImage (mInImageName, FileBuffer, NewBaseAddress); + } else { + Status = SetAddressToSectionHeader (mInImageName, FileBuffer, NewBaseAddress); + } + if (EFI_ERROR (Status)) { + if (NegativeAddr) { + Error (NULL, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address -0x%llx can't success", mInImageName, 0 - NewBaseAddress); + } else { + Error (NULL, 0, 3000, "Invalid", "Rebase/Set Image %s to Base address 0x%llx can't success", mInImageName, NewBaseAddress); + } + goto Finish; + } + + // + // Write file + // + goto WriteFile; + } + + // + // Extract bin data from Pe image. + // + if (mOutImageType == FW_BIN_IMAGE) { + if (FileLength < PeHdr->Pe32.OptionalHeader.SizeOfHeaders) { + Error (NULL, 0, 3000, "Invalid", "FileSize of %s is not a legal size.", mInImageName); + goto Finish; + } + // + // Output bin data from exe file + // + FileLength = FileLength - PeHdr->Pe32.OptionalHeader.SizeOfHeaders; + memmove (FileBuffer, FileBuffer + PeHdr->Pe32.OptionalHeader.SizeOfHeaders, FileLength); + VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength); + goto WriteFile; + } + + // + // Zero Debug Information of Pe Image + // + if (mOutImageType == FW_ZERO_DEBUG_IMAGE) { + Status = ZeroDebugData (FileBuffer, TRUE); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "Zero DebugData Error status is 0x%x", (int) Status); + goto Finish; + } + + // + // Write the updated Image + // + VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength); + goto WriteFile; + } + + // + // Set Time Stamp of Pe Image + // + if (mOutImageType == FW_SET_STAMP_IMAGE) { + Status = SetStamp (FileBuffer, TimeStamp); + if (EFI_ERROR (Status)) { + goto Finish; + } + + // + // Write the updated Image + // + VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength); + goto WriteFile; + } + + // + // Extract acpi data from pe image. + // + if (mOutImageType == FW_ACPI_IMAGE) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + if (strcmp ((char *)SectionHeader->Name, ".data") == 0 || strcmp ((char *)SectionHeader->Name, ".sdata") == 0) { + // + // Check Acpi Table + // + if (SectionHeader->Misc.VirtualSize < SectionHeader->SizeOfRawData) { + FileLength = SectionHeader->Misc.VirtualSize; + } else { + FileLength = SectionHeader->SizeOfRawData; + } + + if (CheckAcpiTable (FileBuffer + SectionHeader->PointerToRawData, FileLength) != STATUS_SUCCESS) { + Error (NULL, 0, 3000, "Invalid", "ACPI table check failed in %s.", mInImageName); + goto Finish; + } + + // + // Output Apci data to file + // + memmove (FileBuffer, FileBuffer + SectionHeader->PointerToRawData, FileLength); + VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength); + goto WriteFile; + } + } + Error (NULL, 0, 3000, "Invalid", "failed to get ACPI table from %s.", mInImageName); + goto Finish; + } + // + // Zero all unused fields of the DOS header + // + if (DosHdr != NULL) { + memcpy (&BackupDosHdr, DosHdr, sizeof (EFI_IMAGE_DOS_HEADER)); + memset (DosHdr, 0, sizeof (EFI_IMAGE_DOS_HEADER)); + DosHdr->e_magic = BackupDosHdr.e_magic; + DosHdr->e_lfanew = BackupDosHdr.e_lfanew; + + for (Index = sizeof (EFI_IMAGE_DOS_HEADER); Index < (UINT32 ) DosHdr->e_lfanew; Index++) { + FileBuffer[Index] = (UINT8) DosHdr->e_cp; + } + } + + // + // Initialize TeImage Header + // + memset (&TEImageHeader, 0, sizeof (EFI_TE_IMAGE_HEADER)); + TEImageHeader.Signature = EFI_TE_IMAGE_HEADER_SIGNATURE; + TEImageHeader.Machine = PeHdr->Pe32.FileHeader.Machine; + TEImageHeader.NumberOfSections = (UINT8) PeHdr->Pe32.FileHeader.NumberOfSections; + TEImageHeader.StrippedSize = (UINT16) ((UINTN) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader) - (UINTN) FileBuffer); + TEImageHeader.Subsystem = (UINT8) Type; + + // + // Patch the PE header + // + PeHdr->Pe32.OptionalHeader.Subsystem = (UINT16) Type; + + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader; + if (!KeepOptionalHeaderFlag) { + Optional32->MajorOperatingSystemVersion = 0; + Optional32->MinorOperatingSystemVersion = 0; + Optional32->MajorImageVersion = 0; + Optional32->MinorImageVersion = 0; + Optional32->MajorSubsystemVersion = 0; + Optional32->MinorSubsystemVersion = 0; + Optional32->Win32VersionValue = 0; + Optional32->CheckSum = 0; + Optional32->SizeOfStackReserve = 0; + Optional32->SizeOfStackCommit = 0; + Optional32->SizeOfHeapReserve = 0; + Optional32->SizeOfHeapCommit = 0; + } + TEImageHeader.AddressOfEntryPoint = Optional32->AddressOfEntryPoint; + TEImageHeader.BaseOfCode = Optional32->BaseOfCode; + TEImageHeader.ImageBase = (UINT64) (Optional32->ImageBase); + + if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; + } + + if (Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size; + } + + // + // Zero .pdata section data. + // + if (!KeepExceptionTableFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION && + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 && + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) { + if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) { + // + // Zero .pdata Section data + // + memset (FileBuffer + SectionHeader->PointerToRawData, 0, SectionHeader->SizeOfRawData); + // + // Zero .pdata Section header name + // + memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name)); + // + // Zero Exception Table + // + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0; + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0; + DebugMsg (NULL, 0, 9, "Zero the .pdata section for PE image", NULL); + break; + } + } + } + + // + // Strip zero padding at the end of the .reloc section + // + if (!KeepZeroPendingFlag && Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + if (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) { + // + // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory + // + if (SectionHeader->VirtualAddress == Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) { + SectionHeader->Misc.VirtualSize = Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; + AllignedRelocSize = (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional32->FileAlignment - 1) & (~(Optional32->FileAlignment - 1)); + // + // Check to see if there is zero padding at the end of the base relocations + // + if (AllignedRelocSize < SectionHeader->SizeOfRawData) { + // + // Check to see if the base relocations are at the end of the file + // + if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional32->SizeOfImage) { + // + // All the required conditions are met to strip the zero padding of the end of the base relocations section + // + Optional32->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize); + Optional32->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize); + SectionHeader->SizeOfRawData = AllignedRelocSize; + FileLength = Optional32->SizeOfImage; + DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader->SizeOfRawData - AllignedRelocSize)); + } + } + } + } + } + } + } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader; + if (!KeepOptionalHeaderFlag) { + Optional64->MajorOperatingSystemVersion = 0; + Optional64->MinorOperatingSystemVersion = 0; + Optional64->MajorImageVersion = 0; + Optional64->MinorImageVersion = 0; + Optional64->MajorSubsystemVersion = 0; + Optional64->MinorSubsystemVersion = 0; + Optional64->Win32VersionValue = 0; + Optional64->CheckSum = 0; + Optional64->SizeOfStackReserve = 0; + Optional64->SizeOfStackCommit = 0; + Optional64->SizeOfHeapReserve = 0; + Optional64->SizeOfHeapCommit = 0; + } + TEImageHeader.AddressOfEntryPoint = Optional64->AddressOfEntryPoint; + TEImageHeader.BaseOfCode = Optional64->BaseOfCode; + TEImageHeader.ImageBase = (UINT64) (Optional64->ImageBase); + + if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress; + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; + } + + if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size; + } + + // + // Zero the .pdata section for X64 machine and don't check the Debug Directory is empty + // For Itaninum and X64 Image, remove .pdata section. + // + if ((!KeepExceptionTableFlag && PeHdr->Pe32.FileHeader.Machine == IMAGE_FILE_MACHINE_X64)) { + if (Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION && + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0 && + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) { + if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress) { + // + // Zero .pdata Section header name + // + memset (SectionHeader->Name, 0, sizeof (SectionHeader->Name)); + + RuntimeFunction = (RUNTIME_FUNCTION *)(FileBuffer + SectionHeader->PointerToRawData); + for (Index1 = 0; Index1 < Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size / sizeof (RUNTIME_FUNCTION); Index1++, RuntimeFunction++) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index2 = 0; Index2 < PeHdr->Pe32.FileHeader.NumberOfSections; Index2++, SectionHeader++) { + if (RuntimeFunction->UnwindInfoAddress >= SectionHeader->VirtualAddress && RuntimeFunction->UnwindInfoAddress < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData)) { + UnwindInfo = (UNWIND_INFO *)(FileBuffer + SectionHeader->PointerToRawData + (RuntimeFunction->UnwindInfoAddress - SectionHeader->VirtualAddress)); + if (UnwindInfo->Version == 1) { + memset (UnwindInfo + 1, 0, UnwindInfo->CountOfUnwindCodes * sizeof (UINT16)); + memset (UnwindInfo, 0, sizeof (UNWIND_INFO)); + } + break; + } + } + memset (RuntimeFunction, 0, sizeof (RUNTIME_FUNCTION)); + } + // + // Zero Exception Table + // + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0; + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0; + DebugMsg (NULL, 0, 9, "Zero the .pdata section if the machine type is X64 for PE32+ image", NULL); + break; + } + } + } + } + + // + // Strip zero padding at the end of the .reloc section + // + if (!KeepZeroPendingFlag && Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) { + if (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++, SectionHeader++) { + // + // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory + // + if (SectionHeader->VirtualAddress == Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) { + SectionHeader->Misc.VirtualSize = Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size; + AllignedRelocSize = (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size + Optional64->FileAlignment - 1) & (~(Optional64->FileAlignment - 1)); + // + // Check to see if there is zero padding at the end of the base relocations + // + if (AllignedRelocSize < SectionHeader->SizeOfRawData) { + // + // Check to see if the base relocations are at the end of the file + // + if (SectionHeader->PointerToRawData + SectionHeader->SizeOfRawData == Optional64->SizeOfImage) { + // + // All the required conditions are met to strip the zero padding of the end of the base relocations section + // + Optional64->SizeOfImage -= (SectionHeader->SizeOfRawData - AllignedRelocSize); + Optional64->SizeOfInitializedData -= (SectionHeader->SizeOfRawData - AllignedRelocSize); + SectionHeader->SizeOfRawData = AllignedRelocSize; + FileLength = Optional64->SizeOfImage; + DebugMsg (NULL, 0, 9, "Remove the zero padding bytes at the end of the base relocations", "The size of padding bytes is %u", (unsigned) (SectionHeader->SizeOfRawData - AllignedRelocSize)); + } + } + } + } + } + } + } else { + Error (NULL, 0, 3000, "Invalid", "Magic 0x%x of PeImage %s is unknown.", PeHdr->Pe32.OptionalHeader.Magic, mInImageName); + goto Finish; + } + + if (((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) == 0) && \ + (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress == 0) && \ + (TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size == 0)) { + // + // PeImage can be loaded into memory, but it has no relocation section. + // Fix TeImage Header to set VA of relocation data directory to not zero, the size is still zero. + // + if (Optional32 != NULL) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional32->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION); + } else if (Optional64 != NULL) { + TEImageHeader.DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress = Optional64->SizeOfImage - sizeof (EFI_IMAGE_BASE_RELOCATION); + } + } + + // + // Fill HII section data + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) { + if (stricmp ((char *)SectionHeader[Index].Name, ".hii") == 0) { + // + // Update resource section header offset + // + SetHiiResourceHeader ((UINT8*) FileBuffer + SectionHeader[Index].PointerToRawData, SectionHeader[Index].VirtualAddress); + // + // Update resource section name + // + strcpy((char *) SectionHeader[Index].Name, ".rsrc"); + // + // Update resource data directory. + // + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader; + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress; + Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize; + } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader; + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = SectionHeader[Index].VirtualAddress; + Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = SectionHeader[Index].Misc.VirtualSize; + } + break; + } + } + + // + // Zero ExceptionTable Xdata + // + if (!KeepExceptionTableFlag) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) &(PeHdr->Pe32.OptionalHeader) + PeHdr->Pe32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->Pe32.FileHeader.NumberOfSections; Index++) { + if (stricmp ((char *)SectionHeader[Index].Name, ".xdata") == 0) { + // + // zero .xdata section + // + memset (FileBuffer + SectionHeader[Index].PointerToRawData, 0, SectionHeader[Index].SizeOfRawData); + DebugMsg (NULL, 0, 9, NULL, "Zero the .xdata section for PE image at Offset 0x%x and Length 0x%x", (unsigned) SectionHeader[Index].PointerToRawData, (unsigned) SectionHeader[Index].SizeOfRawData); + break; + } + } + } + + // + // Zero Time/Data field + // + ZeroDebugData (FileBuffer, ZeroDebugFlag); + + if (mOutImageType == FW_TE_IMAGE) { + if ((PeHdr->Pe32.FileHeader.NumberOfSections &~0xFF) || (Type &~0xFF)) { + // + // Pack the subsystem and NumberOfSections into 1 byte. Make sure they fit both. + // + Error (NULL, 0, 3000, "Invalid", "Image's subsystem or NumberOfSections of PeImage %s cannot be packed into 1 byte.", mInImageName); + goto Finish; + } + + if ((PeHdr->Pe32.OptionalHeader.SectionAlignment != PeHdr->Pe32.OptionalHeader.FileAlignment)) { + // + // TeImage has the same section alignment and file alignment. + // + Error (NULL, 0, 3000, "Invalid", "Section-Alignment and File-Alignment of PeImage %s do not match, they must be equal for a TeImage.", mInImageName); + goto Finish; + } + + DebugMsg (NULL, 0, 9, "TeImage Header Info", "Machine type is %X, Number of sections is %X, Stripped size is %X, EntryPoint is %X, BaseOfCode is %X, ImageBase is %llX", + TEImageHeader.Machine, TEImageHeader.NumberOfSections, TEImageHeader.StrippedSize, (unsigned) TEImageHeader.AddressOfEntryPoint, (unsigned) TEImageHeader.BaseOfCode, (unsigned long long) TEImageHeader.ImageBase); + // + // Update Image to TeImage + // + FileLength = FileLength - TEImageHeader.StrippedSize; + memmove (FileBuffer + sizeof (EFI_TE_IMAGE_HEADER), FileBuffer + TEImageHeader.StrippedSize, FileLength); + FileLength = FileLength + sizeof (EFI_TE_IMAGE_HEADER); + memcpy (FileBuffer, &TEImageHeader, sizeof (EFI_TE_IMAGE_HEADER)); + VerboseMsg ("the size of output file is %u bytes", (unsigned) (FileLength)); + } else { + + // + // Following codes are to fix the objcopy's issue: + // objcopy in binutil 2.50.18 will set PE image's charactices to "RELOC_STRIPPED" if image has no ".reloc" section + // It cause issue for EFI image which has no ".reloc" sections. + // Following codes will be removed when objcopy in binutil fix this problem for PE image. + // + if ((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0) { + if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->Pe32.OptionalHeader; + if (Optional32->ImageBase == 0) { + PeHdr->Pe32.FileHeader.Characteristics &= ~EFI_IMAGE_FILE_RELOCS_STRIPPED; + } + } else if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->Pe32.OptionalHeader; + if (Optional64->ImageBase == 0) { + PeHdr->Pe32.FileHeader.Characteristics &= ~EFI_IMAGE_FILE_RELOCS_STRIPPED; + } + } + } + } + +WriteFile: + // + // Update Image to EfiImage or TE image + // + if (ReplaceFlag) { + if ((FileLength != InputFileLength) || (memcmp (FileBuffer, InputFileBuffer, FileLength) != 0)) { + // + // Update File when File is changed. + // + fpInOut = fopen (LongFilePath (mInImageName), "wb"); + if (fpInOut == NULL) { + Error (NULL, 0, 0001, "Error opening file", mInImageName); + goto Finish; + } + fwrite (FileBuffer, 1, FileLength, fpInOut); + VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength); + } + } else { + if ((OutputFileTime < InputFileTime) || (FileLength != OutputFileLength) || (memcmp (FileBuffer, OutputFileBuffer, FileLength) != 0)) { + // + // Update File when File is changed or File is old. + // + fpOut = fopen (LongFilePath (OutImageName), "wb"); + if (fpOut == NULL) { + Error (NULL, 0, 0001, "Error opening output file", OutImageName); + goto Finish; + } + fwrite (FileBuffer, 1, FileLength, fpOut); + VerboseMsg ("the size of output file is %u bytes", (unsigned) FileLength); + } + } + mImageSize = FileLength; + +Finish: + if (fpInOut != NULL) { + if (GetUtilityStatus () != STATUS_SUCCESS) { + // + // when file updates failed, original file is still recovered. + // + fwrite (InputFileBuffer, 1, InputFileLength, fpInOut); + } + // + // Write converted data into fpInOut file and close input file. + // + fclose (fpInOut); + } + + if (FileBuffer != NULL) { + free (FileBuffer); + } + + if (InputFileName != NULL) { + free (InputFileName); + } + + if (fpOut != NULL) { + // + // Write converted data into fpOut file and close output file. + // + fclose (fpOut); + if (GetUtilityStatus () != STATUS_SUCCESS) { + if (OutputFileBuffer == NULL) { + remove (OutImageName); + } else { + fpOut = fopen (LongFilePath (OutImageName), "wb"); + fwrite (OutputFileBuffer, 1, OutputFileLength, fpOut); + fclose (fpOut); + } + } + } + + if (InputFileBuffer != NULL) { + free (InputFileBuffer); + } + + if (OutputFileBuffer != NULL) { + free (OutputFileBuffer); + } + + // + // Write module size and time stamp to report file. + // + if (OutImageName != NULL) { + FileLen = strlen (OutImageName); + } + if (FileLen >= 4 && strcmp (OutImageName + (FileLen - 4), ".efi") == 0) { + ReportFileName = (CHAR8 *) malloc (FileLen + 1); + if (ReportFileName != NULL) { + strcpy (ReportFileName, OutImageName); + strcpy (ReportFileName + (FileLen - 4), ".txt"); + ReportFile = fopen (LongFilePath (ReportFileName), "w+"); + if (ReportFile != NULL) { + fprintf (ReportFile, "MODULE_SIZE = %u\n", (unsigned) mImageSize); + fprintf (ReportFile, "TIME_STAMP = %u\n", (unsigned) mImageTimeStamp); + fclose(ReportFile); + } + free (ReportFileName); + } + } + VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ()); + + return GetUtilityStatus (); +} + +STATIC +EFI_STATUS +ZeroDebugData ( + IN OUT UINT8 *FileBuffer, + BOOLEAN ZeroDebugFlag + ) +/*++ + +Routine Description: + + Zero debug information in PeImage. + +Arguments: + + FileBuffer - Pointer to PeImage. + ZeroDebugFlag - TRUE to zero Debug information, FALSE to only zero time/stamp + +Returns: + + EFI_ABORTED - PeImage is invalid. + EFI_SUCCESS - Zero debug data successfully. + +--*/ +{ + UINT32 Index; + UINT32 DebugDirectoryEntryRva; + UINT32 DebugDirectoryEntrySize; + UINT32 DebugDirectoryEntryFileOffset; + UINT32 ExportDirectoryEntryRva; + UINT32 ExportDirectoryEntryFileOffset; + UINT32 ResourceDirectoryEntryRva; + UINT32 ResourceDirectoryEntryFileOffset; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_FILE_HEADER *FileHdr; + EFI_IMAGE_OPTIONAL_HEADER32 *Optional32Hdr; + EFI_IMAGE_OPTIONAL_HEADER64 *Optional64Hdr; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry; + EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY *RsdsEntry; + UINT32 *NewTimeStamp; + + // + // Init variable. + // + DebugDirectoryEntryRva = 0; + DebugDirectoryEntrySize = 0; + ExportDirectoryEntryRva = 0; + ResourceDirectoryEntryRva = 0; + DebugDirectoryEntryFileOffset = 0; + ExportDirectoryEntryFileOffset = 0; + ResourceDirectoryEntryFileOffset = 0; + DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer; + FileHdr = (EFI_IMAGE_FILE_HEADER *) (FileBuffer + DosHdr->e_lfanew + sizeof (UINT32)); + + + DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer; + if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + // NO DOS header, must start with PE/COFF header + FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32)); + } else { + FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32)); + } + + // + // Get Debug, Export and Resource EntryTable RVA address. + // Resource Directory entry need to review. + // + Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER)); + Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER)); + if (Optional32Hdr->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr + FileHdr->SizeOfOptionalHeader); + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) { + ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + } + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) { + ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; + } + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) { + DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + DebugDirectoryEntrySize = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size; + if (ZeroDebugFlag) { + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0; + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0; + } + } + } else { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr + FileHdr->SizeOfOptionalHeader); + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) { + ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + } + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) { + ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; + } + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) { + DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + DebugDirectoryEntrySize = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size; + if (ZeroDebugFlag) { + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = 0; + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress = 0; + } + } + } + + // + // Get DirectoryEntryTable file offset. + // + for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) { + if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress && + DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + DebugDirectoryEntryFileOffset = + DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress && + ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + ExportDirectoryEntryFileOffset = + ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress && + ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + ResourceDirectoryEntryFileOffset = + ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + } + + // + //Zero Debug Data and TimeStamp + // + FileHdr->TimeDateStamp = 0; + mImageTimeStamp = 0; + if (ExportDirectoryEntryFileOffset != 0) { + NewTimeStamp = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32)); + *NewTimeStamp = 0; + } + + if (ResourceDirectoryEntryFileOffset != 0) { + NewTimeStamp = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32)); + *NewTimeStamp = 0; + } + + if (DebugDirectoryEntryFileOffset != 0) { + DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (FileBuffer + DebugDirectoryEntryFileOffset); + Index = 0; + for (Index=0; Index < DebugDirectoryEntrySize / sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); Index ++, DebugEntry ++) { + DebugEntry->TimeDateStamp = 0; + if (mIsConvertXip) { + DebugEntry->FileOffset = DebugEntry->RVA; + } + if (ZeroDebugFlag || DebugEntry->Type != EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + memset (FileBuffer + DebugEntry->FileOffset, 0, DebugEntry->SizeOfData); + memset (DebugEntry, 0, sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)); + } + if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) { + RsdsEntry = (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY *) (FileBuffer + DebugEntry->FileOffset); + if (RsdsEntry->Signature == CODEVIEW_SIGNATURE_MTOC) { + // MTOC sets DebugDirectoryEntrySize to size of the .debug section, so fix it. + if (!ZeroDebugFlag) { + if (Optional32Hdr->Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + } else { + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); + } + } + break; + } + } + } + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +SetStamp ( + IN OUT UINT8 *FileBuffer, + IN CHAR8 *TimeStamp + ) +/*++ + +Routine Description: + + Set new time stamp into PeImage FileHdr and Directory table: + Debug, Export and Resource. + +Arguments: + + FileBuffer - Pointer to PeImage. + TimeStamp - Time stamp string. + +Returns: + + EFI_INVALID_PARAMETER - TimeStamp format is not recognized. + EFI_SUCCESS - Set new time stamp in this image successfully. + +--*/ +{ + struct tm stime; + struct tm *ptime; + time_t newtime; + UINT32 Index; + UINT32 DebugDirectoryEntryRva; + UINT32 DebugDirectoryEntryFileOffset; + UINT32 ExportDirectoryEntryRva; + UINT32 ExportDirectoryEntryFileOffset; + UINT32 ResourceDirectoryEntryRva; + UINT32 ResourceDirectoryEntryFileOffset; + EFI_IMAGE_DOS_HEADER *DosHdr; + EFI_IMAGE_FILE_HEADER *FileHdr; + EFI_IMAGE_OPTIONAL_HEADER32 *Optional32Hdr; + EFI_IMAGE_OPTIONAL_HEADER64 *Optional64Hdr; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + UINT32 *NewTimeStamp; + + // + // Init variable. + // + DebugDirectoryEntryRva = 0; + DebugDirectoryEntryFileOffset = 0; + ExportDirectoryEntryRva = 0; + ExportDirectoryEntryFileOffset = 0; + ResourceDirectoryEntryRva = 0; + ResourceDirectoryEntryFileOffset = 0; + // + // Get time and date that will be set. + // + if (TimeStamp == NULL) { + Error (NULL, 0, 3000, "Invalid", "TimeStamp cannot be NULL."); + return EFI_INVALID_PARAMETER; + } + // + // compare the value with "NOW", if yes, current system time is set. + // + if (stricmp (TimeStamp, "NOW") == 0) { + // + // get system current time and date + // + time (&newtime); + } else { + // + // Check Time Format strictly yyyy-mm-dd 00:00:00 + // + for (Index = 0; TimeStamp[Index] != '\0' && Index < 20; Index ++) { + if (Index == 4 || Index == 7) { + if (TimeStamp[Index] == '-') { + continue; + } + } else if (Index == 13 || Index == 16) { + if (TimeStamp[Index] == ':') { + continue; + } + } else if (Index == 10 && TimeStamp[Index] == ' ') { + continue; + } else if ((TimeStamp[Index] < '0') || (TimeStamp[Index] > '9')) { + break; + } + } + + if (Index < 19 || TimeStamp[19] != '\0') { + Error (NULL, 0, 1003, "Invalid option value", "Incorrect Time \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp); + return EFI_INVALID_PARAMETER; + } + + // + // get the date and time from TimeStamp + // + if (sscanf (TimeStamp, "%d-%d-%d %d:%d:%d", + &stime.tm_year, + &stime.tm_mon, + &stime.tm_mday, + &stime.tm_hour, + &stime.tm_min, + &stime.tm_sec + ) != 6) { + Error (NULL, 0, 1003, "Invalid option value", "Incorrect Tiem \"%s\"\n Correct Format \"yyyy-mm-dd 00:00:00\"", TimeStamp); + return EFI_INVALID_PARAMETER; + } + + // + // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it + // + if (stime.tm_mon <= 0 || stime.tm_mday <=0) { + Error (NULL, 0, 3000, "Invalid", "%s Invalid date!", TimeStamp); + return EFI_INVALID_PARAMETER; + } + stime.tm_mon -= 1; + + // + // in struct, Year (current year minus 1900) + // and only the dates can be handled from Jan 1, 1970 to Jan 18, 2038 + // + // + // convert 0 -> 100 (2000), 1 -> 101 (2001), ..., 38 -> 138 (2038) + // + if (stime.tm_year >= 1970 && stime.tm_year <= 2038) { + // + // convert 1970 -> 70, 2000 -> 100, ... + // + stime.tm_year -= 1900; + } else { + Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp); + return EFI_INVALID_PARAMETER; + } + + // + // convert the date and time to time_t format + // + newtime = mktime (&stime); + if (newtime == (time_t) - 1) { + Error (NULL, 0, 3000, "Invalid", "%s Invalid or unsupported datetime!", TimeStamp); + return EFI_INVALID_PARAMETER; + } + } + + ptime = localtime (&newtime); + if (ptime != NULL) { + DebugMsg (NULL, 0, 9, "New Image Time Stamp", "%04d-%02d-%02d %02d:%02d:%02d", + ptime->tm_year + 1900, ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour, ptime->tm_min, ptime->tm_sec); + } + // + // Set new time and data into PeImage. + // + DosHdr = (EFI_IMAGE_DOS_HEADER *)FileBuffer; + if (DosHdr->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + // NO DOS header, must start with PE/COFF header + FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + sizeof (UINT32)); + } else { + FileHdr = (EFI_IMAGE_FILE_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof (UINT32)); + } + + // + // Get Debug, Export and Resource EntryTable RVA address. + // Resource Directory entry need to review. + // + if (FileHdr->Machine == EFI_IMAGE_MACHINE_IA32) { + Optional32Hdr = (EFI_IMAGE_OPTIONAL_HEADER32 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER)); + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional32Hdr + FileHdr->SizeOfOptionalHeader); + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) { + ExportDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + } + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) { + ResourceDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; + } + if (Optional32Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \ + Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) { + DebugDirectoryEntryRva = Optional32Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + } + } else { + Optional64Hdr = (EFI_IMAGE_OPTIONAL_HEADER64 *) ((UINT8*) FileHdr + sizeof (EFI_IMAGE_FILE_HEADER)); + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ((UINT8 *) Optional64Hdr + FileHdr->SizeOfOptionalHeader); + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_EXPORT && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].Size != 0) { + ExportDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress; + } + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].Size != 0) { + ResourceDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress; + } + if (Optional64Hdr->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_DEBUG && \ + Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].Size != 0) { + DebugDirectoryEntryRva = Optional64Hdr->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress; + } + } + + // + // Get DirectoryEntryTable file offset. + // + for (Index = 0; Index < FileHdr->NumberOfSections; Index ++, SectionHeader ++) { + if (DebugDirectoryEntryRva >= SectionHeader->VirtualAddress && + DebugDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + DebugDirectoryEntryFileOffset = + DebugDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + if (ExportDirectoryEntryRva >= SectionHeader->VirtualAddress && + ExportDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + ExportDirectoryEntryFileOffset = + ExportDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + if (ResourceDirectoryEntryRva >= SectionHeader->VirtualAddress && + ResourceDirectoryEntryRva < SectionHeader->VirtualAddress + SectionHeader->Misc.VirtualSize) { + ResourceDirectoryEntryFileOffset = + ResourceDirectoryEntryRva - SectionHeader->VirtualAddress + SectionHeader->PointerToRawData; + } + } + + // + // Set new stamp + // + FileHdr->TimeDateStamp = (UINT32) newtime; + mImageTimeStamp = (UINT32) newtime; + if (ExportDirectoryEntryRva != 0) { + NewTimeStamp = (UINT32 *) (FileBuffer + ExportDirectoryEntryFileOffset + sizeof (UINT32)); + *NewTimeStamp = (UINT32) newtime; + } + + if (ResourceDirectoryEntryRva != 0) { + NewTimeStamp = (UINT32 *) (FileBuffer + ResourceDirectoryEntryFileOffset + sizeof (UINT32)); + *NewTimeStamp = (UINT32) newtime; + } + + if (DebugDirectoryEntryRva != 0) { + NewTimeStamp = (UINT32 *) (FileBuffer + DebugDirectoryEntryFileOffset + sizeof (UINT32)); + *NewTimeStamp = (UINT32) newtime; + } + + return EFI_SUCCESS; +} + +STATIC +STATUS +MicrocodeReadData ( + FILE *InFptr, + UINT32 *Data + ) +/*++ + +Routine Description: + Read a 32-bit microcode data value from a text file and convert to raw binary form. + +Arguments: + InFptr - file pointer to input text file + Data - pointer to where to return the data parsed + +Returns: + STATUS_SUCCESS - no errors or warnings, Data contains valid information + STATUS_ERROR - errors were encountered + +--*/ +{ + CHAR8 Line[MAX_LINE_LEN]; + CHAR8 *cptr; + int ScannedData = 0; + + Line[MAX_LINE_LEN - 1] = 0; + while (1) { + if (fgets (Line, MAX_LINE_LEN, InFptr) == NULL) { + return STATUS_ERROR; + } + // + // If it was a binary file, then it may have overwritten our null terminator + // + if (Line[MAX_LINE_LEN - 1] != 0) { + return STATUS_ERROR; + } + + // + // strip space + // + for (cptr = Line; *cptr && isspace((int)*cptr); cptr++) { + } + + // Skip Blank Lines and Comment Lines + if ((strlen(cptr) != 0) && (*cptr != ';')) { + break; + } + } + + // Look for + // dd 000000001h ; comment + // dd XXXXXXXX + // DD XXXXXXXXX + // DD XXXXXXXXX + // + if ((tolower((int)cptr[0]) == 'd') && (tolower((int)cptr[1]) == 'd') && isspace ((int)cptr[2])) { + // + // Skip blanks and look for a hex digit + // + cptr += 3; + for (; *cptr && isspace((int)*cptr); cptr++) { + } + if (isxdigit ((int)*cptr)) { + if (sscanf (cptr, "%X", &ScannedData) != 1) { + return STATUS_ERROR; + } + } + *Data = (UINT32) ScannedData; + return STATUS_SUCCESS; + } + + return STATUS_ERROR; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.h new file mode 100644 index 00000000..ff206497 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/GenFw.h @@ -0,0 +1,50 @@ +/** @file +Header file for GenFw + +Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _GEN_FW_H_ +#define _GEN_FW_H_ + +// +// Action for this tool. +// +#define FW_DUMMY_IMAGE 0 +#define FW_EFI_IMAGE 1 +#define FW_TE_IMAGE 2 +#define FW_ACPI_IMAGE 3 +#define FW_BIN_IMAGE 4 +#define FW_ZERO_DEBUG_IMAGE 5 +#define FW_SET_STAMP_IMAGE 6 +#define FW_MCI_IMAGE 7 +#define FW_MERGE_IMAGE 8 +#define FW_RELOC_STRIPEED_IMAGE 9 +#define FW_HII_PACKAGE_LIST_RCIMAGE 10 +#define FW_HII_PACKAGE_LIST_BINIMAGE 11 +#define FW_REBASE_IMAGE 12 +#define FW_SET_ADDRESS_IMAGE 13 + +#define DUMP_TE_HEADER 0x11 + +VOID +SetHiiResourceHeader ( + UINT8 *HiiBinData, + UINT32 OffsetToFile + ); + +INTN +IsElfHeader ( + UINT8 *FileBuffer + ); + +BOOLEAN +ConvertElf ( + UINT8 **FileBuffer, + UINT32 *FileLength + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Makefile new file mode 100644 index 00000000..193bf3dc --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Makefile @@ -0,0 +1,18 @@ +## @file +# Windows makefile for 'GenFw' module build. +# +# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenFw + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = GenFw.obj ElfConvert.obj Elf32Convert.obj Elf64Convert.obj + +#CFLAGS = $(CFLAGS) /nodefaultlib:libc.lib + +!INCLUDE ..\Makefiles\ms.app + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Makefile.kmk new file mode 100644 index 00000000..5beae65a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/Makefile.kmk @@ -0,0 +1,49 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-makefile for the EFI GenFw build tool. +# + +# +# Copyright (C) 2013-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# 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, in version 3 of the +# License. +# +# 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 . +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +SUB_DEPTH = ../../../../../../../../.. +include $(KBUILD_PATH)/subheader.kmk + +BLDPROGS += GenFw +GenFw_TEMPLATE = VBoxEfiBldProg +GenFw_SOURCES = \ + GenFw.c \ + ElfConvert.c \ + Elf32Convert.c \ + Elf64Convert.c + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf32.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf32.h new file mode 100644 index 00000000..8795fab4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf32.h @@ -0,0 +1,252 @@ +/** @file +Ported ELF include files from FreeBSD + +Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.2 2007/12/03 21:30:36 marius Exp $ + */ + +#ifndef _SYS_ELF32_H_ +#define _SYS_ELF32_H_ 1 + + +/* + * ELF definitions common to all 32-bit architectures. + */ + +typedef UINT32 Elf32_Addr; +typedef UINT16 Elf32_Half; +typedef UINT32 Elf32_Off; +typedef INT32 Elf32_Sword; +typedef UINT32 Elf32_Word; +typedef UINT64 Elf32_Lword; + +typedef Elf32_Word Elf32_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf32_Word Elf32_Size; +typedef Elf32_Sword Elf32_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf32_Half e_type; /* File type. */ + Elf32_Half e_machine; /* Machine architecture. */ + Elf32_Word e_version; /* ELF format version. */ + Elf32_Addr e_entry; /* Entry point. */ + Elf32_Off e_phoff; /* Program header file offset. */ + Elf32_Off e_shoff; /* Section header file offset. */ + Elf32_Word e_flags; /* Architecture-specific flags. */ + Elf32_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf32_Half e_phentsize; /* Size of program header entry. */ + Elf32_Half e_phnum; /* Number of program header entries. */ + Elf32_Half e_shentsize; /* Size of section header entry. */ + Elf32_Half e_shnum; /* Number of section header entries. */ + Elf32_Half e_shstrndx; /* Section name strings section. */ +} Elf32_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf32_Word sh_name; /* Section name (index into the + section header string table). */ + Elf32_Word sh_type; /* Section type. */ + Elf32_Word sh_flags; /* Section flags. */ + Elf32_Addr sh_addr; /* Address in memory image. */ + Elf32_Off sh_offset; /* Offset in file. */ + Elf32_Word sh_size; /* Size in bytes. */ + Elf32_Word sh_link; /* Index of a related section. */ + Elf32_Word sh_info; /* Depends on section type. */ + Elf32_Word sh_addralign; /* Alignment in bytes. */ + Elf32_Word sh_entsize; /* Size of each entry in section. */ +} Elf32_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf32_Word p_type; /* Entry type. */ + Elf32_Off p_offset; /* File offset of contents. */ + Elf32_Addr p_vaddr; /* Virtual address in memory image. */ + Elf32_Addr p_paddr; /* Physical address (not used). */ + Elf32_Word p_filesz; /* Size of contents in file. */ + Elf32_Word p_memsz; /* Size of contents in memory. */ + Elf32_Word p_flags; /* Access permission flags. */ + Elf32_Word p_align; /* Alignment in memory and file. */ +} Elf32_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf32_Sword d_tag; /* Entry type. */ + union { + Elf32_Word d_val; /* Integer value. */ + Elf32_Addr d_ptr; /* Address value. */ + } d_un; +} Elf32_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ +} Elf32_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ + Elf32_Sword r_addend; /* Addend. */ +} Elf32_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF32_R_SYM(info) ((info) >> 8) +#define ELF32_R_TYPE(info) ((unsigned char)(info)) + +/* Macro for constructing r_info from field values. */ +#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf32_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf32_Lword m_value; /* symbol value */ + Elf32_Word m_info; /* size + index */ + Elf32_Word m_poffset; /* symbol offset */ + Elf32_Half m_repeat; /* repeat count */ + Elf32_Half m_stride; /* stride info */ +} Elf32_Move; + +/* + * The macros compose and decompose values for Move.r_info + * + * sym = ELF32_M_SYM(M.m_info) + * size = ELF32_M_SIZE(M.m_info) + * M.m_info = ELF32_M_INFO(sym, size) + */ +#define ELF32_M_SYM(info) ((info)>>8) +#define ELF32_M_SIZE(info) ((unsigned char)(info)) +#define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf32_Word c_tag; /* how to interpret value */ + union { + Elf32_Word c_val; + Elf32_Addr c_ptr; + } c_un; +} Elf32_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf32_Word st_name; /* String table index of name. */ + Elf32_Addr st_value; /* Symbol value. */ + Elf32_Word st_size; /* Size of associated object. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf32_Half st_shndx; /* Section index of symbol. */ +} Elf32_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF32_ST_BIND(info) ((info) >> 4) +#define ELF32_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU symbol versioning. */ +typedef struct +{ + Elf32_Half vd_version; + Elf32_Half vd_flags; + Elf32_Half vd_ndx; + Elf32_Half vd_cnt; + Elf32_Word vd_hash; + Elf32_Word vd_aux; + Elf32_Word vd_next; +} Elf32_Verdef; + +typedef struct +{ + Elf32_Word vda_name; + Elf32_Word vda_next; +} Elf32_Verdaux; + +typedef struct +{ + Elf32_Half vn_version; + Elf32_Half vn_cnt; + Elf32_Word vn_file; + Elf32_Word vn_aux; + Elf32_Word vn_next; +} Elf32_Verneed; + +typedef struct +{ + Elf32_Word vna_hash; + Elf32_Half vna_flags; + Elf32_Half vna_other; + Elf32_Word vna_name; + Elf32_Word vna_next; +} Elf32_Vernaux; + +typedef Elf32_Half Elf32_Versym; + +typedef struct { + Elf32_Half si_boundto; /* direct bindings - symbol bound to */ + Elf32_Half si_flags; /* per symbol flags */ +} Elf32_Syminfo; + +#endif /* !_SYS_ELF32_H_ */ diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf64.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf64.h new file mode 100644 index 00000000..8dc10f6b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf64.h @@ -0,0 +1,254 @@ +/** @file +Ported ELF include files from FreeBSD + +Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.2 2007/12/03 21:30:36 marius Exp $ + */ + +#ifndef _SYS_ELF64_H_ +#define _SYS_ELF64_H_ 1 + + +/* + * ELF definitions common to all 64-bit architectures. + */ + +typedef UINT64 Elf64_Addr; +typedef UINT16 Elf64_Half; +typedef UINT64 Elf64_Off; +typedef INT32 Elf64_Sword; +typedef INT64 Elf64_Sxword; +typedef UINT32 Elf64_Word; +typedef UINT64 Elf64_Lword; +typedef UINT64 Elf64_Xword; + +/* + * Types of dynamic symbol hash table bucket and chain elements. + * + * This is inconsistent among 64 bit architectures, so a machine dependent + * typedef is required. + */ + +typedef Elf64_Word Elf64_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf64_Xword Elf64_Size; +typedef Elf64_Sxword Elf64_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf64_Half e_type; /* File type. */ + Elf64_Half e_machine; /* Machine architecture. */ + Elf64_Word e_version; /* ELF format version. */ + Elf64_Addr e_entry; /* Entry point. */ + Elf64_Off e_phoff; /* Program header file offset. */ + Elf64_Off e_shoff; /* Section header file offset. */ + Elf64_Word e_flags; /* Architecture-specific flags. */ + Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf64_Half e_phentsize; /* Size of program header entry. */ + Elf64_Half e_phnum; /* Number of program header entries. */ + Elf64_Half e_shentsize; /* Size of section header entry. */ + Elf64_Half e_shnum; /* Number of section header entries. */ + Elf64_Half e_shstrndx; /* Section name strings section. */ +} Elf64_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf64_Word sh_name; /* Section name (index into the + section header string table). */ + Elf64_Word sh_type; /* Section type. */ + Elf64_Xword sh_flags; /* Section flags. */ + Elf64_Addr sh_addr; /* Address in memory image. */ + Elf64_Off sh_offset; /* Offset in file. */ + Elf64_Xword sh_size; /* Size in bytes. */ + Elf64_Word sh_link; /* Index of a related section. */ + Elf64_Word sh_info; /* Depends on section type. */ + Elf64_Xword sh_addralign; /* Alignment in bytes. */ + Elf64_Xword sh_entsize; /* Size of each entry in section. */ +} Elf64_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf64_Word p_type; /* Entry type. */ + Elf64_Word p_flags; /* Access permission flags. */ + Elf64_Off p_offset; /* File offset of contents. */ + Elf64_Addr p_vaddr; /* Virtual address in memory image. */ + Elf64_Addr p_paddr; /* Physical address (not used). */ + Elf64_Xword p_filesz; /* Size of contents in file. */ + Elf64_Xword p_memsz; /* Size of contents in memory. */ + Elf64_Xword p_align; /* Alignment in memory and file. */ +} Elf64_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf64_Sxword d_tag; /* Entry type. */ + union { + Elf64_Xword d_val; /* Integer value. */ + Elf64_Addr d_ptr; /* Address value. */ + } d_un; +} Elf64_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ +} Elf64_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ + Elf64_Sxword r_addend; /* Addend. */ +} Elf64_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF64_R_SYM(info) ((info) >> 32) +#define ELF64_R_TYPE(info) ((info) & 0xffffffffL) + +/* Macro for constructing r_info from field values. */ +#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL)) + +#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40) +#define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56) +#define ELF64_R_TYPE_INFO(data, type) \ + (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf64_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf64_Lword m_value; /* symbol value */ + Elf64_Xword m_info; /* size + index */ + Elf64_Xword m_poffset; /* symbol offset */ + Elf64_Half m_repeat; /* repeat count */ + Elf64_Half m_stride; /* stride info */ +} Elf64_Move; + +#define ELF64_M_SYM(info) ((info)>>8) +#define ELF64_M_SIZE(info) ((unsigned char)(info)) +#define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf64_Xword c_tag; /* how to interpret value */ + union { + Elf64_Xword c_val; + Elf64_Addr c_ptr; + } c_un; +} Elf64_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf64_Word st_name; /* String table index of name. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf64_Half st_shndx; /* Section index of symbol. */ + Elf64_Addr st_value; /* Symbol value. */ + Elf64_Xword st_size; /* Size of associated object. */ +} Elf64_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF64_ST_BIND(info) ((info) >> 4) +#define ELF64_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU-style symbol versioning. */ +typedef struct { + Elf64_Half vd_version; + Elf64_Half vd_flags; + Elf64_Half vd_ndx; + Elf64_Half vd_cnt; + Elf64_Word vd_hash; + Elf64_Word vd_aux; + Elf64_Word vd_next; +} Elf64_Verdef; + +typedef struct { + Elf64_Word vda_name; + Elf64_Word vda_next; +} Elf64_Verdaux; + +typedef struct { + Elf64_Half vn_version; + Elf64_Half vn_cnt; + Elf64_Word vn_file; + Elf64_Word vn_aux; + Elf64_Word vn_next; +} Elf64_Verneed; + +typedef struct { + Elf64_Word vna_hash; + Elf64_Half vna_flags; + Elf64_Half vna_other; + Elf64_Word vna_name; + Elf64_Word vna_next; +} Elf64_Vernaux; + +typedef Elf64_Half Elf64_Versym; + +typedef struct { + Elf64_Half si_boundto; /* direct bindings - symbol bound to */ + Elf64_Half si_flags; /* per symbol flags */ +} Elf64_Syminfo; + +#endif /* !_SYS_ELF64_H_ */ diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf_common.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf_common.h new file mode 100644 index 00000000..8bbf7596 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenFw/elf_common.h @@ -0,0 +1,1045 @@ +/** @file +Ported ELF include files from FreeBSD + +Copyright (c) 2009 - 2010, Apple Inc. All rights reserved.
+Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+Portion Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + + +**/ +/*- + * Copyright (c) 1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD: src/sys/sys/elf_common.h,v 1.15.8.2 2007/12/03 21:30:36 marius Exp $ + */ + +#ifndef _SYS_ELF_COMMON_H_ +#define _SYS_ELF_COMMON_H_ 1 + +/* + * ELF definitions that are independent of architecture or word size. + */ + +/* + * Note header. The ".note" section contains an array of notes. Each + * begins with this header, aligned to a word boundary. Immediately + * following the note header is n_namesz bytes of name, padded to the + * next word boundary. Then comes n_descsz bytes of descriptor, again + * padded to a word boundary. The values of n_namesz and n_descsz do + * not include the padding. + */ + +typedef struct { + UINT32 n_namesz; /* Length of name. */ + UINT32 n_descsz; /* Length of descriptor. */ + UINT32 n_type; /* Type of this note. */ +} Elf_Note; + +/* Indexes into the e_ident array. Keep synced with + http://www.sco.com/developers/gabi/latest/ch4.eheader.html */ +#define EI_MAG0 0 /* Magic number, byte 0. */ +#define EI_MAG1 1 /* Magic number, byte 1. */ +#define EI_MAG2 2 /* Magic number, byte 2. */ +#define EI_MAG3 3 /* Magic number, byte 3. */ +#define EI_CLASS 4 /* Class of machine. */ +#define EI_DATA 5 /* Data format. */ +#define EI_VERSION 6 /* ELF format version. */ +#define EI_OSABI 7 /* Operating system / ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define OLD_EI_BRAND 8 /* Start of architecture identification. */ +#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ +#define EI_NIDENT 16 /* Size of e_ident array. */ + +/* Values for the magic number bytes. */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" /* magic string */ +#define SELFMAG 4 /* magic string size */ + +/* Values for e_ident[EI_VERSION] and e_version. */ +#define EV_NONE 0 +#define EV_CURRENT 1 + +/* Values for e_ident[EI_CLASS]. */ +#define ELFCLASSNONE 0 /* Unknown class. */ +#define ELFCLASS32 1 /* 32-bit architecture. */ +#define ELFCLASS64 2 /* 64-bit architecture. */ + +/* Values for e_ident[EI_DATA]. */ +#define ELFDATANONE 0 /* Unknown data format. */ +#define ELFDATA2LSB 1 /* 2's complement little-endian. */ +#define ELFDATA2MSB 2 /* 2's complement big-endian. */ + +/* Values for e_ident[EI_OSABI]. */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_OPENVMS 13 /* Open VMS */ +#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ +#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* Values for e_type. */ +#define ET_NONE 0 /* Unknown type. */ +#define ET_REL 1 /* Relocatable. */ +#define ET_EXEC 2 /* Executable. */ +#define ET_DYN 3 /* Shared object. */ +#define ET_CORE 4 /* Core file. */ +#define ET_LOOS 0xfe00 /* First operating system specific. */ +#define ET_HIOS 0xfeff /* Last operating system-specific. */ +#define ET_LOPROC 0xff00 /* First processor-specific. */ +#define ET_HIPROC 0xffff /* Last processor-specific. */ + +/* Values for e_machine. */ +#define EM_NONE 0 /* Unknown machine. */ +#define EM_M32 1 /* AT&T WE32100. */ +#define EM_SPARC 2 /* Sun SPARC. */ +#define EM_386 3 /* Intel i386. */ +#define EM_68K 4 /* Motorola 68000. */ +#define EM_88K 5 /* Motorola 88000. */ +#define EM_860 7 /* Intel i860. */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */ +#define EM_S370 9 /* IBM System/370. */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */ +#define EM_PARISC 15 /* HP PA-RISC. */ +#define EM_VPP500 17 /* Fujitsu VPP500. */ +#define EM_SPARC32PLUS 18 /* SPARC v8plus. */ +#define EM_960 19 /* Intel 80960. */ +#define EM_PPC 20 /* PowerPC 32-bit. */ +#define EM_PPC64 21 /* PowerPC 64-bit. */ +#define EM_S390 22 /* IBM System/390. */ +#define EM_V800 36 /* NEC V800. */ +#define EM_FR20 37 /* Fujitsu FR20. */ +#define EM_RH32 38 /* TRW RH-32. */ +#define EM_RCE 39 /* Motorola RCE. */ +#define EM_ARM 40 /* ARM. */ +#define EM_SH 42 /* Hitachi SH. */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit. */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */ +#define EM_ARC 45 /* Argonaut RISC Core. */ +#define EM_H8_300 46 /* Hitachi H8/300. */ +#define EM_H8_300H 47 /* Hitachi H8/300H. */ +#define EM_H8S 48 /* Hitachi H8S. */ +#define EM_H8_500 49 /* Hitachi H8/500. */ +#define EM_MIPS_X 51 /* Stanford MIPS-X. */ +#define EM_COLDFIRE 52 /* Motorola ColdFire. */ +#define EM_68HC12 53 /* Motorola M68HC12. */ +#define EM_MMA 54 /* Fujitsu MMA. */ +#define EM_PCP 55 /* Siemens PCP. */ +#define EM_NCPU 56 /* Sony nCPU. */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor. */ +#define EM_STARCORE 58 /* Motorola Star*Core processor. */ +#define EM_ME16 59 /* Toyota ME16 processor. */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor. */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */ +#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ +#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */ +#define EM_AARCH64 183 /* ARM 64bit Architecture */ +#define EM_RISCV64 243 /* 64bit RISC-V Architecture */ +#define EM_RISCV 244 /* 32bit RISC-V Architecture */ + +/* Non-standard or deprecated. */ +#define EM_486 6 /* Intel i486. */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ +#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ + +/* Special section indexes. */ +#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ +#define SHN_LORESERVE 0xff00 /* First of reserved range. */ +#define SHN_LOPROC 0xff00 /* First processor-specific. */ +#define SHN_HIPROC 0xff1f /* Last processor-specific. */ +#define SHN_LOOS 0xff20 /* First operating system-specific. */ +#define SHN_HIOS 0xff3f /* Last operating system-specific. */ +#define SHN_ABS 0xfff1 /* Absolute values. */ +#define SHN_COMMON 0xfff2 /* Common data. */ +#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ +#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends */ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relocation section - no addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ +#define SHT_FINI_ARRAY 15 /* Termination function pointers. */ +#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ +#define SHT_GROUP 17 /* Section group. */ +#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ +#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ +#define SHT_LOSUNW 0x6ffffff4 +#define SHT_SUNW_dof 0x6ffffff4 +#define SHT_SUNW_cap 0x6ffffff5 +#define SHT_SUNW_SIGNATURE 0x6ffffff6 +#define SHT_SUNW_ANNOTATE 0x6ffffff7 +#define SHT_SUNW_DEBUGSTR 0x6ffffff8 +#define SHT_SUNW_DEBUG 0x6ffffff9 +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_SUNW_verdef 0x6ffffffd +#define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */ +#define SHT_SUNW_verneed 0x6ffffffe +#define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */ +#define SHT_SUNW_versym 0x6fffffff +#define SHT_GNU_versym 0x6fffffff /* Symbol version table */ +#define SHT_HISUNW 0x6fffffff +#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Flags for sh_flags. */ +#define SHF_WRITE 0x1 /* Section contains writable data. */ +#define SHF_ALLOC 0x2 /* Section occupies memory. */ +#define SHF_EXECINSTR 0x4 /* Section contains instructions. */ +#define SHF_MERGE 0x10 /* Section may be merged. */ +#define SHF_STRINGS 0x20 /* Section contains strings. */ +#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */ +#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ +#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ +#define SHF_GROUP 0x200 /* Member of section group. */ +#define SHF_TLS 0x400 /* Section contains TLS data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ + +/* Values for p_type. */ +#define PT_NULL 0 /* Unused entry. */ +#define PT_LOAD 1 /* Loadable segment. */ +#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ +#define PT_INTERP 3 /* Pathname of interpreter. */ +#define PT_NOTE 4 /* Auxiliary information. */ +#define PT_SHLIB 5 /* Reserved (not used). */ +#define PT_PHDR 6 /* Location of program header itself. */ +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* First OS-specific. */ +#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */ +#define PT_GNU_EH_FRAME 0x6474e550 +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ +#define PT_SUNWDTRACE 0x6ffffffc /* private */ +#define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* Last OS-specific. */ +#define PT_LOPROC 0x70000000 /* First processor-specific type. */ +#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for p_flags. */ +#define PF_X 0x1 /* Executable. */ +#define PF_W 0x2 /* Writable. */ +#define PF_R 0x4 /* Readable. */ +#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific. */ + +/* Extended program header index. */ +#define PN_XNUM 0xffff + +/* Values for d_tag. */ +#define DT_NULL 0 /* Terminating entry. */ +#define DT_NEEDED 1 /* String table offset of a needed shared + library. */ +#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ +#define DT_PLTGOT 3 /* Processor-dependent address. */ +#define DT_HASH 4 /* Address of symbol hash table. */ +#define DT_STRTAB 5 /* Address of string table. */ +#define DT_SYMTAB 6 /* Address of symbol table. */ +#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ +#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ +#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ +#define DT_STRSZ 10 /* Size of string table. */ +#define DT_SYMENT 11 /* Size of each symbol table entry. */ +#define DT_INIT 12 /* Address of initialization function. */ +#define DT_FINI 13 /* Address of finalization function. */ +#define DT_SONAME 14 /* String table offset of shared object + name. */ +#define DT_RPATH 15 /* String table offset of library path. [sup] */ +#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ +#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ +#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ +#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ +#define DT_PLTREL 20 /* Type of relocation used for PLT. */ +#define DT_DEBUG 21 /* Reserved (not used). */ +#define DT_TEXTREL 22 /* Indicates there may be relocations in + non-writable segments. [sup] */ +#define DT_JMPREL 23 /* Address of PLT relocations. */ +#define DT_BIND_NOW 24 /* [sup] */ +#define DT_INIT_ARRAY 25 /* Address of the array of pointers to + initialization functions */ +#define DT_FINI_ARRAY 26 /* Address of the array of pointers to + termination functions */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of + initialization functions. */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of + terminationfunctions. */ +#define DT_RUNPATH 29 /* String table offset of a null-terminated + library search path string. */ +#define DT_FLAGS 30 /* Object specific flag values. */ +#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING + and less than DT_LOOS follow the rules for + the interpretation of the d_un union + as follows: even == 'd_ptr', even == 'd_val' + or none */ +#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to + pre-initialization functions. */ +#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of + pre-initialization functions. */ +#define DT_MAXPOSTAGS 34 /* number of positive tags */ +#define DT_LOOS 0x6000000d /* First OS-specific */ +#define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */ +#define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */ +#define DT_SUNW_FILTER 0x6000000f /* symbol filter name */ +#define DT_SUNW_CAP 0x60000010 /* hardware/software */ +#define DT_HIOS 0x6ffff000 /* Last OS-specific */ + +/* + * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + * Dyn.d_un.d_val field of the Elf*_Dyn structure. + */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */ +#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */ +#define DT_MOVEENT 0x6ffffdfa /* move table entry size */ +#define DT_MOVESZ 0x6ffffdfb /* move table size */ +#define DT_FEATURE_1 0x6ffffdfc /* feature holder */ +#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */ + /* the following DT_* entry. */ + /* See DF_P1_* definitions */ +#define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */ +#define DT_VALRNGHI 0x6ffffdff + +/* + * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + * Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + * + * If any adjustment is made to the ELF object after it has been + * built, these entries will need to be adjusted. + */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_CONFIG 0x6ffffefa /* configuration information */ +#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */ +#define DT_AUDIT 0x6ffffefc /* object auditing */ +#define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */ +#define DT_MOVETAB 0x6ffffefe /* move table */ +#define DT_SYMINFO 0x6ffffeff /* syminfo table */ +#define DT_ADDRRNGHI 0x6ffffeff + +#define DT_VERSYM 0x6ffffff0 /* Address of versym section. */ +#define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */ +#define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */ +#define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */ +#define DT_VERDEF 0x6ffffffc /* Address of verdef section. */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */ +#define DT_VERNEED 0x6ffffffe /* Address of verneed section. */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */ + +#define DT_LOPROC 0x70000000 /* First processor-specific type. */ +#define DT_DEPRECATED_SPARC_REGISTER 0x7000001 +#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */ +#define DT_USED 0x7ffffffe /* ignored - same as needed */ +#define DT_FILTER 0x7fffffff /* shared library filter name */ +#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for DT_FLAGS */ +#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may + make reference to the $ORIGIN substitution + string */ +#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ +#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in + non-writable segments. */ +#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should + process all relocations for the object + containing this entry before transferring + control to the program. */ +#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or + executable contains code using a static + thread-local storage scheme. */ + +/* Values for n_type. Used in core files. */ +#define NT_PRSTATUS 1 /* Process status. */ +#define NT_FPREGSET 2 /* Floating point registers. */ +#define NT_PRPSINFO 3 /* Process state info. */ + +/* Symbol Binding - ELFNN_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_LOOS 10 /* Reserved range for operating system */ +#define STB_HIOS 12 /* specific semantics. */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific semantics. */ + +/* Symbol type - ELFNN_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* Unspecified type. */ +#define STT_OBJECT 1 /* Data object. */ +#define STT_FUNC 2 /* Function. */ +#define STT_SECTION 3 /* Section. */ +#define STT_FILE 4 /* Source file. */ +#define STT_COMMON 5 /* Uninitialized common block. */ +#define STT_TLS 6 /* TLS object. */ +#define STT_NUM 7 +#define STT_LOOS 10 /* Reserved range for operating system */ +#define STT_HIOS 12 /* specific semantics. */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific semantics. */ + +/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ +#define STV_DEFAULT 0x0 /* Default visibility (see binding). */ +#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */ +#define STV_HIDDEN 0x2 /* Not visible. */ +#define STV_PROTECTED 0x3 /* Visible but not preemptible. */ + +/* Special symbol table indexes. */ +#define STN_UNDEF 0 /* Undefined symbol index. */ + +/* Symbol versioning flags. */ +#define VER_DEF_CURRENT 1 +#define VER_DEF_IDX(x) VER_NDX(x) + +#define VER_FLG_BASE 0x01 +#define VER_FLG_WEAK 0x02 + +#define VER_NEED_CURRENT 1 +#define VER_NEED_WEAK (1u << 15) +#define VER_NEED_HIDDEN VER_NDX_HIDDEN +#define VER_NEED_IDX(x) VER_NDX(x) + +#define VER_NDX_LOCAL 0 +#define VER_NDX_GLOBAL 1 +#define VER_NDX_GIVEN 2 + +#define VER_NDX_HIDDEN (1u << 15) +#define VER_NDX(x) ((x) & ~(1u << 15)) + +#define CA_SUNW_NULL 0 +#define CA_SUNW_HW_1 1 /* first hardware capabilities entry */ +#define CA_SUNW_SF_1 2 /* first software capabilities entry */ + +/* + * Syminfo flag values + */ +#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */ + /* to object containing defn. */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */ +#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */ + /* lazily-loaded */ +#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */ + /* object containing defn. */ +#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */ + /* directly bind to this symbol */ +#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */ +#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */ + +/* + * Syminfo.si_boundto values. + */ +#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */ +#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */ +#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */ + +/* + * Syminfo version values. + */ +#define SYMINFO_NONE 0 /* Syminfo version */ +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +/* + * Relocation types. + * + * All machine architectures are defined here to allow tools on one to + * handle others. + */ + +#define R_386_NONE 0 /* No relocation. */ +#define R_386_32 1 /* Add symbol value. */ +#define R_386_PC32 2 /* Add PC-relative symbol value. */ +#define R_386_GOT32 3 /* Add PC-relative GOT offset. */ +#define R_386_PLT32 4 /* Add PC-relative PLT offset. */ +#define R_386_COPY 5 /* Copy data from shared object. */ +#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_386_RELATIVE 8 /* Add load address of shared object. */ +#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ +#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ +#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ +#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ +#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */ +#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ +#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */ +#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */ +#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */ +#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */ +#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ +#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ +#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ + +/* Null relocation */ +#define R_AARCH64_NONE 256 /* No relocation */ +/* Static AArch64 relocations */ + /* Static data relocations */ +#define R_AARCH64_ABS64 257 /* S + A */ +#define R_AARCH64_ABS32 258 /* S + A */ +#define R_AARCH64_ABS16 259 /* S + A */ +#define R_AARCH64_PREL64 260 /* S + A - P */ +#define R_AARCH64_PREL32 261 /* S + A - P */ +#define R_AARCH64_PREL16 262 /* S + A - P */ + /* Group relocations to create a 16, 32, 48, or 64 bit unsigned data value or address inline */ +#define R_AARCH64_MOVW_UABS_G0 263 /* S + A */ +#define R_AARCH64_MOVW_UABS_G0_NC 264 /* S + A */ +#define R_AARCH64_MOVW_UABS_G1 265 /* S + A */ +#define R_AARCH64_MOVW_UABS_G1_NC 266 /* S + A */ +#define R_AARCH64_MOVW_UABS_G2 267 /* S + A */ +#define R_AARCH64_MOVW_UABS_G2_NC 268 /* S + A */ +#define R_AARCH64_MOVW_UABS_G3 269 /* S + A */ + /* Group relocations to create a 16, 32, 48, or 64 bit signed data or offset value inline */ +#define R_AARCH64_MOVW_SABS_G0 270 /* S + A */ +#define R_AARCH64_MOVW_SABS_G1 271 /* S + A */ +#define R_AARCH64_MOVW_SABS_G2 272 /* S + A */ + /* Relocations to generate 19, 21 and 33 bit PC-relative addresses */ +#define R_AARCH64_LD_PREL_LO19 273 /* S + A - P */ +#define R_AARCH64_ADR_PREL_LO21 274 /* S + A - P */ +#define R_AARCH64_ADR_PREL_PG_HI21 275 /* Page(S+A) - Page(P) */ +#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 /* Page(S+A) - Page(P) */ +#define R_AARCH64_ADD_ABS_LO12_NC 277 /* S + A */ +#define R_AARCH64_LDST8_ABS_LO12_NC 278 /* S + A */ +#define R_AARCH64_LDST16_ABS_LO12_NC 284 /* S + A */ +#define R_AARCH64_LDST32_ABS_LO12_NC 285 /* S + A */ +#define R_AARCH64_LDST64_ABS_LO12_NC 286 /* S + A */ +#define R_AARCH64_LDST128_ABS_LO12_NC 299 /* S + A */ + /* Relocations for control-flow instructions - all offsets are a multiple of 4 */ +#define R_AARCH64_TSTBR14 279 /* S+A-P */ +#define R_AARCH64_CONDBR19 280 /* S+A-P */ +#define R_AARCH64_JUMP26 282 /* S+A-P */ +#define R_AARCH64_CALL26 283 /* S+A-P */ + /* Group relocations to create a 16, 32, 48, or 64 bit PC-relative offset inline */ +#define R_AARCH64_MOVW_PREL_G0 287 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G0_NC 288 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G1 289 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G1_NC 290 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G2 291 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G2_NC 292 /* S+A-P */ +#define R_AARCH64_MOVW_PREL_G3 293 /* S+A-P */ + /* Group relocations to create a 16, 32, 48, or 64 bit GOT-relative offsets inline */ +#define R_AARCH64_MOVW_GOTOFF_G0 300 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G0_NC 301 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G1 302 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G1_NC 303 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G2 304 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G2_NC 305 /* G(S)-GOT */ +#define R_AARCH64_MOVW_GOTOFF_G3 306 /* G(S)-GOT */ + /* GOT-relative data relocations */ +#define R_AARCH64_GOTREL64 307 /* S+A-GOT */ +#define R_AARCH64_GOTREL32 308 /* S+A-GOT */ + /* GOT-relative instruction relocations */ +#define R_AARCH64_GOT_LD_PREL19 309 /* G(S)-P */ +#define R_AARCH64_LD64_GOTOFF_LO15 310 /* G(S)-GOT */ +#define R_AARCH64_ADR_GOT_PAGE 311 /* Page(G(S))-Page(P) */ +#define R_AARCH64_LD64_GOT_LO12_NC 312 /* G(S) */ +#define R_AARCH64_LD64_GOTPAGE_LO15 313 /* G(S)-Page(GOT) */ +/* Relocations for thread-local storage */ + /* General Dynamic TLS relocations */ +#define R_AARCH64_TLSGD_ADR_PREL21 512 /* G(TLSIDX(S+A)) - P */ +#define R_AARCH64_TLSGD_ADR_PAGE21 513 /* Page(G(TLSIDX(S+A))) - Page(P) */ +#define R_AARCH64_TLSGD_ADD_LO12_NC 514 /* G(TLSIDX(S+A)) */ +#define R_AARCH64_TLSGD_MOVW_G1 515 /* G(TLSIDX(S+A)) - GOT */ +#define R_AARCH64_TLSGD_MOVW_G0_NC 516 /* G(TLSIDX(S+A)) - GOT */ + /* Local Dynamic TLS relocations */ +#define R_AARCH64_TLSLD_ADR_PREL21 517 /* G(LDM(S))) - P */ +#define R_AARCH64_TLSLD_ADR_PAGE21 518 /* Page(G(LDM(S)))-Page(P) */ +#define R_AARCH64_TLSLD_ADD_LO12_NC 519 /* G(LDM(S)) */ +#define R_AARCH64_TLSLD_MOVW_G1 520 /* G(LDM(S)) - GOT */ +#define R_AARCH64_TLSLD_MOVW_G0_NC 521 /* G(LDM(S)) - GOT */ +#define R_AARCH64_TLSLD_LD_PREL19 522 /* G(LDM(S)) - P */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537 /* DTPREL(S+A) */ +#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538 /* DTPREL(S+A) */ + /* Initial Exec TLS relocations */ +#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539 /* G(TPREL(S+A)) - GOT */ +#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540 /* G(TPREL(S+A)) - GOT */ +#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541 /* Page(G(TPREL(S+A))) - Page(P) */ +#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542 /* G(TPREL(S+A)) */ +#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543 /* G(TPREL(S+A)) - P */ + /* Local Exec TLS relocations */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G1 545 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G0 547 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_ADD_TPREL_HI12 549 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_ADD_TPREL_LO12 550 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558 /* TPREL(S+A) */ +#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559 /* TPREL(S+A) */ +/* Dynamic relocations */ + /* Dynamic relocations */ +#define R_AARCH64_COPY 1024 +#define R_AARCH64_GLOB_DAT 1025 /* S + A */ +#define R_AARCH64_JUMP_SLOT 1026 /* S + A */ +#define R_AARCH64_RELATIVE 1027 /* Delta(S) + A , Delta(P) + A */ +#define R_AARCH64_TLS_DTPREL64 1028 /* DTPREL(S+A) */ +#define R_AARCH64_TLS_DTPMOD64 1029 /* LDM(S) */ +#define R_AARCH64_TLS_TPREL64 1030 /* TPREL(S+A) */ +#define R_AARCH64_TLS_DTPREL32 1031 /* DTPREL(S+A) */ +#define R_AARCH64_TLS_DTPMOD32 1032 /* LDM(S) */ +#define R_AARCH64_TLS_TPREL32 1033 /* DTPREL(S+A) */ + +#define R_ALPHA_NONE 0 /* No reloc */ +#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ +#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ +#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ +#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ +#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ +#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ +#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ +#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ +#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ +#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ +#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ +#define R_ALPHA_OP_PUSH 12 /* OP stack push */ +#define R_ALPHA_OP_STORE 13 /* OP stack pop and store */ +#define R_ALPHA_OP_PSUB 14 /* OP stack subtract */ +#define R_ALPHA_OP_PRSHIFT 15 /* OP stack right shift */ +#define R_ALPHA_GPVALUE 16 +#define R_ALPHA_GPRELHIGH 17 +#define R_ALPHA_GPRELLOW 18 +#define R_ALPHA_IMMED_GP_16 19 +#define R_ALPHA_IMMED_GP_HI32 20 +#define R_ALPHA_IMMED_SCN_HI32 21 +#define R_ALPHA_IMMED_BR_HI32 22 +#define R_ALPHA_IMMED_LO32 23 +#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ +#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ +#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ +#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ + +#define R_ARM_NONE 0 /* No relocation. */ +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +#define R_ARM_COPY 20 /* Copy data from shared object. */ +#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ +#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ +#define R_ARM_RELATIVE 23 /* Add load address of shared object. */ +#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */ +#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ +#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ +#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */ +#define R_ARM_CALL 28 +#define R_ARM_JMP24 29 +#define R_ARM_THM_MOVW_ABS_NC 47 +#define R_ARM_THM_MOVT_ABS 48 + +// Block of PC-relative relocations added to work around gcc putting +// object relocations in static executables. +#define R_ARM_THM_JUMP24 30 +#define R_ARM_PREL31 42 +#define R_ARM_MOVW_PREL_NC 45 +#define R_ARM_MOVT_PREL 46 +#define R_ARM_THM_MOVW_PREL_NC 49 +#define R_ARM_THM_MOVT_PREL 50 +#define R_ARM_THM_JMP6 52 +#define R_ARM_THM_ALU_PREL_11_0 53 +#define R_ARM_THM_PC12 54 +#define R_ARM_REL32_NOI 56 +#define R_ARM_ALU_PC_G0_NC 57 +#define R_ARM_ALU_PC_G0 58 +#define R_ARM_ALU_PC_G1_NC 59 +#define R_ARM_ALU_PC_G1 60 +#define R_ARM_ALU_PC_G2 61 +#define R_ARM_LDR_PC_G1 62 +#define R_ARM_LDR_PC_G2 63 +#define R_ARM_LDRS_PC_G0 64 +#define R_ARM_LDRS_PC_G1 65 +#define R_ARM_LDRS_PC_G2 66 +#define R_ARM_LDC_PC_G0 67 +#define R_ARM_LDC_PC_G1 68 +#define R_ARM_LDC_PC_G2 69 +#define R_ARM_GOT_PREL 96 +#define R_ARM_THM_JUMP11 102 +#define R_ARM_THM_JUMP8 103 +#define R_ARM_TLS_GD32 104 +#define R_ARM_TLS_LDM32 105 +#define R_ARM_TLS_IE32 107 + +#define R_ARM_THM_JUMP19 51 +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS32 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 + +#define R_PPC_NONE 0 /* No relocation. */ +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR24 2 +#define R_PPC_ADDR16 3 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_ADDR14 7 +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 +#define R_PPC_REL14 11 +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +/* + * TLS relocations + */ +#define R_PPC_TLS 67 +#define R_PPC_DTPMOD32 68 +#define R_PPC_TPREL16 69 +#define R_PPC_TPREL16_LO 70 +#define R_PPC_TPREL16_HI 71 +#define R_PPC_TPREL16_HA 72 +#define R_PPC_TPREL32 73 +#define R_PPC_DTPREL16 74 +#define R_PPC_DTPREL16_LO 75 +#define R_PPC_DTPREL16_HI 76 +#define R_PPC_DTPREL16_HA 77 +#define R_PPC_DTPREL32 78 +#define R_PPC_GOT_TLSGD16 79 +#define R_PPC_GOT_TLSGD16_LO 80 +#define R_PPC_GOT_TLSGD16_HI 81 +#define R_PPC_GOT_TLSGD16_HA 82 +#define R_PPC_GOT_TLSLD16 83 +#define R_PPC_GOT_TLSLD16_LO 84 +#define R_PPC_GOT_TLSLD16_HI 85 +#define R_PPC_GOT_TLSLD16_HA 86 +#define R_PPC_GOT_TPREL16 87 +#define R_PPC_GOT_TPREL16_LO 88 +#define R_PPC_GOT_TPREL16_HI 89 +#define R_PPC_GOT_TPREL16_HA 90 + +/* + * The remaining relocs are from the Embedded ELF ABI, and are not in the + * SVR4 ELF ABI. + */ + +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 + +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 + +#define R_X86_64_NONE 0 /* No relocation. */ +#define R_X86_64_64 1 /* Add 64 bit symbol value. */ +#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */ +#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */ +#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */ +#define R_X86_64_COPY 5 /* Copy data from shared object. */ +#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */ +#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */ +#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */ +#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */ +#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */ +#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */ +#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */ +#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ +#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ +#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ +#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ +#define R_X86_64_PC64 24 /* PC relative 64 bit */ +#define R_X86_64_GOTOFF64 25 /* 64 bit offset to GOT */ +#define R_X86_64_GOTPC3 26 /* 32 bit signed pc relative offset to GOT */ +#define R_X86_64_GOT64 27 /* 64-bit GOT entry offset */ +#define R_X86_64_GOTPCREL64 28 /* 64-bit PC relative offset to GOT entry */ +#define R_X86_64_GOTPC64 29 /* 64-bit PC relative offset to GOT */ +#define R_X86_64_GOTPLT64 30 /* like GOT64, says PLT entry needed */ +#define R_X86_64_PLTOFF64 31 /* 64-bit GOT relative offset to PLT entry */ +#define R_X86_64_SIZE32 32 /* Size of symbol plus 32-bit addend */ +#define R_X86_64_SIZE64 33 /* Size of symbol plus 64-bit addend */ +#define R_X86_64_GOTPC32_TLSDESC 34 /* GOT offset for TLS descriptor. */ +#define R_X86_64_TLSDESC_CALL 35 /* Marker for call through TLS descriptor. */ +#define R_X86_64_TLSDESC 36 /* TLS descriptor. */ +#define R_X86_64_IRELATIVE 37 /* Adjust indirectly by program base */ +#define R_X86_64_RELATIVE64 38 /* 64-bit adjust by program base */ +#define R_X86_64_GOTPCRELX 41 /* Load from 32 bit signed pc relative offset to GOT entry without REX prefix, relaxable. */ +#define R_X86_64_REX_GOTPCRELX 42 /* Load from 32 bit signed pc relative offset to GOT entry with REX prefix, relaxable. */ + +/* + * RISC-V relocation types + */ + +/* Relocation types used by the dynamic linker */ +#define R_RISCV_NONE 0 +#define R_RISCV_32 1 +#define R_RISCV_64 2 +#define R_RISCV_RELATIVE 3 +#define R_RISCV_COPY 4 +#define R_RISCV_JUMP_SLOT 5 +#define R_RISCV_TLS_DTPMOD32 6 +#define R_RISCV_TLS_DTPMOD64 7 +#define R_RISCV_TLS_DTPREL32 8 +#define R_RISCV_TLS_DTPREL64 9 +#define R_RISCV_TLS_TPREL32 10 +#define R_RISCV_TLS_TPREL64 11 + +/* Relocation types not used by the dynamic linker */ +#define R_RISCV_BRANCH 16 +#define R_RISCV_JAL 17 +#define R_RISCV_CALL 18 +#define R_RISCV_CALL_PLT 19 +#define R_RISCV_GOT_HI20 20 +#define R_RISCV_TLS_GOT_HI20 21 +#define R_RISCV_TLS_GD_HI20 22 +#define R_RISCV_PCREL_HI20 23 +#define R_RISCV_PCREL_LO12_I 24 +#define R_RISCV_PCREL_LO12_S 25 +#define R_RISCV_HI20 26 +#define R_RISCV_LO12_I 27 +#define R_RISCV_LO12_S 28 +#define R_RISCV_TPREL_HI20 29 +#define R_RISCV_TPREL_LO12_I 30 +#define R_RISCV_TPREL_LO12_S 31 +#define R_RISCV_TPREL_ADD 32 +#define R_RISCV_ADD8 33 +#define R_RISCV_ADD16 34 +#define R_RISCV_ADD32 35 +#define R_RISCV_ADD64 36 +#define R_RISCV_SUB8 37 +#define R_RISCV_SUB16 38 +#define R_RISCV_SUB32 39 +#define R_RISCV_SUB64 40 +#define R_RISCV_GNU_VTINHERIT 41 +#define R_RISCV_GNU_VTENTRY 42 +#define R_RISCV_ALIGN 43 +#define R_RISCV_RVC_BRANCH 44 +#define R_RISCV_RVC_JUMP 45 +#define R_RISCV_RVC_LUI 46 +#define R_RISCV_GPREL_I 47 +#define R_RISCV_GPREL_S 48 +#define R_RISCV_TPREL_I 49 +#define R_RISCV_TPREL_S 50 +#define R_RISCV_RELAX 51 +#define R_RISCV_SUB6 52 +#define R_RISCV_SET6 53 +#define R_RISCV_SET8 54 +#define R_RISCV_SET16 55 +#define R_RISCV_SET32 56 +#endif /* !_SYS_ELF_COMMON_H_ */ diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/GNUmakefile new file mode 100644 index 00000000..869dabb1 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/GNUmakefile @@ -0,0 +1,23 @@ +## @file +# GNU/Linux makefile for 'GenSec' module build. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +MAKEROOT ?= .. + +APPNAME = GenSec + +OBJECTS = GenSec.o + +include $(MAKEROOT)/Makefiles/app.makefile + +LIBS = -lCommon +ifeq ($(CYGWIN), CYGWIN) + LIBS += -L/lib/e2fsprogs -luuid +endif + +ifeq ($(LINUX), Linux) + LIBS += -luuid +endif + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/GenSec.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/GenSec.c new file mode 100644 index 00000000..01719a7c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/GenSec.c @@ -0,0 +1,1818 @@ +/** @file +Creates output file that is a properly formed section per the PI spec. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#ifndef __GNUC__ +# ifdef VBOX +# include +# else +#include +# endif +#include +#include +#include +#endif + +#include +#include +#include +#include + +#include +#include +#include +#if defined(VBOX) && defined(RT_OS_WINDOWS) +# define _SKIP_DEFINE_RUNTIME_FUNCTION 1 +#endif +#include + +#include "CommonLib.h" +#include "Compress.h" +#include "Crc32.h" +#include "EfiUtilityMsgs.h" +#include "ParseInf.h" +#include "FvLib.h" +#include "PeCoffLib.h" + +// +// GenSec Tool Information +// +#define UTILITY_NAME "GenSec" +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +STATIC CHAR8 *mSectionTypeName[] = { + NULL, // 0x00 - reserved + "EFI_SECTION_COMPRESSION", // 0x01 + "EFI_SECTION_GUID_DEFINED", // 0x02 + NULL, // 0x03 - reserved + NULL, // 0x04 - reserved + NULL, // 0x05 - reserved + NULL, // 0x06 - reserved + NULL, // 0x07 - reserved + NULL, // 0x08 - reserved + NULL, // 0x09 - reserved + NULL, // 0x0A - reserved + NULL, // 0x0B - reserved + NULL, // 0x0C - reserved + NULL, // 0x0D - reserved + NULL, // 0x0E - reserved + NULL, // 0x0F - reserved + "EFI_SECTION_PE32", // 0x10 + "EFI_SECTION_PIC", // 0x11 + "EFI_SECTION_TE", // 0x12 + "EFI_SECTION_DXE_DEPEX", // 0x13 + "EFI_SECTION_VERSION", // 0x14 + "EFI_SECTION_USER_INTERFACE", // 0x15 + "EFI_SECTION_COMPATIBILITY16", // 0x16 + "EFI_SECTION_FIRMWARE_VOLUME_IMAGE", // 0x17 + "EFI_SECTION_FREEFORM_SUBTYPE_GUID", // 0x18 + "EFI_SECTION_RAW", // 0x19 + NULL, // 0x1A + "EFI_SECTION_PEI_DEPEX", // 0x1B + "EFI_SECTION_SMM_DEPEX" // 0x1C +}; + +STATIC CHAR8 *mCompressionTypeName[] = { "PI_NONE", "PI_STD" }; + +#define EFI_GUIDED_SECTION_NONE 0x80 +STATIC CHAR8 *mGUIDedSectionAttribue[] = { "NONE", "PROCESSING_REQUIRED", "AUTH_STATUS_VALID"}; + +STATIC CHAR8 *mAlignName[] = { + "1", "2", "4", "8", "16", "32", "64", "128", "256", "512", + "1K", "2K", "4K", "8K", "16K", "32K", "64K", "128K", "256K", + "512K", "1M", "2M", "4M", "8M", "16M" +}; + +// +// Crc32 GUID section related definitions. +// +typedef struct { + EFI_GUID_DEFINED_SECTION GuidSectionHeader; + UINT32 CRC32Checksum; +} CRC32_SECTION_HEADER; + +typedef struct { + EFI_GUID_DEFINED_SECTION2 GuidSectionHeader; + UINT32 CRC32Checksum; +} CRC32_SECTION_HEADER2; + +STATIC EFI_GUID mZeroGuid = {0x0, 0x0, 0x0, {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; +STATIC EFI_GUID mEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID; + +STATIC +VOID +Version ( + VOID + ) +/*++ + +Routine Description: + + Print out version information for this utility. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION); +} + +STATIC +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Print Help message. + +Arguments: + + VOID + +Returns: + + None + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "\nUsage: %s [options] [input_file]\n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n"); + + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " -o FileName, --outputfile FileName\n\ + File is the SectionFile to be created.\n"); + fprintf (stdout, " -s [SectionType], --sectiontype [SectionType]\n\ + SectionType defined in PI spec is one type of\n\ + EFI_SECTION_COMPRESSION, EFI_SECTION_GUID_DEFINED,\n\ + EFI_SECTION_PE32, EFI_SECTION_PIC, EFI_SECTION_TE,\n\ + EFI_SECTION_DXE_DEPEX, EFI_SECTION_COMPATIBILITY16,\n\ + EFI_SECTION_USER_INTERFACE, EFI_SECTION_VERSION,\n\ + EFI_SECTION_FIRMWARE_VOLUME_IMAGE, EFI_SECTION_RAW,\n\ + EFI_SECTION_FREEFORM_SUBTYPE_GUID,\n\ + EFI_SECTION_PEI_DEPEX, EFI_SECTION_SMM_DEPEX.\n\ + if -s option is not given, \n\ + EFI_SECTION_ALL is default section type.\n"); + fprintf (stdout, " -c [Type], --compress [Type]\n\ + Compress method type can be PI_NONE or PI_STD.\n\ + if -c option is not given, PI_STD is default type.\n"); + fprintf (stdout, " -g GuidValue, --vendor GuidValue\n\ + GuidValue is one specific vendor guid value.\n\ + Its format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n"); + fprintf (stdout, " -l GuidHeaderLength, --HeaderLength GuidHeaderLength\n\ + GuidHeaderLength is the size of header of guided data\n"); + fprintf (stdout, " -r GuidAttr, --attributes GuidAttr\n\ + GuidAttr is guid section attributes, which may be\n\ + PROCESSING_REQUIRED, AUTH_STATUS_VALID and NONE. \n\ + if -r option is not given, default PROCESSING_REQUIRED\n"); + fprintf (stdout, " -n String, --name String\n\ + String is a NULL terminated string used in Ui section.\n"); + fprintf (stdout, " -j Number, --buildnumber Number\n\ + Number is an integer value between 0 and 65535\n\ + used in Ver section.\n"); + fprintf (stdout, " --sectionalign SectionAlign\n\ + SectionAlign points to section alignment, which support\n\ + the alignment scope 0~16M. If SectionAlign is specified\n\ + as 0, tool get alignment value from SectionFile. It is\n\ + specified in same order that the section file is input.\n"); + fprintf (stdout, " --dummy dummyfile\n\ + compare dummpyfile with input_file to decide whether\n\ + need to set PROCESSING_REQUIRED attribute.\n"); + fprintf (stdout, " -v, --verbose Turn on verbose output with informational messages.\n"); + fprintf (stdout, " -q, --quiet Disable all messages except key message and fatal error\n"); + fprintf (stdout, " -d, --debug level Enable debug messages, at input debug level.\n"); + fprintf (stdout, " --version Show program's version number and exit.\n"); + fprintf (stdout, " -h, --help Show this help message and exit.\n"); +} + +VOID +Ascii2UnicodeString ( + CHAR8 *String, + CHAR16 *UniString + ) +/*++ + +Routine Description: + + Write ascii string as unicode string format to FILE + +Arguments: + + String - Pointer to string that is written to FILE. + UniString - Pointer to unicode string + +Returns: + + NULL + +--*/ +{ + while (*String != '\0') { + *(UniString++) = (CHAR16) *(String++); + } + // + // End the UniString with a NULL. + // + *UniString = '\0'; +} + +STATUS +GenSectionCommonLeafSection ( + CHAR8 **InputFileName, + UINT32 InputFileNum, + UINT8 SectionType, + UINT8 **OutFileBuffer + ) +/*++ + +Routine Description: + + Generate a leaf section of type other than EFI_SECTION_VERSION + and EFI_SECTION_USER_INTERFACE. Input file must be well formed. + The function won't validate the input file's contents. For + common leaf sections, the input file may be a binary file. + The utility will add section header to the file. + +Arguments: + + InputFileName - Name of the input file. + + InputFileNum - Number of input files. Should be 1 for leaf section. + + SectionType - A valid section type string + + OutFileBuffer - Buffer pointer to Output file contents + +Returns: + + STATUS_ERROR - can't continue + STATUS_SUCCESS - successful return + +--*/ +{ + UINT32 InputFileLength; + FILE *InFile; + UINT8 *Buffer; + UINT32 TotalLength; + UINT32 HeaderLength; + EFI_COMMON_SECTION_HEADER *CommonSect; + STATUS Status; + + if (InputFileNum > 1) { + Error (NULL, 0, 2000, "Invalid parameter", "more than one input file specified"); + return STATUS_ERROR; + } else if (InputFileNum < 1) { + Error (NULL, 0, 2000, "Invalid parameter", "no input file specified"); + return STATUS_ERROR; + } + // + // Open the input file + // + InFile = fopen (LongFilePath (InputFileName[0]), "rb"); + if (InFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", InputFileName[0]); + return STATUS_ERROR; + } + + Status = STATUS_ERROR; + Buffer = NULL; + // + // Seek to the end of the input file so we can determine its size + // + fseek (InFile, 0, SEEK_END); + InputFileLength = ftell (InFile); + fseek (InFile, 0, SEEK_SET); + DebugMsg (NULL, 0, 9, "Input file", "File name is %s and File size is %u bytes", InputFileName[0], (unsigned) InputFileLength); + TotalLength = sizeof (EFI_COMMON_SECTION_HEADER) + InputFileLength; + // + // Size must fit in 3 bytes + // + //if (TotalLength >= MAX_SECTION_SIZE) { + // Error (NULL, 0, 2000, "Invalid parameter", "%s file size (0x%X) exceeds section size limit(%uM).", InputFileName[0], (unsigned) TotalLength, MAX_SECTION_SIZE>>20); + // goto Done; + //} + HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER); + if (TotalLength >= MAX_SECTION_SIZE) { + TotalLength = sizeof (EFI_COMMON_SECTION_HEADER2) + InputFileLength; + HeaderLength = sizeof (EFI_COMMON_SECTION_HEADER2); + } + VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength); + // + // Fill in the fields in the local section header structure + // + Buffer = (UINT8 *) malloc ((size_t) TotalLength); + if (Buffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated"); + goto Done; + } + CommonSect = (EFI_COMMON_SECTION_HEADER *) Buffer; + CommonSect->Type = SectionType; + if (TotalLength < MAX_SECTION_SIZE) { + CommonSect->Size[0] = (UINT8) (TotalLength & 0xff); + CommonSect->Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8); + CommonSect->Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16); + } else { + memset(CommonSect->Size, 0xff, sizeof(UINT8) * 3); + ((EFI_COMMON_SECTION_HEADER2 *)CommonSect)->ExtendedSize = TotalLength; + } + + // + // read data from the input file. + // + if (InputFileLength != 0) { + if (fread (Buffer + HeaderLength, (size_t) InputFileLength, 1, InFile) != 1) { + Error (NULL, 0, 0004, "Error reading file", InputFileName[0]); + goto Done; + } + } + + // + // Set OutFileBuffer + // + *OutFileBuffer = Buffer; + Status = STATUS_SUCCESS; + +Done: + fclose (InFile); + + return Status; +} + +STATIC +EFI_STATUS +StringtoAlignment ( + IN CHAR8 *AlignBuffer, + OUT UINT32 *AlignNumber + ) +/*++ + +Routine Description: + + Converts Align String to align value (1~16M). + +Arguments: + + AlignBuffer - Pointer to Align string. + AlignNumber - Pointer to Align value. + +Returns: + + EFI_SUCCESS Successfully convert align string to align value. + EFI_INVALID_PARAMETER Align string is invalid or align value is not in scope. + +--*/ +{ + UINT32 Index = 0; + // + // Check AlignBuffer + // + if (AlignBuffer == NULL) { + return EFI_INVALID_PARAMETER; + } + for (Index = 0; Index < sizeof (mAlignName) / sizeof (CHAR8 *); Index ++) { + if (stricmp (AlignBuffer, mAlignName [Index]) == 0) { + *AlignNumber = 1 << Index; + return EFI_SUCCESS; + } + } + return EFI_INVALID_PARAMETER; +} + +EFI_STATUS +GetSectionContents ( + CHAR8 **InputFileName, + UINT32 *InputFileAlign, + UINT32 InputFileNum, + UINT8 *FileBuffer, + UINT32 *BufferLength + ) +/*++ + +Routine Description: + + Get the contents of all section files specified in InputFileName + into FileBuffer. + +Arguments: + + InputFileName - Name of the input file. + + InputFileAlign - Alignment required by the input file data. + + InputFileNum - Number of input files. Should be at least 1. + + FileBuffer - Output buffer to contain data + + BufferLength - On input, this is size of the FileBuffer. + On output, this is the actual length of the data. + +Returns: + + EFI_SUCCESS on successful return + EFI_INVALID_PARAMETER if InputFileNum is less than 1 or BufferLength point is NULL. + EFI_ABORTED if unable to open input file. + EFI_BUFFER_TOO_SMALL FileBuffer is not enough to contain all file data. +--*/ +{ + UINT32 Size; + UINT32 Offset; + UINT32 FileSize; + UINT32 Index; + FILE *InFile; + EFI_COMMON_SECTION_HEADER *SectHeader; + EFI_COMMON_SECTION_HEADER2 TempSectHeader; + EFI_TE_IMAGE_HEADER TeHeader; + UINT32 TeOffset; + EFI_GUID_DEFINED_SECTION GuidSectHeader; + EFI_GUID_DEFINED_SECTION2 GuidSectHeader2; + UINT32 HeaderSize; + + if (InputFileNum < 1) { + Error (NULL, 0, 2000, "Invalid parameter", "must specify at least one input file"); + return EFI_INVALID_PARAMETER; + } + + if (BufferLength == NULL) { + Error (NULL, 0, 2000, "Invalid parameter", "BufferLength can't be NULL"); + return EFI_INVALID_PARAMETER; + } + + Size = 0; + Offset = 0; + TeOffset = 0; + // + // Go through our array of file names and copy their contents + // to the output buffer. + // + for (Index = 0; Index < InputFileNum; Index++) { + // + // make sure section ends on a DWORD boundary + // + while ((Size & 0x03) != 0) { + if (FileBuffer != NULL && Size < *BufferLength) { + FileBuffer[Size] = 0; + } + Size++; + } + + // + // Open file and read contents + // + InFile = fopen (LongFilePath (InputFileName[Index]), "rb"); + if (InFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", InputFileName[Index]); + return EFI_ABORTED; + } + + fseek (InFile, 0, SEEK_END); + FileSize = ftell (InFile); + fseek (InFile, 0, SEEK_SET); + DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName[Index], (unsigned) FileSize); + // + // Adjust section buffer when section alignment is required. + // + if (InputFileAlign != NULL) { + // + // Check this section is Te/Pe section, and Calculate the numbers of Te/Pe section. + // + TeOffset = 0; + // + // The section might be EFI_COMMON_SECTION_HEADER2 + // But only Type needs to be checked + // + if (FileSize >= MAX_SECTION_SIZE) { + HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER2); + } else { + HeaderSize = sizeof (EFI_COMMON_SECTION_HEADER); + } + fread (&TempSectHeader, 1, HeaderSize, InFile); + if (TempSectHeader.Type == EFI_SECTION_TE) { + fread (&TeHeader, 1, sizeof (TeHeader), InFile); + if (TeHeader.Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) { + TeOffset = TeHeader.StrippedSize - sizeof (TeHeader); + } + } else if (TempSectHeader.Type == EFI_SECTION_GUID_DEFINED) { + fseek (InFile, 0, SEEK_SET); + if (FileSize >= MAX_SECTION_SIZE) { + fread (&GuidSectHeader2, 1, sizeof (GuidSectHeader2), InFile); + if ((GuidSectHeader2.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) { + HeaderSize = GuidSectHeader2.DataOffset; + } + } else { + fread (&GuidSectHeader, 1, sizeof (GuidSectHeader), InFile); + if ((GuidSectHeader.Attributes & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) == 0) { + HeaderSize = GuidSectHeader.DataOffset; + } + } + } + + fseek (InFile, 0, SEEK_SET); + + // + // Revert TeOffset to the converse value relative to Alignment + // This is to assure the original PeImage Header at Alignment. + // + if (TeOffset != 0) { + TeOffset = InputFileAlign [Index] - (TeOffset % InputFileAlign [Index]); + TeOffset = TeOffset % InputFileAlign [Index]; + } + + // + // make sure section data meet its alignment requirement by adding one raw pad section. + // + if ((InputFileAlign [Index] != 0) && (((Size + HeaderSize + TeOffset) % InputFileAlign [Index]) != 0)) { + Offset = (Size + sizeof (EFI_COMMON_SECTION_HEADER) + HeaderSize + TeOffset + InputFileAlign [Index] - 1) & ~(InputFileAlign [Index] - 1); + Offset = Offset - Size - HeaderSize - TeOffset; + + if (FileBuffer != NULL && ((Size + Offset) < *BufferLength)) { + // + // The maximal alignment is 64K, the raw section size must be less than 0xffffff + // + memset (FileBuffer + Size, 0, Offset); + SectHeader = (EFI_COMMON_SECTION_HEADER *) (FileBuffer + Size); + SectHeader->Type = EFI_SECTION_RAW; + SectHeader->Size[0] = (UINT8) (Offset & 0xff); + SectHeader->Size[1] = (UINT8) ((Offset & 0xff00) >> 8); + SectHeader->Size[2] = (UINT8) ((Offset & 0xff0000) >> 16); + } + DebugMsg (NULL, 0, 9, "Pad raw section for section data alignment", "Pad Raw section size is %u", (unsigned) Offset); + + Size = Size + Offset; + } + } + + // + // Now read the contents of the file into the buffer + // Buffer must be enough to contain the file content. + // + if ((FileSize > 0) && (FileBuffer != NULL) && ((Size + FileSize) <= *BufferLength)) { + if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) { + Error (NULL, 0, 0004, "Error reading file", InputFileName[Index]); + fclose (InFile); + return EFI_ABORTED; + } + } + + fclose (InFile); + Size += FileSize; + } + + // + // Set the real required buffer size. + // + if (Size > *BufferLength) { + *BufferLength = Size; + return EFI_BUFFER_TOO_SMALL; + } else { + *BufferLength = Size; + return EFI_SUCCESS; + } +} + +EFI_STATUS +GenSectionCompressionSection ( + CHAR8 **InputFileName, + UINT32 *InputFileAlign, + UINT32 InputFileNum, + UINT8 SectCompSubType, + UINT8 **OutFileBuffer + ) +/*++ + +Routine Description: + + Generate an encapsulating section of type EFI_SECTION_COMPRESSION + Input file must be already sectioned. The function won't validate + the input files' contents. Caller should hand in files already + with section header. + +Arguments: + + InputFileName - Name of the input file. + + InputFileAlign - Alignment required by the input file data. + + InputFileNum - Number of input files. Should be at least 1. + + SectCompSubType - Specify the compression algorithm requested. + + OutFileBuffer - Buffer pointer to Output file contents + +Returns: + + EFI_SUCCESS on successful return + EFI_INVALID_PARAMETER if InputFileNum is less than 1 + EFI_ABORTED if unable to open input file. + EFI_OUT_OF_RESOURCES No resource to complete the operation. +--*/ +{ + UINT32 TotalLength; + UINT32 InputLength; + UINT32 CompressedLength; + UINT32 HeaderLength; + UINT8 *FileBuffer; + UINT8 *OutputBuffer; + EFI_STATUS Status; + EFI_COMPRESSION_SECTION *CompressionSect; + EFI_COMPRESSION_SECTION2 *CompressionSect2; + COMPRESS_FUNCTION CompressFunction; + + InputLength = 0; + FileBuffer = NULL; + OutputBuffer = NULL; + CompressedLength = 0; + TotalLength = 0; + // + // read all input file contents into a buffer + // first get the size of all file contents + // + Status = GetSectionContents ( + InputFileName, + InputFileAlign, + InputFileNum, + FileBuffer, + &InputLength + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + FileBuffer = (UINT8 *) malloc (InputLength); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated"); + return EFI_OUT_OF_RESOURCES; + } + // + // read all input file contents into a buffer + // + Status = GetSectionContents ( + InputFileName, + InputFileAlign, + InputFileNum, + FileBuffer, + &InputLength + ); + } + + if (EFI_ERROR (Status)) { + if (FileBuffer != NULL) { + free (FileBuffer); + } + return Status; + } + + if (FileBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CompressFunction = NULL; + + // + // Now data is in FileBuffer, compress the data + // + switch (SectCompSubType) { + case EFI_NOT_COMPRESSED: + CompressedLength = InputLength; + HeaderLength = sizeof (EFI_COMPRESSION_SECTION); + if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) { + HeaderLength = sizeof (EFI_COMPRESSION_SECTION2); + } + TotalLength = CompressedLength + HeaderLength; + // + // Copy file buffer to the none compressed data. + // + OutputBuffer = malloc (TotalLength); + if (OutputBuffer == NULL) { + free (FileBuffer); + return EFI_OUT_OF_RESOURCES; + } + memcpy (OutputBuffer + HeaderLength, FileBuffer, CompressedLength); + free (FileBuffer); + FileBuffer = OutputBuffer; + break; + + case EFI_STANDARD_COMPRESSION: + CompressFunction = (COMPRESS_FUNCTION) EfiCompress; + break; + + default: + Error (NULL, 0, 2000, "Invalid parameter", "unknown compression type"); + free (FileBuffer); + return EFI_ABORTED; + } + + if (CompressFunction != NULL) { + + Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength); + if (Status == EFI_BUFFER_TOO_SMALL) { + HeaderLength = sizeof (EFI_COMPRESSION_SECTION); + if (CompressedLength + HeaderLength >= MAX_SECTION_SIZE) { + HeaderLength = sizeof (EFI_COMPRESSION_SECTION2); + } + TotalLength = CompressedLength + HeaderLength; + OutputBuffer = malloc (TotalLength); + if (!OutputBuffer) { + free (FileBuffer); + return EFI_OUT_OF_RESOURCES; + } + + Status = CompressFunction (FileBuffer, InputLength, OutputBuffer + HeaderLength, &CompressedLength); + } + + free (FileBuffer); + FileBuffer = OutputBuffer; + + if (EFI_ERROR (Status)) { + if (FileBuffer != NULL) { + free (FileBuffer); + } + + return Status; + } + + if (FileBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + } + + DebugMsg (NULL, 0, 9, "comprss file size", + "the original section size is %d bytes and the compressed section size is %u bytes", (unsigned) InputLength, (unsigned) CompressedLength); + + //if (TotalLength >= MAX_SECTION_SIZE) { + // Error (NULL, 0, 2000, "Invalid parameter", "The size of all files exceeds section size limit(%uM).", MAX_SECTION_SIZE>>20); + // if (FileBuffer != NULL) { + // free (FileBuffer); + // } + // if (OutputBuffer != NULL) { + // free (OutputBuffer); + // } + // return STATUS_ERROR; + //} + VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength); + + // + // Add the section header for the compressed data + // + if (TotalLength >= MAX_SECTION_SIZE) { + CompressionSect2 = (EFI_COMPRESSION_SECTION2 *)FileBuffer; + + memset(CompressionSect2->CommonHeader.Size, 0xff, sizeof(UINT8) * 3); + CompressionSect2->CommonHeader.Type = EFI_SECTION_COMPRESSION; + CompressionSect2->CommonHeader.ExtendedSize = TotalLength; + CompressionSect2->CompressionType = SectCompSubType; + CompressionSect2->UncompressedLength = InputLength; + } else { + CompressionSect = (EFI_COMPRESSION_SECTION *) FileBuffer; + + CompressionSect->CommonHeader.Type = EFI_SECTION_COMPRESSION; + CompressionSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff); + CompressionSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8); + CompressionSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16); + CompressionSect->CompressionType = SectCompSubType; + CompressionSect->UncompressedLength = InputLength; + } + + // + // Set OutFileBuffer + // + *OutFileBuffer = FileBuffer; + + return EFI_SUCCESS; +} + +EFI_STATUS +GenSectionGuidDefinedSection ( + CHAR8 **InputFileName, + UINT32 *InputFileAlign, + UINT32 InputFileNum, + EFI_GUID *VendorGuid, + UINT16 DataAttribute, + UINT32 DataHeaderSize, + UINT8 **OutFileBuffer + ) +/*++ + +Routine Description: + + Generate an encapsulating section of type EFI_SECTION_GUID_DEFINED + Input file must be already sectioned. The function won't validate + the input files' contents. Caller should hand in files already + with section header. + +Arguments: + + InputFileName - Name of the input file. + + InputFileAlign - Alignment required by the input file data. + + InputFileNum - Number of input files. Should be at least 1. + + VendorGuid - Specify vendor guid value. + + DataAttribute - Specify attribute for the vendor guid data. + + DataHeaderSize- Guided Data Header Size + + OutFileBuffer - Buffer pointer to Output file contents + +Returns: + + EFI_SUCCESS on successful return + EFI_INVALID_PARAMETER if InputFileNum is less than 1 + EFI_ABORTED if unable to open input file. + EFI_OUT_OF_RESOURCES No resource to complete the operation. + +--*/ +{ + UINT32 TotalLength; + UINT32 InputLength; + UINT32 Offset; + UINT8 *FileBuffer; + UINT32 Crc32Checksum; + EFI_STATUS Status; + CRC32_SECTION_HEADER *Crc32GuidSect; + CRC32_SECTION_HEADER2 *Crc32GuidSect2; + EFI_GUID_DEFINED_SECTION *VendorGuidSect; + EFI_GUID_DEFINED_SECTION2 *VendorGuidSect2; + + InputLength = 0; + Offset = 0; + FileBuffer = NULL; + TotalLength = 0; + + // + // read all input file contents into a buffer + // first get the size of all file contents + // + Status = GetSectionContents ( + InputFileName, + InputFileAlign, + InputFileNum, + FileBuffer, + &InputLength + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + if (CompareGuid (VendorGuid, &mZeroGuid) == 0) { + Offset = sizeof (CRC32_SECTION_HEADER); + if (InputLength + Offset >= MAX_SECTION_SIZE) { + Offset = sizeof (CRC32_SECTION_HEADER2); + } + } else { + Offset = sizeof (EFI_GUID_DEFINED_SECTION); + if (InputLength + Offset >= MAX_SECTION_SIZE) { + Offset = sizeof (EFI_GUID_DEFINED_SECTION2); + } + } + TotalLength = InputLength + Offset; + + FileBuffer = (UINT8 *) malloc (InputLength + Offset); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated"); + return EFI_OUT_OF_RESOURCES; + } + // + // read all input file contents into a buffer + // + Status = GetSectionContents ( + InputFileName, + InputFileAlign, + InputFileNum, + FileBuffer + Offset, + &InputLength + ); + } + + if (EFI_ERROR (Status)) { + if (FileBuffer != NULL) { + free (FileBuffer); + } + Error (NULL, 0, 0001, "Error opening file for reading", InputFileName[0]); + return Status; + } + + if (InputLength == 0) { + if (FileBuffer != NULL) { + free (FileBuffer); + } + Error (NULL, 0, 2000, "Invalid parameter", "the size of input file %s can't be zero", InputFileName); + return EFI_NOT_FOUND; + } + + // + // InputLength != 0, but FileBuffer == NULL means out of resources. + // + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated"); + return EFI_OUT_OF_RESOURCES; + } + + // + // Now data is in FileBuffer + Offset + // + if (CompareGuid (VendorGuid, &mZeroGuid) == 0) { + // + // Default Guid section is CRC32. + // + Crc32Checksum = 0; + CalculateCrc32 (FileBuffer + Offset, InputLength, &Crc32Checksum); + + if (TotalLength >= MAX_SECTION_SIZE) { + Crc32GuidSect2 = (CRC32_SECTION_HEADER2 *) FileBuffer; + Crc32GuidSect2->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED; + Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) 0xff; + Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) 0xff; + Crc32GuidSect2->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) 0xff; + Crc32GuidSect2->GuidSectionHeader.CommonHeader.ExtendedSize = TotalLength; + memcpy (&(Crc32GuidSect2->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID)); + Crc32GuidSect2->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID; + Crc32GuidSect2->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER2); + Crc32GuidSect2->CRC32Checksum = Crc32Checksum; + DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect2->GuidSectionHeader.DataOffset); + } else { + Crc32GuidSect = (CRC32_SECTION_HEADER *) FileBuffer; + Crc32GuidSect->GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED; + Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff); + Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8); + Crc32GuidSect->GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16); + memcpy (&(Crc32GuidSect->GuidSectionHeader.SectionDefinitionGuid), &mEfiCrc32SectionGuid, sizeof (EFI_GUID)); + Crc32GuidSect->GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID; + Crc32GuidSect->GuidSectionHeader.DataOffset = sizeof (CRC32_SECTION_HEADER); + Crc32GuidSect->CRC32Checksum = Crc32Checksum; + DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", Crc32GuidSect->GuidSectionHeader.DataOffset); + } + } else { + if (TotalLength >= MAX_SECTION_SIZE) { + VendorGuidSect2 = (EFI_GUID_DEFINED_SECTION2 *) FileBuffer; + VendorGuidSect2->CommonHeader.Type = EFI_SECTION_GUID_DEFINED; + VendorGuidSect2->CommonHeader.Size[0] = (UINT8) 0xff; + VendorGuidSect2->CommonHeader.Size[1] = (UINT8) 0xff; + VendorGuidSect2->CommonHeader.Size[2] = (UINT8) 0xff; + VendorGuidSect2->CommonHeader.ExtendedSize = InputLength + sizeof (EFI_GUID_DEFINED_SECTION2); + memcpy (&(VendorGuidSect2->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID)); + VendorGuidSect2->Attributes = DataAttribute; + VendorGuidSect2->DataOffset = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION2) + DataHeaderSize); + DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect2->DataOffset); + } else { + VendorGuidSect = (EFI_GUID_DEFINED_SECTION *) FileBuffer; + VendorGuidSect->CommonHeader.Type = EFI_SECTION_GUID_DEFINED; + VendorGuidSect->CommonHeader.Size[0] = (UINT8) (TotalLength & 0xff); + VendorGuidSect->CommonHeader.Size[1] = (UINT8) ((TotalLength & 0xff00) >> 8); + VendorGuidSect->CommonHeader.Size[2] = (UINT8) ((TotalLength & 0xff0000) >> 16); + memcpy (&(VendorGuidSect->SectionDefinitionGuid), VendorGuid, sizeof (EFI_GUID)); + VendorGuidSect->Attributes = DataAttribute; + VendorGuidSect->DataOffset = (UINT16) (sizeof (EFI_GUID_DEFINED_SECTION) + DataHeaderSize); + DebugMsg (NULL, 0, 9, "Guided section", "Data offset is %u", VendorGuidSect->DataOffset); + } + } + VerboseMsg ("the size of the created section file is %u bytes", (unsigned) TotalLength); + + // + // Set OutFileBuffer + // + *OutFileBuffer = FileBuffer; + + return EFI_SUCCESS; +} + +EFI_STATUS +FfsRebaseImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINT32 *ReadSize, + OUT VOID *Buffer + ) + /*++ + + Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + + Arguments: + + FileHandle - The handle to the PE/COFF file + + FileOffset - The offset, in bytes, into the file to read + + ReadSize - The number of bytes to read from the file starting at FileOffset + + Buffer - A pointer to the buffer to read the data into. + + Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + + --*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + UINT32 Length; + + Destination8 = Buffer; + Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); + Length = *ReadSize; + while (Length--) { + *(Destination8++) = *(Source8++); + } + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +GetAlignmentFromFile(char *InFile, UINT32 *Alignment) + /* + InFile is input file for getting alignment + return the alignment + */ +{ + FILE *InFileHandle; + UINT8 *PeFileBuffer; + UINTN PeFileSize; + UINT32 CurSecHdrSize; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + EFI_COMMON_SECTION_HEADER *CommonHeader; + EFI_STATUS Status; + + InFileHandle = NULL; + PeFileBuffer = NULL; + *Alignment = 0; + + memset (&ImageContext, 0, sizeof (ImageContext)); + + InFileHandle = fopen(LongFilePath(InFile), "rb"); + if (InFileHandle == NULL){ + Error (NULL, 0, 0001, "Error opening file", InFile); + return EFI_ABORTED; + } + PeFileSize = _filelength (fileno(InFileHandle)); + PeFileBuffer = (UINT8 *) malloc (PeFileSize); + if (PeFileBuffer == NULL) { + fclose (InFileHandle); + Error(NULL, 0, 4001, "Resource", "memory cannot be allocated of %s", InFileHandle); + return EFI_OUT_OF_RESOURCES; + } + fread (PeFileBuffer, sizeof (UINT8), PeFileSize, InFileHandle); + fclose (InFileHandle); + CommonHeader = (EFI_COMMON_SECTION_HEADER *) PeFileBuffer; + CurSecHdrSize = GetSectionHeaderLength(CommonHeader); + ImageContext.Handle = (VOID *) ((UINTN)PeFileBuffer + CurSecHdrSize); + ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE)FfsRebaseImageRead; + Status = PeCoffLoaderGetImageInfo(&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid PeImage", "The input file is %s and return status is %x", InFile, (int) Status); + return Status; + } + *Alignment = ImageContext.SectionAlignment; + // Free the allocated memory resource + if (PeFileBuffer != NULL) { + free (PeFileBuffer); + PeFileBuffer = NULL; + } + return EFI_SUCCESS; +} + +int +main ( + int argc, + char *argv[] + ) +/*++ + +Routine Description: + + Main + +Arguments: + + command line parameters + +Returns: + + EFI_SUCCESS Section header successfully generated and section concatenated. + EFI_ABORTED Could not generate the section + EFI_OUT_OF_RESOURCES No resource to complete the operation. + +--*/ +{ + UINT32 Index; + UINT32 InputFileNum; + FILE *OutFile; + CHAR8 **InputFileName; + CHAR8 *OutputFileName; + CHAR8 *SectionName; + CHAR8 *CompressionName; + CHAR8 *StringBuffer; + EFI_GUID VendorGuid = mZeroGuid; + int VersionNumber; + UINT8 SectType; + UINT8 SectCompSubType; + UINT16 SectGuidAttribute; + UINT64 SectGuidHeaderLength; + EFI_VERSION_SECTION *VersionSect; + EFI_USER_INTERFACE_SECTION *UiSect; + UINT32 InputLength; + UINT8 *OutFileBuffer; + EFI_STATUS Status; + UINT64 LogLevel; + UINT32 *InputFileAlign; + UINT32 InputFileAlignNum; + EFI_COMMON_SECTION_HEADER *SectionHeader; + CHAR8 *DummyFileName; + FILE *DummyFile; + UINTN DummyFileSize; + UINT8 *DummyFileBuffer; + FILE *InFile; + UINT8 *InFileBuffer; + UINTN InFileSize; + + InputFileAlign = NULL; + InputFileAlignNum = 0; + InputFileName = NULL; + OutputFileName = NULL; + SectionName = NULL; + CompressionName = NULL; + StringBuffer = ""; + OutFile = NULL; + VersionNumber = 0; + InputFileNum = 0; + SectType = EFI_SECTION_ALL; + SectCompSubType = 0; + SectGuidAttribute = EFI_GUIDED_SECTION_NONE; + OutFileBuffer = NULL; + InputLength = 0; + Status = STATUS_SUCCESS; + LogLevel = 0; + SectGuidHeaderLength = 0; + VersionSect = NULL; + UiSect = NULL; + DummyFileSize = 0; + DummyFileName = NULL; + DummyFile = NULL; + DummyFileBuffer = NULL; + InFile = NULL; + InFileSize = 0; + InFileBuffer = NULL; + + SetUtilityName (UTILITY_NAME); + + if (argc == 1) { + Error (NULL, 0, 1001, "Missing options", "No options input"); + Usage (); + return STATUS_ERROR; + } + + // + // Parse command line + // + argc --; + argv ++; + + if ((stricmp (argv[0], "-h") == 0) || (stricmp (argv[0], "--help") == 0)) { + Version (); + Usage (); + return STATUS_SUCCESS; + } + + if (stricmp (argv[0], "--version") == 0) { + Version (); + return STATUS_SUCCESS; + } + + while (argc > 0) { + if ((stricmp (argv[0], "-s") == 0) || (stricmp (argv[0], "--SectionType") == 0)) { + SectionName = argv[1]; + if (SectionName == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Section Type can't be NULL"); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-o") == 0) || (stricmp (argv[0], "--outputfile") == 0)) { + OutputFileName = argv[1]; + if (OutputFileName == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Output file can't be NULL"); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-c") == 0) || (stricmp (argv[0], "--compress") == 0)) { + CompressionName = argv[1]; + if (CompressionName == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Compression Type can't be NULL"); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-g") == 0) || (stricmp (argv[0], "--vendor") == 0)) { + Status = StringToGuid (argv[1], &VendorGuid); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + if (stricmp (argv[0], "--dummy") == 0) { + DummyFileName = argv[1]; + if (DummyFileName == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Dummy file can't be NULL"); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-r") == 0) || (stricmp (argv[0], "--attributes") == 0)) { + if (argv[1] == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Guid section attributes can't be NULL"); + goto Finish; + } + if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]) == 0) { + SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED; + } else if (stricmp (argv[1], mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]) == 0) { + SectGuidAttribute |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID; + } else if (stricmp (argv[1], mGUIDedSectionAttribue[0]) == 0) { + // + // NONE attribute + // + SectGuidAttribute |= EFI_GUIDED_SECTION_NONE; + } else { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-l") == 0) || (stricmp (argv[0], "--HeaderLength") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &SectGuidHeaderLength); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value for GuidHeaderLength", "%s = %s", argv[0], argv[1]); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-n") == 0) || (stricmp (argv[0], "--name") == 0)) { + StringBuffer = argv[1]; + if (StringBuffer == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "Name can't be NULL"); + goto Finish; + } + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-j") == 0) || (stricmp (argv[0], "--buildnumber") == 0)) { + if (argv[1] == NULL) { + Error (NULL, 0, 1003, "Invalid option value", "build number can't be NULL"); + goto Finish; + } + // + // Verify string is a integrator number + // + for (Index = 0; Index < strlen (argv[1]); Index++) { + if ((argv[1][Index] != '-') && (isdigit ((int)argv[1][Index]) == 0)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + } + + sscanf (argv[1], "%d", &VersionNumber); + argc -= 2; + argv += 2; + continue; + } + + if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) { + SetPrintLevel (VERBOSE_LOG_LEVEL); + VerboseMsg ("Verbose output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + SetPrintLevel (KEY_LOG_LEVEL); + KeyMsg ("Quiet output Mode Set!"); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + if (LogLevel > 9) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0~9, current input level is %d", (int) LogLevel); + goto Finish; + } + SetPrintLevel (LogLevel); + DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]); + argc -= 2; + argv += 2; + continue; + } + + // + // Section File alignment requirement + // + if (stricmp (argv[0], "--sectionalign") == 0) { + if (InputFileAlignNum == 0) { + InputFileAlign = (UINT32 *) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)); + if (InputFileAlign == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + goto Finish; + } + memset (InputFileAlign, 1, MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32)); + } else if (InputFileAlignNum % MAXIMUM_INPUT_FILE_NUM == 0) { + InputFileAlign = (UINT32 *) realloc ( + InputFileAlign, + (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (UINT32) + ); + + if (InputFileAlign == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + goto Finish; + } + memset (&(InputFileAlign[InputFileNum]), 1, (MAXIMUM_INPUT_FILE_NUM * sizeof (UINT32))); + } + if (stricmp(argv[1], "0") == 0) { + InputFileAlign[InputFileAlignNum] = 0; + } else { + Status = StringtoAlignment (argv[1], &(InputFileAlign[InputFileAlignNum])); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + goto Finish; + } + } + argc -= 2; + argv += 2; + InputFileAlignNum ++; + continue; + } + + // + // Get Input file name + // + if ((InputFileNum == 0) && (InputFileName == NULL)) { + InputFileName = (CHAR8 **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *)); + if (InputFileName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated"); + goto Finish; + } + memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *))); + } else if (InputFileNum % MAXIMUM_INPUT_FILE_NUM == 0) { + // + // InputFileName buffer too small, need to realloc + // + InputFileName = (CHAR8 **) realloc ( + InputFileName, + (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (CHAR8 *) + ); + + if (InputFileName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated"); + goto Finish; + } + memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (CHAR8 *))); + } + + InputFileName[InputFileNum++] = argv[0]; + argc --; + argv ++; + } + + if (InputFileAlignNum > 0 && InputFileAlignNum != InputFileNum) { + Error (NULL, 0, 1003, "Invalid option", "section alignment must be set for each section"); + goto Finish; + } + for (Index = 0; Index < InputFileAlignNum; Index++) + { + if (InputFileAlign[Index] == 0) { + Status = GetAlignmentFromFile(InputFileName[Index], &(InputFileAlign[Index])); + if (EFI_ERROR(Status)) { + Error (NULL, 0, 1003, "Fail to get Alignment from %s", InputFileName[InputFileNum]); + goto Finish; + } + } + } + + VerboseMsg ("%s tool start.", UTILITY_NAME); + + if (DummyFileName != NULL) { + // + // Open file and read contents + // + DummyFile = fopen (LongFilePath (DummyFileName), "rb"); + if (DummyFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", DummyFileName); + goto Finish; + } + + fseek (DummyFile, 0, SEEK_END); + DummyFileSize = ftell (DummyFile); + fseek (DummyFile, 0, SEEK_SET); + DummyFileBuffer = (UINT8 *) malloc (DummyFileSize); + if (DummyFileBuffer == NULL) { + fclose(DummyFile); + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated"); + goto Finish; + } + + fread(DummyFileBuffer, 1, DummyFileSize, DummyFile); + fclose(DummyFile); + DebugMsg (NULL, 0, 9, "Dummy files", "the dummy file name is %s and the size is %u bytes", DummyFileName, (unsigned) DummyFileSize); + + if (InputFileName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated"); + goto Finish; + } + InFile = fopen(LongFilePath(InputFileName[0]), "rb"); + if (InFile == NULL) { + Error (NULL, 0, 0001, "Error opening file", InputFileName[0]); + goto Finish; + } + + fseek (InFile, 0, SEEK_END); + InFileSize = ftell (InFile); + fseek (InFile, 0, SEEK_SET); + InFileBuffer = (UINT8 *) malloc (InFileSize); + if (InFileBuffer == NULL) { + fclose(InFile); + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated"); + goto Finish; + } + + fread(InFileBuffer, 1, InFileSize, InFile); + fclose(InFile); + DebugMsg (NULL, 0, 9, "Input files", "the input file name is %s and the size is %u bytes", InputFileName[0], (unsigned) InFileSize); + if (InFileSize > DummyFileSize){ + if (stricmp((CHAR8 *)DummyFileBuffer, (CHAR8 *)(InFileBuffer + (InFileSize - DummyFileSize))) == 0){ + SectGuidHeaderLength = InFileSize - DummyFileSize; + } + } + if (SectGuidHeaderLength == 0) { + SectGuidAttribute |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED; + } + if (DummyFileBuffer != NULL) { + free (DummyFileBuffer); + DummyFileBuffer = NULL; + } + if (InFileBuffer != NULL) { + free (InFileBuffer); + } + } + + // + // Parse all command line parameters to get the corresponding section type. + // + VerboseMsg ("Section type is %s", SectionName); + if (SectionName == NULL) { + // + // No specified Section type, default is SECTION_ALL. + // + SectType = EFI_SECTION_ALL; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPRESSION]) == 0) { + SectType = EFI_SECTION_COMPRESSION; + if (CompressionName == NULL) { + // + // Default is PI_STD compression algorithm. + // + SectCompSubType = EFI_STANDARD_COMPRESSION; + } else if (stricmp (CompressionName, mCompressionTypeName[EFI_NOT_COMPRESSED]) == 0) { + SectCompSubType = EFI_NOT_COMPRESSED; + } else if (stricmp (CompressionName, mCompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) { + SectCompSubType = EFI_STANDARD_COMPRESSION; + } else { + Error (NULL, 0, 1003, "Invalid option value", "--compress = %s", CompressionName); + goto Finish; + } + VerboseMsg ("Compress method is %s", mCompressionTypeName [SectCompSubType]); + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) { + SectType = EFI_SECTION_GUID_DEFINED; + + if ((SectGuidAttribute & EFI_GUIDED_SECTION_NONE) != 0) { + // + // NONE attribute, clear attribute value. + // + SectGuidAttribute = SectGuidAttribute & ~EFI_GUIDED_SECTION_NONE; + } + VerboseMsg ("Vendor Guid is %08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + (unsigned) VendorGuid.Data1, + VendorGuid.Data2, + VendorGuid.Data3, + VendorGuid.Data4[0], + VendorGuid.Data4[1], + VendorGuid.Data4[2], + VendorGuid.Data4[3], + VendorGuid.Data4[4], + VendorGuid.Data4[5], + VendorGuid.Data4[6], + VendorGuid.Data4[7]); + if ((SectGuidAttribute & EFI_GUIDED_SECTION_PROCESSING_REQUIRED) != 0) { + VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_PROCESSING_REQUIRED]); + } + if ((SectGuidAttribute & EFI_GUIDED_SECTION_AUTH_STATUS_VALID) != 0) { + VerboseMsg ("Guid Attribute is %s", mGUIDedSectionAttribue[EFI_GUIDED_SECTION_AUTH_STATUS_VALID]); + } + if (SectGuidHeaderLength != 0) { + VerboseMsg ("Guid Data Header size is 0x%llx", (unsigned long long) SectGuidHeaderLength); + } + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PE32]) == 0) { + SectType = EFI_SECTION_PE32; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PIC]) == 0) { + SectType = EFI_SECTION_PIC; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_TE]) == 0) { + SectType = EFI_SECTION_TE; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) { + SectType = EFI_SECTION_DXE_DEPEX; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_SMM_DEPEX]) == 0) { + SectType = EFI_SECTION_SMM_DEPEX; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_VERSION]) == 0) { + SectType = EFI_SECTION_VERSION; + if (VersionNumber < 0 || VersionNumber > 65535) { + Error (NULL, 0, 1003, "Invalid option value", "%d is not in 0~65535", VersionNumber); + goto Finish; + } + VerboseMsg ("Version section number is %d", VersionNumber); + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) { + SectType = EFI_SECTION_USER_INTERFACE; + if (StringBuffer[0] == '\0') { + Error (NULL, 0, 1001, "Missing option", "user interface string"); + goto Finish; + } + VerboseMsg ("UI section string name is %s", StringBuffer); + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) { + SectType = EFI_SECTION_COMPATIBILITY16; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) { + SectType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) { + SectType = EFI_SECTION_FREEFORM_SUBTYPE_GUID; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_RAW]) == 0) { + SectType = EFI_SECTION_RAW; + } else if (stricmp (SectionName, mSectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) { + SectType = EFI_SECTION_PEI_DEPEX; + } else { + Error (NULL, 0, 1003, "Invalid option value", "SectionType = %s", SectionName); + goto Finish; + } + + // + // GuidValue is only required by Guided section. + // + if ((SectType != EFI_SECTION_GUID_DEFINED) && + (SectionName != NULL) && + (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) { + fprintf (stdout, "Warning: the input guid value is not required for this section type %s\n", SectionName); + } + + // + // Check whether there is input file + // + if ((SectType != EFI_SECTION_VERSION) && (SectType != EFI_SECTION_USER_INTERFACE)) { + // + // The input file are required for other section type. + // + if (InputFileNum == 0) { + Error (NULL, 0, 1001, "Missing options", "Input files"); + goto Finish; + } + } + // + // Check whether there is output file + // + for (Index = 0; Index < InputFileNum; Index ++) { + VerboseMsg ("the %uth input file name is %s", (unsigned) Index, InputFileName[Index]); + } + if (OutputFileName == NULL) { + Error (NULL, 0, 1001, "Missing options", "Output file"); + goto Finish; + // OutFile = stdout; + } + VerboseMsg ("Output file name is %s", OutputFileName); + + // + // At this point, we've fully validated the command line, and opened appropriate + // files, so let's go and do what we've been asked to do... + // + // + // Within this switch, build and write out the section header including any + // section type specific pieces. If there's an input file, it's tacked on later + // + switch (SectType) { + case EFI_SECTION_COMPRESSION: + if (InputFileAlign != NULL) { + free (InputFileAlign); + InputFileAlign = NULL; + } + Status = GenSectionCompressionSection ( + InputFileName, + InputFileAlign, + InputFileNum, + SectCompSubType, + &OutFileBuffer + ); + break; + + case EFI_SECTION_GUID_DEFINED: + if (InputFileAlign != NULL && (CompareGuid (&VendorGuid, &mZeroGuid) != 0)) { + // + // Only process alignment for the default known CRC32 guided section. + // For the unknown guided section, the alignment is processed when the dummy all section (EFI_SECTION_ALL) is generated. + // + free (InputFileAlign); + InputFileAlign = NULL; + } + Status = GenSectionGuidDefinedSection ( + InputFileName, + InputFileAlign, + InputFileNum, + &VendorGuid, + SectGuidAttribute, + (UINT32) SectGuidHeaderLength, + &OutFileBuffer + ); + break; + + case EFI_SECTION_VERSION: + Index = sizeof (EFI_COMMON_SECTION_HEADER); + // + // 2 bytes for the build number UINT16 + // + Index += 2; + // + // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null. + // + Index += (strlen (StringBuffer) * 2) + 2; + OutFileBuffer = (UINT8 *) malloc (Index); + if (OutFileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated"); + goto Finish; + } + VersionSect = (EFI_VERSION_SECTION *) OutFileBuffer; + VersionSect->CommonHeader.Type = SectType; + VersionSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff); + VersionSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8); + VersionSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16); + VersionSect->BuildNumber = (UINT16) VersionNumber; + Ascii2UnicodeString (StringBuffer, VersionSect->VersionString); + VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index); + break; + + case EFI_SECTION_USER_INTERFACE: + Index = sizeof (EFI_COMMON_SECTION_HEADER); + // + // StringBuffer is ascii.. unicode is 2X + 2 bytes for terminating unicode null. + // + Index += (strlen (StringBuffer) * 2) + 2; + OutFileBuffer = (UINT8 *) malloc (Index); + if (OutFileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated"); + goto Finish; + } + UiSect = (EFI_USER_INTERFACE_SECTION *) OutFileBuffer; + UiSect->CommonHeader.Type = SectType; + UiSect->CommonHeader.Size[0] = (UINT8) (Index & 0xff); + UiSect->CommonHeader.Size[1] = (UINT8) ((Index & 0xff00) >> 8); + UiSect->CommonHeader.Size[2] = (UINT8) ((Index & 0xff0000) >> 16); + Ascii2UnicodeString (StringBuffer, UiSect->FileNameString); + VerboseMsg ("the size of the created section file is %u bytes", (unsigned) Index); + break; + + case EFI_SECTION_ALL: + // + // read all input file contents into a buffer + // first get the size of all file contents + // + Status = GetSectionContents ( + InputFileName, + InputFileAlign, + InputFileNum, + OutFileBuffer, + &InputLength + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + OutFileBuffer = (UINT8 *) malloc (InputLength); + if (OutFileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated"); + goto Finish; + } + // + // read all input file contents into a buffer + // + Status = GetSectionContents ( + InputFileName, + InputFileAlign, + InputFileNum, + OutFileBuffer, + &InputLength + ); + } + VerboseMsg ("the size of the created section file is %u bytes", (unsigned) InputLength); + break; + default: + // + // All other section types are caught by default (they're all the same) + // + Status = GenSectionCommonLeafSection ( + InputFileName, + InputFileNum, + SectType, + &OutFileBuffer + ); + break; + } + + if (Status != EFI_SUCCESS || OutFileBuffer == NULL) { + Error (NULL, 0, 2000, "Status is not successful", "Status value is 0x%X", (int) Status); + goto Finish; + } + + // + // Get output file length + // + if (SectType != EFI_SECTION_ALL) { + SectionHeader = (EFI_COMMON_SECTION_HEADER *)OutFileBuffer; + InputLength = *(UINT32 *)SectionHeader->Size & 0x00ffffff; + if (InputLength == 0xffffff) { + InputLength = ((EFI_COMMON_SECTION_HEADER2 *)SectionHeader)->ExtendedSize; + } + } + + // + // Write the output file + // + OutFile = fopen (LongFilePath (OutputFileName), "wb"); + if (OutFile == NULL) { + Error (NULL, 0, 0001, "Error opening file for writing", OutputFileName); + goto Finish; + } + + fwrite (OutFileBuffer, InputLength, 1, OutFile); + +Finish: + if (InputFileName != NULL) { + free (InputFileName); + } + + if (InputFileAlign != NULL) { + free (InputFileAlign); + } + + if (OutFileBuffer != NULL) { + free (OutFileBuffer); + } + + if (OutFile != NULL) { + fclose (OutFile); + } + + if (DummyFileBuffer != NULL) { + free (DummyFileBuffer); + } + + VerboseMsg ("%s tool done with return code is 0x%x.", UTILITY_NAME, GetUtilityStatus ()); + + return GetUtilityStatus (); +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/Makefile new file mode 100644 index 00000000..8b9d4841 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/Makefile @@ -0,0 +1,18 @@ +## @file +# Windows makefile for 'GenSec' module build. +# +# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenSec + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = GenSec.obj + +#CFLAGS = $(CFLAGS) /nodefaultlib:libc.lib + +!INCLUDE ..\Makefiles\ms.app + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/Makefile.kmk new file mode 100644 index 00000000..d294db44 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/GenSec/Makefile.kmk @@ -0,0 +1,45 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-makefile for the EFI GenSec build tool. +# + +# +# Copyright (C) 2013-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# 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, in version 3 of the +# License. +# +# 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 . +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +SUB_DEPTH = ../../../../../../../../.. +include $(KBUILD_PATH)/subheader.kmk + +BLDPROGS += GenSec +GenSec_TEMPLATE = VBoxEfiBldProg +GenSec_SOURCES = GenSec.c + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/AArch64/ProcessorBind.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/AArch64/ProcessorBind.h new file mode 100644 index 00000000..93d656f5 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/AArch64/ProcessorBind.h @@ -0,0 +1,148 @@ +/** @file + Processor or Compiler specific defines and types for AArch64. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ Portions copyright (c) 2013, ARM Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __PROCESSOR_BIND_H__ +#define __PROCESSOR_BIND_H__ + +/// +/// Define the processor type so other code can make processor based choices +/// +#define MDE_CPU_AARCH64 + +// +// Make sure we are using the correct packing rules per EFI specification +// +#ifndef __GNUC__ +#pragma pack() +#endif + +#if _MSC_EXTENSIONS + // + // use Microsoft* C compiler dependent integer width types + // + typedef unsigned __int64 UINT64; + typedef __int64 INT64; + typedef unsigned __int32 UINT32; + typedef __int32 INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef signed char INT8; +#else + // + // Use ANSI C 2000 stdint.h integer width declarations + // + #include + typedef uint8_t BOOLEAN; + typedef int8_t INT8; + typedef uint8_t UINT8; + typedef int16_t INT16; + typedef uint16_t UINT16; + typedef int32_t INT32; + typedef uint32_t UINT32; + typedef int64_t INT64; + typedef uint64_t UINT64; + typedef char CHAR8; + typedef uint16_t CHAR16; + +#endif + +/// +/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions, +/// 8 bytes on supported 64-bit processor instructions) +/// +typedef UINT64 UINTN; + +/// +/// Signed value of native width. (4 bytes on supported 32-bit processor instructions, +/// 8 bytes on supported 64-bit processor instructions) +/// +typedef INT64 INTN; + +// +// Processor specific defines +// + +/// +/// A value of native width with the highest bit set. +/// +#define MAX_BIT 0x8000000000000000 + +/// +/// A value of native width with the two highest bits set. +/// +#define MAX_2_BITS 0xC000000000000000 + +/// +/// The stack alignment required for AARCH64 +/// +#define CPU_STACK_ALIGNMENT 16 + +// +// Modifier to ensure that all protocol member functions and EFI intrinsics +// use the correct C calling convention. All protocol member functions and +// EFI intrinsics are required to modify their member functions with EFIAPI. +// +#define EFIAPI + +#if defined(__GNUC__) + /// + /// For GNU assembly code, .global or .globl can declare global symbols. + /// Define this macro to unify the usage. + /// + #define ASM_GLOBAL .globl + + #if !defined(__APPLE__) + /// + /// ARM EABI defines that the linker should not manipulate call relocations + /// (do bl/blx conversion) unless the target symbol has function type. + /// CodeSourcery 2010.09 started requiring the .type to function properly + /// + #define INTERWORK_FUNC(func__) .type ASM_PFX(func__), %function + + #define GCC_ASM_EXPORT(func__) \ + .global _CONCATENATE (__USER_LABEL_PREFIX__, func__) ;\ + .type ASM_PFX(func__), %function + + #define GCC_ASM_IMPORT(func__) \ + .extern _CONCATENATE (__USER_LABEL_PREFIX__, func__) + + #else + // + // .type not supported by Apple Xcode tools + // + #define INTERWORK_FUNC(func__) + + #define GCC_ASM_EXPORT(func__) \ + .globl _CONCATENATE (__USER_LABEL_PREFIX__, func__) \ + + #define GCC_ASM_IMPORT(name) + + #endif +#endif + +/** + Return the pointer to the first instruction of a function given a function pointer. + On ARM CPU architectures, these two pointer values are the same, + so the implementation of this macro is very simple. + + @param FunctionPointer A pointer to a function. + + @return The pointer to the first instruction of a function given a function pointer. + +**/ +#define FUNCTION_ENTRY_POINT(FunctionPointer) (VOID *)(UINTN)(FunctionPointer) + +#endif + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Arm/ProcessorBind.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Arm/ProcessorBind.h new file mode 100644 index 00000000..de5c5a0a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Arm/ProcessorBind.h @@ -0,0 +1,147 @@ +/** @file + Processor or Compiler specific defines and types for ARM. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __PROCESSOR_BIND_H__ +#define __PROCESSOR_BIND_H__ + +/// +/// Define the processor type so other code can make processor based choices +/// +#define MDE_CPU_ARM + +// +// Make sure we are using the correct packing rules per EFI specification +// +#ifndef __GNUC__ +#pragma pack() +#endif + +#if _MSC_EXTENSIONS + // + // use Microsoft* C compiler dependent integer width types + // + typedef unsigned __int64 UINT64; + typedef __int64 INT64; + typedef unsigned __int32 UINT32; + typedef __int32 INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef signed char INT8; +#else + // + // Assume standard ARM alignment. + // + typedef unsigned long long UINT64; + typedef long long INT64; + typedef unsigned int UINT32; + typedef int INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef signed char INT8; + + #define UINT8_MAX 0xff +#endif + +/// +/// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions, +/// 8 bytes on supported 64-bit processor instructions) +/// +typedef UINT32 UINTN; + +/// +/// Signed value of native width. (4 bytes on supported 32-bit processor instructions, +/// 8 bytes on supported 64-bit processor instructions) +/// +typedef INT32 INTN; + +// +// Processor specific defines +// + +/// +/// A value of native width with the highest bit set. +/// +#define MAX_BIT 0x80000000 + +/// +/// A value of native width with the two highest bits set. +/// +#define MAX_2_BITS 0xC0000000 + +/// +/// The stack alignment required for ARM +/// +#define CPU_STACK_ALIGNMENT sizeof(UINT64) + +// +// Modifier to ensure that all protocol member functions and EFI intrinsics +// use the correct C calling convention. All protocol member functions and +// EFI intrinsics are required to modify their member functions with EFIAPI. +// +#define EFIAPI + +#if defined(__GNUC__) + /// + /// For GNU assembly code, .global or .globl can declare global symbols. + /// Define this macro to unify the usage. + /// + #define ASM_GLOBAL .globl + + #if !defined(__APPLE__) + /// + /// ARM EABI defines that the linker should not manipulate call relocations + /// (do bl/blx conversion) unless the target symbol has function type. + /// CodeSourcery 2010.09 started requiring the .type to function properly + /// + #define INTERWORK_FUNC(func__) .type ASM_PFX(func__), %function + + #define GCC_ASM_EXPORT(func__) \ + .global _CONCATENATE (__USER_LABEL_PREFIX__, func__) ;\ + .type ASM_PFX(func__), %function + + #define GCC_ASM_IMPORT(func__) \ + .extern _CONCATENATE (__USER_LABEL_PREFIX__, func__) + + #else + // + // .type not supported by Apple Xcode tools + // + #define INTERWORK_FUNC(func__) + + #define GCC_ASM_EXPORT(func__) \ + .globl _CONCATENATE (__USER_LABEL_PREFIX__, func__) \ + + #define GCC_ASM_IMPORT(name) + + #endif +#endif + +/** + Return the pointer to the first instruction of a function given a function pointer. + On ARM CPU architectures, these two pointer values are the same, + so the implementation of this macro is very simple. + + @param FunctionPointer A pointer to a function. + + @return The pointer to the first instruction of a function given a function pointer. + +**/ +#define FUNCTION_ENTRY_POINT(FunctionPointer) (VOID *)(UINTN)(FunctionPointer) + +#endif + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/BaseTypes.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/BaseTypes.h new file mode 100644 index 00000000..18d202e0 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/BaseTypes.h @@ -0,0 +1,318 @@ +/** @file + Processor or Compiler specific defines for all supported processors. + + This file is stand alone self consistent set of definitions. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __BASE_TYPES_H__ +#define __BASE_TYPES_H__ + +// +// Include processor specific binding +// +#include +#include + +// +// Modifiers to abstract standard types to aid in debug of problems +// +#define CONST const +#define STATIC static +#define VOID void + +// +// Modifiers for Data Types used to self document code. +// This concept is borrowed for UEFI specification. +// +#ifndef IN +// +// Some other environments use this construct, so #ifndef to prevent +// multiple definition. +// +#define IN +#define OUT +#define OPTIONAL +#endif + +// +// Constants. They may exist in other build structures, so #ifndef them. +// +#ifndef TRUE +// +// BugBug: UEFI specification claims 1 and 0. We are concerned about the +// compiler portability so we did it this way. +// +#define TRUE ((BOOLEAN)(1==1)) +#endif + +#ifndef FALSE +#define FALSE ((BOOLEAN)(0==1)) +#endif + +#ifndef NULL +#define NULL ((VOID *) 0) +#endif + +#ifdef __CC_ARM + // + // Older RVCT ARM compilers don't fully support #pragma pack and require __packed + // as a prefix for the structure. + // + #define PACKED __packed +#else + #define PACKED +#endif + +// +// Support for variable length argument lists using the ANSI standard. +// +// Since we are using the ANSI standard we used the standard naming and +// did not follow the coding convention +// +// VA_LIST - typedef for argument list. +// VA_START (VA_LIST Marker, argument before the ...) - Init Marker for use. +// VA_END (VA_LIST Marker) - Clear Marker +// VA_ARG (VA_LIST Marker, var arg size) - Use Marker to get an argument from +// the ... list. You must know the size and pass it in this macro. +// +// example: +// +// UINTN +// ExampleVarArg ( +// IN UINTN NumberOfArgs, +// ... +// ) +// { +// VA_LIST Marker; +// UINTN Index; +// UINTN Result; +// +// // +// // Initialize the Marker +// // +// VA_START (Marker, NumberOfArgs); +// for (Index = 0, Result = 0; Index < NumberOfArgs; Index++) { +// // +// // The ... list is a series of UINTN values, so average them up. +// // +// Result += VA_ARG (Marker, UINTN); +// } +// +// VA_END (Marker); +// return Result +// } +// + +#define _INT_SIZE_OF(n) ((sizeof (n) + sizeof (UINTN) - 1) &~(sizeof (UINTN) - 1)) + +// +// Also support coding convention rules for var arg macros +// +#ifndef VA_START + +// typedef CHAR8 *VA_LIST; +// #define VA_START(ap, v) (ap = (VA_LIST) & (v) + _INT_SIZE_OF (v)) +// #define VA_ARG(ap, t) (*(t *) ((ap += _INT_SIZE_OF (t)) - _INT_SIZE_OF (t))) +// #define VA_END(ap) (ap = (VA_LIST) 0) +// Use the native arguments for tools. +#define VA_START va_start +#define VA_ARG va_arg +#define VA_END va_end +#define VA_LIST va_list + +#endif + +#ifndef GUID_DEFINED +#define GUID_DEFINED +/// +/// 128 bit buffer containing a unique identifier value. +/// Unless otherwise specified, aligned on a 64 bit boundary. +/// +typedef struct { + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; +} GUID; +#endif + +/// +/// 4-byte buffer. An IPv4 internet protocol address. +/// +typedef struct { + UINT8 Addr[4]; +} IPv4_ADDRESS; + +/// +/// 16-byte buffer. An IPv6 internet protocol address. +/// +typedef struct { + UINT8 Addr[16]; +} IPv6_ADDRESS; + +// +// Macro that returns the byte offset of a field in a data structure. +// +#define OFFSET_OF(TYPE, Field) ((UINTN) &(((TYPE *)0)->Field)) + +/// +/// _CR - returns a pointer to the structure +/// from one of its elements. +/// +#define _CR(Record, TYPE, Field) ((TYPE *) ((CHAR8 *) (Record) - (CHAR8 *) &(((TYPE *) 0)->Field))) + +/// +/// ALIGN_POINTER - aligns a pointer to the lowest boundary +/// +#define ALIGN_POINTER(p, s) ((VOID *) ((UINTN)(p) + (((s) - ((UINTN) (p))) & ((s) - 1)))) + +/// +/// ALIGN_VARIABLE - aligns a variable up to the next natural boundary for int size of a processor +/// +#define ALIGN_VARIABLE(Value, Adjustment) \ + Adjustment = 0U; \ + if ((UINTN) (Value) % sizeof (UINTN)) { \ + (Adjustment) = (UINTN)(sizeof (UINTN) - ((UINTN) (Value) % sizeof (UINTN))); \ + } \ + (Value) = (UINTN)((UINTN) (Value) + (UINTN) (Adjustment)) + +// +// Return the maximum of two operands. +// This macro returns the maximum of two operand specified by a and b. +// Both a and b must be the same numerical types, signed or unsigned. +// +#define MAX(a, b) \ + (((a) > (b)) ? (a) : (b)) + + +// +// Return the minimum of two operands. +// This macro returns the minimal of two operand specified by a and b. +// Both a and b must be the same numerical types, signed or unsigned. +// +#define MIN(a, b) \ + (((a) < (b)) ? (a) : (b)) + + +// +// EFI Error Codes common to all execution phases +// + +typedef UINTN RETURN_STATUS; + +/// +/// Set the upper bit to indicate EFI Error. +/// +#define ENCODE_ERROR(a) ((RETURN_STATUS)(MAX_BIT | (a))) + +#define ENCODE_WARNING(a) ((RETURN_STATUS)(a)) +#define RETURN_ERROR(a) (((INTN)(RETURN_STATUS)(a)) < 0) + +#define RETURN_SUCCESS 0 +#define RETURN_LOAD_ERROR ENCODE_ERROR (1) +#define RETURN_INVALID_PARAMETER ENCODE_ERROR (2) +#define RETURN_UNSUPPORTED ENCODE_ERROR (3) +#define RETURN_BAD_BUFFER_SIZE ENCODE_ERROR (4) +#define RETURN_BUFFER_TOO_SMALL ENCODE_ERROR (5) +#define RETURN_NOT_READY ENCODE_ERROR (6) +#define RETURN_DEVICE_ERROR ENCODE_ERROR (7) +#define RETURN_WRITE_PROTECTED ENCODE_ERROR (8) +#define RETURN_OUT_OF_RESOURCES ENCODE_ERROR (9) +#define RETURN_VOLUME_CORRUPTED ENCODE_ERROR (10) +#define RETURN_VOLUME_FULL ENCODE_ERROR (11) +#define RETURN_NO_MEDIA ENCODE_ERROR (12) +#define RETURN_MEDIA_CHANGED ENCODE_ERROR (13) +#define RETURN_NOT_FOUND ENCODE_ERROR (14) +#define RETURN_ACCESS_DENIED ENCODE_ERROR (15) +#define RETURN_NO_RESPONSE ENCODE_ERROR (16) +#define RETURN_NO_MAPPING ENCODE_ERROR (17) +#define RETURN_TIMEOUT ENCODE_ERROR (18) +#define RETURN_NOT_STARTED ENCODE_ERROR (19) +#define RETURN_ALREADY_STARTED ENCODE_ERROR (20) +#define RETURN_ABORTED ENCODE_ERROR (21) +#define RETURN_ICMP_ERROR ENCODE_ERROR (22) +#define RETURN_TFTP_ERROR ENCODE_ERROR (23) +#define RETURN_PROTOCOL_ERROR ENCODE_ERROR (24) +#define RETURN_INCOMPATIBLE_VERSION ENCODE_ERROR (25) +#define RETURN_SECURITY_VIOLATION ENCODE_ERROR (26) +#define RETURN_CRC_ERROR ENCODE_ERROR (27) +#define RETURN_END_OF_MEDIA ENCODE_ERROR (28) +#define RETURN_END_OF_FILE ENCODE_ERROR (31) + +#define RETURN_WARN_UNKNOWN_GLYPH ENCODE_WARNING (1) +#define RETURN_WARN_DELETE_FAILURE ENCODE_WARNING (2) +#define RETURN_WARN_WRITE_FAILURE ENCODE_WARNING (3) +#define RETURN_WARN_BUFFER_TOO_SMALL ENCODE_WARNING (4) + +typedef UINT64 PHYSICAL_ADDRESS; + +#define BIT0 0x00000001 +#define BIT1 0x00000002 +#define BIT2 0x00000004 +#define BIT3 0x00000008 +#define BIT4 0x00000010 +#define BIT5 0x00000020 +#define BIT6 0x00000040 +#define BIT7 0x00000080 +#define BIT8 0x00000100 +#define BIT9 0x00000200 +#define BIT10 0x00000400 +#define BIT11 0x00000800 +#define BIT12 0x00001000 +#define BIT13 0x00002000 +#define BIT14 0x00004000 +#define BIT15 0x00008000 +#define BIT16 0x00010000 +#define BIT17 0x00020000 +#define BIT18 0x00040000 +#define BIT19 0x00080000 +#define BIT20 0x00100000 +#define BIT21 0x00200000 +#define BIT22 0x00400000 +#define BIT23 0x00800000 +#define BIT24 0x01000000 +#define BIT25 0x02000000 +#define BIT26 0x04000000 +#define BIT27 0x08000000 +#define BIT28 0x10000000 +#define BIT29 0x20000000 +#define BIT30 0x40000000 +#define BIT31 0x80000000 +#define BIT32 0x0000000100000000ULL +#define BIT33 0x0000000200000000ULL +#define BIT34 0x0000000400000000ULL +#define BIT35 0x0000000800000000ULL +#define BIT36 0x0000001000000000ULL +#define BIT37 0x0000002000000000ULL +#define BIT38 0x0000004000000000ULL +#define BIT39 0x0000008000000000ULL +#define BIT40 0x0000010000000000ULL +#define BIT41 0x0000020000000000ULL +#define BIT42 0x0000040000000000ULL +#define BIT43 0x0000080000000000ULL +#define BIT44 0x0000100000000000ULL +#define BIT45 0x0000200000000000ULL +#define BIT46 0x0000400000000000ULL +#define BIT47 0x0000800000000000ULL +#define BIT48 0x0001000000000000ULL +#define BIT49 0x0002000000000000ULL +#define BIT50 0x0004000000000000ULL +#define BIT51 0x0008000000000000ULL +#define BIT52 0x0010000000000000ULL +#define BIT53 0x0020000000000000ULL +#define BIT54 0x0040000000000000ULL +#define BIT55 0x0080000000000000ULL +#define BIT56 0x0100000000000000ULL +#define BIT57 0x0200000000000000ULL +#define BIT58 0x0400000000000000ULL +#define BIT59 0x0800000000000000ULL +#define BIT60 0x1000000000000000ULL +#define BIT61 0x2000000000000000ULL +#define BIT62 0x4000000000000000ULL +#define BIT63 0x8000000000000000ULL + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/BuildVersion.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/BuildVersion.h new file mode 100644 index 00000000..de1cbde8 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/BuildVersion.h @@ -0,0 +1,9 @@ +/** @file +This file is for build version number auto generation + +Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#define __BUILD_VERSION "Developer Build based on Revision: Unknown" diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/MdeModuleHii.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/MdeModuleHii.h new file mode 100644 index 00000000..b52a6358 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/MdeModuleHii.h @@ -0,0 +1,233 @@ +/** @file + EDK II specific HII relative definition. + + Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _MDEMODULE_HII_H +#define _MDEMODULE_HII_H + +#define NARROW_CHAR 0xFFF0 +#define WIDE_CHAR 0xFFF1 +#define NON_BREAKING_CHAR 0xFFF2 + +/// +/// State defined for password statemachine . +/// +#define BROWSER_STATE_VALIDATE_PASSWORD 0 +#define BROWSER_STATE_SET_PASSWORD 1 + +/// +/// GUIDed opcodes defined for EDKII implementation. +/// +#define EFI_IFR_TIANO_GUID \ + { 0xf0b1735, 0x87a0, 0x4193, {0xb2, 0x66, 0x53, 0x8c, 0x38, 0xaf, 0x48, 0xce} } + +#pragma pack(1) + +/// +/// EDKII implementation extension opcodes, new extension can be added here later. +/// +#define EFI_IFR_EXTEND_OP_LABEL 0x0 +#define EFI_IFR_EXTEND_OP_BANNER 0x1 +#define EFI_IFR_EXTEND_OP_TIMEOUT 0x2 +#define EFI_IFR_EXTEND_OP_CLASS 0x3 +#define EFI_IFR_EXTEND_OP_SUBCLASS 0x4 + +/// +/// Label opcode. +/// +typedef struct _EFI_IFR_GUID_LABEL { + EFI_IFR_OP_HEADER Header; + /// + /// EFI_IFR_TIANO_GUID. + /// + EFI_GUID Guid; + /// + /// EFI_IFR_EXTEND_OP_LABEL. + /// + UINT8 ExtendOpCode; + /// + /// Label Number. + /// + UINT16 Number; +} EFI_IFR_GUID_LABEL; + +#define EFI_IFR_BANNER_ALIGN_LEFT 0 +#define EFI_IFR_BANNER_ALIGN_CENTER 1 +#define EFI_IFR_BANNER_ALIGN_RIGHT 2 + +/// +/// Banner opcode. +/// +typedef struct _EFI_IFR_GUID_BANNER { + EFI_IFR_OP_HEADER Header; + /// + /// EFI_IFR_TIANO_GUID. + /// + EFI_GUID Guid; + /// + /// EFI_IFR_EXTEND_OP_BANNER + /// + UINT8 ExtendOpCode; + EFI_STRING_ID Title; ///< The string token for the banner title. + UINT16 LineNumber; ///< 1-based line number. + UINT8 Alignment; ///< left, center, or right-aligned. +} EFI_IFR_GUID_BANNER; + +/// +/// Timeout opcode. +/// +typedef struct _EFI_IFR_GUID_TIMEOUT { + EFI_IFR_OP_HEADER Header; + /// + /// EFI_IFR_TIANO_GUID. + /// + EFI_GUID Guid; + /// + /// EFI_IFR_EXTEND_OP_TIMEOUT. + /// + UINT8 ExtendOpCode; + UINT16 TimeOut; ///< TimeOut Value. +} EFI_IFR_GUID_TIMEOUT; + +#define EFI_NON_DEVICE_CLASS 0x00 +#define EFI_DISK_DEVICE_CLASS 0x01 +#define EFI_VIDEO_DEVICE_CLASS 0x02 +#define EFI_NETWORK_DEVICE_CLASS 0x04 +#define EFI_INPUT_DEVICE_CLASS 0x08 +#define EFI_ON_BOARD_DEVICE_CLASS 0x10 +#define EFI_OTHER_DEVICE_CLASS 0x20 + +/// +/// Device Class opcode. +/// +typedef struct _EFI_IFR_GUID_CLASS { + EFI_IFR_OP_HEADER Header; + /// + /// EFI_IFR_TIANO_GUID. + /// + EFI_GUID Guid; + /// + /// EFI_IFR_EXTEND_OP_CLASS. + /// + UINT8 ExtendOpCode; + UINT16 Class; ///< Device Class from the above. +} EFI_IFR_GUID_CLASS; + +#define EFI_SETUP_APPLICATION_SUBCLASS 0x00 +#define EFI_GENERAL_APPLICATION_SUBCLASS 0x01 +#define EFI_FRONT_PAGE_SUBCLASS 0x02 +#define EFI_SINGLE_USE_SUBCLASS 0x03 + +/// +/// SubClass opcode +/// +typedef struct _EFI_IFR_GUID_SUBCLASS { + EFI_IFR_OP_HEADER Header; + /// + /// EFI_IFR_TIANO_GUID. + /// + EFI_GUID Guid; + /// + /// EFI_IFR_EXTEND_OP_SUBCLASS. + /// + UINT8 ExtendOpCode; + UINT16 SubClass; ///< Sub Class type from the above. +} EFI_IFR_GUID_SUBCLASS; + +/// +/// GUIDed opcodes support for framework vfr. +/// +#define EFI_IFR_FRAMEWORK_GUID \ + { 0x31ca5d1a, 0xd511, 0x4931, { 0xb7, 0x82, 0xae, 0x6b, 0x2b, 0x17, 0x8c, 0xd7 } } + +/// +/// Two extended opcodes are added, and new extensions can be added here later. +/// One is for framework OneOf question Option Key value; +/// another is for framework vareqval. +/// +#define EFI_IFR_EXTEND_OP_OPTIONKEY 0x0 +#define EFI_IFR_EXTEND_OP_VAREQNAME 0x1 + +/// +/// Store the framework vfr option key value. +/// +typedef struct _EFI_IFR_GUID_OPTIONKEY { + EFI_IFR_OP_HEADER Header; + /// + /// EFI_IFR_FRAMEWORK_GUID. + /// + EFI_GUID Guid; + /// + /// EFI_IFR_EXTEND_OP_OPTIONKEY. + /// + UINT8 ExtendOpCode; + /// + /// OneOf Questiond ID binded by OneOf Option. + /// + EFI_QUESTION_ID QuestionId; + /// + /// The OneOf Option Value. + /// + EFI_IFR_TYPE_VALUE OptionValue; + /// + /// The Framework OneOf Option Key Value. + /// + UINT16 KeyValue; +} EFI_IFR_GUID_OPTIONKEY; + +/// +/// Store the framework vfr vareqval name number. +/// +typedef struct _EFI_IFR_GUID_VAREQNAME { + EFI_IFR_OP_HEADER Header; + /// + /// EFI_IFR_FRAMEWORK_GUID. + /// + EFI_GUID Guid; + /// + /// EFI_IFR_EXTEND_OP_VAREQNAME. + /// + UINT8 ExtendOpCode; + /// + /// Question ID of the Numeric Opcode created. + /// + EFI_QUESTION_ID QuestionId; + /// + /// For vareqval (0x100), NameId is 0x100. + /// This value will convert to a Unicode String following this rule; + /// sprintf(StringBuffer, "%d", NameId) . + /// The Unicode String will be used as a EFI Variable Name. + /// + UINT16 NameId; +} EFI_IFR_GUID_VAREQNAME; + +/// +/// EDKII implementation extension GUID, used to indicate there are bit fields in the varstore. +/// +#define EDKII_IFR_BIT_VARSTORE_GUID \ + { 0x82DDD68B, 0x9163, 0x4187, {0x9B, 0x27, 0x20, 0xA8, 0xFD, 0x60 ,0xA7, 0x1D}} + +/// +/// EDKII implementation extension flags, used to indicate the display style and bit width for bit filed storage. +/// Two high bits for display style and the low six bits for bit width. +/// +#define EDKII_IFR_DISPLAY_BIT 0xC0 +#define EDKII_IFR_DISPLAY_INT_DEC_BIT 0x00 +#define EDKII_IFR_DISPLAY_UINT_DEC_BIT 0x40 +#define EDKII_IFR_DISPLAY_UINT_HEX_BIT 0x80 + +#define EDKII_IFR_NUMERIC_SIZE_BIT 0x3F + +#pragma pack() + +extern EFI_GUID gEfiIfrTianoGuid; +extern EFI_GUID gEfiIfrFrameworkGuid; +extern EFI_GUID gEdkiiIfrBitVarStoreGuid; + +#endif + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/PiFirmwareFile.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/PiFirmwareFile.h new file mode 100644 index 00000000..3919aa0b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/PiFirmwareFile.h @@ -0,0 +1,350 @@ +/** @file + The firmware file related definitions in PI. + + @par Revision Reference: + Version 1.4. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __PI_FIRMWARE_FILE_H__ +#define __PI_FIRMWARE_FILE_H__ + +#pragma pack(1) +// +// Used to verify the integrity of the file. +// +typedef union { + struct { + UINT8 Header; + UINT8 File; + } Checksum; + UINT16 Checksum16; +} EFI_FFS_INTEGRITY_CHECK; + +typedef UINT8 EFI_FV_FILETYPE; +typedef UINT8 EFI_FFS_FILE_ATTRIBUTES; +typedef UINT8 EFI_FFS_FILE_STATE; + +// +// File Types Definitions +// +#define EFI_FV_FILETYPE_ALL 0x00 +#define EFI_FV_FILETYPE_RAW 0x01 +#define EFI_FV_FILETYPE_FREEFORM 0x02 +#define EFI_FV_FILETYPE_SECURITY_CORE 0x03 +#define EFI_FV_FILETYPE_PEI_CORE 0x04 +#define EFI_FV_FILETYPE_DXE_CORE 0x05 +#define EFI_FV_FILETYPE_PEIM 0x06 +#define EFI_FV_FILETYPE_DRIVER 0x07 +#define EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER 0x08 +#define EFI_FV_FILETYPE_APPLICATION 0x09 +#define EFI_FV_FILETYPE_SMM 0x0A +#define EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE 0x0B +#define EFI_FV_FILETYPE_COMBINED_SMM_DXE 0x0C +#define EFI_FV_FILETYPE_SMM_CORE 0x0D +#define EFI_FV_FILETYPE_MM_STANDALONE 0x0E +#define EFI_FV_FILETYPE_MM_CORE_STANDALONE 0x0F +#define EFI_FV_FILETYPE_OEM_MIN 0xc0 +#define EFI_FV_FILETYPE_OEM_MAX 0xdf +#define EFI_FV_FILETYPE_DEBUG_MIN 0xe0 +#define EFI_FV_FILETYPE_DEBUG_MAX 0xef +#define EFI_FV_FILETYPE_FFS_MIN 0xf0 +#define EFI_FV_FILETYPE_FFS_MAX 0xff +#define EFI_FV_FILETYPE_FFS_PAD 0xf0 +// +// FFS File Attributes. +// +#define FFS_ATTRIB_LARGE_FILE 0x01 +#define FFS_ATTRIB_DATA_ALIGNMENT2 0x02 +#define FFS_ATTRIB_FIXED 0x04 +#define FFS_ATTRIB_DATA_ALIGNMENT 0x38 +#define FFS_ATTRIB_CHECKSUM 0x40 +// +// FFS_FIXED_CHECKSUM is the checksum value used when the +// FFS_ATTRIB_CHECKSUM attribute bit is clear +// +#define FFS_FIXED_CHECKSUM 0xAA + +// +// FFS File State Bits. +// +#define EFI_FILE_HEADER_CONSTRUCTION 0x01 +#define EFI_FILE_HEADER_VALID 0x02 +#define EFI_FILE_DATA_VALID 0x04 +#define EFI_FILE_MARKED_FOR_UPDATE 0x08 +#define EFI_FILE_DELETED 0x10 +#define EFI_FILE_HEADER_INVALID 0x20 + +#define EFI_FILE_ALL_STATE_BITS (EFI_FILE_HEADER_CONSTRUCTION | \ + EFI_FILE_HEADER_VALID | \ + EFI_FILE_DATA_VALID | \ + EFI_FILE_MARKED_FOR_UPDATE | \ + EFI_FILE_DELETED | \ + EFI_FILE_HEADER_INVALID \ + ) + +// +// Each file begins with the header that describe the +// contents and state of the files. +// +typedef struct { + EFI_GUID Name; + EFI_FFS_INTEGRITY_CHECK IntegrityCheck; + EFI_FV_FILETYPE Type; + EFI_FFS_FILE_ATTRIBUTES Attributes; + UINT8 Size[3]; + EFI_FFS_FILE_STATE State; +} EFI_FFS_FILE_HEADER; + +typedef struct { + EFI_GUID Name; + EFI_FFS_INTEGRITY_CHECK IntegrityCheck; + EFI_FV_FILETYPE Type; + EFI_FFS_FILE_ATTRIBUTES Attributes; + UINT8 Size[3]; + EFI_FFS_FILE_STATE State; + UINT64 ExtendedSize; +} EFI_FFS_FILE_HEADER2; + +#define MAX_FFS_SIZE 0x1000000 + +typedef UINT8 EFI_SECTION_TYPE; + +// +// Pseudo type. It is +// used as a wild card when retrieving sections. The section +// type EFI_SECTION_ALL matches all section types. +// +#define EFI_SECTION_ALL 0x00 + +// +// Encapsulation section Type values +// +#define EFI_SECTION_COMPRESSION 0x01 + +#define EFI_SECTION_GUID_DEFINED 0x02 + +// +// Leaf section Type values +// +#define EFI_SECTION_PE32 0x10 +#define EFI_SECTION_PIC 0x11 +#define EFI_SECTION_TE 0x12 +#define EFI_SECTION_DXE_DEPEX 0x13 +#define EFI_SECTION_VERSION 0x14 +#define EFI_SECTION_USER_INTERFACE 0x15 +#define EFI_SECTION_COMPATIBILITY16 0x16 +#define EFI_SECTION_FIRMWARE_VOLUME_IMAGE 0x17 +#define EFI_SECTION_FREEFORM_SUBTYPE_GUID 0x18 +#define EFI_SECTION_RAW 0x19 +#define EFI_SECTION_PEI_DEPEX 0x1B +#define EFI_SECTION_SMM_DEPEX 0x1C + +typedef struct { + UINT8 Size[3]; + EFI_SECTION_TYPE Type; +} EFI_COMMON_SECTION_HEADER; + +typedef struct { + UINT8 Size[3]; + EFI_SECTION_TYPE Type; + UINT32 ExtendedSize; +} EFI_COMMON_SECTION_HEADER2; + +#define MAX_SECTION_SIZE 0x1000000 + +// +// Leaf section type that contains an +// IA-32 16-bit executable image. +// +typedef EFI_COMMON_SECTION_HEADER EFI_COMPATIBILITY16_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_COMPATIBILITY16_SECTION2; + +// +// CompressionType of EFI_COMPRESSION_SECTION. +// +#define EFI_NOT_COMPRESSED 0x00 +#define EFI_STANDARD_COMPRESSION 0x01 +// +// An encapsulation section type in which the +// section data is compressed. +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + UINT32 UncompressedLength; + UINT8 CompressionType; +} EFI_COMPRESSION_SECTION; + +typedef struct { + EFI_COMMON_SECTION_HEADER2 CommonHeader; + UINT32 UncompressedLength; + UINT8 CompressionType; +} EFI_COMPRESSION_SECTION2; + +// +// Leaf section which could be used to determine the dispatch order of DXEs. +// +typedef EFI_COMMON_SECTION_HEADER EFI_DXE_DEPEX_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_DXE_DEPEX_SECTION2; + +// +// Leaf section witch contains a PI FV. +// +typedef EFI_COMMON_SECTION_HEADER EFI_FIRMWARE_VOLUME_IMAGE_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_FIRMWARE_VOLUME_IMAGE_SECTION2; + +// +// Leaf section which contains a single GUID. +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + EFI_GUID SubTypeGuid; +} EFI_FREEFORM_SUBTYPE_GUID_SECTION; + +typedef struct { + EFI_COMMON_SECTION_HEADER2 CommonHeader; + EFI_GUID SubTypeGuid; +} EFI_FREEFORM_SUBTYPE_GUID_SECTION2; + +// +// Attributes of EFI_GUID_DEFINED_SECTION +// +#define EFI_GUIDED_SECTION_PROCESSING_REQUIRED 0x01 +#define EFI_GUIDED_SECTION_AUTH_STATUS_VALID 0x02 +// +// Leaf section which is encapsulation defined by specific GUID +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + EFI_GUID SectionDefinitionGuid; + UINT16 DataOffset; + UINT16 Attributes; +} EFI_GUID_DEFINED_SECTION; + +typedef struct { + EFI_COMMON_SECTION_HEADER2 CommonHeader; + EFI_GUID SectionDefinitionGuid; + UINT16 DataOffset; + UINT16 Attributes; +} EFI_GUID_DEFINED_SECTION2; + +// +// Leaf section which contains PE32+ image. +// +typedef EFI_COMMON_SECTION_HEADER EFI_PE32_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_PE32_SECTION2; + +// +// Leaf section which contains PIC image. +// +typedef EFI_COMMON_SECTION_HEADER EFI_PIC_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_PIC_SECTION2; + +// +// Leaf section which used to determine the dispatch order of PEIMs. +// +typedef EFI_COMMON_SECTION_HEADER EFI_PEI_DEPEX_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_PEI_DEPEX_SECTION2; + +// +// Leaf section which constains the position-independent-code image. +// +typedef EFI_COMMON_SECTION_HEADER EFI_TE_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_TE_SECTION2; + +// +// Leaf section which contains an array of zero or more bytes. +// +typedef EFI_COMMON_SECTION_HEADER EFI_RAW_SECTION; +typedef EFI_COMMON_SECTION_HEADER2 EFI_RAW_SECTION2; + +// +// Leaf section which contains a unicode string that +// is human readable file name. +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + + // + // Array of unicode string. + // + CHAR16 FileNameString[1]; +} EFI_USER_INTERFACE_SECTION; + +typedef struct { + EFI_COMMON_SECTION_HEADER2 CommonHeader; + + // + // Array of unicode string. + // + CHAR16 FileNameString[1]; +} EFI_USER_INTERFACE_SECTION2; + +// +// Leaf section which contains a numeric build number and +// an optional unicode string that represent the file revision. +// +typedef struct { + EFI_COMMON_SECTION_HEADER CommonHeader; + UINT16 BuildNumber; + CHAR16 VersionString[1]; +} EFI_VERSION_SECTION; + +typedef struct { + EFI_COMMON_SECTION_HEADER2 CommonHeader; + UINT16 BuildNumber; + CHAR16 VersionString[1]; +} EFI_VERSION_SECTION2; + +// +// The argument passed as the SectionHeaderPtr parameter to the SECTION_SIZE() +// function-like macro below must not have side effects: SectionHeaderPtr is +// evaluated multiple times. +// +#define SECTION_SIZE(SectionHeaderPtr) ((UINT32) ( \ + (((EFI_COMMON_SECTION_HEADER *) (SectionHeaderPtr))->Size[0] ) | \ + (((EFI_COMMON_SECTION_HEADER *) (SectionHeaderPtr))->Size[1] << 8) | \ + (((EFI_COMMON_SECTION_HEADER *) (SectionHeaderPtr))->Size[2] << 16))) + +#pragma pack() + +typedef union { + EFI_COMMON_SECTION_HEADER *CommonHeader; + EFI_COMPRESSION_SECTION *CompressionSection; + EFI_GUID_DEFINED_SECTION *GuidDefinedSection; + EFI_PE32_SECTION *Pe32Section; + EFI_PIC_SECTION *PicSection; + EFI_TE_SECTION *TeSection; + EFI_PEI_DEPEX_SECTION *PeimHeaderSection; + EFI_DXE_DEPEX_SECTION *DependencySection; + EFI_VERSION_SECTION *VersionSection; + EFI_USER_INTERFACE_SECTION *UISection; + EFI_COMPATIBILITY16_SECTION *Code16Section; + EFI_FIRMWARE_VOLUME_IMAGE_SECTION *FVImageSection; + EFI_FREEFORM_SUBTYPE_GUID_SECTION *FreeformSubtypeSection; + EFI_RAW_SECTION *RawSection; + // + // For section whose size is equal or greater than 0x1000000 + // + EFI_COMMON_SECTION_HEADER2 *CommonHeader2; + EFI_COMPRESSION_SECTION2 *CompressionSection2; + EFI_GUID_DEFINED_SECTION2 *GuidDefinedSection2; + EFI_PE32_SECTION2 *Pe32Section2; + EFI_PIC_SECTION2 *PicSection2; + EFI_TE_SECTION2 *TeSection2; + EFI_PEI_DEPEX_SECTION2 *PeimHeaderSection2; + EFI_DXE_DEPEX_SECTION2 *DependencySection2; + EFI_VERSION_SECTION2 *VersionSection2; + EFI_USER_INTERFACE_SECTION2 *UISection2; + EFI_COMPATIBILITY16_SECTION2 *Code16Section2; + EFI_FIRMWARE_VOLUME_IMAGE_SECTION2 *FVImageSection2; + EFI_FREEFORM_SUBTYPE_GUID_SECTION2 *FreeformSubtypeSection2; + EFI_RAW_SECTION2 *RawSection2; +} EFI_FILE_SECTION_POINTER; + +#endif + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/PiFirmwareVolume.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/PiFirmwareVolume.h new file mode 100644 index 00000000..dec5a321 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/PiFirmwareVolume.h @@ -0,0 +1,157 @@ +/** @file + The firmware volume related definitions in PI. + + @par Revision Reference: + Version 1.2C + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __PI_FIRMWAREVOLUME_H__ +#define __PI_FIRMWAREVOLUME_H__ + +// +// EFI_FV_FILE_ATTRIBUTES +// +typedef UINT32 EFI_FV_FILE_ATTRIBUTES; + +// +// Value of EFI_FV_FILE_ATTRIBUTES. +// +#define EFI_FV_FILE_ATTRIB_ALIGNMENT 0x0000001F +#define EFI_FV_FILE_ATTRIB_FIXED 0x00000100 +#define EFI_FV_FILE_ATTRIB_MEMORY_MAPPED 0x00000200 + +typedef UINT32 EFI_FVB_ATTRIBUTES_2; + +// +// Attributes bit definitions +// +#define EFI_FVB2_READ_DISABLED_CAP 0x00000001 +#define EFI_FVB2_READ_ENABLED_CAP 0x00000002 +#define EFI_FVB2_READ_STATUS 0x00000004 +#define EFI_FVB2_WRITE_DISABLED_CAP 0x00000008 +#define EFI_FVB2_WRITE_ENABLED_CAP 0x00000010 +#define EFI_FVB2_WRITE_STATUS 0x00000020 +#define EFI_FVB2_LOCK_CAP 0x00000040 +#define EFI_FVB2_LOCK_STATUS 0x00000080 +#define EFI_FVB2_STICKY_WRITE 0x00000200 +#define EFI_FVB2_MEMORY_MAPPED 0x00000400 +#define EFI_FVB2_ERASE_POLARITY 0x00000800 +#define EFI_FVB2_READ_LOCK_CAP 0x00001000 +#define EFI_FVB2_READ_LOCK_STATUS 0x00002000 +#define EFI_FVB2_WRITE_LOCK_CAP 0x00004000 +#define EFI_FVB2_WRITE_LOCK_STATUS 0x00008000 +#define EFI_FVB2_ALIGNMENT 0x001F0000 +#define EFI_FVB2_WEAK_ALIGNMENT 0x80000000 +#define EFI_FVB2_ALIGNMENT_1 0x00000000 +#define EFI_FVB2_ALIGNMENT_2 0x00010000 +#define EFI_FVB2_ALIGNMENT_4 0x00020000 +#define EFI_FVB2_ALIGNMENT_8 0x00030000 +#define EFI_FVB2_ALIGNMENT_16 0x00040000 +#define EFI_FVB2_ALIGNMENT_32 0x00050000 +#define EFI_FVB2_ALIGNMENT_64 0x00060000 +#define EFI_FVB2_ALIGNMENT_128 0x00070000 +#define EFI_FVB2_ALIGNMENT_256 0x00080000 +#define EFI_FVB2_ALIGNMENT_512 0x00090000 +#define EFI_FVB2_ALIGNMENT_1K 0x000A0000 +#define EFI_FVB2_ALIGNMENT_2K 0x000B0000 +#define EFI_FVB2_ALIGNMENT_4K 0x000C0000 +#define EFI_FVB2_ALIGNMENT_8K 0x000D0000 +#define EFI_FVB2_ALIGNMENT_16K 0x000E0000 +#define EFI_FVB2_ALIGNMENT_32K 0x000F0000 +#define EFI_FVB2_ALIGNMENT_64K 0x00100000 +#define EFI_FVB2_ALIGNMENT_128K 0x00110000 +#define EFI_FVB2_ALIGNMENT_256K 0x00120000 +#define EFI_FVB2_ALIGNMENT_512K 0x00130000 +#define EFI_FVB2_ALIGNMENT_1M 0x00140000 +#define EFI_FVB2_ALIGNMENT_2M 0x00150000 +#define EFI_FVB2_ALIGNMENT_4M 0x00160000 +#define EFI_FVB2_ALIGNMENT_8M 0x00170000 +#define EFI_FVB2_ALIGNMENT_16M 0x00180000 +#define EFI_FVB2_ALIGNMENT_32M 0x00190000 +#define EFI_FVB2_ALIGNMENT_64M 0x001A0000 +#define EFI_FVB2_ALIGNMENT_128M 0x001B0000 +#define EFI_FVB2_ALIGNMENT_256M 0x001C0000 +#define EFI_FVB2_ALIGNMENT_512M 0x001D0000 +#define EFI_FVB2_ALIGNMENT_1G 0x001E0000 +#define EFI_FVB2_ALIGNMENT_2G 0x001F0000 + + +typedef struct { + UINT32 NumBlocks; + UINT32 Length; +} EFI_FV_BLOCK_MAP_ENTRY; + +// +// Describes the features and layout of the firmware volume. +// +typedef struct { + UINT8 ZeroVector[16]; + EFI_GUID FileSystemGuid; + UINT64 FvLength; + UINT32 Signature; + EFI_FVB_ATTRIBUTES_2 Attributes; + UINT16 HeaderLength; + UINT16 Checksum; + UINT16 ExtHeaderOffset; + UINT8 Reserved[1]; + UINT8 Revision; + EFI_FV_BLOCK_MAP_ENTRY BlockMap[1]; +} EFI_FIRMWARE_VOLUME_HEADER; + +#define EFI_FVH_SIGNATURE SIGNATURE_32 ('_', 'F', 'V', 'H') + +/// +/// Firmware Volume Header Revision definition +/// +#define EFI_FVH_REVISION 0x02 + +// +// Extension header pointed by ExtHeaderOffset of volume header. +// +typedef struct { + EFI_GUID FvName; + UINT32 ExtHeaderSize; +} EFI_FIRMWARE_VOLUME_EXT_HEADER; + +typedef struct { + UINT16 ExtEntrySize; + UINT16 ExtEntryType; +} EFI_FIRMWARE_VOLUME_EXT_ENTRY; + +#define EFI_FV_EXT_TYPE_OEM_TYPE 0x01 +typedef struct { + EFI_FIRMWARE_VOLUME_EXT_ENTRY Hdr; + UINT32 TypeMask; + + // + // Array of GUIDs. + // Each GUID represents an OEM file type. + // + // EFI_GUID Types[1]; + // +} EFI_FIRMWARE_VOLUME_EXT_ENTRY_OEM_TYPE; + +#define EFI_FV_EXT_TYPE_GUID_TYPE 0x0002 +typedef struct { + EFI_FIRMWARE_VOLUME_EXT_ENTRY Hdr; + EFI_GUID FormatType; + + // + // An array of bytes of length Length. + // + // UINT8 Data[1]; + // +} EFI_FIRMWARE_VOLUME_EXT_ENTRY_GUID_TYPE; + +#define EFI_FV_EXT_TYPE_USED_SIZE_TYPE 0x03 +typedef struct { + EFI_FIRMWARE_VOLUME_EXT_ENTRY Hdr; + UINT32 UsedSize; +} EFI_FIRMWARE_VOLUME_EXT_ENTRY_USED_SIZE_TYPE; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/UefiBaseTypes.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/UefiBaseTypes.h new file mode 100644 index 00000000..8f0cdf60 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/UefiBaseTypes.h @@ -0,0 +1,168 @@ +/** @file + Defines data types and constants introduced in UEFI. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __UEFI_BASETYPE_H__ +#define __UEFI_BASETYPE_H__ + +#include + +// +// Basical data type definitions introduced in UEFI. +// +typedef struct { + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; +} EFI_GUID; + +typedef RETURN_STATUS EFI_STATUS; +typedef VOID *EFI_HANDLE; + +typedef VOID *EFI_EVENT; + +typedef UINTN EFI_TPL; + + +typedef UINT64 EFI_LBA; + + +typedef UINT16 STRING_REF; + +typedef UINT64 EFI_PHYSICAL_ADDRESS; +typedef UINT64 EFI_VIRTUAL_ADDRESS; + +// +// EFI Time Abstraction: +// Year: 2000 - 20XX +// Month: 1 - 12 +// Day: 1 - 31 +// Hour: 0 - 23 +// Minute: 0 - 59 +// Second: 0 - 59 +// Nanosecond: 0 - 999,999,999 +// TimeZone: -1440 to 1440 or 2047 +// +typedef struct { + UINT16 Year; + UINT8 Month; + UINT8 Day; + UINT8 Hour; + UINT8 Minute; + UINT8 Second; + UINT8 Pad1; + UINT32 Nanosecond; + INT16 TimeZone; + UINT8 Daylight; + UINT8 Pad2; +} EFI_TIME; + + +// +// Networking Definitions +// +typedef struct { + UINT8 Addr[4]; +} EFI_IPv4_ADDRESS; + +typedef struct { + UINT8 Addr[16]; +} EFI_IPv6_ADDRESS; + +typedef struct { + UINT8 Addr[32]; +} EFI_MAC_ADDRESS; + +typedef union { + UINT32 Addr[4]; + EFI_IPv4_ADDRESS v4; + EFI_IPv6_ADDRESS v6; +} EFI_IP_ADDRESS; + + +// +// Enumeration of EFI_STATUS. +// +#define EFI_SUCCESS RETURN_SUCCESS +#define EFI_LOAD_ERROR RETURN_LOAD_ERROR +#define EFI_INVALID_PARAMETER RETURN_INVALID_PARAMETER +#define EFI_UNSUPPORTED RETURN_UNSUPPORTED +#define EFI_BAD_BUFFER_SIZE RETURN_BAD_BUFFER_SIZE +#define EFI_BUFFER_TOO_SMALL RETURN_BUFFER_TOO_SMALL +#define EFI_NOT_READY RETURN_NOT_READY +#define EFI_DEVICE_ERROR RETURN_DEVICE_ERROR +#define EFI_WRITE_PROTECTED RETURN_WRITE_PROTECTED +#define EFI_OUT_OF_RESOURCES RETURN_OUT_OF_RESOURCES +#define EFI_VOLUME_CORRUPTED RETURN_VOLUME_CORRUPTED +#define EFI_VOLUME_FULL RETURN_VOLUME_FULL +#define EFI_NO_MEDIA RETURN_NO_MEDIA +#define EFI_MEDIA_CHANGED RETURN_MEDIA_CHANGED +#define EFI_NOT_FOUND RETURN_NOT_FOUND +#define EFI_ACCESS_DENIED RETURN_ACCESS_DENIED +#define EFI_NO_RESPONSE RETURN_NO_RESPONSE +#define EFI_NO_MAPPING RETURN_NO_MAPPING +#define EFI_TIMEOUT RETURN_TIMEOUT +#define EFI_NOT_STARTED RETURN_NOT_STARTED +#define EFI_ALREADY_STARTED RETURN_ALREADY_STARTED +#define EFI_ABORTED RETURN_ABORTED +#define EFI_ICMP_ERROR RETURN_ICMP_ERROR +#define EFI_TFTP_ERROR RETURN_TFTP_ERROR +#define EFI_PROTOCOL_ERROR RETURN_PROTOCOL_ERROR +#define EFI_INCOMPATIBLE_VERSION RETURN_INCOMPATIBLE_VERSION +#define EFI_SECURITY_VIOLATION RETURN_SECURITY_VIOLATION +#define EFI_CRC_ERROR RETURN_CRC_ERROR +#define EFI_END_OF_MEDIA RETURN_END_OF_MEDIA +#define EFI_END_OF_FILE RETURN_END_OF_FILE + +#define EFI_WARN_UNKNOWN_GLYPH RETURN_WARN_UNKNOWN_GLYPH +#define EFI_WARN_DELETE_FAILURE RETURN_WARN_DELETE_FAILURE +#define EFI_WARN_WRITE_FAILURE RETURN_WARN_WRITE_FAILURE +#define EFI_WARN_BUFFER_TOO_SMALL RETURN_WARN_BUFFER_TOO_SMALL + + +#define NULL_HANDLE ((VOID *) 0) + +// +// Define macro to encode the status code. +// +#define EFIERR(_a) ENCODE_ERROR(_a) + +#define EFI_ERROR(A) RETURN_ERROR(A) + +// +// Define macros to build data structure signatures from characters. +// +#define SIGNATURE_16(A, B) ((A) | (B << 8)) +#define SIGNATURE_32(A, B, C, D) (SIGNATURE_16 (A, B) | (SIGNATURE_16 (C, D) << 16)) +#define SIGNATURE_64(A, B, C, D, E, F, G, H) \ + (SIGNATURE_32 (A, B, C, D) | ((UINT64) (SIGNATURE_32 (E, F, G, H)) << 32)) + + +// +// Returns the byte offset to a field within a structure +// +#define EFI_FIELD_OFFSET(TYPE,Field) ((UINTN)(&(((TYPE *) 0)->Field))) + +// +// The EFI memory allocation functions work in units of EFI_PAGEs that are +// 4K. This should in no way be confused with the page size of the processor. +// An EFI_PAGE is just the quanta of memory in EFI. +// +#define EFI_PAGE_SIZE 0x1000 +#define EFI_PAGE_MASK 0xFFF +#define EFI_PAGE_SHIFT 12 + +#define EFI_SIZE_TO_PAGES(a) (((a) >> EFI_PAGE_SHIFT) + (((a) & EFI_PAGE_MASK) ? 1 : 0)) + +#define EFI_PAGES_TO_SIZE(a) ( (a) << EFI_PAGE_SHIFT) + + +#define EFI_MAX_BIT MAX_BIT + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/UefiCapsule.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/UefiCapsule.h new file mode 100644 index 00000000..1ab539b3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/UefiCapsule.h @@ -0,0 +1,26 @@ +/** @file + Defines for the EFI Capsule functionality. + @par Revision Reference: + These definitions are from Uefi Spec. + + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_CAPSULE_H_ +#define _EFI_CAPSULE_H_ + +typedef struct { + EFI_GUID CapsuleGuid; + UINT32 HeaderSize; + UINT32 Flags; + UINT32 CapsuleImageSize; +} EFI_CAPSULE_HEADER; + +#define CAPSULE_FLAGS_PERSIST_ACROSS_RESET 0x00010000 +#define CAPSULE_FLAGS_POPULATE_SYSTEM_TABLE 0x00020000 +#define CAPSULE_FLAGS_INITIATE_RESET 0x00040000 + +#endif // #ifndef _EFI_CAPSULE_H_ diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/UefiInternalFormRepresentation.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/UefiInternalFormRepresentation.h new file mode 100644 index 00000000..22c99a1b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/UefiInternalFormRepresentation.h @@ -0,0 +1,1680 @@ +/** @file + This file defines the encoding for the VFR (Visual Form Representation) language. + IFR is primarily consumed by the EFI presentation engine, and produced by EFI + internal application and drivers as well as all add-in card option-ROM drivers + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + + @par Revision Reference: + These definitions are from UEFI 2.6 + +**/ + +#ifndef __UEFI_INTERNAL_FORMREPRESENTATION_H__ +#define __UEFI_INTERNAL_FORMREPRESENTATION_H__ + + +#define EFI_HII_PLATFORM_SETUP_FORMSET_GUID \ + { 0x93039971, 0x8545, 0x4b04, { 0xb4, 0x5e, 0x32, 0xeb, 0x83, 0x26, 0x4, 0xe } } + +// +// The following types are currently defined: +// +typedef UINT32 RELOFST; + +typedef VOID* EFI_HII_HANDLE; +typedef CHAR16* EFI_STRING; +typedef UINT16 EFI_IMAGE_ID; +typedef UINT16 EFI_QUESTION_ID; +typedef UINT16 EFI_STRING_ID; +typedef UINT16 EFI_FORM_ID; +typedef UINT16 EFI_VARSTORE_ID; +typedef UINT16 EFI_DEFAULT_ID; +typedef UINT32 EFI_HII_FONT_STYLE; + + + +#pragma pack(1) + + +// +// HII package list +// +typedef struct { + EFI_GUID PackageListGuid; + UINT32 PackageLength; +} EFI_HII_PACKAGE_LIST_HEADER; + +/** + + Each package starts with a header, as defined above, which + indicates the size and type of the package. When added to a + pointer pointing to the start of the header, Length points at + the next package. The package lists form a package list when + concatenated together and terminated with an + EFI_HII_PACKAGE_HEADER with a Type of EFI_HII_PACKAGE_END. The + type EFI_HII_PACKAGE_TYPE_GUID is used for vendor-defined HII + packages, whose contents are determined by the Guid. The range + of package types starting with EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN + through EFI_HII_PACKAGE_TYPE_SYSTEM_END are reserved for system + firmware implementers. + + @param Length The size of the package in bytes. + + @param Type The package type. See EFI_HII_PACKAGE_TYPE_x, + below. + + @param Data The package data, the format of which is + determined by Type. + +**/ +typedef struct { + UINT32 Length:24; + UINT32 Type:8; + // UINT8 Data[...]; +} EFI_HII_PACKAGE_HEADER; + +// +// EFI_HII_PACKAGE_TYPE_x. +// +#define EFI_HII_PACKAGE_TYPE_ALL 0x00 +#define EFI_HII_PACKAGE_TYPE_GUID 0x01 +#define EFI_HII_PACKAGE_FORM 0x02 +#define EFI_HII_PACKAGE_KEYBOARD_LAYOUT 0x03 +#define EFI_HII_PACKAGE_STRINGS 0x04 +#define EFI_HII_PACKAGE_FONTS 0x05 +#define EFI_HII_PACKAGE_IMAGES 0x06 +#define EFI_HII_PACKAGE_SIMPLE_FONTS 0x07 +#define EFI_HII_PACKAGE_DEVICE_PATH 0x08 +#define EFI_HII_PACKAGE_END 0xDF +#define EFI_HII_PACKAGE_TYPE_SYSTEM_BEGIN 0xE0 +#define EFI_HII_PACKAGE_TYPE_SYSTEM_END 0xFF + +// +// Simplified Font Package +// + +#define EFI_GLYPH_HEIGHT 19 +#define EFI_GLYPH_WIDTH 8 +// +// Contents of EFI_NARROW_GLYPH.Attributes +// +#define EFI_GLYPH_NON_SPACING 0x01 +#define EFI_GLYPH_WIDE 0x02 + +typedef struct { + CHAR16 UnicodeWeight; + UINT8 Attributes; + UINT8 GlyphCol1[EFI_GLYPH_HEIGHT]; +} EFI_NARROW_GLYPH; + +typedef struct { + CHAR16 UnicodeWeight; + UINT8 Attributes; + UINT8 GlyphCol1[EFI_GLYPH_HEIGHT]; + UINT8 GlyphCol2[EFI_GLYPH_HEIGHT]; + UINT8 Pad[3]; +} EFI_WIDE_GLYPH; + + +typedef struct _EFI_HII_SIMPLE_FONT_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + UINT16 NumberOfNarrowGlyphs; + UINT16 NumberOfWideGlyphs; + // EFI_NARROW_GLYPH NarrowGlyphs[]; + // EFI_WIDE_GLYPH WideGlyphs[]; +} EFI_HII_SIMPLE_FONT_PACKAGE_HDR; + +// +// Font Package +// + +#define EFI_HII_FONT_STYLE_BOLD 0x00000001 +#define EFI_HII_FONT_STYLE_ITALIC 0x00000002 +#define EFI_HII_FONT_STYLE_EMBOSS 0x00010000 +#define EFI_HII_FONT_STYLE_OUTLINE 0x00020000 +#define EFI_HII_FONT_STYLE_SHADOW 0x00040000 +#define EFI_HII_FONT_STYLE_UNDERLINE 0x00080000 +#define EFI_HII_FONT_STYLE_DBL_UNDER 0x00100000 + +typedef struct _EFI_HII_GLYPH_INFO { + UINT16 Width; + UINT16 Height; + INT16 OffsetX; + INT16 OffsetY; + INT16 AdvanceX; +} EFI_HII_GLYPH_INFO; + +typedef struct _EFI_HII_FONT_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + UINT32 HdrSize; + UINT32 GlyphBlockOffset; + EFI_HII_GLYPH_INFO Cell; + EFI_HII_FONT_STYLE FontStyle; + CHAR16 FontFamily[1]; +} EFI_HII_FONT_PACKAGE_HDR; + +#define EFI_HII_GIBT_END 0x00 +#define EFI_HII_GIBT_GLYPH 0x10 +#define EFI_HII_GIBT_GLYPHS 0x11 +#define EFI_HII_GIBT_GLYPH_DEFAULT 0x12 +#define EFI_HII_GIBT_GLYPHS_DEFAULT 0x13 +#define EFI_HII_GIBT_GLYPH_VARIABILITY 0x14 +#define EFI_HII_GIBT_DUPLICATE 0x20 +#define EFI_HII_GIBT_SKIP2 0x21 +#define EFI_HII_GIBT_SKIP1 0x22 +#define EFI_HII_GIBT_DEFAULTS 0x23 +#define EFI_HII_GIBT_EXT1 0x30 +#define EFI_HII_GIBT_EXT2 0x31 +#define EFI_HII_GIBT_EXT4 0x32 + +typedef struct _EFI_HII_GLYPH_BLOCK { + UINT8 BlockType; +} EFI_HII_GLYPH_BLOCK; + +typedef struct _EFI_HII_GIBT_DEFAULTS_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + EFI_HII_GLYPH_INFO Cell; +} EFI_HII_GIBT_DEFAULTS_BLOCK; + +typedef struct _EFI_HII_GIBT_DUPLICATE_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + CHAR16 CharValue; +} EFI_HII_GIBT_DUPLICATE_BLOCK; + +typedef struct _EFI_GLYPH_GIBT_END_BLOCK { + EFI_HII_GLYPH_BLOCK Header; +} EFI_GLYPH_GIBT_END_BLOCK; + +typedef struct _EFI_HII_GIBT_EXT1_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 BlockType2; + UINT8 Length; +} EFI_HII_GIBT_EXT1_BLOCK; + +typedef struct _EFI_HII_GIBT_EXT2_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 BlockType2; + UINT16 Length; +} EFI_HII_GIBT_EXT2_BLOCK; + +typedef struct _EFI_HII_GIBT_EXT4_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 BlockType2; + UINT32 Length; +} EFI_HII_GIBT_EXT4_BLOCK; + +typedef struct _EFI_HII_GIBT_GLYPH_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + EFI_HII_GLYPH_INFO Cell; + UINT8 BitmapData[1]; // the number of bytes per bitmap can be calculated by ((Cell.Width+7)/8)*Cell.Height +} EFI_HII_GIBT_GLYPH_BLOCK; + +typedef struct _EFI_HII_GIBT_GLYPHS_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + EFI_HII_GLYPH_INFO Cell; + UINT16 Count; + UINT8 BitmapData[1]; // the number of bytes per bitmap can be calculated by ((Cell.Width+7)/8)*Cell.Height +} EFI_HII_GIBT_GLYPHS_BLOCK; + +typedef struct _EFI_HII_GIBT_GLYPH_DEFAULT_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 BitmapData[1]; // the number of bytes per bitmap can be calculated by ((Global.Cell.Width+7)/8)*Global.Cell.Height +} EFI_HII_GIBT_GLYPH_DEFAULT_BLOCK; + +typedef struct _EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT16 Count; + UINT8 BitmapData[1]; // the number of bytes per bitmap can be calculated by ((Global.Cell.Width+7)/8)*Global.Cell.Height +} EFI_HII_GIBT_GLYPHS_DEFAULT_BLOCK; + +typedef struct _EFI_HII_GIBT_VARIABILITY_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + EFI_HII_GLYPH_INFO Cell; + UINT8 GlyphPackInBits; + UINT8 BitmapData [1]; +} EFI_HII_GIBT_VARIABILITY_BLOCK; + +typedef struct _EFI_HII_GIBT_SKIP1_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT8 SkipCount; +} EFI_HII_GIBT_SKIP1_BLOCK; + +typedef struct _EFI_HII_GIBT_SKIP2_BLOCK { + EFI_HII_GLYPH_BLOCK Header; + UINT16 SkipCount; +} EFI_HII_GIBT_SKIP2_BLOCK; + +// +// Device Path Package +// +typedef struct _EFI_HII_DEVICE_PATH_PACKAGE { + EFI_HII_PACKAGE_HEADER Header; + // EFI_DEVICE_PATH_PROTOCOL DevicePath[]; +} EFI_HII_DEVICE_PATH_PACKAGE; + +// +// GUID Package +// +typedef struct _EFI_HII_GUID_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + EFI_GUID Guid; + // Data per GUID definition may follow +} EFI_HII_GUID_PACKAGE_HDR; + +// +// String Package +// + +#define UEFI_CONFIG_LANG "x-UEFI" +#define UEFI_CONFIG_LANG2 "x-i-UEFI" + +typedef struct _EFI_HII_STRING_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + UINT32 HdrSize; + UINT32 StringInfoOffset; + CHAR16 LanguageWindow[16]; + EFI_STRING_ID LanguageName; + CHAR8 Language[1]; +} EFI_HII_STRING_PACKAGE_HDR; + +typedef struct { + UINT8 BlockType; +} EFI_HII_STRING_BLOCK; + +#define EFI_HII_SIBT_END 0x00 +#define EFI_HII_SIBT_STRING_SCSU 0x10 +#define EFI_HII_SIBT_STRING_SCSU_FONT 0x11 +#define EFI_HII_SIBT_STRINGS_SCSU 0x12 +#define EFI_HII_SIBT_STRINGS_SCSU_FONT 0x13 +#define EFI_HII_SIBT_STRING_UCS2 0x14 +#define EFI_HII_SIBT_STRING_UCS2_FONT 0x15 +#define EFI_HII_SIBT_STRINGS_UCS2 0x16 +#define EFI_HII_SIBT_STRINGS_UCS2_FONT 0x17 +#define EFI_HII_SIBT_DUPLICATE 0x20 +#define EFI_HII_SIBT_SKIP2 0x21 +#define EFI_HII_SIBT_SKIP1 0x22 +#define EFI_HII_SIBT_EXT1 0x30 +#define EFI_HII_SIBT_EXT2 0x31 +#define EFI_HII_SIBT_EXT4 0x32 +#define EFI_HII_SIBT_FONT 0x40 + +typedef struct _EFI_HII_SIBT_DUPLICATE_BLOCK { + EFI_HII_STRING_BLOCK Header; + EFI_STRING_ID StringId; +} EFI_HII_SIBT_DUPLICATE_BLOCK; + +typedef struct _EFI_HII_SIBT_END_BLOCK { + EFI_HII_STRING_BLOCK Header; +} EFI_HII_SIBT_END_BLOCK; + +typedef struct _EFI_HII_SIBT_EXT1_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 BlockType2; + UINT8 Length; +} EFI_HII_SIBT_EXT1_BLOCK; + +typedef struct _EFI_HII_SIBT_EXT2_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 BlockType2; + UINT16 Length; +} EFI_HII_SIBT_EXT2_BLOCK; + +typedef struct _EFI_HII_SIBT_EXT4_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 BlockType2; + UINT32 Length; +} EFI_HII_SIBT_EXT4_BLOCK; + +typedef struct _EFI_HII_SIBT_FONT_BLOCK { + EFI_HII_SIBT_EXT2_BLOCK Header; + UINT8 FontId; + UINT16 FontSize; + EFI_HII_FONT_STYLE FontStyle; + CHAR16 FontName[1]; +} EFI_HII_SIBT_FONT_BLOCK; + +typedef struct _EFI_HII_SIBT_SKIP1_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 SkipCount; +} EFI_HII_SIBT_SKIP1_BLOCK; + +typedef struct _EFI_HII_SIBT_SKIP2_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT16 SkipCount; +} EFI_HII_SIBT_SKIP2_BLOCK; + +typedef struct _EFI_HII_SIBT_STRING_SCSU_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 StringText[1]; +} EFI_HII_SIBT_STRING_SCSU_BLOCK; + +typedef struct _EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 FontIdentifier; + UINT8 StringText[1]; +} EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK; + +typedef struct _EFI_HII_SIBT_STRINGS_SCSU_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT16 StringCount; + UINT8 StringText[1]; +} EFI_HII_SIBT_STRINGS_SCSU_BLOCK; + +typedef struct _EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 FontIdentifier; + UINT16 StringCount; + UINT8 StringText[1]; +} EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK; + +typedef struct _EFI_HII_SIBT_STRING_UCS2_BLOCK { + EFI_HII_STRING_BLOCK Header; + CHAR16 StringText[1]; +} EFI_HII_SIBT_STRING_UCS2_BLOCK; + +typedef struct _EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 FontIdentifier; + CHAR16 StringText[1]; +} EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK; + +typedef struct _EFI_HII_SIBT_STRINGS_UCS2_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT16 StringCount; + CHAR16 StringText[1]; +} EFI_HII_SIBT_STRINGS_UCS2_BLOCK; + +typedef struct _EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK { + EFI_HII_STRING_BLOCK Header; + UINT8 FontIdentifier; + UINT16 StringCount; + CHAR16 StringText[1]; +} EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK; + +// +// Image Packages +// + +typedef struct _EFI_HII_IMAGE_PACKAGE_HDR { + EFI_HII_PACKAGE_HEADER Header; + UINT32 ImageInfoOffset; + UINT32 PaletteInfoOffset; +} EFI_HII_IMAGE_PACKAGE_HDR; + +typedef struct _EFI_HII_IMAGE_BLOCK { + UINT8 BlockType; +} EFI_HII_IMAGE_BLOCK; + +#define EFI_HII_IIBT_END 0x00 +#define EFI_HII_IIBT_IMAGE_1BIT 0x10 +#define EFI_HII_IIBT_IMAGE_1BIT_TRANS 0x11 +#define EFI_HII_IIBT_IMAGE_4BIT 0x12 +#define EFI_HII_IIBT_IMAGE_4BIT_TRANS 0x13 +#define EFI_HII_IIBT_IMAGE_8BIT 0x14 +#define EFI_HII_IIBT_IMAGE_8BIT_TRANS 0x15 +#define EFI_HII_IIBT_IMAGE_24BIT 0x16 +#define EFI_HII_IIBT_IMAGE_24BIT_TRANS 0x17 +#define EFI_HII_IIBT_IMAGE_JPEG 0x18 +#define EFI_HII_IIBT_IMAGE_PNG 0x19 +#define EFI_HII_IIBT_DUPLICATE 0x20 +#define EFI_HII_IIBT_SKIP2 0x21 +#define EFI_HII_IIBT_SKIP1 0x22 +#define EFI_HII_IIBT_EXT1 0x30 +#define EFI_HII_IIBT_EXT2 0x31 +#define EFI_HII_IIBT_EXT4 0x32 + +typedef struct _EFI_HII_IIBT_END_BLOCK { + EFI_HII_IMAGE_BLOCK Header; +} EFI_HII_IIBT_END_BLOCK; + +typedef struct _EFI_HII_IIBT_EXT1_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 BlockType2; + UINT8 Length; +} EFI_HII_IIBT_EXT1_BLOCK; + +typedef struct _EFI_HII_IIBT_EXT2_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 BlockType2; + UINT16 Length; +} EFI_HII_IIBT_EXT2_BLOCK; + +typedef struct _EFI_HII_IIBT_EXT4_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 BlockType2; + UINT32 Length; +} EFI_HII_IIBT_EXT4_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_1BIT_BASE { + UINT16 Width; + UINT16 Height; + UINT8 Data[1]; +} EFI_HII_IIBT_IMAGE_1BIT_BASE; + +typedef struct _EFI_HII_IIBT_IMAGE_1BIT_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_1BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_1BIT_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_1BIT_TRANS_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_1BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_1BIT_TRANS_BLOCK; + +typedef struct _EFI_HII_RGB_PIXEL { + UINT8 b; + UINT8 g; + UINT8 r; +} EFI_HII_RGB_PIXEL; + +typedef struct _EFI_HII_IIBT_IMAGE_24BIT_BASE { + UINT16 Width; + UINT16 Height; + EFI_HII_RGB_PIXEL Bitmap[1]; +} EFI_HII_IIBT_IMAGE_24BIT_BASE; + +typedef struct _EFI_HII_IIBT_IMAGE_24BIT_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + EFI_HII_IIBT_IMAGE_24BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_24BIT_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_24BIT_TRANS_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + EFI_HII_IIBT_IMAGE_24BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_24BIT_TRANS_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_4BIT_BASE { + UINT16 Width; + UINT16 Height; + UINT8 Data[1]; +} EFI_HII_IIBT_IMAGE_4BIT_BASE; + +typedef struct _EFI_HII_IIBT_IMAGE_4BIT_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_4BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_4BIT_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_4BIT_TRANS_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_4BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_4BIT_TRANS_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_8BIT_BASE { + UINT16 Width; + UINT16 Height; + UINT8 Data[1]; +} EFI_HII_IIBT_IMAGE_8BIT_BASE; + +typedef struct _EFI_HII_IIBT_IMAGE_8BIT_PALETTE_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_8BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_8BIT_BLOCK; + +typedef struct _EFI_HII_IIBT_IMAGE_8BIT_TRANS_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 PaletteIndex; + EFI_HII_IIBT_IMAGE_8BIT_BASE Bitmap; +} EFI_HII_IIBT_IMAGE_8BIT_TRAN_BLOCK; + +typedef struct _EFI_HII_IIBT_DUPLICATE_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + EFI_IMAGE_ID ImageId; +} EFI_HII_IIBT_DUPLICATE_BLOCK; + +typedef struct _EFI_HII_IIBT_JPEG_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT32 Size; + UINT8 Data[1]; +} EFI_HII_IIBT_JPEG_BLOCK; + +typedef struct _EFI_HII_IIBT_PNG_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT32 Size; + UINT8 Data[1]; +} EFI_HII_IIBT_PNG_BLOCK; + +typedef struct _EFI_HII_IIBT_SKIP1_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT8 SkipCount; +} EFI_HII_IIBT_SKIP1_BLOCK; + +typedef struct _EFI_HII_IIBT_SKIP2_BLOCK { + EFI_HII_IMAGE_BLOCK Header; + UINT16 SkipCount; +} EFI_HII_IIBT_SKIP2_BLOCK; + +typedef struct _EFI_HII_IMAGE_PALETTE_INFO_HEADER { + UINT16 PaletteCount; +} EFI_HII_IMAGE_PALETTE_INFO_HEADER; + +typedef struct _EFI_HII_IMAGE_PALETTE_INFO { + UINT16 PaletteSize; + EFI_HII_RGB_PIXEL PaletteValue[1]; +} EFI_HII_IMAGE_PALETTE_INFO; + +// +// Forms Package +// + +typedef struct _EFI_HII_FORM_PACKAGE { + EFI_HII_PACKAGE_HEADER Header; + // EFI_IFR_OP_HEADER OpCodeHeader; + // More op-codes follow +} EFI_HII_FORM_PACKAGE; + +typedef struct { + UINT8 Hour; + UINT8 Minute; + UINT8 Second; +} EFI_HII_TIME; + +typedef struct { + UINT16 Year; + UINT8 Month; + UINT8 Day; +} EFI_HII_DATE; + +typedef struct { + EFI_QUESTION_ID QuestionId; + EFI_FORM_ID FormId; + EFI_GUID FormSetGuid; + EFI_STRING_ID DevicePath; +} EFI_HII_REF; + +typedef union { + UINT8 u8; + UINT16 u16; + UINT32 u32; + UINT64 u64; + BOOLEAN b; + EFI_HII_TIME time; + EFI_HII_DATE date; + EFI_STRING_ID string; + EFI_HII_REF ref; +} EFI_IFR_TYPE_VALUE; + +#define EFI_IFR_FORM_OP 0x01 +#define EFI_IFR_SUBTITLE_OP 0x02 +#define EFI_IFR_TEXT_OP 0x03 +#define EFI_IFR_IMAGE_OP 0x04 +#define EFI_IFR_ONE_OF_OP 0x05 +#define EFI_IFR_CHECKBOX_OP 0x06 +#define EFI_IFR_NUMERIC_OP 0x07 +#define EFI_IFR_PASSWORD_OP 0x08 +#define EFI_IFR_ONE_OF_OPTION_OP 0x09 +#define EFI_IFR_SUPPRESS_IF_OP 0x0A +#define EFI_IFR_LOCKED_OP 0x0B +#define EFI_IFR_ACTION_OP 0x0C +#define EFI_IFR_RESET_BUTTON_OP 0x0D +#define EFI_IFR_FORM_SET_OP 0x0E +#define EFI_IFR_REF_OP 0x0F +#define EFI_IFR_NO_SUBMIT_IF_OP 0x10 +#define EFI_IFR_INCONSISTENT_IF_OP 0x11 +#define EFI_IFR_EQ_ID_VAL_OP 0x12 +#define EFI_IFR_EQ_ID_ID_OP 0x13 +#define EFI_IFR_EQ_ID_VAL_LIST_OP 0x14 +#define EFI_IFR_AND_OP 0x15 +#define EFI_IFR_OR_OP 0x16 +#define EFI_IFR_NOT_OP 0x17 +#define EFI_IFR_RULE_OP 0x18 +#define EFI_IFR_GRAY_OUT_IF_OP 0x19 +#define EFI_IFR_DATE_OP 0x1A +#define EFI_IFR_TIME_OP 0x1B +#define EFI_IFR_STRING_OP 0x1C +#define EFI_IFR_REFRESH_OP 0x1D +#define EFI_IFR_DISABLE_IF_OP 0x1E +#define EFI_IFR_TO_LOWER_OP 0x20 +#define EFI_IFR_TO_UPPER_OP 0x21 +#define EFI_IFR_MAP_OP 0x22 +#define EFI_IFR_ORDERED_LIST_OP 0x23 +#define EFI_IFR_VARSTORE_OP 0x24 +#define EFI_IFR_VARSTORE_NAME_VALUE_OP 0x25 +#define EFI_IFR_VARSTORE_EFI_OP 0x26 +#define EFI_IFR_VARSTORE_DEVICE_OP 0x27 +#define EFI_IFR_VERSION_OP 0x28 +#define EFI_IFR_END_OP 0x29 +#define EFI_IFR_MATCH_OP 0x2A +#define EFI_IFR_GET_OP 0x2B +#define EFI_IFR_SET_OP 0x2C +#define EFI_IFR_READ_OP 0x2D +#define EFI_IFR_WRITE_OP 0x2E +#define EFI_IFR_EQUAL_OP 0x2F +#define EFI_IFR_NOT_EQUAL_OP 0x30 +#define EFI_IFR_GREATER_THAN_OP 0x31 +#define EFI_IFR_GREATER_EQUAL_OP 0x32 +#define EFI_IFR_LESS_THAN_OP 0x33 +#define EFI_IFR_LESS_EQUAL_OP 0x34 +#define EFI_IFR_BITWISE_AND_OP 0x35 +#define EFI_IFR_BITWISE_OR_OP 0x36 +#define EFI_IFR_BITWISE_NOT_OP 0x37 +#define EFI_IFR_SHIFT_LEFT_OP 0x38 +#define EFI_IFR_SHIFT_RIGHT_OP 0x39 +#define EFI_IFR_ADD_OP 0x3A +#define EFI_IFR_SUBTRACT_OP 0x3B +#define EFI_IFR_MULTIPLY_OP 0x3C +#define EFI_IFR_DIVIDE_OP 0x3D +#define EFI_IFR_MODULO_OP 0x3E +#define EFI_IFR_RULE_REF_OP 0x3F +#define EFI_IFR_QUESTION_REF1_OP 0x40 +#define EFI_IFR_QUESTION_REF2_OP 0x41 +#define EFI_IFR_UINT8_OP 0x42 +#define EFI_IFR_UINT16_OP 0x43 +#define EFI_IFR_UINT32_OP 0x44 +#define EFI_IFR_UINT64_OP 0x45 +#define EFI_IFR_TRUE_OP 0x46 +#define EFI_IFR_FALSE_OP 0x47 +#define EFI_IFR_TO_UINT_OP 0x48 +#define EFI_IFR_TO_STRING_OP 0x49 +#define EFI_IFR_TO_BOOLEAN_OP 0x4A +#define EFI_IFR_MID_OP 0x4B +#define EFI_IFR_FIND_OP 0x4C +#define EFI_IFR_TOKEN_OP 0x4D +#define EFI_IFR_STRING_REF1_OP 0x4E +#define EFI_IFR_STRING_REF2_OP 0x4F +#define EFI_IFR_CONDITIONAL_OP 0x50 +#define EFI_IFR_QUESTION_REF3_OP 0x51 +#define EFI_IFR_ZERO_OP 0x52 +#define EFI_IFR_ONE_OP 0x53 +#define EFI_IFR_ONES_OP 0x54 +#define EFI_IFR_UNDEFINED_OP 0x55 +#define EFI_IFR_LENGTH_OP 0x56 +#define EFI_IFR_DUP_OP 0x57 +#define EFI_IFR_THIS_OP 0x58 +#define EFI_IFR_SPAN_OP 0x59 +#define EFI_IFR_VALUE_OP 0x5A +#define EFI_IFR_DEFAULT_OP 0x5B +#define EFI_IFR_DEFAULTSTORE_OP 0x5C +#define EFI_IFR_FORM_MAP_OP 0x5D +#define EFI_IFR_CATENATE_OP 0x5E +#define EFI_IFR_GUID_OP 0x5F +#define EFI_IFR_SECURITY_OP 0x60 +#define EFI_IFR_MODAL_TAG_OP 0x61 +#define EFI_IFR_REFRESH_ID_OP 0x62 +#define EFI_IFR_WARNING_IF_OP 0x63 +#define EFI_IFR_MATCH2_OP 0x64 + + +typedef struct _EFI_IFR_OP_HEADER { + UINT8 OpCode; + UINT8 Length:7; + UINT8 Scope:1; +} EFI_IFR_OP_HEADER; + +typedef struct _EFI_IFR_STATEMENT_HEADER { + EFI_STRING_ID Prompt; + EFI_STRING_ID Help; +} EFI_IFR_STATEMENT_HEADER; + +typedef struct _EFI_IFR_QUESTION_HEADER { + EFI_IFR_STATEMENT_HEADER Header; + EFI_QUESTION_ID QuestionId; + EFI_VARSTORE_ID VarStoreId; + union { + EFI_STRING_ID VarName; + UINT16 VarOffset; + } VarStoreInfo; + UINT8 Flags; +} EFI_IFR_QUESTION_HEADER; + +#define EFI_IFR_FLAG_READ_ONLY 0x01 +#define EFI_IFR_FLAG_CALLBACK 0x04 +#define EFI_IFR_FLAG_RESET_REQUIRED 0x10 +#define EFI_IFR_FLAG_REST_STYLE 0x20 +#define EFI_IFR_FLAG_RECONNECT_REQUIRED 0x40 +#define EFI_IFR_FLAG_OPTIONS_ONLY 0x80 + +typedef struct _EFI_IFR_DEFAULTSTORE { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID DefaultName; + UINT16 DefaultId; +} EFI_IFR_DEFAULTSTORE; + +#define EFI_HII_DEFAULT_CLASS_STANDARD 0x0000 +#define EFI_HII_DEFAULT_CLASS_MANUFACTURING 0x0001 +#define EFI_HII_DEFAULT_CLASS_SAFE 0x0002 +#define EFI_HII_DEFAULT_CLASS_PLATFORM_BEGIN 0x4000 +#define EFI_HII_DEFAULT_CLASS_PLATFORM_END 0x7fff +#define EFI_HII_DEFAULT_CLASS_HARDWARE_BEGIN 0x8000 +#define EFI_HII_DEFAULT_CLASS_HARDWARE_END 0xbfff +#define EFI_HII_DEFAULT_CLASS_FIRMWARE_BEGIN 0xc000 +#define EFI_HII_DEFAULT_CLASS_FIRMWARE_END 0xffff + +typedef struct _EFI_IFR_VARSTORE { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + EFI_VARSTORE_ID VarStoreId; + UINT16 Size; + UINT8 Name[1]; +} EFI_IFR_VARSTORE; + +typedef struct _EFI_IFR_VARSTORE_EFI { + EFI_IFR_OP_HEADER Header; + EFI_VARSTORE_ID VarStoreId; + EFI_GUID Guid; + UINT32 Attributes; + UINT16 Size; + UINT8 Name[1]; +} EFI_IFR_VARSTORE_EFI; + +typedef struct _EFI_IFR_VARSTORE_NAME_VALUE { + EFI_IFR_OP_HEADER Header; + EFI_VARSTORE_ID VarStoreId; + EFI_GUID Guid; +} EFI_IFR_VARSTORE_NAME_VALUE; + +typedef struct _EFI_IFR_FORM_SET { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + EFI_STRING_ID FormSetTitle; + EFI_STRING_ID Help; + UINT8 Flags; + // EFI_GUID ClassGuid[]; +} EFI_IFR_FORM_SET; + +typedef struct _EFI_IFR_END { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_END; + +typedef struct _EFI_IFR_FORM { + EFI_IFR_OP_HEADER Header; + UINT16 FormId; + EFI_STRING_ID FormTitle; +} EFI_IFR_FORM; + +typedef struct _EFI_IFR_IMAGE { + EFI_IFR_OP_HEADER Header; + EFI_IMAGE_ID Id; +} EFI_IFR_IMAGE; + +typedef struct _EFI_IFR_MODAL_TAG { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MODAL_TAG; + +typedef struct _EFI_IFR_LOCKED { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_LOCKED; + +typedef struct _EFI_IFR_RULE { + EFI_IFR_OP_HEADER Header; + UINT8 RuleId; +} EFI_IFR_RULE; + +typedef struct _EFI_IFR_DEFAULT { + EFI_IFR_OP_HEADER Header; + UINT16 DefaultId; + UINT8 Type; + EFI_IFR_TYPE_VALUE Value; +} EFI_IFR_DEFAULT; + +typedef struct _EFI_IFR_DEFAULT_2 { + EFI_IFR_OP_HEADER Header; + UINT16 DefaultId; + UINT8 Type; +} EFI_IFR_DEFAULT_2; + +typedef struct _EFI_IFR_VALUE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_VALUE; + +typedef struct _EFI_IFR_SUBTITLE { + EFI_IFR_OP_HEADER Header; + EFI_IFR_STATEMENT_HEADER Statement; + UINT8 Flags; +} EFI_IFR_SUBTITLE; + +#define EFI_IFR_FLAGS_HORIZONTAL 0x01 + +typedef struct _EFI_IFR_CHECKBOX { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; +} EFI_IFR_CHECKBOX; + +#define EFI_IFR_CHECKBOX_DEFAULT 0x01 +#define EFI_IFR_CHECKBOX_DEFAULT_MFG 0x02 + +typedef struct _EFI_IFR_TEXT { + EFI_IFR_OP_HEADER Header; + EFI_IFR_STATEMENT_HEADER Statement; + EFI_STRING_ID TextTwo; +} EFI_IFR_TEXT; + +typedef struct _EFI_IFR_REF { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_FORM_ID FormId; +} EFI_IFR_REF; + +typedef struct _EFI_IFR_REF2 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_FORM_ID FormId; + EFI_QUESTION_ID QuestionId; +} EFI_IFR_REF2; + +typedef struct _EFI_IFR_REF3 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_FORM_ID FormId; + EFI_QUESTION_ID QuestionId; + EFI_GUID FormSetId; +} EFI_IFR_REF3; + +typedef struct _EFI_IFR_REF4 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_FORM_ID FormId; + EFI_QUESTION_ID QuestionId; + EFI_GUID FormSetId; + EFI_STRING_ID DevicePath; +} EFI_IFR_REF4; + +typedef struct _EFI_IFR_REF5 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; +} EFI_IFR_REF5; + +typedef struct _EFI_IFR_RESET_BUTTON { + EFI_IFR_OP_HEADER Header; + EFI_IFR_STATEMENT_HEADER Statement; + EFI_DEFAULT_ID DefaultId; +} EFI_IFR_RESET_BUTTON; + +typedef struct _EFI_IFR_ACTION { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + EFI_STRING_ID QuestionConfig; +} EFI_IFR_ACTION; + +typedef struct _EFI_IFR_ACTION_1 { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; +} EFI_IFR_ACTION_1; + +typedef struct _EFI_IFR_DATE { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; +} EFI_IFR_DATE; + +#define EFI_QF_DATE_YEAR_SUPPRESS 0x01 +#define EFI_QF_DATE_MONTH_SUPPRESS 0x02 +#define EFI_QF_DATE_DAY_SUPPRESS 0x04 + +#define EFI_QF_DATE_STORAGE 0x30 +#define QF_DATE_STORAGE_NORMAL 0x00 +#define QF_DATE_STORAGE_TIME 0x10 +#define QF_DATE_STORAGE_WAKEUP 0x20 + +typedef union { + struct { + UINT8 MinValue; + UINT8 MaxValue; + UINT8 Step; + } u8; + struct { + UINT16 MinValue; + UINT16 MaxValue; + UINT16 Step; + } u16; + struct { + UINT32 MinValue; + UINT32 MaxValue; + UINT32 Step; + } u32; + struct { + UINT64 MinValue; + UINT64 MaxValue; + UINT64 Step; + } u64; +} MINMAXSTEP_DATA; + +typedef struct _EFI_IFR_NUMERIC { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; + MINMAXSTEP_DATA data; +} EFI_IFR_NUMERIC; + +#define EFI_IFR_NUMERIC_SIZE 0x03 +#define EFI_IFR_NUMERIC_SIZE_1 0x00 +#define EFI_IFR_NUMERIC_SIZE_2 0x01 +#define EFI_IFR_NUMERIC_SIZE_4 0x02 +#define EFI_IFR_NUMERIC_SIZE_8 0x03 + +#define EFI_IFR_DISPLAY 0x30 +#define EFI_IFR_DISPLAY_INT_DEC 0x00 +#define EFI_IFR_DISPLAY_UINT_DEC 0x10 +#define EFI_IFR_DISPLAY_UINT_HEX 0x20 + +typedef struct _EFI_IFR_ONE_OF { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; + MINMAXSTEP_DATA data; +} EFI_IFR_ONE_OF; + +typedef struct _EFI_IFR_STRING { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 MinSize; + UINT8 MaxSize; + UINT8 Flags; +} EFI_IFR_STRING; + +#define EFI_IFR_STRING_MULTI_LINE 0x01 + +typedef struct _EFI_IFR_PASSWORD { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT16 MinSize; + UINT16 MaxSize; +} EFI_IFR_PASSWORD; + +typedef struct _EFI_IFR_ORDERED_LIST { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 MaxContainers; + UINT8 Flags; +} EFI_IFR_ORDERED_LIST; + +#define EFI_IFR_UNIQUE_SET 0x01 +#define EFI_IFR_NO_EMPTY_SET 0x02 + +typedef struct _EFI_IFR_TIME { + EFI_IFR_OP_HEADER Header; + EFI_IFR_QUESTION_HEADER Question; + UINT8 Flags; +} EFI_IFR_TIME; + +#define QF_TIME_HOUR_SUPPRESS 0x01 +#define QF_TIME_MINUTE_SUPPRESS 0x02 +#define QF_TIME_SECOND_SUPPRESS 0x04 + +#define QF_TIME_STORAGE 0x30 +#define QF_TIME_STORAGE_NORMAL 0x00 +#define QF_TIME_STORAGE_TIME 0x10 +#define QF_TIME_STORAGE_WAKEUP 0x20 + +typedef struct _EFI_IFR_DISABLE_IF { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_DISABLE_IF; + +typedef struct _EFI_IFR_SUPPRESS_IF { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_SUPPRESS_IF; + +typedef struct _EFI_IFR_GRAY_OUT_IF { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_GRAY_OUT_IF; + +typedef struct _EFI_IFR_INCONSISTENT_IF { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID Error; +} EFI_IFR_INCONSISTENT_IF; + +typedef struct _EFI_IFR_NO_SUBMIT_IF { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID Error; +} EFI_IFR_NO_SUBMIT_IF; + +typedef struct _EFI_IFR_WARNING_IF { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID Warning; + UINT8 TimeOut; +} EFI_IFR_WARNING_IF; + +typedef struct _EFI_IFR_REFRESH { + EFI_IFR_OP_HEADER Header; + UINT8 RefreshInterval; +} EFI_IFR_REFRESH; + +typedef struct _EFI_IFR_REFRESH_ID { + EFI_IFR_OP_HEADER Header; + EFI_GUID RefreshEventGroupId; +} EFI_IFR_REFRESH_ID; + +typedef struct _EFI_IFR_VARSTORE_DEVICE { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID DevicePath; +} EFI_IFR_VARSTORE_DEVICE; + +typedef struct _EFI_IFR_ONE_OF_OPTION { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID Option; + UINT8 Flags; + UINT8 Type; + EFI_IFR_TYPE_VALUE Value; +} EFI_IFR_ONE_OF_OPTION; + +#define EFI_IFR_TYPE_NUM_SIZE_8 0x00 +#define EFI_IFR_TYPE_NUM_SIZE_16 0x01 +#define EFI_IFR_TYPE_NUM_SIZE_32 0x02 +#define EFI_IFR_TYPE_NUM_SIZE_64 0x03 +#define EFI_IFR_TYPE_BOOLEAN 0x04 +#define EFI_IFR_TYPE_TIME 0x05 +#define EFI_IFR_TYPE_DATE 0x06 +#define EFI_IFR_TYPE_STRING 0x07 +#define EFI_IFR_TYPE_OTHER 0x08 +#define EFI_IFR_TYPE_UNDEFINED 0x09 +#define EFI_IFR_TYPE_ACTION 0x0A +#define EFI_IFR_TYPE_BUFFER 0x0B +#define EFI_IFR_TYPE_REF 0x0C + +#define EFI_IFR_OPTION_DEFAULT 0x10 +#define EFI_IFR_OPTION_DEFAULT_MFG 0x20 + +typedef struct _EFI_IFR_GUID { + EFI_IFR_OP_HEADER Header; + EFI_GUID Guid; + //Optional Data Follows +} EFI_IFR_GUID; + +typedef struct _EFI_IFR_DUP { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_DUP; + +typedef struct _EFI_IFR_EQ_ID_ID { + EFI_IFR_OP_HEADER Header; + EFI_QUESTION_ID QuestionId1; + EFI_QUESTION_ID QuestionId2; +} EFI_IFR_EQ_ID_ID; + +typedef struct _EFI_IFR_EQ_ID_VAL { + EFI_IFR_OP_HEADER Header; + EFI_QUESTION_ID QuestionId; + UINT16 Value; +} EFI_IFR_EQ_ID_VAL; + +typedef struct _EFI_IFR_EQ_ID_VAL_LIST { + EFI_IFR_OP_HEADER Header; + EFI_QUESTION_ID QuestionId; + UINT16 ListLength; + UINT16 ValueList[1]; +} EFI_IFR_EQ_ID_VAL_LIST; + +typedef struct _EFI_IFR_QUESTION_REF1 { + EFI_IFR_OP_HEADER Header; + EFI_QUESTION_ID QuestionId; +} EFI_IFR_QUESTION_REF1; + +typedef struct _EFI_IFR_UINT8 { + EFI_IFR_OP_HEADER Header; + UINT8 Value; +} EFI_IFR_UINT8; + +typedef struct _EFI_IFR_UINT16 { + EFI_IFR_OP_HEADER Header; + UINT16 Value; +} EFI_IFR_UINT16; + +typedef struct _EFI_IFR_QUESTION_REF2 { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_QUESTION_REF2; + +typedef struct _EFI_IFR_UINT32 { + EFI_IFR_OP_HEADER Header; + UINT32 Value; +} EFI_IFR_UINT32; + +typedef struct _EFI_IFR_UINT64 { + EFI_IFR_OP_HEADER Header; + UINT64 Value; +} EFI_IFR_UINT64; + +typedef struct _EFI_IFR_QUESTION_REF3 { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_QUESTION_REF3; + +typedef struct _EFI_IFR_QUESTION_REF3_2 { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID DevicePath; +} EFI_IFR_QUESTION_REF3_2; + +typedef struct _EFI_IFR_QUESTION_REF3_3 { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID DevicePath; + EFI_GUID Guid; +} EFI_IFR_QUESTION_REF3_3; + +typedef struct _EFI_IFR_RULE_REF { + EFI_IFR_OP_HEADER Header; + UINT8 RuleId; +} EFI_IFR_RULE_REF; + +typedef struct _EFI_IFR_STRING_REF1 { + EFI_IFR_OP_HEADER Header; + EFI_STRING_ID StringId; +} EFI_IFR_STRING_REF1; + +typedef struct _EFI_IFR_STRING_REF2 { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_STRING_REF2; + +typedef struct _EFI_IFR_THIS { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_THIS; + +typedef struct _EFI_IFR_TRUE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TRUE; + +typedef struct _EFI_IFR_FALSE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_FALSE; + +typedef struct _EFI_IFR_ONE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_ONE; + +typedef struct _EFI_IFR_ONES { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_ONES; + +typedef struct _EFI_IFR_ZERO { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_ZERO; + +typedef struct _EFI_IFR_UNDEFINED { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_UNDEFINED; + +typedef struct _EFI_IFR_VERSION { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_VERSION; + +typedef struct _EFI_IFR_LENGTH { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_LENGTH; + +typedef struct _EFI_IFR_NOT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_NOT; + +typedef struct _EFI_IFR_BITWISE_NOT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_BITWISE_NOT; + +typedef struct _EFI_IFR_TO_BOOLEAN { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TO_BOOLEAN; + +#define EFI_IFR_STRING_UNSIGNED_DEC 0 +#define EFI_IFR_STRING_SIGNED_DEC 1 +#define EFI_IFR_STRING_LOWERCASE_HEX 2 +#define EFI_IFR_STRING_UPPERCASE_HEX 3 + +#define EFI_IFR_STRING_ASCII 0 +#define EFI_IFR_STRING_UNICODE 8 + +typedef struct _EFI_IFR_TO_STRING { + EFI_IFR_OP_HEADER Header; + UINT8 Format; +} EFI_IFR_TO_STRING; + +typedef struct _EFI_IFR_TO_UINT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TO_UINT; + +typedef struct _EFI_IFR_TO_UPPER { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TO_UPPER; + +typedef struct _EFI_IFR_TO_LOWER { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TO_LOWER; + +typedef struct _EFI_IFR_ADD { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_ADD; + +typedef struct _EFI_IFR_AND { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_AND; + +typedef struct _EFI_IFR_BITWISE_AND { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_BITWISE_AND; + +typedef struct _EFI_IFR_BITWISE_OR { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_BITWISE_OR; + +typedef struct _EFI_IFR_CATENATE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_CATENATE; + +typedef struct _EFI_IFR_DIVIDE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_DIVIDE; + +typedef struct _EFI_IFR_EQUAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_EQUAL; + +typedef struct _EFI_IFR_GREATER_EQUAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_GREATER_EQUAL; + +typedef struct _EFI_IFR_GREATER_THAN { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_GREATER_THAN; + +typedef struct _EFI_IFR_LESS_EQUAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_LESS_EQUAL; + +typedef struct _EFI_IFR_LESS_THAN { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_LESS_THAN; + +typedef struct _EFI_IFR_MATCH { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MATCH; + +typedef struct _EFI_IFR_MATCH2 { + EFI_IFR_OP_HEADER Header; + EFI_GUID SyntaxType; +} EFI_IFR_MATCH2; + +typedef struct _EFI_IFR_MULTIPLY { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MULTIPLY; + +typedef struct _EFI_IFR_MODULO { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MODULO; + +typedef struct _EFI_IFR_NOT_EQUAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_NOT_EQUAL; + +typedef struct _EFI_IFR_OR { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_OR; + +typedef struct _EFI_IFR_SHIFT_LEFT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_SHIFT_LEFT; + +typedef struct _EFI_IFR_SHIFT_RIGHT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_SHIFT_RIGHT; + +typedef struct _EFI_IFR_SUBTRACT { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_SUBTRACT; + +typedef struct _EFI_IFR_CONDITIONAL { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_CONDITIONAL; + +#define EFI_IFR_FF_CASE_SENSITIVE 0x00 +#define EFI_IFR_FF_CASE_INSENSITIVE 0x01 + +typedef struct _EFI_IFR_FIND { + EFI_IFR_OP_HEADER Header; + UINT8 Format; +} EFI_IFR_FIND; + +typedef struct _EFI_IFR_MID { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MID; + +typedef struct _EFI_IFR_TOKEN { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_TOKEN; + +#define EFI_IFR_FLAGS_FIRST_MATCHING 0x00 +#define EFI_IFR_FLAGS_FIRST_NON_MATCHING 0x01 + +typedef struct _EFI_IFR_SPAN { + EFI_IFR_OP_HEADER Header; + UINT8 Flags; +} EFI_IFR_SPAN; + +typedef struct _EFI_IFR_SECURITY { + /// + /// Standard opcode header, where Header.Op = EFI_IFR_SECURITY_OP. + /// + EFI_IFR_OP_HEADER Header; + /// + /// Security permission level. + /// + EFI_GUID Permissions; +} EFI_IFR_SECURITY; + +typedef struct _EFI_IFR_FORM_MAP_METHOD { + /// + /// The string identifier which provides the human-readable name of + /// the configuration method for this standards map form. + /// + EFI_STRING_ID MethodTitle; + /// + /// Identifier which uniquely specifies the configuration methods + /// associated with this standards map form. + /// + EFI_GUID MethodIdentifier; +} EFI_IFR_FORM_MAP_METHOD; + +typedef struct _EFI_IFR_FORM_MAP { + /// + /// The sequence that defines the type of opcode as well as the length + /// of the opcode being defined. Header.OpCode = EFI_IFR_FORM_MAP_OP. + /// + EFI_IFR_OP_HEADER Header; + /// + /// The unique identifier for this particular form. + /// + EFI_FORM_ID FormId; + /// + /// One or more configuration method's name and unique identifier. + /// + // EFI_IFR_FORM_MAP_METHOD Methods[]; +} EFI_IFR_FORM_MAP; + +typedef struct _EFI_IFR_SET { + /// + /// The sequence that defines the type of opcode as well as the length + /// of the opcode being defined. Header.OpCode = EFI_IFR_SET_OP. + /// + EFI_IFR_OP_HEADER Header; + /// + /// Specifies the identifier of a previously declared variable store to + /// use when storing the question's value. + /// + EFI_VARSTORE_ID VarStoreId; + union { + /// + /// A 16-bit Buffer Storage offset. + /// + EFI_STRING_ID VarName; + /// + /// A Name Value or EFI Variable name (VarName). + /// + UINT16 VarOffset; + } VarStoreInfo; + /// + /// Specifies the type used for storage. + /// + UINT8 VarStoreType; +} EFI_IFR_SET; + +typedef struct _EFI_IFR_GET { + /// + /// The sequence that defines the type of opcode as well as the length + /// of the opcode being defined. Header.OpCode = EFI_IFR_GET_OP. + /// + EFI_IFR_OP_HEADER Header; + /// + /// Specifies the identifier of a previously declared variable store to + /// use when retrieving the value. + /// + EFI_VARSTORE_ID VarStoreId; + union { + /// + /// A 16-bit Buffer Storage offset. + /// + EFI_STRING_ID VarName; + /// + /// A Name Value or EFI Variable name (VarName). + /// + UINT16 VarOffset; + } VarStoreInfo; + /// + /// Specifies the type used for storage. + /// + UINT8 VarStoreType; +} EFI_IFR_GET; + +typedef struct _EFI_IFR_READ { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_READ; + +typedef struct _EFI_IFR_WRITE { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_WRITE; + +typedef struct _EFI_IFR_MAP { + EFI_IFR_OP_HEADER Header; +} EFI_IFR_MAP; +// +// Keyboard Package +// + +typedef enum { + EfiKeyLCtrl, + EfiKeyA0, + EfiKeyLAlt, + EfiKeySpaceBar, + EfiKeyA2, + EfiKeyA3, + EfiKeyA4, + EfiKeyRCtrl, + EfiKeyLeftArrow, + EfiKeyDownArrow, + EfiKeyRightArrow, + EfiKeyZero, + EfiKeyPeriod, + EfiKeyEnter, + EfiKeyLShift, + EfiKeyB0, + EfiKeyB1, + EfiKeyB2, + EfiKeyB3, + EfiKeyB4, + EfiKeyB5, + EfiKeyB6, + EfiKeyB7, + EfiKeyB8, + EfiKeyB9, + EfiKeyB10, + EfiKeyRshift, + EfiKeyUpArrow, + EfiKeyOne, + EfiKeyTwo, + EfiKeyThree, + EfiKeyCapsLock, + EfiKeyC1, + EfiKeyC2, + EfiKeyC3, + EfiKeyC4, + EfiKeyC5, + EfiKeyC6, + EfiKeyC7, + EfiKeyC8, + EfiKeyC9, + EfiKeyC10, + EfiKeyC11, + EfiKeyC12, + EfiKeyFour, + EfiKeyFive, + EfiKeySix, + EfiKeyPlus, + EfiKeyTab, + EfiKeyD1, + EfiKeyD2, + EfiKeyD3, + EfiKeyD4, + EfiKeyD5, + EfiKeyD6, + EfiKeyD7, + EfiKeyD8, + EfiKeyD9, + EfiKeyD10, + EfiKeyD11, + EfiKeyD12, + EfiKeyD13, + EfiKeyDel, + EfiKeyEnd, + EfiKeyPgDn, + EfiKeySeven, + EfiKeyEight, + EfiKeyNine, + EfiKeyE0, + EfiKeyE1, + EfiKeyE2, + EfiKeyE3, + EfiKeyE4, + EfiKeyE5, + EfiKeyE6, + EfiKeyE7, + EfiKeyE8, + EfiKeyE9, + EfiKeyE10, + EfiKeyE11, + EfiKeyE12, + EfiKeyBackSpace, + EfiKeyIns, + EfiKeyHome, + EfiKeyPgUp, + EfiKeyNLck, + EfiKeySlash, + EfiKeyAsterisk, + EfiKeyMinus, + EfiKeyEsc, + EfiKeyF1, + EfiKeyF2, + EfiKeyF3, + EfiKeyF4, + EfiKeyF5, + EfiKeyF6, + EfiKeyF7, + EfiKeyF8, + EfiKeyF9, + EfiKeyF10, + EfiKeyF11, + EfiKeyF12, + EfiKeyPrint, + EfiKeySLck, + EfiKeyPause +} EFI_KEY; + +typedef struct { + EFI_KEY Key; + CHAR16 Unicode; + CHAR16 ShiftedUnicode; + CHAR16 AltGrUnicode; + CHAR16 ShiftedAltGrUnicode; + UINT16 Modifier; + UINT16 AffectedAttribute; +} EFI_KEY_DESCRIPTOR; + +// +// A key which is affected by all the standard shift modifiers. +// Most keys would be expected to have this bit active. +// +#define EFI_AFFECTED_BY_STANDARD_SHIFT 0x0001 +// +// This key is affected by the caps lock so that if a keyboard driver +// would need to disambiguate between a key which had a "1" defined +// versus a "a" character. Having this bit turned on would tell +// the keyboard driver to use the appropriate shifted state or not. +// +#define EFI_AFFECTED_BY_CAPS_LOCK 0x0002 +// +// Similar to the case of CAPS lock, if this bit is active, the key +// is affected by the num lock being turned on. +// +#define EFI_AFFECTED_BY_NUM_LOCK 0x0004 + +typedef struct { + UINT16 LayoutLength; + EFI_GUID Guid; + UINT32 LayoutDescriptorStringOffset; + UINT8 DescriptorCount; + // EFI_KEY_DESCRIPTOR Descriptors[]; +} EFI_HII_KEYBOARD_LAYOUT; + +typedef struct { + EFI_HII_PACKAGE_HEADER Header; + UINT16 LayoutCount; + // EFI_HII_KEYBOARD_LAYOUT Layout[]; +} EFI_HII_KEYBOARD_PACKAGE_HDR; + +typedef struct { + CHAR16 Language[3]; + CHAR16 Space; + CHAR16 DescriptionString[1]; +} EFI_DESCRIPTION_STRING; + +typedef struct { + UINT16 DescriptionCount; + EFI_DESCRIPTION_STRING DescriptionString[1]; +} EFI_DESCRIPTION_STRING_BUNDLE; + +// +// Modifier values +// +#define EFI_NULL_MODIFIER 0x0000 +#define EFI_LEFT_CONTROL_MODIFIER 0x0001 +#define EFI_RIGHT_CONTROL_MODIFIER 0x0002 +#define EFI_LEFT_ALT_MODIFIER 0x0003 +#define EFI_RIGHT_ALT_MODIFIER 0x0004 +#define EFI_ALT_GR_MODIFIER 0x0005 +#define EFI_INSERT_MODIFIER 0x0006 +#define EFI_DELETE_MODIFIER 0x0007 +#define EFI_PAGE_DOWN_MODIFIER 0x0008 +#define EFI_PAGE_UP_MODIFIER 0x0009 +#define EFI_HOME_MODIFIER 0x000A +#define EFI_END_MODIFIER 0x000B +#define EFI_LEFT_SHIFT_MODIFIER 0x000C +#define EFI_RIGHT_SHIFT_MODIFIER 0x000D +#define EFI_CAPS_LOCK_MODIFIER 0x000E +#define EFI_NUM_LOCK _MODIFIER 0x000F +#define EFI_LEFT_ARROW_MODIFIER 0x0010 +#define EFI_RIGHT_ARROW_MODIFIER 0x0011 +#define EFI_DOWN_ARROW_MODIFIER 0x0012 +#define EFI_UP_ARROW_MODIFIER 0x0013 +#define EFI_NS_KEY_MODIFIER 0x0014 +#define EFI_NS_KEY_DEPENDENCY_MODIFIER 0x0015 +#define EFI_FUNCTION_KEY_ONE_MODIFIER 0x0016 +#define EFI_FUNCTION_KEY_TWO_MODIFIER 0x0017 +#define EFI_FUNCTION_KEY_THREE_MODIFIER 0x0018 +#define EFI_FUNCTION_KEY_FOUR_MODIFIER 0x0019 +#define EFI_FUNCTION_KEY_FIVE_MODIFIER 0x001A +#define EFI_FUNCTION_KEY_SIX_MODIFIER 0x001B +#define EFI_FUNCTION_KEY_SEVEN_MODIFIER 0x001C +#define EFI_FUNCTION_KEY_EIGHT_MODIFIER 0x001D +#define EFI_FUNCTION_KEY_NINE_MODIFIER 0x001E +#define EFI_FUNCTION_KEY_TEN_MODIFIER 0x001F +#define EFI_FUNCTION_KEY_ELEVEN_MODIFIER 0x0020 +#define EFI_FUNCTION_KEY_TWELVE_MODIFIER 0x0021 + +// +// Keys that have multiple control functions based on modifier +// settings are handled in the keyboard driver implementation. +// For instance PRINT_KEY might have a modifier held down and +// is still a nonprinting character, but might have an alternate +// control function like SYSREQUEST +// +#define EFI_PRINT_MODIFIER 0x0022 +#define EFI_SYS_REQUEST_MODIFIER 0x0023 +#define EFI_SCROLL_LOCK_MODIFIER 0x0024 +#define EFI_PAUSE_MODIFIER 0x0025 +#define EFI_BREAK_MODIFIER 0x0026 + +#pragma pack() + + + +// +// References to string tokens must use this macro to enable scanning for +// token usages. +// +// +// STRING_TOKEN is not defined in UEFI specification. But it is placed +// here for the easy access by C files and VFR source files. +// +#define STRING_TOKEN(t) t + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/UefiMultiPhase.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/UefiMultiPhase.h new file mode 100644 index 00000000..dbaed77a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/UefiMultiPhase.h @@ -0,0 +1,226 @@ +/** @file + This includes some definitions introduced in UEFI that will be used in both PEI + and DXE phases. + + (C) Copyright 2015 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __UEFI_MULTIPHASE_H__ +#define __UEFI_MULTIPHASE_H__ + +// +// Enumeration of memory types introduced in UEFI. +// +typedef enum { + EfiReservedMemoryType, + EfiLoaderCode, + EfiLoaderData, + EfiBootServicesCode, + EfiBootServicesData, + EfiRuntimeServicesCode, + EfiRuntimeServicesData, + EfiConventionalMemory, + EfiUnusableMemory, + EfiACPIReclaimMemory, + EfiACPIMemoryNVS, + EfiMemoryMappedIO, + EfiMemoryMappedIOPortSpace, + EfiPalCode, + EfiPersistentMemory, + EfiMaxMemoryType +} EFI_MEMORY_TYPE; + + +// +// Data structure that precedes all of the standard EFI table types. +// +typedef struct { + UINT64 Signature; + UINT32 Revision; + UINT32 HeaderSize; + UINT32 CRC32; + UINT32 Reserved; +} EFI_TABLE_HEADER; + +// +// Attributes of variable. +// +#define EFI_VARIABLE_NON_VOLATILE 0x00000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 +#define EFI_VARIABLE_HARDWARE_ERROR_RECORD 0x00000008 + +// +// This attribute is identified by the mnemonic 'HR' +// elsewhere in this specification. +// +#define EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS 0x00000010 + + + +// +// _WIN_CERTIFICATE.wCertificateType +// +#define WIN_CERT_TYPE_EFI_PKCS115 0x0EF0 +#define WIN_CERT_TYPE_EFI_GUID 0x0EF1 + +/** + + The WIN_CERTIFICATE structure is part of the PE/COFF + specification and has the following definition: + + @param dwLength The length of the entire certificate, + including the length of the header, in + bytes. + + @param wRevision The revision level of the WIN_CERTIFICATE + structure. The current revision level is + 0x0200. + + @param wCertificateType The certificate type. See + WIN_CERT_TYPE_xxx for the UEFI + certificate types. The UEFI + specification reserves the range of + certificate type values from 0x0EF0 + to 0x0EFF. + + @param bCertificate The actual certificate. The format of + the certificate depends on + wCertificateType. The format of the UEFI + certificates is defined below. + + +**/ +typedef struct _WIN_CERTIFICATE { + UINT32 dwLength; + UINT16 wRevision; + UINT16 wCertificateType; + //UINT8 bCertificate[ANYSIZE_ARRAY]; +} WIN_CERTIFICATE; + +// +// WIN_CERTIFICATE_UEFI_GUID.CertType +// +#define EFI_CERT_TYPE_RSA2048_SHA256_GUID \ + {0xa7717414, 0xc616, 0x4977, {0x94, 0x20, 0x84, 0x47, 0x12, 0xa7, 0x35, 0xbf } } + +// +// WIN_CERTIFICATE_UEFI_GUID.CertData +// +typedef struct _EFI_CERT_BLOCK_RSA_2048_SHA256 { + EFI_GUID HashType; + UINT8 PublicKey[256]; + UINT8 Signature[256]; +} EFI_CERT_BLOCK_RSA_2048_SHA256; + + +/** + + @param Hdr This is the standard WIN_CERTIFICATE header, where + wCertificateType is set to + WIN_CERT_TYPE_EFI_GUID. + + @param CertType This is the unique id which determines the + format of the CertData. In this case, the + value is EFI_CERT_TYPE_RSA2048_SHA256_GUID. + + @param CertData This is the certificate data. The format of + the data is determined by the CertType. In + this case the value is + EFI_CERT_BLOCK_RSA_2048_SHA256. + + @param Information The WIN_CERTIFICATE_UEFI_GUID certificate + type allows new types of certificates to + be developed for driver authentication + without requiring a new certificate type. + The CertType defines the format of the + CertData, which length is defined by the + size of the certificate less the fixed + size of the WIN_CERTIFICATE_UEFI_GUID + structure. + +**/ +typedef struct _WIN_CERTIFICATE_UEFI_GUID { + WIN_CERTIFICATE Hdr; + EFI_GUID CertType; + UINT8 CertData[1]; +} WIN_CERTIFICATE_UEFI_GUID; + + +/** + + Certificate which encapsulates the RSASSA_PKCS1-v1_5 digital + signature. + + The WIN_CERTIFICATE_UEFI_PKCS1_15 structure is derived from + WIN_CERTIFICATE and encapsulate the information needed to + implement the RSASSA-PKCS1-v1_5 digital signature algorithm as + specified in RFC2437. + + @param Hdr This is the standard WIN_CERTIFICATE header, where + wCertificateType is set to + WIN_CERT_TYPE_UEFI_PKCS1_15. + + @param HashAlgorithm This is the hashing algorithm which was + performed on the UEFI executable when + creating the digital signature. It is + one of the enumerated values pre-defined + in Section 26.4.1. See + EFI_HASH_ALGORITHM_x. + + @param Signature This is the actual digital signature. The + size of the signature is the same size as + the key (1024-bit key is 128 bytes) and can + be determined by subtracting the length of + the other parts of this header from the + total length of the certificate as found in + Hdr.dwLength. + +**/ +typedef struct _WIN_CERTIFICATE_EFI_PKCS1_15 { + WIN_CERTIFICATE Hdr; + EFI_GUID HashAlgorithm; + // UINT8 Signature[ANYSIZE_ARRAY]; +} WIN_CERTIFICATE_EFI_PKCS1_15; + + +/** + + AuthInfo is a WIN_CERTIFICATE using the wCertificateType + WIN_CERTIFICATE_UEFI_GUID and the CertType + EFI_CERT_TYPE_RSA2048_SHA256. If the attribute specifies + authenticated access, then the Data buffer should begin with an + authentication descriptor prior to the data payload and DataSize + should reflect the data.and descriptor size. The caller + shall digest the Monotonic Count value and the associated data + for the variable update using the SHA-256 1-way hash algorithm. + The ensuing the 32-byte digest will be signed using the private + key associated w/ the public/private 2048-bit RSA key-pair. The + WIN_CERTIFICATE shall be used to describe the signature of the + Variable data *Data. In addition, the signature will also + include the MonotonicCount value to guard against replay attacks + + @param MonotonicCount Included in the signature of + AuthInfo.Used to ensure freshness/no + replay. Incremented during each + "Write" access. + + @param AuthInfo Provides the authorization for the variable + access. It is a signature across the + variable data and the Monotonic Count + value. Caller uses Private key that is + associated with a public key that has been + provisioned via the key exchange. + +**/ +typedef struct { + UINT64 MonotonicCount; + WIN_CERTIFICATE_UEFI_GUID AuthInfo; +} EFI_VARIABLE_AUTHENTICATION; + +#endif + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/VariableFormat.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/VariableFormat.h new file mode 100644 index 00000000..765f4e50 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/VariableFormat.h @@ -0,0 +1,44 @@ +/**@file + Header file for EFI Variable Services. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __VARIABLE_FORMAT_H__ +#define __VARIABLE_FORMAT_H__ + +#define VARIABLE_DATA 0x55AA + +// +// Variable Store Header flags +// +#define VARIABLE_STORE_FORMATTED 0x5a +#define VARIABLE_STORE_HEALTHY 0xfe + +#pragma pack(1) + +typedef struct { + EFI_GUID Signature; + UINT32 Size; + UINT8 Format; + UINT8 State; + UINT16 Reserved; + UINT32 Reserved1; +} VARIABLE_STORE_HEADER; + +typedef struct { + UINT16 StartId; + UINT8 State; + UINT8 Reserved; + UINT32 Attributes; + UINT32 NameSize; + UINT32 DataSize; + EFI_GUID VendorGuid; +} VARIABLE_HEADER; + +#pragma pack() + +#endif // _EFI_VARIABLE_H_ diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/WorkingBlockHeader.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/WorkingBlockHeader.h new file mode 100644 index 00000000..8912949b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Common/WorkingBlockHeader.h @@ -0,0 +1,35 @@ +/** @file + Defines data structure that is the headers found at the runtime + updatable firmware volumes, such as the FileSystemGuid of the + working block, the header structure of the variable block, FTW + working block, or event log block. + + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __EFI_WORKING_BLOCK_HEADER_H__ +#define __EFI_WORKING_BLOCK_HEADER_H__ + +// +// EFI Fault tolerant working block header +// The header is immediately followed by the write queue. +// +typedef struct { + EFI_GUID Signature; + UINT32 Crc; + UINT8 WorkingBlockValid : 1; + UINT8 WorkingBlockInvalid : 1; +#define WORKING_BLOCK_VALID 0x1 +#define WORKING_BLOCK_INVALID 0x2 + UINT8 Reserved : 6; + UINT8 Reserved3[3]; + UINT64 WriteQueueSize; + // + // UINT8 WriteQueue[WriteQueueSize]; + // +} EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Guid/FfsSectionAlignmentPadding.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Guid/FfsSectionAlignmentPadding.h new file mode 100644 index 00000000..c067446a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Guid/FfsSectionAlignmentPadding.h @@ -0,0 +1,16 @@ +/** @file + Copyright (c) 2015, Linaro Ltd. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __FFS_SECTION_ALIGNMENT_PADDING_GUID_H__ +#define __FFS_SECTION_ALIGNMENT_PADDING_GUID_H__ + +#define EFI_FFS_SECTION_ALIGNMENT_PADDING_GUID \ + { \ + 0x04132C8D, 0x0A22, 0x4FA8, {0x82, 0x6E, 0x8B, 0xBF, 0xEF, 0xDB, 0x83, 0x6C } \ + } + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Guid/PcAnsi.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Guid/PcAnsi.h new file mode 100644 index 00000000..6f1cd564 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Guid/PcAnsi.h @@ -0,0 +1,52 @@ +/** @file + Terminal Device Path Vendor Guid. + @par Revision Reference: + GUIDs defined in UEFI 2.0 spec. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __PC_ANSI_H__ +#define __PC_ANSI_H__ + +#define EFI_PC_ANSI_GUID \ + { \ + 0xe0c14753, 0xf9be, 0x11d2, {0x9a, 0x0c, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +#define EFI_VT_100_GUID \ + { \ + 0xdfa66065, 0xb419, 0x11d3, {0x9a, 0x2d, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \ + } + +#define EFI_VT_100_PLUS_GUID \ + { \ + 0x7baec70b, 0x57e0, 0x4c76, {0x8e, 0x87, 0x2f, 0x9e, 0x28, 0x08, 0x83, 0x43 } \ + } + +#define EFI_VT_UTF8_GUID \ + { \ + 0xad15a0d6, 0x8bec, 0x4acf, {0xa0, 0x73, 0xd0, 0x1d, 0xe7, 0x7e, 0x2d, 0x88 } \ + } + +#define EFI_UART_DEVICE_PATH_GUID \ + { \ + 0x37499a9d, 0x542f, 0x4c89, {0xa0, 0x26, 0x35, 0xda, 0x14, 0x20, 0x94, 0xe4 } \ + } + +#define EFI_SAS_DEVICE_PATH_GUID \ + { \ + 0xd487ddb4, 0x008b, 0x11d9, {0xaf, 0xdc, 0x00, 0x10, 0x83, 0xff, 0xca, 0x4d } \ + } + +extern EFI_GUID gEfiPcAnsiGuid; +extern EFI_GUID gEfiVT100Guid; +extern EFI_GUID gEfiVT100PlusGuid; +extern EFI_GUID gEfiVTUTF8Guid; +extern EFI_GUID gEfiUartDevicePathGuid; +extern EFI_GUID gEfiSasDevicePathGuid; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Guid/PiFirmwareFileSystem.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Guid/PiFirmwareFileSystem.h new file mode 100644 index 00000000..c2ba64da --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Guid/PiFirmwareFileSystem.h @@ -0,0 +1,39 @@ +/** @file + Guid used to define the Firmware File System. See PI spec volume 3 for more + details. + + @par Revision Reference: + Guids defined in PI Spec Volume 3 + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __FIRMWARE_FILE_SYSTEM2_GUID_H__ +#define __FIRMWARE_FILE_SYSTEM2_GUID_H__ + +// +// GUIDs defined by the PI specification. +// +#define EFI_FIRMWARE_FILE_SYSTEM2_GUID \ + { \ + 0x8c8ce578, 0x8a3d, 0x4f1c, {0x99, 0x35, 0x89, 0x61, 0x85, 0xc3, 0x2d, 0xd3 } \ + } + +#define EFI_FIRMWARE_FILE_SYSTEM3_GUID \ + { \ + 0x5473c07a, 0x3dcb, 0x4dca, {0xbd, 0x6f, 0x1e, 0x96, 0x89, 0xe7, 0x34, 0x9a } \ + } + +#define EFI_FFS_VOLUME_TOP_FILE_GUID \ + { \ + 0x1BA0062E, 0xC779, 0x4582, {0x85, 0x66, 0x33, 0x6A, 0xE8, 0xF7, 0x8F, 0x09 } \ + } + +extern EFI_GUID gEfiFirmwareFileSystem2Guid; +extern EFI_GUID gEfiFirmwareFileSystem3Guid; +extern EFI_GUID gEfiFirmwareVolumeTopFileGuid; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Ia32/ProcessorBind.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Ia32/ProcessorBind.h new file mode 100644 index 00000000..983f7679 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Ia32/ProcessorBind.h @@ -0,0 +1,155 @@ +/** @file + Processor or Compiler specific defines and types for x64. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __PROCESSOR_BIND_H__ +#define __PROCESSOR_BIND_H__ + +// +// Define the processor type so other code can make processor based choices +// +#define MDE_CPU_IA32 + +// +// Make sure we are useing the correct packing rules per EFI specification +// +#ifndef __GNUC__ +#pragma pack() +#endif + +#if _MSC_EXTENSIONS + +// +// Disable warning that make it impossible to compile at /W4 +// This only works for Microsoft* tools +// + +// +// Disabling bitfield type checking warnings. +// +#pragma warning ( disable : 4214 ) + +// +// Disabling the unreferenced formal parameter warnings. +// +#pragma warning ( disable : 4100 ) + +// +// Disable slightly different base types warning as CHAR8 * can not be set +// to a constant string. +// +#pragma warning ( disable : 4057 ) + +// +// ASSERT(FALSE) or while (TRUE) are legal constructs so suppress this warning +// +#pragma warning ( disable : 4127 ) + + +#endif + + +#if !defined(__GNUC__) && (__STDC_VERSION__ < 199901L) + // + // No ANSI C 2000 stdint.h integer width declarations, so define equivalents + // + + #if _MSC_EXTENSIONS + + // + // use Microsoft* C compiler dependent integer width types + // + typedef unsigned __int64 UINT64; + typedef __int64 INT64; + typedef unsigned __int32 UINT32; + typedef __int32 INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef char INT8; + #else + + // + // Assume standard IA-32 alignment. + // BugBug: Need to check portability of long long + // + typedef unsigned long long UINT64; + typedef long long INT64; + typedef unsigned int UINT32; + typedef int INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef char INT8; + #endif + + #define UINT8_MAX 0xff + +#else + // + // Use ANSI C 2000 stdint.h integer width declarations + // + #include "stdint.h" + typedef uint8_t BOOLEAN; + typedef int8_t INT8; + typedef uint8_t UINT8; + typedef int16_t INT16; + typedef uint16_t UINT16; + typedef int32_t INT32; + typedef uint32_t UINT32; + typedef int64_t INT64; + typedef uint64_t UINT64; + typedef char CHAR8; + typedef uint16_t CHAR16; + +#endif + +typedef UINT32 UINTN; +typedef INT32 INTN; + + +// +// Processor specific defines +// +#define MAX_BIT 0x80000000 +#define MAX_2_BITS 0xC0000000 + +// +// Modifier to ensure that all protocol member functions and EFI intrinsics +// use the correct C calling convention. All protocol member functions and +// EFI intrinsics are required to modify their member functions with EFIAPI. +// +#if _MSC_EXTENSIONS + // + // Microsoft* compiler requires _EFIAPI usage, __cdecl is Microsoft* specific C. + // + #define EFIAPI __cdecl +#endif + +#ifdef __GNUC__ + #define EFIAPI __attribute__((cdecl)) +#endif + +// +// The Microsoft* C compiler can removed references to unreferenced data items +// if the /OPT:REF linker option is used. We defined a macro as this is a +// a non standard extension +// +#if _MSC_EXTENSIONS + #define GLOBAL_REMOVE_IF_UNREFERENCED __declspec(selectany) +#else + #define GLOBAL_REMOVE_IF_UNREFERENCED +#endif + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Acpi.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Acpi.h new file mode 100644 index 00000000..72577a22 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Acpi.h @@ -0,0 +1,117 @@ +/** @file + This file contains some basic ACPI definitions that are consumed by drivers + that do not care about ACPI versions. + + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _ACPI_H_ +#define _ACPI_H_ + +// +// Common table header, this prefaces all ACPI tables, including FACS, but +// excluding the RSD PTR structure +// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_COMMON_HEADER; + +// +// Common ACPI description table header. This structure prefaces most ACPI tables. +// +#pragma pack(1) + +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT8 Revision; + UINT8 Checksum; + UINT8 OemId[6]; + UINT64 OemTableId; + UINT32 OemRevision; + UINT32 CreatorId; + UINT32 CreatorRevision; +} EFI_ACPI_DESCRIPTION_HEADER; + +#pragma pack() +// +// Define for Pci Host Bridge Resource Allocation +// +#define ACPI_ADDRESS_SPACE_DESCRIPTOR 0x8A +#define ACPI_END_TAG_DESCRIPTOR 0x79 + +#define ACPI_ADDRESS_SPACE_TYPE_MEM 0x00 +#define ACPI_ADDRESS_SPACE_TYPE_IO 0x01 +#define ACPI_ADDRESS_SPACE_TYPE_BUS 0x02 + +// +// Power Management Timer frequency is fixed at 3.579545MHz +// +#define ACPI_TIMER_FREQUENCY 3579545 + +// +// Make sure structures match spec +// +#pragma pack(1) + +typedef struct { + UINT8 Desc; + UINT16 Len; + UINT8 ResType; + UINT8 GenFlag; + UINT8 SpecificFlag; + UINT64 AddrSpaceGranularity; + UINT64 AddrRangeMin; + UINT64 AddrRangeMax; + UINT64 AddrTranslationOffset; + UINT64 AddrLen; +} EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR; + +typedef struct { + UINT8 Desc; + UINT8 Checksum; +} EFI_ACPI_END_TAG_DESCRIPTOR; + +// +// General use definitions +// +#define EFI_ACPI_RESERVED_BYTE 0x00 +#define EFI_ACPI_RESERVED_WORD 0x0000 +#define EFI_ACPI_RESERVED_DWORD 0x00000000 +#define EFI_ACPI_RESERVED_QWORD 0x0000000000000000 + +// +// Resource Type Specific Flags +// Ref ACPI specification 6.4.3.5.5 +// +// Bit [0] : Write Status, _RW +// +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_READ_WRITE (1 << 0) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_READ_ONLY (0 << 0) +// +// Bit [2:1] : Memory Attributes, _MEM +// +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_NON_CACHEABLE (0 << 1) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE (1 << 1) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_WRITE_COMBINING (2 << 1) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE (3 << 1) +// +// Bit [4:3] : Memory Attributes, _MTP +// +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_ADDRESS_RANGE_MEMORY (0 << 3) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_ADDRESS_RANGE_RESERVED (1 << 3) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_ADDRESS_RANGE_ACPI (2 << 3) +#define EFI_APCI_MEMORY_RESOURCE_SPECIFIC_FLAG_ADDRESS_RANGE_NVS (3 << 3) +// +// Bit [5] : Memory to I/O Translation, _TTP +// +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_TYPE_TRANSLATION (1 << 5) +#define EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_TYPE_STATIC (0 << 5) + +#pragma pack() + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Acpi1_0.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Acpi1_0.h new file mode 100644 index 00000000..55b9168a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Acpi1_0.h @@ -0,0 +1,285 @@ +/** @file + ACPI 1.0b definitions from the ACPI Specification, revision 1.0b + + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _ACPI_1_0_H_ +#define _ACPI_1_0_H_ + +#include "IndustryStandard/Acpi.h" + +// +// Ensure proper structure formats +// +#pragma pack(1) +// +// ACPI 1.0b table structures +// +// +// Root System Description Pointer Structure +// +typedef struct { + UINT64 Signature; + UINT8 Checksum; + UINT8 OemId[6]; + UINT8 Reserved; + UINT32 RsdtAddress; +} EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER; + +// +// Root System Description Table +// No definition needed as it is a common description table header followed by a +// variable number of UINT32 table pointers. +// +// +// RSDT Revision (as defined in ACPI 1.0b spec.) +// +#define EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Fixed ACPI Description Table Structure (FADT) +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 FirmwareCtrl; + UINT32 Dsdt; + UINT8 IntModel; + UINT8 Reserved1; + UINT16 SciInt; + UINT32 SmiCmd; + UINT8 AcpiEnable; + UINT8 AcpiDisable; + UINT8 S4BiosReq; + UINT8 Reserved2; + UINT32 Pm1aEvtBlk; + UINT32 Pm1bEvtBlk; + UINT32 Pm1aCntBlk; + UINT32 Pm1bCntBlk; + UINT32 Pm2CntBlk; + UINT32 PmTmrBlk; + UINT32 Gpe0Blk; + UINT32 Gpe1Blk; + UINT8 Pm1EvtLen; + UINT8 Pm1CntLen; + UINT8 Pm2CntLen; + UINT8 PmTmLen; + UINT8 Gpe0BlkLen; + UINT8 Gpe1BlkLen; + UINT8 Gpe1Base; + UINT8 Reserved3; + UINT16 PLvl2Lat; + UINT16 PLvl3Lat; + UINT16 FlushSize; + UINT16 FlushStride; + UINT8 DutyOffset; + UINT8 DutyWidth; + UINT8 DayAlrm; + UINT8 MonAlrm; + UINT8 Century; + UINT8 Reserved4; + UINT8 Reserved5; + UINT8 Reserved6; + UINT32 Flags; +} EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE; + +// +// FADT Version (as defined in ACPI 1.0b spec.) +// +#define EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Fixed ACPI Description Table Fixed Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_1_0_WBINVD (1 << 0) +#define EFI_ACPI_1_0_WBINVD_FLUSH (1 << 1) +#define EFI_ACPI_1_0_PROC_C1 (1 << 2) +#define EFI_ACPI_1_0_P_LVL2_UP (1 << 3) +#define EFI_ACPI_1_0_PWR_BUTTON (1 << 4) +#define EFI_ACPI_1_0_SLP_BUTTON (1 << 5) +#define EFI_ACPI_1_0_FIX_RTC (1 << 6) +#define EFI_ACPI_1_0_RTC_S4 (1 << 7) +#define EFI_ACPI_1_0_TMR_VAL_EXT (1 << 8) +#define EFI_ACPI_1_0_DCK_CAP (1 << 9) + +#define EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION 0x0 +// +// Firmware ACPI Control Structure +// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT32 HardwareSignature; + UINT32 FirmwareWakingVector; + UINT32 GlobalLock; + UINT32 Flags; + UINT8 Reserved[40]; +} EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE; + +// +// Firmware Control Structure Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_1_0_S4BIOS_F (1 << 0) + +// +// Multiple APIC Description Table header definition. The rest of the table +// must be defined in a platform specific manner. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 LocalApicAddress; + UINT32 Flags; +} EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER; + +// +// MADT Revision (as defined in ACPI 1.0b spec.) +// +#define EFI_ACPI_1_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Multiple APIC Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_1_0_PCAT_COMPAT (1 << 0) + +// +// Multiple APIC Description Table APIC structure types +// All other values between 0x09 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC 0x00 +#define EFI_ACPI_1_0_IO_APIC 0x01 +#define EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE 0x02 +#define EFI_ACPI_1_0_NON_MASKABLE_INTERRUPT_SOURCE 0x03 +#define EFI_ACPI_1_0_LOCAL_APIC_NMI 0x04 + +// +// APIC Structure Definitions +// +// +// Processor Local APIC Structure Definition +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 ApicId; + UINT32 Flags; +} EFI_ACPI_1_0_PROCESSOR_LOCAL_APIC_STRUCTURE; + +// +// Local APIC Flags. All other bits are reserved and must be 0. +// +#define EFI_ACPI_1_0_LOCAL_APIC_ENABLED (1 << 0) + +// +// IO APIC Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 IoApicAddress; + UINT32 SystemVectorBase; +} EFI_ACPI_1_0_IO_APIC_STRUCTURE; + +// +// Interrupt Source Override Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Bus; + UINT8 Source; + UINT32 GlobalSystemInterruptVector; + UINT16 Flags; +} EFI_ACPI_1_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE; + +// +// Non-Maskable Interrupt Source Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 GlobalSystemInterruptVector; +} EFI_ACPI_1_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE; + +// +// Local APIC NMI Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT16 Flags; + UINT8 LocalApicInti; +} EFI_ACPI_1_0_LOCAL_APIC_NMI_STRUCTURE; + +// +// Smart Battery Description Table (SBST) +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 WarningEnergyLevel; + UINT32 LowEnergyLevel; + UINT32 CriticalEnergyLevel; +} EFI_ACPI_1_0_SMART_BATTERY_DESCRIPTION_TABLE; + +// +// Known table signatures +// +// +// "RSD PTR " Root System Description Pointer +// +#define EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE 0x2052545020445352ULL + +// +// "APIC" Multiple APIC Description Table +// +#define EFI_ACPI_1_0_APIC_SIGNATURE 0x43495041 + +// +// "DSDT" Differentiated System Description Table +// +#define EFI_ACPI_1_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445344 + +// +// "FACS" Firmware ACPI Control Structure +// +#define EFI_ACPI_1_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE 0x53434146 + +// +// "FACP" Fixed ACPI Description Table +// +#define EFI_ACPI_1_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE 0x50434146 + +// +// "PSDT" Persistent System Description Table +// +#define EFI_ACPI_1_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445350 + +// +// "RSDT" Root System Description Table +// +#define EFI_ACPI_1_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445352 + +// +// "SBST" Smart Battery Specification Table +// +#define EFI_ACPI_1_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE 0x54534253 + +// +// "SSDT" Secondary System Description Table +// +#define EFI_ACPI_1_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445353 + +#pragma pack() + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Acpi2_0.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Acpi2_0.h new file mode 100644 index 00000000..22ce87f8 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Acpi2_0.h @@ -0,0 +1,520 @@ +/** @file + ACPI 2.0 definitions from the ACPI Specification, revision 2.0 + + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _ACPI_2_0_H_ +#define _ACPI_2_0_H_ + +#include "IndustryStandard/Acpi.h" + +// +// Ensure proper structure formats +// +#pragma pack(1) +// +// ACPI Specification Revision +// +#define EFI_ACPI_2_0_REVISION 0x02 + +// +// BUGBUG: OEM values need to be moved somewhere else, probably read from data hub +// and produced by a platform specific driver. +// +// +// ACPI OEM ID +// +#define EFI_ACPI_2_0_OEM_ID "INTEL " +#define EFI_ACPI_2_0_OEM_TABLE_ID 0x5034303738543245 // "E2T8704P" +// +// ACPI OEM Revision +// +#define EFI_ACPI_2_0_OEM_REVISION 0x00000002 + +// +// ACPI table creator ID +// +#define EFI_ACPI_2_0_CREATOR_ID 0x5446534D // TBD "MSFT" +// +// ACPI table creator revision +// +#define EFI_ACPI_2_0_CREATOR_REVISION 0x01000013 // TBD +// +// ACPI 2.0 Generic Address Space definition +// +typedef struct { + UINT8 AddressSpaceId; + UINT8 RegisterBitWidth; + UINT8 RegisterBitOffset; + UINT8 Reserved; + UINT64 Address; +} EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE; + +// +// Generic Address Space Address IDs +// +#define EFI_ACPI_2_0_SYSTEM_MEMORY 0 +#define EFI_ACPI_2_0_SYSTEM_IO 1 +#define EFI_ACPI_2_0_PCI_CONFIGURATION_SPACE 2 +#define EFI_ACPI_2_0_EMBEDDED_CONTROLLER 3 +#define EFI_ACPI_2_0_SMBUS 4 +#define EFI_ACPI_2_0_FUNCTIONAL_FIXED_HARDWARE 0x7F + +// +// ACPI 2.0 table structures +// +// +// Root System Description Pointer Structure +// +typedef struct { + UINT64 Signature; + UINT8 Checksum; + UINT8 OemId[6]; + UINT8 Revision; + UINT32 RsdtAddress; + UINT32 Length; + UINT64 XsdtAddress; + UINT8 ExtendedChecksum; + UINT8 Reserved[3]; +} EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER; + +// +// RSD_PTR Revision (as defined in ACPI 2.0 spec.) +// +#define EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION 0x02 + +// +// Common table header, this prefaces all ACPI tables, including FACS, but +// excluding the RSD PTR structure +// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_2_0_COMMON_HEADER; + +// +// Root System Description Table +// No definition needed as it is a common description table header followed by a +// variable number of UINT32 table pointers. +// +// +// RSDT Revision (as defined in ACPI 2.0 spec.) +// +#define EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Extended System Description Table +// No definition needed as it is a common description table header followed by a +// variable number of UINT64 table pointers. +// +// +// XSDT Revision (as defined in ACPI 2.0 spec.) +// +#define EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Fixed ACPI Description Table Structure (FADT) +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 FirmwareCtrl; + UINT32 Dsdt; + UINT8 Reserved0; + UINT8 PreferredPmProfile; + UINT16 SciInt; + UINT32 SmiCmd; + UINT8 AcpiEnable; + UINT8 AcpiDisable; + UINT8 S4BiosReq; + UINT8 PstateCnt; + UINT32 Pm1aEvtBlk; + UINT32 Pm1bEvtBlk; + UINT32 Pm1aCntBlk; + UINT32 Pm1bCntBlk; + UINT32 Pm2CntBlk; + UINT32 PmTmrBlk; + UINT32 Gpe0Blk; + UINT32 Gpe1Blk; + UINT8 Pm1EvtLen; + UINT8 Pm1CntLen; + UINT8 Pm2CntLen; + UINT8 PmTmrLen; + UINT8 Gpe0BlkLen; + UINT8 Gpe1BlkLen; + UINT8 Gpe1Base; + UINT8 CstCnt; + UINT16 PLvl2Lat; + UINT16 PLvl3Lat; + UINT16 FlushSize; + UINT16 FlushStride; + UINT8 DutyOffset; + UINT8 DutyWidth; + UINT8 DayAlrm; + UINT8 MonAlrm; + UINT8 Century; + UINT16 IaPcBootArch; + UINT8 Reserved1; + UINT32 Flags; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE ResetReg; + UINT8 ResetValue; + UINT8 Reserved2[3]; + UINT64 XFirmwareCtrl; + UINT64 XDsdt; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPm1aEvtBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPm1bEvtBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPm1aCntBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPm1bCntBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPm2CntBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XPmTmrBlk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XGpe0Blk; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE XGpe1Blk; +} EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE; + +// +// FADT Version (as defined in ACPI 2.0 spec.) +// +#define EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION 0x03 + +// +// Fixed ACPI Description Table Boot Architecture Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_2_0_LEGACY_DEVICES (1 << 0) +#define EFI_ACPI_2_0_8042 (1 << 1) + +// +// Fixed ACPI Description Table Fixed Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_2_0_WBINVD (1 << 0) +#define EFI_ACPI_2_0_WBINVD_FLUSH (1 << 1) +#define EFI_ACPI_2_0_PROC_C1 (1 << 2) +#define EFI_ACPI_2_0_P_LVL2_UP (1 << 3) +#define EFI_ACPI_2_0_PWR_BUTTON (1 << 4) +#define EFI_ACPI_2_0_SLP_BUTTON (1 << 5) +#define EFI_ACPI_2_0_FIX_RTC (1 << 6) +#define EFI_ACPI_2_0_RTC_S4 (1 << 7) +#define EFI_ACPI_2_0_TMR_VAL_EXT (1 << 8) +#define EFI_ACPI_2_0_DCK_CAP (1 << 9) +#define EFI_ACPI_2_0_RESET_REG_SUP (1 << 10) +#define EFI_ACPI_2_0_SEALED_CASE (1 << 11) +#define EFI_ACPI_2_0_HEADLESS (1 << 12) +#define EFI_ACPI_2_0_CPU_SW_SLP (1 << 13) + +// +// Firmware ACPI Control Structure +// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT32 HardwareSignature; + UINT32 FirmwareWakingVector; + UINT32 GlobalLock; + UINT32 Flags; + UINT64 XFirmwareWakingVector; + UINT8 Version; + UINT8 Reserved[31]; +} EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE; + +// +// FACS Version (as defined in ACPI 2.0 spec.) +// +#define EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION 0x01 + +// +// Firmware Control Structure Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_2_0_S4BIOS_F (1 << 0) + +// +// Multiple APIC Description Table header definition. The rest of the table +// must be defined in a platform specific manner. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 LocalApicAddress; + UINT32 Flags; +} EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER; + +// +// MADT Revision (as defined in ACPI 2.0 spec.) +// +#define EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Multiple APIC Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_2_0_PCAT_COMPAT (1 << 0) + +// +// Multiple APIC Description Table APIC structure types +// All other values between 0x09 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC 0x00 +#define EFI_ACPI_2_0_IO_APIC 0x01 +#define EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE 0x02 +#define EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE 0x03 +#define EFI_ACPI_2_0_LOCAL_APIC_NMI 0x04 +#define EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE 0x05 +#define EFI_ACPI_2_0_IO_SAPIC 0x06 +#define EFI_ACPI_2_0_PROCESSOR_LOCAL_SAPIC 0x07 +#define EFI_ACPI_2_0_PLATFORM_INTERRUPT_SOURCES 0x08 + +// +// APIC Structure Definitions +// +// +// Processor Local APIC Structure Definition +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 ApicId; + UINT32 Flags; +} EFI_ACPI_2_0_PROCESSOR_LOCAL_APIC_STRUCTURE; + +// +// Local APIC Flags. All other bits are reserved and must be 0. +// +#define EFI_ACPI_2_0_LOCAL_APIC_ENABLED (1 << 0) + +// +// IO APIC Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 IoApicAddress; + UINT32 GlobalSystemInterruptBase; +} EFI_ACPI_2_0_IO_APIC_STRUCTURE; + +// +// Interrupt Source Override Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Bus; + UINT8 Source; + UINT32 GlobalSystemInterrupt; + UINT16 Flags; +} EFI_ACPI_2_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE; + +// +// Non-Maskable Interrupt Source Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 GlobalSystemInterrupt; +} EFI_ACPI_2_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE; + +// +// Local APIC NMI Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT16 Flags; + UINT8 LocalApicLint; +} EFI_ACPI_2_0_LOCAL_APIC_NMI_STRUCTURE; + +// +// Local APIC Address Override Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT64 LocalApicAddress; +} EFI_ACPI_2_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE; + +// +// IO SAPIC Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 GlobalSystemInterruptBase; + UINT64 IoSapicAddress; +} EFI_ACPI_2_0_IO_SAPIC_STRUCTURE; + +// +// Local SAPIC Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 LocalSapicId; + UINT8 LocalSapicEid; + UINT8 Reserved[3]; + UINT32 Flags; +} EFI_ACPI_2_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE; + +// +// Platform Interrupt Sources Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 Reserved; +} EFI_ACPI_2_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE; + +// +// Smart Battery Description Table (SBST) +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 WarningEnergyLevel; + UINT32 LowEnergyLevel; + UINT32 CriticalEnergyLevel; +} EFI_ACPI_2_0_SMART_BATTERY_DESCRIPTION_TABLE; + +// +// SBST Version (as defined in ACPI 2.0 spec.) +// +#define EFI_ACPI_2_0_SMART_BATTERY_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Embedded Controller Boot Resources Table (ECDT) +// The table is followed by a null terminated ASCII string that contains +// a fully qualified reference to the name space object. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE EcControl; + EFI_ACPI_2_0_GENERIC_ADDRESS_STRUCTURE EcData; + UINT32 Uid; + UINT8 GpeBit; +} EFI_ACPI_2_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE; + +// +// ECDT Version (as defined in ACPI 2.0 spec.) +// +#define EFI_ACPI_2_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_REVISION 0x01 + +// +// Known table signatures +// +// +// "RSD PTR " Root System Description Pointer +// +#define EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE 0x2052545020445352 + +// +// "SPIC" Multiple SAPIC Description Table +// +// BUGBUG: Don't know where this came from except SR870BN4 uses it. +// #define EFI_ACPI_2_0_MULTIPLE_SAPIC_DESCRIPTION_TABLE_SIGNATURE 0x43495053 +// +#define EFI_ACPI_2_0_MULTIPLE_SAPIC_DESCRIPTION_TABLE_SIGNATURE 0x43495041 + +// +// "BOOT" MS Simple Boot Spec +// +#define EFI_ACPI_2_0_SIMPLE_BOOT_FLAG_TABLE_SIGNATURE 0x544F4F42 + +// +// "DBGP" MS Bebug Port Spec +// +#define EFI_ACPI_2_0_DEBUG_PORT_TABLE_SIGNATURE 0x50474244 + +// +// "DSDT" Differentiated System Description Table +// +#define EFI_ACPI_2_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445344 + +// +// "ECDT" Embedded Controller Boot Resources Table +// +#define EFI_ACPI_2_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_SIGNATURE 0x54444345 + +// +// "ETDT" Event Timer Description Table +// +#define EFI_ACPI_2_0_EVENT_TIMER_DESCRIPTION_TABLE_SIGNATURE 0x54445445 + +// +// "FACS" Firmware ACPI Control Structure +// +#define EFI_ACPI_2_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE 0x53434146 + +// +// "FACP" Fixed ACPI Description Table +// +#define EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE 0x50434146 + +// +// "APIC" Multiple APIC Description Table +// +#define EFI_ACPI_2_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE 0x43495041 + +// +// "PSDT" Persistent System Description Table +// +#define EFI_ACPI_2_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445350 + +// +// "RSDT" Root System Description Table +// +#define EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445352 + +// +// "SBST" Smart Battery Specification Table +// +#define EFI_ACPI_2_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE 0x54534253 + +// +// "SLIT" System Locality Information Table +// +#define EFI_ACPI_2_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE 0x54494C53 + +// +// "SPCR" Serial Port Console Redirection Table +// +#define EFI_ACPI_2_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE 0x52435053 + +// +// "SRAT" Static Resource Affinity Table +// +#define EFI_ACPI_2_0_STATIC_RESOURCE_AFFINITY_TABLE_SIGNATURE 0x54415253 + +// +// "SSDT" Secondary System Description Table +// +#define EFI_ACPI_2_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445353 + +// +// "SPMI" Server Platform Management Interface Table +// +#define EFI_ACPI_2_0_SERVER_PLATFORM_MANAGEMENT_INTERFACE_SIGNATURE 0x494D5053 + +// +// "XSDT" Extended System Description Table +// +#define EFI_ACPI_2_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445358 + +#pragma pack() + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Acpi3_0.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Acpi3_0.h new file mode 100644 index 00000000..3fd85f60 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Acpi3_0.h @@ -0,0 +1,668 @@ +/** @file + ACPI 3.0 definitions from the ACPI Specification Revision 3.0 September 2, 2004 + + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _ACPI_3_0_H_ +#define _ACPI_3_0_H_ + +#include "IndustryStandard/Acpi.h" + +// +// Ensure proper structure formats +// +#pragma pack(1) +// +// ACPI Specification Revision +// +#define EFI_ACPI_3_0_REVISION 0x03 // BUGBUG: Not in spec yet. +// +// BUGBUG: OEM values need to be moved somewhere else, probably read from data hub +// and produced by a platform specific driver. +// +// +// ACPI 3.0 Generic Address Space definition +// +typedef struct { + UINT8 AddressSpaceId; + UINT8 RegisterBitWidth; + UINT8 RegisterBitOffset; + UINT8 AccessSize; + UINT64 Address; +} EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE; + +// +// Generic Address Space Address IDs +// +#define EFI_ACPI_3_0_SYSTEM_MEMORY 0 +#define EFI_ACPI_3_0_SYSTEM_IO 1 +#define EFI_ACPI_3_0_PCI_CONFIGURATION_SPACE 2 +#define EFI_ACPI_3_0_EMBEDDED_CONTROLLER 3 +#define EFI_ACPI_3_0_SMBUS 4 +#define EFI_ACPI_3_0_FUNCTIONAL_FIXED_HARDWARE 0x7F + +// +// Generic Address Space Access Sizes +// +#define EFI_ACPI_3_0_UNDEFINED 0 +#define EFI_ACPI_3_0_BYTE 1 +#define EFI_ACPI_3_0_WORD 2 +#define EFI_ACPI_3_0_DWORD 3 +#define EFI_ACPI_3_0_QWORD 4 + +// +// ACPI 3.0 table structures +// +// +// Root System Description Pointer Structure +// +typedef struct { + UINT64 Signature; + UINT8 Checksum; + UINT8 OemId[6]; + UINT8 Revision; + UINT32 RsdtAddress; + UINT32 Length; + UINT64 XsdtAddress; + UINT8 ExtendedChecksum; + UINT8 Reserved[3]; +} EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER; + +// +// RSD_PTR Revision (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION 0x02 // ACPISpec30 (Revision 3.0 September 2, 2004) says current value is 2 +// +// Common table header, this prefaces all ACPI tables, including FACS, but +// excluding the RSD PTR structure +// +typedef struct { + UINT32 Signature; + UINT32 Length; +} EFI_ACPI_3_0_COMMON_HEADER; + +// +// Root System Description Table +// No definition needed as it is a common description table header followed by a +// variable number of UINT32 table pointers. +// +// +// RSDT Revision (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Extended System Description Table +// No definition needed as it is a common description table header followed by a +// variable number of UINT64 table pointers. +// +// +// XSDT Revision (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Fixed ACPI Description Table Structure (FADT) +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 FirmwareCtrl; + UINT32 Dsdt; + UINT8 Reserved0; + UINT8 PreferredPmProfile; + UINT16 SciInt; + UINT32 SmiCmd; + UINT8 AcpiEnable; + UINT8 AcpiDisable; + UINT8 S4BiosReq; + UINT8 PstateCnt; + UINT32 Pm1aEvtBlk; + UINT32 Pm1bEvtBlk; + UINT32 Pm1aCntBlk; + UINT32 Pm1bCntBlk; + UINT32 Pm2CntBlk; + UINT32 PmTmrBlk; + UINT32 Gpe0Blk; + UINT32 Gpe1Blk; + UINT8 Pm1EvtLen; + UINT8 Pm1CntLen; + UINT8 Pm2CntLen; + UINT8 PmTmrLen; + UINT8 Gpe0BlkLen; + UINT8 Gpe1BlkLen; + UINT8 Gpe1Base; + UINT8 CstCnt; + UINT16 PLvl2Lat; + UINT16 PLvl3Lat; + UINT16 FlushSize; + UINT16 FlushStride; + UINT8 DutyOffset; + UINT8 DutyWidth; + UINT8 DayAlrm; + UINT8 MonAlrm; + UINT8 Century; + UINT16 IaPcBootArch; + UINT8 Reserved1; + UINT32 Flags; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE ResetReg; + UINT8 ResetValue; + UINT8 Reserved2[3]; + UINT64 XFirmwareCtrl; + UINT64 XDsdt; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPm1aEvtBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPm1bEvtBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPm1aCntBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPm1bCntBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPm2CntBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XPmTmrBlk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XGpe0Blk; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE XGpe1Blk; +} EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE; + +// +// FADT Version (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_REVISION 0x04 + +// +// Fixed ACPI Description Table Preferred Power Management Profile +// +#define EFI_ACPI_3_0_PM_PROFILE_UNSPECIFIED 0 +#define EFI_ACPI_3_0_PM_PROFILE_DESKTOP 1 +#define EFI_ACPI_3_0_PM_PROFILE_MOBILE 2 +#define EFI_ACPI_3_0_PM_PROFILE_WORKSTATION 3 +#define EFI_ACPI_3_0_PM_PROFILE_ENTERPRISE_SERVER 4 +#define EFI_ACPI_3_0_PM_PROFILE_SOHO_SERVER 5 +#define EFI_ACPI_3_0_PM_PROFILE_APPLIANCE_PC 6 +#define EFI_ACPI_3_0_PM_PROFILE_PERFORMANCE_SERVER 7 + +// +// Fixed ACPI Description Table Boot Architecture Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_3_0_LEGACY_DEVICES (1 << 0) +#define EFI_ACPI_3_0_8042 (1 << 1) +#define EFI_ACPI_3_0_VGA_NOT_PRESENT (1 << 2) +#define EFI_ACPI_3_0_MSI_NOT_SUPPORTED (1 << 3) +// +// Fixed ACPI Description Table Fixed Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_3_0_WBINVD (1 << 0) +#define EFI_ACPI_3_0_WBINVD_FLUSH (1 << 1) +#define EFI_ACPI_3_0_PROC_C1 (1 << 2) +#define EFI_ACPI_3_0_P_LVL2_UP (1 << 3) +#define EFI_ACPI_3_0_PWR_BUTTON (1 << 4) +#define EFI_ACPI_3_0_SLP_BUTTON (1 << 5) +#define EFI_ACPI_3_0_FIX_RTC (1 << 6) +#define EFI_ACPI_3_0_RTC_S4 (1 << 7) +#define EFI_ACPI_3_0_TMR_VAL_EXT (1 << 8) +#define EFI_ACPI_3_0_DCK_CAP (1 << 9) +#define EFI_ACPI_3_0_RESET_REG_SUP (1 << 10) +#define EFI_ACPI_3_0_SEALED_CASE (1 << 11) +#define EFI_ACPI_3_0_HEADLESS (1 << 12) +#define EFI_ACPI_3_0_CPU_SW_SLP (1 << 13) +#define EFI_ACPI_3_0_PCI_EXP_WAK (1 << 14) +#define EFI_ACPI_3_0_USE_PLATFORM_CLOCK (1 << 15) +#define EFI_ACPI_3_0_S4_RTC_STS_VALID (1 << 16) +#define EFI_ACPI_3_0_REMOTE_POWER_ON_CAPABLE (1 << 17) +#define EFI_ACPI_3_0_FORCE_APIC_CLUSTER_MODEL (1 << 18) +#define EFI_ACPI_3_0_FORCE_APIC_PHYSICAL_DESTINATION_MODE (1 << 19) + +// +// Firmware ACPI Control Structure +// +typedef struct { + UINT32 Signature; + UINT32 Length; + UINT32 HardwareSignature; + UINT32 FirmwareWakingVector; + UINT32 GlobalLock; + UINT32 Flags; + UINT64 XFirmwareWakingVector; + UINT8 Version; + UINT8 Reserved[31]; +} EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE; + +// +// FACS Version (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_VERSION 0x01 + +// +// Firmware Control Structure Feature Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_3_0_S4BIOS_F (1 << 0) + +// +// Differentiated System Description Table, +// Secondary System Description Table +// and Persistent System Description Table, +// no definition needed as they are common description table header followed by a +// definition block. +// +#define EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 +#define EFI_ACPI_3_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_REVISION 0x02 + +// +// Multiple APIC Description Table header definition. The rest of the table +// must be defined in a platform specific manner. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 LocalApicAddress; + UINT32 Flags; +} EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_HEADER; + +// +// MADT Revision (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_REVISION 0x02 + +// +// Multiple APIC Flags +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_3_0_PCAT_COMPAT (1 << 0) + +// +// Multiple APIC Description Table APIC structure types +// All other values between 0x09 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC 0x00 +#define EFI_ACPI_3_0_IO_APIC 0x01 +#define EFI_ACPI_3_0_INTERRUPT_SOURCE_OVERRIDE 0x02 +#define EFI_ACPI_3_0_NON_MASKABLE_INTERRUPT_SOURCE 0x03 +#define EFI_ACPI_3_0_LOCAL_APIC_NMI 0x04 +#define EFI_ACPI_3_0_LOCAL_APIC_ADDRESS_OVERRIDE 0x05 +#define EFI_ACPI_3_0_IO_SAPIC 0x06 +#define EFI_ACPI_3_0_LOCAL_SAPIC 0x07 +#define EFI_ACPI_3_0_PLATFORM_INTERRUPT_SOURCES 0x08 + +// +// APIC Structure Definitions +// +// +// Processor Local APIC Structure Definition +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 ApicId; + UINT32 Flags; +} EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC_STRUCTURE; + +// +// Local APIC Flags. All other bits are reserved and must be 0. +// +#define EFI_ACPI_3_0_LOCAL_APIC_ENABLED (1 << 0) + +// +// IO APIC Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 IoApicAddress; + UINT32 GlobalSystemInterruptBase; +} EFI_ACPI_3_0_IO_APIC_STRUCTURE; + +// +// Interrupt Source Override Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 Bus; + UINT8 Source; + UINT32 GlobalSystemInterrupt; + UINT16 Flags; +} EFI_ACPI_3_0_INTERRUPT_SOURCE_OVERRIDE_STRUCTURE; + +// +// Platform Interrupt Sources Structure Definition +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; + UINT8 CpeiProcessorOverride; + UINT8 Reserved[31]; +} EFI_ACPI_3_0_PLATFORM_INTERRUPT_APIC_STRUCTURE; + +// +// MPS INTI flags. +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_3_0_POLARITY (3 << 0) +#define EFI_ACPI_3_0_TRIGGER_MODE (3 << 2) + +// +// Non-Maskable Interrupt Source Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT32 GlobalSystemInterrupt; +} EFI_ACPI_3_0_NON_MASKABLE_INTERRUPT_SOURCE_STRUCTURE; + +// +// Local APIC NMI Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT16 Flags; + UINT8 LocalApicLint; +} EFI_ACPI_3_0_LOCAL_APIC_NMI_STRUCTURE; + +// +// Local APIC Address Override Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Reserved; + UINT64 LocalApicAddress; +} EFI_ACPI_3_0_LOCAL_APIC_ADDRESS_OVERRIDE_STRUCTURE; + +// +// IO SAPIC Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 IoApicId; + UINT8 Reserved; + UINT32 GlobalSystemInterruptBase; + UINT64 IoSapicAddress; +} EFI_ACPI_3_0_IO_SAPIC_STRUCTURE; + +// +// Local SAPIC Structure +// This struct followed by a null-terminated ASCII string - ACPI Processor UID String +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 AcpiProcessorId; + UINT8 LocalSapicId; + UINT8 LocalSapicEid; + UINT8 Reserved[3]; + UINT32 Flags; + UINT32 ACPIProcessorUIDValue; +} EFI_ACPI_3_0_PROCESSOR_LOCAL_SAPIC_STRUCTURE; + +// +// Platform Interrupt Sources Structure +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT16 Flags; + UINT8 InterruptType; + UINT8 ProcessorId; + UINT8 ProcessorEid; + UINT8 IoSapicVector; + UINT32 GlobalSystemInterrupt; + UINT32 PlatformInterruptSourceFlags; +} EFI_ACPI_3_0_PLATFORM_INTERRUPT_SOURCES_STRUCTURE; + +// +// Platform Interrupt Source Flags. +// All other bits are reserved and must be set to 0. +// +#define EFI_ACPI_3_0_CPEI_PROCESSOR_OVERRIDE (1 << 0) + +// +// Smart Battery Description Table (SBST) +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 WarningEnergyLevel; + UINT32 LowEnergyLevel; + UINT32 CriticalEnergyLevel; +} EFI_ACPI_3_0_SMART_BATTERY_DESCRIPTION_TABLE; + +// +// SBST Version (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_SMART_BATTERY_DESCRIPTION_TABLE_REVISION 0x01 + +// +// Embedded Controller Boot Resources Table (ECDT) +// The table is followed by a null terminated ASCII string that contains +// a fully qualified reference to the name space object. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE EcControl; + EFI_ACPI_3_0_GENERIC_ADDRESS_STRUCTURE EcData; + UINT32 Uid; + UINT8 GpeBit; +} EFI_ACPI_3_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE; + +// +// ECDT Version (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_REVISION 0x01 + +// +// System Resource Affinity Table (SRAT. The rest of the table +// must be defined in a platform specific manner. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT32 Reserved1; // Must be set to 1 + UINT64 Reserved2; +} EFI_ACPI_3_0_SYSTEM_RESOURCE_AFFINITY_TABLE_HEADER; + +// +// SRAT Version (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_SYSTEM_RESOURCE_AFFINITY_TABLE_REVISION 0x02 + +// +// SRAT structure types. +// All other values between 0x02 an 0xFF are reserved and +// will be ignored by OSPM. +// +#define EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY 0x00 +#define EFI_ACPI_3_0_MEMORY_AFFINITY 0x01 + +// +// Processor Local APIC/SAPIC Affinity Structure Definition +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT8 ProximityDomain7To0; + UINT8 ApicId; + UINT32 Flags; + UINT8 LocalSapicEid; + UINT8 ProximityDomain31To8[3]; + UINT8 Reserved[4]; +} EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC_SAPIC_AFFINITY_STRUCTURE; + +// +// Local APIC/SAPIC Flags. All other bits are reserved and must be 0. +// +#define EFI_ACPI_3_0_PROCESSOR_LOCAL_APIC_SAPIC_ENABLED (1 << 0) + +// +// Memory Affinity Structure Definition +// +typedef struct { + UINT8 Type; + UINT8 Length; + UINT32 ProximityDomain; + UINT16 Reserved1; + UINT32 AddressBaseLow; + UINT32 AddressBaseHigh; + UINT32 LengthLow; + UINT32 LengthHigh; + UINT32 Reserved2; + UINT32 Flags; + UINT64 Reserved3; +} EFI_ACPI_3_0_MEMORY_AFFINITY_STRUCTURE; + +// +// Memory Flags. All other bits are reserved and must be 0. +// +#define EFI_ACPI_3_0_MEMORY_ENABLED (1 << 0) +#define EFI_ACPI_3_0_MEMORY_HOT_PLUGGABLE (1 << 1) +#define EFI_ACPI_3_0_MEMORY_NONVOLATILE (1 << 2) + +// +// System Locality Distance Information Table (SLIT). +// The rest of the table is a matrix. +// +typedef struct { + EFI_ACPI_DESCRIPTION_HEADER Header; + UINT64 NumberOfSystemLocalities; +} EFI_ACPI_3_0_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_HEADER; + +// +// SLIT Version (as defined in ACPI 3.0 spec.) +// +#define EFI_ACPI_3_0_SYSTEM_LOCALITY_DISTANCE_INFORMATION_TABLE_REVISION 0x01 + +// +// Known table signatures +// +// +// "RSD PTR " Root System Description Pointer +// +#define EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_POINTER_SIGNATURE 0x2052545020445352ULL + +// +// "APIC" Multiple APIC Description Table +// +#define EFI_ACPI_3_0_MULTIPLE_APIC_DESCRIPTION_TABLE_SIGNATURE 0x43495041 + +// +// "DSDT" Differentiated System Description Table +// +#define EFI_ACPI_3_0_DIFFERENTIATED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445344 + +// +// "ECDT" Embedded Controller Boot Resources Table +// +#define EFI_ACPI_3_0_EMBEDDED_CONTROLLER_BOOT_RESOURCES_TABLE_SIGNATURE 0x54444345 + +// +// "FACP" Fixed ACPI Description Table +// +#define EFI_ACPI_3_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE 0x50434146 + +// +// "FACS" Firmware ACPI Control Structure +// +#define EFI_ACPI_3_0_FIRMWARE_ACPI_CONTROL_STRUCTURE_SIGNATURE 0x53434146 + +// +// "PSDT" Persistent System Description Table +// +#define EFI_ACPI_3_0_PERSISTENT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445350 + +// +// "RSDT" Root System Description Table +// +#define EFI_ACPI_3_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445352 + +// +// "SBST" Smart Battery Specification Table +// +#define EFI_ACPI_3_0_SMART_BATTERY_SPECIFICATION_TABLE_SIGNATURE 0x54534253 + +// +// "SLIT" System Locality Information Table +// +#define EFI_ACPI_3_0_SYSTEM_LOCALITY_INFORMATION_TABLE_SIGNATURE 0x54494C53 + +// +// "SRAT" System Resource Affinity Table +// +#define EFI_ACPI_3_0_SYSTEM_RESOURCE_AFFINITY_TABLE_SIGNATURE 0x54415253 + +// +// "SSDT" Secondary System Description Table +// +#define EFI_ACPI_3_0_SECONDARY_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445353 + +// +// "XSDT" Extended System Description Table +// +#define EFI_ACPI_3_0_EXTENDED_SYSTEM_DESCRIPTION_TABLE_SIGNATURE 0x54445358 + +// +// "BOOT" MS Simple Boot Spec +// +#define EFI_ACPI_3_0_SIMPLE_BOOT_FLAG_TABLE_SIGNATURE 0x544F4F42 + +// +// "CPEP" Corrected Platform Error Polling Table +// See +// +#define EFI_ACPI_3_0_CORRECTED_PLATFORM_ERROR_POLLING_TABLE_SIGNATURE 0x50455043 + +// +// "DBGP" MS Debug Port Spec +// +#define EFI_ACPI_3_0_DEBUG_PORT_TABLE_SIGNATURE 0x50474244 + +// +// "ETDT" Event Timer Description Table +// +#define EFI_ACPI_3_0_EVENT_TIMER_DESCRIPTION_TABLE_SIGNATURE 0x54445445 + +// +// "HPET" IA-PC High Precision Event Timer Table +// +#define EFI_ACPI_3_0_HIGH_PRECISION_EVENT_TIMER_TABLE_SIGNATURE 0x54455048 + +// +// "MCFG" PCI Express Memory Mapped Configuration Space Base Address Description Table +// +#define EFI_ACPI_3_0_PCI_EXPRESS_MEMORY_MAPPED_CONFIGURATION_SPACE_BASE_ADDRESS_DESCRIPTION_TABLE_SIGNATURE 0x4746434D + +// +// "SPCR" Serial Port Console Redirection Table +// +#define EFI_ACPI_3_0_SERIAL_PORT_CONSOLE_REDIRECTION_TABLE_SIGNATURE 0x52435053 + +// +// "SPMI" Server Platform Management Interface Table +// +#define EFI_ACPI_3_0_SERVER_PLATFORM_MANAGEMENT_INTERFACE_TABLE_SIGNATURE 0x494D5053 + +// +// "TCPA" Trusted Computing Platform Alliance Capabilities Table +// +#define EFI_ACPI_3_0_TRUSTED_COMPUTING_PLATFORM_ALLIANCE_CAPABILITIES_TABLE_SIGNATURE 0x41504354 + +// +// "WDRT" Watchdog Resource Table +// +#define EFI_ACPI_3_0_WATCHDOG_RESOURCE_TABLE_SIGNATURE 0x54524457 + +#pragma pack() + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Bluetooth.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Bluetooth.h new file mode 100644 index 00000000..0e8c5227 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/Bluetooth.h @@ -0,0 +1,56 @@ +/** @file + This file contains the Bluetooth definitions that are consumed by drivers. + These definitions are from Bluetooth Core Specification Version 4.0 June, 2010 + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _BLUETOOTH_H_ +#define _BLUETOOTH_H_ + +#pragma pack(1) + +/// +/// BLUETOOTH_ADDRESS +/// +typedef struct { + /// + /// 48bit Bluetooth device address. + /// + UINT8 Address[6]; +} BLUETOOTH_ADDRESS; + +/// +/// BLUETOOTH_CLASS_OF_DEVICE. See Bluetooth specification for detail. +/// +typedef struct { + UINT8 FormatType:2; + UINT8 MinorDeviceClass: 6; + UINT16 MajorDeviceClass: 5; + UINT16 MajorServiceClass:11; +} BLUETOOTH_CLASS_OF_DEVICE; + +/// +/// BLUETOOTH_LE_ADDRESS +/// +typedef struct { + /// + /// 48-bit Bluetooth device address + /// + UINT8 Address[6]; + /// + /// 0x00 - Public Device Address + /// 0x01 - Random Device Address + /// + UINT8 Type; +} BLUETOOTH_LE_ADDRESS; + +#pragma pack() + +#define BLUETOOTH_HCI_COMMAND_LOCAL_READABLE_NAME_MAX_SIZE 248 + +#define BLUETOOTH_HCI_LINK_KEY_SIZE 16 + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/EfiPci.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/EfiPci.h new file mode 100644 index 00000000..27fa8bd4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/EfiPci.h @@ -0,0 +1,51 @@ +/** @file + Support for EFI PCI specification. + + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFI_PCI_H_ +#define _EFI_PCI_H_ + +//#include "pci22.h" +//#include "pci23.h" +//#include "pci30.h" + +#pragma pack(push, 1) + +typedef struct { + UINT8 Register; + UINT8 Function; + UINT8 Device; + UINT8 Bus; + UINT8 Reserved[4]; +} DEFIO_PCI_ADDR; + +#define EFI_ROOT_BRIDGE_LIST 'eprb' +#define EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE 0x0EF1 + +typedef struct { + UINT16 Signature; // 0xaa55 + UINT16 InitializationSize; + UINT32 EfiSignature; // 0x0EF1 + UINT16 EfiSubsystem; + UINT16 EfiMachineType; + UINT16 CompressionType; + UINT8 Reserved[8]; + UINT16 EfiImageHeaderOffset; + UINT16 PcirOffset; +} EFI_PCI_EXPANSION_ROM_HEADER; + +typedef union { + UINT8 *Raw; + PCI_EXPANSION_ROM_HEADER *Generic; + EFI_PCI_EXPANSION_ROM_HEADER *Efi; + EFI_LEGACY_EXPANSION_ROM_HEADER *PcAt; +} EFI_PCI_ROM_HEADER; + +#pragma pack(pop) + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h new file mode 100644 index 00000000..5b90a229 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/MemoryMappedConfigurationSpaceAccessTable.h @@ -0,0 +1,39 @@ +/** @file + ACPI memory mapped configuration space access table definition, defined at + in the PCI Firmware Specification, version 3.0 draft version 0.5. + Specification is available at http://www.pcisig.com. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_H_ +#define _MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_H_ + +// +// Ensure proper structure formats +// +#pragma pack(1) +// +// Memory Mapped Configuration Space Access Table (MCFG) +// This table is a basic description table header followed by +// a number of base address allocation structures. +// +typedef struct { + UINT64 BaseAddress; + UINT16 PciSegmentGroupNumber; + UINT8 StartBusNumber; + UINT8 EndBusNumber; + UINT32 Reserved; +} EFI_ACPI_MEMORY_MAPPED_ENHANCED_CONFIGURATION_SPACE_BASE_ADDRESS_ALLOCATION_STRUCTURE; + +// +// MCFG Revision (defined in spec) +// +#define EFI_ACPI_MEMORY_MAPPED_CONFIGURATION_SPACE_ACCESS_TABLE_REVISION 0x01 + +#pragma pack() + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/PeImage.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/PeImage.h new file mode 100644 index 00000000..36039220 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/PeImage.h @@ -0,0 +1,768 @@ +/** @file + EFI image format for PE32+. Please note some data structures are different + for IA-32 and Itanium-based images, look for UINTN and the #ifdef EFI_IA64 + + @bug Fix text - doc as defined in MSFT EFI specification. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+ Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __PE_IMAGE_H__ +#define __PE_IMAGE_H__ + +// +// PE32+ Subsystem type for EFI images +// +#define EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION 10 +#define EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER 11 +#define EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER 12 +#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 + +// +// BugBug: Need to get a real answer for this problem. This is not in the +// PE specification. +// +// A SAL runtime driver does not get fixed up when a transition to +// virtual mode is made. In all other cases it should be treated +// like a EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER image +// +#define EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER 13 + +// +// PE32+ Machine type for EFI images +// +#define IMAGE_FILE_MACHINE_I386 0x014c +#define IMAGE_FILE_MACHINE_EBC 0x0EBC +#define IMAGE_FILE_MACHINE_X64 0x8664 +#define IMAGE_FILE_MACHINE_ARM 0x01c0 // Thumb only +#define IMAGE_FILE_MACHINE_ARMT 0x01c2 // 32bit Mixed ARM and Thumb/Thumb 2 Little Endian +#define IMAGE_FILE_MACHINE_ARM64 0xAA64 // 64bit ARM Architecture, Little Endian +#define IMAGE_FILE_MACHINE_RISCV64 0x5064 // 64bit RISC-V ISA + +// +// Support old names for backward compatible +// +#define EFI_IMAGE_MACHINE_IA32 IMAGE_FILE_MACHINE_I386 +#define EFI_IMAGE_MACHINE_EBC IMAGE_FILE_MACHINE_EBC +#define EFI_IMAGE_MACHINE_X64 IMAGE_FILE_MACHINE_X64 +#define EFI_IMAGE_MACHINE_ARMT IMAGE_FILE_MACHINE_ARMT +#define EFI_IMAGE_MACHINE_AARCH64 IMAGE_FILE_MACHINE_ARM64 +#define EFI_IMAGE_MACHINE_RISCV64 IMAGE_FILE_MACHINE_RISCV64 + +#define EFI_IMAGE_DOS_SIGNATURE 0x5A4D // MZ +#define EFI_IMAGE_OS2_SIGNATURE 0x454E // NE +#define EFI_IMAGE_OS2_SIGNATURE_LE 0x454C // LE +#define EFI_IMAGE_NT_SIGNATURE 0x00004550 // PE00 +#define EFI_IMAGE_EDOS_SIGNATURE 0x44454550 // PEED + +/// +/// PE images can start with an optional DOS header, so if an image is run +/// under DOS it can print an error message. +/// +typedef struct { + UINT16 e_magic; // Magic number + UINT16 e_cblp; // Bytes on last page of file + UINT16 e_cp; // Pages in file + UINT16 e_crlc; // Relocations + UINT16 e_cparhdr; // Size of header in paragraphs + UINT16 e_minalloc; // Minimum extra paragraphs needed + UINT16 e_maxalloc; // Maximum extra paragraphs needed + UINT16 e_ss; // Initial (relative) SS value + UINT16 e_sp; // Initial SP value + UINT16 e_csum; // Checksum + UINT16 e_ip; // Initial IP value + UINT16 e_cs; // Initial (relative) CS value + UINT16 e_lfarlc; // File address of relocation table + UINT16 e_ovno; // Overlay number + UINT16 e_res[4]; // Reserved words + UINT16 e_oemid; // OEM identifier (for e_oeminfo) + UINT16 e_oeminfo; // OEM information; e_oemid specific + UINT16 e_res2[10]; // Reserved words + UINT32 e_lfanew; // File address of new exe header +} EFI_IMAGE_DOS_HEADER; + +/// +/// File header format. +/// +typedef struct { + UINT16 Machine; + UINT16 NumberOfSections; + UINT32 TimeDateStamp; + UINT32 PointerToSymbolTable; + UINT32 NumberOfSymbols; + UINT16 SizeOfOptionalHeader; + UINT16 Characteristics; +} EFI_IMAGE_FILE_HEADER; + +#define EFI_IMAGE_SIZEOF_FILE_HEADER 20 + +#define EFI_IMAGE_FILE_RELOCS_STRIPPED 0x0001 // Relocation info stripped from file. +#define EFI_IMAGE_FILE_EXECUTABLE_IMAGE 0x0002 // File is executable (i.e. no unresolved externel references). +#define EFI_IMAGE_FILE_LINE_NUMS_STRIPPED 0x0004 // Line nunbers stripped from file. +#define EFI_IMAGE_FILE_LOCAL_SYMS_STRIPPED 0x0008 // Local symbols stripped from file. +#define EFI_IMAGE_FILE_LARGE_ADDRESS_AWARE 0x0020 // Supports addresses > 2-GB +#define EFI_IMAGE_FILE_BYTES_REVERSED_LO 0x0080 // Bytes of machine word are reversed. +#define EFI_IMAGE_FILE_32BIT_MACHINE 0x0100 // 32 bit word machine. +#define EFI_IMAGE_FILE_DEBUG_STRIPPED 0x0200 // Debugging info stripped from file in .DBG file +#define EFI_IMAGE_FILE_SYSTEM 0x1000 // System File. +#define EFI_IMAGE_FILE_DLL 0x2000 // File is a DLL. +#define EFI_IMAGE_FILE_BYTES_REVERSED_HI 0x8000 // Bytes of machine word are reversed. +#define EFI_IMAGE_FILE_MACHINE_UNKNOWN 0 +#define EFI_IMAGE_FILE_MACHINE_I386 0x14c // Intel 386. +#define EFI_IMAGE_FILE_MACHINE_R3000 0x162 // MIPS* little-endian, 0540 big-endian +#define EFI_IMAGE_FILE_MACHINE_R4000 0x166 // MIPS* little-endian +#define EFI_IMAGE_FILE_MACHINE_ALPHA 0x184 // Alpha_AXP* +#define EFI_IMAGE_FILE_MACHINE_POWERPC 0x1F0 // IBM* PowerPC Little-Endian +#define EFI_IMAGE_FILE_MACHINE_TAHOE 0x7cc // Intel EM machine +// +// * Other names and brands may be claimed as the property of others. +// + +/// +/// Directory format. +/// +typedef struct { + UINT32 VirtualAddress; + UINT32 Size; +} EFI_IMAGE_DATA_DIRECTORY; + +#define EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES 16 + +typedef struct { + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + UINT32 BaseOfBss; + UINT32 GprMask; + UINT32 CprMask[4]; + UINT32 GpValue; +} EFI_IMAGE_ROM_OPTIONAL_HEADER; + +#define EFI_IMAGE_ROM_OPTIONAL_HDR_MAGIC 0x107 +#define EFI_IMAGE_SIZEOF_ROM_OPTIONAL_HEADER sizeof (EFI_IMAGE_ROM_OPTIONAL_HEADER) + +typedef struct { + EFI_IMAGE_FILE_HEADER FileHeader; + EFI_IMAGE_ROM_OPTIONAL_HEADER OptionalHeader; +} EFI_IMAGE_ROM_HEADERS; + +/// +/// @attention +/// EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64 +/// are for use ONLY by tools. All proper EFI code MUST use +/// EFI_IMAGE_OPTIONAL_HEADER ONLY!!! +/// +#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC 0x10b + +typedef struct { + // + // Standard fields. + // + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + UINT32 BaseOfData; + // + // NT additional fields. + // + UINT32 ImageBase; + UINT32 SectionAlignment; + UINT32 FileAlignment; + UINT16 MajorOperatingSystemVersion; + UINT16 MinorOperatingSystemVersion; + UINT16 MajorImageVersion; + UINT16 MinorImageVersion; + UINT16 MajorSubsystemVersion; + UINT16 MinorSubsystemVersion; + UINT32 Win32VersionValue; + UINT32 SizeOfImage; + UINT32 SizeOfHeaders; + UINT32 CheckSum; + UINT16 Subsystem; + UINT16 DllCharacteristics; + UINT32 SizeOfStackReserve; + UINT32 SizeOfStackCommit; + UINT32 SizeOfHeapReserve; + UINT32 SizeOfHeapCommit; + UINT32 LoaderFlags; + UINT32 NumberOfRvaAndSizes; + EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES]; +} EFI_IMAGE_OPTIONAL_HEADER32; + +/// +/// @attention +/// EFI_IMAGE_OPTIONAL_HEADER32 and EFI_IMAGE_OPTIONAL_HEADER64 +/// are for use ONLY by tools. All proper EFI code MUST use +/// EFI_IMAGE_OPTIONAL_HEADER ONLY!!! +/// +#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC 0x20b + +typedef struct { + // + // Standard fields. + // + UINT16 Magic; + UINT8 MajorLinkerVersion; + UINT8 MinorLinkerVersion; + UINT32 SizeOfCode; + UINT32 SizeOfInitializedData; + UINT32 SizeOfUninitializedData; + UINT32 AddressOfEntryPoint; + UINT32 BaseOfCode; + // + // NT additional fields. + // + UINT64 ImageBase; + UINT32 SectionAlignment; + UINT32 FileAlignment; + UINT16 MajorOperatingSystemVersion; + UINT16 MinorOperatingSystemVersion; + UINT16 MajorImageVersion; + UINT16 MinorImageVersion; + UINT16 MajorSubsystemVersion; + UINT16 MinorSubsystemVersion; + UINT32 Win32VersionValue; + UINT32 SizeOfImage; + UINT32 SizeOfHeaders; + UINT32 CheckSum; + UINT16 Subsystem; + UINT16 DllCharacteristics; + UINT64 SizeOfStackReserve; + UINT64 SizeOfStackCommit; + UINT64 SizeOfHeapReserve; + UINT64 SizeOfHeapCommit; + UINT32 LoaderFlags; + UINT32 NumberOfRvaAndSizes; + EFI_IMAGE_DATA_DIRECTORY DataDirectory[EFI_IMAGE_NUMBER_OF_DIRECTORY_ENTRIES]; +} EFI_IMAGE_OPTIONAL_HEADER64; + +/// +/// @attention +/// EFI_IMAGE_NT_HEADERS32 and EFI_IMAGE_HEADERS64 are for use ONLY +/// by tools. All proper EFI code MUST use EFI_IMAGE_NT_HEADERS ONLY!!! +/// +typedef struct { + UINT32 Signature; + EFI_IMAGE_FILE_HEADER FileHeader; + EFI_IMAGE_OPTIONAL_HEADER32 OptionalHeader; +} EFI_IMAGE_NT_HEADERS32; + +#define EFI_IMAGE_SIZEOF_NT_OPTIONAL32_HEADER sizeof (EFI_IMAGE_NT_HEADERS32) + +typedef struct { + UINT32 Signature; + EFI_IMAGE_FILE_HEADER FileHeader; + EFI_IMAGE_OPTIONAL_HEADER64 OptionalHeader; +} EFI_IMAGE_NT_HEADERS64; + +#define EFI_IMAGE_SIZEOF_NT_OPTIONAL64_HEADER sizeof (EFI_IMAGE_NT_HEADERS64) + +// +// Subsystem Values +// +#define EFI_IMAGE_SUBSYSTEM_UNKNOWN 0 +#define EFI_IMAGE_SUBSYSTEM_NATIVE 1 +#define EFI_IMAGE_SUBSYSTEM_WINDOWS_GUI 2 +#define EFI_IMAGE_SUBSYSTEM_WINDOWS_CUI 3. +#define EFI_IMAGE_SUBSYSTEM_OS2_CUI 5 +#define EFI_IMAGE_SUBSYSTEM_POSIX_CUI 7 + +// +// Directory Entries +// +#define EFI_IMAGE_DIRECTORY_ENTRY_EXPORT 0 +#define EFI_IMAGE_DIRECTORY_ENTRY_IMPORT 1 +#define EFI_IMAGE_DIRECTORY_ENTRY_RESOURCE 2 +#define EFI_IMAGE_DIRECTORY_ENTRY_EXCEPTION 3 +#define EFI_IMAGE_DIRECTORY_ENTRY_SECURITY 4 +#define EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC 5 +#define EFI_IMAGE_DIRECTORY_ENTRY_DEBUG 6 +#define EFI_IMAGE_DIRECTORY_ENTRY_COPYRIGHT 7 +#define EFI_IMAGE_DIRECTORY_ENTRY_GLOBALPTR 8 +#define EFI_IMAGE_DIRECTORY_ENTRY_TLS 9 +#define EFI_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG 10 + +// +// Section header format. +// +#define EFI_IMAGE_SIZEOF_SHORT_NAME 8 + +typedef struct { + UINT8 Name[EFI_IMAGE_SIZEOF_SHORT_NAME]; + union { + UINT32 PhysicalAddress; + UINT32 VirtualSize; + } Misc; + UINT32 VirtualAddress; + UINT32 SizeOfRawData; + UINT32 PointerToRawData; + UINT32 PointerToRelocations; + UINT32 PointerToLinenumbers; + UINT16 NumberOfRelocations; + UINT16 NumberOfLinenumbers; + UINT32 Characteristics; +} EFI_IMAGE_SECTION_HEADER; + +#define EFI_IMAGE_SIZEOF_SECTION_HEADER 40 + +#define EFI_IMAGE_SCN_TYPE_NO_PAD 0x00000008 // Reserved. +#define EFI_IMAGE_SCN_CNT_CODE 0x00000020 +#define EFI_IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040 +#define EFI_IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x00000080 + +#define EFI_IMAGE_SCN_LNK_OTHER 0x00000100 // Reserved. +#define EFI_IMAGE_SCN_LNK_INFO 0x00000200 // Section contains comments or some other type of information. +#define EFI_IMAGE_SCN_LNK_REMOVE 0x00000800 // Section contents will not become part of image. +#define EFI_IMAGE_SCN_LNK_COMDAT 0x00001000 + +#define EFI_IMAGE_SCN_ALIGN_1BYTES 0x00100000 +#define EFI_IMAGE_SCN_ALIGN_2BYTES 0x00200000 +#define EFI_IMAGE_SCN_ALIGN_4BYTES 0x00300000 +#define EFI_IMAGE_SCN_ALIGN_8BYTES 0x00400000 +#define EFI_IMAGE_SCN_ALIGN_16BYTES 0x00500000 +#define EFI_IMAGE_SCN_ALIGN_32BYTES 0x00600000 +#define EFI_IMAGE_SCN_ALIGN_64BYTES 0x00700000 + +#define EFI_IMAGE_SCN_MEM_DISCARDABLE 0x02000000 +#define EFI_IMAGE_SCN_MEM_NOT_CACHED 0x04000000 +#define EFI_IMAGE_SCN_MEM_NOT_PAGED 0x08000000 +#define EFI_IMAGE_SCN_MEM_SHARED 0x10000000 +#define EFI_IMAGE_SCN_MEM_EXECUTE 0x20000000 +#define EFI_IMAGE_SCN_MEM_READ 0x40000000 +#define EFI_IMAGE_SCN_MEM_WRITE 0x80000000 + +/// +/// Symbol format. +/// +#define EFI_IMAGE_SIZEOF_SYMBOL 18 + +// +// Section values. +// +// Symbols have a section number of the section in which they are +// defined. Otherwise, section numbers have the following meanings: +// +#define EFI_IMAGE_SYM_UNDEFINED (UINT16) 0 // Symbol is undefined or is common. +#define EFI_IMAGE_SYM_ABSOLUTE (UINT16) -1 // Symbol is an absolute value. +#define EFI_IMAGE_SYM_DEBUG (UINT16) -2 // Symbol is a special debug item. +// +// Type (fundamental) values. +// +#define EFI_IMAGE_SYM_TYPE_NULL 0 // no type. +#define EFI_IMAGE_SYM_TYPE_VOID 1 // +#define EFI_IMAGE_SYM_TYPE_CHAR 2 // type character. +#define EFI_IMAGE_SYM_TYPE_SHORT 3 // type short integer. +#define EFI_IMAGE_SYM_TYPE_INT 4 +#define EFI_IMAGE_SYM_TYPE_LONG 5 +#define EFI_IMAGE_SYM_TYPE_FLOAT 6 +#define EFI_IMAGE_SYM_TYPE_DOUBLE 7 +#define EFI_IMAGE_SYM_TYPE_STRUCT 8 +#define EFI_IMAGE_SYM_TYPE_UNION 9 +#define EFI_IMAGE_SYM_TYPE_ENUM 10 // enumeration. +#define EFI_IMAGE_SYM_TYPE_MOE 11 // member of enumeration. +#define EFI_IMAGE_SYM_TYPE_BYTE 12 +#define EFI_IMAGE_SYM_TYPE_WORD 13 +#define EFI_IMAGE_SYM_TYPE_UINT 14 +#define EFI_IMAGE_SYM_TYPE_DWORD 15 + +// +// Type (derived) values. +// +#define EFI_IMAGE_SYM_DTYPE_NULL 0 // no derived type. +#define EFI_IMAGE_SYM_DTYPE_POINTER 1 +#define EFI_IMAGE_SYM_DTYPE_FUNCTION 2 +#define EFI_IMAGE_SYM_DTYPE_ARRAY 3 + +// +// Storage classes. +// +#define EFI_IMAGE_SYM_CLASS_END_OF_FUNCTION (UINT8) -1 +#define EFI_IMAGE_SYM_CLASS_NULL 0 +#define EFI_IMAGE_SYM_CLASS_AUTOMATIC 1 +#define EFI_IMAGE_SYM_CLASS_EXTERNAL 2 +#define EFI_IMAGE_SYM_CLASS_STATIC 3 +#define EFI_IMAGE_SYM_CLASS_REGISTER 4 +#define EFI_IMAGE_SYM_CLASS_EXTERNAL_DEF 5 +#define EFI_IMAGE_SYM_CLASS_LABEL 6 +#define EFI_IMAGE_SYM_CLASS_UNDEFINED_LABEL 7 +#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT 8 +#define EFI_IMAGE_SYM_CLASS_ARGUMENT 9 +#define EFI_IMAGE_SYM_CLASS_STRUCT_TAG 10 +#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_UNION 11 +#define EFI_IMAGE_SYM_CLASS_UNION_TAG 12 +#define EFI_IMAGE_SYM_CLASS_TYPE_DEFINITION 13 +#define EFI_IMAGE_SYM_CLASS_UNDEFINED_STATIC 14 +#define EFI_IMAGE_SYM_CLASS_ENUM_TAG 15 +#define EFI_IMAGE_SYM_CLASS_MEMBER_OF_ENUM 16 +#define EFI_IMAGE_SYM_CLASS_REGISTER_PARAM 17 +#define EFI_IMAGE_SYM_CLASS_BIT_FIELD 18 +#define EFI_IMAGE_SYM_CLASS_BLOCK 100 +#define EFI_IMAGE_SYM_CLASS_FUNCTION 101 +#define EFI_IMAGE_SYM_CLASS_END_OF_STRUCT 102 +#define EFI_IMAGE_SYM_CLASS_FILE 103 +#define EFI_IMAGE_SYM_CLASS_SECTION 104 +#define EFI_IMAGE_SYM_CLASS_WEAK_EXTERNAL 105 + +// +// type packing constants +// +#define EFI_IMAGE_N_BTMASK 017 +#define EFI_IMAGE_N_TMASK 060 +#define EFI_IMAGE_N_TMASK1 0300 +#define EFI_IMAGE_N_TMASK2 0360 +#define EFI_IMAGE_N_BTSHFT 4 +#define EFI_IMAGE_N_TSHIFT 2 + +// +// Communal selection types. +// +#define EFI_IMAGE_COMDAT_SELECT_NODUPLICATES 1 +#define EFI_IMAGE_COMDAT_SELECT_ANY 2 +#define EFI_IMAGE_COMDAT_SELECT_SAME_SIZE 3 +#define EFI_IMAGE_COMDAT_SELECT_EXACT_MATCH 4 +#define EFI_IMAGE_COMDAT_SELECT_ASSOCIATIVE 5 + +#define EFI_IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY 1 +#define EFI_IMAGE_WEAK_EXTERN_SEARCH_LIBRARY 2 +#define EFI_IMAGE_WEAK_EXTERN_SEARCH_ALIAS 3 + +/// +/// Relocation format. +/// +typedef struct { + UINT32 VirtualAddress; + UINT32 SymbolTableIndex; + UINT16 Type; +} EFI_IMAGE_RELOCATION; + +#define EFI_IMAGE_SIZEOF_RELOCATION 10 + +// +// I386 relocation types. +// +#define EFI_IMAGE_REL_I386_ABSOLUTE 0 // Reference is absolute, no relocation is necessary +#define EFI_IMAGE_REL_I386_DIR16 01 // Direct 16-bit reference to the symbols virtual address +#define EFI_IMAGE_REL_I386_REL16 02 // PC-relative 16-bit reference to the symbols virtual address +#define EFI_IMAGE_REL_I386_DIR32 06 // Direct 32-bit reference to the symbols virtual address +#define EFI_IMAGE_REL_I386_DIR32NB 07 // Direct 32-bit reference to the symbols virtual address, base not included +#define EFI_IMAGE_REL_I386_SEG12 09 // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address +#define EFI_IMAGE_REL_I386_SECTION 010 +#define EFI_IMAGE_REL_I386_SECREL 011 +#define EFI_IMAGE_REL_I386_REL32 020 // PC-relative 32-bit reference to the symbols virtual address + +// +// x64 processor relocation types. +// +#define IMAGE_REL_AMD64_ABSOLUTE 0x0000 +#define IMAGE_REL_AMD64_ADDR64 0x0001 +#define IMAGE_REL_AMD64_ADDR32 0x0002 +#define IMAGE_REL_AMD64_ADDR32NB 0x0003 +#define IMAGE_REL_AMD64_REL32 0x0004 +#define IMAGE_REL_AMD64_REL32_1 0x0005 +#define IMAGE_REL_AMD64_REL32_2 0x0006 +#define IMAGE_REL_AMD64_REL32_3 0x0007 +#define IMAGE_REL_AMD64_REL32_4 0x0008 +#define IMAGE_REL_AMD64_REL32_5 0x0009 +#define IMAGE_REL_AMD64_SECTION 0x000A +#define IMAGE_REL_AMD64_SECREL 0x000B +#define IMAGE_REL_AMD64_SECREL7 0x000C +#define IMAGE_REL_AMD64_TOKEN 0x000D +#define IMAGE_REL_AMD64_SREL32 0x000E +#define IMAGE_REL_AMD64_PAIR 0x000F +#define IMAGE_REL_AMD64_SSPAN32 0x0010 + +/// +/// Based relocation format. +/// +typedef struct { + UINT32 VirtualAddress; + UINT32 SizeOfBlock; +} EFI_IMAGE_BASE_RELOCATION; + +#define EFI_IMAGE_SIZEOF_BASE_RELOCATION 8 + +// +// Based relocation types. +// +#define EFI_IMAGE_REL_BASED_ABSOLUTE 0 +#define EFI_IMAGE_REL_BASED_HIGH 1 +#define EFI_IMAGE_REL_BASED_LOW 2 +#define EFI_IMAGE_REL_BASED_HIGHLOW 3 +#define EFI_IMAGE_REL_BASED_HIGHADJ 4 +#define EFI_IMAGE_REL_BASED_MIPS_JMPADDR 5 +#define EFI_IMAGE_REL_BASED_ARM_MOV32A 5 +#define EFI_IMAGE_REL_BASED_RISCV_HI20 5 +#define EFI_IMAGE_REL_BASED_ARM_MOV32T 7 +#define EFI_IMAGE_REL_BASED_RISCV_LOW12I 7 +#define EFI_IMAGE_REL_BASED_RISCV_LOW12S 8 +#define EFI_IMAGE_REL_BASED_IA64_IMM64 9 +#define EFI_IMAGE_REL_BASED_DIR64 10 + + +/// +/// Line number format. +/// +typedef struct { + union { + UINT32 SymbolTableIndex; // Symbol table index of function name if Linenumber is 0. + UINT32 VirtualAddress; // Virtual address of line number. + } Type; + UINT16 Linenumber; // Line number. +} EFI_IMAGE_LINENUMBER; + +#define EFI_IMAGE_SIZEOF_LINENUMBER 6 + +// +// Archive format. +// +#define EFI_IMAGE_ARCHIVE_START_SIZE 8 +#define EFI_IMAGE_ARCHIVE_START "!\n" +#define EFI_IMAGE_ARCHIVE_END "`\n" +#define EFI_IMAGE_ARCHIVE_PAD "\n" +#define EFI_IMAGE_ARCHIVE_LINKER_MEMBER "/ " +#define EFI_IMAGE_ARCHIVE_LONGNAMES_MEMBER "// " + +typedef struct { + UINT8 Name[16]; // File member name - `/' terminated. + UINT8 Date[12]; // File member date - decimal. + UINT8 UserID[6]; // File member user id - decimal. + UINT8 GroupID[6]; // File member group id - decimal. + UINT8 Mode[8]; // File member mode - octal. + UINT8 Size[10]; // File member size - decimal. + UINT8 EndHeader[2]; // String to end header. +} EFI_IMAGE_ARCHIVE_MEMBER_HEADER; + +#define EFI_IMAGE_SIZEOF_ARCHIVE_MEMBER_HDR 60 + +// +// DLL support. +// + +/// +/// DLL Export Format +/// +typedef struct { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT32 Name; + UINT32 Base; + UINT32 NumberOfFunctions; + UINT32 NumberOfNames; + UINT32 AddressOfFunctions; + UINT32 AddressOfNames; + UINT32 AddressOfNameOrdinals; +} EFI_IMAGE_EXPORT_DIRECTORY; + +/// +/// DLL support. +/// Import Format +/// +typedef struct { + UINT16 Hint; + UINT8 Name[1]; +} EFI_IMAGE_IMPORT_BY_NAME; + +typedef struct { + union { + UINT32 Function; + UINT32 Ordinal; + EFI_IMAGE_IMPORT_BY_NAME *AddressOfData; + } u1; +} EFI_IMAGE_THUNK_DATA; + +#define EFI_IMAGE_ORDINAL_FLAG 0x80000000 +#define EFI_IMAGE_SNAP_BY_ORDINAL(Ordinal) ((Ordinal & EFI_IMAGE_ORDINAL_FLAG) != 0) +#define EFI_IMAGE_ORDINAL(Ordinal) (Ordinal & 0xffff) + +typedef struct { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT32 ForwarderChain; + UINT32 Name; + EFI_IMAGE_THUNK_DATA *FirstThunk; +} EFI_IMAGE_IMPORT_DESCRIPTOR; + +/// +/// Debug Format +/// +#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW 2 + +typedef struct { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT32 Type; + UINT32 SizeOfData; + UINT32 RVA; + UINT32 FileOffset; +} EFI_IMAGE_DEBUG_DIRECTORY_ENTRY; + +#define CODEVIEW_SIGNATURE_NB10 0x3031424E // "NB10" +typedef struct { + UINT32 Signature; // "NB10" + UINT32 Unknown; + UINT32 Unknown2; + UINT32 Unknown3; + // + // Filename of .PDB goes here + // +} EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY; + +#define CODEVIEW_SIGNATURE_RSDS 0x53445352 // "RSDS" +typedef struct { + UINT32 Signature; // "RSDS" + UINT32 Unknown; + UINT32 Unknown2; + UINT32 Unknown3; + UINT32 Unknown4; + UINT32 Unknown5; + // + // Filename of .PDB goes here + // +} EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY; + +/// +/// Debug Data Structure defined by Apple Mach-O to Coff utility +/// +#define CODEVIEW_SIGNATURE_MTOC SIGNATURE_32('M', 'T', 'O', 'C') +typedef struct { + UINT32 Signature; ///< "MTOC" + EFI_GUID MachOUuid; + // + // Filename of .DLL (Mach-O with debug info) goes here + // +} EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY; + +// +// .pdata entries for X64 +// +#if defined(VBOX) && !defined(_SKIP_DEFINE_RUNTIME_FUNCTION) +typedef struct { + UINT32 FunctionStartAddress; + UINT32 FunctionEndAddress; + UINT32 UnwindInfoAddress; +} RUNTIME_FUNCTION; +#endif + +typedef struct { + UINT8 Version:3; + UINT8 Flags:5; + UINT8 SizeOfProlog; + UINT8 CountOfUnwindCodes; + UINT8 FrameRegister:4; + UINT8 FrameRegisterOffset:4; +} UNWIND_INFO; + +/// +/// Resource format. +/// +typedef struct { + UINT32 Characteristics; + UINT32 TimeDateStamp; + UINT16 MajorVersion; + UINT16 MinorVersion; + UINT16 NumberOfNamedEntries; + UINT16 NumberOfIdEntries; + // + // Array of EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY entries goes here. + // +} EFI_IMAGE_RESOURCE_DIRECTORY; + +/// +/// Resource directory entry format. +/// +typedef struct { + union { + struct { + UINT32 NameOffset:31; + UINT32 NameIsString:1; + } s; + UINT32 Id; + } u1; + union { + UINT32 OffsetToData; + struct { + UINT32 OffsetToDirectory:31; + UINT32 DataIsDirectory:1; + } s; + } u2; +} EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY; + +/// +/// Resource directory entry for string. +/// +typedef struct { + UINT16 Length; + CHAR16 String[1]; +} EFI_IMAGE_RESOURCE_DIRECTORY_STRING; + +/// +/// Resource directory entry for data array. +/// +typedef struct { + UINT32 OffsetToData; + UINT32 Size; + UINT32 CodePage; + UINT32 Reserved; +} EFI_IMAGE_RESOURCE_DATA_ENTRY; + +/// +/// Header format for TE images +/// +typedef struct { + UINT16 Signature; // signature for TE format = "VZ" + UINT16 Machine; // from the original file header + UINT8 NumberOfSections; // from the original file header + UINT8 Subsystem; // from original optional header + UINT16 StrippedSize; // how many bytes we removed from the header + UINT32 AddressOfEntryPoint; // offset to entry point -- from original optional header + UINT32 BaseOfCode; // from original image -- required for ITP debug + UINT64 ImageBase; // from original file header + EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]; // only base relocation and debug directory +} EFI_TE_IMAGE_HEADER; + +#define EFI_TE_IMAGE_HEADER_SIGNATURE 0x5A56 // "VZ" + +// +// Data directory indexes in our TE image header +// +#define EFI_TE_IMAGE_DIRECTORY_ENTRY_BASERELOC 0 +#define EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG 1 + + +// +// Union of PE32, PE32+, and TE headers +// +typedef union { + EFI_IMAGE_NT_HEADERS32 Pe32; + EFI_IMAGE_NT_HEADERS64 Pe32Plus; + EFI_TE_IMAGE_HEADER Te; +} EFI_IMAGE_OPTIONAL_HEADER_UNION; + +typedef union { + EFI_IMAGE_NT_HEADERS32 *Pe32; + EFI_IMAGE_NT_HEADERS64 *Pe32Plus; + EFI_TE_IMAGE_HEADER *Te; + EFI_IMAGE_OPTIONAL_HEADER_UNION *Union; +} EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/pci22.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/pci22.h new file mode 100644 index 00000000..616bc473 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/pci22.h @@ -0,0 +1,536 @@ +/** @file + Support for PCI 2.2 standard. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _PCI22_H +#define _PCI22_H + +#define PCI_MAX_SEGMENT 0 + +#define PCI_MAX_BUS 255 + +#define PCI_MAX_DEVICE 31 +#define PCI_MAX_FUNC 7 + +// +// Command +// +#define PCI_VGA_PALETTE_SNOOP_DISABLED 0x20 + +#pragma pack(push, 1) +typedef struct { + UINT16 VendorId; + UINT16 DeviceId; + UINT16 Command; + UINT16 Status; + UINT8 RevisionID; + UINT8 ClassCode[3]; + UINT8 CacheLineSize; + UINT8 LatencyTimer; + UINT8 HeaderType; + UINT8 BIST; +} PCI_DEVICE_INDEPENDENT_REGION; + +typedef struct { + UINT32 Bar[6]; + UINT32 CISPtr; + UINT16 SubsystemVendorID; + UINT16 SubsystemID; + UINT32 ExpansionRomBar; + UINT8 CapabilityPtr; + UINT8 Reserved1[3]; + UINT32 Reserved2; + UINT8 InterruptLine; + UINT8 InterruptPin; + UINT8 MinGnt; + UINT8 MaxLat; +} PCI_DEVICE_HEADER_TYPE_REGION; + +typedef struct { + PCI_DEVICE_INDEPENDENT_REGION Hdr; + PCI_DEVICE_HEADER_TYPE_REGION Device; +} PCI_TYPE00; + +typedef struct { + UINT32 Bar[2]; + UINT8 PrimaryBus; + UINT8 SecondaryBus; + UINT8 SubordinateBus; + UINT8 SecondaryLatencyTimer; + UINT8 IoBase; + UINT8 IoLimit; + UINT16 SecondaryStatus; + UINT16 MemoryBase; + UINT16 MemoryLimit; + UINT16 PrefetchableMemoryBase; + UINT16 PrefetchableMemoryLimit; + UINT32 PrefetchableBaseUpper32; + UINT32 PrefetchableLimitUpper32; + UINT16 IoBaseUpper16; + UINT16 IoLimitUpper16; + UINT8 CapabilityPtr; + UINT8 Reserved[3]; + UINT32 ExpansionRomBAR; + UINT8 InterruptLine; + UINT8 InterruptPin; + UINT16 BridgeControl; +} PCI_BRIDGE_CONTROL_REGISTER; + +typedef struct { + PCI_DEVICE_INDEPENDENT_REGION Hdr; + PCI_BRIDGE_CONTROL_REGISTER Bridge; +} PCI_TYPE01; + +typedef union { + PCI_TYPE00 Device; + PCI_TYPE01 Bridge; +} PCI_TYPE_GENERIC; + +typedef struct { + UINT32 CardBusSocketReg; // Cardbus Socket/ExCA Base + // Address Register + // + UINT16 Reserved; + UINT16 SecondaryStatus; // Secondary Status + UINT8 PciBusNumber; // PCI Bus Number + UINT8 CardBusBusNumber; // CardBus Bus Number + UINT8 SubordinateBusNumber; // Subordinate Bus Number + UINT8 CardBusLatencyTimer; // CardBus Latency Timer + UINT32 MemoryBase0; // Memory Base Register 0 + UINT32 MemoryLimit0; // Memory Limit Register 0 + UINT32 MemoryBase1; + UINT32 MemoryLimit1; + UINT32 IoBase0; + UINT32 IoLimit0; // I/O Base Register 0 + UINT32 IoBase1; // I/O Limit Register 0 + UINT32 IoLimit1; + UINT8 InterruptLine; // Interrupt Line + UINT8 InterruptPin; // Interrupt Pin + UINT16 BridgeControl; // Bridge Control +} PCI_CARDBUS_CONTROL_REGISTER; + +// +// Definitions of PCI class bytes and manipulation macros. +// +#define PCI_CLASS_OLD 0x00 +#define PCI_CLASS_OLD_OTHER 0x00 +#define PCI_CLASS_OLD_VGA 0x01 + +#define PCI_CLASS_MASS_STORAGE 0x01 +#define PCI_CLASS_MASS_STORAGE_SCSI 0x00 +#define PCI_CLASS_MASS_STORAGE_IDE 0x01 // obsolete +#define PCI_CLASS_IDE 0x01 +#define PCI_CLASS_MASS_STORAGE_FLOPPY 0x02 +#define PCI_CLASS_MASS_STORAGE_IPI 0x03 +#define PCI_CLASS_MASS_STORAGE_RAID 0x04 +#define PCI_CLASS_MASS_STORAGE_OTHER 0x80 + +#define PCI_CLASS_NETWORK 0x02 +#define PCI_CLASS_NETWORK_ETHERNET 0x00 +#define PCI_CLASS_ETHERNET 0x00 // obsolete +#define PCI_CLASS_NETWORK_TOKENRING 0x01 +#define PCI_CLASS_NETWORK_FDDI 0x02 +#define PCI_CLASS_NETWORK_ATM 0x03 +#define PCI_CLASS_NETWORK_ISDN 0x04 +#define PCI_CLASS_NETWORK_OTHER 0x80 + +#define PCI_CLASS_DISPLAY 0x03 +#define PCI_CLASS_DISPLAY_CTRL 0x03 // obsolete +#define PCI_CLASS_DISPLAY_VGA 0x00 +#define PCI_CLASS_VGA 0x00 // obsolete +#define PCI_CLASS_DISPLAY_XGA 0x01 +#define PCI_CLASS_DISPLAY_3D 0x02 +#define PCI_CLASS_DISPLAY_OTHER 0x80 +#define PCI_CLASS_DISPLAY_GFX 0x80 +#define PCI_CLASS_GFX 0x80 // obsolete +#define PCI_CLASS_BRIDGE 0x06 +#define PCI_CLASS_BRIDGE_HOST 0x00 +#define PCI_CLASS_BRIDGE_ISA 0x01 +#define PCI_CLASS_ISA 0x01 // obsolete +#define PCI_CLASS_BRIDGE_EISA 0x02 +#define PCI_CLASS_BRIDGE_MCA 0x03 +#define PCI_CLASS_BRIDGE_P2P 0x04 +#define PCI_CLASS_BRIDGE_PCMCIA 0x05 +#define PCI_CLASS_BRIDGE_NUBUS 0x06 +#define PCI_CLASS_BRIDGE_CARDBUS 0x07 +#define PCI_CLASS_BRIDGE_RACEWAY 0x08 +#define PCI_CLASS_BRIDGE_ISA_PDECODE 0x80 +#define PCI_CLASS_ISA_POSITIVE_DECODE 0x80 // obsolete + +#define PCI_CLASS_SCC 0x07 // Simple communications controllers +#define PCI_SUBCLASS_SERIAL 0x00 +#define PCI_IF_GENERIC_XT 0x00 +#define PCI_IF_16450 0x01 +#define PCI_IF_16550 0x02 +#define PCI_IF_16650 0x03 +#define PCI_IF_16750 0x04 +#define PCI_IF_16850 0x05 +#define PCI_IF_16950 0x06 +#define PCI_SUBCLASS_PARALLEL 0x01 +#define PCI_IF_PARALLEL_PORT 0x00 +#define PCI_IF_BI_DIR_PARALLEL_PORT 0x01 +#define PCI_IF_ECP_PARALLEL_PORT 0x02 +#define PCI_IF_1284_CONTROLLER 0x03 +#define PCI_IF_1284_DEVICE 0xFE +#define PCI_SUBCLASS_MULTIPORT_SERIAL 0x02 +#define PCI_SUBCLASS_MODEM 0x03 +#define PCI_IF_GENERIC_MODEM 0x00 +#define PCI_IF_16450_MODEM 0x01 +#define PCI_IF_16550_MODEM 0x02 +#define PCI_IF_16650_MODEM 0x03 +#define PCI_IF_16750_MODEM 0x04 +#define PCI_SUBCLASS_OTHER 0x80 + +#define PCI_CLASS_SYSTEM_PERIPHERAL 0x08 +#define PCI_SUBCLASS_PIC 0x00 +#define PCI_IF_8259_PIC 0x00 +#define PCI_IF_ISA_PIC 0x01 +#define PCI_IF_EISA_PIC 0x02 +#define PCI_IF_APIC_CONTROLLER 0x10 // I/O APIC interrupt controller , 32 byte none-prefetchable memory. +#define PCI_IF_APIC_CONTROLLER2 0x20 +#define PCI_SUBCLASS_TIMER 0x02 +#define PCI_IF_8254_TIMER 0x00 +#define PCI_IF_ISA_TIMER 0x01 +#define PCI_EISA_TIMER 0x02 +#define PCI_SUBCLASS_RTC 0x03 +#define PCI_IF_GENERIC_RTC 0x00 +#define PCI_IF_ISA_RTC 0x00 +#define PCI_SUBCLASS_PNP_CONTROLLER 0x04 // HotPlug Controller + +#define PCI_CLASS_INPUT_DEVICE 0x09 +#define PCI_SUBCLASS_KEYBOARD 0x00 +#define PCI_SUBCLASS_PEN 0x01 +#define PCI_SUBCLASS_MOUSE_CONTROLLER 0x02 +#define PCI_SUBCLASS_SCAN_CONTROLLER 0x03 +#define PCI_SUBCLASS_GAMEPORT 0x04 + +#define PCI_CLASS_DOCKING_STATION 0x0A + +#define PCI_CLASS_PROCESSOR 0x0B +#define PCI_SUBCLASS_PROC_386 0x00 +#define PCI_SUBCLASS_PROC_486 0x01 +#define PCI_SUBCLASS_PROC_PENTIUM 0x02 +#define PCI_SUBCLASS_PROC_ALPHA 0x10 +#define PCI_SUBCLASS_PROC_POWERPC 0x20 +#define PCI_SUBCLASS_PROC_MIPS 0x30 +#define PCI_SUBCLASS_PROC_CO_PORC 0x40 // Co-Processor + +#define PCI_CLASS_SERIAL 0x0C +#define PCI_CLASS_SERIAL_FIREWIRE 0x00 +#define PCI_CLASS_SERIAL_ACCESS_BUS 0x01 +#define PCI_CLASS_SERIAL_SSA 0x02 +#define PCI_CLASS_SERIAL_USB 0x03 +#define PCI_CLASS_SERIAL_FIBRECHANNEL 0x04 +#define PCI_CLASS_SERIAL_SMB 0x05 + +#define PCI_CLASS_WIRELESS 0x0D +#define PCI_SUBCLASS_IRDA 0x00 +#define PCI_SUBCLASS_IR 0x01 +#define PCI_SUBCLASS_RF 0x02 + +#define PCI_CLASS_INTELLIGENT_IO 0x0E + +#define PCI_CLASS_SATELLITE 0x0F +#define PCI_SUBCLASS_TV 0x01 +#define PCI_SUBCLASS_AUDIO 0x02 +#define PCI_SUBCLASS_VOICE 0x03 +#define PCI_SUBCLASS_DATA 0x04 + +#define PCI_SECURITY_CONTROLLER 0x10 // Encryption and decryption controller +#define PCI_SUBCLASS_NET_COMPUT 0x00 +#define PCI_SUBCLASS_ENTERTAINMENT 0x10 + +#define PCI_CLASS_DPIO 0x11 + +#define IS_CLASS1(_p, c) ((_p)->Hdr.ClassCode[2] == (c)) +#define IS_CLASS2(_p, c, s) (IS_CLASS1 (_p, c) && ((_p)->Hdr.ClassCode[1] == (s))) +#define IS_CLASS3(_p, c, s, p) (IS_CLASS2 (_p, c, s) && ((_p)->Hdr.ClassCode[0] == (p))) + +#define IS_PCI_DISPLAY(_p) IS_CLASS1 (_p, PCI_CLASS_DISPLAY) +#define IS_PCI_VGA(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, 0) +#define IS_PCI_8514(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_VGA, 1) +#define IS_PCI_GFX(_p) IS_CLASS3 (_p, PCI_CLASS_DISPLAY, PCI_CLASS_DISPLAY_GFX, 0) +#define IS_PCI_OLD(_p) IS_CLASS1 (_p, PCI_CLASS_OLD) +#define IS_PCI_OLD_VGA(_p) IS_CLASS2 (_p, PCI_CLASS_OLD, PCI_CLASS_OLD_VGA) +#define IS_PCI_IDE(_p) IS_CLASS2 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_IDE) +#define IS_PCI_SCSI(_p) IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_SCSI, 0) +#define IS_PCI_RAID(_p) IS_CLASS3 (_p, PCI_CLASS_MASS_STORAGE, PCI_CLASS_MASS_STORAGE_RAID, 0) +#define IS_PCI_LPC(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA, 0) +#define IS_PCI_P2P(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, 0) +#define IS_PCI_P2P_SUB(_p) IS_CLASS3 (_p, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_P2P, 1) +#define IS_PCI_USB(_p) IS_CLASS2 (_p, PCI_CLASS_SERIAL, PCI_CLASS_SERIAL_USB) + +#define HEADER_TYPE_DEVICE 0x00 +#define HEADER_TYPE_PCI_TO_PCI_BRIDGE 0x01 +#define HEADER_TYPE_CARDBUS_BRIDGE 0x02 + +#define HEADER_TYPE_MULTI_FUNCTION 0x80 +#define HEADER_LAYOUT_CODE 0x7f + +#define IS_PCI_BRIDGE(_p) (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_PCI_TO_PCI_BRIDGE)) +#define IS_CARDBUS_BRIDGE(_p) (((_p)->Hdr.HeaderType & HEADER_LAYOUT_CODE) == (HEADER_TYPE_CARDBUS_BRIDGE)) +#define IS_PCI_MULTI_FUNC(_p) ((_p)->Hdr.HeaderType & HEADER_TYPE_MULTI_FUNCTION) + +#define PCI_DEVICE_ROMBAR 0x30 +#define PCI_BRIDGE_ROMBAR 0x38 + +#define PCI_MAX_BAR 0x0006 +#define PCI_MAX_CONFIG_OFFSET 0x0100 + +#define PCI_VENDOR_ID_OFFSET 0x00 +#define PCI_DEVICE_ID_OFFSET 0x02 +#define PCI_COMMAND_OFFSET 0x04 +#define PCI_PRIMARY_STATUS_OFFSET 0x06 +#define PCI_REVISION_ID_OFFSET 0x08 +#define PCI_CLASSCODE_OFFSET 0x09 +#define PCI_CACHELINE_SIZE_OFFSET 0x0C +#define PCI_LATENCY_TIMER_OFFSET 0x0D +#define PCI_HEADER_TYPE_OFFSET 0x0E +#define PCI_BIST_OFFSET 0x0F +#define PCI_BASE_ADDRESSREG_OFFSET 0x10 +#define PCI_CARDBUS_CIS_OFFSET 0x28 +#define PCI_SVID_OFFSET 0x2C // SubSystem Vendor id +#define PCI_SUBSYSTEM_VENDOR_ID_OFFSET 0x2C +#define PCI_SID_OFFSET 0x2E // SubSystem ID +#define PCI_SUBSYSTEM_ID_OFFSET 0x2E +#define PCI_EXPANSION_ROM_BASE 0x30 +#define PCI_CAPBILITY_POINTER_OFFSET 0x34 +#define PCI_INT_LINE_OFFSET 0x3C // Interrupt Line Register +#define PCI_INT_PIN_OFFSET 0x3D // Interrupt Pin Register +#define PCI_MAXGNT_OFFSET 0x3E // Max Grant Register +#define PCI_MAXLAT_OFFSET 0x3F // Max Latency Register + +#define PCI_BRIDGE_CONTROL_REGISTER_OFFSET 0x3E +#define PCI_BRIDGE_STATUS_REGISTER_OFFSET 0x1E + +#define PCI_BRIDGE_PRIMARY_BUS_REGISTER_OFFSET 0x18 +#define PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET 0x19 +#define PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET 0x1a + +typedef union { + struct { + UINT32 Reg : 8; + UINT32 Func : 3; + UINT32 Dev : 5; + UINT32 Bus : 8; + UINT32 Reserved : 7; + UINT32 Enable : 1; + } Bits; + UINT32 Uint32; +} PCI_CONFIG_ACCESS_CF8; + +#pragma pack() + +#define PCI_EXPANSION_ROM_HEADER_SIGNATURE 0xaa55 +#define PCI_DATA_STRUCTURE_SIGNATURE SIGNATURE_32 ('P', 'C', 'I', 'R') +#define PCI_CODE_TYPE_PCAT_IMAGE 0x00 +#define PCI_CODE_TYPE_EFI_IMAGE 0x03 +#define EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED 0x0001 + +#define EFI_PCI_COMMAND_IO_SPACE 0x0001 +#define EFI_PCI_COMMAND_MEMORY_SPACE 0x0002 +#define EFI_PCI_COMMAND_BUS_MASTER 0x0004 +#define EFI_PCI_COMMAND_SPECIAL_CYCLE 0x0008 +#define EFI_PCI_COMMAND_MEMORY_WRITE_AND_INVALIDATE 0x0010 +#define EFI_PCI_COMMAND_VGA_PALETTE_SNOOP 0x0020 +#define EFI_PCI_COMMAND_PARITY_ERROR_RESPOND 0x0040 +#define EFI_PCI_COMMAND_STEPPING_CONTROL 0x0080 +#define EFI_PCI_COMMAND_SERR 0x0100 +#define EFI_PCI_COMMAND_FAST_BACK_TO_BACK 0x0200 + +#define EFI_PCI_BRIDGE_CONTROL_PARITY_ERROR_RESPONSE 0x0001 +#define EFI_PCI_BRIDGE_CONTROL_SERR 0x0002 +#define EFI_PCI_BRIDGE_CONTROL_ISA 0x0004 +#define EFI_PCI_BRIDGE_CONTROL_VGA 0x0008 +#define EFI_PCI_BRIDGE_CONTROL_VGA_16 0x0010 +#define EFI_PCI_BRIDGE_CONTROL_MASTER_ABORT 0x0020 +#define EFI_PCI_BRIDGE_CONTROL_RESET_SECONDARY_BUS 0x0040 +#define EFI_PCI_BRIDGE_CONTROL_FAST_BACK_TO_BACK 0x0080 +#define EFI_PCI_BRIDGE_CONTROL_PRIMARY_DISCARD_TIMER 0x0100 +#define EFI_PCI_BRIDGE_CONTROL_SECONDARY_DISCARD_TIMER 0x0200 +#define EFI_PCI_BRIDGE_CONTROL_TIMER_STATUS 0x0400 +#define EFI_PCI_BRIDGE_CONTROL_DISCARD_TIMER_SERR 0x0800 + +// +// Following are the PCI-CARDBUS bridge control bit +// +#define EFI_PCI_BRIDGE_CONTROL_IREQINT_ENABLE 0x0080 +#define EFI_PCI_BRIDGE_CONTROL_RANGE0_MEMORY_TYPE 0x0100 +#define EFI_PCI_BRIDGE_CONTROL_RANGE1_MEMORY_TYPE 0x0200 +#define EFI_PCI_BRIDGE_CONTROL_WRITE_POSTING_ENABLE 0x0400 + +// +// Following are the PCI status control bit +// +#define EFI_PCI_STATUS_CAPABILITY 0x0010 +#define EFI_PCI_STATUS_66MZ_CAPABLE 0x0020 +#define EFI_PCI_FAST_BACK_TO_BACK_CAPABLE 0x0080 +#define EFI_PCI_MASTER_DATA_PARITY_ERROR 0x0100 + +#define EFI_PCI_CAPABILITY_PTR 0x34 +#define EFI_PCI_CARDBUS_BRIDGE_CAPABILITY_PTR 0x14 + +#pragma pack(1) +typedef struct { + UINT16 Signature; // 0xaa55 + UINT8 Reserved[0x16]; + UINT16 PcirOffset; +} PCI_EXPANSION_ROM_HEADER; + +typedef struct { + UINT16 Signature; // 0xaa55 + UINT8 Size512; + UINT8 InitEntryPoint[3]; + UINT8 Reserved[0x12]; + UINT16 PcirOffset; +} EFI_LEGACY_EXPANSION_ROM_HEADER; + +typedef struct { + UINT32 Signature; // "PCIR" + UINT16 VendorId; + UINT16 DeviceId; + UINT16 Reserved0; + UINT16 Length; + UINT8 Revision; + UINT8 ClassCode[3]; + UINT16 ImageLength; + UINT16 CodeRevision; + UINT8 CodeType; + UINT8 Indicator; + UINT16 Reserved1; +} PCI_DATA_STRUCTURE; + +// +// PCI Capability List IDs and records +// +#define EFI_PCI_CAPABILITY_ID_PMI 0x01 +#define EFI_PCI_CAPABILITY_ID_AGP 0x02 +#define EFI_PCI_CAPABILITY_ID_VPD 0x03 +#define EFI_PCI_CAPABILITY_ID_SLOTID 0x04 +#define EFI_PCI_CAPABILITY_ID_MSI 0x05 +#define EFI_PCI_CAPABILITY_ID_HOTPLUG 0x06 +#define EFI_PCI_CAPABILITY_ID_PCIX 0x07 + +typedef struct { + UINT8 CapabilityID; + UINT8 NextItemPtr; +} EFI_PCI_CAPABILITY_HDR; + +// +// Capability EFI_PCI_CAPABILITY_ID_PMI +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 PMC; + UINT16 PMCSR; + UINT8 BridgeExtention; + UINT8 Data; +} EFI_PCI_CAPABILITY_PMI; + +// +// Capability EFI_PCI_CAPABILITY_ID_AGP +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT8 Rev; + UINT8 Reserved; + UINT32 Status; + UINT32 Command; +} EFI_PCI_CAPABILITY_AGP; + +// +// Capability EFI_PCI_CAPABILITY_ID_VPD +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 AddrReg; + UINT32 DataReg; +} EFI_PCI_CAPABILITY_VPD; + +// +// Capability EFI_PCI_CAPABILITY_ID_SLOTID +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT8 ExpnsSlotReg; + UINT8 ChassisNo; +} EFI_PCI_CAPABILITY_SLOTID; + +// +// Capability EFI_PCI_CAPABILITY_ID_MSI +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 MsgCtrlReg; + UINT32 MsgAddrReg; + UINT16 MsgDataReg; +} EFI_PCI_CAPABILITY_MSI32; + +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 MsgCtrlReg; + UINT32 MsgAddrRegLsdw; + UINT32 MsgAddrRegMsdw; + UINT16 MsgDataReg; +} EFI_PCI_CAPABILITY_MSI64; + +// +// Capability EFI_PCI_CAPABILITY_ID_HOTPLUG +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + // + // not finished - fields need to go here + // +} EFI_PCI_CAPABILITY_HOTPLUG; + +// +// Capability EFI_PCI_CAPABILITY_ID_PCIX +// +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 CommandReg; + UINT32 StatusReg; +} EFI_PCI_CAPABILITY_PCIX; + +typedef struct { + EFI_PCI_CAPABILITY_HDR Hdr; + UINT16 SecStatusReg; + UINT32 StatusReg; + UINT32 SplitTransCtrlRegUp; + UINT32 SplitTransCtrlRegDn; +} EFI_PCI_CAPABILITY_PCIX_BRDG; + +#define DEVICE_ID_NOCARE 0xFFFF + +#define PCI_ACPI_UNUSED 0 +#define PCI_BAR_NOCHANGE 0 +#define PCI_BAR_OLD_ALIGN 0xFFFFFFFFFFFFFFFFULL +#define PCI_BAR_EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL +#define PCI_BAR_SQUAD_ALIGN 0xFFFFFFFFFFFFFFFDULL +#define PCI_BAR_DQUAD_ALIGN 0xFFFFFFFFFFFFFFFCULL + +#define PCI_BAR_IDX0 0x00 +#define PCI_BAR_IDX1 0x01 +#define PCI_BAR_IDX2 0x02 +#define PCI_BAR_IDX3 0x03 +#define PCI_BAR_IDX4 0x04 +#define PCI_BAR_IDX5 0x05 +#define PCI_BAR_ALL 0xFF + +#pragma pack(pop) + +// +// NOTE: The following header files are included here for +// compatibility consideration. +// +#include "pci23.h" +#include "pci30.h" +#include "EfiPci.h" + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/pci23.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/pci23.h new file mode 100644 index 00000000..256b7989 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/pci23.h @@ -0,0 +1,18 @@ +/** @file + Support for PCI 2.3 standard. + + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _PCI23_H +#define _PCI23_H + +//#include "pci22.h" + +#define PCI_EXP_MAX_CONFIG_OFFSET 0x1000 +#define EFI_PCI_CAPABILITY_ID_PCIEXP 0x10 + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/pci30.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/pci30.h new file mode 100644 index 00000000..c1ffa9a0 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/IndustryStandard/pci30.h @@ -0,0 +1,38 @@ +/** @file + Support for PCI 3.0 standard. + + Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _PCI30_H +#define _PCI30_H + +//#include "pci23.h" + +#define PCI_CLASS_MASS_STORAGE_SATADPA 0x06 + +#pragma pack(push, 1) + +typedef struct { + UINT32 Signature; // "PCIR" + UINT16 VendorId; + UINT16 DeviceId; + UINT16 DeviceListOffset; + UINT16 Length; + UINT8 Revision; + UINT8 ClassCode[3]; + UINT16 ImageLength; + UINT16 CodeRevision; + UINT8 CodeType; + UINT8 Indicator; + UINT16 MaxRuntimeImageLength; + UINT16 ConfigUtilityCodeHeaderOffset; + UINT16 DMTFCLPEntryPointOffset; +} PCI_3_0_DATA_STRUCTURE; + +#pragma pack(pop) + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/DevicePath.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/DevicePath.h new file mode 100644 index 00000000..644499b6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/DevicePath.h @@ -0,0 +1,1404 @@ +/** @file + The device path protocol as defined in UEFI 2.0. + + The device path represents a programmatic path to a device, + from a software point of view. The path must persist from boot to boot, so + it can not contain things like PCI bus numbers that change from boot to boot. + +Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __EFI_DEVICE_PATH_H__ +#define __EFI_DEVICE_PATH_H__ + +#include +#include +#include + +/// +/// Device Path protocol. +/// +#define EFI_DEVICE_PATH_PROTOCOL_GUID \ + { \ + 0x9576e91, 0x6d3f, 0x11d2, {0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \ + } + +/// +/// Device Path guid definition for backward-compatible with EFI1.1. +/// +#define DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH_PROTOCOL_GUID + +#pragma pack(1) + +#if defined(_MSC_EXTENSIONS) +// +// Disable warning when last field of data structure is a zero sized array. +// +#pragma warning ( disable : 4200 ) +#endif + +/** + This protocol can be used on any device handle to obtain generic path/location + information concerning the physical device or logical device. If the handle does + not logically map to a physical device, the handle may not necessarily support + the device path protocol. The device path describes the location of the device + the handle is for. The size of the Device Path can be determined from the structures + that make up the Device Path. +**/ +typedef struct { + UINT8 Type; ///< 0x01 Hardware Device Path. + ///< 0x02 ACPI Device Path. + ///< 0x03 Messaging Device Path. + ///< 0x04 Media Device Path. + ///< 0x05 BIOS Boot Specification Device Path. + ///< 0x7F End of Hardware Device Path. + + UINT8 SubType; ///< Varies by Type + ///< 0xFF End Entire Device Path, or + ///< 0x01 End This Instance of a Device Path and start a new + ///< Device Path. + + UINT8 Length[2]; ///< Specific Device Path data. Type and Sub-Type define + ///< type of data. Size of data is included in Length. + +} EFI_DEVICE_PATH_PROTOCOL; + +/// +/// Device Path protocol definition for backward-compatible with EFI1.1. +/// +typedef EFI_DEVICE_PATH_PROTOCOL EFI_DEVICE_PATH; + +/// +/// Hardware Device Paths. +/// +#define HARDWARE_DEVICE_PATH 0x01 + +/// +/// PCI Device Path SubType. +/// +#define HW_PCI_DP 0x01 + +/// +/// PCI Device Path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// PCI Function Number. + /// + UINT8 Function; + /// + /// PCI Device Number. + /// + UINT8 Device; +} PCI_DEVICE_PATH; + +/// +/// PCCARD Device Path SubType. +/// +#define HW_PCCARD_DP 0x02 + +/// +/// PCCARD Device Path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Function Number (0 = First Function). + /// + UINT8 FunctionNumber; +} PCCARD_DEVICE_PATH; + +/// +/// Memory Mapped Device Path SubType. +/// +#define HW_MEMMAP_DP 0x03 + +/// +/// Memory Mapped Device Path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// EFI_MEMORY_TYPE + /// + UINT32 MemoryType; + /// + /// Starting Memory Address. + /// + EFI_PHYSICAL_ADDRESS StartingAddress; + /// + /// Ending Memory Address. + /// + EFI_PHYSICAL_ADDRESS EndingAddress; +} MEMMAP_DEVICE_PATH; + +/// +/// Hardware Vendor Device Path SubType. +/// +#define HW_VENDOR_DP 0x04 + +/// +/// The Vendor Device Path allows the creation of vendor-defined Device Paths. A vendor must +/// allocate a Vendor GUID for a Device Path. The Vendor GUID can then be used to define the +/// contents on the n bytes that follow in the Vendor Device Path node. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Vendor-assigned GUID that defines the data that follows. + /// + EFI_GUID Guid; + /// + /// Vendor-defined variable size data. + /// +} VENDOR_DEVICE_PATH; + +/// +/// Controller Device Path SubType. +/// +#define HW_CONTROLLER_DP 0x05 + +/// +/// Controller Device Path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Controller number. + /// + UINT32 ControllerNumber; +} CONTROLLER_DEVICE_PATH; + +/// +/// BMC Device Path SubType. +/// +#define HW_BMC_DP 0x06 + +/// +/// BMC Device Path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Interface Type. + /// + UINT8 InterfaceType; + /// + /// Base Address. + /// + UINT8 BaseAddress[8]; +} BMC_DEVICE_PATH; + +/// +/// ACPI Device Paths. +/// +#define ACPI_DEVICE_PATH 0x02 + +/// +/// ACPI Device Path SubType. +/// +#define ACPI_DP 0x01 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Device's PnP hardware ID stored in a numeric 32-bit + /// compressed EISA-type ID. This value must match the + /// corresponding _HID in the ACPI name space. + /// + UINT32 HID; + /// + /// Unique ID that is required by ACPI if two devices have the + /// same _HID. This value must also match the corresponding + /// _UID/_HID pair in the ACPI name space. Only the 32-bit + /// numeric value type of _UID is supported. Thus, strings must + /// not be used for the _UID in the ACPI name space. + /// + UINT32 UID; +} ACPI_HID_DEVICE_PATH; + +/// +/// Expanded ACPI Device Path SubType. +/// +#define ACPI_EXTENDED_DP 0x02 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Device's PnP hardware ID stored in a numeric 32-bit + /// compressed EISA-type ID. This value must match the + /// corresponding _HID in the ACPI name space. + /// + UINT32 HID; + /// + /// Unique ID that is required by ACPI if two devices have the + /// same _HID. This value must also match the corresponding + /// _UID/_HID pair in the ACPI name space. + /// + UINT32 UID; + /// + /// Device's compatible PnP hardware ID stored in a numeric + /// 32-bit compressed EISA-type ID. This value must match at + /// least one of the compatible device IDs returned by the + /// corresponding _CID in the ACPI name space. + /// + UINT32 CID; + /// + /// Optional variable length _HIDSTR. + /// Optional variable length _UIDSTR. + /// Optional variable length _CIDSTR. + /// +} ACPI_EXTENDED_HID_DEVICE_PATH; + +// +// EISA ID Macro +// EISA ID Definition 32-bits +// bits[15:0] - three character compressed ASCII EISA ID. +// bits[31:16] - binary number +// Compressed ASCII is 5 bits per character 0b00001 = 'A' 0b11010 = 'Z' +// +#define PNP_EISA_ID_CONST 0x41d0 +#define EISA_ID(_Name, _Num) ((UINT32)((_Name) | (_Num) << 16)) +#define EISA_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId))) +#define EFI_PNP_ID(_PNPId) (EISA_ID(PNP_EISA_ID_CONST, (_PNPId))) + +#define PNP_EISA_ID_MASK 0xffff +#define EISA_ID_TO_NUM(_Id) ((_Id) >> 16) + +/// +/// ACPI _ADR Device Path SubType. +/// +#define ACPI_ADR_DP 0x03 + +/// +/// The _ADR device path is used to contain video output device attributes to support the Graphics +/// Output Protocol. The device path can contain multiple _ADR entries if multiple video output +/// devices are displaying the same output. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// _ADR value. For video output devices the value of this + /// field comes from Table B-2 of the ACPI 3.0 specification. At + /// least one _ADR value is required. + /// + UINT32 ADR; + // + // This device path may optionally contain more than one _ADR entry. + // +} ACPI_ADR_DEVICE_PATH; + +#define ACPI_ADR_DISPLAY_TYPE_OTHER 0 +#define ACPI_ADR_DISPLAY_TYPE_VGA 1 +#define ACPI_ADR_DISPLAY_TYPE_TV 2 +#define ACPI_ADR_DISPLAY_TYPE_EXTERNAL_DIGITAL 3 +#define ACPI_ADR_DISPLAY_TYPE_INTERNAL_DIGITAL 4 + +#define ACPI_DISPLAY_ADR(_DeviceIdScheme, _HeadId, _NonVgaOutput, _BiosCanDetect, _VendorInfo, _Type, _Port, _Index) \ + ((UINT32)( ((UINT32)((_DeviceIdScheme) & 0x1) << 31) | \ + (((_HeadId) & 0x7) << 18) | \ + (((_NonVgaOutput) & 0x1) << 17) | \ + (((_BiosCanDetect) & 0x1) << 16) | \ + (((_VendorInfo) & 0xf) << 12) | \ + (((_Type) & 0xf) << 8) | \ + (((_Port) & 0xf) << 4) | \ + ((_Index) & 0xf) )) + +/// +/// Messaging Device Paths. +/// This Device Path is used to describe the connection of devices outside the resource domain of the +/// system. This Device Path can describe physical messaging information like SCSI ID, or abstract +/// information like networking protocol IP addresses. +/// +#define MESSAGING_DEVICE_PATH 0x03 + +/// +/// ATAPI Device Path SubType +/// +#define MSG_ATAPI_DP 0x01 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Set to zero for primary, or one for secondary. + /// + UINT8 PrimarySecondary; + /// + /// Set to zero for master, or one for slave mode. + /// + UINT8 SlaveMaster; + /// + /// Logical Unit Number. + /// + UINT16 Lun; +} ATAPI_DEVICE_PATH; + +/// +/// SCSI Device Path SubType. +/// +#define MSG_SCSI_DP 0x02 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Target ID on the SCSI bus (PUN). + /// + UINT16 Pun; + /// + /// Logical Unit Number (LUN). + /// + UINT16 Lun; +} SCSI_DEVICE_PATH; + +/// +/// Fibre Channel SubType. +/// +#define MSG_FIBRECHANNEL_DP 0x03 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Reserved for the future. + /// + UINT32 Reserved; + /// + /// Fibre Channel World Wide Number. + /// + UINT64 WWN; + /// + /// Fibre Channel Logical Unit Number. + /// + UINT64 Lun; +} FIBRECHANNEL_DEVICE_PATH; + +/// +/// Fibre Channel Ex SubType. +/// +#define MSG_FIBRECHANNELEX_DP 0x15 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Reserved for the future. + /// + UINT32 Reserved; + /// + /// 8 byte array containing Fibre Channel End Device Port Name. + /// + UINT8 WWN[8]; + /// + /// 8 byte array containing Fibre Channel Logical Unit Number. + /// + UINT8 Lun[8]; +} FIBRECHANNELEX_DEVICE_PATH; + +/// +/// 1394 Device Path SubType +/// +#define MSG_1394_DP 0x04 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Reserved for the future. + /// + UINT32 Reserved; + /// + /// 1394 Global Unique ID (GUID). + /// + UINT64 Guid; +} F1394_DEVICE_PATH; + +/// +/// USB Device Path SubType. +/// +#define MSG_USB_DP 0x05 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// USB Parent Port Number. + /// + UINT8 ParentPortNumber; + /// + /// USB Interface Number. + /// + UINT8 InterfaceNumber; +} USB_DEVICE_PATH; + +/// +/// USB Class Device Path SubType. +/// +#define MSG_USB_CLASS_DP 0x0f +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Vendor ID assigned by USB-IF. A value of 0xFFFF will + /// match any Vendor ID. + /// + UINT16 VendorId; + /// + /// Product ID assigned by USB-IF. A value of 0xFFFF will + /// match any Product ID. + /// + UINT16 ProductId; + /// + /// The class code assigned by the USB-IF. A value of 0xFF + /// will match any class code. + /// + UINT8 DeviceClass; + /// + /// The subclass code assigned by the USB-IF. A value of + /// 0xFF will match any subclass code. + /// + UINT8 DeviceSubClass; + /// + /// The protocol code assigned by the USB-IF. A value of + /// 0xFF will match any protocol code. + /// + UINT8 DeviceProtocol; +} USB_CLASS_DEVICE_PATH; + +/// +/// USB WWID Device Path SubType. +/// +#define MSG_USB_WWID_DP 0x10 + +/// +/// This device path describes a USB device using its serial number. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// USB interface number. + /// + UINT16 InterfaceNumber; + /// + /// USB vendor id of the device. + /// + UINT16 VendorId; + /// + /// USB product id of the device. + /// + UINT16 ProductId; + /// + /// Last 64-or-fewer UTF-16 characters of the USB + /// serial number. The length of the string is + /// determined by the Length field less the offset of the + /// Serial Number field (10) + /// + /// CHAR16 SerialNumber[...]; +} USB_WWID_DEVICE_PATH; + +/// +/// Device Logical Unit SubType. +/// +#define MSG_DEVICE_LOGICAL_UNIT_DP 0x11 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Logical Unit Number for the interface. + /// + UINT8 Lun; +} DEVICE_LOGICAL_UNIT_DEVICE_PATH; + +/// +/// SATA Device Path SubType. +/// +#define MSG_SATA_DP 0x12 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// The HBA port number that facilitates the connection to the + /// device or a port multiplier. The value 0xFFFF is reserved. + /// + UINT16 HBAPortNumber; + /// + /// The Port multiplier port number that facilitates the connection + /// to the device. Must be set to 0xFFFF if the device is directly + /// connected to the HBA. + /// + UINT16 PortMultiplierPortNumber; + /// + /// Logical Unit Number. + /// + UINT16 Lun; +} SATA_DEVICE_PATH; + +/// +/// Flag for if the device is directly connected to the HBA. +/// +#define SATA_HBA_DIRECT_CONNECT_FLAG 0x8000 + +/// +/// I2O Device Path SubType. +/// +#define MSG_I2O_DP 0x06 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Target ID (TID) for a device. + /// + UINT32 Tid; +} I2O_DEVICE_PATH; + +/// +/// MAC Address Device Path SubType. +/// +#define MSG_MAC_ADDR_DP 0x0b +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// The MAC address for a network interface padded with 0s. + /// + EFI_MAC_ADDRESS MacAddress; + /// + /// Network interface type(i.e. 802.3, FDDI). + /// + UINT8 IfType; +} MAC_ADDR_DEVICE_PATH; + +/// +/// IPv4 Device Path SubType +/// +#define MSG_IPv4_DP 0x0c +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// The local IPv4 address. + /// + EFI_IPv4_ADDRESS LocalIpAddress; + /// + /// The remote IPv4 address. + /// + EFI_IPv4_ADDRESS RemoteIpAddress; + /// + /// The local port number. + /// + UINT16 LocalPort; + /// + /// The remote port number. + /// + UINT16 RemotePort; + /// + /// The network protocol(i.e. UDP, TCP). + /// + UINT16 Protocol; + /// + /// 0x00 - The Source IP Address was assigned though DHCP. + /// 0x01 - The Source IP Address is statically bound. + /// + BOOLEAN StaticIpAddress; + /// + /// The gateway IP address + /// + EFI_IPv4_ADDRESS GatewayIpAddress; + /// + /// The subnet mask + /// + EFI_IPv4_ADDRESS SubnetMask; +} IPv4_DEVICE_PATH; + +/// +/// IPv6 Device Path SubType. +/// +#define MSG_IPv6_DP 0x0d +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// The local IPv6 address. + /// + EFI_IPv6_ADDRESS LocalIpAddress; + /// + /// The remote IPv6 address. + /// + EFI_IPv6_ADDRESS RemoteIpAddress; + /// + /// The local port number. + /// + UINT16 LocalPort; + /// + /// The remote port number. + /// + UINT16 RemotePort; + /// + /// The network protocol(i.e. UDP, TCP). + /// + UINT16 Protocol; + /// + /// 0x00 - The Local IP Address was manually configured. + /// 0x01 - The Local IP Address is assigned through IPv6 + /// stateless auto-configuration. + /// 0x02 - The Local IP Address is assigned through IPv6 + /// stateful configuration. + /// + UINT8 IpAddressOrigin; + /// + /// The prefix length + /// + UINT8 PrefixLength; + /// + /// The gateway IP address + /// + EFI_IPv6_ADDRESS GatewayIpAddress; +} IPv6_DEVICE_PATH; + +/// +/// InfiniBand Device Path SubType. +/// +#define MSG_INFINIBAND_DP 0x09 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Flags to help identify/manage InfiniBand device path elements: + /// Bit 0 - IOC/Service (0b = IOC, 1b = Service). + /// Bit 1 - Extend Boot Environment. + /// Bit 2 - Console Protocol. + /// Bit 3 - Storage Protocol. + /// Bit 4 - Network Protocol. + /// All other bits are reserved. + /// + UINT32 ResourceFlags; + /// + /// 128-bit Global Identifier for remote fabric port. + /// + UINT8 PortGid[16]; + /// + /// 64-bit unique identifier to remote IOC or server process. + /// Interpretation of field specified by Resource Flags (bit 0). + /// + UINT64 ServiceId; + /// + /// 64-bit persistent ID of remote IOC port. + /// + UINT64 TargetPortId; + /// + /// 64-bit persistent ID of remote device. + /// + UINT64 DeviceId; +} INFINIBAND_DEVICE_PATH; + +#define INFINIBAND_RESOURCE_FLAG_IOC_SERVICE 0x01 +#define INFINIBAND_RESOURCE_FLAG_EXTENDED_BOOT_ENVIRONMENT 0x02 +#define INFINIBAND_RESOURCE_FLAG_CONSOLE_PROTOCOL 0x04 +#define INFINIBAND_RESOURCE_FLAG_STORAGE_PROTOCOL 0x08 +#define INFINIBAND_RESOURCE_FLAG_NETWORK_PROTOCOL 0x10 + +/// +/// UART Device Path SubType. +/// +#define MSG_UART_DP 0x0e +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Reserved. + /// + UINT32 Reserved; + /// + /// The baud rate setting for the UART style device. A value of 0 + /// means that the device's default baud rate will be used. + /// + UINT64 BaudRate; + /// + /// The number of data bits for the UART style device. A value + /// of 0 means that the device's default number of data bits will be used. + /// + UINT8 DataBits; + /// + /// The parity setting for the UART style device. + /// Parity 0x00 - Default Parity. + /// Parity 0x01 - No Parity. + /// Parity 0x02 - Even Parity. + /// Parity 0x03 - Odd Parity. + /// Parity 0x04 - Mark Parity. + /// Parity 0x05 - Space Parity. + /// + UINT8 Parity; + /// + /// The number of stop bits for the UART style device. + /// Stop Bits 0x00 - Default Stop Bits. + /// Stop Bits 0x01 - 1 Stop Bit. + /// Stop Bits 0x02 - 1.5 Stop Bits. + /// Stop Bits 0x03 - 2 Stop Bits. + /// + UINT8 StopBits; +} UART_DEVICE_PATH; + +/// +/// NVDIMM Namespace Device Path SubType. +/// +#define NVDIMM_NAMESPACE_DP 0x20 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Namespace unique label identifier UUID. + /// + EFI_GUID Uuid; +} NVDIMM_NAMESPACE_DEVICE_PATH; + +// +// Use VENDOR_DEVICE_PATH struct +// +#define MSG_VENDOR_DP 0x0a +typedef VENDOR_DEVICE_PATH VENDOR_DEFINED_DEVICE_PATH; + +#define DEVICE_PATH_MESSAGING_PC_ANSI EFI_PC_ANSI_GUID +#define DEVICE_PATH_MESSAGING_VT_100 EFI_VT_100_GUID +#define DEVICE_PATH_MESSAGING_VT_100_PLUS EFI_VT_100_PLUS_GUID +#define DEVICE_PATH_MESSAGING_VT_UTF8 EFI_VT_UTF8_GUID + +/// +/// A new device path node is defined to declare flow control characteristics. +/// UART Flow Control Messaging Device Path +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// DEVICE_PATH_MESSAGING_UART_FLOW_CONTROL GUID. + /// + EFI_GUID Guid; + /// + /// Bitmap of supported flow control types. + /// Bit 0 set indicates hardware flow control. + /// Bit 1 set indicates Xon/Xoff flow control. + /// All other bits are reserved and are clear. + /// + UINT32 FlowControlMap; +} UART_FLOW_CONTROL_DEVICE_PATH; + +#define UART_FLOW_CONTROL_HARDWARE 0x00000001 +#define UART_FLOW_CONTROL_XON_XOFF 0x00000010 + +#define DEVICE_PATH_MESSAGING_SAS EFI_SAS_DEVICE_PATH_GUID +/// +/// Serial Attached SCSI (SAS) Device Path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// DEVICE_PATH_MESSAGING_SAS GUID. + /// + EFI_GUID Guid; + /// + /// Reserved for future use. + /// + UINT32 Reserved; + /// + /// SAS Address for Serial Attached SCSI Target. + /// + UINT64 SasAddress; + /// + /// SAS Logical Unit Number. + /// + UINT64 Lun; + /// + /// More Information about the device and its interconnect. + /// + UINT16 DeviceTopology; + /// + /// Relative Target Port (RTP). + /// + UINT16 RelativeTargetPort; +} SAS_DEVICE_PATH; + +/// +/// Serial Attached SCSI (SAS) Ex Device Path SubType +/// +#define MSG_SASEX_DP 0x16 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// 8-byte array of the SAS Address for Serial Attached SCSI Target Port. + /// + UINT8 SasAddress[8]; + /// + /// 8-byte array of the SAS Logical Unit Number. + /// + UINT8 Lun[8]; + /// + /// More Information about the device and its interconnect. + /// + UINT16 DeviceTopology; + /// + /// Relative Target Port (RTP). + /// + UINT16 RelativeTargetPort; +} SASEX_DEVICE_PATH; + +/// +/// NvmExpress Namespace Device Path SubType. +/// +#define MSG_NVME_NAMESPACE_DP 0x17 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 NamespaceId; + UINT64 NamespaceUuid; +} NVME_NAMESPACE_DEVICE_PATH; + +/// +/// DNS Device Path SubType +/// +#define MSG_DNS_DP 0x1F +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Indicates the DNS server address is IPv4 or IPv6 address. + /// + UINT8 IsIPv6; + /// + /// Instance of the DNS server address. + /// + EFI_IP_ADDRESS DnsServerIp[]; +} DNS_DEVICE_PATH; + +/// +/// Uniform Resource Identifiers (URI) Device Path SubType +/// +#define MSG_URI_DP 0x18 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Instance of the URI pursuant to RFC 3986. + /// + CHAR8 Uri[]; +} URI_DEVICE_PATH; + +/// +/// Universal Flash Storage (UFS) Device Path SubType. +/// +#define MSG_UFS_DP 0x19 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Target ID on the UFS bus (PUN). + /// + UINT8 Pun; + /// + /// Logical Unit Number (LUN). + /// + UINT8 Lun; +} UFS_DEVICE_PATH; + +/// +/// SD (Secure Digital) Device Path SubType. +/// +#define MSG_SD_DP 0x1A +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 SlotNumber; +} SD_DEVICE_PATH; + +/// +/// EMMC (Embedded MMC) Device Path SubType. +/// +#define MSG_EMMC_DP 0x1D +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT8 SlotNumber; +} EMMC_DEVICE_PATH; + +/// +/// iSCSI Device Path SubType +/// +#define MSG_ISCSI_DP 0x13 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Network Protocol (0 = TCP, 1+ = reserved). + /// + UINT16 NetworkProtocol; + /// + /// iSCSI Login Options. + /// + UINT16 LoginOption; + /// + /// iSCSI Logical Unit Number. + /// + UINT64 Lun; + /// + /// iSCSI Target Portal group tag the initiator intends + /// to establish a session with. + /// + UINT16 TargetPortalGroupTag; + /// + /// iSCSI NodeTarget Name. The length of the name + /// is determined by subtracting the offset of this field from Length. + /// + /// CHAR8 iSCSI Target Name. +} ISCSI_DEVICE_PATH; + +#define ISCSI_LOGIN_OPTION_NO_HEADER_DIGEST 0x0000 +#define ISCSI_LOGIN_OPTION_HEADER_DIGEST_USING_CRC32C 0x0002 +#define ISCSI_LOGIN_OPTION_NO_DATA_DIGEST 0x0000 +#define ISCSI_LOGIN_OPTION_DATA_DIGEST_USING_CRC32C 0x0008 +#define ISCSI_LOGIN_OPTION_AUTHMETHOD_CHAP 0x0000 +#define ISCSI_LOGIN_OPTION_AUTHMETHOD_NON 0x1000 +#define ISCSI_LOGIN_OPTION_CHAP_BI 0x0000 +#define ISCSI_LOGIN_OPTION_CHAP_UNI 0x2000 + +/// +/// VLAN Device Path SubType. +/// +#define MSG_VLAN_DP 0x14 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// VLAN identifier (0-4094). + /// + UINT16 VlanId; +} VLAN_DEVICE_PATH; + +/// +/// Bluetooth Device Path SubType. +/// +#define MSG_BLUETOOTH_DP 0x1b +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// 48bit Bluetooth device address. + /// + BLUETOOTH_ADDRESS BD_ADDR; +} BLUETOOTH_DEVICE_PATH; + +/// +/// Wi-Fi Device Path SubType. +/// +#define MSG_WIFI_DP 0x1C +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Service set identifier. A 32-byte octets string. + /// + UINT8 SSId[32]; +} WIFI_DEVICE_PATH; + +/// +/// Bluetooth LE Device Path SubType. +/// +#define MSG_BLUETOOTH_LE_DP 0x1E +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + BLUETOOTH_LE_ADDRESS Address; +} BLUETOOTH_LE_DEVICE_PATH; + +// +// Media Device Path +// +#define MEDIA_DEVICE_PATH 0x04 + +/// +/// Hard Drive Media Device Path SubType. +/// +#define MEDIA_HARDDRIVE_DP 0x01 + +/// +/// The Hard Drive Media Device Path is used to represent a partition on a hard drive. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Describes the entry in a partition table, starting with entry 1. + /// Partition number zero represents the entire device. Valid + /// partition numbers for a MBR partition are [1, 4]. Valid + /// partition numbers for a GPT partition are [1, NumberOfPartitionEntries]. + /// + UINT32 PartitionNumber; + /// + /// Starting LBA of the partition on the hard drive. + /// + UINT64 PartitionStart; + /// + /// Size of the partition in units of Logical Blocks. + /// + UINT64 PartitionSize; + /// + /// Signature unique to this partition: + /// If SignatureType is 0, this field has to be initialized with 16 zeros. + /// If SignatureType is 1, the MBR signature is stored in the first 4 bytes of this field. + /// The other 12 bytes are initialized with zeros. + /// If SignatureType is 2, this field contains a 16 byte signature. + /// + UINT8 Signature[16]; + /// + /// Partition Format: (Unused values reserved). + /// 0x01 - PC-AT compatible legacy MBR. + /// 0x02 - GUID Partition Table. + /// + UINT8 MBRType; + /// + /// Type of Disk Signature: (Unused values reserved). + /// 0x00 - No Disk Signature. + /// 0x01 - 32-bit signature from address 0x1b8 of the type 0x01 MBR. + /// 0x02 - GUID signature. + /// + UINT8 SignatureType; +} HARDDRIVE_DEVICE_PATH; + +#define MBR_TYPE_PCAT 0x01 +#define MBR_TYPE_EFI_PARTITION_TABLE_HEADER 0x02 + +#define NO_DISK_SIGNATURE 0x00 +#define SIGNATURE_TYPE_MBR 0x01 +#define SIGNATURE_TYPE_GUID 0x02 + +/// +/// CD-ROM Media Device Path SubType. +/// +#define MEDIA_CDROM_DP 0x02 + +/// +/// The CD-ROM Media Device Path is used to define a system partition that exists on a CD-ROM. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Boot Entry number from the Boot Catalog. The Initial/Default entry is defined as zero. + /// + UINT32 BootEntry; + /// + /// Starting RBA of the partition on the medium. CD-ROMs use Relative logical Block Addressing. + /// + UINT64 PartitionStart; + /// + /// Size of the partition in units of Blocks, also called Sectors. + /// + UINT64 PartitionSize; +} CDROM_DEVICE_PATH; + +// +// Use VENDOR_DEVICE_PATH struct +// +#define MEDIA_VENDOR_DP 0x03 ///< Media vendor device path subtype. + +/// +/// File Path Media Device Path SubType +/// +#define MEDIA_FILEPATH_DP 0x04 +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// A NULL-terminated Path string including directory and file names. + /// + CHAR16 PathName[1]; +} FILEPATH_DEVICE_PATH; + +#define SIZE_OF_FILEPATH_DEVICE_PATH OFFSET_OF(FILEPATH_DEVICE_PATH,PathName) + +/// +/// Media Protocol Device Path SubType. +/// +#define MEDIA_PROTOCOL_DP 0x05 + +/// +/// The Media Protocol Device Path is used to denote the protocol that is being +/// used in a device path at the location of the path specified. +/// Many protocols are inherent to the style of device path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// The ID of the protocol. + /// + EFI_GUID Protocol; +} MEDIA_PROTOCOL_DEVICE_PATH; + +/// +/// PIWG Firmware File SubType. +/// +#define MEDIA_PIWG_FW_FILE_DP 0x06 + +/// +/// This device path is used by systems implementing the UEFI PI Specification 1.0 to describe a firmware file. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Firmware file name + /// + EFI_GUID FvFileName; +} MEDIA_FW_VOL_FILEPATH_DEVICE_PATH; + +/// +/// PIWG Firmware Volume Device Path SubType. +/// +#define MEDIA_PIWG_FW_VOL_DP 0x07 + +/// +/// This device path is used by systems implementing the UEFI PI Specification 1.0 to describe a firmware volume. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Firmware volume name. + /// + EFI_GUID FvName; +} MEDIA_FW_VOL_DEVICE_PATH; + +/// +/// Media relative offset range device path. +/// +#define MEDIA_RELATIVE_OFFSET_RANGE_DP 0x08 + +/// +/// Used to describe the offset range of media relative. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + UINT32 Reserved; + UINT64 StartingOffset; + UINT64 EndingOffset; +} MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH; + +/// +/// This GUID defines a RAM Disk supporting a raw disk format in volatile memory. +/// +#define EFI_VIRTUAL_DISK_GUID \ + { \ + 0x77AB535A, 0x45FC, 0x624B, {0x55, 0x60, 0xF7, 0xB2, 0x81, 0xD1, 0xF9, 0x6E } \ + } + +extern EFI_GUID gEfiVirtualDiskGuid; + +/// +/// This GUID defines a RAM Disk supporting an ISO image in volatile memory. +/// +#define EFI_VIRTUAL_CD_GUID \ + { \ + 0x3D5ABD30, 0x4175, 0x87CE, {0x6D, 0x64, 0xD2, 0xAD, 0xE5, 0x23, 0xC4, 0xBB } \ + } +extern EFI_GUID gEfiVirtualCdGuid; + +/// +/// This GUID defines a RAM Disk supporting a raw disk format in persistent memory. +/// +#define EFI_PERSISTENT_VIRTUAL_DISK_GUID \ + { \ + 0x5CEA02C9, 0x4D07, 0x69D3, {0x26, 0x9F ,0x44, 0x96, 0xFB, 0xE0, 0x96, 0xF9 } \ + } + +extern EFI_GUID gEfiPersistentVirtualDiskGuid; + +/// +/// This GUID defines a RAM Disk supporting an ISO image in persistent memory. +/// +#define EFI_PERSISTENT_VIRTUAL_CD_GUID \ + { \ + 0x08018188, 0x42CD, 0xBB48, {0x10, 0x0F, 0x53, 0x87, 0xD5, 0x3D, 0xED, 0x3D } \ + } + +extern EFI_GUID gEfiPersistentVirtualCdGuid; + +/// +/// Media ram disk device path. +/// +#define MEDIA_RAM_DISK_DP 0x09 + +/// +/// Used to describe the ram disk device path. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Starting Memory Address. + /// + UINT32 StartingAddr[2]; + /// + /// Ending Memory Address. + /// + UINT32 EndingAddr[2]; + /// + /// GUID that defines the type of the RAM Disk. + /// + EFI_GUID TypeGuid; + /// + /// RAM Diskinstance number, if supported. The default value is zero. + /// + UINT16 Instance; +} MEDIA_RAM_DISK_DEVICE_PATH; + +/// +/// BIOS Boot Specification Device Path. +/// +#define BBS_DEVICE_PATH 0x05 + +/// +/// BIOS Boot Specification Device Path SubType. +/// +#define BBS_BBS_DP 0x01 + +/// +/// This Device Path is used to describe the booting of non-EFI-aware operating systems. +/// +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + /// + /// Device Type as defined by the BIOS Boot Specification. + /// + UINT16 DeviceType; + /// + /// Status Flags as defined by the BIOS Boot Specification. + /// + UINT16 StatusFlag; + /// + /// Null-terminated ASCII string that describes the boot device to a user. + /// + CHAR8 String[1]; +} BBS_BBS_DEVICE_PATH; + +// +// DeviceType definitions - from BBS specification +// +#define BBS_TYPE_FLOPPY 0x01 +#define BBS_TYPE_HARDDRIVE 0x02 +#define BBS_TYPE_CDROM 0x03 +#define BBS_TYPE_PCMCIA 0x04 +#define BBS_TYPE_USB 0x05 +#define BBS_TYPE_EMBEDDED_NETWORK 0x06 +#define BBS_TYPE_BEV 0x80 +#define BBS_TYPE_UNKNOWN 0xFF + + +/// +/// Union of all possible Device Paths and pointers to Device Paths. +/// +typedef union { + EFI_DEVICE_PATH_PROTOCOL DevPath; + PCI_DEVICE_PATH Pci; + PCCARD_DEVICE_PATH PcCard; + MEMMAP_DEVICE_PATH MemMap; + VENDOR_DEVICE_PATH Vendor; + + CONTROLLER_DEVICE_PATH Controller; + BMC_DEVICE_PATH Bmc; + ACPI_HID_DEVICE_PATH Acpi; + ACPI_EXTENDED_HID_DEVICE_PATH ExtendedAcpi; + ACPI_ADR_DEVICE_PATH AcpiAdr; + + ATAPI_DEVICE_PATH Atapi; + SCSI_DEVICE_PATH Scsi; + ISCSI_DEVICE_PATH Iscsi; + FIBRECHANNEL_DEVICE_PATH FibreChannel; + FIBRECHANNELEX_DEVICE_PATH FibreChannelEx; + + F1394_DEVICE_PATH F1394; + USB_DEVICE_PATH Usb; + SATA_DEVICE_PATH Sata; + USB_CLASS_DEVICE_PATH UsbClass; + USB_WWID_DEVICE_PATH UsbWwid; + DEVICE_LOGICAL_UNIT_DEVICE_PATH LogicUnit; + I2O_DEVICE_PATH I2O; + MAC_ADDR_DEVICE_PATH MacAddr; + IPv4_DEVICE_PATH Ipv4; + IPv6_DEVICE_PATH Ipv6; + VLAN_DEVICE_PATH Vlan; + INFINIBAND_DEVICE_PATH InfiniBand; + UART_DEVICE_PATH Uart; + UART_FLOW_CONTROL_DEVICE_PATH UartFlowControl; + SAS_DEVICE_PATH Sas; + SASEX_DEVICE_PATH SasEx; + NVME_NAMESPACE_DEVICE_PATH NvmeNamespace; + DNS_DEVICE_PATH Dns; + URI_DEVICE_PATH Uri; + BLUETOOTH_DEVICE_PATH Bluetooth; + WIFI_DEVICE_PATH WiFi; + UFS_DEVICE_PATH Ufs; + SD_DEVICE_PATH Sd; + EMMC_DEVICE_PATH Emmc; + HARDDRIVE_DEVICE_PATH HardDrive; + CDROM_DEVICE_PATH CD; + + FILEPATH_DEVICE_PATH FilePath; + MEDIA_PROTOCOL_DEVICE_PATH MediaProtocol; + + MEDIA_FW_VOL_DEVICE_PATH FirmwareVolume; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FirmwareFile; + MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH Offset; + MEDIA_RAM_DISK_DEVICE_PATH RamDisk; + BBS_BBS_DEVICE_PATH Bbs; +} EFI_DEV_PATH; + + + +typedef union { + EFI_DEVICE_PATH_PROTOCOL *DevPath; + PCI_DEVICE_PATH *Pci; + PCCARD_DEVICE_PATH *PcCard; + MEMMAP_DEVICE_PATH *MemMap; + VENDOR_DEVICE_PATH *Vendor; + + CONTROLLER_DEVICE_PATH *Controller; + BMC_DEVICE_PATH *Bmc; + ACPI_HID_DEVICE_PATH *Acpi; + ACPI_EXTENDED_HID_DEVICE_PATH *ExtendedAcpi; + ACPI_ADR_DEVICE_PATH *AcpiAdr; + + ATAPI_DEVICE_PATH *Atapi; + SCSI_DEVICE_PATH *Scsi; + ISCSI_DEVICE_PATH *Iscsi; + FIBRECHANNEL_DEVICE_PATH *FibreChannel; + FIBRECHANNELEX_DEVICE_PATH *FibreChannelEx; + + F1394_DEVICE_PATH *F1394; + USB_DEVICE_PATH *Usb; + SATA_DEVICE_PATH *Sata; + USB_CLASS_DEVICE_PATH *UsbClass; + USB_WWID_DEVICE_PATH *UsbWwid; + DEVICE_LOGICAL_UNIT_DEVICE_PATH *LogicUnit; + I2O_DEVICE_PATH *I2O; + MAC_ADDR_DEVICE_PATH *MacAddr; + IPv4_DEVICE_PATH *Ipv4; + IPv6_DEVICE_PATH *Ipv6; + VLAN_DEVICE_PATH *Vlan; + INFINIBAND_DEVICE_PATH *InfiniBand; + UART_DEVICE_PATH *Uart; + UART_FLOW_CONTROL_DEVICE_PATH *UartFlowControl; + SAS_DEVICE_PATH *Sas; + SASEX_DEVICE_PATH *SasEx; + NVME_NAMESPACE_DEVICE_PATH *NvmeNamespace; + DNS_DEVICE_PATH *Dns; + URI_DEVICE_PATH *Uri; + BLUETOOTH_DEVICE_PATH *Bluetooth; + WIFI_DEVICE_PATH *WiFi; + UFS_DEVICE_PATH *Ufs; + SD_DEVICE_PATH *Sd; + EMMC_DEVICE_PATH *Emmc; + HARDDRIVE_DEVICE_PATH *HardDrive; + CDROM_DEVICE_PATH *CD; + + FILEPATH_DEVICE_PATH *FilePath; + MEDIA_PROTOCOL_DEVICE_PATH *MediaProtocol; + + MEDIA_FW_VOL_DEVICE_PATH *FirmwareVolume; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FirmwareFile; + MEDIA_RELATIVE_OFFSET_RANGE_DEVICE_PATH *Offset; + MEDIA_RAM_DISK_DEVICE_PATH *RamDisk; + BBS_BBS_DEVICE_PATH *Bbs; + UINT8 *Raw; +} EFI_DEV_PATH_PTR; + +#define EFI_DEBUGPORT_PROTOCOL_GUID \ + { \ + 0xEBA4E8D2, 0x3858, 0x41EC, {0xA2, 0x81, 0x26, 0x47, 0xBA, 0x96, 0x60, 0xD0 } \ + } +// +// DEBUGPORT variable definitions... +// +#define EFI_DEBUGPORT_VARIABLE_NAME L"DEBUGPORT" +#define EFI_DEBUGPORT_VARIABLE_GUID EFI_DEBUGPORT_PROTOCOL_GUID +extern EFI_GUID gEfiDebugPortVariableGuid; + +// +// DebugPort device path definitions... +// +#define DEVICE_PATH_MESSAGING_DEBUGPORT EFI_DEBUGPORT_PROTOCOL_GUID +extern EFI_GUID gEfiDebugPortProtocolGuid; + +typedef struct { + EFI_DEVICE_PATH_PROTOCOL Header; + EFI_GUID Guid; +} DEBUGPORT_DEVICE_PATH; + +#pragma pack() + +#define END_DEVICE_PATH_TYPE 0x7f +#define END_ENTIRE_DEVICE_PATH_SUBTYPE 0xFF +#define END_INSTANCE_DEVICE_PATH_SUBTYPE 0x01 + +extern EFI_GUID gEfiDevicePathProtocolGuid; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/DevicePathUtilities.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/DevicePathUtilities.h new file mode 100644 index 00000000..bd6920c6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/DevicePathUtilities.h @@ -0,0 +1,288 @@ +/** @file + EFI_DEVICE_PATH_UTILITIES_PROTOCOL as defined in UEFI 2.0. + Use to create and manipulate device paths and device nodes. + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __DEVICE_PATH_UTILITIES_H__ +#define __DEVICE_PATH_UTILITIES_H__ + +/// +/// Device Path Utilities protocol +/// +#define EFI_DEVICE_PATH_UTILITIES_GUID \ + { \ + 0x379be4e, 0xd706, 0x437d, {0xb0, 0x37, 0xed, 0xb8, 0x2f, 0xb7, 0x72, 0xa4 } \ + } + +/** + Returns the size of the device path, in bytes. + + @param DevicePath Points to the start of the EFI device path. + + @return Size Size of the specified device path, in bytes, including the end-of-path tag. + @retval 0 DevicePath is NULL + +**/ +typedef +UINTN +( *EFI_DEVICE_PATH_UTILS_GET_DEVICE_PATH_SIZE)( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + + +/** + Create a duplicate of the specified path. + + @param DevicePath Points to the source EFI device path. + + @retval Pointer A pointer to the duplicate device path. + @retval NULL insufficient memory or DevicePath is NULL + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +( *EFI_DEVICE_PATH_UTILS_DUP_DEVICE_PATH)( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/** + Create a new path by appending the second device path to the first. + If Src1 is NULL and Src2 is non-NULL, then a duplicate of Src2 is returned. + If Src1 is non-NULL and Src2 is NULL, then a duplicate of Src1 is returned. + If Src1 and Src2 are both NULL, then a copy of an end-of-device-path is returned. + + @param Src1 Points to the first device path. + @param Src2 Points to the second device path. + + @retval Pointer A pointer to the newly created device path. + @retval NULL Memory could not be allocated + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +( *EFI_DEVICE_PATH_UTILS_APPEND_PATH)( + CONST EFI_DEVICE_PATH_PROTOCOL *Src1, + CONST EFI_DEVICE_PATH_PROTOCOL *Src2 + ); + +/** + Creates a new path by appending the device node to the device path. + If DeviceNode is NULL then a copy of DevicePath is returned. + If DevicePath is NULL then a copy of DeviceNode, followed by an end-of-device path device node is returned. + If both DeviceNode and DevicePath are NULL then a copy of an end-of-device-path device node is returned. + + @param DevicePath Points to the device path. + @param DeviceNode Points to the device node. + + @retval Pointer A pointer to the allocated device node. + @retval NULL There was insufficient memory. + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +( *EFI_DEVICE_PATH_UTILS_APPEND_NODE)( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + CONST EFI_DEVICE_PATH_PROTOCOL *DeviceNode + ); + +/** + Creates a new path by appending the specified device path instance to the specified device path. + + @param DevicePath Points to the device path. If NULL, then ignored. + @param DevicePathInstance Points to the device path instance. + + @retval Pointer A pointer to the newly created device path + @retval NULL Memory could not be allocated or DevicePathInstance is NULL. + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +( *EFI_DEVICE_PATH_UTILS_APPEND_INSTANCE)( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance + ); + +/** + Creates a copy of the current device path instance and returns a pointer to the next device path + instance. + + @param DevicePathInstance On input, this holds the pointer to the current device path + instance. On output, this holds the pointer to the next + device path instance or NULL if there are no more device + path instances in the device path. + @param DevicePathInstanceSize On output, this holds the size of the device path instance, + in bytes or zero, if DevicePathInstance is NULL. + If NULL, then the instance size is not output. + + @retval Pointer A pointer to the copy of the current device path instance. + @retval NULL DevicePathInstance was NULL on entry or there was insufficient memory. + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +( *EFI_DEVICE_PATH_UTILS_GET_NEXT_INSTANCE)( + EFI_DEVICE_PATH_PROTOCOL **DevicePathInstance, + UINTN *DevicePathInstanceSize + ); + +/** + Creates a device node + + @param NodeType NodeType is the device node type (EFI_DEVICE_PATH.Type) for + the new device node. + @param NodeSubType NodeSubType is the device node sub-type + EFI_DEVICE_PATH.SubType) for the new device node. + @param NodeLength NodeLength is the length of the device node + (EFI_DEVICE_PATH.Length) for the new device node. + + @retval Pointer A pointer to the newly created device node. + @retval NULL NodeLength is less than + the size of the header or there was insufficient memory. + +**/ +typedef +EFI_DEVICE_PATH_PROTOCOL* +( *EFI_DEVICE_PATH_UTILS_CREATE_NODE)( + UINT8 NodeType, + UINT8 NodeSubType, + UINT16 NodeLength +); + +/** + Returns whether a device path is multi-instance. + + @param DevicePath Points to the device path. If NULL, then ignored. + + @retval TRUE The device path has more than one instance + @retval FALSE The device path is empty or contains only a single instance. + +**/ +typedef +BOOLEAN +( *EFI_DEVICE_PATH_UTILS_IS_MULTI_INSTANCE)( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +/// +/// This protocol is used to creates and manipulates device paths and device nodes. +/// +typedef struct { + EFI_DEVICE_PATH_UTILS_GET_DEVICE_PATH_SIZE GetDevicePathSize; + EFI_DEVICE_PATH_UTILS_DUP_DEVICE_PATH DuplicateDevicePath; + EFI_DEVICE_PATH_UTILS_APPEND_PATH AppendDevicePath; + EFI_DEVICE_PATH_UTILS_APPEND_NODE AppendDeviceNode; + EFI_DEVICE_PATH_UTILS_APPEND_INSTANCE AppendDevicePathInstance; + EFI_DEVICE_PATH_UTILS_GET_NEXT_INSTANCE GetNextDevicePathInstance; + EFI_DEVICE_PATH_UTILS_IS_MULTI_INSTANCE IsDevicePathMultiInstance; + EFI_DEVICE_PATH_UTILS_CREATE_NODE CreateDeviceNode; +} EFI_DEVICE_PATH_UTILITIES_PROTOCOL; + +extern EFI_GUID gEfiDevicePathUtilitiesProtocolGuid; + +VOID +SetDevicePathEndNode ( + VOID *Node + ); + +BOOLEAN +IsDevicePathValid ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + UINTN MaxSize + ); + +UINT8 +DevicePathType ( + CONST VOID *Node + ); + +UINT8 +DevicePathSubType ( + CONST VOID *Node + ); + +UINTN +DevicePathNodeLength ( + CONST VOID *Node + ); + +EFI_DEVICE_PATH_PROTOCOL * +NextDevicePathNode ( + CONST VOID *Node + ); + +BOOLEAN +IsDevicePathEndType ( + CONST VOID *Node + ); + +BOOLEAN +IsDevicePathEnd ( + CONST VOID *Node + ); +BOOLEAN +IsDevicePathEndInstance ( + CONST VOID *Node + ); + +UINT16 +SetDevicePathNodeLength ( + VOID *Node, + UINTN Length + ); + +VOID +SetDevicePathEndNode ( + VOID *Node + ); + +UINTN +UefiDevicePathLibGetDevicePathSize ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibDuplicateDevicePath ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibAppendDevicePath ( + CONST EFI_DEVICE_PATH_PROTOCOL *FirstDevicePath, + CONST EFI_DEVICE_PATH_PROTOCOL *SecondDevicePath + ); + +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibAppendDevicePathNode ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathNode + ); + +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibAppendDevicePathInstance ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath, + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePathInstance + ); + +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibGetNextDevicePathInstance ( + EFI_DEVICE_PATH_PROTOCOL **DevicePath, + UINTN *Size + ); + +EFI_DEVICE_PATH_PROTOCOL * +UefiDevicePathLibCreateDeviceNode ( + UINT8 NodeType, + UINT8 NodeSubType, + UINT16 NodeLength + ); + +BOOLEAN +UefiDevicePathLibIsDevicePathMultiInstance ( + CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/GraphicsOutput.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/GraphicsOutput.h new file mode 100644 index 00000000..d075365c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/GraphicsOutput.h @@ -0,0 +1,187 @@ +/** @file + Graphics Output Protocol from the UEFI 2.0 specification. + + Abstraction of a very simple graphics device. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __GRAPHICS_OUTPUT_H__ +#define __GRAPHICS_OUTPUT_H__ + +#define EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID \ + { \ + 0x9042a9de, 0x23dc, 0x4a38, {0x96, 0xfb, 0x7a, 0xde, 0xd0, 0x80, 0x51, 0x6a } \ + } + +typedef struct _EFI_GRAPHICS_OUTPUT_PROTOCOL EFI_GRAPHICS_OUTPUT_PROTOCOL; + +typedef struct { + UINT32 RedMask; + UINT32 GreenMask; + UINT32 BlueMask; + UINT32 ReservedMask; +} EFI_PIXEL_BITMASK; + +typedef enum { + PixelRedGreenBlueReserved8BitPerColor, + PixelBlueGreenRedReserved8BitPerColor, + PixelBitMask, + PixelBltOnly, + PixelFormatMax +} EFI_GRAPHICS_PIXEL_FORMAT; + +typedef struct { + UINT32 Version; + UINT32 HorizontalResolution; + UINT32 VerticalResolution; + EFI_GRAPHICS_PIXEL_FORMAT PixelFormat; + EFI_PIXEL_BITMASK PixelInformation; + UINT32 PixelsPerScanLine; +} EFI_GRAPHICS_OUTPUT_MODE_INFORMATION; + +/** + Return the current video mode information. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to return information on. + @param SizeOfInfo A pointer to the size, in bytes, of the Info buffer. + @param Info A pointer to callee allocated buffer that returns information about ModeNumber. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_BUFFER_TOO_SMALL The Info buffer was too small. + @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the video mode. + @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () + @retval EFI_INVALID_PARAMETER One of the input args was NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE) ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber, + OUT UINTN *SizeOfInfo, + OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION **Info + ) +; + +/** + Return the current video mode information. + + @param This Protocol instance pointer. + @param ModeNumber The mode number to be set. + + @retval EFI_SUCCESS Graphics mode was changed. + @retval EFI_DEVICE_ERROR The device had an error and could not complete the request. + @retval EFI_UNSUPPORTED ModeNumber is not supported by this device. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE) ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN UINT32 ModeNumber + ) +; + +typedef struct { + UINT8 Blue; + UINT8 Green; + UINT8 Red; + UINT8 Reserved; +} EFI_GRAPHICS_OUTPUT_BLT_PIXEL; + +typedef union { + EFI_GRAPHICS_OUTPUT_BLT_PIXEL Pixel; + UINT32 Raw; +} EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION; + +typedef enum { + EfiBltVideoFill, + EfiBltVideoToBltBuffer, + EfiBltBufferToVideo, + EfiBltVideoToVideo, + EfiGraphicsOutputBltOperationMax +} EFI_GRAPHICS_OUTPUT_BLT_OPERATION; + +/** + The following table defines actions for BltOperations: + + EfiBltVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY) + directly to every pixel of the video display rectangle + (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + Only one pixel will be used from the BltBuffer. Delta is NOT used. + + EfiBltVideoToBltBuffer - Read data from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in + the BltBuffer rectangle (DestinationX, DestinationY ) + (DestinationX + Width, DestinationY + Height). If DestinationX or + DestinationY is not zero then Delta must be set to the length in bytes + of a row in the BltBuffer. + + EfiBltBufferToVideo - Write data from the BltBuffer rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the + video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is + not zero then Delta must be set to the length in bytes of a row in the + BltBuffer. + + EfiBltVideoToVideo - Copy from the video display rectangle (SourceX, SourceY) + (SourceX + Width, SourceY + Height) .to the video display rectangle + (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + The BltBuffer and Delta are not used in this mode. + + @param This Protocol instance pointer. + @param BltBuffer Buffer containing data to blit into video buffer. This + buffer has a size of Width*Height*sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL) + @param BltOperation Operation to perform on BlitBuffer and video memory + @param SourceX X coordinate of source for the BltBuffer. + @param SourceY Y coordinate of source for the BltBuffer. + @param DestinationX X coordinate of destination for the BltBuffer. + @param DestinationY Y coordinate of destination for the BltBuffer. + @param Width Width of rectangle in BltBuffer in pixels. + @param Height Height of rectangle in BltBuffer in pixels. + @param Delta OPTIONAL + + @retval EFI_SUCCESS The Blt operation completed. + @retval EFI_INVALID_PARAMETER BltOperation is not valid. + @retval EFI_DEVICE_ERROR A hardware error occurred writing to the video buffer. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT) ( + IN EFI_GRAPHICS_OUTPUT_PROTOCOL *This, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer, OPTIONAL + IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ); + +typedef struct { + UINT32 MaxMode; + UINT32 Mode; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *Info; + UINTN SizeOfInfo; + EFI_PHYSICAL_ADDRESS FrameBufferBase; + UINTN FrameBufferSize; +} EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE; + +struct _EFI_GRAPHICS_OUTPUT_PROTOCOL { + EFI_GRAPHICS_OUTPUT_PROTOCOL_QUERY_MODE QueryMode; + EFI_GRAPHICS_OUTPUT_PROTOCOL_SET_MODE SetMode; + EFI_GRAPHICS_OUTPUT_PROTOCOL_BLT Blt; + EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *Mode; +}; + +extern EFI_GUID gEfiGraphicsOutputProtocolGuid; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/GuidedSectionExtraction.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/GuidedSectionExtraction.h new file mode 100644 index 00000000..6dfe1db3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/GuidedSectionExtraction.h @@ -0,0 +1,145 @@ +/** @file + This file declares GUIDed section extraction protocol. + + This interface provides a means of decoding a GUID defined encapsulation + section. There may be multiple different GUIDs associated with the GUIDed + section extraction protocol. That is, all instances of the GUIDed section + extraction protocol must have the same interface structure. + + @par Revision Reference: PI + Version 1.00. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL_H__ +#define __EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL_H__ + +// +// Forward reference for pure ANSI compatibility + +typedef struct _EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL; + + +/** + The ExtractSection() function processes the input section and + allocates a buffer from the pool in which it returns the section + contents. If the section being extracted contains + authentication information (the section's + GuidedSectionHeader.Attributes field has the + EFI_GUIDED_SECTION_AUTH_STATUS_VALID bit set), the values + returned in AuthenticationStatus must reflect the results of + the authentication operation. Depending on the algorithm and + size of the encapsulated data, the time that is required to do + a full authentication may be prohibitively long for some + classes of systems. To indicate this, use + EFI_SECURITY_POLICY_PROTOCOL_GUID, which may be published by + the security policy driver (see the Platform Initialization + Driver Execution Environment Core Interface Specification for + more details and the GUID definition). If the + EFI_SECURITY_POLICY_PROTOCOL_GUID exists in the handle + database, then, if possible, full authentication should be + skipped and the section contents simply returned in the + OutputBuffer. In this case, the + EFI_AUTH_STATUS_PLATFORM_OVERRIDE bit AuthenticationStatus + must be set on return. ExtractSection() is callable only from + TPL_NOTIFY and below. Behavior of ExtractSection() at any + EFI_TPL above TPL_NOTIFY is undefined. Type EFI_TPL is + defined in RaiseTPL() in the UEFI 2.0 specification. + + + @param This Indicates the + EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL instance. + + @param InputSection Buffer containing the input GUIDed section + to be processed. OutputBuffer OutputBuffer + is allocated from boot services pool + memory and contains the new section + stream. The caller is responsible for + freeing this buffer. + + @param OutputSize A pointer to a caller-allocated UINTN in + which the size of OutputBuffer allocation + is stored. If the function returns + anything other than EFI_SUCCESS, the value + of OutputSize is undefined. + + @param AuthenticationStatus A pointer to a caller-allocated + UINT32 that indicates the + authentication status of the + output buffer. If the input + section's + GuidedSectionHeader.Attributes + field has the + EFI_GUIDED_SECTION_AUTH_STATUS_VAL + bit as clear, AuthenticationStatus + must return zero. Both local bits + (19:16) and aggregate bits (3:0) + in AuthenticationStatus are + returned by ExtractSection(). + These bits reflect the status of + the extraction operation. The bit + pattern in both regions must be + the same, as the local and + aggregate authentication statuses + have equivalent meaning at this + level. If the function returns + anything other than EFI_SUCCESS, + the value of AuthenticationStatus + is undefined. + + + @retval EFI_SUCCESS The InputSection was successfully + processed and the section contents were + returned. + + @retval EFI_OUT_OF_RESOURCES The system has insufficient + resources to process the + request. + + @retval EFI_INVALID_PARAMETER The GUID in InputSection does + not match this instance of the + GUIDed Section Extraction + Protocol. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_EXTRACT_GUIDED_SECTION)( + IN CONST EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL *This, + IN CONST VOID *InputSection, + OUT VOID **OutputBuffer, + OUT UINTN *OutputSize, + OUT UINT32 *AuthenticationStatus +); + + +/** + + Takes the GUIDed section as input and produces the section + stream data. See the ExtractSection() function description. + +**/ +struct _EFI_GUIDED_SECTION_EXTRACTION_PROTOCOL { + EFI_EXTRACT_GUIDED_SECTION ExtractSection; +}; + +// +// Protocol GUID definition. Each GUIDed section extraction protocol has the +// same interface but with different GUID. All the GUIDs is defined here. +// May add multiple GUIDs here. +// +#define EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID \ + { \ + 0xFC1BCDB0, 0x7D31, 0x49aa, {0x93, 0x6A, 0xA4, 0x60, 0x0D, 0x9D, 0xD0, 0x83 } \ + } + +// +// may add other GUID here +// +extern EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/HiiFramework.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/HiiFramework.h new file mode 100644 index 00000000..5cf78739 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/HiiFramework.h @@ -0,0 +1,944 @@ +/** @file + This file defines the Human Interface Infrastructure protocol which will + be used by resources which want to publish IFR/Font/String data and have it + collected by the Configuration engine. + + @par Revision Reference: + This protocol is defined in HII spec 0.92. + + Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _FRAMEWORK_HII_H_ +#define _FRAMEWORK_HII_H_ + +//#include + +// +// To get EFI_GRAPHICS_OUTPUT_BLT_PIXEL, +// is defined in MdePkg/Protocol/GraphicsOutput.h +// +#include + +#define EFI_HII_PROTOCOL_GUID \ + { \ + 0xd7ad636e, 0xb997, 0x459b, {0xbf, 0x3f, 0x88, 0x46, 0x89, 0x79, 0x80, 0xe1} \ + } + +// BugBug: +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// If UGA goes away we need to put this some place. I'm not sure where? +// +//typedef struct { +// UINT8 Blue; +// UINT8 Green; +// UINT8 Red; +// UINT8 Reserved; +//} EFI_UGA_PIXEL; + +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +// + +typedef struct _EFI_HII_PROTOCOL EFI_HII_PROTOCOL; + +// +// Global definition +// +#define NARROW_CHAR 0xFFF0 +#define WIDE_CHAR 0xFFF1 +#define NON_BREAKING_CHAR 0xFFF2 +#define GLYPH_WIDTH 8 +#define GLYPH_HEIGHT 19 + +#define EFI_HII_FONT 1 +#define EFI_HII_STRING 2 +#define EFI_HII_IFR 3 +#define EFI_HII_KEYBOARD 4 +#define EFI_HII_HANDLES 5 +#define EFI_HII_VARIABLE 6 +#define EFI_HII_DEVICE_PATH 7 + + +// References to string tokens must use this macro to enable scanning for +// token usages. +// +#define STRING_TOKEN(t) t + +// +// The following types are currently defined: +// EFI_FROM_ID has been defined in UEFI spec. +// +typedef UINT16 EFI_FORM_LABEL; + +#pragma pack(1) + +typedef struct { + UINT32 Length; + UINT16 Type; +} EFI_HII_PACK_HEADER; + +// +// A form list consists of a large variety of structure +// possibilities so to represent the binary blob of data +// associated with a package of forms, we will assume a +// pointer to a self-describing data buffer. +// +typedef struct { + EFI_HII_PACK_HEADER Header; +} EFI_HII_IFR_PACK; + +typedef struct { + EFI_HII_PACK_HEADER Header; // Must be filled in + EFI_HANDLE ImageHandle; // Must be filled in + EFI_HANDLE DeviceHandle; // Optional + EFI_HANDLE ControllerHandle; // Optional + EFI_HANDLE CallbackHandle; // Optional + EFI_HANDLE COBExportHandle; // Optional +} EFI_HII_HANDLE_PACK; + +// +// ******************************************************** +// EFI_VARIABLE_CONTENTS +// ******************************************************** +// +typedef struct { + EFI_HII_PACK_HEADER Header; + EFI_GUID VariableGuid; + UINT32 VariableNameLength; + UINT16 VariableId; + // + // CHAR16 VariableName[]; //Null-terminated + // +} EFI_HII_VARIABLE_PACK; + +// +// ******************************************************** +// EFI_DEVICE_PATH_PACK +// ******************************************************** +// +typedef struct { + EFI_HII_PACK_HEADER Header; + // + // EFI_DEVICE_PATH DevicePath[]; + // +} EFI_HII_DEVICE_PATH_PACK; + +// +// ******************************************************** +// EFI_HII_DATA_TABLE +// ******************************************************** +// +typedef struct { + EFI_HII_HANDLE HiiHandle; + EFI_GUID PackageGuid; + UINT32 DataTableSize; + UINT32 IfrDataOffset; + UINT32 StringDataOffset; + UINT32 VariableDataOffset; + UINT32 DevicePathOffset; + UINT32 NumberOfVariableData; + UINT32 NumberOfLanguages; + // + // EFI_HII_DEVICE_PATH_PACK DevicePath[]; + // EFI_HII_VARIABLE_PACK VariableData[]; + // EFI_HII_IFR_PACK IfrData; + // EFI_HII_STRING_PACK StringData[]; + // +} EFI_HII_DATA_TABLE; + +// +// ******************************************************** +// EFI_HII_EXPORT_TABLE +// ******************************************************** +// +typedef struct { + UINT32 NumberOfHiiDataTables; + EFI_GUID Revision; + // + // EFI_HII_DATA_TABLE HiiDataTable[]; + // +} EFI_HII_EXPORT_TABLE; + +typedef struct { + BOOLEAN FormSetUpdate; // If TRUE, next variable is significant + EFI_PHYSICAL_ADDRESS FormCallbackHandle; // If not 0, will update Formset with this info + BOOLEAN FormUpdate; // If TRUE, next variable is significant + UINT16 FormValue; // specify which form is to be updated if FormUpdate value is TRUE. + STRING_REF FormTitle; // If not 0, will update Form with this info + UINT16 DataCount; // The number of Data entries in this structure + UINT8 *Data; // An array of 1+ op-codes, specified by DataCount +} EFI_HII_UPDATE_DATA; + +// +// String attributes +// +#define LANG_RIGHT_TO_LEFT 0x00000001 + +// +// A string package is used to localize strings to a particular +// language. The package is associated with a particular driver +// or set of drivers. Tools are used to associate tokens with +// string references in forms and in programs. These tokens are +// language agnostic. When paired with a language pack (directly +// or indirectly), the string token resolves into an actual +// UNICODE string. The NumStringPointers determines how many +// StringPointers (offset values) there are as well as the total +// number of Strings that are defined. +// +typedef struct { + EFI_HII_PACK_HEADER Header; + RELOFST LanguageNameString; + RELOFST PrintableLanguageName; + UINT32 NumStringPointers; + UINT32 Attributes; + // + // RELOFST StringPointers[]; + // EFI_STRING Strings[]; + // +} EFI_HII_STRING_PACK; + +// +// Glyph Attributes +// +#define EFI_GLYPH_NON_SPACING 1 +#define EFI_GLYPH_WIDE 2 + +typedef struct { + CHAR16 UnicodeWeight; + UINT8 Attributes; + UINT8 GlyphCol1[GLYPH_HEIGHT]; +} EFI_NARROW_GLYPH; + +typedef struct { + CHAR16 UnicodeWeight; + UINT8 Attributes; + UINT8 GlyphCol1[GLYPH_HEIGHT]; + UINT8 GlyphCol2[GLYPH_HEIGHT]; + UINT8 Pad[3]; +} EFI_WIDE_GLYPH; + +// +// A font list consists of a font header followed by a series +// of glyph structures. Note that fonts are not language specific. +// +typedef struct { + EFI_HII_PACK_HEADER Header; + UINT16 NumberOfNarrowGlyphs; + UINT16 NumberOfWideGlyphs; +} EFI_HII_FONT_PACK; + +// +// The IfrData in the EFI_HII_IFR_PACK structure definition +// is variable length, and not really part of the header. To +// simplify from code the size of the header, define an +// identical structure that does not include the IfrData field. +// Then use sizeof() this new structure to determine the +// actual size of the header. +// +typedef struct { + EFI_HII_PACK_HEADER Header; +} EFI_HII_IFR_PACK_HEADER; + +// +// pedef EFI_HII_PACK_HEADER EFI_HII_IFR_PACK_HEADER; +// +typedef enum { + EfiKeyLCtrl, + EfiKeyA0, + EfiKeyLAlt, + EfiKeySpaceBar, + EfiKeyA2, + EfiKeyA3, + EfiKeyA4, + EfiKeyRCtrl, + EfiKeyLeftArrow, + EfiKeyDownArrow, + EfiKeyRightArrow, + EfiKeyZero, + EfiKeyPeriod, + EfiKeyEnter, + EfiKeyLShift, + EfiKeyB0, + EfiKeyB1, + EfiKeyB2, + EfiKeyB3, + EfiKeyB4, + EfiKeyB5, + EfiKeyB6, + EfiKeyB7, + EfiKeyB8, + EfiKeyB9, + EfiKeyB10, + EfiKeyRshift, + EfiKeyUpArrow, + EfiKeyOne, + EfiKeyTwo, + EfiKeyThree, + EfiKeyCapsLock, + EfiKeyC1, + EfiKeyC2, + EfiKeyC3, + EfiKeyC4, + EfiKeyC5, + EfiKeyC6, + EfiKeyC7, + EfiKeyC8, + EfiKeyC9, + EfiKeyC10, + EfiKeyC11, + EfiKeyC12, + EfiKeyFour, + EfiKeyFive, + EfiKeySix, + EfiKeyPlus, + EfiKeyTab, + EfiKeyD1, + EfiKeyD2, + EfiKeyD3, + EfiKeyD4, + EfiKeyD5, + EfiKeyD6, + EfiKeyD7, + EfiKeyD8, + EfiKeyD9, + EfiKeyD10, + EfiKeyD11, + EfiKeyD12, + EfiKeyD13, + EfiKeyDel, + EfiKeyEnd, + EfiKeyPgDn, + EfiKeySeven, + EfiKeyEight, + EfiKeyNine, + EfiKeyE0, + EfiKeyE1, + EfiKeyE2, + EfiKeyE3, + EfiKeyE4, + EfiKeyE5, + EfiKeyE6, + EfiKeyE7, + EfiKeyE8, + EfiKeyE9, + EfiKeyE10, + EfiKeyE11, + EfiKeyE12, + EfiKeyBackSpace, + EfiKeyIns, + EfiKeyHome, + EfiKeyPgUp, + EfiKeyNLck, + EfiKeySlash, + EfiKeyAsterisk, + EfiKeyMinus, + EfiKeyEsc, + EfiKeyF1, + EfiKeyF2, + EfiKeyF3, + EfiKeyF4, + EfiKeyF5, + EfiKeyF6, + EfiKeyF7, + EfiKeyF8, + EfiKeyF9, + EfiKeyF10, + EfiKeyF11, + EfiKeyF12, + EfiKeyPrint, + EfiKeySLck, + EfiKeyPause +} EFI_KEY; + +typedef struct { + EFI_KEY Key; + CHAR16 Unicode; + CHAR16 ShiftedUnicode; + CHAR16 AltGrUnicode; + CHAR16 ShiftedAltGrUnicode; + UINT16 Modifier; +} EFI_KEY_DESCRIPTOR; + +// +// This structure allows a sparse set of keys to be redefined +// or a complete redefinition of the keyboard layout. Most +// keyboards have a lot of commonality in their layouts, therefore +// only defining those keys that need to change from the default +// minimizes the passed in information. +// +// Additionally, when an update occurs, the active keyboard layout +// will be switched to the newly updated keyboard layout. This +// allows for situations that when a keyboard layout driver is +// loaded as part of system initialization, the system will default +// the keyboard behavior to the new layout. +// +// Each call to update the keyboard mapping should contain the +// complete set of key descriptors to be updated, since every +// call to the HII which contains an EFI_HII_KEYBOARD_PACK will +// wipe the previous set of overrides. A call to +// +typedef struct { + EFI_HII_PACK_HEADER Header; + EFI_KEY_DESCRIPTOR *Descriptor; + UINT8 DescriptorCount; +} EFI_HII_KEYBOARD_PACK; + +// +// The EFI_HII_PACKAGES can contain different types of packages just +// after the structure as inline data. +// +typedef struct { + UINTN NumberOfPackages; + EFI_GUID *GuidId; + // + // EFI_HII_HANDLE_PACK *HandlePack; // Only one pack. + // EFI_HII_IFR_PACK *IfrPack; // Only one pack. + // EFI_HII_FONT_PACK *FontPack[]; // Multiple packs ok + // EFI_HII_STRING_PACK *StringPack[]; // Multiple packs ok + // EFI_HII_KEYBOARD_PACK *KeyboardPack[]; // Multiple packs ok + // +} EFI_HII_PACKAGES; + +typedef struct _EFI_HII_VARIABLE_PACK_LIST { + struct _EFI_HII_VARIABLE_PACK_LIST *NextVariablePack; + EFI_HII_VARIABLE_PACK *VariablePack; +} EFI_HII_VARIABLE_PACK_LIST; + + +#pragma pack() + +/** + Registers the various packs that are passed in via the Packages parameter. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Packages A pointer to an EFI_HII_PACKAGES package instance. + @param Handle A pointer to the EFI_HII_HANDLE instance. + + @retval EFI_SUCCESS Data was extracted from Packages, the database + was updated with the data, and Handle returned successfully. + @retval EFI_INVALID_PARAMETER The content of Packages was invalid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_NEW_PACK) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_PACKAGES *Packages, + OUT EFI_HII_HANDLE *Handle + ); + +/** + Removes a package from the HII database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle The handle that was registered to the data that is requested + for removal. + + @retval EFI_SUCCESS The data associated with the Handle was removed + from the HII database. + @retval EFI_INVALID_PARAMETER The Handle was not valid. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_REMOVE_PACK) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle + ); + +/** + Determines the handles that are currently active in the database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param HandleBufferLength On input, a pointer to the length of the handle + buffer. On output, the length of the handle buffer that is required + for the handles found. + @param Handle An array of EFI_HII_HANDLE instances returned. + + @retval EFI_SUCCESS Handle was updated successfully. + @retval EFI_BUFFER_TOO_SMALL The HandleBufferLength parameter indicates + that Handle is too small to support the number of handles. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_FIND_HANDLES) ( + IN EFI_HII_PROTOCOL *This, + IN OUT UINT16 *HandleBufferLength, + OUT EFI_HII_HANDLE *Handle + ); + +/** + Exports the contents of the database into a buffer. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle An EFI_HII_HANDLE that corresponds to the desired + handle to export. If the value is 0, the entire database will be exported. + In either case, the data will be exported in a format described by the + structure definition of EFI_HII_EXPORT_TABLE. + @param BufferSize + On input, a pointer to the length of the buffer. On output, the length + of the buffer that is required for the export data. + @param Buffer A pointer to a buffer that will contain the results of the export function. + + @retval EFI_SUCCESS The buffer was successfully filled with BufferSize amount of data. + @retval EFI_BUFFER_TOO_SMALL The value in BufferSize was too small to contain the export data. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_EXPORT) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ); + +/** + Remove any new strings that were added after the initial string export + for this handle. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle The handle on which the string resides. + + @retval EFI_SUCCESS Remove strings from the handle successfully. + @retval EFI_INVALID_PARAMETER The Handle was unknown. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_RESET_STRINGS) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle + ); + +/** + Tests if all of the characters in a string have corresponding font characters. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param StringToTest A pointer to a Unicode string. + @param FirstMissing A pointer to an index into the string. On input, + the index of the first character in the StringToTest to examine. On exit, + the index of the first character encountered for which a glyph is unavailable. + If all glyphs in the string are available, the index is the index of the + terminator of the string. + @param GlyphBufferSize A pointer to a value. On output, if the function + returns EFI_SUCCESS, it contains the amount of memory that is required to + store the string's glyph equivalent. + + @retval EFI_SUCCESS All glyphs are available. Note that an empty string + always returns this value. + @retval EFI_NOT_FOUND A glyph was not found for a character. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_TEST_STRING) ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *StringToTest, + IN OUT UINT32 *FirstMissing, + OUT UINT32 *GlyphBufferSize + ); + +/** + Translates a Unicode character into the corresponding font glyph. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Source A pointer to a Unicode string. + @param Index On input, the offset into the string from which to fetch + the character.On successful completion, the index is updated to the first + character past the character(s) making up the just extracted glyph. + @param GlyphBuffer Pointer to an array where the glyphs corresponding + to the characters in the source may be stored. GlyphBuffer is assumed + to be wide enough to accept a wide glyph character. + @param BitWidth If EFI_SUCCESS was returned, the UINT16 pointed to by + this value is filled with the length of the glyph in pixels. It is unchanged + if the call was unsuccessful. + @param InternalStatus The cell pointed to by this parameter must be + initialized to zero prior to invoking the call the first time for any string. + + @retval EFI_SUCCESS It worked. + @retval EFI_NOT_FOUND A glyph for a character was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_GLYPH) ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Source, + IN OUT UINT16 *Index, + OUT UINT8 **GlyphBuffer, + OUT UINT16 *BitWidth, + IN OUT UINT32 *InternalStatus + ); + +/** + Translates a glyph into the format required for input to the Universal + Graphics Adapter (UGA) Block Transfer (BLT) routines. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param GlyphBuffer A pointer to the buffer that contains glyph data. + @param Foreground The foreground setting requested to be used for the + generated BltBuffer data. + @param Background The background setting requested to be used for the + generated BltBuffer data. + @param Count The entry in the BltBuffer upon which to act. + @param Width The width in bits of the glyph being converted. + @param Height The height in bits of the glyph being converted + @param BltBuffer A pointer to the buffer that contains the data that is + ready to be used by the UGA BLT routines. + + @retval EFI_SUCCESS It worked. + @retval EFI_NOT_FOUND A glyph for a character was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GLYPH_TO_BLT) ( + IN EFI_HII_PROTOCOL *This, + IN UINT8 *GlyphBuffer, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Foreground, + IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background, + IN UINTN Count, + IN UINTN Width, + IN UINTN Height, + IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer + ); + +/** + Allows a new string to be added to an already existing string package. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Pointer to a NULL-terminated string containing a single ISO 639-2 + language identifier, indicating the language in which the string is translated. + @param Handle The handle of the language pack to which the string is to be added. + @param Reference The identifier of the string to be added. If the reference + value is zero, then the string will be assigned a new identifier on that + handle for the language specified. Otherwise, the string will be updated + with the NewString Value. + @param NewString The string to be added. + + @retval EFI_SUCCESS The string was effectively registered. + @retval EFI_INVALID_PARAMETER The Handle was unknown. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_NEW_STRING) ( + IN EFI_HII_PROTOCOL *This, + IN CHAR16 *Language, + IN EFI_HII_HANDLE Handle, + IN OUT STRING_REF *Reference, + IN CHAR16 *NewString + ); + +/** + Allows a program to determine the primary languages that are supported + on a given handle. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle The handle on which the strings reside. + @param LanguageString A string allocated by GetPrimaryLanguages() that + contains a list of all primary languages registered on the handle. + + @retval EFI_SUCCESS LanguageString was correctly returned. + @retval EFI_INVALID_PARAMETER The Handle was unknown. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_PRI_LANGUAGES) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + OUT EFI_STRING *LanguageString + ); + +/** + Allows a program to determine which secondary languages are supported + on a given handle for a given primary language. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle The handle on which the strings reside. + @param PrimaryLanguage Pointer to a NULL-terminated string containing a single + ISO 639-2 language identifier, indicating the primary language. + @param LanguageString A string allocated by GetSecondaryLanguages() + containing a list of all secondary languages registered on the handle. + + @retval EFI_SUCCESS LanguageString was correctly returned. + @retval EFI_INVALID_PARAMETER The Handle was unknown. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_SEC_LANGUAGES) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN CHAR16 *PrimaryLanguage, + OUT EFI_STRING *LanguageString + ); + +/** + Extracts a string from a package already registered with the EFI HII database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle The handle on which the string resides. + @param Token The string token assigned to the string. + @param Raw If TRUE, the string is returned unedited in the internal + storage format described above. If false, the string returned is edited + by replacing with and by removing special characters such + as the prefix. + @param LanguageString Pointer to a NULL-terminated string containing a + single ISO 639-2 language identifier, indicating the language to print. + If the LanguageString is empty (starts with a NULL), the default system + language will be used to determine the language. + @param BufferLength Length of the StringBuffer. + @param StringBuffer The buffer designed to receive the characters in the string. + + @retval EFI_SUCCESS StringBuffer is filled with a NULL-terminated string. + @retval EFI_INVALID_PARAMETER The handle or string token is unknown. + @retval EFI_BUFFER_TOO_SMALL The buffer provided was not large enough to + allow the entire string to be stored. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_STRING) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN BOOLEAN Raw, + IN CHAR16 *LanguageString, + IN OUT UINTN *BufferLength, + OUT EFI_STRING StringBuffer + ); + +/** + Allows a program to extract a part of a string of not more than a given width. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle The handle on which the string resides. + @param Token The string token assigned to the string. + @param Index On input, the offset into the string where the line is to start. + On output, the index is updated to point to beyond the last character returned + in the call. + @param LineWidth The maximum width of the line in units of narrow glyphs. + @param LanguageString Pointer to a NULL-terminated string containing a + single ISO 639-2 language identifier, indicating the language to print. + @param BufferLength Pointer to the length of the StringBuffer. + @param StringBuffer The buffer designed to receive the characters in the string. + + @retval EFI_SUCCESS StringBuffer filled with characters that will fit on the line. + @retval EFI_NOT_FOUND The font glyph for at least one of the characters in + the string is not in the font database. + @retval EFI_BUFFER_TOO_SMALL The buffer provided was not large enough + to allow the entire string to be stored. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_LINE) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN STRING_REF Token, + IN OUT UINT16 *Index, + IN UINT16 LineWidth, + IN CHAR16 *LanguageString, + IN OUT UINT16 *BufferLength, + OUT EFI_STRING StringBuffer + ); + +/** + Allows a program to extract a form or form package that has previously + been registered with the HII database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle Handle on which the form resides. + @param FormId The ID of the form to return. If the ID is zero, + the entire form package is returned. + @param BufferLength On input, the length of the Buffer. On output, + the length of the returned buffer, + @param Buffer The buffer designed to receive the form(s). + + @retval EFI_SUCCESS Buffer filled with the requested forms. BufferLength + was updated. + @retval EFI_INVALID_PARAMETER The handle is unknown. + @retval EFI_NOT_FOUND A form on the requested handle cannot be found with + the requested FormId. + @retval EFI_BUFFER_TOO_SMALL The buffer provided was not large enough + to allow the form to be stored. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_FORMS) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_ID FormId, + IN OUT UINTN *BufferLength, + OUT UINT8 *Buffer + ); + +/** + Extracts the defaults that are associated with a given handle in the HII database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle The HII handle from which will have default data retrieved. + @param DefaultMask The mask used to specify some type of default override when extracting + the default image data. + @param VariablePackList A indirect pointer to the first entry of a link list with + type EFI_HII_VARIABLE_PACK_LIST. + + @retval EFI_SUCCESS The VariablePackList was populated with the appropriate + default setting data. + @retval EFI_NOT_FOUND The IFR does not have any explicit or default map(s). + @retval EFI_INVALID_PARAMETER The HII database entry associated with Handle + contain invalid data. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_DEFAULT_IMAGE) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN UINTN DefaultMask, + OUT EFI_HII_VARIABLE_PACK_LIST **VariablePackList + ); + +/** + Allows the caller to update a form or form package that has previously been + registered with the EFI HII database. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param Handle Handle of the package where the form to be updated resides. + @param Label The label inside the form package where the update is to take place. + @param AddData If TRUE, adding data at a given Label; otherwise, + if FALSE, removing data at a given Label. + @param Data The buffer containing the new tags to insert after the Label + + @retval EFI_SUCCESS The form was updated with the new tags. + @retval EFI_INVALID_PARAMETER The buffer for the buffer length does not + contain an integral number of tags. + @retval EFI_NOT_FOUND The Handle, Label, or FormId was not found. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_UPDATE_FORM) ( + IN EFI_HII_PROTOCOL *This, + IN EFI_HII_HANDLE Handle, + IN EFI_FORM_LABEL Label, + IN BOOLEAN AddData, + IN EFI_HII_UPDATE_DATA *Data + ); + +/** + Retrieves the current keyboard layout. + + @param This A pointer to the EFI_HII_PROTOCOL instance. + @param DescriptorCount A pointer to the number of Descriptor entries being + described in the keyboard layout being retrieved. + @param Descriptor A pointer to a buffer containing an array of EFI_KEY_DESCRIPTOR + entries. Each entry will reflect the definition of a specific physical key. + + @retval EFI_SUCCESS The keyboard layout was retrieved successfully. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_HII_GET_KEYBOARD_LAYOUT) ( + IN EFI_HII_PROTOCOL *This, + OUT UINT16 *DescriptorCount, + OUT EFI_KEY_DESCRIPTOR *Descriptor + ); + +/** + @par Protocol Description: + The HII Protocol manages the HII database, which is a repository for data + having to do with fonts, strings, forms, keyboards, and other future human + interface items. + + @param NewPack + Extracts the various packs from a package list. + + @param RemovePack + Removes a package from the HII database. + + @param FindHandles + Determines the handles that are currently active in the database. + + @param ExportDatabase + Export the entire contents of the database to a buffer. + + @param TestString + Tests if all of the characters in a string have corresponding font characters. + + @param GetGlyph + Translates a Unicode character into the corresponding font glyph. + + @param GlyphToBlt + Converts a glyph value into a format that is ready for a UGA BLT command. + + @param NewString + Allows a new string to be added to an already existing string package. + + @param GetPrimaryLanguages + Allows a program to determine the primary languages that are supported + on a given handle. + + @param GetSecondaryLanguages + Allows a program to determine which secondary languages are supported + on a given handle for a given primary language. + + @param GetString + Extracts a string from a package that is already registered with the + EFI HII database. + + @param ResetString + Remove any new strings that were added after the initial string export + for this handle. + + @param GetLine + Allows a program to extract a part of a string of not more than a given width. + + @param GetForms + Allows a program to extract a form or form package that has been previously registered. + + @param GetDefaultImage + Allows a program to extract the nonvolatile image that represents the default storage image. + + @param UpdateForm + Allows a program to update a previously registered form. + + @param GetKeyboardLayout + Allows a program to extract the current keyboard layout. + +**/ +struct _EFI_HII_PROTOCOL { + EFI_HII_NEW_PACK NewPack; + EFI_HII_REMOVE_PACK RemovePack; + EFI_HII_FIND_HANDLES FindHandles; + EFI_HII_EXPORT ExportDatabase; + + EFI_HII_TEST_STRING TestString; + EFI_HII_GET_GLYPH GetGlyph; + EFI_HII_GLYPH_TO_BLT GlyphToBlt; + + EFI_HII_NEW_STRING NewString; + EFI_HII_GET_PRI_LANGUAGES GetPrimaryLanguages; + EFI_HII_GET_SEC_LANGUAGES GetSecondaryLanguages; + EFI_HII_GET_STRING GetString; + EFI_HII_RESET_STRINGS ResetStrings; + EFI_HII_GET_LINE GetLine; + EFI_HII_GET_FORMS GetForms; + EFI_HII_GET_DEFAULT_IMAGE GetDefaultImage; + EFI_HII_UPDATE_FORM UpdateForm; + + EFI_HII_GET_KEYBOARD_LAYOUT GetKeyboardLayout; +}; + +extern EFI_GUID gEfiHiiProtocolGuid; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/UgaDraw.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/UgaDraw.h new file mode 100644 index 00000000..6c58660e --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/Protocol/UgaDraw.h @@ -0,0 +1,161 @@ +/** @file + UGA Draw protocol from the EFI 1.1 specification. + + Abstraction of a very simple graphics device. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __UGA_DRAW_H__ +#define __UGA_DRAW_H__ + +#define EFI_UGA_DRAW_PROTOCOL_GUID \ + { \ + 0x982c298b, 0xf4fa, 0x41cb, {0xb8, 0x38, 0x77, 0xaa, 0x68, 0x8f, 0xb8, 0x39 } \ + } + +typedef struct _EFI_UGA_DRAW_PROTOCOL EFI_UGA_DRAW_PROTOCOL; + +/** + Return the current video mode information. + + @param This Protocol instance pointer. + @param HorizontalResolution Current video horizontal resolution in pixels + @param VerticalResolution Current video vertical resolution in pixels + @param ColorDepth Current video color depth in bits per pixel + @param RefreshRate Current video refresh rate in Hz. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () + @retval EFI_INVALID_PARAMETER One of the input args was NULL. + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UGA_DRAW_PROTOCOL_GET_MODE) ( + IN EFI_UGA_DRAW_PROTOCOL *This, + OUT UINT32 *HorizontalResolution, + OUT UINT32 *VerticalResolution, + OUT UINT32 *ColorDepth, + OUT UINT32 *RefreshRate + ) +; + +/** + Return the current video mode information. + + @param This Protocol instance pointer. + @param HorizontalResolution Current video horizontal resolution in pixels + @param VerticalResolution Current video vertical resolution in pixels + @param ColorDepth Current video color depth in bits per pixel + @param RefreshRate Current video refresh rate in Hz. + + @retval EFI_SUCCESS Mode information returned. + @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode () + +**/ +typedef +EFI_STATUS +(EFIAPI *EFI_UGA_DRAW_PROTOCOL_SET_MODE) ( + IN EFI_UGA_DRAW_PROTOCOL *This, + IN UINT32 HorizontalResolution, + IN UINT32 VerticalResolution, + IN UINT32 ColorDepth, + IN UINT32 RefreshRate + ) +; + +typedef struct { + UINT8 Blue; + UINT8 Green; + UINT8 Red; + UINT8 Reserved; +} EFI_UGA_PIXEL; + +typedef union { + EFI_UGA_PIXEL Pixel; + UINT32 Raw; +} EFI_UGA_PIXEL_UNION; + +typedef enum { + EfiUgaVideoFill, + EfiUgaVideoToBltBuffer, + EfiUgaBltBufferToVideo, + EfiUgaVideoToVideo, + EfiUgaBltMax +} EFI_UGA_BLT_OPERATION; + +/** + Type specifying a pointer to a function to perform an UGA Blt operation. + + The following table defines actions for BltOperations: + + EfiUgaVideoFill - Write data from the BltBuffer pixel (SourceX, SourceY) + directly to every pixel of the video display rectangle + (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + Only one pixel will be used from the BltBuffer. Delta is NOT used. + + EfiUgaVideoToBltBuffer - Read data from the video display rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) and place it in + the BltBuffer rectangle (DestinationX, DestinationY ) + (DestinationX + Width, DestinationY + Height). If DestinationX or + DestinationY is not zero then Delta must be set to the length in bytes + of a row in the BltBuffer. + + EfiUgaBltBufferToVideo - Write data from the BltBuffer rectangle + (SourceX, SourceY) (SourceX + Width, SourceY + Height) directly to the + video display rectangle (DestinationX, DestinationY) + (DestinationX + Width, DestinationY + Height). If SourceX or SourceY is + not zero then Delta must be set to the length in bytes of a row in the + BltBuffer. + + EfiUgaVideoToVideo - Copy from the video display rectangle (SourceX, SourceY) + (SourceX + Width, SourceY + Height) .to the video display rectangle + (DestinationX, DestinationY) (DestinationX + Width, DestinationY + Height). + The BltBuffer and Delta are not used in this mode. + + + @param[in] This - Protocol instance pointer. + @param[in] BltBuffer - Buffer containing data to blit into video buffer. This + buffer has a size of Width*Height*sizeof(EFI_UGA_PIXEL) + @param[in] BltOperation - Operation to perform on BlitBuffer and video memory + @param[in] SourceX - X coordinate of source for the BltBuffer. + @param[in] SourceY - Y coordinate of source for the BltBuffer. + @param[in] DestinationX - X coordinate of destination for the BltBuffer. + @param[in] DestinationY - Y coordinate of destination for the BltBuffer. + @param[in] Width - Width of rectangle in BltBuffer in pixels. + @param[in] Height - Height of rectangle in BltBuffer in pixels. + @param[in] Delta - OPTIONAL + + @retval EFI_SUCCESS - The Blt operation completed. + @retval EFI_INVALID_PARAMETER - BltOperation is not valid. + @retval EFI_DEVICE_ERROR - A hardware error occurred writing to the video buffer. + +--*/ +typedef +EFI_STATUS +(EFIAPI *EFI_UGA_DRAW_PROTOCOL_BLT) ( + IN EFI_UGA_DRAW_PROTOCOL * This, + IN EFI_UGA_PIXEL * BltBuffer, OPTIONAL + IN EFI_UGA_BLT_OPERATION BltOperation, + IN UINTN SourceX, + IN UINTN SourceY, + IN UINTN DestinationX, + IN UINTN DestinationY, + IN UINTN Width, + IN UINTN Height, + IN UINTN Delta OPTIONAL + ); + +struct _EFI_UGA_DRAW_PROTOCOL { + EFI_UGA_DRAW_PROTOCOL_GET_MODE GetMode; + EFI_UGA_DRAW_PROTOCOL_SET_MODE SetMode; + EFI_UGA_DRAW_PROTOCOL_BLT Blt; +}; + +extern EFI_GUID gEfiUgaDrawProtocolGuid; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/RiscV64/ProcessorBind.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/RiscV64/ProcessorBind.h new file mode 100644 index 00000000..3446334d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/RiscV64/ProcessorBind.h @@ -0,0 +1,85 @@ +/** @file + Processor or Compiler specific defines and types for RISC-V. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __PROCESSOR_BIND_H__ +#define __PROCESSOR_BIND_H__ + +// +// Define the processor type so other code can make processor based choices +// +#define MDE_CPU_RISCV64 + +// +// Make sure we are using the correct packing rules per EFI specification +// +#ifndef __GNUC__ +#pragma pack() +#endif + +// +// Use ANSI C 2000 stdint.h integer width declarations +// +#include +typedef uint8_t BOOLEAN; +typedef int8_t INT8; +typedef uint8_t UINT8; +typedef int16_t INT16; +typedef uint16_t UINT16; +typedef int32_t INT32; +typedef uint32_t UINT32; +typedef int64_t INT64; +typedef uint64_t UINT64; +typedef char CHAR8; +typedef uint16_t CHAR16; + +// +// Unsigned value of native width. (4 bytes on supported 32-bit processor instructions, +// 8 bytes on supported 64-bit processor instructions) +// +typedef UINT64 UINTN; + +// +// Signed value of native width. (4 bytes on supported 32-bit processor instructions, +// 8 bytes on supported 64-bit processor instructions) +// +typedef INT64 INTN; + +// +// Processor specific defines +// + +// +// A value of native width with the highest bit set. +// +#define MAX_BIT 0x8000000000000000 + +// +// A value of native width with the two highest bits set. +// +#define MAX_2_BITS 0xC000000000000000 + +// +// The stack alignment required for RISC-V +// +#define CPU_STACK_ALIGNMENT 16 + +// +// Modifier to ensure that all protocol member functions and EFI intrinsics +// use the correct C calling convention. All protocol member functions and +// EFI intrinsics are required to modify their member functions with EFIAPI. +// +#define EFIAPI + +#if defined(__GNUC__) + // + // For GNU assembly code, .global or .globl can declare global symbols. + // Define this macro to unify the usage. + // + #define ASM_GLOBAL .globl +#endif + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/X64/ProcessorBind.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/X64/ProcessorBind.h new file mode 100644 index 00000000..31ce7bba --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Include/X64/ProcessorBind.h @@ -0,0 +1,185 @@ +/** @file + Processor or Compiler specific defines and types x64 (Intel(r) EM64T, AMD64). + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __PROCESSOR_BIND_H__ +#define __PROCESSOR_BIND_H__ + +// +// Define the processor type so other code can make processor based choices +// +#define MDE_CPU_X64 + + +// +// Make sure we are useing the correct packing rules per EFI specification +// +#ifndef __GNUC__ +#pragma pack() +#endif + + +#if _MSC_EXTENSIONS + +// +// Disable warning that make it impossible to compile at /W4 +// This only works for Microsoft* tools +// + +// +// Disabling bitfield type checking warnings. +// +#pragma warning ( disable : 4214 ) + +// +// Disabling the unreferenced formal parameter warnings. +// +#pragma warning ( disable : 4100 ) + +// +// Disable slightly different base types warning as CHAR8 * can not be set +// to a constant string. +// +#pragma warning ( disable : 4057 ) + +// +// ASSERT(FALSE) or while (TRUE) are legal constructes so supress this warning +// +#pragma warning ( disable : 4127 ) + + +#endif + + +#if !defined(__GNUC__) && (__STDC_VERSION__ < 199901L) + // + // No ANSI C 2000 stdint.h integer width declarations, so define equivalents + // + + #if _MSC_EXTENSIONS + + + // + // use Microsoft C compiler dependent integer width types + // + typedef unsigned __int64 UINT64; + typedef __int64 INT64; + typedef unsigned __int32 UINT32; + typedef __int32 INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef char INT8; + #else + #ifdef _EFI_P64 + // + // P64 - is Intel Itanium(TM) speak for pointers being 64-bit and longs and ints + // are 32-bits + // + typedef unsigned long long UINT64; + typedef long long INT64; + typedef unsigned int UINT32; + typedef int INT32; + typedef unsigned short CHAR16; + typedef unsigned short UINT16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef char INT8; + #else + // + // Assume LP64 - longs and pointers are 64-bit. Ints are 32-bit. + // + typedef unsigned long UINT64; + typedef long INT64; + typedef unsigned int UINT32; + typedef int INT32; + typedef unsigned short UINT16; + typedef unsigned short CHAR16; + typedef short INT16; + typedef unsigned char BOOLEAN; + typedef unsigned char UINT8; + typedef char CHAR8; + typedef char INT8; + #endif + #endif + + #if !defined(UINT8_MAX) || !defined(VBOX) /* collides with iprt/stdint.h */ + #define UINT8_MAX 0xff + #endif + +#else + // + // Use ANSI C 2000 stdint.h integer width declarations + // + #include + typedef uint8_t BOOLEAN; + typedef int8_t INT8; + typedef uint8_t UINT8; + typedef int16_t INT16; + typedef uint16_t UINT16; + typedef int32_t INT32; + typedef uint32_t UINT32; + typedef int64_t INT64; + typedef uint64_t UINT64; + typedef char CHAR8; + typedef uint16_t CHAR16; + +#endif + +typedef UINT64 UINTN; +typedef INT64 INTN; + + +// +// Processor specific defines +// +#define MAX_BIT 0x8000000000000000ULL +#define MAX_2_BITS 0xC000000000000000ULL + +// +// Modifier to ensure that all protocol member functions and EFI intrinsics +// use the correct C calling convention. All protocol member functions and +// EFI intrinsics are required to modify their member functions with EFIAPI. +// +#if _MSC_EXTENSIONS + /// + /// Define the standard calling convention regardless of optimization level. + /// __cdecl is Microsoft* specific C extension. + /// + #define EFIAPI __cdecl +#elif __GNUC__ + /// + /// Define the standard calling convention regardless of optimization level. + /// efidecl is an extension to GCC that supports the differnece between x64 + /// GCC ABI and x64 Microsoft* ABI. EFI is closer to the Microsoft* ABI and + /// EFIAPI makes sure the right ABI is used for public interfaces. + /// eficecl is a work in progress and we do not yet have the compiler + /// + #define EFIAPI +#else + #define EFIAPI +#endif + +// +// The Microsoft* C compiler can removed references to unreferenced data items +// if the /OPT:REF linker option is used. We defined a macro as this is a +// a non standard extension +// +#if _MSC_EXTENSIONS + #define GLOBAL_REMOVE_IF_UNREFERENCED __declspec(selectany) +#else + #define GLOBAL_REMOVE_IF_UNREFERENCED +#endif + +#endif + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/GNUmakefile new file mode 100644 index 00000000..d8eb9cb4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/GNUmakefile @@ -0,0 +1,27 @@ +## @file +# GNU/Linux makefile for 'LzmaCompress' module build. +# +# Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +MAKEROOT ?= .. + +APPNAME = LzmaCompress + +LIBS = -lCommon + +SDK_C = Sdk/C + +OBJECTS = \ + LzmaCompress.o \ + $(SDK_C)/Alloc.o \ + $(SDK_C)/LzFind.o \ + $(SDK_C)/LzmaDec.o \ + $(SDK_C)/LzmaEnc.o \ + $(SDK_C)/7zFile.o \ + $(SDK_C)/7zStream.o \ + $(SDK_C)/Bra86.o + +include $(MAKEROOT)/Makefiles/app.makefile + +BUILD_CFLAGS += -D_7ZIP_ST diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LZMA-SDK-README.txt b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LZMA-SDK-README.txt new file mode 100644 index 00000000..553eacea --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LZMA-SDK-README.txt @@ -0,0 +1,3 @@ +LzmaCompress is based on the LZMA SDK 19.00. LZMA SDK 19.00 +was placed in the public domain on 2019-02-21. It was +released on the http://www.7-zip.org/sdk.html website. diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LzmaCompress.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LzmaCompress.c new file mode 100644 index 00000000..1ecc51c5 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LzmaCompress.c @@ -0,0 +1,406 @@ +/** @file + LZMA Compress/Decompress tool (LzmaCompress) + + Based on LZMA SDK 19.00: + LzmaUtil.c -- Test application for LZMA compression + 2019-02-21 : Igor Pavlov : Public domain + + Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include + +#include "Sdk/C/Alloc.h" +#include "Sdk/C/7zFile.h" +#include "Sdk/C/7zVersion.h" +#include "Sdk/C/LzmaDec.h" +#include "Sdk/C/LzmaEnc.h" +#include "Sdk/C/Bra.h" +#include "CommonLib.h" +#include "ParseInf.h" + +#define LZMA_HEADER_SIZE (LZMA_PROPS_SIZE + 8) + +typedef enum { + NoConverter, + X86Converter, + MaxConverter +} CONVERTER_TYPE; + +const char *kCantReadMessage = "Can not read input file"; +const char *kCantWriteMessage = "Can not write output file"; +const char *kCantAllocateMessage = "Can not allocate memory"; +const char *kDataErrorMessage = "Data error"; +const char *kInvalidParamValMessage = "Invalid parameter value"; + +static BoolInt mQuietMode = False; +static CONVERTER_TYPE mConType = NoConverter; + +UINT64 mDictionarySize = 28; +UINT64 mCompressionMode = 2; + +#define UTILITY_NAME "LzmaCompress" +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 2 +#define INTEL_COPYRIGHT \ + "Copyright (c) 2009-2018, Intel Corporation. All rights reserved." +void PrintHelp(char *buffer) +{ + strcat(buffer, + "\n" UTILITY_NAME " - " INTEL_COPYRIGHT "\n" + "Based on LZMA Utility " MY_VERSION_COPYRIGHT_DATE "\n" + "\nUsage: LzmaCompress -e|-d [options] \n" + " -e: encode file\n" + " -d: decode file\n" + " -o FileName, --output FileName: specify the output filename\n" + " --f86: enable converter for x86 code\n" + " -v, --verbose: increase output messages\n" + " -q, --quiet: reduce output messages\n" + " --debug [0-9]: set debug level\n" + " -a: set compression mode 0 = fast, 1 = normal, default: 1 (normal)\n" + " d: sets Dictionary size - [0, 27], default: 24 (16MB)\n" + " --version: display the program version and exit\n" + " -h, --help: display this help text\n" + ); +} + +int PrintError(char *buffer, const char *message) +{ + strcat(buffer, "\nError: "); + strcat(buffer, message); + strcat(buffer, "\n"); + return 1; +} + +int PrintErrorNumber(char *buffer, SRes val) +{ + sprintf(buffer + strlen(buffer), "\nError code: %x\n", (unsigned)val); + return 1; +} + +int PrintUserError(char *buffer) +{ + return PrintError(buffer, "Incorrect command"); +} + +void PrintVersion(char *buffer) +{ + sprintf (buffer, "%s Version %d.%d %s ", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION); +} + +static SRes Encode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize, CLzmaEncProps *props) +{ + SRes res; + size_t inSize = (size_t)fileSize; + Byte *inBuffer = 0; + Byte *outBuffer = 0; + Byte *filteredStream = 0; + size_t outSize; + + if (inSize != 0) { + inBuffer = (Byte *)MyAlloc(inSize); + if (inBuffer == 0) + return SZ_ERROR_MEM; + } else { + return SZ_ERROR_INPUT_EOF; + } + + if (SeqInStream_Read(inStream, inBuffer, inSize) != SZ_OK) { + res = SZ_ERROR_READ; + goto Done; + } + + // we allocate 105% of original size + 64KB for output buffer + outSize = (size_t)fileSize / 20 * 21 + (1 << 16); + outBuffer = (Byte *)MyAlloc(outSize); + if (outBuffer == 0) { + res = SZ_ERROR_MEM; + goto Done; + } + + { + int i; + for (i = 0; i < 8; i++) + outBuffer[i + LZMA_PROPS_SIZE] = (Byte)(fileSize >> (8 * i)); + } + + if (mConType != NoConverter) + { + filteredStream = (Byte *)MyAlloc(inSize); + if (filteredStream == 0) { + res = SZ_ERROR_MEM; + goto Done; + } + memcpy(filteredStream, inBuffer, inSize); + + if (mConType == X86Converter) { + { + UInt32 x86State; + x86_Convert_Init(x86State); + x86_Convert(filteredStream, (SizeT) inSize, 0, &x86State, 1); + } + } + } + + { + size_t outSizeProcessed = outSize - LZMA_HEADER_SIZE; + size_t outPropsSize = LZMA_PROPS_SIZE; + + res = LzmaEncode(outBuffer + LZMA_HEADER_SIZE, &outSizeProcessed, + mConType != NoConverter ? filteredStream : inBuffer, inSize, + props, outBuffer, &outPropsSize, 0, + NULL, &g_Alloc, &g_Alloc); + + if (res != SZ_OK) + goto Done; + + outSize = LZMA_HEADER_SIZE + outSizeProcessed; + } + + if (outStream->Write(outStream, outBuffer, outSize) != outSize) + res = SZ_ERROR_WRITE; + +Done: + MyFree(outBuffer); + MyFree(inBuffer); + MyFree(filteredStream); + + return res; +} + +static SRes Decode(ISeqOutStream *outStream, ISeqInStream *inStream, UInt64 fileSize) +{ + SRes res; + size_t inSize = (size_t)fileSize; + Byte *inBuffer = 0; + Byte *outBuffer = 0; + size_t outSize = 0; + size_t inSizePure; + ELzmaStatus status; + UInt64 outSize64 = 0; + + int i; + + if (inSize < LZMA_HEADER_SIZE) + return SZ_ERROR_INPUT_EOF; + + inBuffer = (Byte *)MyAlloc(inSize); + if (inBuffer == 0) + return SZ_ERROR_MEM; + + if (SeqInStream_Read(inStream, inBuffer, inSize) != SZ_OK) { + res = SZ_ERROR_READ; + goto Done; + } + + for (i = 0; i < 8; i++) + outSize64 += ((UInt64)inBuffer[LZMA_PROPS_SIZE + i]) << (i * 8); + + outSize = (size_t)outSize64; + if (outSize != 0) { + outBuffer = (Byte *)MyAlloc(outSize); + if (outBuffer == 0) { + res = SZ_ERROR_MEM; + goto Done; + } + } else { + res = SZ_OK; + goto Done; + } + + inSizePure = inSize - LZMA_HEADER_SIZE; + res = LzmaDecode(outBuffer, &outSize, inBuffer + LZMA_HEADER_SIZE, &inSizePure, + inBuffer, LZMA_PROPS_SIZE, LZMA_FINISH_END, &status, &g_Alloc); + + if (res != SZ_OK) + goto Done; + + if (mConType == X86Converter) + { + UInt32 x86State; + x86_Convert_Init(x86State); + x86_Convert(outBuffer, (SizeT) outSize, 0, &x86State, 0); + } + + if (outStream->Write(outStream, outBuffer, outSize) != outSize) + res = SZ_ERROR_WRITE; + +Done: + MyFree(outBuffer); + MyFree(inBuffer); + + return res; +} + +int main2(int numArgs, const char *args[], char *rs) +{ + CFileSeqInStream inStream; + CFileOutStream outStream; + int res; + int encodeMode = 0; + BoolInt modeWasSet = False; + const char *inputFile = NULL; + const char *outputFile = "file.tmp"; + int param; + UInt64 fileSize; + CLzmaEncProps props; + + LzmaEncProps_Init(&props); + LzmaEncProps_Normalize(&props); + + FileSeqInStream_CreateVTable(&inStream); + File_Construct(&inStream.file); + + FileOutStream_CreateVTable(&outStream); + File_Construct(&outStream.file); + + if (numArgs == 1) + { + PrintHelp(rs); + return 0; + } + + for (param = 1; param < numArgs; param++) { + if (strcmp(args[param], "-e") == 0 || strcmp(args[param], "-d") == 0) { + encodeMode = (args[param][1] == 'e'); + modeWasSet = True; +#ifdef VBOX_LZMA_F86_COMPRESS + mConType = X86Converter; +#endif + } else if (strcmp(args[param], "--f86") == 0) { + mConType = X86Converter; + } else if (strcmp(args[param], "-o") == 0 || + strcmp(args[param], "--output") == 0) { + if (numArgs < (param + 2)) { + return PrintUserError(rs); + } + outputFile = args[++param]; + } else if (strcmp(args[param], "--debug") == 0) { + if (numArgs < (param + 2)) { + return PrintUserError(rs); + } + // + // For now we silently ignore this parameter to achieve command line + // parameter compatibility with other build tools. + // + param++; + } else if (strcmp(args[param], "-a") == 0) { + AsciiStringToUint64(args[param + 1],FALSE,&mCompressionMode); + if ((mCompressionMode == 0)||(mCompressionMode == 1)){ + props.algo = (int)mCompressionMode; + param++; + continue; + } else { + return PrintError(rs, kInvalidParamValMessage); + } + } else if (strcmp(args[param], "d") == 0) { + AsciiStringToUint64(args[param + 1],FALSE,&mDictionarySize); + if (mDictionarySize <= 27) { + if (mDictionarySize == 0) { + props.dictSize = 0; + } else { + props.dictSize = (1 << mDictionarySize); + } + param++; + continue; + } else { + return PrintError(rs, kInvalidParamValMessage); + } + } else if ( + strcmp(args[param], "-h") == 0 || + strcmp(args[param], "--help") == 0 + ) { + PrintHelp(rs); + return 0; + } else if ( + strcmp(args[param], "-v") == 0 || + strcmp(args[param], "--verbose") == 0 + ) { + // + // For now we silently ignore this parameter to achieve command line + // parameter compatibility with other build tools. + // + } else if ( + strcmp(args[param], "-q") == 0 || + strcmp(args[param], "--quiet") == 0 + ) { + mQuietMode = True; + } else if (strcmp(args[param], "--version") == 0) { + PrintVersion(rs); + return 0; + } else if (inputFile == NULL) { + inputFile = args[param]; + } else { + return PrintUserError(rs); + } + } + + if ((inputFile == NULL) || !modeWasSet) { + return PrintUserError(rs); + } + + { + size_t t4 = sizeof(UInt32); + size_t t8 = sizeof(UInt64); + if (t4 != 4 || t8 != 8) + return PrintError(rs, "Incorrect UInt32 or UInt64"); + } + + if (InFile_Open(&inStream.file, inputFile) != 0) + return PrintError(rs, "Can not open input file"); + + if (OutFile_Open(&outStream.file, outputFile) != 0) { + File_Close(&inStream.file); + return PrintError(rs, "Can not open output file"); + } + + File_GetLength(&inStream.file, &fileSize); + + if (encodeMode) + { + if (!mQuietMode) { + printf("Encoding\n"); + } + res = Encode(&outStream.vt, &inStream.vt, fileSize, &props); + } + else + { + if (!mQuietMode) { + printf("Decoding\n"); + } + res = Decode(&outStream.vt, &inStream.vt, fileSize); + } + + File_Close(&outStream.file); + File_Close(&inStream.file); + + if (res != SZ_OK) + { + if (res == SZ_ERROR_MEM) + return PrintError(rs, kCantAllocateMessage); + else if (res == SZ_ERROR_DATA) + return PrintError(rs, kDataErrorMessage); + else if (res == SZ_ERROR_WRITE) + return PrintError(rs, kCantWriteMessage); + else if (res == SZ_ERROR_READ) + return PrintError(rs, kCantReadMessage); + return PrintErrorNumber(rs, res); + } + return 0; +} + +int MY_CDECL main(int numArgs, const char *args[]) +{ + char rs[2000] = { 0 }; + int res = main2(numArgs, args, rs); + if (strlen(rs) > 0) { + puts(rs); + } + return res; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LzmaF86Compress.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LzmaF86Compress.bat new file mode 100644 index 00000000..95b96564 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/LzmaF86Compress.bat @@ -0,0 +1,26 @@ +@REM @file +@REM This script will exec LzmaCompress tool with --f86 option that enables +@REM converter for x86 code. +@REM +@REM Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.
+@REM SPDX-License-Identifier: BSD-2-Clause-Patent +@REM + +@echo off +@setlocal + +:Begin +if "%1"=="" goto End +if "%1"=="-e" ( + set FLAG=--f86 +) +if "%1"=="-d" ( + set FLAG=--f86 +) +set ARGS=%ARGS% %1 +shift +goto Begin + +:End +LzmaCompress %ARGS% %FLAG% +@echo on diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Makefile new file mode 100644 index 00000000..2f410a1e --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Makefile @@ -0,0 +1,37 @@ +## @file +# Windows makefile for 'LzmaCompress' module build. +# +# Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +!INCLUDE ..\Makefiles\ms.common + +APPNAME = LzmaCompress + +LIBS = $(LIB_PATH)\Common.lib + +SDK_C = Sdk\C + +OBJECTS = \ + LzmaCompress.obj \ + $(SDK_C)\Alloc.obj \ + $(SDK_C)\LzFind.obj \ + $(SDK_C)\LzmaDec.obj \ + $(SDK_C)\LzmaEnc.obj \ + $(SDK_C)\7zFile.obj \ + $(SDK_C)\7zStream.obj \ + $(SDK_C)\Bra86.obj \ + $(SDK_C)\LzFindMt.obj \ + $(SDK_C)\Threads.obj + +!INCLUDE ..\Makefiles\ms.app + +all: $(BIN_PATH)\LzmaF86Compress.bat + +$(BIN_PATH)\LzmaF86Compress.bat: LzmaF86Compress.bat + copy LzmaF86Compress.bat $(BIN_PATH)\LzmaF86Compress.bat /Y + +cleanall: localCleanall + +localCleanall: + del /f /q $(BIN_PATH)\LzmaF86Compress.bat > nul diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Makefile.kmk new file mode 100644 index 00000000..846c9fab --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Makefile.kmk @@ -0,0 +1,58 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-makefile for the EFI LzmaCompress build tool. +# + +# +# Copyright (C) 2013-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# 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, in version 3 of the +# License. +# +# 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 . +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +SUB_DEPTH = ../../../../../../../../.. +include $(KBUILD_PATH)/subheader.kmk + +BLDPROGS += LzmaCompress +LzmaCompress_TEMPLATE = VBoxEfiBldProg +LzmaCompress_DEFS = _7ZIP_ST +LzmaCompress_SOURCES = \ + LzmaCompress.c \ + Sdk/C/Alloc.c \ + Sdk/C/LzFind.c \ + Sdk/C/LzmaDec.c \ + Sdk/C/LzmaEnc.c \ + Sdk/C/7zFile.c \ + Sdk/C/7zStream.c \ + Sdk/C/Bra86.c + +BLDPROGS += LzmaF86Compress +LzmaF86Compress_EXTENDS = LzmaCompress +LzmaF86Compress_DEFS = VBOX_LZMA_F86_COMPRESS _7ZIP_ST + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.c new file mode 100644 index 00000000..40aa2411 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.c @@ -0,0 +1,286 @@ +/* 7zFile.c -- File IO +2017-04-03 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "7zFile.h" + +#ifndef USE_WINDOWS_FILE + +#ifndef UNDER_CE +#include +#endif + +#else + +/* + ReadFile and WriteFile functions in Windows have BUG: + If you Read or Write 64MB or more (probably min_failure_size = 64MB - 32KB + 1) + from/to Network file, it returns ERROR_NO_SYSTEM_RESOURCES + (Insufficient system resources exist to complete the requested service). + Probably in some version of Windows there are problems with other sizes: + for 32 MB (maybe also for 16 MB). + And message can be "Network connection was lost" +*/ + +#define kChunkSizeMax (1 << 22) + +#endif + +void File_Construct(CSzFile *p) +{ + #ifdef USE_WINDOWS_FILE + p->handle = INVALID_HANDLE_VALUE; + #else + p->file = NULL; + #endif +} + +#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) +static WRes File_Open(CSzFile *p, const char *name, int writeMode) +{ + #ifdef USE_WINDOWS_FILE + p->handle = CreateFileA(name, + writeMode ? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ, NULL, + writeMode ? CREATE_ALWAYS : OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); + #else + p->file = fopen(name, writeMode ? "wb+" : "rb"); + return (p->file != 0) ? 0 : + #ifdef UNDER_CE + 2; /* ENOENT */ + #else + errno; + #endif + #endif +} + +WRes InFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 0); } +WRes OutFile_Open(CSzFile *p, const char *name) { return File_Open(p, name, 1); } +#endif + +#ifdef USE_WINDOWS_FILE +static WRes File_OpenW(CSzFile *p, const WCHAR *name, int writeMode) +{ + p->handle = CreateFileW(name, + writeMode ? GENERIC_WRITE : GENERIC_READ, + FILE_SHARE_READ, NULL, + writeMode ? CREATE_ALWAYS : OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + return (p->handle != INVALID_HANDLE_VALUE) ? 0 : GetLastError(); +} +WRes InFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 0); } +WRes OutFile_OpenW(CSzFile *p, const WCHAR *name) { return File_OpenW(p, name, 1); } +#endif + +WRes File_Close(CSzFile *p) +{ + #ifdef USE_WINDOWS_FILE + if (p->handle != INVALID_HANDLE_VALUE) + { + if (!CloseHandle(p->handle)) + return GetLastError(); + p->handle = INVALID_HANDLE_VALUE; + } + #else + if (p->file != NULL) + { + int res = fclose(p->file); + if (res != 0) + return res; + p->file = NULL; + } + #endif + return 0; +} + +WRes File_Read(CSzFile *p, void *data, size_t *size) +{ + size_t originalSize = *size; + if (originalSize == 0) + return 0; + + #ifdef USE_WINDOWS_FILE + + *size = 0; + do + { + DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; + DWORD processed = 0; + BOOL res = ReadFile(p->handle, data, curSize, &processed, NULL); + data = (void *)((Byte *)data + processed); + originalSize -= processed; + *size += processed; + if (!res) + return GetLastError(); + if (processed == 0) + break; + } + while (originalSize > 0); + return 0; + + #else + + *size = fread(data, 1, originalSize, p->file); + if (*size == originalSize) + return 0; + return ferror(p->file); + + #endif +} + +WRes File_Write(CSzFile *p, const void *data, size_t *size) +{ + size_t originalSize = *size; + if (originalSize == 0) + return 0; + + #ifdef USE_WINDOWS_FILE + + *size = 0; + do + { + DWORD curSize = (originalSize > kChunkSizeMax) ? kChunkSizeMax : (DWORD)originalSize; + DWORD processed = 0; + BOOL res = WriteFile(p->handle, data, curSize, &processed, NULL); + data = (void *)((Byte *)data + processed); + originalSize -= processed; + *size += processed; + if (!res) + return GetLastError(); + if (processed == 0) + break; + } + while (originalSize > 0); + return 0; + + #else + + *size = fwrite(data, 1, originalSize, p->file); + if (*size == originalSize) + return 0; + return ferror(p->file); + + #endif +} + +WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin) +{ + #ifdef USE_WINDOWS_FILE + + LARGE_INTEGER value; + DWORD moveMethod; + value.LowPart = (DWORD)*pos; + value.HighPart = (LONG)((UInt64)*pos >> 16 >> 16); /* for case when UInt64 is 32-bit only */ + switch (origin) + { + case SZ_SEEK_SET: moveMethod = FILE_BEGIN; break; + case SZ_SEEK_CUR: moveMethod = FILE_CURRENT; break; + case SZ_SEEK_END: moveMethod = FILE_END; break; + default: return ERROR_INVALID_PARAMETER; + } + value.LowPart = SetFilePointer(p->handle, value.LowPart, &value.HighPart, moveMethod); + if (value.LowPart == 0xFFFFFFFF) + { + WRes res = GetLastError(); + if (res != NO_ERROR) + return res; + } + *pos = ((Int64)value.HighPart << 32) | value.LowPart; + return 0; + + #else + + int moveMethod; + int res; + switch (origin) + { + case SZ_SEEK_SET: moveMethod = SEEK_SET; break; + case SZ_SEEK_CUR: moveMethod = SEEK_CUR; break; + case SZ_SEEK_END: moveMethod = SEEK_END; break; + default: return 1; + } + res = fseek(p->file, (long)*pos, moveMethod); + *pos = ftell(p->file); + return res; + + #endif +} + +WRes File_GetLength(CSzFile *p, UInt64 *length) +{ + #ifdef USE_WINDOWS_FILE + + DWORD sizeHigh; + DWORD sizeLow = GetFileSize(p->handle, &sizeHigh); + if (sizeLow == 0xFFFFFFFF) + { + DWORD res = GetLastError(); + if (res != NO_ERROR) + return res; + } + *length = (((UInt64)sizeHigh) << 32) + sizeLow; + return 0; + + #else + + long pos = ftell(p->file); + int res = fseek(p->file, 0, SEEK_END); + *length = ftell(p->file); + fseek(p->file, pos, SEEK_SET); + return res; + + #endif +} + + +/* ---------- FileSeqInStream ---------- */ + +static SRes FileSeqInStream_Read(const ISeqInStream *pp, void *buf, size_t *size) +{ + CFileSeqInStream *p = CONTAINER_FROM_VTBL(pp, CFileSeqInStream, vt); + return File_Read(&p->file, buf, size) == 0 ? SZ_OK : SZ_ERROR_READ; +} + +void FileSeqInStream_CreateVTable(CFileSeqInStream *p) +{ + p->vt.Read = FileSeqInStream_Read; +} + + +/* ---------- FileInStream ---------- */ + +static SRes FileInStream_Read(const ISeekInStream *pp, void *buf, size_t *size) +{ + CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt); + return (File_Read(&p->file, buf, size) == 0) ? SZ_OK : SZ_ERROR_READ; +} + +static SRes FileInStream_Seek(const ISeekInStream *pp, Int64 *pos, ESzSeek origin) +{ + CFileInStream *p = CONTAINER_FROM_VTBL(pp, CFileInStream, vt); + return File_Seek(&p->file, pos, origin); +} + +void FileInStream_CreateVTable(CFileInStream *p) +{ + p->vt.Read = FileInStream_Read; + p->vt.Seek = FileInStream_Seek; +} + + +/* ---------- FileOutStream ---------- */ + +static size_t FileOutStream_Write(const ISeqOutStream *pp, const void *data, size_t size) +{ + CFileOutStream *p = CONTAINER_FROM_VTBL(pp, CFileOutStream, vt); + File_Write(&p->file, data, &size); + return size; +} + +void FileOutStream_CreateVTable(CFileOutStream *p) +{ + p->vt.Write = FileOutStream_Write; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.h new file mode 100644 index 00000000..ee3b003a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zFile.h @@ -0,0 +1,87 @@ +/* 7zFile.h -- File IO +2017-04-03 : Igor Pavlov : Public domain */ + +#ifndef __7Z_FILE_H +#define __7Z_FILE_H + +#ifdef _WIN32 +#define USE_WINDOWS_FILE +#endif + +#ifdef USE_WINDOWS_FILE +# ifdef VBOX +# include +# else +#include +# endif +#else +#include +#endif + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* ---------- File ---------- */ + +typedef struct +{ + #ifdef USE_WINDOWS_FILE + HANDLE handle; + #else + FILE *file; + #endif +} CSzFile; + +void File_Construct(CSzFile *p); +#if !defined(UNDER_CE) || !defined(USE_WINDOWS_FILE) +WRes InFile_Open(CSzFile *p, const char *name); +WRes OutFile_Open(CSzFile *p, const char *name); +#endif +#ifdef USE_WINDOWS_FILE +WRes InFile_OpenW(CSzFile *p, const WCHAR *name); +WRes OutFile_OpenW(CSzFile *p, const WCHAR *name); +#endif +WRes File_Close(CSzFile *p); + +/* reads max(*size, remain file's size) bytes */ +WRes File_Read(CSzFile *p, void *data, size_t *size); + +/* writes *size bytes */ +WRes File_Write(CSzFile *p, const void *data, size_t *size); + +WRes File_Seek(CSzFile *p, Int64 *pos, ESzSeek origin); +WRes File_GetLength(CSzFile *p, UInt64 *length); + + +/* ---------- FileInStream ---------- */ + +typedef struct +{ + ISeqInStream vt; + CSzFile file; +} CFileSeqInStream; + +void FileSeqInStream_CreateVTable(CFileSeqInStream *p); + + +typedef struct +{ + ISeekInStream vt; + CSzFile file; +} CFileInStream; + +void FileInStream_CreateVTable(CFileInStream *p); + + +typedef struct +{ + ISeqOutStream vt; + CSzFile file; +} CFileOutStream; + +void FileOutStream_CreateVTable(CFileOutStream *p); + +EXTERN_C_END + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zStream.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zStream.c new file mode 100644 index 00000000..6b5aa162 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zStream.c @@ -0,0 +1,176 @@ +/* 7zStream.c -- 7z Stream functions +2017-04-03 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "7zTypes.h" + +SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType) +{ + while (size != 0) + { + size_t processed = size; + RINOK(ISeqInStream_Read(stream, buf, &processed)); + if (processed == 0) + return errorType; + buf = (void *)((Byte *)buf + processed); + size -= processed; + } + return SZ_OK; +} + +SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size) +{ + return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); +} + +SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf) +{ + size_t processed = 1; + RINOK(ISeqInStream_Read(stream, buf, &processed)); + return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; +} + + + +SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset) +{ + Int64 t = offset; + return ILookInStream_Seek(stream, &t, SZ_SEEK_SET); +} + +SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size) +{ + const void *lookBuf; + if (*size == 0) + return SZ_OK; + RINOK(ILookInStream_Look(stream, &lookBuf, size)); + memcpy(buf, lookBuf, *size); + return ILookInStream_Skip(stream, *size); +} + +SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType) +{ + while (size != 0) + { + size_t processed = size; + RINOK(ILookInStream_Read(stream, buf, &processed)); + if (processed == 0) + return errorType; + buf = (void *)((Byte *)buf + processed); + size -= processed; + } + return SZ_OK; +} + +SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size) +{ + return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); +} + + + +#define GET_LookToRead2 CLookToRead2 *p = CONTAINER_FROM_VTBL(pp, CLookToRead2, vt); + +static SRes LookToRead2_Look_Lookahead(const ILookInStream *pp, const void **buf, size_t *size) +{ + SRes res = SZ_OK; + GET_LookToRead2 + size_t size2 = p->size - p->pos; + if (size2 == 0 && *size != 0) + { + p->pos = 0; + p->size = 0; + size2 = p->bufSize; + res = ISeekInStream_Read(p->realStream, p->buf, &size2); + p->size = size2; + } + if (*size > size2) + *size = size2; + *buf = p->buf + p->pos; + return res; +} + +static SRes LookToRead2_Look_Exact(const ILookInStream *pp, const void **buf, size_t *size) +{ + SRes res = SZ_OK; + GET_LookToRead2 + size_t size2 = p->size - p->pos; + if (size2 == 0 && *size != 0) + { + p->pos = 0; + p->size = 0; + if (*size > p->bufSize) + *size = p->bufSize; + res = ISeekInStream_Read(p->realStream, p->buf, size); + size2 = p->size = *size; + } + if (*size > size2) + *size = size2; + *buf = p->buf + p->pos; + return res; +} + +static SRes LookToRead2_Skip(const ILookInStream *pp, size_t offset) +{ + GET_LookToRead2 + p->pos += offset; + return SZ_OK; +} + +static SRes LookToRead2_Read(const ILookInStream *pp, void *buf, size_t *size) +{ + GET_LookToRead2 + size_t rem = p->size - p->pos; + if (rem == 0) + return ISeekInStream_Read(p->realStream, buf, size); + if (rem > *size) + rem = *size; + memcpy(buf, p->buf + p->pos, rem); + p->pos += rem; + *size = rem; + return SZ_OK; +} + +static SRes LookToRead2_Seek(const ILookInStream *pp, Int64 *pos, ESzSeek origin) +{ + GET_LookToRead2 + p->pos = p->size = 0; + return ISeekInStream_Seek(p->realStream, pos, origin); +} + +void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead) +{ + p->vt.Look = lookahead ? + LookToRead2_Look_Lookahead : + LookToRead2_Look_Exact; + p->vt.Skip = LookToRead2_Skip; + p->vt.Read = LookToRead2_Read; + p->vt.Seek = LookToRead2_Seek; +} + + + +static SRes SecToLook_Read(const ISeqInStream *pp, void *buf, size_t *size) +{ + CSecToLook *p = CONTAINER_FROM_VTBL(pp, CSecToLook, vt); + return LookInStream_LookRead(p->realStream, buf, size); +} + +void SecToLook_CreateVTable(CSecToLook *p) +{ + p->vt.Read = SecToLook_Read; +} + +static SRes SecToRead_Read(const ISeqInStream *pp, void *buf, size_t *size) +{ + CSecToRead *p = CONTAINER_FROM_VTBL(pp, CSecToRead, vt); + return ILookInStream_Read(p->realStream, buf, size); +} + +void SecToRead_CreateVTable(CSecToRead *p) +{ + p->vt.Read = SecToRead_Read; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zTypes.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zTypes.h new file mode 100644 index 00000000..7a9cadb9 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zTypes.h @@ -0,0 +1,375 @@ +/* 7zTypes.h -- Basic types +2018-08-04 : Igor Pavlov : Public domain */ + +#ifndef __7Z_TYPES_H +#define __7Z_TYPES_H + +#ifdef _WIN32 +/* #include */ +#endif + +#include + +#ifndef EXTERN_C_BEGIN +#ifdef __cplusplus +#define EXTERN_C_BEGIN extern "C" { +#define EXTERN_C_END } +#else +#define EXTERN_C_BEGIN +#define EXTERN_C_END +#endif +#endif + +EXTERN_C_BEGIN + +#define SZ_OK 0 + +#define SZ_ERROR_DATA 1 +#define SZ_ERROR_MEM 2 +#define SZ_ERROR_CRC 3 +#define SZ_ERROR_UNSUPPORTED 4 +#define SZ_ERROR_PARAM 5 +#define SZ_ERROR_INPUT_EOF 6 +#define SZ_ERROR_OUTPUT_EOF 7 +#define SZ_ERROR_READ 8 +#define SZ_ERROR_WRITE 9 +#define SZ_ERROR_PROGRESS 10 +#define SZ_ERROR_FAIL 11 +#define SZ_ERROR_THREAD 12 + +#define SZ_ERROR_ARCHIVE 16 +#define SZ_ERROR_NO_ARCHIVE 17 + +typedef int SRes; + + +#ifdef _WIN32 + +/* typedef DWORD WRes; */ +typedef unsigned WRes; +#define MY_SRes_HRESULT_FROM_WRes(x) HRESULT_FROM_WIN32(x) + +#else + +typedef int WRes; +#define MY__FACILITY_WIN32 7 +#define MY__FACILITY__WRes MY__FACILITY_WIN32 +#define MY_SRes_HRESULT_FROM_WRes(x) ((HRESULT)(x) <= 0 ? ((HRESULT)(x)) : ((HRESULT) (((x) & 0x0000FFFF) | (MY__FACILITY__WRes << 16) | 0x80000000))) + +#endif + + +#ifndef RINOK +#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } +#endif + +typedef unsigned char Byte; +typedef short Int16; +typedef unsigned short UInt16; + +#ifdef _LZMA_UINT32_IS_ULONG +typedef long Int32; +typedef unsigned long UInt32; +#else +typedef int Int32; +typedef unsigned int UInt32; +#endif + +#ifdef _SZ_NO_INT_64 + +/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. + NOTES: Some code will work incorrectly in that case! */ + +typedef long Int64; +typedef unsigned long UInt64; + +#else + +#if defined(_MSC_VER) || defined(__BORLANDC__) +typedef __int64 Int64; +typedef unsigned __int64 UInt64; +#define UINT64_CONST(n) n +#else +typedef long long int Int64; +typedef unsigned long long int UInt64; +#define UINT64_CONST(n) n ## ULL +#endif + +#endif + +#ifdef _LZMA_NO_SYSTEM_SIZE_T +typedef UInt32 SizeT; +#else +typedef size_t SizeT; +#endif + +typedef int BoolInt; +/* typedef BoolInt Bool; */ +#define True 1 +#define False 0 + + +#ifdef _WIN32 +#define MY_STD_CALL __stdcall +#else +#define MY_STD_CALL +#endif + +#ifdef _MSC_VER + +#if _MSC_VER >= 1300 +#define MY_NO_INLINE __declspec(noinline) +#else +#define MY_NO_INLINE +#endif + +#define MY_FORCE_INLINE __forceinline + +#define MY_CDECL __cdecl +#define MY_FAST_CALL __fastcall + +#else + +#define MY_NO_INLINE +#define MY_FORCE_INLINE +#define MY_CDECL +#define MY_FAST_CALL + +/* inline keyword : for C++ / C99 */ + +/* GCC, clang: */ +/* +#if defined (__GNUC__) && (__GNUC__ >= 4) +#define MY_FORCE_INLINE __attribute__((always_inline)) +#define MY_NO_INLINE __attribute__((noinline)) +#endif +*/ + +#endif + + +/* The following interfaces use first parameter as pointer to structure */ + +typedef struct IByteIn IByteIn; +struct IByteIn +{ + Byte (*Read)(const IByteIn *p); /* reads one byte, returns 0 in case of EOF or error */ +}; +#define IByteIn_Read(p) (p)->Read(p) + + +typedef struct IByteOut IByteOut; +struct IByteOut +{ + void (*Write)(const IByteOut *p, Byte b); +}; +#define IByteOut_Write(p, b) (p)->Write(p, b) + + +typedef struct ISeqInStream ISeqInStream; +struct ISeqInStream +{ + SRes (*Read)(const ISeqInStream *p, void *buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) < input(*size)) is allowed */ +}; +#define ISeqInStream_Read(p, buf, size) (p)->Read(p, buf, size) + +/* it can return SZ_ERROR_INPUT_EOF */ +SRes SeqInStream_Read(const ISeqInStream *stream, void *buf, size_t size); +SRes SeqInStream_Read2(const ISeqInStream *stream, void *buf, size_t size, SRes errorType); +SRes SeqInStream_ReadByte(const ISeqInStream *stream, Byte *buf); + + +typedef struct ISeqOutStream ISeqOutStream; +struct ISeqOutStream +{ + size_t (*Write)(const ISeqOutStream *p, const void *buf, size_t size); + /* Returns: result - the number of actually written bytes. + (result < size) means error */ +}; +#define ISeqOutStream_Write(p, buf, size) (p)->Write(p, buf, size) + +typedef enum +{ + SZ_SEEK_SET = 0, + SZ_SEEK_CUR = 1, + SZ_SEEK_END = 2 +} ESzSeek; + + +typedef struct ISeekInStream ISeekInStream; +struct ISeekInStream +{ + SRes (*Read)(const ISeekInStream *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ + SRes (*Seek)(const ISeekInStream *p, Int64 *pos, ESzSeek origin); +}; +#define ISeekInStream_Read(p, buf, size) (p)->Read(p, buf, size) +#define ISeekInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin) + + +typedef struct ILookInStream ILookInStream; +struct ILookInStream +{ + SRes (*Look)(const ILookInStream *p, const void **buf, size_t *size); + /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. + (output(*size) > input(*size)) is not allowed + (output(*size) < input(*size)) is allowed */ + SRes (*Skip)(const ILookInStream *p, size_t offset); + /* offset must be <= output(*size) of Look */ + + SRes (*Read)(const ILookInStream *p, void *buf, size_t *size); + /* reads directly (without buffer). It's same as ISeqInStream::Read */ + SRes (*Seek)(const ILookInStream *p, Int64 *pos, ESzSeek origin); +}; + +#define ILookInStream_Look(p, buf, size) (p)->Look(p, buf, size) +#define ILookInStream_Skip(p, offset) (p)->Skip(p, offset) +#define ILookInStream_Read(p, buf, size) (p)->Read(p, buf, size) +#define ILookInStream_Seek(p, pos, origin) (p)->Seek(p, pos, origin) + + +SRes LookInStream_LookRead(const ILookInStream *stream, void *buf, size_t *size); +SRes LookInStream_SeekTo(const ILookInStream *stream, UInt64 offset); + +/* reads via ILookInStream::Read */ +SRes LookInStream_Read2(const ILookInStream *stream, void *buf, size_t size, SRes errorType); +SRes LookInStream_Read(const ILookInStream *stream, void *buf, size_t size); + + + +typedef struct +{ + ILookInStream vt; + const ISeekInStream *realStream; + + size_t pos; + size_t size; /* it's data size */ + + /* the following variables must be set outside */ + Byte *buf; + size_t bufSize; +} CLookToRead2; + +void LookToRead2_CreateVTable(CLookToRead2 *p, int lookahead); + +#define LookToRead2_Init(p) { (p)->pos = (p)->size = 0; } + + +typedef struct +{ + ISeqInStream vt; + const ILookInStream *realStream; +} CSecToLook; + +void SecToLook_CreateVTable(CSecToLook *p); + + + +typedef struct +{ + ISeqInStream vt; + const ILookInStream *realStream; +} CSecToRead; + +void SecToRead_CreateVTable(CSecToRead *p); + + +typedef struct ICompressProgress ICompressProgress; + +struct ICompressProgress +{ + SRes (*Progress)(const ICompressProgress *p, UInt64 inSize, UInt64 outSize); + /* Returns: result. (result != SZ_OK) means break. + Value (UInt64)(Int64)-1 for size means unknown value. */ +}; +#define ICompressProgress_Progress(p, inSize, outSize) (p)->Progress(p, inSize, outSize) + + + +typedef struct ISzAlloc ISzAlloc; +typedef const ISzAlloc * ISzAllocPtr; + +struct ISzAlloc +{ + void *(*Alloc)(ISzAllocPtr p, size_t size); + void (*Free)(ISzAllocPtr p, void *address); /* address can be 0 */ +}; + +#define ISzAlloc_Alloc(p, size) (p)->Alloc(p, size) +#define ISzAlloc_Free(p, a) (p)->Free(p, a) + +/* deprecated */ +#define IAlloc_Alloc(p, size) ISzAlloc_Alloc(p, size) +#define IAlloc_Free(p, a) ISzAlloc_Free(p, a) + + + + + +#ifndef MY_offsetof + #ifdef offsetof + #define MY_offsetof(type, m) offsetof(type, m) + /* + #define MY_offsetof(type, m) FIELD_OFFSET(type, m) + */ + #else + #define MY_offsetof(type, m) ((size_t)&(((type *)0)->m)) + #endif +#endif + + + +#ifndef MY_container_of + +/* +#define MY_container_of(ptr, type, m) container_of(ptr, type, m) +#define MY_container_of(ptr, type, m) CONTAINING_RECORD(ptr, type, m) +#define MY_container_of(ptr, type, m) ((type *)((char *)(ptr) - offsetof(type, m))) +#define MY_container_of(ptr, type, m) (&((type *)0)->m == (ptr), ((type *)(((char *)(ptr)) - MY_offsetof(type, m)))) +*/ + +/* + GCC shows warning: "perhaps the 'offsetof' macro was used incorrectly" + GCC 3.4.4 : classes with constructor + GCC 4.8.1 : classes with non-public variable members" +*/ + +#define MY_container_of(ptr, type, m) ((type *)((char *)(1 ? (ptr) : &((type *)0)->m) - MY_offsetof(type, m))) + + +#endif + +#define CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) ((type *)(ptr)) + +/* +#define CONTAINER_FROM_VTBL(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) +*/ +#define CONTAINER_FROM_VTBL(ptr, type, m) MY_container_of(ptr, type, m) + +#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL_SIMPLE(ptr, type, m) +/* +#define CONTAINER_FROM_VTBL_CLS(ptr, type, m) CONTAINER_FROM_VTBL(ptr, type, m) +*/ + + + +#ifdef _WIN32 + +#define CHAR_PATH_SEPARATOR '\\' +#define WCHAR_PATH_SEPARATOR L'\\' +#define STRING_PATH_SEPARATOR "\\" +#define WSTRING_PATH_SEPARATOR L"\\" + +#else + +#define CHAR_PATH_SEPARATOR '/' +#define WCHAR_PATH_SEPARATOR L'/' +#define STRING_PATH_SEPARATOR "/" +#define WSTRING_PATH_SEPARATOR L"/" + +#endif + +EXTERN_C_END + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zVersion.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zVersion.h new file mode 100644 index 00000000..c176823a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/7zVersion.h @@ -0,0 +1,27 @@ +#define MY_VER_MAJOR 19 +#define MY_VER_MINOR 00 +#define MY_VER_BUILD 0 +#define MY_VERSION_NUMBERS "19.00" +#define MY_VERSION MY_VERSION_NUMBERS + +#ifdef MY_CPU_NAME + #define MY_VERSION_CPU MY_VERSION " (" MY_CPU_NAME ")" +#else + #define MY_VERSION_CPU MY_VERSION +#endif + +#define MY_DATE "2019-02-21" +#undef MY_COPYRIGHT +#undef MY_VERSION_COPYRIGHT_DATE +#define MY_AUTHOR_NAME "Igor Pavlov" +#define MY_COPYRIGHT_PD "Igor Pavlov : Public domain" +#define MY_COPYRIGHT_CR "Copyright (c) 1999-2018 Igor Pavlov" + +#ifdef USE_COPYRIGHT_CR + #define MY_COPYRIGHT MY_COPYRIGHT_CR +#else + #define MY_COPYRIGHT MY_COPYRIGHT_PD +#endif + +#define MY_COPYRIGHT_DATE MY_COPYRIGHT " : " MY_DATE +#define MY_VERSION_COPYRIGHT_DATE MY_VERSION_CPU " : " MY_COPYRIGHT " : " MY_DATE diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.c new file mode 100644 index 00000000..a21de447 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.c @@ -0,0 +1,460 @@ +/* Alloc.c -- Memory allocation functions +2018-04-27 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#ifdef _WIN32 +# ifdef VBOX +# include +# else +#include +# endif +#endif +#include + +#include "Alloc.h" + +/* #define _SZ_ALLOC_DEBUG */ + +/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ +#ifdef _SZ_ALLOC_DEBUG + +#include +int g_allocCount = 0; +int g_allocCountMid = 0; +int g_allocCountBig = 0; + + +#define CONVERT_INT_TO_STR(charType, tempSize) \ + unsigned char temp[tempSize]; unsigned i = 0; \ + while (val >= 10) { temp[i++] = (unsigned char)('0' + (unsigned)(val % 10)); val /= 10; } \ + *s++ = (charType)('0' + (unsigned)val); \ + while (i != 0) { i--; *s++ = temp[i]; } \ + *s = 0; + +static void ConvertUInt64ToString(UInt64 val, char *s) +{ + CONVERT_INT_TO_STR(char, 24); +} + +#define GET_HEX_CHAR(t) ((char)(((t < 10) ? ('0' + t) : ('A' + (t - 10))))) + +static void ConvertUInt64ToHex(UInt64 val, char *s) +{ + UInt64 v = val; + unsigned i; + for (i = 1;; i++) + { + v >>= 4; + if (v == 0) + break; + } + s[i] = 0; + do + { + unsigned t = (unsigned)(val & 0xF); + val >>= 4; + s[--i] = GET_HEX_CHAR(t); + } + while (i); +} + +#define DEBUG_OUT_STREAM stderr + +static void Print(const char *s) +{ + fputs(s, DEBUG_OUT_STREAM); +} + +static void PrintAligned(const char *s, size_t align) +{ + size_t len = strlen(s); + for(;;) + { + fputc(' ', DEBUG_OUT_STREAM); + if (len >= align) + break; + ++len; + } + Print(s); +} + +static void PrintLn() +{ + Print("\n"); +} + +static void PrintHex(UInt64 v, size_t align) +{ + char s[32]; + ConvertUInt64ToHex(v, s); + PrintAligned(s, align); +} + +static void PrintDec(UInt64 v, size_t align) +{ + char s[32]; + ConvertUInt64ToString(v, s); + PrintAligned(s, align); +} + +static void PrintAddr(void *p) +{ + PrintHex((UInt64)(size_t)(ptrdiff_t)p, 12); +} + + +#define PRINT_ALLOC(name, cnt, size, ptr) \ + Print(name " "); \ + PrintDec(cnt++, 10); \ + PrintHex(size, 10); \ + PrintAddr(ptr); \ + PrintLn(); + +#define PRINT_FREE(name, cnt, ptr) if (ptr) { \ + Print(name " "); \ + PrintDec(--cnt, 10); \ + PrintAddr(ptr); \ + PrintLn(); } + +#else + +#define PRINT_ALLOC(name, cnt, size, ptr) +#define PRINT_FREE(name, cnt, ptr) +#define Print(s) +#define PrintLn() +#define PrintHex(v, align) +#define PrintDec(v, align) +#define PrintAddr(p) + +#endif + + + +void *MyAlloc(size_t size) +{ + if (size == 0) + return NULL; + #ifdef _SZ_ALLOC_DEBUG + { + void *p = malloc(size); + PRINT_ALLOC("Alloc ", g_allocCount, size, p); + return p; + } + #else + return malloc(size); + #endif +} + +void MyFree(void *address) +{ + PRINT_FREE("Free ", g_allocCount, address); + + free(address); +} + +#ifdef _WIN32 + +void *MidAlloc(size_t size) +{ + if (size == 0) + return NULL; + + PRINT_ALLOC("Alloc-Mid", g_allocCountMid, size, NULL); + + return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); +} + +void MidFree(void *address) +{ + PRINT_FREE("Free-Mid", g_allocCountMid, address); + + if (!address) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#ifndef MEM_LARGE_PAGES +#undef _7ZIP_LARGE_PAGES +#endif + +#ifdef _7ZIP_LARGE_PAGES +SIZE_T g_LargePageSize = 0; +typedef SIZE_T (WINAPI *GetLargePageMinimumP)(); +#endif + +void SetLargePageSize() +{ + #ifdef _7ZIP_LARGE_PAGES + SIZE_T size; + GetLargePageMinimumP largePageMinimum = (GetLargePageMinimumP) + GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetLargePageMinimum"); + if (!largePageMinimum) + return; + size = largePageMinimum(); + if (size == 0 || (size & (size - 1)) != 0) + return; + g_LargePageSize = size; + #endif +} + + +void *BigAlloc(size_t size) +{ + if (size == 0) + return NULL; + + PRINT_ALLOC("Alloc-Big", g_allocCountBig, size, NULL); + + #ifdef _7ZIP_LARGE_PAGES + { + SIZE_T ps = g_LargePageSize; + if (ps != 0 && ps <= (1 << 30) && size > (ps / 2)) + { + size_t size2; + ps--; + size2 = (size + ps) & ~ps; + if (size2 >= size) + { + void *res = VirtualAlloc(NULL, size2, MEM_COMMIT | MEM_LARGE_PAGES, PAGE_READWRITE); + if (res) + return res; + } + } + } + #endif + + return VirtualAlloc(NULL, size, MEM_COMMIT, PAGE_READWRITE); +} + +void BigFree(void *address) +{ + PRINT_FREE("Free-Big", g_allocCountBig, address); + + if (!address) + return; + VirtualFree(address, 0, MEM_RELEASE); +} + +#endif + + +static void *SzAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MyAlloc(size); } +static void SzFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MyFree(address); } +const ISzAlloc g_Alloc = { SzAlloc, SzFree }; + +static void *SzMidAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return MidAlloc(size); } +static void SzMidFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); MidFree(address); } +const ISzAlloc g_MidAlloc = { SzMidAlloc, SzMidFree }; + +static void *SzBigAlloc(ISzAllocPtr p, size_t size) { UNUSED_VAR(p); return BigAlloc(size); } +static void SzBigFree(ISzAllocPtr p, void *address) { UNUSED_VAR(p); BigFree(address); } +const ISzAlloc g_BigAlloc = { SzBigAlloc, SzBigFree }; + + +/* + uintptr_t : C99 (optional) + : unsupported in VS6 +*/ + +#ifdef _WIN32 + typedef UINT_PTR UIntPtr; +#else + /* + typedef uintptr_t UIntPtr; + */ + typedef ptrdiff_t UIntPtr; +#endif + + +#define ADJUST_ALLOC_SIZE 0 +/* +#define ADJUST_ALLOC_SIZE (sizeof(void *) - 1) +*/ +/* + Use (ADJUST_ALLOC_SIZE = (sizeof(void *) - 1)), if + MyAlloc() can return address that is NOT multiple of sizeof(void *). +*/ + + +/* +#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((char *)(p) - ((size_t)(UIntPtr)(p) & ((align) - 1)))) +*/ +#define MY_ALIGN_PTR_DOWN(p, align) ((void *)((((UIntPtr)(p)) & ~((UIntPtr)(align) - 1)))) + +#define MY_ALIGN_PTR_UP_PLUS(p, align) MY_ALIGN_PTR_DOWN(((char *)(p) + (align) + ADJUST_ALLOC_SIZE), align) + +#if defined(VBOX) && defined(_POSIX_C_SOURCE) +#if (_POSIX_C_SOURCE >= 200112L) && !defined(_WIN32) + #define USE_posix_memalign +#endif +#endif + +/* + This posix_memalign() is for test purposes only. + We also need special Free() function instead of free(), + if this posix_memalign() is used. +*/ + +/* +static int posix_memalign(void **ptr, size_t align, size_t size) +{ + size_t newSize = size + align; + void *p; + void *pAligned; + *ptr = NULL; + if (newSize < size) + return 12; // ENOMEM + p = MyAlloc(newSize); + if (!p) + return 12; // ENOMEM + pAligned = MY_ALIGN_PTR_UP_PLUS(p, align); + ((void **)pAligned)[-1] = p; + *ptr = pAligned; + return 0; +} +*/ + +/* + ALLOC_ALIGN_SIZE >= sizeof(void *) + ALLOC_ALIGN_SIZE >= cache_line_size +*/ + +#define ALLOC_ALIGN_SIZE ((size_t)1 << 7) + +static void *SzAlignedAlloc(ISzAllocPtr pp, size_t size) +{ + #ifndef USE_posix_memalign + + void *p; + void *pAligned; + size_t newSize; + UNUSED_VAR(pp); + + /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned + block to prevent cache line sharing with another allocated blocks */ + + newSize = size + ALLOC_ALIGN_SIZE * 1 + ADJUST_ALLOC_SIZE; + if (newSize < size) + return NULL; + + p = MyAlloc(newSize); + + if (!p) + return NULL; + pAligned = MY_ALIGN_PTR_UP_PLUS(p, ALLOC_ALIGN_SIZE); + + Print(" size="); PrintHex(size, 8); + Print(" a_size="); PrintHex(newSize, 8); + Print(" ptr="); PrintAddr(p); + Print(" a_ptr="); PrintAddr(pAligned); + PrintLn(); + + ((void **)pAligned)[-1] = p; + + return pAligned; + + #else + + void *p; + UNUSED_VAR(pp); + if (posix_memalign(&p, ALLOC_ALIGN_SIZE, size)) + return NULL; + + Print(" posix_memalign="); PrintAddr(p); + PrintLn(); + + return p; + + #endif +} + + +static void SzAlignedFree(ISzAllocPtr pp, void *address) +{ + UNUSED_VAR(pp); + #ifndef USE_posix_memalign + if (address) + MyFree(((void **)address)[-1]); + #else + free(address); + #endif +} + + +const ISzAlloc g_AlignedAlloc = { SzAlignedAlloc, SzAlignedFree }; + + + +#define MY_ALIGN_PTR_DOWN_1(p) MY_ALIGN_PTR_DOWN(p, sizeof(void *)) + +/* we align ptr to support cases where CAlignOffsetAlloc::offset is not multiply of sizeof(void *) */ +#define REAL_BLOCK_PTR_VAR(p) ((void **)MY_ALIGN_PTR_DOWN_1(p))[-1] +/* +#define REAL_BLOCK_PTR_VAR(p) ((void **)(p))[-1] +*/ + +static void *AlignOffsetAlloc_Alloc(ISzAllocPtr pp, size_t size) +{ + CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt); + void *adr; + void *pAligned; + size_t newSize; + size_t extra; + size_t alignSize = (size_t)1 << p->numAlignBits; + + if (alignSize < sizeof(void *)) + alignSize = sizeof(void *); + + if (p->offset >= alignSize) + return NULL; + + /* also we can allocate additional dummy ALLOC_ALIGN_SIZE bytes after aligned + block to prevent cache line sharing with another allocated blocks */ + extra = p->offset & (sizeof(void *) - 1); + newSize = size + alignSize + extra + ADJUST_ALLOC_SIZE; + if (newSize < size) + return NULL; + + adr = ISzAlloc_Alloc(p->baseAlloc, newSize); + + if (!adr) + return NULL; + + pAligned = (char *)MY_ALIGN_PTR_DOWN((char *)adr + + alignSize - p->offset + extra + ADJUST_ALLOC_SIZE, alignSize) + p->offset; + + PrintLn(); + Print("- Aligned: "); + Print(" size="); PrintHex(size, 8); + Print(" a_size="); PrintHex(newSize, 8); + Print(" ptr="); PrintAddr(adr); + Print(" a_ptr="); PrintAddr(pAligned); + PrintLn(); + + REAL_BLOCK_PTR_VAR(pAligned) = adr; + + return pAligned; +} + + +static void AlignOffsetAlloc_Free(ISzAllocPtr pp, void *address) +{ + if (address) + { + CAlignOffsetAlloc *p = CONTAINER_FROM_VTBL(pp, CAlignOffsetAlloc, vt); + PrintLn(); + Print("- Aligned Free: "); + PrintLn(); + ISzAlloc_Free(p->baseAlloc, REAL_BLOCK_PTR_VAR(address)); + } +} + + +void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p) +{ + p->vt.Alloc = AlignOffsetAlloc_Alloc; + p->vt.Free = AlignOffsetAlloc_Free; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.h new file mode 100644 index 00000000..64823764 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Alloc.h @@ -0,0 +1,51 @@ +/* Alloc.h -- Memory allocation functions +2018-02-19 : Igor Pavlov : Public domain */ + +#ifndef __COMMON_ALLOC_H +#define __COMMON_ALLOC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +void *MyAlloc(size_t size); +void MyFree(void *address); + +#ifdef _WIN32 + +void SetLargePageSize(); + +void *MidAlloc(size_t size); +void MidFree(void *address); +void *BigAlloc(size_t size); +void BigFree(void *address); + +#else + +#define MidAlloc(size) MyAlloc(size) +#define MidFree(address) MyFree(address) +#define BigAlloc(size) MyAlloc(size) +#define BigFree(address) MyFree(address) + +#endif + +extern const ISzAlloc g_Alloc; +extern const ISzAlloc g_BigAlloc; +extern const ISzAlloc g_MidAlloc; +extern const ISzAlloc g_AlignedAlloc; + + +typedef struct +{ + ISzAlloc vt; + ISzAllocPtr baseAlloc; + unsigned numAlignBits; /* ((1 << numAlignBits) >= sizeof(void *)) */ + size_t offset; /* (offset == (k * sizeof(void *)) && offset < (1 << numAlignBits) */ +} CAlignOffsetAlloc; + +void AlignOffsetAlloc_CreateVTable(CAlignOffsetAlloc *p); + + +EXTERN_C_END + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Bra.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Bra.h new file mode 100644 index 00000000..184c291a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Bra.h @@ -0,0 +1,64 @@ +/* Bra.h -- Branch converters for executables +2013-01-18 : Igor Pavlov : Public domain */ + +#ifndef __BRA_H +#define __BRA_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* +These functions convert relative addresses to absolute addresses +in CALL instructions to increase the compression ratio. + + In: + data - data buffer + size - size of data + ip - current virtual Instruction Pinter (IP) value + state - state variable for x86 converter + encoding - 0 (for decoding), 1 (for encoding) + + Out: + state - state variable for x86 converter + + Returns: + The number of processed bytes. If you call these functions with multiple calls, + you must start next call with first byte after block of processed bytes. + + Type Endian Alignment LookAhead + + x86 little 1 4 + ARMT little 2 2 + ARM little 4 0 + PPC big 4 0 + SPARC big 4 0 + IA64 little 16 0 + + size must be >= Alignment + LookAhead, if it's not last block. + If (size < Alignment + LookAhead), converter returns 0. + + Example: + + UInt32 ip = 0; + for () + { + ; size must be >= Alignment + LookAhead, if it's not last block + SizeT processed = Convert(data, size, ip, 1); + data += processed; + size -= processed; + ip += processed; + } +*/ + +#define x86_Convert_Init(state) { state = 0; } +SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); +SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); +SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); + +EXTERN_C_END + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Bra86.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Bra86.c new file mode 100644 index 00000000..93ed4d76 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Bra86.c @@ -0,0 +1,82 @@ +/* Bra86.c -- Converter for x86 code (BCJ) +2017-04-03 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "Bra.h" + +#define Test86MSByte(b) ((((b) + 1) & 0xFE) == 0) + +SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) +{ + SizeT pos = 0; + UInt32 mask = *state & 7; + if (size < 5) + return 0; + size -= 4; + ip += 5; + + for (;;) + { + Byte *p = data + pos; + const Byte *limit = data + size; + for (; p < limit; p++) + if ((*p & 0xFE) == 0xE8) + break; + + { + SizeT d = (SizeT)(p - data - pos); + pos = (SizeT)(p - data); + if (p >= limit) + { + *state = (d > 2 ? 0 : mask >> (unsigned)d); + return pos; + } + if (d > 2) + mask = 0; + else + { + mask >>= (unsigned)d; + if (mask != 0 && (mask > 4 || mask == 3 || Test86MSByte(p[(size_t)(mask >> 1) + 1]))) + { + mask = (mask >> 1) | 4; + pos++; + continue; + } + } + } + + if (Test86MSByte(p[4])) + { + UInt32 v = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); + UInt32 cur = ip + (UInt32)pos; + pos += 5; + if (encoding) + v += cur; + else + v -= cur; + if (mask != 0) + { + unsigned sh = (mask & 6) << 2; + if (Test86MSByte((Byte)(v >> sh))) + { + v ^= (((UInt32)0x100 << sh) - 1); + if (encoding) + v += cur; + else + v -= cur; + } + mask = 0; + } + p[1] = (Byte)v; + p[2] = (Byte)(v >> 8); + p[3] = (Byte)(v >> 16); + p[4] = (Byte)(0 - ((v >> 24) & 1)); + } + else + { + mask = (mask >> 1) | 4; + pos++; + } + } +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Compiler.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Compiler.h new file mode 100644 index 00000000..0cc409d8 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Compiler.h @@ -0,0 +1,33 @@ +/* Compiler.h +2017-04-03 : Igor Pavlov : Public domain */ + +#ifndef __7Z_COMPILER_H +#define __7Z_COMPILER_H + +#ifdef _MSC_VER + + #ifdef UNDER_CE + #define RPC_NO_WINDOWS_H + /* #pragma warning(disable : 4115) // '_RPC_ASYNC_STATE' : named type definition in parentheses */ + #pragma warning(disable : 4201) // nonstandard extension used : nameless struct/union + #pragma warning(disable : 4214) // nonstandard extension used : bit field types other than int + #endif + + #if _MSC_VER >= 1300 + #pragma warning(disable : 4996) // This function or variable may be unsafe + #else + #pragma warning(disable : 4511) // copy constructor could not be generated + #pragma warning(disable : 4512) // assignment operator could not be generated + #pragma warning(disable : 4514) // unreferenced inline function has been removed + #pragma warning(disable : 4702) // unreachable code + #pragma warning(disable : 4710) // not inlined + #pragma warning(disable : 4714) // function marked as __forceinline not inlined + #pragma warning(disable : 4786) // identifier was truncated to '255' characters in the debug information + #endif + +#endif + +#define UNUSED_VAR(x) (void)x; +/* #define UNUSED_VAR(x) x=x; */ + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/CpuArch.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/CpuArch.h new file mode 100644 index 00000000..bd429388 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/CpuArch.h @@ -0,0 +1,336 @@ +/* CpuArch.h -- CPU specific code +2018-02-18 : Igor Pavlov : Public domain */ + +#ifndef __CPU_ARCH_H +#define __CPU_ARCH_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* +MY_CPU_LE means that CPU is LITTLE ENDIAN. +MY_CPU_BE means that CPU is BIG ENDIAN. +If MY_CPU_LE and MY_CPU_BE are not defined, we don't know about ENDIANNESS of platform. + +MY_CPU_LE_UNALIGN means that CPU is LITTLE ENDIAN and CPU supports unaligned memory accesses. +*/ + +#if defined(_M_X64) \ + || defined(_M_AMD64) \ + || defined(__x86_64__) \ + || defined(__AMD64__) \ + || defined(__amd64__) + #define MY_CPU_AMD64 + #ifdef __ILP32__ + #define MY_CPU_NAME "x32" + #else + #define MY_CPU_NAME "x64" + #endif + #define MY_CPU_64BIT +#endif + + +#if defined(_M_IX86) \ + || defined(__i386__) + #define MY_CPU_X86 + #define MY_CPU_NAME "x86" + #define MY_CPU_32BIT +#endif + + +#if defined(_M_ARM64) \ + || defined(__AARCH64EL__) \ + || defined(__AARCH64EB__) \ + || defined(__aarch64__) + #define MY_CPU_ARM64 + #define MY_CPU_NAME "arm64" + #define MY_CPU_64BIT +#endif + + +#if defined(_M_ARM) \ + || defined(_M_ARM_NT) \ + || defined(_M_ARMT) \ + || defined(__arm__) \ + || defined(__thumb__) \ + || defined(__ARMEL__) \ + || defined(__ARMEB__) \ + || defined(__THUMBEL__) \ + || defined(__THUMBEB__) + #define MY_CPU_ARM + #define MY_CPU_NAME "arm" + #define MY_CPU_32BIT +#endif + + +#if defined(_M_IA64) \ + || defined(__ia64__) + #define MY_CPU_IA64 + #define MY_CPU_NAME "ia64" + #define MY_CPU_64BIT +#endif + + +#if defined(__mips64) \ + || defined(__mips64__) \ + || (defined(__mips) && (__mips == 64 || __mips == 4 || __mips == 3)) + #define MY_CPU_NAME "mips64" + #define MY_CPU_64BIT +#elif defined(__mips__) + #define MY_CPU_NAME "mips" + /* #define MY_CPU_32BIT */ +#endif + + +#if defined(__ppc64__) \ + || defined(__powerpc64__) + #ifdef __ILP32__ + #define MY_CPU_NAME "ppc64-32" + #else + #define MY_CPU_NAME "ppc64" + #endif + #define MY_CPU_64BIT +#elif defined(__ppc__) \ + || defined(__powerpc__) + #define MY_CPU_NAME "ppc" + #define MY_CPU_32BIT +#endif + + +#if defined(__sparc64__) + #define MY_CPU_NAME "sparc64" + #define MY_CPU_64BIT +#elif defined(__sparc__) + #define MY_CPU_NAME "sparc" + /* #define MY_CPU_32BIT */ +#endif + + +#if defined(MY_CPU_X86) || defined(MY_CPU_AMD64) +#define MY_CPU_X86_OR_AMD64 +#endif + + +#ifdef _WIN32 + + #ifdef MY_CPU_ARM + #define MY_CPU_ARM_LE + #endif + + #ifdef MY_CPU_ARM64 + #define MY_CPU_ARM64_LE + #endif + + #ifdef _M_IA64 + #define MY_CPU_IA64_LE + #endif + +#endif + + +#if defined(MY_CPU_X86_OR_AMD64) \ + || defined(MY_CPU_ARM_LE) \ + || defined(MY_CPU_ARM64_LE) \ + || defined(MY_CPU_IA64_LE) \ + || defined(__LITTLE_ENDIAN__) \ + || defined(__ARMEL__) \ + || defined(__THUMBEL__) \ + || defined(__AARCH64EL__) \ + || defined(__MIPSEL__) \ + || defined(__MIPSEL) \ + || defined(_MIPSEL) \ + || defined(__BFIN__) \ + || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) + #define MY_CPU_LE +#endif + +#if defined(__BIG_ENDIAN__) \ + || defined(__ARMEB__) \ + || defined(__THUMBEB__) \ + || defined(__AARCH64EB__) \ + || defined(__MIPSEB__) \ + || defined(__MIPSEB) \ + || defined(_MIPSEB) \ + || defined(__m68k__) \ + || defined(__s390__) \ + || defined(__s390x__) \ + || defined(__zarch__) \ + || (defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) + #define MY_CPU_BE +#endif + + +#if defined(MY_CPU_LE) && defined(MY_CPU_BE) + #error Stop_Compiling_Bad_Endian +#endif + + +#if defined(MY_CPU_32BIT) && defined(MY_CPU_64BIT) + #error Stop_Compiling_Bad_32_64_BIT +#endif + + +#ifndef MY_CPU_NAME + #ifdef MY_CPU_LE + #define MY_CPU_NAME "LE" + #elif defined(MY_CPU_BE) + #define MY_CPU_NAME "BE" + #else + /* + #define MY_CPU_NAME "" + */ + #endif +#endif + + + + + +#ifdef MY_CPU_LE + #if defined(MY_CPU_X86_OR_AMD64) \ + || defined(MY_CPU_ARM64) \ + || defined(__ARM_FEATURE_UNALIGNED) + #define MY_CPU_LE_UNALIGN + #endif +#endif + + +#ifdef MY_CPU_LE_UNALIGN + +#define GetUi16(p) (*(const UInt16 *)(const void *)(p)) +#define GetUi32(p) (*(const UInt32 *)(const void *)(p)) +#define GetUi64(p) (*(const UInt64 *)(const void *)(p)) + +#define SetUi16(p, v) { *(UInt16 *)(p) = (v); } +#define SetUi32(p, v) { *(UInt32 *)(p) = (v); } +#define SetUi64(p, v) { *(UInt64 *)(p) = (v); } + +#else + +#define GetUi16(p) ( (UInt16) ( \ + ((const Byte *)(p))[0] | \ + ((UInt16)((const Byte *)(p))[1] << 8) )) + +#define GetUi32(p) ( \ + ((const Byte *)(p))[0] | \ + ((UInt32)((const Byte *)(p))[1] << 8) | \ + ((UInt32)((const Byte *)(p))[2] << 16) | \ + ((UInt32)((const Byte *)(p))[3] << 24)) + +#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) + +#define SetUi16(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ + _ppp_[0] = (Byte)_vvv_; \ + _ppp_[1] = (Byte)(_vvv_ >> 8); } + +#define SetUi32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ + _ppp_[0] = (Byte)_vvv_; \ + _ppp_[1] = (Byte)(_vvv_ >> 8); \ + _ppp_[2] = (Byte)(_vvv_ >> 16); \ + _ppp_[3] = (Byte)(_vvv_ >> 24); } + +#define SetUi64(p, v) { Byte *_ppp2_ = (Byte *)(p); UInt64 _vvv2_ = (v); \ + SetUi32(_ppp2_ , (UInt32)_vvv2_); \ + SetUi32(_ppp2_ + 4, (UInt32)(_vvv2_ >> 32)); } + +#endif + +#ifdef __has_builtin + #define MY__has_builtin(x) __has_builtin(x) +#else + #define MY__has_builtin(x) 0 +#endif + +#if defined(MY_CPU_LE_UNALIGN) && /* defined(_WIN64) && */ (_MSC_VER >= 1300) + +/* Note: we use bswap instruction, that is unsupported in 386 cpu */ + +#include + +#pragma intrinsic(_byteswap_ushort) +#pragma intrinsic(_byteswap_ulong) +#pragma intrinsic(_byteswap_uint64) + +/* #define GetBe16(p) _byteswap_ushort(*(const UInt16 *)(const Byte *)(p)) */ +#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) +#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) + +#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = _byteswap_ulong(v) + +#elif defined(MY_CPU_LE_UNALIGN) && ( \ + (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))) \ + || (defined(__clang__) && MY__has_builtin(__builtin_bswap16)) ) + +/* #define GetBe16(p) __builtin_bswap16(*(const UInt16 *)(const Byte *)(p)) */ +#define GetBe32(p) __builtin_bswap32(*(const UInt32 *)(const Byte *)(p)) +#define GetBe64(p) __builtin_bswap64(*(const UInt64 *)(const Byte *)(p)) + +#define SetBe32(p, v) (*(UInt32 *)(void *)(p)) = __builtin_bswap32(v) + +#else + +#define GetBe32(p) ( \ + ((UInt32)((const Byte *)(p))[0] << 24) | \ + ((UInt32)((const Byte *)(p))[1] << 16) | \ + ((UInt32)((const Byte *)(p))[2] << 8) | \ + ((const Byte *)(p))[3] ) + +#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) + +#define SetBe32(p, v) { Byte *_ppp_ = (Byte *)(p); UInt32 _vvv_ = (v); \ + _ppp_[0] = (Byte)(_vvv_ >> 24); \ + _ppp_[1] = (Byte)(_vvv_ >> 16); \ + _ppp_[2] = (Byte)(_vvv_ >> 8); \ + _ppp_[3] = (Byte)_vvv_; } + +#endif + + +#ifndef GetBe16 + +#define GetBe16(p) ( (UInt16) ( \ + ((UInt16)((const Byte *)(p))[0] << 8) | \ + ((const Byte *)(p))[1] )) + +#endif + + + +#ifdef MY_CPU_X86_OR_AMD64 + +typedef struct +{ + UInt32 maxFunc; + UInt32 vendor[3]; + UInt32 ver; + UInt32 b; + UInt32 c; + UInt32 d; +} Cx86cpuid; + +enum +{ + CPU_FIRM_INTEL, + CPU_FIRM_AMD, + CPU_FIRM_VIA +}; + +void MyCPUID(UInt32 function, UInt32 *a, UInt32 *b, UInt32 *c, UInt32 *d); + +BoolInt x86cpuid_CheckAndRead(Cx86cpuid *p); +int x86cpuid_GetFirm(const Cx86cpuid *p); + +#define x86cpuid_GetFamily(ver) (((ver >> 16) & 0xFF0) | ((ver >> 8) & 0xF)) +#define x86cpuid_GetModel(ver) (((ver >> 12) & 0xF0) | ((ver >> 4) & 0xF)) +#define x86cpuid_GetStepping(ver) (ver & 0xF) + +BoolInt CPU_Is_InOrder(); +BoolInt CPU_Is_Aes_Supported(); +BoolInt CPU_IsSupported_PageGB(); + +#endif + +EXTERN_C_END + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.c new file mode 100644 index 00000000..92264c7a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.c @@ -0,0 +1,1127 @@ +/* LzFind.c -- Match finder for LZ algorithms +2018-07-08 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +#include "LzFind.h" +#include "LzHash.h" + +#define kEmptyHashValue 0 +#define kMaxValForNormalize ((UInt32)0xFFFFFFFF) +#define kNormalizeStepMin (1 << 10) /* it must be power of 2 */ +#define kNormalizeMask (~(UInt32)(kNormalizeStepMin - 1)) +#define kMaxHistorySize ((UInt32)7 << 29) + +#define kStartMaxLen 3 + +static void LzInWindow_Free(CMatchFinder *p, ISzAllocPtr alloc) +{ + if (!p->directInput) + { + ISzAlloc_Free(alloc, p->bufferBase); + p->bufferBase = NULL; + } +} + +/* keepSizeBefore + keepSizeAfter + keepSizeReserv must be < 4G) */ + +static int LzInWindow_Create(CMatchFinder *p, UInt32 keepSizeReserv, ISzAllocPtr alloc) +{ + UInt32 blockSize = p->keepSizeBefore + p->keepSizeAfter + keepSizeReserv; + if (p->directInput) + { + p->blockSize = blockSize; + return 1; + } + if (!p->bufferBase || p->blockSize != blockSize) + { + LzInWindow_Free(p, alloc); + p->blockSize = blockSize; + p->bufferBase = (Byte *)ISzAlloc_Alloc(alloc, (size_t)blockSize); + } + return (p->bufferBase != NULL); +} + +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p) { return p->buffer; } + +UInt32 MatchFinder_GetNumAvailableBytes(CMatchFinder *p) { return p->streamPos - p->pos; } + +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue) +{ + p->posLimit -= subValue; + p->pos -= subValue; + p->streamPos -= subValue; +} + +static void MatchFinder_ReadBlock(CMatchFinder *p) +{ + if (p->streamEndWasReached || p->result != SZ_OK) + return; + + /* We use (p->streamPos - p->pos) value. (p->streamPos < p->pos) is allowed. */ + + if (p->directInput) + { + UInt32 curSize = 0xFFFFFFFF - (p->streamPos - p->pos); + if (curSize > p->directInputRem) + curSize = (UInt32)p->directInputRem; + p->directInputRem -= curSize; + p->streamPos += curSize; + if (p->directInputRem == 0) + p->streamEndWasReached = 1; + return; + } + + for (;;) + { + Byte *dest = p->buffer + (p->streamPos - p->pos); + size_t size = (p->bufferBase + p->blockSize - dest); + if (size == 0) + return; + + p->result = ISeqInStream_Read(p->stream, dest, &size); + if (p->result != SZ_OK) + return; + if (size == 0) + { + p->streamEndWasReached = 1; + return; + } + p->streamPos += (UInt32)size; + if (p->streamPos - p->pos > p->keepSizeAfter) + return; + } +} + +void MatchFinder_MoveBlock(CMatchFinder *p) +{ + memmove(p->bufferBase, + p->buffer - p->keepSizeBefore, + (size_t)(p->streamPos - p->pos) + p->keepSizeBefore); + p->buffer = p->bufferBase + p->keepSizeBefore; +} + +int MatchFinder_NeedMove(CMatchFinder *p) +{ + if (p->directInput) + return 0; + /* if (p->streamEndWasReached) return 0; */ + return ((size_t)(p->bufferBase + p->blockSize - p->buffer) <= p->keepSizeAfter); +} + +void MatchFinder_ReadIfRequired(CMatchFinder *p) +{ + if (p->streamEndWasReached) + return; + if (p->keepSizeAfter >= p->streamPos - p->pos) + MatchFinder_ReadBlock(p); +} + +static void MatchFinder_CheckAndMoveAndRead(CMatchFinder *p) +{ + if (MatchFinder_NeedMove(p)) + MatchFinder_MoveBlock(p); + MatchFinder_ReadBlock(p); +} + +static void MatchFinder_SetDefaultSettings(CMatchFinder *p) +{ + p->cutValue = 32; + p->btMode = 1; + p->numHashBytes = 4; + p->bigHash = 0; +} + +#define kCrcPoly 0xEDB88320 + +void MatchFinder_Construct(CMatchFinder *p) +{ + unsigned i; + p->bufferBase = NULL; + p->directInput = 0; + p->hash = NULL; + p->expectedDataSize = (UInt64)(Int64)-1; + MatchFinder_SetDefaultSettings(p); + + for (i = 0; i < 256; i++) + { + UInt32 r = (UInt32)i; + unsigned j; + for (j = 0; j < 8; j++) + r = (r >> 1) ^ (kCrcPoly & ((UInt32)0 - (r & 1))); + p->crc[i] = r; + } +} + +static void MatchFinder_FreeThisClassMemory(CMatchFinder *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->hash); + p->hash = NULL; +} + +void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc) +{ + MatchFinder_FreeThisClassMemory(p, alloc); + LzInWindow_Free(p, alloc); +} + +static CLzRef* AllocRefs(size_t num, ISzAllocPtr alloc) +{ + size_t sizeInBytes = (size_t)num * sizeof(CLzRef); + if (sizeInBytes / sizeof(CLzRef) != num) + return NULL; + return (CLzRef *)ISzAlloc_Alloc(alloc, sizeInBytes); +} + +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAllocPtr alloc) +{ + UInt32 sizeReserv; + + if (historySize > kMaxHistorySize) + { + MatchFinder_Free(p, alloc); + return 0; + } + + sizeReserv = historySize >> 1; + if (historySize >= ((UInt32)3 << 30)) sizeReserv = historySize >> 3; + else if (historySize >= ((UInt32)2 << 30)) sizeReserv = historySize >> 2; + + sizeReserv += (keepAddBufferBefore + matchMaxLen + keepAddBufferAfter) / 2 + (1 << 19); + + p->keepSizeBefore = historySize + keepAddBufferBefore + 1; + p->keepSizeAfter = matchMaxLen + keepAddBufferAfter; + + /* we need one additional byte, since we use MoveBlock after pos++ and before dictionary using */ + + if (LzInWindow_Create(p, sizeReserv, alloc)) + { + UInt32 newCyclicBufferSize = historySize + 1; + UInt32 hs; + p->matchMaxLen = matchMaxLen; + { + p->fixedHashSize = 0; + if (p->numHashBytes == 2) + hs = (1 << 16) - 1; + else + { + hs = historySize; + if (hs > p->expectedDataSize) + hs = (UInt32)p->expectedDataSize; + if (hs != 0) + hs--; + hs |= (hs >> 1); + hs |= (hs >> 2); + hs |= (hs >> 4); + hs |= (hs >> 8); + hs >>= 1; + hs |= 0xFFFF; /* don't change it! It's required for Deflate */ + if (hs > (1 << 24)) + { + if (p->numHashBytes == 3) + hs = (1 << 24) - 1; + else + hs >>= 1; + /* if (bigHash) mode, GetHeads4b() in LzFindMt.c needs (hs >= ((1 << 24) - 1))) */ + } + } + p->hashMask = hs; + hs++; + if (p->numHashBytes > 2) p->fixedHashSize += kHash2Size; + if (p->numHashBytes > 3) p->fixedHashSize += kHash3Size; + if (p->numHashBytes > 4) p->fixedHashSize += kHash4Size; + hs += p->fixedHashSize; + } + + { + size_t newSize; + size_t numSons; + p->historySize = historySize; + p->hashSizeSum = hs; + p->cyclicBufferSize = newCyclicBufferSize; + + numSons = newCyclicBufferSize; + if (p->btMode) + numSons <<= 1; + newSize = hs + numSons; + + if (p->hash && p->numRefs == newSize) + return 1; + + MatchFinder_FreeThisClassMemory(p, alloc); + p->numRefs = newSize; + p->hash = AllocRefs(newSize, alloc); + + if (p->hash) + { + p->son = p->hash + p->hashSizeSum; + return 1; + } + } + } + + MatchFinder_Free(p, alloc); + return 0; +} + +static void MatchFinder_SetLimits(CMatchFinder *p) +{ + UInt32 limit = kMaxValForNormalize - p->pos; + UInt32 limit2 = p->cyclicBufferSize - p->cyclicBufferPos; + + if (limit2 < limit) + limit = limit2; + limit2 = p->streamPos - p->pos; + + if (limit2 <= p->keepSizeAfter) + { + if (limit2 > 0) + limit2 = 1; + } + else + limit2 -= p->keepSizeAfter; + + if (limit2 < limit) + limit = limit2; + + { + UInt32 lenLimit = p->streamPos - p->pos; + if (lenLimit > p->matchMaxLen) + lenLimit = p->matchMaxLen; + p->lenLimit = lenLimit; + } + p->posLimit = p->pos + limit; +} + + +void MatchFinder_Init_LowHash(CMatchFinder *p) +{ + size_t i; + CLzRef *items = p->hash; + size_t numItems = p->fixedHashSize; + for (i = 0; i < numItems; i++) + items[i] = kEmptyHashValue; +} + + +void MatchFinder_Init_HighHash(CMatchFinder *p) +{ + size_t i; + CLzRef *items = p->hash + p->fixedHashSize; + size_t numItems = (size_t)p->hashMask + 1; + for (i = 0; i < numItems; i++) + items[i] = kEmptyHashValue; +} + + +void MatchFinder_Init_3(CMatchFinder *p, int readData) +{ + p->cyclicBufferPos = 0; + p->buffer = p->bufferBase; + p->pos = + p->streamPos = p->cyclicBufferSize; + p->result = SZ_OK; + p->streamEndWasReached = 0; + + if (readData) + MatchFinder_ReadBlock(p); + + MatchFinder_SetLimits(p); +} + + +void MatchFinder_Init(CMatchFinder *p) +{ + MatchFinder_Init_HighHash(p); + MatchFinder_Init_LowHash(p); + MatchFinder_Init_3(p, True); +} + + +static UInt32 MatchFinder_GetSubValue(CMatchFinder *p) +{ + return (p->pos - p->historySize - 1) & kNormalizeMask; +} + +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems) +{ + size_t i; + for (i = 0; i < numItems; i++) + { + UInt32 value = items[i]; + if (value <= subValue) + value = kEmptyHashValue; + else + value -= subValue; + items[i] = value; + } +} + +static void MatchFinder_Normalize(CMatchFinder *p) +{ + UInt32 subValue = MatchFinder_GetSubValue(p); + MatchFinder_Normalize3(subValue, p->hash, p->numRefs); + MatchFinder_ReduceOffsets(p, subValue); +} + + +MY_NO_INLINE +static void MatchFinder_CheckLimits(CMatchFinder *p) +{ + if (p->pos == kMaxValForNormalize) + MatchFinder_Normalize(p); + if (!p->streamEndWasReached && p->keepSizeAfter == p->streamPos - p->pos) + MatchFinder_CheckAndMoveAndRead(p); + if (p->cyclicBufferPos == p->cyclicBufferSize) + p->cyclicBufferPos = 0; + MatchFinder_SetLimits(p); +} + + +/* + (lenLimit > maxLen) +*/ +MY_FORCE_INLINE +static UInt32 * Hc_GetMatchesSpec(unsigned lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *distances, unsigned maxLen) +{ + /* + son[_cyclicBufferPos] = curMatch; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + return distances; + { + const Byte *pb = cur - delta; + curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; + if (pb[maxLen] == cur[maxLen] && *pb == *cur) + { + UInt32 len = 0; + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + maxLen = len; + *distances++ = len; + *distances++ = delta - 1; + if (len == lenLimit) + return distances; + } + } + } + } + */ + + const Byte *lim = cur + lenLimit; + son[_cyclicBufferPos] = curMatch; + do + { + UInt32 delta = pos - curMatch; + if (delta >= _cyclicBufferSize) + break; + { + ptrdiff_t diff; + curMatch = son[_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)]; + diff = (ptrdiff_t)0 - delta; + if (cur[maxLen] == cur[maxLen + diff]) + { + const Byte *c = cur; + while (*c == c[diff]) + { + if (++c == lim) + { + distances[0] = (UInt32)(lim - cur); + distances[1] = delta - 1; + return distances + 2; + } + } + { + unsigned len = (unsigned)(c - cur); + if (maxLen < len) + { + maxLen = len; + distances[0] = (UInt32)len; + distances[1] = delta - 1; + distances += 2; + } + } + } + } + } + while (--cutValue); + + return distances; +} + + +MY_FORCE_INLINE +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue, + UInt32 *distances, UInt32 maxLen) +{ + CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); + unsigned len0 = 0, len1 = 0; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + return distances; + } + { + CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + unsigned len = (len0 < len1 ? len0 : len1); + UInt32 pair0 = pair[0]; + if (pb[len] == cur[len]) + { + if (++len != lenLimit && pb[len] == cur[len]) + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + maxLen = (UInt32)len; + *distances++ = (UInt32)len; + *distances++ = delta - 1; + if (len == lenLimit) + { + *ptr1 = pair0; + *ptr0 = pair[1]; + return distances; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } +} + +static void SkipMatchesSpec(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *cur, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 cutValue) +{ + CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); + unsigned len0 = 0, len1 = 0; + for (;;) + { + UInt32 delta = pos - curMatch; + if (cutValue-- == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + return; + } + { + CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((delta > _cyclicBufferPos) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + unsigned len = (len0 < len1 ? len0 : len1); + if (pb[len] == cur[len]) + { + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + { + if (len == lenLimit) + { + *ptr1 = pair[0]; + *ptr0 = pair[1]; + return; + } + } + } + if (pb[len] < cur[len]) + { + *ptr1 = curMatch; + ptr1 = pair + 1; + curMatch = *ptr1; + len1 = len; + } + else + { + *ptr0 = curMatch; + ptr0 = pair; + curMatch = *ptr0; + len0 = len; + } + } + } +} + +#define MOVE_POS \ + ++p->cyclicBufferPos; \ + p->buffer++; \ + if (++p->pos == p->posLimit) MatchFinder_CheckLimits(p); + +#define MOVE_POS_RET MOVE_POS return (UInt32)offset; + +static void MatchFinder_MovePos(CMatchFinder *p) { MOVE_POS; } + +#define GET_MATCHES_HEADER2(minLen, ret_op) \ + unsigned lenLimit; UInt32 hv; const Byte *cur; UInt32 curMatch; \ + lenLimit = (unsigned)p->lenLimit; { if (lenLimit < minLen) { MatchFinder_MovePos(p); ret_op; }} \ + cur = p->buffer; + +#define GET_MATCHES_HEADER(minLen) GET_MATCHES_HEADER2(minLen, return 0) +#define SKIP_HEADER(minLen) GET_MATCHES_HEADER2(minLen, continue) + +#define MF_PARAMS(p) p->pos, p->buffer, p->son, p->cyclicBufferPos, p->cyclicBufferSize, p->cutValue + +#define GET_MATCHES_FOOTER(offset, maxLen) \ + offset = (unsigned)(GetMatchesSpec1((UInt32)lenLimit, curMatch, MF_PARAMS(p), \ + distances + offset, (UInt32)maxLen) - distances); MOVE_POS_RET; + +#define SKIP_FOOTER \ + SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); MOVE_POS; + +#define UPDATE_maxLen { \ + ptrdiff_t diff = (ptrdiff_t)0 - d2; \ + const Byte *c = cur + maxLen; \ + const Byte *lim = cur + lenLimit; \ + for (; c != lim; c++) if (*(c + diff) != *c) break; \ + maxLen = (unsigned)(c - cur); } + +static UInt32 Bt2_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + unsigned offset; + GET_MATCHES_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hv]; + p->hash[hv] = p->pos; + offset = 0; + GET_MATCHES_FOOTER(offset, 1) +} + +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + unsigned offset; + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hv]; + p->hash[hv] = p->pos; + offset = 0; + GET_MATCHES_FOOTER(offset, 2) +} + +static UInt32 Bt3_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 h2, d2, pos; + unsigned maxLen, offset; + UInt32 *hash; + GET_MATCHES_HEADER(3) + + HASH3_CALC; + + hash = p->hash; + pos = p->pos; + + d2 = pos - hash[h2]; + + curMatch = (hash + kFix3HashSize)[hv]; + + hash[h2] = pos; + (hash + kFix3HashSize)[hv] = pos; + + maxLen = 2; + offset = 0; + + if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + { + UPDATE_maxLen + distances[0] = (UInt32)maxLen; + distances[1] = d2 - 1; + offset = 2; + if (maxLen == lenLimit) + { + SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + + GET_MATCHES_FOOTER(offset, maxLen) +} + +static UInt32 Bt4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 h2, h3, d2, d3, pos; + unsigned maxLen, offset; + UInt32 *hash; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + hash = p->hash; + pos = p->pos; + + d2 = pos - hash [h2]; + d3 = pos - (hash + kFix3HashSize)[h3]; + + curMatch = (hash + kFix4HashSize)[hv]; + + hash [h2] = pos; + (hash + kFix3HashSize)[h3] = pos; + (hash + kFix4HashSize)[hv] = pos; + + maxLen = 0; + offset = 0; + + if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + { + maxLen = 2; + distances[0] = 2; + distances[1] = d2 - 1; + offset = 2; + } + + if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur) + { + maxLen = 3; + distances[(size_t)offset + 1] = d3 - 1; + offset += 2; + d2 = d3; + } + + if (offset != 0) + { + UPDATE_maxLen + distances[(size_t)offset - 2] = (UInt32)maxLen; + if (maxLen == lenLimit) + { + SkipMatchesSpec((UInt32)lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + + if (maxLen < 3) + maxLen = 3; + + GET_MATCHES_FOOTER(offset, maxLen) +} + +/* +static UInt32 Bt5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos; + UInt32 *hash; + GET_MATCHES_HEADER(5) + + HASH5_CALC; + + hash = p->hash; + pos = p->pos; + + d2 = pos - hash [h2]; + d3 = pos - (hash + kFix3HashSize)[h3]; + d4 = pos - (hash + kFix4HashSize)[h4]; + + curMatch = (hash + kFix5HashSize)[hv]; + + hash [h2] = pos; + (hash + kFix3HashSize)[h3] = pos; + (hash + kFix4HashSize)[h4] = pos; + (hash + kFix5HashSize)[hv] = pos; + + maxLen = 0; + offset = 0; + + if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = d2 - 1; + offset = 2; + if (*(cur - d2 + 2) == cur[2]) + distances[0] = maxLen = 3; + else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur) + { + distances[2] = maxLen = 3; + distances[3] = d3 - 1; + offset = 4; + d2 = d3; + } + } + else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur) + { + distances[0] = maxLen = 3; + distances[1] = d3 - 1; + offset = 2; + d2 = d3; + } + + if (d2 != d4 && d4 < p->cyclicBufferSize + && *(cur - d4) == *cur + && *(cur - d4 + 3) == *(cur + 3)) + { + maxLen = 4; + distances[(size_t)offset + 1] = d4 - 1; + offset += 2; + d2 = d4; + } + + if (offset != 0) + { + UPDATE_maxLen + distances[(size_t)offset - 2] = maxLen; + if (maxLen == lenLimit) + { + SkipMatchesSpec(lenLimit, curMatch, MF_PARAMS(p)); + MOVE_POS_RET; + } + } + + if (maxLen < 4) + maxLen = 4; + + GET_MATCHES_FOOTER(offset, maxLen) +} +*/ + +static UInt32 Hc4_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 h2, h3, d2, d3, pos; + unsigned maxLen, offset; + UInt32 *hash; + GET_MATCHES_HEADER(4) + + HASH4_CALC; + + hash = p->hash; + pos = p->pos; + + d2 = pos - hash [h2]; + d3 = pos - (hash + kFix3HashSize)[h3]; + curMatch = (hash + kFix4HashSize)[hv]; + + hash [h2] = pos; + (hash + kFix3HashSize)[h3] = pos; + (hash + kFix4HashSize)[hv] = pos; + + maxLen = 0; + offset = 0; + + if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + { + maxLen = 2; + distances[0] = 2; + distances[1] = d2 - 1; + offset = 2; + } + + if (d2 != d3 && d3 < p->cyclicBufferSize && *(cur - d3) == *cur) + { + maxLen = 3; + distances[(size_t)offset + 1] = d3 - 1; + offset += 2; + d2 = d3; + } + + if (offset != 0) + { + UPDATE_maxLen + distances[(size_t)offset - 2] = (UInt32)maxLen; + if (maxLen == lenLimit) + { + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS_RET; + } + } + + if (maxLen < 3) + maxLen = 3; + + offset = (unsigned)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances + offset, maxLen) - (distances)); + MOVE_POS_RET +} + +/* +static UInt32 Hc5_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + UInt32 h2, h3, h4, d2, d3, d4, maxLen, offset, pos + UInt32 *hash; + GET_MATCHES_HEADER(5) + + HASH5_CALC; + + hash = p->hash; + pos = p->pos; + + d2 = pos - hash [h2]; + d3 = pos - (hash + kFix3HashSize)[h3]; + d4 = pos - (hash + kFix4HashSize)[h4]; + + curMatch = (hash + kFix5HashSize)[hv]; + + hash [h2] = pos; + (hash + kFix3HashSize)[h3] = pos; + (hash + kFix4HashSize)[h4] = pos; + (hash + kFix5HashSize)[hv] = pos; + + maxLen = 0; + offset = 0; + + if (d2 < p->cyclicBufferSize && *(cur - d2) == *cur) + { + distances[0] = maxLen = 2; + distances[1] = d2 - 1; + offset = 2; + if (*(cur - d2 + 2) == cur[2]) + distances[0] = maxLen = 3; + else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur) + { + distances[2] = maxLen = 3; + distances[3] = d3 - 1; + offset = 4; + d2 = d3; + } + } + else if (d3 < p->cyclicBufferSize && *(cur - d3) == *cur) + { + distances[0] = maxLen = 3; + distances[1] = d3 - 1; + offset = 2; + d2 = d3; + } + + if (d2 != d4 && d4 < p->cyclicBufferSize + && *(cur - d4) == *cur + && *(cur - d4 + 3) == *(cur + 3)) + { + maxLen = 4; + distances[(size_t)offset + 1] = d4 - 1; + offset += 2; + d2 = d4; + } + + if (offset != 0) + { + UPDATE_maxLen + distances[(size_t)offset - 2] = maxLen; + if (maxLen == lenLimit) + { + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS_RET; + } + } + + if (maxLen < 4) + maxLen = 4; + + offset = (UInt32)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances + offset, maxLen) - (distances)); + MOVE_POS_RET +} +*/ + +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances) +{ + unsigned offset; + GET_MATCHES_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hv]; + p->hash[hv] = p->pos; + offset = (unsigned)(Hc_GetMatchesSpec(lenLimit, curMatch, MF_PARAMS(p), + distances, 2) - (distances)); + MOVE_POS_RET +} + +static void Bt2_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(2) + HASH2_CALC; + curMatch = p->hash[hv]; + p->hash[hv] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hv]; + p->hash[hv] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt3_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 h2; + UInt32 *hash; + SKIP_HEADER(3) + HASH3_CALC; + hash = p->hash; + curMatch = (hash + kFix3HashSize)[hv]; + hash[h2] = + (hash + kFix3HashSize)[hv] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +static void Bt4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 h2, h3; + UInt32 *hash; + SKIP_HEADER(4) + HASH4_CALC; + hash = p->hash; + curMatch = (hash + kFix4HashSize)[hv]; + hash [h2] = + (hash + kFix3HashSize)[h3] = + (hash + kFix4HashSize)[hv] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} + +/* +static void Bt5_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 h2, h3, h4; + UInt32 *hash; + SKIP_HEADER(5) + HASH5_CALC; + hash = p->hash; + curMatch = (hash + kFix5HashSize)[hv]; + hash [h2] = + (hash + kFix3HashSize)[h3] = + (hash + kFix4HashSize)[h4] = + (hash + kFix5HashSize)[hv] = p->pos; + SKIP_FOOTER + } + while (--num != 0); +} +*/ + +static void Hc4_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 h2, h3; + UInt32 *hash; + SKIP_HEADER(4) + HASH4_CALC; + hash = p->hash; + curMatch = (hash + kFix4HashSize)[hv]; + hash [h2] = + (hash + kFix3HashSize)[h3] = + (hash + kFix4HashSize)[hv] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} + +/* +static void Hc5_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + UInt32 h2, h3, h4; + UInt32 *hash; + SKIP_HEADER(5) + HASH5_CALC; + hash = p->hash; + curMatch = hash + kFix5HashSize)[hv]; + hash [h2] = + (hash + kFix3HashSize)[h3] = + (hash + kFix4HashSize)[h4] = + (hash + kFix5HashSize)[hv] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} +*/ + +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num) +{ + do + { + SKIP_HEADER(3) + HASH_ZIP_CALC; + curMatch = p->hash[hv]; + p->hash[hv] = p->pos; + p->son[p->cyclicBufferPos] = curMatch; + MOVE_POS + } + while (--num != 0); +} + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable) +{ + vTable->Init = (Mf_Init_Func)MatchFinder_Init; + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinder_GetNumAvailableBytes; + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinder_GetPointerToCurrentPos; + if (!p->btMode) + { + /* if (p->numHashBytes <= 4) */ + { + vTable->GetMatches = (Mf_GetMatches_Func)Hc4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Hc4_MatchFinder_Skip; + } + /* + else + { + vTable->GetMatches = (Mf_GetMatches_Func)Hc5_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Hc5_MatchFinder_Skip; + } + */ + } + else if (p->numHashBytes == 2) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt2_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt2_MatchFinder_Skip; + } + else if (p->numHashBytes == 3) + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt3_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt3_MatchFinder_Skip; + } + else /* if (p->numHashBytes == 4) */ + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt4_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt4_MatchFinder_Skip; + } + /* + else + { + vTable->GetMatches = (Mf_GetMatches_Func)Bt5_MatchFinder_GetMatches; + vTable->Skip = (Mf_Skip_Func)Bt5_MatchFinder_Skip; + } + */ +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.h new file mode 100644 index 00000000..f2c8519b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFind.h @@ -0,0 +1,121 @@ +/* LzFind.h -- Match finder for LZ algorithms +2017-06-10 : Igor Pavlov : Public domain */ + +#ifndef __LZ_FIND_H +#define __LZ_FIND_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +typedef UInt32 CLzRef; + +typedef struct _CMatchFinder +{ + Byte *buffer; + UInt32 pos; + UInt32 posLimit; + UInt32 streamPos; + UInt32 lenLimit; + + UInt32 cyclicBufferPos; + UInt32 cyclicBufferSize; /* it must be = (historySize + 1) */ + + Byte streamEndWasReached; + Byte btMode; + Byte bigHash; + Byte directInput; + + UInt32 matchMaxLen; + CLzRef *hash; + CLzRef *son; + UInt32 hashMask; + UInt32 cutValue; + + Byte *bufferBase; + ISeqInStream *stream; + + UInt32 blockSize; + UInt32 keepSizeBefore; + UInt32 keepSizeAfter; + + UInt32 numHashBytes; + size_t directInputRem; + UInt32 historySize; + UInt32 fixedHashSize; + UInt32 hashSizeSum; + SRes result; + UInt32 crc[256]; + size_t numRefs; + + UInt64 expectedDataSize; +} CMatchFinder; + +#define Inline_MatchFinder_GetPointerToCurrentPos(p) ((p)->buffer) + +#define Inline_MatchFinder_GetNumAvailableBytes(p) ((p)->streamPos - (p)->pos) + +#define Inline_MatchFinder_IsFinishedOK(p) \ + ((p)->streamEndWasReached \ + && (p)->streamPos == (p)->pos \ + && (!(p)->directInput || (p)->directInputRem == 0)) + +int MatchFinder_NeedMove(CMatchFinder *p); +Byte *MatchFinder_GetPointerToCurrentPos(CMatchFinder *p); +void MatchFinder_MoveBlock(CMatchFinder *p); +void MatchFinder_ReadIfRequired(CMatchFinder *p); + +void MatchFinder_Construct(CMatchFinder *p); + +/* Conditions: + historySize <= 3 GB + keepAddBufferBefore + matchMaxLen + keepAddBufferAfter < 511MB +*/ +int MatchFinder_Create(CMatchFinder *p, UInt32 historySize, + UInt32 keepAddBufferBefore, UInt32 matchMaxLen, UInt32 keepAddBufferAfter, + ISzAllocPtr alloc); +void MatchFinder_Free(CMatchFinder *p, ISzAllocPtr alloc); +void MatchFinder_Normalize3(UInt32 subValue, CLzRef *items, size_t numItems); +void MatchFinder_ReduceOffsets(CMatchFinder *p, UInt32 subValue); + +UInt32 * GetMatchesSpec1(UInt32 lenLimit, UInt32 curMatch, UInt32 pos, const Byte *buffer, CLzRef *son, + UInt32 _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, + UInt32 *distances, UInt32 maxLen); + +/* +Conditions: + Mf_GetNumAvailableBytes_Func must be called before each Mf_GetMatchLen_Func. + Mf_GetPointerToCurrentPos_Func's result must be used only before any other function +*/ + +typedef void (*Mf_Init_Func)(void *object); +typedef UInt32 (*Mf_GetNumAvailableBytes_Func)(void *object); +typedef const Byte * (*Mf_GetPointerToCurrentPos_Func)(void *object); +typedef UInt32 (*Mf_GetMatches_Func)(void *object, UInt32 *distances); +typedef void (*Mf_Skip_Func)(void *object, UInt32); + +typedef struct _IMatchFinder +{ + Mf_Init_Func Init; + Mf_GetNumAvailableBytes_Func GetNumAvailableBytes; + Mf_GetPointerToCurrentPos_Func GetPointerToCurrentPos; + Mf_GetMatches_Func GetMatches; + Mf_Skip_Func Skip; +} IMatchFinder; + +void MatchFinder_CreateVTable(CMatchFinder *p, IMatchFinder *vTable); + +void MatchFinder_Init_LowHash(CMatchFinder *p); +void MatchFinder_Init_HighHash(CMatchFinder *p); +void MatchFinder_Init_3(CMatchFinder *p, int readData); +void MatchFinder_Init(CMatchFinder *p); + +UInt32 Bt3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); +UInt32 Hc3Zip_MatchFinder_GetMatches(CMatchFinder *p, UInt32 *distances); + +void Bt3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); +void Hc3Zip_MatchFinder_Skip(CMatchFinder *p, UInt32 num); + +EXTERN_C_END + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.c new file mode 100644 index 00000000..2d170d66 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.c @@ -0,0 +1,853 @@ +/* LzFindMt.c -- multithreaded Match finder for LZ algorithms +2018-12-29 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include "LzHash.h" + +#include "LzFindMt.h" + +static void MtSync_Construct(CMtSync *p) +{ + p->wasCreated = False; + p->csWasInitialized = False; + p->csWasEntered = False; + Thread_Construct(&p->thread); + Event_Construct(&p->canStart); + Event_Construct(&p->wasStarted); + Event_Construct(&p->wasStopped); + Semaphore_Construct(&p->freeSemaphore); + Semaphore_Construct(&p->filledSemaphore); +} + +static void MtSync_GetNextBlock(CMtSync *p) +{ + if (p->needStart) + { + p->numProcessedBlocks = 1; + p->needStart = False; + p->stopWriting = False; + p->exit = False; + Event_Reset(&p->wasStarted); + Event_Reset(&p->wasStopped); + + Event_Set(&p->canStart); + Event_Wait(&p->wasStarted); + + // if (mt) MatchFinder_Init_LowHash(mt->MatchFinder); + } + else + { + CriticalSection_Leave(&p->cs); + p->csWasEntered = False; + p->numProcessedBlocks++; + Semaphore_Release1(&p->freeSemaphore); + } + Semaphore_Wait(&p->filledSemaphore); + CriticalSection_Enter(&p->cs); + p->csWasEntered = True; +} + +/* MtSync_StopWriting must be called if Writing was started */ + +static void MtSync_StopWriting(CMtSync *p) +{ + UInt32 myNumBlocks = p->numProcessedBlocks; + if (!Thread_WasCreated(&p->thread) || p->needStart) + return; + p->stopWriting = True; + if (p->csWasEntered) + { + CriticalSection_Leave(&p->cs); + p->csWasEntered = False; + } + Semaphore_Release1(&p->freeSemaphore); + + Event_Wait(&p->wasStopped); + + while (myNumBlocks++ != p->numProcessedBlocks) + { + Semaphore_Wait(&p->filledSemaphore); + Semaphore_Release1(&p->freeSemaphore); + } + p->needStart = True; +} + +static void MtSync_Destruct(CMtSync *p) +{ + if (Thread_WasCreated(&p->thread)) + { + MtSync_StopWriting(p); + p->exit = True; + if (p->needStart) + Event_Set(&p->canStart); + Thread_Wait(&p->thread); + Thread_Close(&p->thread); + } + if (p->csWasInitialized) + { + CriticalSection_Delete(&p->cs); + p->csWasInitialized = False; + } + + Event_Close(&p->canStart); + Event_Close(&p->wasStarted); + Event_Close(&p->wasStopped); + Semaphore_Close(&p->freeSemaphore); + Semaphore_Close(&p->filledSemaphore); + + p->wasCreated = False; +} + +#define RINOK_THREAD(x) { if ((x) != 0) return SZ_ERROR_THREAD; } + +static SRes MtSync_Create2(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks) +{ + if (p->wasCreated) + return SZ_OK; + + RINOK_THREAD(CriticalSection_Init(&p->cs)); + p->csWasInitialized = True; + + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->canStart)); + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStarted)); + RINOK_THREAD(AutoResetEvent_CreateNotSignaled(&p->wasStopped)); + + RINOK_THREAD(Semaphore_Create(&p->freeSemaphore, numBlocks, numBlocks)); + RINOK_THREAD(Semaphore_Create(&p->filledSemaphore, 0, numBlocks)); + + p->needStart = True; + + RINOK_THREAD(Thread_Create(&p->thread, startAddress, obj)); + p->wasCreated = True; + return SZ_OK; +} + +static SRes MtSync_Create(CMtSync *p, THREAD_FUNC_TYPE startAddress, void *obj, UInt32 numBlocks) +{ + SRes res = MtSync_Create2(p, startAddress, obj, numBlocks); + if (res != SZ_OK) + MtSync_Destruct(p); + return res; +} + +void MtSync_Init(CMtSync *p) { p->needStart = True; } + +#define kMtMaxValForNormalize 0xFFFFFFFF + +#define DEF_GetHeads2(name, v, action) \ + static void GetHeads ## name(const Byte *p, UInt32 pos, \ + UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc) \ + { action; for (; numHeads != 0; numHeads--) { \ + const UInt32 value = (v); p++; *heads++ = pos - hash[value]; hash[value] = pos++; } } + +#define DEF_GetHeads(name, v) DEF_GetHeads2(name, v, ;) + +DEF_GetHeads2(2, (p[0] | ((UInt32)p[1] << 8)), UNUSED_VAR(hashMask); UNUSED_VAR(crc); ) +DEF_GetHeads(3, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8)) & hashMask) +DEF_GetHeads(4, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5)) & hashMask) +DEF_GetHeads(4b, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ ((UInt32)p[3] << 16)) & hashMask) +/* DEF_GetHeads(5, (crc[p[0]] ^ p[1] ^ ((UInt32)p[2] << 8) ^ (crc[p[3]] << 5) ^ (crc[p[4]] << 3)) & hashMask) */ + +static void HashThreadFunc(CMatchFinderMt *mt) +{ + CMtSync *p = &mt->hashSync; + for (;;) + { + UInt32 numProcessedBlocks = 0; + Event_Wait(&p->canStart); + Event_Set(&p->wasStarted); + + MatchFinder_Init_HighHash(mt->MatchFinder); + + for (;;) + { + if (p->exit) + return; + if (p->stopWriting) + { + p->numProcessedBlocks = numProcessedBlocks; + Event_Set(&p->wasStopped); + break; + } + + { + CMatchFinder *mf = mt->MatchFinder; + if (MatchFinder_NeedMove(mf)) + { + CriticalSection_Enter(&mt->btSync.cs); + CriticalSection_Enter(&mt->hashSync.cs); + { + const Byte *beforePtr = Inline_MatchFinder_GetPointerToCurrentPos(mf); + ptrdiff_t offset; + MatchFinder_MoveBlock(mf); + offset = beforePtr - Inline_MatchFinder_GetPointerToCurrentPos(mf); + mt->pointerToCurPos -= offset; + mt->buffer -= offset; + } + CriticalSection_Leave(&mt->btSync.cs); + CriticalSection_Leave(&mt->hashSync.cs); + continue; + } + + Semaphore_Wait(&p->freeSemaphore); + + MatchFinder_ReadIfRequired(mf); + if (mf->pos > (kMtMaxValForNormalize - kMtHashBlockSize)) + { + UInt32 subValue = (mf->pos - mf->historySize - 1); + MatchFinder_ReduceOffsets(mf, subValue); + MatchFinder_Normalize3(subValue, mf->hash + mf->fixedHashSize, (size_t)mf->hashMask + 1); + } + { + UInt32 *heads = mt->hashBuf + ((numProcessedBlocks++) & kMtHashNumBlocksMask) * kMtHashBlockSize; + UInt32 num = mf->streamPos - mf->pos; + heads[0] = 2; + heads[1] = num; + if (num >= mf->numHashBytes) + { + num = num - mf->numHashBytes + 1; + if (num > kMtHashBlockSize - 2) + num = kMtHashBlockSize - 2; + mt->GetHeadsFunc(mf->buffer, mf->pos, mf->hash + mf->fixedHashSize, mf->hashMask, heads + 2, num, mf->crc); + heads[0] = 2 + num; + } + mf->pos += num; + mf->buffer += num; + } + } + + Semaphore_Release1(&p->filledSemaphore); + } + } +} + +static void MatchFinderMt_GetNextBlock_Hash(CMatchFinderMt *p) +{ + MtSync_GetNextBlock(&p->hashSync); + p->hashBufPosLimit = p->hashBufPos = ((p->hashSync.numProcessedBlocks - 1) & kMtHashNumBlocksMask) * kMtHashBlockSize; + p->hashBufPosLimit += p->hashBuf[p->hashBufPos++]; + p->hashNumAvail = p->hashBuf[p->hashBufPos++]; +} + +#define kEmptyHashValue 0 + +#define MFMT_GM_INLINE + +#ifdef MFMT_GM_INLINE + +/* + we use size_t for _cyclicBufferPos instead of UInt32 + to eliminate "movsx" BUG in old MSVC x64 compiler. +*/ + +MY_NO_INLINE +static UInt32 *GetMatchesSpecN(UInt32 lenLimit, UInt32 pos, const Byte *cur, CLzRef *son, + size_t _cyclicBufferPos, UInt32 _cyclicBufferSize, UInt32 _cutValue, + UInt32 *distances, UInt32 _maxLen, const UInt32 *hash, const UInt32 *limit, UInt32 size, UInt32 *posRes) +{ + do + { + UInt32 *_distances = ++distances; + UInt32 delta = *hash++; + + CLzRef *ptr0 = son + ((size_t)_cyclicBufferPos << 1) + 1; + CLzRef *ptr1 = son + ((size_t)_cyclicBufferPos << 1); + unsigned len0 = 0, len1 = 0; + UInt32 cutValue = _cutValue; + unsigned maxLen = (unsigned)_maxLen; + + /* + if (size > 1) + { + UInt32 delta = *hash; + if (delta < _cyclicBufferSize) + { + UInt32 cyc1 = _cyclicBufferPos + 1; + CLzRef *pair = son + ((size_t)(cyc1 - delta + ((delta > cyc1) ? _cyclicBufferSize : 0)) << 1); + Byte b = *(cur + 1 - delta); + _distances[0] = pair[0]; + _distances[1] = b; + } + } + */ + if (cutValue == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + } + else + for(;;) + { + { + CLzRef *pair = son + ((size_t)(_cyclicBufferPos - delta + ((_cyclicBufferPos < delta) ? _cyclicBufferSize : 0)) << 1); + const Byte *pb = cur - delta; + unsigned len = (len0 < len1 ? len0 : len1); + UInt32 pair0 = *pair; + if (pb[len] == cur[len]) + { + if (++len != lenLimit && pb[len] == cur[len]) + while (++len != lenLimit) + if (pb[len] != cur[len]) + break; + if (maxLen < len) + { + maxLen = len; + *distances++ = (UInt32)len; + *distances++ = delta - 1; + if (len == lenLimit) + { + UInt32 pair1 = pair[1]; + *ptr1 = pair0; + *ptr0 = pair1; + break; + } + } + } + { + UInt32 curMatch = pos - delta; + // delta = pos - *pair; + // delta = pos - pair[((UInt32)pb[len] - (UInt32)cur[len]) >> 31]; + if (pb[len] < cur[len]) + { + delta = pos - pair[1]; + *ptr1 = curMatch; + ptr1 = pair + 1; + len1 = len; + } + else + { + delta = pos - *pair; + *ptr0 = curMatch; + ptr0 = pair; + len0 = len; + } + } + } + if (--cutValue == 0 || delta >= _cyclicBufferSize) + { + *ptr0 = *ptr1 = kEmptyHashValue; + break; + } + } + pos++; + _cyclicBufferPos++; + cur++; + { + UInt32 num = (UInt32)(distances - _distances); + _distances[-1] = num; + } + } + while (distances < limit && --size != 0); + *posRes = pos; + return distances; +} + +#endif + + + +static void BtGetMatches(CMatchFinderMt *p, UInt32 *distances) +{ + UInt32 numProcessed = 0; + UInt32 curPos = 2; + UInt32 limit = kMtBtBlockSize - (p->matchMaxLen * 2); // * 2 + + distances[1] = p->hashNumAvail; + + while (curPos < limit) + { + if (p->hashBufPos == p->hashBufPosLimit) + { + MatchFinderMt_GetNextBlock_Hash(p); + distances[1] = numProcessed + p->hashNumAvail; + if (p->hashNumAvail >= p->numHashBytes) + continue; + distances[0] = curPos + p->hashNumAvail; + distances += curPos; + for (; p->hashNumAvail != 0; p->hashNumAvail--) + *distances++ = 0; + return; + } + { + UInt32 size = p->hashBufPosLimit - p->hashBufPos; + UInt32 lenLimit = p->matchMaxLen; + UInt32 pos = p->pos; + UInt32 cyclicBufferPos = p->cyclicBufferPos; + if (lenLimit >= p->hashNumAvail) + lenLimit = p->hashNumAvail; + { + UInt32 size2 = p->hashNumAvail - lenLimit + 1; + if (size2 < size) + size = size2; + size2 = p->cyclicBufferSize - cyclicBufferPos; + if (size2 < size) + size = size2; + } + + #ifndef MFMT_GM_INLINE + while (curPos < limit && size-- != 0) + { + UInt32 *startDistances = distances + curPos; + UInt32 num = (UInt32)(GetMatchesSpec1(lenLimit, pos - p->hashBuf[p->hashBufPos++], + pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, + startDistances + 1, p->numHashBytes - 1) - startDistances); + *startDistances = num - 1; + curPos += num; + cyclicBufferPos++; + pos++; + p->buffer++; + } + #else + { + UInt32 posRes; + curPos = (UInt32)(GetMatchesSpecN(lenLimit, pos, p->buffer, p->son, cyclicBufferPos, p->cyclicBufferSize, p->cutValue, + distances + curPos, p->numHashBytes - 1, p->hashBuf + p->hashBufPos, + distances + limit, + size, &posRes) - distances); + p->hashBufPos += posRes - pos; + cyclicBufferPos += posRes - pos; + p->buffer += posRes - pos; + pos = posRes; + } + #endif + + numProcessed += pos - p->pos; + p->hashNumAvail -= pos - p->pos; + p->pos = pos; + if (cyclicBufferPos == p->cyclicBufferSize) + cyclicBufferPos = 0; + p->cyclicBufferPos = cyclicBufferPos; + } + } + + distances[0] = curPos; +} + +static void BtFillBlock(CMatchFinderMt *p, UInt32 globalBlockIndex) +{ + CMtSync *sync = &p->hashSync; + if (!sync->needStart) + { + CriticalSection_Enter(&sync->cs); + sync->csWasEntered = True; + } + + BtGetMatches(p, p->btBuf + (globalBlockIndex & kMtBtNumBlocksMask) * kMtBtBlockSize); + + if (p->pos > kMtMaxValForNormalize - kMtBtBlockSize) + { + UInt32 subValue = p->pos - p->cyclicBufferSize; + MatchFinder_Normalize3(subValue, p->son, (size_t)p->cyclicBufferSize * 2); + p->pos -= subValue; + } + + if (!sync->needStart) + { + CriticalSection_Leave(&sync->cs); + sync->csWasEntered = False; + } +} + +void BtThreadFunc(CMatchFinderMt *mt) +{ + CMtSync *p = &mt->btSync; + for (;;) + { + UInt32 blockIndex = 0; + Event_Wait(&p->canStart); + Event_Set(&p->wasStarted); + for (;;) + { + if (p->exit) + return; + if (p->stopWriting) + { + p->numProcessedBlocks = blockIndex; + MtSync_StopWriting(&mt->hashSync); + Event_Set(&p->wasStopped); + break; + } + Semaphore_Wait(&p->freeSemaphore); + BtFillBlock(mt, blockIndex++); + Semaphore_Release1(&p->filledSemaphore); + } + } +} + +void MatchFinderMt_Construct(CMatchFinderMt *p) +{ + p->hashBuf = NULL; + MtSync_Construct(&p->hashSync); + MtSync_Construct(&p->btSync); +} + +static void MatchFinderMt_FreeMem(CMatchFinderMt *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->hashBuf); + p->hashBuf = NULL; +} + +void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc) +{ + MtSync_Destruct(&p->hashSync); + MtSync_Destruct(&p->btSync); + MatchFinderMt_FreeMem(p, alloc); +} + +#define kHashBufferSize (kMtHashBlockSize * kMtHashNumBlocks) +#define kBtBufferSize (kMtBtBlockSize * kMtBtNumBlocks) + +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE HashThreadFunc2(void *p) { HashThreadFunc((CMatchFinderMt *)p); return 0; } +static THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE BtThreadFunc2(void *p) +{ + Byte allocaDummy[0x180]; + unsigned i = 0; + for (i = 0; i < 16; i++) + allocaDummy[i] = (Byte)0; + if (allocaDummy[0] == 0) + BtThreadFunc((CMatchFinderMt *)p); + return 0; +} + +SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc) +{ + CMatchFinder *mf = p->MatchFinder; + p->historySize = historySize; + if (kMtBtBlockSize <= matchMaxLen * 4) + return SZ_ERROR_PARAM; + if (!p->hashBuf) + { + p->hashBuf = (UInt32 *)ISzAlloc_Alloc(alloc, (kHashBufferSize + kBtBufferSize) * sizeof(UInt32)); + if (!p->hashBuf) + return SZ_ERROR_MEM; + p->btBuf = p->hashBuf + kHashBufferSize; + } + keepAddBufferBefore += (kHashBufferSize + kBtBufferSize); + keepAddBufferAfter += kMtHashBlockSize; + if (!MatchFinder_Create(mf, historySize, keepAddBufferBefore, matchMaxLen, keepAddBufferAfter, alloc)) + return SZ_ERROR_MEM; + + RINOK(MtSync_Create(&p->hashSync, HashThreadFunc2, p, kMtHashNumBlocks)); + RINOK(MtSync_Create(&p->btSync, BtThreadFunc2, p, kMtBtNumBlocks)); + return SZ_OK; +} + +/* Call it after ReleaseStream / SetStream */ +static void MatchFinderMt_Init(CMatchFinderMt *p) +{ + CMatchFinder *mf = p->MatchFinder; + + p->btBufPos = + p->btBufPosLimit = 0; + p->hashBufPos = + p->hashBufPosLimit = 0; + + /* Init without data reading. We don't want to read data in this thread */ + MatchFinder_Init_3(mf, False); + MatchFinder_Init_LowHash(mf); + + p->pointerToCurPos = Inline_MatchFinder_GetPointerToCurrentPos(mf); + p->btNumAvailBytes = 0; + p->lzPos = p->historySize + 1; + + p->hash = mf->hash; + p->fixedHashSize = mf->fixedHashSize; + p->crc = mf->crc; + + p->son = mf->son; + p->matchMaxLen = mf->matchMaxLen; + p->numHashBytes = mf->numHashBytes; + p->pos = mf->pos; + p->buffer = mf->buffer; + p->cyclicBufferPos = mf->cyclicBufferPos; + p->cyclicBufferSize = mf->cyclicBufferSize; + p->cutValue = mf->cutValue; +} + +/* ReleaseStream is required to finish multithreading */ +void MatchFinderMt_ReleaseStream(CMatchFinderMt *p) +{ + MtSync_StopWriting(&p->btSync); + /* p->MatchFinder->ReleaseStream(); */ +} + +static void MatchFinderMt_Normalize(CMatchFinderMt *p) +{ + MatchFinder_Normalize3(p->lzPos - p->historySize - 1, p->hash, p->fixedHashSize); + p->lzPos = p->historySize + 1; +} + +static void MatchFinderMt_GetNextBlock_Bt(CMatchFinderMt *p) +{ + UInt32 blockIndex; + MtSync_GetNextBlock(&p->btSync); + blockIndex = ((p->btSync.numProcessedBlocks - 1) & kMtBtNumBlocksMask); + p->btBufPosLimit = p->btBufPos = blockIndex * kMtBtBlockSize; + p->btBufPosLimit += p->btBuf[p->btBufPos++]; + p->btNumAvailBytes = p->btBuf[p->btBufPos++]; + if (p->lzPos >= kMtMaxValForNormalize - kMtBtBlockSize) + MatchFinderMt_Normalize(p); +} + +static const Byte * MatchFinderMt_GetPointerToCurrentPos(CMatchFinderMt *p) +{ + return p->pointerToCurPos; +} + +#define GET_NEXT_BLOCK_IF_REQUIRED if (p->btBufPos == p->btBufPosLimit) MatchFinderMt_GetNextBlock_Bt(p); + +static UInt32 MatchFinderMt_GetNumAvailableBytes(CMatchFinderMt *p) +{ + GET_NEXT_BLOCK_IF_REQUIRED; + return p->btNumAvailBytes; +} + +static UInt32 * MixMatches2(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) +{ + UInt32 h2, curMatch2; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 lzPos = p->lzPos; + MT_HASH2_CALC + + curMatch2 = hash[h2]; + hash[h2] = lzPos; + + if (curMatch2 >= matchMinPos) + if (cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) + { + *distances++ = 2; + *distances++ = lzPos - curMatch2 - 1; + } + + return distances; +} + +static UInt32 * MixMatches3(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) +{ + UInt32 h2, h3, curMatch2, curMatch3; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 lzPos = p->lzPos; + MT_HASH3_CALC + + curMatch2 = hash[ h2]; + curMatch3 = (hash + kFix3HashSize)[h3]; + + hash[ h2] = lzPos; + (hash + kFix3HashSize)[h3] = lzPos; + + if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) + { + distances[1] = lzPos - curMatch2 - 1; + if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) + { + distances[0] = 3; + return distances + 2; + } + distances[0] = 2; + distances += 2; + } + + if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) + { + *distances++ = 3; + *distances++ = lzPos - curMatch3 - 1; + } + + return distances; +} + +/* +static UInt32 *MixMatches4(CMatchFinderMt *p, UInt32 matchMinPos, UInt32 *distances) +{ + UInt32 h2, h3, h4, curMatch2, curMatch3, curMatch4; + UInt32 *hash = p->hash; + const Byte *cur = p->pointerToCurPos; + UInt32 lzPos = p->lzPos; + MT_HASH4_CALC + + curMatch2 = hash[ h2]; + curMatch3 = (hash + kFix3HashSize)[h3]; + curMatch4 = (hash + kFix4HashSize)[h4]; + + hash[ h2] = lzPos; + (hash + kFix3HashSize)[h3] = lzPos; + (hash + kFix4HashSize)[h4] = lzPos; + + if (curMatch2 >= matchMinPos && cur[(ptrdiff_t)curMatch2 - lzPos] == cur[0]) + { + distances[1] = lzPos - curMatch2 - 1; + if (cur[(ptrdiff_t)curMatch2 - lzPos + 2] == cur[2]) + { + distances[0] = (cur[(ptrdiff_t)curMatch2 - lzPos + 3] == cur[3]) ? 4 : 3; + return distances + 2; + } + distances[0] = 2; + distances += 2; + } + + if (curMatch3 >= matchMinPos && cur[(ptrdiff_t)curMatch3 - lzPos] == cur[0]) + { + distances[1] = lzPos - curMatch3 - 1; + if (cur[(ptrdiff_t)curMatch3 - lzPos + 3] == cur[3]) + { + distances[0] = 4; + return distances + 2; + } + distances[0] = 3; + distances += 2; + } + + if (curMatch4 >= matchMinPos) + if ( + cur[(ptrdiff_t)curMatch4 - lzPos] == cur[0] && + cur[(ptrdiff_t)curMatch4 - lzPos + 3] == cur[3] + ) + { + *distances++ = 4; + *distances++ = lzPos - curMatch4 - 1; + } + + return distances; +} +*/ + +#define INCREASE_LZ_POS p->lzPos++; p->pointerToCurPos++; + +static UInt32 MatchFinderMt2_GetMatches(CMatchFinderMt *p, UInt32 *distances) +{ + const UInt32 *btBuf = p->btBuf + p->btBufPos; + UInt32 len = *btBuf++; + p->btBufPos += 1 + len; + p->btNumAvailBytes--; + { + UInt32 i; + for (i = 0; i < len; i += 2) + { + UInt32 v0 = btBuf[0]; + UInt32 v1 = btBuf[1]; + btBuf += 2; + distances[0] = v0; + distances[1] = v1; + distances += 2; + } + } + INCREASE_LZ_POS + return len; +} + +static UInt32 MatchFinderMt_GetMatches(CMatchFinderMt *p, UInt32 *distances) +{ + const UInt32 *btBuf = p->btBuf + p->btBufPos; + UInt32 len = *btBuf++; + p->btBufPos += 1 + len; + + if (len == 0) + { + /* change for bt5 ! */ + if (p->btNumAvailBytes-- >= 4) + len = (UInt32)(p->MixMatchesFunc(p, p->lzPos - p->historySize, distances) - (distances)); + } + else + { + /* Condition: there are matches in btBuf with length < p->numHashBytes */ + UInt32 *distances2; + p->btNumAvailBytes--; + distances2 = p->MixMatchesFunc(p, p->lzPos - btBuf[1], distances); + do + { + UInt32 v0 = btBuf[0]; + UInt32 v1 = btBuf[1]; + btBuf += 2; + distances2[0] = v0; + distances2[1] = v1; + distances2 += 2; + } + while ((len -= 2) != 0); + len = (UInt32)(distances2 - (distances)); + } + INCREASE_LZ_POS + return len; +} + +#define SKIP_HEADER2_MT do { GET_NEXT_BLOCK_IF_REQUIRED +#define SKIP_HEADER_MT(n) SKIP_HEADER2_MT if (p->btNumAvailBytes-- >= (n)) { const Byte *cur = p->pointerToCurPos; UInt32 *hash = p->hash; +#define SKIP_FOOTER_MT } INCREASE_LZ_POS p->btBufPos += p->btBuf[p->btBufPos] + 1; } while (--num != 0); + +static void MatchFinderMt0_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER2_MT { p->btNumAvailBytes--; + SKIP_FOOTER_MT +} + +static void MatchFinderMt2_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER_MT(2) + UInt32 h2; + MT_HASH2_CALC + hash[h2] = p->lzPos; + SKIP_FOOTER_MT +} + +static void MatchFinderMt3_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER_MT(3) + UInt32 h2, h3; + MT_HASH3_CALC + (hash + kFix3HashSize)[h3] = + hash[ h2] = + p->lzPos; + SKIP_FOOTER_MT +} + +/* +static void MatchFinderMt4_Skip(CMatchFinderMt *p, UInt32 num) +{ + SKIP_HEADER_MT(4) + UInt32 h2, h3, h4; + MT_HASH4_CALC + (hash + kFix4HashSize)[h4] = + (hash + kFix3HashSize)[h3] = + hash[ h2] = + p->lzPos; + SKIP_FOOTER_MT +} +*/ + +void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable) +{ + vTable->Init = (Mf_Init_Func)MatchFinderMt_Init; + vTable->GetNumAvailableBytes = (Mf_GetNumAvailableBytes_Func)MatchFinderMt_GetNumAvailableBytes; + vTable->GetPointerToCurrentPos = (Mf_GetPointerToCurrentPos_Func)MatchFinderMt_GetPointerToCurrentPos; + vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt_GetMatches; + + switch (p->MatchFinder->numHashBytes) + { + case 2: + p->GetHeadsFunc = GetHeads2; + p->MixMatchesFunc = (Mf_Mix_Matches)NULL; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt0_Skip; + vTable->GetMatches = (Mf_GetMatches_Func)MatchFinderMt2_GetMatches; + break; + case 3: + p->GetHeadsFunc = GetHeads3; + p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches2; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt2_Skip; + break; + default: + /* case 4: */ + p->GetHeadsFunc = p->MatchFinder->bigHash ? GetHeads4b : GetHeads4; + p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches3; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt3_Skip; + break; + /* + default: + p->GetHeadsFunc = GetHeads5; + p->MixMatchesFunc = (Mf_Mix_Matches)MixMatches4; + vTable->Skip = (Mf_Skip_Func)MatchFinderMt4_Skip; + break; + */ + } +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.h new file mode 100644 index 00000000..708157ec --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzFindMt.h @@ -0,0 +1,101 @@ +/* LzFindMt.h -- multithreaded Match finder for LZ algorithms +2018-07-04 : Igor Pavlov : Public domain */ + +#ifndef __LZ_FIND_MT_H +#define __LZ_FIND_MT_H + +#include "LzFind.h" +#include "Threads.h" + +EXTERN_C_BEGIN + +#define kMtHashBlockSize (1 << 13) +#define kMtHashNumBlocks (1 << 3) +#define kMtHashNumBlocksMask (kMtHashNumBlocks - 1) + +#define kMtBtBlockSize (1 << 14) +#define kMtBtNumBlocks (1 << 6) +#define kMtBtNumBlocksMask (kMtBtNumBlocks - 1) + +typedef struct _CMtSync +{ + BoolInt wasCreated; + BoolInt needStart; + BoolInt exit; + BoolInt stopWriting; + + CThread thread; + CAutoResetEvent canStart; + CAutoResetEvent wasStarted; + CAutoResetEvent wasStopped; + CSemaphore freeSemaphore; + CSemaphore filledSemaphore; + BoolInt csWasInitialized; + BoolInt csWasEntered; + CCriticalSection cs; + UInt32 numProcessedBlocks; +} CMtSync; + +typedef UInt32 * (*Mf_Mix_Matches)(void *p, UInt32 matchMinPos, UInt32 *distances); + +/* kMtCacheLineDummy must be >= size_of_CPU_cache_line */ +#define kMtCacheLineDummy 128 + +typedef void (*Mf_GetHeads)(const Byte *buffer, UInt32 pos, + UInt32 *hash, UInt32 hashMask, UInt32 *heads, UInt32 numHeads, const UInt32 *crc); + +typedef struct _CMatchFinderMt +{ + /* LZ */ + const Byte *pointerToCurPos; + UInt32 *btBuf; + UInt32 btBufPos; + UInt32 btBufPosLimit; + UInt32 lzPos; + UInt32 btNumAvailBytes; + + UInt32 *hash; + UInt32 fixedHashSize; + UInt32 historySize; + const UInt32 *crc; + + Mf_Mix_Matches MixMatchesFunc; + + /* LZ + BT */ + CMtSync btSync; + Byte btDummy[kMtCacheLineDummy]; + + /* BT */ + UInt32 *hashBuf; + UInt32 hashBufPos; + UInt32 hashBufPosLimit; + UInt32 hashNumAvail; + + CLzRef *son; + UInt32 matchMaxLen; + UInt32 numHashBytes; + UInt32 pos; + const Byte *buffer; + UInt32 cyclicBufferPos; + UInt32 cyclicBufferSize; /* it must be historySize + 1 */ + UInt32 cutValue; + + /* BT + Hash */ + CMtSync hashSync; + /* Byte hashDummy[kMtCacheLineDummy]; */ + + /* Hash */ + Mf_GetHeads GetHeadsFunc; + CMatchFinder *MatchFinder; +} CMatchFinderMt; + +void MatchFinderMt_Construct(CMatchFinderMt *p); +void MatchFinderMt_Destruct(CMatchFinderMt *p, ISzAllocPtr alloc); +SRes MatchFinderMt_Create(CMatchFinderMt *p, UInt32 historySize, UInt32 keepAddBufferBefore, + UInt32 matchMaxLen, UInt32 keepAddBufferAfter, ISzAllocPtr alloc); +void MatchFinderMt_CreateVTable(CMatchFinderMt *p, IMatchFinder *vTable); +void MatchFinderMt_ReleaseStream(CMatchFinderMt *p); + +EXTERN_C_END + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzHash.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzHash.h new file mode 100644 index 00000000..e7c94230 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzHash.h @@ -0,0 +1,57 @@ +/* LzHash.h -- HASH functions for LZ algorithms +2015-04-12 : Igor Pavlov : Public domain */ + +#ifndef __LZ_HASH_H +#define __LZ_HASH_H + +#define kHash2Size (1 << 10) +#define kHash3Size (1 << 16) +#define kHash4Size (1 << 20) + +#define kFix3HashSize (kHash2Size) +#define kFix4HashSize (kHash2Size + kHash3Size) +#define kFix5HashSize (kHash2Size + kHash3Size + kHash4Size) + +#define HASH2_CALC hv = cur[0] | ((UInt32)cur[1] << 8); + +#define HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + hv = (temp ^ ((UInt32)cur[2] << 8)) & p->hashMask; } + +#define HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + temp ^= ((UInt32)cur[2] << 8); \ + h3 = temp & (kHash3Size - 1); \ + hv = (temp ^ (p->crc[cur[3]] << 5)) & p->hashMask; } + +#define HASH5_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + temp ^= ((UInt32)cur[2] << 8); \ + h3 = temp & (kHash3Size - 1); \ + temp ^= (p->crc[cur[3]] << 5); \ + h4 = temp & (kHash4Size - 1); \ + hv = (temp ^ (p->crc[cur[4]] << 3)) & p->hashMask; } + +/* #define HASH_ZIP_CALC hv = ((cur[0] | ((UInt32)cur[1] << 8)) ^ p->crc[cur[2]]) & 0xFFFF; */ +#define HASH_ZIP_CALC hv = ((cur[2] | ((UInt32)cur[0] << 8)) ^ p->crc[cur[1]]) & 0xFFFF; + + +#define MT_HASH2_CALC \ + h2 = (p->crc[cur[0]] ^ cur[1]) & (kHash2Size - 1); + +#define MT_HASH3_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + h3 = (temp ^ ((UInt32)cur[2] << 8)) & (kHash3Size - 1); } + +#define MT_HASH4_CALC { \ + UInt32 temp = p->crc[cur[0]] ^ cur[1]; \ + h2 = temp & (kHash2Size - 1); \ + temp ^= ((UInt32)cur[2] << 8); \ + h3 = temp & (kHash3Size - 1); \ + h4 = (temp ^ (p->crc[cur[3]] << 5)) & (kHash4Size - 1); } + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.c new file mode 100644 index 00000000..9749efe9 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.c @@ -0,0 +1,1185 @@ +/* LzmaDec.c -- LZMA Decoder +2018-07-04 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +/* #include "CpuArch.h" */ +#include "LzmaDec.h" + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 + +#define RC_INIT_SIZE 5 + +#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound) +#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); +#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); +#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ + { UPDATE_0(p); i = (i + i); A0; } else \ + { UPDATE_1(p); i = (i + i) + 1; A1; } + +#define TREE_GET_BIT(probs, i) { GET_BIT2(probs + i, i, ;, ;); } + +#define REV_BIT(p, i, A0, A1) IF_BIT_0(p + i) \ + { UPDATE_0(p + i); A0; } else \ + { UPDATE_1(p + i); A1; } +#define REV_BIT_VAR( p, i, m) REV_BIT(p, i, i += m; m += m, m += m; i += m; ) +#define REV_BIT_CONST(p, i, m) REV_BIT(p, i, i += m; , i += m * 2; ) +#define REV_BIT_LAST( p, i, m) REV_BIT(p, i, i -= m , ; ) + +#define TREE_DECODE(probs, limit, i) \ + { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } + +/* #define _LZMA_SIZE_OPT */ + +#ifdef _LZMA_SIZE_OPT +#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) +#else +#define TREE_6_DECODE(probs, i) \ + { i = 1; \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + TREE_GET_BIT(probs, i); \ + i -= 0x40; } +#endif + +#define NORMAL_LITER_DEC TREE_GET_BIT(prob, symbol) +#define MATCHED_LITER_DEC \ + matchByte += matchByte; \ + bit = offs; \ + offs &= matchByte; \ + probLit = prob + (offs + bit + symbol); \ + GET_BIT2(probLit, symbol, offs ^= bit; , ;) + + + +#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } + +#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * (UInt32)ttt; if (code < bound) +#define UPDATE_0_CHECK range = bound; +#define UPDATE_1_CHECK range -= bound; code -= bound; +#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ + { UPDATE_0_CHECK; i = (i + i); A0; } else \ + { UPDATE_1_CHECK; i = (i + i) + 1; A1; } +#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) +#define TREE_DECODE_CHECK(probs, limit, i) \ + { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } + + +#define REV_BIT_CHECK(p, i, m) IF_BIT_0_CHECK(p + i) \ + { UPDATE_0_CHECK; i += m; m += m; } else \ + { UPDATE_1_CHECK; m += m; i += m; } + + +#define kNumPosBitsMax 4 +#define kNumPosStatesMax (1 << kNumPosBitsMax) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) + +#define LenLow 0 +#define LenHigh (LenLow + 2 * (kNumPosStatesMax << kLenNumLowBits)) +#define kNumLenProbs (LenHigh + kLenNumHighSymbols) + +#define LenChoice LenLow +#define LenChoice2 (LenLow + (1 << kLenNumLowBits)) + +#define kNumStates 12 +#define kNumStates2 16 +#define kNumLitStates 7 + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +#define kNumPosSlotBits 6 +#define kNumLenToPosStates 4 + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) + +#define kMatchMinLen 2 +#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols * 2 + kLenNumHighSymbols) + +/* External ASM code needs same CLzmaProb array layout. So don't change it. */ + +/* (probs_1664) is faster and better for code size at some platforms */ +/* +#ifdef MY_CPU_X86_OR_AMD64 +*/ +#define kStartOffset 1664 +#define GET_PROBS p->probs_1664 +/* +#define GET_PROBS p->probs + kStartOffset +#else +#define kStartOffset 0 +#define GET_PROBS p->probs +#endif +*/ + +#define SpecPos (-kStartOffset) +#define IsRep0Long (SpecPos + kNumFullDistances) +#define RepLenCoder (IsRep0Long + (kNumStates2 << kNumPosBitsMax)) +#define LenCoder (RepLenCoder + kNumLenProbs) +#define IsMatch (LenCoder + kNumLenProbs) +#define Align (IsMatch + (kNumStates2 << kNumPosBitsMax)) +#define IsRep (Align + kAlignTableSize) +#define IsRepG0 (IsRep + kNumStates) +#define IsRepG1 (IsRepG0 + kNumStates) +#define IsRepG2 (IsRepG1 + kNumStates) +#define PosSlot (IsRepG2 + kNumStates) +#define Literal (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) +#define NUM_BASE_PROBS (Literal + kStartOffset) + +#if Align != 0 && kStartOffset != 0 + #error Stop_Compiling_Bad_LZMA_kAlign +#endif + +#if NUM_BASE_PROBS != 1984 + #error Stop_Compiling_Bad_LZMA_PROBS +#endif + + +#define LZMA_LIT_SIZE 0x300 + +#define LzmaProps_GetNumProbs(p) (NUM_BASE_PROBS + ((UInt32)LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) + + +#define CALC_POS_STATE(processedPos, pbMask) (((processedPos) & (pbMask)) << 4) +#define COMBINED_PS_STATE (posState + state) +#define GET_LEN_STATE (posState) + +#define LZMA_DIC_MIN (1 << 12) + +/* +p->remainLen : shows status of LZMA decoder: + < kMatchSpecLenStart : normal remain + = kMatchSpecLenStart : finished + = kMatchSpecLenStart + 1 : need init range coder + = kMatchSpecLenStart + 2 : need init range coder and state +*/ + +/* ---------- LZMA_DECODE_REAL ---------- */ +/* +LzmaDec_DecodeReal_3() can be implemented in external ASM file. +3 - is the code compatibility version of that function for check at link time. +*/ + +#define LZMA_DECODE_REAL LzmaDec_DecodeReal_3 + +/* +LZMA_DECODE_REAL() +In: + RangeCoder is normalized + if (p->dicPos == limit) + { + LzmaDec_TryDummy() was called before to exclude LITERAL and MATCH-REP cases. + So first symbol can be only MATCH-NON-REP. And if that MATCH-NON-REP symbol + is not END_OF_PAYALOAD_MARKER, then function returns error code. + } + +Processing: + first LZMA symbol will be decoded in any case + All checks for limits are at the end of main loop, + It will decode new LZMA-symbols while (p->buf < bufLimit && dicPos < limit), + RangeCoder is still without last normalization when (p->buf < bufLimit) is being checked. + +Out: + RangeCoder is normalized + Result: + SZ_OK - OK + SZ_ERROR_DATA - Error + p->remainLen: + < kMatchSpecLenStart : normal remain + = kMatchSpecLenStart : finished +*/ + + +#ifdef _LZMA_DEC_OPT + +int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit); + +#else + +static +int MY_FAST_CALL LZMA_DECODE_REAL(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + CLzmaProb *probs = GET_PROBS; + unsigned state = (unsigned)p->state; + UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; + unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; + unsigned lc = p->prop.lc; + unsigned lpMask = ((unsigned)0x100 << p->prop.lp) - ((unsigned)0x100 >> lc); + + Byte *dic = p->dic; + SizeT dicBufSize = p->dicBufSize; + SizeT dicPos = p->dicPos; + + UInt32 processedPos = p->processedPos; + UInt32 checkDicSize = p->checkDicSize; + unsigned len = 0; + + const Byte *buf = p->buf; + UInt32 range = p->range; + UInt32 code = p->code; + + do + { + CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = CALC_POS_STATE(processedPos, pbMask); + + prob = probs + IsMatch + COMBINED_PS_STATE; + IF_BIT_0(prob) + { + unsigned symbol; + UPDATE_0(prob); + prob = probs + Literal; + if (processedPos != 0 || checkDicSize != 0) + prob += (UInt32)3 * ((((processedPos << 8) + dic[(dicPos == 0 ? dicBufSize : dicPos) - 1]) & lpMask) << lc); + processedPos++; + + if (state < kNumLitStates) + { + state -= (state < 4) ? state : 3; + symbol = 1; + #ifdef _LZMA_SIZE_OPT + do { NORMAL_LITER_DEC } while (symbol < 0x100); + #else + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + NORMAL_LITER_DEC + #endif + } + else + { + unsigned matchByte = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; + unsigned offs = 0x100; + state -= (state < 10) ? 3 : 6; + symbol = 1; + #ifdef _LZMA_SIZE_OPT + do + { + unsigned bit; + CLzmaProb *probLit; + MATCHED_LITER_DEC + } + while (symbol < 0x100); + #else + { + unsigned bit; + CLzmaProb *probLit; + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + MATCHED_LITER_DEC + } + #endif + } + + dic[dicPos++] = (Byte)symbol; + continue; + } + + { + UPDATE_1(prob); + prob = probs + IsRep + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + state += kNumStates; + prob = probs + LenCoder; + } + else + { + UPDATE_1(prob); + /* + // that case was checked before with kBadRepCode + if (checkDicSize == 0 && processedPos == 0) + return SZ_ERROR_DATA; + */ + prob = probs + IsRepG0 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + prob = probs + IsRep0Long + COMBINED_PS_STATE; + IF_BIT_0(prob) + { + UPDATE_0(prob); + dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; + dicPos++; + processedPos++; + state = state < kNumLitStates ? 9 : 11; + continue; + } + UPDATE_1(prob); + } + else + { + UInt32 distance; + UPDATE_1(prob); + prob = probs + IsRepG1 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep1; + } + else + { + UPDATE_1(prob); + prob = probs + IsRepG2 + state; + IF_BIT_0(prob) + { + UPDATE_0(prob); + distance = rep2; + } + else + { + UPDATE_1(prob); + distance = rep3; + rep3 = rep2; + } + rep2 = rep1; + } + rep1 = rep0; + rep0 = distance; + } + state = state < kNumLitStates ? 8 : 11; + prob = probs + RepLenCoder; + } + + #ifdef _LZMA_SIZE_OPT + { + unsigned lim, offset; + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + GET_LEN_STATE; + offset = 0; + lim = (1 << kLenNumLowBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenChoice2; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits); + offset = kLenNumLowSymbols; + lim = (1 << kLenNumLowBits); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenHigh; + offset = kLenNumLowSymbols * 2; + lim = (1 << kLenNumHighBits); + } + } + TREE_DECODE(probLen, lim, len); + len += offset; + } + #else + { + CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + GET_LEN_STATE; + len = 1; + TREE_GET_BIT(probLen, len); + TREE_GET_BIT(probLen, len); + TREE_GET_BIT(probLen, len); + len -= 8; + } + else + { + UPDATE_1(probLen); + probLen = prob + LenChoice2; + IF_BIT_0(probLen) + { + UPDATE_0(probLen); + probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits); + len = 1; + TREE_GET_BIT(probLen, len); + TREE_GET_BIT(probLen, len); + TREE_GET_BIT(probLen, len); + } + else + { + UPDATE_1(probLen); + probLen = prob + LenHigh; + TREE_DECODE(probLen, (1 << kLenNumHighBits), len); + len += kLenNumLowSymbols * 2; + } + } + } + #endif + + if (state >= kNumStates) + { + UInt32 distance; + prob = probs + PosSlot + + ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); + TREE_6_DECODE(prob, distance); + if (distance >= kStartPosModelIndex) + { + unsigned posSlot = (unsigned)distance; + unsigned numDirectBits = (unsigned)(((distance >> 1) - 1)); + distance = (2 | (distance & 1)); + if (posSlot < kEndPosModelIndex) + { + distance <<= numDirectBits; + prob = probs + SpecPos; + { + UInt32 m = 1; + distance++; + do + { + REV_BIT_VAR(prob, distance, m); + } + while (--numDirectBits); + distance -= m; + } + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE + range >>= 1; + + { + UInt32 t; + code -= range; + t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ + distance = (distance << 1) + (t + 1); + code += range & t; + } + /* + distance <<= 1; + if (code >= range) + { + code -= range; + distance |= 1; + } + */ + } + while (--numDirectBits); + prob = probs + Align; + distance <<= kNumAlignBits; + { + unsigned i = 1; + REV_BIT_CONST(prob, i, 1); + REV_BIT_CONST(prob, i, 2); + REV_BIT_CONST(prob, i, 4); + REV_BIT_LAST (prob, i, 8); + distance |= i; + } + if (distance == (UInt32)0xFFFFFFFF) + { + len = kMatchSpecLenStart; + state -= kNumStates; + break; + } + } + } + + rep3 = rep2; + rep2 = rep1; + rep1 = rep0; + rep0 = distance + 1; + state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; + if (distance >= (checkDicSize == 0 ? processedPos: checkDicSize)) + { + p->dicPos = dicPos; + return SZ_ERROR_DATA; + } + } + + len += kMatchMinLen; + + { + SizeT rem; + unsigned curLen; + SizeT pos; + + if ((rem = limit - dicPos) == 0) + { + p->dicPos = dicPos; + return SZ_ERROR_DATA; + } + + curLen = ((rem < len) ? (unsigned)rem : len); + pos = dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0); + + processedPos += (UInt32)curLen; + + len -= curLen; + if (curLen <= dicBufSize - pos) + { + Byte *dest = dic + dicPos; + ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; + const Byte *lim = dest + curLen; + dicPos += (SizeT)curLen; + do + *(dest) = (Byte)*(dest + src); + while (++dest != lim); + } + else + { + do + { + dic[dicPos++] = dic[pos]; + if (++pos == dicBufSize) + pos = 0; + } + while (--curLen != 0); + } + } + } + } + while (dicPos < limit && buf < bufLimit); + + NORMALIZE; + + p->buf = buf; + p->range = range; + p->code = code; + p->remainLen = (UInt32)len; + p->dicPos = dicPos; + p->processedPos = processedPos; + p->reps[0] = rep0; + p->reps[1] = rep1; + p->reps[2] = rep2; + p->reps[3] = rep3; + p->state = (UInt32)state; + + return SZ_OK; +} +#endif + +static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) +{ + if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) + { + Byte *dic = p->dic; + SizeT dicPos = p->dicPos; + SizeT dicBufSize = p->dicBufSize; + unsigned len = (unsigned)p->remainLen; + SizeT rep0 = p->reps[0]; /* we use SizeT to avoid the BUG of VC14 for AMD64 */ + SizeT rem = limit - dicPos; + if (rem < len) + len = (unsigned)(rem); + + if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) + p->checkDicSize = p->prop.dicSize; + + p->processedPos += (UInt32)len; + p->remainLen -= (UInt32)len; + while (len != 0) + { + len--; + dic[dicPos] = dic[dicPos - rep0 + (dicPos < rep0 ? dicBufSize : 0)]; + dicPos++; + } + p->dicPos = dicPos; + } +} + + +#define kRange0 0xFFFFFFFF +#define kBound0 ((kRange0 >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1)) +#define kBadRepCode (kBound0 + (((kRange0 - kBound0) >> kNumBitModelTotalBits) << (kNumBitModelTotalBits - 1))) +#if kBadRepCode != (0xC0000000 - 0x400) + #error Stop_Compiling_Bad_LZMA_Check +#endif + +static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) +{ + do + { + SizeT limit2 = limit; + if (p->checkDicSize == 0) + { + UInt32 rem = p->prop.dicSize - p->processedPos; + if (limit - p->dicPos > rem) + limit2 = p->dicPos + rem; + + if (p->processedPos == 0) + if (p->code >= kBadRepCode) + return SZ_ERROR_DATA; + } + + RINOK(LZMA_DECODE_REAL(p, limit2, bufLimit)); + + if (p->checkDicSize == 0 && p->processedPos >= p->prop.dicSize) + p->checkDicSize = p->prop.dicSize; + + LzmaDec_WriteRem(p, limit); + } + while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); + + return 0; +} + +typedef enum +{ + DUMMY_ERROR, /* unexpected end of input stream */ + DUMMY_LIT, + DUMMY_MATCH, + DUMMY_REP +} ELzmaDummy; + +static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) +{ + UInt32 range = p->range; + UInt32 code = p->code; + const Byte *bufLimit = buf + inSize; + const CLzmaProb *probs = GET_PROBS; + unsigned state = (unsigned)p->state; + ELzmaDummy res; + + { + const CLzmaProb *prob; + UInt32 bound; + unsigned ttt; + unsigned posState = CALC_POS_STATE(p->processedPos, (1 << p->prop.pb) - 1); + + prob = probs + IsMatch + COMBINED_PS_STATE; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK + + /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ + + prob = probs + Literal; + if (p->checkDicSize != 0 || p->processedPos != 0) + prob += ((UInt32)LZMA_LIT_SIZE * + ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + + (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); + + if (state < kNumLitStates) + { + unsigned symbol = 1; + do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); + } + else + { + unsigned matchByte = p->dic[p->dicPos - p->reps[0] + + (p->dicPos < p->reps[0] ? p->dicBufSize : 0)]; + unsigned offs = 0x100; + unsigned symbol = 1; + do + { + unsigned bit; + const CLzmaProb *probLit; + matchByte += matchByte; + bit = offs; + offs &= matchByte; + probLit = prob + (offs + bit + symbol); + GET_BIT2_CHECK(probLit, symbol, offs ^= bit; , ; ) + } + while (symbol < 0x100); + } + res = DUMMY_LIT; + } + else + { + unsigned len; + UPDATE_1_CHECK; + + prob = probs + IsRep + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + state = 0; + prob = probs + LenCoder; + res = DUMMY_MATCH; + } + else + { + UPDATE_1_CHECK; + res = DUMMY_REP; + prob = probs + IsRepG0 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + prob = probs + IsRep0Long + COMBINED_PS_STATE; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + NORMALIZE_CHECK; + return DUMMY_REP; + } + else + { + UPDATE_1_CHECK; + } + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG1 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + prob = probs + IsRepG2 + state; + IF_BIT_0_CHECK(prob) + { + UPDATE_0_CHECK; + } + else + { + UPDATE_1_CHECK; + } + } + } + state = kNumStates; + prob = probs + RepLenCoder; + } + { + unsigned limit, offset; + const CLzmaProb *probLen = prob + LenChoice; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenLow + GET_LEN_STATE; + offset = 0; + limit = 1 << kLenNumLowBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenChoice2; + IF_BIT_0_CHECK(probLen) + { + UPDATE_0_CHECK; + probLen = prob + LenLow + GET_LEN_STATE + (1 << kLenNumLowBits); + offset = kLenNumLowSymbols; + limit = 1 << kLenNumLowBits; + } + else + { + UPDATE_1_CHECK; + probLen = prob + LenHigh; + offset = kLenNumLowSymbols * 2; + limit = 1 << kLenNumHighBits; + } + } + TREE_DECODE_CHECK(probLen, limit, len); + len += offset; + } + + if (state < 4) + { + unsigned posSlot; + prob = probs + PosSlot + + ((len < kNumLenToPosStates - 1 ? len : kNumLenToPosStates - 1) << + kNumPosSlotBits); + TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); + if (posSlot >= kStartPosModelIndex) + { + unsigned numDirectBits = ((posSlot >> 1) - 1); + + /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ + + if (posSlot < kEndPosModelIndex) + { + prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits); + } + else + { + numDirectBits -= kNumAlignBits; + do + { + NORMALIZE_CHECK + range >>= 1; + code -= range & (((code - range) >> 31) - 1); + /* if (code >= range) code -= range; */ + } + while (--numDirectBits); + prob = probs + Align; + numDirectBits = kNumAlignBits; + } + { + unsigned i = 1; + unsigned m = 1; + do + { + REV_BIT_CHECK(prob, i, m); + } + while (--numDirectBits); + } + } + } + } + } + NORMALIZE_CHECK; + return res; +} + + +void LzmaDec_InitDicAndState(CLzmaDec *p, BoolInt initDic, BoolInt initState) +{ + p->remainLen = kMatchSpecLenStart + 1; + p->tempBufSize = 0; + + if (initDic) + { + p->processedPos = 0; + p->checkDicSize = 0; + p->remainLen = kMatchSpecLenStart + 2; + } + if (initState) + p->remainLen = kMatchSpecLenStart + 2; +} + +void LzmaDec_Init(CLzmaDec *p) +{ + p->dicPos = 0; + LzmaDec_InitDicAndState(p, True, True); +} + + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, + ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT inSize = *srcLen; + (*srcLen) = 0; + + *status = LZMA_STATUS_NOT_SPECIFIED; + + if (p->remainLen > kMatchSpecLenStart) + { + for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) + p->tempBuf[p->tempBufSize++] = *src++; + if (p->tempBufSize != 0 && p->tempBuf[0] != 0) + return SZ_ERROR_DATA; + if (p->tempBufSize < RC_INIT_SIZE) + { + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + p->code = + ((UInt32)p->tempBuf[1] << 24) + | ((UInt32)p->tempBuf[2] << 16) + | ((UInt32)p->tempBuf[3] << 8) + | ((UInt32)p->tempBuf[4]); + p->range = 0xFFFFFFFF; + p->tempBufSize = 0; + + if (p->remainLen > kMatchSpecLenStart + 1) + { + SizeT numProbs = LzmaProps_GetNumProbs(&p->prop); + SizeT i; + CLzmaProb *probs = p->probs; + for (i = 0; i < numProbs; i++) + probs[i] = kBitModelTotal >> 1; + p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; + p->state = 0; + } + + p->remainLen = 0; + } + + LzmaDec_WriteRem(p, dicLimit); + + while (p->remainLen != kMatchSpecLenStart) + { + int checkEndMarkNow = 0; + + if (p->dicPos >= dicLimit) + { + if (p->remainLen == 0 && p->code == 0) + { + *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; + return SZ_OK; + } + if (finishMode == LZMA_FINISH_ANY) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_OK; + } + if (p->remainLen != 0) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + checkEndMarkNow = 1; + } + + if (p->tempBufSize == 0) + { + SizeT processed; + const Byte *bufLimit; + if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, src, inSize); + if (dummyRes == DUMMY_ERROR) + { + memcpy(p->tempBuf, src, inSize); + p->tempBufSize = (unsigned)inSize; + (*srcLen) += inSize; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + bufLimit = src; + } + else + bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; + p->buf = src; + if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) + return SZ_ERROR_DATA; + processed = (SizeT)(p->buf - src); + (*srcLen) += processed; + src += processed; + inSize -= processed; + } + else + { + unsigned rem = p->tempBufSize, lookAhead = 0; + while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) + p->tempBuf[rem++] = src[lookAhead++]; + p->tempBufSize = rem; + if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) + { + int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, (SizeT)rem); + if (dummyRes == DUMMY_ERROR) + { + (*srcLen) += (SizeT)lookAhead; + *status = LZMA_STATUS_NEEDS_MORE_INPUT; + return SZ_OK; + } + if (checkEndMarkNow && dummyRes != DUMMY_MATCH) + { + *status = LZMA_STATUS_NOT_FINISHED; + return SZ_ERROR_DATA; + } + } + p->buf = p->tempBuf; + if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) + return SZ_ERROR_DATA; + + { + unsigned kkk = (unsigned)(p->buf - p->tempBuf); + if (rem < kkk) + return SZ_ERROR_FAIL; /* some internal error */ + rem -= kkk; + if (lookAhead < rem) + return SZ_ERROR_FAIL; /* some internal error */ + lookAhead -= rem; + } + (*srcLen) += (SizeT)lookAhead; + src += lookAhead; + inSize -= (SizeT)lookAhead; + p->tempBufSize = 0; + } + } + + if (p->code != 0) + return SZ_ERROR_DATA; + *status = LZMA_STATUS_FINISHED_WITH_MARK; + return SZ_OK; +} + + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) +{ + SizeT outSize = *destLen; + SizeT inSize = *srcLen; + *srcLen = *destLen = 0; + for (;;) + { + SizeT inSizeCur = inSize, outSizeCur, dicPos; + ELzmaFinishMode curFinishMode; + SRes res; + if (p->dicPos == p->dicBufSize) + p->dicPos = 0; + dicPos = p->dicPos; + if (outSize > p->dicBufSize - dicPos) + { + outSizeCur = p->dicBufSize; + curFinishMode = LZMA_FINISH_ANY; + } + else + { + outSizeCur = dicPos + outSize; + curFinishMode = finishMode; + } + + res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); + src += inSizeCur; + inSize -= inSizeCur; + *srcLen += inSizeCur; + outSizeCur = p->dicPos - dicPos; + memcpy(dest, p->dic + dicPos, outSizeCur); + dest += outSizeCur; + outSize -= outSizeCur; + *destLen += outSizeCur; + if (res != 0) + return res; + if (outSizeCur == 0 || outSize == 0) + return SZ_OK; + } +} + +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->probs); + p->probs = NULL; +} + +static void LzmaDec_FreeDict(CLzmaDec *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->dic); + p->dic = NULL; +} + +void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc) +{ + LzmaDec_FreeProbs(p, alloc); + LzmaDec_FreeDict(p, alloc); +} + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) +{ + UInt32 dicSize; + Byte d; + + if (size < LZMA_PROPS_SIZE) + return SZ_ERROR_UNSUPPORTED; + else + dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); + + if (dicSize < LZMA_DIC_MIN) + dicSize = LZMA_DIC_MIN; + p->dicSize = dicSize; + + d = data[0]; + if (d >= (9 * 5 * 5)) + return SZ_ERROR_UNSUPPORTED; + + p->lc = (Byte)(d % 9); + d /= 9; + p->pb = (Byte)(d / 5); + p->lp = (Byte)(d % 5); + + return SZ_OK; +} + +static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAllocPtr alloc) +{ + UInt32 numProbs = LzmaProps_GetNumProbs(propNew); + if (!p->probs || numProbs != p->numProbs) + { + LzmaDec_FreeProbs(p, alloc); + p->probs = (CLzmaProb *)ISzAlloc_Alloc(alloc, numProbs * sizeof(CLzmaProb)); + if (!p->probs) + return SZ_ERROR_MEM; + p->probs_1664 = p->probs + 1664; + p->numProbs = numProbs; + } + return SZ_OK; +} + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc) +{ + CLzmaProps propNew; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc) +{ + CLzmaProps propNew; + SizeT dicBufSize; + RINOK(LzmaProps_Decode(&propNew, props, propsSize)); + RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); + + { + UInt32 dictSize = propNew.dicSize; + SizeT mask = ((UInt32)1 << 12) - 1; + if (dictSize >= ((UInt32)1 << 30)) mask = ((UInt32)1 << 22) - 1; + else if (dictSize >= ((UInt32)1 << 22)) mask = ((UInt32)1 << 20) - 1;; + dicBufSize = ((SizeT)dictSize + mask) & ~mask; + if (dicBufSize < dictSize) + dicBufSize = dictSize; + } + + if (!p->dic || dicBufSize != p->dicBufSize) + { + LzmaDec_FreeDict(p, alloc); + p->dic = (Byte *)ISzAlloc_Alloc(alloc, dicBufSize); + if (!p->dic) + { + LzmaDec_FreeProbs(p, alloc); + return SZ_ERROR_MEM; + } + } + p->dicBufSize = dicBufSize; + p->prop = propNew; + return SZ_OK; +} + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAllocPtr alloc) +{ + CLzmaDec p; + SRes res; + SizeT outSize = *destLen, inSize = *srcLen; + *destLen = *srcLen = 0; + *status = LZMA_STATUS_NOT_SPECIFIED; + if (inSize < RC_INIT_SIZE) + return SZ_ERROR_INPUT_EOF; + LzmaDec_Construct(&p); + RINOK(LzmaDec_AllocateProbs(&p, propData, propSize, alloc)); + p.dic = dest; + p.dicBufSize = outSize; + LzmaDec_Init(&p); + *srcLen = inSize; + res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); + *destLen = p.dicPos; + if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) + res = SZ_ERROR_INPUT_EOF; + LzmaDec_FreeProbs(&p, alloc); + return res; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.h new file mode 100644 index 00000000..f3702f5c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaDec.h @@ -0,0 +1,234 @@ +/* LzmaDec.h -- LZMA Decoder +2018-04-21 : Igor Pavlov : Public domain */ + +#ifndef __LZMA_DEC_H +#define __LZMA_DEC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +/* #define _LZMA_PROB32 */ +/* _LZMA_PROB32 can increase the speed on some CPUs, + but memory usage for CLzmaDec::probs will be doubled in that case */ + +typedef +#ifdef _LZMA_PROB32 + UInt32 +#else + UInt16 +#endif + CLzmaProb; + + +/* ---------- LZMA Properties ---------- */ + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaProps +{ + Byte lc; + Byte lp; + Byte pb; + Byte _pad_; + UInt32 dicSize; +} CLzmaProps; + +/* LzmaProps_Decode - decodes properties +Returns: + SZ_OK + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); + + +/* ---------- LZMA Decoder state ---------- */ + +/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. + Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ + +#define LZMA_REQUIRED_INPUT_MAX 20 + +typedef struct +{ + /* Don't change this structure. ASM code can use it. */ + CLzmaProps prop; + CLzmaProb *probs; + CLzmaProb *probs_1664; + Byte *dic; + SizeT dicBufSize; + SizeT dicPos; + const Byte *buf; + UInt32 range; + UInt32 code; + UInt32 processedPos; + UInt32 checkDicSize; + UInt32 reps[4]; + UInt32 state; + UInt32 remainLen; + + UInt32 numProbs; + unsigned tempBufSize; + Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; +} CLzmaDec; + +#define LzmaDec_Construct(p) { (p)->dic = NULL; (p)->probs = NULL; } + +void LzmaDec_Init(CLzmaDec *p); + +/* There are two types of LZMA streams: + - Stream with end mark. That end mark adds about 6 bytes to compressed size. + - Stream without end mark. You must know exact uncompressed size to decompress such stream. */ + +typedef enum +{ + LZMA_FINISH_ANY, /* finish at any point */ + LZMA_FINISH_END /* block must be finished at the end */ +} ELzmaFinishMode; + +/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! + + You must use LZMA_FINISH_END, when you know that current output buffer + covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. + + If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, + and output value of destLen will be less than output buffer size limit. + You can check status result also. + + You can use multiple checks to test data integrity after full decompression: + 1) Check Result and "status" variable. + 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. + 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. + You must use correct finish mode in that case. */ + +typedef enum +{ + LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ + LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ + LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ + LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ +} ELzmaStatus; + +/* ELzmaStatus is used only as output value for function call */ + + +/* ---------- Interfaces ---------- */ + +/* There are 3 levels of interfaces: + 1) Dictionary Interface + 2) Buffer Interface + 3) One Call Interface + You can select any of these interfaces, but don't mix functions from different + groups for same object. */ + + +/* There are two variants to allocate state for Dictionary Interface: + 1) LzmaDec_Allocate / LzmaDec_Free + 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs + You can use variant 2, if you set dictionary buffer manually. + For Buffer Interface you must always use variant 1. + +LzmaDec_Allocate* can return: + SZ_OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties +*/ + +SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc); +void LzmaDec_FreeProbs(CLzmaDec *p, ISzAllocPtr alloc); + +SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAllocPtr alloc); +void LzmaDec_Free(CLzmaDec *p, ISzAllocPtr alloc); + +/* ---------- Dictionary Interface ---------- */ + +/* You can use it, if you want to eliminate the overhead for data copying from + dictionary to some other external buffer. + You must work with CLzmaDec variables directly in this interface. + + STEPS: + LzmaDec_Construct() + LzmaDec_Allocate() + for (each new stream) + { + LzmaDec_Init() + while (it needs more decompression) + { + LzmaDec_DecodeToDic() + use data from CLzmaDec::dic and update CLzmaDec::dicPos + } + } + LzmaDec_Free() +*/ + +/* LzmaDec_DecodeToDic + + The decoding to internal dictionary buffer (CLzmaDec::dic). + You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! + +finishMode: + It has meaning only if the decoding reaches output limit (dicLimit). + LZMA_FINISH_ANY - Decode just dicLimit bytes. + LZMA_FINISH_END - Stream must be finished after dicLimit. + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_NEEDS_MORE_INPUT + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error +*/ + +SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- Buffer Interface ---------- */ + +/* It's zlib-like interface. + See LzmaDec_DecodeToDic description for information about STEPS and return results, + but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need + to work with CLzmaDec variables manually. + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). +*/ + +SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, + const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); + + +/* ---------- One Call Interface ---------- */ + +/* LzmaDecode + +finishMode: + It has meaning only if the decoding reaches output limit (*destLen). + LZMA_FINISH_ANY - Decode just destLen bytes. + LZMA_FINISH_END - Stream must be finished after (*destLen). + +Returns: + SZ_OK + status: + LZMA_STATUS_FINISHED_WITH_MARK + LZMA_STATUS_NOT_FINISHED + LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK + SZ_ERROR_DATA - Data error + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_UNSUPPORTED - Unsupported properties + SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). +*/ + +SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, + const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, + ELzmaStatus *status, ISzAllocPtr alloc); + +EXTERN_C_END + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c new file mode 100644 index 00000000..68e97c95 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.c @@ -0,0 +1,2976 @@ +/* LzmaEnc.c -- LZMA Encoder +2019-01-10: Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#include + +/* #define SHOW_STAT */ +/* #define SHOW_STAT2 */ + +#if defined(SHOW_STAT) || defined(SHOW_STAT2) +#include +#endif + +#include "LzmaEnc.h" + +#include "LzFind.h" +#ifndef _7ZIP_ST +#include "LzFindMt.h" +#endif + +#ifdef SHOW_STAT +static unsigned g_STAT_OFFSET = 0; +#endif + +#define kLzmaMaxHistorySize ((UInt32)3 << 29) +/* #define kLzmaMaxHistorySize ((UInt32)7 << 29) */ + +#define kNumTopBits 24 +#define kTopValue ((UInt32)1 << kNumTopBits) + +#define kNumBitModelTotalBits 11 +#define kBitModelTotal (1 << kNumBitModelTotalBits) +#define kNumMoveBits 5 +#define kProbInitValue (kBitModelTotal >> 1) + +#define kNumMoveReducingBits 4 +#define kNumBitPriceShiftBits 4 +#define kBitPrice (1 << kNumBitPriceShiftBits) + +#define REP_LEN_COUNT 64 + +void LzmaEncProps_Init(CLzmaEncProps *p) +{ + p->level = 5; + p->dictSize = p->mc = 0; + p->reduceSize = (UInt64)(Int64)-1; + p->lc = p->lp = p->pb = p->algo = p->fb = p->btMode = p->numHashBytes = p->numThreads = -1; + p->writeEndMark = 0; +} + +void LzmaEncProps_Normalize(CLzmaEncProps *p) +{ + int level = p->level; + if (level < 0) level = 5; + p->level = level; + + if (p->dictSize == 0) p->dictSize = (level <= 5 ? (1 << (level * 2 + 14)) : (level <= 7 ? (1 << 25) : (1 << 26))); + if (p->dictSize > p->reduceSize) + { + unsigned i; + UInt32 reduceSize = (UInt32)p->reduceSize; + for (i = 11; i <= 30; i++) + { + if (reduceSize <= ((UInt32)2 << i)) { p->dictSize = ((UInt32)2 << i); break; } + if (reduceSize <= ((UInt32)3 << i)) { p->dictSize = ((UInt32)3 << i); break; } + } + } + + if (p->lc < 0) p->lc = 3; + if (p->lp < 0) p->lp = 0; + if (p->pb < 0) p->pb = 2; + + if (p->algo < 0) p->algo = (level < 5 ? 0 : 1); + if (p->fb < 0) p->fb = (level < 7 ? 32 : 64); + if (p->btMode < 0) p->btMode = (p->algo == 0 ? 0 : 1); + if (p->numHashBytes < 0) p->numHashBytes = 4; + if (p->mc == 0) p->mc = (16 + (p->fb >> 1)) >> (p->btMode ? 0 : 1); + + if (p->numThreads < 0) + p->numThreads = + #ifndef _7ZIP_ST + ((p->btMode && p->algo) ? 2 : 1); + #else + 1; + #endif +} + +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2) +{ + CLzmaEncProps props = *props2; + LzmaEncProps_Normalize(&props); + return props.dictSize; +} + +#if (_MSC_VER >= 1400) +/* BSR code is fast for some new CPUs */ +/* #define LZMA_LOG_BSR */ +#endif + +#ifdef LZMA_LOG_BSR + +#define kDicLogSizeMaxCompress 32 + +#define BSR2_RET(pos, res) { unsigned long zz; _BitScanReverse(&zz, (pos)); res = (zz + zz) + ((pos >> (zz - 1)) & 1); } + +static unsigned GetPosSlot1(UInt32 pos) +{ + unsigned res; + BSR2_RET(pos, res); + return res; +} +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +#define GetPosSlot(pos, res) { if (pos < 2) res = pos; else BSR2_RET(pos, res); } + +#else + +#define kNumLogBits (9 + sizeof(size_t) / 2) +/* #define kNumLogBits (11 + sizeof(size_t) / 8 * 3) */ + +#define kDicLogSizeMaxCompress ((kNumLogBits - 1) * 2 + 7) + +static void LzmaEnc_FastPosInit(Byte *g_FastPos) +{ + unsigned slot; + g_FastPos[0] = 0; + g_FastPos[1] = 1; + g_FastPos += 2; + + for (slot = 2; slot < kNumLogBits * 2; slot++) + { + size_t k = ((size_t)1 << ((slot >> 1) - 1)); + size_t j; + for (j = 0; j < k; j++) + g_FastPos[j] = (Byte)slot; + g_FastPos += k; + } +} + +/* we can use ((limit - pos) >> 31) only if (pos < ((UInt32)1 << 31)) */ +/* +#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \ + (0 - (((((UInt32)1 << (kNumLogBits + 6)) - 1) - pos) >> 31))); \ + res = p->g_FastPos[pos >> zz] + (zz * 2); } +*/ + +/* +#define BSR2_RET(pos, res) { unsigned zz = 6 + ((kNumLogBits - 1) & \ + (0 - (((((UInt32)1 << (kNumLogBits)) - 1) - (pos >> 6)) >> 31))); \ + res = p->g_FastPos[pos >> zz] + (zz * 2); } +*/ + +#define BSR2_RET(pos, res) { unsigned zz = (pos < (1 << (kNumLogBits + 6))) ? 6 : 6 + kNumLogBits - 1; \ + res = p->g_FastPos[pos >> zz] + (zz * 2); } + +/* +#define BSR2_RET(pos, res) { res = (pos < (1 << (kNumLogBits + 6))) ? \ + p->g_FastPos[pos >> 6] + 12 : \ + p->g_FastPos[pos >> (6 + kNumLogBits - 1)] + (6 + (kNumLogBits - 1)) * 2; } +*/ + +#define GetPosSlot1(pos) p->g_FastPos[pos] +#define GetPosSlot2(pos, res) { BSR2_RET(pos, res); } +#define GetPosSlot(pos, res) { if (pos < kNumFullDistances) res = p->g_FastPos[pos & (kNumFullDistances - 1)]; else BSR2_RET(pos, res); } + +#endif + + +#define LZMA_NUM_REPS 4 + +typedef UInt16 CState; +typedef UInt16 CExtra; + +typedef struct +{ + UInt32 price; + CState state; + CExtra extra; + // 0 : normal + // 1 : LIT : MATCH + // > 1 : MATCH (extra-1) : LIT : REP0 (len) + UInt32 len; + UInt32 dist; + UInt32 reps[LZMA_NUM_REPS]; +} COptimal; + + +// 18.06 +#define kNumOpts (1 << 11) +#define kPackReserve (kNumOpts * 8) +// #define kNumOpts (1 << 12) +// #define kPackReserve (1 + kNumOpts * 2) + +#define kNumLenToPosStates 4 +#define kNumPosSlotBits 6 +#define kDicLogSizeMin 0 +#define kDicLogSizeMax 32 +#define kDistTableSizeMax (kDicLogSizeMax * 2) + +#define kNumAlignBits 4 +#define kAlignTableSize (1 << kNumAlignBits) +#define kAlignMask (kAlignTableSize - 1) + +#define kStartPosModelIndex 4 +#define kEndPosModelIndex 14 +#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) + +typedef +#ifdef _LZMA_PROB32 + UInt32 +#else + UInt16 +#endif + CLzmaProb; + +#define LZMA_PB_MAX 4 +#define LZMA_LC_MAX 8 +#define LZMA_LP_MAX 4 + +#define LZMA_NUM_PB_STATES_MAX (1 << LZMA_PB_MAX) + +#define kLenNumLowBits 3 +#define kLenNumLowSymbols (1 << kLenNumLowBits) +#define kLenNumHighBits 8 +#define kLenNumHighSymbols (1 << kLenNumHighBits) +#define kLenNumSymbolsTotal (kLenNumLowSymbols * 2 + kLenNumHighSymbols) + +#define LZMA_MATCH_LEN_MIN 2 +#define LZMA_MATCH_LEN_MAX (LZMA_MATCH_LEN_MIN + kLenNumSymbolsTotal - 1) + +#define kNumStates 12 + + +typedef struct +{ + CLzmaProb low[LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)]; + CLzmaProb high[kLenNumHighSymbols]; +} CLenEnc; + + +typedef struct +{ + unsigned tableSize; + UInt32 prices[LZMA_NUM_PB_STATES_MAX][kLenNumSymbolsTotal]; + // UInt32 prices1[LZMA_NUM_PB_STATES_MAX][kLenNumLowSymbols * 2]; + // UInt32 prices2[kLenNumSymbolsTotal]; +} CLenPriceEnc; + +#define GET_PRICE_LEN(p, posState, len) \ + ((p)->prices[posState][(size_t)(len) - LZMA_MATCH_LEN_MIN]) + +/* +#define GET_PRICE_LEN(p, posState, len) \ + ((p)->prices2[(size_t)(len) - 2] + ((p)->prices1[posState][((len) - 2) & (kLenNumLowSymbols * 2 - 1)] & (((len) - 2 - kLenNumLowSymbols * 2) >> 9))) +*/ + +typedef struct +{ + UInt32 range; + unsigned cache; + UInt64 low; + UInt64 cacheSize; + Byte *buf; + Byte *bufLim; + Byte *bufBase; + ISeqOutStream *outStream; + UInt64 processed; + SRes res; +} CRangeEnc; + + +typedef struct +{ + CLzmaProb *litProbs; + + unsigned state; + UInt32 reps[LZMA_NUM_REPS]; + + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances]; + + CLenEnc lenProbs; + CLenEnc repLenProbs; + +} CSaveState; + + +typedef UInt32 CProbPrice; + + +typedef struct +{ + void *matchFinderObj; + IMatchFinder matchFinder; + + unsigned optCur; + unsigned optEnd; + + unsigned longestMatchLen; + unsigned numPairs; + UInt32 numAvail; + + unsigned state; + unsigned numFastBytes; + unsigned additionalOffset; + UInt32 reps[LZMA_NUM_REPS]; + unsigned lpMask, pbMask; + CLzmaProb *litProbs; + CRangeEnc rc; + + UInt32 backRes; + + unsigned lc, lp, pb; + unsigned lclp; + + BoolInt fastMode; + BoolInt writeEndMark; + BoolInt finished; + BoolInt multiThread; + BoolInt needInit; + // BoolInt _maxMode; + + UInt64 nowPos64; + + unsigned matchPriceCount; + // unsigned alignPriceCount; + int repLenEncCounter; + + unsigned distTableSize; + + UInt32 dictSize; + SRes result; + + #ifndef _7ZIP_ST + BoolInt mtMode; + // begin of CMatchFinderMt is used in LZ thread + CMatchFinderMt matchFinderMt; + // end of CMatchFinderMt is used in BT and HASH threads + #endif + + CMatchFinder matchFinderBase; + + #ifndef _7ZIP_ST + Byte pad[128]; + #endif + + // LZ thread + CProbPrice ProbPrices[kBitModelTotal >> kNumMoveReducingBits]; + + UInt32 matches[LZMA_MATCH_LEN_MAX * 2 + 2 + 1]; + + UInt32 alignPrices[kAlignTableSize]; + UInt32 posSlotPrices[kNumLenToPosStates][kDistTableSizeMax]; + UInt32 distancesPrices[kNumLenToPosStates][kNumFullDistances]; + + CLzmaProb posAlignEncoder[1 << kNumAlignBits]; + CLzmaProb isRep[kNumStates]; + CLzmaProb isRepG0[kNumStates]; + CLzmaProb isRepG1[kNumStates]; + CLzmaProb isRepG2[kNumStates]; + CLzmaProb isMatch[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb isRep0Long[kNumStates][LZMA_NUM_PB_STATES_MAX]; + CLzmaProb posSlotEncoder[kNumLenToPosStates][1 << kNumPosSlotBits]; + CLzmaProb posEncoders[kNumFullDistances]; + + CLenEnc lenProbs; + CLenEnc repLenProbs; + + #ifndef LZMA_LOG_BSR + Byte g_FastPos[1 << kNumLogBits]; + #endif + + CLenPriceEnc lenEnc; + CLenPriceEnc repLenEnc; + + COptimal opt[kNumOpts]; + + CSaveState saveState; + + #ifndef _7ZIP_ST + Byte pad2[128]; + #endif +} CLzmaEnc; + + + +#define COPY_ARR(dest, src, arr) memcpy(dest->arr, src->arr, sizeof(src->arr)); + +void LzmaEnc_SaveState(CLzmaEncHandle pp) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + CSaveState *dest = &p->saveState; + + dest->state = p->state; + + dest->lenProbs = p->lenProbs; + dest->repLenProbs = p->repLenProbs; + + COPY_ARR(dest, p, reps); + + COPY_ARR(dest, p, posAlignEncoder); + COPY_ARR(dest, p, isRep); + COPY_ARR(dest, p, isRepG0); + COPY_ARR(dest, p, isRepG1); + COPY_ARR(dest, p, isRepG2); + COPY_ARR(dest, p, isMatch); + COPY_ARR(dest, p, isRep0Long); + COPY_ARR(dest, p, posSlotEncoder); + COPY_ARR(dest, p, posEncoders); + + memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << p->lclp) * sizeof(CLzmaProb)); +} + + +void LzmaEnc_RestoreState(CLzmaEncHandle pp) +{ + CLzmaEnc *dest = (CLzmaEnc *)pp; + const CSaveState *p = &dest->saveState; + + dest->state = p->state; + + dest->lenProbs = p->lenProbs; + dest->repLenProbs = p->repLenProbs; + + COPY_ARR(dest, p, reps); + + COPY_ARR(dest, p, posAlignEncoder); + COPY_ARR(dest, p, isRep); + COPY_ARR(dest, p, isRepG0); + COPY_ARR(dest, p, isRepG1); + COPY_ARR(dest, p, isRepG2); + COPY_ARR(dest, p, isMatch); + COPY_ARR(dest, p, isRep0Long); + COPY_ARR(dest, p, posSlotEncoder); + COPY_ARR(dest, p, posEncoders); + + memcpy(dest->litProbs, p->litProbs, ((UInt32)0x300 << dest->lclp) * sizeof(CLzmaProb)); +} + + + +SRes LzmaEnc_SetProps(CLzmaEncHandle pp, const CLzmaEncProps *props2) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + CLzmaEncProps props = *props2; + LzmaEncProps_Normalize(&props); + + if (props.lc > LZMA_LC_MAX + || props.lp > LZMA_LP_MAX + || props.pb > LZMA_PB_MAX + || props.dictSize > ((UInt64)1 << kDicLogSizeMaxCompress) + || props.dictSize > kLzmaMaxHistorySize) + return SZ_ERROR_PARAM; + + p->dictSize = props.dictSize; + { + unsigned fb = props.fb; + if (fb < 5) + fb = 5; + if (fb > LZMA_MATCH_LEN_MAX) + fb = LZMA_MATCH_LEN_MAX; + p->numFastBytes = fb; + } + p->lc = props.lc; + p->lp = props.lp; + p->pb = props.pb; + p->fastMode = (props.algo == 0); + // p->_maxMode = True; + p->matchFinderBase.btMode = (Byte)(props.btMode ? 1 : 0); + { + unsigned numHashBytes = 4; + if (props.btMode) + { + if (props.numHashBytes < 2) + numHashBytes = 2; + else if (props.numHashBytes < 4) + numHashBytes = props.numHashBytes; + } + p->matchFinderBase.numHashBytes = numHashBytes; + } + + p->matchFinderBase.cutValue = props.mc; + + p->writeEndMark = props.writeEndMark; + + #ifndef _7ZIP_ST + /* + if (newMultiThread != _multiThread) + { + ReleaseMatchFinder(); + _multiThread = newMultiThread; + } + */ + p->multiThread = (props.numThreads > 1); + #endif + + return SZ_OK; +} + + +void LzmaEnc_SetDataSize(CLzmaEncHandle pp, UInt64 expectedDataSiize) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + p->matchFinderBase.expectedDataSize = expectedDataSiize; +} + + +#define kState_Start 0 +#define kState_LitAfterMatch 4 +#define kState_LitAfterRep 5 +#define kState_MatchAfterLit 7 +#define kState_RepAfterLit 8 + +static const Byte kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; +static const Byte kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; +static const Byte kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; +static const Byte kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; + +#define IsLitState(s) ((s) < 7) +#define GetLenToPosState2(len) (((len) < kNumLenToPosStates - 1) ? (len) : kNumLenToPosStates - 1) +#define GetLenToPosState(len) (((len) < kNumLenToPosStates + 1) ? (len) - 2 : kNumLenToPosStates - 1) + +#define kInfinityPrice (1 << 30) + +static void RangeEnc_Construct(CRangeEnc *p) +{ + p->outStream = NULL; + p->bufBase = NULL; +} + +#define RangeEnc_GetProcessed(p) ((p)->processed + ((p)->buf - (p)->bufBase) + (p)->cacheSize) +#define RangeEnc_GetProcessed_sizet(p) ((size_t)(p)->processed + ((p)->buf - (p)->bufBase) + (size_t)(p)->cacheSize) + +#define RC_BUF_SIZE (1 << 16) + +static int RangeEnc_Alloc(CRangeEnc *p, ISzAllocPtr alloc) +{ + if (!p->bufBase) + { + p->bufBase = (Byte *)ISzAlloc_Alloc(alloc, RC_BUF_SIZE); + if (!p->bufBase) + return 0; + p->bufLim = p->bufBase + RC_BUF_SIZE; + } + return 1; +} + +static void RangeEnc_Free(CRangeEnc *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->bufBase); + p->bufBase = 0; +} + +static void RangeEnc_Init(CRangeEnc *p) +{ + /* Stream.Init(); */ + p->range = 0xFFFFFFFF; + p->cache = 0; + p->low = 0; + p->cacheSize = 0; + + p->buf = p->bufBase; + + p->processed = 0; + p->res = SZ_OK; +} + +MY_NO_INLINE static void RangeEnc_FlushStream(CRangeEnc *p) +{ + size_t num; + if (p->res != SZ_OK) + return; + num = p->buf - p->bufBase; + if (num != ISeqOutStream_Write(p->outStream, p->bufBase, num)) + p->res = SZ_ERROR_WRITE; + p->processed += num; + p->buf = p->bufBase; +} + +MY_NO_INLINE static void MY_FAST_CALL RangeEnc_ShiftLow(CRangeEnc *p) +{ + UInt32 low = (UInt32)p->low; + unsigned high = (unsigned)(p->low >> 32); + p->low = (UInt32)(low << 8); + if (low < (UInt32)0xFF000000 || high != 0) + { + { + Byte *buf = p->buf; + *buf++ = (Byte)(p->cache + high); + p->cache = (unsigned)(low >> 24); + p->buf = buf; + if (buf == p->bufLim) + RangeEnc_FlushStream(p); + if (p->cacheSize == 0) + return; + } + high += 0xFF; + for (;;) + { + Byte *buf = p->buf; + *buf++ = (Byte)(high); + p->buf = buf; + if (buf == p->bufLim) + RangeEnc_FlushStream(p); + if (--p->cacheSize == 0) + return; + } + } + p->cacheSize++; +} + +static void RangeEnc_FlushData(CRangeEnc *p) +{ + int i; + for (i = 0; i < 5; i++) + RangeEnc_ShiftLow(p); +} + +#define RC_NORM(p) if (range < kTopValue) { range <<= 8; RangeEnc_ShiftLow(p); } + +#define RC_BIT_PRE(p, prob) \ + ttt = *(prob); \ + newBound = (range >> kNumBitModelTotalBits) * ttt; + +// #define _LZMA_ENC_USE_BRANCH + +#ifdef _LZMA_ENC_USE_BRANCH + +#define RC_BIT(p, prob, bit) { \ + RC_BIT_PRE(p, prob) \ + if (bit == 0) { range = newBound; ttt += (kBitModelTotal - ttt) >> kNumMoveBits; } \ + else { (p)->low += newBound; range -= newBound; ttt -= ttt >> kNumMoveBits; } \ + *(prob) = (CLzmaProb)ttt; \ + RC_NORM(p) \ + } + +#else + +#define RC_BIT(p, prob, bit) { \ + UInt32 mask; \ + RC_BIT_PRE(p, prob) \ + mask = 0 - (UInt32)bit; \ + range &= mask; \ + mask &= newBound; \ + range -= mask; \ + (p)->low += mask; \ + mask = (UInt32)bit - 1; \ + range += newBound & mask; \ + mask &= (kBitModelTotal - ((1 << kNumMoveBits) - 1)); \ + mask += ((1 << kNumMoveBits) - 1); \ + ttt += (Int32)(mask - ttt) >> kNumMoveBits; \ + *(prob) = (CLzmaProb)ttt; \ + RC_NORM(p) \ + } + +#endif + + + + +#define RC_BIT_0_BASE(p, prob) \ + range = newBound; *(prob) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); + +#define RC_BIT_1_BASE(p, prob) \ + range -= newBound; (p)->low += newBound; *(prob) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); \ + +#define RC_BIT_0(p, prob) \ + RC_BIT_0_BASE(p, prob) \ + RC_NORM(p) + +#define RC_BIT_1(p, prob) \ + RC_BIT_1_BASE(p, prob) \ + RC_NORM(p) + +static void RangeEnc_EncodeBit_0(CRangeEnc *p, CLzmaProb *prob) +{ + UInt32 range, ttt, newBound; + range = p->range; + RC_BIT_PRE(p, prob) + RC_BIT_0(p, prob) + p->range = range; +} + +static void LitEnc_Encode(CRangeEnc *p, CLzmaProb *probs, UInt32 sym) +{ + UInt32 range = p->range; + sym |= 0x100; + do + { + UInt32 ttt, newBound; + // RangeEnc_EncodeBit(p, probs + (sym >> 8), (sym >> 7) & 1); + CLzmaProb *prob = probs + (sym >> 8); + UInt32 bit = (sym >> 7) & 1; + sym <<= 1; + RC_BIT(p, prob, bit); + } + while (sym < 0x10000); + p->range = range; +} + +static void LitEnc_EncodeMatched(CRangeEnc *p, CLzmaProb *probs, UInt32 sym, UInt32 matchByte) +{ + UInt32 range = p->range; + UInt32 offs = 0x100; + sym |= 0x100; + do + { + UInt32 ttt, newBound; + CLzmaProb *prob; + UInt32 bit; + matchByte <<= 1; + // RangeEnc_EncodeBit(p, probs + (offs + (matchByte & offs) + (sym >> 8)), (sym >> 7) & 1); + prob = probs + (offs + (matchByte & offs) + (sym >> 8)); + bit = (sym >> 7) & 1; + sym <<= 1; + offs &= ~(matchByte ^ sym); + RC_BIT(p, prob, bit); + } + while (sym < 0x10000); + p->range = range; +} + + + +static void LzmaEnc_InitPriceTables(CProbPrice *ProbPrices) +{ + UInt32 i; + for (i = 0; i < (kBitModelTotal >> kNumMoveReducingBits); i++) + { + const unsigned kCyclesBits = kNumBitPriceShiftBits; + UInt32 w = (i << kNumMoveReducingBits) + (1 << (kNumMoveReducingBits - 1)); + unsigned bitCount = 0; + unsigned j; + for (j = 0; j < kCyclesBits; j++) + { + w = w * w; + bitCount <<= 1; + while (w >= ((UInt32)1 << 16)) + { + w >>= 1; + bitCount++; + } + } + ProbPrices[i] = (CProbPrice)((kNumBitModelTotalBits << kCyclesBits) - 15 - bitCount); + // printf("\n%3d: %5d", i, ProbPrices[i]); + } +} + + +#define GET_PRICE(prob, bit) \ + p->ProbPrices[((prob) ^ (unsigned)(((-(int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + +#define GET_PRICEa(prob, bit) \ + ProbPrices[((prob) ^ (unsigned)((-((int)(bit))) & (kBitModelTotal - 1))) >> kNumMoveReducingBits]; + +#define GET_PRICE_0(prob) p->ProbPrices[(prob) >> kNumMoveReducingBits] +#define GET_PRICE_1(prob) p->ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] + +#define GET_PRICEa_0(prob) ProbPrices[(prob) >> kNumMoveReducingBits] +#define GET_PRICEa_1(prob) ProbPrices[((prob) ^ (kBitModelTotal - 1)) >> kNumMoveReducingBits] + + +static UInt32 LitEnc_GetPrice(const CLzmaProb *probs, UInt32 sym, const CProbPrice *ProbPrices) +{ + UInt32 price = 0; + sym |= 0x100; + do + { + unsigned bit = sym & 1; + sym >>= 1; + price += GET_PRICEa(probs[sym], bit); + } + while (sym >= 2); + return price; +} + + +static UInt32 LitEnc_Matched_GetPrice(const CLzmaProb *probs, UInt32 sym, UInt32 matchByte, const CProbPrice *ProbPrices) +{ + UInt32 price = 0; + UInt32 offs = 0x100; + sym |= 0x100; + do + { + matchByte <<= 1; + price += GET_PRICEa(probs[offs + (matchByte & offs) + (sym >> 8)], (sym >> 7) & 1); + sym <<= 1; + offs &= ~(matchByte ^ sym); + } + while (sym < 0x10000); + return price; +} + + +static void RcTree_ReverseEncode(CRangeEnc *rc, CLzmaProb *probs, unsigned numBits, unsigned sym) +{ + UInt32 range = rc->range; + unsigned m = 1; + do + { + UInt32 ttt, newBound; + unsigned bit = sym & 1; + // RangeEnc_EncodeBit(rc, probs + m, bit); + sym >>= 1; + RC_BIT(rc, probs + m, bit); + m = (m << 1) | bit; + } + while (--numBits); + rc->range = range; +} + + + +static void LenEnc_Init(CLenEnc *p) +{ + unsigned i; + for (i = 0; i < (LZMA_NUM_PB_STATES_MAX << (kLenNumLowBits + 1)); i++) + p->low[i] = kProbInitValue; + for (i = 0; i < kLenNumHighSymbols; i++) + p->high[i] = kProbInitValue; +} + +static void LenEnc_Encode(CLenEnc *p, CRangeEnc *rc, unsigned sym, unsigned posState) +{ + UInt32 range, ttt, newBound; + CLzmaProb *probs = p->low; + range = rc->range; + RC_BIT_PRE(rc, probs); + if (sym >= kLenNumLowSymbols) + { + RC_BIT_1(rc, probs); + probs += kLenNumLowSymbols; + RC_BIT_PRE(rc, probs); + if (sym >= kLenNumLowSymbols * 2) + { + RC_BIT_1(rc, probs); + rc->range = range; + // RcTree_Encode(rc, p->high, kLenNumHighBits, sym - kLenNumLowSymbols * 2); + LitEnc_Encode(rc, p->high, sym - kLenNumLowSymbols * 2); + return; + } + sym -= kLenNumLowSymbols; + } + + // RcTree_Encode(rc, probs + (posState << kLenNumLowBits), kLenNumLowBits, sym); + { + unsigned m; + unsigned bit; + RC_BIT_0(rc, probs); + probs += (posState << (1 + kLenNumLowBits)); + bit = (sym >> 2) ; RC_BIT(rc, probs + 1, bit); m = (1 << 1) + bit; + bit = (sym >> 1) & 1; RC_BIT(rc, probs + m, bit); m = (m << 1) + bit; + bit = sym & 1; RC_BIT(rc, probs + m, bit); + rc->range = range; + } +} + +static void SetPrices_3(const CLzmaProb *probs, UInt32 startPrice, UInt32 *prices, const CProbPrice *ProbPrices) +{ + unsigned i; + for (i = 0; i < 8; i += 2) + { + UInt32 price = startPrice; + UInt32 prob; + price += GET_PRICEa(probs[1 ], (i >> 2)); + price += GET_PRICEa(probs[2 + (i >> 2)], (i >> 1) & 1); + prob = probs[4 + (i >> 1)]; + prices[i ] = price + GET_PRICEa_0(prob); + prices[i + 1] = price + GET_PRICEa_1(prob); + } +} + + +MY_NO_INLINE static void MY_FAST_CALL LenPriceEnc_UpdateTables( + CLenPriceEnc *p, + unsigned numPosStates, + const CLenEnc *enc, + const CProbPrice *ProbPrices) +{ + UInt32 b; + + { + unsigned prob = enc->low[0]; + UInt32 a, c; + unsigned posState; + b = GET_PRICEa_1(prob); + a = GET_PRICEa_0(prob); + c = b + GET_PRICEa_0(enc->low[kLenNumLowSymbols]); + for (posState = 0; posState < numPosStates; posState++) + { + UInt32 *prices = p->prices[posState]; + const CLzmaProb *probs = enc->low + (posState << (1 + kLenNumLowBits)); + SetPrices_3(probs, a, prices, ProbPrices); + SetPrices_3(probs + kLenNumLowSymbols, c, prices + kLenNumLowSymbols, ProbPrices); + } + } + + /* + { + unsigned i; + UInt32 b; + a = GET_PRICEa_0(enc->low[0]); + for (i = 0; i < kLenNumLowSymbols; i++) + p->prices2[i] = a; + a = GET_PRICEa_1(enc->low[0]); + b = a + GET_PRICEa_0(enc->low[kLenNumLowSymbols]); + for (i = kLenNumLowSymbols; i < kLenNumLowSymbols * 2; i++) + p->prices2[i] = b; + a += GET_PRICEa_1(enc->low[kLenNumLowSymbols]); + } + */ + + // p->counter = numSymbols; + // p->counter = 64; + + { + unsigned i = p->tableSize; + + if (i > kLenNumLowSymbols * 2) + { + const CLzmaProb *probs = enc->high; + UInt32 *prices = p->prices[0] + kLenNumLowSymbols * 2; + i -= kLenNumLowSymbols * 2 - 1; + i >>= 1; + b += GET_PRICEa_1(enc->low[kLenNumLowSymbols]); + do + { + /* + p->prices2[i] = a + + // RcTree_GetPrice(enc->high, kLenNumHighBits, i - kLenNumLowSymbols * 2, ProbPrices); + LitEnc_GetPrice(probs, i - kLenNumLowSymbols * 2, ProbPrices); + */ + // UInt32 price = a + RcTree_GetPrice(probs, kLenNumHighBits - 1, sym, ProbPrices); + unsigned sym = --i + (1 << (kLenNumHighBits - 1)); + UInt32 price = b; + do + { + unsigned bit = sym & 1; + sym >>= 1; + price += GET_PRICEa(probs[sym], bit); + } + while (sym >= 2); + + { + unsigned prob = probs[(size_t)i + (1 << (kLenNumHighBits - 1))]; + prices[(size_t)i * 2 ] = price + GET_PRICEa_0(prob); + prices[(size_t)i * 2 + 1] = price + GET_PRICEa_1(prob); + } + } + while (i); + + { + unsigned posState; + size_t num = (p->tableSize - kLenNumLowSymbols * 2) * sizeof(p->prices[0][0]); + for (posState = 1; posState < numPosStates; posState++) + memcpy(p->prices[posState] + kLenNumLowSymbols * 2, p->prices[0] + kLenNumLowSymbols * 2, num); + } + } + } +} + +/* + #ifdef SHOW_STAT + g_STAT_OFFSET += num; + printf("\n MovePos %u", num); + #endif +*/ + +#define MOVE_POS(p, num) { \ + p->additionalOffset += (num); \ + p->matchFinder.Skip(p->matchFinderObj, (UInt32)(num)); } + + +static unsigned ReadMatchDistances(CLzmaEnc *p, unsigned *numPairsRes) +{ + unsigned numPairs; + + p->additionalOffset++; + p->numAvail = p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); + numPairs = p->matchFinder.GetMatches(p->matchFinderObj, p->matches); + *numPairsRes = numPairs; + + #ifdef SHOW_STAT + printf("\n i = %u numPairs = %u ", g_STAT_OFFSET, numPairs / 2); + g_STAT_OFFSET++; + { + unsigned i; + for (i = 0; i < numPairs; i += 2) + printf("%2u %6u | ", p->matches[i], p->matches[i + 1]); + } + #endif + + if (numPairs == 0) + return 0; + { + unsigned len = p->matches[(size_t)numPairs - 2]; + if (len != p->numFastBytes) + return len; + { + UInt32 numAvail = p->numAvail; + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + { + const Byte *p1 = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + const Byte *p2 = p1 + len; + ptrdiff_t dif = (ptrdiff_t)-1 - p->matches[(size_t)numPairs - 1]; + const Byte *lim = p1 + numAvail; + for (; p2 != lim && *p2 == p2[dif]; p2++) + {} + return (unsigned)(p2 - p1); + } + } + } +} + +#define MARK_LIT ((UInt32)(Int32)-1) + +#define MakeAs_Lit(p) { (p)->dist = MARK_LIT; (p)->extra = 0; } +#define MakeAs_ShortRep(p) { (p)->dist = 0; (p)->extra = 0; } +#define IsShortRep(p) ((p)->dist == 0) + + +#define GetPrice_ShortRep(p, state, posState) \ + ( GET_PRICE_0(p->isRepG0[state]) + GET_PRICE_0(p->isRep0Long[state][posState])) + +#define GetPrice_Rep_0(p, state, posState) ( \ + GET_PRICE_1(p->isMatch[state][posState]) \ + + GET_PRICE_1(p->isRep0Long[state][posState])) \ + + GET_PRICE_1(p->isRep[state]) \ + + GET_PRICE_0(p->isRepG0[state]) + +MY_FORCE_INLINE +static UInt32 GetPrice_PureRep(const CLzmaEnc *p, unsigned repIndex, size_t state, size_t posState) +{ + UInt32 price; + UInt32 prob = p->isRepG0[state]; + if (repIndex == 0) + { + price = GET_PRICE_0(prob); + price += GET_PRICE_1(p->isRep0Long[state][posState]); + } + else + { + price = GET_PRICE_1(prob); + prob = p->isRepG1[state]; + if (repIndex == 1) + price += GET_PRICE_0(prob); + else + { + price += GET_PRICE_1(prob); + price += GET_PRICE(p->isRepG2[state], repIndex - 2); + } + } + return price; +} + + +static unsigned Backward(CLzmaEnc *p, unsigned cur) +{ + unsigned wr = cur + 1; + p->optEnd = wr; + + for (;;) + { + UInt32 dist = p->opt[cur].dist; + unsigned len = (unsigned)p->opt[cur].len; + unsigned extra = (unsigned)p->opt[cur].extra; + cur -= len; + + if (extra) + { + wr--; + p->opt[wr].len = (UInt32)len; + cur -= extra; + len = extra; + if (extra == 1) + { + p->opt[wr].dist = dist; + dist = MARK_LIT; + } + else + { + p->opt[wr].dist = 0; + len--; + wr--; + p->opt[wr].dist = MARK_LIT; + p->opt[wr].len = 1; + } + } + + if (cur == 0) + { + p->backRes = dist; + p->optCur = wr; + return len; + } + + wr--; + p->opt[wr].dist = dist; + p->opt[wr].len = (UInt32)len; + } +} + + + +#define LIT_PROBS(pos, prevByte) \ + (p->litProbs + (UInt32)3 * (((((pos) << 8) + (prevByte)) & p->lpMask) << p->lc)) + + +static unsigned GetOptimum(CLzmaEnc *p, UInt32 position) +{ + unsigned last, cur; + UInt32 reps[LZMA_NUM_REPS]; + unsigned repLens[LZMA_NUM_REPS]; + UInt32 *matches; + + { + UInt32 numAvail; + unsigned numPairs, mainLen, repMaxIndex, i, posState; + UInt32 matchPrice, repMatchPrice; + const Byte *data; + Byte curByte, matchByte; + + p->optCur = p->optEnd = 0; + + if (p->additionalOffset == 0) + mainLen = ReadMatchDistances(p, &numPairs); + else + { + mainLen = p->longestMatchLen; + numPairs = p->numPairs; + } + + numAvail = p->numAvail; + if (numAvail < 2) + { + p->backRes = MARK_LIT; + return 1; + } + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + repMaxIndex = 0; + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + unsigned len; + const Byte *data2; + reps[i] = p->reps[i]; + data2 = data - reps[i]; + if (data[0] != data2[0] || data[1] != data2[1]) + { + repLens[i] = 0; + continue; + } + for (len = 2; len < numAvail && data[len] == data2[len]; len++) + {} + repLens[i] = len; + if (len > repLens[repMaxIndex]) + repMaxIndex = i; + } + + if (repLens[repMaxIndex] >= p->numFastBytes) + { + unsigned len; + p->backRes = (UInt32)repMaxIndex; + len = repLens[repMaxIndex]; + MOVE_POS(p, len - 1) + return len; + } + + matches = p->matches; + + if (mainLen >= p->numFastBytes) + { + p->backRes = matches[(size_t)numPairs - 1] + LZMA_NUM_REPS; + MOVE_POS(p, mainLen - 1) + return mainLen; + } + + curByte = *data; + matchByte = *(data - reps[0]); + + last = repLens[repMaxIndex]; + if (last <= mainLen) + last = mainLen; + + if (last < 2 && curByte != matchByte) + { + p->backRes = MARK_LIT; + return 1; + } + + p->opt[0].state = (CState)p->state; + + posState = (position & p->pbMask); + + { + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); + p->opt[1].price = GET_PRICE_0(p->isMatch[p->state][posState]) + + (!IsLitState(p->state) ? + LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) : + LitEnc_GetPrice(probs, curByte, p->ProbPrices)); + } + + MakeAs_Lit(&p->opt[1]); + + matchPrice = GET_PRICE_1(p->isMatch[p->state][posState]); + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[p->state]); + + // 18.06 + if (matchByte == curByte && repLens[0] == 0) + { + UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, p->state, posState); + if (shortRepPrice < p->opt[1].price) + { + p->opt[1].price = shortRepPrice; + MakeAs_ShortRep(&p->opt[1]); + } + if (last < 2) + { + p->backRes = p->opt[1].dist; + return 1; + } + } + + p->opt[1].len = 1; + + p->opt[0].reps[0] = reps[0]; + p->opt[0].reps[1] = reps[1]; + p->opt[0].reps[2] = reps[2]; + p->opt[0].reps[3] = reps[3]; + + // ---------- REP ---------- + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + unsigned repLen = repLens[i]; + UInt32 price; + if (repLen < 2) + continue; + price = repMatchPrice + GetPrice_PureRep(p, i, p->state, posState); + do + { + UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, repLen); + COptimal *opt = &p->opt[repLen]; + if (price2 < opt->price) + { + opt->price = price2; + opt->len = (UInt32)repLen; + opt->dist = (UInt32)i; + opt->extra = 0; + } + } + while (--repLen >= 2); + } + + + // ---------- MATCH ---------- + { + unsigned len = repLens[0] + 1; + if (len <= mainLen) + { + unsigned offs = 0; + UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[p->state]); + + if (len < 2) + len = 2; + else + while (len > matches[offs]) + offs += 2; + + for (; ; len++) + { + COptimal *opt; + UInt32 dist = matches[(size_t)offs + 1]; + UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len); + unsigned lenToPosState = GetLenToPosState(len); + + if (dist < kNumFullDistances) + price += p->distancesPrices[lenToPosState][dist & (kNumFullDistances - 1)]; + else + { + unsigned slot; + GetPosSlot2(dist, slot); + price += p->alignPrices[dist & kAlignMask]; + price += p->posSlotPrices[lenToPosState][slot]; + } + + opt = &p->opt[len]; + + if (price < opt->price) + { + opt->price = price; + opt->len = (UInt32)len; + opt->dist = dist + LZMA_NUM_REPS; + opt->extra = 0; + } + + if (len == matches[offs]) + { + offs += 2; + if (offs == numPairs) + break; + } + } + } + } + + + cur = 0; + + #ifdef SHOW_STAT2 + /* if (position >= 0) */ + { + unsigned i; + printf("\n pos = %4X", position); + for (i = cur; i <= last; i++) + printf("\nprice[%4X] = %u", position - cur + i, p->opt[i].price); + } + #endif + } + + + + // ---------- Optimal Parsing ---------- + + for (;;) + { + unsigned numAvail; + UInt32 numAvailFull; + unsigned newLen, numPairs, prev, state, posState, startLen; + UInt32 litPrice, matchPrice, repMatchPrice; + BoolInt nextIsLit; + Byte curByte, matchByte; + const Byte *data; + COptimal *curOpt, *nextOpt; + + if (++cur == last) + break; + + // 18.06 + if (cur >= kNumOpts - 64) + { + unsigned j, best; + UInt32 price = p->opt[cur].price; + best = cur; + for (j = cur + 1; j <= last; j++) + { + UInt32 price2 = p->opt[j].price; + if (price >= price2) + { + price = price2; + best = j; + } + } + { + unsigned delta = best - cur; + if (delta != 0) + { + MOVE_POS(p, delta); + } + } + cur = best; + break; + } + + newLen = ReadMatchDistances(p, &numPairs); + + if (newLen >= p->numFastBytes) + { + p->numPairs = numPairs; + p->longestMatchLen = newLen; + break; + } + + curOpt = &p->opt[cur]; + + position++; + + // we need that check here, if skip_items in p->opt are possible + /* + if (curOpt->price >= kInfinityPrice) + continue; + */ + + prev = cur - curOpt->len; + + if (curOpt->len == 1) + { + state = (unsigned)p->opt[prev].state; + if (IsShortRep(curOpt)) + state = kShortRepNextStates[state]; + else + state = kLiteralNextStates[state]; + } + else + { + const COptimal *prevOpt; + UInt32 b0; + UInt32 dist = curOpt->dist; + + if (curOpt->extra) + { + prev -= (unsigned)curOpt->extra; + state = kState_RepAfterLit; + if (curOpt->extra == 1) + state = (dist < LZMA_NUM_REPS ? kState_RepAfterLit : kState_MatchAfterLit); + } + else + { + state = (unsigned)p->opt[prev].state; + if (dist < LZMA_NUM_REPS) + state = kRepNextStates[state]; + else + state = kMatchNextStates[state]; + } + + prevOpt = &p->opt[prev]; + b0 = prevOpt->reps[0]; + + if (dist < LZMA_NUM_REPS) + { + if (dist == 0) + { + reps[0] = b0; + reps[1] = prevOpt->reps[1]; + reps[2] = prevOpt->reps[2]; + reps[3] = prevOpt->reps[3]; + } + else + { + reps[1] = b0; + b0 = prevOpt->reps[1]; + if (dist == 1) + { + reps[0] = b0; + reps[2] = prevOpt->reps[2]; + reps[3] = prevOpt->reps[3]; + } + else + { + reps[2] = b0; + reps[0] = prevOpt->reps[dist]; + reps[3] = prevOpt->reps[dist ^ 1]; + } + } + } + else + { + reps[0] = (dist - LZMA_NUM_REPS + 1); + reps[1] = b0; + reps[2] = prevOpt->reps[1]; + reps[3] = prevOpt->reps[2]; + } + } + + curOpt->state = (CState)state; + curOpt->reps[0] = reps[0]; + curOpt->reps[1] = reps[1]; + curOpt->reps[2] = reps[2]; + curOpt->reps[3] = reps[3]; + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + curByte = *data; + matchByte = *(data - reps[0]); + + posState = (position & p->pbMask); + + /* + The order of Price checks: + < LIT + <= SHORT_REP + < LIT : REP_0 + < REP [ : LIT : REP_0 ] + < MATCH [ : LIT : REP_0 ] + */ + + { + UInt32 curPrice = curOpt->price; + unsigned prob = p->isMatch[state][posState]; + matchPrice = curPrice + GET_PRICE_1(prob); + litPrice = curPrice + GET_PRICE_0(prob); + } + + nextOpt = &p->opt[(size_t)cur + 1]; + nextIsLit = False; + + // here we can allow skip_items in p->opt, if we don't check (nextOpt->price < kInfinityPrice) + // 18.new.06 + if ((nextOpt->price < kInfinityPrice + // && !IsLitState(state) + && matchByte == curByte) + || litPrice > nextOpt->price + ) + litPrice = 0; + else + { + const CLzmaProb *probs = LIT_PROBS(position, *(data - 1)); + litPrice += (!IsLitState(state) ? + LitEnc_Matched_GetPrice(probs, curByte, matchByte, p->ProbPrices) : + LitEnc_GetPrice(probs, curByte, p->ProbPrices)); + + if (litPrice < nextOpt->price) + { + nextOpt->price = litPrice; + nextOpt->len = 1; + MakeAs_Lit(nextOpt); + nextIsLit = True; + } + } + + repMatchPrice = matchPrice + GET_PRICE_1(p->isRep[state]); + + numAvailFull = p->numAvail; + { + unsigned temp = kNumOpts - 1 - cur; + if (numAvailFull > temp) + numAvailFull = (UInt32)temp; + } + + // 18.06 + // ---------- SHORT_REP ---------- + if (IsLitState(state)) // 18.new + if (matchByte == curByte) + if (repMatchPrice < nextOpt->price) // 18.new + // if (numAvailFull < 2 || data[1] != *(data - reps[0] + 1)) + if ( + // nextOpt->price >= kInfinityPrice || + nextOpt->len < 2 // we can check nextOpt->len, if skip items are not allowed in p->opt + || (nextOpt->dist != 0 + // && nextOpt->extra <= 1 // 17.old + ) + ) + { + UInt32 shortRepPrice = repMatchPrice + GetPrice_ShortRep(p, state, posState); + // if (shortRepPrice <= nextOpt->price) // 17.old + if (shortRepPrice < nextOpt->price) // 18.new + { + nextOpt->price = shortRepPrice; + nextOpt->len = 1; + MakeAs_ShortRep(nextOpt); + nextIsLit = False; + } + } + + if (numAvailFull < 2) + continue; + numAvail = (numAvailFull <= p->numFastBytes ? numAvailFull : p->numFastBytes); + + // numAvail <= p->numFastBytes + + // ---------- LIT : REP_0 ---------- + + if (!nextIsLit + && litPrice != 0 // 18.new + && matchByte != curByte + && numAvailFull > 2) + { + const Byte *data2 = data - reps[0]; + if (data[1] == data2[1] && data[2] == data2[2]) + { + unsigned len; + unsigned limit = p->numFastBytes + 1; + if (limit > numAvailFull) + limit = numAvailFull; + for (len = 3; len < limit && data[len] == data2[len]; len++) + {} + + { + unsigned state2 = kLiteralNextStates[state]; + unsigned posState2 = (position + 1) & p->pbMask; + UInt32 price = litPrice + GetPrice_Rep_0(p, state2, posState2); + { + unsigned offset = cur + len; + + if (last < offset) + last = offset; + + // do + { + UInt32 price2; + COptimal *opt; + len--; + // price2 = price + GetPrice_Len_Rep_0(p, len, state2, posState2); + price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len); + + opt = &p->opt[offset]; + // offset--; + if (price2 < opt->price) + { + opt->price = price2; + opt->len = (UInt32)len; + opt->dist = 0; + opt->extra = 1; + } + } + // while (len >= 3); + } + } + } + } + + startLen = 2; /* speed optimization */ + + { + // ---------- REP ---------- + unsigned repIndex = 0; // 17.old + // unsigned repIndex = IsLitState(state) ? 0 : 1; // 18.notused + for (; repIndex < LZMA_NUM_REPS; repIndex++) + { + unsigned len; + UInt32 price; + const Byte *data2 = data - reps[repIndex]; + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + + for (len = 2; len < numAvail && data[len] == data2[len]; len++) + {} + + // if (len < startLen) continue; // 18.new: speed optimization + + { + unsigned offset = cur + len; + if (last < offset) + last = offset; + } + { + unsigned len2 = len; + price = repMatchPrice + GetPrice_PureRep(p, repIndex, state, posState); + do + { + UInt32 price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState, len2); + COptimal *opt = &p->opt[cur + len2]; + if (price2 < opt->price) + { + opt->price = price2; + opt->len = (UInt32)len2; + opt->dist = (UInt32)repIndex; + opt->extra = 0; + } + } + while (--len2 >= 2); + } + + if (repIndex == 0) startLen = len + 1; // 17.old + // startLen = len + 1; // 18.new + + /* if (_maxMode) */ + { + // ---------- REP : LIT : REP_0 ---------- + // numFastBytes + 1 + numFastBytes + + unsigned len2 = len + 1; + unsigned limit = len2 + p->numFastBytes; + if (limit > numAvailFull) + limit = numAvailFull; + + len2 += 2; + if (len2 <= limit) + if (data[len2 - 2] == data2[len2 - 2]) + if (data[len2 - 1] == data2[len2 - 1]) + { + unsigned state2 = kRepNextStates[state]; + unsigned posState2 = (position + len) & p->pbMask; + price += GET_PRICE_LEN(&p->repLenEnc, posState, len) + + GET_PRICE_0(p->isMatch[state2][posState2]) + + LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]), + data[len], data2[len], p->ProbPrices); + + // state2 = kLiteralNextStates[state2]; + state2 = kState_LitAfterRep; + posState2 = (posState2 + 1) & p->pbMask; + + + price += GetPrice_Rep_0(p, state2, posState2); + + for (; len2 < limit && data[len2] == data2[len2]; len2++) + {} + + len2 -= len; + // if (len2 >= 3) + { + { + unsigned offset = cur + len + len2; + + if (last < offset) + last = offset; + // do + { + UInt32 price2; + COptimal *opt; + len2--; + // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2); + price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2); + + opt = &p->opt[offset]; + // offset--; + if (price2 < opt->price) + { + opt->price = price2; + opt->len = (UInt32)len2; + opt->extra = (CExtra)(len + 1); + opt->dist = (UInt32)repIndex; + } + } + // while (len2 >= 3); + } + } + } + } + } + } + + + // ---------- MATCH ---------- + /* for (unsigned len = 2; len <= newLen; len++) */ + if (newLen > numAvail) + { + newLen = numAvail; + for (numPairs = 0; newLen > matches[numPairs]; numPairs += 2); + matches[numPairs] = (UInt32)newLen; + numPairs += 2; + } + + // startLen = 2; /* speed optimization */ + + if (newLen >= startLen) + { + UInt32 normalMatchPrice = matchPrice + GET_PRICE_0(p->isRep[state]); + UInt32 dist; + unsigned offs, posSlot, len; + + { + unsigned offset = cur + newLen; + if (last < offset) + last = offset; + } + + offs = 0; + while (startLen > matches[offs]) + offs += 2; + dist = matches[(size_t)offs + 1]; + + // if (dist >= kNumFullDistances) + GetPosSlot2(dist, posSlot); + + for (len = /*2*/ startLen; ; len++) + { + UInt32 price = normalMatchPrice + GET_PRICE_LEN(&p->lenEnc, posState, len); + { + COptimal *opt; + unsigned lenNorm = len - 2; + lenNorm = GetLenToPosState2(lenNorm); + if (dist < kNumFullDistances) + price += p->distancesPrices[lenNorm][dist & (kNumFullDistances - 1)]; + else + price += p->posSlotPrices[lenNorm][posSlot] + p->alignPrices[dist & kAlignMask]; + + opt = &p->opt[cur + len]; + if (price < opt->price) + { + opt->price = price; + opt->len = (UInt32)len; + opt->dist = dist + LZMA_NUM_REPS; + opt->extra = 0; + } + } + + if (len == matches[offs]) + { + // if (p->_maxMode) { + // MATCH : LIT : REP_0 + + const Byte *data2 = data - dist - 1; + unsigned len2 = len + 1; + unsigned limit = len2 + p->numFastBytes; + if (limit > numAvailFull) + limit = numAvailFull; + + len2 += 2; + if (len2 <= limit) + if (data[len2 - 2] == data2[len2 - 2]) + if (data[len2 - 1] == data2[len2 - 1]) + { + for (; len2 < limit && data[len2] == data2[len2]; len2++) + {} + + len2 -= len; + + // if (len2 >= 3) + { + unsigned state2 = kMatchNextStates[state]; + unsigned posState2 = (position + len) & p->pbMask; + unsigned offset; + price += GET_PRICE_0(p->isMatch[state2][posState2]); + price += LitEnc_Matched_GetPrice(LIT_PROBS(position + len, data[(size_t)len - 1]), + data[len], data2[len], p->ProbPrices); + + // state2 = kLiteralNextStates[state2]; + state2 = kState_LitAfterMatch; + + posState2 = (posState2 + 1) & p->pbMask; + price += GetPrice_Rep_0(p, state2, posState2); + + offset = cur + len + len2; + + if (last < offset) + last = offset; + // do + { + UInt32 price2; + COptimal *opt; + len2--; + // price2 = price + GetPrice_Len_Rep_0(p, len2, state2, posState2); + price2 = price + GET_PRICE_LEN(&p->repLenEnc, posState2, len2); + opt = &p->opt[offset]; + // offset--; + if (price2 < opt->price) + { + opt->price = price2; + opt->len = (UInt32)len2; + opt->extra = (CExtra)(len + 1); + opt->dist = dist + LZMA_NUM_REPS; + } + } + // while (len2 >= 3); + } + + } + + offs += 2; + if (offs == numPairs) + break; + dist = matches[(size_t)offs + 1]; + // if (dist >= kNumFullDistances) + GetPosSlot2(dist, posSlot); + } + } + } + } + + do + p->opt[last].price = kInfinityPrice; + while (--last); + + return Backward(p, cur); +} + + + +#define ChangePair(smallDist, bigDist) (((bigDist) >> 7) > (smallDist)) + + + +static unsigned GetOptimumFast(CLzmaEnc *p) +{ + UInt32 numAvail, mainDist; + unsigned mainLen, numPairs, repIndex, repLen, i; + const Byte *data; + + if (p->additionalOffset == 0) + mainLen = ReadMatchDistances(p, &numPairs); + else + { + mainLen = p->longestMatchLen; + numPairs = p->numPairs; + } + + numAvail = p->numAvail; + p->backRes = MARK_LIT; + if (numAvail < 2) + return 1; + // if (mainLen < 2 && p->state == 0) return 1; // 18.06.notused + if (numAvail > LZMA_MATCH_LEN_MAX) + numAvail = LZMA_MATCH_LEN_MAX; + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + repLen = repIndex = 0; + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + unsigned len; + const Byte *data2 = data - p->reps[i]; + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + for (len = 2; len < numAvail && data[len] == data2[len]; len++) + {} + if (len >= p->numFastBytes) + { + p->backRes = (UInt32)i; + MOVE_POS(p, len - 1) + return len; + } + if (len > repLen) + { + repIndex = i; + repLen = len; + } + } + + if (mainLen >= p->numFastBytes) + { + p->backRes = p->matches[(size_t)numPairs - 1] + LZMA_NUM_REPS; + MOVE_POS(p, mainLen - 1) + return mainLen; + } + + mainDist = 0; /* for GCC */ + + if (mainLen >= 2) + { + mainDist = p->matches[(size_t)numPairs - 1]; + while (numPairs > 2) + { + UInt32 dist2; + if (mainLen != p->matches[(size_t)numPairs - 4] + 1) + break; + dist2 = p->matches[(size_t)numPairs - 3]; + if (!ChangePair(dist2, mainDist)) + break; + numPairs -= 2; + mainLen--; + mainDist = dist2; + } + if (mainLen == 2 && mainDist >= 0x80) + mainLen = 1; + } + + if (repLen >= 2) + if ( repLen + 1 >= mainLen + || (repLen + 2 >= mainLen && mainDist >= (1 << 9)) + || (repLen + 3 >= mainLen && mainDist >= (1 << 15))) + { + p->backRes = (UInt32)repIndex; + MOVE_POS(p, repLen - 1) + return repLen; + } + + if (mainLen < 2 || numAvail <= 2) + return 1; + + { + unsigned len1 = ReadMatchDistances(p, &p->numPairs); + p->longestMatchLen = len1; + + if (len1 >= 2) + { + UInt32 newDist = p->matches[(size_t)p->numPairs - 1]; + if ( (len1 >= mainLen && newDist < mainDist) + || (len1 == mainLen + 1 && !ChangePair(mainDist, newDist)) + || (len1 > mainLen + 1) + || (len1 + 1 >= mainLen && mainLen >= 3 && ChangePair(newDist, mainDist))) + return 1; + } + } + + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - 1; + + for (i = 0; i < LZMA_NUM_REPS; i++) + { + unsigned len, limit; + const Byte *data2 = data - p->reps[i]; + if (data[0] != data2[0] || data[1] != data2[1]) + continue; + limit = mainLen - 1; + for (len = 2;; len++) + { + if (len >= limit) + return 1; + if (data[len] != data2[len]) + break; + } + } + + p->backRes = mainDist + LZMA_NUM_REPS; + if (mainLen != 2) + { + MOVE_POS(p, mainLen - 2) + } + return mainLen; +} + + + + +static void WriteEndMarker(CLzmaEnc *p, unsigned posState) +{ + UInt32 range; + range = p->rc.range; + { + UInt32 ttt, newBound; + CLzmaProb *prob = &p->isMatch[p->state][posState]; + RC_BIT_PRE(&p->rc, prob) + RC_BIT_1(&p->rc, prob) + prob = &p->isRep[p->state]; + RC_BIT_PRE(&p->rc, prob) + RC_BIT_0(&p->rc, prob) + } + p->state = kMatchNextStates[p->state]; + + p->rc.range = range; + LenEnc_Encode(&p->lenProbs, &p->rc, 0, posState); + range = p->rc.range; + + { + // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[0], (1 << kNumPosSlotBits) - 1); + CLzmaProb *probs = p->posSlotEncoder[0]; + unsigned m = 1; + do + { + UInt32 ttt, newBound; + RC_BIT_PRE(p, probs + m) + RC_BIT_1(&p->rc, probs + m); + m = (m << 1) + 1; + } + while (m < (1 << kNumPosSlotBits)); + } + { + // RangeEnc_EncodeDirectBits(&p->rc, ((UInt32)1 << (30 - kNumAlignBits)) - 1, 30 - kNumAlignBits); UInt32 range = p->range; + unsigned numBits = 30 - kNumAlignBits; + do + { + range >>= 1; + p->rc.low += range; + RC_NORM(&p->rc) + } + while (--numBits); + } + + { + // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, kAlignMask); + CLzmaProb *probs = p->posAlignEncoder; + unsigned m = 1; + do + { + UInt32 ttt, newBound; + RC_BIT_PRE(p, probs + m) + RC_BIT_1(&p->rc, probs + m); + m = (m << 1) + 1; + } + while (m < kAlignTableSize); + } + p->rc.range = range; +} + + +static SRes CheckErrors(CLzmaEnc *p) +{ + if (p->result != SZ_OK) + return p->result; + if (p->rc.res != SZ_OK) + p->result = SZ_ERROR_WRITE; + if (p->matchFinderBase.result != SZ_OK) + p->result = SZ_ERROR_READ; + if (p->result != SZ_OK) + p->finished = True; + return p->result; +} + + +MY_NO_INLINE static SRes Flush(CLzmaEnc *p, UInt32 nowPos) +{ + /* ReleaseMFStream(); */ + p->finished = True; + if (p->writeEndMark) + WriteEndMarker(p, nowPos & p->pbMask); + RangeEnc_FlushData(&p->rc); + RangeEnc_FlushStream(&p->rc); + return CheckErrors(p); +} + + +MY_NO_INLINE static void FillAlignPrices(CLzmaEnc *p) +{ + unsigned i; + const CProbPrice *ProbPrices = p->ProbPrices; + const CLzmaProb *probs = p->posAlignEncoder; + // p->alignPriceCount = 0; + for (i = 0; i < kAlignTableSize / 2; i++) + { + UInt32 price = 0; + unsigned sym = i; + unsigned m = 1; + unsigned bit; + UInt32 prob; + bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit; + bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit; + bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[m], bit); m = (m << 1) + bit; + prob = probs[m]; + p->alignPrices[i ] = price + GET_PRICEa_0(prob); + p->alignPrices[i + 8] = price + GET_PRICEa_1(prob); + // p->alignPrices[i] = RcTree_ReverseGetPrice(p->posAlignEncoder, kNumAlignBits, i, p->ProbPrices); + } +} + + +MY_NO_INLINE static void FillDistancesPrices(CLzmaEnc *p) +{ + // int y; for (y = 0; y < 100; y++) { + + UInt32 tempPrices[kNumFullDistances]; + unsigned i, lps; + + const CProbPrice *ProbPrices = p->ProbPrices; + p->matchPriceCount = 0; + + for (i = kStartPosModelIndex / 2; i < kNumFullDistances / 2; i++) + { + unsigned posSlot = GetPosSlot1(i); + unsigned footerBits = (posSlot >> 1) - 1; + unsigned base = ((2 | (posSlot & 1)) << footerBits); + const CLzmaProb *probs = p->posEncoders + (size_t)base * 2; + // tempPrices[i] = RcTree_ReverseGetPrice(p->posEncoders + base, footerBits, i - base, p->ProbPrices); + UInt32 price = 0; + unsigned m = 1; + unsigned sym = i; + unsigned offset = (unsigned)1 << footerBits; + base += i; + + if (footerBits) + do + { + unsigned bit = sym & 1; + sym >>= 1; + price += GET_PRICEa(probs[m], bit); + m = (m << 1) + bit; + } + while (--footerBits); + + { + unsigned prob = probs[m]; + tempPrices[base ] = price + GET_PRICEa_0(prob); + tempPrices[base + offset] = price + GET_PRICEa_1(prob); + } + } + + for (lps = 0; lps < kNumLenToPosStates; lps++) + { + unsigned slot; + unsigned distTableSize2 = (p->distTableSize + 1) >> 1; + UInt32 *posSlotPrices = p->posSlotPrices[lps]; + const CLzmaProb *probs = p->posSlotEncoder[lps]; + + for (slot = 0; slot < distTableSize2; slot++) + { + // posSlotPrices[slot] = RcTree_GetPrice(encoder, kNumPosSlotBits, slot, p->ProbPrices); + UInt32 price; + unsigned bit; + unsigned sym = slot + (1 << (kNumPosSlotBits - 1)); + unsigned prob; + bit = sym & 1; sym >>= 1; price = GET_PRICEa(probs[sym], bit); + bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit); + bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit); + bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit); + bit = sym & 1; sym >>= 1; price += GET_PRICEa(probs[sym], bit); + prob = probs[(size_t)slot + (1 << (kNumPosSlotBits - 1))]; + posSlotPrices[(size_t)slot * 2 ] = price + GET_PRICEa_0(prob); + posSlotPrices[(size_t)slot * 2 + 1] = price + GET_PRICEa_1(prob); + } + + { + UInt32 delta = ((UInt32)((kEndPosModelIndex / 2 - 1) - kNumAlignBits) << kNumBitPriceShiftBits); + for (slot = kEndPosModelIndex / 2; slot < distTableSize2; slot++) + { + posSlotPrices[(size_t)slot * 2 ] += delta; + posSlotPrices[(size_t)slot * 2 + 1] += delta; + delta += ((UInt32)1 << kNumBitPriceShiftBits); + } + } + + { + UInt32 *dp = p->distancesPrices[lps]; + + dp[0] = posSlotPrices[0]; + dp[1] = posSlotPrices[1]; + dp[2] = posSlotPrices[2]; + dp[3] = posSlotPrices[3]; + + for (i = 4; i < kNumFullDistances; i += 2) + { + UInt32 slotPrice = posSlotPrices[GetPosSlot1(i)]; + dp[i ] = slotPrice + tempPrices[i]; + dp[i + 1] = slotPrice + tempPrices[i + 1]; + } + } + } + // } +} + + + +void LzmaEnc_Construct(CLzmaEnc *p) +{ + RangeEnc_Construct(&p->rc); + MatchFinder_Construct(&p->matchFinderBase); + + #ifndef _7ZIP_ST + MatchFinderMt_Construct(&p->matchFinderMt); + p->matchFinderMt.MatchFinder = &p->matchFinderBase; + #endif + + { + CLzmaEncProps props; + LzmaEncProps_Init(&props); + LzmaEnc_SetProps(p, &props); + } + + #ifndef LZMA_LOG_BSR + LzmaEnc_FastPosInit(p->g_FastPos); + #endif + + LzmaEnc_InitPriceTables(p->ProbPrices); + p->litProbs = NULL; + p->saveState.litProbs = NULL; + +} + +CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc) +{ + void *p; + p = ISzAlloc_Alloc(alloc, sizeof(CLzmaEnc)); + if (p) + LzmaEnc_Construct((CLzmaEnc *)p); + return p; +} + +void LzmaEnc_FreeLits(CLzmaEnc *p, ISzAllocPtr alloc) +{ + ISzAlloc_Free(alloc, p->litProbs); + ISzAlloc_Free(alloc, p->saveState.litProbs); + p->litProbs = NULL; + p->saveState.litProbs = NULL; +} + +void LzmaEnc_Destruct(CLzmaEnc *p, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + #ifndef _7ZIP_ST + MatchFinderMt_Destruct(&p->matchFinderMt, allocBig); + #endif + + MatchFinder_Free(&p->matchFinderBase, allocBig); + LzmaEnc_FreeLits(p, alloc); + RangeEnc_Free(&p->rc, alloc); +} + +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + LzmaEnc_Destruct((CLzmaEnc *)p, alloc, allocBig); + ISzAlloc_Free(alloc, p); +} + + +static SRes LzmaEnc_CodeOneBlock(CLzmaEnc *p, UInt32 maxPackSize, UInt32 maxUnpackSize) +{ + UInt32 nowPos32, startPos32; + if (p->needInit) + { + p->matchFinder.Init(p->matchFinderObj); + p->needInit = 0; + } + + if (p->finished) + return p->result; + RINOK(CheckErrors(p)); + + nowPos32 = (UInt32)p->nowPos64; + startPos32 = nowPos32; + + if (p->nowPos64 == 0) + { + unsigned numPairs; + Byte curByte; + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) + return Flush(p, nowPos32); + ReadMatchDistances(p, &numPairs); + RangeEnc_EncodeBit_0(&p->rc, &p->isMatch[kState_Start][0]); + // p->state = kLiteralNextStates[p->state]; + curByte = *(p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset); + LitEnc_Encode(&p->rc, p->litProbs, curByte); + p->additionalOffset--; + nowPos32++; + } + + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) != 0) + + for (;;) + { + UInt32 dist; + unsigned len, posState; + UInt32 range, ttt, newBound; + CLzmaProb *probs; + + if (p->fastMode) + len = GetOptimumFast(p); + else + { + unsigned oci = p->optCur; + if (p->optEnd == oci) + len = GetOptimum(p, nowPos32); + else + { + const COptimal *opt = &p->opt[oci]; + len = opt->len; + p->backRes = opt->dist; + p->optCur = oci + 1; + } + } + + posState = (unsigned)nowPos32 & p->pbMask; + range = p->rc.range; + probs = &p->isMatch[p->state][posState]; + + RC_BIT_PRE(&p->rc, probs) + + dist = p->backRes; + + #ifdef SHOW_STAT2 + printf("\n pos = %6X, len = %3u pos = %6u", nowPos32, len, dist); + #endif + + if (dist == MARK_LIT) + { + Byte curByte; + const Byte *data; + unsigned state; + + RC_BIT_0(&p->rc, probs); + p->rc.range = range; + data = p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; + probs = LIT_PROBS(nowPos32, *(data - 1)); + curByte = *data; + state = p->state; + p->state = kLiteralNextStates[state]; + if (IsLitState(state)) + LitEnc_Encode(&p->rc, probs, curByte); + else + LitEnc_EncodeMatched(&p->rc, probs, curByte, *(data - p->reps[0])); + } + else + { + RC_BIT_1(&p->rc, probs); + probs = &p->isRep[p->state]; + RC_BIT_PRE(&p->rc, probs) + + if (dist < LZMA_NUM_REPS) + { + RC_BIT_1(&p->rc, probs); + probs = &p->isRepG0[p->state]; + RC_BIT_PRE(&p->rc, probs) + if (dist == 0) + { + RC_BIT_0(&p->rc, probs); + probs = &p->isRep0Long[p->state][posState]; + RC_BIT_PRE(&p->rc, probs) + if (len != 1) + { + RC_BIT_1_BASE(&p->rc, probs); + } + else + { + RC_BIT_0_BASE(&p->rc, probs); + p->state = kShortRepNextStates[p->state]; + } + } + else + { + RC_BIT_1(&p->rc, probs); + probs = &p->isRepG1[p->state]; + RC_BIT_PRE(&p->rc, probs) + if (dist == 1) + { + RC_BIT_0_BASE(&p->rc, probs); + dist = p->reps[1]; + } + else + { + RC_BIT_1(&p->rc, probs); + probs = &p->isRepG2[p->state]; + RC_BIT_PRE(&p->rc, probs) + if (dist == 2) + { + RC_BIT_0_BASE(&p->rc, probs); + dist = p->reps[2]; + } + else + { + RC_BIT_1_BASE(&p->rc, probs); + dist = p->reps[3]; + p->reps[3] = p->reps[2]; + } + p->reps[2] = p->reps[1]; + } + p->reps[1] = p->reps[0]; + p->reps[0] = dist; + } + + RC_NORM(&p->rc) + + p->rc.range = range; + + if (len != 1) + { + LenEnc_Encode(&p->repLenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState); + --p->repLenEncCounter; + p->state = kRepNextStates[p->state]; + } + } + else + { + unsigned posSlot; + RC_BIT_0(&p->rc, probs); + p->rc.range = range; + p->state = kMatchNextStates[p->state]; + + LenEnc_Encode(&p->lenProbs, &p->rc, len - LZMA_MATCH_LEN_MIN, posState); + // --p->lenEnc.counter; + + dist -= LZMA_NUM_REPS; + p->reps[3] = p->reps[2]; + p->reps[2] = p->reps[1]; + p->reps[1] = p->reps[0]; + p->reps[0] = dist + 1; + + p->matchPriceCount++; + GetPosSlot(dist, posSlot); + // RcTree_Encode_PosSlot(&p->rc, p->posSlotEncoder[GetLenToPosState(len)], posSlot); + { + UInt32 sym = (UInt32)posSlot + (1 << kNumPosSlotBits); + range = p->rc.range; + probs = p->posSlotEncoder[GetLenToPosState(len)]; + do + { + CLzmaProb *prob = probs + (sym >> kNumPosSlotBits); + UInt32 bit = (sym >> (kNumPosSlotBits - 1)) & 1; + sym <<= 1; + RC_BIT(&p->rc, prob, bit); + } + while (sym < (1 << kNumPosSlotBits * 2)); + p->rc.range = range; + } + + if (dist >= kStartPosModelIndex) + { + unsigned footerBits = ((posSlot >> 1) - 1); + + if (dist < kNumFullDistances) + { + unsigned base = ((2 | (posSlot & 1)) << footerBits); + RcTree_ReverseEncode(&p->rc, p->posEncoders + base, footerBits, (unsigned)(dist /* - base */)); + } + else + { + UInt32 pos2 = (dist | 0xF) << (32 - footerBits); + range = p->rc.range; + // RangeEnc_EncodeDirectBits(&p->rc, posReduced >> kNumAlignBits, footerBits - kNumAlignBits); + /* + do + { + range >>= 1; + p->rc.low += range & (0 - ((dist >> --footerBits) & 1)); + RC_NORM(&p->rc) + } + while (footerBits > kNumAlignBits); + */ + do + { + range >>= 1; + p->rc.low += range & (0 - (pos2 >> 31)); + pos2 += pos2; + RC_NORM(&p->rc) + } + while (pos2 != 0xF0000000); + + + // RcTree_ReverseEncode(&p->rc, p->posAlignEncoder, kNumAlignBits, posReduced & kAlignMask); + + { + unsigned m = 1; + unsigned bit; + bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit; + bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit; + bit = dist & 1; dist >>= 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); m = (m << 1) + bit; + bit = dist & 1; RC_BIT(&p->rc, p->posAlignEncoder + m, bit); + p->rc.range = range; + // p->alignPriceCount++; + } + } + } + } + } + + nowPos32 += (UInt32)len; + p->additionalOffset -= len; + + if (p->additionalOffset == 0) + { + UInt32 processed; + + if (!p->fastMode) + { + /* + if (p->alignPriceCount >= 16) // kAlignTableSize + FillAlignPrices(p); + if (p->matchPriceCount >= 128) + FillDistancesPrices(p); + if (p->lenEnc.counter <= 0) + LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices); + */ + if (p->matchPriceCount >= 64) + { + FillAlignPrices(p); + // { int y; for (y = 0; y < 100; y++) { + FillDistancesPrices(p); + // }} + LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices); + } + if (p->repLenEncCounter <= 0) + { + p->repLenEncCounter = REP_LEN_COUNT; + LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices); + } + } + + if (p->matchFinder.GetNumAvailableBytes(p->matchFinderObj) == 0) + break; + processed = nowPos32 - startPos32; + + if (maxPackSize) + { + if (processed + kNumOpts + 300 >= maxUnpackSize + || RangeEnc_GetProcessed_sizet(&p->rc) + kPackReserve >= maxPackSize) + break; + } + else if (processed >= (1 << 17)) + { + p->nowPos64 += nowPos32 - startPos32; + return CheckErrors(p); + } + } + } + + p->nowPos64 += nowPos32 - startPos32; + return Flush(p, nowPos32); +} + + + +#define kBigHashDicLimit ((UInt32)1 << 24) + +static SRes LzmaEnc_Alloc(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + UInt32 beforeSize = kNumOpts; + if (!RangeEnc_Alloc(&p->rc, alloc)) + return SZ_ERROR_MEM; + + #ifndef _7ZIP_ST + p->mtMode = (p->multiThread && !p->fastMode && (p->matchFinderBase.btMode != 0)); + #endif + + { + unsigned lclp = p->lc + p->lp; + if (!p->litProbs || !p->saveState.litProbs || p->lclp != lclp) + { + LzmaEnc_FreeLits(p, alloc); + p->litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb)); + p->saveState.litProbs = (CLzmaProb *)ISzAlloc_Alloc(alloc, ((UInt32)0x300 << lclp) * sizeof(CLzmaProb)); + if (!p->litProbs || !p->saveState.litProbs) + { + LzmaEnc_FreeLits(p, alloc); + return SZ_ERROR_MEM; + } + p->lclp = lclp; + } + } + + p->matchFinderBase.bigHash = (Byte)(p->dictSize > kBigHashDicLimit ? 1 : 0); + + if (beforeSize + p->dictSize < keepWindowSize) + beforeSize = keepWindowSize - p->dictSize; + + #ifndef _7ZIP_ST + if (p->mtMode) + { + RINOK(MatchFinderMt_Create(&p->matchFinderMt, p->dictSize, beforeSize, p->numFastBytes, + LZMA_MATCH_LEN_MAX + + 1 /* 18.04 */ + , allocBig)); + p->matchFinderObj = &p->matchFinderMt; + p->matchFinderBase.bigHash = (Byte)( + (p->dictSize > kBigHashDicLimit && p->matchFinderBase.hashMask >= 0xFFFFFF) ? 1 : 0); + MatchFinderMt_CreateVTable(&p->matchFinderMt, &p->matchFinder); + } + else + #endif + { + if (!MatchFinder_Create(&p->matchFinderBase, p->dictSize, beforeSize, p->numFastBytes, LZMA_MATCH_LEN_MAX, allocBig)) + return SZ_ERROR_MEM; + p->matchFinderObj = &p->matchFinderBase; + MatchFinder_CreateVTable(&p->matchFinderBase, &p->matchFinder); + } + + return SZ_OK; +} + +void LzmaEnc_Init(CLzmaEnc *p) +{ + unsigned i; + p->state = 0; + p->reps[0] = + p->reps[1] = + p->reps[2] = + p->reps[3] = 1; + + RangeEnc_Init(&p->rc); + + for (i = 0; i < (1 << kNumAlignBits); i++) + p->posAlignEncoder[i] = kProbInitValue; + + for (i = 0; i < kNumStates; i++) + { + unsigned j; + for (j = 0; j < LZMA_NUM_PB_STATES_MAX; j++) + { + p->isMatch[i][j] = kProbInitValue; + p->isRep0Long[i][j] = kProbInitValue; + } + p->isRep[i] = kProbInitValue; + p->isRepG0[i] = kProbInitValue; + p->isRepG1[i] = kProbInitValue; + p->isRepG2[i] = kProbInitValue; + } + + { + for (i = 0; i < kNumLenToPosStates; i++) + { + CLzmaProb *probs = p->posSlotEncoder[i]; + unsigned j; + for (j = 0; j < (1 << kNumPosSlotBits); j++) + probs[j] = kProbInitValue; + } + } + { + for (i = 0; i < kNumFullDistances; i++) + p->posEncoders[i] = kProbInitValue; + } + + { + UInt32 num = (UInt32)0x300 << (p->lp + p->lc); + UInt32 k; + CLzmaProb *probs = p->litProbs; + for (k = 0; k < num; k++) + probs[k] = kProbInitValue; + } + + + LenEnc_Init(&p->lenProbs); + LenEnc_Init(&p->repLenProbs); + + p->optEnd = 0; + p->optCur = 0; + + { + for (i = 0; i < kNumOpts; i++) + p->opt[i].price = kInfinityPrice; + } + + p->additionalOffset = 0; + + p->pbMask = (1 << p->pb) - 1; + p->lpMask = ((UInt32)0x100 << p->lp) - ((unsigned)0x100 >> p->lc); +} + + +void LzmaEnc_InitPrices(CLzmaEnc *p) +{ + if (!p->fastMode) + { + FillDistancesPrices(p); + FillAlignPrices(p); + } + + p->lenEnc.tableSize = + p->repLenEnc.tableSize = + p->numFastBytes + 1 - LZMA_MATCH_LEN_MIN; + + p->repLenEncCounter = REP_LEN_COUNT; + + LenPriceEnc_UpdateTables(&p->lenEnc, 1 << p->pb, &p->lenProbs, p->ProbPrices); + LenPriceEnc_UpdateTables(&p->repLenEnc, 1 << p->pb, &p->repLenProbs, p->ProbPrices); +} + +static SRes LzmaEnc_AllocAndInit(CLzmaEnc *p, UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + unsigned i; + for (i = kEndPosModelIndex / 2; i < kDicLogSizeMax; i++) + if (p->dictSize <= ((UInt32)1 << i)) + break; + p->distTableSize = i * 2; + + p->finished = False; + p->result = SZ_OK; + RINOK(LzmaEnc_Alloc(p, keepWindowSize, alloc, allocBig)); + LzmaEnc_Init(p); + LzmaEnc_InitPrices(p); + p->nowPos64 = 0; + return SZ_OK; +} + +static SRes LzmaEnc_Prepare(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, + ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + p->matchFinderBase.stream = inStream; + p->needInit = 1; + p->rc.outStream = outStream; + return LzmaEnc_AllocAndInit(p, 0, alloc, allocBig); +} + +SRes LzmaEnc_PrepareForLzma2(CLzmaEncHandle pp, + ISeqInStream *inStream, UInt32 keepWindowSize, + ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + p->matchFinderBase.stream = inStream; + p->needInit = 1; + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); +} + +static void LzmaEnc_SetInputBuf(CLzmaEnc *p, const Byte *src, SizeT srcLen) +{ + p->matchFinderBase.directInput = 1; + p->matchFinderBase.bufferBase = (Byte *)src; + p->matchFinderBase.directInputRem = srcLen; +} + +SRes LzmaEnc_MemPrepare(CLzmaEncHandle pp, const Byte *src, SizeT srcLen, + UInt32 keepWindowSize, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + LzmaEnc_SetInputBuf(p, src, srcLen); + p->needInit = 1; + + LzmaEnc_SetDataSize(pp, srcLen); + return LzmaEnc_AllocAndInit(p, keepWindowSize, alloc, allocBig); +} + +void LzmaEnc_Finish(CLzmaEncHandle pp) +{ + #ifndef _7ZIP_ST + CLzmaEnc *p = (CLzmaEnc *)pp; + if (p->mtMode) + MatchFinderMt_ReleaseStream(&p->matchFinderMt); + #else + UNUSED_VAR(pp); + #endif +} + + +typedef struct +{ + ISeqOutStream vt; + Byte *data; + SizeT rem; + BoolInt overflow; +} CLzmaEnc_SeqOutStreamBuf; + +static size_t SeqOutStreamBuf_Write(const ISeqOutStream *pp, const void *data, size_t size) +{ + CLzmaEnc_SeqOutStreamBuf *p = CONTAINER_FROM_VTBL(pp, CLzmaEnc_SeqOutStreamBuf, vt); + if (p->rem < size) + { + size = p->rem; + p->overflow = True; + } + memcpy(p->data, data, size); + p->rem -= size; + p->data += size; + return size; +} + + +UInt32 LzmaEnc_GetNumAvailableBytes(CLzmaEncHandle pp) +{ + const CLzmaEnc *p = (CLzmaEnc *)pp; + return p->matchFinder.GetNumAvailableBytes(p->matchFinderObj); +} + + +const Byte *LzmaEnc_GetCurBuf(CLzmaEncHandle pp) +{ + const CLzmaEnc *p = (CLzmaEnc *)pp; + return p->matchFinder.GetPointerToCurrentPos(p->matchFinderObj) - p->additionalOffset; +} + + +SRes LzmaEnc_CodeOneMemBlock(CLzmaEncHandle pp, BoolInt reInit, + Byte *dest, size_t *destLen, UInt32 desiredPackSize, UInt32 *unpackSize) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + UInt64 nowPos64; + SRes res; + CLzmaEnc_SeqOutStreamBuf outStream; + + outStream.vt.Write = SeqOutStreamBuf_Write; + outStream.data = dest; + outStream.rem = *destLen; + outStream.overflow = False; + + p->writeEndMark = False; + p->finished = False; + p->result = SZ_OK; + + if (reInit) + LzmaEnc_Init(p); + LzmaEnc_InitPrices(p); + + nowPos64 = p->nowPos64; + RangeEnc_Init(&p->rc); + p->rc.outStream = &outStream.vt; + + if (desiredPackSize == 0) + return SZ_ERROR_OUTPUT_EOF; + + res = LzmaEnc_CodeOneBlock(p, desiredPackSize, *unpackSize); + + *unpackSize = (UInt32)(p->nowPos64 - nowPos64); + *destLen -= outStream.rem; + if (outStream.overflow) + return SZ_ERROR_OUTPUT_EOF; + + return res; +} + + +static SRes LzmaEnc_Encode2(CLzmaEnc *p, ICompressProgress *progress) +{ + SRes res = SZ_OK; + + #ifndef _7ZIP_ST + Byte allocaDummy[0x300]; + allocaDummy[0] = 0; + allocaDummy[1] = allocaDummy[0]; + #endif + + for (;;) + { + res = LzmaEnc_CodeOneBlock(p, 0, 0); + if (res != SZ_OK || p->finished) + break; + if (progress) + { + res = ICompressProgress_Progress(progress, p->nowPos64, RangeEnc_GetProcessed(&p->rc)); + if (res != SZ_OK) + { + res = SZ_ERROR_PROGRESS; + break; + } + } + } + + LzmaEnc_Finish(p); + + /* + if (res == SZ_OK && !Inline_MatchFinder_IsFinishedOK(&p->matchFinderBase)) + res = SZ_ERROR_FAIL; + } + */ + + return res; +} + + +SRes LzmaEnc_Encode(CLzmaEncHandle pp, ISeqOutStream *outStream, ISeqInStream *inStream, ICompressProgress *progress, + ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + RINOK(LzmaEnc_Prepare(pp, outStream, inStream, alloc, allocBig)); + return LzmaEnc_Encode2((CLzmaEnc *)pp, progress); +} + + +SRes LzmaEnc_WriteProperties(CLzmaEncHandle pp, Byte *props, SizeT *size) +{ + CLzmaEnc *p = (CLzmaEnc *)pp; + unsigned i; + UInt32 dictSize = p->dictSize; + if (*size < LZMA_PROPS_SIZE) + return SZ_ERROR_PARAM; + *size = LZMA_PROPS_SIZE; + props[0] = (Byte)((p->pb * 5 + p->lp) * 9 + p->lc); + + if (dictSize >= ((UInt32)1 << 22)) + { + UInt32 kDictMask = ((UInt32)1 << 20) - 1; + if (dictSize < (UInt32)0xFFFFFFFF - kDictMask) + dictSize = (dictSize + kDictMask) & ~kDictMask; + } + else for (i = 11; i <= 30; i++) + { + if (dictSize <= ((UInt32)2 << i)) { dictSize = (2 << i); break; } + if (dictSize <= ((UInt32)3 << i)) { dictSize = (3 << i); break; } + } + + for (i = 0; i < 4; i++) + props[1 + i] = (Byte)(dictSize >> (8 * i)); + return SZ_OK; +} + + +unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle pp) +{ + return ((CLzmaEnc *)pp)->writeEndMark; +} + + +SRes LzmaEnc_MemEncode(CLzmaEncHandle pp, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + SRes res; + CLzmaEnc *p = (CLzmaEnc *)pp; + + CLzmaEnc_SeqOutStreamBuf outStream; + + outStream.vt.Write = SeqOutStreamBuf_Write; + outStream.data = dest; + outStream.rem = *destLen; + outStream.overflow = False; + + p->writeEndMark = writeEndMark; + p->rc.outStream = &outStream.vt; + + res = LzmaEnc_MemPrepare(pp, src, srcLen, 0, alloc, allocBig); + + if (res == SZ_OK) + { + res = LzmaEnc_Encode2(p, progress); + if (res == SZ_OK && p->nowPos64 != srcLen) + res = SZ_ERROR_FAIL; + } + + *destLen -= outStream.rem; + if (outStream.overflow) + return SZ_ERROR_OUTPUT_EOF; + return res; +} + + +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig) +{ + CLzmaEnc *p = (CLzmaEnc *)LzmaEnc_Create(alloc); + SRes res; + if (!p) + return SZ_ERROR_MEM; + + res = LzmaEnc_SetProps(p, props); + if (res == SZ_OK) + { + res = LzmaEnc_WriteProperties(p, propsEncoded, propsSize); + if (res == SZ_OK) + res = LzmaEnc_MemEncode(p, dest, destLen, src, srcLen, + writeEndMark, progress, alloc, allocBig); + } + + LzmaEnc_Destroy(p, alloc, allocBig); + return res; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.h new file mode 100644 index 00000000..867d60ba --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/LzmaEnc.h @@ -0,0 +1,76 @@ +/* LzmaEnc.h -- LZMA Encoder +2017-07-27 : Igor Pavlov : Public domain */ + +#ifndef __LZMA_ENC_H +#define __LZMA_ENC_H + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +#define LZMA_PROPS_SIZE 5 + +typedef struct _CLzmaEncProps +{ + int level; /* 0 <= level <= 9 */ + UInt32 dictSize; /* (1 << 12) <= dictSize <= (1 << 27) for 32-bit version + (1 << 12) <= dictSize <= (3 << 29) for 64-bit version + default = (1 << 24) */ + int lc; /* 0 <= lc <= 8, default = 3 */ + int lp; /* 0 <= lp <= 4, default = 0 */ + int pb; /* 0 <= pb <= 4, default = 2 */ + int algo; /* 0 - fast, 1 - normal, default = 1 */ + int fb; /* 5 <= fb <= 273, default = 32 */ + int btMode; /* 0 - hashChain Mode, 1 - binTree mode - normal, default = 1 */ + int numHashBytes; /* 2, 3 or 4, default = 4 */ + UInt32 mc; /* 1 <= mc <= (1 << 30), default = 32 */ + unsigned writeEndMark; /* 0 - do not write EOPM, 1 - write EOPM, default = 0 */ + int numThreads; /* 1 or 2, default = 2 */ + + UInt64 reduceSize; /* estimated size of data that will be compressed. default = (UInt64)(Int64)-1. + Encoder uses this value to reduce dictionary size */ +} CLzmaEncProps; + +void LzmaEncProps_Init(CLzmaEncProps *p); +void LzmaEncProps_Normalize(CLzmaEncProps *p); +UInt32 LzmaEncProps_GetDictSize(const CLzmaEncProps *props2); + + +/* ---------- CLzmaEncHandle Interface ---------- */ + +/* LzmaEnc* functions can return the following exit codes: +SRes: + SZ_OK - OK + SZ_ERROR_MEM - Memory allocation error + SZ_ERROR_PARAM - Incorrect parameter in props + SZ_ERROR_WRITE - ISeqOutStream write callback error + SZ_ERROR_OUTPUT_EOF - output buffer overflow - version with (Byte *) output + SZ_ERROR_PROGRESS - some break from progress callback + SZ_ERROR_THREAD - error in multithreading functions (only for Mt version) +*/ + +typedef void * CLzmaEncHandle; + +CLzmaEncHandle LzmaEnc_Create(ISzAllocPtr alloc); +void LzmaEnc_Destroy(CLzmaEncHandle p, ISzAllocPtr alloc, ISzAllocPtr allocBig); + +SRes LzmaEnc_SetProps(CLzmaEncHandle p, const CLzmaEncProps *props); +void LzmaEnc_SetDataSize(CLzmaEncHandle p, UInt64 expectedDataSiize); +SRes LzmaEnc_WriteProperties(CLzmaEncHandle p, Byte *properties, SizeT *size); +unsigned LzmaEnc_IsWriteEndMark(CLzmaEncHandle p); + +SRes LzmaEnc_Encode(CLzmaEncHandle p, ISeqOutStream *outStream, ISeqInStream *inStream, + ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); +SRes LzmaEnc_MemEncode(CLzmaEncHandle p, Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + int writeEndMark, ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); + + +/* ---------- One Call Interface ---------- */ + +SRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, + const CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, + ICompressProgress *progress, ISzAllocPtr alloc, ISzAllocPtr allocBig); + +EXTERN_C_END + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Precomp.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Precomp.h new file mode 100644 index 00000000..e8ff8b40 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Precomp.h @@ -0,0 +1,10 @@ +/* Precomp.h -- StdAfx +2013-11-12 : Igor Pavlov : Public domain */ + +#ifndef __7Z_PRECOMP_H +#define __7Z_PRECOMP_H + +#include "Compiler.h" +/* #include "7zTypes.h" */ + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.c new file mode 100644 index 00000000..c0668664 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.c @@ -0,0 +1,95 @@ +/* Threads.c -- multithreading library +2017-06-26 : Igor Pavlov : Public domain */ + +#include "Precomp.h" + +#ifndef UNDER_CE +#include +#endif + +#include "Threads.h" + +static WRes GetError() +{ + DWORD res = GetLastError(); + return res ? (WRes)res : 1; +} + +static WRes HandleToWRes(HANDLE h) { return (h != NULL) ? 0 : GetError(); } +static WRes BOOLToWRes(BOOL v) { return v ? 0 : GetError(); } + +WRes HandlePtr_Close(HANDLE *p) +{ + if (*p != NULL) + { + if (!CloseHandle(*p)) + return GetError(); + *p = NULL; + } + return 0; +} + +WRes Handle_WaitObject(HANDLE h) { return (WRes)WaitForSingleObject(h, INFINITE); } + +WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param) +{ + /* Windows Me/98/95: threadId parameter may not be NULL in _beginthreadex/CreateThread functions */ + + #ifdef UNDER_CE + + DWORD threadId; + *p = CreateThread(0, 0, func, param, 0, &threadId); + + #else + + unsigned threadId; + *p = (HANDLE)_beginthreadex(NULL, 0, func, param, 0, &threadId); + + #endif + + /* maybe we must use errno here, but probably GetLastError() is also OK. */ + return HandleToWRes(*p); +} + +static WRes Event_Create(CEvent *p, BOOL manualReset, int signaled) +{ + *p = CreateEvent(NULL, manualReset, (signaled ? TRUE : FALSE), NULL); + return HandleToWRes(*p); +} + +WRes Event_Set(CEvent *p) { return BOOLToWRes(SetEvent(*p)); } +WRes Event_Reset(CEvent *p) { return BOOLToWRes(ResetEvent(*p)); } + +WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled) { return Event_Create(p, TRUE, signaled); } +WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled) { return Event_Create(p, FALSE, signaled); } +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p) { return ManualResetEvent_Create(p, 0); } +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p) { return AutoResetEvent_Create(p, 0); } + + +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount) +{ + *p = CreateSemaphore(NULL, (LONG)initCount, (LONG)maxCount, NULL); + return HandleToWRes(*p); +} + +static WRes Semaphore_Release(CSemaphore *p, LONG releaseCount, LONG *previousCount) + { return BOOLToWRes(ReleaseSemaphore(*p, releaseCount, previousCount)); } +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num) + { return Semaphore_Release(p, (LONG)num, NULL); } +WRes Semaphore_Release1(CSemaphore *p) { return Semaphore_ReleaseN(p, 1); } + +WRes CriticalSection_Init(CCriticalSection *p) +{ + /* InitializeCriticalSection can raise only STATUS_NO_MEMORY exception */ + #ifdef _MSC_VER + __try + #endif + { + InitializeCriticalSection(p); + /* InitializeCriticalSectionAndSpinCount(p, 0); */ + } + #ifdef _MSC_VER + __except (EXCEPTION_EXECUTE_HANDLER) { return 1; } + #endif + return 0; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.h new file mode 100644 index 00000000..488e65d3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/C/Threads.h @@ -0,0 +1,72 @@ +/* Threads.h -- multithreading library +2017-06-18 : Igor Pavlov : Public domain */ + +#ifndef __7Z_THREADS_H +#define __7Z_THREADS_H + +#ifdef _WIN32 +# ifdef VBOX +# include +# else +#include +# endif +#endif + +#include "7zTypes.h" + +EXTERN_C_BEGIN + +WRes HandlePtr_Close(HANDLE *h); +WRes Handle_WaitObject(HANDLE h); + +typedef HANDLE CThread; +#define Thread_Construct(p) *(p) = NULL +#define Thread_WasCreated(p) (*(p) != NULL) +#define Thread_Close(p) HandlePtr_Close(p) +#define Thread_Wait(p) Handle_WaitObject(*(p)) + +typedef +#ifdef UNDER_CE + DWORD +#else + unsigned +#endif + THREAD_FUNC_RET_TYPE; + +#define THREAD_FUNC_CALL_TYPE MY_STD_CALL +#define THREAD_FUNC_DECL THREAD_FUNC_RET_TYPE THREAD_FUNC_CALL_TYPE +typedef THREAD_FUNC_RET_TYPE (THREAD_FUNC_CALL_TYPE * THREAD_FUNC_TYPE)(void *); +WRes Thread_Create(CThread *p, THREAD_FUNC_TYPE func, LPVOID param); + +typedef HANDLE CEvent; +typedef CEvent CAutoResetEvent; +typedef CEvent CManualResetEvent; +#define Event_Construct(p) *(p) = NULL +#define Event_IsCreated(p) (*(p) != NULL) +#define Event_Close(p) HandlePtr_Close(p) +#define Event_Wait(p) Handle_WaitObject(*(p)) +WRes Event_Set(CEvent *p); +WRes Event_Reset(CEvent *p); +WRes ManualResetEvent_Create(CManualResetEvent *p, int signaled); +WRes ManualResetEvent_CreateNotSignaled(CManualResetEvent *p); +WRes AutoResetEvent_Create(CAutoResetEvent *p, int signaled); +WRes AutoResetEvent_CreateNotSignaled(CAutoResetEvent *p); + +typedef HANDLE CSemaphore; +#define Semaphore_Construct(p) *(p) = NULL +#define Semaphore_IsCreated(p) (*(p) != NULL) +#define Semaphore_Close(p) HandlePtr_Close(p) +#define Semaphore_Wait(p) Handle_WaitObject(*(p)) +WRes Semaphore_Create(CSemaphore *p, UInt32 initCount, UInt32 maxCount); +WRes Semaphore_ReleaseN(CSemaphore *p, UInt32 num); +WRes Semaphore_Release1(CSemaphore *p); + +typedef CRITICAL_SECTION CCriticalSection; +WRes CriticalSection_Init(CCriticalSection *p); +#define CriticalSection_Delete(p) DeleteCriticalSection(p) +#define CriticalSection_Enter(p) EnterCriticalSection(p) +#define CriticalSection_Leave(p) LeaveCriticalSection(p) + +EXTERN_C_END + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-history.txt b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-history.txt new file mode 100644 index 00000000..e82fd33c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-history.txt @@ -0,0 +1,446 @@ +HISTORY of the LZMA SDK +----------------------- + +19.00 2019-02-21 +------------------------- +- Encryption strength for 7z archives was increased: + the size of random initialization vector was increased from 64-bit to 128-bit, + and the pseudo-random number generator was improved. +- The bug in 7zIn.c code was fixed. + + +18.06 2018-12-30 +------------------------- +- The speed for LZMA/LZMA2 compressing was increased by 3-10%, + and there are minor changes in compression ratio. +- Some bugs were fixed. +- The bug in 7-Zip 18.02-18.05 was fixed: + There was memory leak in multithreading xz decoder - XzDecMt_Decode(), + if xz stream contains only one block. +- The changes for MSVS compiler makefiles: + - the makefiles now use "PLATFORM" macroname with values (x64, x86, arm64) + instead of "CPU" macroname with values (AMD64, ARM64). + - the makefiles by default now use static version of the run-time library. + + +18.05 2018-04-30 +------------------------- +- The speed for LZMA/LZMA2 compressing was increased + by 8% for fastest/fast compression levels and + by 3% for normal/maximum compression levels. +- Previous versions of 7-Zip could work incorrectly in "Large memory pages" mode in + Windows 10 because of some BUG with "Large Pages" in Windows 10. + Now 7-Zip doesn't use "Large Pages" on Windows 10 up to revision 1709 (16299). +- The BUG was fixed in Lzma2Enc.c + Lzma2Enc_Encode2() function worked incorretly, + if (inStream == NULL) and the number of block threads is more than 1. + + +18.03 beta 2018-03-04 +------------------------- +- Asm\x86\LzmaDecOpt.asm: new optimized LZMA decoder written in asm + for x64 with about 30% higher speed than main version of LZMA decoder written in C. +- The speed for single-thread LZMA/LZMA2 decoder written in C was increased by 3%. +- 7-Zip now can use multi-threading for 7z/LZMA2 decoding, + if there are multiple independent data chunks in LZMA2 stream. +- 7-Zip now can use multi-threading for xz decoding, + if there are multiple blocks in xz stream. + + +18.01 2019-01-28 +------------------------- +- The BUG in 17.01 - 18.00 beta was fixed: + XzDec.c : random block unpacking and XzUnpacker_IsBlockFinished() + didn't work correctly for xz archives without checksum (CRC). + + +18.00 beta 2019-01-10 +------------------------- +- The BUG in xz encoder was fixed: + There was memory leak of 16 KB for each file compressed with + xz compression method, if additional filter was used. + + +17.01 beta 2017-08-28 +------------------------- +- Minor speed optimization for LZMA2 (xz and 7z) multi-threading compression. + 7-Zip now uses additional memory buffers for multi-block LZMA2 compression. + CPU utilization was slightly improved. +- 7-zip now creates multi-block xz archives by default. Block size can be + specified with -ms[Size]{m|g} switch. +- xz decoder now can unpack random block from multi-block xz archives. +- 7-Zip command line: @listfile now doesn't work after -- switch. + Use -i@listfile before -- switch instead. +- The BUGs were fixed: + 7-Zip 17.00 beta crashed for commands that write anti-item to 7z archive. + + +17.00 beta 2017-04-29 +------------------------- +- NewHandler.h / NewHandler.cpp: + now it redefines operator new() only for old MSVC compilers (_MSC_VER < 1900). +- C/7zTypes.h : the names of variables in interface structures were changed (vt). +- Some bugs were fixed. 7-Zip could crash in some cases. +- Some internal changes in code. + + +16.04 2016-10-04 +------------------------- +- The bug was fixed in DllSecur.c. + + +16.03 2016-09-28 +------------------------- +- SFX modules now use some protection against DLL preloading attack. +- Some bugs in 7z code were fixed. + + +16.02 2016-05-21 +------------------------- +- The BUG in 16.00 - 16.01 was fixed: + Split Handler (SplitHandler.cpp) returned incorrect + total size value (kpidSize) for split archives. + + +16.01 2016-05-19 +------------------------- +- Some internal changes to reduce the number of compiler warnings. + + +16.00 2016-05-10 +------------------------- +- Some bugs were fixed. + + +15.12 2015-11-19 +------------------------- +- The BUG in C version of 7z decoder was fixed: + 7zDec.c : SzDecodeLzma2() + 7z decoder could mistakenly report about decoding error for some 7z archives + that use LZMA2 compression method. + The probability to get that mistaken decoding error report was about + one error per 16384 solid blocks for solid blocks larger than 16 KB (compressed size). +- The BUG (in 9.26-15.11) in C version of 7z decoder was fixed: + 7zArcIn.c : SzReadHeader2() + 7z decoder worked incorrectly for 7z archives that contain + empty solid blocks, that can be placed to 7z archive, if some file is + unavailable for reading during archive creation. + + +15.09 beta 2015-10-16 +------------------------- +- The BUG in LZMA / LZMA2 encoding code was fixed. + The BUG in LzFind.c::MatchFinder_ReadBlock() function. + If input data size is larger than (4 GiB - dictionary_size), + the following code worked incorrectly: + - LZMA : LzmaEnc_MemEncode(), LzmaEncode() : LZMA encoding functions + for compressing from memory to memory. + That BUG is not related to LZMA encoder version that works via streams. + - LZMA2 : multi-threaded version of LZMA2 encoder worked incorrectly, if + default value of chunk size (CLzma2EncProps::blockSize) is changed + to value larger than (4 GiB - dictionary_size). + + +9.38 beta 2015-01-03 +------------------------- +- The BUG in 9.31-9.37 was fixed: + IArchiveGetRawProps interface was disabled for 7z archives. +- The BUG in 9.26-9.36 was fixed: + Some code in CPP\7zip\Archive\7z\ worked correctly only under Windows. + + +9.36 beta 2014-12-26 +------------------------- +- The BUG in command line version was fixed: + 7-Zip created temporary archive in current folder during update archive + operation, if -w{Path} switch was not specified. + The fixed 7-Zip creates temporary archive in folder that contains updated archive. +- The BUG in 9.33-9.35 was fixed: + 7-Zip silently ignored file reading errors during 7z or gz archive creation, + and the created archive contained only part of file that was read before error. + The fixed 7-Zip stops archive creation and it reports about error. + + +9.35 beta 2014-12-07 +------------------------- +- 7zr.exe now support AES encryption. +- SFX modules were added to LZMA SDK +- Some bugs were fixed. + + +9.21 beta 2011-04-11 +------------------------- +- New class FString for file names at file systems. +- Speed optimization in CRC code for big-endian CPUs. +- The BUG in Lzma2Dec.c was fixed: + Lzma2Decode function didn't work. + + +9.18 beta 2010-11-02 +------------------------- +- New small SFX module for installers (SfxSetup). + + +9.12 beta 2010-03-24 +------------------------- +- The BUG in LZMA SDK 9.* was fixed: LZMA2 codec didn't work, + if more than 10 threads were used (or more than 20 threads in some modes). + + +9.11 beta 2010-03-15 +------------------------- +- PPMd compression method support + + +9.09 2009-12-12 +------------------------- +- The bug was fixed: + Utf16_To_Utf8 funstions in UTFConvert.cpp and 7zMain.c + incorrectly converted surrogate characters (the code >= 0x10000) to UTF-8. +- Some bugs were fixed + + +9.06 2009-08-17 +------------------------- +- Some changes in ANSI-C 7z Decoder interfaces. + + +9.04 2009-05-30 +------------------------- +- LZMA2 compression method support +- xz format support + + +4.65 2009-02-03 +------------------------- +- Some minor fixes + + +4.63 2008-12-31 +------------------------- +- Some minor fixes + + +4.61 beta 2008-11-23 +------------------------- +- The bug in ANSI-C LZMA Decoder was fixed: + If encoded stream was corrupted, decoder could access memory + outside of allocated range. +- Some changes in ANSI-C 7z Decoder interfaces. +- LZMA SDK is placed in the public domain. + + +4.60 beta 2008-08-19 +------------------------- +- Some minor fixes. + + +4.59 beta 2008-08-13 +------------------------- +- The bug was fixed: + LZMA Encoder in fast compression mode could access memory outside of + allocated range in some rare cases. + + +4.58 beta 2008-05-05 +------------------------- +- ANSI-C LZMA Decoder was rewritten for speed optimizations. +- ANSI-C LZMA Encoder was included to LZMA SDK. +- C++ LZMA code now is just wrapper over ANSI-C code. + + +4.57 2007-12-12 +------------------------- +- Speed optimizations in ?++ LZMA Decoder. +- Small changes for more compatibility with some C/C++ compilers. + + +4.49 beta 2007-07-05 +------------------------- +- .7z ANSI-C Decoder: + - now it supports BCJ and BCJ2 filters + - now it supports files larger than 4 GB. + - now it supports "Last Write Time" field for files. +- C++ code for .7z archives compressing/decompressing from 7-zip + was included to LZMA SDK. + + +4.43 2006-06-04 +------------------------- +- Small changes for more compatibility with some C/C++ compilers. + + +4.42 2006-05-15 +------------------------- +- Small changes in .h files in ANSI-C version. + + +4.39 beta 2006-04-14 +------------------------- +- The bug in versions 4.33b:4.38b was fixed: + C++ version of LZMA encoder could not correctly compress + files larger than 2 GB with HC4 match finder (-mfhc4). + + +4.37 beta 2005-04-06 +------------------------- +- Fixes in C++ code: code could no be compiled if _NO_EXCEPTIONS was defined. + + +4.35 beta 2005-03-02 +------------------------- +- The bug was fixed in C++ version of LZMA Decoder: + If encoded stream was corrupted, decoder could access memory + outside of allocated range. + + +4.34 beta 2006-02-27 +------------------------- +- Compressing speed and memory requirements for compressing were increased +- LZMA now can use only these match finders: HC4, BT2, BT3, BT4 + + +4.32 2005-12-09 +------------------------- +- Java version of LZMA SDK was included + + +4.30 2005-11-20 +------------------------- +- Compression ratio was improved in -a2 mode +- Speed optimizations for compressing in -a2 mode +- -fb switch now supports values up to 273 +- The bug in 7z_C (7zIn.c) was fixed: + It used Alloc/Free functions from different memory pools. + So if program used two memory pools, it worked incorrectly. +- 7z_C: .7z format supporting was improved +- LZMA# SDK (C#.NET version) was included + + +4.27 (Updated) 2005-09-21 +------------------------- +- Some GUIDs/interfaces in C++ were changed. + IStream.h: + ISequentialInStream::Read now works as old ReadPart + ISequentialOutStream::Write now works as old WritePart + + +4.27 2005-08-07 +------------------------- +- The bug in LzmaDecodeSize.c was fixed: + if _LZMA_IN_CB and _LZMA_OUT_READ were defined, + decompressing worked incorrectly. + + +4.26 2005-08-05 +------------------------- +- Fixes in 7z_C code and LzmaTest.c: + previous versions could work incorrectly, + if malloc(0) returns 0 + + +4.23 2005-06-29 +------------------------- +- Small fixes in C++ code + + +4.22 2005-06-10 +------------------------- +- Small fixes + + +4.21 2005-06-08 +------------------------- +- Interfaces for ANSI-C LZMA Decoder (LzmaDecode.c) were changed +- New additional version of ANSI-C LZMA Decoder with zlib-like interface: + - LzmaStateDecode.h + - LzmaStateDecode.c + - LzmaStateTest.c +- ANSI-C LZMA Decoder now can decompress files larger than 4 GB + + +4.17 2005-04-18 +------------------------- +- New example for RAM->RAM compressing/decompressing: + LZMA + BCJ (filter for x86 code): + - LzmaRam.h + - LzmaRam.cpp + - LzmaRamDecode.h + - LzmaRamDecode.c + - -f86 switch for lzma.exe + + +4.16 2005-03-29 +------------------------- +- The bug was fixed in LzmaDecode.c (ANSI-C LZMA Decoder): + If _LZMA_OUT_READ was defined, and if encoded stream was corrupted, + decoder could access memory outside of allocated range. +- Speed optimization of ANSI-C LZMA Decoder (now it's about 20% faster). + Old version of LZMA Decoder now is in file LzmaDecodeSize.c. + LzmaDecodeSize.c can provide slightly smaller code than LzmaDecode.c +- Small speed optimization in LZMA C++ code +- filter for SPARC's code was added +- Simplified version of .7z ANSI-C Decoder was included + + +4.06 2004-09-05 +------------------------- +- The bug in v4.05 was fixed: + LZMA-Encoder didn't release output stream in some cases. + + +4.05 2004-08-25 +------------------------- +- Source code of filters for x86, IA-64, ARM, ARM-Thumb + and PowerPC code was included to SDK +- Some internal minor changes + + +4.04 2004-07-28 +------------------------- +- More compatibility with some C++ compilers + + +4.03 2004-06-18 +------------------------- +- "Benchmark" command was added. It measures compressing + and decompressing speed and shows rating values. + Also it checks hardware errors. + + +4.02 2004-06-10 +------------------------- +- C++ LZMA Encoder/Decoder code now is more portable + and it can be compiled by GCC on Linux. + + +4.01 2004-02-15 +------------------------- +- Some detection of data corruption was enabled. + LzmaDecode.c / RangeDecoderReadByte + ..... + { + rd->ExtraBytes = 1; + return 0xFF; + } + + +4.00 2004-02-13 +------------------------- +- Original version of LZMA SDK + + + +HISTORY of the LZMA +------------------- + 2001-2008: Improvements to LZMA compressing/decompressing code, + keeping compatibility with original LZMA format + 1996-2001: Development of LZMA compression format + + Some milestones: + + 2001-08-30: LZMA compression was added to 7-Zip + 1999-01-02: First version of 7-Zip was released + + +End of document diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-sdk.txt b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-sdk.txt new file mode 100644 index 00000000..abe578ff --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/LzmaCompress/Sdk/DOC/lzma-sdk.txt @@ -0,0 +1,357 @@ +LZMA SDK 19.00 +-------------- + +LZMA SDK provides the documentation, samples, header files, +libraries, and tools you need to develop applications that +use 7z / LZMA / LZMA2 / XZ compression. + +LZMA is an improved version of famous LZ77 compression algorithm. +It was improved in way of maximum increasing of compression ratio, +keeping high decompression speed and low memory requirements for +decompressing. + +LZMA2 is a LZMA based compression method. LZMA2 provides better +multithreading support for compression than LZMA and some other improvements. + +7z is a file format for data compression and file archiving. +7z is a main file format for 7-Zip compression program (www.7-zip.org). +7z format supports different compression methods: LZMA, LZMA2 and others. +7z also supports AES-256 based encryption. + +XZ is a file format for data compression that uses LZMA2 compression. +XZ format provides additional features: SHA/CRC check, filters for +improved compression ratio, splitting to blocks and streams, + + + +LICENSE +------- + +LZMA SDK is written and placed in the public domain by Igor Pavlov. + +Some code in LZMA SDK is based on public domain code from another developers: + 1) PPMd var.H (2001): Dmitry Shkarin + 2) SHA-256: Wei Dai (Crypto++ library) + +Anyone is free to copy, modify, publish, use, compile, sell, or distribute the +original LZMA SDK code, either in source code form or as a compiled binary, for +any purpose, commercial or non-commercial, and by any means. + +LZMA SDK code is compatible with open source licenses, for example, you can +include it to GNU GPL or GNU LGPL code. + + +LZMA SDK Contents +----------------- + + Source code: + + - C / C++ / C# / Java - LZMA compression and decompression + - C / C++ - LZMA2 compression and decompression + - C / C++ - XZ compression and decompression + - C - 7z decompression + - C++ - 7z compression and decompression + - C - small SFXs for installers (7z decompression) + - C++ - SFXs and SFXs for installers (7z decompression) + + Precompiled binaries: + + - console programs for lzma / 7z / xz compression and decompression + - SFX modules for installers. + + +UNIX/Linux version +------------------ +To compile C++ version of file->file LZMA encoding, go to directory +CPP/7zip/Bundles/LzmaCon +and call make to recompile it: + make -f makefile.gcc clean all + +In some UNIX/Linux versions you must compile LZMA with static libraries. +To compile with static libraries, you can use +LIB = -lm -static + +Also you can use p7zip (port of 7-Zip for POSIX systems like Unix or Linux): + + http://p7zip.sourceforge.net/ + + +Files +----- + +DOC/7zC.txt - 7z ANSI-C Decoder description +DOC/7zFormat.txt - 7z Format description +DOC/installer.txt - information about 7-Zip for installers +DOC/lzma.txt - LZMA compression description +DOC/lzma-sdk.txt - LZMA SDK description (this file) +DOC/lzma-history.txt - history of LZMA SDK +DOC/lzma-specification.txt - Specification of LZMA +DOC/Methods.txt - Compression method IDs for .7z + +bin/installer/ - example script to create installer that uses SFX module, + +bin/7zdec.exe - simplified 7z archive decoder +bin/7zr.exe - 7-Zip console program (reduced version) +bin/x64/7zr.exe - 7-Zip console program (reduced version) (x64 version) +bin/lzma.exe - file->file LZMA encoder/decoder for Windows +bin/7zS2.sfx - small SFX module for installers (GUI version) +bin/7zS2con.sfx - small SFX module for installers (Console version) +bin/7zSD.sfx - SFX module for installers. + + +7zDec.exe +--------- +7zDec.exe is simplified 7z archive decoder. +It supports only LZMA, LZMA2, and PPMd methods. +7zDec decodes whole solid block from 7z archive to RAM. +The RAM consumption can be high. + + + + +Source code structure +--------------------- + + +Asm/ - asm files (optimized code for CRC calculation and Intel-AES encryption) + +C/ - C files (compression / decompression and other) + Util/ + 7z - 7z decoder program (decoding 7z files) + Lzma - LZMA program (file->file LZMA encoder/decoder). + LzmaLib - LZMA library (.DLL for Windows) + SfxSetup - small SFX module for installers + +CPP/ -- CPP files + + Common - common files for C++ projects + Windows - common files for Windows related code + + 7zip - files related to 7-Zip + + Archive - files related to archiving + + Common - common files for archive handling + 7z - 7z C++ Encoder/Decoder + + Bundles - Modules that are bundles of other modules (files) + + Alone7z - 7zr.exe: Standalone 7-Zip console program (reduced version) + Format7zExtractR - 7zxr.dll: Reduced version of 7z DLL: extracting from 7z/LZMA/BCJ/BCJ2. + Format7zR - 7zr.dll: Reduced version of 7z DLL: extracting/compressing to 7z/LZMA/BCJ/BCJ2 + LzmaCon - lzma.exe: LZMA compression/decompression + LzmaSpec - example code for LZMA Specification + SFXCon - 7zCon.sfx: Console 7z SFX module + SFXSetup - 7zS.sfx: 7z SFX module for installers + SFXWin - 7z.sfx: GUI 7z SFX module + + Common - common files for 7-Zip + + Compress - files for compression/decompression + + Crypto - files for encryption / decompression + + UI - User Interface files + + Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll + Common - Common UI files + Console - Code for console program (7z.exe) + Explorer - Some code from 7-Zip Shell extension + FileManager - Some GUI code from 7-Zip File Manager + GUI - Some GUI code from 7-Zip + + +CS/ - C# files + 7zip + Common - some common files for 7-Zip + Compress - files related to compression/decompression + LZ - files related to LZ (Lempel-Ziv) compression algorithm + LZMA - LZMA compression/decompression + LzmaAlone - file->file LZMA compression/decompression + RangeCoder - Range Coder (special code of compression/decompression) + +Java/ - Java files + SevenZip + Compression - files related to compression/decompression + LZ - files related to LZ (Lempel-Ziv) compression algorithm + LZMA - LZMA compression/decompression + RangeCoder - Range Coder (special code of compression/decompression) + + +Note: + Asm / C / C++ source code of LZMA SDK is part of 7-Zip's source code. + 7-Zip's source code can be downloaded from 7-Zip's SourceForge page: + + http://sourceforge.net/projects/sevenzip/ + + + +LZMA features +------------- + - Variable dictionary size (up to 1 GB) + - Estimated compressing speed: about 2 MB/s on 2 GHz CPU + - Estimated decompressing speed: + - 20-30 MB/s on modern 2 GHz cpu + - 1-2 MB/s on 200 MHz simple RISC cpu: (ARM, MIPS, PowerPC) + - Small memory requirements for decompressing (16 KB + DictionarySize) + - Small code size for decompressing: 5-8 KB + +LZMA decoder uses only integer operations and can be +implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). + +Some critical operations that affect the speed of LZMA decompression: + 1) 32*16 bit integer multiply + 2) Mispredicted branches (penalty mostly depends from pipeline length) + 3) 32-bit shift and arithmetic operations + +The speed of LZMA decompressing mostly depends from CPU speed. +Memory speed has no big meaning. But if your CPU has small data cache, +overall weight of memory speed will slightly increase. + + +How To Use +---------- + +Using LZMA encoder/decoder executable +-------------------------------------- + +Usage: LZMA inputFile outputFile [...] + + e: encode file + + d: decode file + + b: Benchmark. There are two tests: compressing and decompressing + with LZMA method. Benchmark shows rating in MIPS (million + instructions per second). Rating value is calculated from + measured speed and it is normalized with Intel's Core 2 results. + Also Benchmark checks possible hardware errors (RAM + errors in most cases). Benchmark uses these settings: + (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. + Also you can change the number of iterations. Example for 30 iterations: + LZMA b 30 + Default number of iterations is 10. + + + + + -a{N}: set compression mode 0 = fast, 1 = normal + default: 1 (normal) + + d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB) + The maximum value for dictionary size is 1 GB = 2^30 bytes. + Dictionary size is calculated as DictionarySize = 2^N bytes. + For decompressing file compressed by LZMA method with dictionary + size D = 2^N you need about D bytes of memory (RAM). + + -fb{N}: set number of fast bytes - [5, 273], default: 128 + Usually big number gives a little bit better compression ratio + and slower compression process. + + -lc{N}: set number of literal context bits - [0, 8], default: 3 + Sometimes lc=4 gives gain for big files. + + -lp{N}: set number of literal pos bits - [0, 4], default: 0 + lp switch is intended for periodical data when period is + equal 2^N. For example, for 32-bit (4 bytes) + periodical data you can use lp=2. Often it's better to set lc0, + if you change lp switch. + + -pb{N}: set number of pos bits - [0, 4], default: 2 + pb switch is intended for periodical data + when period is equal 2^N. + + -mf{MF_ID}: set Match Finder. Default: bt4. + Algorithms from hc* group doesn't provide good compression + ratio, but they often works pretty fast in combination with + fast mode (-a0). + + Memory requirements depend from dictionary size + (parameter "d" in table below). + + MF_ID Memory Description + + bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing. + bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing. + bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing. + hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing. + + -eos: write End Of Stream marker. By default LZMA doesn't write + eos marker, since LZMA decoder knows uncompressed size + stored in .lzma file header. + + -si: Read data from stdin (it will write End Of Stream marker). + -so: Write data to stdout + + +Examples: + +1) LZMA e file.bin file.lzma -d16 -lc0 + +compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) +and 0 literal context bits. -lc0 allows to reduce memory requirements +for decompression. + + +2) LZMA e file.bin file.lzma -lc0 -lp2 + +compresses file.bin to file.lzma with settings suitable +for 32-bit periodical data (for example, ARM or MIPS code). + +3) LZMA d file.lzma file.bin + +decompresses file.lzma to file.bin. + + +Compression ratio hints +----------------------- + +Recommendations +--------------- + +To increase the compression ratio for LZMA compressing it's desirable +to have aligned data (if it's possible) and also it's desirable to locate +data in such order, where code is grouped in one place and data is +grouped in other place (it's better than such mixing: code, data, code, +data, ...). + + +Filters +------- +You can increase the compression ratio for some data types, using +special filters before compressing. For example, it's possible to +increase the compression ratio on 5-10% for code for those CPU ISAs: +x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. + +You can find C source code of such filters in C/Bra*.* files + +You can check the compression ratio gain of these filters with such +7-Zip commands (example for ARM code): +No filter: + 7z a a1.7z a.bin -m0=lzma + +With filter for little-endian ARM code: + 7z a a2.7z a.bin -m0=arm -m1=lzma + +It works in such manner: +Compressing = Filter_encoding + LZMA_encoding +Decompressing = LZMA_decoding + Filter_decoding + +Compressing and decompressing speed of such filters is very high, +so it will not increase decompressing time too much. +Moreover, it reduces decompression time for LZMA_decoding, +since compression ratio with filtering is higher. + +These filters convert CALL (calling procedure) instructions +from relative offsets to absolute addresses, so such data becomes more +compressible. + +For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. + + + +--- + +http://www.7-zip.org +http://www.7-zip.org/sdk.html +http://www.7-zip.org/support.html diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile new file mode 100644 index 00000000..25875fe7 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile @@ -0,0 +1,69 @@ +## @file +# Windows makefile for C tools build. +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +HOST_ARCH = IA32 + +!INCLUDE Makefiles\ms.common + +LIBRARIES = Common +APPLICATIONS = \ + VfrCompile \ + BrotliCompress \ + EfiRom \ + GenCrc32 \ + GenFfs \ + GenFv \ + GenFw \ + GenSec \ + LzmaCompress \ + TianoCompress \ + VolInfo \ + DevicePath + +all: libs apps install + +libs: $(LIBRARIES) + @echo. + @echo ###################### + @echo # Build libraries + @echo ###################### + @if not exist $(LIB_PATH) mkdir $(LIB_PATH) + @if defined PYTHON_COMMAND $(PYTHON_COMMAND) Makefiles\NmakeSubdirs.py all $** + @if not defined PYTHON_COMMAND $(PYTHON_HOME)\python.exe Makefiles\NmakeSubdirs.py all $** + +apps: $(APPLICATIONS) + @echo. + @echo ###################### + @echo # Build executables + @echo ###################### + @if not exist $(BIN_PATH) mkdir $(BIN_PATH) + @if defined PYTHON_COMMAND $(PYTHON_COMMAND) Makefiles\NmakeSubdirs.py all $** + @if not defined PYTHON_COMMAND $(PYTHON_HOME)\python.exe Makefiles\NmakeSubdirs.py all $** + +install: $(LIB_PATH) $(BIN_PATH) + @echo. + @echo ###################### + @echo # Install to $(SYS_LIB_PATH) + @echo # Install to $(SYS_BIN_PATH) + @echo ###################### + @-xcopy $(LIB_PATH)\*.lib $(SYS_LIB_PATH) /I /D /E /F /Y > NUL 2>&1 + @-xcopy $(BIN_PATH)\*.exe $(SYS_BIN_PATH) /I /D /E /F /Y > NUL 2>&1 + @-xcopy $(BIN_PATH)\*.bat $(SYS_BIN_PATH) /I /D /E /F /Y > NUL 2>&1 + +.PHONY: clean +clean: + @if defined PYTHON_COMMAND $(PYTHON_COMMAND) Makefiles\NmakeSubdirs.py clean $(LIBRARIES) $(APPLICATIONS) + @if not defined PYTHON_COMMAND $(PYTHON_HOME)\python.exe Makefiles\NmakeSubdirs.py clean $(LIBRARIES) $(APPLICATIONS) + +.PHONY: cleanall +cleanall: + @if defined PYTHON_COMMAND $(PYTHON_COMMAND) Makefiles\NmakeSubdirs.py cleanall $(LIBRARIES) $(APPLICATIONS) + @if not defined PYTHON_COMMAND $(PYTHON_HOME)\python.exe Makefiles\NmakeSubdirs.py cleanall $(LIBRARIES) $(APPLICATIONS) +# Next line protects the libs pseudo target from inadvertent GNU make activity + if exist libs RMDIR /S /Q libs + +!INCLUDE Makefiles\ms.rule + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile.kmk new file mode 100644 index 00000000..23a6b8dc --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefile.kmk @@ -0,0 +1,54 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-Makefile for EFI C build programs. +# + +# +# Copyright (C) 2013-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# 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, in version 3 of the +# License. +# +# 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 . +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +SUB_DEPTH = ../../../../../../../.. +include $(KBUILD_PATH)/subheader.kmk + +include $(PATH_SUB_CURRENT)/Common/Makefile.kmk + +include $(PATH_SUB_CURRENT)/GenFv/Makefile.kmk +include $(PATH_SUB_CURRENT)/LzmaCompress/Makefile.kmk +include $(PATH_SUB_CURRENT)/GenFw/Makefile.kmk +include $(PATH_SUB_CURRENT)/TianoCompress/Makefile.kmk +include $(PATH_SUB_CURRENT)/EfiRom/Makefile.kmk +include $(PATH_SUB_CURRENT)/GenSec/Makefile.kmk +include $(PATH_SUB_CURRENT)/GenFfs/Makefile.kmk +include $(PATH_SUB_CURRENT)/GenCrc32/Makefile.kmk +include $(PATH_SUB_CURRENT)/VolInfo/Makefile.kmk +include $(PATH_SUB_CURRENT)/VfrCompile/Makefile.kmk + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/NmakeSubdirs.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/NmakeSubdirs.bat new file mode 100644 index 00000000..2ea3cf8a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/NmakeSubdirs.bat @@ -0,0 +1,40 @@ +@REM ## @file +@REM # Makefile +@REM # +@REM # Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+@REM # SPDX-License-Identifier: BSD-2-Clause-Patent +@REM # + +@echo off +setlocal +set TOOL_ERROR=0 +SET NMAKE_COMMAND=%1 +SHIFT + +:loop +if "%1"=="" goto success + +ECHO Building %1 +pushd %1 +nmake %NMAKE_COMMAND% +if ERRORLEVEL 1 ( + set /A TOOL_ERROR= %TOOL_ERROR% + %ERRORLEVEL% + goto error +) +ECHO %1 built successfully (%NMAKE_COMMAND%) +ECHO. +shift +popd +goto loop + +:success +goto exit + +:error +popd +set /A TOOL_ERROR=%TOOL_ERROR%+%ERRORLEVEL% +ECHO Error while making %1! +VERIFY OTHER 2>NUL + +:exit +exit /B %TOOL_ERROR% diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/NmakeSubdirs.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/NmakeSubdirs.py new file mode 100755 index 00000000..155eb223 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/NmakeSubdirs.py @@ -0,0 +1,166 @@ +# @file NmakeSubdirs.py +# This script support parallel build for nmake in windows environment. +# It supports Python2.x and Python3.x both. +# +# Copyright (c) 2018, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +# +# Import Modules +# + +from __future__ import print_function +import argparse +import threading +import time +import os +import subprocess +import multiprocessing +import copy +import sys +__prog__ = 'NmakeSubdirs' +__version__ = '%s Version %s' % (__prog__, '0.10 ') +__copyright__ = 'Copyright (c) 2018, Intel Corporation. All rights reserved.' +__description__ = 'Replace for NmakeSubdirs.bat in windows ,support parallel build for nmake.\n' + +cpu_count = multiprocessing.cpu_count() +output_lock = threading.Lock() +def RunCommand(WorkDir=None, *Args, **kwargs): + if WorkDir is None: + WorkDir = os.curdir + if "stderr" not in kwargs: + kwargs["stderr"] = subprocess.STDOUT + if "stdout" not in kwargs: + kwargs["stdout"] = subprocess.PIPE + p = subprocess.Popen(Args, cwd=WorkDir, stderr=kwargs["stderr"], stdout=kwargs["stdout"]) + stdout, stderr = p.communicate() + message = "" + if stdout is not None: + message = stdout.decode(errors='ignore') #for compatibility in python 2 and 3 + + if p.returncode != 0: + raise RuntimeError("Error while execute command \'{0}\' in direcotry {1}\n{2}".format(" ".join(Args), WorkDir, message)) + + output_lock.acquire(True) + print("execute command \"{0}\" in directory {1}".format(" ".join(Args), WorkDir)) + try: + print(message) + except: + pass + output_lock.release() + + return p.returncode, stdout + +class TaskUnit(object): + def __init__(self, func, args, kwargs): + self.func = func + self.args = args + self.kwargs = kwargs + + def __eq__(self, other): + return id(self).__eq__(id(other)) + + def run(self): + return self.func(*self.args, **self.kwargs) + + def __str__(self): + para = list(self.args) + para.extend("{0}={1}".format(k, v)for k, v in self.kwargs.items()) + + return "{0}({1})".format(self.func.__name__, ",".join(para)) + +class ThreadControl(object): + + def __init__(self, maxthread): + self._processNum = maxthread + self.pending = [] + self.running = [] + self.pendingLock = threading.Lock() + self.runningLock = threading.Lock() + self.error = False + self.errorLock = threading.Lock() + self.errorMsg = "errorMsg" + + def addTask(self, func, *args, **kwargs): + self.pending.append(TaskUnit(func, args, kwargs)) + + def waitComplete(self): + self._schedule.join() + + def startSchedule(self): + self._schedule = threading.Thread(target=self.Schedule) + self._schedule.start() + + def Schedule(self): + for i in range(self._processNum): + task = threading.Thread(target=self.startTask) + task.daemon = False + self.running.append(task) + + self.runningLock.acquire(True) + for thread in self.running: + thread.start() + self.runningLock.release() + + while len(self.running) > 0: + time.sleep(0.1) + if self.error: + print("subprocess not exit successfully") + print(self.errorMsg) + + def startTask(self): + while True: + if self.error: + break + self.pendingLock.acquire(True) + if len(self.pending) == 0: + self.pendingLock.release() + break + task = self.pending.pop(0) + self.pendingLock.release() + try: + task.run() + except RuntimeError as e: + if self.error: break + self.errorLock.acquire(True) + self.error = True + self.errorMsg = str(e) + time.sleep(0.1) + self.errorLock.release() + break + + self.runningLock.acquire(True) + self.running.remove(threading.currentThread()) + self.runningLock.release() + +def Run(): + curdir = os.path.abspath(os.curdir) + if len(args.subdirs) == 1: + args.jobs = 1 + if args.jobs == 1: + try: + for dir in args.subdirs: + RunCommand(os.path.join(curdir, dir), "nmake", args.target, stdout=sys.stdout, stderr=subprocess.STDOUT) + except RuntimeError: + exit(1) + else: + controller = ThreadControl(args.jobs) + for dir in args.subdirs: + controller.addTask(RunCommand, os.path.join(curdir, dir), "nmake", args.target) + controller.startSchedule() + controller.waitComplete() + if controller.error: + exit(1) + +if __name__ == "__main__": + parser = argparse.ArgumentParser(prog=__prog__, description=__description__ + __copyright__, conflict_handler='resolve') + + parser.add_argument("target", help="the target for nmake") + parser.add_argument("subdirs", nargs="+", help="the relative dir path of makefile") + parser.add_argument("--jobs", type=int, dest="jobs", default=cpu_count, help="thread number") + parser.add_argument('--version', action='version', version=__version__) + args = parser.parse_args() + Run() + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/app.makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/app.makefile new file mode 100644 index 00000000..37ed3c2f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/app.makefile @@ -0,0 +1,22 @@ +## @file +# Makefiles +# +# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +MAKEROOT ?= ../.. + +include $(MAKEROOT)/Makefiles/header.makefile + +APPLICATION = $(MAKEROOT)/bin/$(APPNAME) + +.PHONY:all +all: $(MAKEROOT)/bin $(APPLICATION) + +$(APPLICATION): $(OBJECTS) + $(LINKER) -o $(APPLICATION) $(BUILD_LFLAGS) $(OBJECTS) -L$(MAKEROOT)/libs $(LIBS) + +$(OBJECTS): $(MAKEROOT)/Include/Common/BuildVersion.h + +include $(MAKEROOT)/Makefiles/footer.makefile diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/footer.makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/footer.makefile new file mode 100644 index 00000000..4eeb1a06 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/footer.makefile @@ -0,0 +1,30 @@ +## @file +# Makefile +# +# Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +DEPFILES = $(OBJECTS:%.o=%.d) + +$(MAKEROOT)/libs-$(HOST_ARCH): + mkdir -p $(MAKEROOT)/libs-$(HOST_ARCH) + +.PHONY: install +install: $(MAKEROOT)/libs-$(HOST_ARCH) $(LIBRARY) + cp $(LIBRARY) $(MAKEROOT)/libs-$(HOST_ARCH) + +$(LIBRARY): $(OBJECTS) + $(BUILD_AR) crs $@ $^ + +%.o : %.c + $(BUILD_CC) -c $(BUILD_CPPFLAGS) $(BUILD_CFLAGS) $< -o $@ + +%.o : %.cpp + $(BUILD_CXX) -c $(BUILD_CPPFLAGS) $(BUILD_CXXFLAGS) $< -o $@ + +.PHONY: clean +clean: + @rm -f $(OBJECTS) $(LIBRARY) $(DEPFILES) + +-include $(DEPFILES) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/header.makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/header.makefile new file mode 100644 index 00000000..45c93595 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/header.makefile @@ -0,0 +1,137 @@ +## @file +# +# The makefile can be invoked with +# HOST_ARCH = x86_64 or x64 for EM64T build +# HOST_ARCH = ia32 or IA32 for IA32 build +# HOST_ARCH = Arm or ARM for ARM build +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent + +ifndef HOST_ARCH + # + # If HOST_ARCH is not defined, then we use 'uname -m' to attempt + # try to figure out the appropriate HOST_ARCH. + # + uname_m = $(shell uname -m) + $(info Attempting to detect HOST_ARCH from 'uname -m': $(uname_m)) + ifneq (,$(strip $(filter $(uname_m), x86_64 amd64))) + HOST_ARCH=X64 + endif + ifeq ($(patsubst i%86,IA32,$(uname_m)),IA32) + HOST_ARCH=IA32 + endif + ifneq (,$(findstring aarch64,$(uname_m))) + HOST_ARCH=AARCH64 + else ifneq (,$(findstring arm64,$(uname_m))) + HOST_ARCH=AARCH64 + else ifneq (,$(findstring arm,$(uname_m))) + HOST_ARCH=ARM + endif + ifneq (,$(findstring riscv64,$(uname_m))) + HOST_ARCH=RISCV64 + endif + ifndef HOST_ARCH + $(info Could not detected HOST_ARCH from uname results) + $(error HOST_ARCH is not defined!) + endif + $(info Detected HOST_ARCH of $(HOST_ARCH) using uname.) +endif + +CYGWIN:=$(findstring CYGWIN, $(shell uname -s)) +LINUX:=$(findstring Linux, $(shell uname -s)) +DARWIN:=$(findstring Darwin, $(shell uname -s)) +ifeq ($(CXX), llvm) +BUILD_CC ?= $(CLANG_BIN)clang +BUILD_CXX ?= $(CLANG_BIN)clang++ +BUILD_AS ?= $(CLANG_BIN)clang +BUILD_AR ?= $(CLANG_BIN)llvm-ar +BUILD_LD ?= $(CLANG_BIN)llvm-ld +else +BUILD_CC ?= gcc +BUILD_CXX ?= g++ +BUILD_AS ?= gcc +BUILD_AR ?= ar +BUILD_LD ?= ld +endif +LINKER ?= $(BUILD_CC) +ifeq ($(HOST_ARCH), IA32) +ARCH_INCLUDE = -I $(MAKEROOT)/Include/Ia32/ + +else ifeq ($(HOST_ARCH), X64) +ARCH_INCLUDE = -I $(MAKEROOT)/Include/X64/ + +else ifeq ($(HOST_ARCH), ARM) +ARCH_INCLUDE = -I $(MAKEROOT)/Include/Arm/ + +else ifeq ($(HOST_ARCH), AARCH64) +ARCH_INCLUDE = -I $(MAKEROOT)/Include/AArch64/ + +else ifeq ($(HOST_ARCH), RISCV64) +ARCH_INCLUDE = -I $(MAKEROOT)/Include/RiscV64/ + +else +$(error Bad HOST_ARCH) +endif + +INCLUDE = $(TOOL_INCLUDE) -I $(MAKEROOT) -I $(MAKEROOT)/Include/Common -I $(MAKEROOT)/Include/ -I $(MAKEROOT)/Include/IndustryStandard -I $(MAKEROOT)/Common/ -I .. -I . $(ARCH_INCLUDE) +BUILD_CPPFLAGS = $(INCLUDE) + +# keep EXTRA_OPTFLAGS last +BUILD_OPTFLAGS = -O2 $(EXTRA_OPTFLAGS) + +ifeq ($(DARWIN),Darwin) +# assume clang or clang compatible flags on OS X +BUILD_CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -Wall -Werror \ +-Wno-deprecated-declarations -Wno-self-assign -Wno-unused-result -nostdlib -g +else +ifeq ($(CXX), llvm) +BUILD_CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -fwrapv \ +-fno-delete-null-pointer-checks -Wall -Werror \ +-Wno-deprecated-declarations -Wno-self-assign \ +-Wno-unused-result -nostdlib -g +else +BUILD_CFLAGS = -MD -fshort-wchar -fno-strict-aliasing -fwrapv \ +-fno-delete-null-pointer-checks -Wall -Werror \ +-Wno-deprecated-declarations -Wno-stringop-truncation -Wno-restrict \ +-Wno-unused-result -nostdlib -g +endif +endif +ifeq ($(CXX), llvm) +BUILD_LFLAGS = +BUILD_CXXFLAGS = -Wno-deprecated-register -Wno-unused-result +else +BUILD_LFLAGS = +BUILD_CXXFLAGS = -Wno-unused-result +endif +ifeq ($(HOST_ARCH), IA32) +# +# Snow Leopard is a 32-bit and 64-bit environment. uname -m returns i386, but gcc defaults +# to x86_64. So make sure tools match uname -m. You can manual have a 64-bit kernal on Snow Leopard +# so only do this is uname -m returns i386. +# +ifeq ($(DARWIN),Darwin) + BUILD_CFLAGS += -arch i386 + BUILD_CPPFLAGS += -arch i386 + BUILD_LFLAGS += -arch i386 +endif +endif + +# keep BUILD_OPTFLAGS last +BUILD_CFLAGS += $(BUILD_OPTFLAGS) +BUILD_CXXFLAGS += $(BUILD_OPTFLAGS) + +# keep EXTRA_LDFLAGS last +BUILD_LFLAGS += $(EXTRA_LDFLAGS) + +.PHONY: all +.PHONY: install +.PHONY: clean + +all: + +$(MAKEROOT)/libs: + mkdir $(MAKEROOT)/libs + +$(MAKEROOT)/bin: + mkdir $(MAKEROOT)/bin diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/lib.makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/lib.makefile new file mode 100644 index 00000000..ea6bf247 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/lib.makefile @@ -0,0 +1,14 @@ +## @file +# Makefiles +# +# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +include $(MAKEROOT)/Makefiles/header.makefile + +LIBRARY = $(MAKEROOT)/libs/lib$(LIBNAME).a + +all: $(MAKEROOT)/libs $(LIBRARY) + +include $(MAKEROOT)/Makefiles/footer.makefile diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.app b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.app new file mode 100644 index 00000000..3aeb5974 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.app @@ -0,0 +1,28 @@ +## @file +# Makefile +# +# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +APPLICATION = $(BIN_PATH)\$(APPNAME).exe + +all: $(APPLICATION) + +$(APPLICATION) : $(OBJECTS) + -@if not exist $(BIN_PATH) mkdir $(BIN_PATH) + $(LD) /nologo /debug /OPT:REF /OPT:ICF=10 /incremental:no /nodefaultlib:libc.lib /out:$@ $(LIBS) $** + +$(OBJECTS) : $(SOURCE_PATH)\Include\Common\BuildVersion.h + +.PHONY:clean +.PHONY:cleanall + +clean: + del /f /q $(OBJECTS) *.pdb > nul + +cleanall: + del /f /q $(OBJECTS) $(APPLICATION) *.pdb $(BIN_PATH)\$(APPNAME).pdb > nul + +!INCLUDE $(SOURCE_PATH)\Makefiles\ms.rule + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.common b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.common new file mode 100644 index 00000000..695da7a3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.common @@ -0,0 +1,62 @@ +## @file +# Makefile +# +# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +!IFNDEF EDK_TOOLS_PATH +!ERROR "Please set your EDK_TOOLS_PATH!" +!ENDIF + +!IFNDEF BASE_TOOLS_PATH +!ERROR "BASE_TOOLS_PATH is not set! Please run build_tools.bat at first!" +!ENDIF + +!IFNDEF HOST_ARCH +HOST_ARCH = IA32 +!ENDIF + +MAKE = nmake -nologo + +# DOS del command doesn't support ":\\" in the file path, such as j:\\BaseTools. Convert ":\\" to ":\" +BASE_TOOLS_PATH = $(BASE_TOOLS_PATH::\\=:\) +EDK_TOOLS_PATH = $(EDK_TOOLS_PATH::\\=:\) + +SOURCE_PATH = $(BASE_TOOLS_PATH)\Source\C +BIN_PATH = $(BASE_TOOLS_PATH)\Bin +LIB_PATH = $(BASE_TOOLS_PATH)\Lib + +SYS_BIN_PATH=$(EDK_TOOLS_PATH)\Bin +SYS_LIB_PATH=$(EDK_TOOLS_PATH)\Lib + +!IF "$(HOST_ARCH)"=="IA32" +ARCH_INCLUDE = $(SOURCE_PATH)\Include\Ia32 +BIN_PATH = $(BASE_TOOLS_PATH)\Bin\Win32 +LIB_PATH = $(BASE_TOOLS_PATH)\Lib\Win32 +SYS_BIN_PATH = $(EDK_TOOLS_PATH)\Bin\Win32 +SYS_LIB_PATH = $(EDK_TOOLS_PATH)\Lib\Win32 + +!ELSEIF "$(HOST_ARCH)"=="X64" +ARCH_INCLUDE = $(SOURCE_PATH)\Include\X64 +BIN_PATH = $(BASE_TOOLS_PATH)\Bin\Win64 +LIB_PATH = $(BASE_TOOLS_PATH)\Lib\Win64 +SYS_BIN_PATH = $(EDK_TOOLS_PATH)\Bin\Win64 +SYS_LIB_PATH = $(EDK_TOOLS_PATH)\Lib\Win64 + +!ELSE +!ERROR "Bad HOST_ARCH" +!ENDIF + +CC = cl.exe +CXX = cl.exe +AS = ml.exe +AR = lib.exe +LD = link.exe +LINKER = $(LD) + +INC = $(INC) -I . -I $(SOURCE_PATH)\Include -I $(ARCH_INCLUDE) -I $(SOURCE_PATH)\Common + +CFLAGS = $(CFLAGS) /nologo /Zi /c /O2 /MT /W4 /WX /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE +CPPFLAGS = $(CPPFLAGS) /EHsc /nologo /Zi /c /O2 /MT /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.lib b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.lib new file mode 100644 index 00000000..6b61fa47 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.lib @@ -0,0 +1,25 @@ +## @file +# +# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent + +!INCLUDE ..\Makefiles\ms.common + +LIBRARY = $(LIB_PATH)\$(LIBNAME).lib + +all: $(LIBRARY) + +$(LIBRARY) : $(OBJECTS) + -@if not exist $(LIB_PATH) mkdir $(LIB_PATH) + $(AR) /nologo /out:$@ $** + +.PHONY:clean +clean: + del /f /q $(OBJECTS) *.pdb > nul + +.PHONY:cleanall +cleanall: + del /f /q $(OBJECTS) $(LIBRARY) *.pdb > nul + +!INCLUDE ..\Makefiles\ms.rule + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.rule b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.rule new file mode 100644 index 00000000..ba34eabd --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/Makefiles/ms.rule @@ -0,0 +1,20 @@ +## @file +# Makefile +# +# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +#DEPFILES = $(OBJECTS:%.o=%.d) + +.c.obj : + $(CC) -c $(CFLAGS) $(INC) $< -Fo$@ + +.S.obj : + $(AS) -c $(ASFLAGS) $< -Fo$@ + +.cpp.obj : + $(CXX) -c $(CPPFLAGS) $(INC) $< -Fo$@ + +#-include $(DEPFILES) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/PyEfiCompressor/EfiCompressor.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/PyEfiCompressor/EfiCompressor.c new file mode 100644 index 00000000..4c9ce442 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/PyEfiCompressor/EfiCompressor.c @@ -0,0 +1,206 @@ +/** @file +Efi Compressor + +Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +/* + UefiDecompress(data_buffer, size, original_size) +*/ +STATIC +PyObject* +UefiDecompress( + PyObject *Self, + PyObject *Args + ) +{ + PyObject *SrcData; + UINT32 SrcDataSize; + UINT32 DstDataSize; + UINTN Status; + UINT8 *SrcBuf; + UINT8 *DstBuf; + UINT8 *TmpBuf; + Py_ssize_t SegNum; + Py_ssize_t Index; + + Status = PyArg_ParseTuple( + Args, + "Oi", + &SrcData, + &SrcDataSize + ); + if (Status == 0) { + return NULL; + } + + if (SrcData->ob_type->tp_as_buffer == NULL + || SrcData->ob_type->tp_as_buffer->bf_getreadbuffer == NULL + || SrcData->ob_type->tp_as_buffer->bf_getsegcount == NULL) { + PyErr_SetString(PyExc_Exception, "First argument is not a buffer\n"); + return NULL; + } + + // Because some Python objects which support "buffer" protocol have more than one + // memory segment, we have to copy them into a contiguous memory. + SrcBuf = PyMem_Malloc(SrcDataSize); + if (SrcBuf == NULL) { + PyErr_SetString(PyExc_Exception, "Not enough memory\n"); + goto ERROR; + } + + SegNum = SrcData->ob_type->tp_as_buffer->bf_getsegcount((PyObject *)SrcData, NULL); + TmpBuf = SrcBuf; + for (Index = 0; Index < SegNum; ++Index) { + VOID *BufSeg; + Py_ssize_t Len; + + Len = SrcData->ob_type->tp_as_buffer->bf_getreadbuffer((PyObject *)SrcData, Index, &BufSeg); + if (Len < 0) { + PyErr_SetString(PyExc_Exception, "Buffer segment is not available\n"); + goto ERROR; + } + memcpy(TmpBuf, BufSeg, Len); + TmpBuf += Len; + } + + Status = Extract((VOID *)SrcBuf, SrcDataSize, (VOID **)&DstBuf, &DstDataSize, 1); + if (Status != EFI_SUCCESS) { + PyErr_SetString(PyExc_Exception, "Failed to decompress\n"); + goto ERROR; + } + + return PyBuffer_FromMemory(DstBuf, (Py_ssize_t)DstDataSize); + +ERROR: + if (SrcBuf != NULL) { + free(SrcBuf); + } + + if (DstBuf != NULL) { + free(DstBuf); + } + return NULL; +} + + +STATIC +PyObject* +FrameworkDecompress( + PyObject *Self, + PyObject *Args + ) +{ + PyObject *SrcData; + UINT32 SrcDataSize; + UINT32 DstDataSize; + UINTN Status; + UINT8 *SrcBuf; + UINT8 *DstBuf; + UINT8 *TmpBuf; + Py_ssize_t SegNum; + Py_ssize_t Index; + + Status = PyArg_ParseTuple( + Args, + "Oi", + &SrcData, + &SrcDataSize + ); + if (Status == 0) { + return NULL; + } + + if (SrcData->ob_type->tp_as_buffer == NULL + || SrcData->ob_type->tp_as_buffer->bf_getreadbuffer == NULL + || SrcData->ob_type->tp_as_buffer->bf_getsegcount == NULL) { + PyErr_SetString(PyExc_Exception, "First argument is not a buffer\n"); + return NULL; + } + + // Because some Python objects which support "buffer" protocol have more than one + // memory segment, we have to copy them into a contiguous memory. + SrcBuf = PyMem_Malloc(SrcDataSize); + if (SrcBuf == NULL) { + PyErr_SetString(PyExc_Exception, "Not enough memory\n"); + goto ERROR; + } + + SegNum = SrcData->ob_type->tp_as_buffer->bf_getsegcount((PyObject *)SrcData, NULL); + TmpBuf = SrcBuf; + for (Index = 0; Index < SegNum; ++Index) { + VOID *BufSeg; + Py_ssize_t Len; + + Len = SrcData->ob_type->tp_as_buffer->bf_getreadbuffer((PyObject *)SrcData, Index, &BufSeg); + if (Len < 0) { + PyErr_SetString(PyExc_Exception, "Buffer segment is not available\n"); + goto ERROR; + } + memcpy(TmpBuf, BufSeg, Len); + TmpBuf += Len; + } + + Status = Extract((VOID *)SrcBuf, SrcDataSize, (VOID **)&DstBuf, &DstDataSize, 2); + if (Status != EFI_SUCCESS) { + PyErr_SetString(PyExc_Exception, "Failed to decompress\n"); + goto ERROR; + } + + return PyString_FromStringAndSize((CONST INT8*)DstBuf, (Py_ssize_t)DstDataSize); + +ERROR: + if (SrcBuf != NULL) { + free(SrcBuf); + } + + if (DstBuf != NULL) { + free(DstBuf); + } + return NULL; +} + + +STATIC +PyObject* +UefiCompress( + PyObject *Self, + PyObject *Args + ) +{ + return NULL; +} + + +STATIC +PyObject* +FrameworkCompress( + PyObject *Self, + PyObject *Args + ) +{ + return NULL; +} + +STATIC INT8 DecompressDocs[] = "Decompress(): Decompress data using UEFI standard algorithm\n"; +STATIC INT8 CompressDocs[] = "Compress(): Compress data using UEFI standard algorithm\n"; + +STATIC PyMethodDef EfiCompressor_Funcs[] = { + {"UefiDecompress", (PyCFunction)UefiDecompress, METH_VARARGS, DecompressDocs}, + {"UefiCompress", (PyCFunction)UefiCompress, METH_VARARGS, DecompressDocs}, + {"FrameworkDecompress", (PyCFunction)FrameworkDecompress, METH_VARARGS, DecompressDocs}, + {"FrameworkCompress", (PyCFunction)FrameworkCompress, METH_VARARGS, DecompressDocs}, + {NULL, NULL, 0, NULL} +}; + +PyMODINIT_FUNC +initEfiCompressor(VOID) { + Py_InitModule3("EfiCompressor", EfiCompressor_Funcs, "EFI Compression Algorithm Extension Module"); +} + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/PyEfiCompressor/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/PyEfiCompressor/Makefile new file mode 100644 index 00000000..46322b8d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/PyEfiCompressor/Makefile @@ -0,0 +1,18 @@ +## @file +# Makefile +# +# Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent + +!INCLUDE ..\Makefiles\ms.common + +APPNAME = GenSec + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = GenSec.obj + +#CFLAGS = $(CFLAGS) /nodefaultlib:libc.lib + +!INCLUDE ..\Makefiles\ms.app + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/PyEfiCompressor/setup.py b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/PyEfiCompressor/setup.py new file mode 100755 index 00000000..7ccc6d8c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/PyEfiCompressor/setup.py @@ -0,0 +1,37 @@ +## @file +# package and install PyEfiCompressor extension +# +# Copyright (c) 2008, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +## +# Import Modules +# +from distutils.core import setup, Extension +import os + +if 'BASE_TOOLS_PATH' not in os.environ: + raise "Please define BASE_TOOLS_PATH to the root of base tools tree" + +BaseToolsDir = os.environ['BASE_TOOLS_PATH'] +setup( + name="EfiCompressor", + version="0.01", + ext_modules=[ + Extension( + 'EfiCompressor', + sources=[ + os.path.join(BaseToolsDir, 'Source', 'C', 'Common', 'Decompress.c'), + 'EfiCompressor.c' + ], + include_dirs=[ + os.path.join(BaseToolsDir, 'Source', 'C', 'Include'), + os.path.join(BaseToolsDir, 'Source', 'C', 'Include', 'Ia32'), + os.path.join(BaseToolsDir, 'Source', 'C', 'Common') + ], + ) + ], + ) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/GNUmakefile new file mode 100644 index 00000000..6e0e25c1 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/GNUmakefile @@ -0,0 +1,15 @@ +## @file +# GNU/Linux makefile for 'TianoCompress' module build. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +MAKEROOT ?= .. + +APPNAME = TianoCompress + +LIBS = -lCommon + +OBJECTS = TianoCompress.o + +include $(MAKEROOT)/Makefiles/app.makefile diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/Makefile new file mode 100644 index 00000000..46a250e7 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/Makefile @@ -0,0 +1,16 @@ +## @file +# Windows makefile for 'TianoCompress' module build. +# +# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +!INCLUDE ..\Makefiles\ms.common + +APPNAME = TianoCompress + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = TianoCompress.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/Makefile.kmk new file mode 100644 index 00000000..77e3e9d2 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/Makefile.kmk @@ -0,0 +1,45 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-makefile for the EFI TianoCompress build tool. +# + +# +# Copyright (C) 2013-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# 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, in version 3 of the +# License. +# +# 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 . +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +SUB_DEPTH = ../../../../../../../../.. +include $(KBUILD_PATH)/subheader.kmk + +BLDPROGS += TianoCompress +TianoCompress_TEMPLATE = VBoxEfiBldProg +TianoCompress_SOURCES = TianoCompress.c + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/TianoCompress.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/TianoCompress.c new file mode 100644 index 00000000..8288b97d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/TianoCompress.c @@ -0,0 +1,2795 @@ +/** @file +Compression routine. The compression algorithm is a mixture of LZ77 and Huffman +coding. LZ77 transforms the source data into a sequence of Original Characters +and Pointers to repeated strings. +This sequence is further divided into Blocks and Huffman codings are applied to +each Block. + +Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Compress.h" +#include "Decompress.h" +#include "TianoCompress.h" +#include "EfiUtilityMsgs.h" +#include "ParseInf.h" +#include +#include "assert.h" + +// +// Macro Definitions +// +static BOOLEAN VerboseMode = FALSE; +static BOOLEAN QuietMode = FALSE; +#undef UINT8_MAX +#define UINT8_MAX 0xff +#define UINT8_BIT 8 +#define THRESHOLD 3 +#define INIT_CRC 0 +#define WNDBIT 19 +#define WNDSIZ (1U << WNDBIT) +#define MAXMATCH 256 +#define BLKSIZ (1U << 14) // 16 * 1024U +#define PERC_FLAG 0x80000000U +#define CODE_BIT 16 +#define NIL 0 +#define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX) +#define HASH(p, c) ((p) + ((c) << (WNDBIT - 9)) + WNDSIZ * 2) +#define CRCPOLY 0xA001 +#define UPDATE_CRC(c) mCrc = mCrcTable[(mCrc ^ (c)) & 0xFF] ^ (mCrc >> UINT8_BIT) + +// +// C: the Char&Len Set; P: the Position Set; T: the exTra Set +// +//#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD) +#define CBIT 9 +#define NP (WNDBIT + 1) +#define PBIT 5 +//#define NT (CODE_BIT + 3) +//#define TBIT 5 +//#if NT > NP +//#define NPT NT +//#else +//#define NPT NP +//#endif + +// +// Global Variables +// +STATIC BOOLEAN ENCODE = FALSE; +STATIC BOOLEAN DECODE = FALSE; +STATIC BOOLEAN UEFIMODE = FALSE; +STATIC UINT8 *mSrc, *mDst, *mSrcUpperLimit, *mDstUpperLimit; +STATIC UINT8 *mLevel, *mText, *mChildCount, *mBuf, mCLen[NC], mPTLen[NPT], *mLen; +STATIC INT16 mHeap[NC + 1]; +STATIC INT32 mRemainder, mMatchLen, mBitCount, mHeapSize, mN; +STATIC UINT32 mBufSiz = 0, mOutputPos, mOutputMask, mSubBitBuf, mCrc; +STATIC UINT32 mCompSize, mOrigSize; + +STATIC UINT16 *mFreq, *mSortPtr, mLenCnt[17], mLeft[2 * NC - 1], mRight[2 * NC - 1], mCrcTable[UINT8_MAX + 1], + mCFreq[2 * NC - 1], mCCode[NC], mPFreq[2 * NP - 1], mPTCode[NPT], mTFreq[2 * NT - 1]; + +STATIC NODE mPos, mMatchPos, mAvail, *mPosition, *mParent, *mPrev, *mNext = NULL; + +static UINT64 DebugLevel; +static BOOLEAN DebugMode; +// +// functions +// +EFI_STATUS +TianoCompress ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ) +/*++ + +Routine Description: + + The internal implementation of [Efi/Tiano]Compress(). + +Arguments: + + SrcBuffer - The buffer storing the source data + SrcSize - The size of source data + DstBuffer - The buffer to store the compressed data + + Version - The version of de/compression algorithm. + Version 1 for EFI 1.1 de/compression algorithm. + Version 2 for Tiano de/compression algorithm. + +Returns: + + EFI_BUFFER_TOO_SMALL - The DstBuffer is too small. In this case, + DstSize contains the size needed. + EFI_SUCCESS - Compression is successful. + EFI_OUT_OF_RESOURCES - No resource to complete function. + EFI_INVALID_PARAMETER - Parameter supplied is wrong. + +--*/ +{ + EFI_STATUS Status; + + // + // Initializations + // + mBufSiz = 0; + mBuf = NULL; + mText = NULL; + mLevel = NULL; + mChildCount = NULL; + mPosition = NULL; + mParent = NULL; + mPrev = NULL; + mNext = NULL; + + + mSrc = SrcBuffer; + mSrcUpperLimit = mSrc + SrcSize; + mDst = DstBuffer; + mDstUpperLimit = mDst +*DstSize; + + PutDword (0L); + PutDword (0L); + + MakeCrcTable (); + + mOrigSize = mCompSize = 0; + mCrc = INIT_CRC; + + // + // Compress it + // + Status = Encode (); + if (EFI_ERROR (Status)) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Null terminate the compressed data + // + + if (mDst < mDstUpperLimit) { + *mDst++ = 0; + } + + // + // Fill in compressed size and original size + // + mDst = DstBuffer; + + PutDword (mCompSize + 1); + PutDword (mOrigSize); + // + // Return + // + + if (mCompSize + 1 + 8 > *DstSize) { + *DstSize = mCompSize + 1 + 8; + return EFI_BUFFER_TOO_SMALL; + } else { + *DstSize = mCompSize + 1 + 8; + return EFI_SUCCESS; + } +} + +STATIC +VOID +PutDword ( + IN UINT32 Data + ) +/*++ + +Routine Description: + + Put a dword to output stream + +Arguments: + + Data - the dword to put + +Returns: (VOID) + +--*/ +{ + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff); + } + + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff); + } + + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff); + } + + if (mDst < mDstUpperLimit) { + *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff); + } +} + +STATIC +EFI_STATUS +AllocateMemory ( + VOID + ) +/*++ + +Routine Description: + + Allocate memory spaces for data structures used in compression process + +Arguments: + VOID + +Returns: + + EFI_SUCCESS - Memory is allocated successfully + EFI_OUT_OF_RESOURCES - Allocation fails + +--*/ +{ + UINT32 Index; + + mText = malloc (WNDSIZ * 2 + MAXMATCH); + if (mText == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return EFI_OUT_OF_RESOURCES; + } + for (Index = 0; Index < WNDSIZ * 2 + MAXMATCH; Index++) { + mText[Index] = 0; + } + + mLevel = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel)); + mChildCount = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount)); + mPosition = malloc ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition)); + mParent = malloc (WNDSIZ * 2 * sizeof (*mParent)); + mPrev = malloc (WNDSIZ * 2 * sizeof (*mPrev)); + mNext = malloc ((MAX_HASH_VAL + 1) * sizeof (*mNext)); + if (mLevel == NULL || mChildCount == NULL || mPosition == NULL || + mParent == NULL || mPrev == NULL || mNext == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return EFI_OUT_OF_RESOURCES; + } + + mBufSiz = BLKSIZ; + mBuf = malloc (mBufSiz); + while (mBuf == NULL) { + mBufSiz = (mBufSiz / 10U) * 9U; + if (mBufSiz < 4 * 1024U) { + return EFI_OUT_OF_RESOURCES; + } + + mBuf = malloc (mBufSiz); + } + + mBuf[0] = 0; + + return EFI_SUCCESS; +} + +VOID +FreeMemory ( + VOID + ) +/*++ + +Routine Description: + + Called when compression is completed to free memory previously allocated. + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + if (mText != NULL) { + free (mText); + } + + if (mLevel != NULL) { + free (mLevel); + } + + if (mChildCount != NULL) { + free (mChildCount); + } + + if (mPosition != NULL) { + free (mPosition); + } + + if (mParent != NULL) { + free (mParent); + } + + if (mPrev != NULL) { + free (mPrev); + } + + if (mNext != NULL) { + free (mNext); + } + + if (mBuf != NULL) { + free (mBuf); + } + + return ; +} + +STATIC +VOID +InitSlide ( + VOID + ) +/*++ + +Routine Description: + + Initialize String Info Log data structures + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + NODE Index; + + for (Index = WNDSIZ; Index <= WNDSIZ + UINT8_MAX; Index++) { + mLevel[Index] = 1; + mPosition[Index] = NIL; // sentinel + } + + for (Index = WNDSIZ; Index < WNDSIZ * 2; Index++) { + mParent[Index] = NIL; + } + + mAvail = 1; + for (Index = 1; Index < WNDSIZ - 1; Index++) { + mNext[Index] = (NODE) (Index + 1); + } + + mNext[WNDSIZ - 1] = NIL; + for (Index = WNDSIZ * 2; Index <= MAX_HASH_VAL; Index++) { + mNext[Index] = NIL; + } +} + +STATIC +NODE +Child ( + IN NODE NodeQ, + IN UINT8 CharC + ) +/*++ + +Routine Description: + + Find child node given the parent node and the edge character + +Arguments: + + NodeQ - the parent node + CharC - the edge character + +Returns: + + The child node (NIL if not found) + +--*/ +{ + NODE NodeR; + + NodeR = mNext[HASH (NodeQ, CharC)]; + // + // sentinel + // + mParent[NIL] = NodeQ; + while (mParent[NodeR] != NodeQ) { + NodeR = mNext[NodeR]; + } + + return NodeR; +} + +STATIC +VOID +MakeChild ( + IN NODE Parent, + IN UINT8 CharC, + IN NODE Child + ) +/*++ + +Routine Description: + + Create a new child for a given parent node. + +Arguments: + + Parent - the parent node + CharC - the edge character + Child - the child node + +Returns: (VOID) + +--*/ +{ + NODE Node1; + NODE Node2; + + Node1 = (NODE) HASH (Parent, CharC); + Node2 = mNext[Node1]; + mNext[Node1] = Child; + mNext[Child] = Node2; + mPrev[Node2] = Child; + mPrev[Child] = Node1; + mParent[Child] = Parent; + mChildCount[Parent]++; +} + +STATIC +VOID +Split ( + NODE Old + ) +/*++ + +Routine Description: + + Split a node. + +Arguments: + + Old - the node to split + +Returns: (VOID) + +--*/ +{ + NODE New; + NODE TempNode; + + New = mAvail; + mAvail = mNext[New]; + mChildCount[New] = 0; + TempNode = mPrev[Old]; + mPrev[New] = TempNode; + mNext[TempNode] = New; + TempNode = mNext[Old]; + mNext[New] = TempNode; + mPrev[TempNode] = New; + mParent[New] = mParent[Old]; + mLevel[New] = (UINT8) mMatchLen; + mPosition[New] = mPos; + MakeChild (New, mText[mMatchPos + mMatchLen], Old); + MakeChild (New, mText[mPos + mMatchLen], mPos); +} + +STATIC +VOID +InsertNode ( + VOID + ) +/*++ + +Routine Description: + + Insert string info for current position into the String Info Log + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + NODE NodeQ; + NODE NodeR; + NODE Index2; + NODE NodeT; + UINT8 CharC; + UINT8 *t1; + UINT8 *t2; + + if (mMatchLen >= 4) { + // + // We have just got a long match, the target tree + // can be located by MatchPos + 1. Traverse the tree + // from bottom up to get to a proper starting point. + // The usage of PERC_FLAG ensures proper node deletion + // in DeleteNode() later. + // + mMatchLen--; + NodeR = (NODE) ((mMatchPos + 1) | WNDSIZ); + NodeQ = mParent[NodeR]; + while (NodeQ == NIL) { + NodeR = mNext[NodeR]; + NodeQ = mParent[NodeR]; + } + + while (mLevel[NodeQ] >= mMatchLen) { + NodeR = NodeQ; + NodeQ = mParent[NodeQ]; + } + + NodeT = NodeQ; + while (mPosition[NodeT] < 0) { + mPosition[NodeT] = mPos; + NodeT = mParent[NodeT]; + } + + if (NodeT < WNDSIZ) { + mPosition[NodeT] = (NODE) (mPos | (UINT32) PERC_FLAG); + } + } else { + // + // Locate the target tree + // + NodeQ = (NODE) (mText[mPos] + WNDSIZ); + CharC = mText[mPos + 1]; + NodeR = Child (NodeQ, CharC); + if (NodeR == NIL) { + MakeChild (NodeQ, CharC, mPos); + mMatchLen = 1; + return ; + } + + mMatchLen = 2; + } + // + // Traverse down the tree to find a match. + // Update Position value along the route. + // Node split or creation is involved. + // + for (;;) { + if (NodeR >= WNDSIZ) { + Index2 = MAXMATCH; + mMatchPos = NodeR; + } else { + Index2 = mLevel[NodeR]; + mMatchPos = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); + } + + if (mMatchPos >= mPos) { + mMatchPos -= WNDSIZ; + } + + t1 = &mText[mPos + mMatchLen]; + t2 = &mText[mMatchPos + mMatchLen]; + while (mMatchLen < Index2) { + if (*t1 != *t2) { + Split (NodeR); + return ; + } + + mMatchLen++; + t1++; + t2++; + } + + if (mMatchLen >= MAXMATCH) { + break; + } + + mPosition[NodeR] = mPos; + NodeQ = NodeR; + NodeR = Child (NodeQ, *t1); + if (NodeR == NIL) { + MakeChild (NodeQ, *t1, mPos); + return ; + } + + mMatchLen++; + } + + NodeT = mPrev[NodeR]; + mPrev[mPos] = NodeT; + mNext[NodeT] = mPos; + NodeT = mNext[NodeR]; + mNext[mPos] = NodeT; + mPrev[NodeT] = mPos; + mParent[mPos] = NodeQ; + mParent[NodeR] = NIL; + + // + // Special usage of 'next' + // + mNext[NodeR] = mPos; + +} + +STATIC +VOID +DeleteNode ( + VOID + ) +/*++ + +Routine Description: + + Delete outdated string info. (The Usage of PERC_FLAG + ensures a clean deletion) + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + NODE NodeQ; + NODE NodeR; + NODE NodeS; + NODE NodeT; + NODE NodeU; + + if (mParent[mPos] == NIL) { + return ; + } + + NodeR = mPrev[mPos]; + NodeS = mNext[mPos]; + mNext[NodeR] = NodeS; + mPrev[NodeS] = NodeR; + NodeR = mParent[mPos]; + mParent[mPos] = NIL; + if (NodeR >= WNDSIZ) { + return ; + } + + mChildCount[NodeR]--; + if (mChildCount[NodeR] > 1) { + return ; + } + + NodeT = (NODE) (mPosition[NodeR] & (UINT32)~PERC_FLAG); + if (NodeT >= mPos) { + NodeT -= WNDSIZ; + } + + NodeS = NodeT; + NodeQ = mParent[NodeR]; + NodeU = mPosition[NodeQ]; + while (NodeU & (UINT32) PERC_FLAG) { + NodeU &= (UINT32)~PERC_FLAG; + if (NodeU >= mPos) { + NodeU -= WNDSIZ; + } + + if (NodeU > NodeS) { + NodeS = NodeU; + } + + mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ); + NodeQ = mParent[NodeQ]; + NodeU = mPosition[NodeQ]; + } + + if (NodeQ < WNDSIZ) { + if (NodeU >= mPos) { + NodeU -= WNDSIZ; + } + + if (NodeU > NodeS) { + NodeS = NodeU; + } + + mPosition[NodeQ] = (NODE) (NodeS | WNDSIZ | (UINT32) PERC_FLAG); + } + + NodeS = Child (NodeR, mText[NodeT + mLevel[NodeR]]); + NodeT = mPrev[NodeS]; + NodeU = mNext[NodeS]; + mNext[NodeT] = NodeU; + mPrev[NodeU] = NodeT; + NodeT = mPrev[NodeR]; + mNext[NodeT] = NodeS; + mPrev[NodeS] = NodeT; + NodeT = mNext[NodeR]; + mPrev[NodeT] = NodeS; + mNext[NodeS] = NodeT; + mParent[NodeS] = mParent[NodeR]; + mParent[NodeR] = NIL; + mNext[NodeR] = mAvail; + mAvail = NodeR; +} + +STATIC +VOID +GetNextMatch ( + VOID + ) +/*++ + +Routine Description: + + Advance the current position (read in new data if needed). + Delete outdated string info. Find a match string for current position. + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + INT32 Number; + + mRemainder--; + mPos++; + if (mPos == WNDSIZ * 2) { + memmove (&mText[0], &mText[WNDSIZ], WNDSIZ + MAXMATCH); + Number = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ); + mRemainder += Number; + mPos = WNDSIZ; + } + + DeleteNode (); + InsertNode (); +} + +STATIC +EFI_STATUS +Encode ( + VOID + ) +/*++ + +Routine Description: + + The main controlling routine for compression process. + +Arguments: (VOID) + +Returns: + + EFI_SUCCESS - The compression is successful + EFI_OUT_0F_RESOURCES - Not enough memory for compression process + +--*/ +{ + EFI_STATUS Status; + INT32 LastMatchLen; + NODE LastMatchPos; + + Status = AllocateMemory (); + if (EFI_ERROR (Status)) { + FreeMemory (); + return Status; + } + + InitSlide (); + + HufEncodeStart (); + + mRemainder = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH); + + mMatchLen = 0; + mPos = WNDSIZ; + InsertNode (); + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + + while (mRemainder > 0) { + LastMatchLen = mMatchLen; + LastMatchPos = mMatchPos; + GetNextMatch (); + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + + if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) { + // + // Not enough benefits are gained by outputting a pointer, + // so just output the original character + // + Output (mText[mPos - 1], 0); + + } else { + + if (LastMatchLen == THRESHOLD) { + if (((mPos - LastMatchPos - 2) & (WNDSIZ - 1)) > (1U << 11)) { + Output (mText[mPos - 1], 0); + continue; + } + } + // + // Outputting a pointer is beneficial enough, do it. + // + Output ( + LastMatchLen + (UINT8_MAX + 1 - THRESHOLD), + (mPos - LastMatchPos - 2) & (WNDSIZ - 1) + ); + LastMatchLen--; + while (LastMatchLen > 0) { + GetNextMatch (); + LastMatchLen--; + } + + if (mMatchLen > mRemainder) { + mMatchLen = mRemainder; + } + } + } + + HufEncodeEnd (); + FreeMemory (); + return EFI_SUCCESS; +} + +STATIC +VOID +CountTFreq ( + VOID + ) +/*++ + +Routine Description: + + Count the frequencies for the Extra Set + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + INT32 Index; + INT32 Index3; + INT32 Number; + INT32 Count; + + for (Index = 0; Index < NT; Index++) { + mTFreq[Index] = 0; + } + + Number = NC; + while (Number > 0 && mCLen[Number - 1] == 0) { + Number--; + } + + Index = 0; + while (Index < Number) { + Index3 = mCLen[Index++]; + if (Index3 == 0) { + Count = 1; + while (Index < Number && mCLen[Index] == 0) { + Index++; + Count++; + } + + if (Count <= 2) { + mTFreq[0] = (UINT16) (mTFreq[0] + Count); + } else if (Count <= 18) { + mTFreq[1]++; + } else if (Count == 19) { + mTFreq[0]++; + mTFreq[1]++; + } else { + mTFreq[2]++; + } + } else { + mTFreq[Index3 + 2]++; + } + } +} + +STATIC +VOID +WritePTLen ( + IN INT32 Number, + IN INT32 nbit, + IN INT32 Special + ) +/*++ + +Routine Description: + + Outputs the code length array for the Extra Set or the Position Set. + +Arguments: + + Number - the number of symbols + nbit - the number of bits needed to represent 'n' + Special - the special symbol that needs to be take care of + +Returns: (VOID) + +--*/ +{ + INT32 Index; + INT32 Index3; + + while (Number > 0 && mPTLen[Number - 1] == 0) { + Number--; + } + + PutBits (nbit, Number); + Index = 0; + while (Index < Number) { + Index3 = mPTLen[Index++]; + if (Index3 <= 6) { + PutBits (3, Index3); + } else { + PutBits (Index3 - 3, (1U << (Index3 - 3)) - 2); + } + + if (Index == Special) { + while (Index < 6 && mPTLen[Index] == 0) { + Index++; + } + + PutBits (2, (Index - 3) & 3); + } + } +} + +STATIC +VOID +WriteCLen ( + VOID + ) +/*++ + +Routine Description: + + Outputs the code length array for Char&Length Set + +Arguments: (VOID) + +Returns: (VOID) + +--*/ +{ + INT32 Index; + INT32 Index3; + INT32 Number; + INT32 Count; + + Number = NC; + while (Number > 0 && mCLen[Number - 1] == 0) { + Number--; + } + + PutBits (CBIT, Number); + Index = 0; + while (Index < Number) { + Index3 = mCLen[Index++]; + if (Index3 == 0) { + Count = 1; + while (Index < Number && mCLen[Index] == 0) { + Index++; + Count++; + } + + if (Count <= 2) { + for (Index3 = 0; Index3 < Count; Index3++) { + PutBits (mPTLen[0], mPTCode[0]); + } + } else if (Count <= 18) { + PutBits (mPTLen[1], mPTCode[1]); + PutBits (4, Count - 3); + } else if (Count == 19) { + PutBits (mPTLen[0], mPTCode[0]); + PutBits (mPTLen[1], mPTCode[1]); + PutBits (4, 15); + } else { + PutBits (mPTLen[2], mPTCode[2]); + PutBits (CBIT, Count - 20); + } + } else { + PutBits (mPTLen[Index3 + 2], mPTCode[Index3 + 2]); + } + } +} + +STATIC +VOID +EncodeC ( + IN INT32 Value + ) +{ + PutBits (mCLen[Value], mCCode[Value]); +} + +STATIC +VOID +EncodeP ( + IN UINT32 Value + ) +{ + UINT32 Index; + UINT32 NodeQ; + + Index = 0; + NodeQ = Value; + while (NodeQ) { + NodeQ >>= 1; + Index++; + } + + PutBits (mPTLen[Index], mPTCode[Index]); + if (Index > 1) { + PutBits (Index - 1, Value & (0xFFFFFFFFU >> (32 - Index + 1))); + } +} + +STATIC +VOID +SendBlock ( + VOID + ) +/*++ + +Routine Description: + + Huffman code the block and output it. + +Arguments: + (VOID) + +Returns: + (VOID) + +--*/ +{ + UINT32 Index; + UINT32 Index2; + UINT32 Index3; + UINT32 Flags; + UINT32 Root; + UINT32 Pos; + UINT32 Size; + Flags = 0; + + Root = MakeTree (NC, mCFreq, mCLen, mCCode); + Size = mCFreq[Root]; + + PutBits (16, Size); + if (Root >= NC) { + CountTFreq (); + Root = MakeTree (NT, mTFreq, mPTLen, mPTCode); + if (Root >= NT) { + WritePTLen (NT, TBIT, 3); + } else { + PutBits (TBIT, 0); + PutBits (TBIT, Root); + } + + WriteCLen (); + } else { + PutBits (TBIT, 0); + PutBits (TBIT, 0); + PutBits (CBIT, 0); + PutBits (CBIT, Root); + } + + Root = MakeTree (NP, mPFreq, mPTLen, mPTCode); + if (Root >= NP) { + WritePTLen (NP, PBIT, -1); + } else { + PutBits (PBIT, 0); + PutBits (PBIT, Root); + } + + Pos = 0; + for (Index = 0; Index < Size; Index++) { + if (Index % UINT8_BIT == 0) { + Flags = mBuf[Pos++]; + } else { + Flags <<= 1; + } + + if (Flags & (1U << (UINT8_BIT - 1))) { + EncodeC (mBuf[Pos++] + (1U << UINT8_BIT)); + Index3 = mBuf[Pos++]; + for (Index2 = 0; Index2 < 3; Index2++) { + Index3 <<= UINT8_BIT; + Index3 += mBuf[Pos++]; + } + + EncodeP (Index3); + } else { + EncodeC (mBuf[Pos++]); + } + } + + for (Index = 0; Index < NC; Index++) { + mCFreq[Index] = 0; + } + + for (Index = 0; Index < NP; Index++) { + mPFreq[Index] = 0; + } +} + +STATIC +VOID +Output ( + IN UINT32 CharC, + IN UINT32 Pos + ) +/*++ + +Routine Description: + + Outputs an Original Character or a Pointer + +Arguments: + + CharC - The original character or the 'String Length' element of a Pointer + Pos - The 'Position' field of a Pointer + +Returns: (VOID) + +--*/ +{ + STATIC UINT32 CPos; + + if ((mOutputMask >>= 1) == 0) { + mOutputMask = 1U << (UINT8_BIT - 1); + // + // Check the buffer overflow per outputing UINT8_BIT symbols + // which is an Original Character or a Pointer. The biggest + // symbol is a Pointer which occupies 5 bytes. + // + if (mOutputPos >= mBufSiz - 5 * UINT8_BIT) { + SendBlock (); + mOutputPos = 0; + } + + CPos = mOutputPos++; + mBuf[CPos] = 0; + } + + mBuf[mOutputPos++] = (UINT8) CharC; + mCFreq[CharC]++; + if (CharC >= (1U << UINT8_BIT)) { + mBuf[CPos] |= mOutputMask; + mBuf[mOutputPos++] = (UINT8) (Pos >> 24); + mBuf[mOutputPos++] = (UINT8) (Pos >> 16); + mBuf[mOutputPos++] = (UINT8) (Pos >> (UINT8_BIT)); + mBuf[mOutputPos++] = (UINT8) Pos; + CharC = 0; + while (Pos) { + Pos >>= 1; + CharC++; + } + + mPFreq[CharC]++; + } +} + +STATIC +VOID +HufEncodeStart ( + VOID + ) +{ + INT32 Index; + + for (Index = 0; Index < NC; Index++) { + mCFreq[Index] = 0; + } + + for (Index = 0; Index < NP; Index++) { + mPFreq[Index] = 0; + } + + mOutputPos = mOutputMask = 0; + InitPutBits (); + return ; +} + +STATIC +VOID +HufEncodeEnd ( + VOID + ) +{ + SendBlock (); + + // + // Flush remaining bits + // + PutBits (UINT8_BIT - 1, 0); + + return ; +} + +STATIC +VOID +MakeCrcTable ( + VOID + ) +{ + UINT32 Index; + UINT32 Index2; + UINT32 Temp; + + for (Index = 0; Index <= UINT8_MAX; Index++) { + Temp = Index; + for (Index2 = 0; Index2 < UINT8_BIT; Index2++) { + if (Temp & 1) { + Temp = (Temp >> 1) ^ CRCPOLY; + } else { + Temp >>= 1; + } + } + + mCrcTable[Index] = (UINT16) Temp; + } +} + +STATIC +VOID +PutBits ( + IN INT32 Number, + IN UINT32 Value + ) +/*++ + +Routine Description: + + Outputs rightmost n bits of x + +Arguments: + + Number - the rightmost n bits of the data is used + x - the data + +Returns: (VOID) + +--*/ +{ + UINT8 Temp; + + while (Number >= mBitCount) { + // + // Number -= mBitCount should never equal to 32 + // + Temp = (UINT8) (mSubBitBuf | (Value >> (Number -= mBitCount))); + + if (mDst < mDstUpperLimit) { + *mDst++ = Temp; + } + + mCompSize++; + mSubBitBuf = 0; + mBitCount = UINT8_BIT; + } + + mSubBitBuf |= Value << (mBitCount -= Number); +} + +STATIC +INT32 +FreadCrc ( + OUT UINT8 *Pointer, + IN INT32 Number + ) +/*++ + +Routine Description: + + Read in source data + +Arguments: + + Pointer - the buffer to hold the data + Number - number of bytes to read + +Returns: + + number of bytes actually read + +--*/ +{ + INT32 Index; + + for (Index = 0; mSrc < mSrcUpperLimit && Index < Number; Index++) { + *Pointer++ = *mSrc++; + } + + Number = Index; + + Pointer -= Number; + mOrigSize += Number; + + Index--; + while (Index >= 0) { + UPDATE_CRC (*Pointer++); + Index--; + } + + return Number; +} + +STATIC +VOID +InitPutBits ( + VOID + ) +{ + mBitCount = UINT8_BIT; + mSubBitBuf = 0; +} + +STATIC +VOID +CountLen ( + IN INT32 Index + ) +/*++ + +Routine Description: + + Count the number of each code length for a Huffman tree. + +Arguments: + + Index - the top node + +Returns: (VOID) + +--*/ +{ + STATIC INT32 Depth = 0; + + if (Index < mN) { + mLenCnt[(Depth < 16) ? Depth : 16]++; + } else { + Depth++; + CountLen (mLeft[Index]); + CountLen (mRight[Index]); + Depth--; + } +} + +STATIC +VOID +MakeLen ( + IN INT32 Root + ) +/*++ + +Routine Description: + + Create code length array for a Huffman tree + +Arguments: + + Root - the root of the tree + +Returns: + + VOID + +--*/ +{ + INT32 Index; + INT32 Index3; + UINT32 Cum; + + for (Index = 0; Index <= 16; Index++) { + mLenCnt[Index] = 0; + } + + CountLen (Root); + + // + // Adjust the length count array so that + // no code will be generated longer than its designated length + // + Cum = 0; + for (Index = 16; Index > 0; Index--) { + Cum += mLenCnt[Index] << (16 - Index); + } + + while (Cum != (1U << 16)) { + mLenCnt[16]--; + for (Index = 15; Index > 0; Index--) { + if (mLenCnt[Index] != 0) { + mLenCnt[Index]--; + mLenCnt[Index + 1] += 2; + break; + } + } + + Cum--; + } + + for (Index = 16; Index > 0; Index--) { + Index3 = mLenCnt[Index]; + Index3--; + while (Index3 >= 0) { + mLen[*mSortPtr++] = (UINT8) Index; + Index3--; + } + } +} + +STATIC +VOID +DownHeap ( + IN INT32 Index + ) +{ + INT32 Index2; + INT32 Index3; + + // + // priority queue: send Index-th entry down heap + // + Index3 = mHeap[Index]; + Index2 = 2 * Index; + while (Index2 <= mHeapSize) { + if (Index2 < mHeapSize && mFreq[mHeap[Index2]] > mFreq[mHeap[Index2 + 1]]) { + Index2++; + } + + if (mFreq[Index3] <= mFreq[mHeap[Index2]]) { + break; + } + + mHeap[Index] = mHeap[Index2]; + Index = Index2; + Index2 = 2 * Index; + } + + mHeap[Index] = (INT16) Index3; +} + +STATIC +VOID +MakeCode ( + IN INT32 Number, + IN UINT8 Len[ ], + OUT UINT16 Code[] + ) +/*++ + +Routine Description: + + Assign code to each symbol based on the code length array + +Arguments: + + Number - number of symbols + Len - the code length array + Code - stores codes for each symbol + +Returns: (VOID) + +--*/ +{ + INT32 Index; + UINT16 Start[18]; + + Start[1] = 0; + for (Index = 1; Index <= 16; Index++) { + Start[Index + 1] = (UINT16) ((Start[Index] + mLenCnt[Index]) << 1); + } + + for (Index = 0; Index < Number; Index++) { + Code[Index] = Start[Len[Index]]++; + } +} + +STATIC +INT32 +MakeTree ( + IN INT32 NParm, + IN UINT16 FreqParm[], + OUT UINT8 LenParm[ ], + OUT UINT16 CodeParm[] + ) +/*++ + +Routine Description: + + Generates Huffman codes given a frequency distribution of symbols + +Arguments: + + NParm - number of symbols + FreqParm - frequency of each symbol + LenParm - code length for each symbol + CodeParm - code for each symbol + +Returns: + + Root of the Huffman tree. + +--*/ +{ + INT32 Index; + INT32 Index2; + INT32 Index3; + INT32 Avail; + + // + // make tree, calculate len[], return root + // + mN = NParm; + mFreq = FreqParm; + mLen = LenParm; + Avail = mN; + mHeapSize = 0; + mHeap[1] = 0; + for (Index = 0; Index < mN; Index++) { + mLen[Index] = 0; + if (mFreq[Index]) { + mHeapSize++; + mHeap[mHeapSize] = (INT16) Index; + } + } + + if (mHeapSize < 2) { + CodeParm[mHeap[1]] = 0; + return mHeap[1]; + } + + for (Index = mHeapSize / 2; Index >= 1; Index--) { + // + // make priority queue + // + DownHeap (Index); + } + + mSortPtr = CodeParm; + do { + Index = mHeap[1]; + if (Index < mN) { + *mSortPtr++ = (UINT16) Index; + } + + mHeap[1] = mHeap[mHeapSize--]; + DownHeap (1); + Index2 = mHeap[1]; + if (Index2 < mN) { + *mSortPtr++ = (UINT16) Index2; + } + + Index3 = Avail++; + mFreq[Index3] = (UINT16) (mFreq[Index] + mFreq[Index2]); + mHeap[1] = (INT16) Index3; + DownHeap (1); + mLeft[Index3] = (UINT16) Index; + mRight[Index3] = (UINT16) Index2; + } while (mHeapSize > 1); + + mSortPtr = CodeParm; + MakeLen (Index3); + MakeCode (NParm, LenParm, CodeParm); + + // + // return root + // + return Index3; +} + +EFI_STATUS +GetFileContents ( + IN char *InputFileName, + OUT UINT8 *FileBuffer, + OUT UINT32 *BufferLength + ) +/*++ + +Routine Description: + + Get the contents of file specified in InputFileName + into FileBuffer. + +Arguments: + + InputFileName - Name of the input file. + + FileBuffer - Output buffer to contain data + + BufferLength - Actual length of the data + +Returns: + + EFI_SUCCESS on successful return + EFI_ABORTED if unable to open input file. + +--*/ +{ + UINTN Size; + UINTN FileSize; + FILE *InputFile; + + Size = 0; + // + // Copy the file contents to the output buffer. + // + InputFile = fopen (LongFilePath (InputFileName), "rb"); + if (InputFile == NULL) { + Error (NULL, 0, 0001, "Error opening file: %s", InputFileName); + return EFI_ABORTED; + } + + fseek (InputFile, 0, SEEK_END); + FileSize = ftell (InputFile); + fseek (InputFile, 0, SEEK_SET); + // + // Now read the contents of the file into the buffer + // + if (FileSize > 0 && FileBuffer != NULL) { + if (fread (FileBuffer, FileSize, 1, InputFile) != 1) { + Error (NULL, 0, 0004, "Error reading contents of input file: %s", InputFileName); + fclose (InputFile); + return EFI_ABORTED; + } + } + + fclose (InputFile); + Size += (UINTN) FileSize; + *BufferLength = Size; + + if (FileBuffer != NULL) { + return EFI_SUCCESS; + } else { + return EFI_BUFFER_TOO_SMALL; + } +} + +VOID +Version ( + VOID + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + fprintf (stdout, "%s Version %d.%d %s \n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION, __BUILD_VERSION); +} + +VOID +Usage ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "Usage: %s -e|-d [options] \n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n"); + + // + // Details Option + // + fprintf (stdout, "Options:\n"); + fprintf (stdout, " --uefi\n\ + Enable UefiCompress, use TianoCompress when without this option\n"); + fprintf (stdout, " -o FileName, --output FileName\n\ + File will be created to store the output content.\n"); + fprintf (stdout, " -v, --verbose\n\ + Turn on verbose output with informational messages.\n"); + fprintf (stdout, " -q, --quiet\n\ + Disable all messages except key message and fatal error\n"); + fprintf (stdout, " --debug [0-9]\n\ + Enable debug messages, at input debug level.\n"); + fprintf (stdout, " --version\n\ + Show program's version number and exit.\n"); + fprintf (stdout, " -h, --help\n\ + Show this help message and exit.\n"); +} + + +int +main ( + int argc, + char *argv[] + ) +/*++ + +Routine Description: + + Main + +Arguments: + + command line parameters + +Returns: + + EFI_SUCCESS Section header successfully generated and section concatenated. + EFI_ABORTED Could not generate the section + EFI_OUT_OF_RESOURCES No resource to complete the operation. + +--*/ +{ + FILE *OutputFile; + char *OutputFileName; + char *InputFileName; + FILE *InputFile; + EFI_STATUS Status; + UINT8 *FileBuffer; + UINT8 *OutBuffer; + UINT32 InputLength; + UINT32 DstSize; + SCRATCH_DATA *Scratch; + UINT8 *Src; + UINT32 OrigSize; + UINT32 CompSize; + + SetUtilityName(UTILITY_NAME); + + FileBuffer = NULL; + Src = NULL; + OutBuffer = NULL; + Scratch = NULL; + OrigSize = 0; + CompSize = 0; + InputLength = 0; + InputFileName = NULL; + OutputFileName = NULL; + InputFile = NULL; + OutputFile = NULL; + DstSize=0; + DebugLevel = 0; + DebugMode = FALSE; + + // + // Verify the correct number of arguments + // + if (argc == 1) { + Error (NULL, 0, 1001, "Missing options", "No input options specified."); + Usage(); + return 0; + } + + if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) { + Usage(); + return 0; + } + + if ((strcmp(argv[1], "--version") == 0)) { + Version(); + return 0; + } + + argc--; + argv++; + if (strcmp(argv[0],"-e") == 0) { + // + // encode the input file + // + ENCODE = TRUE; + argc--; + argv++; + } else if (strcmp(argv[0], "-d") == 0) { + // + // decode the input file + // + DECODE = TRUE; + argc--; + argv++; + } else { + // + // Error command line + // + Error (NULL, 0, 1003, "Invalid option value", "the options specified are not recognized."); + Usage(); + return 1; + } + + while (argc > 0) { + if ((strcmp(argv[0], "-v") == 0) || (stricmp(argv[0], "--verbose") == 0)) { + VerboseMode = TRUE; + argc--; + argv++; + continue; + } + + if (stricmp(argv[0], "--uefi") == 0) { + UEFIMODE = TRUE; + argc--; + argv++; + continue; + } + + if (stricmp (argv[0], "--debug") == 0) { + argc-=2; + argv++; + Status = AsciiStringToUint64(argv[0], FALSE, &DebugLevel); + if (DebugLevel > 9) { + Error (NULL, 0 ,2000, "Invalid parameter", "Unrecognized argument %s", argv[0]); + goto ERROR; + } + if (DebugLevel>=5 && DebugLevel <=9){ + DebugMode = TRUE; + } else { + DebugMode = FALSE; + } + argv++; + continue; + } + + if ((strcmp(argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + QuietMode = TRUE; + argc--; + argv++; + continue; + } + + if ((strcmp(argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) { + if (argv[1] == NULL || argv[1][0] == '-') { + Error (NULL, 0, 1003, "Invalid option value", "Output File name is missing for -o option"); + goto ERROR; + } + OutputFileName = argv[1]; + argc -=2; + argv +=2; + continue; + } + + if (argv[0][0]!='-') { + InputFileName = argv[0]; + argc--; + argv++; + continue; + } + + Error (NULL, 0, 1000, "Unknown option", argv[0]); + goto ERROR; + } + + if (InputFileName == NULL) { + Error (NULL, 0, 1001, "Missing options", "No input files specified."); + goto ERROR; + } + +// +// All Parameters has been parsed, now set the message print level +// + if (QuietMode) { + SetPrintLevel(40); + } else if (VerboseMode) { + SetPrintLevel(15); + } else if (DebugMode) { + SetPrintLevel(DebugLevel); + } + + if (VerboseMode) { + VerboseMsg("%s tool start.\n", UTILITY_NAME); + } + Scratch = (SCRATCH_DATA *)malloc(sizeof(SCRATCH_DATA)); + if (Scratch == NULL) { + Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!"); + goto ERROR; + } + + InputFile = fopen (LongFilePath (InputFileName), "rb"); + if (InputFile == NULL) { + Error (NULL, 0, 0001, "Error opening input file", InputFileName); + goto ERROR; + } + + Status = GetFileContents( + InputFileName, + FileBuffer, + &InputLength); + + if (Status == EFI_BUFFER_TOO_SMALL) { + FileBuffer = (UINT8 *) malloc (InputLength); + if (FileBuffer == NULL) { + Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!"); + goto ERROR; + } + + Status = GetFileContents ( + InputFileName, + FileBuffer, + &InputLength + ); + } + + if (EFI_ERROR(Status)) { + Error (NULL, 0, 0004, "Error getting contents of file: %s", InputFileName); + goto ERROR; + } + + if (OutputFileName == NULL) { + OutputFileName = DEFAULT_OUTPUT_FILE; + } + OutputFile = fopen (LongFilePath (OutputFileName), "wb"); + if (OutputFile == NULL) { + Error (NULL, 0, 0001, "Error opening output file for writing", OutputFileName); + goto ERROR; + } + + if (ENCODE) { + // + // First call TianoCompress to get DstSize + // + if (DebugMode) { + DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding", NULL); + } + if (UEFIMODE) { + Status = EfiCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize); + } else { + Status = TianoCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize); + } + + if (Status == EFI_BUFFER_TOO_SMALL) { + OutBuffer = (UINT8 *) malloc (DstSize); + if (OutBuffer == NULL) { + Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!"); + goto ERROR; + } + } + + if (UEFIMODE) { + Status = EfiCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize); + } else { + Status = TianoCompress ((UINT8 *)FileBuffer, InputLength, OutBuffer, &DstSize); + } + if (Status != EFI_SUCCESS) { + Error (NULL, 0, 0007, "Error compressing file", NULL); + goto ERROR; + } + + if (OutBuffer == NULL) { + Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!"); + goto ERROR; + } + + fwrite(OutBuffer,(size_t)DstSize, 1, OutputFile); + fclose(OutputFile); + fclose(InputFile); + free(Scratch); + free(FileBuffer); + free(OutBuffer); + + if (DebugMode) { + DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding Successful!\n", NULL); + } + if (VerboseMode) { + VerboseMsg("Encoding successful\n"); + } + return 0; + } + else if (DECODE) { + if (DebugMode) { + DebugMsg(UTILITY_NAME, 0, DebugLevel, "Decoding\n", NULL); + } + + if (UEFIMODE) { + Status = Extract((VOID *)FileBuffer, InputLength, (VOID *)&OutBuffer, &DstSize, 1); + if (Status != EFI_SUCCESS) { + goto ERROR; + } + fwrite(OutBuffer, (size_t)(DstSize), 1, OutputFile); + } else { + if (InputLength < 8){ + Error (NULL, 0, 3000, "Invalid", "The input file %s is too small.", InputFileName); + goto ERROR; + } + // + // Get Compressed file original size + // + Src = (UINT8 *)FileBuffer; + OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + CompSize = Src[0] + (Src[1] << 8) + (Src[2] <<16) + (Src[3] <<24); + + // + // Allocate OutputBuffer + // + if (InputLength < CompSize + 8 || (CompSize + 8) < 8) { + Error (NULL, 0, 3000, "Invalid", "The input file %s data is invalid.", InputFileName); + goto ERROR; + } + OutBuffer = (UINT8 *)malloc(OrigSize); + if (OutBuffer == NULL) { + Error (NULL, 0, 4001, "Resource:", "Memory cannot be allocated!"); + goto ERROR; + } + + Status = TDecompress((VOID *)FileBuffer, (VOID *)OutBuffer, (VOID *)Scratch, 2); + if (Status != EFI_SUCCESS) { + goto ERROR; + } + fwrite(OutBuffer, (size_t)(Scratch->mOrigSize), 1, OutputFile); + } + fclose(OutputFile); + fclose(InputFile); + if (Scratch != NULL) { + free(Scratch); + } + if (FileBuffer != NULL) { + free(FileBuffer); + } + if (OutBuffer != NULL) { + free(OutBuffer); + } + + if (DebugMode) { + DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding successful!\n", NULL); + } + + if (VerboseMode) { + VerboseMsg("Decoding successful\n"); + } + return 0; + } + +ERROR: + if (DebugMode) { + if (ENCODE) { + DebugMsg(UTILITY_NAME, 0, DebugLevel, "Encoding Error\n", NULL); + } else if (DECODE) { + DebugMsg(UTILITY_NAME, 0, DebugLevel, "Decoding Error\n", NULL); + } + } + if (OutputFile != NULL) { + fclose(OutputFile); + } + if (InputFile != NULL) { + fclose (InputFile); + } + if (Scratch != NULL) { + free(Scratch); + } + if (FileBuffer != NULL) { + free(FileBuffer); + } + if (OutBuffer != NULL) { + free(OutBuffer); + } + + if (VerboseMode) { + VerboseMsg("%s tool done with return code is 0x%x.\n", UTILITY_NAME, GetUtilityStatus ()); + } + return GetUtilityStatus (); +} + +VOID +FillBuf ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +/*++ + +Routine Description: + + Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source. + +Arguments: + + Sd - The global scratch data + NumOfBits - The number of bits to shift and read. + +Returns: (VOID) + +--*/ +{ + Sd->mBitBuf = (UINT32) (((UINT64)Sd->mBitBuf) << NumOfBits); + + while (NumOfBits > Sd->mBitCount) { + + Sd->mBitBuf |= (UINT32) (((UINT64)Sd->mSubBitBuf) << (NumOfBits = (UINT16) (NumOfBits - Sd->mBitCount))); + + if (Sd->mCompSize > 0) { + // + // Get 1 byte into SubBitBuf + // + Sd->mCompSize--; + Sd->mSubBitBuf = 0; + Sd->mSubBitBuf = Sd->mSrcBase[Sd->mInBuf++]; + Sd->mBitCount = 8; + + } else { + // + // No more bits from the source, just pad zero bit. + // + Sd->mSubBitBuf = 0; + Sd->mBitCount = 8; + + } + } + + Sd->mBitCount = (UINT16) (Sd->mBitCount - NumOfBits); + Sd->mBitBuf |= Sd->mSubBitBuf >> Sd->mBitCount; +} + +UINT32 +GetBits ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ) +/*++ + +Routine Description: + + Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent + NumOfBits of bits from source. Returns NumOfBits of bits that are + popped out. + +Arguments: + + Sd - The global scratch data. + NumOfBits - The number of bits to pop and read. + +Returns: + + The bits that are popped out. + +--*/ +{ + UINT32 OutBits; + + OutBits = (UINT32) (Sd->mBitBuf >> (BITBUFSIZ - NumOfBits)); + + FillBuf (Sd, NumOfBits); + + return OutBits; +} + +UINT16 +MakeTable ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfChar, + IN UINT8 *BitLen, + IN UINT16 TableBits, + OUT UINT16 *Table + ) +/*++ + +Routine Description: + + Creates Huffman Code mapping table according to code length array. + +Arguments: + + Sd - The global scratch data + NumOfChar - Number of symbols in the symbol set + BitLen - Code length array + TableBits - The width of the mapping table + Table - The table + +Returns: + + 0 - OK. + BAD_TABLE - The table is corrupted. + +--*/ +{ + UINT16 Count[17]; + UINT16 Weight[17]; + UINT16 Start[18]; + UINT16 *Pointer; + UINT16 Index3; + UINT16 Index; + UINT16 Len; + UINT16 Char; + UINT16 JuBits; + UINT16 Avail; + UINT16 NextCode; + UINT16 Mask; + UINT16 WordOfStart; + UINT16 WordOfCount; + UINT16 MaxTableLength; + + for (Index = 0; Index <= 16; Index++) { + Count[Index] = 0; + } + + for (Index = 0; Index < NumOfChar; Index++) { + if (BitLen[Index] > 16) { + return (UINT16) BAD_TABLE; + } + Count[BitLen[Index]]++; + } + + Start[0] = 0; + Start[1] = 0; + + for (Index = 1; Index <= 16; Index++) { + WordOfStart = Start[Index]; + WordOfCount = Count[Index]; + Start[Index + 1] = (UINT16) (WordOfStart + (WordOfCount << (16 - Index))); + } + + if (Start[17] != 0) { + // + //(1U << 16) + // + return (UINT16) BAD_TABLE; + } + + JuBits = (UINT16) (16 - TableBits); + + Weight[0] = 0; + for (Index = 1; Index <= TableBits; Index++) { + Start[Index] >>= JuBits; + Weight[Index] = (UINT16) (1U << (TableBits - Index)); + } + + while (Index <= 16) { + Weight[Index] = (UINT16) (1U << (16 - Index)); + Index++; + } + + Index = (UINT16) (Start[TableBits + 1] >> JuBits); + + if (Index != 0) { + Index3 = (UINT16) (1U << TableBits); + while (Index != Index3) { + Table[Index++] = 0; + } + } + + Avail = NumOfChar; + Mask = (UINT16) (1U << (15 - TableBits)); + MaxTableLength = (UINT16) (1U << TableBits); + + for (Char = 0; Char < NumOfChar; Char++) { + + Len = BitLen[Char]; + if (Len == 0 || Len >= 17) { + continue; + } + + NextCode = (UINT16) (Start[Len] + Weight[Len]); + + if (Len <= TableBits) { + + if (Start[Len] >= NextCode || NextCode > MaxTableLength){ + return (UINT16) BAD_TABLE; + } + + for (Index = Start[Len]; Index < NextCode; Index++) { + Table[Index] = Char; + } + + } else { + + Index3 = Start[Len]; + Pointer = &Table[Index3 >> JuBits]; + Index = (UINT16) (Len - TableBits); + + while (Index != 0) { + if (*Pointer == 0) { + Sd->mRight[Avail] = Sd->mLeft[Avail] = 0; + *Pointer = Avail++; + } + + if (Index3 & Mask) { + Pointer = &Sd->mRight[*Pointer]; + } else { + Pointer = &Sd->mLeft[*Pointer]; + } + + Index3 <<= 1; + Index--; + } + + *Pointer = Char; + + } + + Start[Len] = NextCode; + } + // + // Succeeds + // + return 0; +} + +UINT32 +DecodeP ( + IN SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decodes a position value. + +Arguments: + + Sd - the global scratch data + +Returns: + + The position value decoded. + +--*/ +{ + UINT16 Val; + UINT32 Mask; + UINT32 Pos; + + Val = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + + if (Val >= MAXNP) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if (Sd->mBitBuf & Mask) { + Val = Sd->mRight[Val]; + } else { + Val = Sd->mLeft[Val]; + } + + Mask >>= 1; + } while (Val >= MAXNP); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[Val]); + + Pos = Val; + if (Val > 1) { + Pos = (UINT32) ((1U << (Val - 1)) + GetBits (Sd, (UINT16) (Val - 1))); + } + + return Pos; +} + +UINT16 +ReadPTLen ( + IN SCRATCH_DATA *Sd, + IN UINT16 nn, + IN UINT16 nbit, + IN UINT16 Special + ) +/*++ + +Routine Description: + + Reads code lengths for the Extra Set or the Position Set + +Arguments: + + Sd - The global scratch data + nn - Number of symbols + nbit - Number of bits needed to represent nn + Special - The special symbol that needs to be taken care of + +Returns: + + 0 - OK. + BAD_TABLE - Table is corrupted. + +--*/ +{ + UINT16 Number; + UINT16 CharC; + volatile UINT16 Index; + UINT32 Mask; + + assert (nn <= NPT); + + Number = (UINT16) GetBits (Sd, nbit); + + if (Number == 0) { + CharC = (UINT16) GetBits (Sd, nbit); + + for (Index = 0; Index < 256; Index++) { + Sd->mPTTable[Index] = CharC; + } + + for (Index = 0; Index < nn; Index++) { + Sd->mPTLen[Index] = 0; + } + + return 0; + } + + Index = 0; + + while (Index < Number) { + + CharC = (UINT16) (Sd->mBitBuf >> (BITBUFSIZ - 3)); + + if (CharC == 7) { + Mask = 1U << (BITBUFSIZ - 1 - 3); + while (Mask & Sd->mBitBuf) { + Mask >>= 1; + CharC += 1; + } + } + + FillBuf (Sd, (UINT16) ((CharC < 7) ? 3 : CharC - 3)); + + Sd->mPTLen[Index++] = (UINT8) CharC; + + if (Index == Special) { + CharC = (UINT16) GetBits (Sd, 2); + while ((INT16) (--CharC) >= 0) { + Sd->mPTLen[Index++] = 0; + } + } + } + + while (Index < nn) { + Sd->mPTLen[Index++] = 0; + } + + return MakeTable (Sd, nn, Sd->mPTLen, 8, Sd->mPTTable); +} + +VOID +ReadCLen ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Reads code lengths for Char&Len Set. + +Arguments: + + Sd - the global scratch data + +Returns: (VOID) + +--*/ +{ + UINT16 Number; + UINT16 CharC; + volatile UINT16 Index; + UINT32 Mask; + + Number = (UINT16) GetBits (Sd, CBIT); + + if (Number == 0) { + CharC = (UINT16) GetBits (Sd, CBIT); + + for (Index = 0; Index < NC; Index++) { + Sd->mCLen[Index] = 0; + } + + for (Index = 0; Index < 4096; Index++) { + Sd->mCTable[Index] = CharC; + } + + return ; + } + + Index = 0; + while (Index < Number) { + + CharC = Sd->mPTTable[Sd->mBitBuf >> (BITBUFSIZ - 8)]; + if (CharC >= NT) { + Mask = 1U << (BITBUFSIZ - 1 - 8); + + do { + + if (Mask & Sd->mBitBuf) { + CharC = Sd->mRight[CharC]; + } else { + CharC = Sd->mLeft[CharC]; + } + + Mask >>= 1; + + } while (CharC >= NT); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mPTLen[CharC]); + + if (CharC <= 2) { + + if (CharC == 0) { + CharC = 1; + } else if (CharC == 1) { + CharC = (UINT16) (GetBits (Sd, 4) + 3); + } else if (CharC == 2) { + CharC = (UINT16) (GetBits (Sd, CBIT) + 20); + } + + while ((INT16) (--CharC) >= 0) { + Sd->mCLen[Index++] = 0; + } + + } else { + + Sd->mCLen[Index++] = (UINT8) (CharC - 2); + + } + } + + while (Index < NC) { + Sd->mCLen[Index++] = 0; + } + + MakeTable (Sd, NC, Sd->mCLen, 12, Sd->mCTable); + + return ; +} + +UINT16 +DecodeC ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decode a character/length value. + +Arguments: + + Sd - The global scratch data. + +Returns: + + The value decoded. + +--*/ +{ + UINT16 Index2; + UINT32 Mask; + + if (Sd->mBlockSize == 0) { + // + // Starting a new block + // + Sd->mBlockSize = (UINT16) GetBits (Sd, 16); + Sd->mBadTableFlag = ReadPTLen (Sd, NT, TBIT, 3); + if (Sd->mBadTableFlag != 0) { + return 0; + } + + ReadCLen (Sd); + + Sd->mBadTableFlag = ReadPTLen (Sd, MAXNP, Sd->mPBit, (UINT16) (-1)); + if (Sd->mBadTableFlag != 0) { + return 0; + } + } + + Sd->mBlockSize--; + Index2 = Sd->mCTable[Sd->mBitBuf >> (BITBUFSIZ - 12)]; + + if (Index2 >= NC) { + Mask = 1U << (BITBUFSIZ - 1 - 12); + + do { + if (Sd->mBitBuf & Mask) { + Index2 = Sd->mRight[Index2]; + } else { + Index2 = Sd->mLeft[Index2]; + } + + Mask >>= 1; + } while (Index2 >= NC); + } + // + // Advance what we have read + // + FillBuf (Sd, Sd->mCLen[Index2]); + + return Index2; +} + +VOID +Decode ( + SCRATCH_DATA *Sd + ) +/*++ + +Routine Description: + + Decode the source data and put the resulting data into the destination buffer. + +Arguments: + + Sd - The global scratch data + +Returns: (VOID) + + --*/ +{ + UINT16 BytesRemain; + UINT32 DataIdx; + UINT16 CharC; + + BytesRemain = (UINT16) (-1); + + DataIdx = 0; + + for (;;) { + CharC = DecodeC (Sd); + if (Sd->mBadTableFlag != 0) { + goto Done ; + } + + if (CharC < 256) { + // + // Process an Original character + // + if (Sd->mOutBuf >= Sd->mOrigSize) { + goto Done ; + } else { + Sd->mDstBase[Sd->mOutBuf++] = (UINT8) CharC; + } + + } else { + // + // Process a Pointer + // + CharC = (UINT16) (CharC - (UINT8_MAX + 1 - THRESHOLD)); + + BytesRemain = CharC; + + DataIdx = Sd->mOutBuf - DecodeP (Sd) - 1; + + BytesRemain--; + + while ((INT16) (BytesRemain) >= 0) { + if (Sd->mOutBuf >= Sd->mOrigSize) { + goto Done ; + } + if (DataIdx >= Sd->mOrigSize) { + Sd->mBadTableFlag = (UINT16) BAD_TABLE; + goto Done ; + } + Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; + + BytesRemain--; + } + // + // Once mOutBuf is fully filled, directly return + // + if (Sd->mOutBuf >= Sd->mOrigSize) { + goto Done ; + } + } + } + +Done: + return ; +} + +RETURN_STATUS +EFIAPI +TDecompress ( + IN VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch, + IN UINT32 Version + ) +/*++ + +Routine Description: + + The internal implementation of Decompress(). + +Arguments: + + Source - The source buffer containing the compressed data. + Destination - The destination buffer to store the decompressed data + Scratch - The buffer used internally by the decompress routine. This buffer is needed to store intermediate data. + Version - 1 for EFI1.1 Decompress algorithm, 2 for Tiano Decompress algorithm + +Returns: + + RETURN_SUCCESS - Decompression is successful + RETURN_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + volatile UINT32 Index; + UINT32 CompSize; + UINT32 OrigSize; + SCRATCH_DATA *Sd; + CONST UINT8 *Src; + UINT8 *Dst; + + // + // Verify input is not NULL + // + assert(Source); +// assert(Destination); + assert(Scratch); + + Src = (UINT8 *)Source; + Dst = (UINT8 *)Destination; + + Sd = (SCRATCH_DATA *) Scratch; + CompSize = Src[0] + (Src[1] << 8) + (Src[2] << 16) + (Src[3] << 24); + OrigSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + + // + // If compressed file size is 0, return + // + if (OrigSize == 0) { + return RETURN_SUCCESS; + } + + Src = Src + 8; + + for (Index = 0; Index < sizeof (SCRATCH_DATA); Index++) { + ((UINT8 *) Sd)[Index] = 0; + } + // + // The length of the field 'Position Set Code Length Array Size' in Block Header. + // For EFI 1.1 de/compression algorithm(Version 1), mPBit = 4 + // For Tiano de/compression algorithm(Version 2), mPBit = 5 + // + switch (Version) { + case 1 : + Sd->mPBit = 4; + break; + case 2 : + Sd->mPBit = 5; + break; + default: + assert(FALSE); + } + Sd->mSrcBase = (UINT8 *)Src; + Sd->mDstBase = Dst; + Sd->mCompSize = CompSize; + Sd->mOrigSize = OrigSize; + + // + // Fill the first BITBUFSIZ bits + // + FillBuf (Sd, BITBUFSIZ); + + // + // Decompress it + // + + Decode (Sd); + + if (Sd->mBadTableFlag != 0) { + // + // Something wrong with the source + // + return RETURN_INVALID_PARAMETER; + } + + return RETURN_SUCCESS; +} + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/TianoCompress.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/TianoCompress.h new file mode 100644 index 00000000..b4867b8f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/TianoCompress/TianoCompress.h @@ -0,0 +1,431 @@ +/** @file + Internal include file for Tiano Decompress Library. + + Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __TIANO_DECOMPRESS_H__ +#define __TIANO_DECOMPRESS_H__ + +#include +#include +#include + + +// +// Decompression algorithm begins here +// +#define UTILITY_NAME "TianoCompress" +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 + +// +// Default output file name +// +#define DEFAULT_OUTPUT_FILE "file.tmp" + +#define BITBUFSIZ 32 +#define MAXMATCH 256 +#define THRESHOLD 3 +#define CODE_BIT 16 +#define BAD_TABLE - 1 + +typedef INT32 NODE; + +// +// C: Char&Len Set; P: Position Set; T: exTra Set +// +#define NC (0xff + MAXMATCH + 2 - THRESHOLD) +#define CBIT 9 +#define MAXPBIT 5 +#define TBIT 5 +#define MAXNP ((1U << MAXPBIT) - 1) +#define NT (CODE_BIT + 3) +#if NT > MAXNP +#define NPT NT +#else +#define NPT MAXNP +#endif + +typedef struct { + UINT8 *mSrcBase; // Starting address of compressed data + UINT8 *mDstBase; // Starting address of decompressed data + UINT32 mOutBuf; + UINT32 mInBuf; + + UINT16 mBitCount; + UINT32 mBitBuf; + UINT32 mSubBitBuf; + UINT16 mBlockSize; + UINT32 mCompSize; + UINT32 mOrigSize; + + UINT16 mBadTableFlag; + + UINT16 mLeft[2 * NC - 1]; + UINT16 mRight[2 * NC - 1]; + UINT8 mCLen[NC]; + UINT8 mPTLen[NPT]; + UINT16 mCTable[4096]; + UINT16 mPTTable[256]; + + // + // The length of the field 'Position Set Code Length Array Size' in Block Header. + // For EFI 1.1 de/compression algorithm, mPBit = 4 + // For Tiano de/compression algorithm, mPBit = 5 + // + UINT8 mPBit; +} SCRATCH_DATA; + +// +// Function Prototypes +// + +EFI_STATUS +GetFileContents ( + IN char *InputFileName, + OUT UINT8 *FileBuffer, + OUT UINT32 *BufferLength + ); + +STATIC +VOID +PutDword( + IN UINT32 Data + ); + +STATIC +EFI_STATUS +AllocateMemory ( + VOID + ); + +STATIC +VOID +FreeMemory ( + VOID + ); + +STATIC +VOID +InitSlide ( + VOID + ); + +STATIC +NODE +Child ( + IN NODE NodeQ, + IN UINT8 CharC + ); + +STATIC +VOID +MakeChild ( + IN NODE NodeQ, + IN UINT8 CharC, + IN NODE NodeR + ); + +STATIC +VOID +Split ( + IN NODE Old + ); + +STATIC +VOID +InsertNode ( + VOID + ); + +STATIC +VOID +DeleteNode ( + VOID + ); + +STATIC +VOID +GetNextMatch ( + VOID + ); + +STATIC +EFI_STATUS +Encode ( + VOID + ); + +STATIC +VOID +CountTFreq ( + VOID + ); + +STATIC +VOID +WritePTLen ( + IN INT32 Number, + IN INT32 nbit, + IN INT32 Special + ); + +STATIC +VOID +WriteCLen ( + VOID + ); + +STATIC +VOID +EncodeC ( + IN INT32 Value + ); + +STATIC +VOID +EncodeP ( + IN UINT32 Value + ); + +STATIC +VOID +SendBlock ( + VOID + ); + +STATIC +VOID +Output ( + IN UINT32 c, + IN UINT32 p + ); + +STATIC +VOID +HufEncodeStart ( + VOID + ); + +STATIC +VOID +HufEncodeEnd ( + VOID + ); + +STATIC +VOID +MakeCrcTable ( + VOID + ); + + +STATIC +VOID +PutBits ( + IN INT32 Number, + IN UINT32 Value + ); + +STATIC +INT32 +FreadCrc ( + OUT UINT8 *Pointer, + IN INT32 Number + ); + +STATIC +VOID +InitPutBits ( + VOID + ); + +STATIC +VOID +CountLen ( + IN INT32 Index + ); + +STATIC +VOID +MakeLen ( + IN INT32 Root + ); + +STATIC +VOID +DownHeap ( + IN INT32 Index + ); + +STATIC +VOID +MakeCode ( + IN INT32 Number, + IN UINT8 Len[ ], + OUT UINT16 Code[] + ); + +STATIC +INT32 +MakeTree ( + IN INT32 NParm, + IN UINT16 FreqParm[], + OUT UINT8 LenParm[ ], + OUT UINT16 CodeParm[] + ); + +/** + Read NumOfBit of bits from source into mBitBuf + + Shift mBitBuf NumOfBits left. Read in NumOfBits of bits from source. + + @param Sd The global scratch data + @param NumOfBits The number of bits to shift and read. + +**/ +VOID +FillBuf ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ); + +/** + Get NumOfBits of bits out from mBitBuf + + Get NumOfBits of bits out from mBitBuf. Fill mBitBuf with subsequent + NumOfBits of bits from source. Returns NumOfBits of bits that are + popped out. + + @param Sd The global scratch data. + @param NumOfBits The number of bits to pop and read. + + @return The bits that are popped out. + +**/ +UINT32 +GetBits ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfBits + ); + +/** + Creates Huffman Code mapping table according to code length array. + + Creates Huffman Code mapping table for Extra Set, Char&Len Set + and Position Set according to code length array. + + @param Sd The global scratch data + @param NumOfChar Number of symbols in the symbol set + @param BitLen Code length array + @param TableBits The width of the mapping table + @param Table The table + + @retval 0 OK. + @retval BAD_TABLE The table is corrupted. + +**/ +UINT16 +MakeTable ( + IN SCRATCH_DATA *Sd, + IN UINT16 NumOfChar, + IN UINT8 *BitLen, + IN UINT16 TableBits, + OUT UINT16 *Table + ); + +/** + Decodes a position value. + + Get a position value according to Position Huffman Table. + + @param Sd the global scratch data + + @return The position value decoded. + +**/ +UINT32 +DecodeP ( + IN SCRATCH_DATA *Sd + ); + +/** + Reads code lengths for the Extra Set or the Position Set. + + Read in the Extra Set or Position Set Length Array, then + generate the Huffman code mapping for them. + + @param Sd The global scratch data. + @param nn Number of symbols. + @param nbit Number of bits needed to represent nn. + @param Special The special symbol that needs to be taken care of. + + @retval 0 OK. + @retval BAD_TABLE Table is corrupted. + +**/ +UINT16 +ReadPTLen ( + IN SCRATCH_DATA *Sd, + IN UINT16 nn, + IN UINT16 nbit, + IN UINT16 Special + ); + +/** + Reads code lengths for Char&Len Set. + + Read in and decode the Char&Len Set Code Length Array, then + generate the Huffman Code mapping table for the Char&Len Set. + + @param Sd the global scratch data + +**/ +VOID +ReadCLen ( + SCRATCH_DATA *Sd + ); + +/** + Decode a character/length value. + + Read one value from mBitBuf, Get one code from mBitBuf. If it is at block boundary, generates + Huffman code mapping table for Extra Set, Code&Len Set and + Position Set. + + @param Sd The global scratch data. + + @return The value decoded. + +**/ +UINT16 +DecodeC ( + SCRATCH_DATA *Sd + ); + +/** + Decode the source data and put the resulting data into the destination buffer. + + Decode the source data and put the resulting data into the destination buffer. + + @param Sd The global scratch data + +**/ +VOID +Decode ( + SCRATCH_DATA *Sd + ); + +RETURN_STATUS +EFIAPI +TDecompress ( + IN VOID *Source, + IN OUT VOID *Destination, + IN OUT VOID *Scratch, + IN UINT32 Version + ); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/EfiVfr.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/EfiVfr.h new file mode 100644 index 00000000..e9d80fe7 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/EfiVfr.h @@ -0,0 +1,44 @@ +/** @file +Defines and prototypes for the UEFI VFR compiler internal use. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFIVFR_H_ +#define _EFIVFR_H_ + +#include "Common/UefiBaseTypes.h" +#include "Common/UefiInternalFormRepresentation.h" +#include "Common/MdeModuleHii.h" + +#define MAX_VFR_LINE_LEN 4096 + +#define EFI_IFR_MAX_LENGTH 0xFF +#define MAX_IFR_EXPRESSION_DEPTH 0x9 + +#define EFI_VARSTORE_ID_INVALID 0 +#define EFI_VAROFFSET_INVALID 0xFFFF +#define EFI_VARSTORE_ID_START 0x20 +#define EFI_STRING_ID_INVALID 0x0 +#define EFI_IMAGE_ID_INVALID 0xFFFF + +#define EFI_IFR_MAX_DEFAULT_TYPE 0x10 + +typedef enum { + QUESTION_NORMAL, + QUESTION_DATE, + QUESTION_TIME, + QUESTION_REF, +} EFI_QUESION_TYPE; + +typedef enum { + EQUAL, + LESS_EQUAL, + LESS_THAN, + GREATER_THAN, + GREATER_EQUAL +} EFI_COMPARE_TYPE; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/GNUmakefile new file mode 100644 index 00000000..5cf434ae --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/GNUmakefile @@ -0,0 +1,80 @@ +## @file +# GNU/Linux makefile for 'VfrCompile' module build. +# +# Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +MAKEROOT ?= .. + +APPNAME = VfrCompile + +LIBS = -lCommon + +TOOL_INCLUDE = -I Pccts/h + +#OBJECTS = VfrSyntax.o VfrServices.o DLGLexer.o EfiVfrParser.o ATokenBuffer.o DLexerBase.o AParser.o +OBJECTS = AParser.o DLexerBase.o ATokenBuffer.o EfiVfrParser.o VfrLexer.o VfrSyntax.o \ + VfrFormPkg.o VfrError.o VfrUtilityLib.o VfrCompiler.o +ifeq ($(CXX), llvm) +VFR_CPPFLAGS = -Wno-deprecated-register -DPCCTS_USE_NAMESPACE_STD $(BUILD_CPPFLAGS) +else +VFR_CPPFLAGS = -DPCCTS_USE_NAMESPACE_STD $(BUILD_CPPFLAGS) +endif +# keep BUILD_OPTFLAGS last +VFR_CXXFLAGS = $(BUILD_OPTFLAGS) + +# keep EXTRA_LDFLAGS last +VFR_LFLAGS = $(EXTRA_LDFLAGS) + +LINKER = $(BUILD_CXX) + +EXTRA_CLEAN_OBJECTS = EfiVfrParser.cpp EfiVfrParser.h VfrParser.dlg VfrTokens.h VfrLexer.cpp VfrLexer.h VfrSyntax.cpp tokens.h + +MAKEROOT ?= ../.. + +include $(MAKEROOT)/Makefiles/header.makefile + +APPLICATION = $(MAKEROOT)/bin/$(APPNAME) + +.PHONY:all +all: $(MAKEROOT)/bin $(APPLICATION) + +$(APPLICATION): $(OBJECTS) + $(LINKER) -o $(APPLICATION) $(VFR_LFLAGS) $(OBJECTS) -L$(MAKEROOT)/libs $(LIBS) + +VfrCompiler.o: ../Include/Common/BuildVersion.h + +include $(MAKEROOT)/Makefiles/footer.makefile + +VfrSyntax.cpp EfiVfrParser.cpp EfiVfrParser.h VfrParser.dlg VfrTokens.h: Pccts/antlr/antlr VfrSyntax.g + Pccts/antlr/antlr -CC -e3 -ck 3 -k 2 -fl VfrParser.dlg -ft VfrTokens.h -o . VfrSyntax.g + +VfrLexer.cpp VfrLexer.h: Pccts/dlg/dlg VfrParser.dlg + Pccts/dlg/dlg -C2 -i -CC -cl VfrLexer -o . VfrParser.dlg + +Pccts/antlr/antlr: + BIN_DIR='.' $(MAKE) -C Pccts/antlr + +Pccts/dlg/dlg: + BIN_DIR='.' $(MAKE) -C Pccts/dlg + +ATokenBuffer.o: Pccts/h/ATokenBuffer.cpp + $(BUILD_CXX) -c $(VFR_CPPFLAGS) $(INC) $(VFR_CXXFLAGS) $? -o $@ + +DLexerBase.o: Pccts/h/DLexerBase.cpp + $(BUILD_CXX) -c $(VFR_CPPFLAGS) $(INC) $(VFR_CXXFLAGS) $? -o $@ + +AParser.o: Pccts/h/AParser.cpp + $(BUILD_CXX) -c $(VFR_CPPFLAGS) $(INC) $(VFR_CXXFLAGS) $? -o $@ + +VfrSyntax.o: VfrSyntax.cpp + $(BUILD_CXX) -c $(VFR_CPPFLAGS) $(INC) $(VFR_CXXFLAGS) $? -o $@ + +clean: localClean + +localClean: + BIN_DIR='.' $(MAKE) -C Pccts/antlr clean + BIN_DIR='.' $(MAKE) -C Pccts/dlg clean + rm -f $(EXTRA_CLEAN_OBJECTS) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Makefile new file mode 100644 index 00000000..24c3dbd6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Makefile @@ -0,0 +1,50 @@ +## @file +# Windows makefile for 'VfrCompile' module build. +# +# Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +!INCLUDE ..\Makefiles\ms.common + +CPPFLAGS = $(CPPFLAGS) /WX /D PCCTS_USE_NAMESPACE_STD +APPNAME = VfrCompile + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = AParser.obj DLexerBase.obj ATokenBuffer.obj \ + EfiVfrParser.obj VfrLexer.obj VfrSyntax.obj \ + VfrFormPkg.obj VfrError.obj VfrUtilityLib.obj VfrCompiler.obj + +INC = $(INC) -I $(BASE_TOOLS_PATH)\Source\C\VfrCompile\Pccts\h + +!INCLUDE ..\Makefiles\ms.app + +VfrSyntax.cpp EfiVfrParser.cpp EfiVfrParser.h VfrParser.dlg VfrTokens.h: VfrSyntax.g + pushd . & cd Pccts & $(MAKE) & popd + antlr -CC -e3 -ck 3 -k 2 -fl VfrParser.dlg -ft VfrTokens.h -o . VfrSyntax.g +# pushd . & cd Pccts & $(MAKE) clean + +VfrLexer.cpp VfrLexer.h: VfrParser.dlg + dlg -C2 -i -CC -cl VfrLexer -o . VfrParser.dlg + +ATokenBuffer.obj: Pccts\h\ATokenBuffer.cpp + $(CXX) -c $(CPPFLAGS) $(INC) $? -Fo$@ + +DLexerBase.obj: Pccts\h\DLexerBase.cpp + $(CXX) -c $(CPPFLAGS) $(INC) $? -Fo$@ + +AParser.obj: Pccts\h\AParser.cpp + $(CXX) -c $(CPPFLAGS) $(INC) $? -Fo$@ + +EXTRA_CLEAN_OBJECTS = VfrParser.dlg EfiVfrParser.cpp EfiVfrParser.h \ + VfrLexer.cpp VfrLexer.h \ + VfrSyntax.cpp VfrTokens.h + +clean: localClean +cleanall: localClean localCleanall + +localClean: + -DEL $(EXTRA_CLEAN_OBJECTS) + +localCleanall: + pushd . & cd Pccts & $(MAKE) cleanall & popd diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Makefile.kmk new file mode 100644 index 00000000..821ed919 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Makefile.kmk @@ -0,0 +1,155 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-makefile for the EFI VfrCompile build tool. +# + +# +# Copyright (C) 2013-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# 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, in version 3 of the +# License. +# +# 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 . +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +SUB_DEPTH = ../../../../../../../../.. +include $(KBUILD_PATH)/subheader.kmk + +BLDPROGS += VfrCompile +VfrCompile_TEMPLATE = VBoxEfiBldProg +VfrCompile_DEFS = PCCTS_USE_NAMESPACE_STD __USE_PROTOS +# +# Workaround a crash in the release version of VfrCompile on Windos +# when parsing Tcg2Config.vfr, no time to investigate that deeper right now... +# +if "$(KBUILD_TARGET)" == "win" && "$(KBUILD_TYPE)" == "release" + VfrCompile_CXXFLAGS += -noover -Od +endif +VfrCompile_INCS = \ + . \ + Pccts/h \ + $(VfrCompile_0_OUTDIR) +VfrCompile_SOURCES = \ + VfrCompiler.cpp \ + VfrFormPkg.cpp \ + VfrError.cpp \ + VfrUtilityLib.cpp \ + Pccts/h/AParser.cpp \ + Pccts/h/DLexerBase.cpp \ + Pccts/h/ATokenBuffer.cpp \ + $(VfrCompile_0_OUTDIR)/VfrSyntax.cpp \ + $(VfrCompile_0_OUTDIR)/EfiVfrParser.cpp \ + $(VfrCompile_0_OUTDIR)/VfrLexer.cpp +VfrCompile_INTERMEDIATES = \ + $(VfrCompile_0_OUTDIR)/VfrTokens.h \ + $(VfrCompile_0_OUTDIR)/VfrLexer.h \ + $(VfrCompile_0_OUTDIR)/EfiVfrParser.h +VfrCompile_CLEAN = \ + $(VfrCompile_0_OUTDIR)/VfrSyntax.cpp \ + $(VfrCompile_0_OUTDIR)/EfiVfrParser.cpp \ + $(VfrCompile_0_OUTDIR)/VfrLexer.cpp + +$$(VfrCompile_0_OUTDIR)/VfrSyntax.cpp \ ++ $$(VfrCompile_0_OUTDIR)/EfiVfrParser.cpp \ ++ $$(VfrCompile_0_OUTDIR)/EfiVfrParser.h \ ++ $$(VfrCompile_0_OUTDIR)/VfrParser.dlg \ ++ $$(VfrCompile_0_OUTDIR)/VfrTokens.h: \ + $$(antlr_1_TARGET) \ + $(PATH_SUB_CURRENT)/VfrSyntax.g + $(antlr_1_TARGET) -CC -e3 -ck 3 -k 2 \ + -fl $(dir $@)/VfrParser.dlg \ + -ft $(dir $@)/VfrTokens.h \ + -o $(dir $@) \ + $(VfrCompile_DEFPATH)/VfrSyntax.g + +$$(VfrCompile_0_OUTDIR)/VfrLexer.cpp \ ++ $$(VfrCompile_0_OUTDIR)/VfrLexer.h: \ + $$(dlg_1_TARGET) \ + $$(VfrCompile_0_OUTDIR)/VfrParser.dlg + $(dlg_1_TARGET) -C2 -i -CC -cl VfrLexer \ + -o $(dir $@) \ + $(VfrCompile_0_OUTDIR)/VfrParser.dlg + + +# +# Antlr parser generator from the Purdue Compiler Construction Tool Set. +# +BLDPROGS += antlr +antlr_TEMPLATE = VBoxEfiBldProg +antlr_DEFS = \ + USER_ZZSYN \ + ZZLEXBUFSIZE=65536 \ + __USE_PROTOS +antlr_INCS = \ + Pccts/antlr \ + Pccts/support/set \ + Pccts/h +antlr_SOURCES = \ + Pccts/antlr/antlr.c \ + Pccts/antlr/bits.c \ + Pccts/antlr/build.c \ + Pccts/antlr/egman.c \ + Pccts/antlr/err.c \ + Pccts/antlr/fcache.c \ + Pccts/antlr/fset.c \ + Pccts/antlr/fset2.c \ + Pccts/antlr/gen.c \ + Pccts/antlr/globals.c \ + Pccts/antlr/hash.c \ + Pccts/antlr/lex.c \ + Pccts/antlr/main.c \ + Pccts/antlr/misc.c \ + Pccts/antlr/mrhoist.c \ + Pccts/antlr/pred.c \ + Pccts/antlr/scan.c \ + Pccts/support/set/set.c + +# +# DFA lexical analyzer generator from the Purdue Compiler Construction Tool Set. +# +BLDPROGS += dlg +dlg_TEMPLATE = VBoxEfiBldProg +dlg_DEFS = \ + USER_ZZSYN \ + ZZLEXBUFSIZE=65536 \ + __USE_PROTOS +dlg_INCS = \ + Pccts/dlg \ + Pccts/support/set \ + Pccts/h +dlg_SOURCES = \ + Pccts/dlg/automata.c \ + Pccts/dlg/dlg_a.c \ + Pccts/dlg/dlg_p.c \ + Pccts/dlg/err.c \ + Pccts/dlg/main.c \ + Pccts/dlg/output.c \ + Pccts/dlg/relabel.c \ + Pccts/dlg/support.c \ + Pccts/support/set/set.c + + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_131.txt b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_131.txt new file mode 100644 index 00000000..0888cbf1 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_131.txt @@ -0,0 +1,522 @@ +CHANGES FROM 1.31 + +This file contains the migration of PCCTS from 1.31 in the order that +changes were made. 1.32b7 is the last beta before full 1.32. +Terence Parr, Parr Research Corporation 1995. + + +====================================================================== +1.32b1 +Added Russell Quong to banner, changed banner for output slightly +Fixed it so that you have before / after actions for C++ in class def +Fixed bug in optimizer that made it sometimes forget to set internal + token pointers. Only showed up when a {...} was in the "wrong spot". + +====================================================================== +1.32b2 +Added fixes by Dave Seidel for PC compilers in 32 bit mode (config.h +and set.h). + +====================================================================== +1.32b3 +Fixed hideous bug in code generator for wildcard and for ~token op. + +from Dave Seidel + + Added pcnames.bat + 1. in antlr/main.c: change strcasecmp() to stricmp() + + 2. in dlg/output.c: use DLEXER_C instead on "DLexer.C" + + 3. in h/PBlackBox.h: use instead of + +====================================================================== +1.32b4 +When the -ft option was used, any path prefix screwed up +the gate on the .h files + +Fixed yet another bug due to the optimizer. + +The exception handling thing was a bit wacko: + +a : ( A B )? A B + | A C + ; + exception ... + +caused an exception if "A C" was the input. In other words, +it found that A C didn't match the (A B)? pred and caused +an exception rather than trying the next alt. All I did +was to change the zzmatch_wsig() macros. + +Fixed some problems in gen.c relating to the name of token +class bit sets in the output. + +Added the tremendously cool generalized predicate. For the +moment, I'll give this bried description. + +a : <>? blah + | foo + ; + +This implies that (assuming blah and foo are syntactically +ambiguous) "predicate" indicates the semantic validity of +applying "blah". If "predicate" is false, "foo" is attempted. + +Previously, you had to say: + +a : <>? ID + | ID + ; + +Now, you can simply use "predicate" without the ?: operator +if you turn on ANTLR command line option: "-prc on". This +tells ANTLR to compute that all by itself. It computes n +tokens of lookahead where LT(n) or LATEXT(n) is the farthest +ahead you look. + +If you give a predicate using "-prc on" that is followed +by a construct that can recognize more than one n-sequence, +you will get a warning from ANTLR. For example, + +a : <getText())>>? (ID|INT) + ; + +This is wrong because the predicate will be applied to INTs +as well as ID's. You should use this syntax to make +the predicate more specific: + +a : (ID)? => <getText())>>? (ID|INT) + ; + +which says "don't apply the predicate unless ID is the +current lookahead context". + +You cannot currently have anything in the "(context)? =>" +except sequences such as: + +( LPAREN ID | LPAREN SCOPE )? => <>? + +I haven't tested this THAT much, but it does work for the +C++ grammar. + +====================================================================== +1.32b5 + +Added getLine() to the ANTLRTokenBase and DLGBasedToken classes +left line() for backward compatibility. +---- +Removed SORCERER_TRANSFORM from the ast.h stuff. +------- +Fixed bug in code gen of ANTLR such that nested syn preds work more +efficiently now. The ANTLRTokenBuffer was getting very large +with nested predicates. +------ +Memory leak is now gone from ANTLRTokenBuf; all tokens are deleted. +For backward compatibility reasons, you have to say parser->deleteTokens() +or mytokenbuffer->deleteTokens() but later it will be the default mode. +Say this after the parser is constructed. E.g., + + ParserBlackBox p(stdin); + p.parser()->deleteTokens(); + p.parser()->start_symbol(); + + +============================== +1.32b6 + +Changed so that deleteTokens() will do a delete ((ANTLRTokenBase *)) +on the ptr. This gets the virtual destructor. + +Fixed some weird things in the C++ header files (a few return types). + +Made the AST routines correspond to the book and SORCERER stuff. + +New token stuff: See testcpp/14/test.g + +ANTLR accepts a #pragma gc_tokens which says +[1] Generate label = copy(LT(1)) instead of label=LT(1) for + all labeled token references. +[2] User now has to define ANTLRTokenPtr (as a class or a typedef + to just a pointer) as well as the ANTLRToken class itself. + See the example. + +To delete tokens in token buffer, use deleteTokens() message on parser. + + All tokens that fall off the ANTLRTokenBuffer get deleted + which is what currently happens when deleteTokens() message + has been sent to token buffer. + +We always generate ANTLRTokenPtr instead of 'ANTLRToken *' now. +Then if no pragma set, ANTLR generates a + + class ANTLRToken; + typedef ANTLRToken *ANTLRTokenPtr; + +in each file. + +Made a warning for x:rule_ref <<$x>>; still no warning for $i's, however. +class BB { + +a : x:b y:A <<$x +$y>> + ; + +b : B; + +} +generates +Antlr parser generator Version 1.32b6 1989-1995 +test.g, line 3: error: There are no token ptrs for rule references: '$x' + +=================== +1.32b7: + +[With respect to token object garbage collection (GC), 1.32b7 + backtracks from 1.32b6, but results in better and less intrusive GC. + This is the last beta version before full 1.32.] + +BIGGEST CHANGES: + +o The "#pragma gc_tokens" is no longer used. + +o .C files are now .cpp files (hence, makefiles will have to + be changed; or you can rerun genmk). This is a good move, + but causes some backward incompatibility problems. You can + avoid this by changing CPP_FILE_SUFFIX to ".C" in pccts/h/config.h. + +o The token object class hierarchy has been flattened to include + only three classes: ANTLRAbstractToken, ANTLRCommonToken, and + ANTLRCommonNoRefCountToken. The common token now does garbage + collection via ref counting. + +o "Smart" pointers are now used for garbage collection. That is, + ANTLRTokenPtr is used instead of "ANTLRToken *". + +o The antlr.1 man page has been cleaned up slightly. + +o The SUN C++ compiler now complains less about C++ support code. + +o Grammars which subclass ANTLRCommonToken must wrap all token + pointer references in mytoken(token_ptr). This is the only + serious backward incompatibility. See below. + + +MINOR CHANGES: + +-------------------------------------------------------- +1 deleteTokens() + +The deleteTokens() message to the parser or token buffer has been changed +to one of: + + void noGarbageCollectTokens() { inputTokens->noGarbageCollectTokens(); } + void garbageCollectTokens() { inputTokens->garbageCollectTokens(); } + +The token buffer deletes all non-referenced tokens by default now. + +-------------------------------------------------------- +2 makeToken() + +The makeToken() message returns a new type. The function should look +like: + + virtual ANTLRAbstractToken *makeToken(ANTLRTokenType tt, + ANTLRChar *txt, + int line) + { + ANTLRAbstractToken *t = new ANTLRCommonToken(tt,txt); + t->setLine(line); + return t; + } + +-------------------------------------------------------- +3 TokenType + +Changed TokenType-> ANTLRTokenType (often forces changes in AST defs due +to #[] constructor called to AST(tokentype, string)). + +-------------------------------------------------------- +4 AST() + +You must define AST(ANTLRTokenPtr t) now in your AST class definition. +You might also have to include ATokPtr.h above the definition; e.g., +if AST is defined in a separate file, such as AST.h, it's a good idea +to include ATOKPTR_H (ATokPtr.h). For example, + + #include ATOKPTR_H + class AST : public ASTBase { + protected: + ANTLRTokenPtr token; + public: + AST(ANTLRTokenPtr t) { token = t; } + void preorder_action() { + char *s = token->getText(); + printf(" %s", s); + } + }; + +Note the use of smart pointers rather than "ANTLRToken *". + +-------------------------------------------------------- +5 SUN C++ + +From robertb oakhill.sps.mot.com Bob Bailey. Changed ANTLR C++ output +to avoid an error in Sun C++ 3.0.1. Made "public" return value +structs created to hold multiple return values public. + +-------------------------------------------------------- +6 genmk + +Fixed genmk so that target List.* is not included anymore. It's +called SList.* anyway. + +-------------------------------------------------------- +7 \r vs \n + +Scott Vorthmann fixed antlr.g in ANTLR so that \r +is allowed as the return character as well as \n. + +-------------------------------------------------------- +8 Exceptions + +Bug in exceptions attached to labeled token/tokclass references. Didn't gen +code for exceptions. This didn't work: + +a : "help" x:ID + ; + exception[x] + catch MismatchedToken : <> + +Now ANTLR generates (which is kinda big, but necessary): + + if ( !_match_wsig(ID) ) { + if ( guessing ) goto fail; + _signal=MismatchedToken; + switch ( _signal ) { + case MismatchedToken : + printf("eh?\n"); + _signal = NoSignal; + break; + default : + goto _handler; + } + } + +which implies that you can recover and continue parsing after a missing/bad +token reference. + +-------------------------------------------------------- +9 genmk + +genmk now correctly uses config file for CPP_FILE_SUFFIX stuff. + +-------------------------------------------------------- +10 general cleanup / PURIFY + +Anthony Green suggested a bunch of good general +clean up things for the code; he also suggested a few things to +help out the "PURIFY" memory allocation checker. + +-------------------------------------------------------- +11 $-variable references. + +Manuel ORNATO indicated that a $-variable outside of a rule caused +ANTLR to crash. I fixed this. + +12 Tom Moog suggestion + +Fail action of semantic predicate needs "{}" envelope. FIXED. + +13 references to LT(1). + +I have enclosed all assignments such as: + + _t22 = (ANTLRTokenPtr)LT(1); + +in "if ( !guessing )" so that during backtracking the reference count +for token objects is not increased. + + +TOKEN OBJECT GARBAGE COLLECTION + +1 INTRODUCTION + +The class ANTLRCommonToken is now garbaged collected through a "smart" +pointer called ANTLRTokenPtr using reference counting. Any token +object not referenced by your grammar actions is destroyed by the +ANTLRTokenBuffer when it must make room for more token objects. +Referenced tokens are then destroyed in your parser when local +ANTLRTokenPtr objects are deleted. For example, + +a : label:ID ; + +would be converted to something like: + +void yourclass::a(void) +{ + zzRULE; + ANTLRTokenPtr label=NULL; // used to be ANTLRToken *label; + zzmatch(ID); + label = (ANTLRTokenPtr)LT(1); + consume(); + ... +} + +When the "label" object is destroyed (it's just a pointer to your +input token object LT(1)), it decrements the reference count on the +object created for the ID. If the count goes to zero, the object +pointed by label is deleted. + +To correctly manage the garbage collection, you should use +ANTLRTokenPtr instead of "ANTLRToken *". Most ANTLR support code +(visible to the user) has been modified to use the smart pointers. + +*************************************************************** +Remember that any local objects that you create are not deleted when a +lonjmp() is executed. Unfortunately, the syntactic predicates (...)? +use setjmp()/longjmp(). There are some situations when a few tokens +will "leak". +*************************************************************** + +2 DETAILS + +o The default is to perform token object garbage collection. + You may use parser->noGarbageCollectTokens() to turn off + garbage collection. + + +o The type ANTLRTokenPtr is always defined now (automatically). + If you do not wish to use smart pointers, you will have to + redefined ANTLRTokenPtr by subclassing, changing the header + file or changing ANTLR's code generation (easy enough to + do in gen.c). + +o If you don't use ParserBlackBox, the new initialization sequence is: + + ANTLRTokenPtr aToken = new ANTLRToken; + scan.setToken(mytoken(aToken)); + + where mytoken(aToken) gets an ANTLRToken * from the smart pointer. + +o Define C++ preprocessor symbol DBG_REFCOUNTTOKEN to see a bunch of + debugging stuff for reference counting if you suspect something. + + +3 WHY DO I HAVE TO TYPECAST ALL MY TOKEN POINTERS NOW?????? + +If you subclass ANTLRCommonToken and then attempt to refer to one of +your token members via a token pointer in your grammar actions, the +C++ compiler will complain that your token object does not have that +member. For example, if you used to do this + +<< +class ANTLRToken : public ANTLRCommonToken { + int muck; + ... +}; +>> + +class Foo { +a : t:ID << t->muck = ...; >> ; +} + +Now, you must do change the t->muck reference to: + +a : t:ID << mytoken(t)->muck = ...; >> ; + +in order to downcast 't' to be an "ANTLRToken *" not the +"ANTLRAbstractToken *" resulting from ANTLRTokenPtr::operator->(). +The macro is defined as: + +/* + * Since you cannot redefine operator->() to return one of the user's + * token object types, we must down cast. This is a drag. Here's + * a macro that helps. template: "mytoken(a-smart-ptr)->myfield". + */ +#define mytoken(tp) ((ANTLRToken *)(tp.operator->())) + +You have to use macro mytoken(grammar-label) now because smart +pointers are not specific to a parser's token objects. In other +words, the ANTLRTokenPtr class has a pointer to a generic +ANTLRAbstractToken not your ANTLRToken; the ANTLR support code must +use smart pointers too, but be able to work with any kind of +ANTLRToken. Sorry about this, but it's C++'s fault not mine. Some +nebulous future version of the C++ compilers should obviate the need +to downcast smart pointers with runtime type checking (and by allowing +different return type of overridden functions). + +A way to have backward compatible code is to shut off the token object +garbage collection; i.e., use parser->noGarbageCollectTokens() and +change the definition of ANTLRTokenPtr (that's why you get source code +). + + +PARSER EXCEPTION HANDLING + +I've noticed some weird stuff with the exception handling. I intend +to give this top priority for the "book release" of ANTLR. + +========== +1.32 Full Release + +o Changed Token class hierarchy to be (Thanks to Tom Moog): + + ANTLRAbstractToken + ANTLRRefCountToken + ANTLRCommonToken + ANTLRNoRefCountCommonToken + +o Added virtual panic() to ANTLRAbstractToken. Made ANTLRParser::panic() + virtual also. + +o Cleaned up the dup() stuff in AST hierarchy to use shallowCopy() to + make node copies. John Farr at Medtronic suggested this. I.e., + if you want to use dup() with either ANTLR or SORCERER or -transform + mode with SORCERER, you must defined shallowCopy() as: + + virtual PCCTS_AST *shallowCopy() + { + return new AST; + p->setDown(NULL); + p->setRight(NULL); + return p; + } + + or + + virtual PCCTS_AST *shallowCopy() + { + return new AST(*this); + } + + if you have defined a copy constructor such as + + AST(const AST &t) // shallow copy constructor + { + token = t.token; + iconst = t.iconst; + setDown(NULL); + setRight(NULL); + } + +o Added a warning with -CC and -gk are used together. This is broken, + hence a warning is appropriate. + +o Added warning when #-stuff is used w/o -gt option. + +o Updated MPW installation. + +o "Miller, Philip W." suggested + that genmk be use RENAME_OBJ_FLAG RENAME_EXE_FLAG instead of + hardcoding "-o" in genmk.c. + +o made all exit() calls use EXIT_SUCCESS or EXIT_FAILURE. + +=========================================================================== +1.33 + +EXIT_FAILURE and EXIT_SUCCESS were not always defined. I had to modify +a bunch of files to use PCCTS_EXIT_XXX, which forces a new version. Sorry +about that. + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_133.txt b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_133.txt new file mode 100644 index 00000000..a9e40a12 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_133.txt @@ -0,0 +1,2448 @@ +======================================================================= +List of Implemented Fixes and Changes for Maintenance Releases of PCCTS +======================================================================= + + DISCLAIMER + + The software and these notes are provided "as is". They may include + typographical or technical errors and their authors disclaims all + liability of any kind or nature for damages due to error, fault, + defect, or deficiency regardless of cause. All warranties of any + kind, either express or implied, including, but not limited to, the + implied warranties of merchantability and fitness for a particular + purpose are disclaimed. + + + ------------------------------------------------------- + Note: Items #153 to #1 are now in a separate file named + CHANGES_FROM_133_BEFORE_MR13.txt + ------------------------------------------------------- + +#312. (Changed in MR33) Bug caused by change #299. + + In change #299 a warning message was suppressed when there was + no LT(1) in a semantic predicate and max(k,ck) was 1. The + changed caused the code which set a default predicate depth for + the semantic predicate to be left as 0 rather than set to 1. + + This manifested as an error at line #1559 of mrhost.c + + Reported by Peter Dulimov. + +#311. (Changed in MR33) Added sorcer/lib to Makefile. + + Reported by Dale Martin. + +#310. (Changed in MR32) In C mode zzastPush was spelled zzastpush in one case. + + Reported by Jean-Claude Durand + +#309. (Changed in MR32) Renamed baseName because of VMS name conflict + + Renamed baseName to pcctsBaseName to avoid library name conflict with + VMS library routine. Reported by Jean-François PIÉRONNE. + +#308. (Changed in MR32) Used "template" as name of formal in C routine + + In astlib.h routine ast_scan a formal was named "template". This caused + problems when the C code was compiled with a C++ compiler. Reported by + Sabyasachi Dey. + +#307. (Changed in MR31) Compiler dependent bug in function prototype generation + + The code which generated function prototypes contained a bug which + was compiler/optimization dependent. Under some circumstance an + extra character would be included in portions of a function prototype. + + Reported by David Cook. + +#306. (Changed in MR30) Validating predicate following a token + + A validating predicate which immediately followed a token match + consumed the token after the predicate rather than before. Prior + to this fix (in the following example) isValidTimeScaleValue() in + the predicate would test the text for TIMESCALE rather than for + NUMBER: + + time_scale : + TIMESCALE + <getText())>>? + ts:NUMBER + ( us:MICROSECOND << tVal = ...>> + | ns:NANOSECOND << tVal = ... >> + ) + + Reported by Adalbert Perbandt. + +#305. (Changed in MR30) Alternatives with guess blocks inside (...)* blocks. + + In MR14 change #175 fixed a bug in the prediction expressions for guess + blocks which were of the form (alpha)? beta. Unfortunately, this + resulted in a new bug as exemplified by the example below, which computed + the first set for r as {B} rather than {B C}: + + r : ( (A)? B + | C + )* + + This example doesn't make any sense as A is not a prefix of B, but it + illustrates the problem. This bug did not appear for: + + r : ( (A)? + | C + )* + + because it does not use the (alpha)? beta form. + + Item #175 fixed an asymmetry in ambiguity messages for the following + constructs which appear to have identical ambiguities (between repeating + the loop vs. exiting the loop). MR30 retains this fix, but the implementation + is slightly different. + + r_star : ( (A B)? )* A ; + r_plus : ( (A B)? )+ A ; + + Reported by Arpad Beszedes (beszedes inf.u-szeged.hu). + +#304. (Changed in MR30) Crash when mismatch between output value counts. + + For a rule such as: + + r1 : r2>[i,j]; + r2 >[int i, int j] : A; + + If there were extra actuals for the reference to rule r2 from rule r1 + there antlr would crash. This bug was introduced by change #276. + + Reported by Sinan Karasu. + +#303. (Changed in MR30) DLGLexerBase::replchar + + DLGLexerBase::replchar and the C mode routine zzreplchar did not work + properly when the new character was 0. + + Reported with fix by Philippe Laporte + +#302. (Changed in MR28) Fix significant problems in initial release of MR27. + +#301. (Changed in MR27) Default tab stops set to 2 spaces. + + To have antlr generate true tabs rather than spaces, use "antlr -tab 0". + To generate 4 spaces per tab stop use "antlr -tab 4" + +#300. (Changed in MR27) + + Consider the following methods of constructing an AST from ID: + + rule1! + : id:ID << #0 = #[id]; >> ; + + rule2! + : id:ID << #0 = #id; >> ; + + rule3 + : ID ; + + rule4 + : id:ID << #0 = #id; >> ; + + For rule_2, the AST corresponding to id would always be NULL. This + is because the user explicitly suppressed AST construction using the + "!" operator on the rule. In MR27 the use of an AST expression + such as #id overrides the "!" operator and forces construction of + the AST. + + This fix does not apply to C mode ASTs when the ASTs are referenced + using numbers rather than symbols. + + For C mode, this requires that the (optional) function/macro zzmk_ast + be defined. This functions copies information from an attribute into + a previously allocated AST. + + Reported by Jan Langer (jan langernetz.de) + +#299. (Changed in MR27) Don't warn if k=1 and semantic predicate missing LT(i) + + If a semantic does not have a reference to LT(i) or (C mode LATEXT(i)) + then pccts doesn't know how many lookahead tokens to use for context. + However, if max(k,ck) is 1 then there is really only one choice and + the warning is unnecessary. + +#298. (Changed in MR27) Removed "register" for lastpos in dlgauto.c zzgettok + +#297. (Changed in MR27) Incorrect prototypes when used with classic C + + There were a number of errors in function headers when antlr was + built with compilers that do not have __STDC__ or __cplusplus set. + + The functions which have variable length argument lists now use + PCCTS_USE_STDARG rather than __USE_PROTOTYPES__ to determine + whether to use stdargs or varargs. + +#296. (Changed in MR27) Complex return types in rules. + + The following return type was not properly handled when + unpacking a struct with containing multiple return values: + + rule > [int i, IIR_Bool (IIR_Decl::*constraint)()] : ... + + Instead of using "constraint", the program got lost and used + an empty string. + + Reported by P.A. Wilsey. + +#295. (Changed in MR27) Extra ";" following zzGUESS_DONE sometimes. + + Certain constructs with guess blocks in MR23 led to extra ";" + preceding the "else" clause of an "if". + + Reported by P.A. Wilsey. + +#294. (Changed in MR27) Infinite loop in antlr for nested blocks + + An oversight in detecting an empty alternative sometimes led + to an infinite loop in antlr when it encountered a rule with + nested blocks and guess blocks. + + Reported by P.A. Wilsey. + +#293. (Changed in MR27) Sorcerer optimization of _t->type() + + Sorcerer generated code may contain many calls to _t->type() in a + single statement. This change introduces a temporary variable + to eliminate unnecesary function calls. + + Change implemented by Tom Molteno (tim videoscript.com). + +#292. (Changed in MR27) + + WARNING: Item #267 changes the signature of methods in the AST class. + + **** Be sure to revise your AST functions of the same name *** + +#291. (Changed in MR24) + + Fix to serious code generation error in MR23 for (...)+ block. + +#290. (Changed in MR23) + + Item #247 describes a change in the way {...} blocks handled + an error. Consider: + + r1 : {A} b ; + b : B; + + with input "C". + + Prior to change #247, the error would resemble "expected B - + found C". This is correct but incomplete, and therefore + misleading. In #247 it was changed to "expected A, B - found + C". This was fine, except for users of parser exception + handling because the exception was generated in the epilogue + for {...} block rather than in rule b. This made it difficult + for users of parser exception handling because B was not + expected in that context. Those not using parser exception + handling didn't notice the difference. + + The current change restores the behavior prior to #247 when + parser exceptions are present, but retains the revised behavior + otherwise. This change should be visible only when exceptions + are in use and only for {...} blocks and sub-blocks of the form + (something|something | something | epsilon) where epsilon represents + an empty production and it is the last alternative of a sub-block. + In contrast, (something | epsilon | something) should generate the + same code as before, even when exceptions are used. + + Reported by Philippe Laporte (philippe at transvirtual.com). + +#289. (Changed in MR23) Bug in matching complement of a #tokclass + + Prior to MR23 when a #tokclass was matched in both its complemented form + and uncomplemented form, the bit set generated for its first use was used + for both cases. However, the prediction expression was correctly computed + in both cases. This meant that the second case would never be matched + because, for the second appearance, the prediction expression and the + set to be matched would be complements of each other. + + Consider: + + #token A "a" + #token B "b" + #token C "c" + #tokclass AB {A B} + + r1 : AB /* alt 1x */ + | ~AB /* alt 1y */ + ; + + Prior to MR23, this resulted in alternative 1y being unreachable. Had it + been written: + + r2 : ~AB /* alt 2x */ + : AB /* alt 2y */ + + then alternative 2y would have become unreachable. + + This bug was only for the case of complemented #tokclass. For complemented + #token the proper code was generated. + +#288. (Changed in MR23) #errclass not restricted to choice points + + The #errclass directive is supposed to allow a programmer to define + print strings which should appear in syntax error messages as a replacement + for some combinations of tokens. For instance: + + #errclass Operator {PLUS MINUS TIMES DIVIDE} + + If a syntax message includes all four of these tokens, and there is no + "better" choice of error class, the word "Operator" will be used rather + than a list of the four token names. + + Prior to MR23 the #errclass definitions were used only at choice points + (which call the FAIL macro). In other cases where there was no choice + (e.g. where a single token or token class were matched) the #errclass + information was not used. + + With MR23 the #errclass declarations are used for syntax error messages + when matching a #tokclass, a wildcard (i.e. "*"), or the complement of a + #token or #tokclass (e.g. ~Operator). + + Please note that #errclass may now be defined using #tokclass names + (see Item #284). + + Reported by Philip A. Wilsey. + +#287. (Changed in MR23) Print name for #tokclass + + Item #148 describes how to give a print name to a #token so that,for + example, #token ID could have the expression "identifier" in syntax + error messages. This has been extended to #tokclass: + + #token ID("identifier") "[a-zA-Z]+" + #tokclass Primitive("primitive type") + {INT, FLOAT, CHAR, FLOAT, DOUBLE, BOOL} + + This is really a cosmetic change, since #tokclass names do not appear + in any error messages. + +#286. (Changed in MR23) Makefile change to use of cd + + In cases where a pccts subdirectory name matched a directory identified + in a $CDPATH environment variable the build would fail. All makefile + cd commands have been changed from "cd xyz" to "cd ./xyz" in order + to avoid this problem. + +#285. (Changed in MR23) Check for null pointers in some dlg structures + + An invalid regular expression can cause dlg to build an invalid + structure to represent the regular expression even while it issues + error messages. Additional pointer checks were added. + + Reported by Robert Sherry. + +#284. (Changed in MR23) Allow #tokclass in #errclass definitions + + Previously, a #tokclass reference in the definition of an + #errclass was not handled properly. Instead of being expanded + into the set of tokens represented by the #tokclass it was + treated somewhat like an #errclass. However, in a later phase + when all #errclass were expanded into the corresponding tokens + the #tokclass reference was not expanded (because it wasn't an + #errclass). In effect the reference was ignored. + + This has been fixed. + + Problem reported by Mike Dimmick (mike dimmick.demon.co.uk). + +#283. (Changed in MR23) Option -tmake invoke's parser's tmake + + When the string #(...) appears in an action antlr replaces it with + a call to ASTBase::tmake(...) to construct an AST. It is sometimes + useful to change the tmake routine so that it has access to information + in the parser - something which is not possible with a static method + in an application where they may be multiple parsers active. + + The antlr option -tmake replaces the call to ASTBase::tmake with a call + to a user supplied tmake routine. + +#282. (Changed in MR23) Initialization error for DBG_REFCOUNTTOKEN + + When the pre-processor symbol DBG_REFCOUNTTOKEN is defined + incorrect code is generated to initialize ANTLRRefCountToken::ctor and + dtor. + + Fix reported by Sven Kuehn (sven sevenkuehn.de). + +#281. (Changed in MR23) Addition of -noctor option for Sorcerer + + Added a -noctor option to suppress generation of the blank ctor + for users who wish to define their own ctor. + + Contributed by Jan Langer (jan langernetz.de). + +#280. (Changed in MR23) Syntax error message for EOF token + + The EOF token now receives special treatment in syntax error messages + because there is no text matched by the eof token. The token name + of the eof token is used unless it is "@" - in which case the string + "" is used. + + Problem reported by Erwin Achermann (erwin.achermann switzerland.org). + +#279. (Changed in MR23) Exception groups + + There was a bug in the way that exception groups were attached to + alternatives which caused problems when there was a block contained + in an alternative. For instance, in the following rule; + + statement : IF S { ELSE S } + exception .... + ; + + the exception would be attached to the {...} block instead of the + entire alternative because it was attached, in error, to the last + alternative instead of the last OPEN alternative. + + Reported by Ty Mordane (tymordane hotmail.com). + +#278. (Changed in MR23) makefile changes + + Contributed by Tomasz Babczynski (faster lab05-7.ict.pwr.wroc.pl). + + The -cfile option is not absolutely needed: when extension of + source file is one of the well-known C/C++ extensions it is + treated as C/C++ source + + The gnu make defines the CXX variable as the default C++ compiler + name, so I added a line to copy this (if defined) to the CCC var. + + Added a -sor option: after it any -class command defines the class + name for sorcerer, not for ANTLR. A file extended with .sor is + treated as sorcerer input. Because sorcerer can be called multiple + times, -sor option can be repeated. Any files and classes (one class + per group) after each -sor makes one tree parser. + + Not implemented: + + 1. Generate dependences for user c/c++ files. + 2. Support for -sor in c mode not. + + I have left the old genmk program in the directory as genmk_old.c. + +#277. (Changed in MR23) Change in macro for failed semantic predicates + + In the past, a semantic predicate that failed generated a call to + the macro zzfailed_pred: + + #ifndef zzfailed_pred + #define zzfailed_pred(_p) \ + if (guessing) { \ + zzGUESS_FAIL; \ + } else { \ + something(_p) + } + #endif + + If a user wished to use the failed action option for semantic predicates: + + rule : <>? [my_fail_action] A + | ... + + + the code for my_fail_action would have to contain logic for handling + the guess part of the zzfailed_pred macro. The user should not have + to be aware of the guess logic in writing the fail action. + + The zzfailed_pred has been rewritten to have three arguments: + + arg 1: the stringized predicate of the semantic predicate + arg 2: 0 => there is no user-defined fail action + 1 => there is a user-defined fail action + arg 3: the user-defined fail action (if defined) + otherwise a no-operation + + The zzfailed_pred macro is now defined as: + + #ifndef zzfailed_pred + #define zzfailed_pred(_p,_hasuseraction,_useraction) \ + if (guessing) { \ + zzGUESS_FAIL; \ + } else { \ + zzfailed_pred_action(_p,_hasuseraction,_useraction) \ + } + #endif + + + With zzfailed_pred_action defined as: + + #ifndef zzfailed_pred_action + #define zzfailed_pred_action(_p,_hasuseraction,_useraction) \ + if (_hasUserAction) { _useraction } else { failedSemanticPredicate(_p); } + #endif + + In C++ mode failedSemanticPredicate() is a virtual function. + In C mode the default action is a fprintf statement. + + Suggested by Erwin Achermann (erwin.achermann switzerland.org). + +#276. (Changed in MR23) Addition of return value initialization syntax + + In an attempt to reduce the problems caused by the PURIFY macro I have + added new syntax for initializing the return value of rules and the + antlr option "-nopurify". + + A rule with a single return argument: + + r1 > [Foo f = expr] : + + now generates code that resembles: + + Foo r1(void) { + Foo _retv = expr; + ... + } + + A rule with more than one return argument: + + r2 > [Foo f = expr1, Bar b = expr2 ] : + + generates code that resembles: + + struct _rv1 { + Foo f; + Bar b; + } + + _rv1 r2(void) { + struct _rv1 _retv; + _retv.f = expr1; + _retv.b = expr2; + ... + } + + C++ style comments appearing in the initialization list may cause problems. + +#275. (Changed in MR23) Addition of -nopurify option to antlr + + A long time ago the PURIFY macro was introduced to initialize + return value arguments and get rid of annoying messages from program + that checked for uninitialized variables. + + This has caused significant annoyance for C++ users that had + classes with virtual functions or non-trivial constructors because + it would zero the object, including the pointer to the virtual + function table. This could be defeated by redefining + the PURIFY macro to be empty, but it was a constant surprise to + new C++ users of pccts. + + I would like to remove it, but I fear that some existing programs + depend on it and would break. My temporary solution is to add + an antlr option -nopurify which disables generation of the PURIFY + macro call. + + The PURIFY macro should be avoided in favor of the new syntax + for initializing return arguments described in item #275. + + To avoid name clash, the PURIFY macro has been renamed PCCTS_PURIFY. + +#274. (Changed in MR23) DLexer.cpp renamed to DLexer.h + (Changed in MR23) ATokPtr.cpp renamed to ATokPtrImpl.h + + These two files had .cpp extensions but acted like .h files because + there were included in other files. This caused problems for many IDE. + I have renamed them. The ATokPtrImpl.h was necessary because there was + already an ATokPtr.h. + +#273. (Changed in MR23) Default win32 library changed to multi-threaded DLL + + The model used for building the Win32 debug and release libraries has changed + to multi-threaded DLL. + + To make this change in your MSVC 6 project: + + Project -> Settings + Select the C++ tab in the right pane of the dialog box + Select "Category: Code Generation" + Under "Use run-time library" select one of the following: + + Multi-threaded DLL + Debug Multi-threaded DLL + + Suggested by Bill Menees (bill.menees gogallagher.com) + +#272. (Changed in MR23) Failed semantic predicate reported via virtual function + + In the past, a failed semantic predicated reported the problem via a + macro which used fprintf(). The macro now expands into a call on + the virtual function ANTLRParser::failedSemanticPredicate(). + +#271. (Changed in MR23) Warning for LT(i), LATEXT(i) in token match actions + + An bug (or at least an oddity) is that a reference to LT(1), LA(1), + or LATEXT(1) in an action which immediately follows a token match + in a rule refers to the token matched, not the token which is in + the lookahead buffer. Consider: + + r : abc <> D <> E; + + In this case LT(1) in action alpha will refer to the next token in + the lookahead buffer ("D"), but LT(1) in action beta will refer to + the token matched by D - the preceding token. + + A warning has been added for users about this when an action + following a token match contains a reference to LT(1), LA(1), or LATEXT(1). + + This behavior should be changed, but it appears in too many programs + now. Another problem, perhaps more significant, is that the obvious + fix (moving the consume() call to before the action) could change the + order in which input is requested and output appears in existing programs. + + This problem was reported, along with a fix by Benjamin Mandel + (beny sd.co.il). However, I felt that changing the behavior was too + dangerous for existing code. + +#270. (Changed in MR23) Removed static objects from PCCTSAST.cpp + + There were some statically allocated objects in PCCTSAST.cpp + These were changed to non-static. + +#269. (Changed in MR23) dlg output for initializing static array + + The output from dlg contains a construct similar to the + following: + + struct XXX { + static const int size; + static int array1[5]; + }; + + const int XXX::size = 4; + int XXX::array1[size+1]; + + + The problem is that although the expression "size+1" used in + the definition of array1 is equal to 5 (the expression used to + declare array), it is not considered equivalent by some compilers. + + Reported with fix by Volker H. Simonis (simonis informatik.uni-tuebingen.de) + +#268. (Changed in MR23) syn() routine output when k > 1 + + The syn() routine is supposed to print out the text of the + token causing the syntax error. It appears that it always + used the text from the first lookahead token rather than the + appropriate one. The appropriate one is computed by comparing + the token codes of lookahead token i (for i = 1 to k) with + the FIRST(i) set. + + This has been corrected in ANTLRParser::syn(). + + Reported by Bill Menees (bill.menees gogallagher.com) + +#267. (Changed in MR23) AST traversal functions client data argument + + The AST traversal functions now take an extra (optional) parameter + which can point to client data: + + preorder_action(void* pData = NULL) + preorder_before_action(void* pData = NULL) + preorder_after_action(void* pData = NULL) + + **** Warning: this changes the AST signature. *** + **** Be sure to revise your AST functions of the same name *** + + Bill Menees (bill.menees gogallagher.com) + +#266. (Changed in MR23) virtual function printMessage() + + Bill Menees (bill.menees gogallagher.com) has completed the + tedious tasks of replacing all calls to fprintf() with calls + to the virtual function printMessage(). For classes which + have a pointer to the parser it forwards the printMessage() + call to the parser's printMessage() routine. + + This should make it significantly easier to redirect pccts + error and warning messages. + +#265. (Changed in MR23) Remove "labase++" in C++ mode + + In C++ mode labase++ is called when a token is matched. + It appears that labase is not used in C++ mode at all, so + this code has been commented out. + +#264. (Changed in MR23) Complete rewrite of ParserBlackBox.h + + The parser black box (PBlackBox.h) was completely rewritten + by Chris Uzdavinis (chris atdesk.com) to improve its robustness. + +#263. (Changed in MR23) -preamble and -preamble_first rescinded + + Changes for item #253 have been rescinded. + +#262. (Changed in MR23) Crash with -alpha option during traceback + + Under some circumstances a -alpha traceback was started at the + "wrong" time. As a result, internal data structures were not + initialized. + + Reported by Arpad Beszedes (beszedes inf.u-szeged.hu). + +#261. (Changed in MR23) Defer token fetch for C++ mode + + Item #216 has been revised to indicate that use of the defer fetch + option (ZZDEFER_FETCH) requires dlg option -i. + +#260. (MR22) Raise default lex buffer size from 8,000 to 32,000 bytes. + + ZZLEXBUFSIZE is the size (in bytes) of the buffer used by dlg + generated lexers. The default value has been raised to 32,000 and + the value used by antlr, dlg, and sorcerer has also been raised to + 32,000. + +#259. (MR22) Default function arguments in C++ mode. + + If a rule is declared: + + rr [int i = 0] : .... + + then the declaration generated by pccts resembles: + + void rr(int i = 0); + + however, the definition must omit the default argument: + + void rr(int i) {...} + + In the past the default value was not omitted. In MR22 + the generated code resembles: + + void rr(int i /* = 0 */ ) {...} + + Implemented by Volker H. Simonis (simonis informatik.uni-tuebingen.de) + + + Note: In MR23 this was changed so that nested C style comments + ("/* ... */") would not cause problems. + +#258. (MR22) Using a base class for your parser + + In item #102 (MR10) the class statement was extended to allow one + to specify a base class other than ANTLRParser for the generated + parser. It turned out that this was less than useful because + the constructor still specified ANTLRParser as the base class. + + The class statement now uses the first identifier appearing after + the ":" as the name of the base class. For example: + + class MyParser : public FooParser { + + Generates in MyParser.h: + + class MyParser : public FooParser { + + Generates in MyParser.cpp something that resembles: + + MyParser::MyParser(ANTLRTokenBuffer *input) : + FooParser(input,1,0,0,4) + { + token_tbl = _token_tbl; + traceOptionValueDefault=1; // MR10 turn trace ON + } + + The base class constructor must have a signature similar to + that of ANTLRParser. + +#257. (MR21a) Removed dlg statement that -i has no effect in C++ mode. + + This was incorrect. + +#256. (MR21a) Malformed syntax graph causes crash after error message. + + In the past, certain kinds of errors in the very first grammar + element could cause the construction of a malformed graph + representing the grammar. This would eventually result in a + fatal internal error. The code has been changed to be more + resistant to this particular error. + +#255. (MR21a) ParserBlackBox(FILE* f) + + This constructor set openByBlackBox to the wrong value. + + Reported by Kees Bakker (kees_bakker tasking.nl). + +#254. (MR21a) Reporting syntax error at end-of-file + + When there was a syntax error at the end-of-file the syntax + error routine would substitute "" for the programmer's + end-of-file symbol. This substitution is now done only when + the programmer does not define his own end-of-file symbol + or the symbol begins with the character "@". + + Reported by Kees Bakker (kees_bakker tasking.nl). + +#253. (MR21) Generation of block preamble (-preamble and -preamble_first) + + *** This change was rescinded by item #263 *** + + The antlr option -preamble causes antlr to insert the code + BLOCK_PREAMBLE at the start of each rule and block. It does + not insert code before rules references, token references, or + actions. By properly defining the macro BLOCK_PREAMBLE the + user can generate code which is specific to the start of blocks. + + The antlr option -preamble_first is similar, but inserts the + code BLOCK_PREAMBLE_FIRST(PreambleFirst_123) where the symbol + PreambleFirst_123 is equivalent to the first set defined by + the #FirstSetSymbol described in Item #248. + + I have not investigated how these options interact with guess + mode (syntactic predicates). + +#252. (MR21) Check for null pointer in trace routine + + When some trace options are used when the parser is generated + without the trace enabled, the current rule name may be a + NULL pointer. A guard was added to check for this in + restoreState. + + Reported by Douglas E. Forester (dougf projtech.com). + +#251. (MR21) Changes to #define zzTRACE_RULES + + The macro zzTRACE_RULES was being use to pass information to + AParser.h. If this preprocessor symbol was not properly + set the first time AParser.h was #included, the declaration + of zzTRACEdata would be omitted (it is used by the -gd option). + Subsequent #includes of AParser.h would be skipped because of + the #ifdef guard, so the declaration of zzTracePrevRuleName would + never be made. The result was that proper compilation was very + order dependent. + + The declaration of zzTRACEdata was made unconditional and the + problem of removing unused declarations will be left to optimizers. + + Diagnosed by Douglas E. Forester (dougf projtech.com). + +#250. (MR21) Option for EXPERIMENTAL change to error sets for blocks + + The antlr option -mrblkerr turns on an experimental feature + which is supposed to provide more accurate syntax error messages + for k=1, ck=1 grammars. When used with k>1 or ck>1 grammars the + behavior should be no worse than the current behavior. + + There is no problem with the matching of elements or the computation + of prediction expressions in pccts. The task is only one of listing + the most appropriate tokens in the error message. The error sets used + in pccts error messages are approximations of the exact error set when + optional elements in (...)* or (...)+ are involved. While entirely + correct, the error messages are sometimes not 100% accurate. + + There is also a minor philosophical issue. For example, suppose the + grammar expects the token to be an optional A followed by Z, and it + is X. X, of course, is neither A nor Z, so an error message is appropriate. + Is it appropriate to say "Expected Z" ? It is correct, it is accurate, + but it is not complete. + + When k>1 or ck>1 the problem of providing the exactly correct + list of tokens for the syntax error messages ends up becoming + equivalent to evaluating the prediction expression for the + alternatives twice. However, for k=1 ck=1 grammars the prediction + expression can be computed easily and evaluated cheaply, so I + decided to try implementing it to satisfy a particular application. + This application uses the error set in an interactive command language + to provide prompts which list the alternatives available at that + point in the parser. The user can then enter additional tokens to + complete the command line. To do this required more accurate error + sets then previously provided by pccts. + + In some cases the default pccts behavior may lead to more robust error + recovery or clearer error messages then having the exact set of tokens. + This is because (a) features like -ge allow the use of symbolic names for + certain sets of tokens, so having extra tokens may simply obscure things + and (b) the error set is use to resynchronize the parser, so a good + choice is sometimes more important than having the exact set. + + Consider the following example: + + Note: All examples code has been abbreviated + to the absolute minimum in order to make the + examples concise. + + star1 : (A)* Z; + + The generated code resembles: + + old new (with -mrblkerr) + --//----------- -------------------- + for (;;) { for (;;) { + match(A); match(A); + } } + match(Z); if (! A and ! Z) then + FAIL(...{A,Z}...); + } + match(Z); + + + With input X + old message: Found X, expected Z + new message: Found X, expected A, Z + + For the example: + + star2 : (A|B)* Z; + + old new (with -mrblkerr) + ------------- -------------------- + for (;;) { for (;;) { + if (!A and !B) break; if (!A and !B) break; + if (...) { if (...) { + + } } + else { else { + FAIL(...{A,B,Z}...) FAIL(...{A,B}...); + } } + } } + match(B); if (! A and ! B and !Z) then + FAIL(...{A,B,Z}...); + } + match(B); + + With input X + old message: Found X, expected Z + new message: Found X, expected A, B, Z + With input A X + old message: Found X, expected Z + new message: Found X, expected A, B, Z + + This includes the choice of looping back to the + star block. + + The code for plus blocks: + + plus1 : (A)+ Z; + + The generated code resembles: + + old new (with -mrblkerr) + ------------- -------------------- + do { do { + match(A); match(A); + } while (A) } while (A) + match(Z); if (! A and ! Z) then + FAIL(...{A,Z}...); + } + match(Z); + + With input A X + old message: Found X, expected Z + new message: Found X, expected A, Z + + This includes the choice of looping back to the + plus block. + + For the example: + + plus2 : (A|B)+ Z; + + old new (with -mrblkerr) + ------------- -------------------- + do { do { + if (A) { + match(A); + } else if (B) { + match(B); + } else { + if (cnt > 1) break; + FAIL(...{A,B,Z}...) FAIL(...{A,B}...); + } } + cnt++; + } } + + match(Z); if (! A and ! B and !Z) then + FAIL(...{A,B,Z}...); + } + match(B); + + With input X + old message: Found X, expected A, B, Z + new message: Found X, expected A, B + With input A X + old message: Found X, expected Z + new message: Found X, expected A, B, Z + + This includes the choice of looping back to the + star block. + +#249. (MR21) Changes for DEC/VMS systems + + Jean-François Piéronne (jfp altavista.net) has updated some + VMS related command files and fixed some minor problems related + to building pccts under the DEC/VMS operating system. For DEC/VMS + users the most important differences are: + + a. Revised makefile.vms + b. Revised genMMS for genrating VMS style makefiles. + +#248. (MR21) Generate symbol for first set of an alternative + + pccts can generate a symbol which represents the tokens which may + appear at the start of a block: + + rr : #FirstSetSymbol(rr_FirstSet) ( Foo | Bar ) ; + + This will generate the symbol rr_FirstSet of type SetWordType with + elements Foo and Bar set. The bits can be tested using code similar + to the following: + + if (set_el(Foo, &rr_FirstSet)) { ... + + This can be combined with the C array zztokens[] or the C++ routine + tokenName() to get the print name of the token in the first set. + + The size of the set is given by the newly added enum SET_SIZE, a + protected member of the generated parser's class. The number of + elements in the generated set will not be exactly equal to the + value of SET_SIZE because of synthetic tokens created by #tokclass, + #errclass, the -ge option, and meta-tokens such as epsilon, and + end-of-file. + + The #FirstSetSymbol must appear immediately before a block + such as (...)+, (...)*, and {...}, and (...). It may not appear + immediately before a token, a rule reference, or action. However + a token or rule reference can be enclosed in a (...) in order to + make the use of #pragma FirstSetSymbol legal. + + rr_bad : #FirstSetSymbol(rr_bad_FirstSet) Foo; // Illegal + + rr_ok : #FirstSetSymbol(rr_ok_FirstSet) (Foo); // Legal + + Do not confuse FirstSetSymbol sets with the sets used for testing + lookahead. The sets used for FirstSetSymbol have one element per bit, + so the number of bytes is approximately the largest token number + divided by 8. The sets used for testing lookahead store 8 lookahead + sets per byte, so the length of the array is approximately the largest + token number. + + If there is demand, a similar routine for follow sets can be added. + +#247. (MR21) Misleading error message on syntax error for optional elements. + + =================================================== + The behavior has been revised when parser exception + handling is used. See Item #290 + =================================================== + + Prior to MR21, tokens which were optional did not appear in syntax + error messages if the block which immediately followed detected a + syntax error. + + Consider the following grammar which accepts Number, Word, and Other: + + rr : {Number} Word; + + For this rule the code resembles: + + if (LA(1) == Number) { + match(Number); + consume(); + } + match(Word); + + Prior to MR21, the error message for input "$ a" would be: + + line 1: syntax error at "$" missing Word + + With MR21 the message will be: + + line 1: syntax error at "$" expecting Word, Number. + + The generate code resembles: + + if ( (LA(1)==Number) ) { + zzmatch(Number); + consume(); + } + else { + if ( (LA(1)==Word) ) { + /* nothing */ + } + else { + FAIL(... message for both Number and Word ...); + } + } + match(Word); + + The code generated for optional blocks in MR21 is slightly longer + than the previous versions, but it should give better error messages. + + The code generated for: + + { a | b | c } + + should now be *identical* to: + + ( a | b | c | ) + + which was not the case prior to MR21. + + Reported by Sue Marvin (sue siara.com). + +#246. (Changed in MR21) Use of $(MAKE) for calls to make + + Calls to make from the makefiles were replaced with $(MAKE) + because of problems when using gmake. + + Reported with fix by Sunil K.Vallamkonda (sunil siara.com). + +#245. (Changed in MR21) Changes to genmk + + The following command line options have been added to genmk: + + -cfiles ... + + To add a user's C or C++ files into makefile automatically. + The list of files must be enclosed in apostrophes. This + option may be specified multiple times. + + -compiler ... + + The name of the compiler to use for $(CCC) or $(CC). The + default in C++ mode is "CC". The default in C mode is "cc". + + -pccts_path ... + + The value for $(PCCTS), the pccts directory. The default + is /usr/local/pccts. + + Contributed by Tomasz Babczynski (t.babczynski ict.pwr.wroc.pl). + +#244. (Changed in MR21) Rename variable "not" in antlr.g + + When antlr.g is compiled with a C++ compiler, a variable named + "not" causes problems. Reported by Sinan Karasu + (sinan.karasu boeing.com). + +#243 (Changed in MR21) Replace recursion with iteration in zzfree_ast + + Another refinement to zzfree_ast in ast.c to limit recursion. + + NAKAJIMA Mutsuki (muc isr.co.jp). + + +#242. (Changed in MR21) LineInfoFormatStr + + Added an #ifndef/#endif around LineInfoFormatStr in pcctscfg.h. + +#241. (Changed in MR21) Changed macro PURIFY to a no-op + + *********************** + *** NOT IMPLEMENTED *** + *********************** + + The PURIFY macro was changed to a no-op because it was causing + problems when passing C++ objects. + + The old definition: + + #define PURIFY(r,s) memset((char *) &(r),'\\0',(s)); + + The new definition: + + #define PURIFY(r,s) /* nothing */ +#endif + +#240. (Changed in MR21) sorcerer/h/sorcerer.h _MATCH and _MATCHRANGE + + Added test for NULL token pointer. + + Suggested by Peter Keller (keller ebi.ac.uk) + +#239. (Changed in MR21) C++ mode AParser::traceGuessFail + + If tracing is turned on when the code has been generated + without trace code, a failed guess generates a trace report + even though there are no other trace reports. This + make the behavior consistent with other parts of the + trace system. + + Reported by David Wigg (wiggjd sbu.ac.uk). + +#238. (Changed in MR21) Namespace version #include files + + Changed reference from CStdio to cstdio (and other + #include file names) in the namespace version of pccts. + Should have known better. + +#237. (Changed in MR21) ParserBlackBox(FILE*) + + In the past, ParserBlackBox would close the FILE in the dtor + even though it was not opened by ParserBlackBox. The problem + is that there were two constructors, one which accepted a file + name and did an fopen, the other which accepted a FILE and did + not do an fopen. There is now an extra member variable which + remembers whether ParserBlackBox did the open or not. + + Suggested by Mike Percy (mpercy scires.com). + +#236. (Changed in MR21) tmake now reports down pointer problem + + When ASTBase::tmake attempts to update the down pointer of + an AST it checks to see if the down pointer is NULL. If it + is not NULL it does not do the update and returns NULL. + An attempt to update the down pointer is almost always a + result of a user error. This can lead to difficult to find + problems during tree construction. + + With this change, the routine calls a virtual function + reportOverwriteOfDownPointer() which calls panic to + report the problem. Users who want the old behavior can + redefined the virtual function in their AST class. + + Suggested by Sinan Karasu (sinan.karasu boeing.com) + +#235. (Changed in MR21) Made ANTLRParser::resynch() virtual + + Suggested by Jerry Evans (jerry swsl.co.uk). + +#234. (Changed in MR21) Implicit int for function return value + + ATokenBuffer:bufferSize() did not specify a type for the + return value. + + Reported by Hai Vo-Ba (hai fc.hp.com). + +#233. (Changed in MR20) Converted to MSVC 6.0 + + Due to external circumstances I have had to convert to MSVC 6.0 + The MSVC 5.0 project files (.dsw and .dsp) have been retained as + xxx50.dsp and xxx50.dsw. The MSVC 6.0 files are named xxx60.dsp + and xxx60.dsw (where xxx is the related to the directory/project). + +#232. (Changed in MR20) Make setwd bit vectors protected in parser.h + + The access for the setwd array in the parser header was not + specified. As a result, it would depend on the code which + preceded it. In MR20 it will always have access "protected". + + Reported by Piotr Eljasiak (eljasiak zt.gdansk.tpsa.pl). + +#231. (Changed in MR20) Error in token buffer debug code. + + When token buffer debugging is selected via the pre-processor + symbol DEBUG_TOKENBUFFER there is an erroneous check in + AParser.cpp: + + #ifdef DEBUG_TOKENBUFFER + if (i >= inputTokens->bufferSize() || + inputTokens->minTokens() < LLk ) /* MR20 Was "<=" */ + ... + #endif + + Reported by David Wigg (wiggjd sbu.ac.uk). + +#230. (Changed in MR20) Fixed problem with #define for -gd option + + There was an error in setting zzTRACE_RULES for the -gd (trace) option. + + Reported by Gary Funck (gary intrepid.com). + +#229. (Changed in MR20) Additional "const" for literals + + "const" was added to the token name literal table. + "const" was added to some panic() and similar routine + +#228. (Changed in MR20) dlg crashes on "()" + + The following token definition will cause DLG to crash. + + #token "()" + + When there is a syntax error in a regular expression + many of the dlg routines return a structure which has + null pointers. When this is accessed by callers it + generates the crash. + + I have attempted to fix the more common cases. + + Reported by Mengue Olivier (dolmen bigfoot.com). + +#227. (Changed in MR20) Array overwrite + + Steveh Hand (sassth unx.sas.com) reported a problem which + was traced to a temporary array which was not properly + resized for deeply nested blocks. This has been fixed. + +#226. (Changed in MR20) -pedantic conformance + + G. Hobbelt (i_a mbh.org) and THM made many, many minor + changes to create prototypes for all the functions and + bring antlr, dlg, and sorcerer into conformance with + the gcc -pedantic option. + + This may require uses to add pccts/h/pcctscfg.h to some + files or makefiles in order to have __USE_PROTOS defined. + +#225 (Changed in MR20) AST stack adjustment in C mode + + The fix in #214 for AST stack adjustment in C mode missed + some cases. + + Reported with fix by Ger Hobbelt (i_a mbh.org). + +#224 (Changed in MR20) LL(1) and LL(2) with #pragma approx + + This may take a record for the oldest, most trival, lexical + error in pccts. The regular expressions for LL(1) and LL(2) + lacked an escape for the left and right parenthesis. + + Reported by Ger Hobbelt (i_a mbh.org). + +#223 (Changed in MR20) Addition of IBM_VISUAL_AGE directory + + Build files for antlr, dlg, and sorcerer under IBM Visual Age + have been contributed by Anton Sergeev (ags mlc.ru). They have + been placed in the pccts/IBM_VISUAL_AGE directory. + +#222 (Changed in MR20) Replace __STDC__ with __USE_PROTOS + + Most occurrences of __STDC__ replaced with __USE_PROTOS due to + complaints from several users. + +#221 (Changed in MR20) Added #include for DLexerBase.h to PBlackBox. + + Added #include for DLexerBase.h to PBlackBox. + +#220 (Changed in MR19) strcat arguments reversed in #pred parse + + The arguments to strcat are reversed when creating a print + name for a hash table entry for use with #pred feature. + + Problem diagnosed and fix reported by Scott Harrington + (seh4 ix.netcom.com). + +#219. (Changed in MR19) C Mode routine zzfree_ast + + Changes to reduce use of recursion for AST trees with only right + links or only left links in the C mode routine zzfree_ast. + + Implemented by SAKAI Kiyotaka (ksakai isr.co.jp). + +#218. (Changed in MR19) Changes to support unsigned char in C mode + + Changes to antlr.h and err.h to fix omissions in use of zzchar_t + + Implemented by SAKAI Kiyotaka (ksakai isr.co.jp). + +#217. (Changed in MR19) Error message when dlg -i and -CC options selected + + *** This change was rescinded by item #257 *** + + The parsers generated by pccts in C++ mode are not able to support the + interactive lexer option (except, perhaps, when using the deferred fetch + parser option.(Item #216). + + DLG now warns when both -i and -CC are selected. + + This warning was suggested by David Venditti (07751870267-0001 t-online.de). + +#216. (Changed in MR19) Defer token fetch for C++ mode + + Implemented by Volker H. Simonis (simonis informatik.uni-tuebingen.de) + + Normally, pccts keeps the lookahead token buffer completely filled. + This requires max(k,ck) tokens of lookahead. For some applications + this can cause deadlock problems. For example, there may be cases + when the parser can't tell when the input has been completely consumed + until the parse is complete, but the parse can't be completed because + the input routines are waiting for additional tokens to fill the + lookahead buffer. + + When the ANTLRParser class is built with the pre-processor option + ZZDEFER_FETCH defined, the fetch of new tokens by consume() is deferred + until LA(i) or LT(i) is called. + + To test whether this option has been built into the ANTLRParser class + use "isDeferFetchEnabled()". + + Using the -gd trace option with the default tracein() and traceout() + routines will defeat the effort to defer the fetch because the + trace routines print out information about the lookahead token at + the start of the rule. + + Because the tracein and traceout routines are virtual it is + easy to redefine them in your parser: + + class MyParser { + << + virtual void tracein(ANTLRChar * ruleName) + { fprintf(stderr,"Entering: %s\n", ruleName); } + virtual void traceout(ANTLRChar * ruleName) + { fprintf(stderr,"Leaving: %s\n", ruleName); } + >> + + The originals for those routines are pccts/h/AParser.cpp + + This requires use of the dlg option -i (interactive lexer). + + This is implemented only for C++ mode. + + This is experimental. The interaction with guess mode (syntactic + predicates)is not known. + +#215. (Changed in MR19) Addition of reset() to DLGLexerBase + + There was no obvious way to reset the lexer for reuse. The + reset() method now does this. + + Suggested by David Venditti (07751870267-0001 t-online.de). + +#214. (Changed in MR19) C mode: Adjust AST stack pointer at exit + + In C mode the AST stack pointer needs to be reset if there will + be multiple calls to the ANTLRx macros. + + Reported with fix by Paul D. Smith (psmith baynetworks.com). + +#213. (Changed in MR18) Fatal error with -mrhoistk (k>1 hoisting) + + When rearranging code I forgot to un-comment a critical line of + code that handles hoisting of predicates with k>1 lookahead. This + is now fixed. + + Reported by Reinier van den Born (reinier vnet.ibm.com). + +#212. (Changed in MR17) Mac related changes by Kenji Tanaka + + Kenji Tanaka (kentar osa.att.ne.jp) has made a number of changes for + Macintosh users. + + a. The following Macintosh MPW files aid in installing pccts on Mac: + + pccts/MPW_Read_Me + + pccts/install68K.mpw + pccts/installPPC.mpw + + pccts/antlr/antlr.r + pccts/antlr/antlr68K.make + pccts/antlr/antlrPPC.make + + pccts/dlg/dlg.r + pccts/dlg/dlg68K.make + pccts/dlg/dlgPPC.make + + pccts/sorcerer/sor.r + pccts/sorcerer/sor68K.make + pccts/sorcerer/sorPPC.make + + They completely replace the previous Mac installation files. + + b. The most significant is a change in the MAC_FILE_CREATOR symbol + in pcctscfg.h: + + old: #define MAC_FILE_CREATOR 'MMCC' /* Metrowerks C/C++ Text files */ + new: #define MAC_FILE_CREATOR 'CWIE' /* Metrowerks C/C++ Text files */ + + c. Added calls to special_fopen_actions() where necessary. + +#211. (Changed in MR16a) C++ style comment in dlg + + This has been fixed. + +#210. (Changed in MR16a) Sor accepts \r\n, \r, or \n for end-of-line + + A user requested that Sorcerer be changed to accept other forms + of end-of-line. + +#209. (Changed in MR16) Name of files changed. + + Old: CHANGES_FROM_1.33 + New: CHANGES_FROM_133.txt + + Old: KNOWN_PROBLEMS + New: KNOWN_PROBLEMS.txt + +#208. (Changed in MR16) Change in use of pccts #include files + + There were problems with MS DevStudio when mixing Sorcerer and + PCCTS in the same source file. The problem is caused by the + redefinition of setjmp in the MS header file setjmp.h. In + setjmp.h the pre-processor symbol setjmp was redefined to be + _setjmp. A later effort to execute #include resulted + in an effort to #include <_setjmp.h>. I'm not sure whether this + is a bug or a feature. In any case, I decided to fix it by + avoiding the use of pre-processor symbols in #include statements + altogether. This has the added benefit of making pre-compiled + headers work again. + + I've replaced statements: + + old: #include PCCTS_SETJMP_H + new: #include "pccts_setjmp.h" + + Where pccts_setjmp.h contains: + + #ifndef __PCCTS_SETJMP_H__ + #define __PCCTS_SETJMP_H__ + + #ifdef PCCTS_USE_NAMESPACE_STD + #include + #else + #include + #endif + + #endif + + A similar change has been made for other standard header files + required by pccts and sorcerer: stdlib.h, stdarg.h, stdio.h, etc. + + Reported by Jeff Vincent (JVincent novell.com) and Dale Davis + (DalDavis spectrace.com). + +#207. (Changed in MR16) dlg reports an invalid range for: [\0x00-\0xff] + + ----------------------------------------------------------------- + Note from MR23: This fix does not work. I am investigating why. + ----------------------------------------------------------------- + + dlg will report that this is an invalid range. + + Diagnosed by Piotr Eljasiak (eljasiak no-spam.zt.gdansk.tpsa.pl): + + I think this problem is not specific to unsigned chars + because dlg reports no error for the range [\0x00-\0xfe]. + + I've found that information on range is kept in field + letter (unsigned char) of Attrib struct. Unfortunately + the letter value internally is for some reasons increased + by 1, so \0xff is represented here as 0. + + That's why dlg complains about the range [\0x00-\0xff] in + dlg_p.g: + + if ($$.letter > $2.letter) { + error("invalid range ", zzline); + } + + The fix is: + + if ($$.letter > $2.letter && 255 != $$2.letter) { + error("invalid range ", zzline); + } + +#206. (Changed in MR16) Free zzFAILtext in ANTLRParser destructor + + The ANTLRParser destructor now frees zzFAILtext. + + Problem and fix reported by Manfred Kogler (km cast.uni-linz.ac.at). + +#205. (Changed in MR16) DLGStringReset argument now const + + Changed: void DLGStringReset(DLGChar *s) {...} + To: void DLGStringReset(const DLGChar *s) {...} + + Suggested by Dale Davis (daldavis spectrace.com) + +#204. (Changed in MR15a) Change __WATCOM__ to __WATCOMC__ in pcctscfg.h + + Reported by Oleg Dashevskii (olegdash my-dejanews.com). + +#203. (Changed in MR15) Addition of sorcerer to distribution kit + + I have finally caved in to popular demand. The pccts 1.33mr15 + kit will include sorcerer. The separate sorcerer kit will be + discontinued. + +#202. (Changed) in MR15) Organization of MS Dev Studio Projects in Kit + + Previously there was one workspace that contained projects for + all three parts of pccts: antlr, dlg, and sorcerer. Now each + part (and directory) has its own workspace/project and there + is an additional workspace/project to build a library from the + .cpp files in the pccts/h directory. + + The library build will create pccts_debug.lib or pccts_release.lib + according to the configuration selected. + + If you don't want to build pccts 1.33MR15 you can download a + ready-to-run kit for win32 from http://www.polhode.com/win32.zip. + The ready-to-run for win32 includes executables, a pre-built static + library for the .cpp files in the pccts/h directory, and a sample + application + + You will need to define the environment variable PCCTS to point to + the root of the pccts directory hierarchy. + +#201. (Changed in MR15) Several fixes by K.J. Cummings (cummings peritus.com) + + Generation of SETJMP rather than SETJMP_H in gen.c. + + (Sor B19) Declaration of ref_vars_inits for ref_var_inits in + pccts/sorcerer/sorcerer.h. + +#200. (Changed in MR15) Remove operator=() in AToken.h + + User reported that WatCom couldn't handle use of + explicit operator =(). Replace with equivalent + using cast operator. + +#199. (Changed in MR15) Don't allow use of empty #tokclass + + Change antlr.g to disallow empty #tokclass sets. + + Reported by Manfred Kogler (km cast.uni-linz.ac.at). + +#198. Revised ANSI C grammar due to efforts by Manuel Kessler + + Manuel Kessler (mlkessler cip.physik.uni-wuerzburg.de) + + Allow trailing ... in function parameter lists. + Add bit fields. + Allow old-style function declarations. + Support cv-qualified pointers. + Better checking of combinations of type specifiers. + Release of memory for local symbols on scope exit. + Allow input file name on command line as well as by redirection. + + and other miscellaneous tweaks. + + This is not part of the pccts distribution kit. It must be + downloaded separately from: + + http://www.polhode.com/ansi_mr15.zip + +#197. (Changed in MR14) Resetting the lookahead buffer of the parser + + Explanation and fix by Sinan Karasu (sinan.karasu boeing.com) + + Consider the code used to prime the lookahead buffer LA(i) + of the parser when init() is called: + + void + ANTLRParser:: + prime_lookahead() + { + int i; + for(i=1;i<=LLk; i++) consume(); + dirty=0; + //lap = 0; // MR14 - Sinan Karasu (sinan.karusu boeing.com) + //labase = 0; // MR14 + labase=lap; // MR14 + } + + When the parser is instantiated, lap=0,labase=0 is set. + + The "for" loop runs LLk times. In consume(), lap = lap +1 (mod LLk) is + computed. Therefore, lap(before the loop) == lap (after the loop). + + Now the only problem comes in when one does an init() of the parser + after an Eof has been seen. At that time, lap could be non zero. + Assume it was lap==1. Now we do a prime_lookahead(). If LLk is 2, + then + + consume() + { + NLA = inputTokens->getToken()->getType(); + dirty--; + lap = (lap+1)&(LLk-1); + } + + or expanding NLA, + + token_type[lap&(LLk-1)]) = inputTokens->getToken()->getType(); + dirty--; + lap = (lap+1)&(LLk-1); + + so now we prime locations 1 and 2. In prime_lookahead it used to set + lap=0 and labase=0. Now, the next token will be read from location 0, + NOT 1 as it should have been. + + This was never caught before, because if a parser is just instantiated, + then lap and labase are 0, the offending assignment lines are + basically no-ops, since the for loop wraps around back to 0. + +#196. (Changed in MR14) Problems with "(alpha)? beta" guess + + Consider the following syntactic predicate in a grammar + with 2 tokens of lookahead (k=2 or ck=2): + + rule : ( alpha )? beta ; + alpha : S t ; + t : T U + | T + ; + beta : S t Z ; + + When antlr computes the prediction expression with one token + of lookahead for alts 1 and 2 of rule t it finds an ambiguity. + + Because the grammar has a lookahead of 2 it tries to compute + two tokens of lookahead for alts 1 and 2 of t. Alt 1 clearly + has a lookahead of (T U). Alt 2 is one token long so antlr + tries to compute the follow set of alt 2, which means finding + the things which can follow rule t in the context of (alpha)?. + This cannot be computed, because alpha is only part of a rule, + and antlr can't tell what part of beta is matched by alpha and + what part remains to be matched. Thus it impossible for antlr + to properly determine the follow set of rule t. + + Prior to 1.33MR14, the follow of (alpha)? was computed as + FIRST(beta) as a result of the internal representation of + guess blocks. + + With MR14 the follow set will be the empty set for that context. + + Normally, one expects a rule appearing in a guess block to also + appear elsewhere. When the follow context for this other use + is "ored" with the empty set, the context from the other use + results, and a reasonable follow context results. However if + there is *no* other use of the rule, or it is used in a different + manner then the follow context will be inaccurate - it was + inaccurate even before MR14, but it will be inaccurate in a + different way. + + For the example given earlier, a reasonable way to rewrite the + grammar: + + rule : ( alpha )? beta + alpha : S t ; + t : T U + | T + ; + beta : alpha Z ; + + If there are no other uses of the rule appearing in the guess + block it will generate a test for EOF - a workaround for + representing a null set in the lookahead tests. + + If you encounter such a problem you can use the -alpha option + to get additional information: + + line 2: error: not possible to compute follow set for alpha + in an "(alpha)? beta" block. + + With the antlr -alpha command line option the following information + is inserted into the generated file: + + #if 0 + + Trace of references leading to attempt to compute the follow set of + alpha in an "(alpha)? beta" block. It is not possible for antlr to + compute this follow set because it is not known what part of beta has + already been matched by alpha and what part remains to be matched. + + Rules which make use of the incorrect follow set will also be incorrect + + 1 #token T alpha/2 line 7 brief.g + 2 end alpha alpha/3 line 8 brief.g + 2 end (...)? block at start/1 line 2 brief.g + + #endif + + At the moment, with the -alpha option selected the program marks + any rules which appear in the trace back chain (above) as rules with + possible problems computing follow set. + + Reported by Greg Knapen (gregory.knapen bell.ca). + +#195. (Changed in MR14) #line directive not at column 1 + + Under certain circumstances a predicate test could generate + a #line directive which was not at column 1. + + Reported with fix by David Kågedal (davidk lysator.liu.se) + (http://www.lysator.liu.se/~davidk/). + +#194. (Changed in MR14) (C Mode only) Demand lookahead with #tokclass + + In C mode with the demand lookahead option there is a bug in the + code which handles matches for #tokclass (zzsetmatch and + zzsetmatch_wsig). + + The bug causes the lookahead pointer to get out of synchronization + with the current token pointer. + + The problem was reported with a fix by Ger Hobbelt (hobbelt axa.nl). + +#193. (Changed in MR14) Use of PCCTS_USE_NAMESPACE_STD + + The pcctscfg.h now contains the following definitions: + + #ifdef PCCTS_USE_NAMESPACE_STD + #define PCCTS_STDIO_H + #define PCCTS_STDLIB_H + #define PCCTS_STDARG_H + #define PCCTS_SETJMP_H + #define PCCTS_STRING_H + #define PCCTS_ASSERT_H + #define PCCTS_ISTREAM_H + #define PCCTS_IOSTREAM_H + #define PCCTS_NAMESPACE_STD namespace std {}; using namespace std; + #else + #define PCCTS_STDIO_H + #define PCCTS_STDLIB_H + #define PCCTS_STDARG_H + #define PCCTS_SETJMP_H + #define PCCTS_STRING_H + #define PCCTS_ASSERT_H + #define PCCTS_ISTREAM_H + #define PCCTS_IOSTREAM_H + #define PCCTS_NAMESPACE_STD + #endif + + The runtime support in pccts/h uses these pre-processor symbols + consistently. + + Also, antlr and dlg have been changed to generate code which uses + these pre-processor symbols rather than having the names of the + #include files hard-coded in the generated code. + + This required the addition of "#include pcctscfg.h" to a number of + files in pccts/h. + + It appears that this sometimes causes problems for MSVC 5 in + combination with the "automatic" option for pre-compiled headers. + In such cases disable the "automatic" pre-compiled headers option. + + Suggested by Hubert Holin (Hubert.Holin Bigfoot.com). + +#192. (Changed in MR14) Change setText() to accept "const ANTLRChar *" + + Changed ANTLRToken::setText(ANTLRChar *) to setText(const ANTLRChar *). + This allows literal strings to be used to initialize tokens. Since + the usual token implementation (ANTLRCommonToken) makes a copy of the + input string, this was an unnecessary limitation. + + Suggested by Bob McWhirter (bob netwrench.com). + +#191. (Changed in MR14) HP/UX aCC compiler compatibility problem + + Needed to explicitly declare zzINF_DEF_TOKEN_BUFFER_SIZE and + zzINF_BUFFER_TOKEN_CHUNK_SIZE as ints in pccts/h/AParser.cpp. + + Reported by David Cook (dcook bmc.com). + +#190. (Changed in MR14) IBM OS/2 CSet compiler compatibility problem + + Name conflict with "_cs" in pccts/h/ATokenBuffer.cpp + + Reported by David Cook (dcook bmc.com). + +#189. (Changed in MR14) -gxt switch in C mode + + The -gxt switch in C mode didn't work because of incorrect + initialization. + + Reported by Sinan Karasu (sinan boeing.com). + +#188. (Changed in MR14) Added pccts/h/DLG_stream_input.h + + This is a DLG stream class based on C++ istreams. + + Contributed by Hubert Holin (Hubert.Holin Bigfoot.com). + +#187. (Changed in MR14) Rename config.h to pcctscfg.h + + The PCCTS configuration file has been renamed from config.h to + pcctscfg.h. The problem with the original name is that it led + to name collisions when pccts parsers were combined with other + software. + + All of the runtime support routines in pccts/h/* have been + changed to use the new name. Existing software can continue + to use pccts/h/config.h. The contents of pccts/h/config.h is + now just "#include "pcctscfg.h". + + I don't have a record of the user who suggested this. + +#186. (Changed in MR14) Pre-processor symbol DllExportPCCTS class modifier + + Classes in the C++ runtime support routines are now declared: + + class DllExportPCCTS className .... + + By default, the pre-processor symbol is defined as the empty + string. This if for use by MSVC++ users to create DLL classes. + + Suggested by Manfred Kogler (km cast.uni-linz.ac.at). + +#185. (Changed in MR14) Option to not use PCCTS_AST base class for ASTBase + + Normally, the ASTBase class is derived from PCCTS_AST which contains + functions useful to Sorcerer. If these are not necessary then the + user can define the pre-processor symbol "PCCTS_NOT_USING_SOR" which + will cause the ASTBase class to replace references to PCCTS_AST with + references to ASTBase where necessary. + + The class ASTDoublyLinkedBase will contain a pure virtual function + shallowCopy() that was formerly defined in class PCCTS_AST. + + Suggested by Bob McWhirter (bob netwrench.com). + +#184. (Changed in MR14) Grammars with no tokens generate invalid tokens.h + + Reported by Hubert Holin (Hubert.Holin bigfoot.com). + +#183. (Changed in MR14) -f to specify file with names of grammar files + + In DEC/VMS it is difficult to specify very long command lines. + The -f option allows one to place the names of the grammar files + in a data file in order to bypass limitations of the DEC/VMS + command language interpreter. + + Addition supplied by Bernard Giroud (b_giroud decus.ch). + +#182. (Changed in MR14) Output directory option for DEC/VMS + + Fix some problems with the -o option under DEC/VMS. + + Fix supplied by Bernard Giroud (b_giroud decus.ch). + +#181. (Changed in MR14) Allow chars > 127 in DLGStringInput::nextChar() + + Changed DLGStringInput to cast the character using (unsigned char) + so that languages with character codes greater than 127 work + without changes. + + Suggested by Manfred Kogler (km cast.uni-linz.ac.at). + +#180. (Added in MR14) ANTLRParser::getEofToken() + + Added "ANTLRToken ANTLRParser::getEofToken() const" to match the + setEofToken routine. + + Requested by Manfred Kogler (km cast.uni-linz.ac.at). + +#179. (Fixed in MR14) Memory leak for BufFileInput subclass of DLGInputStream + + The BufFileInput class described in Item #142 neglected to release + the allocated buffer when an instance was destroyed. + + Reported by Manfred Kogler (km cast.uni-linz.ac.at). + +#178. (Fixed in MR14) Bug in "(alpha)? beta" guess blocks first sets + + In 1.33 vanilla, and all maintenance releases prior to MR14 + there is a bug in the handling of guess blocks which use the + "long" form: + + (alpha)? beta + + inside a (...)*, (...)+, or {...} block. + + This problem does *not* apply to the case where beta is omitted + or when the syntactic predicate is on the leading edge of an + alternative. + + The problem is that both alpha and beta are stored in the + syntax diagram, and that some analysis routines would fail + to skip the alpha portion when it was not on the leading edge. + Consider the following grammar with -ck 2: + + r : ( (A)? B )* C D + + | A B /* forces -ck 2 computation for old antlr */ + /* reports ambig for alts 1 & 2 */ + + | B C /* forces -ck 2 computation for new antlr */ + /* reports ambig for alts 1 & 3 */ + ; + + The prediction expression for the first alternative should be + LA(1)={B C} LA(2)={B C D}, but previous versions of antlr + would compute the prediction expression as LA(1)={A C} LA(2)={B D} + + Reported by Arpad Beszedes (beszedes inf.u-szeged.hu) who provided + a very clear example of the problem and identified the probable cause. + +#177. (Changed in MR14) #tokdefs and #token with regular expression + + In MR13 the change described by Item #162 caused an existing + feature of antlr to fail. Prior to the change it was possible + to give regular expression definitions and actions to tokens + which were defined via the #tokdefs directive. + + This now works again. + + Reported by Manfred Kogler (km cast.uni-linz.ac.at). + +#176. (Changed in MR14) Support for #line in antlr source code + + Note: this was implemented by Arpad Beszedes (beszedes inf.u-szeged.hu). + + In 1.33MR14 it is possible for a pre-processor to generate #line + directives in the antlr source and have those line numbers and file + names used in antlr error messages and in the #line directives + generated by antlr. + + The #line directive may appear in the following forms: + + #line ll "sss" xx xx ... + + where ll represents a line number, "sss" represents the name of a file + enclosed in quotation marks, and xxx are arbitrary integers. + + The following form (without "line") is not supported at the moment: + + # ll "sss" xx xx ... + + The result: + + zzline + + is replaced with ll from the # or #line directive + + FileStr[CurFile] + + is updated with the contents of the string (if any) + following the line number + + Note + ---- + The file-name string following the line number can be a complete + name with a directory-path. Antlr generates the output files from + the input file name (by replacing the extension from the file-name + with .c or .cpp). + + If the input file (or the file-name from the line-info) contains + a path: + + "../grammar.g" + + the generated source code will be placed in "../grammar.cpp" (i.e. + in the parent directory). This is inconvenient in some cases + (even the -o switch can not be used) so the path information is + removed from the #line directive. Thus, if the line-info was + + #line 2 "../grammar.g" + + then the current file-name will become "grammar.g" + + In this way, the generated source code according to the grammar file + will always be in the current directory, except when the -o switch + is used. + +#175. (Changed in MR14) Bug when guess block appears at start of (...)* + + In 1.33 vanilla and all maintenance releases prior to 1.33MR14 + there is a bug when a guess block appears at the start of a (...)+. + Consider the following k=1 (ck=1) grammar: + + rule : + ( (STAR)? ZIP )* ID ; + + Prior to 1.33MR14, the generated code resembled: + + ... + zzGUESS_BLOCK + while ( 1 ) { + if ( ! LA(1)==STAR) break; + zzGUESS + if ( !zzrv ) { + zzmatch(STAR); + zzCONSUME; + zzGUESS_DONE + zzmatch(ZIP); + zzCONSUME; + ... + + Note that the routine uses STAR for the prediction expression + rather than ZIP. With 1.33MR14 the generated code resembles: + + ... + while ( 1 ) { + if ( ! LA(1)==ZIP) break; + ... + + This problem existed only with (...)* blocks and was caused + by the slightly more complicated graph which represents (...)* + blocks. This caused the analysis routine to compute the first + set for the alpha part of the "(alpha)? beta" rather than the + beta part. + + Both (...)+ and {...} blocks handled the guess block correctly. + + Reported by Arpad Beszedes (beszedes inf.u-szeged.hu) who provided + a very clear example of the problem and identified the probable cause. + +#174. (Changed in MR14) Bug when action precedes syntactic predicate + + In 1.33 vanilla, and all maintenance releases prior to MR14, + there was a bug when a syntactic predicate was immediately + preceded by an action. Consider the following -ck 2 grammar: + + rule : + <> + (alpha)? beta C + | A B + ; + + alpha : A ; + beta : A B; + + Prior to MR14, the code generated for the first alternative + resembled: + + ... + zzGUESS + if ( !zzrv && LA(1)==A && LA(2)==A) { + alpha(); + zzGUESS_DONE + beta(); + zzmatch(C); + zzCONSUME; + } else { + ... + + The prediction expression (i.e. LA(1)==A && LA(2)==A) is clearly + wrong because LA(2) should be matched to B (first[2] of beta is {B}). + + With 1.33MR14 the prediction expression is: + + ... + if ( !zzrv && LA(1)==A && LA(2)==B) { + alpha(); + zzGUESS_DONE + beta(); + zzmatch(C); + zzCONSUME; + } else { + ... + + This will only affect users in which alpha is shorter than + than max(k,ck) and there is an action immediately preceding + the syntactic predicate. + + This problem was reported by reported by Arpad Beszedes + (beszedes inf.u-szeged.hu) who provided a very clear example + of the problem and identified the presence of the init-action + as the likely culprit. + +#173. (Changed in MR13a) -glms for Microsoft style filenames with -gl + + With the -gl option antlr generates #line directives using the + exact name of the input files specified on the command line. + An oddity of the Microsoft C and C++ compilers is that they + don't accept file names in #line directives containing "\" + even though these are names from the native file system. + + With -glms option, the "\" in file names appearing in #line + directives is replaced with a "/" in order to conform to + Microsoft compiler requirements. + + Reported by Erwin Achermann (erwin.achermann switzerland.org). + +#172. (Changed in MR13) \r\n in antlr source counted as one line + + Some MS software uses \r\n to indicate a new line. Antlr + now recognizes this in counting lines. + + Reported by Edward L. Hepler (elh ece.vill.edu). + +#171. (Changed in MR13) #tokclass L..U now allowed + + The following is now allowed: + + #tokclass ABC { A..B C } + + Reported by Dave Watola (dwatola amtsun.jpl.nasa.gov) + +#170. (Changed in MR13) Suppression for predicates with lookahead depth >1 + + In MR12 the capability for suppression of predicates with lookahead + depth=1 was introduced. With MR13 this had been extended to + predicates with lookahead depth > 1 and released for use by users + on an experimental basis. + + Consider the following grammar with -ck 2 and the predicate in rule + "a" with depth 2: + + r1 : (ab)* "@" + ; + + ab : a + | b + ; + + a : (A B)? => <>? A B C + ; + + b : A B C + ; + + Normally, the predicate would be hoisted into rule r1 in order to + determine whether to call rule "ab". However it should *not* be + hoisted because, even if p is false, there is a valid alternative + in rule b. With "-mrhoistk on" the predicate will be suppressed. + + If "-info p" command line option is present the following information + will appear in the generated code: + + while ( (LA(1)==A) + #if 0 + + Part (or all) of predicate with depth > 1 suppressed by alternative + without predicate + + pred << p(LATEXT(2))>>? + depth=k=2 ("=>" guard) rule a line 8 t1.g + tree context: + (root = A + B + ) + + The token sequence which is suppressed: ( A B ) + The sequence of references which generate that sequence of tokens: + + 1 to ab r1/1 line 1 t1.g + 2 ab ab/1 line 4 t1.g + 3 to b ab/2 line 5 t1.g + 4 b b/1 line 11 t1.g + 5 #token A b/1 line 11 t1.g + 6 #token B b/1 line 11 t1.g + + #endif + + A slightly more complicated example: + + r1 : (ab)* "@" + ; + + ab : a + | b + ; + + a : (A B)? => <>? (A B | D E) + ; + + b : <>? D E + ; + + + In this case, the sequence (D E) in rule "a" which lies behind + the guard is used to suppress the predicate with context (D E) + in rule b. + + while ( (LA(1)==A || LA(1)==D) + #if 0 + + Part (or all) of predicate with depth > 1 suppressed by alternative + without predicate + + pred << q(LATEXT(2))>>? + depth=k=2 rule b line 11 t2.g + tree context: + (root = D + E + ) + + The token sequence which is suppressed: ( D E ) + The sequence of references which generate that sequence of tokens: + + 1 to ab r1/1 line 1 t2.g + 2 ab ab/1 line 4 t2.g + 3 to a ab/1 line 4 t2.g + 4 a a/1 line 8 t2.g + 5 #token D a/1 line 8 t2.g + 6 #token E a/1 line 8 t2.g + + #endif + && + #if 0 + + pred << p(LATEXT(2))>>? + depth=k=2 ("=>" guard) rule a line 8 t2.g + tree context: + (root = A + B + ) + + #endif + + (! ( LA(1)==A && LA(2)==B ) || p(LATEXT(2)) ) { + ab(); + ... + +#169. (Changed in MR13) Predicate test optimization for depth=1 predicates + + When the MR12 generated a test of a predicate which had depth 1 + it would use the depth >1 routines, resulting in correct but + inefficient behavior. In MR13, a bit test is used. + +#168. (Changed in MR13) Token expressions in context guards + + The token expressions appearing in context guards such as: + + (A B)? => <>? someRule + + are computed during an early phase of antlr processing. As + a result, prior to MR13, complex expressions such as: + + ~B + L..U + ~L..U + TokClassName + ~TokClassName + + were not computed properly. This resulted in incorrect + context being computed for such expressions. + + In MR13 these context guards are verified for proper semantics + in the initial phase and then re-evaluated after complex token + expressions have been computed in order to produce the correct + behavior. + + Reported by Arpad Beszedes (beszedes inf.u-szeged.hu). + +#167. (Changed in MR13) ~L..U + + Prior to MR13, the complement of a token range was + not properly computed. + +#166. (Changed in MR13) token expression L..U + + The token U was represented as an unsigned char, restricting + the use of L..U to cases where U was assigned a token number + less than 256. This is corrected in MR13. + +#165. (Changed in MR13) option -newAST + + To create ASTs from an ANTLRTokenPtr antlr usually calls + "new AST(ANTLRTokenPtr)". This option generates a call + to "newAST(ANTLRTokenPtr)" instead. This allows a user + to define a parser member function to create an AST object. + + Similar changes for ASTBase::tmake and ASTBase::link were not + thought necessary since they do not create AST objects, only + use existing ones. + +#164. (Changed in MR13) Unused variable _astp + + For many compilations, we have lived with warnings about + the unused variable _astp. It turns out that this variable + can *never* be used because the code which references it was + commented out. + + This investigation was sparked by a note from Erwin Achermann + (erwin.achermann switzerland.org). + +#163. (Changed in MR13) Incorrect makefiles for testcpp examples + + All the examples in pccts/testcpp/* had incorrect definitions + in the makefiles for the symbol "CCC". Instead of CCC=CC they + had CC=$(CCC). + + There was an additional problem in testcpp/1/test.g due to the + change in ANTLRToken::getText() to a const member function + (Item #137). + + Reported by Maurice Mass (maas cuci.nl). + +#162. (Changed in MR13) Combining #token with #tokdefs + + When it became possible to change the print-name of a + #token (Item #148) it became useful to give a #token + statement whose only purpose was to giving a print name + to the #token. Prior to this change this could not be + combined with the #tokdefs feature. + +#161. (Changed in MR13) Switch -gxt inhibits generation of tokens.h + +#160. (Changed in MR13) Omissions in list of names for remap.h + + When a user selects the -gp option antlr creates a list + of macros in remap.h to rename some of the standard + antlr routines from zzXXX to userprefixXXX. + + There were number of omissions from the remap.h name + list related to the new trace facility. This was reported, + along with a fix, by Bernie Solomon (bernard ug.eds.com). + +#159. (Changed in MR13) Violations of classic C rules + + There were a number of violations of classic C style in + the distribution kit. This was reported, along with fixes, + by Bernie Solomon (bernard ug.eds.com). + +#158. (Changed in MR13) #header causes problem for pre-processors + + A user who runs the C pre-processor on antlr source suggested + that another syntax be allowed. With MR13 such directives + such as #header, #pragma, etc. may be written as "\#header", + "\#pragma", etc. For escaping pre-processor directives inside + a #header use something like the following: + + \#header + << + \#include + >> + +#157. (Fixed in MR13) empty error sets for rules with infinite recursion + + When the first set for a rule cannot be computed due to infinite + left recursion and it is the only alternative for a block then + the error set for the block would be empty. This would result + in a fatal error. + + Reported by Darin Creason (creason genedax.com) + +#156. (Changed in MR13) DLGLexerBase::getToken() now public + +#155. (Changed in MR13) Context behind predicates can suppress + + With -mrhoist enabled the context behind a guarded predicate can + be used to suppress other predicates. Consider the following grammar: + + r0 : (r1)+; + + r1 : rp + | rq + ; + rp : <

>? B ; + rq : (A)? => <>? (A|B); + + In earlier versions both predicates "p" and "q" would be hoisted into + rule r0. With MR12c predicate p is suppressed because the context which + follows predicate q includes "B" which can "cover" predicate "p". In + other words, in trying to decide in r0 whether to call r1, it doesn't + really matter whether p is false or true because, either way, there is + a valid choice within r1. + +#154. (Changed in MR13) Making hoist suppression explicit using <> + + A common error, even among experienced pccts users, is to code + an init-action to inhibit hoisting rather than a leading action. + An init-action does not inhibit hoisting. + + This was coded: + + rule1 : <<;>> rule2 + + This is what was meant: + + rule1 : <<;>> <<;>> rule2 + + With MR13, the user can code: + + rule1 : <<;>> <> rule2 + + The following will give an error message: + + rule1 : <> rule2 + + If the <> appears as an init-action rather than a leading + action an error message is issued. The meaning of an init-action + containing "nohoist" is unclear: does it apply to just one + alternative or to all alternatives ? + + + + + + + + + ------------------------------------------------------- + Note: Items #153 to #1 are now in a separate file named + CHANGES_FROM_133_BEFORE_MR13.txt + ------------------------------------------------------- diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_133_BEFORE_MR13.txt b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_133_BEFORE_MR13.txt new file mode 100644 index 00000000..56bced8c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_FROM_133_BEFORE_MR13.txt @@ -0,0 +1,3666 @@ + + ------------------------------------------------------------ + This is the second part of a two part file. + This is a list of changes to pccts 1.33 prior to MR13 + For more recent information see CHANGES_FROM_133.txt + ------------------------------------------------------------ + + DISCLAIMER + + The software and these notes are provided "as is". They may include + typographical or technical errors and their authors disclaims all + liability of any kind or nature for damages due to error, fault, + defect, or deficiency regardless of cause. All warranties of any + kind, either express or implied, including, but not limited to, the + implied warranties of merchantability and fitness for a particular + purpose are disclaimed. + + +#153. (Changed in MR12b) Bug in computation of -mrhoist suppression set + + Consider the following grammar with k=1 and "-mrhoist on": + + r1 : (A)? => ((p>>? x /* l1 */ + | r2 /* l2 */ + ; + r2 : A /* l4 */ + | (B)? => <>? y /* l5 */ + ; + + In earlier versions the mrhoist routine would see that both l1 and + l2 contained predicates and would assume that this prevented either + from acting to suppress the other predicate. In the example above + it didn't realize the A at line l4 is capable of suppressing the + predicate at l1 even though alt l2 contains (indirectly) a predicate. + + This is fixed in MR12b. + + Reported by Reinier van den Born (reinier@vnet.ibm.com) + +#153. (Changed in MR12a) Bug in computation of -mrhoist suppression set + + An oversight similar to that described in Item #152 appeared in + the computation of the set that "covered" a predicate. If a + predicate expression included a term such as p=AND(q,r) the context + of p was taken to be context(q) & context(r), when it should have + been context(q) | context(r). This is fixed in MR12a. + +#152. (Changed in MR12) Bug in generation of predicate expressions + + The primary purpose for MR12 is to make quite clear that MR11 is + obsolete and to fix the bug related to predicate expressions. + + In MR10 code was added to optimize the code generated for + predicate expression tests. Unfortunately, there was a + significant oversight in the code which resulted in a bug in + the generation of code for predicate expression tests which + contained predicates combined using AND: + + r0 : (r1)* "@" ; + r1 : (AAA)? => <

>? r2 ; + r2 : (BBB)? => <>? Q + | (BBB)? => <>? Q + ; + + In MR11 (and MR10 when using "-mrhoist on") the code generated + for r0 to predict r1 would be equivalent to: + + if ( LA(1)==Q && + (LA(1)==AAA && LA(1)==BBB) && + ( p && ( q || r )) ) { + + This is incorrect because it expresses the idea that LA(1) + *must* be AAA in order to attempt r1, and *must* be BBB to + attempt r2. The result was that r1 became unreachable since + both condition can not be simultaneously true. + + The general philosophy of code generation for predicates + can be summarized as follows: + + a. If the context is true don't enter an alt + for which the corresponding predicate is false. + + If the context is false then it is okay to enter + the alt without evaluating the predicate at all. + + b. A predicate created by ORing of predicates has + context which is the OR of their individual contexts. + + c. A predicate created by ANDing of predicates has + (surprise) context which is the OR of their individual + contexts. + + d. Apply these rules recursively. + + e. Remember rule (a) + + The correct code should express the idea that *if* LA(1) is + AAA then p must be true to attempt r1, but if LA(1) is *not* + AAA then it is okay to attempt r1, provided that *if* LA(1) is + BBB then one of q or r must be true. + + if ( LA(1)==Q && + ( !(LA(1)==AAA || LA(1)==BBB) || + ( ! LA(1) == AAA || p) && + ( ! LA(1) == BBB || q || r ) ) ) { + + I believe this is fixed in MR12. + + Reported by Reinier van den Born (reinier@vnet.ibm.com) + +#151a. (Changed in MR12) ANTLRParser::getLexer() + + As a result of several requests, I have added public methods to + get a pointer to the lexer belonging to a parser. + + ANTLRTokenStream *ANTLRParser::getLexer() const + + Returns a pointer to the lexer being used by the + parser. ANTLRTokenStream is the base class of + DLGLexer + + ANTLRTokenStream *ANTLRTokenBuffer::getLexer() const + + Returns a pointer to the lexer being used by the + ANTLRTokenBuffer. ANTLRTokenStream is the base + class of DLGLexer + + You must manually cast the ANTLRTokenStream to your program's + lexer class. Because the name of the lexer's class is not fixed. + Thus it is impossible to incorporate it into the DLGLexerBase + class. + +#151b.(Changed in MR12) ParserBlackBox member getLexer() + + The template class ParserBlackBox now has a member getLexer() + which returns a pointer to the lexer. + +#150. (Changed in MR12) syntaxErrCount and lexErrCount now public + + See Item #127 for more information. + +#149. (Changed in MR12) antlr option -info o (letter o for orphan) + + If there is more than one rule which is not referenced by any + other rule then all such rules are listed. This is useful for + alerting one to rules which are not used, but which can still + contribute to ambiguity. For example: + + start : a Z ; + unused: a A ; + a : (A)+ ; + + will cause an ambiguity report for rule "a" which will be + difficult to understand if the user forgets about rule "unused" + simply because it is not used in the grammar. + +#148. (Changed in MR11) #token names appearing in zztokens,token_tbl + + In a #token statement like the following: + + #token Plus "\+" + + the string "Plus" appears in the zztokens array (C mode) and + token_tbl (C++ mode). This string is used in most error + messages. In MR11 one has the option of using some other string, + (e.g. "+") in those tables. + + In MR11 one can write: + + #token Plus ("+") "\+" + #token RP ("(") "\(" + #token COM ("comment begin") "/\*" + + A #token statement is allowed to appear in more than one #lexclass + with different regular expressions. However, the token name appears + only once in the zztokens/token_tbl array. This means that only + one substitute can be specified for a given #token name. The second + attempt to define a substitute name (different from the first) will + result in an error message. + +#147. (Changed in MR11) Bug in follow set computation + + There is a bug in 1.33 vanilla and all maintenance releases + prior to MR11 in the computation of the follow set. The bug is + different than that described in Item #82 and probably more + common. It was discovered in the ansi.g grammar while testing + the "ambiguity aid" (Item #119). The search for a bug started + when the ambiguity aid was unable to discover the actual source + of an ambiguity reported by antlr. + + The problem appears when an optimization of the follow set + computation is used inappropriately. The result is that the + follow set used is the "worst case". In other words, the error + can lead to false reports of ambiguity. The good news is that + if you have a grammar in which you have addressed all reported + ambiguities you are ok. The bad news is that you may have spent + time fixing ambiguities that were not real, or used k=2 when + ck=2 might have been sufficient, and so on. + + The following grammar demonstrates the problem: + + ------------------------------------------------------------ + expr : ID ; + + start : stmt SEMI ; + + stmt : CASE expr COLON + | expr SEMI + | plain_stmt + ; + + plain_stmt : ID COLON ; + ------------------------------------------------------------ + + When compiled with k=1 and ck=2 it will report: + + warning: alts 2 and 3 of the rule itself ambiguous upon + { IDENTIFIER }, { COLON } + + When antlr analyzes "stmt" it computes the first[1] set of all + alternatives. It finds an ambiguity between alts 2 and 3 for ID. + It then computes the first[2] set for alternatives 2 and 3 to resolve + the ambiguity. In computing the first[2] set of "expr" (which is + only one token long) it needs to determine what could follow "expr". + Under a certain combination of circumstances antlr forgets that it + is trying to analyze "stmt" which can only be followed by SEMI and + adds to the first[2] set of "expr" the "global" follow set (including + "COLON") which could follow "expr" (under other conditions) in the + phrase "CASE expr COLON". + +#146. (Changed in MR11) Option -treport for locating "difficult" alts + + It can be difficult to determine which alternatives are causing + pccts to work hard to resolve an ambiguity. In some cases the + ambiguity is successfully resolved after much CPU time so there + is no message at all. + + A rough measure of the amount of work being peformed which is + independent of the CPU speed and system load is the number of + tnodes created. Using "-info t" gives information about the + total number of tnodes created and the peak number of tnodes. + + Tree Nodes: peak 1300k created 1416k lost 0 + + It also puts in the generated C or C++ file the number of tnodes + created for a rule (at the end of the rule). However this + information is not sufficient to locate the alternatives within + a rule which are causing the creation of tnodes. + + Using: + + antlr -treport 100000 .... + + causes antlr to list on stdout any alternatives which require the + creation of more than 100,000 tnodes, along with the lookahead sets + for those alternatives. + + The following is a trivial case from the ansi.g grammar which shows + the format of the report. This report might be of more interest + in cases where 1,000,000 tuples were created to resolve the ambiguity. + + ------------------------------------------------------------------------- + There were 0 tuples whose ambiguity could not be resolved + by full lookahead + There were 157 tnodes created to resolve ambiguity between: + + Choice 1: statement/2 line 475 file ansi.g + Choice 2: statement/3 line 476 file ansi.g + + Intersection of lookahead[1] sets: + + IDENTIFIER + + Intersection of lookahead[2] sets: + + LPARENTHESIS COLON AMPERSAND MINUS + STAR PLUSPLUS MINUSMINUS ONESCOMPLEMENT + NOT SIZEOF OCTALINT DECIMALINT + HEXADECIMALINT FLOATONE FLOATTWO IDENTIFIER + STRING CHARACTER + ------------------------------------------------------------------------- + +#145. (Documentation) Generation of Expression Trees + + Item #99 was misleading because it implied that the optimization + for tree expressions was available only for trees created by + predicate expressions and neglected to mention that it required + the use of "-mrhoist on". The optimization applies to tree + expressions created for grammars with k>1 and for predicates with + lookahead depth >1. + + In MR11 the optimized version is always used so the -mrhoist on + option need not be specified. + +#144. (Changed in MR11) Incorrect test for exception group + + In testing for a rule's exception group the label a pointer + is compared against '\0'. The intention is "*pointer". + + Reported by Jeffrey C. Fried (Jeff@Fried.net). + +#143. (Changed in MR11) Optional ";" at end of #token statement + + Fixes problem of: + + #token X "x" + + << + parser action + >> + + Being confused with: + + #token X "x" <> + +#142. (Changed in MR11) class BufFileInput subclass of DLGInputStream + + Alexey Demakov (demakov@kazbek.ispras.ru) has supplied class + BufFileInput derived from DLGInputStream which provides a + function lookahead(char *string) to test characters in the + input stream more than one character ahead. + + The default amount of lookahead is specified by the constructor + and defaults to 8 characters. This does *not* include the one + character of lookahead maintained internally by DLG in member "ch" + and which is not available for testing via BufFileInput::lookahead(). + + This is a useful class for overcoming the one-character-lookahead + limitation of DLG without resorting to a lexer capable of + backtracking (like flex) which is not integrated with antlr as is + DLG. + + There are no restrictions on copying or using BufFileInput.* except + that the authorship and related information must be retained in the + source code. + + The class is located in pccts/h/BufFileInput.* of the kit. + +#141. (Changed in MR11) ZZDEBUG_CONSUME for ANTLRParser::consume() + + A debug aid has been added to file ANTLRParser::consume() in + file AParser.cpp: + + #ifdef ZZDEBUG_CONSUME_ACTION + zzdebug_consume_action(); + #endif + + Suggested by Sramji Ramanathan (ps@kumaran.com). + +#140. (Changed in MR11) #pred to define predicates + + +---------------------------------------------------+ + | Note: Assume "-prc on" for this entire discussion | + +---------------------------------------------------+ + + A problem with predicates is that each one is regarded as + unique and capable of disambiguating cases where two + alternatives have identical lookahead. For example: + + rule : <>? A + | <>? A + ; + + will not cause any error messages or warnings to be issued + by earlier versions of pccts. To compare the text of the + predicates is an incomplete solution. + + In 1.33MR11 I am introducing the #pred statement in order to + solve some problems with predicates. The #pred statement allows + one to give a symbolic name to a "predicate literal" or a + "predicate expression" in order to refer to it in other predicate + expressions or in the rules of the grammar. + + The predicate literal associated with a predicate symbol is C + or C++ code which can be used to test the condition. A + predicate expression defines a predicate symbol in terms of other + predicate symbols using "!", "&&", and "||". A predicate symbol + can be defined in terms of a predicate literal, a predicate + expression, or *both*. + + When a predicate symbol is defined with both a predicate literal + and a predicate expression, the predicate literal is used to generate + code, but the predicate expression is used to check for two + alternatives with identical predicates in both alternatives. + + Here are some examples of #pred statements: + + #pred IsLabel <>? + #pred IsLocalVar <>? + #pred IsGlobalVar <>? + #pred IsVar <>? IsLocalVar || IsGlobalVar + #pred IsScoped <>? IsLabel || IsLocalVar + + I hope that the use of EBNF notation to describe the syntax of the + #pred statement will not cause problems for my readers (joke). + + predStatement : "#pred" + CapitalizedName + ( + "<>?" + | "<>?" predOrExpr + | predOrExpr + ) + ; + + predOrExpr : predAndExpr ( "||" predAndExpr ) * ; + + predAndExpr : predPrimary ( "&&" predPrimary ) * ; + + predPrimary : CapitalizedName + | "!" predPrimary + | "(" predOrExpr ")" + ; + + What is the purpose of this nonsense ? + + To understand how predicate symbols help, you need to realize that + predicate symbols are used in two different ways with two different + goals. + + a. Allow simplification of predicates which have been combined + during predicate hoisting. + + b. Allow recognition of identical predicates which can't disambiguate + alternatives with common lookahead. + + First we will discuss goal (a). Consider the following rule: + + rule0: rule1 + | ID + | ... + ; + + rule1: rule2 + | rule3 + ; + + rule2: <>? ID ; + rule3: <>? ID ; + + When the predicates in rule2 and rule3 are combined by hoisting + to create a prediction expression for rule1 the result is: + + if ( LA(1)==ID + && ( isX(LATEXT(1) || !isX(LATEXT(1) ) ) { rule1(); ... + + This is inefficient, but more importantly, can lead to false + assumptions that the predicate expression distinguishes the rule1 + alternative with some other alternative with lookahead ID. In + MR11 one can write: + + #pred IsX <>? + + ... + + rule2: <>? ID ; + rule3: <>? ID ; + + During hoisting MR11 recognizes this as a special case and + eliminates the predicates. The result is a prediction + expression like the following: + + if ( LA(1)==ID ) { rule1(); ... + + Please note that the following cases which appear to be equivalent + *cannot* be simplified by MR11 during hoisting because the hoisting + logic only checks for a "!" in the predicate action, not in the + predicate expression for a predicate symbol. + + *Not* equivalent and is not simplified during hoisting: + + #pred IsX <>? + #pred NotX <>? + ... + rule2: <>? ID ; + rule3: <>? ID ; + + *Not* equivalent and is not simplified during hoisting: + + #pred IsX <>? + #pred NotX !IsX + ... + rule2: <>? ID ; + rule3: <>? ID ; + + Now we will discuss goal (b). + + When antlr discovers that there is a lookahead ambiguity between + two alternatives it attempts to resolve the ambiguity by searching + for predicates in both alternatives. In the past any predicate + would do, even if the same one appeared in both alternatives: + + rule: <>? X + | <>? X + ; + + The #pred statement is a start towards solving this problem. + During ambiguity resolution (*not* predicate hoisting) the + predicates for the two alternatives are expanded and compared. + Consider the following example: + + #pred Upper <>? + #pred Lower <>? + #pred Alpha <>? Upper || Lower + + rule0: rule1 + | <>? ID + ; + + rule1: + | rule2 + | rule3 + ... + ; + + rule2: <>? ID; + rule3: <>? ID; + + The definition of #pred Alpha expresses: + + a. to test the predicate use the C code "isAlpha(LATEXT(1))" + + b. to analyze the predicate use the information that + Alpha is equivalent to the union of Upper and Lower, + + During ambiguity resolution the definition of Alpha is expanded + into "Upper || Lower" and compared with the predicate in the other + alternative, which is also "Upper || Lower". Because they are + identical MR11 will report a problem. + + ------------------------------------------------------------------------- + t10.g, line 5: warning: the predicates used to disambiguate rule rule0 + (file t10.g alt 1 line 5 and alt 2 line 6) + are identical when compared without context and may have no + resolving power for some lookahead sequences. + ------------------------------------------------------------------------- + + If you use the "-info p" option the output file will contain: + + +----------------------------------------------------------------------+ + |#if 0 | + | | + |The following predicates are identical when compared without | + | lookahead context information. For some ambiguous lookahead | + | sequences they may not have any power to resolve the ambiguity. | + | | + |Choice 1: rule0/1 alt 1 line 5 file t10.g | + | | + | The original predicate for choice 1 with available context | + | information: | + | | + | OR expr | + | | + | pred << Upper>>? | + | depth=k=1 rule rule2 line 14 t10.g | + | set context: | + | ID | + | | + | pred << Lower>>? | + | depth=k=1 rule rule3 line 15 t10.g | + | set context: | + | ID | + | | + | The predicate for choice 1 after expansion (but without context | + | information): | + | | + | OR expr | + | | + | pred << isUpper(LATEXT(1))>>? | + | depth=k=1 rule line 1 t10.g | + | | + | pred << isLower(LATEXT(1))>>? | + | depth=k=1 rule line 2 t10.g | + | | + | | + |Choice 2: rule0/2 alt 2 line 6 file t10.g | + | | + | The original predicate for choice 2 with available context | + | information: | + | | + | pred << Alpha>>? | + | depth=k=1 rule rule0 line 6 t10.g | + | set context: | + | ID | + | | + | The predicate for choice 2 after expansion (but without context | + | information): | + | | + | OR expr | + | | + | pred << isUpper(LATEXT(1))>>? | + | depth=k=1 rule line 1 t10.g | + | | + | pred << isLower(LATEXT(1))>>? | + | depth=k=1 rule line 2 t10.g | + | | + | | + |#endif | + +----------------------------------------------------------------------+ + + The comparison of the predicates for the two alternatives takes + place without context information, which means that in some cases + the predicates will be considered identical even though they operate + on disjoint lookahead sets. Consider: + + #pred Alpha + + rule1: <>? ID + | <>? Label + ; + + Because the comparison of predicates takes place without context + these will be considered identical. The reason for comparing + without context is that otherwise it would be necessary to re-evaluate + the entire predicate expression for each possible lookahead sequence. + This would require more code to be written and more CPU time during + grammar analysis, and it is not yet clear whether anyone will even make + use of the new #pred facility. + + A temporary workaround might be to use different #pred statements + for predicates you know have different context. This would avoid + extraneous warnings. + + The above example might be termed a "false positive". Comparison + without context will also lead to "false negatives". Consider the + following example: + + #pred Alpha + #pred Beta + + rule1: <>? A + | rule2 + ; + + rule2: <>? A + | <>? B + ; + + The predicate used for alt 2 of rule1 is (Alpha || Beta). This + appears to be different than the predicate Alpha used for alt1. + However, the context of Beta is B. Thus when the lookahead is A + Beta will have no resolving power and Alpha will be used for both + alternatives. Using the same predicate for both alternatives isn't + very helpful, but this will not be detected with 1.33MR11. + + To properly handle this the predicate expression would have to be + evaluated for each distinct lookahead context. + + To determine whether two predicate expressions are identical is + difficult. The routine may fail to identify identical predicates. + + The #pred feature also compares predicates to see if a choice between + alternatives which is resolved by a predicate which makes the second + choice unreachable. Consider the following example: + + #pred A <>? + #pred B <>? + #pred A_or_B A || B + + r : s + | t + ; + s : <>? ID + ; + t : <>? ID + ; + + ---------------------------------------------------------------------------- + t11.g, line 5: warning: the predicate used to disambiguate the + first choice of rule r + (file t11.g alt 1 line 5 and alt 2 line 6) + appears to "cover" the second predicate when compared without context. + The second predicate may have no resolving power for some lookahead + sequences. + ---------------------------------------------------------------------------- + +#139. (Changed in MR11) Problem with -gp in C++ mode + + The -gp option to add a prefix to rule names did not work in + C++ mode. This has been fixed. + + Reported by Alexey Demakov (demakov@kazbek.ispras.ru). + +#138. (Changed in MR11) Additional makefiles for non-MSVC++ MS systems + + Sramji Ramanathan (ps@kumaran.com) has supplied makefiles for + building antlr and dlg with Win95/NT development tools that + are not based on MSVC5. They are pccts/antlr/AntlrMS.mak and + pccts/dlg/DlgMS.mak. + + The first line of the makefiles require a definition of PCCTS_HOME. + + These are in addition to the AntlrMSVC50.* and DlgMSVC50.* + supplied by Jeff Vincent (JVincent@novell.com). + +#137. (Changed in MR11) Token getType(), getText(), getLine() const members + + -------------------------------------------------------------------- + If you use ANTLRCommonToken this change probably does not affect you. + -------------------------------------------------------------------- + + For a long time it has bothered me that these accessor functions + in ANTLRAbstractToken were not const member functions. I have + refrained from changing them because it require users to modify + existing token class definitions which are derived directly + from ANTLRAbstractToken. I think it is now time. + + For those who are not used to C++, a "const member function" is a + member function which does not modify its own object - the thing + to which "this" points. This is quite different from a function + which does not modify its arguments + + Most token definitions based on ANTLRAbstractToken have something like + the following in order to create concrete definitions of the pure + virtual methods in ANTLRAbstractToken: + + class MyToken : public ANTLRAbstractToken { + ... + ANTLRTokenType getType() {return _type; } + int getLine() {return _line; } + ANTLRChar * getText() {return _text; } + ... + } + + The required change is simply to put "const" following the function + prototype in the header (.h file) and the definition file (.cpp if + it is not inline): + + class MyToken : public ANTLRAbstractToken { + ... + ANTLRTokenType getType() const {return _type; } + int getLine() const {return _line; } + ANTLRChar * getText() const {return _text; } + ... + } + + This was originally proposed a long time ago by Bruce + Guenter (bruceg@qcc.sk.ca). + +#136. (Changed in MR11) Added getLength() to ANTLRCommonToken + + Classes ANTLRCommonToken and ANTLRCommonTokenNoRefCountToken + now have a member function: + + int getLength() const { return strlen(getText()) } + + Suggested by Sramji Ramanathan (ps@kumaran.com). + +#135. (Changed in MR11) Raised antlr's own default ZZLEXBUFSIZE to 8k + +#134a. (ansi_mr10.zip) T.J. Parr's ANSI C grammar made 1.33MR11 compatible + + There is a typographical error in the definition of BITWISEOREQ: + + #token BITWISEOREQ "!=" should be "\|=" + + When this change is combined with the bugfix to the follow set cache + problem (Item #147) and a minor rearrangement of the grammar + (Item #134b) it becomes a k=1 ck=2 grammar. + +#134b. (ansi_mr10.zip) T.J. Parr's ANSI C grammar made 1.33MR11 compatible + + The following changes were made in the ansi.g grammar (along with + using -mrhoist on): + + ansi.g + ====== + void tracein(char *) ====> void tracein(const char *) + void traceout(char *) ====> void traceout(const char *) + + getType()==IDENTIFIER ? isTypeName(LT(1)->getText()) : 1>>? + ====> <getText())>>? + + <<(LT(1)->getType()==LPARENTHESIS && LT(2)->getType()==IDENTIFIER) ? \ + isTypeName(LT(2)->getText()) : 1>>? + ====> (LPARENTHESIS IDENTIFIER)? => <getText())>>? + + <<(LT(1)->getType()==LPARENTHESIS && LT(2)->getType()==IDENTIFIER) ? \ + isTypeName(LT(2)->getText()) : 1>>? + ====> (LPARENTHESIS IDENTIFIER)? => <getText())>>? + + added to init(): traceOptionValueDefault=0; + added to init(): traceOption(-1); + + change rule "statement": + + statement + : plain_label_statement + | case_label_statement + | <<;>> expression SEMICOLON + | compound_statement + | selection_statement + | iteration_statement + | jump_statement + | SEMICOLON + ; + + plain_label_statement + : IDENTIFIER COLON statement + ; + + case_label_statement + : CASE constant_expression COLON statement + | DEFAULT COLON statement + ; + + support.cpp + =========== + void tracein(char *) ====> void tracein(const char *) + void traceout(char *) ====> void traceout(const char *) + + added to tracein(): ANTLRParser::tracein(r); // call superclass method + added to traceout(): ANTLRParser::traceout(r); // call superclass method + + Makefile + ======== + added to AFLAGS: -mrhoist on -prc on + +#133. (Changed in 1.33MR11) Make trace options public in ANTLRParser + + In checking T.J. Parr's ANSI C grammar for compatibility with + 1.33MR11 discovered that it was inconvenient to have the + trace facilities with protected access. + +#132. (Changed in 1.33MR11) Recognition of identical predicates in alts + + Prior to 1.33MR11, there would be no ambiguity warning when the + very same predicate was used to disambiguate both alternatives: + + test: ref B + | ref C + ; + + ref : <>? A + + In 1.33MR11 this will cause the warning: + + warning: the predicates used to disambiguate rule test + (file v98.g alt 1 line 1 and alt 2 line 2) + are identical and have no resolving power + + ----------------- Note ----------------- + + This is different than the following case + + test: <>? A B + | <>? A C + ; + + In this case there are two distinct predicates + which have exactly the same text. In the first + example there are two references to the same + predicate. The problem represented by this + grammar will be addressed later. + +#131. (Changed in 1.33MR11) Case insensitive command line options + + Command line switches like "-CC" and keywords like "on", "off", + and "stdin" are no longer case sensitive in antlr, dlg, and sorcerer. + +#130. (Changed in 1.33MR11) Changed ANTLR_VERSION to int from string + + The ANTLR_VERSION was not an integer, making it difficult to + perform conditional compilation based on the antlr version. + + Henceforth, ANTLR_VERSION will be: + + (base_version * 10000) + release number + + thus 1.33MR11 will be: 133*100+11 = 13311 + + Suggested by Rainer Janssen (Rainer.Janssen@Informatik.Uni-Oldenburg.DE). + +#129. (Changed in 1.33MR11) Addition of ANTLR_VERSION to .h + + The following code is now inserted into .h amd + stdpccts.h: + + #ifndef ANTLR_VERSION + #define ANTLR_VERSION 13311 + #endif + + Suggested by Rainer Janssen (Rainer.Janssen@Informatik.Uni-Oldenburg.DE) + +#128. (Changed in 1.33MR11) Redundant predicate code in (<>? ...)+ + + Prior to 1.33MR11, the following grammar would generate + redundant tests for the "while" condition. + + rule2 : (<>? X)+ X + | B + ; + + The code would resemble: + + if (LA(1)==X) { + if (pred) { + do { + if (!pred) {zzfailed_pred(" pred");} + zzmatch(X); zzCONSUME; + } while (LA(1)==X && pred && pred); + } else {... + + With 1.33MR11 the redundant predicate test is omitted. + +#127. (Changed in 1.33MR11) + + Count Syntax Errors Count DLG Errors + ------------------- ---------------- + + C++ mode ANTLRParser:: DLGLexerBase:: + syntaxErrCount lexErrCount + C mode zzSyntaxErrCount zzLexErrCount + + The C mode variables are global and initialized to 0. + They are *not* reset to 0 automatically when antlr is + restarted. + + The C++ mode variables are public. They are initialized + to 0 by the constructors. They are *not* reset to 0 by the + ANTLRParser::init() method. + + Suggested by Reinier van den Born (reinier@vnet.ibm.com). + +#126. (Changed in 1.33MR11) Addition of #first <<...>> + + The #first <<...>> inserts the specified text in the output + files before any other #include statements required by pccts. + The only things before the #first text are comments and + a #define ANTLR_VERSION. + + Requested by and Esa Pulkkinen (esap@cs.tut.fi) and Alexin + Zoltan (alexin@inf.u-szeged.hu). + +#125. (Changed in 1.33MR11) Lookahead for (guard)? && <

>? predicates + + When implementing the new style of guard predicate (Item #113) + in 1.33MR10 I decided to temporarily ignore the problem of + computing the "narrowest" lookahead context. + + Consider the following k=1 grammar: + + start : a + | b + ; + + a : (A)? && <>? ab ; + b : (B)? && <>? ab ; + + ab : A | B ; + + In MR10 the context for both "a" and "b" was {A B} because this is + the first set of rule "ab". Normally, this is not a problem because + the predicate which follows the guard inhibits any ambiguity report + by antlr. + + In MR11 the first set for rule "a" is {A} and for rule "b" it is {B}. + +#124. A Note on the New "&&" Style Guarded Predicates + + I've been asked several times, "What is the difference between + the old "=>" style guard predicates and the new style "&&" guard + predicates, and how do you choose one over the other" ? + + The main difference is that the "=>" does not apply the + predicate if the context guard doesn't match, whereas + the && form always does. What is the significance ? + + If you have a predicate which is not on the "leading edge" + it cannot be hoisted. Suppose you need a predicate that + looks at LA(2). You must introduce it manually. The + classic example is: + + castExpr : + LP typeName RP + | .... + ; + + typeName : <>? ID + | STRUCT ID + ; + + The problem is that typeName isn't on the leading edge + of castExpr, so the predicate isTypeName won't be hoisted into + castExpr to help make a decision on which production to choose. + + The *first* attempt to fix it is this: + + castExpr : + <>? + LP typeName RP + | .... + ; + + Unfortunately, this won't work because it ignores + the problem of STRUCT. The solution is to apply + isTypeName() in castExpr if LA(2) is an ID and + don't apply it when LA(2) is STRUCT: + + castExpr : + (LP ID)? => <>? + LP typeName RP + | .... + ; + + In conclusion, the "=>" style guarded predicate is + useful when: + + a. the tokens required for the predicate + are not on the leading edge + b. there are alternatives in the expression + selected by the predicate for which the + predicate is inappropriate + + If (b) were false, then one could use a simple + predicate (assuming "-prc on"): + + castExpr : + <>? + LP typeName RP + | .... + ; + + typeName : <>? ID + ; + + So, when do you use the "&&" style guarded predicate ? + + The new-style "&&" predicate should always be used with + predicate context. The context guard is in ADDITION to + the automatically computed context. Thus it useful for + predicates which depend on the token type for reasons + other than context. + + The following example is contributed by Reinier van den Born + (reinier@vnet.ibm.com). + + +-------------------------------------------------------------------------+ + | This grammar has two ways to call functions: | + | | + | - a "standard" call syntax with parens and comma separated args | + | - a shell command like syntax (no parens and spacing separated args) | + | | + | The former also allows a variable to hold the name of the function, | + | the latter can also be used to call external commands. | + | | + | The grammar (simplified) looks like this: | + | | + | fun_call : ID "(" { expr ("," expr)* } ")" | + | /* ID is function name */ | + | | "@" ID "(" { expr ("," expr)* } ")" | + | /* ID is var containing fun name */ | + | ; | + | | + | command : ID expr* /* ID is function name */ | + | | path expr* /* path is external command name */ | + | ; | + | | + | path : ID /* left out slashes and such */ | + | | "@" ID /* ID is environment var */ | + | ; | + | | + | expr : .... | + | | "(" expr ")"; | + | | + | call : fun_call | + | | command | + | ; | + | | + | Obviously the call is wildly ambiguous. This is more or less how this | + | is to be resolved: | + | | + | A call begins with an ID or an @ followed by an ID. | + | | + | If it is an ID and if it is an ext. command name -> command | + | if followed by a paren -> fun_call | + | otherwise -> command | + | | + | If it is an @ and if the ID is a var name -> fun_call | + | otherwise -> command | + | | + | One can implement these rules quite neatly using && predicates: | + | | + | call : ("@" ID)? && <>? fun_call | + | | (ID)? && <>? command | + | | (ID "(")? fun_call | + | | command | + | ; | + | | + | This can be done better, so it is not an ideal example, but it | + | conveys the principle. | + +-------------------------------------------------------------------------+ + +#123. (Changed in 1.33MR11) Correct definition of operators in ATokPtr.h + + The return value of operators in ANTLRTokenPtr: + + changed: unsigned ... operator !=(...) + to: int ... operator != (...) + changed: unsigned ... operator ==(...) + to: int ... operator == (...) + + Suggested by R.A. Nelson (cowboy@VNET.IBM.COM) + +#122. (Changed in 1.33MR11) Member functions to reset DLG in C++ mode + + void DLGFileReset(FILE *f) { input = f; found_eof = 0; } + void DLGStringReset(DLGChar *s) { input = s; p = &input[0]; } + + Supplied by R.A. Nelson (cowboy@VNET.IBM.COM) + +#121. (Changed in 1.33MR11) Another attempt to fix -o (output dir) option + + Another attempt is made to improve the -o option of antlr, dlg, + and sorcerer. This one by JVincent (JVincent@novell.com). + + The current rule: + + a. If -o is not specified than any explicit directory + names are retained. + + b. If -o is specified than the -o directory name overrides any + explicit directory names. + + c. The directory name of the grammar file is *not* stripped + to create the main output file. However it is stil subject + to override by the -o directory name. + +#120. (Changed in 1.33MR11) "-info f" output to stdout rather than stderr + + Added option 0 (e.g. "-info 0") which is a noop. + +#119. (Changed in 1.33MR11) Ambiguity aid for grammars + + The user can ask for additional information on ambiguities reported + by antlr to stdout. At the moment, only one ambiguity report can + be created in an antlr run. + + This feature is enabled using the "-aa" (Ambiguity Aid) option. + + The following options control the reporting of ambiguities: + + -aa ruleName Selects reporting by name of rule + -aa lineNumber Selects reporting by line number + (file name not compared) + + -aam Selects "multiple" reporting for a token + in the intersection set of the + alternatives. + + For instance, the token ID may appear dozens + of times in various paths as the program + explores the rules which are reachable from + the point of an ambiguity. With option -aam + every possible path the search program + encounters is reported. + + Without -aam only the first encounter is + reported. This may result in incomplete + information, but the information may be + sufficient and much shorter. + + -aad depth Selects the depth of the search. + The default value is 1. + + The number of paths to be searched, and the + size of the report can grow geometrically + with the -ck value if a full search for all + contributions to the source of the ambiguity + is explored. + + The depth represents the number of tokens + in the lookahead set which are matched against + the set of ambiguous tokens. A depth of 1 + means that the search stops when a lookahead + sequence of just one token is matched. + + A k=1 ck=6 grammar might generate 5,000 items + in a report if a full depth 6 search is made + with the Ambiguity Aid. The source of the + problem may be in the first token and obscured + by the volume of data - I hesitate to call + it information. + + When the user selects a depth > 1, the search + is first performed at depth=1 for both + alternatives, then depth=2 for both alternatives, + etc. + + Sample output for rule grammar in antlr.g itself: + + +---------------------------------------------------------------------+ + | Ambiguity Aid | + | | + | Choice 1: grammar/70 line 632 file a.g | + | Choice 2: grammar/82 line 644 file a.g | + | | + | Intersection of lookahead[1] sets: | + | | + | "\}" "class" "#errclass" "#tokclass" | + | | + | Choice:1 Depth:1 Group:1 ("#errclass") | + | 1 in (...)* block grammar/70 line 632 a.g | + | 2 to error grammar/73 line 635 a.g | + | 3 error error/1 line 894 a.g | + | 4 #token "#errclass" error/2 line 895 a.g | + | | + | Choice:1 Depth:1 Group:2 ("#tokclass") | + | 2 to tclass grammar/74 line 636 a.g | + | 3 tclass tclass/1 line 937 a.g | + | 4 #token "#tokclass" tclass/2 line 938 a.g | + | | + | Choice:1 Depth:1 Group:3 ("class") | + | 2 to class_def grammar/75 line 637 a.g | + | 3 class_def class_def/1 line 669 a.g | + | 4 #token "class" class_def/3 line 671 a.g | + | | + | Choice:1 Depth:1 Group:4 ("\}") | + | 2 #token "\}" grammar/76 line 638 a.g | + | | + | Choice:2 Depth:1 Group:5 ("#errclass") | + | 1 in (...)* block grammar/83 line 645 a.g | + | 2 to error grammar/93 line 655 a.g | + | 3 error error/1 line 894 a.g | + | 4 #token "#errclass" error/2 line 895 a.g | + | | + | Choice:2 Depth:1 Group:6 ("#tokclass") | + | 2 to tclass grammar/94 line 656 a.g | + | 3 tclass tclass/1 line 937 a.g | + | 4 #token "#tokclass" tclass/2 line 938 a.g | + | | + | Choice:2 Depth:1 Group:7 ("class") | + | 2 to class_def grammar/95 line 657 a.g | + | 3 class_def class_def/1 line 669 a.g | + | 4 #token "class" class_def/3 line 671 a.g | + | | + | Choice:2 Depth:1 Group:8 ("\}") | + | 2 #token "\}" grammar/96 line 658 a.g | + +---------------------------------------------------------------------+ + + For a linear lookahead set ambiguity (where k=1 or for k>1 but + when all lookahead sets [i] with i>? A ; + c : A ; + + Prior to 1.33MR10 the code generated for "start" would resemble: + + while { + if (LA(1)==A && + (!LA(1)==A || isUpper())) { + a(); + } + }; + + This code is wrong because it makes rule "c" unreachable from + "start". The essence of the problem is that antlr fails to + recognize that there can be a valid alternative within "a" even + when the predicate <>? is false. + + In 1.33MR10 with -mrhoist the hoisting of the predicate into + "start" is suppressed because it recognizes that "c" can + cover all the cases where the predicate is false: + + while { + if (LA(1)==A) { + a(); + } + }; + + With the antlr "-info p" switch the user will receive information + about the predicate suppression in the generated file: + + -------------------------------------------------------------- + #if 0 + + Hoisting of predicate suppressed by alternative without predicate. + The alt without the predicate includes all cases where + the predicate is false. + + WITH predicate: line 7 v1.g + WITHOUT predicate: line 7 v1.g + + The context set for the predicate: + + A + + The lookahead set for the alt WITHOUT the semantic predicate: + + A + + The predicate: + + pred << isUpper(LATEXT(1))>>? + depth=k=1 rule b line 9 v1.g + set context: + A + tree context: null + + Chain of referenced rules: + + #0 in rule start (line 5 v1.g) to rule a + #1 in rule a (line 7 v1.g) + + #endif + -------------------------------------------------------------- + + A predicate can be suppressed by a combination of alternatives + which, taken together, cover a predicate: + + start : (a)* "@" ; + + a : b | ca | cb | cc ; + + b : <>? ( A | B | C ) ; + + ca : A ; + cb : B ; + cc : C ; + + Consider a more complex example in which "c" covers only part of + a predicate: + + start : (a)* "@" ; + + a : b + | c + ; + + b : <>? + ( A + | X + ); + + c : A + ; + + Prior to 1.33MR10 the code generated for "start" would resemble: + + while { + if ( (LA(1)==A || LA(1)==X) && + (! (LA(1)==A || LA(1)==X) || isUpper()) { + a(); + } + }; + + With 1.33MR10 and -mrhoist the predicate context is restricted to + the non-covered lookahead. The code resembles: + + while { + if ( (LA(1)==A || LA(1)==X) && + (! (LA(1)==X) || isUpper()) { + a(); + } + }; + + With the antlr "-info p" switch the user will receive information + about the predicate restriction in the generated file: + + -------------------------------------------------------------- + #if 0 + + Restricting the context of a predicate because of overlap + in the lookahead set between the alternative with the + semantic predicate and one without + Without this restriction the alternative without the predicate + could not be reached when input matched the context of the + predicate and the predicate was false. + + WITH predicate: line 11 v4.g + WITHOUT predicate: line 12 v4.g + + The original context set for the predicate: + + A X + + The lookahead set for the alt WITHOUT the semantic predicate: + + A + + The intersection of the two sets + + A + + The original predicate: + + pred << isUpper(LATEXT(1))>>? + depth=k=1 rule b line 15 v4.g + set context: + A X + tree context: null + + The new (modified) form of the predicate: + + pred << isUpper(LATEXT(1))>>? + depth=k=1 rule b line 15 v4.g + set context: + X + tree context: null + + #endif + -------------------------------------------------------------- + + The bad news about -mrhoist: + + (a) -mrhoist does not analyze predicates with lookahead + depth > 1. + + (b) -mrhoist does not look past a guarded predicate to + find context which might cover other predicates. + + For these cases you might want to use syntactic predicates. + When a semantic predicate fails during guess mode the guess + fails and the next alternative is tried. + + Limitation (a) is illustrated by the following example: + + start : (stmt)* EOF ; + + stmt : cast + | expr + ; + cast : <>? LP ID RP ; + + expr : LP ID RP ; + + This is not much different from the first example, except that + it requires two tokens of lookahead context to determine what + to do. This predicate is NOT suppressed because the current version + is unable to handle predicates with depth > 1. + + A predicate can be combined with other predicates during hoisting. + In those cases the depth=1 predicates are still handled. Thus, + in the following example the isUpper() predicate will be suppressed + by line #4 when hoisted from "bizarre" into "start", but will still + be present in "bizarre" in order to predict "stmt". + + start : (bizarre)* EOF ; // #1 + // #2 + bizarre : stmt // #3 + | A // #4 + ; + + stmt : cast + | expr + ; + + cast : <>? LP ID RP ; + + expr : LP ID RP ; + | <>? A + + Limitation (b) is illustrated by the following example of a + context guarded predicate: + + rule : (A)? <

>? // #1 + (A // #2 + |B // #3 + ) // #4 + | <> B // #5 + ; + + Recall that this means that when the lookahead is NOT A then + the predicate "p" is ignored and it attempts to match "A|B". + Ideally, the "B" at line #3 should suppress predicate "q". + However, the current version does not attempt to look past + the guard predicate to find context which might suppress other + predicates. + + In some cases -mrhoist will lead to the reporting of ambiguities + which were not visible before: + + start : (a)* "@"; + a : bc | d; + bc : b | c ; + + b : <>? A; + c : A ; + + d : A ; + + In this case there is a true ambiguity in "a" between "bc" and "d" + which can both match "A". Without -mrhoist the predicate in "b" + is hoisted into "a" and there is no ambiguity reported. However, + with -mrhoist, the predicate in "b" is suppressed by "c" (as it + should be) making the ambiguity in "a" apparent. + + The motivations for these changes were hoisting problems reported + by Reinier van den Born (reinier@vnet.ibm.com) and several others. + +#116. (Changed in 1.33MR10) C++ mode: tracein/traceout rule name is (const char *) + + The prototype for C++ mode routine tracein (and traceout) has changed from + "char *" to "const char *". + +#115. (Changed in 1.33MR10) Using guess mode with exception handlers in C mode + + The definition of the C mode macros zzmatch_wsig and zzsetmatch_wsig + neglected to consider guess mode. When control passed to the rule's + parse exception handler the routine would exit without ever closing the + guess block. This would lead to unpredictable behavior. + + In 1.33MR10 the behavior of exceptions in C mode and C++ mode should be + identical. + +#114. (Changed in 1.33MR10) difference in [zz]resynch() between C and C++ modes + + There was a slight difference in the way C and C++ mode resynchronized + following a parsing error. The C routine would sometimes skip an extra + token before attempting to resynchronize. + + The C routine was changed to match the C++ routine. + +#113. (Changed in 1.33MR10) new context guarded pred: (g)? && <

>? expr + + The existing context guarded predicate: + + rule : (guard)? => <

>? expr + | next_alternative + ; + + generates code which resembles: + + if (lookahead(expr) && (!guard || pred)) { + expr() + } else .... + + This is not suitable for some applications because it allows + expr() to be invoked when the predicate is false. This is + intentional because it is meant to mimic automatically computed + predicate context. + + The new context guarded predicate uses the guard information + differently because it has a different goal. Consider: + + rule : (guard)? && <

>? expr + | next_alternative + ; + + The new style of context guarded predicate is equivalent to: + + rule : <>? expr + | next_alternative + ; + + It generates code which resembles: + + if (lookahead(expr) && guard && pred) { + expr(); + } else ... + + Both forms of guarded predicates severely restrict the form of + the context guard: it can contain no rule references, no + (...)*, no (...)+, and no {...}. It may contain token and + token class references, and alternation ("|"). + + Addition for 1.33MR11: in the token expression all tokens must + be at the same height of the token tree: + + (A ( B | C))? && ... is ok (all height 2) + (A ( B | ))? && ... is not ok (some 1, some 2) + (A B C D | E F G H)? && ... is ok (all height 4) + (A B C D | E )? && ... is not ok (some 4, some 1) + + This restriction is required in order to properly compute the lookahead + set for expressions like: + + rule1 : (A B C)? && <>? rule2 ; + rule2 : (A|X) (B|Y) (C|Z); + + This addition was suggested by Rienier van den Born (reinier@vnet.ibm.com) + +#112. (Changed in 1.33MR10) failed validation predicate in C guess mode + + John Lilley (jlilley@empathy.com) suggested that failed validation + predicates abort a guess rather than reporting a failed error. + This was installed in C++ mode (Item #4). Only now was it noticed + that the fix was never installed for C mode. + +#111. (Changed in 1.33MR10) moved zzTRACEIN to before init action + + When the antlr -gd switch is present antlr generates calls to + zzTRACEIN at the start of a rule and zzTRACEOUT at the exit + from a rule. Prior to 1.33MR10 Tthe call to zzTRACEIN was + after the init-action, which could cause confusion because the + init-actions were reported with the name of the enclosing rule, + rather than the active rule. + +#110. (Changed in 1.33MR10) antlr command line copied to generated file + + The antlr command line is now copied to the generated file near + the start. + +#109. (Changed in 1.33MR10) improved trace information + + The quality of the trace information provided by the "-gd" + switch has been improved significantly. Here is an example + of the output from a test program. It shows the rule name, + the first token of lookahead, the call depth, and the guess + status: + + exit rule gusxx {"?"} depth 2 + enter rule gusxx {"?"} depth 2 + enter rule gus1 {"o"} depth 3 guessing + guess done - returning to rule gus1 {"o"} at depth 3 + (guess mode continues - an enclosing guess is still active) + guess done - returning to rule gus1 {"Z"} at depth 3 + (guess mode continues - an enclosing guess is still active) + exit rule gus1 {"Z"} depth 3 guessing + guess done - returning to rule gusxx {"o"} at depth 2 (guess mode ends) + enter rule gus1 {"o"} depth 3 + guess done - returning to rule gus1 {"o"} at depth 3 (guess mode ends) + guess done - returning to rule gus1 {"Z"} at depth 3 (guess mode ends) + exit rule gus1 {"Z"} depth 3 + line 1: syntax error at "Z" missing SC + ... + + Rule trace reporting is controlled by the value of the integer + [zz]traceOptionValue: when it is positive tracing is enabled, + otherwise it is disabled. Tracing during guess mode is controlled + by the value of the integer [zz]traceGuessOptionValue. When + it is positive AND [zz]traceOptionValue is positive rule trace + is reported in guess mode. + + The values of [zz]traceOptionValue and [zz]traceGuessOptionValue + can be adjusted by subroutine calls listed below. + + Depending on the presence or absence of the antlr -gd switch + the variable [zz]traceOptionValueDefault is set to 0 or 1. When + the parser is initialized or [zz]traceReset() is called the + value of [zz]traceOptionValueDefault is copied to [zz]traceOptionValue. + The value of [zz]traceGuessOptionValue is always initialized to 1, + but, as noted earlier, nothing will be reported unless + [zz]traceOptionValue is also positive. + + When the parser state is saved/restored the value of the trace + variables are also saved/restored. If a restore causes a change in + reporting behavior from on to off or vice versa this will be reported. + + When the -gd option is selected, the macro "#define zzTRACE_RULES" + is added to appropriate output files. + + C++ mode + -------- + int traceOption(int delta) + int traceGuessOption(int delta) + void traceReset() + int traceOptionValueDefault + + C mode + -------- + int zzTraceOption(int delta) + int zzTraceGuessOption(int delta) + void zzTraceReset() + int zzTraceOptionValueDefault + + The argument "delta" is added to the traceOptionValue. To + turn on trace when inside a particular rule one: + + rule : <> + ( + rest-of-rule + ) + <> + ; /* fail clause */ <> + + One can use the same idea to turn *off* tracing within a + rule by using a delta of (-1). + + An improvement in the rule trace was suggested by Sramji + Ramanathan (ps@kumaran.com). + +#108. A Note on Deallocation of Variables Allocated in Guess Mode + + NOTE + ------------------------------------------------------ + This mechanism only works for heap allocated variables + ------------------------------------------------------ + + The rewrite of the trace provides the machinery necessary + to properly free variables or undo actions following a + failed guess. + + The macro zzUSER_GUESS_HOOK(guessSeq,zzrv) is expanded + as part of the zzGUESS macro. When a guess is opened + the value of zzrv is 0. When a longjmp() is executed to + undo the guess, the value of zzrv will be 1. + + The macro zzUSER_GUESS_DONE_HOOK(guessSeq) is expanded + as part of the zzGUESS_DONE macro. This is executed + whether the guess succeeds or fails as part of closing + the guess. + + The guessSeq is a sequence number which is assigned to each + guess and is incremented by 1 for each guess which becomes + active. It is needed by the user to associate the start of + a guess with the failure and/or completion (closing) of a + guess. + + Guesses are nested. They must be closed in the reverse + of the order that they are opened. + + In order to free memory used by a variable during a guess + a user must write a routine which can be called to + register the variable along with the current guess sequence + number provided by the zzUSER_GUESS_HOOK macro. If the guess + fails, all variables tagged with the corresponding guess + sequence number should be released. This is ugly, but + it would require a major rewrite of antlr 1.33 to use + some mechanism other than setjmp()/longjmp(). + + The order of calls for a *successful* guess would be: + + zzUSER_GUESS_HOOK(guessSeq,0); + zzUSER_GUESS_DONE_HOOK(guessSeq); + + The order of calls for a *failed* guess would be: + + zzUSER_GUESS_HOOK(guessSeq,0); + zzUSER_GUESS_HOOK(guessSeq,1); + zzUSER_GUESS_DONE_HOOK(guessSeq); + + The default definitions of these macros are empty strings. + + Here is an example in C++ mode. The zzUSER_GUESS_HOOK and + zzUSER_GUESS_DONE_HOOK macros and myGuessHook() routine + can be used without change in both C and C++ versions. + + ---------------------------------------------------------------------- + << + + #include "AToken.h" + + typedef ANTLRCommonToken ANTLRToken; + + #include "DLGLexer.h" + + int main() { + + { + DLGFileInput in(stdin); + DLGLexer lexer(&in,2000); + ANTLRTokenBuffer pipe(&lexer,1); + ANTLRCommonToken aToken; + P parser(&pipe); + + lexer.setToken(&aToken); + parser.init(); + parser.start(); + }; + + fclose(stdin); + fclose(stdout); + return 0; + } + + >> + + << + char *s=NULL; + + #undef zzUSER_GUESS_HOOK + #define zzUSER_GUESS_HOOK(guessSeq,zzrv) myGuessHook(guessSeq,zzrv); + #undef zzUSER_GUESS_DONE_HOOK + #define zzUSER_GUESS_DONE_HOOK(guessSeq) myGuessHook(guessSeq,2); + + void myGuessHook(int guessSeq,int zzrv) { + if (zzrv == 0) { + fprintf(stderr,"User hook: starting guess #%d\n",guessSeq); + } else if (zzrv == 1) { + free (s); + s=NULL; + fprintf(stderr,"User hook: failed guess #%d\n",guessSeq); + } else if (zzrv == 2) { + free (s); + s=NULL; + fprintf(stderr,"User hook: ending guess #%d\n",guessSeq); + }; + } + + >> + + #token A "a" + #token "[\t \ \n]" <> + + class P { + + start : (top)+ + ; + + top : (which) ? <> + | other <> + ; <> + + which : which2 + ; + + which2 : which3 + ; + which3 + : (label)? <> + | (global)? <> + | (exclamation)? <> + ; + + label : <getText());>> A ":" ; + + global : <getText());>> A "::" ; + + exclamation : <getText());>> A "!" ; + + other : <getText());>> "other" ; + + } + ---------------------------------------------------------------------- + + This is a silly example, but illustrates the idea. For the input + "a ::" with tracing enabled the output begins: + + ---------------------------------------------------------------------- + enter rule "start" depth 1 + enter rule "top" depth 2 + User hook: starting guess #1 + enter rule "which" depth 3 guessing + enter rule "which2" depth 4 guessing + enter rule "which3" depth 5 guessing + User hook: starting guess #2 + enter rule "label" depth 6 guessing + guess failed + User hook: failed guess #2 + guess done - returning to rule "which3" at depth 5 (guess mode continues + - an enclosing guess is still active) + User hook: ending guess #2 + User hook: starting guess #3 + enter rule "global" depth 6 guessing + exit rule "global" depth 6 guessing + guess done - returning to rule "which3" at depth 5 (guess mode continues + - an enclosing guess is still active) + User hook: ending guess #3 + enter rule "global" depth 6 guessing + exit rule "global" depth 6 guessing + exit rule "which3" depth 5 guessing + exit rule "which2" depth 4 guessing + exit rule "which" depth 3 guessing + guess done - returning to rule "top" at depth 2 (guess mode ends) + User hook: ending guess #1 + enter rule "which" depth 3 + ..... + ---------------------------------------------------------------------- + + Remember: + + (a) Only init-actions are executed during guess mode. + (b) A rule can be invoked multiple times during guess mode. + (c) If the guess succeeds the rule will be called once more + without guess mode so that normal actions will be executed. + This means that the init-action might need to distinguish + between guess mode and non-guess mode using the variable + [zz]guessing. + +#107. (Changed in 1.33MR10) construction of ASTs in guess mode + + Prior to 1.33MR10, when using automatic AST construction in C++ + mode for a rule, an AST would be constructed for elements of the + rule even while in guess mode. In MR10 this no longer occurs. + +#106. (Changed in 1.33MR10) guess variable confusion + + In C++ mode a guess which failed always restored the parser state + using zzGUESS_DONE as part of zzGUESS_FAIL. Prior to 1.33MR10, + C mode required an explicit call to zzGUESS_DONE after the + call to zzGUESS_FAIL. + + Consider: + + rule : (alpha)? beta + | ... + ; + + The generated code resembles: + + zzGUESS + if (!zzrv && LA(1)==ID) { <==== line #1 + alpha + zzGUESS_DONE + beta + } else { + if (! zzrv) zzGUESS_DONE <==== line #2a + .... + + However, in some cases line #2 was rendered: + + if (guessing) zzGUESS_DONE <==== line #2b + + This would work for simple test cases, but would fail in + some cases where there was a guess while another guess was active. + One kind of failure would be to match up the zzGUESS_DONE at line + #2b with the "outer" guess which was still active. The outer + guess would "succeed" when only the inner guess should have + succeeded. + + In 1.33MR10 the behavior of zzGUESS and zzGUESS_FAIL in C and + and C++ mode should be identical. + + The same problem appears in 1.33 vanilla in some places. For + example: + + start : { (sub)? } ; + + or: + + start : ( + B + | ( sub )? + | C + )+ + ; + + generates incorrect code. + + The general principle is: + + (a) use [zz]guessing only when deciding between a call to zzFAIL + or zzGUESS_FAIL + + (b) use zzrv in all other cases + + This problem was discovered while testing changes to item #105. + I believe this is now fixed. My apologies. + +#105. (Changed in 1.33MR10) guess block as single alt of (...)+ + + Prior to 1.33MR10 the following constructs: + + rule_plus : ( + (sub)? + )+ + ; + + rule_star : ( + (sub)? + )* + ; + + generated incorrect code for the guess block (which could result + in runtime errors) because of an incorrect optimization of a + block with only a single alternative. + + The fix caused some changes to the fix described in Item #49 + because there are now three code generation sequences for (...)+ + blocks containing a guess block: + + a. single alternative which is a guess block + b. multiple alternatives in which the last is a guess block + c. all other cases + + Forms like "rule_star" can have unexpected behavior when there + is a syntax error: if the subrule "sub" is not matched *exactly* + then "rule_star" will consume no tokens. + + Reported by Esa Pulkkinen (esap@cs.tut.fi). + +#104. (Changed in 1.33MR10) -o option for dlg + + There was problem with the code added by item #74 to handle the + -o option of dlg. This should fix it. + +#103. (Changed in 1.33MR10) ANDed semantic predicates + + Rescinded. + + The optimization was a mistake. + The resulting problem is described in Item #150. + +#102. (Changed in 1.33MR10) allow "class parser : .... {" + + The syntax of the class statement ("class parser-name {") + has been extended to allow for the specification of base + classes. An arbitrary number of tokens may now appear + between the class name and the "{". They are output + again when the class declaration is generated. For + example: + + class Parser : public MyBaseClassANTLRparser { + + This was suggested by a user, but I don't have a record + of who it was. + +#101. (Changed in 1.33MR10) antlr -info command line switch + + -info + + p - extra predicate information in generated file + + t - information about tnode use: + at the end of each rule in generated file + summary on stderr at end of program + + m - monitor progress + prints name of each rule as it is started + flushes output at start of each rule + + f - first/follow set information to stdout + + 0 - no operation (added in 1.33MR11) + + The options may be combined and may appear in any order. + For example: + + antlr -info ptm -CC -gt -mrhoist on mygrammar.g + +#100a. (Changed in 1.33MR10) Predicate tree simplification + + When the same predicates can be referenced in more than one + alternative of a block large predicate trees can be formed. + + The difference that these optimizations make is so dramatic + that I have decided to use it even when -mrhoist is not selected. + + Consider the following grammar: + + start : ( all )* ; + + all : a + | d + | e + | f + ; + + a : c A B + | c A C + ; + + c : <>? + ; + + d : <>? B C + ; + + e : <>? B C + ; + + f : e X Y + ; + + In rule "a" there is a reference to rule "c" in both alternatives. + The length of the predicate AAA is k=2 and it can be followed in + alternative 1 only by (A B) while in alternative 2 it can be + followed only by (A C). Thus they do not have identical context. + + In rule "all" the alternatives which refer to rules "e" and "f" allow + elimination of the duplicate reference to predicate CCC. + + The table below summarized the kind of simplification performed by + 1.33MR10. In the table, X and Y stand for single predicates + (not trees). + + (OR X (OR Y (OR Z))) => (OR X Y Z) + (AND X (AND Y (AND Z))) => (AND X Y Z) + + (OR X (... (OR X Y) ... )) => (OR X (... Y ... )) + (AND X (... (AND X Y) ... )) => (AND X (... Y ... )) + (OR X (... (AND X Y) ... )) => (OR X (... ... )) + (AND X (... (OR X Y) ... )) => (AND X (... ... )) + + (AND X) => X + (OR X) => X + + In a test with a complex grammar for a real application, a predicate + tree with six OR nodes and 12 leaves was reduced to "(OR X Y Z)". + + In 1.33MR10 there is a greater effort to release memory used + by predicates once they are no longer in use. + +#100b. (Changed in 1.33MR10) Suppression of extra predicate tests + + The following optimizations require that -mrhoist be selected. + + It is relatively easy to optimize the code generated for predicate + gates when they are of the form: + + (AND X Y Z ...) + or (OR X Y Z ...) + + where X, Y, Z, and "..." represent individual predicates (leaves) not + predicate trees. + + If the predicate is an AND the contexts of the X, Y, Z, etc. are + ANDed together to create a single Tree context for the group and + context tests for the individual predicates are suppressed: + + -------------------------------------------------- + Note: This was incorrect. The contexts should be + ORed together. This has been fixed. A more + complete description is available in item #152. + --------------------------------------------------- + + Optimization 1: (AND X Y Z ...) + + Suppose the context for Xtest is LA(1)==LP and the context for + Ytest is LA(1)==LP && LA(2)==ID. + + Without the optimization the code would resemble: + + if (lookaheadContext && + !(LA(1)==LP && LA(1)==LP && LA(2)==ID) || + ( (! LA(1)==LP || Xtest) && + (! (LA(1)==LP || LA(2)==ID) || Xtest) + )) {... + + With the -mrhoist optimization the code would resemble: + + if (lookaheadContext && + ! (LA(1)==LP && LA(2)==ID) || (Xtest && Ytest) {... + + Optimization 2: (OR X Y Z ...) with identical contexts + + Suppose the context for Xtest is LA(1)==ID and for Ytest + the context is also LA(1)==ID. + + Without the optimization the code would resemble: + + if (lookaheadContext && + ! (LA(1)==ID || LA(1)==ID) || + (LA(1)==ID && Xtest) || + (LA(1)==ID && Ytest) {... + + With the -mrhoist optimization the code would resemble: + + if (lookaheadContext && + (! LA(1)==ID) || (Xtest || Ytest) {... + + Optimization 3: (OR X Y Z ...) with distinct contexts + + Suppose the context for Xtest is LA(1)==ID and for Ytest + the context is LA(1)==LP. + + Without the optimization the code would resemble: + + if (lookaheadContext && + ! (LA(1)==ID || LA(1)==LP) || + (LA(1)==ID && Xtest) || + (LA(1)==LP && Ytest) {... + + With the -mrhoist optimization the code would resemble: + + if (lookaheadContext && + (zzpf=0, + (LA(1)==ID && (zzpf=1) && Xtest) || + (LA(1)==LP && (zzpf=1) && Ytest) || + !zzpf) { + + These may appear to be of similar complexity at first, + but the non-optimized version contains two tests of each + context while the optimized version contains only one + such test, as well as eliminating some of the inverted + logic (" !(...) || "). + + Optimization 4: Computation of predicate gate trees + + When generating code for the gates of predicate expressions + antlr 1.33 vanilla uses a recursive procedure to generate + "&&" and "||" expressions for testing the lookahead. As each + layer of the predicate tree is exposed a new set of "&&" and + "||" expressions on the lookahead are generated. In many + cases the lookahead being tested has already been tested. + + With -mrhoist a lookahead tree is computed for the entire + lookahead expression. This means that predicates with identical + context or context which is a subset of another predicate's + context disappear. + + This is especially important for predicates formed by rules + like the following: + + upperCaseVowel : <>? vowel; + vowel: : <>? LETTERS; + + These predicates are combined using AND since both must be + satisfied for rule upperCaseVowel. They have identical + context which makes this optimization very effective. + + The affect of Items #100a and #100b together can be dramatic. In + a very large (but real world) grammar one particular predicate + expression was reduced from an (unreadable) 50 predicate leaves, + 195 LA(1) terms, and 5500 characters to an (easily comprehensible) + 3 predicate leaves (all different) and a *single* LA(1) term. + +#99. (Changed in 1.33MR10) Code generation for expression trees + + Expression trees are used for k>1 grammars and predicates with + lookahead depth >1. This optimization must be enabled using + "-mrhoist on". (Clarification added for 1.33MR11). + + In the processing of expression trees, antlr can generate long chains + of token comparisons. Prior to 1.33MR10 there were many redundant + parenthesis which caused problems for compilers which could handle + expressions of only limited complexity. For example, to test an + expression tree (root R A B C D), antlr would generate something + resembling: + + (LA(1)==R && (LA(2)==A || (LA(2)==B || (LA(2)==C || LA(2)==D))))) + + If there were twenty tokens to test then there would be twenty + parenthesis at the end of the expression. + + In 1.33MR10 the generated code for tree expressions resembles: + + (LA(1)==R && (LA(2)==A || LA(2)==B || LA(2)==C || LA(2)==D)) + + For "complex" expressions the output is indented to reflect the LA + number being tested: + + (LA(1)==R + && (LA(2)==A || LA(2)==B || LA(2)==C || LA(2)==D + || LA(2)==E || LA(2)==F) + || LA(1)==S + && (LA(2)==G || LA(2)==H)) + + + Suggested by S. Bochnak (S.Bochnak@@microTool.com.pl), + +#98. (Changed in 1.33MR10) Option "-info p" + + When the user selects option "-info p" the program will generate + detailed information about predicates. If the user selects + "-mrhoist on" additional detail will be provided explaining + the promotion and suppression of predicates. The output is part + of the generated file and sandwiched between #if 0/#endif statements. + + Consider the following k=1 grammar: + + start : ( all ) * ; + + all : ( a + | b + ) + ; + + a : c B + ; + + c : <>? + | B + ; + + b : <>? X + ; + + Below is an excerpt of the output for rule "start" for the three + predicate options (off, on, and maintenance release style hoisting). + + For those who do not wish to use the "-mrhoist on" option for code + generation the option can be used in a "diagnostic" mode to provide + valuable information: + + a. where one should insert null actions to inhibit hoisting + b. a chain of rule references which shows where predicates are + being hoisted + + ====================================================================== + Example of "-info p" with "-mrhoist on" + ====================================================================== + #if 0 + + Hoisting of predicate suppressed by alternative without predicate. + The alt without the predicate includes all cases where the + predicate is false. + + WITH predicate: line 11 v36.g + WITHOUT predicate: line 12 v36.g + + The context set for the predicate: + + B + + The lookahead set for alt WITHOUT the semantic predicate: + + B + + The predicate: + + pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g + + set context: + B + tree context: null + + Chain of referenced rules: + + #0 in rule start (line 1 v36.g) to rule all + #1 in rule all (line 3 v36.g) to rule a + #2 in rule a (line 8 v36.g) to rule c + #3 in rule c (line 11 v36.g) + + #endif + && + #if 0 + + pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g + + set context: + X + tree context: null + + #endif + ====================================================================== + Example of "-info p" with the default -prc setting ( "-prc off") + ====================================================================== + #if 0 + + OR + pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g + + set context: + nil + tree context: null + + pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g + + set context: + nil + tree context: null + + #endif + ====================================================================== + Example of "-info p" with "-prc on" and "-mrhoist off" + ====================================================================== + #if 0 + + OR + pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g + + set context: + B + tree context: null + + pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g + + set context: + X + tree context: null + + #endif + ====================================================================== + +#97. (Fixed in 1.33MR10) "Predicate applied for more than one ... " + + In 1.33 vanilla, the grammar listed below produced this message for + the first alternative (only) of rule "b": + + warning: predicate applied for >1 lookahead 1-sequences + [you may only want one lookahead 1-sequence to apply. + Try using a context guard '(...)? =>' + + In 1.33MR10 the message is issued for both alternatives. + + top : (a)*; + a : b | c ; + + b : <>? ( AAA | BBB ) + | <>? ( XXX | YYY ) + ; + + c : AAA | XXX; + +#96. (Fixed in 1.33MR10) Guard predicates ignored when -prc off + + Prior to 1.33MR10, guard predicate code was not generated unless + "-prc on" was selected. + + This was incorrect, since "-prc off" (the default) is supposed to + disable only AUTOMATIC computation of predicate context, not the + programmer specified context supplied by guard predicates. + +#95. (Fixed in 1.33MR10) Predicate guard context length was k, not max(k,ck) + + Prior to 1.33MR10, predicate guards were computed to k tokens rather + than max(k,ck). Consider the following grammar: + + a : ( A B C)? => <>? (A|X) (B|Y) (C|Z) ; + + The code generated by 1.33 vanilla with "-k 1 -ck 3 -prc on" + for the predicate in "a" resembles: + + if ( (! LA(1)==A) || AAA(LATEXT(1))) {... + + With 1.33MR10 and the same options the code resembles: + + if ( (! (LA(1)==A && LA(2)==B && LA(3)==C) || AAA(LATEXT(1))) {... + +#94. (Fixed in 1.33MR10) Predicates followed by rule references + + Prior to 1.33MR10, a semantic predicate which referenced a token + which was off the end of the rule caused an incomplete context + to be computed (with "-prc on") for the predicate under some circum- + stances. In some cases this manifested itself as illegal C code + (e.g. "LA(2)==[Ep](1)" in the k=2 examples below: + + all : ( a ) *; + + a : <>? ID X + | <>? Y + | Z + ; + + This might also occur when the semantic predicate was followed + by a rule reference which was shorter than the length of the + semantic predicate: + + all : ( a ) *; + + a : <>? ID X + | <>? y + | Z + ; + + y : Y ; + + Depending on circumstance, the resulting context might be too + generous because it was too short, or too restrictive because + of missing alternatives. + +#93. (Changed in 1.33MR10) Definition of Purify macro + + Ofer Ben-Ami (gremlin@cs.huji.ac.il) has supplied a definition + for the Purify macro: + + #define PURIFY(r, s) memset((char *) &(r), '\0', (s)); + + Note: This may not be the right thing to do for C++ objects that + have constructors. Reported by Bonny Rais (bonny@werple.net.au). + + For those cases one should #define PURIFY to an empty macro in the + #header or #first actions. + +#92. (Fixed in 1.33MR10) Guarded predicates and hoisting + + When a guarded predicate participates in hoisting it is linked into + a predicate expression tree. Prior to 1.33MR10 this link was never + cleared and the next time the guard was used to construct a new + tree the link could contain a spurious reference to another element + which had previously been joined to it in the semantic predicate tree. + + For example: + + start : ( all ) *; + all : ( a | b ) ; + + start2 : ( all2 ) *; + all2 : ( a ) ; + + a : (A)? => <>? A ; + b : (B)? => <>? B ; + + Prior to 1.33MR10 the code for "start2" would include a spurious + reference to the BBB predicate which was left from constructing + the predicate tree for rule "start" (i.e. or(AAA,BBB) ). + + In 1.33MR10 this problem is avoided by cloning the original guard + each time it is linked into a predicate tree. + +#91. (Changed in 1.33MR10) Extensive changes to semantic pred hoisting + + ============================================ + This has been rendered obsolete by Item #117 + ============================================ + +#90. (Fixed in 1.33MR10) Semantic pred with LT(i) and i>max(k,ck) + + There is a bug in antlr 1.33 vanilla and all maintenance releases + prior to 1.33MR10 which allows semantic predicates to reference + an LT(i) or LATEXT(i) where i is larger than max(k,ck). When + this occurs antlr will attempt to mark the ith element of an array + in which there are only max(k,ck) elements. The result cannot + be predicted. + + Using LT(i) or LATEXT(i) for i>max(k,ck) is reported as an error + in 1.33MR10. + +#89. Rescinded + +#88. (Fixed in 1.33MR10) Tokens used in semantic predicates in guess mode + + Consider the behavior of a semantic predicate during guess mode: + + rule : a:A ( + <>? b:B + | c:C + ); + + Prior to MR10 the assignment of the token or attribute to + $a did not occur during guess mode, which would cause the + semantic predicate to misbehave because $a would be null. + + In 1.33MR10 a semantic predicate with a reference to an + element label (such as $a) forces the assignment to take + place even in guess mode. + + In order to work, this fix REQUIRES use of the $label format + for token pointers and attributes referenced in semantic + predicates. + + The fix does not apply to semantic predicates using the + numeric form to refer to attributes (e.g. <>?). + The user will receive a warning for this case. + + Reported by Rob Trout (trout@mcs.cs.kent.edu). + +#87. (Fixed in 1.33MR10) Malformed guard predicates + + Context guard predicates may contain only references to + tokens. They may not contain references to (...)+ and + (...)* blocks. This is now checked. This replaces the + fatal error message in item #78 with an appropriate + (non-fatal) error message. + + In theory, context guards should be allowed to reference + rules. However, I have not had time to fix this. + Evaluation of the guard takes place before all rules have + been read, making it difficult to resolve a forward reference + to rule "zzz" - it hasn't been read yet ! To postpone evaluation + of the guard until all rules have been read is too much + for the moment. + +#86. (Fixed in 1.33MR10) Unequal set size in set_sub + + Routine set_sub() in pccts/support/set/set.h did not work + correctly when the sets were of unequal sizes. Rewrote + set_equ to make it simpler and remove unnecessary and + expensive calls to set_deg(). This routine was not used + in 1.33 vanilla. + +#85. (Changed in 1.33MR10) Allow redefinition of MaxNumFiles + + Raised the maximum number of input files to 99 from 20. + Put a #ifndef/#endif around the "#define MaxNumFiles 99". + +#84. (Fixed in 1.33MR10) Initialize zzBadTok in macro zzRULE + + Initialize zzBadTok to NULL in zzRULE macro of AParser.h. + in order to get rid of warning messages. + +#83. (Fixed in 1.33MR10) False warnings with -w2 for #tokclass + + When -w2 is selected antlr gives inappropriate warnings about + #tokclass names not having any associated regular expressions. + Since a #tokclass is not a "real" token it will never have an + associated regular expression and there should be no warning. + + Reported by Derek Pappas (derek.pappas@eng.sun.com) + +#82. (Fixed in 1.33MR10) Computation of follow sets with multiple cycles + + Reinier van den Born (reinier@vnet.ibm.com) reported a problem + in the computation of follow sets by antlr. The problem (bug) + exists in 1.33 vanilla and all maintenance releases prior to 1.33MR10. + + The problem involves the computation of follow sets when there are + cycles - rules which have mutual references. I believe the problem + is restricted to cases where there is more than one cycle AND + elements of those cycles have rules in common. Even when this + occurs it may not affect the code generated - but it might. It + might also lead to undetected ambiguities. + + There were no changes in antlr or dlg output from the revised version. + + The following fragment demonstrates the problem by giving different + follow sets (option -pa) for var_access when built with k=1 and ck=2 on + 1.33 vanilla and 1.33MR10: + + echo_statement : ECHO ( echo_expr )* + ; + + echo_expr : ( command )? + | expression + ; + + command : IDENTIFIER + { concat } + ; + + expression : operand ( OPERATOR operand )* + ; + + operand : value + | START command END + ; + + value : concat + | TYPE operand + ; + + concat : var_access { CONCAT value } + ; + + var_access : IDENTIFIER { INDEX } + + ; +#81. (Changed in 1.33MR10) C mode use of attributes and ASTs + + Reported by Isaac Clark (irclark@mindspring.com). + + C mode code ignores attributes returned by rules which are + referenced using element labels when ASTs are enabled (-gt option). + + 1. start : r:rule t:Token <<$start=$r;>> + + The $r reference will not work when combined with + the -gt option. + + 2. start : t:Token <<$start=$t;>> + + The $t reference works in all cases. + + 3. start : rule <<$0=$1;>> + + Numeric labels work in all cases. + + With MR10 the user will receive an error message for case 1 when + the -gt option is used. + +#80. (Fixed in 1.33MR10) (...)? as last alternative of block + + A construct like the following: + + rule : a + | (b)? + ; + + does not make sense because there is no alternative when + the guess block fails. This is now reported as a warning + to the user. + + Previously, there was a code generation error for this case: + the guess block was not "closed" when the guess failed. + This could cause an infinite loop or other problems. This + is now fixed. + + Example problem: + + #header<< + #include + #include "charptr.h" + >> + + << + #include "charptr.c" + main () + { + ANTLR(start(),stdin); + } + >> + + #token "[\ \t]+" << zzskip(); >> + #token "[\n]" << zzline++; zzskip(); >> + + #token Word "[a-z]+" + #token Number "[0-9]+" + + + start : (test1)? + | (test2)? + ; + test1 : (Word Word Word Word)? + | (Word Word Word Number)? + ; + test2 : (Word Word Number Word)? + | (Word Word Number Number)? + ; + + Test data which caused infinite loop: + + a 1 a a + +#79. (Changed in 1.33MR10) Use of -fh with multiple parsers + + Previously, antlr always used the pre-processor symbol + STDPCCTS_H as a gate for the file stdpccts.h. This + caused problems when there were multiple parsers defined + because they used the same gate symbol. + + In 1.33MR10, the -fh filename is used to generate the + gate file for stdpccts.h. For instance: + + antlr -fh std_parser1.h + + generates the pre-processor symbol "STDPCCTS_std_parser1_H". + + Reported by Ramanathan Santhanam (ps@kumaran.com). + +#78. (Changed in 1.33MR9) Guard predicates that refer to rules + + ------------------------ + Please refer to Item #87 + ------------------------ + + Guard predicates are processed during an early phase + of antlr (during parsing) before all data structures + are completed. + + There is an apparent bug in earlier versions of 1.33 + which caused guard predicates which contained references + to rules (rather than tokens) to reference a structure + which hadn't yet been initialized. + + In some cases (perhaps all cases) references to rules + in guard predicates resulted in the use of "garbage". + +#79. (Changed in 1.33MR9) Jeff Vincent (JVincent@novell.com) + + Previously, the maximum length file name was set + arbitrarily to 300 characters in antlr, dlg, and sorcerer. + + The config.h file now attempts to define the maximum length + filename using _MAX_PATH from stdlib.h before falling back + to using the value 300. + +#78. (Changed in 1.33MR9) Jeff Vincent (JVincent@novell.com) + + Put #ifndef/#endif around definition of ZZLEXBUFSIZE in + antlr. + +#77. (Changed in 1.33MR9) Arithmetic overflow for very large grammars + + In routine HandleAmbiguities() antlr attempts to compute the + number of possible elements in a set that is order of + number-of-tokens raised to the number-of-lookahead-tokens power. + For large grammars or large lookahead (e.g. -ck 7) this can + cause arithmetic overflow. + + With 1.33MR9, arithmetic overflow in this computation is reported + the first time it happens. The program continues to run and + the program branches based on the assumption that the computed + value is larger than any number computed by counting actual cases + because 2**31 is larger than the number of bits in most computers. + + Before 1.33MR9 overflow was not reported. The behavior following + overflow is not predictable by anyone but the original author. + + NOTE + + In 1.33MR10 the warning message is suppressed. + The code which detects the overflow allows the + computation to continue without an error. The + error message itself made made users worry. + +#76. (Changed in 1.33MR9) Jeff Vincent (JVincent@novell.com) + + Jeff Vincent has convinced me to make ANTLRCommonToken and + ANTLRCommonNoRefCountToken use variable length strings + allocated from the heap rather than fixed length strings. + By suitable definition of setText(), the copy constructor, + and operator =() it is possible to maintain "copy" semantics. + By "copy" semantics I mean that when a token is copied from + an existing token it receives its own, distinct, copy of the + text allocated from the heap rather than simply a pointer + to the original token's text. + + ============================================================ + W * A * R * N * I * N * G + ============================================================ + + It is possible that this may cause problems for some users. + For those users I have included the old version of AToken.h as + pccts/h/AToken_traditional.h. + +#75. (Changed in 1.33MR9) Bruce Guenter (bruceg@qcc.sk.ca) + + Make DLGStringInput const correct. Since this is infrequently + subclassed, it should affect few users, I hope. + +#74. (Changed in 1.33MR9) -o (output directory) option + + Antlr does not properly handle the -o output directory option + when the filename of the grammar contains a directory part. For + example: + + antlr -o outdir pccts_src/myfile.g + + causes antlr create a file called "outdir/pccts_src/myfile.cpp. + It SHOULD create outdir/myfile.cpp + + The suggested code fix has been installed in antlr, dlg, and + Sorcerer. + +#73. (Changed in 1.33MR9) Hoisting of semantic predicates and -mrhoist + + ============================================ + This has been rendered obsolete by Item #117 + ============================================ + +#72. (Changed in 1.33MR9) virtual saveState()/restoreState()/guess_XXX + + The following methods in ANTLRParser were made virtual at + the request of S. Bochnak (S.Bochnak@microTool.com.pl): + + saveState() and restoreState() + guess(), guess_fail(), and guess_done() + +#71. (Changed in 1.33MR9) Access to omitted command line argument + + If a switch requiring arguments is the last thing on the + command line, and the argument is omitted, antlr would core. + + antlr test.g -prc + + instead of + + antlr test.g -prc off + +#70. (Changed in 1.33MR9) Addition of MSVC .dsp and .mak build files + + The following MSVC .dsp and .mak files for pccts and sorcerer + were contributed by Stanislaw Bochnak (S.Bochnak@microTool.com.pl) + and Jeff Vincent (JVincent@novell.com) + + PCCTS Distribution Kit + ---------------------- + pccts/PCCTSMSVC50.dsw + + pccts/antlr/AntlrMSVC50.dsp + pccts/antlr/AntlrMSVC50.mak + + pccts/dlg/DlgMSVC50.dsp + pccts/dlg/DlgMSVC50.mak + + pccts/support/msvc.dsp + + Sorcerer Distribution Kit + ------------------------- + pccts/sorcerer/SorcererMSVC50.dsp + pccts/sorcerer/SorcererMSVC50.mak + + pccts/sorcerer/lib/msvc.dsp + +#69. (Changed in 1.33MR9) Change "unsigned int" to plain "int" + + Declaration of max_token_num in misc.c as "unsigned int" + caused comparison between signed and unsigned ints giving + warning message without any special benefit. + +#68. (Changed in 1.33MR9) Add void return for dlg internal_error() + + Get rid of "no return value" message in internal_error() + in file dlg/support.c and dlg/dlg.h. + +#67. (Changed in Sor) sor.g: lisp() has no return value + + Added a "void" for the return type. + +#66. (Added to Sor) sor.g: ZZLEXBUFSIZE enclosed in #ifndef/#endif + + A user needed to be able to change the ZZLEXBUFSIZE for + sor. Put the definition of ZZLEXBUFSIZE inside #ifndef/#endif + +#65. (Changed in 1.33MR9) PCCTSAST::deepCopy() and ast_dup() bug + + Jeff Vincent (JVincent@novell.com) found that deepCopy() + made new copies of only the direct descendents. No new + copies were made of sibling nodes, Sibling pointers are + set to zero by shallowCopy(). + + PCCTS_AST::deepCopy() has been changed to make a + deep copy in the traditional sense. + + The deepCopy() routine depends on the behavior of + shallowCopy(). In all sor examples I've found, + shallowCopy() zeroes the right and down pointers. + + Original Tree Original deepCopy() Revised deepCopy + ------------- ------------------- ---------------- + a->b->c A A + | | | + d->e->f D D->E->F + | | | + g->h->i G G->H->I + | | + j->k J->K + + While comparing deepCopy() for C++ mode with ast_dup for + C mode I found a problem with ast_dup(). + + Routine ast_dup() has been changed to make a deep copy + in the traditional sense. + + Original Tree Original ast_dup() Revised ast_dup() + ------------- ------------------- ---------------- + a->b->c A->B->C A + | | | + d->e->f D->E->F D->E->F + | | | + g->h->i G->H->I G->H->I + | | | + j->k J->K J->K + + + I believe this affects transform mode sorcerer programs only. + +#64. (Changed in 1.33MR9) anltr/hash.h prototype for killHashTable() + +#63. (Changed in 1.33MR8) h/charptr.h does not zero pointer after free + + The charptr.h routine now zeroes the pointer after free(). + + Reported by Jens Tingleff (jensting@imaginet.fr) + +#62. (Changed in 1.33MR8) ANTLRParser::resynch had static variable + + The static variable "consumed" in ANTLRParser::resynch was + changed into an instance variable of the class with the + name "resynchConsumed". + + Reported by S.Bochnak@microTool.com.pl + +#61. (Changed in 1.33MR8) Using rule>[i,j] when rule has no return values + + Previously, the following code would cause antlr to core when + it tried to generate code for rule1 because rule2 had no return + values ("upward inheritance"): + + rule1 : <> + rule2 > [i,j] + ; + + rule2 : Anything ; + + Reported by S.Bochnak@microTool.com.pl + + Verified correct operation of antlr MR8 when missing or extra + inheritance arguments for all combinations. When there are + missing or extra arguments code will still be generated even + though this might cause the invocation of a subroutine with + the wrong number of arguments. + +#60. (Changed in 1.33MR7) Major changes to exception handling + + There were significant problems in the handling of exceptions + in 1.33 vanilla. The general problem is that it can only + process one level of exception handler. For example, a named + exception handler, an exception handler for an alternative, or + an exception for a subrule always went to the rule's exception + handler if there was no "catch" which matched the exception. + + In 1.33MR7 the exception handlers properly "nest". If an + exception handler does not have a matching "catch" then the + nextmost outer exception handler is checked for an appropriate + "catch" clause, and so on until an exception handler with an + appropriate "catch" is found. + + There are still undesirable features in the way exception + handlers are implemented, but I do not have time to fix them + at the moment: + + The exception handlers for alternatives are outside the + block containing the alternative. This makes it impossible + to access variables declared in a block or to resume the + parse by "falling through". The parse can still be easily + resumed in other ways, but not in the most natural fashion. + + This results in an inconsistency between named exception + handlers and exception handlers for alternatives. When + an exception handler for an alternative "falls through" + it goes to the nextmost outer handler - not the "normal + action". + + A major difference between 1.33MR7 and 1.33 vanilla is + the default action after an exception is caught: + + 1.33 Vanilla + ------------ + In 1.33 vanilla the signal value is set to zero ("NoSignal") + and the code drops through to the code following the exception. + For named exception handlers this is the "normal action". + For alternative exception handlers this is the rule's handler. + + 1.33MR7 + ------- + In 1.33MR7 the signal value is NOT automatically set to zero. + + There are two cases: + + For named exception handlers: if the signal value has been + set to zero the code drops through to the "normal action". + + For all other cases the code branches to the nextmost outer + exception handler until it reaches the handler for the rule. + + The following macros have been defined for convenience: + + C/C++ Mode Name + -------------------- + (zz)suppressSignal + set signal & return signal arg to 0 ("NoSignal") + (zz)setSignal(intValue) + set signal & return signal arg to some value + (zz)exportSignal + copy the signal value to the return signal arg + + I'm not sure why PCCTS make a distinction between the local + signal value and the return signal argument, but I'm loathe + to change the code. The burden of copying the local signal + value to the return signal argument can be given to the + default signal handler, I suppose. + +#59. (Changed in 1.33MR7) Prototypes for some functions + + Added prototypes for the following functions to antlr.h + + zzconsumeUntil() + zzconsumeUntilToken() + +#58. (Changed in 1.33MR7) Added definition of zzbufsize to dlgauto.h + +#57. (Changed in 1.33MR7) Format of #line directive + + Previously, the -gl directive for line 1234 would + resemble: "# 1234 filename.g". This caused problems + for some compilers/pre-processors. In MR7 it generates + "#line 1234 filename.g". + +#56. (Added in 1.33MR7) Jan Mikkelsen + + Move PURIFY macro invocation to after rule's init action. + +#55. (Fixed in 1.33MR7) Uninitialized variables in ANTLRParser + + Member variables inf_labase and inf_last were not initialized. + (See item #50.) + +#54. (Fixed in 1.33MR6) Brad Schick (schick@interacess.com) + + Previously, the following constructs generated the same + code: + + rule1 : (A B C)? + | something-else + ; + + rule2 : (A B C)? () + | something-else + ; + + In all versions of pccts rule1 guesses (A B C) and then + consume all three tokens if the guess succeeds. In MR6 + rule2 guesses (A B C) but consumes NONE of the tokens + when the guess succeeds because "()" matches epsilon. + +#53. (Explanation for 1.33MR6) What happens after an exception is caught ? + + The Book is silent about what happens after an exception + is caught. + + The following code fragment prints "Error Action" followed + by "Normal Action". + + test : Word ex:Number <> + exception[ex] + catch NoViableAlt: + <> + ; + + The reason for "Normal Action" is that the normal flow of the + program after a user-written exception handler is to "drop through". + In the case of an exception handler for a rule this results in + the execution of a "return" statement. In the case of an + exception handler attached to an alternative, rule, or token + this is the code that would have executed had there been no + exception. + + The user can achieve the desired result by using a "return" + statement. + + test : Word ex:Number <> + exception[ex] + catch NoViableAlt: + <> + ; + + The most powerful mechanism for recovery from parse errors + in pccts is syntactic predicates because they provide + backtracking. Exceptions allow "return", "break", + "consumeUntil(...)", "goto _handler", "goto _fail", and + changing the _signal value. + +#52. (Fixed in 1.33MR6) Exceptions without syntactic predicates + + The following generates bad code in 1.33 if no syntactic + predicates are present in the grammar. + + test : Word ex:Number <> + exception[ex] + catch NoViableAlt: + <> + + There is a reference to a guess variable. In C mode + this causes a compiler error. In C++ mode it generates + an extraneous check on member "guessing". + + In MR6 correct code is generated for both C and C++ mode. + +#51. (Added to 1.33MR6) Exception operator "@" used without exceptions + + In MR6 added a warning when the exception operator "@" is + used and no exception group is defined. This is probably + a case where "\@" or "@" is meant. + +#50. (Fixed in 1.33MR6) Gunnar Rxnning (gunnar@candleweb.no) + http://www.candleweb.no/~gunnar/ + + Routines zzsave_antlr_state and zzrestore_antlr_state don't + save and restore all the data needed when switching states. + + Suggested patch applied to antlr.h and err.h for MR6. + +#49. (Fixed in 1.33MR6) Sinan Karasu (sinan@boeing.com) + + Generated code failed to turn off guess mode when leaving a + (...)+ block which contained a guess block. The result was + an infinite loop. For example: + + rule : ( + (x)? + | y + )+ + + Suggested code fix implemented in MR6. Replaced + + ... else if (zzcnt>1) break; + + with: + + C++ mode: + ... else if (zzcnt>1) {if (!zzrv) zzGUESS_DONE; break;}; + C mode: + ... else if (zzcnt>1) {if (zzguessing) zzGUESS_DONE; break;}; + +#48. (Fixed in 1.33MR6) Invalid exception element causes core + + A label attached to an invalid construct can cause + pccts to crash while processing the exception associated + with the label. For example: + + rule : t:(B C) + exception[t] catch MismatchedToken: <> + + Version MR6 generates the message: + + reference in exception handler to undefined label 't' + +#47. (Fixed in 1.33MR6) Manuel Ornato + + Under some circumstances involving a k >1 or ck >1 + grammar and a loop block (i.e. (...)* ) pccts will + fail to detect a syntax error and loop indefinitely. + The problem did not exist in 1.20, but has existed + from 1.23 to the present. + + Fixed in MR6. + + --------------------------------------------------- + Complete test program + --------------------------------------------------- + #header<< + #include + #include "charptr.h" + >> + + << + #include "charptr.c" + main () + { + ANTLR(global(),stdin); + } + >> + + #token "[\ \t]+" << zzskip(); >> + #token "[\n]" << zzline++; zzskip(); >> + + #token B "b" + #token C "c" + #token D "d" + #token E "e" + #token LP "\(" + #token RP "\)" + + #token ANTLREOF "@" + + global : ( + (E liste) + | liste + | listed + ) ANTLREOF + ; + + listeb : LP ( B ( B | C )* ) RP ; + listec : LP ( C ( B | C )* ) RP ; + listed : LP ( D ( B | C )* ) RP ; + liste : ( listeb | listec )* ; + + --------------------------------------------------- + Sample data causing infinite loop + --------------------------------------------------- + e (d c) + --------------------------------------------------- + +#46. (Fixed in 1.33MR6) Robert Richter + (Robert.Richter@infotech.tu-chemnitz.de) + + This item from the list of known problems was + fixed by item #18 (below). + +#45. (Fixed in 1.33MR6) Brad Schick (schick@interaccess.com) + + The dependency scanner in VC++ mistakenly sees a + reference to an MPW #include file even though properly + #ifdef/#endif in config.h. The suggested workaround + has been implemented: + + #ifdef MPW + ..... + #define MPW_CursorCtl_Header + #include MPW_CursorCtl_Header + ..... + #endif + +#44. (Fixed in 1.33MR6) cast malloc() to (char *) in charptr.c + + Added (char *) cast for systems where malloc returns "void *". + +#43. (Added to 1.33MR6) Bruce Guenter (bruceg@qcc.sk.ca) + + Add setLeft() and setUp methods to ASTDoublyLinkedBase + for symmetry with setRight() and setDown() methods. + +#42. (Fixed in 1.33MR6) Jeff Katcher (jkatcher@nortel.ca) + + C++ style comment in antlr.c corrected. + +#41. (Added in 1.33MR6) antlr -stdout + + Using "antlr -stdout ..." forces the text that would + normally go to the grammar.c or grammar.cpp file to + stdout. + +#40. (Added in 1.33MR6) antlr -tab to change tab stops + + Using "antlr -tab number ..." changes the tab stops + for the grammar.c or grammar.cpp file. The number + must be between 0 and 8. Using 0 gives tab characters, + values between 1 and 8 give the appropriate number of + space characters. + +#39. (Fixed in 1.33MR5) Jan Mikkelsen + + Commas in function prototype still not correct under + some circumstances. Suggested code fix installed. + +#38. (Fixed in 1.33MR5) ANTLRTokenBuffer constructor + + Have ANTLRTokenBuffer ctor initialize member "parser" to null. + +#37. (Fixed in 1.33MR4) Bruce Guenter (bruceg@qcc.sk.ca) + + In ANTLRParser::FAIL(int k,...) released memory pointed to by + f[i] (as well as f itself. Should only free f itself. + +#36. (Fixed in 1.33MR3) Cortland D. Starrett (cort@shay.ecn.purdue.edu) + + Neglected to properly declare isDLGmaxToken() when fixing problem + reported by Andreas Magnusson. + + Undo "_retv=NULL;" change which caused problems for return values + from rules whose return values weren't pointers. + + Failed to create bin directory if it didn't exist. + +#35. (Fixed in 1.33MR2) Andreas Magnusson +(Andreas.Magnusson@mailbox.swipnet.se) + + Repair bug introduced by 1.33MR1 for #tokdefs. The original fix + placed "DLGmaxToken=9999" and "DLGminToken=0" in the TokenType enum + in order to fix a problem with an aggressive compiler assigning an 8 + bit enum which might be too narrow. This caused #tokdefs to assume + that there were 9999 real tokens. The repair to the fix causes antlr to + ignore TokenTypes "DLGmaxToken" and "DLGminToken" in a #tokdefs file. + +#34. (Added to 1.33MR1) Add public DLGLexerBase::set_line(int newValue) + + Previously there was no public function for changing the line + number maintained by the lexer. + +#33. (Fixed in 1.33MR1) Franklin Chen (chen@adi.com) + + Accidental use of EXIT_FAILURE rather than PCCTS_EXIT_FAILURE + in pccts/h/AParser.cpp. + +#32. (Fixed in 1.33MR1) Franklin Chen (chen@adi.com) + + In PCCTSAST.cpp lines 405 and 466: Change + + free (t) + to + free ( (char *)t ); + + to match prototype. + +#31. (Added to 1.33MR1) Pointer to parser in ANTLRTokenBuffer + Pointer to parser in DLGLexerBase + + The ANTLRTokenBuffer class now contains a pointer to the + parser which is using it. This is established by the + ANTLRParser constructor calling ANTLRTokenBuffer:: + setParser(ANTLRParser *p). + + When ANTLRTokenBuffer::setParser(ANTLRParser *p) is + called it saves the pointer to the parser and then + calls ANTLRTokenStream::setParser(ANTLRParser *p) + so that the lexer can also save a pointer to the + parser. + + There is also a function getParser() in each class + with the obvious purpose. + + It is possible that these functions will return NULL + under some circumstances (e.g. a non-DLG lexer is used). + +#30. (Added to 1.33MR1) function tokenName(int token) standard + + The generated parser class now includes the + function: + + static const ANTLRChar * tokenName(int token) + + which returns a pointer to the "name" corresponding + to the token. + + The base class (ANTLRParser) always includes the + member function: + + const ANTLRChar * parserTokenName(int token) + + which can be accessed by objects which have a pointer + to an ANTLRParser, but do not know the name of the + parser class (e.g. ANTLRTokenBuffer and DLGLexerBase). + +#29. (Added to 1.33MR1) Debugging DLG lexers + + If the pre-processor symbol DEBUG_LEXER is defined + then DLexerBase will include code for printing out + key information about tokens which are recognized. + + The debug feature of the lexer is controlled by: + + int previousDebugValue=lexer.debugLexer(newValue); + + a value of 0 disables output + a value of 1 enables output + + Even if the lexer debug code is compiled into DLexerBase + it must be enabled before any output is generated. For + example: + + DLGFileInput in(stdin); + MyDLG lexer(&in,2000); + + lexer.setToken(&aToken); + + #if DEBUG_LEXER + lexer.debugLexer(1); // enable debug information + #endif + +#28. (Added to 1.33MR1) More control over DLG header + + Version 1.33MR1 adds the following directives to PCCTS + for C++ mode: + + #lexprefix <> + + Adds source code to the DLGLexer.h file + after the #include "DLexerBase.h" but + before the start of the class definition. + + #lexmember <> + + Adds source code to the DLGLexer.h file + as part of the DLGLexer class body. It + appears immediately after the start of + the class and a "public: statement. + +#27. (Fixed in 1.33MR1) Comments in DLG actions + + Previously, DLG would not recognize comments as a special case. + Thus, ">>" in the comments would cause errors. This is fixed. + +#26. (Fixed in 1.33MR1) Removed static variables from error routines + + Previously, the existence of statically allocated variables + in some of the parser's member functions posed a danger when + there was more than one parser active. + + Replaced with dynamically allocated/freed variables in 1.33MR1. + +#25. (Fixed in 1.33MR1) Use of string literals in semantic predicates + + Previously, it was not possible to place a string literal in + a semantic predicate because it was not properly "stringized" + for the report of a failed predicate. + +#24. (Fixed in 1.33MR1) Continuation lines for semantic predicates + + Previously, it was not possible to continue semantic + predicates across a line because it was not properly + "stringized" for the report of a failed predicate. + + rule : <>?[ a very + long statement ] + +#23. (Fixed in 1.33MR1) {...} envelope for failed semantic predicates + + Previously, there was a code generation error for failed + semantic predicates: + + rule : <>?[ stmt1; stmt2; ] + + which generated code which resembled: + + if (! xyz()) stmt1; stmt2; + + It now puts the statements in a {...} envelope: + + if (! xyz()) { stmt1; stmt2; }; + +#22. (Fixed in 1.33MR1) Continuation of #token across lines using "\" + + Previously, it was not possible to continue a #token regular + expression across a line. The trailing "\" and newline caused + a newline to be inserted into the regular expression by DLG. + + Fixed in 1.33MR1. + +#21. (Fixed in 1.33MR1) Use of ">>" (right shift operator in DLG actions + + It is now possible to use the C++ right shift operator ">>" + in DLG actions by using the normal escapes: + + #token "shift-right" << value=value \>\> 1;>> + +#20. (Version 1.33/19-Jan-97 Karl Eccleson + P.A. Keller (P.A.Keller@bath.ac.uk) + + There is a problem due to using exceptions with the -gh option. + + Suggested fix now in 1.33MR1. + +#19. (Fixed in 1.33MR1) Tom Piscotti and John Lilley + + There were problems suppressing messages to stdin and stdout + when running in a window environment because some functions + which uses fprint were not virtual. + + Suggested change now in 1.33MR1. + + I believe all functions containing error messages (excluding those + indicating internal inconsistency) have been placed in functions + which are virtual. + +#18. (Version 1.33/ 22-Nov-96) John Bair (jbair@iftime.com) + + Under some combination of options a required "return _retv" is + not generated. + + Suggested fix now in 1.33MR1. + +#17. (Version 1.33/3-Sep-96) Ron House (house@helios.usq.edu.au) + + The routine ASTBase::predorder_action omits two "tree->" + prefixes, which results in the preorder_action belonging + to the wrong node to be invoked. + + Suggested fix now in 1.33MR1. + +#16. (Version 1.33/7-Jun-96) Eli Sternheim + + Routine consumeUntilToken() does not check for end-of-file + condition. + + Suggested fix now in 1.33MR1. + +#15. (Version 1.33/8 Apr 96) Asgeir Olafsson + + Problem with tree duplication of doubly linked ASTs in ASTBase.cpp. + + Suggested fix now in 1.33MR1. + +#14. (Version 1.33/28-Feb-96) Andreas.Magnusson@mailbox.swipnet.se + + Problem with definition of operator = (const ANTLRTokenPtr rhs). + + Suggested fix now in 1.33MR1. + +#13. (Version 1.33/13-Feb-96) Franklin Chen (chen@adi.com) + + Sun C++ Compiler 3.0.1 can't compile testcpp/1 due to goto in + block with destructors. + + Apparently fixed. Can't locate "goto". + +#12. (Version 1.33/10-Nov-95) Minor problems with 1.33 code + + The following items have been fixed in 1.33MR1: + + 1. pccts/antlr/main.c line 142 + + "void" appears in classic C code + + 2. no makefile in support/genmk + + 3. EXIT_FAILURE/_SUCCESS instead of PCCTS_EXIT_FAILURE/_SUCCESS + + pccts/h/PCCTSAST.cpp + pccts/h/DLexerBase.cpp + pccts/testcpp/6/test.g + + 4. use of "signed int" isn't accepted by AT&T cfront + + pccts/h/PCCTSAST.h line 42 + + 5. in call to ANTLRParser::FAIL the var arg err_k is passed as + "int" but is declared "unsigned int". + + 6. I believe that a failed validation predicate still does not + get put in a "{...}" envelope, despite the release notes. + + 7. The #token ">>" appearing in the DLG grammar description + causes DLG to generate the string literal "\>\>" which + is non-conforming and will cause some compilers to + complain (scan.c function act10 line 143 of source code). + +#11. (Version 1.32b6) Dave Kuhlman (dkuhlman@netcom.com) + + Problem with file close in gen.c. Already fixed in 1.33. + +#10. (Version 1.32b6/29-Aug-95) + + pccts/antlr/main.c contains a C++ style comments on lines 149 + and 176 which causes problems for most C compilers. + + Already fixed in 1.33. + +#9. (Version 1.32b4/14-Mar-95) dlgauto.h #include "config.h" + + The file pccts/h/dlgauto.h should probably contain a #include + "config.h" as it uses the #define symbol __USE_PROTOS. + + Added to 1.33MR1. + +#8. (Version 1.32b4/6-Mar-95) Michael T. Richter (mtr@igs.net) + + In C++ output mode anonymous tokens from in-line regular expressions + can create enum values which are too wide for the datatype of the enum + assigned by the C++ compiler. + + Fixed in 1.33MR1. + +#7. (Version 1.32b4/6-Mar-95) C++ does not imply __STDC__ + + In err.h the combination of # directives assumes that a C++ + compiler has __STDC__ defined. This is not necessarily true. + + This problem also appears in the use of __USE_PROTOS which + is appropriate for both Standard C and C++ in antlr/gen.c + and antlr/lex.c + + Fixed in 1.33MR1. + +#6. (Version 1.32 ?/15-Feb-95) Name conflict for "TokenType" + + Already fixed in 1.33. + +#5. (23-Jan-95) Douglas_Cuthbertson.JTIDS@jtids_qmail.hanscom.af.mil + + The fail action following a semantic predicate is not enclosed in + "{...}". This can lead to problems when the fail action contains + more than one statement. + + Fixed in 1.33MR1. + +#4 . (Version 1.33/31-Mar-96) jlilley@empathy.com (John Lilley) + + Put briefly, a semantic predicate ought to abort a guess if it fails. + + Correction suggested by J. Lilley has been added to 1.33MR1. + +#3 . (Version 1.33) P.A.Keller@bath.ac.uk + + Extra commas are placed in the K&R style argument list for rules + when using both exceptions and ASTs. + + Fixed in 1.33MR1. + +#2. (Version 1.32b6/2-Oct-95) Brad Schick + + Construct #[] generates zzastnew() in C++ mode. + + Already fixed in 1.33. + +#1. (Version 1.33) Bob Bailey (robert@oakhill.sps.mot.com) + + Previously, config.h assumed that all PC systems required + "short" file names. The user can now override that + assumption with "#define LONGFILENAMES". + + Added to 1.33MR1. diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_SUMMARY.txt b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_SUMMARY.txt new file mode 100644 index 00000000..17a37137 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/CHANGES_SUMMARY.txt @@ -0,0 +1,2049 @@ +====================================================================== + + CHANGES_SUMMARY.TXT + + A QUICK overview of changes from 1.33 in reverse order + + A summary of additions rather than bug fixes and minor code changes. + + Numbers refer to items in CHANGES_FROM_133*.TXT + which may contain additional information. + + DISCLAIMER + + The software and these notes are provided "as is". They may include + typographical or technical errors and their authors disclaims all + liability of any kind or nature for damages due to error, fault, + defect, or deficiency regardless of cause. All warranties of any + kind, either express or implied, including, but not limited to, the + implied warranties of merchantability and fitness for a particular + purpose are disclaimed. + +====================================================================== + +#258. You can specify a user-defined base class for your parser + + The base class must constructor must have a signature similar to + that of ANTLRParser. + +#253. Generation of block preamble (-preamble and -preamble_first) + + The antlr option -preamble causes antlr to insert the code + BLOCK_PREAMBLE at the start of each rule and block. + + The antlr option -preamble_first is similar, but inserts the + code BLOCK_PREAMBLE_FIRST(PreambleFirst_123) where the symbol + PreambleFirst_123 is equivalent to the first set defined by + the #FirstSetSymbol described in Item #248. + +#248. Generate symbol for first set of an alternative + + rr : #FirstSetSymbol(rr_FirstSet) ( Foo | Bar ) ; + +#216. Defer token fetch for C++ mode + + When the ANTLRParser class is built with the pre-processor option + ZZDEFER_FETCH defined, the fetch of new tokens by consume() is deferred + until LA(i) or LT(i) is called. + +#215. Use reset() to reset DLGLexerBase +#188. Added pccts/h/DLG_stream_input.h +#180. Added ANTLRParser::getEofToken() +#173. -glms for Microsoft style filenames with -gl +#170. Suppression for predicates with lookahead depth >1 + + Consider the following grammar with -ck 2 and the predicate in rule + "a" with depth 2: + + r1 : (ab)* "@" + ; + + ab : a + | b + ; + + a : (A B)? => <>? A B C + ; + + b : A B C + ; + + Normally, the predicate would be hoisted into rule r1 in order to + determine whether to call rule "ab". However it should *not* be + hoisted because, even if p is false, there is a valid alternative + in rule b. With "-mrhoistk on" the predicate will be suppressed. + + If "-info p" command line option is present the following information + will appear in the generated code: + + while ( (LA(1)==A) + #if 0 + + Part (or all) of predicate with depth > 1 suppressed by alternative + without predicate + + pred << p(LATEXT(2))>>? + depth=k=2 ("=>" guard) rule a line 8 t1.g + tree context: + (root = A + B + ) + + The token sequence which is suppressed: ( A B ) + The sequence of references which generate that sequence of tokens: + + 1 to ab r1/1 line 1 t1.g + 2 ab ab/1 line 4 t1.g + 3 to b ab/2 line 5 t1.g + 4 b b/1 line 11 t1.g + 5 #token A b/1 line 11 t1.g + 6 #token B b/1 line 11 t1.g + + #endif + + A slightly more complicated example: + + r1 : (ab)* "@" + ; + + ab : a + | b + ; + + a : (A B)? => <>? (A B | D E) + ; + + b : <>? D E + ; + + + In this case, the sequence (D E) in rule "a" which lies behind + the guard is used to suppress the predicate with context (D E) + in rule b. + + while ( (LA(1)==A || LA(1)==D) + #if 0 + + Part (or all) of predicate with depth > 1 suppressed by alternative + without predicate + + pred << q(LATEXT(2))>>? + depth=k=2 rule b line 11 t2.g + tree context: + (root = D + E + ) + + The token sequence which is suppressed: ( D E ) + The sequence of references which generate that sequence of tokens: + + 1 to ab r1/1 line 1 t2.g + 2 ab ab/1 line 4 t2.g + 3 to a ab/1 line 4 t2.g + 4 a a/1 line 8 t2.g + 5 #token D a/1 line 8 t2.g + 6 #token E a/1 line 8 t2.g + + #endif + && + #if 0 + + pred << p(LATEXT(2))>>? + depth=k=2 ("=>" guard) rule a line 8 t2.g + tree context: + (root = A + B + ) + + #endif + + (! ( LA(1)==A && LA(2)==B ) || p(LATEXT(2)) ) { + ab(); + ... + +#165. (Changed in MR13) option -newAST + + To create ASTs from an ANTLRTokenPtr antlr usually calls + "new AST(ANTLRTokenPtr)". This option generates a call + to "newAST(ANTLRTokenPtr)" instead. This allows a user + to define a parser member function to create an AST object. + +#161. (Changed in MR13) Switch -gxt inhibits generation of tokens.h + +#158. (Changed in MR13) #header causes problem for pre-processors + + A user who runs the C pre-processor on antlr source suggested + that another syntax be allowed. With MR13 such directives + such as #header, #pragma, etc. may be written as "\#header", + "\#pragma", etc. For escaping pre-processor directives inside + a #header use something like the following: + + \#header + << + \#include + >> + +#155. (Changed in MR13) Context behind predicates can suppress + + With -mrhoist enabled the context behind a guarded predicate can + be used to suppress other predicates. Consider the following grammar: + + r0 : (r1)+; + + r1 : rp + | rq + ; + rp : <

>? B ; + rq : (A)? => <>? (A|B); + + In earlier versions both predicates "p" and "q" would be hoisted into + rule r0. With MR12c predicate p is suppressed because the context which + follows predicate q includes "B" which can "cover" predicate "p". In + other words, in trying to decide in r0 whether to call r1, it doesn't + really matter whether p is false or true because, either way, there is + a valid choice within r1. + +#154. (Changed in MR13) Making hoist suppression explicit using <> + + A common error, even among experienced pccts users, is to code + an init-action to inhibit hoisting rather than a leading action. + An init-action does not inhibit hoisting. + + This was coded: + + rule1 : <<;>> rule2 + + This is what was meant: + + rule1 : <<;>> <<;>> rule2 + + With MR13, the user can code: + + rule1 : <<;>> <> rule2 + + The following will give an error message: + + rule1 : <> rule2 + + If the <> appears as an init-action rather than a leading + action an error message is issued. The meaning of an init-action + containing "nohoist" is unclear: does it apply to just one + alternative or to all alternatives ? + +#151a. Addition of ANTLRParser::getLexer(), ANTLRTokenStream::getLexer() + + You must manually cast the ANTLRTokenStream to your program's + lexer class. Because the name of the lexer's class is not fixed. + Thus it is impossible to incorporate it into the DLGLexerBase + class. + +#151b.(Changed in MR12) ParserBlackBox member getLexer() + +#150. (Changed in MR12) syntaxErrCount and lexErrCount now public + +#149. (Changed in MR12) antlr option -info o (letter o for orphan) + + If there is more than one rule which is not referenced by any + other rule then all such rules are listed. This is useful for + alerting one to rules which are not used, but which can still + contribute to ambiguity. + +#148. (Changed in MR11) #token names appearing in zztokens,token_tbl + + One can write: + + #token Plus ("+") "\+" + #token RP ("(") "\(" + #token COM ("comment begin") "/\*" + + The string in parenthesis will be used in syntax error messages. + +#146. (Changed in MR11) Option -treport for locating "difficult" alts + + It can be difficult to determine which alternatives are causing + pccts to work hard to resolve an ambiguity. In some cases the + ambiguity is successfully resolved after much CPU time so there + is no message at all. + + A rough measure of the amount of work being peformed which is + independent of the CPU speed and system load is the number of + tnodes created. Using "-info t" gives information about the + total number of tnodes created and the peak number of tnodes. + + Tree Nodes: peak 1300k created 1416k lost 0 + + It also puts in the generated C or C++ file the number of tnodes + created for a rule (at the end of the rule). However this + information is not sufficient to locate the alternatives within + a rule which are causing the creation of tnodes. + + Using: + + antlr -treport 100000 .... + + causes antlr to list on stdout any alternatives which require the + creation of more than 100,000 tnodes, along with the lookahead sets + for those alternatives. + + The following is a trivial case from the ansi.g grammar which shows + the format of the report. This report might be of more interest + in cases where 1,000,000 tuples were created to resolve the ambiguity. + + ------------------------------------------------------------------------- + There were 0 tuples whose ambiguity could not be resolved + by full lookahead + There were 157 tnodes created to resolve ambiguity between: + + Choice 1: statement/2 line 475 file ansi.g + Choice 2: statement/3 line 476 file ansi.g + + Intersection of lookahead[1] sets: + + IDENTIFIER + + Intersection of lookahead[2] sets: + + LPARENTHESIS COLON AMPERSAND MINUS + STAR PLUSPLUS MINUSMINUS ONESCOMPLEMENT + NOT SIZEOF OCTALINT DECIMALINT + HEXADECIMALINT FLOATONE FLOATTWO IDENTIFIER + STRING CHARACTER + ------------------------------------------------------------------------- + +#143. (Changed in MR11) Optional ";" at end of #token statement + + Fixes problem of: + + #token X "x" + + << + parser action + >> + + Being confused with: + + #token X "x" <> + +#142. (Changed in MR11) class BufFileInput subclass of DLGInputStream + + Alexey Demakov (demakov@kazbek.ispras.ru) has supplied class + BufFileInput derived from DLGInputStream which provides a + function lookahead(char *string) to test characters in the + input stream more than one character ahead. + The class is located in pccts/h/BufFileInput.* of the kit. + +#140. #pred to define predicates + + +---------------------------------------------------+ + | Note: Assume "-prc on" for this entire discussion | + +---------------------------------------------------+ + + A problem with predicates is that each one is regarded as + unique and capable of disambiguating cases where two + alternatives have identical lookahead. For example: + + rule : <>? A + | <>? A + ; + + will not cause any error messages or warnings to be issued + by earlier versions of pccts. To compare the text of the + predicates is an incomplete solution. + + In 1.33MR11 I am introducing the #pred statement in order to + solve some problems with predicates. The #pred statement allows + one to give a symbolic name to a "predicate literal" or a + "predicate expression" in order to refer to it in other predicate + expressions or in the rules of the grammar. + + The predicate literal associated with a predicate symbol is C + or C++ code which can be used to test the condition. A + predicate expression defines a predicate symbol in terms of other + predicate symbols using "!", "&&", and "||". A predicate symbol + can be defined in terms of a predicate literal, a predicate + expression, or *both*. + + When a predicate symbol is defined with both a predicate literal + and a predicate expression, the predicate literal is used to generate + code, but the predicate expression is used to check for two + alternatives with identical predicates in both alternatives. + + Here are some examples of #pred statements: + + #pred IsLabel <>? + #pred IsLocalVar <>? + #pred IsGlobalVar <>? + #pred IsVar <>? IsLocalVar || IsGlobalVar + #pred IsScoped <>? IsLabel || IsLocalVar + + I hope that the use of EBNF notation to describe the syntax of the + #pred statement will not cause problems for my readers (joke). + + predStatement : "#pred" + CapitalizedName + ( + "<>?" + | "<>?" predOrExpr + | predOrExpr + ) + ; + + predOrExpr : predAndExpr ( "||" predAndExpr ) * ; + + predAndExpr : predPrimary ( "&&" predPrimary ) * ; + + predPrimary : CapitalizedName + | "!" predPrimary + | "(" predOrExpr ")" + ; + + What is the purpose of this nonsense ? + + To understand how predicate symbols help, you need to realize that + predicate symbols are used in two different ways with two different + goals. + + a. Allow simplification of predicates which have been combined + during predicate hoisting. + + b. Allow recognition of identical predicates which can't disambiguate + alternatives with common lookahead. + + First we will discuss goal (a). Consider the following rule: + + rule0: rule1 + | ID + | ... + ; + + rule1: rule2 + | rule3 + ; + + rule2: <>? ID ; + rule3: <>? ID ; + + When the predicates in rule2 and rule3 are combined by hoisting + to create a prediction expression for rule1 the result is: + + if ( LA(1)==ID + && ( isX(LATEXT(1) || !isX(LATEXT(1) ) ) { rule1(); ... + + This is inefficient, but more importantly, can lead to false + assumptions that the predicate expression distinguishes the rule1 + alternative with some other alternative with lookahead ID. In + MR11 one can write: + + #pred IsX <>? + + ... + + rule2: <>? ID ; + rule3: <>? ID ; + + During hoisting MR11 recognizes this as a special case and + eliminates the predicates. The result is a prediction + expression like the following: + + if ( LA(1)==ID ) { rule1(); ... + + Please note that the following cases which appear to be equivalent + *cannot* be simplified by MR11 during hoisting because the hoisting + logic only checks for a "!" in the predicate action, not in the + predicate expression for a predicate symbol. + + *Not* equivalent and is not simplified during hoisting: + + #pred IsX <>? + #pred NotX <>? + ... + rule2: <>? ID ; + rule3: <>? ID ; + + *Not* equivalent and is not simplified during hoisting: + + #pred IsX <>? + #pred NotX !IsX + ... + rule2: <>? ID ; + rule3: <>? ID ; + + Now we will discuss goal (b). + + When antlr discovers that there is a lookahead ambiguity between + two alternatives it attempts to resolve the ambiguity by searching + for predicates in both alternatives. In the past any predicate + would do, even if the same one appeared in both alternatives: + + rule: <>? X + | <>? X + ; + + The #pred statement is a start towards solving this problem. + During ambiguity resolution (*not* predicate hoisting) the + predicates for the two alternatives are expanded and compared. + Consider the following example: + + #pred Upper <>? + #pred Lower <>? + #pred Alpha <>? Upper || Lower + + rule0: rule1 + | <>? ID + ; + + rule1: + | rule2 + | rule3 + ... + ; + + rule2: <>? ID; + rule3: <>? ID; + + The definition of #pred Alpha expresses: + + a. to test the predicate use the C code "isAlpha(LATEXT(1))" + + b. to analyze the predicate use the information that + Alpha is equivalent to the union of Upper and Lower, + + During ambiguity resolution the definition of Alpha is expanded + into "Upper || Lower" and compared with the predicate in the other + alternative, which is also "Upper || Lower". Because they are + identical MR11 will report a problem. + + ------------------------------------------------------------------------- + t10.g, line 5: warning: the predicates used to disambiguate rule rule0 + (file t10.g alt 1 line 5 and alt 2 line 6) + are identical when compared without context and may have no + resolving power for some lookahead sequences. + ------------------------------------------------------------------------- + + If you use the "-info p" option the output file will contain: + + +----------------------------------------------------------------------+ + |#if 0 | + | | + |The following predicates are identical when compared without | + | lookahead context information. For some ambiguous lookahead | + | sequences they may not have any power to resolve the ambiguity. | + | | + |Choice 1: rule0/1 alt 1 line 5 file t10.g | + | | + | The original predicate for choice 1 with available context | + | information: | + | | + | OR expr | + | | + | pred << Upper>>? | + | depth=k=1 rule rule2 line 14 t10.g | + | set context: | + | ID | + | | + | pred << Lower>>? | + | depth=k=1 rule rule3 line 15 t10.g | + | set context: | + | ID | + | | + | The predicate for choice 1 after expansion (but without context | + | information): | + | | + | OR expr | + | | + | pred << isUpper(LATEXT(1))>>? | + | depth=k=1 rule line 1 t10.g | + | | + | pred << isLower(LATEXT(1))>>? | + | depth=k=1 rule line 2 t10.g | + | | + | | + |Choice 2: rule0/2 alt 2 line 6 file t10.g | + | | + | The original predicate for choice 2 with available context | + | information: | + | | + | pred << Alpha>>? | + | depth=k=1 rule rule0 line 6 t10.g | + | set context: | + | ID | + | | + | The predicate for choice 2 after expansion (but without context | + | information): | + | | + | OR expr | + | | + | pred << isUpper(LATEXT(1))>>? | + | depth=k=1 rule line 1 t10.g | + | | + | pred << isLower(LATEXT(1))>>? | + | depth=k=1 rule line 2 t10.g | + | | + | | + |#endif | + +----------------------------------------------------------------------+ + + The comparison of the predicates for the two alternatives takes + place without context information, which means that in some cases + the predicates will be considered identical even though they operate + on disjoint lookahead sets. Consider: + + #pred Alpha + + rule1: <>? ID + | <>? Label + ; + + Because the comparison of predicates takes place without context + these will be considered identical. The reason for comparing + without context is that otherwise it would be necessary to re-evaluate + the entire predicate expression for each possible lookahead sequence. + This would require more code to be written and more CPU time during + grammar analysis, and it is not yet clear whether anyone will even make + use of the new #pred facility. + + A temporary workaround might be to use different #pred statements + for predicates you know have different context. This would avoid + extraneous warnings. + + The above example might be termed a "false positive". Comparison + without context will also lead to "false negatives". Consider the + following example: + + #pred Alpha + #pred Beta + + rule1: <>? A + | rule2 + ; + + rule2: <>? A + | <>? B + ; + + The predicate used for alt 2 of rule1 is (Alpha || Beta). This + appears to be different than the predicate Alpha used for alt1. + However, the context of Beta is B. Thus when the lookahead is A + Beta will have no resolving power and Alpha will be used for both + alternatives. Using the same predicate for both alternatives isn't + very helpful, but this will not be detected with 1.33MR11. + + To properly handle this the predicate expression would have to be + evaluated for each distinct lookahead context. + + To determine whether two predicate expressions are identical is + difficult. The routine may fail to identify identical predicates. + + The #pred feature also compares predicates to see if a choice between + alternatives which is resolved by a predicate which makes the second + choice unreachable. Consider the following example: + + #pred A <>? + #pred B <>? + #pred A_or_B A || B + + r : s + | t + ; + s : <>? ID + ; + t : <>? ID + ; + + ---------------------------------------------------------------------------- + t11.g, line 5: warning: the predicate used to disambiguate the + first choice of rule r + (file t11.g alt 1 line 5 and alt 2 line 6) + appears to "cover" the second predicate when compared without context. + The second predicate may have no resolving power for some lookahead + sequences. + ---------------------------------------------------------------------------- + +#132. (Changed in 1.33MR11) Recognition of identical predicates in alts + + Prior to 1.33MR11, there would be no ambiguity warning when the + very same predicate was used to disambiguate both alternatives: + + test: ref B + | ref C + ; + + ref : <>? A + + In 1.33MR11 this will cause the warning: + + warning: the predicates used to disambiguate rule test + (file v98.g alt 1 line 1 and alt 2 line 2) + are identical and have no resolving power + + ----------------- Note ----------------- + + This is different than the following case + + test: <>? A B + | <>? A C + ; + + In this case there are two distinct predicates + which have exactly the same text. In the first + example there are two references to the same + predicate. The problem represented by this + grammar will be addressed later. + + +#127. (Changed in 1.33MR11) + + Count Syntax Errors Count DLG Errors + ------------------- ---------------- + + C++ mode ANTLRParser:: DLGLexerBase:: + syntaxErrCount lexErrCount + C mode zzSyntaxErrCount zzLexErrCount + + The C mode variables are global and initialized to 0. + They are *not* reset to 0 automatically when antlr is + restarted. + + The C++ mode variables are public. They are initialized + to 0 by the constructors. They are *not* reset to 0 by the + ANTLRParser::init() method. + + Suggested by Reinier van den Born (reinier@vnet.ibm.com). + +#126. (Changed in 1.33MR11) Addition of #first <<...>> + + The #first <<...>> inserts the specified text in the output + files before any other #include statements required by pccts. + The only things before the #first text are comments and + a #define ANTLR_VERSION. + + Requested by and Esa Pulkkinen (esap@cs.tut.fi) and Alexin + Zoltan (alexin@inf.u-szeged.hu). + +#124. A Note on the New "&&" Style Guarded Predicates + + I've been asked several times, "What is the difference between + the old "=>" style guard predicates and the new style "&&" guard + predicates, and how do you choose one over the other" ? + + The main difference is that the "=>" does not apply the + predicate if the context guard doesn't match, whereas + the && form always does. What is the significance ? + + If you have a predicate which is not on the "leading edge" + it is cannot be hoisted. Suppose you need a predicate that + looks at LA(2). You must introduce it manually. The + classic example is: + + castExpr : + LP typeName RP + | .... + ; + + typeName : <>? ID + | STRUCT ID + ; + + The problem is that isTypeName() isn't on the leading edge + of typeName, so it won't be hoisted into castExpr to help + make a decision on which production to choose. + + The *first* attempt to fix it is this: + + castExpr : + <>? + LP typeName RP + | .... + ; + + Unfortunately, this won't work because it ignores + the problem of STRUCT. The solution is to apply + isTypeName() in castExpr if LA(2) is an ID and + don't apply it when LA(2) is STRUCT: + + castExpr : + (LP ID)? => <>? + LP typeName RP + | .... + ; + + In conclusion, the "=>" style guarded predicate is + useful when: + + a. the tokens required for the predicate + are not on the leading edge + b. there are alternatives in the expression + selected by the predicate for which the + predicate is inappropriate + + If (b) were false, then one could use a simple + predicate (assuming "-prc on"): + + castExpr : + <>? + LP typeName RP + | .... + ; + + typeName : <>? ID + ; + + So, when do you use the "&&" style guarded predicate ? + + The new-style "&&" predicate should always be used with + predicate context. The context guard is in ADDITION to + the automatically computed context. Thus it useful for + predicates which depend on the token type for reasons + other than context. + + The following example is contributed by Reinier van den Born + (reinier@vnet.ibm.com). + + +-------------------------------------------------------------------------+ + | This grammar has two ways to call functions: | + | | + | - a "standard" call syntax with parens and comma separated args | + | - a shell command like syntax (no parens and spacing separated args) | + | | + | The former also allows a variable to hold the name of the function, | + | the latter can also be used to call external commands. | + | | + | The grammar (simplified) looks like this: | + | | + | fun_call : ID "(" { expr ("," expr)* } ")" | + | /* ID is function name */ | + | | "@" ID "(" { expr ("," expr)* } ")" | + | /* ID is var containing fun name */ | + | ; | + | | + | command : ID expr* /* ID is function name */ | + | | path expr* /* path is external command name */ | + | ; | + | | + | path : ID /* left out slashes and such */ | + | | "@" ID /* ID is environment var */ | + | ; | + | | + | expr : .... | + | | "(" expr ")"; | + | | + | call : fun_call | + | | command | + | ; | + | | + | Obviously the call is wildly ambiguous. This is more or less how this | + | is to be resolved: | + | | + | A call begins with an ID or an @ followed by an ID. | + | | + | If it is an ID and if it is an ext. command name -> command | + | if followed by a paren -> fun_call | + | otherwise -> command | + | | + | If it is an @ and if the ID is a var name -> fun_call | + | otherwise -> command | + | | + | One can implement these rules quite neatly using && predicates: | + | | + | call : ("@" ID)? && <>? fun_call | + | | (ID)? && <>? command | + | | (ID "(")? fun_call | + | | command | + | ; | + | | + | This can be done better, so it is not an ideal example, but it | + | conveys the principle. | + +-------------------------------------------------------------------------+ + +#122. (Changed in 1.33MR11) Member functions to reset DLG in C++ mode + + void DLGFileReset(FILE *f) { input = f; found_eof = 0; } + void DLGStringReset(DLGChar *s) { input = s; p = &input[0]; } + + Supplied by R.A. Nelson (cowboy@VNET.IBM.COM) + +#119. (Changed in 1.33MR11) Ambiguity aid for grammars + + The user can ask for additional information on ambiguities reported + by antlr to stdout. At the moment, only one ambiguity report can + be created in an antlr run. + + This feature is enabled using the "-aa" (Ambiguity Aid) option. + + The following options control the reporting of ambiguities: + + -aa ruleName Selects reporting by name of rule + -aa lineNumber Selects reporting by line number + (file name not compared) + + -aam Selects "multiple" reporting for a token + in the intersection set of the + alternatives. + + For instance, the token ID may appear dozens + of times in various paths as the program + explores the rules which are reachable from + the point of an ambiguity. With option -aam + every possible path the search program + encounters is reported. + + Without -aam only the first encounter is + reported. This may result in incomplete + information, but the information may be + sufficient and much shorter. + + -aad depth Selects the depth of the search. + The default value is 1. + + The number of paths to be searched, and the + size of the report can grow geometrically + with the -ck value if a full search for all + contributions to the source of the ambiguity + is explored. + + The depth represents the number of tokens + in the lookahead set which are matched against + the set of ambiguous tokens. A depth of 1 + means that the search stops when a lookahead + sequence of just one token is matched. + + A k=1 ck=6 grammar might generate 5,000 items + in a report if a full depth 6 search is made + with the Ambiguity Aid. The source of the + problem may be in the first token and obscured + by the volume of data - I hesitate to call + it information. + + When the user selects a depth > 1, the search + is first performed at depth=1 for both + alternatives, then depth=2 for both alternatives, + etc. + + Sample output for rule grammar in antlr.g itself: + + +---------------------------------------------------------------------+ + | Ambiguity Aid | + | | + | Choice 1: grammar/70 line 632 file a.g | + | Choice 2: grammar/82 line 644 file a.g | + | | + | Intersection of lookahead[1] sets: | + | | + | "\}" "class" "#errclass" "#tokclass" | + | | + | Choice:1 Depth:1 Group:1 ("#errclass") | + | 1 in (...)* block grammar/70 line 632 a.g | + | 2 to error grammar/73 line 635 a.g | + | 3 error error/1 line 894 a.g | + | 4 #token "#errclass" error/2 line 895 a.g | + | | + | Choice:1 Depth:1 Group:2 ("#tokclass") | + | 2 to tclass grammar/74 line 636 a.g | + | 3 tclass tclass/1 line 937 a.g | + | 4 #token "#tokclass" tclass/2 line 938 a.g | + | | + | Choice:1 Depth:1 Group:3 ("class") | + | 2 to class_def grammar/75 line 637 a.g | + | 3 class_def class_def/1 line 669 a.g | + | 4 #token "class" class_def/3 line 671 a.g | + | | + | Choice:1 Depth:1 Group:4 ("\}") | + | 2 #token "\}" grammar/76 line 638 a.g | + | | + | Choice:2 Depth:1 Group:5 ("#errclass") | + | 1 in (...)* block grammar/83 line 645 a.g | + | 2 to error grammar/93 line 655 a.g | + | 3 error error/1 line 894 a.g | + | 4 #token "#errclass" error/2 line 895 a.g | + | | + | Choice:2 Depth:1 Group:6 ("#tokclass") | + | 2 to tclass grammar/94 line 656 a.g | + | 3 tclass tclass/1 line 937 a.g | + | 4 #token "#tokclass" tclass/2 line 938 a.g | + | | + | Choice:2 Depth:1 Group:7 ("class") | + | 2 to class_def grammar/95 line 657 a.g | + | 3 class_def class_def/1 line 669 a.g | + | 4 #token "class" class_def/3 line 671 a.g | + | | + | Choice:2 Depth:1 Group:8 ("\}") | + | 2 #token "\}" grammar/96 line 658 a.g | + +---------------------------------------------------------------------+ + + For a linear lookahead set ambiguity (where k=1 or for k>1 but + when all lookahead sets [i] with i>? A ; + c : A ; + + Prior to 1.33MR10 the code generated for "start" would resemble: + + while { + if (LA(1)==A && + (!LA(1)==A || isUpper())) { + a(); + } + }; + + This code is wrong because it makes rule "c" unreachable from + "start". The essence of the problem is that antlr fails to + recognize that there can be a valid alternative within "a" even + when the predicate <>? is false. + + In 1.33MR10 with -mrhoist the hoisting of the predicate into + "start" is suppressed because it recognizes that "c" can + cover all the cases where the predicate is false: + + while { + if (LA(1)==A) { + a(); + } + }; + + With the antlr "-info p" switch the user will receive information + about the predicate suppression in the generated file: + + -------------------------------------------------------------- + #if 0 + + Hoisting of predicate suppressed by alternative without predicate. + The alt without the predicate includes all cases where + the predicate is false. + + WITH predicate: line 7 v1.g + WITHOUT predicate: line 7 v1.g + + The context set for the predicate: + + A + + The lookahead set for the alt WITHOUT the semantic predicate: + + A + + The predicate: + + pred << isUpper(LATEXT(1))>>? + depth=k=1 rule b line 9 v1.g + set context: + A + tree context: null + + Chain of referenced rules: + + #0 in rule start (line 5 v1.g) to rule a + #1 in rule a (line 7 v1.g) + + #endif + -------------------------------------------------------------- + + A predicate can be suppressed by a combination of alternatives + which, taken together, cover a predicate: + + start : (a)* "@" ; + + a : b | ca | cb | cc ; + + b : <>? ( A | B | C ) ; + + ca : A ; + cb : B ; + cc : C ; + + Consider a more complex example in which "c" covers only part of + a predicate: + + start : (a)* "@" ; + + a : b + | c + ; + + b : <>? + ( A + | X + ); + + c : A + ; + + Prior to 1.33MR10 the code generated for "start" would resemble: + + while { + if ( (LA(1)==A || LA(1)==X) && + (! (LA(1)==A || LA(1)==X) || isUpper()) { + a(); + } + }; + + With 1.33MR10 and -mrhoist the predicate context is restricted to + the non-covered lookahead. The code resembles: + + while { + if ( (LA(1)==A || LA(1)==X) && + (! (LA(1)==X) || isUpper()) { + a(); + } + }; + + With the antlr "-info p" switch the user will receive information + about the predicate restriction in the generated file: + + -------------------------------------------------------------- + #if 0 + + Restricting the context of a predicate because of overlap + in the lookahead set between the alternative with the + semantic predicate and one without + Without this restriction the alternative without the predicate + could not be reached when input matched the context of the + predicate and the predicate was false. + + WITH predicate: line 11 v4.g + WITHOUT predicate: line 12 v4.g + + The original context set for the predicate: + + A X + + The lookahead set for the alt WITHOUT the semantic predicate: + + A + + The intersection of the two sets + + A + + The original predicate: + + pred << isUpper(LATEXT(1))>>? + depth=k=1 rule b line 15 v4.g + set context: + A X + tree context: null + + The new (modified) form of the predicate: + + pred << isUpper(LATEXT(1))>>? + depth=k=1 rule b line 15 v4.g + set context: + X + tree context: null + + #endif + -------------------------------------------------------------- + + The bad news about -mrhoist: + + (a) -mrhoist does not analyze predicates with lookahead + depth > 1. + + (b) -mrhoist does not look past a guarded predicate to + find context which might cover other predicates. + + For these cases you might want to use syntactic predicates. + When a semantic predicate fails during guess mode the guess + fails and the next alternative is tried. + + Limitation (a) is illustrated by the following example: + + start : (stmt)* EOF ; + + stmt : cast + | expr + ; + cast : <>? LP ID RP ; + + expr : LP ID RP ; + + This is not much different from the first example, except that + it requires two tokens of lookahead context to determine what + to do. This predicate is NOT suppressed because the current version + is unable to handle predicates with depth > 1. + + A predicate can be combined with other predicates during hoisting. + In those cases the depth=1 predicates are still handled. Thus, + in the following example the isUpper() predicate will be suppressed + by line #4 when hoisted from "bizarre" into "start", but will still + be present in "bizarre" in order to predict "stmt". + + start : (bizarre)* EOF ; // #1 + // #2 + bizarre : stmt // #3 + | A // #4 + ; + + stmt : cast + | expr + ; + + cast : <>? LP ID RP ; + + expr : LP ID RP ; + | <>? A + + Limitation (b) is illustrated by the following example of a + context guarded predicate: + + rule : (A)? <

>? // #1 + (A // #2 + |B // #3 + ) // #4 + | <> B // #5 + ; + + Recall that this means that when the lookahead is NOT A then + the predicate "p" is ignored and it attempts to match "A|B". + Ideally, the "B" at line #3 should suppress predicate "q". + However, the current version does not attempt to look past + the guard predicate to find context which might suppress other + predicates. + + In some cases -mrhoist will lead to the reporting of ambiguities + which were not visible before: + + start : (a)* "@"; + a : bc | d; + bc : b | c ; + + b : <>? A; + c : A ; + + d : A ; + + In this case there is a true ambiguity in "a" between "bc" and "d" + which can both match "A". Without -mrhoist the predicate in "b" + is hoisted into "a" and there is no ambiguity reported. However, + with -mrhoist, the predicate in "b" is suppressed by "c" (as it + should be) making the ambiguity in "a" apparent. + + The motivations for these changes were hoisting problems reported + by Reinier van den Born (reinier@vnet.ibm.com) and several others. + +#113. (Changed in 1.33MR10) new context guarded pred: (g)? && <

>? expr + + The existing context guarded predicate: + + rule : (guard)? => <

>? expr + | next_alternative + ; + + generates code which resembles: + + if (lookahead(expr) && (!guard || pred)) { + expr() + } else .... + + This is not suitable for some applications because it allows + expr() to be invoked when the predicate is false. This is + intentional because it is meant to mimic automatically computed + predicate context. + + The new context guarded predicate uses the guard information + differently because it has a different goal. Consider: + + rule : (guard)? && <

>? expr + | next_alternative + ; + + The new style of context guarded predicate is equivalent to: + + rule : <>? expr + | next_alternative + ; + + It generates code which resembles: + + if (lookahead(expr) && guard && pred) { + expr(); + } else ... + + Both forms of guarded predicates severely restrict the form of + the context guard: it can contain no rule references, no + (...)*, no (...)+, and no {...}. It may contain token and + token class references, and alternation ("|"). + + Addition for 1.33MR11: in the token expression all tokens must + be at the same height of the token tree: + + (A ( B | C))? && ... is ok (all height 2) + (A ( B | ))? && ... is not ok (some 1, some 2) + (A B C D | E F G H)? && ... is ok (all height 4) + (A B C D | E )? && ... is not ok (some 4, some 1) + + This restriction is required in order to properly compute the lookahead + set for expressions like: + + rule1 : (A B C)? && <>? rule2 ; + rule2 : (A|X) (B|Y) (C|Z); + + This addition was suggested by Rienier van den Born (reinier@vnet.ibm.com) + +#109. (Changed in 1.33MR10) improved trace information + + The quality of the trace information provided by the "-gd" + switch has been improved significantly. Here is an example + of the output from a test program. It shows the rule name, + the first token of lookahead, the call depth, and the guess + status: + + exit rule gusxx {"?"} depth 2 + enter rule gusxx {"?"} depth 2 + enter rule gus1 {"o"} depth 3 guessing + guess done - returning to rule gus1 {"o"} at depth 3 + (guess mode continues - an enclosing guess is still active) + guess done - returning to rule gus1 {"Z"} at depth 3 + (guess mode continues - an enclosing guess is still active) + exit rule gus1 {"Z"} depth 3 guessing + guess done - returning to rule gusxx {"o"} at depth 2 (guess mode ends) + enter rule gus1 {"o"} depth 3 + guess done - returning to rule gus1 {"o"} at depth 3 (guess mode ends) + guess done - returning to rule gus1 {"Z"} at depth 3 (guess mode ends) + exit rule gus1 {"Z"} depth 3 + line 1: syntax error at "Z" missing SC + ... + + Rule trace reporting is controlled by the value of the integer + [zz]traceOptionValue: when it is positive tracing is enabled, + otherwise it is disabled. Tracing during guess mode is controlled + by the value of the integer [zz]traceGuessOptionValue. When + it is positive AND [zz]traceOptionValue is positive rule trace + is reported in guess mode. + + The values of [zz]traceOptionValue and [zz]traceGuessOptionValue + can be adjusted by subroutine calls listed below. + + Depending on the presence or absence of the antlr -gd switch + the variable [zz]traceOptionValueDefault is set to 0 or 1. When + the parser is initialized or [zz]traceReset() is called the + value of [zz]traceOptionValueDefault is copied to [zz]traceOptionValue. + The value of [zz]traceGuessOptionValue is always initialized to 1, + but, as noted earlier, nothing will be reported unless + [zz]traceOptionValue is also positive. + + When the parser state is saved/restored the value of the trace + variables are also saved/restored. If a restore causes a change in + reporting behavior from on to off or vice versa this will be reported. + + When the -gd option is selected, the macro "#define zzTRACE_RULES" + is added to appropriate output files. + + C++ mode + -------- + int traceOption(int delta) + int traceGuessOption(int delta) + void traceReset() + int traceOptionValueDefault + + C mode + -------- + int zzTraceOption(int delta) + int zzTraceGuessOption(int delta) + void zzTraceReset() + int zzTraceOptionValueDefault + + The argument "delta" is added to the traceOptionValue. To + turn on trace when inside a particular rule one: + + rule : <> + ( + rest-of-rule + ) + <> + ; /* fail clause */ <> + + One can use the same idea to turn *off* tracing within a + rule by using a delta of (-1). + + An improvement in the rule trace was suggested by Sramji + Ramanathan (ps@kumaran.com). + +#108. A Note on Deallocation of Variables Allocated in Guess Mode + + NOTE + ------------------------------------------------------ + This mechanism only works for heap allocated variables + ------------------------------------------------------ + + The rewrite of the trace provides the machinery necessary + to properly free variables or undo actions following a + failed guess. + + The macro zzUSER_GUESS_HOOK(guessSeq,zzrv) is expanded + as part of the zzGUESS macro. When a guess is opened + the value of zzrv is 0. When a longjmp() is executed to + undo the guess, the value of zzrv will be 1. + + The macro zzUSER_GUESS_DONE_HOOK(guessSeq) is expanded + as part of the zzGUESS_DONE macro. This is executed + whether the guess succeeds or fails as part of closing + the guess. + + The guessSeq is a sequence number which is assigned to each + guess and is incremented by 1 for each guess which becomes + active. It is needed by the user to associate the start of + a guess with the failure and/or completion (closing) of a + guess. + + Guesses are nested. They must be closed in the reverse + of the order that they are opened. + + In order to free memory used by a variable during a guess + a user must write a routine which can be called to + register the variable along with the current guess sequence + number provided by the zzUSER_GUESS_HOOK macro. If the guess + fails, all variables tagged with the corresponding guess + sequence number should be released. This is ugly, but + it would require a major rewrite of antlr 1.33 to use + some mechanism other than setjmp()/longjmp(). + + The order of calls for a *successful* guess would be: + + zzUSER_GUESS_HOOK(guessSeq,0); + zzUSER_GUESS_DONE_HOOK(guessSeq); + + The order of calls for a *failed* guess would be: + + zzUSER_GUESS_HOOK(guessSeq,0); + zzUSER_GUESS_HOOK(guessSeq,1); + zzUSER_GUESS_DONE_HOOK(guessSeq); + + The default definitions of these macros are empty strings. + + Here is an example in C++ mode. The zzUSER_GUESS_HOOK and + zzUSER_GUESS_DONE_HOOK macros and myGuessHook() routine + can be used without change in both C and C++ versions. + + ---------------------------------------------------------------------- + << + + #include "AToken.h" + + typedef ANTLRCommonToken ANTLRToken; + + #include "DLGLexer.h" + + int main() { + + { + DLGFileInput in(stdin); + DLGLexer lexer(&in,2000); + ANTLRTokenBuffer pipe(&lexer,1); + ANTLRCommonToken aToken; + P parser(&pipe); + + lexer.setToken(&aToken); + parser.init(); + parser.start(); + }; + + fclose(stdin); + fclose(stdout); + return 0; + } + + >> + + << + char *s=NULL; + + #undef zzUSER_GUESS_HOOK + #define zzUSER_GUESS_HOOK(guessSeq,zzrv) myGuessHook(guessSeq,zzrv); + #undef zzUSER_GUESS_DONE_HOOK + #define zzUSER_GUESS_DONE_HOOK(guessSeq) myGuessHook(guessSeq,2); + + void myGuessHook(int guessSeq,int zzrv) { + if (zzrv == 0) { + fprintf(stderr,"User hook: starting guess #%d\n",guessSeq); + } else if (zzrv == 1) { + free (s); + s=NULL; + fprintf(stderr,"User hook: failed guess #%d\n",guessSeq); + } else if (zzrv == 2) { + free (s); + s=NULL; + fprintf(stderr,"User hook: ending guess #%d\n",guessSeq); + }; + } + + >> + + #token A "a" + #token "[\t \ \n]" <> + + class P { + + start : (top)+ + ; + + top : (which) ? <> + | other <> + ; <> + + which : which2 + ; + + which2 : which3 + ; + which3 + : (label)? <> + | (global)? <> + | (exclamation)? <> + ; + + label : <getText());>> A ":" ; + + global : <getText());>> A "::" ; + + exclamation : <getText());>> A "!" ; + + other : <getText());>> "other" ; + + } + ---------------------------------------------------------------------- + + This is a silly example, but illustrates the idea. For the input + "a ::" with tracing enabled the output begins: + + ---------------------------------------------------------------------- + enter rule "start" depth 1 + enter rule "top" depth 2 + User hook: starting guess #1 + enter rule "which" depth 3 guessing + enter rule "which2" depth 4 guessing + enter rule "which3" depth 5 guessing + User hook: starting guess #2 + enter rule "label" depth 6 guessing + guess failed + User hook: failed guess #2 + guess done - returning to rule "which3" at depth 5 (guess mode continues + - an enclosing guess is still active) + User hook: ending guess #2 + User hook: starting guess #3 + enter rule "global" depth 6 guessing + exit rule "global" depth 6 guessing + guess done - returning to rule "which3" at depth 5 (guess mode continues + - an enclosing guess is still active) + User hook: ending guess #3 + enter rule "global" depth 6 guessing + exit rule "global" depth 6 guessing + exit rule "which3" depth 5 guessing + exit rule "which2" depth 4 guessing + exit rule "which" depth 3 guessing + guess done - returning to rule "top" at depth 2 (guess mode ends) + User hook: ending guess #1 + enter rule "which" depth 3 + ..... + ---------------------------------------------------------------------- + + Remember: + + (a) Only init-actions are executed during guess mode. + (b) A rule can be invoked multiple times during guess mode. + (c) If the guess succeeds the rule will be called once more + without guess mode so that normal actions will be executed. + This means that the init-action might need to distinguish + between guess mode and non-guess mode using the variable + [zz]guessing. + +#101. (Changed in 1.33MR10) antlr -info command line switch + + -info + + p - extra predicate information in generated file + + t - information about tnode use: + at the end of each rule in generated file + summary on stderr at end of program + + m - monitor progress + prints name of each rule as it is started + flushes output at start of each rule + + f - first/follow set information to stdout + + 0 - no operation (added in 1.33MR11) + + The options may be combined and may appear in any order. + For example: + + antlr -info ptm -CC -gt -mrhoist on mygrammar.g + +#100a. (Changed in 1.33MR10) Predicate tree simplification + + When the same predicates can be referenced in more than one + alternative of a block large predicate trees can be formed. + + The difference that these optimizations make is so dramatic + that I have decided to use it even when -mrhoist is not selected. + + Consider the following grammar: + + start : ( all )* ; + + all : a + | d + | e + | f + ; + + a : c A B + | c A C + ; + + c : <>? + ; + + d : <>? B C + ; + + e : <>? B C + ; + + f : e X Y + ; + + In rule "a" there is a reference to rule "c" in both alternatives. + The length of the predicate AAA is k=2 and it can be followed in + alternative 1 only by (A B) while in alternative 2 it can be + followed only by (A C). Thus they do not have identical context. + + In rule "all" the alternatives which refer to rules "e" and "f" allow + elimination of the duplicate reference to predicate CCC. + + The table below summarized the kind of simplification performed by + 1.33MR10. In the table, X and Y stand for single predicates + (not trees). + + (OR X (OR Y (OR Z))) => (OR X Y Z) + (AND X (AND Y (AND Z))) => (AND X Y Z) + + (OR X (... (OR X Y) ... )) => (OR X (... Y ... )) + (AND X (... (AND X Y) ... )) => (AND X (... Y ... )) + (OR X (... (AND X Y) ... )) => (OR X (... ... )) + (AND X (... (OR X Y) ... )) => (AND X (... ... )) + + (AND X) => X + (OR X) => X + + In a test with a complex grammar for a real application, a predicate + tree with six OR nodes and 12 leaves was reduced to "(OR X Y Z)". + + In 1.33MR10 there is a greater effort to release memory used + by predicates once they are no longer in use. + +#100b. (Changed in 1.33MR10) Suppression of extra predicate tests + + The following optimizations require that -mrhoist be selected. + + It is relatively easy to optimize the code generated for predicate + gates when they are of the form: + + (AND X Y Z ...) + or (OR X Y Z ...) + + where X, Y, Z, and "..." represent individual predicates (leaves) not + predicate trees. + + If the predicate is an AND the contexts of the X, Y, Z, etc. are + ANDed together to create a single Tree context for the group and + context tests for the individual predicates are suppressed: + + -------------------------------------------------- + Note: This was incorrect. The contexts should be + ORed together. This has been fixed. A more + complete description is available in item #152. + --------------------------------------------------- + + Optimization 1: (AND X Y Z ...) + + Suppose the context for Xtest is LA(1)==LP and the context for + Ytest is LA(1)==LP && LA(2)==ID. + + Without the optimization the code would resemble: + + if (lookaheadContext && + !(LA(1)==LP && LA(1)==LP && LA(2)==ID) || + ( (! LA(1)==LP || Xtest) && + (! (LA(1)==LP || LA(2)==ID) || Xtest) + )) {... + + With the -mrhoist optimization the code would resemble: + + if (lookaheadContext && + ! (LA(1)==LP && LA(2)==ID) || (Xtest && Ytest) {... + + Optimization 2: (OR X Y Z ...) with identical contexts + + Suppose the context for Xtest is LA(1)==ID and for Ytest + the context is also LA(1)==ID. + + Without the optimization the code would resemble: + + if (lookaheadContext && + ! (LA(1)==ID || LA(1)==ID) || + (LA(1)==ID && Xtest) || + (LA(1)==ID && Ytest) {... + + With the -mrhoist optimization the code would resemble: + + if (lookaheadContext && + (! LA(1)==ID) || (Xtest || Ytest) {... + + Optimization 3: (OR X Y Z ...) with distinct contexts + + Suppose the context for Xtest is LA(1)==ID and for Ytest + the context is LA(1)==LP. + + Without the optimization the code would resemble: + + if (lookaheadContext && + ! (LA(1)==ID || LA(1)==LP) || + (LA(1)==ID && Xtest) || + (LA(1)==LP && Ytest) {... + + With the -mrhoist optimization the code would resemble: + + if (lookaheadContext && + (zzpf=0, + (LA(1)==ID && (zzpf=1) && Xtest) || + (LA(1)==LP && (zzpf=1) && Ytest) || + !zzpf) { + + These may appear to be of similar complexity at first, + but the non-optimized version contains two tests of each + context while the optimized version contains only one + such test, as well as eliminating some of the inverted + logic (" !(...) || "). + + Optimization 4: Computation of predicate gate trees + + When generating code for the gates of predicate expressions + antlr 1.33 vanilla uses a recursive procedure to generate + "&&" and "||" expressions for testing the lookahead. As each + layer of the predicate tree is exposed a new set of "&&" and + "||" expressions on the lookahead are generated. In many + cases the lookahead being tested has already been tested. + + With -mrhoist a lookahead tree is computed for the entire + lookahead expression. This means that predicates with identical + context or context which is a subset of another predicate's + context disappear. + + This is especially important for predicates formed by rules + like the following: + + upperCaseVowel : <>? vowel; + vowel: : <>? LETTERS; + + These predicates are combined using AND since both must be + satisfied for rule upperCaseVowel. They have identical + context which makes this optimization very effective. + + The affect of Items #100a and #100b together can be dramatic. In + a very large (but real world) grammar one particular predicate + expression was reduced from an (unreadable) 50 predicate leaves, + 195 LA(1) terms, and 5500 characters to an (easily comprehensible) + 3 predicate leaves (all different) and a *single* LA(1) term. + +#98. (Changed in 1.33MR10) Option "-info p" + + When the user selects option "-info p" the program will generate + detailed information about predicates. If the user selects + "-mrhoist on" additional detail will be provided explaining + the promotion and suppression of predicates. The output is part + of the generated file and sandwiched between #if 0/#endif statements. + + Consider the following k=1 grammar: + + start : ( all ) * ; + + all : ( a + | b + ) + ; + + a : c B + ; + + c : <>? + | B + ; + + b : <>? X + ; + + Below is an excerpt of the output for rule "start" for the three + predicate options (off, on, and maintenance release style hoisting). + + For those who do not wish to use the "-mrhoist on" option for code + generation the option can be used in a "diagnostic" mode to provide + valuable information: + + a. where one should insert null actions to inhibit hoisting + b. a chain of rule references which shows where predicates are + being hoisted + + ====================================================================== + Example of "-info p" with "-mrhoist on" + ====================================================================== + #if 0 + + Hoisting of predicate suppressed by alternative without predicate. + The alt without the predicate includes all cases where the + predicate is false. + + WITH predicate: line 11 v36.g + WITHOUT predicate: line 12 v36.g + + The context set for the predicate: + + B + + The lookahead set for alt WITHOUT the semantic predicate: + + B + + The predicate: + + pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g + + set context: + B + tree context: null + + Chain of referenced rules: + + #0 in rule start (line 1 v36.g) to rule all + #1 in rule all (line 3 v36.g) to rule a + #2 in rule a (line 8 v36.g) to rule c + #3 in rule c (line 11 v36.g) + + #endif + && + #if 0 + + pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g + + set context: + X + tree context: null + + #endif + ====================================================================== + Example of "-info p" with the default -prc setting ( "-prc off") + ====================================================================== + #if 0 + + OR + pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g + + set context: + nil + tree context: null + + pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g + + set context: + nil + tree context: null + + #endif + ====================================================================== + Example of "-info p" with "-prc on" and "-mrhoist off" + ====================================================================== + #if 0 + + OR + pred << LATEXT(1)>>? depth=k=1 rule c line 11 v36.g + + set context: + B + tree context: null + + pred << LATEXT(1)>>? depth=k=1 rule b line 15 v36.g + + set context: + X + tree context: null + + #endif + ====================================================================== + +#60. (Changed in 1.33MR7) Major changes to exception handling + + There were significant problems in the handling of exceptions + in 1.33 vanilla. The general problem is that it can only + process one level of exception handler. For example, a named + exception handler, an exception handler for an alternative, or + an exception for a subrule always went to the rule's exception + handler if there was no "catch" which matched the exception. + + In 1.33MR7 the exception handlers properly "nest". If an + exception handler does not have a matching "catch" then the + nextmost outer exception handler is checked for an appropriate + "catch" clause, and so on until an exception handler with an + appropriate "catch" is found. + + There are still undesirable features in the way exception + handlers are implemented, but I do not have time to fix them + at the moment: + + The exception handlers for alternatives are outside the + block containing the alternative. This makes it impossible + to access variables declared in a block or to resume the + parse by "falling through". The parse can still be easily + resumed in other ways, but not in the most natural fashion. + + This results in an inconsistency between named exception + handlers and exception handlers for alternatives. When + an exception handler for an alternative "falls through" + it goes to the nextmost outer handler - not the "normal + action". + + A major difference between 1.33MR7 and 1.33 vanilla is + the default action after an exception is caught: + + 1.33 Vanilla + ------------ + In 1.33 vanilla the signal value is set to zero ("NoSignal") + and the code drops through to the code following the exception. + For named exception handlers this is the "normal action". + For alternative exception handlers this is the rule's handler. + + 1.33MR7 + ------- + In 1.33MR7 the signal value is NOT automatically set to zero. + + There are two cases: + + For named exception handlers: if the signal value has been + set to zero the code drops through to the "normal action". + + For all other cases the code branches to the nextmost outer + exception handler until it reaches the handler for the rule. + + The following macros have been defined for convenience: + + C/C++ Mode Name + -------------------- + (zz)suppressSignal + set signal & return signal arg to 0 ("NoSignal") + (zz)setSignal(intValue) + set signal & return signal arg to some value + (zz)exportSignal + copy the signal value to the return signal arg + + I'm not sure why PCCTS make a distinction between the local + signal value and the return signal argument, but I'm loathe + to change the code. The burden of copying the local signal + value to the return signal argument can be given to the + default signal handler, I suppose. + +#53. (Explanation for 1.33MR6) What happens after an exception is caught ? + + The Book is silent about what happens after an exception + is caught. + + The following code fragment prints "Error Action" followed + by "Normal Action". + + test : Word ex:Number <> + exception[ex] + catch NoViableAlt: + <> + ; + + The reason for "Normal Action" is that the normal flow of the + program after a user-written exception handler is to "drop through". + In the case of an exception handler for a rule this results in + the execution of a "return" statement. In the case of an + exception handler attached to an alternative, rule, or token + this is the code that would have executed had there been no + exception. + + The user can achieve the desired result by using a "return" + statement. + + test : Word ex:Number <> + exception[ex] + catch NoViableAlt: + <> + ; + + The most powerful mechanism for recovery from parse errors + in pccts is syntactic predicates because they provide + backtracking. Exceptions allow "return", "break", + "consumeUntil(...)", "goto _handler", "goto _fail", and + changing the _signal value. + +#41. (Added in 1.33MR6) antlr -stdout + + Using "antlr -stdout ..." forces the text that would + normally go to the grammar.c or grammar.cpp file to + stdout. + +#40. (Added in 1.33MR6) antlr -tab to change tab stops + + Using "antlr -tab number ..." changes the tab stops + for the grammar.c or grammar.cpp file. The number + must be between 0 and 8. Using 0 gives tab characters, + values between 1 and 8 give the appropriate number of + space characters. + +#34. (Added to 1.33MR1) Add public DLGLexerBase::set_line(int newValue) + + Previously there was no public function for changing the line + number maintained by the lexer. + +#28. (Added to 1.33MR1) More control over DLG header + + Version 1.33MR1 adds the following directives to PCCTS + for C++ mode: + + #lexprefix <> + + Adds source code to the DLGLexer.h file + after the #include "DLexerBase.h" but + before the start of the class definition. + + #lexmember <> + + Adds source code to the DLGLexer.h file + as part of the DLGLexer class body. It + appears immediately after the start of + the class and a "public: statement. + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/KNOWN_PROBLEMS.txt b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/KNOWN_PROBLEMS.txt new file mode 100644 index 00000000..8c4bef7a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/KNOWN_PROBLEMS.txt @@ -0,0 +1,241 @@ + + ======================================================= + Known Problems In PCCTS - Last revised 14 November 1998 + ======================================================= + +#17. The dlg fix for handling characters up to 255 is incorrect. + + See item #207. + + Reported by Frank Hartmann. + +#16. A note about "&&" predicates (Mike Dimmick) + + Mike Dimmick has pointed out a potential pitfall in the use of the + "&&" style predicate. Consider: + + r0: (g)? => <

>? r1 + | ... + ; + r1: A | B; + + If the context guard g is not a subset of the lookahead context for r1 + (in other words g is neither A nor B) then the code may execute r1 + even when the lookahead context is not satisfied. This is an error + by the person coding the grammar, and the error should be reported to + the user, but it isn't. expect. Some examples I've run seem to + indicate that such an error actually results in the rule becoming + unreachable. + + When g is properly coded the code is correct, the problem is when g + is not properly coded. + + A second problem reported by Mike Dimmick is that the test for a + failed validation predicate is equivalent to a test on the predicate + along. In other words, if the "&&" has not been hoisted then it may + falsely report a validation error. + +#15. (Changed in MR23) Warning for LT(i), LATEXT(i) in token match actions + + An bug (or at least an oddity) is that a reference to LT(1), LA(1), + or LATEXT(1) in an action which immediately follows a token match + in a rule refers to the token matched, not the token which is in + the lookahead buffer. Consider: + + r : abc <> D <> E; + + In this case LT(1) in action alpha will refer to the next token in + the lookahead buffer ("D"), but LT(1) in action beta will refer to + the token matched by D - the preceding token. + + A warning has been added which warns users about this when an action + following a token match contains a reference to LT(1), LA(1), or LATEXT(1). + + This behavior should be changed, but it appears in too many programs + now. Another problem, perhaps more significant, is that the obvious + fix (moving the consume() call to before the action) could change the + order in which input is requested and output appears in existing programs. + + This problem was reported, along with a fix by Benjamin Mandel + (beny@sd.co.il). However, I felt that changing the behavior was too + dangerous for existing code. + +#14. Parsing bug in dlg + + THM: I have been unable to reproduce this problem. + + Reported by Rick Howard Mijenix Corporation (rickh@mijenix.com). + + The regular expression parser (in rexpr.c) fails while + trying to parse the following regular expression: + + {[a-zA-Z]:}(\\\\[a-zA-Z0-9]*)+ + + See my comment in the following excerpt from rexpr.c: + + /* + * ::= ( '|' {} )* + * + * Return -1 if syntax error + * Return 0 if none found + * Return 1 if a regExrp was found + */ + static + regExpr(g) + GraphPtr g; + { + Graph g1, g2; + + if ( andExpr(&g1) == -1 ) + { + return -1; + } + + while ( token == '|' ) + { + int a; + next(); + a = andExpr(&g2); + if ( a == -1 ) return -1; /* syntax error below */ + else if ( !a ) return 1; /* empty alternative */ + g1 = BuildNFA_AorB(g1, g2); + } + + if ( token!='\0' ) return -1; + ***** + ***** It appears to fail here becuause token is 125 - the closing '}' + ***** If I change it to: + ***** if ( token!='\0' && token!='}' && token!= ')' ) return -1; + ***** + ***** It succeeds, but I'm not sure this is the corrrect approach. + ***** + *g = g1; + return 1; + } + +#13. dlg reports an invalid range for: [\0x00-\0xff] + + Diagnosed by Piotr Eljasiak (eljasiak@no-spam.zt.gdansk.tpsa.pl): + + Fixed in MR16. + +#12. Strings containing comment actions + + Sequences that looked like C style comments appearing in string + literals are improperly parsed by antlr/dlg. + + << fprintf(out," /* obsolete */ "); + + For this case use: + + << fprintf(out," \/\* obsolete \*\/ "); + + Reported by K.J. Cummings (cummings@peritus.com). + +#11. User hook for deallocation of variables on guess fail + + The mechanism outlined in Item #108 works only for + heap allocated variables. + +#10. Label re-initialization in ( X {y:Y} )* + + If a label assignment is optional and appears in a + (...)* or (...)+ block it will not be reset to NULL + when it is skipped by a subsequent iteration. + + Consider the example: + + ( X { y:Y })* Z + + with input: + + X Y X Z + + The first time through the block Y will be matched and + y will be set to point to the token. On the second + iteration of the (...)* block there is no match for Y. + But y will not be reset to NULL, as the user might + expect, it will contain a reference to the Y that was + matched in the first iteration. + + The work-around is to manually reset y: + + ( X << y = NULL; >> { y:Y } )* Z + + or + + ( X ( y:Y | << y = NULL; >> /* epsilon */ ) )* Z + + Reported by Jeff Vincent (JVincent@novell.com). + +#9. PCCTAST.h PCCTSAST::setType() is a noop + +#8. #tokdefs with ~Token and . + + THM: I have been unable to reproduce this problem. + + When antlr uses #tokdefs to define tokens the fields of + #errclass and #tokclass do not get properly defined. + When it subsequently attempts to take the complement of + the set of tokens (using ~Token or .) it can refer to + tokens which don't have names, generating a fatal error. + +#7. DLG crashes on some invalid inputs + + THM: In MR20 have fixed the most common cases. + + The following token definition will cause DLG to crash. + + #token "()" + + Reported by Mengue Olivier (dolmen@bigfoot.com). + +#6. On MS systems \n\r is treated as two new lines + + Fixed. + +#5. Token expressions in #tokclass + + #errclass does not support TOK1..TOK2 or ~TOK syntax. + #tokclass does not support ~TOKEN syntax + + A workaround for #errclass TOK1..TOK2 is to use a + #tokclass. + + Reported by Dave Watola (dwatola@amtsun.jpl.nasa.gov) + +#4. A #tokdef must appear "early" in the grammar file. + + The "early" section of the grammar file is the only + place where the following directives may appear: + + #header + #first + #tokdefs + #parser + + Any other kind of statement signifiies the end of the + "early" section. + +#3. Use of PURIFY macro for C++ mode + + Item #93 of the CHANGES_FROM_1.33 describes the use of + the PURIFY macro to zero arguments to be passed by + upward inheritance. + + #define PURIFY(r, s) memset((char *) &(r), '\0', (s)); + + This may not be the right thing to do for C++ objects that + have constructors. Reported by Bonny Rais (bonny@werple.net.au). + + For those cases one should #define PURIFY to be an empty macro + in the #header or #first actions. + +#2. Fixed in 1.33MR10 - See CHANGES_FROM_1.33 Item #80. + +#1. The quality of support for systems with 8.3 file names leaves + much to be desired. Since the kit is distributed using the + long file names and the make file uses long file names it requires + some effort to generate. This will probably not be changed due + to the large number of systems already written using the long + file names. diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/MPW_Read_Me b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/MPW_Read_Me new file mode 100644 index 00000000..14587fc3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/MPW_Read_Me @@ -0,0 +1,21 @@ + +1. You can control the creator type of generated files by changing a value of + #if control statement. + + + pccts:h:pcctscfg.h + + line 225-231 + + #if 0 + #define MAC_FILE_CREATOR 'MPS ' /* MPW Text files */ + #endif + #if 0 + #define MAC_FILE_CREATOR 'KAHL' /* THINK C/Symantec C++ Text files */ + #endif + #if 0 + #define MAC_FILE_CREATOR 'CWIE' /* Metrowerks C/C++ Text files */ + #endif + +2. If you want to build 68K version. You must convert all source files to Macintosh + format before compile. diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/Makefile new file mode 100644 index 00000000..577d6cb6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/Makefile @@ -0,0 +1,15 @@ +# +# Main makefile for PCCTS 1.33MR33 /* MRXXX */ +# +pccts: + pushd . & cd antlr & $(MAKE) /nologo /f AntlrMS.mak & popd + pushd . & cd dlg & $(MAKE) /nologo /f DlgMS.mak & popd + +clean: + pushd . & cd antlr & $(MAKE) /nologo /f AntlrMS.mak clean & popd + pushd . & cd dlg & $(MAKE) /nologo /f DlgMS.mak clean & popd + +cleanall: + pushd . & cd antlr & $(MAKE) /nologo /f AntlrMS.mak cleanall & popd + pushd . & cd dlg & $(MAKE) /nologo /f DlgMS.mak cleanall & popd + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/NOTES.bcc b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/NOTES.bcc new file mode 100644 index 00000000..535bba2e --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/NOTES.bcc @@ -0,0 +1,184 @@ +March 95 +Version 1.32 of pccts + +At the moment this file is available via anonymous FTP at + + Node: marvin.ecn.purdue.edu + File: pub/pccts/1.32/NOTES.BCC + +Mail corrections or additions to David Seidel <71333.1575@compuserve.com> +=============================================================================== +Notes on Building PCCTS 1.32 with Borland C++ + +David Seidel, Innovative Data Concepts Incorporated +CompuServe: 71333,1575 +Internet: 71333.1575@compuserve.com + dseidel@delphi.com + +I have gotten ANTLR and DLG to succesfully build with BCC 4.0, but have found +from experience that ANTLR, in particular, is likely to run out of memory +with grammars over a certain size, or with larger values for the -k and -ck +options. Now that BCC 4.02 and the new Borland Power Pack for DOS is now +available, I feel that there is no excuse not to build these tools as +32-bit executables, as they ought to be. + +For people without the Power Pack, the makefiles below should be fairly easily +modified to build 16-bit real-mode executables, but I don't really recommend +it. As an alternative, you might consider the highly regarded DJGPP compiler +(a DOS port of the Gnu GCC compiler, with a DOS extender included). Hopefully +some other PCCTS who has DJGPP can provode whatever advice is necessary. The +Watcom compiler is also an excellent possibility (albeit a commercial one), +and I hope to make available Watcom makefiles in the near future. + +Here are the makefiles I am using. Both makefiles use a compiler configuration +file that contains compiler switches such as optimization settings. I call +this file bor32.cfg and keep a copy in both the ANTLR and DLG subdirectories. + +==== File: bor32.cfg (cut here) =============================================== +-w- +-RT- +-x- +-N- +-k- +-d +-O2-e-l +-Z +-D__STDC__=1 +==== End of file bor32.cfg (cut here) ========================================= + +==== File: antlr\bor32.mak (cut here) ========================================= +# +# ANTLR 1.32 Makefile for Borland C++ 4.02 with DPMI 32-bit DOS extender by +# David Seidel +# Innovative Data Concepts Incorporated +# 71333.1575@compuserve.com (or) dseidel@delphi.com +# +# Notes: 1. Compiler switches (optimization etc.) are contained in the +# file bor32.cfg. +# 2. This makefile requires Borland C++ 4.02 or greater with +# the DOS Power Pack add-on package. +# 3. Change the BCCDIR macro below to the topmost directory in +# which BCC is installed on your system. +# + +BCCDIR = d:\bc4 +CC = bcc32 +SET = ..\support\set +PCCTS_H = ..\h +ANTLR = ..\bin\antlr +DLG = ..\bin\dlg +CFLAGS = -I$(BCCDIR)\include -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN \ + +bor32.cfg +LIBS = dpmi32 cw32 +OBJ_EXT = obj +OBJS = antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj fset.obj \ + gen.obj globals.obj hash.obj lex.obj main.obj misc.obj pred.obj dialog.obj \ + set.obj + +.c.obj: + $(CC) -c $(CFLAGS) {$&.c } + +antlr.exe: $(OBJS) + tlink32 @&&| +-Tpe -ax -c -s -L$(BCCDIR)\lib + +$(BCCDIR)\lib\c0x32 $** +$@ + +$(LIBS) +; +| + copy *.exe ..\bin + + +# *********** Target list of PC machines *********** +# +# Don't worry about the ambiguity messages coming from antlr +# for making antlr.c etc... [should be 10 of them, I think] +# + +# leave this commented out for initial build! +#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g +# $(ANTLR) antlr.g + +antlr.$(OBJ_EXT): antlr.c mode.h tokens.h + +scan.$(OBJ_EXT): scan.c mode.h tokens.h + +# leave this commented out for initial build! +#scan.c mode.h: parser.dlg +# $(DLG) -C2 parser.dlg scan.c + +set.$(OBJ_EXT): $(SET)\set.c + $(CC) -c $(CFLAGS) $(SET)\set.c + +==== End of file antlr\bor32.mak (cut here) =================================== + +==== File: dlg\bor32.mak (cut here) =========================================== +# +# DLG 1.32 Makefile for Borland C++ 4.02 with DPMI 32-bit DOS extender by +# David Seidel +# Innovative Data Concepts Incorporated +# 71333.1575@compuserve.com (or) dseidel@delphi.com +# +# Notes: 1. Compiler switches (optimization etc.) are contained in the +# file bor32.cfg. +# 2. This makefile requires Borland C++ 4.02 or greater with +# the DOS Power Pack add-on package. +# 3. Change the BCCDIR macro below to the topmost directory in +# which BCC is installed on your system. +# + + +BCCDIR = d:\bc4 +CC = bcc32 +SET = ..\support\set +PCCTS_H = ..\h +ANTLR = ..\bin\antlr +DLG = ..\bin\dlg +CFLAGS = -I$(BCCDIR)\include -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN \ + +bor32.cfg +LIBS = dpmi32 cw32 +OBJ_EXT = obj +OBJS = dlg_p.obj dlg_a.obj main.obj err.obj support.obj \ + output.obj relabel.obj automata.obj set.obj + +.c.obj: + $(CC) -c $(CFLAGS) {$&.c } + +dlg.exe : $(OBJS) + tlink32 @&&| +-Tpe -ax -c -s -L$(BCCDIR)\lib + +c0x32 $** +$@ + +$(LIBS) +; +| + copy *.exe ..\bin + +dlg_p.obj: dlg_p.c + +dlg_a.obj: dlg_a.c + +main.obj: main.c + +err.obj: err.c + +support.obj: support.c + +output.obj: output.c + +relabel.obj: relabel.c + +automata.obj: automata.c + +set.$(OBJ_EXT): $(SET)\set.c + $(CC) -c $(CFLAGS) $(SET)\set.c + +==== End of file dlg\bor32.mak (cut here) ===================================== + + + + + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/NOTES.msvc b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/NOTES.msvc new file mode 100644 index 00000000..04809293 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/NOTES.msvc @@ -0,0 +1,189 @@ + + Microsoft Visual C Stuff + + +[Tom Moog 2-Oct-98 + + Users of Microsoft Visual C++ should download a separate + ready-to-run zip file from my web site. It contains + binaries, static library, and a sample project. +] + +[ + Two notes added by Tom Moog 23-Sep-97. I believe the *.dsp and + *.mak files that were once at the end of this file are now obsolete. + + The following MSVC .dsp and .mak files for pccts and sorcerer + were contributed by Stanislaw Bochnak (S.Bochnak@microtool.com.pl) + and Jeff Vincent (jvincent@novell.com) + + PCCTS Distribution Kit + ---------------------- + pccts/antlr/AntlrMSVC50.dsp + pccts/antlr/AntlrMSVC50.mak + + pccts/dlg/DlgMSVC50.dsp + pccts/dlg/DlgMSVC50.mak + + pccts/support/genmk/watgenmk.mak + pccts/support/msvc.dsp + + Sorcerer Distribution Kit + ------------------------- + pccts/sorcerer/SorcererMSVC50.dsp + pccts/sorcerer/SorcererMSVC50.mak + + pccts/sorcerer/lib/msvc.dsp + + I do not have an MS based computer. If you discover problems + please report them so as to save trouble for others in the future. +] + +[ + Modified by Terence Parr (September 1995) to change .C to .cpp +] + +[ + This file contains notes on MSVC for Windows NT console execs by Dave + Seidel and an explanation of flags etc.. by John Hall; good luck, + Terence +] + +=============================================================================== +Date: Sat, 31 Dec 1994 11:40:36 -0500 (EST) +From: David Seidel <75342.2034@compuserve.com> + +I've succesfully build 1.31b3 with djgpp for DOS and MSVC 2.0 for Windows +NT. The only (minor) problem I had was that GNU make (version 3.71, in the +djgpp port) complained about "multiple targets" in both the antlr and dlg +makefiles. I got around the error by, in each makefile, commenting out the +$(SRC) dependency, for example: + + antlr: $(OBJ) #$(SRC) + +I don't know why this is happenning, since you haven't changed that part of +the makefile at all, and I think this used to work ok... + +Here are the makefiles I built from within the MSVC 2.0 environment for antlr +and dlg and Windows NT console executables. Please feel free to pass them +on. Of course, as soon as 1.31 "goes gold", I will send you nice new +binaries. I'm not going to bother to keep doing both Borland and djgpp for +DOS however. Instead, I'll just keep the djgpp version up to date and also +provide WinNT binaries. + +Dave +=============================================================================== + + How to port PCCTS 1.10 (and 1.32 hopefully) to Visual C++ + + By + + John Hall + +Here is how to compile an ANTLR grammar in Visual C++. These steps +describe how to have your ANTLR grammar parse the input file the user +selects when they choose File Open in your Windows application. (Even +if you aren't using Visual C++, the steps should be portable enough to +other compilers.) + + * Make sure that ANTLR and DLG generate ANSI code (use the -ga + switch). + + * Set the following compiler flags in Visual C++ (these are in the + Memory Model category of the compiler options in the Project + Options menu): + + FLAG MEANING + ==== ============================================================== + /AL Large memory model (multiple data segments; data items must be + smaller than 64K). + + /Gtn Allocates all items whose size is greater than or equal to n + in a new data segment. (I let n be 256: /Gt256.) + + /Gx- All references to data items are done with far addressing in + case they are placed in a far segment. + + * Add the following member variable to the attributes section of your + derived CDocument class (you will need to make sure you also + include stdio.h): + + FILE *fp; + + * Add the following method to your derived CDocument class: + + BOOL CAppDoc::OnOpenDocument(const char* pszPathName) + { + // Call CDocument's OnOpenDocument to do housekeeping for us + // DON'T add anything to the loading section of Serialize + if (!CDocument::OnOpenDocument(pszPathName)) + return FALSE; + + // Open input file + if ((fp = fopen(pszPathName, "r")) == NULL) + return FALSE; + + // Parse input file + ANTLR(start(), fp); + + // Close input file + fclose(fp); + return TRUE; + } + + (Note: additional code may be necessary, depending on your parser. + For example, if your parser uses PCCTS's symbol table library, you + will need to insert calls to zzs_init and zzs_done.) + + * Compile the generated C files as C++ files. (I renamed the files + to have a .CPP extension to fool Visual C++ into thinking they were + C++ files. One might also use the /Tp switch, but that switch + requires you separately include the filename.) [I used this step + as an easy out for all the external linking errors I was getting + that I couldn't fix by declaring things extern "C".] + + * Make sure the __STDC__ portion of the generated files gets + compiled. (Either define __STDC__ yourself or else change all + occurrences of __STDC__ to __cplusplus in the generated files. You + can define __STDC__ in the Preprocessor category of the compiler + options.) + + ================================================================ + = Note 23-Sep-97: This is probably not necessary any more. = + = With 1.33MRxxx the use of __STDC__ was replaced with the = + = macro __USE_PROTOS to control the compilation of prototypes. = + ================================================================ + +That last step is important for Visual C++, but may not apply to other +compilers. For C++ compilers, whether __STDC__ is defined is +implementation dependent (ARM, page 379). Apparently, Visual C++ does +not to define it; it also does not support "old style" C function +definitions (which is okay, according to page 404 of the ARM). Those +two things together caused problems when trying to port the code. +When it saw this: + +#ifdef __STDC__ +void +globals(AST **_root) +#else +globals(_root) +AST **_root; +#endif + +it skipped the __STDC__ section and tried to process the "old style" +function definition, where it choked. + +When you finally get your parser to compile and link without error, +you may get General Protection Fault errors at run time. The problem +I had was that a NULL was passed to a variable argument function +without an explicit cast. The function grabbed a pointer (32-bits) +off the stack using va_arg, but the NULL was passed silently as the +integer 0 (16 bits), making the resulting pointer was invalid. (This +was in PCCTS's sample C parser.) + +There is one other thing I might suggest to help you avoid a run-time +error. Make sure you redefine the default error reporting function, +zzsyn. To do this, put "#define USER_ZZSYN" in your #header section +and put your own zzsyn somewhere. You can then pop up a MessageBox or +print the error to some output window. +=============================================================================== diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/README b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/README new file mode 100644 index 00000000..3d1da253 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/README @@ -0,0 +1,159 @@ + + Parr Research Corporation + with + Purdue University Electrical Engineering + and + University of Minnesota, AHPCRC + + Terence Parr + Russell Quong + Will Cohen + Hank Dietz + + +A central place for information about PCCTS 1.33 is: + + http://www.polhode.com/pccts.html + +The maintenance release is available from: + + http://www.polhode.com/pccts133mr.zip + +There is a ready-to-run version for win32 for Microsoft Visual Studio +at the same site. It is available from: + + http://www.polhode.com/win32.zip + +New users should visit http://www.polhode.com/pccts.html in +order to get the following document: + + "Notes For New Users of PCCTS" + +This is a Postscript file of about 40 pages which is extremely +useful for someone starting out. It is a based on 1.33mr21 + +When you have a little more experience, be sure to review the +following documents in the distribution kit: + + CHANGES_FROM_133.txt + CHANGES_FROM_133_BEFORE_MR13.txt + KNOWN_PROBLEMS.txt + +------------------------------------------------------------------------- + INSTALLATION (Unix) +------------------------------------------------------------------------- +0. Download http://www.polhode.com/pccts133mr.zip + +1. Unzip the distribution kit to your preferred location. + If there are newline problems try using zip -a ... + +2. cd to the main pccts directory. + +3. make + + This will create: + + antlr + dlg + sorcerer + genmk + +4. Copy to /usr/local/bin or /usr/local/bin if you like. If you + don't wish to then add pccts/bin to your path. + +5. To get an up-to-date list of program options execute the + program with no command line options. To get up-to-date + documentation read CHANGES_FROM_133*.txt and KNOWN_PROBLEMS.txt + at: + + http://www.polhode.com/pccts.html + +6. You need not create a library. The makefile created by genmk + assumes that the files are not part of a library. + + If you wish to create a library from elements of pccts/h: + + If the first letter of the filename is lowercase (uppercase) it is + related to the code generated using the pccts C mode (C++ mode). + Some of the .c and .cpp files in the h directory are not meant to + be placed in a library and will not compile because they are meant + to be #include in pccts generated files which are grammar specific. + + For C++ users place the following elements in the library: + + AParser.cpp + ASTBase.cpp + ATokenBuffer.cpp + BufFileInput.cpp (optional) + DLexerBase.cpp + PCCTSAST.cpp + SList.cpp + +------------------------------------------------------------------------- + INSTALLATION (Win32) +------------------------------------------------------------------------- + +I've tried to keep the win32 kit to the minimum necessary to get +up and running. The complete kit contains additional information +(some historical), source code, and DevStudio projects for +rebuilding pccts from the source code. + +The kit is now distributed with both MSVC 5 and MSVC6 style projects. + +0. Download http://www.polhode.com/win32.zip. + + You may also wish to download: + + http://www.polhode.com/CHANGES_FROM_133.txt + http://www.polhode.com/CHANGES_FROM_133_BEFORE_MR13.txt + http://www.polhode.com/KNOWN_PROBLEMS.txt + +1. Unzip the distribution kit to your preferred location. + + This will create: + + a pccts directory tree + pccts/bin/*.exe + pccts/lib/*.lib + pccts/h/* + sorcerer/lib/* + sorcerer/h/* + + an example directory tree + pccts\example\calcAST\* + pccts\example\simple\* + +2. Define the environment variable PCCTS to point to the main + pccts directory. + +3. Try building the simple project: pccts\example\simple\simple50.dsw + or simple60.dsw. + +4. Try building the complex project: pccts\example\calcAST\calcAST50.dsw + or calcAST60.dsw. + +------------------------------------------------------------------------- + INSTALLATION (DEC/VMS) +------------------------------------------------------------------------- + +DEC/VMS support added by Piéronne Jean-François (jfp@altavista.net) + +0. Download http://www.polhode.com/pccts133mr.zip + +1. Unzip the distribution kit to your preferred location. + +2. set default to the main pccts directory. + +3. @makefile.vms + + This will create in directory [.bin]: + + antlr.exe + dlg.exe + sorcerer.exe + genmk.exe + +5. To get an up-to-date list of program options execute the + program with no command line options. To get up-to-date + documentation read CHANGES_FROM_133*.txt and KNOWN_PROBLEMS.txt + at http://www.polhode.com/pccts.html. diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/RIGHTS b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/RIGHTS new file mode 100644 index 00000000..5a3e2e76 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/RIGHTS @@ -0,0 +1,26 @@ + +SOFTWARE RIGHTS + +We reserve no LEGAL rights to the Purdue Compiler Construction Tool +Set (PCCTS) -- PCCTS is in the public domain. An individual or +company may do whatever they wish with source code distributed with +PCCTS or the code generated by PCCTS, including the incorporation of +PCCTS, or its output, into commerical software. + +We encourage users to develop software with PCCTS. However, we do ask +that credit is given to us for developing PCCTS. By "credit", we mean +that if you incorporate our source code into one of your programs +(commercial product, research project, or otherwise) that you +acknowledge this fact somewhere in the documentation, research report, +etc... If you like PCCTS and have developed a nice tool with the +output, please mention that you developed it using PCCTS. In +addition, we ask that this header remain intact in our source code. +As long as these guidelines are kept, we expect to continue enhancing +this system and expect to make other tools available as they are +completed. + +ANTLR 1.33 +Terence Parr +Parr Research Corporation +with Purdue University and AHPCRC, University of Minnesota +1989-1995 diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrDDK.mak b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrDDK.mak new file mode 100644 index 00000000..9c6cad59 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrDDK.mak @@ -0,0 +1,233 @@ +# PCCTS directory + +# You will need to set the LIB variable similar to this. +# LIB="C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/lib;c:/Microsoft Visual Studio .NET 2003/Vc7/PlatformSDK/Lib" + +# PCCTS_HOME= +PCCTS_HOME=$(WORKSPACE)\Tools\CCode\Source\Pccts +ANTLR_SRC=$(PCCTS_HOME)\antlr +PCCTS_H=$(PCCTS_HOME)\h + + +# Support directories +SET=$(PCCTS_HOME)\support\set + + +# Compiler stuff +CC = cl +CFLAGS = /nologo -I "." -I "$(PCCTS_H)" -I "$(SET)" -D "USER_ZZSYN" -D "PC" \ + -D "ZZLEXBUFSIZE=65536" -D "LONGFILENAMES" /Zi /W3 -D__USE_PROTOS /wd4700 + +ANTLR_OBJS = antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \ + fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \ + misc.obj pred.obj egman.obj mrhoist.obj fcache.obj + +SUPPORT_OBJS = set.obj + +# Dependencies + +$(WORKSPACE)\Tools\bin\antlr.exe: $(ANTLR_OBJS) $(SUPPORT_OBJS) + $(CC) $(CFLAGS) -o antlr.exe bufferoverflowu.lib $(ANTLR_OBJS) $(SUPPORT_OBJS) + del *.obj + move antlr.exe $(WORKSPACE)\Tools\bin + + +antlr.obj: $(ANTLR_SRC)\antlr.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\mode.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + $(ANTLR_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\antlr.c + +scan.obj: $(ANTLR_SRC)\scan.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgauto.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\mode.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + $(ANTLR_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\scan.c + +err.obj: $(ANTLR_SRC)\err.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(PCCTS_H)\err.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + $(ANTLR_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\err.c + +bits.obj: $(ANTLR_SRC)\bits.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\bits.c + +build.obj: $(ANTLR_SRC)\build.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\build.c + +fset2.obj: $(ANTLR_SRC)\fset2.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\fset2.c + +fset.obj: $(ANTLR_SRC)\fset.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\fset.c + +gen.obj: $(ANTLR_SRC)\gen.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\gen.c + +globals.obj: $(ANTLR_SRC)\globals.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\globals.c + +hash.obj: $(ANTLR_SRC)\hash.c \ + $(PCCTS_H)\config.h \ + $(ANTLR_SRC)\hash.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\hash.c + +lex.obj: $(ANTLR_SRC)\lex.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\lex.c + +main.obj: $(ANTLR_SRC)\main.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\mode.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\stdpccts.h \ + $(ANTLR_SRC)\syn.h \ + $(ANTLR_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\main.c + +misc.obj: $(ANTLR_SRC)\misc.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\misc.c + +pred.obj: $(ANTLR_SRC)\pred.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\pred.c + +egman.obj: $(ANTLR_SRC)\egman.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\egman.c + +mrhoist.obj: $(ANTLR_SRC)\mrhoist.c \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\mrhoist.c + +fcache.obj: $(ANTLR_SRC)\fcache.c \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\fcache.c + +set.obj: $(SET)\set.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + + $(CC) -c $(CFLAGS) $(SET)\set.c + +clean: + del *.obj + +distclean: + del *.obj + del $(WORKSPACE)\Tools\bin\antlr.exe diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrMS.mak b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrMS.mak new file mode 100644 index 00000000..c659ac28 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrMS.mak @@ -0,0 +1,239 @@ +# PCCTS directory + +# You will need to set the LIB variable similar to this. +# LIB="C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/lib;c:/Microsoft Visual Studio .NET 2003/Vc7/PlatformSDK/Lib" + +# PCCTS_HOME= +PCCTS_HOME=$(BASE_TOOLS_PATH)\Source\C\VfrCompile\Pccts +ANTLR_SRC=$(PCCTS_HOME)\antlr +PCCTS_H=$(PCCTS_HOME)\h + + +# Support directories +SET=$(PCCTS_HOME)\support\set + + +# Compiler stuff +CC = cl +CFLAGS = /nologo -I "." -I "$(PCCTS_H)" -I "$(SET)" -D "USER_ZZSYN" -D "PC" \ + -D "ZZLEXBUFSIZE=65536" /D "LONGFILENAMES" /Zi /W3 -D__USE_PROTOS /wd4700 \ + /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE + +ANTLR_OBJS = antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \ + fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \ + misc.obj pred.obj egman.obj mrhoist.obj fcache.obj + +SUPPORT_OBJS = set.obj + +# Dependencies + +$(EDK_TOOLS_PATH)\Bin\Win32\antlr.exe: $(ANTLR_OBJS) $(SUPPORT_OBJS) + $(CC) $(CFLAGS) -Feantlr.exe $(ANTLR_OBJS) $(SUPPORT_OBJS) + -@if not exist $(EDK_TOOLS_PATH)\Bin\Win32 mkdir $(EDK_TOOLS_PATH)\Bin\Win32 + copy antlr.exe $(EDK_TOOLS_PATH)\Bin\Win32 + + +antlr.obj: $(ANTLR_SRC)\antlr.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\mode.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + $(ANTLR_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\antlr.c + +scan.obj: $(ANTLR_SRC)\scan.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgauto.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\mode.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + $(ANTLR_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\scan.c + +err.obj: $(ANTLR_SRC)\err.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(PCCTS_H)\err.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + $(ANTLR_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\err.c + +bits.obj: $(ANTLR_SRC)\bits.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\bits.c + +build.obj: $(ANTLR_SRC)\build.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\build.c + +fset2.obj: $(ANTLR_SRC)\fset2.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\fset2.c + +fset.obj: $(ANTLR_SRC)\fset.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\fset.c + +gen.obj: $(ANTLR_SRC)\gen.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\gen.c + +globals.obj: $(ANTLR_SRC)\globals.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\globals.c + +hash.obj: $(ANTLR_SRC)\hash.c \ + $(PCCTS_H)\config.h \ + $(ANTLR_SRC)\hash.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\hash.c + +lex.obj: $(ANTLR_SRC)\lex.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\lex.c + +main.obj: $(ANTLR_SRC)\main.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\mode.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\stdpccts.h \ + $(ANTLR_SRC)\syn.h \ + $(ANTLR_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\main.c + +misc.obj: $(ANTLR_SRC)\misc.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\misc.c + +pred.obj: $(ANTLR_SRC)\pred.c \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\pred.c + +egman.obj: $(ANTLR_SRC)\egman.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\egman.c + +mrhoist.obj: $(ANTLR_SRC)\mrhoist.c \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\mrhoist.c + +fcache.obj: $(ANTLR_SRC)\fcache.c \ + $(ANTLR_SRC)\generic.h \ + $(ANTLR_SRC)\hash.h \ + $(ANTLR_SRC)\proto.h \ + $(ANTLR_SRC)\syn.h \ + + $(CC) -c $(CFLAGS) $(ANTLR_SRC)\fcache.c + +set.obj: $(SET)\set.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + + $(CC) -c $(CFLAGS) $(SET)\set.c + +clean: + -del *.obj + -del *.ilk + -del *.pdb + +cleanall: + -del *.obj + -del *.ilk + -del *.pdb + -del *.exe + -del $(EDK_TOOLS_PATH)\Bin\Win32\antlr.exe diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrPPC.mak b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrPPC.mak new file mode 100644 index 00000000..437dbe4d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/AntlrPPC.mak @@ -0,0 +1,101 @@ +# Target: antlrPPC +# Sources: ::support:set:set.c +# antlr.c +# bits.c +# build.c +# egman.c +# err.c +# fcache.c +# fset2.c +# fset.c +# gen.c +# globals.c +# hash.c +# lex.c +# main.c +# misc.c +# mrhoist.c +# pred.c +# scan.c +# Created: Sunday, May 17, 1998 10:24:53 PM +# Author: Kenji Tanaka +MAKEFILE = antlrPPC.make +¥MondoBuild¥ = {MAKEFILE} # Make blank to avoid rebuilds when makefile is modified +Includes = ¶ + -i "::h:" ¶ + -i "::support:set:" +Sym¥PPC = +ObjDir¥PPC = :Obj: +PPCCOptions = {Includes} {Sym¥PPC} -w off -d MPW -d __STDC__=1 -d USER_ZZSYN +Objects¥PPC = ¶ + "{ObjDir¥PPC}set.c.x" ¶ + "{ObjDir¥PPC}antlr.c.x" ¶ + "{ObjDir¥PPC}bits.c.x" ¶ + "{ObjDir¥PPC}build.c.x" ¶ + "{ObjDir¥PPC}egman.c.x" ¶ + "{ObjDir¥PPC}err.c.x" ¶ + "{ObjDir¥PPC}fcache.c.x" ¶ + "{ObjDir¥PPC}fset2.c.x" ¶ + "{ObjDir¥PPC}fset.c.x" ¶ + "{ObjDir¥PPC}gen.c.x" ¶ + "{ObjDir¥PPC}globals.c.x" ¶ + "{ObjDir¥PPC}hash.c.x" ¶ + "{ObjDir¥PPC}lex.c.x" ¶ + "{ObjDir¥PPC}main.c.x" ¶ + "{ObjDir¥PPC}misc.c.x" ¶ + "{ObjDir¥PPC}mrhoist.c.x" ¶ + "{ObjDir¥PPC}pred.c.x" ¶ + "{ObjDir¥PPC}scan.c.x" +antlrPPC ÄÄ {¥MondoBuild¥} {Objects¥PPC} + PPCLink ¶ + -o {Targ} {Sym¥PPC} ¶ + {Objects¥PPC} ¶ + -t 'MPST' ¶ + -c 'MPS ' ¶ + "{SharedLibraries}InterfaceLib" ¶ + "{SharedLibraries}StdCLib" ¶ + #"{SharedLibraries}MathLib" ¶ + "{PPCLibraries}StdCRuntime.o" ¶ + "{PPCLibraries}PPCCRuntime.o" ¶ + "{PPCLibraries}PPCToolLibs.o" +"{ObjDir¥PPC}set.c.x" Ä {¥MondoBuild¥} "::support:set:set.c" + {PPCC} "::support:set:set.c" -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}antlr.c.x" Ä {¥MondoBuild¥} antlr.c + {PPCC} antlr.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}bits.c.x" Ä {¥MondoBuild¥} bits.c + {PPCC} bits.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}build.c.x" Ä {¥MondoBuild¥} build.c + {PPCC} build.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}egman.c.x" Ä {¥MondoBuild¥} egman.c + {PPCC} egman.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}err.c.x" Ä {¥MondoBuild¥} err.c + {PPCC} err.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}fcache.c.x" Ä {¥MondoBuild¥} fcache.c + {PPCC} fcache.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}fset2.c.x" Ä {¥MondoBuild¥} fset2.c + {PPCC} fset2.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}fset.c.x" Ä {¥MondoBuild¥} fset.c + {PPCC} fset.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}gen.c.x" Ä {¥MondoBuild¥} gen.c + {PPCC} gen.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}globals.c.x" Ä {¥MondoBuild¥} globals.c + {PPCC} globals.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}hash.c.x" Ä {¥MondoBuild¥} hash.c + {PPCC} hash.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}lex.c.x" Ä {¥MondoBuild¥} lex.c + {PPCC} lex.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}main.c.x" Ä {¥MondoBuild¥} main.c + {PPCC} main.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}misc.c.x" Ä {¥MondoBuild¥} misc.c + {PPCC} misc.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}mrhoist.c.x" Ä {¥MondoBuild¥} mrhoist.c + {PPCC} mrhoist.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}pred.c.x" Ä {¥MondoBuild¥} pred.c + {PPCC} pred.c -o {Targ} {PPCCOptions} +"{ObjDir¥PPC}scan.c.x" Ä {¥MondoBuild¥} scan.c + {PPCC} scan.c -o {Targ} {PPCCOptions} + +antlrPPC ÄÄ antlr.r + Rez antlr.r -o antlrPPC -a +Install Ä antlrPPC + Duplicate -y antlrPPC "{MPW}"Tools:antlr diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/README b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/README new file mode 100644 index 00000000..d6364eca --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/README @@ -0,0 +1,19 @@ + ANTLR 1.33 + +This directory contains the files necessary to build ANTLR. + +If you do a "make scrub", ANTLR will have to run on antlr.g and DLG +will have to run on parser.dlg. Either + +(1) ANTLR uses the previous antlr in that directory to rebuild itself +(2) Needs to find antlr on the search path + +You will find that running "antlr -gh antlr.g" will result in about +10 ambiguity warnings. These are normal. Don't worry. + +If you do a "make clean" right after installation, ANTLR and DLG should +not need to run; only the C files will compile. + +Don't forget to go into the makefile to uncomment the appropriate +definitions for your OS/architecture/compiler or see the appropriate +NOTES.?? file. diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.1 b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.1 new file mode 100644 index 00000000..6ace1b2a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.1 @@ -0,0 +1,209 @@ +.TH ANTLR 1 "September 1995" "ANTLR" "PCCTS Manual Pages" +.SH NAME +antlr \- ANother Tool for Language Recognition +.SH SYNTAX +.LP +\fBantlr\fR [\fIoptions\fR] \fIgrammar_files\fR +.SH DESCRIPTION +.PP +\fIAntlr\fP converts an extended form of context-free grammar into a +set of C functions which directly implement an efficient form of +deterministic recursive-descent LL(k) parser. Context-free grammars +may be augmented with predicates to allow semantics to influence +parsing; this allows a form of context-sensitive parsing. Selective +backtracking is also available to handle non-LL(k) and even +non-LALR(k) constructs. \fIAntlr\fP also produces a definition of a +lexer which can be automatically converted into C code for a DFA-based +lexer by \fIdlg\fR. Hence, \fIantlr\fR serves a function much like +that of \fIyacc\fR, however, it is notably more flexible and is more +integrated with a lexer generator (\fIantlr\fR directly generates +\fIdlg\fR code, whereas \fIyacc\fR and \fIlex\fR are given independent +descriptions). Unlike \fIyacc\fR which accepts LALR(1) grammars, +\fIantlr\fR accepts LL(k) grammars in an extended BNF notation \(em +which eliminates the need for precedence rules. +.PP +Like \fIyacc\fR grammars, \fIantlr\fR grammars can use +automatically-maintained symbol attribute values referenced as dollar +variables. Further, because \fIantlr\fR generates top-down parsers, +arbitrary values may be inherited from parent rules (passed like +function parameters). \fIAntlr\fP also has a mechanism for creating +and manipulating abstract-syntax-trees. +.PP +There are various other niceties in \fIantlr\fR, including the ability to +spread one grammar over multiple files or even multiple grammars in a single +file, the ability to generate a version of the grammar with actions stripped +out (for documentation purposes), and lots more. +.SH OPTIONS +.IP "\fB-ck \fIn\fR" +Use up to \fIn\fR symbols of lookahead when using compressed (linear +approximation) lookahead. This type of lookahead is very cheap to +compute and is attempted before full LL(k) lookahead, which is of +exponential complexity in the worst case. In general, the compressed +lookahead can be much deeper (e.g, \f(CW-ck 10\fP) than the full +lookahead (which usually must be less than 4). +.IP \fB-CC\fP +Generate C++ output from both ANTLR and DLG. +.IP \fB-cr\fP +Generate a cross-reference for all rules. For each rule, print a list +of all other rules that reference it. +.IP \fB-e1\fP +Ambiguities/errors shown in low detail (default). +.IP \fB-e2\fP +Ambiguities/errors shown in more detail. +.IP \fB-e3\fP +Ambiguities/errors shown in excruciating detail. +.IP "\fB-fe\fP file" +Rename \fBerr.c\fP to file. +.IP "\fB-fh\fP file" +Rename \fBstdpccts.h\fP header (turns on \fB-gh\fP) to file. +.IP "\fB-fl\fP file" +Rename lexical output, \fBparser.dlg\fP, to file. +.IP "\fB-fm\fP file" +Rename file with lexical mode definitions, \fBmode.h\fP, to file. +.IP "\fB-fr\fP file" +Rename file which remaps globally visible symbols, \fBremap.h\fP, to file. +.IP "\fB-ft\fP file" +Rename \fBtokens.h\fP to file. +.IP \fB-ga\fP +Generate ANSI-compatible code (default case). This has not been +rigorously tested to be ANSI XJ11 C compliant, but it is close. The +normal output of \fIantlr\fP is currently compilable under both K&R, +ANSI C, and C++\(emthis option does nothing because \fIantlr\fP +generates a bunch of #ifdef's to do the right thing depending on the +language. +.IP \fB-gc\fP +Indicates that \fIantlr\fP should generate no C code, i.e., only +perform analysis on the grammar. +.IP \fB-gd\fP +C code is inserted in each of the \fIantlr\fR generated parsing functions to +provide for user-defined handling of a detailed parse trace. The inserted +code consists of calls to the user-supplied macros or functions called +\fBzzTRACEIN\fR and \fBzzTRACEOUT\fP. The only argument is a +\fIchar *\fR pointing to a C-style string which is the grammar rule +recognized by the current parsing function. If no definition is given +for the trace functions, upon rule entry and exit, a message will be +printed indicating that a particular rule as been entered or exited. +.IP \fB-ge\fP +Generate an error class for each non-terminal. +.IP \fB-gh\fP +Generate \fBstdpccts.h\fP for non-ANTLR-generated files to include. +This file contains all defines needed to describe the type of parser +generated by \fIantlr\fP (e.g. how much lookahead is used and whether +or not trees are constructed) and contains the \fBheader\fP action +specified by the user. +.IP \fB-gk\fP +Generate parsers that delay lookahead fetches until needed. Without +this option, \fIantlr\fP generates parsers which always have \fIk\fP +tokens of lookahead available. +.IP \fB-gl\fP +Generate line info about grammar actions in C parser of the form +\fB#\ \fIline\fP\ "\fIfile\fP"\fR which makes error messages from +the C/C++ compiler make more sense as they will \*Qpoint\*U into the +grammar file not the resulting C file. Debugging is easier as well, +because you will step through the grammar not C file. +.IP \fB-gs\fR +Do not generate sets for token expression lists; instead generate a +\fB||\fP-separated sequence of \fBLA(1)==\fItoken_number\fR. The +default is to generate sets. +.IP \fB-gt\fP +Generate code for Abstract-Syntax Trees. +.IP \fB-gx\fP +Do not create the lexical analyzer files (dlg-related). This option +should be given when the user wishes to provide a customized lexical +analyzer. It may also be used in \fImake\fR scripts to cause only the +parser to be rebuilt when a change not affecting the lexical structure +is made to the input grammars. +.IP "\fB-k \fIn\fR" +Set k of LL(k) to \fIn\fR; i.e. set tokens of look-ahead (default==1). +.IP "\fB-o\fP dir +Directory where output files should go (default="."). This is very +nice for keeping the source directory clear of ANTLR and DLG spawn. +.IP \fB-p\fP +The complete grammar, collected from all input grammar files and +stripped of all comments and embedded actions, is listed to +\fBstdout\fP. This is intended to aid in viewing the entire grammar +as a whole and to eliminate the need to keep actions concisely stated +so that the grammar is easier to read. Hence, it is preferable to +embed even complex actions directly in the grammar, rather than to +call them as subroutines, since the subroutine call overhead will be +saved. +.IP \fB-pa\fP +This option is the same as \fB-p\fP except that the output is +annotated with the first sets determined from grammar analysis. +.IP "\fB-prc on\fR +Turn on the computation and hoisting of predicate context. +.IP "\fB-prc off\fR +Turn off the computation and hoisting of predicate context. This +option makes 1.10 behave like the 1.06 release with option \fB-pr\fR +on. Context computation is off by default. +.IP "\fB-rl \fIn\fR +Limit the maximum number of tree nodes used by grammar analysis to +\fIn\fP. Occasionally, \fIantlr\fP is unable to analyze a grammar +submitted by the user. This rare situation can only occur when the +grammar is large and the amount of lookahead is greater than one. A +nonlinear analysis algorithm is used by PCCTS to handle the general +case of LL(k) parsing. The average complexity of analysis, however, is +near linear due to some fancy footwork in the implementation which +reduces the number of calls to the full LL(k) algorithm. An error +message will be displayed, if this limit is reached, which indicates +the grammar construct being analyzed when \fIantlr\fP hit a +non-linearity. Use this option if \fIantlr\fP seems to go out to +lunch and your disk start thrashing; try \fIn\fP=10000 to start. Once +the offending construct has been identified, try to remove the +ambiguity that \fIantlr\fP was trying to overcome with large lookahead +analysis. The introduction of (...)? backtracking blocks eliminates +some of these problems\ \(em \fIantlr\fP does not analyze alternatives +that begin with (...)? (it simply backtracks, if necessary, at run +time). +.IP \fB-w1\fR +Set low warning level. Do not warn if semantic predicates and/or +(...)? blocks are assumed to cover ambiguous alternatives. +.IP \fB-w2\fR +Ambiguous parsing decisions yield warnings even if semantic predicates +or (...)? blocks are used. Warn if predicate context computed and +semantic predicates incompletely disambiguate alternative productions. +.IP \fB-\fR +Read grammar from standard input and generate \fBstdin.c\fP as the +parser file. +.SH "SPECIAL CONSIDERATIONS" +.PP +\fIAntlr\fP works... we think. There is no implicit guarantee of +anything. We reserve no \fBlegal\fP rights to the software known as +the Purdue Compiler Construction Tool Set (PCCTS) \(em PCCTS is in the +public domain. An individual or company may do whatever they wish +with source code distributed with PCCTS or the code generated by +PCCTS, including the incorporation of PCCTS, or its output, into +commercial software. We encourage users to develop software with +PCCTS. However, we do ask that credit is given to us for developing +PCCTS. By "credit", we mean that if you incorporate our source code +into one of your programs (commercial product, research project, or +otherwise) that you acknowledge this fact somewhere in the +documentation, research report, etc... If you like PCCTS and have +developed a nice tool with the output, please mention that you +developed it using PCCTS. As long as these guidelines are followed, +we expect to continue enhancing this system and expect to make other +tools available as they are completed. +.SH FILES +.IP *.c +output C parser. +.IP *.cpp +output C++ parser when C++ mode is used. +.IP \fBparser.dlg\fP +output \fIdlg\fR lexical analyzer. +.IP \fBerr.c\fP +token string array, error sets and error support routines. Not used in +C++ mode. +.IP \fBremap.h\fP +file that redefines all globally visible parser symbols. The use of +the #parser directive creates this file. Not used in +C++ mode. +.IP \fBstdpccts.h\fP +list of definitions needed by C files, not generated by PCCTS, that +reference PCCTS objects. This is not generated by default. Not used in +C++ mode. +.IP \fBtokens.h\fP +output \fI#defines\fR for tokens used and function prototypes for +functions generated for rules. +.SH "SEE ALSO" +.LP +dlg(1), pccts(1) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.c new file mode 100644 index 00000000..29a593ca --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.c @@ -0,0 +1,3574 @@ +/* + * A n t l r T r a n s l a t i o n H e a d e r + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + * + * ..\bin\antlr -gh antlr.g + * + */ + +#define ANTLR_VERSION 13333 +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include "pcctscfg.h" +#include "set.h" +#include +#include "syn.h" +#include "hash.h" +#include "generic.h" +#define zzcr_attr(attr,tok,t) /*vbox: */ memset((attr), 0, sizeof(*attr)) +#define zzSET_SIZE 20 +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +#include "mode.h" + +/* MR23 In order to remove calls to PURIFY use the antlr -nopurify option */ + +#ifndef PCCTS_PURIFY +#define PCCTS_PURIFY(r,s) memset((char *) &(r),'\0',(s)); +#endif + +ANTLR_INFO + + +/* MR20 G. Hobbelt For Borland C++ 4.x & 5.x compiling with ALL warnings enabled */ +#if defined(__TURBOC__) +#pragma warn -aus /* unused assignment of 'xxx' */ +#endif + +#ifdef VBOX +# ifdef _MSC_VER +# pragma warning(disable : 4068) /* Unguarded '#pragma clang' below */ +# endif +# ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wunknown-pragmas" +# endif +#endif + +#pragma clang diagnostic ignored "-Wparentheses-equality" + +#ifdef __USE_PROTOS +static void chkToken(char *, char *, char *, int); +#else +static void chkToken(); +#endif + +#ifdef __USE_PROTOS +static int isDLGmaxToken(char *Token); /* MR3 */ +#else +static int isDLGmaxToken(); /* MR3 */ +#endif + +static int class_nest_level = 0; + +/* MR20 G. Hobbelt extern definitions moved to antlr.h */ + + + +void +#ifdef __USE_PROTOS +grammar(void) +#else +grammar() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + Graph g; + { + zzBLOCK(zztasp2); + zzMake0; + { + for (;;) { + if ( !((setwd1[LA(1)]&0x1))) break; + if ( (LA(1)==94) ) { + zzmatch(94); zzCONSUME; + zzmatch(Action); + + if ( HdrAction==NULL ) { + HdrAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(HdrAction!=NULL, "rule grammar: cannot allocate header action"); + strcpy(HdrAction, LATEXT(1)); + } + else warn("additional #header statement ignored"); + zzCONSUME; + + } + else { + if ( (LA(1)==95) ) { + zzmatch(95); zzCONSUME; + zzmatch(Action); + + if ( FirstAction==NULL ) { + FirstAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(FirstAction!=NULL, "rule grammar: cannot allocate #first action"); + strcpy(FirstAction, LATEXT(1)); + } else { + warn("additional #first statement ignored"); + }; + zzCONSUME; + + } + else { + if ( (LA(1)==96) ) { + zzmatch(96); zzCONSUME; + zzmatch(QuotedTerm); + + if ( GenCC ) { + warn("#parser meta-op incompatible with -CC; ignored"); + } + else { + if ( strcmp(ParserName,"zzparser")==0 ) { + ParserName=StripQuotes(mystrdup(LATEXT(1))); + if ( RulePrefix[0]!='\0' ) + { + warn("#parser meta-op incompatible with '-gp prefix'; '-gp' ignored"); + RulePrefix[0]='\0'; + } + } + else warn("additional #parser statement ignored"); + } + zzCONSUME; + + } + else { + if ( (LA(1)==97) ) { + zzmatch(97); zzCONSUME; + zzmatch(QuotedTerm); + { + char *fname; + zzantlr_state st; FILE *f; struct zzdlg_state dst; + UserTokenDefsFile = mystrdup(LATEXT(1)); + zzsave_antlr_state(&st); + zzsave_dlg_state(&dst); + fname = mystrdup(LATEXT(1)); + f = fopen(StripQuotes(fname), "r"); + if ( f==NULL ) {warn(eMsg1("cannot open token defs file '%s'", fname+1));} + else { + ANTLRm(enum_file(fname+1), f, PARSE_ENUM_FILE); + UserDefdTokens = 1; + } + zzrestore_antlr_state(&st); + zzrestore_dlg_state(&dst); + } + zzCONSUME; + + } + else break; /* MR6 code for exiting loop "for sure" */ + } + } + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + for (;;) { + if ( !((setwd1[LA(1)]&0x2))) break; + if ( (LA(1)==Action) ) { + zzmatch(Action); + { + UserAction *ua = newUserAction(LATEXT(1)); + ua->file = action_file; ua->line = action_line; + if ( class_nest_level>0 ) list_add(&class_before_actions, ua); + else list_add(&BeforeActions, ua); + } + zzCONSUME; + + } + else { + if ( (LA(1)==108) ) { + laction(); + } + else { + if ( (LA(1)==109) ) { + lmember(); + } + else { + if ( (LA(1)==110) ) { + lprefix(); + } + else { + if ( (LA(1)==116) ) { + aLexclass(); + } + else { + if ( (LA(1)==120) ) { + token(); + } + else { + if ( (LA(1)==117) ) { + error(); + } + else { + if ( (LA(1)==118) ) { + tclass(); + } + else { + if ( (LA(1)==111) ) { + aPred(); + } + else { + if ( (LA(1)==133) ) { + default_exception_handler(); + } + else { + if ( (LA(1)==99) ) { + class_def(); + } + else { + if ( (LA(1)==98) ) { + zzmatch(98); + + if ( class_nest_level==0 ) + warn("missing class definition for trailing '}'"); + class_nest_level--; + zzCONSUME; + + } + else break; /* MR6 code for exiting loop "for sure" */ + } + } + } + } + } + } + } + } + } + } + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + rule(); + g=zzaArg(zztasp1,3); SynDiag = (Junction *) zzaArg(zztasp1,3 ).left; + { + zzBLOCK(zztasp2); + zzMake0; + { + for (;;) { + if ( !((setwd1[LA(1)]&0x4))) break; + if ( (LA(1)==NonTerminal) ) { + rule(); + if ( zzaArg(zztasp2,1 ).left!=NULL ) { + g.right = NULL; + +/* MR21a */ /* Avoid use of a malformed graph when CannotContinue */ + /* MR21a */ /* is already set */ + /* MR21a */ + /* MR21a */ if (! (CannotContinue && g.left == NULL)) { + /* MR21a */ g = Or(g, zzaArg(zztasp2,1)); + /* MR21a */ } + /* MR21a */ } + } + else { + if ( (LA(1)==116) ) { + aLexclass(); + } + else { + if ( (LA(1)==120) ) { + token(); + } + else { + if ( (LA(1)==117) ) { + error(); + } + else { + if ( (LA(1)==118) ) { + tclass(); + } + else { + if ( (LA(1)==111) ) { + aPred(); + } + else { + if ( (LA(1)==99) ) { + class_def(); + } + else { + if ( (LA(1)==98) ) { + zzmatch(98); + + if ( class_nest_level==0 ) + warn("missing class definition for trailing '}'"); + class_nest_level--; + zzCONSUME; + + } + else break; /* MR6 code for exiting loop "for sure" */ + } + } + } + } + } + } + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + for (;;) { + if ( !((setwd1[LA(1)]&0x8))) break; + if ( (LA(1)==Action) ) { + zzmatch(Action); + { + UserAction *ua = newUserAction(LATEXT(1)); + ua->file = action_file; ua->line = action_line; + if ( class_nest_level>0 ) list_add(&class_after_actions, ua); + else list_add(&AfterActions, ua); + } + zzCONSUME; + + } + else { + if ( (LA(1)==108) ) { + laction(); + } + else { + if ( (LA(1)==109) ) { + lmember(); + } + else { + if ( (LA(1)==110) ) { + lprefix(); + } + else { + if ( (LA(1)==117) ) { + error(); + } + else { + if ( (LA(1)==118) ) { + tclass(); + } + else { + if ( (LA(1)==99) ) { + class_def(); + } + else { + if ( (LA(1)==111) ) { + aPred(); + } + else { + if ( (LA(1)==98) ) { + zzmatch(98); + + if ( class_nest_level==0 ) + warn("missing class definition for trailing '}'"); + class_nest_level--; + zzCONSUME; + + } + else break; /* MR6 code for exiting loop "for sure" */ + } + } + } + } + } + } + } + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzmatch(Eof); zzCONSUME; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd1, 0x10); + } +} + +void +#ifdef __USE_PROTOS +class_def(void) +#else +class_def() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + int go=1; char name[MaxRuleName+1]; + zzmatch(99); zzCONSUME; + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==NonTerminal) ) { + zzmatch(NonTerminal); + if(go) strncpy(name,LATEXT(1),MaxRuleName); + zzCONSUME; + + } + else { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + if(go) strncpy(name,LATEXT(1),MaxRuleName); + zzCONSUME; + + } + else {zzFAIL(1,zzerr1,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + + if ( CurrentClassName[0]!='\0' && strcmp(CurrentClassName,name)!=0 + && GenCC ) { + err("only one grammar class allowed in this release"); + go = 0; + } + else strcpy(CurrentClassName, name); + if ( !GenCC ) { err("class meta-op used without C++ option"); } + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (setwd1[LA(1)]&0x20) ) { + zzsetmatch(zzerr2, zzerr3); + if (ClassDeclStuff == NULL) { + /* MR10 */ ClassDeclStuff=(char *)calloc(MaxClassDeclStuff+1,sizeof(char)); + /* MR10 */ }; + /* MR10 */ strncat(ClassDeclStuff," ",MaxClassDeclStuff); + /* MR10 */ strncat(ClassDeclStuff,LATEXT(1),MaxClassDeclStuff); + /* MR22 */ do { + /* MR22 */ if (0 == strcmp(LATEXT(1),"public")) break; + /* MR22 */ if (0 == strcmp(LATEXT(1),"private")) break; + /* MR22 */ if (0 == strcmp(LATEXT(1),"protected")) break; + /* MR22 */ if (0 == strcmp(LATEXT(1),"virtual")) break; + /* MR22 */ if (0 == strcmp(LATEXT(1),",")) break; + /* MR22 */ if (0 == strcmp(LATEXT(1),":")) break; + /* MR22 */ if (BaseClassName != NULL) break; + /* MR22 */ BaseClassName=(char *)calloc(strlen(LATEXT(1))+1,sizeof(char)); + /* MR22 */ require(BaseClassName!=NULL, "rule grammar: cannot allocate base class name"); + /* MR22 */ strcpy(BaseClassName,LATEXT(1)); + /* MR22 */ } while (0); + /* MR10 */ + zzCONSUME; + + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzmatch(102); + + no_classes_found = 0; + if ( class_nest_level>=1 ) {warn("cannot have nested classes");} + else class_nest_level++; + zzCONSUME; + + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd1, 0x40); + } +} + +void +#ifdef __USE_PROTOS +rule(void) +#else +rule() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + + + ExceptionGroup *eg; + RuleEntry *q; Junction *p; Graph r; int f, l; ECnode *e; + set toksrefd, rulesrefd; + char *pdecl=NULL, *ret=NULL, *a; CurRetDef = CurParmDef = NULL; + CurExGroups = NULL; + CurElementLabels = NULL; + CurAstLabelsInActions = NULL; /* MR27 */ + /* We want a new element label hash table for each rule */ + if ( Elabel!=NULL ) killHashTable(Elabel); + Elabel = newHashTable(); + attribsRefdFromAction = empty; + zzmatch(NonTerminal); + q=NULL; + if ( hash_get(Rname, LATEXT(1))!=NULL ) { + err(eMsg1("duplicate rule definition: '%s'",LATEXT(1))); + CannotContinue=TRUE; + } + else + { + q = (RuleEntry *)hash_add(Rname, + LATEXT(1), + (Entry *)newRuleEntry(LATEXT(1))); + CurRule = q->str; + } + CurRuleNode = q; + f = CurFile; l = zzline; + NumRules++; + zzCONSUME; + + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==103) ) { + zzmatch(103); + if ( q!=NULL ) q->noAST = TRUE; + zzCONSUME; + + } + else { + if ( (setwd1[LA(1)]&0x80) ) { + } + else {zzFAIL(1,zzerr4,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + ; + if ( (setwd2[LA(1)]&0x1) ) { + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==104) ) { + zzmatch(104); zzCONSUME; + } + else { + if ( (LA(1)==PassAction) ) { + } + else {zzFAIL(1,zzerr5,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + zzmatch(PassAction); + pdecl = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(pdecl!=NULL, "rule rule: cannot allocate param decl"); + strcpy(pdecl, LATEXT(1)); + CurParmDef = pdecl; + zzCONSUME; + + } + else { + if ( (setwd2[LA(1)]&0x2) ) { + } + else {zzFAIL(1,zzerr6,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==105) ) { + zzmatch(105); zzCONSUME; + zzmatch(PassAction); + ret = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(ret!=NULL, "rule rule: cannot allocate ret type"); + strcpy(ret, LATEXT(1)); + CurRetDef = ret; + zzCONSUME; + + } + else { + if ( (setwd2[LA(1)]&0x4) ) { + } + else {zzFAIL(1,zzerr7,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + if ( q!=NULL ) q->egroup=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==106) ) { + } + else {zzFAIL(1,zzerr8,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + + if ( GenEClasseForRules && q!=NULL ) { + e = newECnode; + require(e!=NULL, "cannot allocate error class node"); + if ( q->egroup == NULL ) {a = q->str; a[0] = (char)toupper(a[0]);} + else a = q->egroup; + if ( Tnum( a ) == 0 ) + { + e->tok = addTname( a ); + list_add(&eclasses, (char *)e); + if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]); + /* refers to itself */ + list_add(&(e->elist), mystrdup(q->str)); + } + else { + warn(eMsg1("default errclass for '%s' would conflict with token/errclass/tokclass",a)); + if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]); + free((char *)e); + } + } + BlkLevel++; + if (BlkLevel >= MAX_BLK_LEVEL) fatal("Blocks nested too deeply"); + /* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID; + /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + zzmatch(106); + inAlt=1; + zzCONSUME; + + block( &toksrefd, &rulesrefd ); + r = makeBlk(zzaArg(zztasp1,7),0, NULL /* pFirstSetSymbol */ ); + CurRuleBlk = (Junction *)r.left; + CurRuleBlk->blockid = CurBlockID; + CurRuleBlk->jtype = RuleBlk; + if ( q!=NULL ) CurRuleBlk->rname = q->str; + CurRuleBlk->file = f; + CurRuleBlk->line = l; + CurRuleBlk->pdecl = pdecl; + CurRuleBlk->ret = ret; + CurRuleBlk->lock = makelocks(); + CurRuleBlk->pred_lock = makelocks(); + CurRuleBlk->tokrefs = toksrefd; + CurRuleBlk->rulerefs = rulesrefd; + p = newJunction(); /* add EndRule Node */ + ((Junction *)r.right)->p1 = (Node *)p; + r.right = (Node *) p; + p->jtype = EndRule; + p->lock = makelocks(); + p->pred_lock = makelocks(); + CurRuleBlk->end = p; + if ( q!=NULL ) q->rulenum = NumRules; + zzaArg(zztasp1,7) = r; + + /* MR23 */ CurBlockID_array[BlkLevel] = (-1); + /* MR23 */ CurAltNum_array[BlkLevel] = (-1); + --BlkLevel; + altFixup();leFixup();egFixup(); + zzmatch(107); + inAlt=0; + zzCONSUME; + + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==Action) ) { + zzmatch(Action); + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule rule: cannot allocate error action"); + strcpy(a, LATEXT(1)); + CurRuleBlk->erraction = a; + zzCONSUME; + + } + else { + if ( (setwd2[LA(1)]&0x8) ) { + } + else {zzFAIL(1,zzerr9,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==133) ) { + eg = exception_group(); + + if ( eg!=NULL ) { + list_add(&CurExGroups, (void *)eg); + if (eg->label == NULL || *eg->label=='\0' ) q->has_rule_exception = 1; + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + if ( q==NULL ) zzaArg(zztasp1,0 ).left = NULL; else zzaArg(zztasp1,0) = zzaArg(zztasp1,7); + CurRuleBlk->exceptions = CurExGroups; + CurRuleBlk->el_labels = CurElementLabels; + CurRuleNode->ast_labels_in_actions = CurAstLabelsInActions; + CurRuleNode = NULL; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd2, 0x10); + } +} + +void +#ifdef __USE_PROTOS +laction(void) +#else +laction() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + char *a; + zzmatch(108); zzCONSUME; + zzmatch(Action); + + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule laction: cannot allocate action"); + strcpy(a, LATEXT(1)); + list_add(&LexActions, a); + zzCONSUME; + + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd2, 0x20); + } +} + +void +#ifdef __USE_PROTOS +lmember(void) +#else +lmember() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + char *a; + zzmatch(109); zzCONSUME; + zzmatch(Action); + + /* MR1 */ if (! GenCC) { + /* MR1 */ err("Use #lexmember only in C++ mode (to insert code in DLG class header"); + /* MR1 */ } else { + /* MR1 */ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + /* MR1 */ require(a!=NULL, "rule lmember: cannot allocate action"); + /* MR1 */ strcpy(a, LATEXT(1)); + /* MR1 */ list_add(&LexMemberActions, a); + /* MR1 */ }; + /* MR1 */ + zzCONSUME; + + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd2, 0x40); + } +} + +void +#ifdef __USE_PROTOS +lprefix(void) +#else +lprefix() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + char *a; + zzmatch(110); zzCONSUME; + zzmatch(Action); + + /* MR1 */ if (! GenCC) { + /* MR1 */ err("Use #lexprefix only in C++ mode (to insert code in DLG class header"); + /* MR1 */ } else { + /* MR1 */ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + /* MR1 */ require(a!=NULL, "rule lprefix: cannot allocate action"); + /* MR1 */ strcpy(a, LATEXT(1)); + /* MR1 */ list_add(&LexPrefixActions, a); + /* MR1 */ }; + /* MR1 */ + zzCONSUME; + + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd2, 0x80); + } +} + +void +#ifdef __USE_PROTOS +aPred(void) +#else +aPred() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + PredEntry *predEntry=NULL; + char *name=NULL; + Predicate *predExpr=NULL; + char *predLiteral=NULL; + int save_file; + int save_line; + int predExprPresent=0; + zzmatch(111); + + MR_usingPredNames=1; /* will need to use -mrhoist version of genPredTree */ + zzCONSUME; + + zzmatch(TokenTerm); + name=mystrdup(LATEXT(1)); + zzCONSUME; + + + /* don't free - referenced in predicates */ + + CurPredName=(char *)calloc(1,strlen(name) + 10); + strcat(CurPredName,"#pred "); + strcat(CurPredName,name); + + predEntry=(PredEntry *) hash_get(Pname,name); + if (predEntry != NULL) { + warnFL(eMsg1("#pred %s previously defined - ignored",name), + FileStr[action_file],action_line); + name=NULL; +}; + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==Pred) ) { + zzmatch(Pred); + predLiteral=mystrdup(LATEXT(1)); + save_line=action_line; + save_file=action_file; + zzCONSUME; + + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (setwd3[LA(1)]&0x1) ) { + predExpr = predOrExpr(); + + predExprPresent=1; + } + else { + if ( (setwd3[LA(1)]&0x2) ) { + } + else {zzFAIL(1,zzerr10,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + if (predLiteral != NULL && name != NULL) { + + /* + * predExpr may be NULL due to syntax errors + * or simply omitted by the user + */ + + predEntry=newPredEntry(name); + predEntry->file=save_file; + predEntry->line=save_line; + predExpr=MR_predFlatten(predExpr); + predEntry->predLiteral=predLiteral; + if (! predExprPresent || predExpr == NULL) { + predExpr=new_pred(); + predExpr->expr=predLiteral; + predExpr->source=newActionNode(); + predExpr->source->action=predExpr->expr; + predExpr->source->rname=CurPredName; + predExpr->source->line=action_line; + predExpr->source->file=action_file; + predExpr->source->is_predicate=1; + predExpr->k=predicateLookaheadDepth(predExpr->source); + }; + predEntry->pred=predExpr; + hash_add(Pname,name,(Entry *)predEntry); + predExpr=NULL; + }; + predicate_free(predExpr); + } + else { + if ( (setwd3[LA(1)]&0x4) ) { + save_line=zzline; save_file=CurFile; + predExpr = predOrExpr(); + + if (predExpr != NULL && name != NULL) { + predEntry=newPredEntry(name); + predEntry->file=CurFile; + predEntry->line=zzline; + predExpr=MR_predFlatten(predExpr); + predEntry->pred=predExpr; + hash_add(Pname,name,(Entry *)predEntry); + predExpr=NULL; + }; + predicate_free(predExpr); + } + else {zzFAIL(1,zzerr11,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==107) ) { + zzmatch(107); zzCONSUME; + } + else { + if ( (setwd3[LA(1)]&0x8) ) { + } + else {zzFAIL(1,zzerr12,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + predicate_free(predExpr); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x10); + } +} + +Predicate * +#ifdef __USE_PROTOS +predOrExpr(void) +#else +predOrExpr() +#endif +{ + Predicate * _retv; + zzRULE; + zzBLOCK(zztasp1); + PCCTS_PURIFY(_retv,sizeof(Predicate * )) + zzMake0; + { + Predicate *ORnode; + Predicate *predExpr; + Predicate **tail=NULL; + predExpr = predAndExpr(); + + + ORnode=new_pred(); + ORnode->expr=PRED_OR_LIST; + if (predExpr != NULL) { + ORnode->down=predExpr; + tail=&predExpr->right; + }; + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==112) ) { + zzmatch(112); zzCONSUME; + predExpr = predAndExpr(); + + + if (predExpr != NULL) { + *tail=predExpr; + tail=&predExpr->right; + }; + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + + _retv=ORnode; + ORnode=NULL; + zzEXIT(zztasp1); + return _retv; +fail: + zzEXIT(zztasp1); + predicate_free(ORnode); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x20); + return _retv; + } +} + +Predicate * +#ifdef __USE_PROTOS +predAndExpr(void) +#else +predAndExpr() +#endif +{ + Predicate * _retv; + zzRULE; + zzBLOCK(zztasp1); + PCCTS_PURIFY(_retv,sizeof(Predicate * )) + zzMake0; + { + Predicate *ANDnode; + Predicate *predExpr; + Predicate **tail=NULL; + predExpr = predPrimary(); + + + ANDnode=new_pred(); + ANDnode->expr=PRED_AND_LIST; + if (predExpr != NULL) { + ANDnode->down=predExpr; + tail=&predExpr->right; + }; + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==113) ) { + zzmatch(113); zzCONSUME; + predExpr = predPrimary(); + + + if (predExpr != NULL) { + *tail=predExpr; + tail=&predExpr->right; + }; + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + + _retv=ANDnode; + ANDnode=NULL; + zzEXIT(zztasp1); + return _retv; +fail: + zzEXIT(zztasp1); + predicate_free(ANDnode); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x40); + return _retv; + } +} + +Predicate * +#ifdef __USE_PROTOS +predPrimary(void) +#else +predPrimary() +#endif +{ + Predicate * _retv; + zzRULE; + zzBLOCK(zztasp1); + PCCTS_PURIFY(_retv,sizeof(Predicate * )) + zzMake0; + { + + char *name=NULL; + PredEntry *predEntry=NULL; + Predicate *predExpr=NULL; + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + name=mystrdup(LATEXT(1)); + zzCONSUME; + + + predEntry=(PredEntry *) hash_get(Pname,name); + if (predEntry == NULL) { + warnFL(eMsg1("no previously defined #pred with name \"%s\"",name), + FileStr[CurFile],zzline); + name=NULL; + _retv=NULL; + } else { + predExpr=predicate_dup(predEntry->pred); + predExpr->predEntry=predEntry; + _retv=predExpr; + }; + } + else { + if ( (LA(1)==114) ) { + zzmatch(114); zzCONSUME; + predExpr = predOrExpr(); + + zzmatch(115); + + _retv=predExpr; + zzCONSUME; + + } + else { + if ( (LA(1)==103) ) { + zzmatch(103); zzCONSUME; + predExpr = predPrimary(); + + + predExpr->inverted=!predExpr->inverted; + _retv=predExpr; + } + else {zzFAIL(1,zzerr13,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp1); + return _retv; +fail: + zzEXIT(zztasp1); + + predicate_free(predExpr); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x80); + return _retv; + } +} + +void +#ifdef __USE_PROTOS +aLexclass(void) +#else +aLexclass() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + zzmatch(116); zzCONSUME; + zzmatch(TokenTerm); + lexclass(mystrdup(LATEXT(1))); + zzCONSUME; + + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd4, 0x1); + } +} + +void +#ifdef __USE_PROTOS +error(void) +#else +error() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + char *t=NULL; ECnode *e; int go=1; TermEntry *p; + zzmatch(117); zzCONSUME; + { + zzBLOCK(zztasp2); + zzMake0; + { + ; + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + t=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + t=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else {zzFAIL(1,zzerr14,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + e = newECnode; + require(e!=NULL, "cannot allocate error class node"); + e->lexclass = CurrentLexClass; + if ( Tnum( (t=StripQuotes(t)) ) == 0 ) + { + if ( hash_get(Texpr, t) != NULL ) + warn(eMsg1("errclass name conflicts with regular expression '%s'",t)); + e->tok = addTname( t ); + set_orel(e->tok, &imag_tokens); + require((p=(TermEntry *)hash_get(Tname, t)) != NULL, + "hash table mechanism is broken"); + p->classname = 1; /* entry is errclass name, not token */ + list_add(&eclasses, (char *)e); + } + else + { + warn(eMsg1("redefinition of errclass or conflict w/token or tokclass '%s'; ignored",t)); + free( (char *)e ); + go=0; +} + zzmatch(102); zzCONSUME; + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==NonTerminal) ) { + zzmatch(NonTerminal); + if ( go ) t=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + if ( go ) t=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + if ( go ) t=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else {zzFAIL(1,zzerr15,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp2); + } + } + if ( go ) list_add(&(e->elist), t); + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (setwd4[LA(1)]&0x2) ) { + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==NonTerminal) ) { + zzmatch(NonTerminal); + if ( go ) t=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + if ( go ) t=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + if ( go ) t=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else {zzFAIL(1,zzerr16,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp3); + } + } + if ( go ) list_add(&(e->elist), t); + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzmatch(98); zzCONSUME; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd4, 0x4); + } +} + +void +#ifdef __USE_PROTOS +tclass(void) +#else +tclass() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + char *t=NULL; TCnode *e; int go=1,tok,totok; TermEntry *p = NULL /* vbox: shut up GCC */, *term, *toterm; + char *akaString=NULL; int save_file; int save_line; + char *totext=NULL; + zzmatch(118); zzCONSUME; + zzmatch(TokenTerm); + t=mystrdup(LATEXT(1)); + zzCONSUME; + + e = newTCnode; + require(e!=NULL, "cannot allocate token class node"); + e->lexclass = CurrentLexClass; + if ( Tnum( t ) == 0 ) + { + e->tok = addTname( t ); + set_orel(e->tok, &imag_tokens); + set_orel(e->tok, &tokclasses); + require((p=(TermEntry *)hash_get(Tname, t)) != NULL, + "hash table mechanism is broken"); + p->classname = 1; /* entry is class name, not token */ + p->tclass = e; /* save ptr to this tclass def */ + list_add(&tclasses, (char *)e); + } + else + { + warn(eMsg1("redefinition of tokclass or conflict w/token '%s'; ignored",t)); + free( (char *)e ); + go=0; +} + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==114) ) { + zzmatch(114); zzCONSUME; + zzmatch(QuotedTerm); + akaString=mystrdup(StripQuotes(LATEXT(1))); + /* MR11 */ save_file=CurFile;save_line=zzline; + /* MR23 */ + zzCONSUME; + + zzmatch(115); zzCONSUME; + } + else { + if ( (LA(1)==102) ) { + } + else {zzFAIL(1,zzerr17,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + + /* MR23 */ if (p!= NULL && akaString != NULL) { + /* MR23 */ if (p->akaString != NULL) { + /* MR23 */ if (strcmp(p->akaString,akaString) != 0) { + /* MR23 */ warnFL(eMsg2("this #tokclass statement conflicts with a previous #tokclass %s(\"%s\") statement", + /* MR23 */ t,p->akaString), + /* MR23 */ FileStr[save_file],save_line); + /* MR23 */ }; + /* MR23 */ } else { + /* MR23 */ p->akaString=akaString; + /* MR23 */ }; + /* MR23 */ }; + /* MR23 */ + zzmatch(102); zzCONSUME; + { + zzBLOCK(zztasp2); + int zzcnt=1; + zzMake0; + { + do { + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + if ( go ) { + term = (TermEntry *) hash_get(Tname, LATEXT(1)); + if ( term==NULL && UserDefdTokens ) { + err("implicit token definition not allowed with #tokdefs"); + go = 0; + } + else {t=mystrdup(LATEXT(1)); tok=addTname(LATEXT(1));} + } + zzCONSUME; + + { + zzBLOCK(zztasp4); + zzMake0; + { + if ( (LA(1)==119) ) { + zzmatch(119); zzCONSUME; + zzmatch(TokenTerm); + if ( go ) { + toterm = (TermEntry *) hash_get(Tname, LATEXT(1)); + if ( toterm==NULL && UserDefdTokens ) { + err("implicit token definition not allowed with #tokdefs"); + go = 0; + } else { + totext=mystrdup(LATEXT(1)); totok=addTname(LATEXT(1)); + } + } + zzCONSUME; + + } + else { + if ( (setwd4[LA(1)]&0x8) ) { + } + else {zzFAIL(1,zzerr18,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp4); + } + } + } + else { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + if ( go ) { + term = (TermEntry *) hash_get(Texpr, LATEXT(1)); + if ( term==NULL && UserDefdTokens ) { + err("implicit token definition not allowed with #tokdefs"); + go = 0; + } + else {t=mystrdup(LATEXT(1)); tok=addTexpr(LATEXT(1));} + } + zzCONSUME; + + } + else {zzFAIL(1,zzerr19,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + if ( go ) { + if (totext == NULL) { + list_add(&(e->tlist), t); + } else { + list_add(&(e->tlist),".."); + list_add(&(e->tlist),t); + list_add(&(e->tlist),totext); + } + totext=NULL; + } + zzLOOP(zztasp2); + } while ( (setwd4[LA(1)]&0x10) ); + zzEXIT(zztasp2); + } + } + zzmatch(98); zzCONSUME; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd4, 0x20); + } +} + +void +#ifdef __USE_PROTOS +token(void) +#else +token() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + char *t=NULL, *e=NULL, *a=NULL; int tnum=0; + char *akaString=NULL; TermEntry *te;int save_file=0,save_line=0; + zzmatch(120); + tokenActionActive=1; + zzCONSUME; + + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + t=mystrdup(LATEXT(1)); + zzCONSUME; + + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==114) ) { + zzmatch(114); zzCONSUME; + zzmatch(QuotedTerm); + akaString=mystrdup(StripQuotes(LATEXT(1))); + /* MR11 */ save_file=CurFile;save_line=zzline; + /* MR11 */ + zzCONSUME; + + zzmatch(115); zzCONSUME; + } + else { + if ( (setwd4[LA(1)]&0x40) ) { + } + else {zzFAIL(1,zzerr20,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==121) ) { + zzmatch(121); zzCONSUME; + zzmatch(122); + tnum = atoi(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (setwd4[LA(1)]&0x80) ) { + } + else {zzFAIL(1,zzerr21,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + } + else { + if ( (setwd5[LA(1)]&0x1) ) { + } + else {zzFAIL(1,zzerr22,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + e=mystrdup(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (setwd5[LA(1)]&0x2) ) { + } + else {zzFAIL(1,zzerr23,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==Action) ) { + zzmatch(Action); + + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule token: cannot allocate action"); + strcpy(a, LATEXT(1)); + zzCONSUME; + + } + else { + if ( (setwd5[LA(1)]&0x4) ) { + } + else {zzFAIL(1,zzerr24,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==107) ) { + zzmatch(107); zzCONSUME; + } + else { + if ( (setwd5[LA(1)]&0x8) ) { + } + else {zzFAIL(1,zzerr25,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + chkToken(t, e, a, tnum); + if (t != NULL) { + te=(TermEntry *)hash_get(Tname,t); + if (te != NULL && akaString != NULL) { + if (te->akaString != NULL) { + if (strcmp(te->akaString,akaString) != 0) { + warnFL(eMsg2("this #token statement conflicts with a previous #token %s(\"%s\") statement", + t,te->akaString), + FileStr[save_file],save_line); + }; + } else { + te->akaString=akaString; + }; + }; + }; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd5, 0x10); + } +} + +void +#ifdef __USE_PROTOS +block(set * toksrefd,set * rulesrefd) +#else +block(toksrefd,rulesrefd) + set *toksrefd; +set *rulesrefd ; +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + + Graph g, b; + set saveblah; + int saveinalt = inAlt; + ExceptionGroup *eg; + * toksrefd = empty; + * rulesrefd = empty; + set_clr(AST_nodes_refd_in_actions); + CurBlockID++; + /* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID; + CurAltNum = 1; + /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + saveblah = attribsRefdFromAction; + attribsRefdFromAction = empty; + alt( toksrefd,rulesrefd ); + b = g = zzaArg(zztasp1,1); + + if ( ((Junction *)g.left)->p1->ntype == nAction ) + { + ActionNode *actionNode=(ActionNode *) + ( ( (Junction *)g.left) ->p1); + if (!actionNode->is_predicate ) + { + actionNode->init_action = TRUE; + /* MR12c */ if (actionNode->noHoist) { + /* MR12c */ errFL("<> appears as init-action - use <<>> <>", + /* MR12c */ FileStr[actionNode->file],actionNode->line); + /* MR12c */ }; + } + } + ((Junction *)g.left)->blockid = CurBlockID; + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==133) ) { + eg = exception_group(); + + + if ( eg!=NULL ) { + /* MR7 ***** eg->altID = makeAltID(CurBlockID,CurAltNum); *****/ + /* MR7 ***** CurAltStart->exception_label = eg->altID; *****/ + list_add(&CurExGroups, (void *)eg); + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + CurAltNum++; + /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==123) ) { + zzmatch(123); + inAlt=1; + zzCONSUME; + + alt( toksrefd,rulesrefd ); + g = Or(g, zzaArg(zztasp2,2)); + + ((Junction *)g.left)->blockid = CurBlockID; + { + zzBLOCK(zztasp3); + zzMake0; + { + while ( (LA(1)==133) ) { + eg = exception_group(); + + + if ( eg!=NULL ) { + /* MR7 ***** eg->altID = makeAltID(CurBlockID,CurAltNum); *****/ + /* MR7 ***** CurAltStart->exception_label = eg->altID; *****/ + list_add(&CurExGroups, (void *)eg); + } + zzLOOP(zztasp3); + } + zzEXIT(zztasp3); + } + } + CurAltNum++; + /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzaArg(zztasp1,0) = b; + attribsRefdFromAction = saveblah; inAlt = saveinalt; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd5, 0x20); + } +} + +void +#ifdef __USE_PROTOS +alt(set * toksrefd,set * rulesrefd) +#else +alt(toksrefd,rulesrefd) + set *toksrefd; +set *rulesrefd ; +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + int n=0; Graph g; int e_num=0, old_not=0; Node *node; set elems, dif; + int first_on_line = 1, use_def_MT_handler = 0; + g.left=NULL; g.right=NULL; + + CurAltStart = NULL; + elems = empty; + inAlt = 1; + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==88) ) { + zzmatch(88); + use_def_MT_handler = 1; + zzCONSUME; + + } + else { + if ( (setwd5[LA(1)]&0x40) ) { + } + else {zzFAIL(1,zzerr26,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + ; + while ( (setwd5[LA(1)]&0x80) ) { + { + zzBLOCK(zztasp3); + zzMake0; + { + old_not=0; + if ( (LA(1)==124) ) { + zzmatch(124); + old_not=1; + zzCONSUME; + + } + else { + if ( (setwd6[LA(1)]&0x1) ) { + } + else {zzFAIL(1,zzerr27,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + node = element( old_not, first_on_line, use_def_MT_handler ); + + if ( node!=NULL && node->ntype!=nAction ) first_on_line = 0; + + if ( zzaArg(zztasp2,2 ).left!=NULL ) { + g = Cat(g, zzaArg(zztasp2,2)); + n++; + if ( node!=NULL ) { + if ( node->ntype!=nAction ) e_num++; + /* record record number of all rule and token refs */ + if ( node->ntype==nToken ) { + TokNode *tk = (TokNode *)((Junction *)zzaArg(zztasp2,2 ).left)->p1; + tk->elnum = e_num; + set_orel(e_num, &elems); + } + else if ( node->ntype==nRuleRef ) { + RuleRefNode *rn = (RuleRefNode *)((Junction *)zzaArg(zztasp2,2 ).left)->p1; + rn->elnum = e_num; + set_orel(e_num, rulesrefd); + } + } + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + if ( n == 0 ) g = emptyAlt(); + zzaArg(zztasp1,0) = g; + /* We want to reduce number of LT(i) calls and the number of + * local attribute variables in C++ mode (for moment, later we'll + * do for C also). However, if trees are being built, they + * require most of the attrib variables to create the tree nodes + * with; therefore, we gen a token ptr for each token ref in C++ + */ + if ( GenCC && !GenAST ) + { + /* This now free's the temp set -ATG 5/6/95 */ + set temp; + temp = set_and(elems, attribsRefdFromAction); + set_orin( toksrefd, temp); + set_free(temp); +} +else set_orin( toksrefd, elems); +if ( GenCC ) { + dif = set_dif(attribsRefdFromAction, elems); + if ( set_deg(dif)>0 ) + err("one or more $i in action(s) refer to non-token elements"); + set_free(dif); +} +set_free(elems); +set_free(attribsRefdFromAction); +inAlt = 0; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd6, 0x2); + } +} + +LabelEntry * +#ifdef __USE_PROTOS +element_label(void) +#else +element_label() +#endif +{ + LabelEntry * _retv; + zzRULE; + zzBLOCK(zztasp1); + PCCTS_PURIFY(_retv,sizeof(LabelEntry * )) + zzMake0; + { + TermEntry *t=NULL; LabelEntry *l=NULL; RuleEntry *r=NULL; char *lab; + zzmatch(LABEL); + lab = mystrdup(LATEXT(1)); + zzCONSUME; + + + UsedNewStyleLabel = 1; + if ( UsedOldStyleAttrib ) err("cannot mix with new-style labels with old-style $i"); + t = (TermEntry *) hash_get(Tname, lab); + if ( t==NULL ) t = (TermEntry *) hash_get(Texpr, lab); + if ( t==NULL ) r = (RuleEntry *) hash_get(Rname, lab); + if ( t!=NULL ) { + err(eMsg1("label definition clashes with token/tokclass definition: '%s'", lab)); + _retv = NULL; + } + else if ( r!=NULL ) { + err(eMsg1("label definition clashes with rule definition: '%s'", lab)); + _retv = NULL; + } + else { + /* we don't clash with anybody else */ + l = (LabelEntry *) hash_get(Elabel, lab); + if ( l==NULL ) { /* ok to add new element label */ + l = (LabelEntry *)hash_add(Elabel, + lab, + (Entry *)newLabelEntry(lab)); + /* add to list of element labels for this rule */ + list_add(&CurElementLabels, (void *)lab); + /* MR7 */ leAdd(l); /* list of labels waiting for exception group definitions */ + _retv = l; + } + else { + err(eMsg1("label definitions must be unique per rule: '%s'", lab)); + _retv = NULL; +} +} + zzmatch(106); zzCONSUME; + zzEXIT(zztasp1); + return _retv; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd6, 0x4); + return _retv; + } +} + +Node * +#ifdef __USE_PROTOS +element(int old_not,int first_on_line,int use_def_MT_handler) +#else +element(old_not,first_on_line,use_def_MT_handler) + int old_not; +int first_on_line; +int use_def_MT_handler ; +#endif +{ + Node * _retv; + zzRULE; + zzBLOCK(zztasp1); + PCCTS_PURIFY(_retv,sizeof(Node * )) + zzMake0; + { + + Attrib blk; + Predicate *pred = NULL; + int local_use_def_MT_handler=0; + ActionNode *act; + RuleRefNode *rr; + set toksrefd, rulesrefd; + TermEntry *term; + TokNode *p=NULL; RuleRefNode *q; int approx=0; + LabelEntry *label=NULL; + int predMsgDone=0; + int semDepth=0; + int ampersandStyle; + int height; /* MR11 */ + int equal_height; /* MR11 */ + + char* pFirstSetSymbol = NULL; /* MR21 */ + + _retv = NULL; + if ( (setwd6[LA(1)]&0x8) ) { + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==LABEL) ) { + label = element_label(); + + } + else { + if ( (setwd6[LA(1)]&0x10) ) { + } + else {zzFAIL(1,zzerr28,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + + term = (TermEntry *) hash_get(Tname, LATEXT(1)); + if ( term==NULL && UserDefdTokens ) { + err("implicit token definition not allowed with #tokdefs"); + zzaRet.left = zzaRet.right = NULL; + } + else { + zzaRet = buildToken(LATEXT(1)); + p=((TokNode *)((Junction *)zzaRet.left)->p1); + term = (TermEntry *) hash_get(Tname, LATEXT(1)); + require( term!= NULL, "hash table mechanism is broken"); + p->tclass = term->tclass; + p->complement = old_not; + if ( label!=NULL ) { + p->el_label = label->str; + label->elem = (Node *)p; + } + } + zzCONSUME; + + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==119) ) { + zzmatch(119); zzCONSUME; + { + zzBLOCK(zztasp4); + zzMake0; + { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + if ( p!=NULL ) setUpperRange(p, LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + if ( p!=NULL ) setUpperRange(p, LATEXT(1)); + zzCONSUME; + + } + else {zzFAIL(1,zzerr29,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp4); + } + } + } + else { + if ( (setwd6[LA(1)]&0x20) ) { + } + else {zzFAIL(1,zzerr30,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + + if ( p!=NULL && (p->upper_range!=0 || p->tclass || old_not) ) + list_add(&MetaTokenNodes, (void *)p); + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==125) ) { + zzmatch(125); + if ( p!=NULL ) p->astnode=ASTroot; + zzCONSUME; + + } + else { + if ( (setwd6[LA(1)]&0x40) ) { + if ( p!=NULL ) p->astnode=ASTchild; + } + else { + if ( (LA(1)==103) ) { + zzmatch(103); + if ( p!=NULL ) p->astnode=ASTexclude; + zzCONSUME; + + } + else {zzFAIL(1,zzerr31,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp3); + } + } + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==88) ) { + zzmatch(88); + local_use_def_MT_handler = 1; + zzCONSUME; + + } + else { + if ( (setwd6[LA(1)]&0x80) ) { + } + else {zzFAIL(1,zzerr32,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + + if ( p!=NULL && first_on_line ) { + CurAltStart = (Junction *)zzaRet.left; + altAdd(CurAltStart); /* MR7 */ + p->altstart = CurAltStart; + } + if ( p!=NULL ) + p->use_def_MT_handler = use_def_MT_handler || local_use_def_MT_handler; + _retv = (Node *)p; + } + else { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + + term = (TermEntry *) hash_get(Texpr, LATEXT(1)); + if ( term==NULL && UserDefdTokens ) { + err("implicit token definition not allowed with #tokdefs"); + zzaRet.left = zzaRet.right = NULL; + } + else { + zzaRet = buildToken(LATEXT(1)); p=((TokNode *)((Junction *)zzaRet.left)->p1); + p->complement = old_not; + if ( label!=NULL ) { + p->el_label = label->str; + label->elem = (Node *)p; + } + } + zzCONSUME; + + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==119) ) { + zzmatch(119); zzCONSUME; + { + zzBLOCK(zztasp4); + zzMake0; + { + if ( (LA(1)==QuotedTerm) ) { + zzmatch(QuotedTerm); + if ( p!=NULL ) setUpperRange(p, LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + if ( p!=NULL ) setUpperRange(p, LATEXT(1)); + zzCONSUME; + + } + else {zzFAIL(1,zzerr33,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp4); + } + } + } + else { + if ( (setwd7[LA(1)]&0x1) ) { + } + else {zzFAIL(1,zzerr34,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==125) ) { + zzmatch(125); + if ( p!=NULL ) p->astnode=ASTroot; + zzCONSUME; + + } + else { + if ( (setwd7[LA(1)]&0x2) ) { + if ( p!=NULL ) p->astnode=ASTchild; + } + else { + if ( (LA(1)==103) ) { + zzmatch(103); + if ( p!=NULL ) p->astnode=ASTexclude; + zzCONSUME; + + } + else {zzFAIL(1,zzerr35,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp3); + } + } + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==88) ) { + zzmatch(88); + local_use_def_MT_handler = 1; + zzCONSUME; + + } + else { + if ( (setwd7[LA(1)]&0x4) ) { + } + else {zzFAIL(1,zzerr36,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + + if ( p!=NULL && (p->upper_range!=0 || p->tclass || old_not) ) + list_add(&MetaTokenNodes, (void *)p); + + if ( first_on_line ) { + CurAltStart = (Junction *)zzaRet.left; + altAdd(CurAltStart); /* MR7 */ + p->altstart = CurAltStart; + } + if ( p!=NULL ) + p->use_def_MT_handler = use_def_MT_handler || local_use_def_MT_handler; + _retv = (Node *)p; + } + else { + if ( (LA(1)==WildCard) ) { + if ( old_not ) warn("~ WILDCARD is an undefined operation (implies 'nothing')"); + zzmatch(WildCard); + zzaRet = buildWildCard(LATEXT(1)); p=((TokNode *)((Junction *)zzaRet.left)->p1); + zzCONSUME; + + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==125) ) { + zzmatch(125); + p->astnode=ASTroot; + zzCONSUME; + + } + else { + if ( (setwd7[LA(1)]&0x8) ) { + p->astnode=ASTchild; + } + else { + if ( (LA(1)==103) ) { + zzmatch(103); + p->astnode=ASTexclude; + zzCONSUME; + + } + else {zzFAIL(1,zzerr37,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp3); + } + } + list_add(&MetaTokenNodes, (void *)p); + + if ( first_on_line ) { + CurAltStart = (Junction *)zzaRet.left; + altAdd(CurAltStart); /* MR7 */ + p->altstart = CurAltStart; + if ( label!=NULL ) { + p->el_label = label->str; + label->elem = (Node *)p; + } + } + _retv = (Node *)p; + } + else { + if ( (LA(1)==NonTerminal) ) { + if ( old_not ) warn("~ NONTERMINAL is an undefined operation"); + zzmatch(NonTerminal); + zzaRet = buildRuleRef(LATEXT(1)); + zzCONSUME; + + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==103) ) { + zzmatch(103); + q = (RuleRefNode *) ((Junction *)zzaRet.left)->p1; + q->astnode=ASTexclude; + zzCONSUME; + + } + else { + if ( (setwd7[LA(1)]&0x10) ) { + } + else {zzFAIL(1,zzerr38,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (setwd7[LA(1)]&0x20) ) { + { + zzBLOCK(zztasp4); + zzMake0; + { + if ( (LA(1)==104) ) { + zzmatch(104); zzCONSUME; + } + else { + if ( (LA(1)==PassAction) ) { + } + else {zzFAIL(1,zzerr39,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp4); + } + } + zzmatch(PassAction); + addParm(((Junction *)zzaRet.left)->p1, LATEXT(1)); + zzCONSUME; + + } + else { + if ( (setwd7[LA(1)]&0x40) ) { + } + else {zzFAIL(1,zzerr40,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + rr=(RuleRefNode *) ((Junction *)zzaRet.left)->p1; + { + zzBLOCK(zztasp3); + zzMake0; + { + char *a; + if ( (LA(1)==105) ) { + zzmatch(105); zzCONSUME; + zzmatch(PassAction); + + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule element: cannot allocate assignment"); + strcpy(a, LATEXT(1)); + rr->assign = a; + zzCONSUME; + + } + else { + if ( (setwd7[LA(1)]&0x80) ) { + } + else {zzFAIL(1,zzerr41,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + + if ( label!=NULL ) { + rr->el_label = label->str; + label->elem = (Node *)rr; + } + if ( first_on_line ) { + CurAltStart = (Junction *)zzaRet.left; + altAdd(CurAltStart); /* MR7 */ + ((RuleRefNode *)((Junction *)zzaRet.left)->p1)->altstart = CurAltStart; + } + _retv = (Node *)rr; + } + else {zzFAIL(1,zzerr42,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + } + zzEXIT(zztasp2); + } + } + } + else { + if ( (LA(1)==Action) ) { + if ( old_not ) warn("~ ACTION is an undefined operation"); + zzmatch(Action); + zzaArg(zztasp1,0) = buildAction(LATEXT(1),action_file,action_line, 0); + zzCONSUME; + + if ( first_on_line ) { /* MR7 */ + CurAltStart = (Junction *)zzaArg(zztasp1,0 ).left; /* MR7 */ + altAdd(CurAltStart); /* MR7 */ + }; + _retv = (Node *) ((Junction *)zzaArg(zztasp1,0 ).left)->p1; + } + else { + if ( (LA(1)==Pred) ) { + if ( old_not ) warn("~ SEMANTIC-PREDICATE is an undefined operation"); + zzmatch(Pred); + zzaArg(zztasp1,0) = buildAction(LATEXT(1),action_file,action_line, 1); + zzCONSUME; + + act = (ActionNode *) ((Junction *)zzaArg(zztasp1,0 ).left)->p1; + if (numericActionLabel) { /* MR10 */ + list_add(&NumericPredLabels,act); /* MR10 */ + numericActionLabel=0; /* MR10 */ + }; /* MR10 */ + { + zzBLOCK(zztasp2); + zzMake0; + { + char *a; + if ( (LA(1)==PassAction) ) { + zzmatch(PassAction); + + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule element: cannot allocate predicate fail action"); + strcpy(a, LATEXT(1)); + act->pred_fail = a; + zzCONSUME; + + } + else { + if ( (setwd8[LA(1)]&0x1) ) { + } + else {zzFAIL(1,zzerr43,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + if ( first_on_line ) { /* MR7 */ + CurAltStart = (Junction *)zzaArg(zztasp1,0 ).left; /* MR7 */ + altAdd(CurAltStart); /* MR7 */ + }; + _retv = (Node *)act; + } + else { + if ( (setwd8[LA(1)]&0x2) ) { + if ( old_not ) warn("~ BLOCK is an undefined operation"); + BlkLevel++; + if (BlkLevel >= MAX_BLK_LEVEL) fatal("Blocks nested too deeply"); + /* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID; + /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==Pragma) ) { + zzmatch(Pragma); zzCONSUME; + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==126) ) { + zzmatch(126); + approx=LL_k; + zzCONSUME; + + } + else { + if ( (LA(1)==127) ) { + zzmatch(127); + approx = 1; + zzCONSUME; + + } + else { + if ( (LA(1)==128) ) { + zzmatch(128); + approx = 2; + zzCONSUME; + + } + else {zzFAIL(1,zzerr44,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp3); + } + } + } + else { + if ( (setwd8[LA(1)]&0x4) ) { + } + else {zzFAIL(1,zzerr45,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==FirstSetSymbol) ) { + zzmatch(FirstSetSymbol); zzCONSUME; + zzmatch(114); zzCONSUME; + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==NonTerminal) ) { + zzmatch(NonTerminal); + + /* MR21 */ pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1, + /* MR21 */ sizeof(char)); + /* MR21 */ require(pFirstSetSymbol!=NULL, + /* MR21 */ "cannot allocate first set name"); + /* MR21 */ strcpy(pFirstSetSymbol, LATEXT(1)); + /* MR21 */ + zzCONSUME; + + } + else { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + + /* MR21 */ pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1, + /* MR21 */ sizeof(char)); + /* MR21 */ require(pFirstSetSymbol!=NULL, + /* MR21 */ "cannot allocate first set name"); + /* MR21 */ strcpy(pFirstSetSymbol, LATEXT(1)); + /* MR21 */ + zzCONSUME; + + } + else {zzFAIL(1,zzerr46,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + zzmatch(115); zzCONSUME; + } + else { + if ( (setwd8[LA(1)]&0x8) ) { + } + else {zzFAIL(1,zzerr47,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==114) ) { + zzmatch(114); zzCONSUME; + block( &toksrefd,&rulesrefd ); + zzmatch(115); + blk = zzaRet = zzaArg(zztasp2,2); + /* MR23 */ CurBlockID_array[BlkLevel] = (-1); + /* MR23 */ CurAltNum_array[BlkLevel] = (-1); + --BlkLevel; + zzCONSUME; + + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==129) ) { + zzmatch(129); + zzaRet = makeLoop(zzaRet,approx,pFirstSetSymbol); + zzCONSUME; + + } + else { + if ( (LA(1)==130) ) { + zzmatch(130); + zzaRet = makePlus(zzaRet,approx,pFirstSetSymbol); + zzCONSUME; + + } + else { + if ( (LA(1)==131) ) { + zzmatch(131); zzCONSUME; + { + zzBLOCK(zztasp4); + zzMake0; + { + if ( (setwd8[LA(1)]&0x10) ) { + { + zzBLOCK(zztasp5); + zzMake0; + { + if ( (LA(1)==132) ) { + zzmatch(132); + ampersandStyle=0; + zzCONSUME; + + } + else { + if ( (LA(1)==113) ) { + zzmatch(113); + ampersandStyle=1; + zzCONSUME; + + } + else {zzFAIL(1,zzerr48,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp5); + } + } + zzmatch(Pred); + zzaRet = buildAction(LATEXT(1),action_file,action_line,1); + zzCONSUME; + + act = (ActionNode *) ((Junction *)zzaRet.left)->p1; + semDepth=predicateLookaheadDepth(act); + if (numericActionLabel) { /* MR10 */ + list_add(&NumericPredLabels,act); /* MR10 */ + numericActionLabel=0; /* MR10 */ + }; /* MR10 */ + { + zzBLOCK(zztasp5); + zzMake0; + { + char *a; + if ( (LA(1)==PassAction) ) { + zzmatch(PassAction); + + a = (char *)calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule element: cannot allocate predicate fail action"); + strcpy(a, LATEXT(1)); + act->pred_fail = a; + zzCONSUME; + + } + else { + if ( (setwd8[LA(1)]&0x20) ) { + } + else {zzFAIL(1,zzerr49,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp5); + } + } + if ( first_on_line) { /* MR7 */ + CurAltStart=(Junction *)zzaRet.left; /* MR7 */ + altAdd(CurAltStart); /* MR7 */ + }; + _retv = (Node *)act; + + pred = computePredFromContextGuard(blk,&predMsgDone); /* MR10 */ + if ( pred==NULL) { /* MR10 */ + if ( !predMsgDone) err("invalid or missing context guard"); /* MR10 */ + predMsgDone=1; /* MR10 */ + } else { /* MR10 */ + act->guardNodes=(Junction *)blk.left; /* MR11 */ + pred->expr = act->action; + pred->source = act; + /* MR10 */ pred->ampersandStyle = ampersandStyle; /* 0 means (g)? => ... 1 means (g)? && ... */ + /* MR13 */ if (pred->tcontext != NULL) { + /* MR13 */ height=MR_max_height_of_tree(pred->tcontext); + /* MR13 */ equal_height=MR_all_leaves_same_height(pred->tcontext,height); + /* MR13 */ if (! equal_height) { + /* MR13 */ errFL("in guarded predicates all tokens in the guard must be at the same height", + /* MR13 */ FileStr[act->file],act->line); + /* MR13 */ }; + /* MR13 */ } + /* MR10 */ if (ampersandStyle) { + /* MR10 */ act->ampersandPred = pred; + /* MR11 */ if (! HoistPredicateContext) { + /* MR11 */ errFL("without \"-prc on\" (guard)? && <>? ... doesn't make sense", + /* MR11 */ FileStr[act->file],act->line); + /* MR11 */ }; + /* MR10 */ } else { + /* MR10 */ act->guardpred = pred; + /* MR10 */ }; + /* MR10 */ if (pred->k != semDepth) { + /* MR10 */ warn(eMsgd2("length of guard (%d) does not match the length of semantic predicate (%d)", + /* MR10 */ pred->k,semDepth)); + /* MR10 */ }; + } + } + else { + if ( (setwd8[LA(1)]&0x40) ) { + zzaRet = makeBlk(zzaRet,approx,pFirstSetSymbol); + FoundGuessBlk = 1; + ((Junction *) ((Junction *)zzaRet.left)->p1)->guess=1; + if ( ! first_on_line ) { + err("(...)? predicate must be first element of production"); + } + } + else {zzFAIL(1,zzerr50,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp4); + } + } + } + else { + if ( (setwd8[LA(1)]&0x80) ) { + zzaRet = makeBlk(zzaRet,approx,pFirstSetSymbol); + } + else {zzFAIL(1,zzerr51,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + } + zzEXIT(zztasp3); + } + } + + if ( pred==NULL && !predMsgDone) { /* MR10 */ + ((Junction *)((Junction *)zzaRet.left)->p1)->blockid = CurBlockID; + ((Junction *)((Junction *)zzaRet.left)->p1)->tokrefs = toksrefd; + ((Junction *)((Junction *)zzaRet.left)->p1)->rulerefs = rulesrefd; + if ( first_on_line ) { /* MR7 */ + CurAltStart = (Junction *)((Junction *)((Junction *)zzaRet.left)->p1); /* MR7 */ + altAdd(CurAltStart); /* MR7 */ + }; /* MR7 */ + _retv = (Node *) ((Junction *)zzaRet.left)->p1; + } + } + else { + if ( (LA(1)==102) ) { + zzmatch(102); zzCONSUME; + block( &toksrefd,&rulesrefd ); + zzaRet = makeOpt(zzaArg(zztasp2,2),approx,pFirstSetSymbol); + /* MR23 */ CurBlockID_array[BlkLevel] = (-1); + /* MR23 */ CurAltNum_array[BlkLevel] = (-1); + --BlkLevel; + zzmatch(98); + + ((Junction *)((Junction *)zzaRet.left)->p1)->blockid = CurBlockID; + ((Junction *)((Junction *)zzaRet.left)->p1)->tokrefs = toksrefd; + ((Junction *)((Junction *)zzaRet.left)->p1)->rulerefs = rulesrefd; + zzCONSUME; + + if ( first_on_line ) { /* MR7 */ + CurAltStart = (Junction *) ((Junction *)((Junction *)zzaRet.left)->p1); /* MR7 */ + altAdd(CurAltStart); /* MR7 */ + }; + _retv = (Node *) ((Junction *)zzaRet.left)->p1; + } + else {zzFAIL(1,zzerr52,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + } + else { + if ( (LA(1)==129) ) { + zzmatch(129); + warn("don't you want a ')' with that '*'?"); CannotContinue=TRUE; + zzCONSUME; + + } + else { + if ( (LA(1)==130) ) { + zzmatch(130); + warn("don't you want a ')' with that '+'?"); CannotContinue=TRUE; + zzCONSUME; + + } + else { + if ( (LA(1)==105) ) { + zzmatch(105); + warn("'>' can only appear after a nonterminal"); CannotContinue=TRUE; + zzCONSUME; + + } + else { + if ( (LA(1)==PassAction) ) { + zzmatch(PassAction); + warn("[...] out of context 'rule > [...]'"); + CannotContinue=TRUE; + zzCONSUME; + + } + else {zzFAIL(1,zzerr53,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + } + } + } + } + } + zzEXIT(zztasp1); + return _retv; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd9, 0x1); + return _retv; + } +} + +void +#ifdef __USE_PROTOS +default_exception_handler(void) +#else +default_exception_handler() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + DefaultExGroup = exception_group(); + + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd9, 0x2); + } +} + +ExceptionGroup * +#ifdef __USE_PROTOS +exception_group(void) +#else +exception_group() +#endif +{ + ExceptionGroup * _retv; + zzRULE; + zzBLOCK(zztasp1); + PCCTS_PURIFY(_retv,sizeof(ExceptionGroup * )) + zzMake0; + { + ExceptionHandler *h; LabelEntry *label=NULL; /* MR6 */ + FoundException = 1; FoundExceptionGroup = 1; + zzmatch(133); + _retv = (ExceptionGroup *)calloc(1, sizeof(ExceptionGroup)); + zzCONSUME; + + { + zzBLOCK(zztasp2); + zzMake0; + { + char *p; + if ( (LA(1)==PassAction) ) { + zzmatch(PassAction); + + p = LATEXT(1)+1; + p[strlen(p)-1] = '\0'; /* kill trailing space */ + label = (LabelEntry *) hash_get(Elabel, LATEXT(1)+1); + if ( label==NULL ) + { + err(eMsg1("unknown label in exception handler: '%s'", LATEXT(1)+1)); + } + zzCONSUME; + + } + else { + if ( (setwd9[LA(1)]&0x4) ) { + } + else {zzFAIL(1,zzerr54,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==135) ) { + h = exception_handler(); + + list_add(&(_retv->handlers), (void *)h); + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==134) ) { + zzmatch(134); zzCONSUME; + zzmatch(106); zzCONSUME; + zzmatch(Action); + { + ExceptionHandler *eh = (ExceptionHandler *) + calloc(1, sizeof(ExceptionHandler)); + char *a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(eh!=NULL, "exception: cannot allocate handler"); + require(a!=NULL, "exception: cannot allocate action"); + strcpy(a, LATEXT(1)); + eh->action = a; + eh->signalname = (char *) calloc(strlen("default")+1, sizeof(char)); + require(eh->signalname!=NULL, "exception: cannot allocate sig name"); + strcpy(eh->signalname, "default"); + list_add(&(_retv->handlers), (void *)eh); + } + zzCONSUME; + + } + else { + if ( (setwd9[LA(1)]&0x8) ) { + } + else {zzFAIL(1,zzerr55,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + + if ( label!=NULL ) { + /* Record ex group in sym tab for this label */ + if ( label->ex_group!=NULL ) { + err(eMsg1("duplicate exception handler for label '%s'",label->str)); + } else { + label->ex_group = _retv; + /* Label the exception group itself */ + _retv->label = label->str; + /* Make the labelled element pt to the exception also */ + /* MR6 */ if (label->elem == NULL) { + /* MR6 */ err(eMsg1("reference in exception handler to undefined label '%s'",label->str)); + /* MR6 */ } else { + switch ( label->elem->ntype ) { + case nRuleRef : + { + RuleRefNode *r = (RuleRefNode *)label->elem; + r->ex_group = _retv; + break; + } + case nToken : + { + TokNode *t = (TokNode *)label->elem; + t->ex_group = _retv; + break; + } + } /* end switch */ + /* MR6 */ }; /* end test on label->elem */ + } /* end test on label->ex_group */ + + } /* end test on exception label */ + +/* MR7 */ + /* MR7 */ if (BlkLevel == 1 && label == NULL) { + /* MR7 */ _retv->forRule=1; + /* MR7 */ } else if (label == NULL) { + /* MR7 */ _retv->altID = makeAltID(CurBlockID_array[BlkLevel], CurAltNum_array[BlkLevel]); + /* MR7 */ egAdd(_retv); + /* MR7 */ } else { + /* MR7 */ _retv->labelEntry=label; + /* MR7 */ }; + /* MR7 */ + /* MR7 */ /* You may want to remove this exc from the rule list */ + /* MR7 */ /* and handle at the labeled element site. */ + /* MR7 */ + /* MR7 */ if (label != NULL) { + /* MR7 */ _retv = NULL; + /* MR7 */ }; + zzEXIT(zztasp1); + return _retv; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd9, 0x10); + return _retv; + } +} + +ExceptionHandler * +#ifdef __USE_PROTOS +exception_handler(void) +#else +exception_handler() +#endif +{ + ExceptionHandler * _retv; + zzRULE; + zzBLOCK(zztasp1); + PCCTS_PURIFY(_retv,sizeof(ExceptionHandler * )) + zzMake0; + { + ; + zzmatch(135); + + _retv = (ExceptionHandler *)calloc(1, sizeof(ExceptionHandler)); + require(_retv!=NULL, "exception: cannot allocate handler"); + zzCONSUME; + + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==NonTerminal) ) { + zzmatch(NonTerminal); + + _retv->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(_retv->signalname!=NULL, "exception: cannot allocate sig name"); + strcpy(_retv->signalname, LATEXT(1)); + zzCONSUME; + + } + else { + if ( (LA(1)==TokenTerm) ) { + zzmatch(TokenTerm); + + _retv->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(_retv->signalname!=NULL, "exception: cannot allocate sig name"); + strcpy(_retv->signalname, LATEXT(1)); + zzCONSUME; + + } + else {zzFAIL(1,zzerr56,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + zzmatch(106); zzCONSUME; + { + zzBLOCK(zztasp2); + zzMake0; + { + _retv->action = NULL; + if ( (LA(1)==Action) ) { + zzmatch(Action); + + _retv->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(_retv->action!=NULL, "exception: cannot allocate action"); + strcpy(_retv->action, LATEXT(1)); + zzCONSUME; + + } + else { + if ( (setwd9[LA(1)]&0x20) ) { + } + else {zzFAIL(1,zzerr57,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + zzEXIT(zztasp1); + return _retv; +fail: + zzEXIT(zztasp1); + CannotContinue=TRUE; + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd9, 0x40); + return _retv; + } +} + +void +#ifdef __USE_PROTOS +enum_file(char * fname) +#else +enum_file(fname) + char *fname ; +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + if ( (setwd9[LA(1)]&0x80) ) { + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==143) ) { + zzmatch(143); zzCONSUME; + zzmatch(ID); zzCONSUME; + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==149) ) { + zzmatch(149); zzCONSUME; + zzmatch(ID); zzCONSUME; + } + else { + if ( (setwd10[LA(1)]&0x1) ) { + } + else {zzFAIL(1,zzerr58,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp3); + } + } + } + else { + if ( (setwd10[LA(1)]&0x2) ) { + } + else {zzFAIL(1,zzerr59,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==151) ) { + { + zzBLOCK(zztasp3); + int zzcnt=1; + zzMake0; + { + do { + enum_def( fname ); + zzLOOP(zztasp3); + } while ( (LA(1)==151) ); + zzEXIT(zztasp3); + } + } + } + else { + if ( (LA(1)==149) ) { + defines( fname ); + } + else {zzFAIL(1,zzerr60,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + } + else { + if ( (LA(1)==Eof) ) { + } + else {zzFAIL(1,zzerr61,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd10, 0x4); + } +} + +void +#ifdef __USE_PROTOS +defines(char * fname) +#else +defines(fname) + char *fname ; +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + int v; int maxt=(-1); char *t; + { + zzBLOCK(zztasp2); + int zzcnt=1; + zzMake0; + { + do { + zzmatch(149); zzCONSUME; + zzmatch(ID); + t = mystrdup(LATEXT(1)); + zzCONSUME; + + zzmatch(INT); + + v = atoi(LATEXT(1)); + /* fprintf(stderr, "#token %s=%d\n", t, v);*/ + + /* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */ + /* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */ + /* MR2 Don't let #tokdefs be confused by */ + /* MR2 DLGminToken and DLGmaxToken */ + + if ( ! isDLGmaxToken(t)) { /* MR2 */ + TokenNum = v; + if ( v>maxt ) maxt=v; + if ( Tnum( t ) == 0 ) { + addForcedTname( t, v ); + } else { + warnFL(eMsg1("redefinition of token %s; ignored",t), fname,zzline); + }; +}; + zzCONSUME; + + zzLOOP(zztasp2); + } while ( (LA(1)==149) ); + zzEXIT(zztasp2); + } + } + TokenNum = maxt + 1; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd10, 0x8); + } +} + +void +#ifdef __USE_PROTOS +enum_def(char * fname) +#else +enum_def(fname) + char *fname ; +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + int v= 0; int maxt=(-1); char *t; + zzmatch(151); zzCONSUME; + zzmatch(ID); zzCONSUME; + zzmatch(152); zzCONSUME; + zzmatch(ID); + t = mystrdup(LATEXT(1)); + zzCONSUME; + + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==153) ) { + zzmatch(153); zzCONSUME; + zzmatch(INT); + v=atoi(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (setwd10[LA(1)]&0x10) ) { + v++; + } + else {zzFAIL(1,zzerr62,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + + /* fprintf(stderr, "#token %s=%d\n", t, v);*/ + TokenNum = v; + if ( v>maxt ) maxt=v; /* MR3 */ + if ( Tnum( t ) == 0 ) addForcedTname( t, v ); + else { + warnFL(eMsg1("redefinition of token %s; ignored",t), fname,zzline); + } + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==154) ) { + zzmatch(154); zzCONSUME; + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==ID)&&(isDLGmaxToken(LATEXT(1))) ) { + if (!(isDLGmaxToken(LATEXT(1))) ) {zzfailed_pred(" isDLGmaxToken(LATEXT(1))",0 /* report */, { ; /* no user action */ } );} + zzmatch(ID); zzCONSUME; + { + zzBLOCK(zztasp4); + zzMake0; + { + if ( (LA(1)==153) ) { + zzmatch(153); zzCONSUME; + zzmatch(INT); zzCONSUME; + } + else { + if ( (setwd10[LA(1)]&0x20) ) { + } + else {zzFAIL(1,zzerr63,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp4); + } + } + } + else { + if ( (LA(1)==ID) ) { + zzmatch(ID); + t = mystrdup(LATEXT(1)); + zzCONSUME; + + { + zzBLOCK(zztasp4); + zzMake0; + { + if ( (LA(1)==153) ) { + zzmatch(153); zzCONSUME; + zzmatch(INT); + v=atoi(LATEXT(1)); + zzCONSUME; + + } + else { + if ( (setwd10[LA(1)]&0x40) ) { + v++; + } + else {zzFAIL(1,zzerr64,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp4); + } + } + + /* fprintf(stderr, "#token %s=%d\n", t, v);*/ + TokenNum = v; + if ( v>maxt ) maxt=v; /* MR3 */ + if ( Tnum( t ) == 0 ) addForcedTname( t, v ); + else { + warnFL(eMsg1("redefinition of token %s; ignored",t), fname,zzline); + } + } + else { + if ( (setwd10[LA(1)]&0x80) ) { + } + else {zzFAIL(1,zzerr65,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp3); + } + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzmatch(155); zzCONSUME; + zzmatch(156); + TokenNum = maxt + 1; + zzCONSUME; + + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd11, 0x1); + } +} + + +/* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */ +/* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */ +/* MR2 Don't let #tokdefs be confused by */ +/* MR2 DLGminToken and DLGmaxToken */ + +/* semantic check on DLGminToken and DLGmaxmaxToken in #tokdefs */ + +#ifdef __USE_PROTOS +static int isDLGmaxToken(char *Token) +#else +static int isDLGmaxToken(Token) +char * Token; +#endif +{ +static char checkStr1[] = "DLGmaxToken"; +static char checkStr2[] = "DLGminToken"; + + if (strcmp(Token, checkStr1) == 0) +return 1; +else if (strcmp(Token, checkStr2) == 0) +return 1; +else +return 0; +} + +/* semantics of #token */ +static void +#ifdef __USE_PROTOS +chkToken(char *t, char *e, char *a, int tnum) +#else +chkToken(t,e,a,tnum) +char *t, *e, *a; +int tnum; +#endif +{ +TermEntry *p; + + /* check to see that they don't try to redefine a token as a token class */ +if ( t!=NULL ) { +p = (TermEntry *) hash_get(Tname, t); +if ( p!=NULL && p->classname ) { + err(eMsg1("redefinition of #tokclass '%s' to #token not allowed; ignored",t)); + if ( a!=NULL ) free((char *)a); + return; +} +} + + if ( t==NULL && e==NULL ) { /* none found */ +err("#token requires at least token name or rexpr"); +} +else if ( t!=NULL && e!=NULL ) { /* both found */ +if ( UserDefdTokens ) { /* if #tokdefs, must not define new */ + p = (TermEntry *) hash_get(Tname, t); + if ( p == NULL) { + err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t)); + return; + }; +} +Tklink(t, e); +if ( a!=NULL ) { + if ( hasAction(e) ) { + err(eMsg1("redefinition of action for %s; ignored",e)); + } + else setHasAction(e, a); +} +} +else if ( t!=NULL ) { /* only one found */ +if ( UserDefdTokens ) { + p = (TermEntry *) hash_get(Tname, t); + if (p == NULL) { + err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t)); + }; + return; +} +if ( Tnum( t ) == 0 ) addTname( t ); +else { + err(eMsg1("redefinition of token %s; ignored",t)); +} +if ( a!=NULL ) { + err(eMsg1("action cannot be attached to a token name (%s); ignored",t)); + free((char *)a); +} +} +else if ( e!=NULL ) { +if ( Tnum( e ) == 0 ) addTexpr( e ); +else { + if ( hasAction(e) ) { + err(eMsg1("redefinition of action for expr %s; ignored",e)); + } + else if ( a==NULL ) { + err(eMsg1("redefinition of expr %s; ignored",e)); + } +} +if ( a!=NULL ) setHasAction(e, a); +} + + /* if a token type number was specified, then add the token ID and 'tnum' +* pair to the ForcedTokens list. (only applies if an id was given) +*/ +if ( t!=NULL && tnum>0 ) +{ +if ( set_el(tnum, reserved_positions) ) +{ + err(eMsgd("a token has already been forced to token number %d; ignored", tnum)); +} +else +{ + list_add(&ForcedTokens, newForcedToken(t,tnum)); + set_orel(tnum, &reserved_positions); +} +} +} + +static int +#ifdef __USE_PROTOS +match_token(char *s, char **nxt) +#else +match_token(s,nxt) +char *s; +char **nxt; +#endif +{ + if ( !(*s>='A' && *s<='Z') ) return 0; + s++; + while ( (*s>='a' && *s<='z') || + (*s>='A' && *s<='Z') || + (*s>='0' && *s<='9') || + *s=='_' ) + { + s++; + } + if ( *s!=' ' && *s!='}' ) return 0; + *nxt = s; + return 1; +} + +static int +#ifdef __USE_PROTOS +match_rexpr(char *s, char **nxt) +#else +match_rexpr(s,nxt) +char *s; +char **nxt; +#endif +{ + if ( *s!='"' ) return 0; + s++; + while ( *s!='"' ) + { + if ( *s=='\n' || *s=='\r' ) /* MR13 */ + warn("eoln found in regular expression"); + if ( *s=='\\' ) s++; + s++; + } + *nxt = s+1; + return 1; +} + +/* +* Walk a string "{ A .. Z }" where A..Z is a space separated list +* of token references (either labels or reg exprs). Return a +* string "inlineX_set" for some unique integer X. Basically, +* we pretend as if we had seen "#tokclass inlineX { A .. Z }" +* on the input stream outside of an action. +*/ +char * +#ifdef __USE_PROTOS +inline_set(char *s) +#else +inline_set(s) +char *s; +#endif +{ + char *nxt; + fprintf(stderr, "found consumeUntil( {...} )\n"); + while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;} + if ( *s!='{' ) + { + err("malformed consumeUntil( {...} ); missing '{'"); + return "bad_set"; + } + s++; + while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;} + while ( *s!='}' ) + { + if ( match_token(s,&nxt) ) fprintf(stderr, "found token %s\n", s); + else if ( match_rexpr(s,&nxt) ) fprintf(stderr, "found rexpr %s\n", s); + else { + err("invalid element in consumeUntil( {...} )"); + return "bad_set"; + } + s = nxt; + while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;} + } + return "inlineX_set"; +} + +/* ANTLR-specific syntax error message generator +* (define USER_ZZSYN when compiling so don't get 2 definitions) +*/ +void +#ifdef __USE_PROTOS +zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, +int k, char *bad_text) +#else +zzsyn(text, tok, egroup, eset, etok, k, bad_text) +char *text, *egroup, *bad_text; +int tok; +int etok; +int k; +SetWordType *eset; +#endif +{ +fprintf(stderr, ErrHdr, FileStr[CurFile]!=NULL?FileStr[CurFile]:"stdin", zzline); +fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text); +if ( !etok && !eset ) {fprintf(stderr, "\n"); return;} +if ( k==1 ) fprintf(stderr, " missing"); +else +{ +fprintf(stderr, "; \"%s\" not", bad_text); +if ( zzset_deg(eset)>1 ) fprintf(stderr, " in"); +} +if ( zzset_deg(eset)>0 ) zzedecode(eset); +else fprintf(stderr, " %s", zztokens[etok]); +if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup); +fprintf(stderr, "\n"); +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.g b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.g new file mode 100644 index 00000000..7df4b319 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.g @@ -0,0 +1,2587 @@ +/* + * antlr.g -- PCCTS Version 1.xx ANTLR + * + * Parse an antlr input grammar and build a syntax-diagram. + * + * Written in itself (needs at least 1.06 to work) + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-1995 + */ + +/* MR1 */ +/* MR1 10-Apr-97 MR1 Replace #if logic with #include "pcctscfg.h" */ +/* MR1 */ + +#header << + #include "pcctscfg.h" + #include "set.h" + #include + #include "syn.h" + #include "hash.h" + #include "generic.h" + #define zzcr_attr(attr,tok,t) + >> + +<< + +/* MR20 G. Hobbelt For Borland C++ 4.x & 5.x compiling with ALL warnings enabled */ +#if defined(__TURBOC__) +#pragma warn -aus /* unused assignment of 'xxx' */ +#endif + +#pragma clang diagnostic ignored "-Wparentheses-equality" + +#ifdef __USE_PROTOS +static void chkToken(char *, char *, char *, int); +#else +static void chkToken(); +#endif + +#ifdef __USE_PROTOS +static int isDLGmaxToken(char *Token); /* MR3 */ +#else +static int isDLGmaxToken(); /* MR3 */ +#endif + +static int class_nest_level = 0; + +/* MR20 G. Hobbelt extern definitions moved to antlr.h */ + +>> + +#lexaction << +/* maintained, but not used for now */ +set AST_nodes_refd_in_actions = set_init; +int inAlt = 0; +set attribsRefdFromAction = set_init; /* MR20 */ +int UsedOldStyleAttrib = 0; +int UsedNewStyleLabel = 0; +#ifdef __USE_PROTOS +char *inline_set(char *); +#else +char *inline_set(); +#endif + +/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ +/* MR1 in DLG action */ + +int tokenActionActive=0; /* MR1 */ + +>> + +#lexclass STRINGS +#token QuotedTerm "\"" << zzmode(START); >> +#token "\n|\r|\r\n" << + zzline++; + warn("eoln found in string"); + zzskip(); + >> +#token "\\(\n|\r|\r\n)" << zzline++; zzmore(); >> +#token "\\~[]" << zzmore(); >> +#token "~[\n\r\"\\]+" << zzmore(); >> + +#lexclass ACTION_STRINGS +#token "\"" << zzmode(ACTIONS); zzmore(); >> +#token "\n|\r|\r\n" << + zzline++; + warn("eoln found in string (in user action)"); + zzskip(); + >> +#token "\\(\n|\r|\r\n)" << zzline++; zzmore(); >> +#token "\\~[]" << zzmore(); >> +#token "~[\n\r\"\\]+" << zzmore(); >> + +#lexclass ACTION_CHARS +#token "'" << zzmode(ACTIONS); zzmore(); >> +#token "\n|\r|\r\n" << + zzline++; + warn("eoln found in char literal (in user action)"); + zzskip(); + >> +#token "\\~[]" << zzmore(); >> +#token "~[\n\r'\\]+" << zzmore(); >> + +#lexclass ACTION_COMMENTS +#token "\*/" << zzmode(ACTIONS); zzmore(); >> +#token "\*" << zzmore(); >> +#token "\n|\r|\r\n" << zzline++; zzmore(); DAWDLE; >> +#token "~[\n\r\*]+" << zzmore(); >> + +#lexclass TOK_DEF_COMMENTS +#token "\*/" << zzmode(PARSE_ENUM_FILE); + zzmore(); >> +#token "\*" << zzmore(); >> +#token "\n|\r|\r\n" << zzline++; zzmore(); DAWDLE; >> +#token "~[\n\r\*]+" << zzmore(); >> + +#lexclass TOK_DEF_CPP_COMMENTS +#token "\n|\r|\r\n" << zzline++; zzmode(PARSE_ENUM_FILE); zzskip(); DAWDLE; >> +#token "~[\n\r]+" << zzskip(); >> + +#lexclass ACTION_CPP_COMMENTS +#token "\n|\r|\r\n" << zzline++; zzmode(ACTIONS); zzmore(); DAWDLE; >> +#token "~[\n\r]+" << zzmore(); >> + +#lexclass CPP_COMMENTS +#token "\n|\r|\r\n" << zzline++; zzmode(START); zzskip(); DAWDLE; >> +#token "~[\n\r]+" << zzskip(); >> + +#lexclass COMMENTS +#token "\*/" << zzmode(START); zzskip(); >> +#token "\*" << zzskip(); >> +#token "\n|\r|\r\n" << zzline++; zzskip(); DAWDLE; >> +#token "~[\n\r\*]+" << zzskip(); >> + +/* + * This lexical class accepts actions of type [..] and <<..>> + * + * It translates the following special items for C: + * + * $j --> "zzaArg(current zztasp, j)" + * $i.j --> "zzaArg(zztaspi, j)" + * $i.nondigit> "zzaArg(current zztasp, i).nondigit" + * $$ --> "zzaRet" + * $alnum --> "alnum" (used to ref parameters) + * $rule --> "zzaRet" + * $retval --> "_retv.retval" if > 1 return values else "_retv" + * $[token, text] --> "zzconstr_attr(token, text)" + * $[] --> "zzempty_attr()" + * + * It translates the following special items for C++: + * (attributes are now stored with 'Token' and $i's are only + * pointers to the Tokens. Rules don't have attributes now.) + * + * $j --> "_tbj" where b is the block level + * $i.j --> "_tij" + * $j->nondigit> "_tbj->nondigit" + * $$ --> "$$" + * $alnum --> "alnum" (used to ref parameters) + * $rule --> "$rule" + * $retval --> "_retv.retval" if > 1 return values else "_retv" + * $[token, text] --> invalid + * $[] --> invalid + * + * And, for trees: + * + * #0 --> "(*_root)" + * #i --> "zzastArg(i)" + * #[args] --> "zzmk_ast(zzastnew(), args)" + * #[] --> "zzastnew()" + * #( root, child1, ..., childn ) + * --> "zztmake(root, child1, ...., childn, NULL)" + * #() --> "NULL" + * + * For C++, ... + * + * #0 --> "(*_root)" + * #i --> "_astbi" where b is the block level + * #alnum --> "alnum_ast" (used to ref #label) + * #[args] --> "new AST(args)" + * #[] --> "new AST" + * #( root, child1, ..., childn ) + * --> "AST::tmake(root, child1, ...., childn, NULL)" + * #() --> "NULL" + * + * To escape, + * + * \] --> ] + * \) --> ) + * \$ --> $ + * \# --> # + * + * A stack is used to nest action terminators because they can be nested + * like crazy: << #[$[..],..] >> + */ +#lexclass ACTIONS +#token Action "\>\>" << /* these do not nest */ + zzmode(START); + NLATEXT[0] = ' '; + NLATEXT[1] = ' '; + zzbegexpr[0] = ' '; + zzbegexpr[1] = ' '; + if ( zzbufovf ) { + err( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE)); + } + +/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ +/* MR1 in DLG action */ +/* MR1 Doesn't matter what kind of action it is - reset*/ + + tokenActionActive=0; /* MR1 */ + >> +#token Pred "\>\>?" << /* these do not nest */ + zzmode(START); + NLATEXT[0] = ' '; + NLATEXT[1] = ' '; + zzbegexpr[0] = '\0'; + if ( zzbufovf ) { + err( eMsgd("predicate buffer overflow; size %d",ZZLEXBUFSIZE)); + }; +#ifdef __cplusplus__ +/* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else +#ifdef __STDC__ +/* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else +#ifdef __USE_PROTOS +/* MRxx */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else +/* MR10 */ list_apply(CurActionLabels,mark_label_used_in_sem_pred); +#endif +#endif +#endif + >> +#token PassAction "\]" << if ( topint() == ']' ) { + popint(); + if ( istackempty() ) /* terminate action */ + { + zzmode(START); + NLATEXT[0] = ' '; + zzbegexpr[0] = ' '; + if ( zzbufovf ) { + err( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE)); + } + } + else { + /* terminate $[..] and #[..] */ + if ( GenCC ) zzreplstr("))"); + else zzreplstr(")"); + zzmore(); + } + } + else if ( topint() == '|' ) { /* end of simple [...] */ + popint(); + zzmore(); + } + else zzmore(); + >> +#token "consumeUntil\( [\ \t]* \{~[\}]+\} [\ \t]* \)" + << + zzmore(); + zzreplstr(inline_set(zzbegexpr+ + strlen("consumeUntil("))); + >> +#token "consumeUntil\( ~[\)]+ \)" + << zzmore(); >> +#token "\n|\r|\r\n" << zzline++; zzmore(); DAWDLE; >> +#token "\>" << zzmore(); >> +#token "$" << zzmore(); >> +#token "$$" << if ( !GenCC ) {zzreplstr("zzaRet"); zzmore();} + else err("$$ use invalid in C++ mode"); >> + +#token "$\[\]" << if ( !GenCC ) {zzreplstr("zzempty_attr"); zzmore();} + else err("$[] use invalid in C++ mode"); >> +#token "$\[" << + pushint(']'); + if ( !GenCC ) zzreplstr("zzconstr_attr("); + else err("$[..] use invalid in C++ mode"); + zzmore(); + >> +#token "$[0-9]+" <<{ + static char buf[100]; + numericActionLabel=1; /* MR10 */ + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("$i attrib ref too big"); + set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction); + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s)", + BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"_t%d%s", + BlkLevel-1,zzbegexpr+1); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + >> +#token "$[0-9]+." <<{ + static char buf[100]; + numericActionLabel=1; /* MR10 */ + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("$i.field attrib ref too big"); + zzbegexpr[strlen(zzbegexpr)-1] = ' '; + set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction); + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s).", + BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"_t%d%s.", + BlkLevel-1,zzbegexpr+1); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + >> +#token "$[0-9]+.[0-9]+" <<{ + static char buf[100]; + static char i[20], j[20]; + char *p,*q; + numericActionLabel=1; /* MR10 */ + if (strlen(zzbegexpr)>(size_t)85) fatal("$i.j attrib ref too big"); + for (p=zzbegexpr+1,q= &i[0]; *p!='.'; p++) { + if ( q == &i[20] ) + fatalFL("i of $i.j attrib ref too big", + FileStr[CurFile], zzline ); + *q++ = *p; + } + *q = '\0'; + for (p++, q= &j[0]; *p!='\0'; p++) { + if ( q == &j[20] ) + fatalFL("j of $i.j attrib ref too big", + FileStr[CurFile], zzline ); + *q++ = *p; + } + *q = '\0'; + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%s,%s)",i,j); + else sprintf(buf,"_t%s%s",i,j); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + >> +#token "$[_a-zA-Z][_a-zA-Z0-9]*" + <<{ static char buf[300]; LabelEntry *el; + zzbegexpr[0] = ' '; + if ( CurRule != NULL && + strcmp(CurRule, &zzbegexpr[1])==0 ) { + if ( !GenCC ) zzreplstr("zzaRet"); + } + else if ( CurRetDef != NULL && + strmember(CurRetDef, &zzbegexpr[1])) { + if ( hasMultipleOperands( CurRetDef ) ) { + require (strlen(zzbegexpr)<=(size_t)285, + "$retval attrib ref too big"); + sprintf(buf,"_retv.%s",&zzbegexpr[1]); + zzreplstr(buf); + } + else zzreplstr("_retv"); + } + else if ( CurParmDef != NULL && + strmember(CurParmDef, &zzbegexpr[1])) { + ; + } + else if ( Elabel==NULL ) { + { err("$-variables in actions outside of rules are not allowed"); } + } else if ( (el=(LabelEntry *)hash_get(Elabel, &zzbegexpr[1]))!=NULL ) { +/* MR10 */ +/* MR10 */ /* element labels might exist without an elem when */ +/* MR10 */ /* it is a forward reference (to a rule) */ +/* MR10 */ +/* MR10 */ if ( GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) ) +/* MR10 */ { err(eMsg1("There are no token ptrs for rule references: '$%s'",&zzbegexpr[1])); } +/* MR10 */ +/* MR10 */ if ( !GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) && GenAST) { +/* MR10 */ err("You can no longer use attributes returned by rules when also using ASTs"); +/* MR10 */ err(" Use upward inheritance (\"rule >[Attrib a] : ... <<$a=...\>\>\")"); +/* MR10 */ }; +/* MR10 */ +/* MR10 */ /* keep track of <<... $label ...>> for semantic predicates in guess mode */ +/* MR10 */ /* element labels contain pointer to the owners node */ +/* MR10 */ +/* MR10 */ if (el->elem != NULL && el->elem->ntype == nToken) { +/* MR10 */ list_add(&CurActionLabels,el); +/* MR10 */ }; + } + else + warn(eMsg1("$%s not parameter, return value, (defined) element label",&zzbegexpr[1])); + } + zzmore(); + >> +#token "#0" << zzreplstr("(*_root)"); zzmore(); chkGTFlag(); >> +#token "#\[\]" << if ( GenCC ) { + if (NewAST) zzreplstr("(newAST)"); + else zzreplstr("(new AST)");} + else {zzreplstr("zzastnew()");} zzmore(); + chkGTFlag(); + >> +#token "#\(\)" << zzreplstr("NULL"); zzmore(); chkGTFlag(); >> +#token "#[0-9]+" <<{ + static char buf[100]; + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("#i AST ref too big"); + if ( GenCC ) sprintf(buf,"_ast%d%s",BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"zzastArg(%s)",zzbegexpr+1); + zzreplstr(buf); + zzmore(); + set_orel(atoi(zzbegexpr+1), &AST_nodes_refd_in_actions); + chkGTFlag(); + } + >> + +/* MR14 Arpad Beszedes 26-May-98 + Add support for #line directives when antlr source is pre-processed + #lexclass ACTIONS +*/ + +#token "#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n)" + << + zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore(); + getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr); + >> + +#token "#line ~[\n\r]* (\n|\r|\r\n)" + << + zzline++; zzmore(); + >> + +/* MR14 end of a block to support #line in antlr source code */ + +#token "#[_a-zA-Z][_a-zA-Z0-9]*" + << + if ( !(strcmp(zzbegexpr, "#ifdef")==0 || + strcmp(zzbegexpr, "#if")==0 || + strcmp(zzbegexpr, "#else")==0 || + strcmp(zzbegexpr, "#endif")==0 || + strcmp(zzbegexpr, "#ifndef")==0 || + strcmp(zzbegexpr, "#define")==0 || + strcmp(zzbegexpr, "#pragma")==0 || + strcmp(zzbegexpr, "#undef")==0 || + strcmp(zzbegexpr, "#import")==0 || + strcmp(zzbegexpr, "#line")==0 || + strcmp(zzbegexpr, "#include")==0 || + strcmp(zzbegexpr, "#error")==0) ) + { + static char buf[100]; + sprintf(buf, "%s_ast", zzbegexpr+1); +/* MR27 */ list_add(&CurAstLabelsInActions, mystrdup(zzbegexpr+1)); + zzreplstr(buf); + chkGTFlag(); + } + zzmore(); + >> +#token "#\[" << + pushint(']'); + if ( GenCC ) { + if (NewAST) zzreplstr("(newAST("); + else zzreplstr("(new AST("); } + else zzreplstr("zzmk_ast(zzastnew(),"); + zzmore(); + chkGTFlag(); + >> +#token "#\(" << + pushint('}'); + if ( GenCC ) { + if (tmakeInParser) { + zzreplstr("tmake("); + } + else { + zzreplstr("ASTBase::tmake("); + } + } + else { + zzreplstr("zztmake("); + } + zzmore(); + chkGTFlag(); + >> +#token "#" << zzmore(); >> +#token "\)" << + if ( istackempty() ) + zzmore(); + else if ( topint()==')' ) { + popint(); + } + else if ( topint()=='}' ) { + popint(); + /* terminate #(..) */ + zzreplstr(", NULL)"); + } + zzmore(); + >> +#token "\[" << + pushint('|'); /* look for '|' to terminate simple [...] */ + zzmore(); + >> +#token "\(" << + pushint(')'); + zzmore(); + >> + +#token "\\\]" << zzreplstr("]"); zzmore(); >> +#token "\\\)" << zzreplstr(")"); zzmore(); >> + +/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ +/* MR1 in DLG action */ + +#token "\\>" << if (! tokenActionActive) zzreplstr(">"); /* MR1 */ + zzmore(); /* MR1 */ + >> /* MR1 */ + + +#token "'" << zzmode(ACTION_CHARS); zzmore();>> +#token "\"" << zzmode(ACTION_STRINGS); zzmore();>> +#token "\\$" << zzreplstr("$"); zzmore(); >> +#token "\\#" << zzreplstr("#"); zzmore(); >> +#token "\\(\n|\r|\r\n)" << zzline++; zzmore(); >> +#token "\\~[\]\)>$#]" << zzmore(); >> /* escaped char, always ignore */ +#token "/" << zzmore(); >> +#token "/\*" << zzmode(ACTION_COMMENTS); zzmore(); >> +#token "\*/" << warn("Missing /*; found dangling */ in action"); zzmore(); >> +#token "//" << zzmode(ACTION_CPP_COMMENTS); zzmore(); >> +#token "~[\n\r\)\(\\$#\>\]\[\"'/]+" << zzmore(); >> + +#lexclass START +#token "[\t\ ]+" << zzskip(); >> /* Ignore White */ +#token "\n|\r|\r\n" << zzline++; zzskip(); >> /* Track Line # */ +#token "\[" << zzmode(ACTIONS); zzmore(); + istackreset(); + pushint(']'); >> +#token "\<\<" << action_file=CurFile; action_line=zzline; + zzmode(ACTIONS); zzmore(); + list_free(&CurActionLabels,0); /* MR10 */ + numericActionLabel=0; /* MR10 */ + istackreset(); + pushint('>'); >> +#token "\"" << zzmode(STRINGS); zzmore(); >> +#token "/\*" << zzmode(COMMENTS); zzskip(); >> +#token "\*/" << warn("Missing /*; found dangling */"); zzskip(); >> +#token "//" << zzmode(CPP_COMMENTS); zzskip(); >> + +/* MR14 Arpad Beszedes 26-May-98 + Add support for #line directives when antlr source is pre-processed + #lexclass START +*/ + +#token "#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n)" + << + zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore(); + getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr); + >> + +#token "#line ~[\n\r]* (\n|\r|\r\n)" + << + zzline++; zzmore(); + >> + +/* MR14 end of a block to support #line in antlr source code */ + +/* */ +/* 8-Apr-97 Regularize escape sequence for ">>" */ +/* appearing in string literals */ +/* */ + +#token "\>\>" << warn("Missing <<; found dangling \>\>"); zzskip(); >> /* MR1 */ +#token WildCard "." +#token "\@" <> /* MR6 */ +#token Eof "@" + << /* L o o k F o r A n o t h e r F i l e */ + { + FILE *new_input; + new_input = NextFile(); + if ( new_input == NULL ) { NLA=Eof; return; } + fclose( input ); + input = new_input; + zzrdstream( input ); + zzskip(); /* Skip the Eof (@) char i.e continue */ + } + >> + +#token LABEL + +#errclass "grammar-element" { element } +#errclass "meta-symbol" { "\}" "!" ";" "\|" "\~" "^" "\)" } + +#token Pragma "{\\}#pragma" /* MR21 */ +#token FirstSetSymbol "{\\}#FirstSetSymbol" /* MR21 */ +/* + * Get a grammar -- Build a list of rules like: + * + * o-->Rule1--o + * | + * o-->Rule2--o + * | + * ... + * | + * o-->RuleN--o + */ + +/* rule grammar */ + +grammar : <> + ( "{\\}#header" Action /* MR13 */ + << + if ( HdrAction==NULL ) { + HdrAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(HdrAction!=NULL, "rule grammar: cannot allocate header action"); + strcpy(HdrAction, LATEXT(1)); + } + else warn("additional #header statement ignored"); + >> + | "{\\}#first" Action + << + if ( FirstAction==NULL ) { + FirstAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(FirstAction!=NULL, "rule grammar: cannot allocate #first action"); + strcpy(FirstAction, LATEXT(1)); + } else { + warn("additional #first statement ignored"); + }; + >> + + | "{\\}#parser" QuotedTerm + << + if ( GenCC ) { + warn("#parser meta-op incompatible with -CC; ignored"); + } + else { + if ( strcmp(ParserName,"zzparser")==0 ) { + ParserName=StripQuotes(mystrdup(LATEXT(1))); + if ( RulePrefix[0]!='\0' ) + { + warn("#parser meta-op incompatible with '-gp prefix'; '-gp' ignored"); + RulePrefix[0]='\0'; + } + } + else warn("additional #parser statement ignored"); + } + >> + | "{\\}#tokdefs" QuotedTerm + <<{ + char *fname; + zzantlr_state st; FILE *f; struct zzdlg_state dst; + UserTokenDefsFile = mystrdup(LATEXT(1)); + zzsave_antlr_state(&st); + zzsave_dlg_state(&dst); + fname = mystrdup(LATEXT(1)); + f = fopen(StripQuotes(fname), "r"); + if ( f==NULL ) {warn(eMsg1("cannot open token defs file '%s'", fname+1));} + else { + ANTLRm(enum_file(fname+1), f, PARSE_ENUM_FILE); + UserDefdTokens = 1; + } + zzrestore_antlr_state(&st); + zzrestore_dlg_state(&dst); + }>> + )* + ( Action + <<{ + UserAction *ua = newUserAction(LATEXT(1)); + ua->file = action_file; ua->line = action_line; + if ( class_nest_level>0 ) list_add(&class_before_actions, ua); + else list_add(&BeforeActions, ua); + }>> + | laction + | lmember /* MR1 */ + | lprefix /* MR1 */ + | aLexclass + | token + | error + | tclass + | aPred /* MR11 */ + | default_exception_handler + | class_def + | "\}" + << + if ( class_nest_level==0 ) + warn("missing class definition for trailing '}'"); + class_nest_level--; + >> + )* + + rule <> + ( rule + + <> + + | aLexclass + | token + | error + | tclass + | aPred /* MR11 */ + | class_def + | "\}" + << + if ( class_nest_level==0 ) + warn("missing class definition for trailing '}'"); + class_nest_level--; + >> + )* + ( Action + <<{ + UserAction *ua = newUserAction(LATEXT(1)); + ua->file = action_file; ua->line = action_line; + if ( class_nest_level>0 ) list_add(&class_after_actions, ua); + else list_add(&AfterActions, ua); + }>> + | laction + | lmember /* MR1 */ + | lprefix /* MR1 */ + | error + | tclass + | class_def + | aPred /* MR11 */ + | "\}" + << + if ( class_nest_level==0 ) + warn("missing class definition for trailing '}'"); + class_nest_level--; + >> + )* + Eof + ; + <> + +/* rule class_def */ + +class_def + : <> + "class" + ( NonTerminal <> + | TokenTerm <> + ) + << + if ( CurrentClassName[0]!='\0' && strcmp(CurrentClassName,name)!=0 + && GenCC ) { + err("only one grammar class allowed in this release"); + go = 0; + } + else strcpy(CurrentClassName, name); + >> + <> + +/* MR10 */ (~ "\{" +/* MR10 */ <> +/* MR10 */ )* + + "\{" + << + no_classes_found = 0; + if ( class_nest_level>=1 ) {warn("cannot have nested classes");} + else class_nest_level++; + >> + ; + <> + +/* + * Build -o-->o-R-o-->o- where -o-R-o- is the block from rule 'block'. + * Construct the RuleBlk front and EndRule node on the end of the + * block. This is used to add FOLLOW pointers to the rule end. Add the + * new rule name to the Rname hash table and sets its rulenum. + * Store the parameter definitions if any are found. + * + * Note that locks are required on the RuleBlk and EndRule nodes to thwart + * infinite recursion. + * + * Return the left graph pointer == NULL to indicate error/dupl rule def. + */ + +/* rule rule */ + +rule : << + + ExceptionGroup *eg; + RuleEntry *q; Junction *p; Graph r; int f, l; ECnode *e; + set toksrefd, rulesrefd; + char *pdecl=NULL, *ret=NULL, *a; CurRetDef = CurParmDef = NULL; + CurExGroups = NULL; + CurElementLabels = NULL; + CurAstLabelsInActions = NULL; /* MR27 */ + /* We want a new element label hash table for each rule */ + if ( Elabel!=NULL ) killHashTable(Elabel); + Elabel = newHashTable(); + attribsRefdFromAction = empty; + >> + NonTerminal + <str; + } + CurRuleNode = q; + f = CurFile; l = zzline; + NumRules++; + >> + { "!" <noAST = TRUE;>> } + { <<;>> + {"\<"} + PassAction + << pdecl = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(pdecl!=NULL, "rule rule: cannot allocate param decl"); + strcpy(pdecl, LATEXT(1)); + CurParmDef = pdecl; + >> + } + { "\>" + PassAction + << ret = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(ret!=NULL, "rule rule: cannot allocate ret type"); + strcpy(ret, LATEXT(1)); + CurRetDef = ret; + >> + } + { QuotedTerm <egroup=mystrdup(LATEXT(1));>> } + << + if ( GenEClasseForRules && q!=NULL ) { + e = newECnode; + require(e!=NULL, "cannot allocate error class node"); + if ( q->egroup == NULL ) {a = q->str; a[0] = (char)toupper(a[0]);} + else a = q->egroup; + if ( Tnum( a ) == 0 ) + { + e->tok = addTname( a ); + list_add(&eclasses, (char *)e); + if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]); + /* refers to itself */ + list_add(&(e->elist), mystrdup(q->str)); + } + else { + warn(eMsg1("default errclass for '%s' would conflict with token/errclass/tokclass",a)); + if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]); + free((char *)e); + } + } + >> + <= MAX_BLK_LEVEL) fatal("Blocks nested too deeply"); +/* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID; +/* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + >> + + ":" <> + block[&toksrefd, &rulesrefd] + <blockid = CurBlockID; + CurRuleBlk->jtype = RuleBlk; + if ( q!=NULL ) CurRuleBlk->rname = q->str; + CurRuleBlk->file = f; + CurRuleBlk->line = l; + CurRuleBlk->pdecl = pdecl; + CurRuleBlk->ret = ret; + CurRuleBlk->lock = makelocks(); + CurRuleBlk->pred_lock = makelocks(); + CurRuleBlk->tokrefs = toksrefd; + CurRuleBlk->rulerefs = rulesrefd; + p = newJunction(); /* add EndRule Node */ + ((Junction *)r.right)->p1 = (Node *)p; + r.right = (Node *) p; + p->jtype = EndRule; + p->lock = makelocks(); + p->pred_lock = makelocks(); + CurRuleBlk->end = p; + if ( q!=NULL ) q->rulenum = NumRules; + $7 = r; + >> + << + /* MR23 */ CurBlockID_array[BlkLevel] = (-1); + /* MR23 */ CurAltNum_array[BlkLevel] = (-1); + --BlkLevel; + >> + <> /* MR7 */ + ";" <> + { Action + << a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule rule: cannot allocate error action"); + strcpy(a, LATEXT(1)); + CurRuleBlk->erraction = a; + >> + } + ( exception_group > [eg] + <label == NULL || *eg->label=='\0' ) q->has_rule_exception = 1; + } + >> + )* + <> + <exceptions = CurExGroups;>> + <el_labels = CurElementLabels;>> + <ast_labels_in_actions = CurAstLabelsInActions;>> /* MR27 */ + <> /* MR27 Moved */ + ; + <> + +/* + * pragma : "{\\}#pragma" "dup\-labeled\-tokens" + * <> + * ; + */ + +/* rule laction */ + +laction : <> + + "{\\}#lexaction" + Action + << + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule laction: cannot allocate action"); + strcpy(a, LATEXT(1)); + list_add(&LexActions, a); + >> + ; + <> + +/* MR1 */ +/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ +/* MR1 via #lexmember <<....>> & #lexprefix <<...>> */ +/* MR1 */ + +/* rule lmember */ + +lmember: <> /* MR1 */ + +/* MR1 */ "{\\}#lexmember" +/* MR1 */ Action +/* MR1 */ << +/* MR1 */ if (! GenCC) { +/* MR1 */ err("Use #lexmember only in C++ mode (to insert code in DLG class header"); +/* MR1 */ } else { +/* MR1 */ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); +/* MR1 */ require(a!=NULL, "rule lmember: cannot allocate action"); +/* MR1 */ strcpy(a, LATEXT(1)); +/* MR1 */ list_add(&LexMemberActions, a); +/* MR1 */ }; +/* MR1 */ >> +/* MR1 */ ; +/* MR1 */ <> + +/* rule lprefix */ + +lprefix: <> /* MR1 */ + +/* MR1 */ "{\\}#lexprefix" +/* MR1 */ Action +/* MR1 */ << +/* MR1 */ if (! GenCC) { +/* MR1 */ err("Use #lexprefix only in C++ mode (to insert code in DLG class header"); +/* MR1 */ } else { +/* MR1 */ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); +/* MR1 */ require(a!=NULL, "rule lprefix: cannot allocate action"); +/* MR1 */ strcpy(a, LATEXT(1)); +/* MR1 */ list_add(&LexPrefixActions, a); +/* MR1 */ }; +/* MR1 */ >> +/* MR1 */ ; +/* MR1 */ <> + +/* + * #pred upper <>? predicate literal + * #pred lower <>? predicate literal + * #pred up_or_low upper || lower predicate expression + * concealed interdependence + * #pred up_or_low_2 <>? A || B predicate literal equals predicate expr + * analyze using lower||upper + * generate using isLetter() + */ + +/* rule aPref */ + +aPred: <> + + "{\\}#pred" + + << + MR_usingPredNames=1; /* will need to use -mrhoist version of genPredTree */ + >> + + /* used to allow NonTerminal but it caused problems + when a rule name immediately followed a #pred statement */ + + TokenTerm <> + + << + /* don't free - referenced in predicates */ + + CurPredName=(char *)calloc(1,strlen(name) + 10); + strcat(CurPredName,"#pred "); + strcat(CurPredName,name); + + predEntry=(PredEntry *) hash_get(Pname,name); + if (predEntry != NULL) { + warnFL(eMsg1("#pred %s previously defined - ignored",name), + FileStr[action_file],action_line); + name=NULL; + }; + >> + + ( + + Pred <> + + { + predOrExpr>[predExpr] <> + } + + <file=save_file; + predEntry->line=save_line; + predExpr=MR_predFlatten(predExpr); + predEntry->predLiteral=predLiteral; + if (! predExprPresent || predExpr == NULL) { + predExpr=new_pred(); + predExpr->expr=predLiteral; + predExpr->source=newActionNode(); + predExpr->source->action=predExpr->expr; + predExpr->source->rname=CurPredName; + predExpr->source->line=action_line; + predExpr->source->file=action_file; + predExpr->source->is_predicate=1; + predExpr->k=predicateLookaheadDepth(predExpr->source); + }; + predEntry->pred=predExpr; + hash_add(Pname,name,(Entry *)predEntry); + predExpr=NULL; + }; + predicate_free(predExpr); + >> + + | + <> + + predOrExpr>[predExpr] + + <file=CurFile; + predEntry->line=zzline; + predExpr=MR_predFlatten(predExpr); + predEntry->pred=predExpr; + hash_add(Pname,name,(Entry *)predEntry); + predExpr=NULL; + }; + predicate_free(predExpr); + >> + ) + {";"} +; + +/* fail */ + +<> + +/* rule predOrExpr */ + +predOrExpr>[Predicate *result] : + <> + predAndExpr>[predExpr] + << + ORnode=new_pred(); + ORnode->expr=PRED_OR_LIST; + if (predExpr != NULL) { + ORnode->down=predExpr; + tail=&predExpr->right; + }; + >> + ( "\|\|" predAndExpr>[predExpr] + << + if (predExpr != NULL) { + *tail=predExpr; + tail=&predExpr->right; + }; + >> + )* + << + $result=ORnode; + ORnode=NULL; + >> +; + +/* fail */ + +<> + +/* rule predAndExpr */ + +predAndExpr>[Predicate *result] : + <> + predPrimary>[predExpr] + << + ANDnode=new_pred(); + ANDnode->expr=PRED_AND_LIST; + if (predExpr != NULL) { + ANDnode->down=predExpr; + tail=&predExpr->right; + }; + >> + ( "&&" predPrimary>[predExpr] + << + if (predExpr != NULL) { + *tail=predExpr; + tail=&predExpr->right; + }; + >> + )* + << + $result=ANDnode; + ANDnode=NULL; + >> +; + +/* fail */ + +<> + + +/* rule predPrimary */ + +predPrimary>[Predicate *result] : + << + char *name=NULL; + PredEntry *predEntry=NULL; + Predicate *predExpr=NULL; + >> + + TokenTerm <> + + << + predEntry=(PredEntry *) hash_get(Pname,name); + if (predEntry == NULL) { + warnFL(eMsg1("no previously defined #pred with name \"%s\"",name), + FileStr[CurFile],zzline); + name=NULL; + $result=NULL; + } else { + predExpr=predicate_dup(predEntry->pred); + predExpr->predEntry=predEntry; + $result=predExpr; + }; + >> + + | "\(" predOrExpr>[predExpr] "\)" + << + $result=predExpr; + >> + + | "!" predPrimary>[predExpr] + << + predExpr->inverted=!predExpr->inverted; + $result=predExpr; + >> +; + +/* fail */ << + predicate_free(predExpr); + >> + +/* rule aLexclass */ + +aLexclass: "{\\}#lexclass" TokenTerm <> + ; + <> + +/* rule error */ + +error : <> + "{\\}#errclass" + (<<;>> TokenTerm <> + | QuotedTerm <> + ) + <lexclass = CurrentLexClass; + if ( Tnum( (t=StripQuotes(t)) ) == 0 ) + { + if ( hash_get(Texpr, t) != NULL ) + warn(eMsg1("errclass name conflicts with regular expression '%s'",t)); + e->tok = addTname( t ); + set_orel(e->tok, &imag_tokens); + require((p=(TermEntry *)hash_get(Tname, t)) != NULL, + "hash table mechanism is broken"); + p->classname = 1; /* entry is errclass name, not token */ + list_add(&eclasses, (char *)e); + } + else + { + warn(eMsg1("redefinition of errclass or conflict w/token or tokclass '%s'; ignored",t)); + free( (char *)e ); + go=0; + } + >> + "\{" + ( NonTerminal <> + | TokenTerm <> + | QuotedTerm <> + ) + <elist), t);>> + ( + ( NonTerminal <> + | TokenTerm <> + | QuotedTerm <> + ) + <elist), t);>> + )* + "\}" + ; + <> + +/* rule tclass */ + +tclass : <> + <> + <> + "{\\}#tokclass" TokenTerm <> + <lexclass = CurrentLexClass; + if ( Tnum( t ) == 0 ) + { + e->tok = addTname( t ); + set_orel(e->tok, &imag_tokens); + set_orel(e->tok, &tokclasses); + require((p=(TermEntry *)hash_get(Tname, t)) != NULL, + "hash table mechanism is broken"); + p->classname = 1; /* entry is class name, not token */ + p->tclass = e; /* save ptr to this tclass def */ + list_add(&tclasses, (char *)e); + } + else + { + warn(eMsg1("redefinition of tokclass or conflict w/token '%s'; ignored",t)); + free( (char *)e ); + go=0; + } + >> +/* MR23 */ { +/* MR23 */ "\(" +/* MR23 */ QuotedTerm +/* MR23 */ <> +/* MR23 */ "\)" +/* MR23 */ } +/* MR23 */ +/* MR23 */ +/* MR23 */ << +/* MR23 */ if (p!= NULL && akaString != NULL) { +/* MR23 */ if (p->akaString != NULL) { +/* MR23 */ if (strcmp(p->akaString,akaString) != 0) { +/* MR23 */ warnFL(eMsg2("this #tokclass statement conflicts with a previous #tokclass %s(\"%s\") statement", +/* MR23 */ t,p->akaString), +/* MR23 */ FileStr[save_file],save_line); +/* MR23 */ }; +/* MR23 */ } else { +/* MR23 */ p->akaString=akaString; +/* MR23 */ }; +/* MR23 */ }; +/* MR23 */ >> + + "\{" + ( + ( TokenTerm + <> + + { + ".." + TokenTerm + + <> + } + + | QuotedTerm + <> + ) + <tlist), t); + } else { + list_add(&(e->tlist),".."); + list_add(&(e->tlist),t); + list_add(&(e->tlist),totext); + } + totext=NULL; + } + >> + )+ // MR15 Manfred Kogler - forbid empty #tokclass sets (was "+") + "\}" + ; + <> + +/* rule token */ + +token : <> + <> /* MR11 */ + "{\\}#token" + +/* MR1 10-Apr-97 MR1 Allow shift right operator in DLG actions */ +/* MR1 Danger when parser feedback to lexer */ +/* MR1 */ + + <> /* MR1 */ + { TokenTerm <> + +/* MR11 */ { +/* MR11 */ "\(" +/* MR11 */ QuotedTerm +/* MR11 */ <> +/* MR11 */ "\)" +/* MR11 */ } + + { "=" "[0-9]+" /* define the token type number */ + <> + } + } + { QuotedTerm <> } + { Action + << + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule token: cannot allocate action"); + strcpy(a, LATEXT(1)); + >> + } + + { ";" } /* MR11 */ + + <> + + <akaString != NULL) { + if (strcmp(te->akaString,akaString) != 0) { + warnFL(eMsg2("this #token statement conflicts with a previous #token %s(\"%s\") statement", + t,te->akaString), + FileStr[save_file],save_line); + }; + } else { + te->akaString=akaString; + }; + }; + }; + >> + ; + <> + +/* rule block */ + +block[set *toksrefd, set *rulesrefd] + : << + Graph g, b; + set saveblah; + int saveinalt = inAlt; + ExceptionGroup *eg; + *$toksrefd = empty; + *$rulesrefd = empty; + set_clr(AST_nodes_refd_in_actions); + CurBlockID++; +/* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID; + CurAltNum = 1; +/* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + saveblah = attribsRefdFromAction; + attribsRefdFromAction = empty; + >> + + alt[toksrefd,rulesrefd] <> + + << + if ( ((Junction *)g.left)->p1->ntype == nAction ) + { + ActionNode *actionNode=(ActionNode *) + ( ( (Junction *)g.left) ->p1); + if (!actionNode->is_predicate ) + { + actionNode->init_action = TRUE; +/* MR12c */ if (actionNode->noHoist) { +/* MR12c */ errFL("<> appears as init-action - use <<>> <>", +/* MR12c */ FileStr[actionNode->file],actionNode->line); +/* MR12c */ }; + } + } + ((Junction *)g.left)->blockid = CurBlockID; + >> + + ( exception_group > [eg] + << + if ( eg!=NULL ) { +/* MR7 ***** eg->altID = makeAltID(CurBlockID,CurAltNum); *****/ +/* MR7 ***** CurAltStart->exception_label = eg->altID; *****/ + list_add(&CurExGroups, (void *)eg); + } + >> + )* + <> + + ( "\|" <> + alt[toksrefd,rulesrefd] <> + << + ((Junction *)g.left)->blockid = CurBlockID; + >> + + ( exception_group > [eg] + << + if ( eg!=NULL ) { +/* MR7 ***** eg->altID = makeAltID(CurBlockID,CurAltNum); *****/ +/* MR7 ***** CurAltStart->exception_label = eg->altID; *****/ + list_add(&CurExGroups, (void *)eg); + } + >> + )* + + <> + + )* + <<$0 = b;>> + <> + ; + <> + +/* rule alt */ + +alt[set *toksrefd, set *rulesrefd] + : <> + { "\@" /* handle MismatchedToken signals with default handler */ + <> + } + + ( <<;>> /* MR9 Removed unreferenced variable "tok" */ + { <> "\~" <> } + element[old_not, first_on_line, use_def_MT_handler] > [node] + <ntype!=nAction ) first_on_line = 0;>> + << + if ( $2.left!=NULL ) { + g = Cat(g, $2); + n++; + if ( node!=NULL ) { + if ( node->ntype!=nAction ) e_num++; + /* record record number of all rule and token refs */ + if ( node->ntype==nToken ) { + TokNode *tk = (TokNode *)((Junction *)$2.left)->p1; + tk->elnum = e_num; + set_orel(e_num, &elems); + } + else if ( node->ntype==nRuleRef ) { + RuleRefNode *rn = (RuleRefNode *)((Junction *)$2.left)->p1; + rn->elnum = e_num; + set_orel(e_num, $rulesrefd); + } + } + } + >> + )* + <0 ) + err("one or more $i in action(s) refer to non-token elements"); + set_free(dif); + } + set_free(elems); + set_free(attribsRefdFromAction); + inAlt = 0; + >> + ; + <> + +/* rule element_label */ + +element_label > [LabelEntry *label] + : <> + LABEL <> + << + UsedNewStyleLabel = 1; + if ( UsedOldStyleAttrib ) err("cannot mix with new-style labels with old-style $i"); + t = (TermEntry *) hash_get(Tname, lab); + if ( t==NULL ) t = (TermEntry *) hash_get(Texpr, lab); + if ( t==NULL ) r = (RuleEntry *) hash_get(Rname, lab); + if ( t!=NULL ) { + err(eMsg1("label definition clashes with token/tokclass definition: '%s'", lab)); + $label = NULL; + } + else if ( r!=NULL ) { + err(eMsg1("label definition clashes with rule definition: '%s'", lab)); + $label = NULL; + } + else { + /* we don't clash with anybody else */ + l = (LabelEntry *) hash_get(Elabel, lab); + if ( l==NULL ) { /* ok to add new element label */ + l = (LabelEntry *)hash_add(Elabel, + lab, + (Entry *)newLabelEntry(lab)); + /* add to list of element labels for this rule */ + list_add(&CurElementLabels, (void *)lab); +/* MR7 */ leAdd(l); /* list of labels waiting for exception group definitions */ + $label = l; + } + else { + err(eMsg1("label definitions must be unique per rule: '%s'", lab)); + $label = NULL; + } + } + >> + ":" + ; + +/* rule element */ + +element[int old_not, int first_on_line, int use_def_MT_handler] > [Node *node] + : << + Attrib blk; + Predicate *pred = NULL; + int local_use_def_MT_handler=0; + ActionNode *act; + RuleRefNode *rr; + set toksrefd, rulesrefd; + TermEntry *term; + TokNode *p=NULL; RuleRefNode *q; int approx=0; + LabelEntry *label=NULL; + int predMsgDone=0; + int semDepth=0; + int ampersandStyle; + int height; /* MR11 */ + int equal_height; /* MR11 */ + + char* pFirstSetSymbol = NULL; /* MR21 */ + + $node = NULL; + >> + {element_label>[label]} + ( TokenTerm + << + term = (TermEntry *) hash_get(Tname, LATEXT(1)); + if ( term==NULL && UserDefdTokens ) { + err("implicit token definition not allowed with #tokdefs"); + $$.left = $$.right = NULL; + } + else { + $$ = buildToken(LATEXT(1)); + p=((TokNode *)((Junction *)$$.left)->p1); + term = (TermEntry *) hash_get(Tname, LATEXT(1)); + require( term!= NULL, "hash table mechanism is broken"); + p->tclass = term->tclass; + p->complement = $old_not; + if ( label!=NULL ) { + p->el_label = label->str; + label->elem = (Node *)p; + } + } + >> + { ".." + ( QuotedTerm + <> + | TokenTerm + <> + ) + } + << + if ( p!=NULL && (p->upper_range!=0 || p->tclass || $old_not) ) + list_add(&MetaTokenNodes, (void *)p); + >> + ( "^" <astnode=ASTroot;>> + | <astnode=ASTchild;>> + | "!" <astnode=ASTexclude;>> + ) + { "\@" <> } + << + if ( p!=NULL && $first_on_line ) { + CurAltStart = (Junction *)$$.left; + altAdd(CurAltStart); /* MR7 */ + p->altstart = CurAltStart; + } + if ( p!=NULL ) + p->use_def_MT_handler = $use_def_MT_handler || local_use_def_MT_handler; + $node = (Node *)p; + >> + | QuotedTerm + << + term = (TermEntry *) hash_get(Texpr, LATEXT(1)); + if ( term==NULL && UserDefdTokens ) { + err("implicit token definition not allowed with #tokdefs"); + $$.left = $$.right = NULL; + } + else { + $$ = buildToken(LATEXT(1)); p=((TokNode *)((Junction *)$$.left)->p1); + p->complement = $old_not; + if ( label!=NULL ) { + p->el_label = label->str; + label->elem = (Node *)p; + } + } + >> + { ".." + ( QuotedTerm + <> + | TokenTerm + <> + ) + } + ( "^" <astnode=ASTroot;>> + | <astnode=ASTchild;>> + | "!" <astnode=ASTexclude;>> + ) + { "\@" <> } + << + if ( p!=NULL && (p->upper_range!=0 || p->tclass || $old_not) ) + list_add(&MetaTokenNodes, (void *)p); + >> + << + if ( $first_on_line ) { + CurAltStart = (Junction *)$$.left; + altAdd(CurAltStart); /* MR7 */ + p->altstart = CurAltStart; + } + if ( p!=NULL ) + p->use_def_MT_handler = $use_def_MT_handler || local_use_def_MT_handler; + $node = (Node *)p; + >> + + | <> + "." + <<$$ = buildWildCard(LATEXT(1)); p=((TokNode *)((Junction *)$$.left)->p1);>> + ( "^" <astnode=ASTroot;>> + | <astnode=ASTchild;>> + | "!" <astnode=ASTexclude;>> + ) + <> + << + if ( $first_on_line ) { + CurAltStart = (Junction *)$$.left; + altAdd(CurAltStart); /* MR7 */ + p->altstart = CurAltStart; + if ( label!=NULL ) { + p->el_label = label->str; + label->elem = (Node *)p; + } + } + $node = (Node *)p; + >> + + | <> + NonTerminal + <<$$ = buildRuleRef(LATEXT(1));>> + { "!" <p1; + q->astnode=ASTexclude;>> + } + { {"\<"} + PassAction <p1, LATEXT(1));>> + } + <p1;>> + { <> + "\>" + PassAction + << + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule element: cannot allocate assignment"); + strcpy(a, LATEXT(1)); + rr->assign = a; + >> + } + << + if ( label!=NULL ) { + rr->el_label = label->str; + label->elem = (Node *)rr; + } + if ( $first_on_line ) { + CurAltStart = (Junction *)$$.left; + altAdd(CurAltStart); /* MR7 */ + ((RuleRefNode *)((Junction *)$$.left)->p1)->altstart = CurAltStart; + } + $node = (Node *)rr; + >> + ) + + | <> + Action <<$0 = buildAction(LATEXT(1),action_file,action_line, 0);>> + <> /* MR7 */ + <<$node = (Node *) ((Junction *)$0.left)->p1;>> + + | <> + Pred <<$0 = buildAction(LATEXT(1),action_file,action_line, 1);>> + <p1;>> + <> + { <> + PassAction + << + a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule element: cannot allocate predicate fail action"); + strcpy(a, LATEXT(1)); + act->pred_fail = a; + >> + } + <> /* MR7 */ + <<$node = (Node *)act;>> + + | <> + <= MAX_BLK_LEVEL) fatal("Blocks nested too deeply"); +/* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID; +/* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; + >> + { Pragma + ( "approx" <> + | "LL\(1\)" <> /* MR20 */ + | "LL\(2\)" <> /* MR20 */ + ) + } + +/* MR21 */ { FirstSetSymbol +/* MR21 */ "\(" +/* MR21 */ ( NonTerminal +/* MR21 */ << +/* MR21 */ pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1, +/* MR21 */ sizeof(char)); +/* MR21 */ require(pFirstSetSymbol!=NULL, +/* MR21 */ "cannot allocate first set name"); +/* MR21 */ strcpy(pFirstSetSymbol, LATEXT(1)); +/* MR21 */ >> +/* MR21 */ | TokenTerm +/* MR21 */ << +/* MR21 */ pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1, +/* MR21 */ sizeof(char)); +/* MR21 */ require(pFirstSetSymbol!=NULL, +/* MR21 */ "cannot allocate first set name"); +/* MR21 */ strcpy(pFirstSetSymbol, LATEXT(1)); +/* MR21 */ >> +/* MR21 */ ) +/* MR21 */ "\)" +/* MR21 */ } + + ( + + "\(" block[&toksrefd,&rulesrefd] "\)" + <> + + ( "\*" <<$$ = makeLoop($$,approx,pFirstSetSymbol);>> + | "\+" <<$$ = makePlus($$,approx,pFirstSetSymbol);>> + | "?" + ( + ( "=>" <> + | "&&" <> /* MR10 (g)? && <

>? */ + ) + Pred /* generalized predicate */ + /* first make into a predicate */ + <<$$ = buildAction(LATEXT(1),action_file,action_line,1);>> + <p1;>> + <> /* MR10 */ + <> + { <> + PassAction + << + a = (char *)calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(a!=NULL, "rule element: cannot allocate predicate fail action"); + strcpy(a, LATEXT(1)); + act->pred_fail = a; + >> + } + <> + <<$node = (Node *)act;>> + + /* for now, just snag context */ + << + pred = computePredFromContextGuard(blk,&predMsgDone); /* MR10 */ + if ( pred==NULL) { /* MR10 */ + if ( !predMsgDone) err("invalid or missing context guard"); /* MR10 */ + predMsgDone=1; /* MR10 */ + } else { /* MR10 */ + act->guardNodes=(Junction *)blk.left; /* MR11 */ + pred->expr = act->action; + pred->source = act; +/* MR10 */ pred->ampersandStyle = ampersandStyle; /* 0 means (g)? => ... 1 means (g)? && ... */ +/* MR13 */ if (pred->tcontext != NULL) { +/* MR13 */ height=MR_max_height_of_tree(pred->tcontext); +/* MR13 */ equal_height=MR_all_leaves_same_height(pred->tcontext,height); +/* MR13 */ if (! equal_height) { +/* MR13 */ errFL("in guarded predicates all tokens in the guard must be at the same height", +/* MR13 */ FileStr[act->file],act->line); +/* MR13 */ }; +/* MR13 */ } +/* MR10 */ if (ampersandStyle) { +/* MR10 */ act->ampersandPred = pred; +/* MR11 */ if (! HoistPredicateContext) { +/* MR11 */ errFL("without \"-prc on\" (guard)? && <>? ... doesn't make sense", +/* MR11 */ FileStr[act->file],act->line); +/* MR11 */ }; +/* MR10 */ } else { +/* MR10 */ act->guardpred = pred; +/* MR10 */ }; +/* MR10 */ if (pred->k != semDepth) { +/* MR10 */ warn(eMsgd2("length of guard (%d) does not match the length of semantic predicate (%d)", +/* MR10 */ pred->k,semDepth)); +/* MR10 */ }; + } + >> + | <<$$ = makeBlk($$,approx,pFirstSetSymbol); + FoundGuessBlk = 1; + ((Junction *) ((Junction *)$$.left)->p1)->guess=1; + if ( !$first_on_line ) { + err("(...)? predicate must be first element of production"); + } + >> + ) + | <<$$ = makeBlk($$,approx,pFirstSetSymbol);>> + ) + << + if ( pred==NULL && !predMsgDone) { /* MR10 */ + ((Junction *)((Junction *)$$.left)->p1)->blockid = CurBlockID; + ((Junction *)((Junction *)$$.left)->p1)->tokrefs = toksrefd; + ((Junction *)((Junction *)$$.left)->p1)->rulerefs = rulesrefd; + if ( $first_on_line ) { /* MR7 */ + CurAltStart = (Junction *)((Junction *)((Junction *)$$.left)->p1); /* MR7 */ + altAdd(CurAltStart); /* MR7 */ + }; /* MR7 */ + $node = (Node *) ((Junction *)$$.left)->p1; + } + >> + + | "\{" block[&toksrefd,&rulesrefd] + <<$$ = makeOpt($2,approx,pFirstSetSymbol); + /* MR23 */ CurBlockID_array[BlkLevel] = (-1); + /* MR23 */ CurAltNum_array[BlkLevel] = (-1); + --BlkLevel; + >> + "\}" + << + ((Junction *)((Junction *)$$.left)->p1)->blockid = CurBlockID; + ((Junction *)((Junction *)$$.left)->p1)->tokrefs = toksrefd; + ((Junction *)((Junction *)$$.left)->p1)->rulerefs = rulesrefd; + >> + <p1); /* MR7 */ + altAdd(CurAltStart); /* MR7 */ + }; + >> + <<$node = (Node *) ((Junction *)$$.left)->p1;>> + + ) + +/* Error catching alternatives */ + | "\*" <> + | "\+" <> + | "\>" <' can only appear after a nonterminal"); CannotContinue=TRUE;>> + | PassAction < [...]'"); + CannotContinue=TRUE;>> + ; + <> + +/* rule default_exception_handler */ + +default_exception_handler + : exception_group > [DefaultExGroup] + ; + +/* rule exception_group */ + +exception_group > [ExceptionGroup *eg] + : <> /* MR6 */ + + "exception" <<$eg = (ExceptionGroup *)calloc(1, sizeof(ExceptionGroup));>> + { <> + PassAction /* did they attach a label? */ + << + p = LATEXT(1)+1; + p[strlen(p)-1] = '\0'; /* kill trailing space */ + label = (LabelEntry *) hash_get(Elabel, LATEXT(1)+1); + if ( label==NULL ) + { + err(eMsg1("unknown label in exception handler: '%s'", LATEXT(1)+1)); + } + >> + } + ( exception_handler > [h] + <handlers), (void *)h);>> + )* + { "default" ":" Action + <<{ + ExceptionHandler *eh = (ExceptionHandler *) + calloc(1, sizeof(ExceptionHandler)); + char *a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require(eh!=NULL, "exception: cannot allocate handler"); + require(a!=NULL, "exception: cannot allocate action"); + strcpy(a, LATEXT(1)); + eh->action = a; + eh->signalname = (char *) calloc(strlen("default")+1, sizeof(char)); + require(eh->signalname!=NULL, "exception: cannot allocate sig name"); + strcpy(eh->signalname, "default"); + list_add(&($eg->handlers), (void *)eh); + }>> + } + + << + if ( label!=NULL ) { + /* Record ex group in sym tab for this label */ + if ( label->ex_group!=NULL ) { + err(eMsg1("duplicate exception handler for label '%s'",label->str)); + } else { + label->ex_group = $eg; + /* Label the exception group itself */ + $eg->label = label->str; + /* Make the labelled element pt to the exception also */ +/* MR6 */ if (label->elem == NULL) { +/* MR6 */ err(eMsg1("reference in exception handler to undefined label '%s'",label->str)); +/* MR6 */ } else { + switch ( label->elem->ntype ) { + case nRuleRef : + { + RuleRefNode *r = (RuleRefNode *)label->elem; + r->ex_group = $eg; + break; + } + case nToken : + { + TokNode *t = (TokNode *)label->elem; + t->ex_group = $eg; + break; + } + } /* end switch */ +/* MR6 */ }; /* end test on label->elem */ + } /* end test on label->ex_group */ + + } /* end test on exception label */ + +/* MR7 */ +/* MR7 */ if (BlkLevel == 1 && label == NULL) { +/* MR7 */ $eg->forRule=1; +/* MR7 */ } else if (label == NULL) { +/* MR7 */ $eg->altID = makeAltID(CurBlockID_array[BlkLevel], CurAltNum_array[BlkLevel]); +/* MR7 */ egAdd($eg); +/* MR7 */ } else { +/* MR7 */ $eg->labelEntry=label; +/* MR7 */ }; +/* MR7 */ +/* MR7 */ /* You may want to remove this exc from the rule list */ +/* MR7 */ /* and handle at the labeled element site. */ +/* MR7 */ +/* MR7 */ if (label != NULL) { +/* MR7 */ $eg = NULL; +/* MR7 */ }; + + >> + ; + <> + +/* rule exception_handler */ + +exception_handler > [ExceptionHandler *eh] + : <<;>> /* MR9 Removed unreferenced variable "a" */ + "catch" + << + $eh = (ExceptionHandler *)calloc(1, sizeof(ExceptionHandler)); + require($eh!=NULL, "exception: cannot allocate handler"); + >> + ( NonTerminal + << + $eh->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require($eh->signalname!=NULL, "exception: cannot allocate sig name"); + strcpy($eh->signalname, LATEXT(1)); + >> + | TokenTerm + << + $eh->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require($eh->signalname!=NULL, "exception: cannot allocate sig name"); + strcpy($eh->signalname, LATEXT(1)); + >> + ) + ":" + { <<$eh->action = NULL;>> + Action + << + $eh->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + require($eh->action!=NULL, "exception: cannot allocate action"); + strcpy($eh->action, LATEXT(1)); + >> + } + ; + <> + +#token NonTerminal "[a-z] [A-Za-z0-9_]*" + << + while ( zzchar==' ' || zzchar=='\t' ) { + zzadvance(); + } + if ( zzchar == ':' && inAlt ) NLA = LABEL; + >> +#token TokenTerm "[A-Z] [A-Za-z0-9_]*" + << + while ( zzchar==' ' || zzchar=='\t' ) { + zzadvance(); + } + if ( zzchar == ':' && inAlt ) NLA = LABEL; + >> +#token "{\\}#[A-Za-z0-9_]*" <> + +#lexclass PARSE_ENUM_FILE + +#token "[\t\ ]+" << zzskip(); >> /* Ignore White */ +#token "\n|\r|\r\n" << zzline++; zzskip(); >> /* Track Line # */ +#token "//" << zzmode(TOK_DEF_CPP_COMMENTS); zzmore(); >> +#token "/\*" << zzmode(TOK_DEF_COMMENTS); zzskip(); >> +#token "#ifdef" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> +#token "#if" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> +#token "#ifndef" << ; >> +#token "#else" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> +#token "#endif" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> +#token "#undef" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> +#token "#import" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> +#token "@" << ; >> + +/* rule enum_file */ + +enum_file[char *fname] + : { "#ifndef" ID + { "#define" ID /* ignore if it smells like a gate */ + /* First #define after the first #ifndef (if any) is ignored */ + } + } + ( ( enum_def[$fname] )+ + | defines[$fname] + ) + | + ; + +/* rule defines */ + +defines[char *fname] + : <> /* MR3 */ + ( + "#define" ID + <> + INT + << + v = atoi(LATEXT(1)); +/* fprintf(stderr, "#token %s=%d\n", t, v);*/ + + /* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */ + /* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */ + /* MR2 Don't let #tokdefs be confused by */ + /* MR2 DLGminToken and DLGmaxToken */ + + if ( ! isDLGmaxToken(t)) { /* MR2 */ + TokenNum = v; + if ( v>maxt ) maxt=v; + if ( Tnum( t ) == 0 ) { + addForcedTname( t, v ); + } else { + warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline); + }; + }; + >> + )+ + <> + ; + +/* rule enum_def */ + +enum_def[char *fname] + : <> /* MR3 */ + "enum" ID + "\{" + ID + <> + ( "=" INT <> + | <> + ) + << +/* fprintf(stderr, "#token %s=%d\n", t, v);*/ + TokenNum = v; + if ( v>maxt ) maxt=v; /* MR3 */ + if ( Tnum( t ) == 0 ) addForcedTname( t, v ); + else { + warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline); + } + >> + ( "," + + /* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */ + /* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */ + /* MR2 Don't let #tokdefs be confused by */ + /* MR2 DLGminToken and DLGmaxToken */ + + { + <>? ID { "=" INT } /* MR2 */ + | ID /* MR2 */ + <> + ( "=" INT <> + | <> + ) + << +/* fprintf(stderr, "#token %s=%d\n", t, v);*/ + TokenNum = v; + if ( v>maxt ) maxt=v; /* MR3 */ + if ( Tnum( t ) == 0 ) addForcedTname( t, v ); + else { + warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline); + } + >> + } + )* + "\}" + ";" + <> /* MR3 */ + ; + +#token INT "[0-9]+" +#token ID "[a-zA-Z_][_a-zA-Z0-9]*" + +#lexclass START + +/* MR14 Arpad Beszedes 26-May-98 + Add support for #line directives when antlr source is pre-processed +*/ + +#lexaction +<< + +static char * +#ifdef __USE_PROTOS +getFileNameFromTheLineInfo(char *toStr, char *fromStr) +#else +getFileNameFromTheLineInfo(toStr, fromStr) +char *toStr, *fromStr; +#endif +{ + int i, j, k; + + if (!fromStr || !toStr) return toStr; + + /* find the first " */ + + for (i=0; + (i> + +<< + +/* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */ +/* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */ +/* MR2 Don't let #tokdefs be confused by */ +/* MR2 DLGminToken and DLGmaxToken */ + +/* semantic check on DLGminToken and DLGmaxmaxToken in #tokdefs */ + +#ifdef __USE_PROTOS +static int isDLGmaxToken(char *Token) +#else +static int isDLGmaxToken(Token) + char * Token; +#endif +{ + static char checkStr1[] = "DLGmaxToken"; + static char checkStr2[] = "DLGminToken"; + + if (strcmp(Token, checkStr1) == 0) + return 1; + else if (strcmp(Token, checkStr2) == 0) + return 1; + else + return 0; +} + +/* semantics of #token */ +static void +#ifdef __USE_PROTOS +chkToken(char *t, char *e, char *a, int tnum) +#else +chkToken(t,e,a,tnum) +char *t, *e, *a; +int tnum; +#endif +{ + TermEntry *p; + + /* check to see that they don't try to redefine a token as a token class */ + if ( t!=NULL ) { + p = (TermEntry *) hash_get(Tname, t); + if ( p!=NULL && p->classname ) { + err(eMsg1("redefinition of #tokclass '%s' to #token not allowed; ignored",t)); + if ( a!=NULL ) free((char *)a); + return; + } + } + + if ( t==NULL && e==NULL ) { /* none found */ + err("#token requires at least token name or rexpr"); + } + else if ( t!=NULL && e!=NULL ) { /* both found */ + if ( UserDefdTokens ) { /* if #tokdefs, must not define new */ + p = (TermEntry *) hash_get(Tname, t); + if ( p == NULL) { +err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t)); + return; + }; + } + Tklink(t, e); + if ( a!=NULL ) { + if ( hasAction(e) ) { + err(eMsg1("redefinition of action for %s; ignored",e)); + } + else setHasAction(e, a); + } + } + else if ( t!=NULL ) { /* only one found */ + if ( UserDefdTokens ) { + p = (TermEntry *) hash_get(Tname, t); + if (p == NULL) { +err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t)); + }; + return; + } + if ( Tnum( t ) == 0 ) addTname( t ); + else { + err(eMsg1("redefinition of token %s; ignored",t)); + } + if ( a!=NULL ) { + err(eMsg1("action cannot be attached to a token name (%s); ignored",t)); + free((char *)a); + } + } + else if ( e!=NULL ) { + if ( Tnum( e ) == 0 ) addTexpr( e ); + else { + if ( hasAction(e) ) { + err(eMsg1("redefinition of action for expr %s; ignored",e)); + } + else if ( a==NULL ) { + err(eMsg1("redefinition of expr %s; ignored",e)); + } + } + if ( a!=NULL ) setHasAction(e, a); + } + + /* if a token type number was specified, then add the token ID and 'tnum' + * pair to the ForcedTokens list. (only applies if an id was given) + */ + if ( t!=NULL && tnum>0 ) + { + if ( set_el(tnum, reserved_positions) ) + { + err(eMsgd("a token has already been forced to token number %d; ignored", tnum)); + } + else + { + list_add(&ForcedTokens, newForcedToken(t,tnum)); + set_orel(tnum, &reserved_positions); + } + } +} +>> + +<< +static int +#ifdef __USE_PROTOS +match_token(char *s, char **nxt) +#else +match_token(s,nxt) +char *s; +char **nxt; +#endif +{ + if ( !(*s>='A' && *s<='Z') ) return 0; + s++; + while ( (*s>='a' && *s<='z') || + (*s>='A' && *s<='Z') || + (*s>='0' && *s<='9') || + *s=='_' ) + { + s++; + } + if ( *s!=' ' && *s!='}' ) return 0; + *nxt = s; + return 1; +} + +static int +#ifdef __USE_PROTOS +match_rexpr(char *s, char **nxt) +#else +match_rexpr(s,nxt) +char *s; +char **nxt; +#endif +{ + if ( *s!='"' ) return 0; + s++; + while ( *s!='"' ) + { + if ( *s=='\n' || *s=='\r' ) /* MR13 */ + warn("eoln found in regular expression"); + if ( *s=='\\' ) s++; + s++; + } + *nxt = s+1; + return 1; +} + +/* + * Walk a string "{ A .. Z }" where A..Z is a space separated list + * of token references (either labels or reg exprs). Return a + * string "inlineX_set" for some unique integer X. Basically, + * we pretend as if we had seen "#tokclass inlineX { A .. Z }" + * on the input stream outside of an action. + */ +char * +#ifdef __USE_PROTOS +inline_set(char *s) +#else +inline_set(s) +char *s; +#endif +{ + char *nxt; + fprintf(stderr, "found consumeUntil( {...} )\n"); + while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;} + if ( *s!='{' ) + { + err("malformed consumeUntil( {...} ); missing '{'"); + return "bad_set"; + } + s++; + while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;} + while ( *s!='}' ) + { + if ( match_token(s,&nxt) ) fprintf(stderr, "found token %s\n", s); + else if ( match_rexpr(s,&nxt) ) fprintf(stderr, "found rexpr %s\n", s); + else { + err("invalid element in consumeUntil( {...} )"); + return "bad_set"; + } + s = nxt; + while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;} + } + return "inlineX_set"; +} +>> + +<< +/* ANTLR-specific syntax error message generator + * (define USER_ZZSYN when compiling so don't get 2 definitions) + */ +void +#ifdef __USE_PROTOS +zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, +int k, char *bad_text) +#else +zzsyn(text, tok, egroup, eset, etok, k, bad_text) +char *text, *egroup, *bad_text; +int tok; +int etok; +int k; +SetWordType *eset; +#endif +{ + fprintf(stderr, ErrHdr, FileStr[CurFile]!=NULL?FileStr[CurFile]:"stdin", zzline); + fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text); + if ( !etok && !eset ) {fprintf(stderr, "\n"); return;} + if ( k==1 ) fprintf(stderr, " missing"); + else + { + fprintf(stderr, "; \"%s\" not", bad_text); + if ( zzset_deg(eset)>1 ) fprintf(stderr, " in"); + } + if ( zzset_deg(eset)>0 ) zzedecode(eset); + else fprintf(stderr, " %s", zztokens[etok]); + if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup); + fprintf(stderr, "\n"); +} +>> + +#lexaction << +#ifdef __USE_PROTOS +void mark_label_used_in_sem_pred(LabelEntry *le) /* MR10 */ +#else +void mark_label_used_in_sem_pred(le) /* MR10 */ + LabelEntry *le; +#endif +{ + TokNode *tn; + require (le->elem->ntype == nToken,"mark_label_used... ntype != nToken"); + tn=(TokNode *)le->elem; + require (tn->label != 0,"mark_label_used... TokNode has no label"); + tn->label_used_in_semantic_pred=1; +} +>> diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.r b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.r new file mode 100644 index 00000000..60d4d9d4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr.r @@ -0,0 +1,787 @@ +/* + File: antlrMPW.r + Target: antlr 133MR + Created: Monday, June 15, 1998 4:41:11 AM + Author: Kenji Tanaka (kentar@osa.att.ne.jp) +*/ + +#include "cmdo.r" + +resource 'cmdo' (128, "Antlr") { + { /* array dialogs: 5 elements */ + /* [1] */ + 295, + "ANTLR -- Purdue Compiler Construction To" + "ol Set (PCCTS) LL(k) parser generator.", + { /* array itemArray: 12 elements */ + /* [1] */ + NotDependent { + + }, + CheckOption { + NotSet, + {18, 23, 33, 223}, + "Read grammar from stdin", + "-", + "Read grammar from stdin." + }, + /* [2] */ + NotDependent { + + }, + CheckOption { + NotSet, + {38, 23, 53, 310}, + "Send grammar.c/grammar.cpp to stdout", + "-stdout", + "Send grammar.c/grammar.cpp to stdout." + }, + /* [3] */ + NotDependent { + + }, + MultiFiles { + "Grammar File(s)É", + "Choose the grammar specification files y" + "ou wish to have ANTLR process.", + {79, 22, 98, 152}, + "Grammar specification:", + "", + MultiInputFiles { + { /* array MultiTypesArray: 1 elements */ + /* [1] */ + text + }, + ".g", + "Files ending in .g", + "All text files" + } + }, + /* [4] */ + NotDependent { + + }, + Files { + DirOnly, + OptionalFile { + {58, 168, 74, 298}, + {79, 169, 98, 299}, + "Output Directory", + ":", + "-o", + "", + "Choose the directory where ANTLR will pu" + "t its output.", + dim, + "Output DirectoryÉ", + "", + "" + }, + NoMore { + + } + }, + /* [5] */ + NotDependent { + + }, + Redirection { + StandardOutput, + {126, 27} + }, + /* [6] */ + NotDependent { + + }, + Redirection { + DiagnosticOutput, + {126, 178} + }, + /* [7] */ + NotDependent { + + }, + TextBox { + gray, + {117, 20, 167, 300}, + "Redirection" + }, + /* [8] */ + NotDependent { + + }, + NestedDialog { + 5, + {20, 324, 40, 460}, + "Parse OptionsÉ", + "Parse control options may be set with th" + "is button." + }, + /* [9] */ + NotDependent { + + }, + NestedDialog { + 2, + {50, 324, 70, 460}, + "Generate OptionsÉ", + "Various command line options may be set " + "with this button." + }, + /* [10] */ + NotDependent { + + }, + NestedDialog { + 3, + {78, 324, 98, 460}, + "More OptionsÉ", + "Antlr has ALOT of options. There are eve" + "n more to be found with this button." + }, + /* [11] */ + NotDependent { + + }, + NestedDialog { + 4, + {106, 324, 126, 460}, + "Rename OptionsÉ", + "Options for renaming output files may be" + " set with this button." + }, + /* [12] */ + NotDependent { + + }, + VersionDialog { + VersionString { + "1.33MR" + }, + "PCCTS was written by Terence Parr, Russe" + "ll Quong, Will Cohen, and Hank Dietz: 19" + "89-1998. MPW port by Scott Haney.", + noDialog + } + }, + /* [2] */ + 295, + "Use this dialog to specify command line " + "Generate Options.", + { /* array itemArray: 15 elements */ + /* [1] */ + NotDependent { + + }, + CheckOption { + NotSet, + {18, 25, 33, 225}, + "Generate C++ code", + "-CC", + "Generate C++ output from both ANTLR and " + "DLG." + }, + /* [2] */ + NotDependent { + + }, + CheckOption { + NotSet, + {38, 25, 53, 225}, + "Generate ASTs", + "-gt", + "Generate code for Abstract-Syntax-Trees " + "(ASTs)." + }, + /* [3] */ + NotDependent { + + }, + CheckOption { + NotSet, + {58, 25, 73, 225}, + "Generate line info", + "-gl", + "If this option is checked, ANTLR will ge" + "nerate line info about grammaractions, t" + "hereby making debugging easier since com" + "pile errors will point to the grammar fi" + "le." + }, + /* [4] */ + NotDependent { + + }, + CheckOption { + NotSet, + {78, 25, 93, 225}, + "Generate error classes", + "-ge", + "If this option is checked, ANTLR will ge" + "nerate an error class foreach non-termin" + "al." + }, + /* [5] */ + NotDependent { + + }, + CheckOption { + NotSet, + {98, 25, 113, 225}, + "Don't generate Code", + "-gc", + "If this option is checked, ANTLR will ge" + "nerate no code, i.e. it will only perfor" + "m analysis on the grammar." + }, + /* [6] */ + NotDependent { + + }, + CheckOption { + NotSet, + {118, 25, 133, 225}, + "Delay lookahead fetches", + "-gk", + "If this option is checked, ANTLR will ge" + "nerate a parser that delays lookahead fe" + "tches until needed." + }, + /* [7] */ + NotDependent { + + }, + CheckOption { + NotSet, + {138, 25, 153, 225}, + "Use newAST(...)", + "-newAST", + "In C++ mode use \"newAST(...)\" rather tha" + "n \"new AST(...)\"" + }, + /* [8] */ + NotDependent { + + }, + CheckOption { + NotSet, + {18, 235, 33, 435}, + "Support parse traces", + "-gd", + "If this option is checked, ANTLR inserts" + " code in each parsing function to provid" + "e for user-defined handling of a detaile" + "d parse trace. The code consists of call" + "s to zzTRACEIN and zzTRACEOUT." + }, + /* [9] */ + NotDependent { + + }, + CheckOption { + NotSet, + {38, 235, 53, 435}, + "Generate cross-references", + "-cr", + "If this option is checked, ANTLR will ge" + "nerate a cross reference for all rules. " + "For each rule it will print a list of al" + "l other rules that reference it." + }, + /* [10] */ + NotDependent { + + }, + CheckOption { + NotSet, + {58, 235, 73, 435}, + "Don't create Lexer files", + "-gx", + "If this option is checked, ANTLR will no" + "t generate DLG-related output files. Thi" + "s option should be used if one wants a c" + "ustom lexical analyzer or if one has mad" + "e changes to the grammar not affecting t" + "he lexical structure." + }, + /* [11] */ + NotDependent { + + }, + CheckOption { + NotSet, + {78, 235, 93, 460}, + "Don't generate token expr sets", + "-gs", + "If this option is checked, ANTLR will no" + "t generate sets for token expression set" + "s; instead, it will generate a || separa" + "ted sequence of LA(1)==token #. " + }, + /* [12] */ + NotDependent { + + }, + CheckOption { + NotSet, + {98, 235, 113, 460}, + "Generate ANSI-compatible", + "-ga", + "Generate ANSI-compatible code (default=F" + "ALSE)" + }, + /* [13] */ + NotDependent { + + }, + CheckOption { + NotSet, + {118, 235, 133, 460}, + "Don't generate tokens.h", + "-gxt", + "Do not generate tokens.h (default=FALSE)" + }, + /* [13] */ + NotDependent { + + }, + CheckOption { + NotSet, + {138, 235, 153, 460}, + "Provide \"(alpha)? beta\" info", + "-alpha", + "Provide additional information for \"(alpha)? beta\" error messages" + }, + /* [14] */ + NotDependent { + + }, + RegularEntry { + "Tabs(1 to 8):", + {162, 23, 177, 117}, + {163, 125, 179, 196}, + "", + keepCase, + "-tab", + "Width of tabs (1 to 8) for grammar.c/gra" + "mmar.cpp files." + }, + /* [15] */ + NotDependent { + + }, + RegularEntry { + "Function Prefix:", + {161, 236, 177, 342}, + {162, 345, 177, 454}, + "", + keepCase, + "-gp", + "Prefix all generated rule functions with" + " a string." + } + }, + /* [3] */ + 295, + "Use this dialog to specify still more co" + "mmand line options.", + { /* array itemArray: 12 elements */ + /* [1] */ + NotDependent { + + }, + RadioButtons { + { /* array radioArray: 3 elements */ + /* [1] */ + {38, 25, 53, 85}, "None", "", Set, "When this option is selected, ANTLR will" + " not print the grammar to stdout.", + /* [2] */ + {38, 100, 53, 160}, "Yes", "-p", NotSet, "When this option is selected, ANTLR will" + " print the grammar, stripped of all acti" + "ons and comments, to stdout.", + /* [3] */ + {38, 175, 53, 235}, "More", "-pa", NotSet, "When this option is selected, ANTLR will" + " print the grammar, stripped of all acti" + "ons and comments, to stdout. It will als" + "o annotate the output with the first set" + "s determined from grammar analysis." + } + }, + /* [2] */ + NotDependent { + + }, + TextBox { + gray, + {28, 15, 60, 250}, + "Grammar Printing" + }, + /* [3] */ + NotDependent { + + }, + RadioButtons { + { /* array radioArray: 3 elements */ + /* [1] */ + {88, 25, 103, 85}, "Low", "", Set, "When this option is selected, ANTLR will" + " show ambiguities/errors in low detail.", + /* [2] */ + {88, 100, 103, 160}, "Medium", "-e2", NotSet, "When this option is selected, ANTLR will" + " show ambiguities/errors in more detail.", + /* [3] */ + {88, 175, 103, 235}, "High", "-e3", NotSet, "When this option is selected, ANTLR will" + " show ambiguities/errors in excruciating" + " detail." + } + }, + /* [4] */ + NotDependent { + + }, + TextBox { + gray, + {78, 15, 110, 250}, + "Error reporting" + }, + /* [5] */ + NotDependent { + + }, + CheckOption { + NotSet, + {130, 22, 145, 222}, + "More warnings", + "-w2", + "If this option is checked, ANTLR will wa" + "rn if semantic predicates and/or (É)? bl" + "ocks are assumed to cover ambiguous alte" + "rnatives." + }, + /* [6] */ + NotDependent { + + }, + RegularEntry { + "Report when tnode usage exceeds:", + {162, 23, 180, 253}, + {162, 255, 178, 326}, + "", + keepCase, + "-treport", + "Report when tnode usage exceeds value du" + "ring ambiguity resolution." + }, + /* [7] */ + NotDependent { + + }, + CheckOption { + NotSet, + {40, 292, 55, 431}, + "Predicate", + "-info p", + "With the antlr \"-info p\" switch the user" + " will receive information about the pred" + "icate suppression in the generated file." + }, + /* [8] */ + NotDependent { + + }, + CheckOption { + NotSet, + {60, 292, 75, 430}, + "Tree Nodes", + "-info t", + "Using \"-info t\" gives information about " + "the total number of tnodes created and t" + "he peak number of tnodes." + }, + /* [9] */ + NotDependent { + + }, + CheckOption { + NotSet, + {80, 292, 95, 425}, + "First/follow", + "-info f", + "first/follow set information." + }, + /* [10] */ + NotDependent { + + }, + CheckOption { + NotSet, + {100, 292, 115, 425}, + "Monitor progress", + "-info m", + "prints name of each rule as it is starte" + "d and flushes output at start of each rule." + }, + /* [11] */ + NotDependent { + + }, + CheckOption { + NotSet, + {120, 292, 135, 416}, + "Orphan rules", + "-info o", + "If there is more than one rule which is " + "not referenced by any other rule then al" + "l such rules are listed." + }, + /* [12] */ + NotDependent { + + }, + TextBox { + gray, + {28, 279, 147, 451}, + "Extra info" + } + }, + /* [4] */ + 295, + "Use this dialog to specify command line " + "options relating to renaming output file" + "s.", + { /* array itemArray: 7 elements */ + /* [1] */ + NotDependent { + + }, + RegularEntry { + "Errors file name:", + {35, 25, 50, 205}, + {35, 205, 51, 300}, + "err.c", + keepCase, + "-fe", + "This entry specifies the name ANTLR uses" + " for the errors file." + }, + /* [2] */ + NotDependent { + + }, + RegularEntry { + "Lexical output name:", + {60, 25, 75, 205}, + {60, 205, 76, 300}, + "parser.dlg", + keepCase, + "-fl", + "This entry specifies the name ANTLR uses" + " for the lexical output file." + }, + /* [3] */ + NotDependent { + + }, + RegularEntry { + "Lexical modes name:", + {85, 25, 100, 205}, + {85, 205, 101, 300}, + "mode.h", + keepCase, + "-fm", + "This entry specifies the name ANTLR uses" + " for the lexical mode definitions file." + }, + /* [4] */ + NotDependent { + + }, + RegularEntry { + "Remap file name:", + {110, 25, 125, 205}, + {110, 205, 126, 300}, + "remap.h", + keepCase, + "-fr", + "This entry specifies the name ANTLR uses" + " for the file that remaps globally visib" + "le symbols." + }, + /* [5] */ + NotDependent { + + }, + RegularEntry { + "Tokens file name:", + {135, 25, 150, 205}, + {135, 205, 151, 300}, + "tokens.h", + keepCase, + "-ft", + "This entry specifies the name ANTLR uses" + " for the tokens file." + }, + /* [6] */ + NotDependent { + + }, + CheckOption { + NotSet, + {160, 25, 175, 175}, + "Create std header", + "-gh", + "If this option is checked, ANTLR will cr" + "eate a standard header file named, by de" + "fault 'stdpccts.h'. This name can be alt" + "ered using the entry right next door." + }, + /* [7] */ + Or { + { /* array OrArray: 1 elements */ + /* [1] */ + 6 + } + }, + RegularEntry { + "Std header file name:", + {160, 175, 175, 355}, + {160, 355, 176, 450}, + "stdpccts.h", + keepCase, + "-fh", + "This entry specifies the name ANTLR uses" + " for the standard header file." + } + }, + /* [5] */ + 295, + "Use this dialog to specify parse options" + ".", + { /* array itemArray: 9 elements */ + /* [1] */ + NotDependent { + + }, + RegularEntry { + "Lookahead:", + {23, 27, 38, 152}, + {46, 29, 62, 154}, + "1", + keepCase, + "-k", + "This entry specifies the number of token" + "s of lookahead." + }, + /* [2] */ + NotDependent { + + }, + RegularEntry { + "Compr lookahead:", + {22, 167, 37, 292}, + {46, 172, 62, 297}, + "", + keepCase, + "-ck", + "This entry specifies the number of token" + "s of lookahead when using compressed (li" + "near approximation) lookahead. In genera" + "l, the compressed lookahead is much deep" + "er than the full lookahead." + }, + /* [3] */ + NotDependent { + + }, + RegularEntry { + "Max tree nodes:", + {22, 312, 37, 437}, + {46, 315, 62, 445}, + "", + keepCase, + "-rl", + "This entry specifies the maximum number " + "of tokens of tree nodes used by the gram" + "mar analysis." + }, + /* [4] */ + NotDependent { + + }, + CheckOption { + NotSet, + {76, 25, 91, 350}, + "Maintenance Release style hoisting", + "-mrhoist", + "Turn on/off k=1 Maintenance Release styl" + "e hoisting." + }, + /* [5] */ + NotDependent { + + }, + CheckOption { + NotSet, + {96, 25, 111, 431}, + "EXPERIMENTAL Maintenance Release style h" + "oisting", + "-mrhoistk", + "Turn on/off k>1 EXPERIMENTAL Maintenance" + " Release style hoisting." + }, + /* [6] */ + NotDependent { + + }, + CheckOption { + NotSet, + {116, 25, 131, 363}, + "Compute context for hoisted predicates", + "-prc on", + "Turn on/off computation of context for h" + "oisted predicates." + }, + /* [7] */ + NotDependent { + + }, + RegularEntry { + "Ambiguity aid:", + {140, 27, 155, 125}, + {141, 135, 155, 209}, + "", + keepCase, + "-aa", + "Ambiguity aid for a rule (rule name or l" + "ine number)." + }, + /* [8] */ + NotDependent { + + }, + RegularEntry { + "Limits exp growth:", + {140, 236, 155, 361}, + {139, 372, 155, 452}, + "", + keepCase, + "-aad", + "Limits exp growth of -aa listing - defau" + "lt=1 (max=ck value)." + }, + /* [9] */ + NotDependent { + + }, + CheckOption { + NotSet, + {164, 26, 179, 366}, + "Lookahead token may appear multiple time" + "s", + "-aam", + "Lookahead token may appear multiple time" + "s in -aa listing." + } + } + } +}; + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr1.txt b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr1.txt new file mode 100644 index 00000000..4545275e --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr1.txt @@ -0,0 +1,264 @@ + + + +ANTLR(1) PCCTS Manual Pages ANTLR(1) + + + +NAME + antlr - ANother Tool for Language Recognition + +SYNTAX + antlr [_o_p_t_i_o_n_s] _g_r_a_m_m_a_r__f_i_l_e_s + +DESCRIPTION + _A_n_t_l_r converts an extended form of context-free grammar into + a set of C functions which directly implement an efficient + form of deterministic recursive-descent LL(k) parser. + Context-free grammars may be augmented with predicates to + allow semantics to influence parsing; this allows a form of + context-sensitive parsing. Selective backtracking is also + available to handle non-LL(k) and even non-LALR(k) con- + structs. _A_n_t_l_r also produces a definition of a lexer which + can be automatically converted into C code for a DFA-based + lexer by _d_l_g. Hence, _a_n_t_l_r serves a function much like that + of _y_a_c_c, however, it is notably more flexible and is more + integrated with a lexer generator (_a_n_t_l_r directly generates + _d_l_g code, whereas _y_a_c_c and _l_e_x are given independent + descriptions). Unlike _y_a_c_c which accepts LALR(1) grammars, + _a_n_t_l_r accepts LL(k) grammars in an extended BNF notation - + which eliminates the need for precedence rules. + + Like _y_a_c_c grammars, _a_n_t_l_r grammars can use automatically- + maintained symbol attribute values referenced as dollar + variables. Further, because _a_n_t_l_r generates top-down + parsers, arbitrary values may be inherited from parent rules + (passed like function parameters). _A_n_t_l_r also has a mechan- + ism for creating and manipulating abstract-syntax-trees. + + There are various other niceties in _a_n_t_l_r, including the + ability to spread one grammar over multiple files or even + multiple grammars in a single file, the ability to generate + a version of the grammar with actions stripped out (for + documentation purposes), and lots more. + +OPTIONS + -ck _n + Use up to _n symbols of lookahead when using compressed + (linear approximation) lookahead. This type of looka- + head is very cheap to compute and is attempted before + full LL(k) lookahead, which is of exponential complex- + ity in the worst case. In general, the compressed loo- + kahead can be much deeper (e.g, -ck 10) _t_h_a_n _t_h_e _f_u_l_l + _l_o_o_k_a_h_e_a_d (_w_h_i_c_h _u_s_u_a_l_l_y _m_u_s_t _b_e _l_e_s_s _t_h_a_n _4). + + -CC Generate C++ output from both ANTLR and DLG. + + -cr Generate a cross-reference for all rules. For each + rule, print a list of all other rules that reference + it. + + -e1 Ambiguities/errors shown in low detail (default). + + -e2 Ambiguities/errors shown in more detail. + + -e3 Ambiguities/errors shown in excruciating detail. + + -fe file + Rename err.c to file. + + -fh file + Rename stdpccts.h header (turns on -gh) to file. + + -fl file + Rename lexical output, parser.dlg, to file. + + -fm file + Rename file with lexical mode definitions, mode.h, to + file. + + -fr file + Rename file which remaps globally visible symbols, + remap.h, to file. + + -ft file + Rename tokens.h to file. + + -ga Generate ANSI-compatible code (default case). This has + not been rigorously tested to be ANSI XJ11 C compliant, + but it is close. The normal output of _a_n_t_l_r is + currently compilable under both K&R, ANSI C, and C++- + this option does nothing because _a_n_t_l_r generates a + bunch of #ifdef's to do the right thing depending on + the language. + + -gc Indicates that _a_n_t_l_r should generate no C code, i.e., + only perform analysis on the grammar. + + -gd C code is inserted in each of the _a_n_t_l_r generated pars- + ing functions to provide for user-defined handling of a + detailed parse trace. The inserted code consists of + calls to the user-supplied macros or functions called + zzTRACEIN and zzTRACEOUT. The only argument is a _c_h_a_r + * pointing to a C-style string which is the grammar + rule recognized by the current parsing function. If no + definition is given for the trace functions, upon rule + entry and exit, a message will be printed indicating + that a particular rule as been entered or exited. + + -ge Generate an error class for each non-terminal. + + -gh Generate stdpccts.h for non-ANTLR-generated files to + include. This file contains all defines needed to + describe the type of parser generated by _a_n_t_l_r (e.g. + how much lookahead is used and whether or not trees are + constructed) and contains the header action specified + by the user. + + -gk Generate parsers that delay lookahead fetches until + needed. Without this option, _a_n_t_l_r generates parsers + which always have _k tokens of lookahead available. + + -gl Generate line info about grammar actions in C parser of + the form # _l_i_n_e "_f_i_l_e" which makes error messages from + the C/C++ compiler make more sense as they will point + into the grammar file not the resulting C file. + Debugging is easier as well, because you will step + through the grammar not C file. + + -gs Do not generate sets for token expression lists; + instead generate a ||-separated sequence of + LA(1)==_t_o_k_e_n__n_u_m_b_e_r. The default is to generate sets. + + -gt Generate code for Abstract-Syntax Trees. + + -gx Do not create the lexical analyzer files (dlg-related). + This option should be given when the user wishes to + provide a customized lexical analyzer. It may also be + used in _m_a_k_e scripts to cause only the parser to be + rebuilt when a change not affecting the lexical struc- + ture is made to the input grammars. + + -k _n Set k of LL(k) to _n; i.e. set tokens of look-ahead + (default==1). + + -o dir + Directory where output files should go (default="."). + This is very nice for keeping the source directory + clear of ANTLR and DLG spawn. + + -p The complete grammar, collected from all input grammar + files and stripped of all comments and embedded + actions, is listed to stdout. This is intended to aid + in viewing the entire grammar as a whole and to elim- + inate the need to keep actions concisely stated so that + the grammar is easier to read. Hence, it is preferable + to embed even complex actions directly in the grammar, + rather than to call them as subroutines, since the sub- + routine call overhead will be saved. + + -pa This option is the same as -p except that the output is + annotated with the first sets determined from grammar + analysis. + + -prc on + Turn on the computation and hoisting of predicate con- + text. + + -prc off + Turn off the computation and hoisting of predicate con- + text. This option makes 1.10 behave like the 1.06 + release with option -pr on. Context computation is off + by default. + + -rl _n + Limit the maximum number of tree nodes used by grammar + analysis to _n. Occasionally, _a_n_t_l_r is unable to + analyze a grammar submitted by the user. This rare + situation can only occur when the grammar is large and + the amount of lookahead is greater than one. A non- + linear analysis algorithm is used by PCCTS to handle + the general case of LL(k) parsing. The average com- + plexity of analysis, however, is near linear due to + some fancy footwork in the implementation which reduces + the number of calls to the full LL(k) algorithm. An + error message will be displayed, if this limit is + reached, which indicates the grammar construct being + analyzed when _a_n_t_l_r hit a non-linearity. Use this + option if _a_n_t_l_r seems to go out to lunch and your disk + start thrashing; try _n=10000 to start. Once the + offending construct has been identified, try to remove + the ambiguity that _a_n_t_l_r was trying to overcome with + large lookahead analysis. The introduction of (...)? + backtracking blocks eliminates some of these problems - + _a_n_t_l_r does not analyze alternatives that begin with + (...)? (it simply backtracks, if necessary, at run + time). + + -w1 Set low warning level. Do not warn if semantic + predicates and/or (...)? blocks are assumed to cover + ambiguous alternatives. + + -w2 Ambiguous parsing decisions yield warnings even if + semantic predicates or (...)? blocks are used. Warn if + predicate context computed and semantic predicates + incompletely disambiguate alternative productions. + + - Read grammar from standard input and generate stdin.c + as the parser file. + +SPECIAL CONSIDERATIONS + _A_n_t_l_r works... we think. There is no implicit guarantee of + anything. We reserve no legal rights to the software known + as the Purdue Compiler Construction Tool Set (PCCTS) - PCCTS + is in the public domain. An individual or company may do + whatever they wish with source code distributed with PCCTS + or the code generated by PCCTS, including the incorporation + of PCCTS, or its output, into commercial software. We + encourage users to develop software with PCCTS. However, we + do ask that credit is given to us for developing PCCTS. By + "credit", we mean that if you incorporate our source code + into one of your programs (commercial product, research pro- + ject, or otherwise) that you acknowledge this fact somewhere + in the documentation, research report, etc... If you like + PCCTS and have developed a nice tool with the output, please + mention that you developed it using PCCTS. As long as these + guidelines are followed, we expect to continue enhancing + this system and expect to make other tools available as they + are completed. + +FILES + *.c output C parser. + + *.cpp + output C++ parser when C++ mode is used. + + parser.dlg + output _d_l_g lexical analyzer. + + err.c + token string array, error sets and error support rou- + tines. Not used in C++ mode. + + remap.h + file that redefines all globally visible parser sym- + bols. The use of the #parser directive creates this + file. Not used in C++ mode. + + stdpccts.h + list of definitions needed by C files, not generated by + PCCTS, that reference PCCTS objects. This is not gen- + erated by default. Not used in C++ mode. + + tokens.h + output #_d_e_f_i_n_e_s for tokens used and function prototypes + for functions generated for rules. + + +SEE ALSO + dlg(1), pccts(1) + + + + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/bits.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/bits.c new file mode 100644 index 00000000..3a466fc1 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/bits.c @@ -0,0 +1,1025 @@ +/* bits.c -- manage creation and output of bit sets used by the parser. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include +#include +#include +#include "pcctscfg.h" +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" + +/* char is only thing that is pretty much always known == 8 bits + * This allows output of antlr (set stuff, anyway) to be androgynous (portable) + */ +typedef unsigned char SetWordType; +#define BitsPerByte 8 +#define BitsPerWord BitsPerByte*sizeof(SetWordType) + +static SetWordType *setwd = NULL; +int setnum = -1; +int wordnum = 0; + +int esetnum = 0; + +/* Used to convert native wordsize, which ANTLR uses (via set.c) to manipulate sets, + to bytes that are most portable size-wise. + */ +void +#ifdef __USE_PROTOS +DumpIntAsChars( FILE *f, char *format, unsigned wd ) +#else +DumpIntAsChars( f, format, wd ) +FILE *f; +char *format; +unsigned wd; +#endif +{ + int i; + /* uses max of 32 bit unsigned integer for the moment */ + static unsigned long byte_mask[sizeof(unsigned long)] = + { 0xFF, 0xFF00UL, 0xFF0000UL, 0xFF000000UL }; /* MR20 G. Hobbelt */ +/* 0xFF00000000, 0xFF0000000000, 0xFF000000000000, 0xFF00000000000000 };*/ + + /* for each byte in the word */ + assert(sizeof(unsigned) <= 4); /* M20 G. Hobbelt Sanity check */ + for (i=0; i>(i*BitsPerByte)); + if ( itok))); + return empty; + } + r = RulePtr[q->rulenum]; + r->end->halt = TRUE; /* don't let reach fall off end of rule here */ + rk = empty; + REACH(r, 1, &rk, a); + r->end->halt = FALSE; + return a; +} + +/* + * scan the list of tokens/eclasses/nonterminals filling the new eclass + * with the set described by the list. Note that an eclass can be + * quoted to allow spaces etc... However, an eclass must not conflict + * with a reg expr found elsewhere. The reg expr will be taken over + * the eclass name. + */ +static void +#ifdef __USE_PROTOS +doEclass( char *eclass ) +#else +doEclass( eclass ) +char *eclass; +#endif +{ + TermEntry *q; + ECnode *p; + TCnode *tcnode; + ListNode *e; + unsigned int t; + unsigned deg=0; + set a; + require(eclass!=NULL, "doEclass: NULL eset"); + + p = (ECnode *) eclass; + lexmode(p->lexclass); /* switch to lexclass where errclass is defined */ + p->eset = empty; + for (e = (p->elist)->next; e!=NULL; e=e->next) + { + q = NULL; /* MR23 */ + + if ( islower( *((char *)e->elem) ) ) /* is it a rule ref? (alias FIRST request) */ + { + a = Efirst((char *)e->elem, p); + set_orin(&p->eset, a); + deg += set_deg(a); + set_free( a ); + continue; + } + else if ( *((char *)e->elem)=='"' ) + { + t = 0; + q = (TermEntry *) hash_get(Texpr, (char *) e->elem); + if ( q == NULL ) + { + /* if quoted and not an expr look for eclass name */ + q = (TermEntry *) hash_get(Tname, *((char **)&(e->elem))=StripQuotes((char *)e->elem)); + if ( q != NULL ) t = q->token; + } + else t = q->token; + } + else /* labelled token/eclass/tokclass */ + { + q = (TermEntry *) hash_get(Tname, (char *)e->elem); + if ( q != NULL ) + { + if ( strcmp((char *)e->elem, TokenString(p->tok))==0 ) + { + warnNoFL(eMsg1("self-referential error class '%s'; ignored", + (char *)e->elem)); + continue; + } + else + t = q->token; + } + else t=0; + } + if ( t!=0 ) + { + if (isTermEntryTokClass(q)) { /* MR23 */ + tcnode = q->tclass; /* MR23 */ + set_orin(&p->eset, tcnode->tset); /* MR23 */ + deg = set_deg(p->eset); /* MR23 */ + } /* MR23 */ + else { + set_orel(t, &p->eset); + deg++; + } + } + else warnNoFL(eMsg2("undefined token '%s' referenced in errclass '%s'; ignored", + (char *)e->elem, TokenString(p->tok))); + } + p->setdeg = deg; +} + +void +#ifdef __USE_PROTOS +ComputeErrorSets( void ) +#else +ComputeErrorSets( ) +#endif +{ +#ifdef __cplusplus + list_apply(eclasses, (void (*)(void *)) doEclass); +#else +#ifdef __USE_PROTOS + list_apply(eclasses, (void (*)(void *)) doEclass); +#else + list_apply(eclasses, doEclass); +#endif +#endif +} + +void +#ifdef __USE_PROTOS +ComputeTokSets( void ) +#else +ComputeTokSets( ) +#endif +{ + ListNode *t, *e = NULL, *e1, *e2; + int something_changed; + int i; + TCnode *p; + TermEntry *q, *q1, *q2; + + if ( tclasses == NULL ) return; + + /* turn lists of token/tokclass references into sets */ + for (t = tclasses->next; t!=NULL; t=t->next) + { + p = (TCnode *) t->elem; + + /* if wild card, then won't have entries in tclass, assume all_tokens */ + if ( p->tok == WildCardToken ) + { + p->tset = set_dup(all_tokens); + continue; + } + + lexmode(p->lexclass); /* switch to lexclass where tokclass is defined */ + p->tset = empty; + + /* instantiate all tokens/token_classes into the tset */ + for (e = (p->tlist)->next; e!=NULL; e=e->next) + { + char *tokstr; + tokstr = (char *)e->elem; + if ( *tokstr == '"' ) { + q = (TermEntry *) hash_get(Texpr, tokstr); + require(q!=NULL, "ComputeTokSets: no token def"); + set_orel(q->token, &p->tset); + } else if (tokstr[0] == '.') { + e1=e->next; + e2=e1->next; + e=e2; + q1= (TermEntry *) hash_get(Tname, (char *)e1->elem); + require(q1!=NULL, "ComputeTokSets: no token def"); + q2= (TermEntry *) hash_get(Tname, (char *)e2->elem); + require(q2!=NULL, "ComputeTokSets: no token def"); + + if (set_el(q1->token,imag_tokens)) { +errNoFL(eMsg2("can't define #tokclass %s using #tokclass or #errclass %s", + TokenString(p->tok),(char *)e1->elem) ); + } + if (set_el(q2->token,imag_tokens)) { +errNoFL(eMsg2("can't define #tokclass %s using #tokclass or #errclass %s", + TokenString(p->tok),(char *)e2->elem) ); + } + if (q1->token > q2->token) { +errNoFL(eMsg3("for #tokclass %s %s..%s - first token number > second token number", + TokenString(p->tok),(char *)e1->elem,(char *)e2->elem) ); + for (i=q2->token; i<=q1->token; i++) { set_orel(i, &p->tset); } + } else { + for (i=q1->token; i<=q2->token; i++) { set_orel(i, &p->tset); } + } + } else { + q = (TermEntry *) hash_get(Tname, tokstr); + require(q!=NULL, "ComputeTokSets: no token def"); + set_orel(q->token, &p->tset); + } + } + } + + /* Go thru list of tokclasses again looking for tokclasses in sets */ +again: + something_changed = 0; + for (t = tclasses->next; t!=NULL; t=t->next) + { + set tcl; + p = (TCnode *) t->elem; + tcl = set_and(p->tset, tokclasses); + if ( !set_nil(tcl) ) + { + int tk; + /* replace refs to tokclasses with the associated set of tokens */ + something_changed = 1; + while ( !set_nil(tcl) ) + { + tk = set_int(tcl); /* grab one of the tok class refs */ + set_rm(tk, tcl); + if ( p->tok != tk ) /* tokclass ref to yourself? */ + { + q = (TermEntry *) hash_get(Tname, TokenString(tk)); + require(q!=NULL, "#tokclass not in hash table"); + set_orin(&p->tset, q->tclass->tset); + } + set_rm(tk, p->tset); /* remove ref that we replaced */ + } + } + set_free(tcl); + } + if ( something_changed ) goto again; +} + +void +#ifdef __USE_PROTOS +DumpRemainingTokSets(void) +#else +DumpRemainingTokSets() +#endif +{ + TCnode *p; + ListNode *t; + + /* Go thru tclasses (for the last time) and dump the sets not dumped + * during code gen; yes, this is a bogus way to do this, but ComputeTokSets() + * can't dump the defs as the error file and tok file has not been created + * yet etc... + */ + if ( tclasses==NULL ) return; + for (t = tclasses->next; t!=NULL; t=t->next) + { + unsigned e; + p = (TCnode *) t->elem; + if ( p->dumped ) continue; + e = DefErrSet(&(p->tset), 0, TokenString(p->tok)); + p->dumped = 1; + p->setnum = e; + } +} + + +/* replace a subset of an error set with an error class name if a subset is found + * repeat process until no replacements made + */ +void +#ifdef __USE_PROTOS +SubstErrorClass( set *f ) +#else +SubstErrorClass( f ) +set *f; +#endif +{ + int max, done = 0; + ListNode *p; + ECnode *ec, *maxclass = NULL; + set a; + require(f!=NULL, "SubstErrorClass: NULL eset"); + + if ( eclasses == NULL ) return; + while ( !done ) + { + max = 0; + maxclass = NULL; + for (p=eclasses->next; p!=NULL; p=p->next) /* chk all error classes */ + { + ec = (ECnode *) p->elem; + if ( ec->setdeg > max ) + { + if ( set_sub(ec->eset, *f) || set_equ(ec->eset, *f) ) + {maxclass = ec; max=ec->setdeg;} + } + } + if ( maxclass != NULL ) /* if subset found, replace with token */ + { + a = set_dif(*f, maxclass->eset); + set_orel((unsigned)maxclass->tok, &a); + set_free(*f); + *f = a; + } + else done = 1; + } +} + +int +#ifdef __USE_PROTOS +DefErrSet1(int nilOK, set *f, int subst, char *name ) +#else +DefErrSet1(nilOK, f, subst, name ) +int nilOK; +set *f; +int subst; /* should be substitute error classes? */ +char *name; +#endif +{ + if ( GenCC ) return DefErrSetForCC1(nilOK, f, subst, name, "_set"); + else return DefErrSetForC1(nilOK, f, subst, name, "_set"); +} + +int +#ifdef __USE_PROTOS +DefErrSet( set *f, int subst, char *name ) +#else +DefErrSet( f, subst, name ) +set *f; +int subst; /* should be substitute error classes? */ +char *name; +#endif +{ + return DefErrSet1(0,f,subst,name); +} + +int +#ifdef __USE_PROTOS +DefErrSetWithSuffix(int nilOK, set *f, int subst, char *name, const char* suffix) +#else +DefErrSetWithSuffix(nilOK, f, subst, name, suffix ) +int nilOK; +set *f; +int subst; /* should be substitute error classes? */ +char *name; +char *suffix; +#endif +{ + if ( GenCC ) return DefErrSetForCC1(nilOK, f, subst, name, suffix ); + else return DefErrSetForC1(nilOK, f, subst, name, suffix); +} + +/* Define a new error set. WARNING...set-implementation dependent. + */ +int +#ifdef __USE_PROTOS +DefErrSetForC1(int nilOK, set *f, int subst, char * name, const char * suffix) +#else +DefErrSetForC1(nilOK, f, subst, name, suffix) +int nilOK; /* MR13 */ +set *f; +int subst; /* should be substitute error classes? */ +char *name; +const char *suffix; +#endif +{ + unsigned *p, *endp; + int e=1; + + if (!nilOK) require(!set_nil(*f), "DefErrSetForC1: nil set to dump?"); + + if ( subst ) SubstErrorClass(f); + p = f->setword; + endp = &(f->setword[f->n]); + esetnum++; + if ( name!=NULL ) + fprintf(DefFile, "extern SetWordType %s%s[];\n", name, suffix); + else + fprintf(DefFile, "extern SetWordType zzerr%d[];\n", esetnum); + if ( name!=NULL ) { + fprintf(ErrFile, "SetWordType %s%s[%lu] = {", + name, + suffix, + NumWords(TokenNum-1)*sizeof(unsigned)); + } + else { + fprintf(ErrFile, "SetWordType zzerr%d[%lu] = {", + esetnum, + NumWords(TokenNum-1)*sizeof(unsigned)); + } + while ( p < endp ) + { + if ( e > 1 ) fprintf(ErrFile, ", "); + DumpIntAsChars(ErrFile, "0x%x", *p++); + if ( e == 3 ) + { + DAWDLE; + if ( p < endp ) fprintf(ErrFile, ","); + fprintf(ErrFile, "\n\t"); + e=1; + } + else e++; + } + fprintf(ErrFile, "};\n"); + + return esetnum; +} + +int +#ifdef __USE_PROTOS +DefErrSetForC( set *f, int subst, char *name ) +#else +DefErrSetForC( f, subst, name ) +set *f; +int subst; /* should be substitute error classes? */ +char *name; +#endif +{ + return DefErrSetForC1(0,f,subst,name, "_set"); +} + +/* Define a new error set. WARNING...set-implementation dependent; + * Only used when -CC on. + */ + +int +#ifdef __USE_PROTOS +DefErrSetForCC1(int nilOK, set *f, int subst, char *name, const char *suffix ) +#else +DefErrSetForCC1(nilOK, f, subst, name, suffix ) +int nilOK; /* MR13 */ +set *f; +int subst; /* should be substitute error classes? */ +char *name; +const char *suffix; +#endif +{ + unsigned *p, *endp; + int e=1; + + if (!nilOK) require(!set_nil(*f), "DefErrSetForCC1: nil set to dump?"); + + if ( subst ) SubstErrorClass(f); + p = f->setword; + endp = &(f->setword[f->n]); + esetnum++; + + if ( name!=NULL ) { + fprintf(Parser_h, "\tstatic SetWordType %s%s[%lu];\n", name, suffix, + NumWords(TokenNum-1)*sizeof(unsigned)); + fprintf(Parser_c, "SetWordType %s::%s%s[%lu] = {", + CurrentClassName, + name, + suffix, + NumWords(TokenNum-1)*sizeof(unsigned)); + } + else { + fprintf(Parser_c, "SetWordType %s::err%d[%lu] = {", + CurrentClassName, + esetnum, + NumWords(TokenNum-1)*sizeof(unsigned)); + fprintf(Parser_h, "\tstatic SetWordType err%d[%lu];\n", esetnum, + NumWords(TokenNum-1)*sizeof(unsigned)); + } + + while ( p < endp ) + { + if ( e > 1 ) fprintf(Parser_c, ", "); + DumpIntAsChars(Parser_c, "0x%x", *p++); + if ( e == 3 ) + { + if ( p < endp ) fprintf(Parser_c, ","); + fprintf(Parser_c, "\n\t"); + e=1; + } + else e++; + } + fprintf(Parser_c, "};\n"); + + return esetnum; +} + +int +#ifdef __USE_PROTOS +DefErrSetForCC( set *f, int subst, char *name ) +#else +DefErrSetForCC( f, subst, name ) +set *f; +int subst; /* should be substitute error classes? */ +char *name; +#endif +{ + return DefErrSetForCC1(0,f,subst,name, "_set"); +} + +void +#ifdef __USE_PROTOS +GenParser_c_Hdr(void) +#else +GenParser_c_Hdr() +#endif +{ + int i,j; + TermEntry *te; + char * hasAkaName = NULL; /* MR23 */ + + hasAkaName = (char *) malloc(TokenNum+1); /* MR23 */ + require(hasAkaName!=NULL, "Cannot alloc hasAkaName\n"); /* MR23 */ + for (i = 0; i < TokenNum; i++) hasAkaName[i]='0'; /* MR23 */ + hasAkaName[TokenNum] = 0; /* MR23 */ + + fprintf(Parser_c, "/*\n"); + fprintf(Parser_c, " * %s: P a r s e r S u p p o r t\n", CurrentClassName); + fprintf(Parser_c, " *\n"); + fprintf(Parser_c, " * Generated from:"); + for (i=0; i=LastTokenCounted ) + { + fprintf(Parser_c, ",\n\t/* %02d */\t\"invalid\"", i); + continue; + } + if ( TokenString(i) != NULL ) { + te=(TermEntry *) hash_get(Tname,TokenString(i)); /* MR11 */ + if (te == NULL || te->akaString == NULL) { /* MR11 */ + fprintf(Parser_c, ",\n\t/* %02d */\t\"%s\"", i, TokenString(i)); + } else { + hasAkaName[i] = '1'; /* MR23 */ + fprintf(Parser_c, ",\n\t/* %02d */\t\"%s\"", i, te->akaString); /* MR11 */ + } + } + else + { + /* look in all lexclasses for the reg expr */ + for (j=0; j=NumLexClasses ) + { + if ( UserDefdTokens ) + { + fprintf(Parser_c, ",\n\t/* %02d */\t\"\"", i); + } + else + fatal_internal(eMsgd("No label or expr for token %d",i)); + } + } + } + fprintf(Parser_c, "\n};\n"); + + /* Build constructors */ + fprintf(Parser_c, "\n%s::", CurrentClassName); + fprintf(Parser_c, "%s(ANTLRTokenBuffer *input) : %s(input,%d,%d,%d,%lu)\n", + CurrentClassName, + (BaseClassName == NULL ? "ANTLRParser" : BaseClassName), + OutputLL_k, + FoundGuessBlk, + DemandLookahead, + NumWords(TokenNum-1)*sizeof(unsigned)); + fprintf(Parser_c, "{\n"); + fprintf(Parser_c, "\ttoken_tbl = _token_tbl;\n"); + if (TraceGen) { + fprintf(Parser_c, "\ttraceOptionValueDefault=1;\t\t// MR10 turn trace ON\n"); + } else { + fprintf(Parser_c, "\ttraceOptionValueDefault=0;\t\t// MR10 turn trace OFF\n"); + }; + fprintf(Parser_c, "}\n\n"); + free ( (void *) hasAkaName); +} + +void +#ifdef __USE_PROTOS +GenParser_h_Hdr(void) +#else +GenParser_h_Hdr() +#endif +{ + int i; + + fprintf(Parser_h, "/*\n"); + fprintf(Parser_h, " * %s: P a r s e r H e a d e r \n", CurrentClassName); + fprintf(Parser_h, " *\n"); + fprintf(Parser_h, " * Generated from:"); + for (i=0; i 1 ) fprintf(ErrFile, "#define LL_K %d\n", OutputLL_k); +#ifdef DUM + if ( LexGen ) fprintf(ErrFile, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken)); +#endif + fprintf(ErrFile, "#define zzSET_SIZE %lu\n", NumWords(TokenNum-1)*sizeof(unsigned)); + if ( DemandLookahead ) fprintf(ErrFile, "#define DEMAND_LOOK\n"); + fprintf(ErrFile, "#include \"antlr.h\"\n"); + if ( GenAST ) fprintf(ErrFile, "#include \"ast.h\"\n"); + + if ( UserDefdTokens ) fprintf(ErrFile, "#include %s\n", UserTokenDefsFile); + /* still need this one as it has the func prototypes */ + fprintf(ErrFile, "#include \"%s\"\n", DefFileName); + fprintf(ErrFile, "#include \"dlgdef.h\"\n"); + fprintf(ErrFile, "#include \"err.h\"\n\n"); + + /* Dump a zztokens for each automaton */ + if ( strcmp(ParserName, DefaultParserName)!=0 ) + { + fprintf(ErrFile, "ANTLRChar *%s_zztokens[%d]={\n", ParserName, TokenNum-1); + } + else + { + fprintf(ErrFile, "ANTLRChar *zztokens[%d]={\n", TokenNum-1); + } + fprintf(ErrFile, "\t/* 00 */\t\"Invalid\""); + for (i=1; i=LastTokenCounted ) + { + fprintf(ErrFile, ",\n\t/* %02d */\t\"invalid\"", i); + continue; + } + if ( TokenString(i) != NULL ) { + te=(TermEntry *) hash_get(Tname,TokenString(i)); /* MR11 */ + if (te == NULL || te->akaString == NULL) { /* MR11 */ + fprintf(ErrFile, ",\n\t/* %02d */\t\"%s\"", i, TokenString(i)); + } else { + fprintf(ErrFile, ",\n\t/* %02d */\t\"%s\"", i, te->akaString); /* MR11 */ + } + } + else + { + /* look in all lexclasses for the reg expr */ + for (j=0; j=NumLexClasses ) + { + if ( UserDefdTokens ) + { + fprintf(ErrFile, ",\n\t/* %02d */\t\"\"", i); + } + else + fatal_internal(eMsgd("No label or expr for token %d",i)); + } + } + } + fprintf(ErrFile, "\n};\n"); +} + +void +#ifdef __USE_PROTOS +dumpExpr( FILE *f, char *e ) +#else +dumpExpr( f, e ) +FILE *f; +char *e; +#endif +{ + while ( *e!='\0' ) + { + if ( *e=='\\' && *(e+1)=='\\' ) + {putc('\\', f); putc('\\', f); e+=2;} + else if ( *e=='\\' && *(e+1)=='"' ) + {putc('\\', f); putc('"', f); e+=2;} + else if ( *e=='\\' ) {putc('\\', f); putc('\\', f); e++;} + else {putc(*e, f); e++;} + } +} + +int +#ifdef __USE_PROTOS +isTermEntryTokClass(TermEntry *te) +#else +isTermEntryTokClass(te) +TermEntry *te; +#endif +{ + ListNode *t; + TCnode *p; + TermEntry *q; + char *tokstr; + + if (tclasses == NULL) return 0; + + for (t = tclasses->next; t!=NULL; t=t->next) + { + p = (TCnode *) t->elem; + tokstr = TokenString(p->tok); + lexmode(p->lexclass); /* switch to lexclass where tokclass is defined */ + q = (TermEntry *) hash_get(Tname, tokstr); + if (q == te) return 1; + } + return 0; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/build.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/build.c new file mode 100644 index 00000000..ec0c1158 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/build.c @@ -0,0 +1,813 @@ +/* + * build.c -- functions associated with building syntax diagrams. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include +#include +#include "pcctscfg.h" +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" + +#define SetBlk(g, t, approx, first_set_symbol) { \ + ((Junction *)g.left)->jtype = t; \ + ((Junction *)g.left)->approx = approx; \ + ((Junction *)g.left)->pFirstSetSymbol = first_set_symbol; \ + ((Junction *)g.left)->end = (Junction *) g.right; \ + ((Junction *)g.right)->jtype = EndBlk;} + +/* Add the parameter string 'parm' to the parms field of a block-type junction + * g.left points to the sentinel node on a block. i.e. g.left->p1 points to + * the actual junction with its jtype == some block-type. + */ +void +#ifdef __USE_PROTOS +addParm( Node *p, char *parm ) +#else +addParm( p, parm ) +Node *p; +char *parm; +#endif +{ + char *q = (char *) malloc( strlen(parm) + 1 ); + require(p!=NULL, "addParm: NULL object\n"); + require(q!=NULL, "addParm: unable to alloc parameter\n"); + + strcpy(q, parm); + if ( p->ntype == nRuleRef ) + { + ((RuleRefNode *)p)->parms = q; + } + else if ( p->ntype == nJunction ) + { + ((Junction *)p)->parm = q; /* only one parameter allowed on subrules */ + } + else fatal_internal("addParm: invalid node for adding parm"); +} + +/* + * Build an action node for the syntax diagram + * + * buildAction(ACTION) ::= --o-->ACTION-->o-- + * + * Where o is a junction node. + */ +Graph +#ifdef __USE_PROTOS +buildAction( char *action, int file, int line, int is_predicate ) +#else +buildAction( action, file, line, is_predicate ) +char *action; +int file; +int line; +int is_predicate; +#endif +{ + Junction *j1, *j2; + Graph g; + ActionNode *a; + require(action!=NULL, "buildAction: invalid action"); + + j1 = newJunction(); + j2 = newJunction(); + a = newActionNode(); + a->action = (char *) malloc( strlen(action)+1 ); + require(a->action!=NULL, "buildAction: cannot alloc space for action\n"); + strcpy(a->action, action); + j1->p1 = (Node *) a; + a->next = (Node *) j2; + a->is_predicate = is_predicate; + + if (is_predicate) { + PredEntry *predEntry; + char *t; + char *key; + char *u; + int inverted=0; + + t=key=(char *)calloc(1,strlen(a->action)+1); + + for (u=a->action; *u != '\0' ; u++) { + if (*u != ' ') { + if (t==key && *u=='!') { + inverted=!inverted; + } else { + *t++=*u; + }; + }; + }; + + *t='\0'; + + + predEntry=(PredEntry *)hash_get(Pname,key); + a->predEntry=predEntry; + if (predEntry != NULL) a->inverted=inverted; + } else { +/* MR12c */ char *strStart=a->action; +/* MR12c */ char *strEnd; +/* MR12c */ strEnd=strStart+strlen(strStart)-1; +/* MR12c */ for ( ; strEnd >= strStart && isspace(*strEnd); strEnd--) *strEnd=0; +/* MR12c */ while (*strStart != '\0' && isspace(*strStart)) strStart++; +/* MR12c */ if (ci_strequ(strStart,"nohoist")) { +/* MR12c */ a->noHoist=1; +/* MR12c */ } + } + + g.left = (Node *) j1; g.right = (Node *) j2; + a->file = file; + a->line = line; + a->rname = CurRule; /* MR10 */ + return g; +} + +/* + * Build a token node for the syntax diagram + * + * buildToken(TOKEN) ::= --o-->TOKEN-->o-- + * + * Where o is a junction node. + */ +Graph +#ifdef __USE_PROTOS +buildToken( char *text ) +#else +buildToken( text ) +char *text; +#endif +{ + Junction *j1, *j2; + Graph g; + TokNode *t; + require(text!=NULL, "buildToken: invalid token name"); + + j1 = newJunction(); + j2 = newJunction(); + t = newTokNode(); + t->altstart = CurAltStart; + if ( *text == '"' ) {t->label=FALSE; t->token = addTexpr( text );} + else {t->label=TRUE; t->token = addTname( text );} + j1->p1 = (Node *) t; + t->next = (Node *) j2; + g.left = (Node *) j1; g.right = (Node *) j2; + return g; +} + +/* + * Build a wild-card node for the syntax diagram + * + * buildToken(TOKEN) ::= --o-->'.'-->o-- + * + * Where o is a junction node. + */ +Graph +#ifdef __USE_PROTOS +buildWildCard( char *text ) +#else +buildWildCard( text ) +char *text; +#endif +{ + Junction *j1, *j2; + Graph g; + TokNode *t; + TCnode *w; + TermEntry *p; + require(text!=NULL, "buildWildCard: invalid token name"); + + j1 = newJunction(); + j2 = newJunction(); + t = newTokNode(); + + /* If the ref a wild card, make a token class for it */ + if ( Tnum(WildCardString) == 0 ) + { + w = newTCnode; + w->tok = addTname( WildCardString ); + set_orel(w->tok, &imag_tokens); + set_orel(w->tok, &tokclasses); + WildCardToken = w->tok; + require((p=(TermEntry *)hash_get(Tname, WildCardString)) != NULL, + "hash table mechanism is broken"); + p->classname = 1; /* entry is class name, not token */ + p->tclass = w; /* save ptr to this tclass def */ + list_add(&tclasses, (char *)w); + } + else { + p=(TermEntry *)hash_get(Tname, WildCardString); + require( p!= NULL, "hash table mechanism is broken"); + w = p->tclass; + } + + t->token = w->tok; + t->wild_card = 1; + t->tclass = w; + + t->altstart = CurAltStart; + j1->p1 = (Node *) t; + t->next = (Node *) j2; + g.left = (Node *) j1; g.right = (Node *) j2; + return g; +} + +void +#ifdef __USE_PROTOS +setUpperRange(TokNode *t, char *text) +#else +setUpperRange(t, text) +TokNode *t; +char *text; +#endif +{ + require(t!=NULL, "setUpperRange: NULL token node"); + require(text!=NULL, "setUpperRange: NULL token string"); + + if ( *text == '"' ) {t->upper_range = addTexpr( text );} + else {t->upper_range = addTname( text );} +} + +/* + * Build a rule reference node of the syntax diagram + * + * buildRuleRef(RULE) ::= --o-->RULE-->o-- + * + * Where o is a junction node. + * + * If rule 'text' has been defined already, don't alloc new space to store string. + * Set r->text to point to old copy in string table. + */ +Graph +#ifdef __USE_PROTOS +buildRuleRef( char *text ) +#else +buildRuleRef( text ) +char *text; +#endif +{ + Junction *j1, *j2; + Graph g; + RuleRefNode *r; + RuleEntry *p; + require(text!=NULL, "buildRuleRef: invalid rule name"); + + j1 = newJunction(); + j2 = newJunction(); + r = newRNode(); + r->altstart = CurAltStart; + r->assign = NULL; + if ( (p=(RuleEntry *)hash_get(Rname, text)) != NULL ) r->text = p->str; + else r->text = mystrdup( text ); + j1->p1 = (Node *) r; + r->next = (Node *) j2; + g.left = (Node *) j1; g.right = (Node *) j2; + return g; +} + +/* + * Or two subgraphs into one graph via: + * + * Or(G1, G2) ::= --o-G1-o-- + * | ^ + * v | + * o-G2-o + * + * Set the altnum of junction starting G2 to 1 + altnum of junction starting G1. + * If, however, the G1 altnum is 0, make it 1 and then + * make G2 altnum = G1 altnum + 1. + */ +Graph +#ifdef __USE_PROTOS +Or( Graph g1, Graph g2 ) +#else +Or( g1, g2 ) +Graph g1; +Graph g2; +#endif +{ + Graph g; + require(g1.left != NULL, "Or: invalid graph"); + require(g2.left != NULL && g2.right != NULL, "Or: invalid graph"); + + ((Junction *)g1.left)->p2 = g2.left; + ((Junction *)g2.right)->p1 = g1.right; + /* set altnums */ + if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1; + ((Junction *)g2.left)->altnum = ((Junction *)g1.left)->altnum + 1; + g.left = g2.left; + g.right = g1.right; + return g; +} + +/* + * Catenate two subgraphs + * + * Cat(G1, G2) ::= --o-G1-o-->o-G2-o-- + * Cat(NULL,G2)::= --o-G2-o-- + * Cat(G1,NULL)::= --o-G1-o-- + */ +Graph +#ifdef __USE_PROTOS +Cat( Graph g1, Graph g2 ) +#else +Cat( g1, g2 ) +Graph g1; +Graph g2; +#endif +{ + Graph g; + + if ( g1.left == NULL && g1.right == NULL ) return g2; + if ( g2.left == NULL && g2.right == NULL ) return g1; + ((Junction *)g1.right)->p1 = g2.left; + g.left = g1.left; + g.right = g2.right; + return g; +} + +/* + * Make a subgraph an optional block + * + * makeOpt(G) ::= --o-->o-G-o-->o-- + * | ^ + * v | + * o-------o + * + * Note that this constructs {A|B|...|Z} as if (A|B|...|Z|) was found. + * + * The node on the far right is added so that every block owns its own + * EndBlk node. + */ +Graph +#ifdef __USE_PROTOS +makeOpt( Graph g1, int approx, char * pFirstSetSymbol ) +#else +makeOpt( g1, approx, pFirstSetSymbol ) +Graph g1; +int approx; +char * pFirstSetSymbol; +#endif +{ + Junction *j1,*j2,*p; + Graph g; + require(g1.left != NULL && g1.right != NULL, "makeOpt: invalid graph"); + + j1 = newJunction(); + j2 = newJunction(); + ((Junction *)g1.right)->p1 = (Node *) j2; /* add node to G at end */ + + /* MR21 + * + * There is code in genBlk which recognizes the node created + * by emptyAlt() as a special case and bypasses it. We don't + * want this to happen for the optBlk. + */ + + g = emptyAlt3(); /* MR21 */ + if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1; + ((Junction *)g.left)->altnum = ((Junction *)g1.left)->altnum + 1; + for(p=(Junction *)g1.left; p->p2!=NULL; p=(Junction *)p->p2) + {;} /* find last alt */ + p->p2 = g.left; /* add optional alternative */ + ((Junction *)g.right)->p1 = (Node *)j2; /* opt alt points to EndBlk */ + g1.right = (Node *)j2; + SetBlk(g1, aOptBlk, approx, pFirstSetSymbol); + j1->p1 = g1.left; /* add generic node in front */ + g.left = (Node *) j1; + g.right = g1.right; + return g; +} + +/* + * Make a graph into subblock + * + * makeBlk(G) ::= --o-->o-G-o-->o-- + * + * The node on the far right is added so that every block owns its own + * EndBlk node. + */ +Graph +#ifdef __USE_PROTOS +makeBlk( Graph g1, int approx, char * pFirstSetSymbol ) +#else +makeBlk( g1, approx, pFirstSetSymbol ) +Graph g1; +int approx; +char * pFirstSetSymbol; +#endif +{ + Junction *j,*j2; + Graph g; + require(g1.left != NULL && g1.right != NULL, "makeBlk: invalid graph"); + + j = newJunction(); + j2 = newJunction(); + ((Junction *)g1.right)->p1 = (Node *) j2; /* add node to G at end */ + g1.right = (Node *)j2; + SetBlk(g1, aSubBlk, approx, pFirstSetSymbol); + j->p1 = g1.left; /* add node in front */ + g.left = (Node *) j; + g.right = g1.right; + + return g; +} + +/* + * Make a subgraph into a loop (closure) block -- (...)* + * + * makeLoop(G) ::= |---| + * v | + * --o-->o-->o-G-o-->o-- + * | ^ + * v | + * o-----------o + * + * After making loop, always place generic node out front. It becomes + * the start of enclosing block. The aLoopBlk is the target of the loop. + * + * Loop blks have TWO EndBlk nodes--the far right and the node that loops back + * to the aLoopBlk node. Node with which we can branch past loop == aLoopBegin and + * one which is loop target == aLoopBlk. + * The branch-past (initial) aLoopBegin node has end + * pointing to the last EndBlk node. The loop-target node has end==NULL. + * + * Loop blocks have a set of locks (from 1..CLL_k) on the aLoopBlk node. + */ +Graph +#ifdef __USE_PROTOS +makeLoop( Graph g1, int approx, char * pFirstSetSymbol ) +#else +makeLoop( g1, approx, pFirstSetSymbol) +Graph g1; +int approx; +char * pFirstSetSymbol; +#endif +{ + Junction *back, *front, *begin; + Graph g; + require(g1.left != NULL && g1.right != NULL, "makeLoop: invalid graph"); + + back = newJunction(); + front = newJunction(); + begin = newJunction(); + g = emptyAlt3(); + ((Junction *)g1.right)->p2 = g1.left; /* add loop branch to G */ + ((Junction *)g1.right)->p1 = (Node *) back; /* add node to G at end */ + ((Junction *)g1.right)->jtype = EndBlk; /* mark 1st EndBlk node */ + ((Junction *)g1.left)->jtype = aLoopBlk; /* mark 2nd aLoopBlk node */ + ((Junction *)g1.left)->end = (Junction *) g1.right; + ((Junction *)g1.left)->lock = makelocks(); + ((Junction *)g1.left)->pred_lock = makelocks(); + g1.right = (Node *) back; + begin->p1 = (Node *) g1.left; + g1.left = (Node *) begin; + begin->p2 = (Node *) g.left; /* make bypass arc */ + ((Junction *)g.right)->p1 = (Node *) back; + SetBlk(g1, aLoopBegin, approx, pFirstSetSymbol); + front->p1 = g1.left; /* add node to front */ + g1.left = (Node *) front; + + return g1; +} + +/* + * Make a subgraph into a plus block -- (...)+ -- 1 or more times + * + * makePlus(G) ::= |---| + * v | + * --o-->o-G-o-->o-- + * + * After making loop, always place generic node out front. It becomes + * the start of enclosing block. The aPlusBlk is the target of the loop. + * + * Plus blks have TWO EndBlk nodes--the far right and the node that loops back + * to the aPlusBlk node. + * + * Plus blocks have a set of locks (from 1..CLL_k) on the aPlusBlk node. + */ +Graph +#ifdef __USE_PROTOS +makePlus( Graph g1, int approx, char * pFirstSetSymbol) +#else +makePlus( g1, approx, pFirstSetSymbol) +Graph g1; +int approx; +char * pFirstSetSymbol; +#endif +{ + int has_empty_alt_already = 0; + Graph g; + Junction *j2, *j3, *first_alt; + Junction *last_alt=NULL, *p; + require(g1.left != NULL && g1.right != NULL, "makePlus: invalid graph"); + + first_alt = (Junction *)g1.left; + j2 = newJunction(); + j3 = newJunction(); + if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1; + ((Junction *)g1.right)->p2 = g1.left; /* add loop branch to G */ + ((Junction *)g1.right)->p1 = (Node *) j2; /* add node to G at end */ + ((Junction *)g1.right)->jtype = EndBlk; /* mark 1st EndBlk node */ + g1.right = (Node *) j2; + SetBlk(g1, aPlusBlk, approx, pFirstSetSymbol); + ((Junction *)g1.left)->lock = makelocks(); + ((Junction *)g1.left)->pred_lock = makelocks(); + j3->p1 = g1.left; /* add node to front */ + g1.left = (Node *) j3; + + /* add an optional branch which is the "exit" branch of loop */ + /* FIRST, check to ensure that there does not already exist + * an optional path. + */ + /* find last alt */ + for(p=first_alt; p!=NULL; p=(Junction *)p->p2) + { + if ( p->p1->ntype == nJunction && + p->p1!=NULL && + ((Junction *)p->p1)->jtype==Generic && + ((Junction *)p->p1)->p1!=NULL && + ((Junction *)((Junction *)p->p1)->p1)->jtype==EndBlk ) + { + has_empty_alt_already = 1; + } + last_alt = p; + } + if ( !has_empty_alt_already ) + { + require(last_alt!=NULL, "last_alt==NULL; bad (..)+"); + g = emptyAlt(); + last_alt->p2 = g.left; + ((Junction *)g.right)->p1 = (Node *) j2; + + /* make sure lookahead computation ignores this alt for + * FIRST("(..)+"); but it's still used for computing the FIRST + * of each alternative. + */ + ((Junction *)g.left)->ignore = 1; + } + + return g1; +} + +/* + * Return an optional path: --o-->o-- + */ + +Graph +#ifdef __USE_PROTOS +emptyAlt( void ) +#else +emptyAlt( ) +#endif +{ + Junction *j1, *j2; + Graph g; + + j1 = newJunction(); + j2 = newJunction(); + j1->p1 = (Node *) j2; + g.left = (Node *) j1; + g.right = (Node *) j2; + + return g; +} + +/* MR21 + * + * There is code in genBlk which recognizes the node created + * by emptyAlt() as a special case and bypasses it. We don't + * want this to happen for the optBlk. + */ + +Graph +#ifdef __USE_PROTOS +emptyAlt3( void ) +#else +emptyAlt3( ) +#endif +{ + Junction *j1, *j2, *j3; + Graph g; + + j1 = newJunction(); + j2 = newJunction(); + j3 = newJunction(); + j1->p1 = (Node *) j2; + j2->p1 = (Node *) j3; + g.left = (Node *) j1; + g.right = (Node *) j3; + + return g; +} + +/* N o d e A l l o c a t i o n */ + +TokNode * +#ifdef __USE_PROTOS +newTokNode( void ) +#else +newTokNode( ) +#endif +{ + static TokNode *FreeList = NULL; + TokNode *p, *newblk; + + if ( FreeList == NULL ) + { + newblk = (TokNode *)calloc(TokenBlockAllocSize, sizeof(TokNode)); + if ( newblk == NULL ) + fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule)); + for (p=newblk; p<&(newblk[TokenBlockAllocSize]); p++) + { + p->next = (Node *)FreeList; /* add all new token nodes to FreeList */ + FreeList = p; + } + } + p = FreeList; + FreeList = (TokNode *)FreeList->next;/* remove a TokNode node */ + p->next = NULL; /* NULL the ptr we used */ + memset( (char *) p, 0, sizeof(TokNode)); /* MR10 */ + p->ntype = nToken; + p->rname = CurRule; + p->file = CurFile; + p->line = zzline; + p->altstart = NULL; + + return p; +} + +RuleRefNode * +#ifdef __USE_PROTOS +newRNode( void ) +#else +newRNode( ) +#endif +{ + static RuleRefNode *FreeList = NULL; + RuleRefNode *p, *newblk; + + if ( FreeList == NULL ) + { + newblk = (RuleRefNode *)calloc(RRefBlockAllocSize, sizeof(RuleRefNode)); + if ( newblk == NULL ) + fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule)); + for (p=newblk; p<&(newblk[RRefBlockAllocSize]); p++) + { + p->next = (Node *)FreeList; /* add all new rref nodes to FreeList */ + FreeList = p; + } + } + p = FreeList; + FreeList = (RuleRefNode *)FreeList->next;/* remove a Junction node */ + p->next = NULL; /* NULL the ptr we used */ + memset( (char *) p, 0, sizeof(RuleRefNode)); /* MR10 */ + p->ntype = nRuleRef; + p->rname = CurRule; + p->file = CurFile; + p->line = zzline; + p->astnode = ASTinclude; + p->altstart = NULL; + + return p; +} + +static int junctionSeqNumber=0; /* MR10 */ + +Junction * +#ifdef __USE_PROTOS +newJunction( void ) +#else +newJunction( ) +#endif +{ + static Junction *FreeList = NULL; + Junction *p, *newblk; + + if ( FreeList == NULL ) + { + newblk = (Junction *)calloc(JunctionBlockAllocSize, sizeof(Junction)); + if ( newblk == NULL ) + fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule)); + for (p=newblk; p<&(newblk[JunctionBlockAllocSize]); p++) + { + p->p1 = (Node *)FreeList; /* add all new Junction nodes to FreeList */ + FreeList = p; + } + } + p = FreeList; + FreeList = (Junction *)FreeList->p1;/* remove a Junction node */ + p->p1 = NULL; /* NULL the ptr we used */ + memset( (char *) p, 0, sizeof(Junction)); /* MR10 */ + p->ntype = nJunction; + p->visited = 0; + p->jtype = Generic; + p->rname = CurRule; + p->file = CurFile; + p->line = zzline; + p->exception_label = NULL; + p->fset = (set *) calloc(CLL_k+1, sizeof(set)); + require(p->fset!=NULL, "cannot allocate fset in newJunction"); + p->seq=++junctionSeqNumber; /* MR10 */ + + return p; +} + +ActionNode * +#ifdef __USE_PROTOS +newActionNode( void ) +#else +newActionNode( ) +#endif +{ + static ActionNode *FreeList = NULL; + ActionNode *p, *newblk; + + if ( FreeList == NULL ) + { + newblk = (ActionNode *)calloc(ActionBlockAllocSize, sizeof(ActionNode)); + if ( newblk == NULL ) + fatal_internal(eMsg1("out of memory while building rule '%s'",CurRule)); + for (p=newblk; p<&(newblk[ActionBlockAllocSize]); p++) + { + p->next = (Node *)FreeList; /* add all new Action nodes to FreeList */ + FreeList = p; + } + } + p = FreeList; + FreeList = (ActionNode *)FreeList->next;/* remove an Action node */ + memset( (char *) p, 0, sizeof(ActionNode)); /* MR10 */ + p->ntype = nAction; + p->next = NULL; /* NULL the ptr we used */ + p->done = 0; + p->pred_fail = NULL; + p->guardpred = NULL; + p->ampersandPred = NULL; + return p; +} + +/* + * allocate the array of locks (1..CLL_k) used to inhibit infinite recursion. + * Infinite recursion can occur in (..)* blocks, FIRST calcs and FOLLOW calcs. + * Therefore, we need locks on aLoopBlk, RuleBlk, EndRule nodes. + * + * if ( lock[k]==TRUE ) then we have been here before looking for k tokens + * of lookahead. + */ +char * +#ifdef __USE_PROTOS +makelocks( void ) +#else +makelocks( ) +#endif +{ + char *p = (char *) calloc(CLL_k+1, sizeof(char)); + require(p!=NULL, "cannot allocate lock array"); + + return p; +} + +#if 0 +** #ifdef __USE_PROTOS +** void my_memset(char *p,char value,int count) +** #else +** void my_memset(p,value,count) +** char *p; +** char value; +** int count; +** #endif +** { +** int i; +** +** for (i=0; i +#include + +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" + +void +#ifdef __USE_PROTOS +dumpcycles(void) +#else +dumpcycles() +#endif +{ + Cycle *c; + CacheEntry *f; + ListNode *p; + int i=0; + int k; + int degree; + + for (k=1; k <= CLL_k; k++) { + if (Cycles[k] == NULL) continue; + + for (p = Cycles[k]->next; p!=NULL; p=p->next) { + c = (Cycle *) p->elem; + degree=set_deg(c->cyclicDep); + fprintf(stderr,"Cycle %d: (degree %d) %s -->\n", i++, degree, RulePtr[c->croot]->rname); + fprintf(stderr," *self*\n"); + MR_dumpRuleSet(c->cyclicDep); + fprintf(stderr,"\n"); + f = (CacheEntry *) + hash_get(Fcache,Fkey(RulePtr[c->croot]->rname,'o',k)); + if (f == NULL) { + fprintf(stderr," *** FOLLOW(%s) must be in cache but isn't ***\n", + RulePtr[c->croot]->rname); + }; + }; + }; +} + +void +#ifdef __USE_PROTOS +dumpfostack(int k) +#else +dumpfostack(k) +int k; +#endif +{ + int i=0; + int *pi; + + fprintf(stderr,"\n"); + if (FoStack[k] == NULL) { + fprintf(stderr,"FoStack[%d] is null\n",k); + }; + if (FoTOS[k] == NULL) { + fprintf(stderr,"FoTOS[%d] is null\n",k); + } + if (FoTOS[k] != NULL && FoStack[k] != NULL) { + for (pi=FoStack[k]; pi <= FoTOS[k]; pi++) { + i++; + fprintf(stderr,"#%d rule %d %s\n",i,*pi,RulePtr[*pi]->rname); + } + } +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/dumpnode.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/dumpnode.c new file mode 100644 index 00000000..7a9c6a7d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/dumpnode.c @@ -0,0 +1,423 @@ +#include +#include + +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" + +#ifdef __USE_PROTOS +void dumpset1(set s) +#else +void dumpset1(s) + set s; +#endif +{ + if (set_nil(s)) { + fprintf(stderr,"{}"); + } else { + s_fprT(stderr,s); + }; +} + +#ifdef __USE_PROTOS +void dumpset(set s) +#else +void dumpset(s) + set s; +#endif +{ + dumpset1(s); + fprintf(stderr,"\n"); +} + +#ifdef __USE_PROTOS +int isEndRule(Node * p) +#else +int isEndRule(p) + Node * p; +#endif +{ + int result=0; + if ( p->ntype == nJunction && + ( (Junction *) p)->jtype == EndRule) { + result=1; + }; + return result; +} + +#ifdef __USE_PROTOS +void dumppred1(int depth,Predicate *p) +#else +void dumppred1(depth,p) + int depth; + Predicate *p; +#endif +{ + int i; + int k; + + for (i=0; iexpr == PRED_AND_LIST || + p->expr == PRED_OR_LIST) { + fprintf(stderr," %s", (p->expr == NULL ? "null expr" : p->expr)); + if (p->inverted) fprintf(stderr," predicate inverted !"); + if (p->redundant) { + fprintf(stderr," Redundant!"); + }; + if (p->isConst) fprintf(stderr," const %d !",p->constValue); + fprintf(stderr,"\n"); + } else { + fprintf(stderr,"predicate k=%d",p->k); + k=set_int(p->completionSet); + if (k >= 0) { + fprintf(stderr," Incomplete Set=%d !",k); + }; + k=set_int(p->completionTree); + if (k >= 0) { + fprintf(stderr," Incomplete Tree=%d !",k); + }; + if (p->redundant) { + fprintf(stderr," Redundant!"); + }; + fprintf(stderr," \"%s\" (%x)", (p->expr == NULL ? "null expr" : p->expr) ,p); + if (p->source != NULL) { + fprintf(stderr,"line %d",p->source->line); + }; + if (p->inverted) fprintf(stderr," predicate inverted !"); + fprintf(stderr,"\n"); + for (i=0; iscontext[1]); + for (i=0; itcontext); + fprintf(stderr,"\n"); + }; + fprintf(stderr,"\n"); + if (p->down != NULL) { + dumppred1(depth+1,p->down); + }; + if (p->right != NULL) { + dumppred1(depth,p->right); + }; +} + +#ifdef __USE_PROTOS +void dumppred(Predicate *p) +#else +void dumppred(p) + Predicate *p; +#endif +{ + fprintf(stderr,"---------------------------------\n"); + dumppred1(0,p); + fprintf(stderr,"\n"); +} + +#ifdef __USE_PROTOS +void dumppredtree(Predicate *p) +#else +void dumppredtree(p) + Predicate *p; +#endif +{ + fprintf(stderr,"predicate k=%d \"%s\" line %d\n",p->k,p->expr,p->source->line); + dumpset(p->scontext[1]); +} + +#ifdef __USE_PROTOS +void dumppredexpr(Predicate *p) +#else +void dumppredexpr(p) + Predicate *p; +#endif +{ + fprintf(stderr," pred expr \"%s\"\n",p->expr); +} + +#ifdef __USE_PROTOS +void dt(Tree *t) +#else +void dt(t) + Tree *t; +#endif +{ + MR_dumpTreeF(stderr,0,t,5); +} + +#ifdef __USE_PROTOS +void d(Node * p) +#else +void d(p) + Node * p; +#endif +{ + + Junction *j; + RuleRefNode *r; + TokNode *t; + ActionNode *a; + + if (p==NULL) { + fprintf(stderr,"dumpNode: Node is NULL"); + return; + }; + + switch (p->ntype) { + case nJunction : + j = (Junction *) p; + fprintf(stderr, "Junction (#%d in rule %s line %d) ",j->seq,j->rname,j->line); + if (j->guess) fprintf(stderr,"guess block "); + switch (j->jtype ) { + case aSubBlk : + fprintf(stderr,"aSubBlk"); + break; + case aOptBlk : + fprintf(stderr,"aOptBlk"); + break; + case aLoopBegin : + fprintf(stderr,"aLoopBeginBlk"); + break; + case aLoopBlk : + fprintf(stderr,"aLoopBlk"); + break; + case aPlusBlk : + fprintf(stderr,"aPlusBlk"); + break; + case EndBlk : + fprintf(stderr,"EndBlk"); + break; + case RuleBlk : + fprintf(stderr,"RuleBlk"); + break; + case Generic : + fprintf(stderr,"Generic"); + break; + case EndRule : + fprintf(stderr,"EndRule"); + break; + }; + if (j->halt) fprintf(stderr," halt!"); + if (j->p1) fprintf(stderr," p1 valid"); + if (j->p2) { + if (j->p2->ntype == nJunction) { + fprintf(stderr," (p2=#%d)",( (Junction *) j->p2)->seq); + } else { + fprintf(stderr," (p2 valid)"); + }; + }; + if (j->ignore) fprintf(stderr, " ignore/plus-block-bypass"); + if (j->fset != NULL && set_deg(*j->fset) != 0) { + fprintf(stderr,"\nfset:\n"); + dumpset(*j->fset); + }; + if (j->ftree != NULL) { + fprintf(stderr,"\nftree:\n"); + preorder(j->ftree); + }; + fprintf(stderr,"\n"); + break; + case nRuleRef : + r = (RuleRefNode *) p; + fprintf(stderr, "RuleRefNode (in rule %s line %d) to rule %s\n", r->rname,r->line,r->text); + break; + case nToken : + t = (TokNode *) p; + fprintf(stderr, "TokNode (in rule %s line %d) token %s\n",t->rname,t->line,TerminalString(t->token)); + break; + case nAction : + a =(ActionNode *) p; + if (a->is_predicate) { + fprintf(stderr, "Predicate (in rule %s line %d) %s",a->rname,a->line,a->action); + if (a->inverted) fprintf(stderr," action inverted !"); + if (a->guardpred != NULL) { + fprintf(stderr," guarded"); + dumppredexpr(a->guardpred); + if (a->ampersandPred) { + fprintf(stderr," \"&&\" style"); + } else { + fprintf(stderr," \"=>\" style"); + }; + }; + if (a->predEntry != NULL) fprintf(stderr," predEntry \"%s\" ",a->predEntry->str); + fprintf(stderr,"\n"); + } else if (a->init_action) { + fprintf(stderr, "Init-Action (in rule %s line %d) %s\n",a->rname,a->line,a->action); + } else { + fprintf(stderr, "Action (in rule %s line %d) %s\n",a->rname,a->line,a->action); + }; + break; + }; +} + +#ifdef __USE_PROTOS +Node * dp1(Node * p) +#else +Node * dp1(p) + Node * p; +#endif +{ + Node *result=NULL; + + if (p->ntype == nJunction) { + result=( (Junction *) p )->p1; + d(result); + } else { + fprintf(stderr,"dp1: Not a Junction node"); + }; + return result; +} + +#ifdef __USE_PROTOS +Node * dp2(Node * p) +#else +Node * dp2(p) + Node * p; +#endif +{ + Node *result=NULL; + + if (p->ntype == nJunction) { + result=( (Junction *) p )->p2; + d(result); + } else { + fprintf(stderr,"dp2: Not a Junction node"); + }; + return result; +} + +#ifdef __USE_PROTOS +Node * dn(Node * p) +#else +Node * dn(p) + Node * p; +#endif + +{ + Node *result=NULL; + + if (p->ntype == nRuleRef) { + result=( (RuleRefNode *)p )->next; + } else if (p->ntype == nAction) { + result=( (ActionNode *)p )->next; + } else if (p->ntype == nToken) { + result=( (TokNode *)p )->next; + } else { + fprintf(stderr,"No next field: Neither a RuleRefNode, ActionNode, nor TokNode"); + }; + if (result != NULL) d(result); + return result; +} + +#ifdef __USE_PROTOS +void df(Node * p) +#else +void df(p) + Node * p; +#endif +{ + int count=0; + Node *next; + + fprintf(stderr,"\n#%d ",++count); + d(p); + + for (next=p; next != NULL && !isEndRule(next) ; ) { + fprintf(stderr,"#%d ",++count); + if (next->ntype == nJunction) { + next=dp1(next); + } else { + next=dn(next); + }; + }; +} + +#ifdef __USE_PROTOS +Node * dfn(Node * p,int target) +#else +Node * dfn(p,target) + Node * p; + int target; +#endif +{ + Node *result=NULL; + int count=0; + Node *next; + + fprintf(stderr,"#%d ",++count); + d(p); + + for (next=p; next != NULL && !isEndRule(next) ; ) { + fprintf(stderr,"#%d ",++count); + if (next->ntype == nJunction) { + next=dp1(next); + } else { + next=dn(next); + }; + if (count == target) { + result=next; + break; + }; + }; + return result; +} + + +static int findnodeMatch; + +#ifdef __USE_PROTOS +Junction *findnode1(Node *n) +#else +Junction *findnode1(n) + Node *n; +#endif +{ + Node *next; + Junction *j; + Junction *match; + + if (n == NULL) return NULL; + if (n->ntype == nJunction) { + j=(Junction *) n; + if (j->seq == findnodeMatch) return j; + if (j->jtype == EndRule) return NULL; + if (j->jtype != RuleBlk && j->jtype != EndBlk) { + if (j->p2 != NULL && !j->ignore) { + match=findnode1(j->p2); + if (match != NULL) return match; + }; + }; + }; + next=MR_advance(n); + return findnode1(next); +} + +#ifdef __USE_PROTOS +Junction *findnode(int match) +#else +Junction *findnode(match) + int match; +#endif +{ + Junction *j; + Junction *result=NULL; + + findnodeMatch=match; + + for (j=SynDiag; j != NULL; j=(Junction *)j->p2) { + require (j->ntype == nJunction && j->jtype == RuleBlk,"Not a rule block"); + result=findnode1( (Node *) j); + if (result != NULL) break; + }; + if (result != NULL) { + d( (Node *) result); + }; + return result; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/egman.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/egman.c new file mode 100644 index 00000000..1bbc9283 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/egman.c @@ -0,0 +1,328 @@ +/* + * egman.c + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33MR10 + * 2001 + * + */ + +#include +#include + +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "proto.h" + +static ExceptionGroup **egArray=NULL; /* ExceptionGroup by BlkLevel */ +static LabelEntry **leArray=NULL; /* LabelEntry by BlkLevel */ +static Junction **altArray=NULL; /* start of alternates */ +static int arraySize=0; +static int highWater=0; +static ExceptionGroup *lastEG=NULL; /* used in altFixup() */ +static int lastBlkLevel=0; /* used in altFixup() */ + +#ifdef __USE_PROTOS +static void arrayCheck(void); +#else +static void arrayCheck(); +#endif + +/* Called to add an exception group for an alternative EG */ + +#ifdef __USE_PROTOS +void egAdd(ExceptionGroup * eg) +#else +void egAdd(eg) +ExceptionGroup *eg; +#endif +{ + int i; + + ExceptionGroup *nextEG; + ExceptionGroup *innerEG; + + LabelEntry *nextLE; + LabelEntry *innerLE; + + Junction *nextAlt; + Junction *innerAlt; + + lastEG=eg; + lastBlkLevel=BlkLevel; + + arrayCheck(); + eg->pendingLink=egArray[BlkLevel]; + egArray[BlkLevel]=eg; + + /* EG for alternates already have their altID filled in */ + + for (i=BlkLevel+1; i<=highWater ; i++) { + for (innerEG=egArray[i]; innerEG != NULL ; innerEG=nextEG) { + nextEG=innerEG->pendingLink; + innerEG->pendingLink=NULL; + innerEG->outerEG=eg; + }; + egArray[i]=NULL; + }; + + /* + * for patching up the LabelEntry you might use an EG for the + * current alternative - unlike patching up an alternative EG + * i.e. start the loop at BlkLevel rather than (BlkLevel+1) + * fill it in only if the EG and the LE are for the very + * same alternative if they're at the same BlkLevel + * it's easier to leave the LE on this list (filled in) rather than + * trying to selectively remove it. It will eventually be + * removed anyway when the BlkLevel gets small enough. + */ + + for (i=BlkLevel; i<=highWater ; i++) { + for (innerLE=leArray[i]; innerLE != NULL ; innerLE=nextLE) { + nextLE=innerLE->pendingLink; + if (BlkLevel != i || + innerLE->curAltNum == CurAltNum_array[BlkLevel]) { + if (innerLE->outerEG == NULL) { + innerLE->outerEG=eg; + }; + }; + }; + if (BlkLevel != i) leArray[i]=NULL; + }; + +/* + * For the start of alternatives it is necessary to make a + * distinction between the exception group for the current + * alternative and the "fallback" EG for the block which + * contains the alternative + * + * The fallback outerEG is used to handle the case where + * no alternative of a block matches. In that case the + * signal is "NoViableAlt" (or "NoSemViableAlt" and the + * generator needs the EG of the block CONTAINING the + * current one. + * + * rule: ( ( ( a + * | b + * ) + * | c + * ) + * | d + * ); + */ + + for (i=BlkLevel; i <= highWater ; i++) { + for (innerAlt=altArray[i]; innerAlt != NULL ; innerAlt=nextAlt) { + nextAlt=innerAlt->pendingLink; + + /* first fill in the EG for the current alternative */ + /* but leave it on the list in order to get the fallback EG */ + /* if the EG is at the same LEVEL as the alternative then */ + /* fill it in only if in the very same alternative */ + /* */ + /* rule: ( a */ + /* | b */ + /* | c exception ... */ + /* ) */ + /* */ + /* if the EG is outside the alternative (e.g. BlkLevel < i) */ + /* then it doesn't matter about the alternative */ + /* */ + /* rule: ( a */ + /* | b */ + /* | c */ + /* ) exception ... */ + /* */ + +#if 0 + printf("BlkLevel=%d i=%d altnum=%d CurAltNum=%d altID=%s\n", + BlkLevel,i,innerAlt->curAltNum,CurAltNum_array[BlkLevel],eg->altID); +#endif + if (BlkLevel != i || + innerAlt->curAltNum == CurAltNum_array[BlkLevel]) { + if (innerAlt->exception_label == NULL) { + innerAlt->exception_label=eg->altID; + }; + }; + + /* occurs at a later pass then for the exception_label */ + /* if an outerEG has been found then fill in the outer EG */ + /* remove if from the list when the BlkLevel gets smaller */ + + if (BlkLevel != i) { + if (innerAlt->outerEG == NULL) { + innerAlt->outerEG=eg; + }; + }; + }; + if (BlkLevel != i) altArray[i]=NULL; + }; +} + +#ifdef __USE_PROTOS +void leAdd(LabelEntry * le) +#else +void leAdd(le) +LabelEntry *le; +#endif + +{ + arrayCheck(); + le->pendingLink=leArray[BlkLevel]; + le->curAltNum=CurAltNum_array[BlkLevel]; + leArray[BlkLevel]=le; +} + +#ifdef __USE_PROTOS +void altAdd(Junction *alt) +#else +void altAdd(alt) +Junction *alt; +#endif + +{ + arrayCheck(); +#if 0 + printf("BlkLevel=%d CurAltNum=%d\n", + BlkLevel,CurAltNum_array[BlkLevel]); +#endif + alt->curAltNum=CurAltNum_array[BlkLevel]; + alt->pendingLink=altArray[BlkLevel]; + altArray[BlkLevel]=alt; +} + +static void +#ifdef __USE_PROTOS +arrayCheck(void) +#else +arrayCheck() +#endif +{ + ExceptionGroup **egArrayNew; + LabelEntry **leArrayNew; + Junction **altArrayNew; + int arraySizeNew; + int i; + + if (BlkLevel > highWater) highWater=BlkLevel; + + if (BlkLevel >= arraySize) { + arraySizeNew=BlkLevel+5; /* MR20 */ + egArrayNew=(ExceptionGroup **) + calloc(arraySizeNew,sizeof(ExceptionGroup *)); + leArrayNew=(LabelEntry **) + calloc(arraySizeNew,sizeof(LabelEntry *)); + altArrayNew=(Junction **) + calloc(arraySizeNew,sizeof(Junction *)); + for (i=0; ipendingLink; + innerEG->pendingLink=NULL; + }; + egArray[i]=NULL; + }; + lastEG=NULL; + lastBlkLevel=0; +} + +/* always call leFixup() BEFORE egFixup() */ + +#ifdef __USE_PROTOS +void leFixup(void) +#else +void leFixup() +#endif +{ + + int i; + LabelEntry *nextLE; + LabelEntry *innerLE; + + for (i=BlkLevel; i<=highWater ; i++) { + for (innerLE=leArray[i]; innerLE != NULL ; innerLE=nextLE) { + nextLE=innerLE->pendingLink; + innerLE->pendingLink=NULL; + }; + leArray[i]=NULL; + }; +} + +/* always call altFixup() BEFORE egFixup() */ + +#ifdef __USE_PROTOS +void altFixup(void) +#else +void altFixup() +#endif +{ + + int i; + Junction *nextAlt; + Junction *innerAlt; + + for (i=BlkLevel; i<=highWater ; i++) { + for (innerAlt=altArray[i]; innerAlt != NULL ; innerAlt=nextAlt) { + + /* if an outerEG has been found then fill in the outer EG */ + + if (lastBlkLevel <= i) { + if (innerAlt->outerEG == NULL) { + innerAlt->outerEG=lastEG; + }; + }; + nextAlt=innerAlt->pendingLink; + innerAlt->pendingLink=NULL; + }; + altArray[i]=NULL; + }; +} + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/err.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/err.c new file mode 100644 index 00000000..f3777ba6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/err.c @@ -0,0 +1,538 @@ +/* + * A n t l r S e t s / E r r o r F i l e H e a d e r + * + * Generated from: antlr.g + * + * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001 + * Parr Research Corporation + * with Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + */ + +#define ANTLR_VERSION 13333 +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include "pcctscfg.h" +#include "set.h" +#include +#include "syn.h" +#include "hash.h" +#include "generic.h" +#define zzcr_attr(attr,tok,t) /*vbox: */ memset((attr), 0, sizeof(*attr)) +#define zzSET_SIZE 20 +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +#include "err.h" + +ANTLRChar *zztokens[157]={ + /* 00 */ "Invalid", + /* 01 */ "Eof", + /* 02 */ "QuotedTerm", + /* 03 */ "\\n|\\r|\\r\\n", + /* 04 */ "\\(\\n|\\r|\\r\\n)", + /* 05 */ "\\~[]", + /* 06 */ "~[\\n\\r\"\\]+", + /* 07 */ "\"", + /* 08 */ "\\n|\\r|\\r\\n", + /* 09 */ "\\(\\n|\\r|\\r\\n)", + /* 10 */ "\\~[]", + /* 11 */ "~[\\n\\r\"\\]+", + /* 12 */ "'", + /* 13 */ "\\n|\\r|\\r\\n", + /* 14 */ "\\~[]", + /* 15 */ "~[\\n\\r'\\]+", + /* 16 */ "\\*/", + /* 17 */ "\\*", + /* 18 */ "\\n|\\r|\\r\\n", + /* 19 */ "~[\\n\\r\\*]+", + /* 20 */ "\\*/", + /* 21 */ "\\*", + /* 22 */ "\\n|\\r|\\r\\n", + /* 23 */ "~[\\n\\r\\*]+", + /* 24 */ "\\n|\\r|\\r\\n", + /* 25 */ "~[\\n\\r]+", + /* 26 */ "\\n|\\r|\\r\\n", + /* 27 */ "~[\\n\\r]+", + /* 28 */ "\\n|\\r|\\r\\n", + /* 29 */ "~[\\n\\r]+", + /* 30 */ "\\*/", + /* 31 */ "\\*", + /* 32 */ "\\n|\\r|\\r\\n", + /* 33 */ "~[\\n\\r\\*]+", + /* 34 */ "Action", + /* 35 */ "Pred", + /* 36 */ "PassAction", + /* 37 */ "consumeUntil\\( [\\ \\t]* \\{~[\\}]+\\} [\\ \\t]* \\)", + /* 38 */ "consumeUntil\\( ~[\\)]+ \\)", + /* 39 */ "\\n|\\r|\\r\\n", + /* 40 */ "\\>", + /* 41 */ "$", + /* 42 */ "$$", + /* 43 */ "$\\[\\]", + /* 44 */ "$\\[", + /* 45 */ "$[0-9]+", + /* 46 */ "$[0-9]+.", + /* 47 */ "$[0-9]+.[0-9]+", + /* 48 */ "$[_a-zA-Z][_a-zA-Z0-9]*", + /* 49 */ "#0", + /* 50 */ "#\\[\\]", + /* 51 */ "#\\(\\)", + /* 52 */ "#[0-9]+", + /* 53 */ "#line[\\ \\t]* [0-9]+ {[\\ \\t]* \"~[\"]+\" ([\\ \\t]* [0-9]*)* } (\\n|\\r|\\r\\n)", + /* 54 */ "#line ~[\\n\\r]* (\\n|\\r|\\r\\n)", + /* 55 */ "#[_a-zA-Z][_a-zA-Z0-9]*", + /* 56 */ "#\\[", + /* 57 */ "#\\(", + /* 58 */ "#", + /* 59 */ "\\)", + /* 60 */ "\\[", + /* 61 */ "\\(", + /* 62 */ "\\\\]", + /* 63 */ "\\\\)", + /* 64 */ "\\>", + /* 65 */ "'", + /* 66 */ "\"", + /* 67 */ "\\$", + /* 68 */ "\\#", + /* 69 */ "\\(\\n|\\r|\\r\\n)", + /* 70 */ "\\~[\\]\\)>$#]", + /* 71 */ "/", + /* 72 */ "/\\*", + /* 73 */ "\\*/", + /* 74 */ "//", + /* 75 */ "~[\\n\\r\\)\\(\\$#\\>\\]\\[\"'/]+", + /* 76 */ "[\\t\\ ]+", + /* 77 */ "\\n|\\r|\\r\\n", + /* 78 */ "\\[", + /* 79 */ "\\<\\<", + /* 80 */ "\"", + /* 81 */ "/\\*", + /* 82 */ "\\*/", + /* 83 */ "//", + /* 84 */ "#line[\\ \\t]* [0-9]+ {[\\ \\t]* \"~[\"]+\" ([\\ \\t]* [0-9]*)* } (\\n|\\r|\\r\\n)", + /* 85 */ "#line ~[\\n\\r]* (\\n|\\r|\\r\\n)", + /* 86 */ "\\>\\>", + /* 87 */ "WildCard", + /* 88 */ "\\@", + /* 89 */ "LABEL", + /* 90 */ "grammar-element", + /* 91 */ "meta-symbol", + /* 92 */ "Pragma", + /* 93 */ "FirstSetSymbol", + /* 94 */ "{\\}#header", + /* 95 */ "{\\}#first", + /* 96 */ "{\\}#parser", + /* 97 */ "{\\}#tokdefs", + /* 98 */ "\\}", + /* 99 */ "class", + /* 100 */ "NonTerminal", + /* 101 */ "TokenTerm", + /* 102 */ "\\{", + /* 103 */ "!", + /* 104 */ "\\<", + /* 105 */ "\\>", + /* 106 */ ":", + /* 107 */ ";", + /* 108 */ "{\\}#lexaction", + /* 109 */ "{\\}#lexmember", + /* 110 */ "{\\}#lexprefix", + /* 111 */ "{\\}#pred", + /* 112 */ "\\|\\|", + /* 113 */ "&&", + /* 114 */ "\\(", + /* 115 */ "\\)", + /* 116 */ "{\\}#lexclass", + /* 117 */ "{\\}#errclass", + /* 118 */ "{\\}#tokclass", + /* 119 */ "..", + /* 120 */ "{\\}#token", + /* 121 */ "=", + /* 122 */ "[0-9]+", + /* 123 */ "\\|", + /* 124 */ "\\~", + /* 125 */ "^", + /* 126 */ "approx", + /* 127 */ "LL\\(1\\)", + /* 128 */ "LL\\(2\\)", + /* 129 */ "\\*", + /* 130 */ "\\+", + /* 131 */ "?", + /* 132 */ "=>", + /* 133 */ "exception", + /* 134 */ "default", + /* 135 */ "catch", + /* 136 */ "{\\}#[A-Za-z0-9_]*", + /* 137 */ "[\\t\\ ]+", + /* 138 */ "\\n|\\r|\\r\\n", + /* 139 */ "//", + /* 140 */ "/\\*", + /* 141 */ "#ifdef", + /* 142 */ "#if", + /* 143 */ "#ifndef", + /* 144 */ "#else", + /* 145 */ "#endif", + /* 146 */ "#undef", + /* 147 */ "#import", + /* 148 */ "ID", + /* 149 */ "#define", + /* 150 */ "INT", + /* 151 */ "enum", + /* 152 */ "\\{", + /* 153 */ "=", + /* 154 */ ",", + /* 155 */ "\\}", + /* 156 */ ";" +}; +SetWordType zzerr1[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr2[20] = {0xfc,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xf3, + 0xbf,0xff,0xff,0xff, 0xff,0xff,0xff,0x1f}; +SetWordType zzerr3[20] = {0xfc,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xfb, + 0x3b,0xf7,0xf7,0xc7, 0xff,0xff,0xff,0x1f}; +SetWordType zzerr4[20] = {0x4,0x0,0x0,0x0, 0x10,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x80,0x7,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType setwd1[157] = {0x0,0x50,0xa0,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x6a,0x20,0xa0,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x0,0x0,0x20,0x20,0x21, + 0x21,0x21,0x21,0x6e,0x6e,0x64,0x20,0x0, + 0x20,0xa0,0xa0,0xa0,0x20,0x6a,0x6a,0x6a, + 0x6e,0x20,0x20,0x20,0x20,0x66,0x6e,0x6e, + 0x20,0x66,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x62,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20,0x20,0x20, + 0x20,0x20,0x20,0x20,0x20,0x20}; +SetWordType zzerr5[20] = {0x0,0x0,0x0,0x0, 0x10,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x1,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr6[20] = {0x4,0x0,0x0,0x0, 0x10,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x7,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr7[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x6,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr8[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x4,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr9[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf0,0x70,0x1, 0x20,0x0,0x0,0x0}; +SetWordType setwd2[157] = {0x0,0xf8,0x6,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xf8,0x0,0x1,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xf8,0xf8,0xf8,0x0,0x0, + 0x0,0x1,0x2,0x6,0x0,0xf8,0xf8,0xf8, + 0xf8,0x0,0x0,0x0,0x0,0xf8,0xf8,0xf8, + 0x0,0xf8,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0xe8,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr10[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0xbc,0xf8,0x74,0x1, 0x20,0x0,0x0,0x0}; +SetWordType zzerr11[20] = {0x0,0x0,0x0,0x0, 0x8,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0xa0,0x0,0x4,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr12[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0}; +SetWordType zzerr13[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0xa0,0x0,0x4,0x0, 0x0,0x0,0x0,0x0}; +SetWordType setwd3[157] = {0x0,0xfa,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xfa,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xfa,0xfa,0xfa,0x5,0x0, + 0x5,0x0,0x0,0x0,0xe2,0xfa,0xfa,0xfa, + 0xfa,0xc0,0x80,0x5,0xe0,0xfa,0xfa,0xfa, + 0x0,0xfa,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0xfa,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr14[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x20,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr15[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr16[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr17[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x40,0x0,0x4,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr18[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x24,0x0,0x80,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr19[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x20,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr20[20] = {0x6,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x74,0x3, 0x20,0x0,0x0,0x0}; +SetWordType zzerr21[20] = {0x6,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x70,0x3, 0x20,0x0,0x0,0x0}; +SetWordType setwd4[157] = {0x0,0xe5,0xda,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xe5,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xed,0xe5,0xe7,0x1a,0x0, + 0x0,0x0,0x0,0x0,0xc0,0xe5,0xe5,0xe5, + 0xe5,0x0,0x0,0x0,0x0,0xe5,0xe5,0xe5, + 0x0,0xe5,0x40,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0xe5,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr22[20] = {0x6,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x3c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0}; +SetWordType zzerr23[20] = {0x6,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0}; +SetWordType zzerr24[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0}; +SetWordType zzerr25[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x70,0x1, 0x20,0x0,0x0,0x0}; +SetWordType zzerr26[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x5, + 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0}; +SetWordType setwd5[157] = {0x0,0x1f,0xc1,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xdf,0xc0,0xc0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0xc0,0x0,0xc0,0x0,0x0,0xc0,0xc0,0x0, + 0x0,0x0,0x0,0x7f,0x1f,0xdf,0xc0,0xc0, + 0x0,0x0,0xc0,0x0,0x67,0x1f,0x1f,0x1f, + 0x1f,0x0,0x0,0xc0,0x60,0x1f,0x1f,0x1f, + 0x0,0x1f,0x0,0x0,0x40,0xc0,0x0,0x0, + 0x0,0x0,0xc0,0xc0,0x0,0x0,0x5f,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr27[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x0,0x0,0x0,0x10, 0x0,0x0,0x0,0x0}; +SetWordType zzerr28[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x80,0x2, + 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr29[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x20,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr30[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xd, + 0x0,0x0,0x80,0x0, 0x20,0x0,0x0,0x0}; +SetWordType zzerr31[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xd, + 0x0,0x0,0x0,0x0, 0x20,0x0,0x0,0x0}; +SetWordType zzerr32[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x5, + 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0}; +SetWordType zzerr33[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x20,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType setwd6[157] = {0x0,0x0,0xfd,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xe1,0xe1,0xe1,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0xfd,0x60,0xe9,0x0,0x0,0xe1,0xe1,0x0, + 0x0,0x0,0x0,0xe2,0x0,0xfd,0xfd,0xe1, + 0x20,0x0,0xe1,0x0,0xe2,0x0,0x0,0x0, + 0x0,0x0,0x0,0xe1,0xe2,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0xe2,0xe0,0x20,0x0, + 0x0,0x0,0xe1,0xe1,0x0,0x0,0xe2,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr34[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xd, + 0x0,0x0,0x80,0x0, 0x20,0x0,0x0,0x0}; +SetWordType zzerr35[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xd, + 0x0,0x0,0x0,0x0, 0x20,0x0,0x0,0x0}; +SetWordType zzerr36[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x5, + 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0}; +SetWordType zzerr37[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xc, + 0x0,0x0,0x0,0x0, 0x20,0x0,0x0,0x0}; +SetWordType zzerr38[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x84,0x9,0x8,0x18, 0x20,0x0,0x0,0x0}; +SetWordType zzerr39[20] = {0x0,0x0,0x0,0x0, 0x10,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x1,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr40[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x4,0x9,0x8,0x18, 0x20,0x0,0x0,0x0}; +SetWordType zzerr41[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0}; +SetWordType zzerr42[20] = {0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x80,0x0, + 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType setwd7[157] = {0x0,0x0,0xdf,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xdf,0xdf,0xff,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0xdf,0x3,0xdf,0x0,0x0,0xdf,0xdf,0x0, + 0x0,0x0,0x0,0xdf,0x0,0xdf,0xdf,0xdf, + 0x1,0x30,0xdf,0x0,0xdf,0x0,0x0,0x0, + 0x0,0x0,0x0,0xdf,0xdf,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0xdf,0xdf,0x1,0x0, + 0x0,0x0,0xdf,0xdf,0x0,0x0,0xdf,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr43[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0}; +SetWordType zzerr44[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xc0, 0x1,0x0,0x0,0x0}; +SetWordType zzerr45[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x30, + 0x40,0x0,0x4,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr46[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr47[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x20, + 0x40,0x0,0x4,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr48[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x2,0x0, 0x10,0x0,0x0,0x0}; +SetWordType zzerr49[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x4,0x8,0x8,0x18, 0x20,0x0,0x0,0x0}; +SetWordType zzerr50[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x4,0x8,0xa,0x18, 0x30,0x0,0x0,0x0}; +SetWordType zzerr51[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x4,0x8,0x8,0x18, 0x28,0x0,0x0,0x0}; +SetWordType zzerr52[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x40,0x0,0x4,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr53[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x4, + 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType setwd8[157] = {0x0,0x0,0xe1,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0xe1,0xe1,0xe1,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0xe1,0x0,0xe1,0x0,0x0,0xe3,0xe7,0x0, + 0x0,0x0,0x0,0xe1,0x0,0xe1,0xe1,0xef, + 0x0,0x0,0xe1,0x0,0xe1,0x0,0x0,0x0, + 0x0,0x0,0x10,0xef,0xe1,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0xe1,0xe1,0x0,0x0, + 0x0,0x0,0xe1,0xe1,0x0,0x10,0xe1,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr54[20] = {0x2,0x0,0x0,0x0, 0x14,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x78,0x9, 0xe0,0x0,0x0,0x0}; +SetWordType zzerr55[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x78,0x9, 0x60,0x0,0x0,0x0}; +SetWordType zzerr56[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x30,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr57[20] = {0x2,0x0,0x0,0x0, 0x4,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x1c,0xf8,0x78,0x9, 0xe0,0x0,0x0,0x0}; +SetWordType setwd9[157] = {0x0,0x7c,0x1,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x7f,0x1,0x1,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x1,0x0,0x1,0x0,0x0,0x1,0x1,0x0, + 0x0,0x0,0x0,0x7f,0x7e,0x7f,0x1,0x1, + 0x0,0x0,0x1,0x0,0x7d,0x7e,0x7e,0x7e, + 0x7e,0x0,0x0,0x1,0x7d,0x7e,0x7e,0x7e, + 0x0,0x7e,0x0,0x0,0x7d,0x1,0x0,0x0, + 0x0,0x0,0x1,0x1,0x0,0x0,0x7f,0x64, + 0x64,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x80,0x0,0x0,0x0,0x0,0x0,0x80,0x0, + 0x80,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr58[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0, 0x0,0x0,0xa0,0x0}; +SetWordType zzerr59[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0, 0x0,0x80,0xa0,0x0}; +SetWordType zzerr60[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0, 0x0,0x0,0xa0,0x0}; +SetWordType zzerr61[20] = {0x2,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0, 0x0,0x80,0xa0,0x0}; +SetWordType zzerr62[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xe}; +SetWordType zzerr63[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xe}; +SetWordType zzerr64[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0xe}; +SetWordType zzerr65[20] = {0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0, 0x0,0x0,0x10,0xc}; +SetWordType setwd10[157] = {0x0,0xc,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x3,0x0, + 0x3,0x0,0x0,0xf0,0xf0,0x0}; +SetWordType setwd11[157] = {0x0,0x1,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, + 0x1,0x0,0x0,0x0,0x0,0x0}; diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/fcache.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/fcache.c new file mode 100644 index 00000000..9b7653de --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/fcache.c @@ -0,0 +1,123 @@ +/* + * fcache.c + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33MR10 + * + */ + +#include +#include + +#include "pcctscfg.h" + +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" + +#ifdef __USE_PROTOS +CacheEntry *dumpFcache1(char *prev) +#else +CacheEntry *dumpFcache1(prev) + char *prev; +#endif +{ + Entry **table=Fcache; + + int low=0; + int hi=0; + + CacheEntry *least=NULL; + + Entry **p; + + for (p=table; p<&(table[HashTableSize]); p++) { + + CacheEntry *q =(CacheEntry *) *p; + + if ( q != NULL && low==0 ) low = p-table; + while ( q != NULL ) { + if (strcmp(q->str,prev) > 0) { + if (least == NULL) { + least=q; + } else { + if (strcmp(q->str,least->str) < 0) { + least=q; + }; + }; + }; + q = q->next; + }; + + if ( *p != NULL ) hi = p-table; + } + return least; +} + +#ifdef __USE_PROTOS +void reportFcache(CacheEntry *q) +#else +void reportFcache(q) + CacheEntry *q; +#endif +{ + char *qstr; + + fprintf(stdout,"\nrule "); + for (qstr=q->str; *qstr != '*' ; qstr++) { + fprintf(stdout,"%c",*qstr); + }; + + qstr++; + if (*qstr == 'i') fprintf(stdout," First["); + if (*qstr == 'o') fprintf(stdout," Follow["); + qstr++; + fprintf(stdout,"%s]",qstr); + if (q->incomplete) fprintf(stdout," *** incomplete ***"); + fprintf(stdout,"\n"); + MR_dumpTokenSet(stdout,1,q->fset); +} + +void +#ifdef __USE_PROTOS +DumpFcache(void) +#else +DumpFcache() +#endif +{ + + char *prev=""; + int n=0; + CacheEntry *next; + + fprintf(stdout,"\n\nDump of First/Follow Cache\n"); + + for(;;) { + next=dumpFcache1(prev); + if (next == NULL) break; + reportFcache(next); + ++n; + prev=next->str; + }; + fprintf(stdout,"\nEnd dump of First/Follow Cache\n"); +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/fset.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/fset.c new file mode 100644 index 00000000..2e013cc1 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/fset.c @@ -0,0 +1,1555 @@ +/* + * fset.c + * + * Compute FIRST and FOLLOW sets. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include + +#include "pcctscfg.h" + +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" +#include "limits.h" + +#ifdef __USE_PROTOS +static void ensure_predicates_cover_ambiguous_lookahead_sequences + (Junction *, Junction *, char *, Tree *); +#else +static void ensure_predicates_cover_ambiguous_lookahead_sequences(); +#endif + +/* + * What tokens are k tokens away from junction q? + * + * Follow both p1 and p2 paths (unless RuleBlk) to collect the tokens k away from this + * node. + * We lock the junction according to k--the lookahead. If we have been at this + * junction before looking for the same, k, number of lookahead tokens, we will + * do it again and again...until we blow up the stack. Locks are only used on aLoopBlk, + * RuleBlk, aPlusBlk and EndRule junctions to remove/detect infinite recursion from + * FIRST and FOLLOW calcs. + * + * If p->jtype == EndRule we are going to attempt a FOLLOW. (FOLLOWs are really defined + * in terms of FIRST's, however). To proceed with the FOLLOW, p->halt cannot be + * set. p->halt is set to indicate that a reference to the current rule is in progress + * and the FOLLOW is not desirable. + * + * If we attempt a FOLLOW and find that there is no FOLLOW or REACHing beyond the EndRule + * junction yields an empty set, replace the empty set with EOF. No FOLLOW means that + * only EOF can follow the current rule. This normally occurs only on the start symbol + * since all other rules are referenced by another rule somewhere. + * + * Normally, both p1 and p2 are followed. However, checking p2 on a RuleBlk node is + * the same as checking the next rule which is clearly incorrect. + * + * Cycles in the FOLLOW sense are possible. e.g. Fo(c) requires Fo(b) which requires + * Fo(c). Both Fo(b) and Fo(c) are defined to be Fo(b) union Fo(c). Let's say + * Fo(c) is attempted first. It finds all of the FOLLOW symbols and then attempts + * to do Fo(b) which finds of its FOLLOW symbols. So, we have: + * + * Fo(c) + * / \ + * a set Fo(b) + * / \ + * a set Fo(c) .....Hmmmm..... Infinite recursion! + * + * The 2nd Fo(c) is not attempted and Fo(b) is left deficient, but Fo(c) is now + * correctly Fo(c) union Fo(b). We wish to pick up where we left off, so the fact + * that Fo(b) terminated early means that we lack Fo(c) in the Fo(b) set already + * laying around. SOOOOoooo, we track FOLLOW cycles. All FOLLOW computations are + * cached in a hash table. After the sequence of FOLLOWs finish, we reconcile all + * cycles --> correct all Fo(rule) sets in the cache. + * + * Confused? Good! Read my MS thesis [Purdue Technical Report TR90-30]. + * TJP 8/93 -- can now read PhD thesis from Purdue. + * + * Also, FIRST sets are cached in the hash table. Keys are (rulename,Fi/Fo,k). + * Only FIRST sets, for which the FOLLOW is not included, are stored. + * + * SPECIAL CASE of (...)+ blocks: + * I added an optional alt so that the alts could see what + * was behind the (...)+ block--thus using enough lookahead + * to branch out rather than just enough to distinguish + * between alts in the (...)+. However, when the FIRST("(...)+") is + * is needed, must not use this last "optional" alt. This routine + * turns off this path by setting a new 'ignore' flag for + * the alt and then resetting it afterwards. + */ + +set +#ifdef __USE_PROTOS +rJunc( Junction *p, int k, set *rk ) +#else +rJunc( p, k, rk ) +Junction *p; +int k; +set *rk; +#endif +{ + set a, b; + + require(p!=NULL, "rJunc: NULL node"); + require(p->ntype==nJunction, "rJunc: not junction"); + +#ifdef DBG_LL1 + if ( p->jtype == RuleBlk ) fprintf(stderr, "FIRST(%s,%d) \n",((Junction *)p)->rname,k); + else fprintf(stderr, "rJunc: %s in rule %s\n", + decodeJType[p->jtype], ((Junction *)p)->rname); +#endif + /* if this is one of the added optional alts for (...)+ then return */ + + /* no need to pop backtrace - hasn't been pushed */ + + if ( p->ignore ) return empty; + + if (MR_MaintainBackTrace) MR_pointerStackPush(&MR_BackTraceStack,p); + +/* MR14 */ if (AlphaBetaTrace && p->alpha_beta_guess_end) { +/* MR14 */ warnFL( +/* MR14 */ "not possible to compute follow set for alpha in an \"(alpha)? beta\" block. ", +/* MR14 */ FileStr[p->file],p->line); +/* MR14 */ MR_alphaBetaTraceReport(); +/* MR14 */ }; + +/* MR14 */ if (p->alpha_beta_guess_end) { +/* MR14 */ if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); +/* MR14 */ return empty; +/* MR14 */ } + + /* locks are valid for aLoopBlk,aPlusBlk,RuleBlk,EndRule junctions only */ + if ( p->jtype==aLoopBlk || p->jtype==RuleBlk || + p->jtype==aPlusBlk || p->jtype==EndRule ) + { + require(p->lock!=NULL, "rJunc: lock array is NULL"); + if ( p->lock[k] ) + { + if ( p->jtype == EndRule ) /* FOLLOW cycle? */ + { +#ifdef DBG_LL1 + fprintf(stderr, "FOLLOW cycle to %s: panic!\n", p->rname); +#endif + if (! MR_AmbSourceSearch) RegisterCycle(p->rname, k); + } + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + return empty; + } + if ( p->jtype == RuleBlk && + p->end->halt && + ! MR_AmbSourceSearch) /* check for FIRST cache */ + { + CacheEntry *q = (CacheEntry *) hash_get(Fcache, Fkey(p->rname,'i',k)); + if ( q != NULL ) + { + set_orin(rk, q->rk); + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + return set_dup( q->fset ); + } + } + if ( p->jtype == EndRule && + !p->halt && /* MR11 was using cache even when halt set */ + ! MR_AmbSourceSearch) /* FOLLOW set cached already? */ + { + CacheEntry *q = (CacheEntry *) hash_get(Fcache, Fkey(p->rname,'o',k)); + if ( q != NULL ) + { +#ifdef DBG_LL1 + fprintf(stderr, "cache for FOLLOW(%s,%d):", p->rname,k); + s_fprT(stderr, q->fset); + if ( q->incomplete ) fprintf(stderr, " (incomplete)"); + fprintf(stderr, "\n"); +#endif + if ( !q->incomplete ) + { + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + return set_dup( q->fset ); + } + } + } + p->lock[k] = TRUE; /* This rule is busy */ + } + + a = b = empty; + + if ( p->jtype == EndRule ) + { + if (p->halt ) /* don't want FOLLOW here? */ /* unless MR10 hoisting */ + { + p->lock[k] = FALSE; + set_orel(k, rk); /* indicate this k value needed */ + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + return empty; + } + if (! MR_AmbSourceSearch) FoPush(p->rname, k); /* Attempting FOLLOW */ + if ( p->p1 == NULL ) set_orel((TokenInd!=NULL?TokenInd[EofToken]:EofToken), &a);/* if no FOLLOW assume EOF */ +#ifdef DBG_LL1 + fprintf(stderr, "-->FOLLOW(%s,%d)\n", p->rname,k); +#endif + } + + if ( p->p1 != NULL ) { +/* MR14 */ if (p->guess) { +/* MR14 */ if (p->guess_analysis_point == NULL) { +/* MR14 */ Node * guess_point; +/* MR14 */ guess_point=(Node *)analysis_point(p); +/* MR14 */ if (guess_point == (Node *)p) { +/* MR14 */ guess_point=p->p1; +/* MR14 */ } +/* MR14 */ p->guess_analysis_point=guess_point; +/* MR14 */ } +/* MR14 */ REACH(p->guess_analysis_point, k, rk, a); + } else { + REACH(p->p1, k, rk, a); + } + } + + /* C a c h e R e s u l t s */ + + if ( p->jtype == RuleBlk && p->end->halt && ! MR_AmbSourceSearch) /* can save FIRST set? */ + { + CacheEntry *q = newCacheEntry( Fkey(p->rname,'i',k) ); + /*fprintf(stderr, "Caching %s FIRST %d\n", p->rname, k);*/ + hash_add(Fcache, Fkey(p->rname,'i',k), (Entry *)q); + q->fset = set_dup( a ); + q->rk = set_dup( *rk ); + } + + if ( p->jtype == EndRule && + !p->halt && /* MR11 was using cache even with halt set */ + ! MR_AmbSourceSearch) /* just completed FOLLOW? */ + { + /* Cache Follow set */ + CacheEntry *q = (CacheEntry *) hash_get(Fcache, Fkey(p->rname,'o',k)); + if ( q==NULL ) + { + q = newCacheEntry( Fkey(p->rname,'o',k) ); + hash_add(Fcache, Fkey(p->rname,'o',k), (Entry *)q); + } + /*fprintf(stderr, "Caching %s FOLLOW %d\n", p->rname, k);*/ + if ( set_nil(a) && !q->incomplete ) + { + /* Don't ever save a nil set as complete. + * Turn it into an eof set. + */ + set_orel(EofToken, &a); + } + set_orin(&(q->fset), a); + FoPop( k ); + if ( FoTOS[k] == NULL && Cycles[k] != NULL ) ResolveFoCycles(k); +#ifdef DBG_LL1 + fprintf(stderr, "saving FOLLOW(%s,%d):", p->rname, k); + s_fprT(stderr, q->fset); + if ( q->incomplete ) fprintf(stderr, " (incomplete)"); + fprintf(stderr, "\n"); +#endif + } + + if (p->jtype != RuleBlk && p->p2 != NULL && /* MR14 */ ! p->guess) { + REACH(p->p2, k, rk, b); + } + + if ( p->jtype==aLoopBlk || p->jtype==RuleBlk || + p->jtype==aPlusBlk || p->jtype==EndRule ) + p->lock[k] = FALSE; /* unlock node */ + + set_orin(&a, b); + set_free(b); + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + return a; +} + +set +#ifdef __USE_PROTOS +rRuleRef( RuleRefNode *p, int k, set *rk_out ) +#else +rRuleRef( p, k, rk_out ) +RuleRefNode *p; +int k; +set *rk_out; +#endif +{ + set rk; + Junction *r; + int k2; + set a, rk2, b; + int save_halt; + RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text); + require(p!=NULL, "rRuleRef: NULL node"); + require(p->ntype==nRuleRef, "rRuleRef: not rule ref"); + +#ifdef DBG_LL1 + fprintf(stderr, "rRuleRef: %s\n", p->text); +#endif + + if (MR_MaintainBackTrace) MR_pointerStackPush(&MR_BackTraceStack,p); + + if ( q == NULL ) + { + warnFL( eMsg1("rule %s not defined",p->text), FileStr[p->file], p->line ); + REACH(p->next, k, rk_out, a); + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + return a; + } + rk2 = empty; + +/* MR9 Problems with rule references in guarded predicates */ +/* MR9 Perhaps can use hash table to find rule ? */ + +/* MR9 */ if (RulePtr == NULL) { +/* MR9 */ fatalFL(eMsg2("Rule %s uses rule %s via RulePtr before it has been initialized", +/* MR9 */ p->rname,q->str),FileStr[p->file],p->line); +/* MR9 */ }; + + r = RulePtr[q->rulenum]; + if ( r->lock[k] ) + { + errNoFL( eMsg2("infinite left-recursion to rule %s from rule %s", + r->rname, p->rname) ); + + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + + return empty; + } + + save_halt = r->end->halt; + r->end->halt = TRUE; /* don't let reach fall off end of rule here */ + rk = empty; + REACH(r, k, &rk, a); + r->end->halt = save_halt; + while ( !set_nil(rk) ) { + k2 = set_int(rk); /* MR11 this messes up the ambiguity search routine */ + set_rm(k2, rk); + REACH(p->next, k2, &rk2, b); /* MR11 by changing the value of k */ + set_orin(&a, b); + set_free(b); + } + set_free(rk); /* this has no members, but free its memory */ + set_orin(rk_out, rk2); /* remember what we couldn't do */ + set_free(rk2); + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + return a; +} + +/* + * Return FIRST sub k ( token_node ) + * + * TJP 10/11/93 modified this so that token nodes that are actually + * ranges (T1..T2) work. + */ +set +#ifdef __USE_PROTOS +rToken( TokNode *p, int k, set *rk ) +#else +rToken( p, k, rk ) +TokNode *p; +int k; +set *rk; +#endif +{ + set a; + + require(p!=NULL, "rToken: NULL node"); + require(p->ntype==nToken, "rToken: not token node"); + +#ifdef DBG_LL1 + fprintf(stderr, "rToken: %s\n", (TokenString(p->token)!=NULL)?TokenString(p->token): + ExprString(p->token)); +#endif + + + if (MR_MaintainBackTrace) MR_pointerStackPush(&MR_BackTraceStack,p); + + if (MR_AmbSourceSearch && (k-1) == 0) { + + set localConstrain; + set intersection; + + localConstrain=fset[maxk-k+1]; + + if (! set_nil(p->tset)) { + intersection=set_and(localConstrain,p->tset); + if (! set_nil(intersection)) { + MR_backTraceReport(); + }; + set_free(intersection); + } else { + if (set_el( (unsigned) p->token,localConstrain)) { + MR_backTraceReport(); + } + }; + }; + + if ( k-1 == 0 ) { + + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + + if ( !set_nil(p->tset) ) { + return set_dup(p->tset); + } else { + return set_of(p->token); + }; + } + + REACH(p->next, k-1, rk, a); + + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + + return a; +} + +set +#ifdef __USE_PROTOS +rAction( ActionNode *p, int k, set *rk ) +#else +rAction( p, k, rk ) +ActionNode *p; +int k; +set *rk; +#endif +{ + set a; + + require(p!=NULL, "rJunc: NULL node"); + require(p->ntype==nAction, "rJunc: not action"); + +/* MR11 */ if (p->is_predicate && p->ampersandPred != NULL) { +/* MR11 */ Predicate *pred=p->ampersandPred; +/* MR11 */ if (k <= pred->k) { +/* MR11 */ REACH(p->guardNodes,k,rk,a); +/* MR11 */ return a; +/* MR11 */ }; +/* MR11 */ }; + + /* it might be a good idea when doing an MR_AmbSourceSearch + to *not* look behind predicates under some circumstances + we'll look into that later + */ + + REACH(p->next, k, rk, a); /* ignore actions */ + return a; +} + + /* A m b i g u i t y R e s o l u t i o n */ + + +void +#ifdef __USE_PROTOS +dumpAmbigMsg( set *fset, FILE *f, int want_nls ) +#else +dumpAmbigMsg( fset, f, want_nls ) +set *fset; +FILE *f; +int want_nls; +#endif +{ + int i; + + set copy; /* MR11 */ + + if ( want_nls ) fprintf(f, "\n\t"); + else fprintf(f, " "); + + for (i=1; i<=CLL_k; i++) + { + copy=set_dup(fset[i]); /* MR11 */ + + if ( i>1 ) + { + if ( !want_nls ) fprintf(f, ", "); + } + if ( set_deg(copy) > 3 && elevel == 1 ) + { + int e,m; + fprintf(f, "{"); + for (m=1; m<=3; m++) + { + e=set_int(copy); + fprintf(f, " %s", TerminalString(e)); + set_rm(e, copy); + } + fprintf(f, " ... }"); + } + else s_fprT(f, copy); + if ( want_nls ) fprintf(f, "\n\t"); + set_free(copy); + } + fprintf(f, "\n"); + +} + +static void +#ifdef __USE_PROTOS +verify_context(Predicate *predicate) +#else +verify_context(predicate) +Predicate *predicate; +#endif +{ + if ( predicate == NULL ) return; + + if ( predicate->expr == PRED_OR_LIST || + predicate->expr == PRED_AND_LIST ) + { + verify_context(predicate->down); + verify_context(predicate->right); /* MR10 */ + return; + } + + if ( !predicate->source->ctxwarned && predicate->source->guardpred==NULL && + ((predicate->k > 1 && + !is_single_tuple(predicate->tcontext)) || + ( predicate->k == 1 && + set_deg(predicate->scontext[1])>1 )) ) + { + +/* MR9 Suppress annoying messages caused by our own clever(?) fix */ + + fprintf(stderr, ErrHdr, FileStr[predicate->source->file], + predicate->source->line); + fprintf(stderr, " warning: predicate applied for >1 lookahead %d-sequences\n", predicate->k); + fprintf(stderr, ErrHdr, FileStr[predicate->source->file], + predicate->source->line); + fprintf(stderr, " predicate text: \"%s\"\n", + (predicate->expr == NULL ? "(null)" : predicate->expr) ); + fprintf(stderr, ErrHdr, FileStr[predicate->source->file], + predicate->source->line); + fprintf(stderr, " You may only want one lookahead %d-sequence to apply\n", predicate->k); + fprintf(stderr, ErrHdr, FileStr[predicate->source->file], + predicate->source->line); + fprintf(stderr, " Try using a context guard '(...)? =>'\n"); + predicate->source->ctxwarned = 1; + } + verify_context(predicate->right); /* MR10 */ +} + +/* + * If delta is the set of ambiguous lookahead sequences, then make sure that + * the predicate(s) for productions alt1,alt2 cover the sequences in delta. + * + * For example, + * a : <>? (A B|A C) + * | b + * ; + * b : <>? A B + * | A C + * ; + * + * This should give a warning that (A C) predicts both productions and alt2 + * does not have a predicate in the production that generates (A C). + * + * The warning detection is simple. Let delta = LOOK(alt1) intersection LOOK(alt2). + * Now, if ( delta set-difference context(predicates-for-alt1) != empty then + * alt1 does not "cover" all ambiguous sequences. + * + * If ambig is nonempty, then ambig in LL(k) sense -> use tree info; else use fset + * info. Actually, sets are used only if k=1 for this grammar. + */ +static void +#ifdef __USE_PROTOS +ensure_predicates_cover_ambiguous_lookahead_sequences + ( Junction *alt1, Junction *alt2, char *sub, Tree *ambig ) +#else +ensure_predicates_cover_ambiguous_lookahead_sequences( alt1, alt2, sub, ambig ) +Junction *alt1; +Junction *alt2; +char *sub; +Tree *ambig; +#endif +{ + if ( !ParseWithPredicates ) return; + + if ( ambig!=NULL ) + { + Tree *non_covered = NULL; + if ( alt1->predicate!=NULL ) + non_covered = tdif(ambig, alt1->predicate, alt1->fset, alt2->fset); + if ( (non_covered!=NULL || alt1->predicate==NULL) && WarningLevel>1 ) + { + fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line); + fprintf(stderr, " warning: alt %d %shas no predicate to resolve ambiguity", + alt1->altnum, sub); + if ( alt1->predicate!=NULL && non_covered!=NULL ) + { + fprintf(stderr, " upon"); + preorder(non_covered); + } + else if ( alt1->predicate==NULL ) + { + fprintf(stderr, " upon"); + preorder(ambig->down); + } + fprintf(stderr, "\n"); + } + Tfree(non_covered); + non_covered = NULL; + if ( alt2->predicate!=NULL ) + non_covered = tdif(ambig, alt2->predicate, alt1->fset, alt2->fset); + if ( (non_covered!=NULL || alt2->predicate==NULL) && WarningLevel>1 ) + { + fprintf(stderr, ErrHdr, FileStr[alt2->file], alt2->line); + fprintf(stderr, " warning: alt %d %shas no predicate to resolve ambiguity", + alt2->altnum, sub); + if ( alt2->predicate!=NULL && non_covered!=NULL ) + { + fprintf(stderr, " upon"); + preorder(non_covered); + } + else if ( alt2->predicate==NULL ) + { + fprintf(stderr, " upon"); + preorder(ambig->down); + } + fprintf(stderr, "\n"); + } + Tfree(non_covered); + } + else if ( !set_nil(alt1->fset[1]) ) + { + set delta, non_covered; + delta = set_and(alt1->fset[1], alt2->fset[1]); + non_covered = set_dif(delta, covered_set(alt1->predicate)); + if ( set_deg(non_covered)>0 && WarningLevel>1 ) + { + fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line); + fprintf(stderr, " warning: alt %d %shas no predicate to resolve ambiguity", + alt1->altnum, sub); + if ( alt1->predicate!=NULL ) + { + fprintf(stderr, " upon "); + s_fprT(stderr, non_covered); + } + fprintf(stderr, "\n"); + } + set_free( non_covered ); + non_covered = set_dif(delta, covered_set(alt2->predicate)); + if ( set_deg(non_covered)>0 && WarningLevel>1 ) + { + fprintf(stderr, ErrHdr, FileStr[alt2->file], alt2->line); + fprintf(stderr, " warning: alt %d %shas no predicate to resolve ambiguity", + alt2->altnum, sub); + if ( alt2->predicate!=NULL ) + { + fprintf(stderr, " upon "); + s_fprT(stderr, non_covered); + } + fprintf(stderr, "\n"); + } + set_free( non_covered ); + set_free( delta ); + } + else fatal_internal("productions have no lookahead in predicate checking routine"); +} + +#ifdef __USE_PROTOS +void MR_doPredicatesHelp(int inGuessBlock,Junction *alt1,Junction *alt2,int jtype,char *sub) +#else +void MR_doPredicatesHelp(inGuessBlock,alt1,alt2,jtype,sub) + int inGuessBlock; + Junction *alt1; + Junction *alt2; + int jtype; + char *sub; +#endif +{ + Predicate *p1; + Predicate *p2; + + Junction *parentRule=MR_nameToRuleBlk(alt1->rname); + + if (inGuessBlock && WarningLevel <= 1) return; + + /* let antlr give the usual error message */ + + if (alt1->predicate == NULL && alt2->predicate == NULL) return; + + if ( (jtype == RuleBlk || jtype == aSubBlk) + && (alt1->predicate == NULL && alt2->predicate != NULL)) { + fprintf(stderr, ErrHdr, FileStr[parentRule->file],parentRule->line); + fprintf(stderr," warning: alt %d line %d and alt %d line %d of %s\n%s%s%s", + alt1->altnum, + alt1->line, + alt2->altnum, + alt2->line, + sub, + " These alts have ambig lookahead sequences resolved by a predicate for\n", + " the second choice. The second choice may not be reachable.\n", + " You may want to use a complementary predicate or rearrange the alts\n" + ); + return; + }; + + /* first do the easy comparison. then do the hard one */ + + if (MR_comparePredicates(alt1->predicate,alt2->predicate)) { + + if (jtype == aLoopBegin || jtype == aPlusBlk ) { + + /* I'm not sure this code is reachable. + Predicates following a (...)+ or (...)* block are probably + considered validation predicates and therefore not + participate in the predication expression + */ + + fprintf(stderr, ErrHdr,FileStr[parentRule->file],parentRule->line); + fprintf(stderr," warning: %s of %s in rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s", + "the predicates used to disambiguate optional/exit paths of ", + sub, + CurRule, + FileStr[alt1->file], + alt1->altnum, + alt1->line, + alt2->altnum, + alt2->line, + " are identical and have no resolving power\n"); + } else { + fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line); + fprintf(stderr," warning: %s rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s", + "the predicates used to disambiguate", + CurRule, + FileStr[alt1->file], + alt1->altnum, + alt1->line, + alt2->altnum, + alt2->line, + " are identical and have no resolving power\n"); + }; + } else { + p1=predicate_dup_without_context(alt1->predicate); + p1=MR_unfold(p1); + MR_clearPredEntry(p1); + MR_simplifyInverted(p1,0); + p1=MR_predSimplifyALL(p1); + p2=predicate_dup_without_context(alt2->predicate); + p2=MR_unfold(p2); + MR_clearPredEntry(p2); + MR_simplifyInverted(p2,0); + p2=MR_predSimplifyALL(p2); + if (MR_comparePredicates(p1,p2)) { + if (jtype == aLoopBegin || jtype == aPlusBlk ) { + fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line); + fprintf(stderr," warning: %s of %s in rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s%s", + "the predicates used to disambiguate optional/exit paths of ", + sub, + CurRule, + FileStr[alt1->file], + alt1->altnum, + alt1->line, + alt2->altnum, + alt2->line, + " are identical when compared without context and may have no\n", + " resolving power for some lookahead sequences.\n"); + } else { + fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line); + fprintf(stderr," warning: %s rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s%s", + "the predicates used to disambiguate", + CurRule, + FileStr[alt1->file], + alt1->altnum, + alt1->line, + alt2->altnum, + alt2->line, + " are identical when compared without context and may have no\n", + " resolving power for some lookahead sequences.\n"); + }; + if (InfoP) { + fprintf(output,"\n#if 0\n\n"); + fprintf(output,"The following predicates are identical when compared without\n"); + fprintf(output," lookahead context information. For some ambiguous lookahead\n"); + fprintf(output," sequences they may not have any power to resolve the ambiguity.\n"); + fprintf(output,"\n"); + + fprintf(output,"Choice 1: %s alt %d line %d file %s\n\n", + MR_ruleNamePlusOffset( (Node *) alt1), + alt1->altnum, + alt1->line, + FileStr[alt1->file]); + fprintf(output," The original predicate for choice 1 with available context information:\n\n"); + MR_dumpPred1(2,alt1->predicate,1); + fprintf(output," The predicate for choice 1 after expansion (but without context information):\n\n"); + MR_dumpPred1(2,p1,0); + if (p1 == NULL) { + Predicate *phelp; + fprintf(output," The predicate for choice 1 after expansion (but before simplification)\n\n"); + phelp=predicate_dup_without_context(alt1->predicate); + phelp=MR_unfold(phelp); + MR_clearPredEntry(phelp); + MR_simplifyInverted(phelp,0); + phelp=MR_predSimplifyALLX(phelp,1); + MR_dumpPred1(2,phelp,0); + predicate_free(phelp); + }; + fprintf(output,"\n"); + + fprintf(output,"Choice 2: %s alt %d line %d file %s\n\n", + MR_ruleNamePlusOffset( (Node *) alt2), + alt2->altnum, + alt2->line, + FileStr[alt2->file]); + fprintf(output," The original predicate for choice 2 with available context information:\n\n"); + MR_dumpPred1(1,alt2->predicate,1); + fprintf(output," The predicate for choice 2 after expansion (but without context information):\n\n"); + MR_dumpPred1(1,p2,0); + if (p2 == NULL) { + Predicate *phelp; + fprintf(output," The predicate for choice 2 after expansion (but before simplification)\n\n"); + phelp=predicate_dup_without_context(alt2->predicate); + phelp=MR_unfold(phelp); + MR_clearPredEntry(phelp); + MR_simplifyInverted(phelp,0); + phelp=MR_predSimplifyALLX(phelp,1); + MR_dumpPred1(2,phelp,0); + predicate_free(phelp); + }; + fprintf(output,"\n#endif\n"); + }; + } else if (MR_secondPredicateUnreachable(p1,p2)) { + if (jtype == aLoopBegin || jtype == aPlusBlk ) { + fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line); + fprintf(stderr," warning: %s of %s in rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s%s", + "the predicate used to disambiguate the first choice of the optional/exit paths of ", + sub, + CurRule, + FileStr[alt1->file], + alt1->altnum, + alt1->line, + alt2->altnum, + alt2->line, + " appears to \"cover\" the second predicate when compared without context.\n", + " The second predicate may have no resolving power for some lookahead sequences.\n"); + } else { + fprintf(stderr, ErrHdr, FileStr[parentRule->file], parentRule->line); + fprintf(stderr," warning: %s rule %s\n (file %s alt %d line %d and alt %d line %d)\n%s%s", + "the predicate used to disambiguate the first choice of", + CurRule, + FileStr[alt1->file], + alt1->altnum, + alt1->line, + alt2->altnum, + alt2->line, + " appears to \"cover\" the second predicate when compared without context.\n", + " The second predicate may have no resolving power for some lookahead sequences.\n"); + }; + if (InfoP) { + fprintf(output,"\n#if 0\n\n"); + fprintf(output,"The first predicate appears to \"cover\" the second predicate when they\n"); + fprintf(output," are compared without lookahead context information. For some ambiguous\n"); + fprintf(output," lookahead sequences the second predicate may not have any power to\n"); + fprintf(output," resolve the ambiguity.\n"); + fprintf(output,"\n"); + fprintf(output,"Choice 1: %s alt %d line %d file %s\n\n", + MR_ruleNamePlusOffset( (Node *) alt1), + alt1->altnum, + alt1->line, + FileStr[alt1->file]); + fprintf(output," The original predicate for choice 1 with available context information:\n\n"); + MR_dumpPred1(2,alt1->predicate,1); + fprintf(output," The predicate for choice 1 after expansion (but without context information):\n\n"); + MR_dumpPred1(2,p1,0); + if (p1 == NULL) { + Predicate *phelp; + fprintf(output," The predicate for choice 1 after expansion (but before simplification)\n\n"); + phelp=predicate_dup_without_context(alt1->predicate); + phelp=MR_unfold(phelp); + MR_clearPredEntry(phelp); + MR_simplifyInverted(phelp,0); + phelp=MR_predSimplifyALLX(phelp,1); + MR_dumpPred1(2,phelp,0); + predicate_free(phelp); + }; + fprintf(output,"\n"); + + fprintf(output,"Choice 2: %s alt %d line %d file %s\n\n", + MR_ruleNamePlusOffset( (Node *) alt2), + alt2->altnum, + alt2->line, + FileStr[alt2->file]); + fprintf(output," The original predicate for choice 2 with available context information:\n\n"); + MR_dumpPred1(1,alt2->predicate,1); + fprintf(output," The predicate for choice 2 after expansion (but without context information):\n\n"); + MR_dumpPred1(1,p2,0); + if (p2 == NULL) { + Predicate *phelp; + fprintf(output," The predicate for choice 2 after expansion (but before simplification)\n\n"); + phelp=predicate_dup_without_context(alt2->predicate); + phelp=MR_unfold(phelp); + MR_clearPredEntry(phelp); + MR_simplifyInverted(phelp,0); + phelp=MR_predSimplifyALLX(phelp,1); + MR_dumpPred1(2,phelp,0); + predicate_free(phelp); + }; + fprintf(output,"\n#endif\n"); + }; + }; + predicate_free(p1); + predicate_free(p2); + }; +} + +static int totalOverflow=0; /* MR9 */ + +void +#ifdef __USE_PROTOS +HandleAmbiguity( Junction *block, Junction *alt1, Junction *alt2, int jtype ) +#else +HandleAmbiguity( block, alt1, alt2, jtype ) +Junction *block; +Junction *alt1; +Junction *alt2; +int jtype; +#endif +{ + unsigned **ftbl; + set *fset, b; + int i, numAmbig,n2; + Tree *ambig=NULL, *t, *u; + char *sub = ""; + long n; + int thisOverflow=0; /* MR9 */ + long set_deg_value; /* MR10 */ + long threshold; /* MR10 */ + + require(block!=NULL, "NULL block"); + require(block->ntype==nJunction, "invalid block"); + + /* These sets are used to constrain LL_k set, but are made CLL_k long anyway */ + fset = (set *) calloc(CLL_k+1, sizeof(set)); + require(fset!=NULL, "cannot allocate fset"); + ftbl = (unsigned **) calloc(CLL_k+1, sizeof(unsigned *)); + require(ftbl!=NULL, "cannot allocate ftbl"); + + /* create constraint table and count number of possible ambiguities (use<=LL_k) */ + for (n=1,i=1; i<=CLL_k; i++) + { + b = set_and(alt1->fset[i], alt2->fset[i]); +/* MR9 */ set_deg_value = set_deg(b); +/* MR10 */ if (n > 0) { +/* MR10 */ threshold = LONG_MAX / n; +/* MR10 */ if (set_deg_value <= threshold) { +/* MR10 */ n *= set_deg_value; +/* MR10 */ } else { +/* MR10 */ n=LONG_MAX; +/* MR9 */ if (totalOverflow == 0) { +#if 0 + /* MR10 comment this out because it just makes users worry */ + +/* MR9 */ warnNoFL("Overflow in computing number of possible ambiguities in HandleAmbiguity\n"); +#endif +/* MR9 */ }; +/* MR9 */ thisOverflow++; +/* MR9 */ totalOverflow++; +/* MR9 */ }; +/* MR10 */ } else { +/* MR10 */ n *= set_deg_value; +/* MR9 */ }; + fset[i] = set_dup(b); + ftbl[i] = set_pdq(b); + set_free(b); + } + + switch ( jtype ) + { + case aSubBlk: sub = "of (..) "; break; + case aOptBlk: sub = "of {..} "; break; + case aLoopBegin: sub = "of (..)* "; break; + case aLoopBlk: sub = "of (..)* "; break; + case aPlusBlk: sub = "of (..)+ "; break; + case RuleBlk: sub = "of the rule itself "; break; + default : sub = ""; break; + } + + /* If the block is marked as a compressed lookahead only block, then + * simply return; ambiguity warning is given only at warning level 2. + */ + if ( block->approx>0 ) + { + if ( ParseWithPredicates ) + { + if (alt1->predicate != NULL) predicate_free(alt1->predicate); /* MR12 */ + if (alt2->predicate != NULL) predicate_free(alt2->predicate); /* MR12 */ + + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + alt1->predicate = MR_find_predicates_and_supp((Node *)alt1->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + require (MR_predicate_context_completed(alt1->predicate),"predicate alt 1 not completed"); + alt1->predicate=MR_predSimplifyALL(alt1->predicate); + + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + alt2->predicate = MR_find_predicates_and_supp((Node *)alt2->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + require (MR_predicate_context_completed(alt2->predicate),"predicate alt 2 not completed"); + alt2->predicate=MR_predSimplifyALL(alt2->predicate); + + MR_doPredicatesHelp(0,alt1,alt2,jtype,sub); + + if ( HoistPredicateContext + && (alt1->predicate!=NULL||alt2->predicate!=NULL) ) + { + verify_context(alt1->predicate); + verify_context(alt2->predicate); + } + + if ( HoistPredicateContext + && (alt1->predicate!=NULL||alt2->predicate!=NULL) + && WarningLevel>1 ) + ensure_predicates_cover_ambiguous_lookahead_sequences(alt1, alt2, sub, ambig); + } + + if ( WarningLevel>1 ) + { + fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line); + if ( jtype == aLoopBegin || jtype == aPlusBlk ) + fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub); + else + fprintf(stderr, " warning(approx): alts %d and %d %sambiguous upon", + alt1->altnum, alt2->altnum, sub); + dumpAmbigMsg(fset, stderr, 0); + MR_traceAmbSource(fset,alt1,alt2); + } + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); + return; + } + + /* if all sets have degree 1 for k=1 permutation; + * don't bother doing full LL(k) analysis. + * (This "if" block handles the LL(1) case) + */ + + n2 = 0; + for (i=1; ifset[i])+set_deg(alt2->fset[i]); + + /* here STARTS the special case in which the lookahead sets for alt1 and alt2 + all have degree 1 for kp1)!=NULL ) + { + if ( WarningLevel==1 ) + { + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); + return; + } + + fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line); + if ( jtype == aLoopBegin || jtype == aPlusBlk ) + fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub); + else + fprintf(stderr, " warning: alts %d and %d %sambiguous upon", + alt1->altnum, alt2->altnum, sub); + dumpAmbigMsg(fset, stderr, 0); + MR_traceAmbSource(fset,alt1,alt2); + } + + ambig = NULL; + if ( LL_k>1 ) ambig = make_tree_from_sets(alt1->fset, alt2->fset); + if ( ParseWithPredicates ) + { + if (alt1->predicate != NULL) predicate_free(alt1->predicate); /* MR12 */ + if (alt2->predicate != NULL) predicate_free(alt2->predicate); /* MR12 */ + + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + alt1->predicate = MR_find_predicates_and_supp((Node *)alt1->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + require (MR_predicate_context_completed(alt1->predicate),"predicate alt 1 not completed"); + alt1->predicate=MR_predSimplifyALL(alt1->predicate); + + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + alt2->predicate = MR_find_predicates_and_supp((Node *)alt2->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + require (MR_predicate_context_completed(alt2->predicate),"predicate alt 2 not completed"); + alt2->predicate=MR_predSimplifyALL(alt2->predicate); + + MR_doPredicatesHelp(0,alt1,alt2,jtype,sub); + + if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) ) + { + verify_context(alt1->predicate); + verify_context(alt2->predicate); + } + if (HoistPredicateContext&&(alt1->predicate!=NULL||alt2->predicate!=NULL) && WarningLevel>1) + ensure_predicates_cover_ambiguous_lookahead_sequences(alt1, alt2, sub, ambig); + if ( WarningLevel == 1 && + (alt1->predicate!=NULL||alt2->predicate!=NULL)) + { + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); + Tfree(ambig); + return; + } + } +/* end TJP (10/24/93) */ + + fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line); + if ( jtype == aLoopBegin || jtype == aPlusBlk ) + fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub); + else + fprintf(stderr, " warning: alts %d and %d %sambiguous upon", + alt1->altnum, alt2->altnum, sub); + if ( elevel == 3 && LL_k>1 ) + { + preorder(ambig); + fprintf(stderr, "\n"); + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); + Tfree(ambig); + return; + }; + + Tfree(ambig); + dumpAmbigMsg(fset, stderr, 0); + + /* because this is a special case in which both alt1 and alt2 have + lookahead sets of degree 1 for kaltnum; + CurAmbigAlt2 = alt2->altnum; + CurAmbigbtype = sub; + CurAmbigfile = alt1->file; + CurAmbigline = alt1->line; + + /* Don't do full LL(n) analysis if (...)? block because the block, + by definition, defies LL(n) analysis. + If guess (...)? block and ambiguous then don't remove anything from + 2nd alt to resolve ambig. + Want to predict with LL sup 1 ( n ) decision not LL(n) if guess block + since it is much cheaper than LL(n). LL sup 1 ( n ) "covers" the LL(n) + lookahead information. + + Note: LL(n) context cannot be computed for semantic predicates when + followed by (..)?. + + If (..)? then we scream "AAAHHHH! No LL(n) analysis will help" + + Is 'ambig' always defined if we enter this if? I hope so + because the 'ensure...()' func references it. TJP Nov 1993. + */ + + /* THM MR30: Instead of using first_item_is_guss_block we use + first_item_is_guess_block_extra which will look inside a + loop block for a guess block. In other words ( (...)? )*. + It there is an ambiguity in this circumstance then we suppress + the normal methods of resolving ambiguities. + */ + + if ( first_item_is_guess_block_extra((Junction *)alt1->p1)!=NULL ) + { + if ( ParseWithPredicates ) + { + if (alt1->predicate != NULL) predicate_free(alt1->predicate); /* MR12 */ + if (alt2->predicate != NULL) predicate_free(alt2->predicate); /* MR12 */ + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + alt1->predicate = MR_find_predicates_and_supp((Node *)alt1->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + require (MR_predicate_context_completed(alt1->predicate),"predicate alt 1 not completed"); + alt1->predicate=MR_predSimplifyALL(alt1->predicate); + + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + alt2->predicate = MR_find_predicates_and_supp((Node *)alt2->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + require (MR_predicate_context_completed(alt2->predicate),"predicate alt 2 not completed"); + alt2->predicate=MR_predSimplifyALL(alt2->predicate); + + MR_doPredicatesHelp(1,alt1,alt2,jtype,sub); + + if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) ) + { + verify_context(alt1->predicate); + verify_context(alt2->predicate); + } + if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) && WarningLevel>1 ) + ensure_predicates_cover_ambiguous_lookahead_sequences(alt1, alt2, sub, ambig); + if ( WarningLevel==1 && + (alt1->predicate!=NULL||alt2->predicate!=NULL)) + { + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); + return; + } + } + + if ( WarningLevel>1 ) + { + fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line); + if ( jtype == aLoopBegin || jtype == aPlusBlk ) + fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub); + else + fprintf(stderr, " warning: alts %d and %d %sambiguous upon", + alt1->altnum, alt2->altnum, sub); + dumpAmbigMsg(fset, stderr, 0); + MR_traceAmbSource(fset,alt1,alt2); + } + + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); + return; + } + + /* Not resolved with (..)? block. Do full LL(n) analysis */ + + /* ambig is the set of k-tuples truly in common between alt 1 and alt 2 */ + /* MR11 VerifyAmbig once used fset destructively */ + + ambig = VerifyAmbig(alt1, alt2, ftbl, fset, &t, &u, &numAmbig); + + /* are all things in intersection really ambigs? */ + + if (thisOverflow || numAmbig < n ) /* MR9 */ + { + Tree *v; + + /* remove ambig permutation from 2nd alternative to resolve ambig; + * We want to compute the set of artificial tuples, arising from + * LL sup 1 (n) compression, that collide with real tuples from the + * 2nd alternative. This is the set of "special case" tuples that + * the LL sup 1 (n) decision template maps incorrectly. + */ + + /* when generating code in genExpr() it does + * + * if ( genExprSets(j->fset) && !genExprTree(j->ftree)) {... + * + * Sooooo the j->ftree is the tree of alt2 + * after removal of conflicts, not alt1 ! + */ + + if ( ambig!=NULL ) + { + /* at the top of ambig is an ALT node */ + + for (v=ambig->down; v!=NULL; v=v->right) + { + u = trm_perm(u, v); /* remove v FROM u */ + } +/* fprintf(stderr, "after rm alt2:"); preorder(u); fprintf(stderr, "\n");*/ + } + Tfree( t ); + alt1->ftree = tappend(alt1->ftree, u); + alt1->ftree = tleft_factor(alt1->ftree); + } + + if ( ambig==NULL ) + { + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); + return; + } + + ambig = tleft_factor(ambig); + +/* TJP: + * At this point, we surely have an LL(k) ambiguity. Check for predicates + */ + if ( ParseWithPredicates ) + { + if (alt1->predicate != NULL) predicate_free(alt1->predicate); /* MR12 */ + if (alt2->predicate != NULL) predicate_free(alt2->predicate); /* MR12 */ + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + alt1->predicate = MR_find_predicates_and_supp((Node *)alt1->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + require (MR_predicate_context_completed(alt1->predicate),"predicate alt 1 not completed"); + alt1->predicate=MR_predSimplifyALL(alt1->predicate); + + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + alt2->predicate = MR_find_predicates_and_supp((Node *)alt2->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + require (MR_predicate_context_completed(alt2->predicate),"predicate alt 2 not completed"); + alt2->predicate=MR_predSimplifyALL(alt2->predicate); + + MR_doPredicatesHelp(0,alt1,alt2,jtype,sub); + + if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) ) + { + verify_context(alt1->predicate); + verify_context(alt2->predicate); + } + if ( HoistPredicateContext && (alt1->predicate!=NULL||alt2->predicate!=NULL) && WarningLevel>1 ) + ensure_predicates_cover_ambiguous_lookahead_sequences(alt1, alt2, sub, ambig); + if ( WarningLevel==1 && + (alt1->predicate!=NULL||alt2->predicate!=NULL)) + { + + /* We found at least one pred for at least one of the alts; + * If warnings are low, just return. + */ + + Tfree(ambig); + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); + return; + } + /* else we're gonna give a warning */ + } +/* end TJP addition */ + + fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line); + if ( jtype == aLoopBegin || jtype == aPlusBlk ) + fprintf(stderr, " warning: optional/exit path and alt(s) %sambiguous upon", sub); + else + fprintf(stderr, " warning: alts %d and %d %sambiguous upon", + alt1->altnum, alt2->altnum, sub); + if ( elevel == 3 ) + { + preorder(ambig->down); /* <===== k>1 ambiguity message data */ + fprintf(stderr, "\n"); + } else { + MR_skipped_e3_report=1; + dumpAmbigMsg(fset, stderr, 0); + }; + + MR_traceAmbSourceK(ambig,alt1,alt2); /* <====== k>1 ambiguity aid */ + + Tfree(ambig); + + for (i=1; i<=CLL_k; i++) set_free( fset[i] ); + free((char *)fset); + for (i=1; i<=CLL_k; i++) free( (char *)ftbl[i] ); + free((char *)ftbl); +} + +/* Don't analyze alpha block of (alpha)?beta; if (alpha)? then analyze + * Return the 1st node of the beta block if present else return j. + */ +Junction * +#ifdef __USE_PROTOS +analysis_point( Junction *j ) +#else +analysis_point( j ) +Junction *j; +#endif +{ + Junction *gblock; + + /* MR13b When there was an action/predicate preceding a guess block + the guess block became invisible at the analysis_point. + + first_item_is_guess_block accepts any kind of node, + despite the fact that the formal is a junction. But + I don't want to have to change it all over the place + until I know it works. + */ + + if ( j->ntype != nJunction && j->ntype != nAction) return j; + + gblock = first_item_is_guess_block((Junction *)j); + + if ( gblock!=NULL ) + { + Junction *past = gblock->end; + Junction *p; + require(past!=NULL, "analysis_point: no end block on (...)? block"); + + for (p=(Junction *)past->p1; p!=NULL; ) + { + if ( p->ntype==nAction ) + { + p=(Junction *)((ActionNode *)p)->next; + continue; + } + if ( p->ntype!=nJunction ) + { + past->alpha_beta_guess_end=1; /* MR14 */ + return (Junction *)past->p1; + } + if ( p->jtype==EndBlk || p->jtype==EndRule ) + { + return j; + } +/* MR6 */ +/* MR6 A guess block is of the form "(alpha)? beta" or "(alpha)?". */ +/* MR6 When beta is omitted (second form) this means "(alpha)? alpha". */ +/* MR6 The program does not store another copy of alpha in this case. */ +/* MR6 During analysis when the program needs to know what follows the */ +/* MR6 guess clause. It calls this routine. */ +/* MR6 */ +/* MR6 If it is of the form "(alpha)? beta" it returns a pointer to beta.*/ +/* MR6 */ +/* MR6 If it is of the form "(alpha)?" it returns a pointer to the guess */ +/* MR6 block itself thereby reusing the junction tree. */ +/* MR6 */ +/* MR6 It works by searching the "next in sequence" chain (skipping actions) */ +/* MR6 searching for a RuleRef or Token node. (Those are the only 4 kinds */ +/* MR6 of nodes: Junctions, RuleRef, Token, and Action.) */ +/* MR6 */ +/* MR6 This won't work for the special case "(alpha)? ()" because it has no */ +/* MR6 rule references or token nodes. It eventually encounters a */ +/* MR6 junction of type EndBlk or EndRule and says to its caller: nothing */ +/* MR6 more here to analyze - must be of the form "(alpha)?". */ +/* MR6 */ +/* MR6 In the case of "(alpha)? ()" it should return a pointer to "()" */ +/* MR6 */ +/* MR6 I think. */ +/* MR6 */ + if ( p->jtype!=Generic) { /* MR6 */ + past->alpha_beta_guess_end=1; /* MR14 */ + return (Junction *)past->p1; /* MR6 */ + }; /* MR6 */ + p=(Junction *)p->p1; + } + } + return j; +} + +set +#ifdef __USE_PROTOS +First( Junction *j, int k, int jtype, int *max_k ) +#else +First( j, k, jtype, max_k ) +Junction *j; +int k; +int jtype; +int *max_k; +#endif +{ + Junction *alt1, *alt2; + set a, rk, fCurBlk; + int savek; + int p1, p2; + + int save_maintainBackTrace; + + require(j->ntype==nJunction, "First: non junction passed"); + + /* C o m p u t e F I R S T s e t w i t h k l o o k a h e a d */ + fCurBlk = rk = empty; + for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2 ) + { + Junction * p = NULL; + Junction * p1junction = NULL; + p = analysis_point((Junction *)alt1->p1); + p1junction = (Junction *) (alt1->p1); +#if 0 + if (p != p1junction) { + fprintf(stdout,"Analysis point for #%d is #%d", p1junction->seq, p->seq); /* debug */ + } +#endif + REACH(p, k, &rk, alt1->fset[k]); + require(set_nil(rk), "rk != nil"); + set_free(rk); + set_orin(&fCurBlk, alt1->fset[k]); + } + + /* D e t e c t A m b i g u i t i e s */ + *max_k = 1; + for (p1=1,alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2, p1++) + { + for (p2=1,alt2=(Junction *)alt1->p2; alt2!=NULL; alt2 = (Junction *)alt2->p2, p2++) + { + savek = k; + a = set_and(alt1->fset[k], alt2->fset[k]); + while ( !set_nil(a) ) + { + /* if we have hit the max k requested, just give warning */ + if ( j->approx==k ) { + } + + if ( k==CLL_k ) + { +#ifdef NOT_USED +*** int save_LL_k = LL_k; +*** int save_CLL_k = CLL_k; +*** /* Get new LL_k from interactive feature if enabled */ +*** if ( AImode ) +*** AmbiguityDialog(j, jtype, alt1, alt2, &CLL_k, &LL_k); +#endif + *max_k = CLL_k; + save_maintainBackTrace=MR_MaintainBackTrace; + if (AlphaBetaTrace) MR_MaintainBackTrace=0; + HandleAmbiguity(j, alt1, alt2, jtype); + MR_MaintainBackTrace=save_maintainBackTrace; + break; + } + else + { + Junction *p = analysis_point((Junction *)alt1->p1); + Junction *q = analysis_point((Junction *)alt2->p1); + k++; /* attempt ambig alts again with more lookahead */ + + REACH(p, k, &rk, alt1->fset[k]); + require(set_nil(rk), "rk != nil"); + REACH(q, k, &rk, alt2->fset[k]); + require(set_nil(rk), "rk != nil"); + set_free(a); + a = set_and(alt1->fset[k], alt2->fset[k]); + if ( k > *max_k ) *max_k = k; + } + } + set_free(a); + k = savek; + } + } + + return fCurBlk; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/fset2.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/fset2.c new file mode 100644 index 00000000..273a25ba --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/fset2.c @@ -0,0 +1,2250 @@ +/* + * fset2.c + * + * Compute FIRST sets for full LL(k) + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include "pcctscfg.h" +#include + +#ifdef PCCTS_USE_STDARG +#include +#else +#include +#endif + +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" + +/* ick! globals. Used by permute() to track which elements of a set have been used */ + +static int *findex; +set *fset; /* MR11 make global */ +static unsigned **ftbl; +static set *constrain; /* pts into fset. constrains tToken() to 'constrain' */ +int ConstrainSearch; +int maxk; /* set to initial k upon tree construction request */ + /* MR11 make global */ +static Tree *FreeList = NULL; + +#ifdef __USE_PROTOS +static int tmember_of_context(Tree *, Predicate *); +#else +static int tmember_of_context(); +#endif + +#ifdef TREE_DEBUG /* VBox: +def */ +set set_of_tnodes_in_use; +int stop_on_tnode_seq_number=(-1); /* (-1) to disable */ +#endif + +/* Do root + * Then each sibling + */ + +void +#ifdef __USE_PROTOS +preorder( Tree *tree ) +#else +preorder( tree ) +Tree *tree; +#endif +{ + if ( tree == NULL ) return; + if ( tree->down != NULL ) fprintf(stderr, " ("); + if ( tree->token == ALT ) fprintf(stderr, " ALT"); + else fprintf(stderr, " %s", TerminalString(tree->token)); + if ( tree->token==EpToken ) fprintf(stderr, "(%d)", tree->v.rk); + preorder(tree->down); + if ( tree->down != NULL ) fprintf(stderr, " )"); + preorder(tree->right); +} + +#ifdef __USE_PROTOS +int MR_tree_matches_constraints(int k,set * constrain,Tree *t) +#else +int MR_tree_matches_constraints(k,constrain,t) + int k; + set * constrain; + Tree * t; +#endif +{ + int i; + Tree *u; + + if (k == 0) return 1; + + /* for testing guard predicates: if the guard tree is shorter + than the constraint then it is a match. The reason is that + a guard of (A B) should be equivalent to a guard of (A B . . .) + where "." matches every token. Thus a match which runs out + of tree before constraint is a match. + */ + + if (t == NULL) return 1; + require (set_deg(constrain[0]) == 1, + "MR_tree_matches_constraints: set_deg != 1"); + i=set_int(constrain[0]); + if (t->token != i) return 0; + if (k-1 == 0) return 1; + for (u=t->down; u != NULL; u=u->right) { + if (MR_tree_matches_constraints(k-1,&constrain[1],u)) { + return 1; + }; + }; + return 0; +} + +/* check the depth of each primary sibling to see that it is exactly + * k deep. e.g.; + * + * ALT + * | + * A ------- B + * | | + * C -- D E + * + * Remove all branches <= k deep. + * + * Added by TJP 9-23-92 to make the LL(k) constraint mechanism to work. + */ + +static int pruneCount=0; +static int prunePeak=200; + +Tree * +#ifdef __USE_PROTOS +prune( Tree *t, int k ) +#else +prune( t, k ) +Tree *t; +int k; +#endif +{ + pruneCount++; + if (pruneCount > prunePeak+100) { + prunePeak=pruneCount; +#if 0 +*** fprintf(stderr,"pruneCount=%d\n",pruneCount); +/*** preorder(t); ***/ +*** fprintf(stderr,"\n",pruneCount); +#endif + }; + if ( t == NULL ) { + pruneCount--; + return NULL; + }; + if ( t->token == ALT ) fatal_internal("prune: ALT node in FIRST tree"); + if ( t->right!=NULL ) t->right = prune(t->right, k); + if ( k>1 ) + { + if ( t->down!=NULL ) t->down = prune(t->down, k-1); + if ( t->down == NULL ) + { + Tree *r = t->right; + t->right = NULL; + Tfree(t); + pruneCount--; + return r; + } + } + pruneCount--; + return t; +} + +/* build a tree (root child1 child2 ... NULL) */ +#ifdef PCCTS_USE_STDARG +Tree *tmake(Tree *root, ...) +#else +Tree *tmake(va_alist) +va_dcl +#endif +{ + Tree *w; + va_list ap; + Tree *child, *sibling=NULL, *tail=NULL; +#ifndef PCCTS_USE_STDARG + Tree *root; +#endif + +#ifdef PCCTS_USE_STDARG + va_start(ap, root); +#else + va_start(ap); + root = va_arg(ap, Tree *); +#endif + child = va_arg(ap, Tree *); + while ( child != NULL ) + { +#ifdef DUM + /* added "find end of child" thing TJP March 1994 */ + for (w=child; w->right!=NULL; w=w->right) {;} /* find end of child */ +#else + w = child; +#endif + + if ( sibling == NULL ) {sibling = child; tail = w;} + else {tail->right = child; tail = w;} + child = va_arg(ap, Tree *); + } + + /* was "root->down = sibling;" */ + if ( root==NULL ) root = sibling; + else root->down = sibling; + + va_end(ap); + return root; +} + +Tree * +#ifdef __USE_PROTOS +tnode( int tok ) +#else +tnode( tok ) +int tok; +#endif +{ + Tree *p, *newblk; + static int n=0; + + if ( FreeList == NULL ) + { + /*fprintf(stderr, "tnode: %d more nodes\n", TreeBlockAllocSize);*/ + if ( TreeResourceLimit > 0 ) + { + if ( (n+TreeBlockAllocSize) >= TreeResourceLimit ) + { + fprintf(stderr, ErrHdr, FileStr[CurAmbigfile], CurAmbigline); + fprintf(stderr, " hit analysis resource limit while analyzing alts %d and %d %s\n", + CurAmbigAlt1, + CurAmbigAlt2, + CurAmbigbtype); + exit(PCCTS_EXIT_FAILURE); + } + } + newblk = (Tree *)calloc(TreeBlockAllocSize, sizeof(Tree)); + if ( newblk == NULL ) + { + fprintf(stderr, ErrHdr, FileStr[CurAmbigfile], CurAmbigline); + fprintf(stderr, " out of memory while analyzing alts %d and %d %s\n", + CurAmbigAlt1, + CurAmbigAlt2, + CurAmbigbtype); + exit(PCCTS_EXIT_FAILURE); + } + n += TreeBlockAllocSize; + for (p=newblk; p<&(newblk[TreeBlockAllocSize]); p++) + { + p->right = FreeList; /* add all new Tree nodes to Free List */ + FreeList = p; + } + } + p = FreeList; + FreeList = FreeList->right; /* remove a tree node */ + p->right = NULL; /* zero out ptrs */ + p->down = NULL; + p->token = tok; + + TnodesAllocated++; /* MR10 */ + TnodesInUse++; /* MR10 */ + if (TnodesInUse > TnodesPeak) TnodesPeak=TnodesInUse; /* MR10 */ + +#ifdef TREE_DEBUG + require(!p->in_use, "tnode: node in use!"); + p->in_use = 1; + p->seq=TnodesAllocated; + set_orel( (unsigned) TnodesAllocated,&set_of_tnodes_in_use); + if (stop_on_tnode_seq_number == p->seq) { + fprintf(stderr,"\n*** just allocated tnode #%d ***\n", + stop_on_tnode_seq_number); + }; +#endif + return p; +} + +static Tree * +#ifdef __USE_PROTOS +eofnode( int k ) +#else +eofnode( k ) +int k; +#endif +{ + Tree *t=NULL; + int i; + + for (i=1; i<=k; i++) + { + t = tmake(tnode((TokenInd!=NULL?TokenInd[EofToken]:EofToken)), t, NULL); + } + return t; +} + + + +void +#ifdef __USE_PROTOS +_Tfree( Tree *t ) +#else +_Tfree( t ) +Tree *t; +#endif +{ + if ( t!=NULL ) + { +#ifdef TREE_DEBUG + if (t->seq == stop_on_tnode_seq_number) { + fprintf(stderr,"\n*** just freed tnode #%d ***\n",t->seq); + }; + require(t->in_use, "_Tfree: node not in use!"); + t->in_use = 0; + set_rm( (unsigned) t->seq,set_of_tnodes_in_use); +#endif + t->right = FreeList; + FreeList = t; + TnodesInUse--; /* MR10 */ + } +} + +/* tree duplicate */ +Tree * +#ifdef __USE_PROTOS +tdup( Tree *t ) +#else +tdup( t ) +Tree *t; +#endif +{ + Tree *u; + + if ( t == NULL ) return NULL; + u = tnode(t->token); + u->v.rk = t->v.rk; + u->right = tdup(t->right); + u->down = tdup(t->down); + return u; +} + +/* tree duplicate (assume tree is a chain downwards) */ +Tree * +#ifdef __USE_PROTOS +tdup_chain( Tree *t ) +#else +tdup_chain( t ) +Tree *t; +#endif +{ + Tree *u; + + if ( t == NULL ) return NULL; + u = tnode(t->token); + u->v.rk = t->v.rk; + u->down = tdup(t->down); + return u; +} + +Tree * +#ifdef __USE_PROTOS +tappend( Tree *t, Tree *u ) +#else +tappend( t, u ) +Tree *t; +Tree *u; +#endif +{ + Tree *w; + +/*** fprintf(stderr, "tappend("); + *** preorder(t); fprintf(stderr, ","); + *** preorder(u); fprintf(stderr, " )\n"); +*/ + if ( t == NULL ) return u; + if ( t->token == ALT && t->right == NULL ) return tappend(t->down, u); + for (w=t; w->right!=NULL; w=w->right) {;} + w->right = u; + return t; +} + +/* dealloc all nodes in a tree */ +void +#ifdef __USE_PROTOS +Tfree( Tree *t ) +#else +Tfree( t ) +Tree *t; +#endif +{ + if ( t == NULL ) return; + Tfree( t->down ); + Tfree( t->right ); + _Tfree( t ); +} + +/* find all children (alts) of t that require remaining_k nodes to be LL_k + * tokens long. + * + * t-->o + * | + * a1--a2--...--an <-- LL(1) tokens + * | | | + * b1 b2 ... bn <-- LL(2) tokens + * | | | + * . . . + * . . . + * z1 z2 ... zn <-- LL(LL_k) tokens + * + * We look for all [Ep] needing remaining_k nodes and replace with u. + * u is not destroyed or actually used by the tree (a copy is made). + */ +Tree * +#ifdef __USE_PROTOS +tlink( Tree *t, Tree *u, int remaining_k ) +#else +tlink( t, u, remaining_k ) +Tree *t; +Tree *u; +int remaining_k; +#endif +{ + Tree *p; + require(remaining_k!=0, "tlink: bad tree"); + + if ( t==NULL ) return NULL; + /*fprintf(stderr, "tlink: u is:"); preorder(u); fprintf(stderr, "\n");*/ + if ( t->token == EpToken && t->v.rk == remaining_k ) + { + require(t->down==NULL, "tlink: invalid tree"); + if ( u == NULL ) { +/* MR10 */ Tree *tt=t->right; +/* MR10 */ _Tfree(t); +/* MR10 */ return tt; + }; + p = tdup( u ); + p->right = t->right; + _Tfree( t ); + return p; + } + t->down = tlink(t->down, u, remaining_k); + t->right = tlink(t->right, u, remaining_k); + return t; +} + +/* remove as many ALT nodes as possible while still maintaining semantics */ +Tree * +#ifdef __USE_PROTOS +tshrink( Tree *t ) +#else +tshrink( t ) +Tree *t; +#endif +{ + if ( t == NULL ) return NULL; + t->down = tshrink( t->down ); + t->right = tshrink( t->right ); + if ( t->down == NULL ) + { + if ( t->token == ALT ) + { + Tree *u = t->right; + _Tfree(t); + return u; /* remove useless alts */ + } + return t; + } + + /* (? (ALT (? ...)) s) ==> (? (? ...) s) where s = sibling, ? = match any */ + if ( t->token == ALT && t->down->right == NULL) + { + Tree *u = t->down; + u->right = t->right; + _Tfree( t ); + return u; + } + /* (? (A (ALT t)) s) ==> (? (A t) s) where A is a token; s,t siblings */ + if ( t->token != ALT && t->down->token == ALT && t->down->right == NULL ) + { + Tree *u = t->down->down; + _Tfree( t->down ); + t->down = u; + return t; + } + return t; +} + +Tree * +#ifdef __USE_PROTOS +tflatten( Tree *t ) +#else +tflatten( t ) +Tree *t; +#endif +{ + if ( t == NULL ) return NULL; + t->down = tflatten( t->down ); + t->right = tflatten( t->right ); + if ( t->down == NULL ) return t; + + if ( t->token == ALT ) + { + Tree *u; + /* find tail of children */ + for (u=t->down; u->right!=NULL; u=u->right) {;} + u->right = t->right; + u = t->down; + _Tfree( t ); + return u; + } + return t; +} + +Tree * +#ifdef __USE_PROTOS +tJunc( Junction *p, int k, set *rk ) +#else +tJunc( p, k, rk ) +Junction *p; +int k; +set *rk; +#endif +{ + Tree *t=NULL, *u=NULL; + Junction *alt; + Tree *tail=NULL, *r; + +#ifdef DBG_TRAV + fprintf(stderr, "tJunc(%d): %s in rule %s\n", k, + decodeJType[p->jtype], ((Junction *)p)->rname); +#endif + +/* MR14 */ if (AlphaBetaTrace && p->alpha_beta_guess_end) { +/* MR14 */ warnFL( +/* MR14 */ "not possible to compute follow set for alpha in an \"(alpha)? beta\" block. ", +/* MR14 */ FileStr[p->file],p->line); +/* MR14 */ MR_alphaBetaTraceReport(); +/* MR14 */ }; + +/* MR14 */ if (p->alpha_beta_guess_end) { +/* MR14 */ return NULL; +/* MR14 */ } + + if ( p->jtype==aLoopBlk || p->jtype==RuleBlk || + p->jtype==aPlusBlk || p->jtype==aSubBlk || p->jtype==aOptBlk ) + { + if ( p->jtype!=aSubBlk && p->jtype!=aOptBlk ) { + require(p->lock!=NULL, "rJunc: lock array is NULL"); + if ( p->lock[k] ) return NULL; + p->lock[k] = TRUE; + } + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p); +/* MR10 */ }; + + TRAV(p->p1, k, rk, tail); + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack); +/* MR10 */ }; + + if ( p->jtype==RuleBlk ) {p->lock[k] = FALSE; return tail;} + r = tmake(tnode(ALT), tail, NULL); + for (alt=(Junction *)p->p2; alt!=NULL; alt = (Junction *)alt->p2) + { + /* if this is one of the added optional alts for (...)+ then break */ + if ( alt->ignore ) break; + + if ( tail==NULL ) {TRAV(alt->p1, k, rk, tail); r->down = tail;} + else + { +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p); +/* MR10 */ }; + + TRAV(alt->p1, k, rk, tail->right); + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack); +/* MR10 */ }; + if ( tail->right != NULL ) tail = tail->right; + } + } + if ( p->jtype!=aSubBlk && p->jtype!=aOptBlk ) p->lock[k] = FALSE; +#ifdef DBG_TREES + fprintf(stderr, "blk(%s) returns:",((Junction *)p)->rname); preorder(r); fprintf(stderr, "\n"); +#endif + if ( r->down == NULL ) {_Tfree(r); return NULL;} + return r; + } + + if ( p->jtype==EndRule ) + { + if ( p->halt ) /* don't want FOLLOW here? */ + { +/**** if ( ContextGuardTRAV ) return NULL; ****/ + set_orel( (unsigned) k, rk); /* indicate this k value needed */ /* MR10 cast */ + t = tnode(EpToken); + t->v.rk = k; + return t; + } + require(p->lock!=NULL, "rJunc: lock array is NULL"); + if ( p->lock[k] ) return NULL; + /* if no FOLLOW assume k EOF's */ + if ( p->p1 == NULL ) return eofnode(k); + p->lock[k] = TRUE; + } + +/* MR14 */ if (p->p1 != NULL && p->guess && p->guess_analysis_point == NULL) { +/* MR14 */ Node * guess_point; +/* MR14 */ guess_point=(Node *)analysis_point(p); +/* MR14 */ if (guess_point == (Node *)p) { +/* MR14 */ guess_point=p->p1; +/* MR14 */ } +/* MR14 */ p->guess_analysis_point=guess_point; +/* MR14 */ } + + if ( p->p2 == NULL ) + { + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p); +/* MR10 */ }; + +/* M14 */ if (p->guess_analysis_point != NULL) { +/* M14 */ TRAV(p->guess_analysis_point, k, rk,t); +/* M14 */ } else { + TRAV(p->p1, k, rk,t); +/* M14 */ } + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack); +/* MR10 */ }; + + if ( p->jtype==EndRule ) p->lock[k]=FALSE; + return t; + } + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (p->jtype != Generic) MR_pointerStackPush(&MR_BackTraceStack,p); +/* MR10 */ }; + +/* M14 */ if (p->guess_analysis_point != NULL) { +/* M14 */ TRAV(p->guess_analysis_point, k, rk,t); +/* M14 */ } else { + TRAV(p->p1, k, rk,t); +/* M14 */ } + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (p->jtype != Generic) MR_pointerStackPop(&MR_BackTraceStack); +/* MR10 */ }; + + if ( p->jtype!=RuleBlk && /* MR14 */ !p->guess) TRAV(p->p2, k, rk, u); + + if ( p->jtype==EndRule ) p->lock[k] = FALSE;/* unlock node */ + + if ( t==NULL ) return tmake(tnode(ALT), u, NULL); + return tmake(tnode(ALT), t, u, NULL); +} + +Tree * +#ifdef __USE_PROTOS +tRuleRef( RuleRefNode *p, int k, set *rk_out ) +#else +tRuleRef( p, k, rk_out ) +RuleRefNode *p; +int k; +set *rk_out; +#endif +{ + int k2; + Tree *t=NULL, *u=NULL; + Junction *r; + set rk, rk2; + int save_halt; + RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text); + +#ifdef DBG_TRAV + fprintf(stderr, "tRuleRef: %s\n", p->text); +#endif + if ( q == NULL ) + { + TRAV(p->next, k, rk_out, t);/* ignore undefined rules */ + return t; + } + rk = rk2 = empty; + if (RulePtr == NULL) fatal("RulePtr==NULL"); + r = RulePtr[q->rulenum]; + if ( r->lock[k] ) return NULL; + save_halt = r->end->halt; + r->end->halt = TRUE; /* don't let reach fall off end of rule here */ + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ MR_pointerStackPush(&MR_BackTraceStack,p); +/* MR10 */ }; + + TRAV(r, k, &rk, t); + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ MR_pointerStackPop(&MR_BackTraceStack); +/* MR10 */ }; + + r->end->halt = save_halt; +#ifdef DBG_TREES + fprintf(stderr, "after ruleref, t is:"); preorder(t); fprintf(stderr, "\n"); +#endif + t = tshrink( t ); + while ( !set_nil(rk) ) { /* any k left to do? if so, link onto tree */ + k2 = set_int(rk); + set_rm(k2, rk); + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ MR_pointerStackPush(&MR_BackTraceStack,p); +/* MR10 */ }; + + TRAV(p->next, k2, &rk2, u); + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ MR_pointerStackPop(&MR_BackTraceStack); +/* MR10 */ }; + + t = tlink(t, u, k2); /* any alts missing k2 toks, add u onto end */ + Tfree(u); /* MR10 */ + } + set_free(rk); /* rk is empty, but free its memory */ + set_orin(rk_out, rk2); /* remember what we couldn't do */ + set_free(rk2); + return t; +} + +Tree * +#ifdef __USE_PROTOS +tToken( TokNode *p, int k, set *rk ) +#else +tToken( p, k, rk ) +TokNode *p; +int k; +set *rk; +#endif +{ + Tree *t=NULL, *tset=NULL, *u; + + if (ConstrainSearch) { + if (MR_AmbSourceSearch) { + require(constrain>=fset&&constrain<=&(fset[CLL_k]),"tToken: constrain is not a valid set"); + } else { + require(constrain>=fset&&constrain<=&(fset[LL_k]),"tToken: constrain is not a valid set"); + }; + constrain = &fset[maxk-k+1]; + } + +#ifdef DBG_TRAV + fprintf(stderr, "tToken(%d): %s\n", k, TerminalString(p->token)); + if ( ConstrainSearch ) { + fprintf(stderr, "constrain is:"); s_fprT(stderr, *constrain); fprintf(stderr, "\n"); + } +#endif + + /* is it a meta token (set of tokens)? */ + + if ( !set_nil(p->tset) ) + { + unsigned e=0; + set a; + Tree *n, *tail = NULL; + + if ( ConstrainSearch ) { + a = set_and(p->tset, *constrain); + if (set_nil(a)) { /* MR10 */ + set_free(a); /* MR11 */ + return NULL; /* MR10 */ + }; /* MR10 */ + } else { + a = set_dup(p->tset); + }; + + for (; !set_nil(a); set_rm(e, a)) + { + e = set_int(a); + n = tnode(e); + if ( tset==NULL ) { tset = n; tail = n; } + else { tail->right = n; tail = n; } + } + set_free( a ); + } + else if ( ConstrainSearch && !set_el(p->token, *constrain) ) + { +/* fprintf(stderr, "ignoring token %s(%d)\n", TerminalString(p->token), + k);*/ + return NULL; + } + else { + tset = tnode( p->token ); + }; + +/* MR10 */ if (MR_MaintainBackTrace) { +/* MR10 */ if (k == 1) { +/* MR10 */ MR_pointerStackPush(&MR_BackTraceStack,p); +/* MR13 */ if (MR_SuppressSearch) { +/* MR13 */ MR_suppressSearchReport(); +/* MR13 */ } else { +/* MR10 */ MR_backTraceReport(); +/* MR13 */ }; +/* MR10 */ MR_pointerStackPop(&MR_BackTraceStack); +/* MR11 */ Tfree(tset); +/* MR11 */ return NULL; +/* MR10 */ }; +/* MR10 */ }; + + if ( k == 1 ) return tset; + + if (MR_MaintainBackTrace) { + MR_pointerStackPush(&MR_BackTraceStack,p); + }; + + TRAV(p->next, k-1, rk, t); + + if (MR_MaintainBackTrace) { + Tfree(t); + Tfree(tset); + MR_pointerStackPop(&MR_BackTraceStack); + return NULL; + }; + + /* here, we are positive that, at least, this tree will not contribute + * to the LL(2) tree since it will be too shallow, IF t==NULL. + * If doing a context guard walk, then don't prune. + */ + if ( t == NULL && !ContextGuardTRAV ) /* tree will be too shallow */ + { + if ( tset!=NULL ) Tfree( tset ); + return NULL; + } +#ifdef DBG_TREES + fprintf(stderr, "tToken(%d)->next:",k); preorder(t); fprintf(stderr, "\n"); +#endif + + /* if single token root, then just make new tree and return */ + /* MR10 - set_nil(p->tset) isn't a good test because of ConstraintSearch */ + + if (tset->right == NULL) return tmake(tset, t, NULL); /* MR10 */ + + /* here we must make a copy of t as a child of each element of the tset; + * e.g., "T1..T3 A" would yield ( nil ( T1 A ) ( T2 A ) ( T3 A ) ) + */ + for (u=tset; u!=NULL; u=u->right) + { + /* make a copy of t and hook it onto bottom of u */ + u->down = tdup(t); + } + Tfree( t ); +#ifdef DBG_TREES + fprintf(stderr, "range is:"); preorder(tset); fprintf(stderr, "\n"); +#endif + return tset; +} + +Tree * +#ifdef __USE_PROTOS +tAction( ActionNode *p, int k, set *rk ) +#else +tAction( p, k, rk ) +ActionNode *p; +int k; +set *rk; +#endif +{ + Tree *t=NULL; + set *save_fset=NULL; + int i; + + /* fprintf(stderr, "tAction\n"); */ + +/* An MR_SuppressSearch is looking for things that can be + reached even when the predicate is false. + + There are three kinds of predicates: + plain: r1: <

>? r2 + guarded: r1: (A)? => <

>? r2 + ampersand style: r1: (A)? && <

>? r2 + + Of the three kinds of predicates, only a guard predicate + has things which are reachable even when the predicate + is false. To be reachable the constraint must *not* + match the guard. + +*/ + + if (p->is_predicate && MR_SuppressSearch) { + + Predicate *pred=p->guardpred; + + if (pred == NULL) { + t=NULL; + goto EXIT; + }; + constrain = &fset[maxk-k+1]; + if (pred->k == 1) { + set dif; + dif=set_dif(*constrain,pred->scontext[1]); + if (set_nil(dif)) { + set_free(dif); + t=NULL; + goto EXIT; + }; + set_free(dif); + } else { + if (MR_tree_matches_constraints(k,constrain,pred->tcontext)) { + t=NULL; + goto EXIT; + }; + } + }; + + /* The ampersand predicate differs from the + other predicates because its first set + is a subset of the first set behind the predicate + + r1: (A)? && <

>? r2 ; + r2: A | B; + + In this case first[1] of r1 is A, even + though first[1] of r2 is {A B}. + */ + + if (p->is_predicate && p->ampersandPred != NULL) { + + Predicate *pred=p->ampersandPred; + Tree *tAND; + Tree *tset; + + if (k <= pred->k) { + if (MR_MaintainBackTrace) MR_pointerStackPush(&MR_BackTraceStack,p); + TRAV(p->guardNodes,k,rk,t); + if (MR_MaintainBackTrace) MR_pointerStackPop(&MR_BackTraceStack); + return t; + } else { + require (k>1,"tAction for ampersandpred: k <= 1"); + if (ConstrainSearch) { + if (MR_AmbSourceSearch) { + require(constrain>=fset&&constrain<=&(fset[CLL_k]), + "tToken: constrain is not a valid set"); + } else { + require(constrain>=fset&&constrain<=&(fset[LL_k]), + "tToken: constrain is not a valid set"); + }; + save_fset=(set *) calloc (CLL_k+1,sizeof(set)); + require (save_fset != NULL,"tAction save_fset alloc"); + for (i=1; i <= CLL_k ; i++) { + save_fset[i]=set_dup(fset[i]); + }; + if (pred->k == 1) { + constrain = &fset[maxk-k+1]; + set_andin(constrain,pred->scontext[1]); + if (set_nil(*constrain)) { + t=NULL; + goto EXIT; + }; + } else { + constrain = &fset[maxk-k+1]; + if (! MR_tree_matches_constraints(pred->k,constrain,pred->tcontext)) { + t=NULL; + goto EXIT; + }; /* end loop on i */ + }; /* end loop on pred scontext/tcontext */ + }; /* end if on k > pred->k */ + }; /* end if on constrain search */ + + TRAV(p->next,k,rk,t); + + if (t != NULL) { + t=tshrink(t); + t=tflatten(t); + t=tleft_factor(t); + if (pred->tcontext != NULL) { + tAND=MR_computeTreeAND(t,pred->tcontext); + } else { + tset=MR_make_tree_from_set(pred->scontext[1]); + tAND=MR_computeTreeAND(t,tset); + Tfree(tset); + }; + Tfree(t); + t=tAND; + }; + goto EXIT; + + }; /* end if on ampersand predicate */ + + TRAV(p->next,k,rk,t); + +EXIT: + if (save_fset != NULL) { + for (i=1 ; i <= CLL_k ; i++) { + set_free(fset[i]); + fset[i]=save_fset[i]; + }; + free ( (char *) save_fset); + }; + return t; +} + +/* see if e exists in s as a possible input permutation (e is always a chain) */ + +int +#ifdef __USE_PROTOS +tmember( Tree *e, Tree *s ) +#else +tmember( e, s ) +Tree *e; +Tree *s; +#endif +{ + if ( e==NULL||s==NULL ) return 0; +/** fprintf(stderr, "tmember("); +*** preorder(e); fprintf(stderr, ","); +*** preorder(s); fprintf(stderr, " )\n"); +*/ + if ( s->token == ALT && s->right == NULL ) return tmember(e, s->down); + if ( e->token!=s->token ) + { + if ( s->right==NULL ) return 0; + return tmember(e, s->right); + } + if ( e->down==NULL && s->down == NULL ) return 1; + if ( tmember(e->down, s->down) ) return 1; + if ( s->right==NULL ) return 0; + return tmember(e, s->right); +} + +/* see if e exists in s as a possible input permutation (e is always a chain); + * Only check s to the depth of e. In other words, 'e' can be a shorter + * sequence than s. + */ +int +#ifdef __USE_PROTOS +tmember_constrained( Tree *e, Tree *s) +#else +tmember_constrained( e, s ) +Tree *e; +Tree *s; +#endif +{ + if ( e==NULL||s==NULL ) return 0; +/** fprintf(stderr, "tmember_constrained("); +*** preorder(e); fprintf(stderr, ","); +*** preorder(s); fprintf(stderr, " )\n"); +**/ + if ( s->token == ALT && s->right == NULL ) + return tmember_constrained(e, s->down); + if ( e->token!=s->token ) + { + if ( s->right==NULL ) return 0; + return tmember_constrained(e, s->right); + } + if ( e->down == NULL ) return 1; /* if s is matched to depth of e return */ + if ( tmember_constrained(e->down, s->down) ) return 1; + if ( s->right==NULL ) return 0; + return tmember_constrained(e, s->right); +} + +/* combine (? (A t) ... (A u) ...) into (? (A t u)) */ +Tree * +#ifdef __USE_PROTOS +tleft_factor( Tree *t ) +#else +tleft_factor( t ) +Tree *t; +#endif +{ + Tree *u, *v, *trail, *w; + + /* left-factor what is at this level */ + if ( t == NULL ) return NULL; + for (u=t; u!=NULL; u=u->right) + { + trail = u; + v=u->right; + while ( v!=NULL ) + { + if ( u->token == v->token ) + { + if ( u->down!=NULL ) + { + for (w=u->down; w->right!=NULL; w=w->right) {;} + w->right = v->down; /* link children together */ + } + else u->down = v->down; + trail->right = v->right; /* unlink factored node */ + _Tfree( v ); + v = trail->right; + } + else {trail = v; v=v->right;} + } + } + /* left-factor what is below */ + for (u=t; u!=NULL; u=u->right) u->down = tleft_factor( u->down ); + return t; +} + +/* remove the permutation p from t if present */ +Tree * +#ifdef __USE_PROTOS +trm_perm( Tree *t, Tree *p ) +#else +trm_perm( t, p ) +Tree *t; +Tree *p; +#endif +{ + /* + fprintf(stderr, "trm_perm("); + preorder(t); fprintf(stderr, ","); + preorder(p); fprintf(stderr, " )\n"); + */ + if ( t == NULL || p == NULL ) return NULL; + if ( t->token == ALT ) + { + t->down = trm_perm(t->down, p); + if ( t->down == NULL ) /* nothing left below, rm cur node */ + { + Tree *u = t->right; + _Tfree( t ); + return trm_perm(u, p); + } + t->right = trm_perm(t->right, p); /* look for more instances of p */ + return t; + } + if ( p->token != t->token ) /* not found, try a sibling */ + { + t->right = trm_perm(t->right, p); + return t; + } + t->down = trm_perm(t->down, p->down); + if ( t->down == NULL ) /* nothing left below, rm cur node */ + { + Tree *u = t->right; + _Tfree( t ); + return trm_perm(u, p); + } + t->right = trm_perm(t->right, p); /* look for more instances of p */ + return t; +} + +/* add the permutation 'perm' to the LL_k sets in 'fset' */ +void +#ifdef __USE_PROTOS +tcvt( set *fset, Tree *perm ) +#else +tcvt( fset, perm ) +set *fset; +Tree *perm; +#endif +{ + if ( perm==NULL ) return; + set_orel(perm->token, fset); + tcvt(fset+1, perm->down); +} + +/* for each element of ftbl[k], make it the root of a tree with permute(ftbl[k+1]) + * as a child. + */ +Tree * +#ifdef __USE_PROTOS +permute( int k, int max_k ) +#else +permute( k, max_k ) +int k, max_k; +#endif +{ + Tree *t, *u; + + if ( k>max_k ) return NULL; + if ( ftbl[k][findex[k]] == nil ) return NULL; + t = permute(k+1, max_k); + if ( t==NULL&&k maxk will have to change. + */ +Tree * +#ifdef __USE_PROTOS +VerifyAmbig( Junction *alt1, Junction *alt2, unsigned **ft, set *fs, Tree **t, Tree **u, int *numAmbig ) +#else +VerifyAmbig( alt1, alt2, ft, fs, t, u, numAmbig ) +Junction *alt1; +Junction *alt2; +unsigned **ft; +set *fs; +Tree **t; +Tree **u; +int *numAmbig; +#endif +{ + set rk; + Tree *perm, *ambig=NULL; + Junction *p; + int k; + int tnodes_at_start=TnodesAllocated; + int tnodes_at_end; + int tnodes_used; + set *save_fs; + int j; + + save_fs=(set *) calloc(CLL_k+1,sizeof(set)); + require(save_fs != NULL,"save_fs calloc"); + + for (j=0; j <= CLL_k ; j++) save_fs[j]=set_dup(fs[j]); + + maxk = LL_k; /* NOTE: for now, we look for LL_k */ + ftbl = ft; + fset = fs; + constrain = &(fset[1]); + findex = (int *) calloc(LL_k+1, sizeof(int)); + if ( findex == NULL ) + { + fprintf(stderr, ErrHdr, FileStr[CurAmbigfile], CurAmbigline); + fprintf(stderr, " out of memory while analyzing alts %d and %d of %s\n", + CurAmbigAlt1, + CurAmbigAlt2, + CurAmbigbtype); + exit(PCCTS_EXIT_FAILURE); + } + for (k=1; k<=LL_k; k++) findex[k] = 0; + + rk = empty; + ConstrainSearch = 1; /* consider only tokens in ambig sets */ + + p = analysis_point((Junction *)alt1->p1); + TRAV(p, LL_k, &rk, *t); + *t = tshrink( *t ); + *t = tflatten( *t ); + *t = tleft_factor( *t ); /* MR10 */ + *t = prune(*t, LL_k); + *t = tleft_factor( *t ); + +/*** fprintf(stderr, "after shrink&flatten&prune&left_factor:"); preorder(*t); fprintf(stderr, "\n");*/ + if ( *t == NULL ) + { +/*** fprintf(stderr, "TreeIncomplete --> no LL(%d) ambiguity\n", LL_k);*/ + Tfree( *t ); /* kill if impossible to have ambig */ + *t = NULL; + } + + p = analysis_point((Junction *)alt2->p1); + + TRAV(p, LL_k, &rk, *u); + *u = tshrink( *u ); + *u = tflatten( *u ); + *t = tleft_factor( *t ); /* MR10 */ + *u = prune(*u, LL_k); + *u = tleft_factor( *u ); +/* fprintf(stderr, "after shrink&flatten&prune&lfactor:"); preorder(*u); fprintf(stderr, "\n");*/ + if ( *u == NULL ) + { +/* fprintf(stderr, "TreeIncomplete --> no LL(%d) ambiguity\n", LL_k);*/ + Tfree( *u ); + *u = NULL; + } + + for (k=1; k<=LL_k; k++) set_clr( fs[k] ); + + ambig = tnode(ALT); + k = 0; + if ( *t!=NULL && *u!=NULL ) + { + while ( (perm=permute(1,LL_k))!=NULL ) + { +/* fprintf(stderr, "chk perm:"); preorder(perm); fprintf(stderr, "\n");*/ + if ( tmember(perm, *t) && tmember(perm, *u) ) + { +/* fprintf(stderr, "ambig upon"); preorder(perm); fprintf(stderr, "\n");*/ + + k++; + perm->right = ambig->down; + ambig->down = perm; + tcvt(&(fs[1]), perm); + } + else Tfree( perm ); + } + } + + for (j=0; j <= CLL_k ; j++) fs[j]=save_fs[j]; + free( (char *) save_fs); + + tnodes_at_end=TnodesAllocated; + tnodes_used=tnodes_at_end - tnodes_at_start; + + if (TnodesReportThreshold > 0 && tnodes_used > TnodesReportThreshold) { + fprintf(stdout,"There were %d tuples whose ambiguity could not be resolved by full lookahead\n",k); + fprintf(stdout,"There were %d tnodes created to resolve ambiguity between:\n\n",tnodes_used); + fprintf(stdout," Choice 1: %s line %d file %s\n", + MR_ruleNamePlusOffset( (Node *) alt1),alt1->line,FileStr[alt1->file]); + fprintf(stdout," Choice 2: %s line %d file %s\n", + MR_ruleNamePlusOffset( (Node *) alt2),alt2->line,FileStr[alt2->file]); + for (j=1; j <= CLL_k ; j++) { + fprintf(stdout,"\n Intersection of lookahead[%d] sets:\n",j); + MR_dumpTokenSet(stdout,2,fs[j]); + }; + fprintf(stdout,"\n"); + }; + + *numAmbig = k; + if ( ambig->down == NULL ) {_Tfree(ambig); ambig = NULL;} + free( (char *)findex ); +/* fprintf(stderr, "final ambig:"); preorder(ambig); fprintf(stderr, "\n");*/ + return ambig; +} + +static Tree * +#ifdef __USE_PROTOS +bottom_of_chain( Tree *t ) +#else +bottom_of_chain( t ) +Tree *t; +#endif +{ + if ( t==NULL ) return NULL; + for (; t->down != NULL; t=t->down) {;} + return t; +} + +/* + * Make a tree from k sets where the degree of the first k-1 sets is 1. + */ +Tree * +#ifdef __USE_PROTOS +make_tree_from_sets( set *fset1, set *fset2 ) +#else +make_tree_from_sets( fset1, fset2 ) +set *fset1; +set *fset2; +#endif +{ + set inter; + int i; + Tree *t=NULL, *n, *u; + unsigned *p,*q; + require(LL_k>1, "make_tree_from_sets: LL_k must be > 1"); + + /* do the degree 1 sets first */ + for (i=1; i<=LL_k-1; i++) + { + inter = set_and(fset1[i], fset2[i]); + require(set_deg(inter)==1, "invalid set to tree conversion"); + n = tnode(set_int(inter)); + if (t==NULL) t=n; else tmake(t, n, NULL); + set_free(inter); + } + + /* now add the chain of tokens at depth k */ + u = bottom_of_chain(t); + inter = set_and(fset1[LL_k], fset2[LL_k]); + if ( (q=p=set_pdq(inter)) == NULL ) fatal_internal("Can't alloc space for set_pdq"); + /* first one is linked to bottom, then others are sibling linked */ + n = tnode(*p++); + u->down = n; + u = u->down; + while ( *p != nil ) + { + n = tnode(*p); + u->right = n; + u = u->right; + p++; + } + free((char *)q); + + return t; +} + +/* create and return the tree of lookahead k-sequences that are in t, but not + * in the context of predicates in predicate list p. + */ +Tree * +#ifdef __USE_PROTOS +tdif( Tree *ambig_tuples, Predicate *p, set *fset1, set *fset2 ) +#else +tdif( ambig_tuples, p, fset1, fset2 ) +Tree *ambig_tuples; +Predicate *p; +set *fset1; +set *fset2; +#endif +{ + unsigned **ft; + Tree *dif=NULL; + Tree *perm; + set b; + int i,k; + + if ( p == NULL ) return tdup(ambig_tuples); + + ft = (unsigned **) calloc(CLL_k+1, sizeof(unsigned *)); + require(ft!=NULL, "cannot allocate ft"); + for (i=1; i<=CLL_k; i++) + { + b = set_and(fset1[i], fset2[i]); + ft[i] = set_pdq(b); + set_free(b); + } + findex = (int *) calloc(LL_k+1, sizeof(int)); + if ( findex == NULL ) + { + fatal_internal("out of memory in tdif while checking predicates"); + } + for (k=1; k<=LL_k; k++) findex[k] = 0; + +#ifdef DBG_TRAV + fprintf(stderr, "tdif_%d[", p->k); + preorder(ambig_tuples); + fprintf(stderr, ","); + preorder(p->tcontext); + fprintf(stderr, "] ="); +#endif + + ftbl = ft; + while ( (perm=permute(1,p->k))!=NULL ) + { +#ifdef DBG_TRAV + fprintf(stderr, "test perm:"); preorder(perm); fprintf(stderr, "\n"); +#endif + if ( tmember_constrained(perm, ambig_tuples) && + !tmember_of_context(perm, p) ) + { +#ifdef DBG_TRAV + fprintf(stderr, "satisfied upon"); preorder(perm); fprintf(stderr, "\n"); +#endif + k++; + if ( dif==NULL ) dif = perm; + else + { + perm->right = dif; + dif = perm; + } + } + else Tfree( perm ); + } + +#ifdef DBG_TRAV + preorder(dif); + fprintf(stderr, "\n"); +#endif + + for (i=1; i<=CLL_k; i++) free( (char *)ft[i] ); + free((char *)ft); + free((char *)findex); + + return dif; +} + +/* is lookahead sequence t a member of any context tree for any + * predicate in p? + */ +static int +#ifdef __USE_PROTOS +tmember_of_context( Tree *t, Predicate *p ) +#else +tmember_of_context( t, p ) +Tree *t; +Predicate *p; +#endif +{ + for (; p!=NULL; p=p->right) + { + if ( p->expr==PRED_AND_LIST || p->expr==PRED_OR_LIST ) + return tmember_of_context(t, p->down); + if ( tmember_constrained(t, p->tcontext) ) return 1; + if ( tmember_of_context(t, p->down) ) return 1; + } + return 0; +} + +int +#ifdef __USE_PROTOS +is_single_tuple( Tree *t ) +#else +is_single_tuple( t ) +Tree *t; +#endif +{ + if ( t == NULL ) return 0; + if ( t->right != NULL ) return 0; + if ( t->down == NULL ) return 1; + return is_single_tuple(t->down); +} + + +/* MR10 Check that a context guard contains only allowed things */ +/* MR10 (mainly token references). */ + +#ifdef __USE_PROTOS +int contextGuardOK(Node *p,int h,int *hmax) +#else +int contextGuardOK(p,h,hmax) + Node *p; + int h; + int *hmax; +#endif +{ + Junction *j; + TokNode *tn; + + if (p == NULL) return 1; + if (p->ntype == nToken) { + h++; + if (h > *hmax) *hmax=h; + tn=(TokNode *)p; + if (tn->el_label != NULL) { + warnFL(eMsg1("a label (\"%s\") for a context guard element is meaningless",tn->el_label), + FileStr[p->file],p->line); + }; + return contextGuardOK( ( (TokNode *) p)->next,h,hmax); + } else if (p->ntype == nAction) { + goto Fail; + } else if (p->ntype == nRuleRef) { + goto Fail; + } else { + require (p->ntype == nJunction,"Unexpected ntype"); + j=(Junction *) p; + if (j->jtype != Generic && + j->jtype != aSubBlk && /* pretty sure this one is allowed */ +/**** j->jtype != aOptBlk && ****/ /* pretty sure this one is allowed */ /* MR11 not any more ! */ + j->jtype != EndBlk) { + errFL("A context guard may not contain an option block: {...} or looping block: (...)* or (...)+", + FileStr[p->file],p->line); + contextGuardOK(j->p1,h,hmax); + return 0; + }; + /* do both p1 and p2 so use | rather than || */ + return contextGuardOK(j->p2,h,hmax) | contextGuardOK(j->p1,h,hmax); + }; +Fail: + errFL("A context guard may contain only Token references - guard will be ignored", + FileStr[p->file],p->line); + contextGuardOK( ( (ActionNode *) p)->next,h,hmax); + return 0; +} + +/* + * Look at a (...)? generalized-predicate context-guard and compute + * either a lookahead set (k==1) or a lookahead tree for k>1. The + * k level is determined by the guard itself rather than the LL_k + * variable. For example, ( A B )? is an LL(2) guard and ( ID )? + * is an LL(1) guard. For the moment, you can only have a single + * tuple in the guard. Physically, the block must look like this + * --o-->TOKEN-->o-->o-->TOKEN-->o-- ... -->o-->TOKEN-->o-- + * An error is printed for any other type. + */ +Predicate * +#ifdef __USE_PROTOS +computePredFromContextGuard(Graph blk,int *msgDone) /* MR10 */ +#else +computePredFromContextGuard(blk,msgDone) /* MR10 */ + Graph blk; + int *msgDone; /* MR10 */ +#endif +{ + Junction *junc = (Junction *)blk.left, *p; + Tree *t=NULL; + Predicate *pred = NULL; + set scontext, rk; + int ok; + int hmax=0; + + require(junc!=NULL && junc->ntype == nJunction, "bad context guard"); + +/* MR10 Check for anything other than Tokens and generic junctions */ + + *msgDone=0; /* MR10 */ + ok=contextGuardOK( (Node *)junc,0,&hmax); /* MR10 */ + if (! ok) { /* MR10 */ + *msgDone=1; /* MR10 */ + return NULL; /* MR10 */ + }; /* MR10 */ + if (hmax == 0) { +errFL("guard is 0 tokens long",FileStr[junc->file],junc->line); /* MR11 */ + *msgDone=1; + return NULL; + }; + if (hmax > CLL_k) { /* MR10 */ +errFL(eMsgd2("guard is %d tokens long - lookahead is limited to max(k,ck)==%d", /* MR10 */ + hmax,CLL_k), /* MR10 */ + FileStr[junc->file],junc->line); /* MR10 */ + *msgDone=1; /* MR10 */ + return NULL; /* MR10 */ + }; /* MR10 */ + + rk = empty; + p = junc; + pred = new_pred(); + pred->k = hmax; /* MR10 should be CLL_k, not LLK ? */ + if (hmax > 1 ) /* MR10 was LL_k */ + { + ConstrainSearch = 0; + ContextGuardTRAV = 1; + TRAV(p, hmax, &rk, t); /* MR10 was LL_k */ + ContextGuardTRAV = 0; + set_free(rk); + t = tshrink( t ); + t = tflatten( t ); + t = tleft_factor( t ); +/* + fprintf(stderr, "ctx guard:"); + preorder(t); + fprintf(stderr, "\n"); +*/ + pred->tcontext = t; + } + else + { + REACH(p, 1, &rk, scontext); + require(set_nil(rk), "rk != nil"); + set_free(rk); +/* + fprintf(stderr, "LL(1) ctx guard is:"); + s_fprT(stderr, scontext); + fprintf(stderr, "\n"); +*/ + pred->scontext[1] = scontext; + } + + list_add(&ContextGuardPredicateList,pred); /* MR13 */ + + return pred; +} + +/* MR13 + When the context guard is originally computed the + meta-tokens are not known. +*/ + +#ifdef __USE_PROTOS +void recomputeContextGuard(Predicate *pred) +#else +void recomputeContextGuard(pred) + Predicate *pred; +#endif +{ + Tree * t=NULL; + set scontext; + set rk; + ActionNode * actionNode; + Junction * p; + + actionNode=pred->source; + require (actionNode != NULL,"context predicate's source == NULL"); + + p=actionNode->guardNodes; + require (p != NULL,"context predicate's guardNodes == NULL"); + + rk = empty; + if (pred->k > 1 ) + { + ConstrainSearch = 0; + ContextGuardTRAV = 1; + TRAV(p, pred->k, &rk, t); + ContextGuardTRAV = 0; + set_free(rk); + t = tshrink( t ); + t = tflatten( t ); + t = tleft_factor( t ); + Tfree(pred->tcontext); + pred->tcontext = t; + } + else + { + REACH(p, 1, &rk, scontext); + require(set_nil(rk), "rk != nil"); + set_free(rk); + set_free(pred->scontext[1]); + pred->scontext[1] = scontext; + } +} + +/* MR11 - had enough of flags yet ? */ + +int MR_AmbSourceSearch=0; +int MR_AmbSourceSearchGroup=0; +int MR_AmbSourceSearchChoice=0; +int MR_AmbSourceSearchLimit=0; +int MR_matched_AmbAidRule=0; + +static set *matchSets[2]={NULL,NULL}; +static int *tokensInChain=NULL; +static Junction *MR_AmbSourceSearchJ[2]; + +void MR_traceAmbSourceKclient() +{ + int i; + set *save_fset; + int save_ConstrainSearch; + set incomplete; + Tree *t; + + if (matchSets[0] == NULL) { + matchSets[0]=(set *) calloc (CLL_k+1,sizeof(set)); + require (matchSets[0] != NULL,"matchSets[0] alloc"); + matchSets[1]=(set *) calloc (CLL_k+1,sizeof(set)); + require (matchSets[1] != NULL,"matchSets[1] alloc"); + }; + + for (i=1 ; i <= MR_AmbSourceSearchLimit ; i++) { + set_clr(matchSets[0][i]); + set_orel( (unsigned) tokensInChain[i], + &matchSets[0][i]); + set_clr(matchSets[1][i]); + set_orel( (unsigned) tokensInChain[i], + &matchSets[1][i]); + }; + + save_fset=fset; + save_ConstrainSearch=ConstrainSearch; + + + + for (i=0 ; i < 2 ; i++) { + +#if 0 +** fprintf(stdout," Choice:%d Depth:%d ",i+1,MR_AmbSourceSearchLimit); +** fprintf(stdout,"("); +** for (j=1 ; j <= MR_AmbSourceSearchLimit ; j++) { +** if (j != 1) fprintf(stdout," "); +** fprintf(stdout,"%s",TerminalString(tokensInChain[j])); +** }; +** fprintf(stdout,")\n\n"); +#endif + + fset=matchSets[i]; + + MR_AmbSourceSearch=1; + MR_MaintainBackTrace=1; + MR_AmbSourceSearchChoice=i; + ConstrainSearch=1; + + maxk = MR_AmbSourceSearchLimit; + + incomplete=empty; + t=NULL; + + constrain = &(fset[1]); + MR_pointerStackReset(&MR_BackTraceStack); + + TRAV(MR_AmbSourceSearchJ[i],maxk,&incomplete,t); + + Tfree(t); + + require (set_nil(incomplete),"MR_traceAmbSourceK TRAV incomplete"); + require (MR_BackTraceStack.count == 0,"K: MR_BackTraceStack.count != 0"); + + set_free(incomplete); + }; + + ConstrainSearch=save_ConstrainSearch; + fset=save_fset; + MR_AmbSourceSearch=0; + MR_MaintainBackTrace=0; + MR_AmbSourceSearchChoice=0; +} + +#ifdef __USE_PROTOS +Tree *tTrunc(Tree *t,int depth) +#else +Tree *tTrunc(t,depth) + Tree *t; +#endif +{ + Tree *u; + + require ( ! (t == NULL && depth > 0),"tree too short"); + + if (depth == 0) return NULL; + + if (t->token == ALT) { + u=tTrunc(t->down,depth); + } else { + u=tnode(t->token); + u->down=tTrunc(t->down,depth-1); + }; + if (t->right != NULL) u->right=tTrunc(t->right,depth); + return u; +} + +#ifdef __USE_PROTOS +void MR_iterateOverTree(Tree *t,int chain[]) +#else +void MR_iterateOverTree(t,chain) + Tree *t; + int chain[]; +#endif +{ + if (t == NULL) return; + chain[0]=t->token; + if (t->down != NULL) { + MR_iterateOverTree(t->down,&chain[1]); + } else { + MR_traceAmbSourceKclient(); + }; + MR_iterateOverTree(t->right,&chain[0]); + chain[0]=0; +} + +#ifdef __USE_PROTOS +void MR_traceAmbSourceK(Tree *t,Junction *alt1,Junction *alt2) +#else +void MR_traceAmbSourceK(t,alt1,alt2) + Tree *t; + Junction *alt1; + Junction *alt2; +#endif +{ + int i; + int depth; + int maxDepth; + Tree *truncatedTree; + + if (MR_AmbAidRule == NULL) return; + + if ( ! ( + strcmp(MR_AmbAidRule,alt1->rname) == 0 || + strcmp(MR_AmbAidRule,alt2->rname) == 0 || + MR_AmbAidLine==alt1->line || + MR_AmbAidLine==alt2->line + ) + ) return; + + MR_matched_AmbAidRule++; + + /* there are no token sets in trees, only in TokNodes */ + + MR_AmbSourceSearchJ[0]=analysis_point( (Junction *) alt1->p1); + MR_AmbSourceSearchJ[1]=analysis_point( (Junction *) alt2->p1); + + if (tokensInChain == NULL) { + tokensInChain=(int *) calloc (CLL_k+1,sizeof(int)); + require (tokensInChain != NULL,"tokensInChain alloc"); + }; + + MR_AmbSourceSearchGroup=0; + + fprintf(stdout,"\n"); + fprintf(stdout," Ambiguity Aid "); + fprintf(stdout, + (MR_AmbAidDepth <= LL_k ? + "(-k %d -aa %s %s -aad %d)\n\n" : + "(-k %d -aa %s %s [-k value limits -aad %d])\n\n"), + LL_k, + MR_AmbAidRule, + (MR_AmbAidMultiple ? "-aam" : ""), + MR_AmbAidDepth); + + for (i=0 ; i < 2 ; i++) { + fprintf(stdout," Choice %d: %-25s line %d file %s\n", + (i+1), + MR_ruleNamePlusOffset( (Node *) MR_AmbSourceSearchJ[i]), + MR_AmbSourceSearchJ[i]->line, + FileStr[MR_AmbSourceSearchJ[i]->file]); + }; + + fprintf(stdout,"\n"); + + if (MR_AmbAidDepth < LL_k) { + maxDepth=MR_AmbAidDepth; + } else { + maxDepth=LL_k; + }; + + for (depth=1 ; depth <= maxDepth; depth++) { + MR_AmbSourceSearchLimit=depth; + if (depth < LL_k) { + truncatedTree=tTrunc(t,depth); + truncatedTree=tleft_factor(truncatedTree); + MR_iterateOverTree(truncatedTree,&tokensInChain[1]); /* <===== */ + Tfree(truncatedTree); + } else { + MR_iterateOverTree(t,tokensInChain); /* <===== */ + }; + fflush(stdout); + fflush(stderr); + }; + + fprintf(stdout,"\n"); + MR_AmbSourceSearch=0; + MR_MaintainBackTrace=0; + MR_AmbSourceSearchGroup=0; + MR_AmbSourceSearchChoice=0; + MR_AmbSourceSearchLimit=0; + +} + + +/* this if for k=1 grammars only + + this is approximate only because of the limitations of linear + approximation lookahead. Don't want to do a k=3 search when + the user only specified a ck=3 grammar +*/ + +#ifdef __USE_PROTOS +void MR_traceAmbSource(set *matchSets,Junction *alt1, Junction *alt2) +#else +void MR_traceAmbSource(matchSets,alt1,alt2) + set *matchSets; + Junction *alt1; + Junction *alt2; +#endif +{ + set *save_fset; + Junction *p[2]; + int i; + int j; + set *dup_matchSets; + set intersection; + set incomplete; + set tokensUsed; + int depth; + + if (MR_AmbAidRule == NULL) return; + if ( ! ( + strcmp(MR_AmbAidRule,alt1->rname) == 0 || + strcmp(MR_AmbAidRule,alt2->rname) == 0 || + MR_AmbAidLine==alt1->line || + MR_AmbAidLine==alt2->line + ) + ) return; + + MR_matched_AmbAidRule++; + + save_fset=fset; + + dup_matchSets=(set *) calloc(CLL_k+1,sizeof(set)); + require (dup_matchSets != NULL,"Can't allocate dup_matchSets"); + + p[0]=analysis_point( (Junction *) alt1->p1); + p[1]=analysis_point( (Junction *) alt2->p1); + + fprintf(stdout,"\n"); + + fprintf(stdout," Ambiguity Aid "); + fprintf(stdout, + (MR_AmbAidDepth <= CLL_k ? + "(-ck %d -aa %s %s -aad %d)\n\n" : + "(-ck %d -aa %s %s [-ck value limits -aad %d])\n\n"), + CLL_k, + MR_AmbAidRule, + (MR_AmbAidMultiple ? "-aam" : ""), + MR_AmbAidDepth); + + for (i=0 ; i < 2 ; i++) { + fprintf(stdout," Choice %d: %-25s line %d file %s\n", + (i+1), + MR_ruleNamePlusOffset( (Node *) p[i]), + p[i]->line,FileStr[p[i]->file]); + }; + + for (j=1; j <= CLL_k ; j++) { + fprintf(stdout,"\n Intersection of lookahead[%d] sets:\n",j); + intersection=set_and(alt1->fset[j],alt2->fset[j]); + MR_dumpTokenSet(stdout,2,intersection); + set_free(intersection); + }; + + fprintf(stdout,"\n"); + + require (1 <= MR_AmbAidDepth && MR_AmbAidDepth <= CLL_k, + "illegal MR_AmbAidDepth"); + + MR_AmbSourceSearchGroup=0; + for (depth=1; depth <= MR_AmbAidDepth; depth++) { + MR_AmbSourceSearchLimit=depth; + for (i=0 ; i < 2 ; i++) { + +/*** fprintf(stdout," Choice:%d Depth:%d\n\n",i+1,depth); ***/ + + for (j=0 ; j <= CLL_k ; j++) { dup_matchSets[j]=set_dup(matchSets[j]); }; + fset=dup_matchSets; + + fflush(output); + fflush(stdout); + + MR_AmbSourceSearch=1; + MR_MaintainBackTrace=1; + MR_AmbSourceSearchChoice=i; + + maxk = depth; + tokensUsed=empty; + incomplete=empty; + + constrain = &(fset[1]); + MR_pointerStackReset(&MR_BackTraceStack); + + REACH(p[i],depth,&incomplete,tokensUsed); + + fflush(output); + fflush(stdout); + + require (set_nil(incomplete),"MR_traceAmbSource REACH incomplete"); + require (MR_BackTraceStack.count == 0,"1: MR_BackTraceStack.count != 0"); + + set_free(incomplete); + set_free(tokensUsed); + + for (j=0 ; j <= CLL_k ; j++) { set_free(dup_matchSets[j]); }; + }; + }; + + fprintf(stdout,"\n"); + + MR_AmbSourceSearch=0; + MR_MaintainBackTrace=0; + MR_AmbSourceSearchGroup=0; + MR_AmbSourceSearchChoice=0; + MR_AmbSourceSearchLimit=0; + + fset=save_fset; + free ( (char *) dup_matchSets); +} + +static int itemCount; + +void MR_backTraceDumpItemReset() { + itemCount=0; +} + +#ifdef __USE_PROTOS +void MR_backTraceDumpItem(FILE *f,int skip,Node *n) +#else +void MR_backTraceDumpItem(f,skip,n) + FILE *f; + int skip; + Node *n; +#endif +{ + TokNode *tn; + RuleRefNode *rrn; + Junction *j; + ActionNode *a; + + switch (n->ntype) { + case nToken: + itemCount++; if (skip) goto EXIT; + tn=(TokNode *)n; + if (set_nil(tn->tset)) { + fprintf(f," %2d #token %-23s",itemCount,TerminalString(tn->token)); + } else { + fprintf(f," %2d #tokclass %-20s",itemCount,TerminalString(tn->token)); + }; + break; + case nRuleRef: + itemCount++; if (skip) goto EXIT; + rrn=(RuleRefNode *)n; + fprintf(f," %2d to %-27s",itemCount,rrn->text); + break; + case nAction: + a=(ActionNode *)n; + goto EXIT; + case nJunction: + + j=(Junction *)n; + + switch (j->jtype) { + case aSubBlk: + if (j->guess) { + itemCount++; if (skip) goto EXIT; + fprintf(f," %2d %-30s",itemCount,"in (...)? block at"); + break; + }; +/****** fprintf(f," %2d %-32s",itemCount,"in (...) block at"); *******/ +/****** break; *******/ + goto EXIT; + case aOptBlk: + itemCount++; if (skip) goto EXIT; + fprintf(f," %2d %-30s",itemCount,"in {...} block"); + break; + case aLoopBlk: + itemCount++; if (skip) goto EXIT; + fprintf(f," %2d %-30s",itemCount,"in (...)* block"); + break; + case EndBlk: + if (j->alpha_beta_guess_end) { + itemCount++; if (skip) goto EXIT; + fprintf(f," %2d %-30s",itemCount,"end (...)? block at"); + break; + }; + goto EXIT; +/****** fprintf(f," %2d %-32s",itemCount,"end of a block at"); *****/ +/****** break; *****/ + case RuleBlk: + itemCount++; if (skip) goto EXIT; + fprintf(f," %2d %-30s",itemCount,j->rname); + break; + case Generic: + goto EXIT; + case EndRule: + itemCount++; if (skip) goto EXIT; + fprintf (f," %2d end %-26s",itemCount,j->rname); + break; + case aPlusBlk: + itemCount++; if (skip) goto EXIT; + fprintf(f," %2d %-30s",itemCount,"in (...)+ block"); + break; + case aLoopBegin: + goto EXIT; + }; + break; + }; + fprintf(f," %-23s line %-4d %s\n",MR_ruleNamePlusOffset(n),n->line,FileStr[n->file]); +EXIT: + return; +} + + +static PointerStack previousBackTrace={0,0,NULL}; + +#ifdef __USE_PROTOS +void MR_backTraceReport(void) +#else +void MR_backTraceReport() +#endif +{ + int i; + int match = 0; + int limitMatch; + + Node *p; + TokNode *tn; + set remainder; + int depth; + + /* Even when doing a k=2 search this routine can get + called when there is only 1 token on the stack. + This is because something like rRuleRef can change + the search value of k from 2 to 1 temporarily. + It does this because the it wants to know the k=1 + first set before it does a k=2 search + */ + + depth=0; + for (i=0; i < MR_BackTraceStack.count ; i++) { + p=(Node *) MR_BackTraceStack.data[i]; + if (p->ntype == nToken) depth++; + }; + +/* MR14 */ if (MR_AmbSourceSearch) { +/* MR14 */ require (depth <= MR_AmbSourceSearchLimit,"depth > MR_AmbSourceSearchLimit"); +/* MR14 */ } + + /* MR23 THM - Traceback report was being called at the wrong time for -alpha reports */ + /* Reported by Arpad Beszedes (beszedes@inf.u-szeged.hu) */ + + if (MR_AmbSourceSearchLimit == 0 || depth < MR_AmbSourceSearchLimit) { + return; + }; + + MR_backTraceDumpItemReset(); + + limitMatch=MR_BackTraceStack.count; + if (limitMatch > previousBackTrace.count) { + limitMatch=previousBackTrace.count; + }; + + for (match=0; match < limitMatch; match++) { + if (MR_BackTraceStack.data[match] != + previousBackTrace.data[match]) { + break; + }; + }; + + /* not sure at the moment why there would be duplicates */ + + if (match != MR_BackTraceStack.count) { + + fprintf(stdout," Choice:%d Depth:%d Group:%d", + (MR_AmbSourceSearchChoice+1), + MR_AmbSourceSearchLimit, + ++MR_AmbSourceSearchGroup); + + depth=0; + fprintf(stdout," ("); + for (i=0; i < MR_BackTraceStack.count ; i++) { + p=(Node *) MR_BackTraceStack.data[i]; + if (p->ntype != nToken) continue; + tn=(TokNode *)p; + if (depth != 0) fprintf(stdout," "); + fprintf(stdout, "%s", TerminalString(tn->token)); + depth++; + if (! MR_AmbAidMultiple) { + if (set_nil(tn->tset)) { + set_rm( (unsigned) tn->token,fset[depth]); + } else { + remainder=set_dif(fset[depth],tn->tset); + set_free(fset[depth]); + fset[depth]=remainder; + }; + }; + }; + fprintf(stdout,")\n"); + + for (i=0; i < MR_BackTraceStack.count ; i++) { + MR_backTraceDumpItem(stdout, (i +#include +#include +#include "pcctscfg.h" +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" + +#define NumExprPerLine 4 +static int on1line=0; +static set tokensRefdInBlock; + + /* T r a n s l a t i o n T a b l e s */ + +/* C_Trans[node type] == pointer to function that knows how to translate that node. */ +#ifdef __cplusplus +void (*C_Trans[NumNodeTypes+1])(...) = { + NULL, + NULL, /* See next table. +Junctions have many types */ + (void (*)(...)) genRuleRef, + (void (*)(...)) genToken, + (void (*)(...)) genAction + }; +#else +void (*C_Trans[NumNodeTypes+1])() = { + NULL, + NULL, /* See next table. +Junctions have many types */ + genRuleRef, + genToken, + genAction + }; +#endif + +/* C_JTrans[Junction type] == pointer to function that knows how to translate that + * kind of junction node. + */ +#ifdef __cplusplus +void (*C_JTrans[NumJuncTypes+1])(...) = { + NULL, + (void (*)(...)) genSubBlk, + (void (*)(...)) genOptBlk, + (void (*)(...)) genLoopBlk, + (void (*)(...)) genEndBlk, + (void (*)(...)) genRule, + (void (*)(...)) genJunction, + (void (*)(...)) genEndRule, + (void (*)(...)) genPlusBlk, + (void (*)(...)) genLoopBegin + }; +#else +void (*C_JTrans[NumJuncTypes+1])() = { + NULL, + genSubBlk, + genOptBlk, + genLoopBlk, + genEndBlk, + genRule, + genJunction, + genEndRule, + genPlusBlk, + genLoopBegin + }; +#endif + +#define PastWhiteSpace(s) while (*(s) == ' ' || *(s) == '\t') {s++;} + +static int tabs = 0; + +/* MR6 Got tired of text running off page when using standard tab stops */ + +#define TAB { int i; \ + if (TabWidth==0) { \ + for (i=0; irname);} + else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname); + } +} + +static void +#ifdef __USE_PROTOS +warn_about_using_gk_option(void) +#else +warn_about_using_gk_option() +#endif +{ + static int warned_already=0; + + if ( !DemandLookahead || warned_already ) return; + warned_already = 1; + warnNoFL("-gk option could cause trouble for <<...>>? predicates"); +} + +void +#ifdef __USE_PROTOS +freeBlkFsets( Junction *q ) +#else +freeBlkFsets( q ) +Junction *q; +#endif +{ + int i; + Junction *alt; + require(q!=NULL, "freeBlkFsets: invalid node"); + + for (alt=q; alt != NULL; alt= (Junction *) alt->p2 ) + { + for (i=1; i<=CLL_k; i++) set_free(alt->fset[i]); + } +} + +/* + * Generate a local variable allocation for each token references + * in this block. + */ +static void +#ifdef __USE_PROTOS +genTokenPointers( Junction *q ) +#else +genTokenPointers( q ) +Junction *q; +#endif +{ + /* Rule refs are counted and can be referenced, but their + * value is not set to anything useful ever. + * + * The ptrs are to be named _tij where i is the current level + * and j is the element number within an alternative. + */ + int first=1, t=0; + set a; + tokensRefdInBlock = q->tokrefs; + + if ( set_deg(q->tokrefs) == 0 ) return; + a = set_dup(q->tokrefs); + gen("ANTLRTokenPtr "); + for (; !set_nil(a); set_rm(t, a)) + { + t = set_int(a); + if ( first ) first = 0; + else _gen(","); + if ( !DontCopyTokens ) _gen2("_tv%d%d,", BlkLevel, t); + _gen2("_t%d%d", BlkLevel, t); + if ( !DontCopyTokens ) {_gen2("= &_tv%d%d", BlkLevel, t);} + else _gen("=NULL"); + } + _gen(";\n"); + set_free(a); +} + +static int +#ifdef __USE_PROTOS +hasDefaultException(ExceptionGroup *eg) +#else +hasDefaultException(eg) +ExceptionGroup *eg; +#endif +{ + ListNode *q; + + for (q = eg->handlers->next; q!=NULL; q=q->next) + { + ExceptionHandler *eh = (ExceptionHandler *)q->elem; + if ( strcmp("default", eh->signalname)==0 ) { + return 1; + } + } + return 0; +} +static void +#ifdef __USE_PROTOS +dumpException(ExceptionGroup *eg, int no_default_case) +#else +dumpException(eg, no_default_case) +ExceptionGroup *eg; +int no_default_case; +#endif +{ + char *outerLabel; /* MR7 */ + int altHandler=0; /* MR7 */ + int namedHandler=0; /* MR7 */ + + outerLabel=findOuterHandlerLabel(eg); /* MR7 */ + + if (eg->label != NULL) { /* MR7 */ + namedHandler=1; /* MR7 */ + } else if (eg->forRule) { /* MR7 */ + /* nothing */ /* MR20 */ + } else { /* MR7 */ + altHandler=1; /* MR7 */ + }; /* MR7 */ + +#if 0 +** if (! eg->used) { /* MR7 */ +** warnFL("exception group never used", /* MR7 */ +** FileStr[eg->altstart->file],eg->altstart->line); /* MR7 */ +** }; /* MR7 */ +#endif + + if (namedHandler) { /* MR7 */ + gen1("switch ( _signal ) { /* [%s] */\n",eg->label); /* MR7 */ + } else { /* MR7 */ + gen("switch ( _signal ) {\n"); /* MR7 */ + gen("case NoSignal: break; /* MR7 */\n"); /* MR7 */ + }; /* MR7 */ + { + ListNode *q; + for (q = eg->handlers->next; q!=NULL; q=q->next) + { + ExceptionHandler *eh = (ExceptionHandler *)q->elem; + if ( strcmp("default", eh->signalname)==0 ) { + gen("default :\n"); + tabs++; + dumpAction(eh->action, output, tabs, -1, 1, 1); + gen("_signal=NoSignal; /* MR7 */\n"); /* MR7 */ + gen("break; /* MR7 */\n"); /* MR7 */ + tabs--; + gen("}\n"); + + /* copied from later code in dumpException */ /* MR7 */ + + if (namedHandler) { /* MR7 */ + gen("if (_signal != NoSignal)"); /* MR7 */ + _gen1(" goto %s_handler; /* MR7 */\n",outerLabel);/* MR7 */ + } else if (altHandler) { /* MR7 */ + gen1("goto %s_handler; /* MR7 */\n",outerLabel); /* MR7 */ + }; + return; + } + gen1("case %s :\n", eh->signalname); + tabs++; + if ( eh->action != NULL ) + { + dumpAction(eh->action, output, tabs, -1, 1, 1); + gen("break; /* MR7 */\n"); /* MR7 */ + } + tabs--; + } + } + if ( no_default_case ) return; + + gen("default :\n"); + tabs++; /* MR7 */ + gen("break; /* MR7 */\n"); /* MR7 */ + tabs--; /* MR7 */ + + tabs++; +/***** gen("*_retsignal = _signal;\n"); *****/ + + tabs--; + gen("}\n"); + + if (namedHandler) { /* MR7 */ + gen("if (_signal != NoSignal)"); /* MR7 */ + _gen1(" goto %s_handler; /* MR7 */\n",outerLabel); /* MR7 */ + } else if (altHandler) { /* MR7 */ + gen1("goto %s_handler; /* MR7 */\n",outerLabel); /* MR7 */ + }; + +} + +static void +#ifdef __USE_PROTOS +dumpExceptions(ListNode *list) +#else +dumpExceptions(list) +ListNode *list; +#endif +{ + ListNode *p; + + for (p = list->next; p!=NULL; p=p->next) + { + ExceptionGroup *eg = (ExceptionGroup *) p->elem; + _gen2("%s%s_handler:\n", + eg->label==NULL?"":eg->label, + eg->altID==NULL?"":eg->altID); + if ( eg->altID!=NULL ) dumpException(eg, 0); + else { + /* This must be the rule exception handler */ + dumpException(eg, 1); + if ( !hasDefaultException(eg) ) + { + gen("default :\n"); + tabs++; + gen("zzdflthandlers(_signal,_retsignal);\n"); + tabs--; + gen("}\n"); + } + } + } +} + +/* For each element label that is found in a rule, generate a unique + * Attribute (and AST pointer if GenAST) variable. + */ +void +#ifdef __USE_PROTOS +genElementLabels(ListNode *list) +#else +genElementLabels(list) +ListNode *list; +#endif +{ + int first=1; + ListNode *p; + + if ( GenCC ) {gen("ANTLRTokenPtr");} + else {gen("Attrib");} + for (p = list->next; p!=NULL; p=p->next) + { + char *ep = (char *)p->elem; + if ( first ) first = 0; + else _gen(","); + if ( GenCC ) {_gen1(" %s=NULL",ep);} + else {_gen1(" %s",ep);} + } + _gen(";\n"); + + if ( !GenAST ) return; + + first = 1; + gen("AST"); + for (p = list->next; p!=NULL; p=p->next) + { + char *ep = (char *)p->elem; + if ( first ) first = 0; + else _gen(","); + _gen1(" *%s_ast=NULL",ep); + } + _gen(";\n"); +} + +/* + * Generate a local variable allocation for each token or rule reference + * in this block. + */ +static void +#ifdef __USE_PROTOS +genASTPointers( Junction *q ) +#else +genASTPointers( q ) +Junction *q; +#endif +{ + int first=1, t; + set a; + + a = set_or(q->tokrefs, q->rulerefs); + if ( set_deg(a) > 0 ) + { + gen("AST "); + for (; !set_nil(a); set_rm(t, a)) + { + t = set_int(a); + if ( first ) first = 0; + else _gen(","); + _gen2("*_ast%d%d=NULL", BlkLevel, t); + } + set_free(a); + } + _gen(";\n"); +} + +static void +#ifdef __USE_PROTOS +BLOCK_Head( void ) +#else +BLOCK_Head( ) +#endif +{ + gen("{\n"); + tabs++; + if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel); +} + +static void +#ifdef __USE_PROTOS +BLOCK_Tail( void ) +#else +BLOCK_Tail( ) +#endif +{ + if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel); + if ( !GenCC ) gen("}\n"); + tabs--; + gen("}\n"); +} + +static void +#ifdef __USE_PROTOS +BLOCK_Preamble( Junction *q ) +#else +BLOCK_Preamble( q ) +Junction *q; +#endif +{ + ActionNode *a; + Junction *begin; + + BLOCK_Head(); + if ( GenCC ) genTokenPointers(q); + if ( GenCC&&GenAST ) genASTPointers(q); + if ( q->jtype == aPlusBlk ) gen("int zzcnt=1;\n"); + if ( q->parm != NULL && !q->predparm ) gen1("zzaPush(%s);\n", q->parm) + else if ( !GenCC ) gen("zzMake0;\n"); + if ( !GenCC ) gen("{\n"); + if ( q->jtype == aLoopBegin ) begin = (Junction *) ((Junction *)q->p1); + else begin = q; + if ( has_guess_block_as_first_item(begin) ) + { + gen("zzGUESS_BLOCK\n"); + } + if ( q->jtype == aLoopBegin ) + a = findImmedAction( ((Junction *)q->p1)->p1 ); /* look at aLoopBlk */ + else + a = findImmedAction( q->p1 ); + if ( a!=NULL && !a->is_predicate) { +/* MR21 */ if (!a->noHoist) dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1); + a->done = 1; /* remove action. We have already handled it */ + } +} + +void +#ifdef __USE_PROTOS +genCombinedPredTreeContextOrig( Predicate *p ) +#else +genCombinedPredTreeContextOrig( p ) +Predicate *p; +#endif +{ + static set *ctx=NULL; /* genExprSets() is destructive, make copy*/ + require(p!=NULL, "can't make context tree for NULL pred tree"); + +#ifdef DBG_PRED + fprintf(stderr, "enter genCombinedPredTreeContextOrig(%s,0x%x) with sets:\n", p->expr, p); + s_fprT(stderr, p->scontext[1]); + fprintf(stderr, "\n"); +#endif + if ( p->down == NULL ) + { +/*** if ( p->k>1 && p->tcontext!=NULL ) ***/ + if ( p->tcontext!=NULL ) + { + _gen("("); + genExprTree(p->tcontext, 1); + _gen(")"); + } +/*** else if ( p->k==1 && set_deg(p->scontext[1])>0 ) ***/ + else if ( set_deg(p->scontext[1])>0 ) + { + if ( ctx==NULL ) ctx = (set *)calloc(CLL_k+1, sizeof(set)); + require(ctx!=NULL, "ctx cannot allocate"); + ctx[0]=empty; + ctx[1]=set_dup(p->scontext[1]); + _gen("("); + genExprSets(&(ctx[0]), p->k); + _gen(")"); + set_free(ctx[1]); + } + else if ( p->expr==PRED_AND_LIST || p->expr==PRED_OR_LIST ) { + fatal_internal("pred tree is orphan OR or AND list"); + } + else { + if (! HoistPredicateContext) { + _gen(" 1 /* no context: prc is off */ "); + } else { + fatal_internal("pred tree context is empty"); + }; + } + return; + } + +/* MR10 - make AND just like OR */ + + if ( p->expr == PRED_AND_LIST ) + { + Predicate *list = p->down; + for (; list!=NULL; list=list->right) + { + genCombinedPredTreeContextOrig(list); + if ( list->right!=NULL ) _gen("|| /* MR10 was wrong */ "); + }; + return; + } + + if ( p->expr == PRED_OR_LIST ) + { + Predicate *list = p->down; + for (; list!=NULL; list=list->right) + { + genCombinedPredTreeContextOrig(list); + if ( list->right!=NULL ) _gen("||"); + }; + return; + }; + + fatal("pred tree is really wacked"); +} + +/* [genCombinedPredTreeContext] */ + +void +#ifdef __USE_PROTOS +genCombinedPredTreeContext( Predicate *p ) +#else +genCombinedPredTreeContext( p ) +Predicate *p; +#endif +{ + Tree *t; + int predDepth=0; + + if (0 && ! MR_usingPredNames && ! MRhoisting) { + genCombinedPredTreeContextOrig(p); + } else { +/* MR13 */ MR_pred_depth(p,&predDepth); +/* MR13 */ if (predDepth == 1) { +/* MR13 */ +/* MR13 */ set scontext[2]; +/* MR13 */ scontext[0]=empty; +/* MR13 */ scontext[1]=MR_compute_pred_set(p); +/* MR13 */ if (set_nil(scontext[1])) { +/* MR13 */ _gen(" 1 /* MR12 no context (-prc off) */ "); +/* MR13 */ } else { +/* MR13 */ _gen("("); +/* MR13 */ genExprSets(&scontext[0], 1); +/* MR13 */ set_free(scontext[1]); +/* MR13 */ _gen(")"); +/* MR13 */ }; + + } else { + t=MR_compute_pred_tree_context(p); + if (t == NULL) { + _gen(" 1 /* MR12 no context (-prc off) */ "); + } else { + _gen("("); + genExprTree(t, 1); + Tfree(t); /* MR10 */ + _gen(")"); + }; + }; + }; +} + +/* [genPredTreeGate] */ + +void +#ifdef __USE_PROTOS +genPredTreeGate( Predicate *p, int in_and_expr ) +#else +genPredTreeGate( p, in_and_expr ) +Predicate *p; +int in_and_expr; +#endif +{ + if ( in_and_expr ) + { + _gen("!("); + genCombinedPredTreeContext(p); + _gen(")||"); + if ( p->down!=NULL ) _gen("\n"); + } + else + { + _gen("("); + genCombinedPredTreeContext(p); + _gen(")&&"); + if ( p->down!=NULL ) _gen("\n"); + } +} + +#ifdef __USE_PROTOS +void genPredEntry(Predicate *p,int outer) +#else +void genPredEntry(p,outer) + Predicate *p; + int outer; +#endif +{ + int inverted=0; + Predicate *q; + int localOuter=outer; + int needRP=0; + + if (p == NULL) return; + + if (p->predEntry != NULL && p->predEntry->predLiteral != NULL) { + if (p->inverted != p->predEntry->pred->inverted) { + _gen("! /* inverted pred */ ("); + needRP=1; + } else { + if (!localOuter) _gen("("); + needRP=1; + }; + dumpAction(p->predEntry->predLiteral,output,0,p->source->file,p->source->line,0); + if (needRP) _gen(")"); + return; + }; + + inverted=p->inverted; + + if (inverted) { + _gen(" ! /* inverted pred */ ("); + localOuter=1; + }; + + if (p->expr == PRED_OR_LIST) { + if (!localOuter) _gen("("); + for (q=p->down; q != NULL ; q=q->right) { + genPredEntry(q,0); + if (q->right != NULL) _gen(" || "); + }; + if (!localOuter) _gen(")"); + } else if (p->expr == PRED_AND_LIST) { + if (!localOuter) _gen("("); + for (q=p->down; q != NULL ; q=q->right) { + genPredEntry(q,0); + if (q->right != NULL) _gen(" && "); + }; + if (!localOuter) _gen(")"); + } else { + if (!localOuter) _gen("("); + require (p->source != NULL,"predEntry->source == NULL"); + require (p->source->inverted == 0,"dumpPredEntry p->source->inverted != 0"); + dumpAction(p->source->action,output,0,p->source->file,p->source->line,0); + if (!localOuter) _gen(")"); + }; + + if (inverted) { + _gen(")"); + } +} + +void +#ifdef __USE_PROTOS +dumpPredAction(ActionNode *anode, + char *s,FILE *output,int tabs,int file,int line,int final_newline) +#else +dumpPredAction(anode, + s,output,tabs,file,line,final_newline) + + ActionNode *anode; + char *s; + FILE *output; + int tabs; + int file; + int line; + int final_newline; +#endif +{ + PredEntry *predEntry=anode->predEntry; + int inverted=anode->inverted; + Predicate *workPred; + + if (predEntry == NULL) { + + /* inline predicate literal */ + + require(inverted == 0,"dumpPredAction action->inverted"); + dumpAction(s,output,tabs,file,line,final_newline); + + } else { + + /* a reference to a predicate - possibly with an inverted source */ + + if (predEntry->predLiteral != NULL) { + if (inverted) _gen("! /* inverted pred */ ("); + dumpAction(predEntry->predLiteral,output,0,anode->file,anode->line,0); + if (inverted) _gen(")"); + } else { + workPred=predicate_dup(predEntry->pred); + if (inverted) workPred->inverted=!workPred->inverted; + genPredEntry(workPred,1); + predicate_free(workPred); + }; + }; +} + +/* [genPred] */ + +void +#ifdef __USE_PROTOS +genPred(Predicate *p, Node *j,int suppress_sva) +#else +genPred(p,j,suppress_sva) + Predicate *p; + Node *j; + int suppress_sva; +#endif +{ + if ( FoundException && !suppress_sva) {_gen("(_sva=(");} /* MR11 suppress_sva */ + else {_gen("(");} + if ( GenLineInfo && j->file != -1 ) _gen("\n"); + if (p->source != NULL && p->source->ampersandPred != NULL) { + if (p->source->ampersandPred->k == 1) { + + set ctx[2]; + + ctx[0]=empty; + ctx[1]=set_dup(p->source->ampersandPred->scontext[1]); + + _gen("("); + genExprSets(&(ctx[0]), p->k); + _gen(") && "); + set_free(ctx[1]); + } else { + _gen("( "); + genExprTree(p->source->ampersandPred->tcontext,1); + _gen(" ) && "); + }; + }; + + dumpPredAction((ActionNode *)p->source, + p->expr, output, 0, -1 /*indicates no line info*/, j->line, 0); + + if ( FoundException && !suppress_sva) /* MR11 suppress_sva */ + {_gen("),_sva)");} /* MR10 - get red of "meant ==" messages */ + else {_gen(")");} +} + +void +#ifdef __USE_PROTOS +MR_distinctORcontextOpt(Predicate *p,Node *j,int in_and_expr) +#else +MR_distinctORcontextOpt(p,j,in_and_expr) + Predicate *p; + Node *j; + int in_and_expr; +#endif +{ + Predicate *q; + + _gen(" /* MR10 Distinct OR context optimization */ \n"); + + if (in_and_expr) { + gen("zzpf=0,\n"); + for (q=p->down; q != NULL; q=q->right) { + gen("( "); + genCombinedPredTreeContext(q); + _gen(" && (zzpf=1, "); + genPred(q,j,0); + _gen(" )) ||\n"); + }; + gen("!zzpf)"); + } else { + require (0, + "MR_distinctORcontextOpt: can't get here when using MR_predSimplify"); +#if 0 +** for (q=p->down; q != NULL; q=q->right) { +** gen("( "); +** genCombinedPredTreeContext(q); +** _gen(" && "); +** genPred(q,j); +** if (q->right != NULL) { +** _gen(" ) ||\n"); +** }; +** }; +** gen(")"); +#endif + }; +} + +void +#ifdef __USE_PROTOS +genPredTreeOrig( Predicate *p, Node *j, int in_and_expr ) +#else +genPredTreeOrig( p, j, in_and_expr ) +Predicate *p; +Node *j; +int in_and_expr; +#endif +{ + +/* MR10 */ int allHaveContext=1; +/* MR10 */ int noneHaveContext=1; + +/* MR10 */ MR_predContextPresent(p,&allHaveContext,&noneHaveContext); + + if ( ! noneHaveContext ) /* MR10 context guards ignored when -prc off */ + { + _gen("("); + genPredTreeGate(p, in_and_expr); + } + + /* if leaf node, just gen predicate */ + + if ( p->down==NULL ) + { + genPred(p,j,0); + if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */ + return; + } + + /* if AND list, do both preds (only two possible) */ + if ( p->expr == PRED_AND_LIST ) + { +#if 0 +** _gen("("); +** genPredTreeOrig(p->down, j, 1); +** _gen("&&"); +** genPredTreeOrig(p->down->right, j, 1); +** _gen(")"); +** if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */ +** return; +#endif + /* MR11 - make it work with AND with more than two children - like OR */ + + Predicate *list; + _gen("("); + list = p->down; + for (; list!=NULL; list=list->right) + { + genPredTreeOrig(list, j, 1); + if ( list->right!=NULL ) _gen("&&"); + } + _gen(")"); + if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */ + return; + }; + + if ( p->expr == PRED_OR_LIST ) + { + Predicate *list; + _gen("("); + list = p->down; + for (; list!=NULL; list=list->right) + { + genPredTreeOrig(list, j, 0); + if ( list->right!=NULL ) _gen("||"); + } + _gen(")"); + if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */ + return; + } + + fatal_internal("genPredTreeOrig: predicate tree is wacked"); +} + +#if 0 +** Predicate member dummyPredDepth is no longer used in MR10 +** but we might need it again in the future +** +** if (MRhoisting) { +** if ( !noneHaveContext && +** ! in_and_expr && +** p->source != NULL && +** p->source->dummyPredicateDepth > 0 && +** p->down == NULL) { +** _gen("("); +** genCombinedPredTreeContext(p); +** _gen(" )\n"); +** return; +** }; +** }; +#endif + +/* [genPredTree] */ + +/* in_and_expr + + what to do if the context is wrong + what to do if the context is correct but the predicate is false + + remember: if the context is wrong it's the same as if the + predicate is true as far as enabling an alternative + + Consider (AND p q r) + + if in an ... && ... expression then you don't want + the entire predicate chain to fail just because the + context for one component is wrong: so return true + + Consider (OR p q r) + + if in an ... || ... expression then you don't want + the entire predicate chain to succeed just because + the context for one component is correct when the + corresponding test is false: so return false when + the context is correct but the test is false. +*/ + +void +#ifdef __USE_PROTOS +genPredTree( Predicate *p, Node *j, int in_and_expr, int suppress_sva ) +#else +genPredTree( p, j, in_and_expr, suppress_sva) + Predicate *p; + Node *j; + int in_and_expr; + int suppress_sva; +#endif +{ + + int allHaveContext=1; + int noneHaveContext=1; + Tree *groupTree; + Tree *oneTree; + Predicate *q; + int identicalORcontextOptimization=0; + int identicalANDcontextOptimization=0; + + if (0 && !MR_usingPredNames && !MRhoisting) { + genPredTreeOrig(p,j,in_and_expr); + return; + }; + + MR_predContextPresent(p,&allHaveContext,&noneHaveContext); + + if ( ! noneHaveContext ) { /* MR10 context guards ignored when -prc off */ + + _gen("("); + + /* MR10 optimize OR predicates which are all leaves */ + + if (p->expr == PRED_OR_LIST && MR_allPredLeaves(p->down)) { + groupTree=MR_compute_pred_tree_context(p); + for (q=p->down ; q != NULL ; q=q->right) { + oneTree=MR_compute_pred_tree_context(q); + if (! MR_tree_equ(groupTree,oneTree)) { + Tfree(oneTree); + break; + }; + Tfree(oneTree); + }; + Tfree(groupTree); + if (q == NULL) { + _gen("/* MR10 individual OR gates suppressed when all predicates are leaves"); + _gen(" with identical context */\n"); + genPredTreeGate(p,in_and_expr); /* use the parent's in_and_expr for this gate */ + identicalORcontextOptimization=1; + } else { + MR_distinctORcontextOpt(p,j,in_and_expr); + return; + }; + } else if (p->expr == PRED_AND_LIST && MR_allPredLeaves(p->down)) { + + /* MR12 optimize AND predicates which are all leaves */ + + groupTree=MR_compute_pred_tree_context(p); + for (q=p->down ; q != NULL ; q=q->right) { + oneTree=MR_compute_pred_tree_context(q); + if (! MR_tree_equ(groupTree,oneTree)) { + Tfree(oneTree); + break; + }; + Tfree(oneTree); + }; + Tfree(groupTree); + if (q == NULL) { + _gen("/* MR12 individual AND gates suppressed when all predicates are leaves"); + _gen(" with identical context */\n"); + genPredTreeGate(p,in_and_expr); /* use the parent's in_and_expr for this gate */ + identicalANDcontextOptimization=1; + } else { + genPredTreeGate(p, in_and_expr); + }; + } else { + genPredTreeGate(p, in_and_expr); + }; + } + + /* if leaf node, just gen predicate */ + + if ( p->down==NULL ) + { + genPred(p,j,suppress_sva); + if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */ + return; + } + + /* if AND list, do both preds (only two possible) */ + /* MR10 not any more ! */ + + if ( p->expr == PRED_AND_LIST ) + { + Predicate *list; + _gen("("); + list = p->down; + for (; list != NULL; list=list->right) { + if (identicalANDcontextOptimization) { + genPred(list, j,suppress_sva); + } else { + genPredTree(list, j, 1, suppress_sva); /* in and context */ + }; + if ( list->right!=NULL ) _gen("&&"); + }; + _gen(")"); + if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */ + return; + } + + if ( p->expr == PRED_OR_LIST ) + { + Predicate *list; + _gen("("); + list = p->down; + for (; list!=NULL; list=list->right) + { + if (identicalORcontextOptimization) { + genPred(list, j,suppress_sva); + } else { + genPredTree(list, j, 0, suppress_sva); + }; + if ( list->right!=NULL ) _gen("||"); + } + _gen(")"); + if ( ! noneHaveContext ) _gen(")"); /* MR10 context guards ignored when -prc off */ + return; + } + + fatal_internal("predicate tree is wacked"); +} + +/* [genPredTreeMainXX] */ + +Predicate * /* MR10 */ +#ifdef __USE_PROTOS +genPredTreeMainXX( Predicate *p, Node *j ,int in_and_expr) +#else +genPredTreeMainXX( p, j ,in_and_expr) + Predicate *p; + Node *j; + int in_and_expr; +#endif +{ + + int allHaveContext=1; + int noneHaveContext=1; + +#if 0 + fprintf(stderr,"Pred before\n"); + dumppred(p); + fprintf(stderr,"\n"); + fprintf(stderr,"Pred after\n"); + dumppred(p); + fprintf(stderr,"\n"); +#endif + + p=MR_predSimplifyALL(p); /* MR10 */ + + require (MR_predicate_context_completed(p),"predicate context is not complete"); + + MR_cleanup_pred_trees(p); /* MR10 */ + + MR_predContextPresent(p,&allHaveContext,&noneHaveContext); + if (!noneHaveContext & !allHaveContext) { + warnFL("predicate contains elements both with and without context", + FileStr[j->file],j->line); + }; + + if (InfoP) { + _gen("\n#if 0\n\n"); + MR_dumpPred(p,1); + _gen("#endif\n"); + }; + genPredTree(p,j,in_and_expr,0); + return p; +} + +Predicate * /* MR10 */ +#ifdef __USE_PROTOS +genPredTreeMain( Predicate *p, Node *j) +#else +genPredTreeMain( p, j) + Predicate *p; + Node *j; +#endif +{ + return genPredTreeMainXX(p,j,1); +} + +static void +#ifdef __USE_PROTOS +genExprTreeOriginal( Tree *t, int k ) +#else +genExprTreeOriginal( t, k ) +Tree *t; +int k; +#endif +{ + require(t!=NULL, "genExprTreeOriginal: NULL tree"); + + if ( t->token == ALT ) + { + _gen("("); genExprTreeOriginal(t->down, k); _gen(")"); + if ( t->right!=NULL ) + { + _gen("||"); + on1line++; + if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); } + _gen("("); genExprTreeOriginal(t->right, k); _gen(")"); + } + return; + } + if ( t->down!=NULL ) _gen("("); + _gen1("LA(%d)==",k); + if ( TokenString(t->token) == NULL ) _gen1("%d", t->token) + else _gen1("%s", TokenString(t->token)); + if ( t->down!=NULL ) + { + _gen("&&"); + on1line++; + if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); } + _gen("("); genExprTreeOriginal(t->down, k+1); _gen(")"); + } + if ( t->down!=NULL ) _gen(")"); + if ( t->right!=NULL ) + { + _gen("||"); + on1line++; + if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); } + _gen("("); genExprTreeOriginal(t->right, k); _gen(")"); + } +} + +#ifdef __USE_PROTOS +static void MR_LAtokenString(int k,int token) +#else +static void MR_LAtokenString(k,token) + int k; + int token; +#endif +{ + char *ts; + + ts=TokenString(token); + if (ts == NULL) { + _gen2(" LA(%d)==%d",k,token); + } else { + _gen2(" LA(%d)==%s",k,ts); + }; +} + + +#ifdef __USE_PROTOS +static int MR_countLeaves(Tree *t) +#else +static int MR_countLeaves(t) + Tree *t; +#endif +{ + if (t == NULL) return 0; + if (t->token == ALT) { + return MR_countLeaves(t->down)+MR_countLeaves(t->right); + } else { + return 1+MR_countLeaves(t->down)+MR_countLeaves(t->right); + }; +} + +#ifdef __USE_PROTOS +static void MR_genOneLine(Tree *tree,int k) +#else +static void MR_genOneLine(tree,k) + Tree *tree; + int k; +#endif +{ + if (tree == NULL) return; + if (tree->token == ALT) { + MR_genOneLine(tree->down,k); + } else { + MR_LAtokenString(k,tree->token); + if (tree->down != NULL && + tree->down->right == NULL) { + _gen(" &&"); + MR_genOneLine(tree->down,k+1); + } else if (tree->down != NULL) { + _gen(" && ("); + MR_genOneLine(tree->down,k+1); + _gen(")"); + }; + }; + if (tree->right != NULL) { + _gen(" ||"); + MR_genOneLine(tree->right,k); + }; +} + +static int across; +static int depth; +static int lastkonline; + +#ifdef __USE_PROTOS +static void MR_genMultiLine(Tree *tree,int k) +#else +static void MR_genMultiLine(tree,k) + Tree *tree; + int k; +#endif +{ + int i; + + if (tree == NULL) return; + if (tree->token == ALT) { + MR_genMultiLine(tree,k); + } else { + MR_LAtokenString(k,tree->token); + lastkonline=k; + across++; + if (tree->down != NULL && tree->down->right == NULL) { + if (across > 3) { + _gen("\n"); + across=0; + lastkonline=0; + for (i=0 ; i < depth+k ; i++) _gen(" "); + _gen("&&"); + } else { + _gen(" &&"); + }; + MR_genMultiLine(tree->down,k+1); + } else if (tree->down != NULL) { + _gen("\n"); + lastkonline=0; + across=0; + for (i=0 ; i < depth+k ; i++) _gen(" "); + _gen("&& ("); + MR_genMultiLine(tree->down,k+1); + _gen(")"); + }; + }; + if (tree->right != NULL) { + if (k < lastkonline) { + _gen("\n"); + across=0; + lastkonline=0; + for (i=0; i < depth+k-1 ; i++) _gen(" "); + _gen("||"); + } else if (across > 3 ) { + _gen("\n"); + across=0; + lastkonline=0; + for (i=0; i < depth+k ; i++) _gen(" "); + _gen("||"); + } else { + _gen(" ||"); + }; + MR_genMultiLine(tree->right,k); + }; +} + +#ifdef __USE_PROTOS +static void genExprTree(Tree *tree,int k) +#else +static void genExprTree(tree,k) + Tree *tree; + int k; +#endif +{ + int count; + +#if 0 + /* MR20 THM This was probably an error. + The routine should probably reference that static + "across" and this declaration hides it. + */ + + int across; +#endif + + require (tree != NULL,"genExprTree: tree is NULL"); + require (k > 0,"genExprTree: k <= 0"); + + if (0 && !MRhoisting) { /* MR11 make new version standard */ + genExprTreeOriginal(tree,k); + } else { + count=MR_countLeaves(tree); + if (count < 5) { + MR_genOneLine(tree,k); + } else { + _gen("\n"); + across=0; + depth=0; + lastkonline=0; + MR_genMultiLine(tree,k); + _gen("\n"); + }; + }; +} + + +/* + * Generate LL(k) type expressions of the form: + * + * (LA(1) == T1 || LA(1) == T2 || ... || LA(1) == Tn) && + * (LA(2) == T1 || LA(2) == T2 || ... || LA(2) == Tn) && + * ..... + * (LA(k) == T1 || LA(k) == T2 || ... || LA(k) == Tn) + * + * If GenExprSetsOpt generate: + * + * (setwdi[LA(1)]&(1<= 1. + * + * This routine is visible only to this file and cannot answer a TRANS message. + * + */ + +/* [genExpr] */ + +static int +#ifdef __USE_PROTOS +genExpr( Junction *j ) +#else +genExpr( j ) +Junction *j; +#endif +{ + int max_k; + + /* if full LL(k) is sufficient, then don't use approximate (-ck) lookahead + * from CLL_k..LL_k + */ + { + int limit; + if ( j->ftree!=NULL ) limit = LL_k; + else limit = CLL_k; + max_k = genExprSets(j->fset, limit); + } + + /* Do tests for real tuples from other productions that conflict with + * artificial tuples generated by compression (using sets of tokens + * rather than k-trees). + */ + if ( j->ftree != NULL ) + { + _gen(" && !("); genExprTree(j->ftree, 1); _gen(")"); + } + + if ( ParseWithPredicates && j->predicate!=NULL ) + { + Predicate *p = j->predicate; + warn_about_using_gk_option(); + _gen("&&"); + j->predicate=genPredTreeMain(p, (Node *)j); /* MR10 */ + } + + return max_k; +} + +static int +#ifdef __USE_PROTOS +genExprSets( set *fset, int limit ) +#else +genExprSets( fset, limit ) +set *fset; +int limit; +#endif +{ + int k = 1; + int max_k = 0; + unsigned *e, *g, firstTime=1; + + if (set_nil(fset[1])) { + _gen(" 0 /* MR13 empty set expression - undefined rule ? infinite left recursion ? */ "); + MR_BadExprSets++; + }; + + if ( GenExprSetsOpt ) + { + while ( k <= limit && !set_nil(fset[k]) ) /* MR11 */ + { + if ( set_deg(fset[k])==1 ) /* too simple for a set? */ + { + int e; + _gen1("(LA(%d)==",k); + e = set_int(fset[k]); + if ( TokenString(e) == NULL ) _gen1("%d)", e) + else _gen1("%s)", TokenString(e)); + } + else + { + NewSet(); + FillSet( fset[k] ); + _gen3("(setwd%d[LA(%d)]&0x%x)", wordnum, k, 1<max_k ) max_k = k; + if ( k == CLL_k ) break; + k++; + if ( k<=limit && !set_nil(fset[k]) ) _gen(" && "); /* MR11 */ + on1line++; + if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); } + } + return max_k; + } + + while ( k<= limit && !set_nil(fset[k]) ) /* MR11 */ + { + if ( (e=g=set_pdq(fset[k])) == NULL ) fatal_internal("genExpr: cannot allocate IF expr pdq set"); + for (; *e!=nil; e++) + { + if ( !firstTime ) _gen(" || ") else { _gen("("); firstTime = 0; } + on1line++; + if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); } + _gen1("LA(%d)==",k); + if ( TokenString(*e) == NULL ) _gen1("%d", *e) + else _gen1("%s", TokenString(*e)); + } + free( (char *)g ); + _gen(")"); + if ( k>max_k ) max_k = k; + if ( k == CLL_k ) break; + k++; + if ( k <= limit && !set_nil(fset[k]) ) { firstTime=1; _gen(" && "); } /* MR11 */ + on1line++; + if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); } + } + return max_k; +} + +/* + * Generate code for any type of block. If the last alternative in the block is + * empty (not even an action) don't bother doing it. This permits us to handle + * optional and loop blocks as well. + * + * Only do this block, return after completing the block. + * This routine is visible only to this file and cannot answer a TRANS message. + */ +static set +#ifdef __USE_PROTOS +genBlk( Junction *q, int jtype, int *max_k, int *need_right_curly, int * lastAltEmpty /* MR23 */) +#else +genBlk( q, jtype, max_k, need_right_curly, lastAltEmpty /* MR23 */) +Junction *q; +int jtype; +int *max_k; +int *need_right_curly; +int *lastAltEmpty; /* MR23 */ +#endif +{ + set f; + Junction *alt; + int a_guess_in_block = 0; + require(q!=NULL, "genBlk: invalid node"); + require(q->ntype == nJunction, "genBlk: not junction"); + *need_right_curly=0; + *lastAltEmpty = 0; /* MR23 */ + if ( q->p2 == NULL ) /* only one alternative? Then don't need if */ + { + if (first_item_is_guess_block((Junction *)q->p1)!=NULL ) + { + if (jtype != aLoopBlk && jtype != aOptBlk && jtype != aPlusBlk) { + warnFL("(...)? as only alternative of block is unnecessary", FileStr[q->file], q->line); + }; + gen("zzGUESS\n"); /* guess anyway to make output code consistent */ +/* MR10 disable */ /**** gen("if ( !zzrv )\n"); ****/ +/* MR10 */ gen("if ( !zzrv ) {\n"); tabs++; (*need_right_curly)++; + }; + TRANS(q->p1); + return empty; /* no decision to be made-->no error set */ + } + + f = First(q, 1, jtype, max_k); + for (alt=q; alt != NULL; alt= (Junction *) alt->p2 ) + { + if ( alt->p2 == NULL ) /* chk for empty alt */ + { + Node *p = alt->p1; + if ( p->ntype == nJunction ) + { + /* we have empty alt */ +/* MR23 + There is a conflict between giving good error information for non-exceptions + and making life easy for those using parser exception handling. Consider: + + r: { A } b; + b: B; + + with input "C" + + Before MR21 the error message would be "expecting B - found C". After MR21 + the error message would be "expect A, B - found C". This was good, but it + caused problems for those using parser exceptions because the reference to + B was generated inside the {...} where B really wasn't part of the block. + + In MR23 this has been changed for the case where exceptions are in use to + not generate the extra check in the tail of the {A} block. +*/ + + +/* MR23 */ if (isEmptyAlt( ((Junction *)p)->p1, (Node *)q->end)) { +/* MR23 */ *lastAltEmpty = 1; +/* MR23 */ if (FoundException) { +/* MR23 */ /* code to restore state if a prev alt didn't follow guess */ +/* MR23 */ if ( a_guess_in_block && jtype != aPlusBlk) { +/* MR23 */ gen("if ( !zzrv ) zzGUESS_DONE; /* MR28 */\n"); +/* MR23 */ } +/* MR23 */ break; +/* MR23 */ }; +/* MR28 */ if (jtype == aPlusBlk) { +/* MR28 */ break; +/* MR28 */ } +/* MR23 */ } + } + } /* end of for loop on alt */ + +/* MR10 */ if (alt->p2 == NULL && +/* MR10 */ ( q->jtype == aSubBlk || q->jtype == RuleBlk) ) { +/* MR10 */ if (first_item_is_guess_block(alt)) { +/* MR10 */ warnFL("(...)? as last alternative of block is unnecessary", +/* MR10 */ FileStr[alt->file],alt->line); +/* MR10 */ }; +/* MR10 */ }; + + if ( alt != q ) gen("else ") + else + { + if ( DemandLookahead ) { + if ( !GenCC ) {gen1("LOOK(%d);\n", *max_k);} + else gen1("look(%d);\n", *max_k); + } + } + + if ( alt!=q ) + { + _gen("{\n"); + tabs++; + (*need_right_curly)++; + /* code to restore state if a prev alt didn't follow guess */ + if ( a_guess_in_block ) + gen("if ( !zzrv ) zzGUESS_DONE;\n"); + } + if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) + { + a_guess_in_block = 1; + gen("zzGUESS\n"); + } + gen("if ( "); + if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) _gen("!zzrv && "); + genExpr(alt); + _gen(" ) "); + _gen("{\n"); + tabs++; + TRANS(alt->p1); + --tabs; + gen("}\n"); +/* MR10 */ if (alt->p2 == NULL) { +/* MR10 */ if (first_item_is_guess_block(alt)) { +/* MR10 */ gen("/* MR10 */ else {\n"); +/* MR10 */ tabs++; +/* MR10 */ (*need_right_curly)++; +/* MR10 */ /* code to restore state if a prev alt didn't follow guess */ +/* MR10 */ gen("/* MR10 */ if ( !zzrv ) zzGUESS_DONE;\n"); +/* MR10 */ gen("/* MR10 */ if (0) {} /* last alternative of block is guess block */\n"); +/* MR10 */ }; +/* MR10 */ }; + } + return f; +} + +static int +#ifdef __USE_PROTOS +has_guess_block_as_first_item( Junction *q ) +#else +has_guess_block_as_first_item( q ) +Junction *q; +#endif +{ + Junction *alt; + + for (alt=q; alt != NULL; alt= (Junction *) alt->p2 ) + { + if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) return 1; + } + return 0; +} + +static int +#ifdef __USE_PROTOS +has_guess_block_as_last_item( Junction *q ) +#else +has_guess_block_as_last_item( q ) +Junction *q; +#endif +{ + Junction *alt; + + if (q == NULL) return 0; + for (alt=q; alt->p2 != NULL && !( (Junction *) alt->p2)->ignore; alt= (Junction *) alt->p2 ) {}; + return first_item_is_guess_block( (Junction *) alt->p1) != NULL; +} + +/* MR30 See description of first_item_is_guess_block for background */ + +Junction * +#ifdef __USE_PROTOS +first_item_is_guess_block_extra(Junction *q ) +#else +first_item_is_guess_block_extra(q) +Junction *q; +#endif +{ + while ( q!=NULL && + ( ( q->ntype==nAction ) || + ( q->ntype==nJunction && + (q->jtype==Generic || q->jtype == aLoopBlk) + ) + ) + ) + { + if ( q->ntype==nJunction ) q = (Junction *)q->p1; + else q = (Junction *) ((ActionNode *)q)->next; + } + + if ( q==NULL ) return NULL; + if ( q->ntype!=nJunction ) return NULL; + if ( q->jtype!=aSubBlk ) return NULL; + if ( !q->guess ) return NULL; + + return q; +} + +/* return NULL if 1st item of alt is NOT (...)? block; else return ptr to aSubBlk node + * of (...)?; This function ignores actions and predicates. + */ + +Junction * +#ifdef __USE_PROTOS +first_item_is_guess_block( Junction *q ) +#else +first_item_is_guess_block( q ) +Junction *q; +#endif +{ + Junction * qOriginal = q; /* DEBUG */ + + /* MR14 Couldn't find aSubBlock which was a guess block when it lay + behind aLoopBlk. The aLoopBlk only appear in conjunction with + aLoopBegin, but the routine didn't know that. I think. + + MR14a Added extra parentheses to clarify precedence + + MR30 This appears to have been a mistake. The First set was then + computed incorrectly for: + + r : ( (A)? B + | C + )* + + The routine analysis_point was seeing the guess block when + it was still analyzing the loopBegin block. As a consequence, + when it looked for the analysis_point it was processing the B, but + skipping over the C alternative altogether because it thought + it was looking at a guess block, not realizing there was a loop + block in front of the loopBegin. + + loopBegin loopBlk subBlk/guess A G EB G B EB EB EB ER + | | | ^ ^ + | | | | + | +-> G C G ----------------------+ | + | | + +--- G G G -------------------------------------+ + + Reported by Arpad Beszedes (beszedes@inf.u-szeged.hu). + + MR30 This is still more complicated. This fix caused ambiguity messages + to be reported for "( (A B)? )* A B" but not for "( (A B)? )+". Why is + there a difference when these are outwardly identical ? It is because the + start of a (...)* block is represented by two nodes: a loopBegin block + followed by a loopBlock whereas the start of a (...)+ block is + represented as a single node: a plusBlock. So if first_item_is_guess_block + is called when the current node is a loopBegin it starts with the + loop block rather than the sub block which follows the loop block. + However, we can't just skip past the loop block because some routines + depend on the old implementation. So, we provide a new implementation + which does skip the loopBlock. However, which should be called when ? + I'm not sure, but my guess is that first_item_is_guess_block_extra (the + new one) should only be called for the ambiguity routines. + + */ + + while ( q!=NULL && + ( ( q->ntype==nAction ) || + ( q->ntype==nJunction && + (q->jtype==Generic /*** || q->jtype == aLoopBlk ***/ ) /*** MR30 Undo MR14 change ***/ + ) + ) + ) + { + if ( q->ntype==nJunction ) q = (Junction *)q->p1; + else q = (Junction *) ((ActionNode *)q)->next; + } + + if ( q==NULL ) return NULL; + if ( q->ntype!=nJunction ) return NULL; + if ( q->jtype!=aSubBlk ) return NULL; + if ( !q->guess ) return NULL; + + return q; +} + +/* MR1 */ +/* MR1 10-Apr-97 MR1 Routine to stringize failed semantic predicates msgs */ +/* MR1 */ + +#define STRINGIZEBUFSIZE 1024 + +static char stringizeBuf[STRINGIZEBUFSIZE]; +char * +#ifdef __USE_PROTOS +stringize(char * s) +#else +stringize(s) +char *s; +#endif + +{ + char *p; + char *stop; + + p=stringizeBuf; + stop=&stringizeBuf[1015]; + + if (s != 0) { + while (*s != 0) { + if (p >= stop) { + goto stringizeStop; + } else if (*s == '\n') { + *p++='\\'; + *p++='n'; + *p++='\\'; + *p++=*s++; + } else if (*s == '\\') { + *p++=*s; + *p++=*s++; + } else if (*s == '\"') { + *p++='\\'; + *p++=*s++; + while (*s != 0) { + if (p >= stop) { + goto stringizeStop; + } else if (*s == '\n') { + *p++='\\'; + *p++=*s++; + } else if (*s == '\\') { + *p++=*s++; + *p++=*s++; + } else if (*s == '\"') { + *p++='\\'; + *p++=*s++; + break; + } else { + *p++=*s++; + }; + }; + } else if (*s == '\'') { + *p++=*s++; + while (*s != 0) { + if (p >= stop) { + goto stringizeStop; + } else if (*s == '\'') { + *p++=*s++; + break; + } else if (*s == '\\') { + *p++=*s++; + *p++=*s++; + } else if (*s == '\"') { + *p++='\\'; + *p++=*s++; + break; + } else { + *p++=*s++; + }; + }; + } else { + *p++=*s++; + }; + }; + }; + goto stringizeExit; +stringizeStop: + *p++='.'; + *p++='.'; + *p++='.'; +stringizeExit: + *p=0; + return stringizeBuf; +} + +#ifdef __USE_PROTOS +int isNullAction(char *s) +#else +int isNullAction(s) + char *s; +#endif +{ + char *p; + for (p=s; *p != '\0' ; p++) { + if (*p != ';' && *p !=' ') return 0; + }; + return 1; +} +/* MR1 */ +/* MR1 End of Routine to stringize code for failed predicates msgs */ +/* MR1 */ + +/* Generate an action. Don't if action is NULL which means that it was already + * handled as an init action. + */ +void +#ifdef __USE_PROTOS +genAction( ActionNode *p ) +#else +genAction( p ) +ActionNode *p; +#endif +{ + require(p!=NULL, "genAction: invalid node and/or rule"); + require(p->ntype==nAction, "genAction: not action"); + + if ( !p->done ) /* MR10 */ /* MR11 */ + { + if ( p->is_predicate) + { + if ( p->guardpred != NULL ) + { + Predicate *guardDup=predicate_dup(p->guardpred); /* MR10 */ + gen("if (!"); + guardDup=genPredTreeMain(guardDup, (Node *)p); + predicate_free(guardDup); + } +/* MR10 */ else if (p->ampersandPred != NULL) { +/* MR10 */ gen("if (!"); +/* MR10 */ p->ampersandPred=genPredTreeMain(p->ampersandPred, (Node *)p); +/* MR10 */ } + else + { + gen("if (!("); + /* make sure that '#line n' is on front of line */ + if ( GenLineInfo && p->file != -1 ) _gen("\n"); + dumpPredAction(p,p->action, output, 0, p->file, p->line, 0); + _gen(")"); + } + +/* MR23 Change failed predicate macro to have three arguments: + + macro arg 1: The stringized predicate itself + macro arg 2: 0 => no user-defined error action + 1 => user-defined error action + macro arg 3: The user-defined error action + + This gives the user more control of the error action. +*/ + tabs++; + gen3(") {zzfailed_pred(\"%s\",%s, { %s } );}\n", /* MR23 */ + stringize(p->action), /* MR23 */ + (p->pred_fail == NULL ? /* MR23/MR27 */ + "0 /* report */" : "1 /* user action */"), /* MR23/MR27 */ + (p->pred_fail == NULL ? /* MR23 */ + "; /* no user action */" : p->pred_fail)); /* MR23 */ + tabs--; + } + else /* not a predicate */ + { + if (! isNullAction(p->action) && !p->noHoist) { + if ( FoundGuessBlk ) { + if ( GenCC ) { + gen("if ( !guessing ) {\n"); + } else { + gen("zzNON_GUESS_MODE {\n"); + }; + }; + dumpActionPlus(p, p->action, output, tabs, p->file, p->line, 1); /* MR21 */ + if ( FoundGuessBlk ) gen("}\n"); + }; + } + } + TRANS(p->next) +} + +/* + * if invoking rule has !noAST pass zzSTR to rule ref and zzlink it in + * else pass addr of temp root ptr (&_ast) (don't zzlink it in). + * + * if ! modifies rule-ref, then never link it in and never pass zzSTR. + * Always pass address of temp root ptr. + */ +void +#ifdef __USE_PROTOS +genRuleRef( RuleRefNode *p ) +#else +genRuleRef( p ) +RuleRefNode *p; +#endif +{ + Junction *q; + char *handler_id = ""; + RuleEntry *r, *r2; + char *parm = "", *exsig = ""; + + int genRuleRef_emittedGuessGuard=0; /* MR10 */ + + require(p!=NULL, "genRuleRef: invalid node and/or rule"); + require(p->ntype==nRuleRef, "genRuleRef: not rule reference"); + + if ( p->altstart!=NULL && p->altstart->exception_label!=NULL ) + handler_id = p->altstart->exception_label; + + r = (RuleEntry *) hash_get(Rname, p->text); + if ( r == NULL ) + { + warnFL( eMsg1("rule %s not defined", + p->text), FileStr[p->file], p->line ); + return; + } + +/* MR8 5-Aug-97 Reported by S.Bochnak@microtool.com.pl */ +/* Don't do assign when no return values declared */ +/* Move definition of q up and use it to guard p->assign */ + + q = RulePtr[r->rulenum]; /* find definition of ref'd rule */ /* MR8 */ + + r2 = (RuleEntry *) hash_get(Rname, p->rname); + if ( r2 == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;} + + OutLineInfo(output,p->line,FileStr[p->file]); + + if ( GenCC && GenAST ) { + gen("_ast = NULL;\n"); + } + + if ( FoundGuessBlk && p->assign!=NULL && q->ret != NULL ) { /* MR8 */ + if ( GenCC ) { + gen("if ( !guessing ) {\n"); + } else { + gen("zzNON_GUESS_MODE {\n"); + }; + tabs++; /* MR11 */ + genRuleRef_emittedGuessGuard=1; /* MR11 */ + }; + + if ( FoundException ) exsig = "&_signal"; + + tab(); + if ( GenAST ) + { + if ( GenCC ) { +/**** if ( r2->noAST || p->astnode==ASTexclude ) +****/ + { +/**** _gen("_ast = NULL;\n"); +****/ + parm = "&_ast"; + } +/*** we always want to set just a pointer now, then set correct +pointer after + + else { + _gen("_astp = +(_tail==NULL)?(&_sibling):(&(_tail->_right));\n"); + parm = "_astp"; + } +****/ + } + else { + if ( r2->noAST || p->astnode==ASTexclude ) + { + _gen("_ast = NULL; "); + parm = "&_ast"; + } + else parm = "zzSTR"; + } + if ( p->assign!=NULL && q->ret!=NULL ) /* MR8 */ + { + if ( !hasMultipleOperands(p->assign) ) {_gen1("%s = ",p->assign);} /* MR23 */ + else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum); + } + if ( FoundException ) { + _gen5("%s%s(%s,&_signal%s%s); ", + RulePrefix, + p->text, + parm, + (p->parms!=NULL)?",":"", + (p->parms!=NULL)?p->parms:""); + if ( p->ex_group!=NULL ) { + _gen("\n"); + gen("if (_signal) {\n"); + tabs++; + dumpException(p->ex_group, 0); + tabs--; + gen("}"); + } + else { + _gen1("if (_signal) goto %s_handler;", handler_id); + } + } + else { + _gen5("%s%s(%s%s%s);", + RulePrefix, + p->text, + parm, + (p->parms!=NULL)?",":"", + (p->parms!=NULL)?p->parms:""); + } + if ( GenCC && (r2->noAST || p->astnode==ASTexclude) ) + { + /* rule has a ! or element does */ + /* still need to assign to #i so we can play with it */ + _gen("\n"); + gen2("_ast%d%d = (AST *)_ast;", BlkLevel-1, p->elnum); + } + else if ( !r2->noAST && p->astnode == ASTinclude ) + { + /* rule doesn't have a ! and neither does element */ +/* MR10 */ if (FoundGuessBlk && !genRuleRef_emittedGuessGuard) { +/* MR10 */ _gen("\n"); +/* MR10 */ if (GenCC) gen ("if (!guessing) { /* MR10 */") +/* MR10 */ else gen ("if (!zzguessing) { /* MR10 */\n"); +/* MR10 */ tabs++; +/* MR10 */ }; + if ( GenCC ) { + _gen("\n"); + gen("if ( _tail==NULL ) _sibling = _ast; else _tail->setRight(_ast);\n"); + gen2("_ast%d%d = (AST *)_ast;\n", BlkLevel-1, p->elnum); + tab(); + } + else _gen(" "); + if ( GenCC ) { + _gen("ASTBase::"); } + else _gen("zz"); + _gen("link(_root, &_sibling, &_tail);"); + +/* MR10 */ if (FoundGuessBlk && !genRuleRef_emittedGuessGuard) { /* MR10 */ +/* MR10 */ _gen("\n"); +/* MR10 */ tabs--; +/* MR10 */ if (GenCC) gen ("}; /* MR10 */") +/* MR10 */ else gen ("}; /* MR10 */"); +/* MR10 */ }; + } + } + else + { + if ( p->assign!=NULL && q->ret!=NULL ) /* MR8 */ + { + if ( !hasMultipleOperands(p->assign) ) {_gen1("%s = ",p->assign);} /* MR23 */ + else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum); + } + if ( FoundException ) { + _gen4("%s%s(&_signal%s%s); ", + RulePrefix, + p->text, + (p->parms!=NULL)?",":"", + (p->parms!=NULL)?p->parms:""); + if ( p->ex_group!=NULL ) { + _gen("\n"); + gen("if (_signal) {\n"); + tabs++; + dumpException(p->ex_group, 0); + tabs--; + gen("}"); + } + else { + _gen1("if (_signal) goto %s_handler;", handler_id); + } + } + else { + _gen3("%s%s(%s);", + RulePrefix, + p->text, + (p->parms!=NULL)?p->parms:""); + } + if ( p->assign!=NULL && q->ret!=NULL ) _gen("\n"); /* MR8 */ + } + + if ( p->assign!=NULL && q->ret!=NULL) { /* MR8 */ + if ( hasMultipleOperands(p->assign) ) /* MR23 */ + { + _gen("\n"); + dumpRetValAssign(p->assign, q->ret, p); /* MR30 */ + _gen("}"); + } + } + _gen("\n"); + + /* Handle element labels now */ + if ( p->el_label!=NULL ) + { + if ( GenAST ) + { + if ( GenCC ) { + gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum); + } + else {gen1("%s_ast = zzastCur;\n", p->el_label);} + } + else if (!GenCC ) { + gen1("%s = zzaCur;\n", p->el_label); + } + } + + if ( FoundGuessBlk && p->assign!=NULL && q->ret!=NULL ) { /* MR8 */ + /* in guessing mode, don't branch to handler upon error */ + tabs--; /* MR11 */ + gen("} else {\n"); + tabs++; /* MR11 */ + if ( FoundException ) { + gen6("%s%s(%s%s&_signal%s%s);\n", + RulePrefix, + p->text, + parm, + (*parm!='\0')?",":"", + (p->parms!=NULL)?",":"", + (p->parms!=NULL)?p->parms:""); + } + else { + gen5("%s%s(%s%s%s);\n", + RulePrefix, + p->text, + parm, + (p->parms!=NULL && *parm!='\0')?",":"", + (p->parms!=NULL)?p->parms:""); + } + tabs--; /* MR11 */ + gen("}\n"); + } + TRANS(p->next) +} + +/* + * Generate code to match a token. + * + * Getting the next token is tricky. We want to ensure that any action + * following a token is executed before the next GetToken(); + */ +void +#ifdef __USE_PROTOS +genToken( TokNode *p ) +#else +genToken( p ) +TokNode *p; +#endif +{ + RuleEntry *r; + char *handler_id = ""; + ActionNode *a; + char *set_name; + char *set_nameErrSet; + int complement; + int ast_label_in_action = 0; /* MR27 */ + int pushedCmodeAST = 0; /* MR27 */ + + require(p!=NULL, "genToken: invalid node and/or rule"); + require(p->ntype==nToken, "genToken: not token"); + if ( p->altstart!=NULL && p->altstart->exception_label!=NULL ) + handler_id = p->altstart->exception_label; + + r = (RuleEntry *) hash_get(Rname, p->rname); + if ( r == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;} + +/* + * MR27 Has the element label been referenced as an AST (with the # operator) ? + * If so, then we'll want to build the AST even though the user has used + * the ! operator. + */ +/* MR27 */ if (GenAST && p->el_label != NULL) { +/* MR27 */ ast_label_in_action = list_search_cstring(r->ast_labels_in_actions, +/* MR27 */ p->el_label); +/* MR27 */ } + + OutLineInfo(output,p->line,FileStr[p->file]); + + if ( !set_nil(p->tset) ) /* implies '.', ~Tok, or tokenclass */ + { + unsigned e; + unsigned eErrSet = 0; + set b; + set bErrSet; /* MR23 */ + b = set_dup(p->tset); + bErrSet = set_dup(p->tset); /* MR23 */ + complement = p->complement; /* MR23 */ + if ( p->tclass!=NULL && complement == 0 /* MR23 */) { /* token class not complemented*/ + static char buf[MaxRuleName+20]; /* MR23 */ + static char bufErrSet[MaxRuleName+20]; /* MR23 */ + if ( p->tclass->dumped ) { + e = p->tclass->setnum; + eErrSet = p->tclass->setnumErrSet; + } + else { + e = DefErrSet(&b, 0, TokenString(p->token)); + eErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, TokenString(p->token), "_errset"); + p->tclass->dumped = 1; /* indicate set has been created */ + p->tclass->setnum = e; + p->tclass->setnumErrSet = eErrSet; /* MR23 */ + } + sprintf(buf, "%s_set", TokenString(p->token)); + sprintf(bufErrSet, "%s_errset", TokenString(p->token)); /* MR23 */ + set_name = buf; + set_nameErrSet = bufErrSet; /* MR23 */ + } + + /* MR23 - Forgot about the case of ~TOKCLASS. */ + + else if ( p->tclass!=NULL && complement != 0 /* MR23 */) + { + static char buf[MaxRuleName+20]; /* MR23 */ + static char bufErrSet[MaxRuleName+20]; /* MR23 */ + if ( p->tclass->dumpedComplement ) { + e = p->tclass->setnumComplement; + eErrSet = p->tclass->setnumErrSetComplement; + } + else { + e = DefErrSetWithSuffix(0, &b, 0, TokenString(p->token), "_setbar"); + eErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, TokenString(p->token), "_errsetbar"); + p->tclass->dumpedComplement = 1; /* indicate set has been created */ + p->tclass->setnumComplement = e; + p->tclass->setnumErrSetComplement = eErrSet; /* MR23 */ + } + sprintf(buf, "%s_setbar", TokenString(p->token)); + sprintf(bufErrSet, "%s_errsetbar", TokenString(p->token)); /* MR23 */ + set_name = buf; + set_nameErrSet = bufErrSet; /* MR23 */ + } + else { /* wild card */ + static char buf[sizeof("zzerr")+10]; + static char bufErrSet[sizeof("zzerr")+10]; + int n = DefErrSet( &b, 0, NULL ); + int nErrSet = DefErrSetWithSuffix(0, &bErrSet, 1, NULL, "_set"); + if ( GenCC ) sprintf(buf, "err%d", n); + else sprintf(buf, "zzerr%d", n); + if ( GenCC ) sprintf(bufErrSet, "err%d", nErrSet); + else sprintf(bufErrSet, "zzerr%d", nErrSet); + set_name = buf; + set_nameErrSet = bufErrSet; + } + + if ( !FoundException ) { +/* MR23 */ gen2("zzsetmatch(%s, %s);", set_name, set_nameErrSet); + } + else if ( p->ex_group==NULL ) { + if ( p->use_def_MT_handler ) + gen3("zzsetmatch_wdfltsig(%s,(ANTLRTokenType)%d,%s);", + set_name, + p->token, + tokenFollowSet(p)) + else + gen2("zzsetmatch_wsig(%s, %s_handler);", + set_name, + handler_id); + } + else + { + gen1("if ( !_setmatch_wsig(%s) ) {\n", set_name); + tabs++; +/* MR6 */ if (FoundGuessBlk) { +/* MR6 */ if ( GenCC ) {gen("if ( guessing ) goto fail;\n");} +/* MR6 */ else gen("if ( zzguessing ) goto fail;\n"); +/* MR6 */ }; + gen("_signal=MismatchedToken;\n"); + dumpException(p->ex_group, 0); + tabs--; + gen("}\n"); + } + set_free(b); + set_free(bErrSet); + } + else if ( TokenString(p->token)!=NULL ) + { + if ( FoundException ) { + if ( p->use_def_MT_handler ) + gen2("zzmatch_wdfltsig(%s,%s);",TokenString(p->token),tokenFollowSet(p)) + else if ( p->ex_group==NULL ) + { + gen2("zzmatch_wsig(%s, %s_handler);", + TokenString(p->token), + handler_id); + } + else + { +/* MR6 */ if (GenCC) { +/* MR6 */ gen1("if ( !_match_wsig(%s) ) {\n", TokenString(p->token)); +/* MR6 */ } else { +/* MR6 */ gen1("if ( !_zzmatch_wsig(%s) ) {\n", TokenString(p->token)); +/* MR6 */ }; + tabs++; +/* MR6 */ if (FoundGuessBlk) { +/* MR6 */ if ( GenCC ) {gen("if ( guessing ) goto fail;\n");} +/* MR6 */ else gen("if ( zzguessing ) goto fail;\n"); +/* MR6 */ }; + gen("_signal=MismatchedToken;\n"); + dumpException(p->ex_group, 0); + tabs--; + gen("}\n"); + } + } + else gen1("zzmatch(%s);", TokenString(p->token)); + } + else { + if ( FoundException ) { + if ( p->use_def_MT_handler ) + gen2("zzmatch_wdfltsig((ANTLRTokenType)%d,%s);", + p->token,tokenFollowSet(p)) + else + gen2("zzmatch_wsig(%d,%s_handler);",p->token,handler_id); + } + else {gen1("zzmatch(%d);", p->token);} + } + + a = findImmedAction( p->next ); + /* generate the token labels */ + if ( GenCC && p->elnum>0 ) + { + /* If building trees in C++, always gen the LT() assigns */ + if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) + { +/* MR10 */ if ( FoundGuessBlk ) { +/* MR10 */ gen("\n"); +/* MR10 */ if (p->label_used_in_semantic_pred) { +/* MR10 */ gen2(" _t%d%d = (ANTLRTokenPtr)LT(1); /* MR10 */\n", BlkLevel-1, p->elnum); +/* MR10 */ } else { +/* MR10 */ gen("if ( !guessing ) {\n"); tab(); +/* MR10 */ _gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);\n", BlkLevel-1, p->elnum); +/* MR10 */ gen("}\n"); +/* MR10 */ }; +/* MR10 */ } else { +/* MR10 */ _gen2(" _t%d%d = (ANTLRTokenPtr)LT(1);", BlkLevel-1, p->elnum); +/* MR10 */ }; +/* MR10 */ + } + +/* + * MR23 labase is never used in the C++ runtime library. + * and this code is generated only in C++ mode + */ + +/*** if ( LL_k>1 ) / * MR23 disabled */ +/*** if ( !DemandLookahead ) _gen(" labase++;"); / * MR23 disabled */ +/*** _gen("\n"); / * MR23 disabled */ +/*** tab(); / * MR23 disabled */ + } + if ( GenAST ) + { + if ( FoundGuessBlk && + (ast_label_in_action || !(p->astnode == ASTexclude || r->noAST)) ) + { + if ( GenCC ) {_gen("if ( !guessing ) {\n"); tab();} + else {_gen("zzNON_GUESS_MODE {\n"); tab();} + } + +/* MR27 addition when labels referenced when operator ! used */ + + pushedCmodeAST = 0; /* MR27 */ + if (ast_label_in_action && (p->astnode == ASTexclude || r->noAST)) { + _gen("\n"); + if (GenCC) { +/* MR13 */ if (NewAST) { +/* MR13 */ gen4("_ast%d%d = newAST(_t%d%d); /* MR27 */\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum); +/* MR13 */ } else { +/* MR13 */ gen4("_ast%d%d = new AST(_t%d%d); /* MR27 */\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum); +/* MR13 */ } + } + else { + pushedCmodeAST = 1; + gen("zzastPush(zzmk_ast(zzastnew(),zzaCur)); /* MR27 */"); + } + } + +/* end MR27 addition for labels referenced when operator ! used */ + + if (!r->noAST ) + { + if (GenCC && !(p->astnode == ASTexclude) ) { + _gen("\n"); +/* MR13 */ if (NewAST) { +/* MR13 */ gen4("_ast%d%d = newAST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum); +/* MR13 */ } else { +/* MR13 */ gen4("_ast%d%d = new AST(_t%d%d);\n", BlkLevel-1, p->elnum, BlkLevel-1, p->elnum); +/* MR13 */ } + tab(); + } + if ( GenCC && !(p->astnode == ASTexclude) ) + {_gen2("_ast%d%d->", BlkLevel-1, p->elnum);} + else _gen(" "); + if ( p->astnode==ASTchild ) { + if ( !GenCC ) _gen("zz"); + _gen("subchild(_root, &_sibling, &_tail);"); + } + else if ( p->astnode==ASTroot ) { + if ( !GenCC ) _gen("zz"); + _gen("subroot(_root, &_sibling, &_tail);"); + } + if ( GenCC && !(p->astnode == ASTexclude) ) { + _gen("\n"); + tab(); + } + } + else if ( !GenCC ) { + if (! pushedCmodeAST) _gen(" zzastDPush;"); + } + if ( FoundGuessBlk && + (ast_label_in_action || !(p->astnode == ASTexclude || r->noAST)) ) + {gen("}\n"); tab();} + } + + /* Handle element labels now */ + if ( p->el_label!=NULL ) + { + int done_NON_GUESSMODE=0; + + _gen("\n"); + +/* MR10 */ /* do Attrib / Token ptr for token label used in semantic pred */ +/* MR10 */ /* for these cases do assign even in guess mode */ +/* MR10 */ +/* MR10 */ if (p->label_used_in_semantic_pred) { +/* MR10 */ if ( GenCC ) { +/* MR10 */ if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) { +/* MR10 */ gen3("%s = _t%d%d;", p->el_label, BlkLevel-1, p->elnum); +/* MR10 */ } else { +/* MR10 */ gen1("%s = (ANTLRTokenPtr)LT(1);\n", p->el_label); +/* MR10 */ }; +/* MR10 */ } else { +/* MR10 */ gen1("%s = zzaCur;", p->el_label); +/* MR10 */ }; +/* MR10 */ if (FoundGuessBlk) _gen(" /* MR10 */"); +/* MR10 */ _gen("\n"); +/* MR10 */ }; + + /* Do Attrib / Token ptr */ + +/* MR10 */ if (! p->label_used_in_semantic_pred) { +/* MR10 */ +/* MR10 */ if ( FoundGuessBlk ) { +/* MR10 */ if (! done_NON_GUESSMODE) { +/* MR10 */ done_NON_GUESSMODE=1; +/* MR10 */ if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();} +/* MR10 */ else {gen("zzNON_GUESS_MODE {\n"); tab();} +/* MR10 */ }; +/* MR10 */ }; +/* MR10 */ +/* MR10 */ if ( GenCC ) { +/* MR10 */ if ( set_el(p->elnum, tokensRefdInBlock) || GenAST ) { +/* MR10 */ gen3("%s = _t%d%d;\n", p->el_label, BlkLevel-1, p->elnum); +/* MR10 */ } else { +/* MR10 */ gen1("%s = (ANTLRTokenPtr)LT(1);\n", p->el_label); +/* MR10 */ }; +/* MR10 */ } else { +/* MR10 */ gen1("%s = zzaCur;\n", p->el_label); +/* MR10 */ }; +/* MR10 */ }; + + /* Do AST ptr */ + + if (GenAST && (ast_label_in_action || !(p->astnode == ASTexclude || r->noAST) )) /* MR27 */ + { + +/* MR10 */ if ( FoundGuessBlk ) { +/* MR10 */ if (! done_NON_GUESSMODE) { +/* MR10 */ done_NON_GUESSMODE=1; +/* MR10 */ if ( GenCC ) {gen("if ( !guessing ) {\n"); tab();} +/* MR10 */ else {gen("zzNON_GUESS_MODE {\n"); tab();} +/* MR10 */ }; +/* MR10 */ }; + + if ( GenCC ) { + gen3("%s_ast = _ast%d%d;\n", p->el_label, BlkLevel-1, p->elnum); + } + else {gen1("%s_ast = zzastCur;\n", p->el_label);} + } + +/* MR10 */ if (done_NON_GUESSMODE) { +/* MR10 */ gen("}\n"); tab(); +/* MR10 */ }; + + } + + /* Handle any actions immediately following action */ + if ( a != NULL ) /* MR10 */ /* MR11 */ + { + /* delay next token fetch until after action */ + _gen("\n"); + if ( a->is_predicate) + { +#if 0 +/* Disabled in MR30 ************************************************************ + And moved into genAction + ***************************************************************************** +*/ + + gen("if (!("); + + /* make sure that '#line n' is on front of line */ /* MR14 */ + if ( GenLineInfo && p->file != -1 ) _gen("\n"); /* MR14 */ + dumpPredAction(a,a->action, output, 0, a->file, a->line, 0); + +/* MR23 Change failed predicate macro to have three arguments: + + macro arg 1: The stringized predicate itself + macro arg 2: 0 => no user-defined error action + 1 => user-defined error action + macro arg 3: The user-defined error action + + This gives the user more control of the error action. +*/ + _gen(")) \n"); + tabs++; + gen3(" {zzfailed_pred(\"%s\",%s,{ %s } );}\n", /* MR23 */ + stringize(a->action), /* MR23 */ + (a->pred_fail == NULL ? /* MR23/MR27 */ + "0 /* report */" : "1 /* user action */"), /* MR23/MR27 */ + (a->pred_fail == NULL ? /* MR23 */ + "; /* no user action */" : a->pred_fail)); /* MR23 */ + tabs--; +/* Disabled in MR30 ************************************************************ + And moved into genAction + ***************************************************************************** +*/ +#endif + } + else /* MR9 a regular action - not a predicate action */ + { + +/* MR23: Search an action which is not a predicate for LT(i), + LA(i), or LATEXT(i) in order to warn novice users that + it refers to the previous matched token, not the next + one. This is different than the case for semantic + predicates. +*/ + +/* MR23 */ if (GenCC) { +/* MR23 */ if (strstr(a->action, "LT(") != NULL) LTinTokenAction = 1; +/* MR23 */ } +/* MR23 */ else { +/* MR23 */ if (strstr(a->action, "LA(") != NULL) LTinTokenAction = 1; +/* MR23 */ if (strstr(a->action, "LATEXT(") != NULL) LTinTokenAction = 1; +/* MR23 */ } + + if ( FoundGuessBlk ) { + if ( GenCC ) {gen("if ( !guessing ) {\n");} + else gen("zzNON_GUESS_MODE {\n"); + } + dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1); /* MR21 */ + if ( FoundGuessBlk ) gen("}\n"); + a->done = 1; /* MR30 */ + } +/*** a->done = 1; MR30 Moved up into then branch for true actions, but not predicates ***/ + if ( !DemandLookahead ) { + if ( GenCC ) { + if ( FoundException && p->use_def_MT_handler ) gen("if (!_signal)"); + _gen(" consume();") + if ( FoundException && p->use_def_MT_handler ) + _gen(" _signal=NoSignal;"); + _gen("\n"); + } + else + { + if ( FoundException && p->use_def_MT_handler ) _gen("if (!_signal)"); + _gen(" zzCONSUME;\n"); + if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;"); + _gen("\n"); + } + } + else gen("\n"); + if (a->done) { /* MR30 */ + TRANS( a->next ); /* MR30 */ + } /* MR30 */ + else { /* MR30 */ + TRANS( p->next ); /* MR30 */ + } /* MR30 */ + } + else + { + if ( !DemandLookahead ) { + if ( GenCC ) { + if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)"); + _gen(" consume();") + if (FoundException&&p->use_def_MT_handler) _gen(" _signal=NoSignal;"); + _gen("\n"); + } + else { + if (FoundException && p->use_def_MT_handler) _gen("if (!_signal)"); + _gen(" zzCONSUME;"); + if ( FoundException && p->use_def_MT_handler ) _gen(" _signal=NoSignal;"); + _gen("\n"); + } + } + else _gen("\n"); + TRANS(p->next); + } +} + +/* MR21 + * + * There was a bug in the code generation for {...} which causes it + * to omit the optional tokens from the error messages. The easiest + * way to fix this was to make the opt block look like a sub block: + * + * { a | b | c } + * + * becomes (internally): + * + * ( a | b | c | ) + * + * The code for genOptBlk is now identical to genSubBlk except for + * cosmetic changes. + */ + +void +#ifdef __USE_PROTOS +genOptBlk( Junction *q ) +#else +genOptBlk( q ) +Junction *q; +#endif +{ + int max_k; + set f; + int need_right_curly; + set savetkref; + int lastAltEmpty; /* MR23 */ + savetkref = tokensRefdInBlock; + require(q->ntype == nJunction, "genOptBlk: not junction"); + require(q->jtype == aOptBlk, "genOptBlk: not opt block"); + + OutLineInfo(output,q->line,FileStr[q->file]); + BLOCK_Preamble(q); + BlkLevel++; + BlockPreambleOption(q,q->pFirstSetSymbol); /* MR21 */ + f = genBlk(q, aOptBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */); +/* MR23 + Bypass error clause generation when exceptions are used in {...} block + See multi-line note in genBlk near call to isEmptyAlt. +*/ + if (! FoundException) { + if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );} + } + else { + gen("/* MR23 skip error clause for {...} when exceptions in use */\n"); + } + { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} } + freeBlkFsets(q); + --BlkLevel; + BLOCK_Tail(); + + if ( q->guess ) + { + gen("zzGUESS_DONE\n"); + } + + /* must duplicate if (alpha)?; one guesses (validates), the + * second pass matches */ + if ( q->guess && analysis_point(q)==q ) + { + OutLineInfo(output,q->line,FileStr[q->file]); + BLOCK_Preamble(q); + BlkLevel++; + f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */); + if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );} + { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} } + freeBlkFsets(q); + --BlkLevel; + BLOCK_Tail(); + } + + tokensRefdInBlock = savetkref; + if (q->end->p1 != NULL) TRANS(q->end->p1); +} + +/* + * Generate code for a loop blk of form: + * + * |---| + * v | + * --o-G-o-->o-- + */ +void +#ifdef __USE_PROTOS +genLoopBlk( Junction *begin, Junction *q, Junction *start, int max_k ) +#else +genLoopBlk( begin, q, start, max_k ) +Junction *begin; +Junction *q; +Junction *start; /* where to start generating code from */ +int max_k; +#endif +{ + set f; + int need_right_curly; + set savetkref; + Junction *guessBlock; /* MR10 */ + int singleAlt; /* MR10 */ + int lastAltEmpty; /* MR23 */ + + savetkref = tokensRefdInBlock; + require(q->ntype == nJunction, "genLoopBlk: not junction"); + require(q->jtype == aLoopBlk, "genLoopBlk: not loop block"); + + if ( q->visited ) return; + q->visited = TRUE; + + /* first_item_is_guess_block doesn't care what kind of node it is */ + + guessBlock=first_item_is_guess_block( (Junction *) q->p1); /* MR10 */ + singleAlt=q->p2==NULL; /* MR10 */ + + if (singleAlt && !guessBlock) /* MR10 */ /* only one alternative? */ + { + if ( DemandLookahead ) { + if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);} + else gen1("look(%d);\n", max_k); + } + gen("while ( "); + if ( begin!=NULL ) genExpr(begin); + else genExpr(q); + /* if no predicates have been hoisted for this single alt (..)* + * do so now + */ + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + if ( ParseWithPredicates && begin->predicate==NULL ) + { + Predicate *a = MR_find_predicates_and_supp((Node *)q->p1); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + + if ( a!=NULL ) + { + _gen("&&"); + a=genPredTreeMain(a, (Node *)q); /* MR10 */ + } +/* MR10 */ if (MRhoisting) { +/* MR10 */ predicate_free(a); +/* MR10 */ }; + } + _gen(" ) {\n"); + tabs++; + TRANS(q->p1); + if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1); + if ( DemandLookahead ) { + if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);} + else gen1("look(%d);\n", max_k); + } + --tabs; + gen("}\n"); + freeBlkFsets(q); + q->visited = FALSE; + tokensRefdInBlock = savetkref; + return; + } + gen("for (;;) {\n"); /* MR20 G. Hobbelt */ + tabs++; +/* MR6 */ +/* MR6 "begin" can never be null when called from genLoopBegin */ +/* MR6 because q==(Junction *)begin->p1 and we know q is valid */ +/* MR6 */ +/* MR6 from genLoopBegin: */ +/* MR6 */ +/* MR6 if ( LL_k>1 && !set_nil(q->fset[2]) ) */ +/* MR6 genLoopBlk( q, (Junction *)q->p1, q, max_k ); */ +/* MR6 else genLoopBlk( q, (Junction *)q->p1, NULL, max_k ); */ +/* MR6 */ + if ( begin!=NULL ) + { + if ( DemandLookahead ) + { + if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);} + else gen1("look(%d);\n", max_k); + } + /* The bypass arc of the (...)* predicts what to do when you fail, but + * ONLY after having tested the loop start expression. To avoid this, + * we simply break out of the (...)* loop when we find something that + * is not in the prediction of the loop (all alts thereof). + */ + gen("if ( !("); + +/*** TJP says: It used to use the prediction expression for the bypass arc + of the (...)*. HOWEVER, if a non LL^1(k) decision was found, this + thing would miss the ftree stored in the aLoopBegin node and generate + an LL^1(k) decision anyway. + + *** genExpr((Junction *)begin->p2); + ***/ + + genExpr((Junction *)begin); + _gen(")) break;\n"); + + } + + /* generate code for terminating loop (this is optional branch) */ + + f = genBlk(q, aLoopBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */); + set_free(f); + freeBlkFsets(q); + + /* generate code for terminating loop (this is optional branch) */ + +/* MR6 */ +/* MR6 30-May-97 Bug reported by Manuel Ornato */ +/* MR6 A definite bug involving the exit from a loop block */ +/* MR6 In 1.23 and later versions (including 1.33) Instead */ +/* MR6 exiting the block and reporting a syntax error the */ +/* MR6 code loops forever. */ +/* MR6 Looking at 1.20 which generates proper code it is not */ +/* MR6 clear which of two changes should be undone. */ +/* MR6 This is my best guess. */ +/* MR6 From earlier MR6 note we know that begin can never be */ +/* MR6 null when genLoopBlk called from genLoopBegin */ +/* MR6 */ +/* MR6 */ if ( begin==NULL) { +/* MR6 */ /* code for exiting loop "for sure" */ +/* MR6 */ gen("/* Suppressed by MR6 */ /*** else break; ***/\n"); +/* MR6 */ }; + +/* MR10 */if (singleAlt && guessBlock) { +/* MR10 */ tabs--; +/* MR6 */ gen("} else break; /* MR6 code for exiting loop \"for sure\" */\n"); +/* MR10 */ need_right_curly--; +/* MR10 */ } else { +/* MR6 */ gen("else break; /* MR6 code for exiting loop \"for sure\" */\n"); +/* MR10 */ }; + + { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} } + if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1); + --tabs; + gen("}\n"); + q->visited = FALSE; + tokensRefdInBlock = savetkref; +} + +/* + * Generate code for a loop blk of form: + * + * |---| + * v | + * --o-->o-->o-G-o-->o-- + * | ^ + * v | + * o-----------o + * + * q->end points to the last node (far right) in the blk. + * + * Note that q->end->jtype must be 'EndBlk'. + * + * Generate code roughly of the following form: + * + * do { + * ... code for alternatives ... + * } while ( First Set of aLoopBlk ); + * + * OR if > 1 alternative + * + * do { + * ... code for alternatives ... + * else break; + * } while ( 1 ); + */ +void +#ifdef __USE_PROTOS +genLoopBegin( Junction *q ) +#else +genLoopBegin( q ) +Junction *q; +#endif +{ + set f; + int i; + int max_k; + set savetkref; + savetkref = tokensRefdInBlock; + require(q!=NULL, "genLoopBegin: invalid node and/or rule"); + require(q->ntype == nJunction, "genLoopBegin: not junction"); + require(q->jtype == aLoopBegin, "genLoopBegin: not loop block"); + require(q->p2!=NULL, "genLoopBegin: invalid Loop Graph"); + + OutLineInfo(output,q->line,FileStr[q->file]); + + BLOCK_Preamble(q); + BlkLevel++; + BlockPreambleOption(q,q->pFirstSetSymbol); /* MR21 */ + f = First(q, 1, aLoopBegin, &max_k); + /* If not simple LL(1), must specify to start at LoopBegin, not LoopBlk */ + if ( LL_k>1 && !set_nil(q->fset[2]) ) + genLoopBlk( q, (Junction *)q->p1, q, max_k ); + else genLoopBlk( q, (Junction *)q->p1, NULL, max_k ); + + for (i=1; i<=CLL_k; i++) set_free(q->fset[i]); + for (i=1; i<=CLL_k; i++) set_free(((Junction *)q->p2)->fset[i]); + --BlkLevel; + BLOCK_Tail(); + set_free(f); + tokensRefdInBlock = savetkref; +/* MR21 */ if (MR_BlkErr) { +/* MR21 */ set f, fArray[2]; +/* MR21 */ f = ComputeErrorSet(q,1,0 /* use plus block bypass ? */ ); +/* MR21 */ fArray[0]= empty; +/* MR21 */ fArray[1]= set_dup(f); +/* MR21 */ gen("if ("); +/* MR21 */ genExprSets(fArray,1); /* note: destroys set arguments */ +/* MR21 */ _gen(") { /* MR21 option -mrblksynerr */\n"); +/* MR21 */ tabs++; +/* MR21 */ tab(); +/* MR21 */ _gen("/* nothing */ }\n"); +/* MR21 */ tab(); +/* MR21 */ makeErrorClause(q,f,1,0 /* use plus block bypass ? */ ); /* frees set */ +/* MR21 */ tabs--; +/* MR21 */ }; + if (q->end->p1 != NULL) TRANS(q->end->p1); +} + +/* + * Generate code for a loop blk of form: + * + * |---| + * v | + * --o-G-o-->o-- + * + * q->end points to the last node (far right) in the blk. + * Note that q->end->jtype must be 'EndBlk'. + * + * Generate code roughly of the following form: + * + * do { + * ... code for alternatives ... + * } while ( First Set of aPlusBlk ); + * + * OR if > 1 alternative + * + * do { + * ... code for alternatives ... + * else if not 1st time through, break; + * } while ( 1 ); + */ +void +#ifdef __USE_PROTOS +genPlusBlk( Junction *q ) +#else +genPlusBlk( q ) +Junction *q; +#endif +{ + int max_k; + set f; + int need_right_curly; + int lastAltEmpty; /* MR23 */ + set savetkref; + Junction *guessBlock; /* MR10 */ + int singleAlt; /* MR10 */ + + savetkref = tokensRefdInBlock; + require(q!=NULL, "genPlusBlk: invalid node and/or rule"); + require(q->ntype == nJunction, "genPlusBlk: not junction"); + require(q->jtype == aPlusBlk, "genPlusBlk: not Plus block"); + require(q->p2 != NULL, "genPlusBlk: not a valid Plus block"); + + if ( q->visited ) return; + q->visited = TRUE; + OutLineInfo(output,q->line,FileStr[q->file]); + BLOCK_Preamble(q); + BlkLevel++; + + BlockPreambleOption((Junction *)q, q->pFirstSetSymbol); /* MR21 */ + + /* first_item_is_guess_block doesn't care what kind of node it is */ + + guessBlock=first_item_is_guess_block( (Junction *)q->p1); /* MR10 */ + + /* if the ignore flag is set on the 2nd alt and that alt is empty, + * then it is the implied optional alternative that we added for (...)+ + * and, hence, only 1 alt. + */ + +/* MR10 Reported by Pulkkinen Esa (esap@cs.tut.fi) + * Outer code for guess blocks ignored when there is only one alt + * for a (...)+ block. + * Force use of regular code rather than "optimized" code for that case + */ + + singleAlt=( ( (Junction *) q->p2)->p2 == NULL) && + ( ( (Junction *) q->p2)->ignore ); /* only one alternative? */ + + if (singleAlt && !guessBlock) /* MR10 */ + { + + Predicate *a=NULL; + /* if the only alt has a semantic predicate, hoist it; must test before + * entering loop. + */ + if ( ParseWithPredicates ) + { + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + a = MR_find_predicates_and_supp((Node *)q); + require(MR_PredRuleRefStack.count == 0,"PredRuleRef stack not empty"); + + if ( a!=NULL ) { + gen("if ("); + a=genPredTreeMain(a, (Node *)q); /* MR10 */ + _gen(") {\n"); + } + } + gen("do {\n"); + tabs++; + TRANS(q->p1); + if ( !GenCC ) gen1("zzLOOP(zztasp%d);\n", BlkLevel-1); + f = First(q, 1, aPlusBlk, &max_k); + if ( DemandLookahead ) { + if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);} + else gen1("look(%d);\n", max_k); + } + --tabs; + gen("} while ( "); + if ( q->parm!=NULL && q->predparm ) _gen1("(%s) && ", q->parm); + genExpr(q); + if ( ParseWithPredicates && a!=NULL ) + { + if (! MR_comparePredicates(q->predicate,a)) { + _gen("&&"); + a=genPredTreeMain(a, (Node *)q); /* MR10 */ + }; + } + _gen(" );\n"); + if ( ParseWithPredicates && a!=NULL ) gen("}\n"); + --BlkLevel; + BLOCK_Tail(); + q->visited = FALSE; + freeBlkFsets(q); + set_free(f); + tokensRefdInBlock = savetkref; +/* MR21 */ if (MR_BlkErr) { +/* MR21 */ set f, fArray[2]; +/* MR21 */ f = ComputeErrorSet(q,1,1 /* use plus block bypass ? */ ); +/* MR21 */ fArray[0]= empty; +/* MR21 */ fArray[1]= set_dup(f); +/* MR21 */ gen("if ("); +/* MR21 */ genExprSets(fArray,1); /* note: destroys set arguments */ +/* MR21 */ _gen(") { /* MR21 option -mrblksynerr */\n"); +/* MR21 */ tabs++; +/* MR21 */ tab(); +/* MR21 */ _gen("/* nothing */ }\n"); +/* MR21 */ tab(); +/* MR21 */ makeErrorClause(q,f,1,1 /* use plus block bypass ? */ ); /* frees set */ +/* MR21 */ tabs--; +/* MR21 */ }; + if (q->end->p1 != NULL) TRANS(q->end->p1); +/* MR10 */ if (MRhoisting) { +/* MR10 */ predicate_free(a); +/* MR10 */ }; + return; + } + gen("do {\n"); + tabs++; + f = genBlk(q, aPlusBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */); +/* MR6 */ +/* MR6 Sinan Karasu (sinan@tardis.ds.boeing.com) */ +/* MR6 Failed to turn off guess mode when leaving block */ +/* MR6 */ +/* MR6 */ if ( has_guess_block_as_last_item(q) ) { +/* MR10 */ gen("/* MR10 ()+ */ else {\n"); +/* MR10 */ tabs++; +/* MR10 */ need_right_curly++; +/* MR10 */ gen("/* MR10 ()+ */ if ( !zzrv ) zzGUESS_DONE;\n"); +/* MR6 */ gen("/* MR10 ()+ */ if ( zzcnt > 1 ) break;\n"); +/* MR10 */ } else { +/* MR10 */ gen("/* MR10 ()+ */ else {\n"); +/* MR10 */ tabs++; +/* MR10 */ need_right_curly++; +/* MR10 */ gen("if ( zzcnt > 1 ) break;\n"); +/* MR10 */ }; + +/* MR21 */ if (MR_BlkErr && 1 >= max_k) { +/* MR21 */ set f; +/* MR21 */ f = ComputeErrorSet(q,1,0 /* use plus block bypass ? */ ); +/* MR21 */ tabs++; +/* MR21 */ tab(); +/* MR21 */ makeErrorClause(q,f,1,0 /* use plus block bypass ? */ ); /* frees set */ +/* MR21 */ tabs--; +/* MR21 */ } +/* MR21 */ else { + tab(); + makeErrorClause(q,f,max_k,1 /* use plus block bypass ? */); + /* MR21 I think this generates the wrong set ? */ + /* MR21 because it includes the plus block bypass ? */ + /* MR21 but I'm afraid to change it without additional checking */ + } + + { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} } + freeBlkFsets(q); + gen("zzcnt++;"); + if ( !GenCC ) _gen1(" zzLOOP(zztasp%d);", BlkLevel-1); + _gen("\n"); + if ( DemandLookahead ) { + if ( !GenCC ) {gen1("LOOK(%d);\n", max_k);} + else gen1("look(%d);\n", max_k); + } + --tabs; + if ( q->parm!=NULL && q->predparm ) {gen1("} while (%s);\n", q->parm);} + else gen("} while ( 1 );\n"); + --BlkLevel; + BLOCK_Tail(); + q->visited = FALSE; + tokensRefdInBlock = savetkref; +/* MR21 */ if (MR_BlkErr) { +/* MR21 */ set f, fArray[2]; +/* MR21 */ f = ComputeErrorSet(q,1,1 /* use plus block bypass ? */ ); +/* MR21 */ fArray[0]= empty; +/* MR21 */ fArray[1]= set_dup(f); +/* MR21 */ gen("if ("); +/* MR21 */ genExprSets(fArray,1); /* note: destroys set arguments */ +/* MR21 */ _gen(") { /* MR21 option -mrblksynerr */\n"); +/* MR21 */ tabs++; +/* MR21 */ tab(); +/* MR21 */ _gen("/* nothing */ }\n"); +/* MR21 */ tab(); +/* MR21 */ makeErrorClause(q,f,1,1 /* use plus block bypass ? */ ); /* frees set */ +/* MR21 */ tabs--; +/* MR21 */ }; + if (q->end->p1 != NULL) TRANS(q->end->p1); +} + +/* + * Generate code for a sub blk of alternatives of form: + * + * --o-G1--o-- + * | ^ + * v /| + * o-G2-o| + * | ^ + * v | + * .......... + * | ^ + * v / + * o-Gn-o + * + * q points to the 1st junction of blk (upper-left). + * q->end points to the last node (far right) in the blk. + * Note that q->end->jtype must be 'EndBlk'. + * The last node in every alt points to q->end. + * + * Generate code of the following form: + * if ( First(G1) ) { + * ...code for G1... + * } + * else if ( First(G2) ) { + * ...code for G2... + * } + * ... + * else { + * ...code for Gn... + * } + */ + +void +#ifdef __USE_PROTOS +genSubBlk( Junction *q ) +#else +genSubBlk( q ) +Junction *q; +#endif +{ + int max_k; + set f; + int need_right_curly; + int lastAltEmpty; /* MR23 */ + set savetkref; + savetkref = tokensRefdInBlock; + require(q->ntype == nJunction, "genSubBlk: not junction"); + require(q->jtype == aSubBlk, "genSubBlk: not subblock"); + + OutLineInfo(output,q->line,FileStr[q->file]); + BLOCK_Preamble(q); + BlkLevel++; + BlockPreambleOption(q,q->pFirstSetSymbol); /* MR21 */ + f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */); + +/* MR23 + Bypass error clause generation when exceptions are used in a sub block + in which the last alternative is epsilon. Example: "(A | B | )". + See multi-line note in genBlk near call to isEmptyAlt. +*/ + if (FoundException && lastAltEmpty) { + gen("/* MR23 skip error clause for (...| epsilon) when exceptions in use */\n"); + } + else { + if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */ );} + } + + { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} } + freeBlkFsets(q); + --BlkLevel; + BLOCK_Tail(); + + if ( q->guess ) + { + gen("zzGUESS_DONE\n"); + } + + /* must duplicate if (alpha)?; one guesses (validates), the + * second pass matches */ + if ( q->guess && analysis_point(q)==q ) + { + OutLineInfo(output,q->line,FileStr[q->file]); + BLOCK_Preamble(q); + BlkLevel++; + f = genBlk(q, aSubBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */); + if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k,0 /* use plus block bypass ? */);} + { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} } + freeBlkFsets(q); + --BlkLevel; + BLOCK_Tail(); + } + + tokensRefdInBlock = savetkref; + if (q->end->p1 != NULL) TRANS(q->end->p1); +} + +static int TnodesAllocatedPrevRule=0; + +/* + * Generate code for a rule. + * + * rule--> o-->o-Alternatives-o-->o + * Or, + * rule--> o-->o-Alternative-o-->o + * + * The 1st junction is a RuleBlk. The second can be a SubBlk or just a junction + * (one alternative--no block), the last is EndRule. + * The second to last is EndBlk if more than one alternative exists in the rule. + * + * To get to the init-action for a rule, we must bypass the RuleBlk, + * and possible SubBlk. + * Mark any init-action as generated so genBlk() does not regenerate it. + */ +void +#ifdef __USE_PROTOS +genRule( Junction *q ) +#else +genRule( q ) +Junction *q; +#endif +{ + + const char * returnValueInitializer; + +do { /* MR10 Change recursion into iteration */ + + int max_k; + set follow, rk, f; + ActionNode *a; + RuleEntry *r; + int lastAltEmpty; /* MR23 */ + static int file = -1; + int need_right_curly; + require(q->ntype == nJunction, "genRule: not junction"); + require(q->jtype == RuleBlk, "genRule: not rule"); + +/* MR14 */ require (MR_BackTraceStack.count == 0,"-alpha MR_BackTraceStack.count != 0"); +/* MR14 */ MR_pointerStackReset(&MR_BackTraceStack); +/* MR14 */ if (AlphaBetaTrace) MR_MaintainBackTrace=1; + + CurRule=q->rname; /* MR11 */ + + r = (RuleEntry *) hash_get(Rname, q->rname); + if ( r == NULL ) warnNoFL("Rule hash table is screwed up beyond belief"); + if ( q->file != file ) /* open new output file if need to */ + { +/* MR6 */ +/* MR6 Simpler to debug when output goes to stdout rather than a file */ +/* MR6 */ +/* MR6 */ if (UseStdout) { +/* MR6 */ output = stdout; +/* MR6 */ } else { +/* MR6 */ if ( output != NULL) fclose( output ); +/* MR6 */ output = fopen(OutMetaName(outname(FileStr[q->file])), "w"); +/* MR6 */ }; + require(output != NULL, "genRule: can't open output file"); + +#ifdef SPECIAL_FOPEN + special_fopen_actions(OutMetaName(outname(FileStr[q->file]))); /* MR1 */ +#endif + if ( file == -1 ) genHdr1(q->file); + else genHdr(q->file); + file = q->file; + } + + if (InfoM) { + fprintf(stderr," rule %s\n",q->rname); + fflush(output); + }; + +#if 0 + if (strcmp(q->rname,"***debug***") == 0) { + fprintf(stderr,"***debug*** %s reached\n",q->rname); + MR_break(); + }; +#endif + + DumpFuncHeader(q,r); + tabs++; + + /* MR23 + + If there is a single return value then it can be initialized in + the declaration using assignment syntax. If there are multiple + return values then antlr creates a struct and initialization takes + place element by element for each element of the struct. For + multiple elements the initialization is by assignment so we have + to wait until all declarations are done before emitting that code - + because of restrictions in C which don't exist in C++. + + In the past (before MR23) the only kind of initialization was + the PURIFY macro which was just a memset() of 0. Now we allow + the user to specify an initial value. PURIFY is still used in C + mode because C does not have constructors. However, PURIFY is + not used in C++ mode because it might overwrite information created + by elements which have their own ctor. + + */ + + if ( q->ret!=NULL ) + { + if ( hasMultipleOperands(q->ret) ) /* MR23 */ + { + + /* Emit initialization code later. */ + + gen1("struct _rv%d _retv;\n",r->rulenum); + } + else + { + /* Emit initialization code now. */ + + tab(); + DumpType(q->ret, output); + returnValueInitializer = getInitializer(q->ret); + if (returnValueInitializer == NULL) { /* MR23 */ + gen(" _retv;\n"); /* MR1 MR3 */ + } /* MR23 */ + else { /* MR23 */ + gen1(" _retv = %s;\n", returnValueInitializer); /* MR23 */ + } /* MR23 */ + } + } + + OutLineInfo(output,q->line,FileStr[q->file]); + + if (InfoM) { + fflush(output); + }; + + gen("zzRULE;\n"); + if ( FoundException ) + { + gen("int _sva=1;\n"); + } + if ( GenCC && GenAST ) + gen("ASTBase *_ast = NULL, *_sibling = NULL, *_tail = NULL;\n"); + if ( GenCC ) genTokenPointers(q); + if ( GenCC&&GenAST ) genASTPointers(q); + if ( q->el_labels!=NULL ) genElementLabels(q->el_labels); + if ( FoundException ) gen("int _signal=NoSignal;\n"); + + if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel); + +/* MR10 */ /* move zzTRACEIN to before init action */ + +/* MR10 */ if ( TraceGen ) { +/* MR10 */ if ( GenCC ) {gen1("zzTRACEIN(\"%s\");\n", q->rname);} +/* MR10 */ else gen1("zzTRACEIN((ANTLRChar *)\"%s\");\n", q->rname); +/* MR10 */ } + +/* MR7 Moved PURIFY() to after all local variables have been declared */ +/* MR7 so that the generated code is valid C as well as C++ */ +/* MR7 Jan Mikkelsen 10-June-1997 */ + + + /* + MR23 Do the PURIFY macro only for C mode. + C++ users should use constructors or initialization expressions. + */ + + if ( q->ret != NULL ) /* MR7 */ + { /* MR7 */ + if (hasMultipleOperands(q->ret)) { /* MR23 */ + if (PURIFY == TRUE) { + gen1("PCCTS_PURIFY(_retv,sizeof(struct _rv%d))\n",r->rulenum); /* MR23 */ + } + } /* MR7 */ + else { /* MR7 */ + + /* MR23 + If there were only one return value operand and + it had an initializer then it would have been + initialized in the declaration. + */ + + returnValueInitializer = getInitializer(q->ret); /* MR23 */ + if (returnValueInitializer == NULL) { /* MR23 */ + if (PURIFY == TRUE) { + gen("PCCTS_PURIFY(_retv,sizeof("); /* MR23 */ + DumpType(q->ret, output); /* MR7 */ + gen("))\n"); /* MR7 */ + } + } /* MR23 */ + } /* MR7 */ + + if (hasMultipleOperands(q->ret)) { /* MR23 */ + DumpInitializers(output, r, q->ret); /* MR23 */ + } + + } + if ( !GenCC ) gen("zzMake0;\n"); + if ( FoundException ) gen("*_retsignal = NoSignal;\n"); + + if ( !GenCC ) gen("{\n"); + + if ( has_guess_block_as_first_item((Junction *)q->p1) ) + { + gen("zzGUESS_BLOCK\n"); + } + + /* L o o k F o r I n i t A c t i o n */ + if ( ((Junction *)q->p1)->jtype == aSubBlk ) + a = findImmedAction( ((Junction *)q->p1)->p1 ); + else + a = findImmedAction( q->p1 ); /* only one alternative in rule */ + if ( a!=NULL && !a->is_predicate) + { + /* MR21 */ if (!a->noHoist) dumpActionPlus(a, a->action, output, tabs, a->file, a->line, 1); + a->done = 1; /* ignore action. We have already handled it */ + } + + BlkLevel++; + q->visited = TRUE; /* mark RULE as visited for FIRST/FOLLOW */ + BlockPreambleOption((Junction *)q->p1, NULL); /* MR21 */ + f = genBlk((Junction *)q->p1, RuleBlk, &max_k, &need_right_curly, &lastAltEmpty /* MR23 */); + if ( q->p1 != NULL ) + if ( ((Junction *)q->p1)->p2 != NULL ) + {tab(); makeErrorClause((Junction *)q->p1,f,max_k,0 /* use plus block bypass ? */);} + { int i; for (i=1; i<=need_right_curly; i++) {tabs--; gen("}\n");} } + freeBlkFsets((Junction *)q->p1); + q->visited = FALSE; + --BlkLevel; + if ( !GenCC ) gen1("zzEXIT(zztasp%d);\n", BlkLevel); + + genTraceOut(q); + + if ( q->ret!=NULL ) gen("return _retv;\n") else gen("return;\n"); + /* E r r o r R e c o v e r y */ + NewSet(); + rk = empty; + +/* MR14 */ if (r->dontComputeErrorSet) { +/* MR14 */ follow=empty; + } else { + MR_pointerStackReset(&MR_BackTraceStack); /* MR14 */ + MR_ErrorSetComputationActive=1; + REACH(q->end, 1, &rk, follow); + MR_ErrorSetComputationActive=0; + require (MR_BackTraceStack.count == 0,"K: MR_BackTraceStack.count != 0"); + } + + FillSet( follow ); + set_free( follow ); + + /* MR20 G. Hobbelt + Isn't it so that "fail:" is ONLY referenced when: + + !FoundException || FoundGuessBlk ? + + Therefore add the "if" around this piece of code generation... + + Should guessing mode also use _handler label instead of "fail" + when exception handling is active? gen can automatically put + "if (guessing)" there so as to skip all kinds of user code. + + */ + + if ( !FoundException || FoundGuessBlk ) /* MR20 G. Hobbelt */ + { /* MR20 G. Hobbelt */ + _gen("fail:\n"); + if ( !GenCC ) gen("zzEXIT(zztasp1);\n"); + if ( FoundGuessBlk ) { + if ( !GenCC ) {gen("if ( zzguessing ) zzGUESS_FAIL;\n");} + else gen("if ( guessing ) zzGUESS_FAIL;\n"); + } + if ( q->erraction!=NULL ) + dumpAction(q->erraction, output, tabs, q->file, q->line, 1); + if ( GenCC ) + { + gen1("syn(zzBadTok, %s, zzMissSet, zzMissTok, zzErrk);\n", + r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup); + } + else + { + gen1("zzsyn(zzMissText, zzBadTok, %s, zzMissSet, zzMissTok, zzErrk, zzBadText);\n", + r->egroup==NULL?"(ANTLRChar *)\"\"":r->egroup); + } + gen3("%sresynch(setwd%d, 0x%x);\n", GenCC?"":"zz", wordnum, 1<ret!=NULL ) { + genTraceOut(q); + gen("return _retv;\n"); + } else if ( q->exceptions!=NULL ) { + genTraceOut(q); + gen("return;\n"); + } else if (!FoundException) { /* MR10 */ + genTraceOut(q); /* MR10 */ + }; + + } /* MR20 G. Hobbelt */ + + if ( !GenCC ) gen("}\n"); + + /* Gen code for exception handlers */ + /* make sure each path out contains genTraceOut() */ + + if ( q->exceptions!=NULL ) + { + + gen("/* exception handlers */\n"); + + dumpExceptions(q->exceptions); + + if ( !r->has_rule_exception ) + { + _gen("_handler:\n"); + gen("zzdflthandlers(_signal,_retsignal);\n"); + } +/* MR20 G. Gobbelt The label "adios" is never referenced */ + +#if 0 + _gen("_adios:\n"); +#endif + if ( q->ret!=NULL ) { + genTraceOut(q); + gen("return _retv;\n"); + } + else { + genTraceOut(q); + gen("return;\n"); + } + } + else if ( FoundException ) + { + _gen("_handler:\n"); + gen("zzdflthandlers(_signal,_retsignal);\n"); + +/* MR1 */ +/* MR1 7-Apr-97 Fix suggested by: John Bair (jbair@iftime.com) */ +/* MR1 */ + + if ( q->ret != NULL) { /* MR1 */ + genTraceOut(q); /* MR10 */ + gen("return _retv;\n"); /* MR1 */ + } else { /* MR1 */ + genTraceOut(q); /* MR10 */ + gen("return;\n") ; /* MR1 */ + }; /* MR1 */ + } + + tabs--; + gen("}\n"); + +/* MR10 Tired of looking at stacks that are as deep as the number of */ +/* MR10 rules. Changes recursion to iteration. */ + + MR_releaseResourcesUsedInRule( (Node *) q ); /* MR10 */ + + if (InfoT) { + fprintf(output,"\n/* tnodes created for rule %s: %d */\n", + q->rname, (TnodesAllocated-TnodesAllocatedPrevRule) ); + }; + + TnodesAllocatedPrevRule=TnodesAllocated; + + if (q->p2 == NULL) dumpAfterActions( output ); + q=(Junction *)q->p2; + require(q==NULL || q->jtype==RuleBlk,"RuleBlk p2 does not point to another RuleBlk"); + +} while (q != NULL); + +/**** The old code ****/ +/**** if ( q->p2 != NULL ) {TRANS(q->p2);} ****/ /* generate code for next rule too */ +/**** else dumpAfterActions( output ); ****/ + +} + + +/* This is for the function definition, not the declaration. */ + +static void +#ifdef __USE_PROTOS +DumpFuncHeader( Junction *q, RuleEntry *r ) +#else +DumpFuncHeader( q, r ) +Junction *q; +RuleEntry *r; +#endif +{ +/* */ +/* MR1 10-Apr-97 MR1 Simplify insertion of commas in function header */ +/* */ + int needComma; /* MR1 */ + + + /* A N S I */ + _gen("\n"); + if ( q->ret!=NULL ) + { + if ( hasMultipleOperands(q->ret) ) /* MR23 */ + { + if (GenCC) gen2("%s::_rv%d\n", CurrentClassName, r->rulenum) + else gen1("struct _rv%d\n",r->rulenum); + } + else + { + DumpType(q->ret, output); + gen("\n"); + } + } + else + { + _gen("void\n"); + } +/* MR1 */ +/* MR1 10-Apr-97 133MR1 Replace __STDC__ with __USE_PROTOS */ +/* MR1 */ + if ( !GenCC ) _gen("#ifdef __USE_PROTOS\n"); /* MR1 */ + if ( !GenCC ) gen2("%s%s(", RulePrefix, q->rname) + else gen3("%s::%s%s(", CurrentClassName, RulePrefix,q->rname); + + /* If we generate C++ method names, we must hide default arguments */ + /* which can appear in the parameter declaration list. */ + /* NOTICE: this is done only here, for the method definition, but */ + /* not for the method declaration inside the class */ + /* definition. This is exactly the behaviour defined in */ + /* C++ standard for default parameters. */ + + DumpANSIFunctionArgDef(output,q, 0 /* emit initializers ? */); + _gen("\n"); + + if ( GenCC ) { + gen("{\n"); + return; + } + + /* K & R */ + gen("#else\n"); + gen2("%s%s(", RulePrefix, q->rname); + needComma=0; /* MR1 */ + if ( GenAST ) /* MR1 */ + { /* MR1 */ + _gen("_root"); /* MR1 */ + needComma=1; /* MR1 */ + } /* MR1 */ + if ( FoundException ) /* MR1 */ + { /* MR1 */ + if (needComma) {_gen(",");needComma=0;}; /* MR1 */ + _gen("_retsignal"); /* MR1 */ + needComma=1; /* MR1 */ + } /* MR1 */ +/* MR5 Change below by Jan Mikkelsen (janm@zeta.org.au) 26-May-97 MR5 */ + DumpListOfParmNames( q->pdecl, output, needComma ); /* MR5 */ + gen(")\n"); + if ( GenAST ) gen("AST **_root;\n"); + if ( FoundException ) gen("int *_retsignal;\n"); + DumpOldStyleParms( q->pdecl, output ); + gen("#endif\n"); + gen("{\n"); +} + +void +#ifdef __USE_PROTOS +DumpANSIFunctionArgDef(FILE *f, Junction *q, int bInitializer) +#else +DumpANSIFunctionArgDef(f,q,bInitializer) +FILE *f; +Junction *q; +int bInitializer; +#endif +{ + if ( GenAST ) + { + if ( GenCC ) {fprintf(f,"ASTBase **_root");} + else fprintf(f,"AST**_root"); + if ( !FoundException && q->pdecl!=NULL ) fprintf(f,","); + } + if ( FoundException ) + { + if ( GenAST ) fprintf(f,","); + fprintf(f,"int *_retsignal"); + if ( q->pdecl!=NULL ) { + fprintf(f,","); + } + } + if ( q->pdecl!=NULL ) { + DumpFormals(f, q->pdecl, bInitializer); /* MR23 */ + } + else { + if ( !GenAST && !FoundException ) { + fprintf(f,"void"); + } + } + fprintf(f,")"); +} + +void +#ifdef __USE_PROTOS +genJunction( Junction *q ) +#else +genJunction( q ) +Junction *q; +#endif +{ + require(q->ntype == nJunction, "genJunction: not junction"); + require(q->jtype == Generic, "genJunction: not generic junction"); + + if ( q->p1 != NULL ) TRANS(q->p1); + if ( q->p2 != NULL ) TRANS(q->p2); +} + +void +#ifdef __USE_PROTOS +genEndBlk( Junction *q ) +#else +genEndBlk( q ) +Junction *q; +#endif +{ +} + +void +#ifdef __USE_PROTOS +genEndRule( Junction *q ) +#else +genEndRule( q ) +Junction *q; +#endif +{ +} + +void +#ifdef __USE_PROTOS +genHdr( int file ) +#else +genHdr( file ) +int file; +#endif +{ + int i; + + _gen("/*\n"); + _gen(" * A n t l r T r a n s l a t i o n H e a d e r\n"); + _gen(" *\n"); + _gen(" * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n"); + _gen(" * Purdue University Electrical Engineering\n"); + _gen(" * With AHPCRC, University of Minnesota\n"); + _gen1(" * ANTLR Version %s\n", Version); + _gen(" *\n"); +/* MR10 */ _gen(" * "); +/* MR10 */ for (i=0 ; i < Save_argc ; i++) { +/* MR10 */ _gen(" "); +/* MR10 */ _gen1("%s", Save_argv[i]); +/* MR10 */ }; + _gen("\n"); + _gen(" *\n"); + _gen(" */\n\n"); + if (FirstAction != NULL ) dumpAction( FirstAction, output, 0, -1, 0, 1); /* MR11 MR15b */ + _gen1("#define ANTLR_VERSION %s\n", VersionDef); + _gen("#include \"pcctscfg.h\"\n"); + _gen("#include \"pccts_stdio.h\"\n"); + if ( strcmp(ParserName, DefaultParserName)!=0 ) + _gen2("#define %s %s\n", DefaultParserName, ParserName); + if ( strcmp(ParserName, DefaultParserName)!=0 ) + {_gen1("#include \"%s\"\n", RemapFileName);} + OutLineInfo(output,1,FileStr[file]); + if ( GenCC ) { + if ( UserTokenDefsFile != NULL ) + fprintf(output, "#include %s\n", UserTokenDefsFile); + else + fprintf(output, "#include \"%s\"\n", DefFileName); + } + + if ( HdrAction != NULL ) dumpAction( HdrAction, output, 0, -1, 0, 1); + if ( !GenCC && FoundGuessBlk ) + { + _gen("#define ZZCAN_GUESS\n"); + _gen("#include \"pccts_setjmp.h\"\n"); /* MR15 K.J. Cummings (cummings@peritus.com) */ + } + if ( FoundException ) + { + _gen("#define EXCEPTION_HANDLING\n"); + _gen1("#define NUM_SIGNALS %d\n", NumSignals); + } + if ( !GenCC && OutputLL_k > 1 ) _gen1("#define LL_K %d\n", OutputLL_k); + if ( GenAST&&!GenCC ) _gen("#define GENAST\n\n"); + if ( GenAST ) { + if ( GenCC ) {_gen1("#include \"%s\"\n\n", ASTBASE_H);} + else _gen("#include \"ast.h\"\n\n"); + } + if ( !GenCC && DemandLookahead ) _gen("#define DEMAND_LOOK\n\n"); +#ifdef DUM + if ( !GenCC && LexGen ) { + _gen1("#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken)); + } +#endif + /* ###WARNING: This will have to change when SetWordSize changes */ + if ( !GenCC ) _gen1("#define zzSET_SIZE %lu\n", NumWords(TokenNum-1)*sizeof(unsigned)); + if (TraceGen) { + _gen("#ifndef zzTRACE_RULES\n"); /* MR20 */ + _gen("#define zzTRACE_RULES\n"); /* MR20 */ + _gen("#endif\n"); /* MR22 */ + }; + if ( !GenCC ) {_gen("#include \"antlr.h\"\n");} + else { + _gen1("#include \"%s\"\n", APARSER_H); + _gen1("#include \"%s.h\"\n", CurrentClassName); + } + if ( !GenCC ) { + if ( UserDefdTokens ) + {_gen1("#include %s\n", UserTokenDefsFile);} + /* still need this one as it has the func prototypes */ + _gen1("#include \"%s\"\n", DefFileName); + } + /* still need this one as it defines the DLG interface */ + if ( !GenCC ) _gen("#include \"dlgdef.h\"\n"); + if ( LexGen && GenCC ) _gen1("#include \"%s\"\n", DLEXERBASE_H); + if ( GenCC ) _gen1("#include \"%s\"\n", ATOKPTR_H); + if ( !GenCC && LexGen ) _gen1("#include \"%s\"\n", ModeFileName); + +/* MR10 Ofer Ben-Ami (gremlin@cs.huji.ac.il) */ +/* MR10 Finally, a definition of the Purify macro */ + + if (PURIFY == TRUE) { /* MR23 */ + _gen("\n/* MR23 In order to remove calls to PURIFY use the antlr"); /* MR23 */ + _gen(" -nopurify option */\n\n"); /* MR23 */ + _gen("#ifndef PCCTS_PURIFY\n"); + _gen("#define PCCTS_PURIFY(r,s) memset((char *) &(r),'\\0',(s));\n"); + _gen("#endif\n\n"); + } /* MR23 */ +} + +void +#ifdef __USE_PROTOS +genHdr1( int file ) +#else +genHdr1( file ) +int file; +#endif +{ + ListNode *p; + + genHdr(file); + if ( GenAST ) + { + if ( !GenCC ) { + _gen("#include \"ast.c\"\n"); + _gen("zzASTgvars\n\n"); + } + } + if ( !GenCC ) _gen("ANTLR_INFO\n"); + if ( BeforeActions != NULL ) + { + for (p = BeforeActions->next; p!=NULL; p=p->next) + { + UserAction *ua = (UserAction *)p->elem; + dumpAction( ua->action, output, 0, ua->file, ua->line, 1); + } + } + + if ( !FoundException ) return; + + if ( GenCC ) + { + _gen1("\nvoid %s::\n", CurrentClassName); + _gen("zzdflthandlers( int _signal, int *_retsignal )\n"); + _gen("{\n"); + } + else + { + _gen("\nvoid\n"); +/* MR1 */ +/* MR1 10-Apr-97 133MR1 Replace __STDC__ with __USE_PROTOS */ +/* MR1 */ + _gen("#ifdef __USE_PROTOS\n"); /* MR1 */ + _gen("zzdflthandlers( int _signal, int *_retsignal )\n"); + _gen("#else\n"); + _gen("zzdflthandlers( _signal, _retsignal )\n"); + _gen("int _signal;\n"); + _gen("int *_retsignal;\n"); + _gen("#endif\n"); + _gen("{\n"); + } + tabs++; + if ( DefaultExGroup!=NULL ) + { + dumpException(DefaultExGroup, 1); + if ( !hasDefaultException(DefaultExGroup) ) + { + gen("default :\n"); + tabs++; + gen("*_retsignal = _signal;\n"); + tabs--; + gen("}\n"); + } + } + else { + gen("*_retsignal = _signal;\n"); + } + + tabs--; + _gen("}\n\n"); +} + +void +#ifdef __USE_PROTOS +genStdPCCTSIncludeFile( FILE *f,char *gate ) /* MR10 */ +#else +genStdPCCTSIncludeFile( f , gate) /* MR10 */ +FILE *f; +char * gate; /* MR10 */ +#endif +{ +/* MR10 Ramanathan Santhanam (ps@kumaran.com) */ +/* MR10 Same preprocessor symbol use to gate stdpccts.h */ +/* MR10 even when two grammars are in use. */ +/* MR10 Derive gate symbol from -fh filename */ + + if (gate == NULL) { + fprintf(f,"#ifndef STDPCCTS_H\n"); /* MR10 */ + fprintf(f,"#define STDPCCTS_H\n"); /* MR10 */ + } else { + fprintf(f,"#ifndef STDPCCTS_%s_H\n",gate); /* MR10 */ + fprintf(f,"#define STDPCCTS_%s_H\n",gate); /* MR10 */ + }; + fprintf(f,"/*\n"); + if (gate == NULL) { + fprintf(f," * %s -- P C C T S I n c l u d e\n", stdpccts); + } else { + fprintf(f," * Standard PCCTS include file with -fh %s -- P C C T S I n c l u d e\n", stdpccts); + } + fprintf(f," *\n"); + fprintf(f," * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001\n"); + fprintf(f," * Purdue University Electrical Engineering\n"); + fprintf(f," * With AHPCRC, University of Minnesota\n"); + fprintf(f," * ANTLR Version %s\n", Version); + fprintf(f," */\n\n"); + + fprintf(f,"#ifndef ANTLR_VERSION\n"); + fprintf(f,"#define ANTLR_VERSION %s\n", VersionDef); + fprintf(f,"#endif\n\n"); + + if (FirstAction != NULL ) dumpAction(FirstAction, f, 0, -1, 0, 1); /* MR11 */ + + fprintf(f,"#include \"pcctscfg.h\"\n"); + fprintf(f,"#include \"pccts_stdio.h\"\n"); + if ( GenCC ) + { + if ( UserDefdTokens ) + fprintf(f, "#include %s\n", UserTokenDefsFile); + else { + fprintf(f, "#include \"%s\"\n", DefFileName); + } + + fprintf(f, "#include \"%s\"\n", ATOKEN_H); + + if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1); + + fprintf(f, "#include \"%s\"\n", ATOKENBUFFER_H); + + if ( OutputLL_k > 1 ) fprintf(f,"static const unsigned LL_K=%d;\n", OutputLL_k); + if ( GenAST ) { + fprintf(f, "#include \"%s\"\n", ASTBASE_H); + } + + if (TraceGen) { + fprintf(f,"#ifndef zzTRACE_RULES\n"); /* MR20 */ + fprintf(f,"#define zzTRACE_RULES\n"); /* MR20 */ + fprintf(f,"#endif\n"); /* MR22 */ + }; + + fprintf(f,"#include \"%s\"\n", APARSER_H); + fprintf(f,"#include \"%s.h\"\n", CurrentClassName); + if ( LexGen ) fprintf(f,"#include \"%s\"\n", DLEXERBASE_H); + fprintf(f, "#endif\n"); + return; + } + + if ( strcmp(ParserName, DefaultParserName)!=0 ) + fprintf(f, "#define %s %s\n", DefaultParserName, ParserName); + if ( strcmp(ParserName, DefaultParserName)!=0 ) + fprintf(f, "#include \"%s\"\n", RemapFileName); + if ( UserTokenDefsFile != NULL ) + fprintf(f, "#include %s\n", UserTokenDefsFile); + if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1); + if ( FoundGuessBlk ) + { + fprintf(f,"#define ZZCAN_GUESS\n"); + fprintf(f,"#include \"pccts_setjmp.h\"\n"); + } + if (TraceGen) { + fprintf(f,"#ifndef zzTRACE_RULES\n"); /* MR20 */ + fprintf(f,"#define zzTRACE_RULES\n"); /* MR20 */ + fprintf(f,"#endif\n"); /* MR22 */ + }; + if ( OutputLL_k > 1 ) fprintf(f,"#define LL_K %d\n", OutputLL_k); + if ( GenAST ) fprintf(f,"#define GENAST\n"); + if ( FoundException ) + { +/* MR1 7-Apr-97 1.33MR1 */ +/* MR1 Fix suggested by: */ +/* MR1 Francois-Xavier Fontaine (fontaine_f@istvax.ist.lu) */ + + fprintf(f,"#define EXCEPTION_HANDLING\n"); /* MR1 */ + fprintf(f,"#define NUM_SIGNALS %d\n", NumSignals); /* MR1 */ + } + if ( DemandLookahead ) fprintf(f,"#define DEMAND_LOOK\n"); +#ifdef DUM + if ( LexGen ) fprintf(f, "#define zzEOF_TOKEN %d\n", (TokenInd!=NULL?TokenInd[EofToken]:EofToken)); +#endif + /* ###WARNING: This will have to change when SetWordSize changes */ + fprintf(f, "#define zzSET_SIZE %lu\n", NumWords(TokenNum-1)*sizeof(unsigned)); + if (TraceGen) { + fprintf(f,"#ifndef zzTRACE_RULES\n"); /* MR20 */ + fprintf(f,"#define zzTRACE_RULES\n"); /* MR20 */ + fprintf(f,"#endif\n"); /* MR22 */ + }; + fprintf(f,"#include \"antlr.h\"\n"); + if ( GenAST ) fprintf(f,"#include \"ast.h\"\n"); + if ( UserDefdTokens ) + fprintf(f, "#include %s\n", UserTokenDefsFile); + /* still need this one as it has the func prototypes */ + fprintf(f, "#include \"%s\"\n", DefFileName); + /* still need this one as it defines the DLG interface */ + fprintf(f,"#include \"dlgdef.h\"\n"); + /* don't need this one unless DLG is used */ + if ( LexGen ) fprintf(f,"#include \"%s\"\n", ModeFileName); + fprintf(f,"#endif\n"); +} + +/* dump action 's' to file 'output' starting at "local" tab 'tabs' + Dump line information in front of action if GenLineInfo is set + If file == -1 then GenLineInfo is ignored. + The user may redefine the LineInfoFormatStr to his/her liking + most compilers will like the default, however. + + June '93; changed so that empty lines are left alone so that + line information is correct for the compiler/debuggers. +*/ +void +#ifdef __USE_PROTOS +dumpAction( char *s, FILE *output, int tabs, int file, int line, +int final_newline ) +#else +dumpAction( s, output, tabs, file, line, final_newline ) +char *s; +FILE *output; +int tabs; +int file; +int line; +int final_newline; +#endif +{ + int inDQuote, inSQuote; + require(s!=NULL, "dumpAction: NULL action"); + require(output!=NULL, eMsg1("dumpAction: output FILE is NULL for %s",s)); + + if ( GenLineInfo && file != -1 ) + { + OutLineInfo(output,line,FileStr[file]); + } + PastWhiteSpace( s ); + /* don't print a tab if first non-white char is a # (preprocessor command) */ + if ( *s!='#' ) {TAB;} + inDQuote = inSQuote = FALSE; + while ( *s != '\0' ) + { + if ( *s == '\\' ) + { + fputc( *s++, output ); /* Avoid '"' Case */ + if ( *s == '\0' ) return; + if ( *s == '\'' ) fputc( *s++, output ); + if ( *s == '\"' ) fputc( *s++, output ); + } + if ( *s == '\'' ) + { + if ( !inDQuote ) inSQuote = !inSQuote; + } + if ( *s == '"' ) + { + if ( !inSQuote ) inDQuote = !inDQuote; + } + if ( *s == '\n' ) + { + fputc('\n', output); + s++; + PastWhiteSpace( s ); + if ( *s == '}' ) + { + --tabs; + TAB; + fputc( *s++, output ); + continue; + } + if ( *s == '\0' ) return; + if ( *s != '#' ) /* #define, #endif etc.. start at col 1 */ + { + TAB; + } + } + if ( *s == '}' && !(inSQuote || inDQuote) ) + { + --tabs; /* Indent one fewer */ + } + if ( *s == '{' && !(inSQuote || inDQuote) ) + { + tabs++; /* Indent one more */ + } + fputc( *s, output ); + s++; + } + if ( final_newline ) fputc('\n', output); +} + +static void +#ifdef __USE_PROTOS +dumpAfterActions( FILE *output ) +#else +dumpAfterActions( output ) +FILE *output; +#endif +{ + ListNode *p; + require(output!=NULL, "dumpAfterActions: output file was NULL for some reason"); + if ( AfterActions != NULL ) + { + for (p = AfterActions->next; p!=NULL; p=p->next) + { + UserAction *ua = (UserAction *)p->elem; + dumpAction( ua->action, output, 0, ua->file, ua->line, 1); + } + } + fclose( output ); +} + +/* + * Find the next action in the stream of execution. Do not pass + * junctions with more than one path leaving them. + * Only pass generic junctions. + * + * Scan forward while (generic junction with p2==NULL) + * If we stop on an action, return ptr to the action + * else return NULL; + */ +static ActionNode * +#ifdef __USE_PROTOS +findImmedAction( Node *q ) +#else +findImmedAction( q ) +Node *q; +#endif +{ + Junction *j; + require(q!=NULL, "findImmedAction: NULL node"); + require(q->ntype>=1 && q->ntype<=NumNodeTypes, "findImmedAction: invalid node"); + + while ( q->ntype == nJunction ) + { + j = (Junction *)q; + if ( j->jtype != Generic || j->p2 != NULL ) return NULL; + q = j->p1; + if ( q == NULL ) return NULL; + } + if ( q->ntype == nAction ) return (ActionNode *)q; + return NULL; +} + +static void +#ifdef __USE_PROTOS +dumpRetValAssign( char *retval, char *ret_def, RuleRefNode * ruleRef /* MR30 */) +#else +dumpRetValAssign( retval, ret_def, ruleRef /* MR30 */) +char *retval; +char *ret_def; +RuleRefNode *ruleRefNode; +#endif +{ + char *q = ret_def; + + tab(); + while ( *retval != '\0' && *q != '\0') + { + while ( isspace((*retval)) ) retval++; + while ( *retval!=',' && *retval!='\0' ) fputc(*retval++, output); + fprintf(output, " = _trv."); + + DumpNextNameInDef(&q, output); + while ( isspace(*q) ) q++; + fputc(';', output); fputc(' ', output); + if ( *retval == ',' ) retval++; + } + if (*retval == '\0' && *q != '\0') { +/* MR30 */ errFL("Fewer output values than output formals for rule reference", +/* MR30 */ FileStr[ruleRef->file],ruleRef->line); + } + if (*retval != '\0' && *q == '\0') { +/* MR30 */ errFL("More output actuals than output formals for rule reference", +/* MR30 */ FileStr[ruleRef->file],ruleRef->line); + } +} + +/* This function computes the set of tokens that can possibly be seen k + * tokens in the future from point j + */ + +static set +#ifdef __USE_PROTOS +ComputeErrorSet( Junction *j, int k, int usePlusBlockBypass) +#else +ComputeErrorSet( j, k, usePlusBlockBypass ) +Junction *j; +int k; +int usePlusBlockBypass; +#endif +{ + Junction *alt1; + set a, rk, f; + require(j->ntype==nJunction, "ComputeErrorSet: non junction passed"); + + f = rk = empty; + for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2) + { + if (alt1->ignore && ! usePlusBlockBypass) continue; /* MR21 - Ignore aPlusBlk forward p2 */ + REACH(alt1->p1, k, &rk, a); + require(set_nil(rk), "ComputeErrorSet: rk != nil"); + set_free(rk); + set_orin(&f, a); + set_free(a); + } + return f; +} + +static char * +#ifdef __USE_PROTOS +tokenFollowSet(TokNode *p) +#else +tokenFollowSet(p) +TokNode *p; +#endif +{ + static char buf[100]; + set rk, a; + int n; + rk = empty; + + REACH(p->next, 1, &rk, a); + require(set_nil(rk), "rk != nil"); + set_free(rk); + n = DefErrSet( &a, 0, NULL ); + set_free(a); + if ( GenCC ) + sprintf(buf, "err%d", n); + else + sprintf(buf, "zzerr%d", n); + return buf; +} + +static void +#ifdef __USE_PROTOS +makeErrorClause( Junction *q, set f, int max_k, int usePlusBlockBypass ) +#else +makeErrorClause( q, f, max_k, usePlusBlockBypass ) +Junction *q; +set f; +int max_k; +int usePlusBlockBypass; +#endif +{ + char * handler_id=""; /* MR7 */ + int nilf=0; /* MR13 */ + RuleEntry *ruleEntry; /* MR14 */ + + if ( FoundException ) + { + _gen("else {\n"); + tabs++; + if ( FoundGuessBlk ) + { + if ( GenCC ) {gen("if ( guessing ) goto fail;\n");} + else gen("if ( zzguessing ) goto fail;\n"); + } + gen("if (_sva) _signal=NoViableAlt;\n"); + gen("else _signal=NoSemViableAlt;\n"); + if (q->outerEG != NULL) { + handler_id=q->outerEG->altID; +#if 0 + } else { + printf("q->curAltNum=%d q->exception_label=%s\n",q->curAltNum,q->exception_label); + gen("*** DEBUG *** outerEG==NULL\n"); +#endif + }; + gen1("goto %s_handler; /* MR7 */\n",handler_id); /* MR7 */ + tabs--; + gen("}\n"); + return; + } + + if ( max_k == 1 ) + { +/* MR13 */ nilf=set_nil(f); + if ( GenCC ) { + _gen1("else {FAIL(1,err%d", DefErrSet1(1,&f,1,NULL)); + } else { + _gen1("else {zzFAIL(1,zzerr%d", DefErrSet1(1,&f,1,NULL)); + }; + set_free(f); + } + else + { + int i; + set_free(f); + if ( GenCC ) {_gen1("else {FAIL(%d", max_k);} + else _gen1("else {zzFAIL(%d", max_k); + + ruleEntry = (RuleEntry *) hash_get(Rname,q->rname); + + for (i=1; i<=max_k; i++) + { +/* MR14 */ if (ruleEntry->dontComputeErrorSet) { +/* MR14 */ f=empty; + } else { + f = ComputeErrorSet(q, i, usePlusBlockBypass /* use plus block bypass ? */ ); + } + + if ( GenCC ) {_gen1(",err%d", DefErrSet( &f, 1, NULL ));} + else _gen1(",zzerr%d", DefErrSet( &f, 1, NULL )); + + set_free(f); + } + } + _gen(",&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}\n"); +/* MR13 */ if (nilf) { +/* MR13 */ errFL("empty error set for alt - probably because of undefined rule or infinite left recursion", +/* MR13 */ FileStr[q->file],q->line); +/* MR13 */ gen(" /* MR13 empty error set for this alt - undef rule ? infinite left recursion ? */"); +/* MR13 */ }; +} + +static /* MR7 */ +#ifdef __USE_PROTOS +char * findOuterHandlerLabel(ExceptionGroup *eg) /* MR7 */ +#else +char * findOuterHandlerLabel(eg) /* MR7 */ +ExceptionGroup *eg; /* MR7 */ +#endif +{ + char *label=NULL; /* MR7 */ + ExceptionGroup *outerEG; /* MR7 */ + + if (eg->forRule == 0) { /* MR7 */ + if (eg->labelEntry != NULL) { /* MR7 */ + outerEG=eg->labelEntry->outerEG; /* MR7 */ + if (outerEG != NULL) { /* MR7 */ + label=outerEG->altID; /* MR7 */ + outerEG->used=1; /* MR7 */ + }; /* MR7 */ + } else if (eg->outerEG != NULL) { /* MR7 */ + outerEG=eg->outerEG; /* MR7 */ + label=outerEG->altID; /* MR7 */ + outerEG->used=1; /* MR7 */ + }; /* MR7 */ + }; /* MR7 */ + return (label==NULL ? "" : label); /* MR7 */ +} /* MR7 */ + +/*** debug ***/ +#if 0 +** static /* MR7 */ +** #ifdef __USE_PROTOS +** char * findOuterAltHandlerLabel(Junction *startJ) /* MR7 */ +** #else +** char * findOuterAltHandlerLabel(startJ) /* MR7 */ +** Junction *startJ; /* MR7 */ +** #endif +** { /* MR7 */ +** char *label=NULL; /* MR7 */ +** Junction *alt; /* MR7 */ +** /* MR7 */ +** for (alt=startJ; alt != NULL; alt=alt->outerAltstart) { /* MR7 */ +** label=alt->exception_label; /* MR7 */ +** if (label != NULL) break; /* MR7 */ +** }; /* MR7 */ +** return (label==NULL ? "" : label); /* MR7 */ +** } /* MR7 */ +#endif + +#ifdef __USE_PROTOS +static void OutLineInfo(FILE *file,int line,char *fileName) +#else +static void OutLineInfo(file,line,fileName) + FILE * file; + int line; + char * fileName; +#endif +{ + static char * prevFileName=NULL; + static char * prevFileNameMS=NULL; + + char * p; + char * q; + + if (! GenLineInfo) return; + + if (!GenLineInfoMS) { + fprintf(file, LineInfoFormatStr,line,fileName); + } else { + if (fileName == prevFileName) { + fprintf(file, LineInfoFormatStr,line,prevFileNameMS); + } else { + if (prevFileNameMS != NULL) free (prevFileNameMS); + prevFileNameMS=(char *)calloc(1,strlen(fileName)+1); + require(prevFileNameMS != NULL,"why not do this in calloc wrapper"); + q=prevFileNameMS; + for (p=fileName; *p != 0; p++) { + *q=*p; + if (*q == '\\') *q='/'; + q++; + } + } + prevFileName=fileName; + }; +} + +#if 0 + +/* MR21 */ + +#ifdef __USE_PROTOS +void OutFirstSetSymbol(Junction *q, char * pSymbol) +#else +void OutFirstSetSymbol(q, pSymbol) + Junction* q; + char * pSymbol +#endif +{ + + set f; + if (pSymbol == NULL) return; + gen1("/** #FirstSetSymbol(%s) **/\n",pSymbol); + f = ComputeErrorSet(q, 1, 0 /* use plus block bypass ? */); + DefErrSetWithSuffix (0 /* nil ok */, &f,0 /* no substitute */, pSymbol, ""); + set_free(f); +} +#endif + +/* MR21 */ + +#ifdef __USE_PROTOS +void BlockPreambleOption(Junction *q, char * pSymbol) +#else +void BlockPreambleOption(q, pSymbol) + Junction* q; + char * pSymbol; +#endif +{ + set f = empty; + if (pSymbol != NULL) { + f = ComputeErrorSet(q, 1, 0 /* use plus block bypass ? */); + gen1("/** #FirstSetSymbol(%s) **/\n",pSymbol); + DefErrSetWithSuffix (0 /* nil ok */, &f,0 /* no substitute */, pSymbol, ""); + } + set_free(f); +} + +/* MR21 */ + +void +#ifdef __USE_PROTOS +dumpActionPlus(ActionNode *a, char *s, FILE *output, int tabs, int file, int line, +int final_newline ) +#else +dumpActionPlus(a, s, output, tabs, file, line, final_newline ) +ActionNode *a; +char *s; +FILE *output; +int tabs; +int file; +int line; +int final_newline; +#endif +{ + dumpAction(s,output,tabs,file,line,final_newline); +} + + +#if 0 +** #ifdef __USE_PROTOS +** void MR_ErrorSets(Junction *q, int max_k, int usePlusBlockBypass) +** #else +** void MR_ErrorSets(q, max_k, usePlusBlockBypass) +** Junction *q; +** int max_k; +** int usePlusBlockBypass; +** #endif +** { +** int k; +** set setResult; +** Junction* alt1; +** Junction* p; +** set rk; +** +** require (max_k <= CLL_k, "k > CLL_k"); +** +** +** for (k = 1; k <= CLL_k; k++) {set_clr(q->fset[k]); } +** +** for (k = 1; k <= max_k; k++) { +** for (alt1=q; alt1 != NULL; alt1 = (Junction *)alt1->p2) +** { +** if (alt1->ignore && ! usePlusBlockBypass) continue; +** p = analysis_point((Junction *)alt1->p1); +** REACH(p, k, &rk, setResult); +** require(set_nil(rk), "rk != nil"); +** set_orin(&q->fset[k], setResult); +** } +** } +** } +#endif + + +#ifdef __USE_PROTOS +void DumpInitializers(FILE* output, RuleEntry *r, char * pReturn) +#else +void DumpInitializers(output, r, pReturn) +FILE* output; +RuleEntry *r; +char * pReturn; +#endif +{ + char *p = pReturn; + char *pDataType; + char *pSymbol; + char *pEqualSign; + char *pValue; + char *pSeparator; + int nest = 0; + char *q; + + require(pReturn!=NULL, "DumpInitializer: invalid string"); + + while (*p != 0) { + p = endFormal(p, + &pDataType, + &pSymbol, + &pEqualSign, + &pValue, + &pSeparator, + &nest); + if (nest != 0) return; + if (pValue != NULL) { + tab(); + q = strBetween(pSymbol, pEqualSign, pSeparator); + fprintf(output, "_retv.%s", q); + q = strBetween(pValue, NULL, pSeparator); + fprintf(output, " = %s;\n", q); + } + } +} + +#ifdef __USE_PROTOS +void DumpFormals(FILE* output, char * pReturn, int bInitializer) +#else +void DumpFormals(output, pReturn, bInitializer) +FILE* output; +char * pReturn; +int bInitializer; +#endif +{ + char *p = pReturn; + char *pDataType; + char *pSymbol; + char *pEqualSign; + char *pValue; + char *pSeparator; + int nest = 0; + char *q; + int count = 0; + + require(pReturn!=NULL, "DumpFormals: invalid string"); + + while (*p != 0) { + p = endFormal(p, + &pDataType, + &pSymbol, + &pEqualSign, + &pValue, + &pSeparator, + &nest); + if (nest != 0) return; + if (count > 0) fprintf(output,","); + if (pDataType != NULL && pSymbol != NULL) { + q = strBetween(pDataType, pSymbol, pSeparator); + fprintf(output, "%s", q); + q = strBetween(pSymbol, pEqualSign, pSeparator); + fprintf(output," %s",q); + if (pValue != NULL) { + q = strBetween(pValue, NULL, pSeparator); + if (bInitializer != 0) { + fprintf(output, " = %s", q); + } + } + } + count++; + } +} + +/* MR23 Check for empty alt in a more intelligent way. + Previously, an empty alt for genBlk had to point directly + to the endBlock. This did not work once I changed {...} + blocks to look like (...|...| epsilon) since there were + intervening generics. This fixes the problem for this + particular case. Things like actions or empty blocks of + various kinds will still cause problems, but I wasn't + prepared to handle pathological cases like (A|()*). It + does handle (A | ()), which is a recommended idiom for + epsilon. + + Actually, this isn't quite correct since it doesn't handle + the case of the ignore bit in the plus block bypass, but + I'm too tired to figure out the correct fix, and will just + work around it. +*/ + +#ifdef __USE_PROTOS +int isEmptyAlt(Node * alt, Node * endBlock) +#else +int isEmptyAlt(alt, endBlock) +Node * alt; +Node * endBlock; +#endif +{ + Node * n = alt; + Junction * j; + while (n != endBlock) { + switch (n->ntype) { + + case nRuleRef: + return 0; + + case nToken: + return 0; + + case nAction: + return 0; + + case nJunction: + goto JUNCTION; + + default: + fatal_internal("Invalid node type"); + return 0; + } +JUNCTION: + j = (Junction *) n; + + switch (j->jtype) { + case Generic: + { + n = j->p1; + goto NEXT; + } + + case aSubBlk: + { + n = j->p1; /* MR26 */ + goto NEXT; /* MR26 */ + } + + case EndBlk: + return 0; + + case EndRule: + return 1; + + default: + return 0; + } +NEXT: continue; + } + return 1; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/generic.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/generic.h new file mode 100644 index 00000000..b4328c7b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/generic.h @@ -0,0 +1,286 @@ +/* + * generic.h -- generic include stuff for new PCCTS ANTLR. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#define StrSame 0 + +#define DefaultParserName "zzparser" + +/* MR9 JVincent@novell.com Allow user to override default ZZLEXBUFSIZE */ +/* MR11 thm Raise antlr's own default ZZLEXBUFSIZE to 8k */ +/* MR22 thm Raise antlr's own default ZZLEXBUFSIZE to 32k */ + +#ifndef ZZLEXBUFSIZE +#define ZZLEXBUFSIZE 32000 +#endif + +/* Tree/FIRST/FOLLOW defines -- valid only after all grammar has been read */ +#define ALT TokenNum+1 +#define SET TokenNum+2 +#define TREE_REF TokenNum+3 + + /* E r r o r M a c r o s */ + +#define fatal(err) fatalFL(err, __FILE__, __LINE__) +#define fatal_internal(err) fatal_intern(err, __FILE__, __LINE__) + + +#define eMsg1(s,a) eMsg3(s,a,NULL,NULL) +#define eMsg2(s,a,b) eMsg3(s,a,b,NULL) + + /* S a n i t y C h e c k i n g */ + +#ifndef require +#define require(expr, err) {if ( !(expr) ) fatal_internal(err);} +#endif + + /* L i s t N o d e s */ + +typedef struct _ListNode { + void *elem; /* pointer to any kind of element */ + struct _ListNode *next; + } ListNode; + +/* Define a Cycle node which is used to track lists of cycles for later + * reconciliation by ResolveFoCycles(). + */ +typedef struct _c { + int croot; /* cycle root */ + set cyclicDep; /* cyclic dependents */ + unsigned deg; /* degree of FOLLOW set of croot */ + } Cycle; + +typedef struct _e { + int tok; /* error class name == TokenStr[tok] */ + ListNode *elist; /* linked list of elements in error set */ + set eset; + int setdeg; /* how big is the set */ + int lexclass; /* which lex class is it in? */ + } ECnode; + +typedef struct _TCnode { + int tok; /* token class name */ + ListNode *tlist; /* linked list of elements in token set */ + set tset; + int lexclass; /* which lex class is it in? */ + unsigned char dumped; /* this def has been been dumped */ + unsigned char dumpedComplement; /* this def has been been dumped */ + unsigned setnum; /* which set number is this guy? (if dumped) */ + unsigned setnumComplement; /* MR23 */ + unsigned setnumErrSet; /* MR23 which set is this #tokclass error set (if dumped) */ + unsigned setnumErrSetComplement; /* MR23 */ + } TCnode; + +typedef struct _ft { + char *token; /* id of token type to remap */ + int tnum; /* move token type to which token position */ + } ForcedToken; + +typedef struct _ContextGuardPredicates { /* MR13 */ + Predicate *pred; /* MR13 */ + } ContextGuardPredicates; /* MR13 */ + +#define newListNode (ListNode *) calloc(1, sizeof(ListNode)); +#define newCycle (Cycle *) calloc(1, sizeof(Cycle)); +#define newECnode (ECnode *) calloc(1, sizeof(ECnode)); +#define newTCnode (TCnode *) calloc(1, sizeof(TCnode)); + + + /* H a s h T a b l e E n t r i e s */ + +typedef struct _t { /* Token name or expression */ + char *str; + struct _t *next; + int token; /* token number */ + unsigned char classname; /* is it a err/tok class name or token */ + TCnode *tclass; /* ptr to token class */ + char *action; + char *akaString; + } TermEntry; + +typedef struct _r { /* Rule name and ptr to start of rule */ + char *str; + struct _t *next; + int rulenum; /* RulePtr[rulenum]== ptr to RuleBlk junction */ + unsigned char noAST;/* gen AST construction code? (def==gen code) */ + char *egroup; /* which error group (err reporting stuff) */ +#if 0 + /* MR27 This appears to never be used. Delete this code later. */ + + ListNode *el_labels;/* list of element labels ref in all of rule */ +#endif + ListNode *ast_labels_in_actions; /* MR27 */ + unsigned char has_rule_exception; + char dontComputeErrorSet; /* MR14 - don't compute error set + special for rule in alpha part of + (alpha)? beta block */ + } RuleEntry; + +typedef struct _f { /* cache Fi/Fo set */ + char *str; /* key == (rulename, computation, k) */ + struct _f *next; + set fset; /* First/Follow of rule */ + set rk; /* set of k's remaining to be done after ruleref */ + int incomplete; /* only w/FOLLOW sets. Use only if complete */ + } CacheEntry; + +typedef struct _LabelEntry { /* element labels */ + char *str; + struct _f *next; + Node *elem; /* which element does it point to? */ + ExceptionGroup *ex_group; + /* Is there an exception attached to label? */ + ExceptionGroup *outerEG; /* MR7 */ + /* next EG if ex_group doesn't catch it MR7 */ + struct _LabelEntry *pendingLink; /* MR7 */ + /* too lazy to use ListNode ? MR7 */ + int curAltNum; /* MR7 */ + } LabelEntry; + +typedef struct _SignalEntry { + char *str; + struct _f *next; + int signum; /* unique signal number */ + } SignalEntry; + +typedef struct _PredEntry { /* MR11 predicate name and ptr to string */ + char *str; + struct _PredEntry *next; + int file; + int line; + Predicate *pred; + char *predLiteral; + } PredEntry; + +typedef struct _PointerStack { /* MR10 */ + int count; + int size; + void **data; + } PointerStack; + +#define newTermEntry(s) (TermEntry *) newEntry(s, sizeof(TermEntry)) +#define newRuleEntry(s) (RuleEntry *) newEntry(s, sizeof(RuleEntry)) +#define newCacheEntry(s) (CacheEntry *) newEntry(s, sizeof(CacheEntry)) +#define newLabelEntry(s) (LabelEntry *) newEntry(s, sizeof(LabelEntry)) +#define newSignalEntry(s) (SignalEntry *) newEntry(s, sizeof(SignalEntry)) +#define newPredEntry(s) (PredEntry *) newEntry(s,sizeof(PredEntry)) + +typedef struct _UserAction { + char *action; + int file, line; + } UserAction; + + + /* L e x i c a l C l a s s */ + +/* to switch lex classes, switch ExprStr and Texpr (hash table) */ +typedef struct _lc { + char *classnum, **exprs; + Entry **htable; + } LClass; + +typedef struct _exprOrder { + char *expr; + int lclass; + } Expr; + + +typedef Graph Attrib; + + /* M a x i m u m s */ + +/* MR20 Note G. Hobbelt These values are superseded by values in hash.h */ + +#ifndef HashTableSize +#define HashTableSize 253 +#endif +#ifndef StrTableSize +#define StrTableSize 15000 /* all tokens, nonterminals, rexprs stored here */ +#endif +#define MaxLexClasses 50 /* how many automatons */ +/* TokenStart and EofToken are ignored if #tokdefs meta-op is used */ +#define TokenStart 2 /* MUST be in 1 + EofToken */ +#define EofToken 1 /* Always predefined to be 1 */ + +#ifndef MaxNumFiles +#define MaxNumFiles 99 +#endif + +/**** MR9 JVincent@novell.com Move to pcctscfg.h */ +/**** #define MaxFileName 300 ****/ /* MR9 Move to pcctscfg.h */ /* largest file name size */ + +#define MaxRuleName 100 /* largest rule name size */ +#define TSChunk 100 /* how much to expand TokenStr/ExprStr each time */ +#define TIChunk TSChunk /* expand TokenInd by same as TokenStr to mirror them */ +#define FoStackSize 100 /* deepest FOLLOW recursion possible */ + +#define MaxClassDeclStuff 256 /* MR10 */ + +#define NumPredefinedSignals 3 + + /* S t a n d a r d S i g n a l s */ + +#define sigNoSignal 0 +#define sigMismatchedToken 1 +#define sigNoViableAlt 2 +#define sigNoSemViableAlt 3 + + + +/* AST token types */ +#define ASTexclude 0 +#define ASTchild 1 +#define ASTroot 2 +#define ASTinclude 3 /* include subtree made by rule ref */ + + +#define PredictionVariable "zzpr_expr" +#define PredictionLexClassSuffix "_zzpred" + +#define WildCardString "WildCard" + +#if 0 + /* Removed in version 1.33MR19 + Don't understand why this never caused problems before + */ + + /********************************************************* + #ifndef ANTLRm + #define ANTLRm(st, f, _m) zzbufsize = ZZLEXBUFSIZE;\ + zzmode(_m); \ + zzenterANTLR(f); \ + st; ++zzasp; \ + zzleaveANTLR(f); + #endif + *********************************************************/ +#endif + +#include "proto.h" +#include "pcctscfg.h" /* MR14 */ +#include diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/globals.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/globals.c new file mode 100644 index 00000000..3b7631f7 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/globals.c @@ -0,0 +1,484 @@ +/* + * globals.c -- File containing all variables/tables visible to all files. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include + +#include "pcctscfg.h" + +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" + +char Version[] = "1.33MR33" ; /* PCCTS version number */ /* MRXXX */ +char VersionDef[] = "13333"; /* same (except int equiv for preproc symbol) */ /* MRXXX */ + +char LexStartSymbol[] = "START";/* Name of starting lexical class/automaton */ +char *RemapFileName = "remap.h"; +char *DlgFileName = "parser.dlg"; +char *DefFileName = "tokens.h"; +char *ErrFileName = "err.c"; +char *ModeFileName = "mode.h"; +char *StdMsgName = NULL; + +char *ParserName = DefaultParserName; + +/* list of PCCTS supplied support symbols; these are renamed when more than + * one ANTLR-generated parsers are linked together to avoid name conflicts. + * Can't use '##' ANSIC preprocessor concat operator with K&R and: + * #define zzskip zzparser ## skip + * will not work for ANSI/C++ as 'zzparserskip' is created w/o zzparser + * being substituted--ack!!! + */ +char *StandardSymbols[] = { +/* ANTLR stuff */ + "zzStackOvfMsg", + "zzasp", + "zzaStack", + "inf_tokens", + "inf_text", + "inf_text_buffer", + "inf_text_buffer_ptr", + "inf_text_buffer_size", + "inf_labase", + "inf_last", + "inf_lap", + "zztokenLA", + "zztextLA", + "zzlap", + "zzlabase", + "zztoktext", + "zztoken", + "zzdirty", + "zzguessing", + "zzguess_start", + "zzresynch", + "zzinf_tokens", + "zzinf_text", + "zzinf_text_buffer", + "zzinf_labase", + "zzinf_last", + "zzfill_inf_look", + "zzFAIL", + "zzsave_antlr_state", + "zzrestore_antlr_state", + "zzsyn", + "zzset_el", + "zzset_deg", + "zzedecode", + "_zzsetmatch", + "_zzmatch", + "_inf_zzgettok", + "zzconsumeUntil", + "zzconsumeUntilToken", + "_zzmatch_wsig", + "_zzsetmatch_wsig", + "_zzmatch_wdfltsig", + "_zzsetmatch_wdfltsig", + "zzdflthandlers", +/* DLG stuff */ + "zzreal_line", + "zzcharfull", + "zzerr", + "zzlextext", + "zzbegexpr", + "zzendexpr", + "zzbufsize", + "zzbegcol", + "zzendcol", + "zzline", + "zzchar", + "zzbufovf", + "zzrdstream", + "zzrdfunc", + "zzrdstr", + "zzclose_stream", + "zzsave_dlg_state", + "zzrestore_dlg_state", + "zzmode", + "zzskip", + "zzmore", + "zzreplchar", + "zzreplstr", + "zzgettok", + "zzadvance", + "zzerrstd", + "zzerr_in", + "zzconstr_attr", + "zzempty_attr", + "zzerraction", + "zztokens", /* list of token regular expressions */ + "dfa", + "accepts", + "actions", + "zzTraceOptionValue", /* MR10 */ + "zzTraceGuessOptionValue", /* MR10 */ + "zzTraceCurrentRuleName", /* MR10 */ + "zzTraceDepth", /* MR10 */ + "zzGuessSeq", /* MR10 */ + "zzSyntaxErrCount", /* MR11 */ + "zzLexErrCount", /* MR11 */ + "zzTraceGuessDone", /* MR13 - BJS */ + "zzTraceGuessFail", /* MR13 - BJS */ + "zzTraceGuessOption", /* MR13 - BJS */ + "zzTraceIn", /* MR13 - BJS */ + "zzTraceOption", /* MR13 - BJS */ + "zzTraceOut", /* MR13 - BJS */ + "zzTraceReset", /* MR13 - BJS */ + NULL /* must be present */ +}; + +/* list of PCCTS supplied support functions; these are renamed when more than + * one ANTLR-generated parsers are linked together to avoid name conflicts. + */ +char *ASTSymbols[] = { + "AST", + "zzast_sp", + "zzastStack", + "zzlink", + "zzastnew", + "zzsubchild", + "zzsubroot", + "zzpre_ast", + "zzfree_ast", + "zztmake", + "zzdup_ast", + "zztfree", + "zzdouble_link", + NULL /* must be present */ +}; + +/* Current ambiguity examination information */ +int CurAmbigAlt1, CurAmbigAlt2, CurAmbigline, CurAmbigfile; +char *CurAmbigbtype; + + + /* M e t h o d T a b l e s */ +/* + * The following tables are used to fill syntax diagram nodes with the correct + * function pointers for computing FIRST sets and printing themselves. + */ + +/* fpTraverse[node type] == pointer to function that calculates trees + * representing the FIRST sets for that node (maintains spatial info). + * We use 'struct _tree' not 'tree' due to a g++ 2.4.3 bug. + */ +#ifdef __cplusplus +struct _tree *(*fpTraverse[NumNodeTypes+1])(... /* Node *, int, set * */) = { + NULL, + (struct _tree *(*)(...)) tJunc, + (struct _tree *(*)(...)) tRuleRef, + (struct _tree *(*)(...)) tToken, + (struct _tree *(*)(...)) tAction +}; +#else +Tree *(*fpTraverse[NumNodeTypes+1])() = { + NULL, + tJunc, + tRuleRef, + tToken, + tAction +}; +#endif + +/* fpReach[node type] == pointer to function that calculates FIRST set for + * that node. (r stands for reach). We use 'struct _set' not 'set' + * due to a g++ 2.4.3 bug. + */ +#ifdef __cplusplus +struct _set (*fpReach[NumNodeTypes+1])(... /* Node *, int, set * */) = { + NULL, + (struct _set (*)(...)) rJunc, + (struct _set (*)(...)) rRuleRef, + (struct _set (*)(...)) rToken, + (struct _set (*)(...)) rAction +}; +#else +set (*fpReach[NumNodeTypes+1])() = { + NULL, + rJunc, + rRuleRef, + rToken, + rAction +}; +#endif + +/* fpPrint[node type] == pointer to function that knows how to print that node. */ +#ifdef __cplusplus +void (*fpPrint[NumNodeTypes+1])(... /* Node * */) = { + NULL, + (void (*)(...)) pJunc, + (void (*)(...)) pRuleRef, + (void (*)(...)) pToken, + (void (*)(...)) pAction +}; +#else +void (*fpPrint[NumNodeTypes+1])() = { + NULL, + pJunc, + pRuleRef, + pToken, + pAction +}; +#endif + +char *decodeJType[] = { + "invalid", + "aSubBlk", + "aOptBlk", + "aLoopBlk", + "EndBlk", + "RuleBlk", + "Generic", + "EndRule", + "aPlusBlk", + "aLoopBegin" +}; + + + /* H a s h T a b l e s */ + +Entry **Tname, /* Table of all token names (maps name to tok num)*/ + **Texpr, /* Table of all token expressions + (maps expr to tok num) */ + **Rname, /* Table of all Rules (has ptr to start of rule) */ + **Fcache, /* Cache of First/Follow Computations */ + **Tcache; /* Tree cache; First/Follow for permute trees */ +Entry **Elabel; /* Table of all element label names */ +Entry **Sname; /* Signal names */ +Entry **Pname; /* symbolic predicate names MR11 */ + + + /* V a r i a b l e s */ + +int Save_argc; /* MR10 */ +char **Save_argv; /* MR10 */ +int EpToken=0; /* Imaginary Epsilon token number */ +int WildCardToken=0; +int CurFile= -1; /* Index into FileStr table */ +char *CurPredName=NULL; /* MR11 */ +char *CurRule=NULL; /* Pointer to current rule name */ +int CurRuleDebug=0; /* MR13 debug flag */ +RuleEntry *CurRuleNode=NULL;/* Pointer to current rule node in syntax tree */ +char *CurRetDef=NULL; /* Pointer to current return type definition */ +char *CurParmDef=NULL; /* Pointer to current parameter definition */ +Junction *CurRuleBlk=NULL; /* Pointer to current block node for enclosing block */ +ListNode *CurExGroups=NULL; /* Current list of exception groups for rule/alts */ +ListNode *CurElementLabels=NULL; +ListNode *CurAstLabelsInActions=NULL; /* MR27 */ + +/* MR10 used by <<>>? to set "label_used_in_semantic_pred" */ +/* MR10 this will force LT(i) assignment even in guess mode */ + +ListNode *CurActionLabels=NULL; /* MR10 Element Labels appearing in last action */ +int numericActionLabel=0 ; /* MR10 << ... $1 ... >> or << ... $1 ... >>? */ +ListNode *NumericPredLabels=NULL; /* MR10 << ... $1 ... >>? ONLY */ +ListNode *ContextGuardPredicateList=NULL; /* MR13 for re-evaluating predicates + after meta tokens are defined */ + +int CurBlockID=0; /* Unique int for each block */ +int CurAltNum=0; +Junction *CurAltStart = NULL; /* Junction node that starts the alt */ +Junction *OuterAltStart = NULL; /* For chaining exception groups MR7 */ +int NumRules=0; /* Rules are from 1 to n */ +FILE *output=NULL; /* current parser output file */ +FILE *input=NULL; /* current grammar input file */ +char *FileStr[MaxNumFiles];/* Ptr to array of file names on command-line */ +int NumFiles=0; /* current grammar file number */ +#ifdef __cplusplus +void (**fpTrans)(...), /* array of ptrs to funcs that translate nodes */ + (**fpJTrans)(...); /* ... that translate junctions */ +#else +void (**fpTrans)(), /* array of ptrs to funcs that translate nodes */ + (**fpJTrans)(); /* ... that translate junctions */ +#endif +int **FoStack; /* Array of LL_k ptrs to stacks of rule numbers */ +int **FoTOS; /* FOLLOW stack top-of-stack pointers */ +Junction *SynDiag = NULL; /* Pointer to start of syntax diagram */ +int BlkLevel=1; /* Current block level. Set by antlr.g, used by + * scanner to translate $i.j attributes */ +set reserved_positions; /* set of token positions reserved by '#token T=i' cmds */ +set all_tokens; /* set of all token types */ +set imag_tokens; /* set of all imaginary token types (EpToken, errclasses...) */ +set tokclasses; /* set of all token class token types */ +ListNode *ForcedTokens = 0; /* list of token_id/token_num pairs to remap */ +ListNode *MetaTokenNodes=NULL; /* list of meta token refs such as token classes etc... */ +int *TokenInd=NULL; /* an indirection level between token num and position + * of that token def in TokenStr and ExprStr */ +int LastTokenCounted=0; /* ==TokenNum if no token renumbering (same as old TokenNum) */ +int TokenNum=TokenStart; +char **TokenStr=NULL; /* map token # to token name */ +char **ExprStr=NULL; /* map token # to expr */ +Junction **RulePtr=NULL; /* map rule # to RuleBlk node of rule */ +ListNode *ExprOrder=NULL; /* list of exprs as they are found in grammar */ +ListNode *BeforeActions=NULL;/* list of grammar actions before rules */ +ListNode *AfterActions=NULL;/* list of grammar actions after rules */ +ListNode *LexActions=NULL; /* list of lexical actions */ + +/* MR1 */ +/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ +/* MR1 via #lexmember <<....>> */ +/* MR1 via #lexprefix <<....>> */ +/* MR1 */ + +ListNode *LexMemberActions=NULL;/* list of lexical header member decl MR1 */ +ListNode *LexPrefixActions=NULL;/* list of lexical header #include decl MR1 */ +ListNode **Cycles=NULL; /* list of cycles (for each k) found when + doing FOLLOWs */ +ListNode *eclasses=NULL; /* list of error classes */ +ListNode *tclasses=NULL; /* list of token classes */ +LClass lclass[MaxLexClasses]; /* array of lex class definitions */ +int CurrentLexClass; /* index into lclass */ +int NumLexClasses=0; /* in range 1..MaxLexClasses (init 0) */ + +char *HdrAction=NULL; /* action defined with #header */ +char *FirstAction=NULL; /* action defined with #first MR11 */ +FILE *ErrFile; /* sets and error recovery stuff */ +FILE *DefFile=NULL; /* list of tokens, return value structs, setwd defs */ +FILE *MRinfoFile=NULL; /* MR10 information file */ +int MRinfo=0; /* MR10 */ +int MRinfoSeq=0; /* MR10 */ +int InfoP=0; /* MR10 predicates */ +int InfoT=0; /* MR10 tnodes */ +int InfoF=0; /* MR10 first/follow sets */ +int InfoM=0; /* MR10 monitor progress */ +int InfoO=0; /* MR12 orphan rules */ +int TnodesInUse=0; /* MR10 */ +int TnodesPeak=0; /* MR10 */ +int TnodesAllocated=0; /* MR10 */ +int TnodesReportThreshold=0; /* MR11 */ +int PotentialSuppression=0; /* MR10 */ +int PotentialDummy=0; /* MR10 */ +int CannotContinue=FALSE; +int OutputLL_k = 1; /* LL_k for parsing must be power of 2 */ +int action_file; /* used to track start of action */ +int action_line; +int FoundGuessBlk=0; /* there is a (...)? block somewhere in grammar */ +int FoundException=0; /* there is an exception somewhere in grammar */ +/* MR6 Distinguish between @ operator and real exception */ +/* MR6 by keeping separate flags for @ operator and real exceptions */ +int FoundAtOperator=0; /* MR6 */ +int FoundExceptionGroup=0; /* MR6 */ +int pLevel=0; /* print Level */ +int pAlt1,pAlt2; /* print "==>" in front of these alts */ + +/* C++ output stuff */ +FILE *Parser_h, /* where subclass of ANTLRParser goes */ + *Parser_c; /* where code for subclass of ANTLRParser goes */ +char Parser_h_Name[MaxFileName+1] = ""; +char Parser_c_Name[MaxFileName+1] = ""; +char MRinfoFile_Name[MaxFileName+1] = ""; /* MR10 */ +char *ClassDeclStuff=NULL; /* MR10 */ +char *BaseClassName=NULL; /* MR22 */ +/* list of actions inside the #class {...} defs */ +ListNode *class_before_actions=NULL; +ListNode *class_after_actions=NULL; + +char CurrentClassName[MaxRuleName]=""; +int no_classes_found=1; +char *UserTokenDefsFile; +int UserDefdTokens=0; /* found #tokdefs? */ +char *OutputDirectory=TopDirectory; +ExceptionGroup *DefaultExGroup = NULL; +int NumSignals = NumPredefinedSignals; +int ContextGuardTRAV=0; + +char *MR_AmbAidRule=NULL; /* MR11 */ +int MR_AmbAidLine=0; /* MR11 */ +int MR_AmbAidDepth=0; /* MR11 */ +int MR_AmbAidMultiple=0; /* MR11 */ +int MR_skipped_e3_report=0; /* MR11 */ +int MR_usingPredNames=0; /* MR11 */ +int MR_BadExprSets=0; /* MR13 */ +int MR_Inhibit_Tokens_h_Gen=0; /* MR13 */ +int NewAST=0; /* MR13 */ +int tmakeInParser=0; /* MR23 */ +int AlphaBetaTrace=0; /* MR14 */ +int MR_BlkErr=0; /* MR21 */ +int MR_AlphaBetaMessageCount=0; /* MR14 */ +int MR_AlphaBetaWarning=0; /* MR14 */ +int MR_ErrorSetComputationActive=0; /* MR14 */ +int MR_MaintainBackTrace=0; /* MR14 */ +set MR_CompromisedRules; /* MR14 */ + +Junction *MR_RuleBlkWithHalt; /* MR10 */ + + /* C m d - L i n e O p t i o n s */ + +int LL_k=1; /* how many tokens of full lookahead */ +int CLL_k= -1; /* how many tokens of compressed lookahead */ +int PrintOut = FALSE; /* print out the grammar */ +int PrintAnnotate = FALSE;/* annotate printout with FIRST sets */ +int CodeGen=TRUE; /* Generate output code? */ +int LexGen=TRUE; /* Generate lexical files? (tokens.h, parser.dlg) */ +int GenAST=FALSE; /* Generate AST's? */ +int GenANSI=FALSE; /* Generate ANSI code where necessary */ +int GenExprSetsOpt=TRUE;/* use sets not (LA(1)==tok) expression lists */ +int GenCR=FALSE; /* Generate cross reference? */ +int GenLineInfo=FALSE; /* Generate # line "file" stuff? */ +int GenLineInfoMS=FALSE;/* Like -gl but replace "\" with "/" for MS C/C++ systems */ +int TraceGen=FALSE; /* Generate code to trace rule invocation */ +int elevel=1; /* error level for ambiguity messages */ +int GenEClasseForRules=0;/* don't generate eclass for each rule */ +int TreeResourceLimit= -1;/* don't limit tree resource */ +int DemandLookahead = 0;/* demand/delayed lookahead or not */ +char *RulePrefix = ""; /* prefix each generated rule with this */ +char *stdpccts = "stdpccts.h";/* where to generate std pccts include file */ +int GenStdPccts = 0; /* don't gen stdpccts.h? */ +int ParseWithPredicates = 1; +int WarningLevel = 1; +int UseStdout = 0; /* MR6 */ +int TabWidth = 2; /* MR6 */ /* MR27 */ +int HoistPredicateContext = 0; +int MRhoisting = 0; /* MR9 */ +int MRhoistingk = 0; /* MR13 */ +int MR_debugGenRule=0; /* MR11 */ + +int GenCC = 0; /* Generate C++ output */ + +PointerStack MR_BackTraceStack={0,0,NULL}; /* MR10 */ +PointerStack MR_PredRuleRefStack={0,0,NULL}; /* MR10 */ +PointerStack MR_RuleBlkWithHaltStack={0,0,NULL}; /* MR10 */ + +/* DontCopyTokens and Pragma_DupLabeledTokens were a bad idea. I've just + turned them off rather than backpatching the code. Who knows? We + may need them in the future. + */ +int DontCopyTokens = 1; /* in C++, don't copy ANTLRToken passed to ANTLR */ + +/* Remember if LT(i), LA(i), or LATEXT(i) used in an action which is not + a predicate. If so, give a warning for novice users. +*/ + +int LTinTokenAction = 0; /* MR23 */ +int PURIFY = 1; /* MR23 */ + +int CurBlockID_array[MAX_BLK_LEVEL]; /* MR23 */ +int CurAltNum_array[MAX_BLK_LEVEL]; /* MR23 */ diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/hash.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/hash.c new file mode 100644 index 00000000..787cf65b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/hash.c @@ -0,0 +1,224 @@ +/* + * hash.c + * + * Manage hash tables. + * + * The following functions are visible: + * + * char *mystrdup(char *); Make space and copy string + * Entry **newHashTable(); Create and return initialized hash table + * Entry *hash_add(Entry **, char *, Entry *) + * Entry *hash_get(Entry **, char *) + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#ifdef VBOX +# include /* for intptr.h */ +#endif +#include "pcctscfg.h" +#include "hash.h" + +#ifdef __USE_PROTOS +#include +#else +#ifdef VAXC +#include +#else +#include +#endif +#endif +#include + +#define StrSame 0 + +#define fatal(err) \ + {fprintf(stderr, "%s(%d):", __FILE__, __LINE__); \ + fprintf(stderr, " %s\n", err); exit(PCCTS_EXIT_FAILURE);} +#define require(expr, err) {if ( !(expr) ) fatal(err);} + +static unsigned size = HashTableSize; +static char *strings = NULL; +static char *strp; +static unsigned strsize = StrTableSize; + +/* create the hash table and string table for terminals (string table only once) */ +Entry ** +#ifdef __USE_PROTOS +newHashTable( void ) +#else +newHashTable( ) +#endif +{ + Entry **table; + + table = (Entry **) calloc(size, sizeof(Entry *)); + require( table != NULL, "cannot allocate hash table"); + if ( strings == NULL ) + { + strings = (char *) calloc(strsize, sizeof(char)); + require( strings != NULL, "cannot allocate string table"); + strp = strings; + } + return table; +} + +void +#ifdef __USE_PROTOS +killHashTable( Entry **table ) +#else +killHashTable( table ) +Entry **table; +#endif +{ + /* for now, just free table, forget entries */ + free( (char *) table ); /* MR10 cast */ +} + +/* Given a table, add 'rec' with key 'key' (add to front of list). return ptr to entry */ +Entry * +#ifdef __USE_PROTOS +hash_add( Entry **table, char *key, Entry *rec ) +#else +hash_add( table, key, rec ) +Entry **table; +char *key; +Entry *rec; +#endif +{ + unsigned h=0; + char *p=key; + require(table!=NULL && key!=NULL && rec!=NULL, "add: invalid addition"); + + Hash(p,h,size); + rec->next = table[h]; /* Add to singly-linked list */ + table[h] = rec; + return rec; +} + +/* Return ptr to 1st entry found in table under key (return NULL if none found) */ +Entry * +#ifdef __USE_PROTOS +hash_get( Entry **table, char *key ) +#else +hash_get( table, key ) +Entry **table; +char *key; +#endif +{ + unsigned h=0; + char *p=key; + Entry *q; +/* require(table!=NULL && key!=NULL, "get: invalid table and/or key");*/ + if ( !(table!=NULL && key!=NULL) ) *((char *)(/*vbox:*/ intptr_t) 34) = 3; + + Hash(p,h,size); + for (q = table[h]; q != NULL; q = q->next) + { + if ( strcmp(key, q->str) == StrSame ) return( q ); + } + return( NULL ); +} + +#ifdef DEBUG_HASH +void +#ifdef __USE_PROTOS +hashStat( Entry **table ) +#else +hashStat( table ) +Entry **table; +#endif +{ + static unsigned short count[20]; + int i,n=0,low=0, hi=0; + Entry **p; + float avg=0.0; + + for (i=0; i<20; i++) count[i] = 0; + for (p=table; p<&(table[size]); p++) + { + Entry *q = *p; + int len; + + if ( q != NULL && low==0 ) low = p-table; + len = 0; + if ( q != NULL ) fprintf(stderr, "[%d]", p-table); + while ( q != NULL ) + { + len++; + n++; + fprintf(stderr, " %s", q->str); + q = q->next; + if ( q == NULL ) fprintf(stderr, "\n"); + } + count[len]++; + if ( *p != NULL ) hi = p-table; + } + + fprintf(stderr, "Storing %d recs used %d hash positions out of %d\n", + n, size-count[0], size); + fprintf(stderr, "%f %% utilization\n", + ((float)(size-count[0]))/((float)size)); + for (i=0; i<20; i++) + { + if ( count[i] != 0 ) + { + avg += (((float)(i*count[i]))/((float)n)) * i; + fprintf(stderr, "Bucket len %d == %d (%f %% of recs)\n", + i, count[i], ((float)(i*count[i]))/((float)n)); + } + } + fprintf(stderr, "Avg bucket length %f\n", avg); + fprintf(stderr, "Range of hash function: %d..%d\n", low, hi); +} +#endif + +/* Add a string to the string table and return a pointer to it. + * Bump the pointer into the string table to next avail position. + */ +char * +#ifdef __USE_PROTOS +mystrdup( char *s ) +#else +mystrdup( s ) +char *s; +#endif +{ + char *start=strp; + require(s!=NULL, "mystrdup: NULL string"); + + while ( *s != '\0' ) + { + require( strp <= &(strings[strsize-2]), + "string table overflow\nIncrease StrTableSize in hash.h and recompile hash.c\n"); + *strp++ = *s++; + } + *strp++ = '\0'; + + return( start ); +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/hash.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/hash.h new file mode 100644 index 00000000..8295c2cd --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/hash.h @@ -0,0 +1,73 @@ +/* + * hash.h -- define hash table entries, sizes, hash function... + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + + /* H a s h T a b l e S t u f f */ + +#ifndef HashTableSize +#define HashTableSize 553 +#endif + +#ifndef StrTableSize +#ifdef PC32 +#define StrTableSize 1000000 +#endif +#endif + +#ifndef StrTableSize +#ifdef PC +#define StrTableSize 655200 +#endif +#endif + +#ifndef StrTableSize +#define StrTableSize 1000000 +#endif + +typedef struct _entry { /* Minimum hash table entry -- superclass */ + char *str; + struct _entry *next; + } Entry; + +/* Hash 's' using 'size', place into h (s is modified) */ +#define Hash(s,h,size) \ + {while ( *s != '\0' ) h = (h<<1) + *s++; \ + h %= size;} + +#ifdef __USE_PROTOS +Entry *hash_get(Entry **, char *), + **newHashTable(void), + *hash_add(Entry **, char *, Entry *); + +void killHashTable(Entry **); + +#else +Entry *hash_get(), **newHashTable(), *hash_add(); +void killHashTable(); /* MR9 23-Sep-97 */ +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/lex.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/lex.c new file mode 100644 index 00000000..fbc91d1c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/lex.c @@ -0,0 +1,878 @@ +/* + * lex.c -- Generate all of the lexical type files: parser.dlg tokens.h + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include +/* MR1 */ +/* MR1 10-Apr-97 MR1 Replace use of __STDC__ with __USE_PROTOS */ +/* MR1 */ +#include "pcctscfg.h" +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" + +#define DLGErrorString "invalid token" + +/* Generate a complete lexical description of the lexemes found in the grammar */ +void +#ifdef __USE_PROTOS +genLexDescr( void ) +#else +genLexDescr( ) +#endif +{ + ListNode *p; + FILE *dlgFile = fopen(OutMetaName(DlgFileName), "w"); + require(dlgFile!=NULL, eMsg1("genLexFile: cannot open %s", OutMetaName(DlgFileName)) ); +#ifdef SPECIAL_FOPEN + special_fopen_actions(OutMetaName(DlgFileName)); /* MR1 */ +#endif + fprintf(dlgFile, "<<\n"); + fprintf(dlgFile, "/* %s -- DLG Description of scanner\n", DlgFileName); + fprintf(dlgFile, " *\n"); + fprintf(dlgFile, " * Generated from:"); + {int i; for (i=0; i 1 ) fprintf(dlgFile, "#define LL_K %d\n", OutputLL_k); + if ( DemandLookahead ) fprintf(dlgFile, "#define DEMAND_LOOK\n"); + if (TraceGen) { + fprintf(dlgFile,"#ifndef zzTRACE_RULES\n"); /* MR20 */ + fprintf(dlgFile,"#define zzTRACE_RULES\n"); /* MR20 */ + fprintf(dlgFile,"#endif\n"); /* MR22 */ + }; + fprintf(dlgFile, "#include \"antlr.h\"\n"); + if ( GenAST ) { + fprintf(dlgFile, "#include \"ast.h\"\n"); + } + if ( UserDefdTokens ) + fprintf(dlgFile, "#include %s\n", UserTokenDefsFile); + /* still need this one as it has the func prototypes */ + fprintf(dlgFile, "#include \"%s\"\n", DefFileName); + fprintf(dlgFile, "#include \"dlgdef.h\"\n"); + fprintf(dlgFile, "LOOKAHEAD\n"); + fprintf(dlgFile, "\n"); + fprintf(dlgFile, "void\n"); + fprintf(dlgFile, "#ifdef __USE_PROTOS\n"); + fprintf(dlgFile, "zzerraction(void)\n"); + fprintf(dlgFile, "#else\n"); + fprintf(dlgFile, "zzerraction()\n"); + fprintf(dlgFile, "#endif\n"); + fprintf(dlgFile, "{\n"); + fprintf(dlgFile, "\t(*zzerr)(\"%s\");\n", DLGErrorString); + fprintf(dlgFile, "\tzzadvance();\n"); + fprintf(dlgFile, "\tzzskip();\n"); + fprintf(dlgFile, "}\n"); + } + fprintf(dlgFile, ">>\n\n"); + + /* dump all actions */ + +/* MR1 */ +/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ +/* MR1 via <<%%lexmember ....>> & <<%%lexprefix ...>> */ +/* MR1 */ + if (LexActions != NULL) { + for (p = LexActions->next; p!=NULL; p=p->next) + { +/* MR1 */ fprintf(dlgFile, "<<%%%%lexaction\n"); + dumpAction( (char *)p->elem, dlgFile, 0, -1, 0, 1 ); + fprintf(dlgFile, ">>\n\n"); + } + }; + +/* MR1 */ if (GenCC) { +/* MR1 */ fprintf(dlgFile,"<<%%%%parserclass %s>>\n\n",CurrentClassName); +/* MR1 */ }; + +/* MR1 */ if (LexPrefixActions != NULL) { +/* MR1 */ for (p = LexPrefixActions->next; p!=NULL; p=p->next) +/* MR1 */ { +/* MR1 */ fprintf(dlgFile, "<<%%%%lexprefix\n"); +/* MR1 */ dumpAction( (char *)p->elem, dlgFile, 0, -1, 0, 1 ); +/* MR1 */ fprintf(dlgFile, ">>\n\n"); +/* MR1 */ } +/* MR1 */ }; + +/* MR1 */ if (LexMemberActions != NULL) { +/* MR1 */ for (p = LexMemberActions->next; p!=NULL; p=p->next) +/* MR1 */ { +/* MR1 */ fprintf(dlgFile, "<<%%%%lexmember\n"); +/* MR1 */ dumpAction( (char *)p->elem, dlgFile, 0, -1, 0, 1 ); +/* MR1 */ fprintf(dlgFile, ">>\n\n"); +/* MR1 */ } +/* MR1 */ }; + + /* dump all regular expression rules/actions (skip sentinel node) */ + if ( ExprOrder == NULL ) { + warnNoFL("no regular expressions found in grammar"); + } + else dumpLexClasses(dlgFile); + fprintf(dlgFile, "%%%%\n"); + fclose( dlgFile ); +} + +/* For each lexical class, scan ExprOrder looking for expressions + * in that lexical class. Print out only those that match. + * Each element of the ExprOrder list has both an expr and an lclass + * field. + */ +void +#ifdef __USE_PROTOS +dumpLexClasses( FILE *dlgFile ) +#else +dumpLexClasses( dlgFile ) +FILE *dlgFile; +#endif +{ + int i; + TermEntry *t; + ListNode *p; + Expr *q; + + for (i=0; inext; p!=NULL; p=p->next) + { + q = (Expr *) p->elem; + if ( q->lclass != i ) continue; + lexmode(i); + t = (TermEntry *) hash_get(Texpr, q->expr); + require(t!=NULL, eMsg1("genLexDescr: rexpr %s not in hash table",q->expr) ); + if ( t->token == EpToken ) continue; + fprintf(dlgFile, "%s\n\t<<\n", StripQuotes(q->expr)); + /* replace " killed by StripQuotes() */ + q->expr[ strlen(q->expr) ] = '"'; + if ( !GenCC ) { + if ( TokenString(t->token) != NULL ) + fprintf(dlgFile, "\t\tNLA = %s;\n", TokenString(t->token)); + else + fprintf(dlgFile, "\t\tNLA = %d;\n", t->token); + } + if ( t->action != NULL ) dumpAction( t->action, dlgFile, 2,-1,0,1 ); + if ( GenCC ) { + if ( TokenString(t->token) != NULL ) + fprintf(dlgFile, "\t\treturn %s;\n", TokenString(t->token)); + else + fprintf(dlgFile, "\t\treturn (ANTLRTokenType)%d;\n", t->token); + } + fprintf(dlgFile, "\t>>\n\n"); + } + } +} + +/* Strip the leading path (if any) from a filename */ +char * +#ifdef __USE_PROTOS +StripPath( char *fileName ) +#else +StripPath( fileName ) +char *fileName; +#endif +{ + char *p; + static char dirSym[2] = DirectorySymbol; + + if(NULL != (p = strrchr(fileName, dirSym[0]))) + p++; + else + p = fileName; + + return(p); +} + +/* Generate a list of #defines && list of struct definitions for + * aggregate retv's */ +void +#ifdef __USE_PROTOS +genDefFile( void ) +#else +genDefFile( ) +#endif +{ + int i; + + /* If C++ mode and #tokdef used, then don't need anything in here since + * C++ puts all definitions in the class file name. + */ + if ( GenCC && UserTokenDefsFile ) return; + if ( MR_Inhibit_Tokens_h_Gen) return; + + DefFile = fopen(OutMetaName(DefFileName), "w"); + require(DefFile!=NULL, eMsg1("genDefFile: cannot open %s", OutMetaName(DefFileName)) ); +#ifdef SPECIAL_FOPEN + special_fopen_actions(OutMetaName(DefFileName)); /* MR1 */ +#endif + fprintf(DefFile, "#ifndef %s\n", StripPath(gate_symbol(DefFileName))); + fprintf(DefFile, "#define %s\n", StripPath(gate_symbol(DefFileName))); + + fprintf(DefFile, "/* %s -- List of labelled tokens and stuff\n", DefFileName); + fprintf(DefFile, " *\n"); + fprintf(DefFile, " * Generated from:"); + for (i=0; i1 ) + { + int j; + /* look in all lexclasses for the reg expr */ + +/* MR10 Derek Pappas */ +/* MR10 A #tokclass doesn't have associated regular expressions */ +/* MR10 so don't warn user about it's omission */ + + p = (TermEntry *) hash_get(Tname, TokenString(i)); + + if (p != NULL && ! p->classname) { + for (j=0; j=NumLexClasses ) + { + warnNoFL(eMsg1("token label has no associated rexpr: %s",TokenString(i))); + } + }; + } + require((p=(TermEntry *)hash_get(Tname, TokenString(i))) != NULL, + "token not in sym tab when it should be"); + if ( !p->classname ) + { + if ( GenCC ) { + if ( !first ) fprintf(DefFile, ",\n"); + first = 0; + fprintf(DefFile, "\t%s=%d", TokenString(i), i); + } + else + fprintf(DefFile, "#define %s %d\n", TokenString(i), i); + } + } + } +/* MR1 */ +/* MR1 10-Apr-97 133MR1 Prevent use of varying sizes of integer */ +/* MR1 for the enum ANTLRTokenType */ +/* MR1 */ + if ( GenCC ) { /* MR1 */ + if ( !first ) fprintf(DefFile, ",\n"); /* MR14 */ + fprintf(DefFile, "\tDLGminToken=0"); /* MR1 */ + fprintf(DefFile, ",\n\tDLGmaxToken=9999};\n"); /* MR1 */ + }; /* MR1 */ + } + + if ( !GenCC ) GenRulePrototypes(DefFile, SynDiag); + + fprintf(DefFile, "\n#endif\n"); +} + +void +#ifdef __USE_PROTOS +GenRemapFile( void ) +#else +GenRemapFile( ) +#endif +{ + if ( strcmp(ParserName, DefaultParserName)!=0 ) + { + FILE *f; + int i; + + f = fopen(OutMetaName(RemapFileName), "w"); + require(f!=NULL, eMsg1("GenRemapFile: cannot open %s", OutMetaName(RemapFileName)) ); +#ifdef SPECIAL_FOPEN + special_fopen_actions(OutMetaName(RemapFileName)); /* MR1 */ +#endif + fprintf(f, "/* %s -- List of symbols to remap\n", RemapFileName); + fprintf(f, " *\n"); + fprintf(f, " * Generated from:"); + for (i=0; irname, ParserName, p->rname); + p = (Junction *)p->p2; + } +} + +/* Generate a bunch of #defines that rename all standard symbols to be + * "ParserName_symbol". The list of standard symbols to change is in + * globals.c. + */ +void +#ifdef __USE_PROTOS +GenPredefinedSymbolRedefs( FILE *f ) +#else +GenPredefinedSymbolRedefs( f ) +FILE *f; +#endif +{ + char **p; + + fprintf(f, "\n/* rename PCCTS-supplied symbols to be 'ParserName_symbol' */\n"); + for (p = &StandardSymbols[0]; *p!=NULL; p++) + { + fprintf(f, "#define %s %s_%s\n", *p, ParserName, *p); + } +} + +/* Generate a bunch of #defines that rename all AST symbols to be + * "ParserName_symbol". The list of AST symbols to change is in + * globals.c. + */ +void +#ifdef __USE_PROTOS +GenASTSymbolRedefs( FILE *f ) +#else +GenASTSymbolRedefs( f ) +FILE *f; +#endif +{ + char **p; + + fprintf(f, "\n/* rename PCCTS-supplied AST symbols to be 'ParserName_symbol' */\n"); + for (p = &ASTSymbols[0]; *p!=NULL; p++) + { + fprintf(f, "#define %s %s_%s\n", *p, ParserName, *p); + } +} + +/* redefine all sets generated by ANTLR; WARNING: 'zzerr', 'setwd' must match + * use in bits.c (DumpSetWd() etc...) + */ +void +#ifdef __USE_PROTOS +GenSetRedefs( FILE *f ) +#else +GenSetRedefs( f ) +FILE *f; +#endif +{ + int i; + + for (i=1; i<=wordnum; i++) + { + fprintf(f, "#define setwd%d %s_setwd%d\n", i, ParserName, i); + } + for (i=1; i<=esetnum; i++) + { + fprintf(f, "#define zzerr%d %s_err%d\n", i, ParserName, i); + } +} + +/* Find all return types/parameters that require structs and def + * all rules with ret types. + * + * This is for the declaration, not the definition. + */ +void +#ifdef __USE_PROTOS +GenRulePrototypes( FILE *f, Junction *p ) +#else +GenRulePrototypes( f, p ) +FILE *f; +Junction *p; +#endif +{ + int i; + + i = 1; + while ( p!=NULL ) + { + if ( p->ret != NULL ) + { +/* MR23 */ if ( hasMultipleOperands(p->ret) ) + { + DumpRetValStruct(f, p->ret, i); + } + fprintf(f, "\n#ifdef __USE_PROTOS\n"); +/* MR23 */ if ( hasMultipleOperands(p->ret) ) + { + fprintf(f, "extern struct _rv%d", i); + } + else + { + fprintf(f, "extern "); + DumpType(p->ret, f); + } + fprintf(f, " %s%s(", RulePrefix, p->rname); + DumpANSIFunctionArgDef(f,p,1 /* emit initializers ? */); + fprintf(f, ";\n"); + fprintf(f, "#else\n"); +/* MR23 */ if ( hasMultipleOperands(p->ret) ) + { + fprintf(f, "extern struct _rv%d", i); + } + else + { + fprintf(f, "extern "); + DumpType(p->ret, f); + } + fprintf(f, " %s%s();\n", RulePrefix, p->rname); + fprintf(f, "#endif\n"); + } + else + { + fprintf(f, "\n#ifdef __USE_PROTOS\n"); + fprintf(f, "void %s%s(", RulePrefix, p->rname); + DumpANSIFunctionArgDef(f,p, 1 /* emit initializers ? */ ); + fprintf(f, ";\n"); +#ifdef OLD + if ( p->pdecl != NULL || GenAST ) + { + if ( GenAST ) { + fprintf(f, "AST **%s",(p->pdecl!=NULL)?",":""); + } + if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl); + } + else fprintf(f, "void"); + fprintf(f, ");\n"); +#endif + fprintf(f, "#else\n"); + fprintf(f, "extern void %s%s();\n", RulePrefix, p->rname); + fprintf(f, "#endif\n"); + } + i++; + p = (Junction *)p->p2; + } +} + +/* Define all rules in the class.h file; generate any required + * struct definitions first, however. + */ +void +#ifdef __USE_PROTOS +GenRuleMemberDeclarationsForCC( FILE *f, Junction *q ) +#else +GenRuleMemberDeclarationsForCC( f, q ) +FILE *f; +Junction *q; +#endif +{ + Junction *p = q; + int i; + + fprintf(f, "private:\n"); + + /* Dump dflt handler declaration */ + fprintf(f, "\tvoid zzdflthandlers( int _signal, int *_retsignal );\n\n"); + + fprintf(f, "public:\n"); + + /* Dump return value structs */ + i = 1; + while ( p!=NULL ) + { + if ( p->ret != NULL ) + { +/* MR23 */ if ( hasMultipleOperands(p->ret) ) + { + DumpRetValStruct(f, p->ret, i); + } + } + i++; + p = (Junction *)p->p2; + } + + /* Dump member func defs && CONSTRUCTOR */ + fprintf(f, "\t%s(ANTLRTokenBuffer *input);\n", CurrentClassName); +/* + fprintf(f, "\t%s(ANTLRTokenBuffer *input, ANTLRTokenType eof);\n", + CurrentClassName); +*/ + + i = 1; + p = q; + while ( p!=NULL ) + { + if ( p->ret != NULL ) + { +/* MR23 */ if ( hasMultipleOperands(p->ret) ) + { + fprintf(f, "\tstruct _rv%d", i); + } + else + { + fprintf(f, "\t"); + DumpType(p->ret, f); + } + fprintf(f, " %s%s(",RulePrefix,p->rname); + DumpANSIFunctionArgDef(f,p, 1 /* emit initializers ? */ ); + fprintf(f, ";\n"); +#ifdef OLD + if ( p->pdecl != NULL || GenAST ) + { + if ( GenAST ) fprintf(f, "ASTBase **%s",(p->pdecl!=NULL)?",":""); + if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl); + } + fprintf(f, ");\n"); +#endif + } + else + { + fprintf(f, "\tvoid %s%s(",RulePrefix,p->rname); + DumpANSIFunctionArgDef(f,p, 1 /* emit initializers ? */); + fprintf(f, ";\n"); +#ifdef OLD + if ( p->pdecl != NULL || GenAST ) + { + if ( GenAST ) fprintf(f, "ASTBase **%s",(p->pdecl!=NULL)?",":""); + if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl); + } + fprintf(f, ");\n"); +#endif + } + i++; + p = (Junction *)p->p2; + } +} + +/* Given a list of ANSI-style parameter declarations, print out a + * comma-separated list of the symbols (w/o types). + * Basically, we look for a comma, then work backwards until start of + * the symbol name. Then print it out until 1st non-alnum char. Now, + * move on to next parameter. + * + */ + +/* MR5 Jan Mikkelsen 26-May-97 - added initialComma parameter */ + +void +#ifdef __USE_PROTOS +DumpListOfParmNames(char *pdecl, FILE *output, int initialComma) /* MR5 */ +#else +DumpListOfParmNames(pdecl, output, initialComma) /* MR5 */ +char *pdecl; /* MR5 */ +FILE *output; /* MR5 */ +int initialComma; /* MR5 */ +#endif +{ + int firstTime = 1, done = 0; + require(output!=NULL, "DumpListOfParmNames: NULL parm"); + + if ( pdecl == NULL ) return; + while ( !done ) + { + if ( !firstTime || initialComma ) putc(',', output); /* MR5 */ + done = DumpNextNameInDef(&pdecl, output); + firstTime = 0; + } +} + +/* given a list of parameters or return values, dump the next + * name to output. Return 1 if last one just printed, 0 if more to go. + */ + +/* MR23 Total rewrite */ + +int +#ifdef __USE_PROTOS +DumpNextNameInDef( char **q, FILE *output ) +#else +DumpNextNameInDef( q, output ) +char **q; +FILE *output; +#endif +{ + char *p; + char *t; + char *pDataType; + char *pSymbol; + char *pEqualSign; + char *pValue; + char *pSeparator; + int nest = 0; + + p = endFormal(*q, + &pDataType, + &pSymbol, + &pEqualSign, + &pValue, + &pSeparator, + &nest); + + /* MR26 Handle rule arguments such as: IIR_Bool (IIR_Decl::*constraint)() + For this we need to strip off anything which follows the symbol. + */ + +/* MR26 */ t = pSymbol; +/* MR26 */ if (t != NULL) { +/* MR26 */ for (t = pSymbol; *t != 0; t++) { +/* MR26 */ if (! (isalpha(*t) || isdigit(*t) || *t == '_' || *t == '$')) break; +/* MR26 */ } +/* MR26 */ } +/* MR26 */ fprintf(output, "%s", strBetween(pSymbol, t, pSeparator)); + + *q = p; + return (*pSeparator == 0); +} + +/* Given a list of ANSI-style parameter declarations, dump K&R-style + * declarations, one per line for each parameter. Basically, convert + * comma to semi-colon, newline. + */ +void +#ifdef __USE_PROTOS +DumpOldStyleParms( char *pdecl, FILE *output ) +#else +DumpOldStyleParms( pdecl, output ) +char *pdecl; +FILE *output; +#endif +{ + require(output!=NULL, "DumpOldStyleParms: NULL parm"); + + if ( pdecl == NULL ) return; + while ( *pdecl != '\0' ) + { + if ( *pdecl == ',' ) + { + pdecl++; + putc(';', output); putc('\n', output); + while ( *pdecl==' ' || *pdecl=='\t' || *pdecl=='\n' ) pdecl++; + } + else {putc(*pdecl, output); pdecl++;} + } + putc(';', output); + putc('\n', output); +} + +/* Take in a type definition (type + symbol) and print out type only */ +/* MR23 Total rewrite */ + +void +#ifdef __USE_PROTOS +DumpType( char *s, FILE *f ) +#else +DumpType( s, f ) +char *s; +FILE *f; +#endif +{ + char *p; + char *pDataType; + char *pSymbol; + char *pEqualSign; + char *pValue; + char *pSeparator; + int nest = 0; + + require(s!=NULL, "DumpType: invalid type string"); + + p = endFormal(s, + &pDataType, + &pSymbol, + &pEqualSign, + &pValue, + &pSeparator, + &nest); + fprintf(f, "%s", strBetween(pDataType, pSymbol, pSeparator)); +} + +/* check to see if string e is a word in string s */ +int +#ifdef __USE_PROTOS +strmember( char *s, char *e ) +#else +strmember( s, e ) +char *s; +char *e; +#endif +{ + register char *p; + require(s!=NULL&&e!=NULL, "strmember: NULL string"); + + if ( *e=='\0' ) return 1; /* empty string is always member */ + do { + while ( *s!='\0' && !isalnum(*s) && *s!='_' ) + ++s; + p = e; + while ( *p!='\0' && *p==*s ) {p++; s++;} + if ( *p=='\0' ) { + if ( *s=='\0' ) return 1; + if ( !isalnum (*s) && *s != '_' ) return 1; + } + while ( isalnum(*s) || *s == '_' ) + ++s; + } while ( *s!='\0' ); + return 0; +} + +#if 0 + +/* MR23 Replaced by hasMultipleOperands() */ + +int +#ifdef __USE_PROTOS +HasComma( char *s ) +#else +HasComma( s ) +char *s; +#endif +{ + while (*s!='\0') + if ( *s++ == ',' ) return 1; + return 0; +} +#endif + + +/* MR23 Total rewrite */ + +void +#ifdef __USE_PROTOS +DumpRetValStruct( FILE *f, char *ret, int i ) +#else +DumpRetValStruct( f, ret, i ) +FILE *f; +char *ret; +int i; +#endif +{ + char *p = ret; + char *pDataType; + char *pSymbol; + char *pEqualSign; + char *pValue; + char *pSeparator; + int nest = 0; + + fprintf(f, "\nstruct _rv%d {\n", i); + while (*p != 0 && nest == 0) { + p = endFormal(p, + &pDataType, + &pSymbol, + &pEqualSign, + &pValue, + &pSeparator, + &nest); + fprintf(f,"\t"); + fprintf(f, "%s", strBetween(pDataType, pSymbol, pSeparator)); + fprintf(f," "); + fprintf(f, "%s", strBetween(pSymbol, pEqualSign, pSeparator)); + fprintf(f,";\n"); + } + fprintf(f,"};\n"); +} + +/* given "s" yield s -- DESTRUCTIVE (we modify s if starts with " else return s) */ +char * +#ifdef __USE_PROTOS +StripQuotes( char *s ) +#else +StripQuotes( s ) +char *s; +#endif +{ + if ( *s == '"' ) + { + s[ strlen(s)-1 ] = '\0'; /* remove last quote */ + return( s+1 ); /* return address past initial quote */ + } + return( s ); +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/main.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/main.c new file mode 100644 index 00000000..bde0c831 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/main.c @@ -0,0 +1,1747 @@ +/* + * main.c -- main program for PCCTS ANTLR. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +/* To set a breakpoint just before exit look for "cleanUp". */ +/* To set a breakpoint for fatal error look for "fatal_intern" */ + +#include + +#include "pcctscfg.h" +#include "stdpccts.h" + +#define MAX_INT_STACK 50 +static int istack[MAX_INT_STACK]; /* Int stack */ +static int isp = MAX_INT_STACK; + +static int DontAcceptFiles = 0; /* if stdin, don't read files */ +static int DontAcceptStdin = 0; /* if files seen first, don't accept stdin */ + +static int tnodes_used_in_guard_predicates_etc; /* MR10 */ + + /* C m d - L i n e O p t i o n S t r u c t & F u n c s */ + +typedef struct _Opt { + char *option; + int arg; +#ifdef __cplusplus + void (*process)(...); +#else + void (*process)(); +#endif + char *descr; + } Opt; + +#ifdef __USE_PROTOS +extern void ProcessArgs(int, char **, Opt *); +#else +extern void ProcessArgs(); +#endif + +#ifdef __USE_PROTOS +int ci_strequ(char *a,char *b) +#else +int ci_strequ(a,b) + char *a; + char *b; +#endif +{ + for ( ;*a != 0 && *b != 0; a++, b++) { + if (toupper(*a) != toupper(*b)) return 0; + } + return (*a == *b); +} + +static void +#ifdef __USE_PROTOS +pStdin( void ) +#else +pStdin( ) +#endif +{ + if ( DontAcceptStdin ) + { + warnNoFL("'-' (stdin) ignored as files were specified first"); + return; + } + + require(NumFiles 8 ) { /* MR6 */ + warnNoFL("tab width must be between 1 and 8"); /* MR6 */ + TabWidth=0; /* MR6 */ + } /* MR6 */ +} /* MR6 */ + +static int ambAidDepthSpecified=0; /* MR11 */ + +static void /* MR11 */ +#ifdef __USE_PROTOS +pAAd( char *s, char *t ) /* MR11 */ +#else +pAAd( s, t ) /* MR11 */ +char *s; /* MR11 */ +char *t; /* MR11 */ +#endif +{ /* MR11 */ + ambAidDepthSpecified=1; /* MR11 */ + MR_AmbAidDepth = atoi(t); /* MR11 */ +} /* MR11 */ + +static void /* MR11 */ +#ifdef __USE_PROTOS +pTreport( char *s, char *t ) /* MR11 */ +#else +pTreport( s, t ) /* MR11 */ + char *s; /* MR11 */ + char *t; /* MR11 */ +#endif +{ /* MR11 */ + TnodesReportThreshold = atoi(t); /* MR11 */ +} /* MR11 */ + +#ifdef __USE_PROTOS +void chkGTFlag(void) /* 7-Apr-97 MR1 */ +#else +void chkGTFlag() /* 7-Apr-97 MR1 */ +#endif +{ + if ( !GenAST ) + warn("#-variable or other AST item referenced w/o -gt option"); +} + + +#ifdef __USE_PROTOS +static void pInfo(char *s, char *t) /* MR10 */ +#else +static void pInfo(s,t) /* MR10 */ + char *s; + char *t; +#endif +{ + char *p; + int q; + for (p=t; *p != 0; p++) { + q=tolower(*p); + if (q=='t') { + InfoT=1; + } else if (q=='p') { + InfoP=1; + } else if (q=='m') { + InfoM=1; + } else if (q=='o') { + InfoO=1; + } else if (q=='0') { + ; /* nothing */ + } else if (q=='f') { + InfoF=1; + } else { + warnNoFL(eMsgd("unrecognized -info option \"%c\"",(int)*p)); + }; + }; +} + +#ifdef __USE_PROTOS +static void pCGen(void) { CodeGen = FALSE; LexGen = FALSE; } +static void pLGen(void) { LexGen = FALSE; } +static void pXTGen(void){ MR_Inhibit_Tokens_h_Gen = TRUE; } +static void pTGen(void) { TraceGen = TRUE; } +static void pSGen(void) { GenExprSetsOpt = FALSE; } +static void pPrt(void) { PrintOut = TRUE; pCGen(); pLGen(); } +static void pPrtA(void) { PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); } +static void pAst(void) { GenAST = TRUE; } +static void pANSI(void) { GenANSI = TRUE; } +static void pCr(void) { GenCR = TRUE; } +static void pNOPURIFY(void) { PURIFY = FALSE; } +/*static void pCt(void) { warnNoFL("-ct option is now the default"); }*/ +static void pLI(void) { GenLineInfo = TRUE; GenLineInfoMS = FALSE; } /* MR14 */ +static void pLIms(void) { GenLineInfo = TRUE; GenLineInfoMS = TRUE; } /* MR14 */ +static void pFr(char *s, char *t) {RemapFileName = t;} +static void pFe(char *s, char *t) {ErrFileName = t;} +static void pFl(char *s, char *t) {DlgFileName = t;} +static void pFm(char *s, char *t) {ModeFileName = t;} +static void pFt(char *s, char *t) {DefFileName = t;} + +static void pE1(void) { elevel = 1; } +static void pE2(void) { elevel = 2; } +static void pE3(void) { elevel = 3; } +static void pEGen(void) { GenEClasseForRules = 1; } +static void pDL(void) + { + DemandLookahead = 1; + if ( GenCC ) { + warnNoFL("-gk does not work currently in C++ mode; -gk turned off"); + DemandLookahead = 0; + } + } + +static void pAA(char *s,char *t) {MR_AmbAidRule = t;} /* MR11 */ +static void pAAm(char *s){MR_AmbAidMultiple = 1;} /* MR11 */ +static void pGHdr(void) { GenStdPccts = 1; } +static void pFHdr(char *s, char *t) { stdpccts = t; pGHdr(); } +static void pW1(void) { WarningLevel = 1; } +static void pNewAST(void) { NewAST = 1; } /* MR13 */ +static void ptmakeInParser(void) { tmakeInParser = 1; } /* MR23 */ +static void pAlpha(void) { AlphaBetaTrace = 1; } /* MR14 */ +static void pMR_BlkErr(void) { MR_BlkErr = 1; } /* MR21 */ +static void pStdout(void) {UseStdout = 1; } /* MR6 */ +static void pW2(void) { WarningLevel = 2; } +static void pCC(void) { GenCC = TRUE; } +#else +static void pCGen() { CodeGen = FALSE; LexGen = FALSE; } +static void pLGen() { LexGen = FALSE; } +static void pXTGen(){ MR_Inhibit_Tokens_h_Gen = TRUE; } /* MR14 */ +static void pTGen() { TraceGen = TRUE; } +static void pSGen() { GenExprSetsOpt = FALSE; } +static void pPrt() { PrintOut = TRUE; pCGen(); pLGen(); } +static void pPrtA() { PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); } +static void pAst() { GenAST = TRUE; } +static void pANSI() { GenANSI = TRUE; } +static void pCr() { GenCR = TRUE; } +static void pNOPURIFY() { PURIFY = FALSE; } + +/*static void pCt() { warnNoFL("-ct option is now the default"); }*/ +static void pLI() { GenLineInfo = TRUE; GenLineInfoMS = FALSE; } /* MR14 */ +static void pLIms() { GenLineInfo = TRUE; GenLineInfoMS = TRUE; } /* MR14 */ +static void pFr(s,t) char *s, *t; {RemapFileName = t;} +static void pFe(s,t) char *s, *t; {ErrFileName = t;} +static void pFl(s,t) char *s, *t; {DlgFileName = t;} +static void pFm(s,t) char *s, *t; {ModeFileName = t;} +static void pFt(s,t) char *s, *t; {DefFileName = t;} + +static void pE1() { elevel = 1; } +static void pE2() { elevel = 2; } +static void pE3() { elevel = 3; } +static void pEGen() { GenEClasseForRules = 1; } +static void pDL() + { + DemandLookahead = 1; + if ( GenCC ) { + warnNoFL("-gk does not work currently in C++ mode; -gk turned off"); + DemandLookahead = 0; + } + } + +static void pAA(s,t) char *s; char *t; {MR_AmbAidRule = t;} /* MR11 BJS 20-Mar-98 */ +static void pAAm(s) char *s; {MR_AmbAidMultiple = 1;} /* MR11 BJS 20-Mar-98 */ +static void pGHdr() { GenStdPccts = 1; } +static void pFHdr(s,t) char *s, *t; { stdpccts = t; pGHdr(); } +static void pW1() { WarningLevel = 1; } +static void pNewAST() { NewAST = 1; } /* MR13 */ +static void ptmakeInParser() { tmakeInParser = 1; } /* MR23 */ +static void pAlpha() { AlphaBetaTrace = 1; } /* MR14 */ +static void pMR_BlkErr() { MR_BlkErr = 1; } /* MR21 */ +static void pStdout() {UseStdout = 1; } /* MR6 */ +static void pW2() { WarningLevel = 2; } +static void pCC() { GenCC = TRUE; } +#endif + +static void +#ifdef __USE_PROTOS +pPre( char *s, char *t ) +#else +pPre( s, t ) +char *s; +char *t; +#endif +{ + RulePrefix = t; +} + +static void +#ifdef __USE_PROTOS +pOut( char *s, char *t ) +#else +pOut( s, t ) +char *s; +char *t; +#endif +{ + OutputDirectory = t; +} + +static void +#ifdef __USE_PROTOS +pPred( void ) +#else +pPred( ) +#endif +{ + warnNoFL("-pr is no longer used (predicates employed if present); see -prc, -mrhoist, -mrhoistk"); +/* +** if ( DemandLookahead ) +** warnNoFL("-gk conflicts with -pr; -gk turned off"); +** DemandLookahead = 0; +** HoistPredicateContext = 0; +*/ +} + +static void +#ifdef __USE_PROTOS +pPredCtx( char *s, char *t ) +#else +pPredCtx(s,t) +char *s; +char *t; +#endif +{ + if ( ci_strequ(t,"on")) HoistPredicateContext = 1; + else if ( ci_strequ(t,"off")) HoistPredicateContext = 0; + if ( DemandLookahead ) + { + warnNoFL("-gk incompatible with semantic predicate usage; -gk turned off"); + DemandLookahead = 0; + } +} + +static void +#ifdef __USE_PROTOS +pMRhoist( char *s, char *t ) +#else +pMRhoist(s,t) +char *s; +char *t; +#endif +{ + if ( ci_strequ(t,"on")) MRhoisting = 1; + else if ( ci_strequ(t,"off")==0 ) MRhoisting = 0; + if (MRhoisting) { + fprintf(stderr,"Maintenance Release style hoisting enabled for predicates with lookahead depth = 1\n"); + fprintf(stderr," No longer considered experimental\n"); + fprintf(stderr," Can't consider suppression for predicates with lookahead depth > 1\n"); + fprintf(stderr," Implies -prc on but does *not* imply -mrhoistk for k>1 predicates\n"); + fprintf(stderr," This is a reminder, not a warning or error.\n"); + }; +} + +static void +#ifdef __USE_PROTOS +pMRhoistk( char *s, char *t ) +#else +pMRhoistk(s,t) +char *s; +char *t; +#endif +{ + if ( ci_strequ(t,"on")) MRhoistingk = 1; + else if ( ci_strequ(t,"off")==0 ) MRhoistingk = 0; + if (MRhoistingk) { + fprintf(stderr,"EXPERIMENTAL Maintenance Release style hoisting enabled\n"); + fprintf(stderr," Applies to predicates with lookahead depth > 1\n"); + fprintf(stderr," Implies -prc on and -mrhoist on\n"); + }; +} + +static void +#ifdef __USE_PROTOS +pTRes( char *s, char *t ) +#else +pTRes( s, t ) +char *s; +char *t; +#endif +{ + TreeResourceLimit = atoi(t); + if ( TreeResourceLimit <= 0 ) + { + warnNoFL("analysis resource limit (# of tree nodes) must be greater than 0"); + TreeResourceLimit = -1; /* set to no limit */ + } +} + +Opt options[] = { +#ifdef __cplusplus + { "-CC", 0, (void (*)(...)) pCC, "Generate C++ output (default=FALSE)"}, + { "-ck", 1, (void (*)(...)) pCk, "Set compressed lookahead depth; fast approximate lookahead"}, + { "-cr", 0, (void (*)(...)) pCr, "Generate cross reference (default=FALSE)"}, + { "-e1", 0, (void (*)(...)) pE1, "Ambiguities/errors shown in low detail (default)"}, + { "-e2", 0, (void (*)(...)) pE2, "Ambiguities/errors shown in more detail"}, + { "-e3", 0, (void (*)(...)) pE3, + "Ambiguities for k>1 grammars shown with exact tuples (not lookahead sets)"}, + { "-f", 1, (void (*)(...)) pFileList,"Read names of grammar files from specified file"}, /* MR14 */ + { "-fe", 1, (void (*)(...)) pFe, "Rename err.c"}, + { "-fh", 1, (void (*)(...)) pFHdr, "Rename stdpccts.h header (turns on -gh)"}, + { "-fl", 1, (void (*)(...)) pFl, "Rename lexical output--parser.dlg"}, + { "-fm", 1, (void (*)(...)) pFm, "Rename mode.h"}, + { "-fr", 1, (void (*)(...)) pFr, "Rename remap.h"}, + { "-ft", 1, (void (*)(...)) pFt, "Rename tokens.h"}, + { "-ga", 0, (void (*)(...)) pANSI, "Generate ANSI-compatible code (default=FALSE)"}, + { "-gc", 0, (void (*)(...)) pCGen, "Do not generate output parser code (default=FALSE)"}, + { "-gd", 0, (void (*)(...)) pTGen, "Generate code to trace rule invocation (default=FALSE)"}, + { "-ge", 0, (void (*)(...)) pEGen, "Generate an error class for each non-terminal (default=FALSE)"}, + { "-gh", 0, (void (*)(...)) pGHdr, "Generate stdpccts.h for non-ANTLR-generated-files to include"}, + { "-gk", 0, (void (*)(...)) pDL, "Generate parsers that delay lookahead fetches until needed"}, + { "-gl", 0, (void (*)(...)) pLI, "Generate line info about grammar actions in parser"}, + { "-glms", 0, (void (*)(...)) pLIms,"Like -gl but replace '\\' with '/' in #line filenames for MS C/C++ systems"}, + { "-gp", 1, (void (*)(...)) pPre, "Prefix all generated rule functions with a string"}, + { "-gs", 0, (void (*)(...)) pSGen, "Do not generate sets for token expression lists (default=FALSE)"}, + { "-gt", 0, (void (*)(...)) pAst, "Generate code for Abstract-Syntax-Trees (default=FALSE)"}, + { "-gx", 0, (void (*)(...)) pLGen, "Do not generate lexical (dlg-related) files (default=FALSE)"}, + { "-gxt",0, (void (*)(...)) pXTGen, "Do not generate tokens.h (default=FALSE)"}, + { "-k", 1, (void (*)(...)) pLLK, "Set full LL(k) lookahead depth (default==1)"}, + { "-o", 1, (void (*)(...)) pOut, OutputDirectoryOption}, + { "-p", 0, (void (*)(...)) pPrt, "Print out the grammar w/o actions (default=no)"}, + { "-pa", 0, (void (*)(...)) pPrtA, "Print out the grammar w/o actions & w/FIRST sets (default=no)"}, + { "-pr",0, (void (*)(...)) pPred, "no longer used; predicates employed if present"}, + { "-prc", 1, (void (*)(...)) pPredCtx,"Turn on/off computation of context for hoisted predicates"}, + { "-rl", 1, (void (*)(...)) pTRes, "Limit max # of tree nodes used by grammar analysis"}, + { "-stdout",0, (void (*)(...)) pStdout,"Send grammar.c/grammar.cpp to stdout"}, /* MR6 */ + { "-tab", 1, (void (*)(...)) pTab, "Width of tabs (1 to 8) for grammar.c/grammar.cpp files"}, /* MR6 */ + { "-w1", 0, (void (*)(...)) pW1, "Set the warning level to 1 (default)"}, + { "-w2", 0, (void (*)(...)) pW2, "Ambiguities yield warnings even if predicates or (...)? block"}, + { "-", 0, (void (*)(...)) pStdin, "Read grammar from stdin" }, + { "-mrhoist",1, (void (*)(...)) pMRhoist, /* MR9 */ + "Turn on/off k=1 Maintenance Release style hoisting"}, /* MR9 */ + { "-mrhoistk",1, (void (*)(...)) pMRhoistk, /* MR9 */ + "Turn on/off EXPERIMENTAL k>1 Maintenance Release style hoisting"}, /* MR13 */ + { "-aa" , 1, (void (*)(...)) pAA, "Ambiguity aid for a rule (rule name or line number)"}, /* MR11 */ + { "-aam" , 0, (void (*)(...)) pAAm, + "Lookahead token may appear multiple times in -aa listing"}, /* MR11 */ + { "-aad" , 1, (void (*)(...)) pAAd, + "Limits exp growth of -aa listing - default=1 (max=ck value)"}, /* MR11 */ + { "-info", 1, (void (*)(...)) pInfo, + "Extra info: p=pred t=tnodes f=first/follow m=monitor o=orphans 0=noop"}, /* MR12 */ + { "-treport",1,(void (*)(...)) pTreport, + "Report when tnode usage exceeds value during ambiguity resolution"}, /* MR11 */ + { "-newAST", 0, (void (*)(...)) pNewAST, + "In C++ mode use \"newAST(...)\" rather than \"new AST(...)\""}, /* MR13 */ + { "-tmake", 0, (void (*)(...)) ptmakeInParser, + "In C++ mode use parser's tmake method rather than \"ASTBase::tmake(...)\""}, /* MR23 */ + { "-alpha",0,(void (*)(...)) pAlpha, + "Provide additional information for \"(alpha)? beta\" error messages"}, /* MR14 */ + { "-mrblkerr",0,(void (*)(...)) pMR_BlkErr, /* MR21 */ + "EXPERIMENTAL change to (...)* and (...)+ syntax error sets"}, /* MR21 */ + { "-nopurify",0,(void (*)(...)) pNOPURIFY, + "Don't use the notorious PURIFY macro (replaced by MR23 initial value syntax) to zero return arguments of rules"}, /* MR23 */ + { "*", 0, (void (*)(...)) pFile, "" }, /* anything else is a file */ +#else + { "-CC", 0, pCC, "Generate C++ output (default=FALSE)"}, + { "-cr", 0, pCr, "Generate cross reference (default=FALSE)"}, + { "-ck", 1, pCk, "Set compressed lookahead depth; fast approximate lookahead"}, + { "-e1", 0, pE1, "Ambiguities/errors shown in low detail (default)"}, + { "-e2", 0, pE2, "Ambiguities/errors shown in more detail"}, + { "-e3", 0, pE3, "Ambiguities for k>1 grammars shown with exact tuples (not lookahead sets)"}, + { "-f", 1, pFileList,"Read names of grammar files from specified file"}, /* MR14 */ + { "-fe", 1, pFe, "Rename err.c"}, + { "-fh", 1, pFHdr, "Rename stdpccts.h header (turns on -gh)"}, + { "-fl", 1, pFl, "Rename lexical output--parser.dlg"}, + { "-fm", 1, pFm, "Rename mode.h"}, + { "-fr", 1, pFr, "Rename remap.h"}, + { "-ft", 1, pFt, "Rename tokens.h"}, + { "-ga", 0, pANSI, "Generate ANSI-compatible code (default=FALSE)"}, + { "-gc", 0, pCGen, "Do not generate output parser code (default=FALSE)"}, + { "-gd", 0, pTGen, "Generate code to trace rule invocation (default=FALSE)"}, + { "-ge", 0, pEGen, "Generate an error class for each non-terminal (default=FALSE)"}, + { "-gh", 0, pGHdr, "Generate stdpccts.h for non-ANTLR-generated-files to include"}, + { "-gk", 0, pDL, "Generate parsers that delay lookahead fetches until needed"}, + { "-gl", 0, pLI, "Generate line info about grammar actions in C parser"}, + { "-glms", 0, pLIms,"Like -gl but replace '\\' with '/' in #line filenames for MS C/C++ systems"}, + { "-gp", 1, pPre, "Prefix all generated rule functions with a string"}, + { "-gs", 0, pSGen, "Do not generate sets for token expression lists (default=FALSE)"}, + { "-gt", 0, pAst, "Generate code for Abstract-Syntax-Trees (default=FALSE)"}, + { "-gx", 0, pLGen, "Do not generate lexical (dlg-related) files (default=FALSE)"}, + { "-gxt",0, pXTGen, "Do not generate tokens.h (default=FALSE)"}, + { "-k", 1, pLLK, "Set full LL(k) lookahead depth (default==1)"}, + { "-o", 1, pOut, OutputDirectoryOption}, + { "-p", 0, pPrt, "Print out the grammar w/o actions (default=no)"}, + { "-pa", 0, pPrtA, "Print out the grammar w/o actions & w/FIRST sets (default=no)"}, + { "-pr",0, pPred, "no longer used; predicates employed if present"}, + { "-prc", 1, pPredCtx,"Turn on/off computation of context for hoisted predicates"}, + { "-rl", 1, pTRes, "Limit max # of tree nodes used by grammar analysis"}, + { "-stdout",0, pStdout, "Send grammar.c/grammar.cpp to stdout"}, /* MR6 */ + { "-tab", 1, pTab, "Width of tabs (1 to 8) for grammar.c/grammar.cpp files"}, /* MR6 */ + { "-w1", 0, pW1, "Set the warning level to 1 (default)"}, + { "-w2", 0, pW2, "Ambiguities yield warnings even if predicates or (...)? block"}, + { "-mrhoist",1,pMRhoist, /* MR9 */ + "Turn on/off k=1 Maintenance Release style hoisting"}, /* MR9 */ + { "-mrhoistk",1,pMRhoistk, /* MR13 */ + "Turn on/off k>1 EXPERIMENTAL Maintenance Release style hoisting"}, /* MR13 */ + { "-aa" ,1,pAA, "Ambiguity aid for a rule (rule name or line number)"}, /* MR11 */ + { "-aam" ,0,pAAm, + "Lookahead token may appear multiple times in -aa listing"}, /* MR11 */ + { "-aad" ,1,pAAd, + "Limits exp growth of -aa listing - default=1 (max=ck value)"}, /* MR11 */ + { "-info",1,pInfo, + "Extra info: p=pred t=tnodes f=first/follow m=monitor o=orphans 0=noop"}, /* MR11 */ + { "-treport",1,pTreport, + "Report when tnode usage exceeds value during ambiguity resolution"}, /* MR11 */ + { "-newAST", 0, pNewAST, + "In C++ mode use \"newAST(...)\" rather than \"new AST(...)\""}, /* MR13 */ + { "-tmake", 0, ptmakeInParser, + "In C++ mode use parser's tmake method rather than \"ASTBase::tmake(...)\""}, /* MR23 */ + { "-alpha",0, pAlpha, + "Provide additional information for \"(alpha)? beta\" error messages"}, /* MR14 */ + { "-mrblkerr",0,pMR_BlkErr, /* MR21 */ + "EXPERIMENTAL change to (...)* and (...)+ syntax error sets"}, /* MR21 */ + { "-nopurify",0,pNOPURIFY, + "Don't use the notorious PURIFY macro (replaced by MR23 initial value syntax) to zero return arguments of rules"}, /* MR23 */ + { "-", 0, pStdin, "Read grammar from stdin" }, + { "*", 0, pFile, "" }, /* anything else is a file */ +#endif + { NULL, 0, NULL } + }; + +void readDescr(); +void cleanUp(); + +#ifdef __USE_PROTOS +static void buildRulePtr( void ); +static void help( void ); +static void init( void ); +static void CompleteTokenSetRefs( void ); +static void ensure_no_C_file_collisions(char *); +static void CompleteContextGuards(void); +#else +static void buildRulePtr( ); +static void help( ); +static void init( ); +static void CompleteTokenSetRefs( ); +static void ensure_no_C_file_collisions(); +static void CompleteContextGuards(); +#endif + +static void +#ifdef __USE_PROTOS /* */ +report_numericPredLabels(ActionNode *a) +#else +report_numericPredLabels(a) +ActionNode *a; +#endif +{ /* MR10 */ + warnFL("numeric references to attributes (e.g. $i or $i.j) in semantic pred will be null during guess mode", /* MR10 */ + FileStr[a->file],a->line); /* MR10 */ +} /* MR10 */ + + /* M a i n */ + +int +#ifdef __USE_PROTOS +main( int argc, char *argv[] ) +#else +main( argc, argv ) +int argc; +char *argv[]; +#endif +{ + int i; + static char EPSTR[] = "[Ep]"; + + Save_argc=argc; /* MR10 */ + Save_argv=argv; /* MR10 */ + +/* malloc_debug(8);*/ + +#ifdef SPECIAL_INITS + special_inits(); /* MR1 */ +#endif + fprintf(stderr, "Antlr parser generator Version %s 1989-2001\n", Version); + if ( argc == 1 ) { help(); zzDIE; } + ProcessArgs(argc-1, &(argv[1]), options); + +/* MR14 */ if (MR_AmbAidRule && AlphaBetaTrace) { +/* MR14 */ fatal("Can't specify both -aa (ambiguity aid) and -alpha (\"(alpha)? beta\" aid)"); +/* MR14 */ } + + if (MRhoistingk) { /* MR13 */ + HoistPredicateContext=1; /* MR13 */ + MRhoisting=1; /* MR13 */ + }; /* MR13 */ + if (MRhoisting && ! HoistPredicateContext) { +/*** warnNoFL("Using \"-mrhoist\" forces \"-prc on\""); ***/ + HoistPredicateContext=1; + }; + if (HoistPredicateContext && ! MRhoisting) { + warnNoFL("When using predicate context (-prc on) -mrhoist on is recommended"); + } + /* Fix lookahead depth */ + /* Compressed lookahead must always be larger than or equal to full lookahead */ + if ( CLL_k < LL_k && CLL_k>0 ) + { + warnNoFL("must have compressed lookahead >= full LL(k) lookahead (setting -ck to -k)"); + CLL_k = LL_k; + } + if ( CLL_k == -1 ) CLL_k = LL_k; + OutputLL_k = CLL_k; + if ( ((CLL_k-1)&CLL_k)!=0 ) { /* output ll(k) must be power of 2 */ + int n; + for(n=1; n 1) { + warnNoFL("The -mrblkerr option is designed only for k=1 ck=1 grammars"); + } + }; + + if ( ! ambAidDepthSpecified) { + MR_AmbAidDepth=1; + } else { + if (MR_AmbAidDepth > CLL_k || MR_AmbAidDepth <= 0) { + warnNoFL(eMsgd( + "Ambiguity aid depth (\"-aad ...\") must be a number between 1 and max(k,ck)=%d",CLL_k)); + MR_AmbAidDepth=1; + }; + if (MR_AmbAidDepth == 0) { + MR_AmbAidDepth=2; + }; + }; + + if (MR_AmbAidRule != NULL) MR_AmbAidLine=atoi(MR_AmbAidRule); + + fpTrans = &(C_Trans[0]); /* Translate to C Language */ + fpJTrans = &(C_JTrans[0]); + init(); + lexclass(LexStartSymbol); + + readDescr(); + LastTokenCounted = TokenNum; + RemapForcedTokens(); + if ( CannotContinue ) {cleanUp(); zzDIE;} + if ( GenCC && no_classes_found ) fatal("required grammar class not found (exiting...)"); + if ( WarningLevel>1 && HdrAction == NULL ) + warnNoFL("no #header action was found"); + if ( FoundAtOperator && ! FoundExceptionGroup) { + warnNoFL("found the exception operator '@' - but no exception group was found"); + }; + EpToken = addTname(EPSTR); /* add imaginary token epsilon */ + set_orel(EpToken, &imag_tokens); + + /* this won't work for hand-built scanners since EofToken is not + * known. Forces EOF to be token type 1. + */ + set_orel(EofToken, &imag_tokens); + + set_size(NumWords(TokenNum-1)); + + /* compute the set of all known token types + * It represents the set of tokens from 1 to last_token_num + the + * reserved positions above that (if any). Don't include the set of + * imaginary tokens such as the token/error classes or EOF. + */ + { + set a; + a = set_dup(reserved_positions); + for (i=1; inext; p!=NULL; p=p->next) + { + UserAction *ua = (UserAction *)p->elem; + dumpAction( ua->action, Parser_h, 0, ua->file, ua->line, 1); + } + } + GenParser_c_Hdr(); + fprintf(Parser_h, "protected:\n"); /* MR20 */ + NewSetWd(); + TRANS(SynDiag); /* Translate to the target language */ + DumpSetWd(); + GenRuleMemberDeclarationsForCC(Parser_h, SynDiag); + if ( class_after_actions != NULL ) + { + ListNode *p; + for (p = class_after_actions->next; p!=NULL; p=p->next) + { + UserAction *ua = (UserAction *)p->elem; + dumpAction( ua->action, Parser_h, 0, ua->file, ua->line, 1); + } + } + DumpRemainingTokSets(); + fprintf(Parser_h, "};\n"); + fprintf(Parser_h, "\n#endif /* %s_h */\n", CurrentClassName); + fclose( Parser_h ); + fclose( Parser_c ); + } + } + + MR_orphanRules(stderr); + if (LTinTokenAction && WarningLevel >= 2) { + if (GenCC) { + warnNoFL("At least one <> following a token match contains a reference to LT(...)\n this will reference the immediately preceding token,\n not the one which follows as is the case with semantic predicates."); + } + warnNoFL("At least one <> following a token match contains a reference to LA(...) or LATEXT(...)\n this will reference the immediately preceding token,\n not the one which follows as is the case with semantic predicates."); + } + + if ( PrintOut ) + { + if ( SynDiag == NULL ) {warnNoFL("no grammar description recognized");} + else PRINT(SynDiag); + } + +#ifdef DBG_LL1 +#endif + GenRemapFile(); /* create remap.h */ +/* MR10 */ if (FoundGuessBlk) { +#ifdef __cplusplus__ +/* MR10 */ list_apply(NumericPredLabels, (void (*)(void *))report_numericPredLabels); +#else +#ifdef __USE_PROTOS +/* MR10 */ list_apply(NumericPredLabels, (void (*)(void *))report_numericPredLabels); +#else +/* MR10 */ list_apply(NumericPredLabels,report_numericPredLabels); +#endif +#endif +/* MR10 */ }; + + if (InfoT && TnodesAllocated > 0) { + if (TnodesPeak > 10000) { + fprintf(stdout,"\nTree Nodes: peak %dk created %dk lost %d\n", + (TnodesPeak/1000), + (TnodesAllocated/1000), + TnodesInUse-tnodes_used_in_guard_predicates_etc); + } else { + fprintf(stdout,"\nTree Nodes: peak %d created %d lost %d\n", + TnodesPeak, + TnodesAllocated, + TnodesInUse-tnodes_used_in_guard_predicates_etc); + }; + }; + if (InfoF) { + DumpFcache(); + }; + if (MR_skipped_e3_report) { + fprintf(stderr,"note: use -e3 to get exact information on ambiguous tuples\n"); + }; + if (MR_BadExprSets != 0) { + fprintf(stderr,"note: Unreachable C or C++ code was generated for empty expression sets,\n"); + fprintf(stderr," probably due to undefined rules or infinite left recursion.\n"); + fprintf(stderr," To locate: search the generated code for \"empty set expression\"\n"); + }; + if (MR_AmbAidRule != NULL && MR_matched_AmbAidRule==0) { + RuleEntry *q = (RuleEntry *) hash_get(Rname,MR_AmbAidRule); + if (MR_AmbAidLine == 0 && q == NULL) { + warnNoFL(eMsg2("there is no rule \"%s\" so \"-aa %s\" will never match", + MR_AmbAidRule,MR_AmbAidRule)); + } else { + warnNoFL(eMsg1("there was no ambiguity that matched \"-aa %s\"",MR_AmbAidRule)); + }; + }; + if (AlphaBetaTrace) { + + if (MR_AlphaBetaMessageCount == 0) { + fprintf(stderr,"note: there were no messages about \"(alpha)? beta\" blocks added to the generated code\n"); + } else { + fprintf(stderr,"note: there were %d messages about \"(alpha)? beta\" blocks added to the generated code\n", + MR_AlphaBetaMessageCount); + } + + if (set_null(MR_CompromisedRules)) { + fprintf(stderr,"note: the list of rules with compromised follow sets is empty\n"); + } else { + fprintf(stderr,"note: the following is a list of rules which *may* have incorrect\n"); + fprintf(stderr," follow sets computed as a result of an \"(alpha)? beta\" block\n"); + fprintf(stderr,"\n"); + MR_dumpRuleSet(MR_CompromisedRules); + fprintf(stderr,"\n"); + } + } + cleanUp(); + exit(PCCTS_EXIT_SUCCESS); + return 0; /* MR11 make compilers happy */ +} + +static void +#ifdef __USE_PROTOS +init( void ) +#else +init( ) +#endif +{ + SignalEntry *q; + + Tname = newHashTable(); + Rname = newHashTable(); + Fcache = newHashTable(); + Tcache = newHashTable(); + Sname = newHashTable(); + Pname = newHashTable(); /* MR11 */ + + /* Add default signal names */ + q = (SignalEntry *)hash_add(Sname, + "NoViableAlt", + (Entry *)newSignalEntry("NoViableAlt")); + require(q!=NULL, "cannot alloc signal entry"); + q->signum = sigNoViableAlt; + q = (SignalEntry *)hash_add(Sname, + "MismatchedToken", + (Entry *)newSignalEntry("MismatchedToken")); + require(q!=NULL, "cannot alloc signal entry"); + q->signum = sigMismatchedToken; + q = (SignalEntry *)hash_add(Sname, + "NoSemViableAlt", + (Entry *)newSignalEntry("NoSemViableAlt")); + require(q!=NULL, "cannot alloc signal entry"); + q->signum = sigNoSemViableAlt; + + reserved_positions = empty; + all_tokens = empty; + imag_tokens = empty; + tokclasses = empty; + TokenStr = (char **) calloc(TSChunk, sizeof(char *)); + require(TokenStr!=NULL, "main: cannot allocate TokenStr"); + FoStack = (int **) calloc(CLL_k+1, sizeof(int *)); + require(FoStack!=NULL, "main: cannot allocate FoStack"); + FoTOS = (int **) calloc(CLL_k+1, sizeof(int *)); + require(FoTOS!=NULL, "main: cannot allocate FoTOS"); + Cycles = (ListNode **) calloc(CLL_k+1, sizeof(ListNode *)); + require(Cycles!=NULL, "main: cannot allocate Cycles List"); + MR_CompromisedRules=empty; /* MR14 */ +} + +static void +#ifdef __USE_PROTOS +help( void ) +#else +help( ) +#endif +{ + Opt *p = options; + fprintf(stderr, "antlr [options] f1 f2 ... fn\n"); + while ( *(p->option) != '*' ) + { + fprintf(stderr, " %-9s%s %s\n", + p->option, + (p->arg)?"___":" ", + p->descr); + p++; + } +} + +/* The RulePtr array is filled in here. RulePtr exists primarily + * so that sets of rules can be maintained for the FOLLOW caching + * mechanism found in rJunc(). RulePtr maps a rule num from 1 to n + * to a pointer to its RuleBlk junction where n is the number of rules. + */ +static void +#ifdef __USE_PROTOS +buildRulePtr( void ) +#else +buildRulePtr( ) +#endif +{ + int r=1; + Junction *p = SynDiag; + RulePtr = (Junction **) calloc(NumRules+1, sizeof(Junction *)); + require(RulePtr!=NULL, "cannot allocate RulePtr array"); + + while ( p!=NULL ) + { + require(r<=NumRules, "too many rules???"); + RulePtr[r++] = p; + p = (Junction *)p->p2; + } +} + +void +#ifdef __USE_PROTOS +dlgerror(const char *s) +#else +dlgerror(s) +char *s; +#endif +{ + fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); + fprintf(stderr, " lexical error: %s (text was '%s')\n", + ((s == NULL) ? "Lexical error" : s), zzlextext); +} + +void +#ifdef __USE_PROTOS +readDescr( void ) +#else +readDescr( ) +#endif +{ + zzerr = dlgerror; + input = NextFile(); + if ( input==NULL ) fatal("No grammar description found (exiting...)"); + ANTLR(grammar(), input); + tnodes_used_in_guard_predicates_etc=TnodesInUse; /* MR10 */ +} + +FILE * +#ifdef __USE_PROTOS +NextFile( void ) +#else +NextFile( ) +#endif +{ + FILE *f; + + for (;;) + { + CurFile++; + if ( CurFile >= NumFiles ) return(NULL); + if ( ci_strequ(FileStr[CurFile],"stdin")) return stdin; + f = fopen(FileStr[CurFile], "r"); + if ( f == NULL ) + { + warnNoFL( eMsg1("file %s doesn't exist; ignored", FileStr[CurFile]) ); + } + else + { + return(f); + } + } +} + +/* + * Return a string corresponding to the output file name associated + * with the input file name passed in. + * + * Observe the following rules: + * + * f.e --> f".c" + * f --> f".c" + * f. --> f".c" + * f.e.g --> f.e".c" + * + * Where f,e,g are arbitrarily long sequences of characters in a file + * name. + * + * In other words, if a ".x" appears on the end of a file name, make it + * ".c". If no ".x" appears, append ".c" to the end of the file name. + * + * C++ mode using .cpp not .c. + * + * Use malloc() for new string. + */ + +char * +#ifdef __USE_PROTOS +outname( char *fs ) +#else +outname( fs ) +char *fs; +#endif +{ + if ( GenCC) { + return outnameX(fs,CPP_FILE_SUFFIX); + } else { + return outnameX(fs,".c"); + }; +} + +char * +#ifdef __USE_PROTOS +outnameX( char *fs ,char *suffix) +#else +outnameX( fs , suffix ) +char *fs; +char *suffix; +#endif +{ + static char buf[MaxFileName+1]; + char *p; + require(fs!=NULL&&*fs!='\0', "outname: NULL filename"); + + p = buf; + strcpy(buf, fs); + while ( *p != '\0' ) {p++;} /* Stop on '\0' */ + while ( *p != '.' && p != buf ) {--p;} /* Find '.' */ + if ( p != buf ) *p = '\0'; /* Found '.' */ + require(strlen(buf) + 2 < (size_t)MaxFileName, "outname: filename too big"); + strcat(buf,suffix); + return( buf ); +} + +void +#ifdef __USE_PROTOS +fatalFL( char *err_, char *f, int l ) +#else +fatalFL( err_, f, l ) +char *err_; +char *f; +int l; +#endif +{ + fprintf(stderr, ErrHdr, f, l); + fprintf(stderr, " %s\n", err_); + cleanUp(); + exit(PCCTS_EXIT_FAILURE); +} + +void +#ifdef __USE_PROTOS +fatal_intern( char *err_, char *f, int l ) +#else +fatal_intern( err_, f, l ) +char *err_; +char *f; +int l; +#endif +{ + fprintf(stderr, ErrHdr, f, l); + fprintf(stderr, " #$%%*&@# internal error: %s\n", err_); + fprintf(stderr, ErrHdr, f, l); + fprintf(stderr, " [complain to nearest government official\n"); + fprintf(stderr, ErrHdr, f, l); + fprintf(stderr, " or send hate-mail to parrt@parr-research.com;\n"); + fprintf(stderr, ErrHdr, f, l); + fprintf(stderr, " please pray to the ``bug'' gods that there is a trival fix.]\n"); + cleanUp(); + exit(PCCTS_EXIT_FAILURE); +} + +void +#ifdef __USE_PROTOS +cleanUp( void ) +#else +cleanUp( ) +#endif +{ + if ( DefFile != NULL) fclose( DefFile ); +} + +/* sprintf up to 3 strings */ +char * +#ifdef __USE_PROTOS +eMsg3( char *s, char *a1, char *a2, char *a3 ) +#else +eMsg3( s, a1, a2, a3 ) +char *s; +char *a1; +char *a2; +char *a3; +#endif +{ + static char buf[250]; /* DANGEROUS as hell !!!!!! */ + + sprintf(buf, s, a1, a2, a3); + return( buf ); +} + +/* sprintf a decimal */ +char * +#ifdef __USE_PROTOS +eMsgd( char *s, int d ) +#else +eMsgd( s, d ) +char *s; +int d; +#endif +{ + static char buf[250]; /* DANGEROUS as hell !!!!!! */ + + sprintf(buf, s, d); + return( buf ); +} + +char * +#ifdef __USE_PROTOS +eMsgd2( char *s, int d1,int d2) +#else +eMsgd2( s, d1, d2 ) +char *s; +int d1; +int d2; +#endif +{ + static char buf[250]; /* DANGEROUS as hell !!!!!! */ + + sprintf(buf, s, d1, d2); + return( buf ); +} + +void +#ifdef __USE_PROTOS +s_fprT( FILE *f, set e ) +#else +s_fprT( f, e ) +FILE *f; +set e; +#endif +{ + register unsigned *p; + unsigned *q; + + if ( set_nil(e) ) return; + if ( (q=p=set_pdq(e)) == NULL ) fatal_internal("Can't alloc space for set_pdq"); + fprintf(f, "{"); + while ( *p != nil ) + { + fprintf(f, " %s", TerminalString(*p)); + p++; + } + fprintf(f, " }"); + free((char *)q); +} + +/* Return the token name or regular expression for a token number. */ +char * +#ifdef __USE_PROTOS +TerminalString( int token ) +#else +TerminalString( token ) +int token; +#endif +{ + int j; + static char imag_name[20]; + + /* look in all lexclasses for the token */ + if ( TokenString(token) != NULL ) return TokenString(token); + for (j=0; j0, "pushint: stack overflow"); + istack[--isp] = i; +} + +int +#ifdef __USE_PROTOS +popint( void ) +#else +popint( ) +#endif +{ + require(isp 0 ) + { + p = options; + while ( p->option != NULL ) + { + if ( strcmp(p->option, "*") == 0 || + ci_strequ(p->option, *argv) == 1 ) + { + if ( p->arg ) + { +/* MR9 26-Sep-97 Check for argv valid */ + if (argc-- > 0) { + (*p->process)( *argv, *(argv+1) ); + argv++; + } else { +fprintf(stderr,"error: required argument for option %s omitted\n",*argv); +exit(PCCTS_EXIT_FAILURE); + }; + } + else + (*p->process)( *argv ); + break; + } + p++; + } + argv++; + } +} + +static void +#ifdef __USE_PROTOS +CompleteContextGuards(void) +#else +CompleteContextGuards() +#endif +{ + ListNode * p; + Predicate * pred; + + if (ContextGuardPredicateList == NULL) return; + + for (p=ContextGuardPredicateList->next; p != NULL; p=p->next) { + pred=(Predicate *)p->elem; + recomputeContextGuard(pred); + } +} + +/* Go back into the syntax diagram and compute all meta tokens; i.e. + * turn all '.', ranges, token class refs etc... into actual token sets + */ +static void +#ifdef __USE_PROTOS +CompleteTokenSetRefs(void) +#else +CompleteTokenSetRefs() +#endif +{ + ListNode *p; + + if ( MetaTokenNodes==NULL ) return; + for (p = MetaTokenNodes->next; p!=NULL; p=p->next) + { + set a,b; + + TokNode *q = (TokNode *)p->elem; + if ( q->wild_card ) + { + q->tset = all_tokens; + } + else if ( q->tclass!=NULL ) + { + if ( q->complement ) q->tset = set_dif(all_tokens, q->tclass->tset); + else q->tset = q->tclass->tset; + } + else if ( q->upper_range!=0 ) + { + /* we have a range on our hands: make a set from q->token .. q->upper_range */ + int i; + a = empty; + for (i=q->token; i<=q->upper_range; i++) { set_orel(i, &a); } /* MR13 */ + +/* MR13 */ if (q->complement) { +/* MR13 */ q->tset = set_dif(all_tokens, a); +/* MR13 */ set_free(a); +/* MR13 */ } else { +/* MR13 */ q->tset = a; +/* MR13 */ } + + } + + /* at this point, it can only be a complemented single token */ + else if ( q->complement ) + { + a = set_of(q->token); + b = set_dif(all_tokens, a); + set_free(a); + q->tset=b; + } + else fatal("invalid meta token"); + } +} + +/* MR10: Jeff Vincent + MR10: Changed to remove directory information from n only if + MR10: if OutputDirectory was changed by user (-o option) +*/ + +char * +#ifdef __USE_PROTOS +OutMetaName(char *n) +#else +OutMetaName(n) +char *n; +#endif +{ + static char *dir_sym = DirectorySymbol; + static char newname[MaxFileName+1]; + char *p; + + /* If OutputDirectory is same as TopDirectory (platform default) then leave n alone. */ + if (strcmp(OutputDirectory, TopDirectory) == 0) /* TopDirectory is "." on Unix. */ + return n; + + /* p will point to filename without path information */ + if ((p = strrchr(n, *dir_sym)) != NULL) /* Directory symbol is "/" on Unix. */ + p++; + else + p = n; + + /* Copy new output directory into newname[] */ + strcpy(newname, OutputDirectory); + + /* if new output directory does not have trailing dir_sym, add it! */ + if (newname[strlen(newname)-1] != *dir_sym) { + strcat(newname, dir_sym); + } + strcat(newname, p); + return newname; +} + +char * +#ifdef __USE_PROTOS +pcctsBaseName(char *n) /* MR32 */ +#else +pcctsBaseName(n) +char *n; +#endif +{ + static char newname[MaxFileName+1]; + static char* dir_sym = DirectorySymbol; + int count = 0; + char *p; + + p = n; + + while ( *p != '\0' ) {p++;} /* go to end of string */ + while ( (*p != *dir_sym) && (p != n) ) {--p;} /* Find last DirectorySymbol */ + while ( *p == *dir_sym) p++; /* step forward if we're on a dir symbol */ + while ( *p != '\0' && *p != '.') + { + newname[count++] = *p; + p++; + } /* create a new name */ + newname[count] = '\0'; + return newname; +} + +static void +#ifdef __USE_PROTOS +ensure_no_C_file_collisions(char *class_c_file) +#else +ensure_no_C_file_collisions(class_c_file) +char *class_c_file; +#endif +{ + int i; + + for (i=0; i= NumFiles && CurFile >= 1 ) CurFile--; + fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); + fprintf(stderr, " warning: %s\n", err); +} + +void +#ifdef __USE_PROTOS +warnNoCR( char *err ) +#else +warnNoCR( err ) +char *err; +#endif +{ + /* back up the file number if we hit an error at the end of the last file */ + if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--; + fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); + fprintf(stderr, " warning: %s", err); +} + +void +#ifdef __USE_PROTOS +errNoFL(char *err) +#else +errNoFL(err) +char *err; +#endif +{ + fprintf(stderr, "error: %s\n", err); +} + +void +#ifdef __USE_PROTOS +errFL(char *err,char *f,int l) +#else +errFL(err,f,l) +char *err; +char *f; +int l; +#endif +{ + fprintf(stderr, ErrHdr, f, l); + fprintf(stderr, " error: %s\n", err); +} + +void +#ifdef __USE_PROTOS +err(char *err) +#else +err(err) +char *err; +#endif +{ + /* back up the file number if we hit an error at the end of the last file */ + if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--; + fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); + fprintf(stderr, " error: %s\n", err); +} + +void +#ifdef __USE_PROTOS +errNoCR( char *err ) +#else +errNoCR( err ) +char *err; +#endif +{ + /* back up the file number if we hit an error at the end of the last file */ + if ( CurFile >= NumFiles && CurFile >= 1 ) CurFile--; + fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); + fprintf(stderr, " error: %s", err); +} + +UserAction * +#ifdef __USE_PROTOS +newUserAction(char *s) +#else +newUserAction(s) +char *s; +#endif +{ + UserAction *ua = (UserAction *) calloc(1, sizeof(UserAction)); + require(ua!=NULL, "cannot allocate UserAction"); + + ua->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); + strcpy(ua->action, s); + return ua; +} + +/* Added by TJP September 1994 */ +/* Take in file.h and return file_h; names w/o '.'s are left alone */ +char * +#ifdef __USE_PROTOS +gate_symbol(char *name) +#else +gate_symbol(name) +char *name; +#endif +{ + static char buf[100]; + char *p; + sprintf(buf, "%s", name); + + for (p=buf; *p!='\0'; p++) + { + if ( *p=='.' ) *p = '_'; + } + return buf; +} + +char * +#ifdef __USE_PROTOS +makeAltID(int blockid, int altnum) +#else +makeAltID(blockid, altnum) +int blockid; +int altnum; +#endif +{ + static char buf[100]; + char *p; + sprintf(buf, "_blk%d_alt%d", blockid, altnum); + p = (char *)malloc(strlen(buf)+1); + strcpy(p, buf); + return p; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile new file mode 100644 index 00000000..b5b4eb40 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile @@ -0,0 +1,225 @@ +# +# Makefile for ANTLR 1.33 +# +# SOFTWARE RIGHTS +# +# We reserve no LEGAL rights to the Purdue Compiler Construction Tool +# Set (PCCTS) -- PCCTS is in the public domain. An individual or +# company may do whatever they wish with source code distributed with +# PCCTS or the code generated by PCCTS, including the incorporation of +# PCCTS, or its output, into commerical software. +# +# We encourage users to develop software with PCCTS. However, we do ask +# that credit is given to us for developing PCCTS. By "credit", +# we mean that if you incorporate our source code into one of your +# programs (commercial product, research project, or otherwise) that you +# acknowledge this fact somewhere in the documentation, research report, +# etc... If you like PCCTS and have developed a nice tool with the +# output, please mention that you developed it using PCCTS. In +# addition, we ask that this header remain intact in our source code. +# As long as these guidelines are kept, we expect to continue enhancing +# this system and expect to make other tools available as they are +# completed. +# +# ANTLR 1.33 +# Terence Parr +# Parr Research Corporation +# with Purdue University +# and AHPCRC, University of Minnesota +# 1989-1995 +# +# Ported to Borland C++, IBM C-Set/2 and Microsoft 6.0 by +# Ed Harfmann +# Micro Data Base Systems +# Lafayette, Indiana +# +SET=../support/set +PCCTS_H=../h + +## +## Uncomment the appropriate section to build +## (both targets and 'make' variable definitions) +## Note that UNIX is the default +## + +# +# OS/2 & DOS 16 bit using MSC 6.0 +# +#CC=cl +#ANTLR=..\bin\antlr +#DLG=..\bin\dlg +#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /AL /Za /W3 -DPC -DUSER_ZZSYN +#OUT_OBJ = -Fo +#LIBS=/NOD:LLIBCE LLIBCEP +#OBJ_EXT = obj +# +#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \ +# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \ +# misc.obj set.obj pred.obj egamn.obj +# link @<< +#$** /NOI +#$@ /STACK:14336 +# +#$(LIBS: = +^ +#) +#$(DEF_FILE) $(LFLAGS) ; +#<< +# bind $@ c:\os2\doscalls.lib +# copy *.exe ..\bin +# + +# +# Borland C++ for DOS +# +#CC=bcc +#ANTLR=..\bin\antlr +#DLG=..\bin\dlg +#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -ml -ff- -w- -DPC -DUSER_ZZSYN +#OUT_OBJ = -o +#LIBS= emu mathl cl +#OBJ_EXT = obj +# +#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \ +# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \ +# misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj +# tlink @&&| +#C0L $** +#$@ /Tde /c +# +#$(LIBS) +#$(DEF_FILE) $(LFLAGS) ; +#| +# copy *.exe ..\bin +# + +# +# C-Set/2 for OS/2 +# +#CC=icc +#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /Sa /W3 -DUSER_ZZSYN -D__STDC__ +#OUT_OBJ = -Fo +#LIBS= +#ANTLR=..\bin\antlr +#DLG=..\bin\dlg +#OBJ_EXT = obj +# +#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \ +# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \ +# misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj +# link386 @<< +#$** /NOI +#$@ /STACK:32768 +# +#$(LIBS: = +^ +#) +#$(DEF_FILE) $(LFLAGS) ; +#<< +# copy *.exe ..\bin +# + +# +# Borland C++ for OS/2 +# +#CC=bcc +#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -w- -v -DUSER_ZZSYN +#OUT_OBJ = -o +#LIBS= c2 os2 +# +#ANTLR=..\bin\antlr +#DLG=..\bin\dlg +#OBJ_EXT = obj +#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \ +# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \ +# misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj +# tlink @&&| +#c02 $** -c -v +#antlr.exe +# +#C2 os2 +# +#| +# copy *.exe ..\bin +# + +# *********** Target list of PC machines *********** +# +# Don't worry about the ambiguity messages coming from antlr +# for making antlr.c etc... [should be 10 of them, I think] +# +#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g +# $(ANTLR) antlr.g +# +#antlr.$(OBJ_EXT): antlr.c mode.h tokens.h +# +#scan.$(OBJ_EXT): scan.c mode.h tokens.h +# +#scan.c mode.h: parser.dlg +# $(DLG) -C2 parser.dlg scan.c +# +#set.$(OBJ_EXT): $(SET)/set.c +# $(BUILD_CC) $(BUILD_CFLAGS) -c $(OUT_OBJ)set.$(OBJ_EXT) $(SET)/set.c + + + +# +# UNIX (default) +# +ifeq ($(CXX), llvm) +BUILD_CC?=$(CLANG_BIN)clang +else +BUILD_CC?=gcc +endif +COPT=-O +ANTLR=${BIN_DIR}/antlr +DLG=${BIN_DIR}/dlg +OBJ_EXT=o +OUT_OBJ = -o +BUILD_CFLAGS= $(COPT) -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN $(COTHER) -DZZLEXBUFSIZE=65536 +BUILD_CPPFLAGS= +# +# SGI Users, use this CFLAGS +# +#CFLAGS= -O -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN -woff 3262 +OBJ=antlr.o scan.o err.o bits.o build.o fset2.o fset.o gen.o \ + globals.o hash.o lex.o main.o misc.o set.o pred.o egman.o mrhoist.o fcache.o + +$(BIN_DIR)/antlr : $(OBJ) $(SRC) + $(BUILD_CC) $(BUILD_CFLAGS) -o $(BIN_DIR)/antlr $(OBJ) + +# what files does PCCTS generate (both ANTLR and DLG) +PCCTS_GEN=antlr.c scan.c err.c tokens.h mode.h parser.dlg stdpccts.h remap.h + +SRC=antlr.c scan.c err.c bits.c build.c fset2.c fset.c gen.c globals.c \ + hash.c lex.c main.c misc.c $(SET)/set.c pred.c egman.c mrhoist.c fcache.c + +# +# Don't worry about the ambiguity messages coming from antlr +# for making antlr.c etc... [should be 10 of them, I think] +# +#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g +# $(ANTLR) -gh antlr.g + +antlr.o : antlr.c mode.h tokens.h + +scan.o : scan.c mode.h tokens.h + +#scan.c mode.h: parser.dlg +# $(DLG) -C2 parser.dlg scan.c + +set.o : $(SET)/set.c + $(BUILD_CC) $(BUILD_CFLAGS) -c -o set.o $(SET)/set.c + +%.o : %.c + $(BUILD_CC) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) $< -o $@ + +# +# ****** These next targets are common to UNIX and PC world ******** +# + +#clean up all the intermediate files +clean: + rm -f $(BIN_DIR)/antlr *.$(OBJ_EXT) core + +#remove everything in clean plus the PCCTS files generated +scrub: + rm -f $(PCCTS_GEN) *.$(OBJ_EXT) core diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile.cygwin b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile.cygwin new file mode 100644 index 00000000..3e9cb5a9 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile.cygwin @@ -0,0 +1,219 @@ +# +# Makefile for ANTLR 1.33 +# +# SOFTWARE RIGHTS +# +# We reserve no LEGAL rights to the Purdue Compiler Construction Tool +# Set (PCCTS) -- PCCTS is in the public domain. An individual or +# company may do whatever they wish with source code distributed with +# PCCTS or the code generated by PCCTS, including the incorporation of +# PCCTS, or its output, into commerical software. +# +# We encourage users to develop software with PCCTS. However, we do ask +# that credit is given to us for developing PCCTS. By "credit", +# we mean that if you incorporate our source code into one of your +# programs (commercial product, research project, or otherwise) that you +# acknowledge this fact somewhere in the documentation, research report, +# etc... If you like PCCTS and have developed a nice tool with the +# output, please mention that you developed it using PCCTS. In +# addition, we ask that this header remain intact in our source code. +# As long as these guidelines are kept, we expect to continue enhancing +# this system and expect to make other tools available as they are +# completed. +# +# ANTLR 1.33 +# Terence Parr +# Parr Research Corporation +# with Purdue University +# and AHPCRC, University of Minnesota +# 1989-1995 +# +# Ported to Borland C++, IBM C-Set/2 and Microsoft 6.0 by +# Ed Harfmann +# Micro Data Base Systems +# Lafayette, Indiana +# +SET=../support/set +PCCTS_H=../h + +## +## Uncomment the appropriate section to build +## (both targets and 'make' variable definitions) +## Note that UNIX is the default +## + +# +# OS/2 & DOS 16 bit using MSC 6.0 +# +#CC=cl +#ANTLR=..\bin\antlr +#DLG=..\bin\dlg +#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /AL /Za /W3 -DPC -DUSER_ZZSYN +#OUT_OBJ = -Fo +#LIBS=/NOD:LLIBCE LLIBCEP +#OBJ_EXT = obj +# +#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \ +# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \ +# misc.obj set.obj pred.obj egamn.obj +# link @<< +#$** /NOI +#$@ /STACK:14336 +# +#$(LIBS: = +^ +#) +#$(DEF_FILE) $(LFLAGS) ; +#<< +# bind $@ c:\os2\doscalls.lib +# copy *.exe ..\bin +# + +# +# Borland C++ for DOS +# +#CC=bcc +#ANTLR=..\bin\antlr +#DLG=..\bin\dlg +#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -ml -ff- -w- -DPC -DUSER_ZZSYN +#OUT_OBJ = -o +#LIBS= emu mathl cl +#OBJ_EXT = obj +# +#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \ +# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \ +# misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj +# tlink @&&| +#C0L $** +#$@ /Tde /c +# +#$(LIBS) +#$(DEF_FILE) $(LFLAGS) ; +#| +# copy *.exe ..\bin +# + +# +# C-Set/2 for OS/2 +# +#CC=icc +#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) /Sa /W3 -DUSER_ZZSYN -D__STDC__ +#OUT_OBJ = -Fo +#LIBS= +#ANTLR=..\bin\antlr +#DLG=..\bin\dlg +#OBJ_EXT = obj +# +#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \ +# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \ +# misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj +# link386 @<< +#$** /NOI +#$@ /STACK:32768 +# +#$(LIBS: = +^ +#) +#$(DEF_FILE) $(LFLAGS) ; +#<< +# copy *.exe ..\bin +# + +# +# Borland C++ for OS/2 +# +#CC=bcc +#CFLAGS= -I. -I$(SET) -I$(PCCTS_H) -w- -v -DUSER_ZZSYN +#OUT_OBJ = -o +#LIBS= c2 os2 +# +#ANTLR=..\bin\antlr +#DLG=..\bin\dlg +#OBJ_EXT = obj +#antlr.exe: antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj \ +# fset.obj gen.obj globals.obj hash.obj lex.obj main.obj \ +# misc.obj set.obj pred.obj egman.obj mrhoist.obj fcache.obj +# tlink @&&| +#c02 $** -c -v +#antlr.exe +# +#C2 os2 +# +#| +# copy *.exe ..\bin +# + +# *********** Target list of PC machines *********** +# +# Don't worry about the ambiguity messages coming from antlr +# for making antlr.c etc... [should be 10 of them, I think] +# +#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g +# $(ANTLR) antlr.g +# +#antlr.$(OBJ_EXT): antlr.c mode.h tokens.h +# +#scan.$(OBJ_EXT): scan.c mode.h tokens.h +# +#scan.c mode.h: parser.dlg +# $(DLG) -C2 parser.dlg scan.c +# +#set.$(OBJ_EXT): $(SET)/set.c +# $(CC) $(CFLAGS) -c $(OUT_OBJ)set.$(OBJ_EXT) $(SET)/set.c + + + +# +# UNIX (default) +# +BIN_DIR=../../../../bin +CC=gcc +COPT=-O +ANTLR=$(BIN_DIR)/antlr.exe +DLG=${BIN_DIR}/dlg.exe +OBJ_EXT=o +OUT_OBJ = -o +CFLAGS= $(COPT) -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN $(COTHER) -DZZLEXBUFSIZE=65536 +# +# SGI Users, use this CFLAGS +# +#CFLAGS= -O -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN -woff 3262 +OBJ=antlr.o scan.o err.o bits.o build.o fset2.o fset.o gen.o \ + globals.o hash.o lex.o main.o misc.o set.o pred.o egman.o mrhoist.o fcache.o + +antlr : $(OBJ) $(SRC) + $(CC) $(CFLAGS) -o $(BIN_DIR)/antlr.exe $(OBJ) + +# what files does PCCTS generate (both ANTLR and DLG) +PCCTS_GEN=antlr.c scan.c err.c tokens.h mode.h parser.dlg stdpccts.h remap.h + +SRC=antlr.c scan.c err.c bits.c build.c fset2.c fset.c gen.c globals.c \ + hash.c lex.c main.c misc.c $(SET)/set.c pred.c egman.c mrhoist.c fcache.c + +# +# Don't worry about the ambiguity messages coming from antlr +# for making antlr.c etc... [should be 10 of them, I think] +# +#antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g +# $(ANTLR) -gh antlr.g + +antlr.o : antlr.c mode.h tokens.h + +scan.o : scan.c mode.h tokens.h + +#scan.c mode.h: parser.dlg +# $(DLG) -C2 parser.dlg scan.c + +set.o : $(SET)/set.c + $(CC) $(CFLAGS) -c -o set.o $(SET)/set.c + + +# +# ****** These next targets are common to UNIX and PC world ******** +# + +#clean up all the intermediate files +clean: + rm -f *.$(OBJ_EXT) core + +#remove everything in clean plus the PCCTS files generated +scrub: + rm -f $(PCCTS_GEN) *.$(OBJ_EXT) core diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile1 b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile1 new file mode 100644 index 00000000..f17a6927 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/makefile1 @@ -0,0 +1,96 @@ +# +# Makefile for ANTLR 1.33 +# +# SOFTWARE RIGHTS +# +# We reserve no LEGAL rights to the Purdue Compiler Construction Tool +# Set (PCCTS) -- PCCTS is in the public domain. An individual or +# company may do whatever they wish with source code distributed with +# PCCTS or the code generated by PCCTS, including the incorporation of +# PCCTS, or its output, into commerical software. +# +# We encourage users to develop software with PCCTS. However, we do ask +# that credit is given to us for developing PCCTS. By "credit", +# we mean that if you incorporate our source code into one of your +# programs (commercial product, research project, or otherwise) that you +# acknowledge this fact somewhere in the documentation, research report, +# etc... If you like PCCTS and have developed a nice tool with the +# output, please mention that you developed it using PCCTS. In +# addition, we ask that this header remain intact in our source code. +# As long as these guidelines are kept, we expect to continue enhancing +# this system and expect to make other tools available as they are +# completed. +# +# ANTLR 1.33 +# Terence Parr +# Parr Research Corporation +# with Purdue University +# and AHPCRC, University of Minnesota +# 1989-1995 +# +# Ported to Borland C++, IBM C-Set/2 and Microsoft 6.0 by +# Ed Harfmann +# Micro Data Base Systems +# Lafayette, Indiana +# +SET=../support/set +PCCTS_H=../h + +# +# UNIX (default) +# +CC=cc +ANTLR=${WORKSPACE}/Tools/bin/antlr +DLG=${WORKSPACE}/Tools/bin/dlg +OBJ_EXT=o +OUT_OBJ = -o +ANSI=-ansi +AOTHER= +CFLAGS= -O0 -g -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN $(COTHER) $(ANSI) -DZZLEXBUFSIZE=32000 +# +# SGI Users, use this CFLAGS +# +#CFLAGS= -O -I. -I$(SET) -I$(PCCTS_H) -DUSER_ZZSYN -woff 3262 + +OBJ=antlr.o scan.o err.o bits.o build.o fset2.o fset.o gen.o \ + globals.o hash.o lex.o main.o misc.o set.o pred.o egman.o mrhoist.o fcache.o $(OBJOTHER) + +antlr : $(OBJ) $(SRC) + $(CC) $(CFLAGS) -o antlr $(OBJ) + mv antlr ${WORKSPACE}/Tools/bin + +# what files does PCCTS generate (both ANTLR and DLG) +PCCTS_GEN=antlr.c scan.c err.c tokens.h mode.h parser.dlg stdpccts.h remap.h + +SRC=antlr.c scan.c err.c bits.c build.c fset2.c fset.c gen.c globals.c \ + hash.c lex.c main.c misc.c $(SET)/set.c pred.c egman.c mrhoist.c fcache.c + +# +# Don't worry about the ambiguity messages coming from antlr +# for making antlr.c etc... [should be 10 of them, I think] +# +antlr.c stdpccts.h parser.dlg tokens.h err.c : antlr.g + $(ANTLR) -gh antlr.g $(AOTHER) + +antlr.o : antlr.c mode.h tokens.h + +scan.o : scan.c mode.h tokens.h + +scan.c mode.h: parser.dlg + $(DLG) -C2 parser.dlg scan.c + +set.o : $(SET)/set.c + $(CC) $(CFLAGS) -c -o set.o $(SET)/set.c + + +# +# ****** These next targets are common to UNIX and PC world ******** +# + +#clean up all the intermediate files +clean: + rm -f *.$(OBJ_EXT) core + +#remove everything in clean plus the PCCTS files generated +scrub: + rm -f $(PCCTS_GEN) *.$(OBJ_EXT) core diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/misc.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/misc.c new file mode 100644 index 00000000..eef73e64 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/misc.c @@ -0,0 +1,1864 @@ +/* + * misc.c + * + * Manage tokens, regular expressions. + * Print methods for debugging + * Compute follow lists onto tail ends of rules. + * + * The following functions are visible: + * + * int addTname(char *); Add token name + * int addTexpr(char *); Add token expression + * int Tnum(char *); Get number of expr/token + * void Tklink(char *, char *); Link a name with an expression + * int hasAction(expr); Does expr already have action assigned? + * void setHasAction(expr); Indicate that expr now has an action + * Entry *newEntry(char *,int); Create new table entry with certain size + * void list_add(ListNode **list, char *e) + * void list_free(ListNode **list, int freeData); *** MR10 *** + * void list_apply(ListNode *list, void (*f)()) + * void lexclass(char *m); switch to new/old lexical class + * void lexmode(int i); switch to old lexical class i + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include "pcctscfg.h" +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" +#include + +static int tsize=TSChunk; /* size of token str arrays */ + +static void +#ifdef __USE_PROTOS +RemapForcedTokensInSyntaxDiagram(Node *); +#else +RemapForcedTokensInSyntaxDiagram(); +#endif + + /* T o k e n M a n i p u l a t i o n */ + +/* + * add token 't' to the TokenStr/Expr array. Make more room if necessary. + * 't' is either an expression or a token name. + * + * There is only one TokenStr array, but multiple ExprStr's. Therefore, + * for each lex class (element of lclass) we must extend the ExprStr array. + * ExprStr's and TokenStr are always all the same size. + * + * Also, there is a Texpr hash table for each automaton. + */ +static void +#ifdef __USE_PROTOS +Ttrack( char *t ) +#else +Ttrack( t ) +char *t; +#endif +{ + if ( TokenNum >= tsize ) /* terminal table overflow? */ + { + char **p; + int i, more, j; + + more = TSChunk * (1 + ((TokenNum-tsize) / TSChunk)); + tsize += more; + TokenStr = (char **) realloc((char *)TokenStr, tsize*sizeof(char *)); + require(TokenStr != NULL, "Ttrack: can't extend TokenStr"); + for (i=0; iexpr = e; + p->lclass = CurrentLexClass; + return p; +} + +/* switch to lexical class/mode m. This amounts to creating a new + * lex mode if one does not already exist and making ExprStr point + * to the correct char string array. We must also switch Texpr tables. + * + * BTW, we need multiple ExprStr arrays because more than one automaton + * may have the same label for a token, but with different expressions. + * We need to track an expr for each automaton. If we disallowed this + * feature, only one ExprStr would be required. + */ +void +#ifdef __USE_PROTOS +lexclass( char *m ) +#else +lexclass( m ) +char *m; +#endif +{ + int i; + TermEntry *p; + static char EOFSTR[] = "\"@\""; + + if ( hash_get(Tname, m) != NULL ) + { + warn(eMsg1("lexclass name conflicts with token/errclass label '%s'",m)); + } + /* does m already exist? */ + i = LexClassIndex(m); + if ( i != -1 ) {lexmode(i); return;} + /* must make new one */ + NumLexClasses++; + CurrentLexClass = NumLexClasses-1; + require(NumLexClasses<=MaxLexClasses, "number of allowable lexclasses exceeded\nIncrease MaxLexClasses in generic.h and recompile all C files"); + lclass[CurrentLexClass].classnum = m; + lclass[CurrentLexClass].exprs = (char **) calloc(tsize, sizeof(char *)); + require(lclass[CurrentLexClass].exprs!=NULL, + "lexclass: cannot allocate ExprStr"); + lclass[CurrentLexClass].htable = newHashTable(); + ExprStr = lclass[CurrentLexClass].exprs; + Texpr = lclass[CurrentLexClass].htable; + /* define EOF for each automaton */ + p = newTermEntry( EOFSTR ); + p->token = EofToken; /* couldn't have remapped tokens yet, use EofToken */ + hash_add(Texpr, EOFSTR, (Entry *)p); + list_add(&ExprOrder, (void *)newExpr(EOFSTR)); + /* note: we use the actual ExprStr array + * here as TokenInd doesn't exist yet + */ + ExprStr[EofToken] = EOFSTR; +} + +void +#ifdef __USE_PROTOS +lexmode( int i ) +#else +lexmode( i ) +int i; +#endif +{ + require(iaction!=NULL); +} + +void +#ifdef __USE_PROTOS +setHasAction( char *expr, char *action ) +#else +setHasAction( expr, action ) +char *expr; +char *action; +#endif +{ + TermEntry *p; + require(expr!=NULL, "setHasAction: invalid expr"); + + p = (TermEntry *) hash_get(Texpr, expr); + require(p!=NULL, eMsg1("setHasAction: expr '%s' doesn't exist",expr)); + p->action = action; +} + +ForcedToken * +#ifdef __USE_PROTOS +newForcedToken(char *token, int tnum) +#else +newForcedToken(token, tnum) +char *token; +int tnum; +#endif +{ + ForcedToken *ft = (ForcedToken *) calloc(1, sizeof(ForcedToken)); + require(ft!=NULL, "out of memory"); + ft->token = token; + ft->tnum = tnum; + return ft; +} + +/* + * Make a token indirection array that remaps token numbers and then walk + * the appropriate symbol tables and SynDiag to change token numbers + */ +void +#ifdef __USE_PROTOS +RemapForcedTokens(void) +#else +RemapForcedTokens() +#endif +{ + ListNode *p; + ForcedToken *q; + int max_token_number=0; /* MR9 23-Sep-97 Removed "unsigned" */ + int i; + + if ( ForcedTokens == NULL ) return; + + /* find max token num */ + for (p = ForcedTokens->next; p!=NULL; p=p->next) + { + q = (ForcedToken *) p->elem; + if ( q->tnum > max_token_number ) max_token_number = q->tnum; + } + fprintf(stderr, "max token number is %d\n", max_token_number); + + /* make token indirection array */ + TokenInd = (int *) calloc(max_token_number+1, sizeof(int)); + LastTokenCounted = TokenNum; + TokenNum = max_token_number+1; + require(TokenInd!=NULL, "RemapForcedTokens: cannot allocate TokenInd"); + + /* fill token indirection array and change token id htable ; swap token indices */ + for (i=1; inext; p!=NULL; p=p->next) + { + TermEntry *te; + int old_pos, t; + + q = (ForcedToken *) p->elem; + fprintf(stderr, "%s forced to %d\n", q->token, q->tnum); + te = (TermEntry *) hash_get(Tname, q->token); + require(te!=NULL, "RemapForcedTokens: token not in hash table"); + old_pos = te->token; + fprintf(stderr, "Before: TokenInd[old_pos==%d] is %d\n", old_pos, TokenInd[old_pos]); + fprintf(stderr, "Before: TokenInd[target==%d] is %d\n", q->tnum, TokenInd[q->tnum]); + q = (ForcedToken *) p->elem; + t = TokenInd[old_pos]; + TokenInd[old_pos] = q->tnum; + TokenInd[q->tnum] = t; + te->token = q->tnum; /* update token type id symbol table */ + fprintf(stderr, "After: TokenInd[old_pos==%d] is %d\n", old_pos, TokenInd[old_pos]); + fprintf(stderr, "After: TokenInd[target==%d] is %d\n", q->tnum, TokenInd[q->tnum]); + + /* Change the token number in the sym tab entry for the exprs + * at the old position of the token id and the target position + */ + /* update expr at target (if any) of forced token id */ + if ( q->tnum < TokenNum ) /* is it a valid position? */ + { + for (i=0; itnum]!=NULL ) + { + /* update the symbol table for this expr */ + TermEntry *e = (TermEntry *) hash_get(lclass[i].htable, lclass[i].exprs[q->tnum]); + require(e!=NULL, "RemapForcedTokens: expr not in hash table"); + e->token = old_pos; + fprintf(stderr, "found expr '%s' at target %d in lclass[%d]; changed to %d\n", + lclass[i].exprs[q->tnum], q->tnum, i, old_pos); + } + } + } + /* update expr at old position (if any) of forced token id */ + for (i=0; itoken = q->tnum; + fprintf(stderr, "found expr '%s' for id %s in lclass[%d]; changed to %d\n", + lclass[i].exprs[old_pos], q->token, i, q->tnum); + } + } + } + + /* Update SynDiag */ + RemapForcedTokensInSyntaxDiagram((Node *)SynDiag); +} + +static void +#ifdef __USE_PROTOS +RemapForcedTokensInSyntaxDiagram(Node *p) +#else +RemapForcedTokensInSyntaxDiagram(p) +Node *p; +#endif +{ + Junction *j = (Junction *) p; + RuleRefNode *r = (RuleRefNode *) p; + TokNode *t = (TokNode *)p; + + if ( p==NULL ) return; + require(p->ntype>=1 && p->ntype<=NumNodeTypes, "Remap...: invalid diagram node"); + switch ( p->ntype ) + { + case nJunction : + if ( j->visited ) return; + if ( j->jtype == EndRule ) return; + j->visited = TRUE; + RemapForcedTokensInSyntaxDiagram( j->p1 ); + RemapForcedTokensInSyntaxDiagram( j->p2 ); + j->visited = FALSE; + return; + case nRuleRef : + RemapForcedTokensInSyntaxDiagram( r->next ); + return; + case nToken : + if ( t->remapped ) return; /* we've been here before */ + t->remapped = 1; + fprintf(stderr, "remapping %d to %d\n", t->token, TokenInd[t->token]); + t->token = TokenInd[t->token]; + RemapForcedTokensInSyntaxDiagram( t->next ); + return; + case nAction : + RemapForcedTokensInSyntaxDiagram( ((ActionNode *)p)->next ); + return; + default : + fatal_internal("invalid node type"); + } +} + +/* + * Add a token name. Return the token number associated with it. If it already + * exists, then return the token number assigned to it. + * + * Track the order in which tokens are found so that the DLG output maintains + * that order. It also lets us map token numbers to strings. + */ +int +#ifdef __USE_PROTOS +addTname( char *token ) +#else +addTname( token ) +char *token; +#endif +{ + TermEntry *p; + require(token!=NULL, "addTname: invalid token name"); + + if ( (p=(TermEntry *)hash_get(Tname, token)) != NULL ) return p->token; + p = newTermEntry( token ); + Ttrack( p->str ); + p->token = TokenNum++; + hash_add(Tname, token, (Entry *)p); + return p->token; +} + +/* This is the same as addTname except we force the TokenNum to be tnum. + * We don't have to use the Forced token stuff as no tokens will have + * been defined with #tokens when this is called. This is only called + * when a #tokdefs meta-op is used. + */ +int +#ifdef __USE_PROTOS +addForcedTname( char *token, int tnum ) +#else +addForcedTname( token, tnum ) +char *token; +int tnum; +#endif +{ + TermEntry *p; + require(token!=NULL, "addTname: invalid token name"); + + if ( (p=(TermEntry *)hash_get(Tname, token)) != NULL ) return p->token; + p = newTermEntry( token ); + Ttrack( p->str ); + p->token = tnum; + hash_add(Tname, token, (Entry *)p); + return p->token; +} + +/* + * Add a token expr. Return the token number associated with it. If it already + * exists, then return the token number assigned to it. + */ +int +#ifdef __USE_PROTOS +addTexpr( char *expr ) +#else +addTexpr( expr ) +char *expr; +#endif +{ + TermEntry *p; + require(expr!=NULL, "addTexpr: invalid regular expression"); + + if ( (p=(TermEntry *)hash_get(Texpr, expr)) != NULL ) return p->token; + p = newTermEntry( expr ); + Ttrack( p->str ); + /* track the order in which they occur */ + list_add(&ExprOrder, (void *)newExpr(p->str)); + p->token = TokenNum++; + hash_add(Texpr, expr, (Entry *)p); + return p->token; +} + +/* return the token number of 'term'. Return 0 if no 'term' exists */ +int +#ifdef __USE_PROTOS +Tnum( char *term ) +#else +Tnum( term ) +char *term; +#endif +{ + TermEntry *p; + require(term!=NULL, "Tnum: invalid terminal"); + + if ( *term=='"' ) p = (TermEntry *) hash_get(Texpr, term); + else p = (TermEntry *) hash_get(Tname, term); + if ( p == NULL ) return 0; + else return p->token; +} + +/* associate a Name with an expr. If both have been already assigned + * token numbers, then an error is reported. Add the token or expr + * that has not been added if no error. This 'represents' the #token + * ANTLR pseudo-op. If both have not been defined, define them both + * linked to same token number. + */ +void +#ifdef __USE_PROTOS +Tklink( char *token, char *expr ) +#else +Tklink( token, expr ) +char *token; +char *expr; +#endif +{ + TermEntry *p, *q; + require(token!=NULL && expr!=NULL, "Tklink: invalid token name and/or expr"); + + p = (TermEntry *) hash_get(Tname, token); + q = (TermEntry *) hash_get(Texpr, expr); + if ( p != NULL && q != NULL ) /* both defined */ + { + warn( eMsg2("token name %s and rexpr %s already defined; ignored", + token, expr) ); + return; + } + if ( p==NULL && q==NULL ) /* both not defined */ + { + int t = addTname( token ); + q = newTermEntry( expr ); + hash_add(Texpr, expr, (Entry *)q); + q->token = t; + /* note: we use the actual ExprStr array + * here as TokenInd doesn't exist yet + */ + ExprStr[t] = q->str; + /* track the order in which they occur */ + list_add(&ExprOrder, (void *)newExpr(q->str)); + return; + } + if ( p != NULL ) /* one is defined, one is not */ + { + q = newTermEntry( expr ); + hash_add(Texpr, expr, (Entry *)q); + q->token = p->token; + ExprStr[p->token] = q->str; /* both expr and token str defined now */ + list_add(&ExprOrder, (void *)newExpr(q->str)); + } + else /* trying to associate name with expr here*/ + { + p = newTermEntry( token ); + hash_add(Tname, token, (Entry *)p); + p->token = q->token; + TokenStr[p->token] = p->str;/* both expr and token str defined now */ + } +} + +/* + * Given a string, this function allocates and returns a pointer to a + * hash table record of size 'sz' whose "str" pointer is reset to a position + * in the string table. + */ +Entry * +#ifdef __USE_PROTOS +newEntry( char *text, int sz ) +#else +newEntry( text, sz ) +char *text; +int sz; +#endif +{ + Entry *p; + require(text!=NULL, "new: NULL terminal"); + + if ( (p = (Entry *) calloc(1,sz)) == 0 ) + { + fatal_internal("newEntry: out of memory for terminals\n"); + exit(PCCTS_EXIT_FAILURE); + } + p->str = mystrdup(text); + + return(p); +} + +/* + * add an element to a list. + * + * Any non-empty list has a sentinel node whose 'elem' pointer is really + * a pointer to the last element. (i.e. length(list) = #elemIn(list)+1). + * Elements are appended to the list. + */ +void +#ifdef __USE_PROTOS +list_add( ListNode **list, void *e ) +#else +list_add( list, e ) +ListNode **list; +void *e; +#endif +{ + ListNode *p, *tail; + require(e!=NULL, "list_add: attempting to add NULL list element"); + + p = newListNode; + require(p!=NULL, "list_add: cannot alloc new list node"); + p->elem = e; + if ( *list == NULL ) + { + ListNode *sentinel = newListNode; + require(sentinel!=NULL, "list_add: cannot alloc sentinel node"); + *list=sentinel; + sentinel->next = p; + sentinel->elem = (char *)p; /* set tail pointer */ + } + else /* find end of list */ + { + tail = (ListNode *) (*list)->elem; /* get tail pointer */ + tail->next = p; + (*list)->elem = (char *) p; /* reset tail */ + } +} + +/* MR10 list_free() frees the ListNode elements in the list */ +/* MR10 if freeData then free the data elements of the list too */ + +void +#ifdef __USE_PROTOS +list_free(ListNode **list,int freeData) +#else +list_free(list,freeData) + ListNode **list; + int freeData; +#endif +{ + ListNode *p; + ListNode *next; + + if (list == NULL) return; + if (*list == NULL) return; + for (p=*list; p != NULL; p=next) { + next=p->next; + if (freeData && p->elem != NULL) { + free( (char *) p->elem); + }; + free( (char *) p); + }; + *list=NULL; +} + +void +#ifdef __USE_PROTOS +list_apply( ListNode *list, void (*f)(void *) ) +#else +list_apply( list, f ) +ListNode *list; +void (*f)(); +#endif +{ + ListNode *p; + require(f!=NULL, "list_apply: NULL function to apply"); + + if ( list == NULL ) return; + for (p = list->next; p!=NULL; p=p->next) (*f)( p->elem ); +} + +/* MR27 */ + +#ifdef __USE_PROTOS +int list_search_cstring(ListNode *list, char * cstring) +#else +int list_search_cstring(list, cstring) + ListNode * list; + char * cstring; +#endif +{ + ListNode *p; + if (list == NULL ) return 0; + for (p = list->next; p!=NULL; p=p->next) { + if (p->elem == NULL) continue; + if (0 == strcmp((char *) p->elem , cstring)) return 1; + } + return 0; +} + + /* F O L L O W C y c l e S t u f f */ + +/* make a key based upon (rulename, computation, k value). + * Computation values are 'i'==FIRST, 'o'==FOLLOW. + */ + +/* MR10 Make the key all characters so it can be read easily */ +/* MR10 by a simple dump program. Also, separates */ +/* MR10 'o' and 'i' from rule name */ + +char * +#ifdef __USE_PROTOS +Fkey( char *rule, int computation, int k ) +#else +Fkey( rule, computation, k ) +char *rule; +int computation; +int k; +#endif +{ + static char key[MaxRuleName+2+2+1]; /* MR10 */ + int i; + + if ( k > 99 ) /* MR10 */ + fatal("k>99 is too big for this implementation of ANTLR!\n"); /* MR10 */ + if ( (i=strlen(rule)) > MaxRuleName ) /* MR10 */ + fatal( eMsgd("rule name > max of %d\n", MaxRuleName) ); /* MR10 */ + strcpy(key,rule); + +/* MR10 */ key[i]='*'; +/* MR10 */ key[i+1] = (char) computation; /* MR20 G. Hobbelt */ +/* MR10 */ if (k < 10) { +/* MR10 */ key[i+2] = (char) ( '0' + k); +/* MR10 */ key[i+3] = '\0'; +/* MR10 */ } else { +/* MR10 */ key[i+2] = (char) ( '0' + k/10); +/* MR10 */ key[i+3] = (char) ( '0' + k % 10); +/* MR10 */ key[i+4] = '\0'; +/* MR10 */ }; + + return key; +} + +/* Push a rule onto the kth FOLLOW stack */ +void +#ifdef __USE_PROTOS +FoPush( char *rule, int k ) +#else +FoPush( rule, k ) +char *rule; +int k; +#endif +{ + RuleEntry *r; + require(rule!=NULL, "FoPush: tried to push NULL rule"); + require(k<=CLL_k, "FoPush: tried to access non-existent stack"); + + /*fprintf(stderr, "FoPush(%s)\n", rule);*/ + r = (RuleEntry *) hash_get(Rname, rule); + if ( r == NULL ) {fatal_internal( eMsg1("rule %s must be defined but isn't", rule) );} + if ( FoStack[k] == NULL ) /* Does the kth stack exist yet? */ + { + /*fprintf(stderr, "allocating FoStack\n");*/ + FoStack[k] = (int *) calloc(FoStackSize, sizeof(int)); + require(FoStack[k]!=NULL, "FoPush: cannot allocate FOLLOW stack\n"); + } + if ( FoTOS[k] == NULL ) + { + FoTOS[k]=FoStack[k]; + *(FoTOS[k]) = r->rulenum; + } + else + { +#ifdef MEMCHK + require(valid(FoStack[k]), "FoPush: invalid FoStack"); +#endif + if ( FoTOS[k] >= &(FoStack[k][FoStackSize-1]) ) + fatal( eMsgd("exceeded max depth of FOLLOW recursion (%d)\n", + FoStackSize) ); + require(FoTOS[k]>=FoStack[k], + eMsg1("FoPush: FoStack stack-ptr is playing out of its sandbox", + rule)); + ++(FoTOS[k]); + *(FoTOS[k]) = r->rulenum; + } + { + /* +**** int *p; +**** fprintf(stderr, "FoStack[k=%d]:\n", k); +**** for (p=FoStack[k]; p<=FoTOS[k]; p++) +**** { +**** fprintf(stderr, "\t%s\n", RulePtr[*p]->rname); +**** } + */ + } +} + +/* Pop one rule off of the FOLLOW stack. TOS ptr is NULL if empty. */ +void +#ifdef __USE_PROTOS +FoPop( int k ) +#else +FoPop( k ) +int k; +#endif +{ + require(k<=CLL_k, "FoPop: tried to access non-existent stack"); + /*fprintf(stderr, "FoPop\n");*/ + require(FoTOS[k]>=FoStack[k]&&FoTOS[k]<=&(FoStack[k][FoStackSize-1]), + "FoPop: FoStack stack-ptr is playing out of its sandbox"); + if ( FoTOS[k] == FoStack[k] ) FoTOS[k] = NULL; + else (FoTOS[k])--; +} + +/* Compute FOLLOW cycle. + * Mark all FOLLOW sets for rules in cycle as incomplete. + * Then, save cycle on the cycle list (Cycles) for later resolution. + * The Cycle is stored in the form: + * (head of cycle==croot, rest of rules in cycle==cyclicDep) + * + * e.g. (Fo means "FOLLOW of", "-->" means requires or depends on) + * + * Fo(x)-->Fo(a)-->Fo(b)-->Fo(c)-->Fo(x) + * ^----Infinite recursion (cycle) + * + * the cycle would be: x -> {a,b,c} or stored as (x,{a,b,c}). Fo(x) depends + * on the FOLLOW of a,b, and c. The root of a cycle is always complete after + * Fo(x) finishes. Fo(a,b,c) however are not. It turns out that all rules + * in a FOLLOW cycle have the same FOLLOW set. + */ +void +#ifdef __USE_PROTOS +RegisterCycle( char *rule, int k ) +#else +RegisterCycle( rule, k ) +char *rule; +int k; +#endif +{ + CacheEntry *f; + Cycle *c; + int *p; + RuleEntry *r; + require(rule!=NULL, "RegisterCycle: tried to register NULL rule"); + require(k<=CLL_k, "RegisterCycle: tried to access non-existent stack"); + + /*fprintf(stderr, "RegisterCycle(%s)\n", rule);*/ + /* Find cycle start */ + r = (RuleEntry *) hash_get(Rname, rule); + require(r!=NULL,eMsg1("rule %s must be defined but isn't", rule)); + require(FoTOS[k]>=FoStack[k]&&FoTOS[k]<=&(FoStack[k][FoStackSize-1]), + eMsg1("RegisterCycle(%s): FoStack stack-ptr is playing out of its sandbox", + rule)); +/*** if ( FoTOS[k]&(FoStack[k][FoStackSize-1]) ) +**** { +**** fprintf(stderr, "RegisterCycle(%s): FoStack stack-ptr is playing out of its sandbox\n", +**** rule); +**** fprintf(stderr, "RegisterCycle: sp==0x%x out of bounds 0x%x...0x%x\n", +**** FoTOS[k], FoStack[k], &(FoStack[k][FoStackSize-1])); +**** exit(PCCTS_EXIT_FAILURE); +**** } +****/ + +#ifdef MEMCHK + require(valid(FoStack[k]), "RegisterCycle: invalid FoStack"); +#endif + for (p=FoTOS[k]; *p != r->rulenum && p >= FoStack[k]; --p) {;} + require(p>=FoStack[k], "RegisterCycle: FoStack is screwed up beyond belief"); + if ( p == FoTOS[k] ) return; /* don't worry about cycles to oneself */ + + /* compute cyclic dependents (rules in cycle except head) */ + c = newCycle; + require(c!=NULL, "RegisterCycle: couldn't alloc new cycle"); + c->cyclicDep = empty; + c->croot = *p++; /* record root of cycle */ + for (; p<=FoTOS[k]; p++) + { + /* Mark all dependent rules as incomplete */ + f = (CacheEntry *) hash_get(Fcache, Fkey(RulePtr[*p]->rname,'o',k)); + if ( f==NULL ) + { + f = newCacheEntry( Fkey(RulePtr[*p]->rname,'o',k) ); + hash_add(Fcache, Fkey(RulePtr[*p]->rname,'o',k), (Entry *)f); + } + f->incomplete = TRUE; + + set_orel(*p, &(c->cyclicDep)); /* mark rule as dependent of croot */ + } + list_add(&(Cycles[k]), (void *)c); +} + +/* make all rules in cycle complete + * + * while ( some set has changed ) do + * for each cycle do + * if degree of FOLLOW set for croot > old degree then + * update all FOLLOW sets for rules in cyclic dependency + * change = TRUE + * endif + * endfor + * endwhile + */ +void +#ifdef __USE_PROTOS +ResolveFoCycles( int k ) +#else +ResolveFoCycles( k ) +int k; +#endif +{ + ListNode *p, *q; + Cycle *c; + int changed = 1; + CacheEntry *f,*g; + int r; +/* int i; */ /* MR10 not useful */ + unsigned d; + + unsigned *cursor; /* MR10 */ + unsigned *origin; /* MR10 */ + + /*fprintf(stderr, "Resolving following cycles for %d\n", k);*/ + while ( changed ) + { + changed = 0; +/* MR10 i = 0; */ + for (p = Cycles[k]->next; p!=NULL; p=p->next) + { + c = (Cycle *) p->elem; + /*fprintf(stderr, "cycle %d: %s -->", i++, RulePtr[c->croot]->rname);*/ + /*s_fprT(stderr, c->cyclicDep);*/ + /*fprintf(stderr, "\n");*/ + f = (CacheEntry *) + hash_get(Fcache, Fkey(RulePtr[c->croot]->rname,'o',k)); + require(f!=NULL, eMsg1("FOLLOW(%s) must be in cache but isn't", RulePtr[c->croot]->rname) ); + if ( (d=set_deg(f->fset)) > c->deg ) + { + /*fprintf(stderr, "Fo(%s) has changed\n", RulePtr[c->croot]->rname);*/ + changed = 1; + c->deg = d; /* update cycle FOLLOW set degree */ + +/* MR10 */ origin=set_pdq(c->cyclicDep); +/* MR10 */ for (cursor=origin; *cursor != nil; cursor++) { +/* MR10 */ r=*cursor; + +/******** while ( !set_nil(c->cyclicDep) ) { *****/ +/******** r = set_int(c->cyclicDep); *****/ +/******** set_rm(r, c->cyclicDep); *****/ + + /*fprintf(stderr, "updating Fo(%s)\n", RulePtr[r]->rname);*/ + g = (CacheEntry *) + hash_get(Fcache, Fkey(RulePtr[r]->rname,'o',k)); + require(g!=NULL, eMsg1("FOLLOW(%s) must be in cache but isn't", RulePtr[r]->rname) ); + set_orin(&(g->fset), f->fset); + g->incomplete = FALSE; + } +/* MR10 */ free( (char *) origin); +/* MR10 */ origin=NULL; + } + } +/* MR10 - this if statement appears to be meaningless since i is always 0 */ +/* MR10 if ( i == 1 ) changed = 0; */ /* if only 1 cycle, no need to repeat */ + } + /* kill Cycle list */ + for (q = Cycles[k]->next; q != NULL; q=p) + { + p = q->next; + set_free( ((Cycle *)q->elem)->cyclicDep ); + free((char *)q); + } + free( (char *)Cycles[k] ); + Cycles[k] = NULL; +} + + + /* P r i n t i n g S y n t a x D i a g r a m s */ + +static void +#ifdef __USE_PROTOS +pBlk( Junction *q, int btype ) +#else +pBlk( q, btype ) +Junction *q; +int btype; +#endif +{ + int k,a; + Junction *alt, *p; + + q->end->pvisited = TRUE; + if ( btype == aLoopBegin ) + { + require(q->p2!=NULL, "pBlk: invalid ()* block"); + PRINT(q->p1); + alt = (Junction *)q->p2; + PRINT(alt->p1); + if ( PrintAnnotate ) + { + printf(" /* Opt "); + k = 1; + while ( !set_nil(alt->fset[k]) ) + { + s_fprT(stdout, alt->fset[k]); + if ( k++ == CLL_k ) break; + if ( !set_nil(alt->fset[k]) ) printf(", "); + } + printf(" */\n"); + } + return; + } + for (a=1,alt=q; alt != NULL; alt= (Junction *) alt->p2, a++) + { + if ( alt->p1 != NULL ) PRINT(alt->p1); + if ( PrintAnnotate ) + { + printf( " /* [%d] ", alt->altnum); + k = 1; + while ( !set_nil(alt->fset[k]) ) + { + s_fprT(stdout, alt->fset[k]); + if ( k++ == CLL_k ) break; + if ( !set_nil(alt->fset[k]) ) printf(", "); + } + if ( alt->p2 == NULL && btype == aOptBlk ) + printf( " (optional branch) */\n"); + else printf( " */\n"); + } + + /* ignore implied empty alt of Plus blocks */ + if ( alt->p2 != NULL && ((Junction *)alt->p2)->ignore ) break; + + if ( alt->p2 != NULL && !(((Junction *)alt->p2)->p2==NULL && btype == aOptBlk) ) + { + if ( pLevel == 1 ) + { + printf("\n"); + if ( a+1==pAlt1 || a+1==pAlt2 ) printf("=>"); + printf("\t"); + } + else printf(" "); + printf("|"); + if ( pLevel == 1 ) + { + p = (Junction *) ((Junction *)alt->p2)->p1; + while ( p!=NULL ) + { + if ( p->ntype==nAction ) + { + p=(Junction *)((ActionNode *)p)->next; + continue; + } + if ( p->ntype!=nJunction ) + { + break; + } + if ( p->jtype==EndBlk || p->jtype==EndRule ) + { + p = NULL; + break; + } + p = (Junction *)p->p1; + } + if ( p==NULL ) printf("\n\t"); /* Empty alt? */ + } + } + } + q->end->pvisited = FALSE; +} + +/* How to print out a junction */ +void +#ifdef __USE_PROTOS +pJunc( Junction *q ) +#else +pJunc( q ) +Junction *q; +#endif +{ + int dum_k; + int doing_rule; + require(q!=NULL, "pJunc: NULL node"); + require(q->ntype==nJunction, "pJunc: not junction"); + + if ( q->pvisited == TRUE ) return; + q->pvisited = TRUE; + switch ( q->jtype ) + { + case aSubBlk : + if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k); + if ( q->end->p1 != NULL && ((Junction *)q->end->p1)->ntype==nJunction && + ((Junction *)q->end->p1)->jtype == EndRule ) doing_rule = 1; + else doing_rule = 0; + pLevel++; + if ( pLevel==1 ) + { + if ( pAlt1==1 ) printf("=>"); + printf("\t"); + } + else printf(" "); + if ( doing_rule ) + { + if ( pLevel==1 ) printf(" "); + pBlk(q,q->jtype); + } + else { + printf("("); + if ( pLevel==1 ) printf(" "); + pBlk(q,q->jtype); + if ( pLevel>1 ) printf(" "); + printf(")"); + } + if ( q->guess ) printf("?"); + pLevel--; + if ( PrintAnnotate ) freeBlkFsets(q); + if ( q->end->p1 != NULL ) PRINT(q->end->p1); + break; + case aOptBlk : + if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k); + pLevel++; + if ( pLevel==1 ) + { + if ( pAlt1==1 ) printf("=>"); + printf("\t"); + } + else printf(" "); + printf("{"); + if ( pLevel==1 ) printf(" "); + pBlk(q,q->jtype); + if ( pLevel>1 ) printf(" "); + else printf("\n\t"); + printf("}"); + pLevel--; + if ( PrintAnnotate ) freeBlkFsets(q); + if ( q->end->p1 != NULL ) PRINT(q->end->p1); + break; + case aLoopBegin : + if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k); + pLevel++; + if ( pLevel==1 ) + { + if ( pAlt1==1 ) printf("=>"); + printf("\t"); + } + else printf(" "); + printf("("); + if ( pLevel==1 ) printf(" "); + pBlk(q,q->jtype); + if ( pLevel>1 ) printf(" "); + else printf("\n\t"); + printf(")*"); + pLevel--; + if ( PrintAnnotate ) freeBlkFsets(q); + if ( q->end->p1 != NULL ) PRINT(q->end->p1); + break; + case aLoopBlk : + if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k); + pBlk(q,q->jtype); + if ( PrintAnnotate ) freeBlkFsets(q); + break; + case aPlusBlk : + if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k); + pLevel++; + if ( pLevel==1 ) + { + if ( pAlt1==1 ) printf("=>"); + printf("\t"); + } + else printf(" "); + printf("("); + if ( pLevel==1 ) printf(" "); + pBlk(q,q->jtype); + if ( pLevel>1 ) printf(" "); + printf(")+"); + pLevel--; + if ( PrintAnnotate ) freeBlkFsets(q); + if ( q->end->p1 != NULL ) PRINT(q->end->p1); + break; + case EndBlk : + break; + case RuleBlk : + printf( "\n%s :\n", q->rname); + PRINT(q->p1); + if ( q->p2 != NULL ) PRINT(q->p2); + break; + case Generic : + if ( q->p1 != NULL ) PRINT(q->p1); + q->pvisited = FALSE; + if ( q->p2 != NULL ) PRINT(q->p2); + break; + case EndRule : + printf( "\n\t;\n"); + break; + } + q->pvisited = FALSE; +} + +/* How to print out a rule reference node */ +void +#ifdef __USE_PROTOS +pRuleRef( RuleRefNode *p ) +#else +pRuleRef( p ) +RuleRefNode *p; +#endif +{ + require(p!=NULL, "pRuleRef: NULL node"); + require(p->ntype==nRuleRef, "pRuleRef: not rule ref node"); + + printf( " %s", p->text); + PRINT(p->next); +} + +/* How to print out a terminal node */ +void +#ifdef __USE_PROTOS +pToken( TokNode *p ) +#else +pToken( p ) +TokNode *p; +#endif +{ + require(p!=NULL, "pToken: NULL node"); + require(p->ntype==nToken, "pToken: not token node"); + + if ( p->wild_card ) printf(" ."); + printf( " %s", TerminalString(p->token)); + PRINT(p->next); +} + +/* How to print out a terminal node */ +void +#ifdef __USE_PROTOS +pAction( ActionNode *p ) +#else +pAction( p ) +ActionNode *p; +#endif +{ + require(p!=NULL, "pAction: NULL node"); + require(p->ntype==nAction, "pAction: not action node"); + + PRINT(p->next); +} + + /* F i l l F o l l o w L i s t s */ + +/* + * Search all rules for all rule reference nodes, q to rule, r. + * Add q->next to follow list dangling off of rule r. + * i.e. + * + * r: -o-R-o-->o--> Ptr to node following rule r in another rule + * | + * o--> Ptr to node following another reference to r. + * + * This is the data structure employed to avoid FOLLOW set computation. We + * simply compute the FIRST (reach) of the EndRule Node which follows the + * list found at the end of all rules which are referenced elsewhere. Rules + * not invoked by other rules have no follow list (r->end->p1==NULL). + * Generally, only start symbols are not invoked by another rule. + * + * Note that this mechanism also gives a free cross-reference mechanism. + * + * The entire syntax diagram is layed out like this: + * + * SynDiag + * | + * v + * o-->R1--o + * | + * o-->R2--o + * | + * ... + * | + * o-->Rn--o + * + */ +void +#ifdef __USE_PROTOS +FoLink( Node *p ) +#else +FoLink( p ) +Node *p; +#endif +{ + RuleEntry *q; + Junction *j = (Junction *) p; + RuleRefNode *r = (RuleRefNode *) p; + + if ( p==NULL ) return; + require(p->ntype>=1 && p->ntype<=NumNodeTypes, + eMsgd("FoLink: invalid diagram node: ntype==%d",p->ntype)); + switch ( p->ntype ) + { + case nJunction : + if ( j->fvisited ) return; + if ( j->jtype == EndRule ) return; + j->fvisited = TRUE; + FoLink( j->p1 ); + FoLink( j->p2 ); +/* MR14 */ +/* MR14 */ /* Need to determine whether the guess block is an */ +/* MR14 */ /* of the form (alpha)? beta before follow sets are */ +/* MR14 */ /* computed. This is necessary to solve problem */ +/* MR14 */ /* of doing follow on the alpha of an (alpha)? beta block. */ +/* MR14 */ +/* MR14 */ /* This is performed by analysis_point as a side-effect. */ +/* MR14 */ +/* MR14 */ +/* MR14 */ if (j->jtype == aSubBlk && j->guess) { +/* MR14 */ Junction *ignore; +/* MR14 */ ignore=analysis_point(j); +/* MR14 */ } +/* MR14 */ + return; + case nRuleRef : + if ( r->linked ) return; + q = (RuleEntry *) hash_get(Rname, r->text); + if ( q == NULL ) + { + warnFL( eMsg1("rule %s not defined",r->text), FileStr[r->file], r->line ); + } + else + { + if ( r->parms!=NULL && RulePtr[q->rulenum]->pdecl==NULL ) + { + warnFL( eMsg1("rule %s accepts no parameter(s)", r->text), + FileStr[r->file], r->line ); + } + if ( r->parms==NULL && RulePtr[q->rulenum]->pdecl!=NULL ) + { + warnFL( eMsg1("rule %s requires parameter(s)", r->text), + FileStr[r->file], r->line ); + } + if ( r->assign!=NULL && RulePtr[q->rulenum]->ret==NULL ) + { + warnFL( eMsg1("rule %s yields no return value(s)", r->text), + FileStr[r->file], r->line ); + } + if ( r->assign==NULL && RulePtr[q->rulenum]->ret!=NULL ) + { + warnFL( eMsg1("rule %s returns a value(s)", r->text), + FileStr[r->file], r->line ); + } + if ( !r->linked ) + { + addFoLink( r->next, r->rname, RulePtr[q->rulenum] ); + r->linked = TRUE; + } + } + FoLink( r->next ); + return; + case nToken : + FoLink( ((TokNode *)p)->next ); + return; + case nAction : + FoLink( ((ActionNode *)p)->next ); + return; + default : + fatal_internal("invalid node type"); + } +} + +/* + * Add a reference to the end of a rule. + * + * 'r' points to the RuleBlk node in a rule. r->end points to the last node + * (EndRule jtype) in a rule. + * + * Initial: + * r->end --> o + * + * After: + * r->end --> o-->o--> Ptr to node following rule r in another rule + * | + * o--> Ptr to node following another reference to r. + * + * Note that the links are added to the head of the list so that r->end->p1 + * always points to the most recently added follow-link. At the end, it should + * point to the last reference found in the grammar (starting from the 1st rule). + */ +void +#ifdef __USE_PROTOS +addFoLink( Node *p, char *rname, Junction *r ) +#else +addFoLink( p, rname, r ) +Node *p; +char *rname; +Junction *r; +#endif +{ + Junction *j; + require(r!=NULL, "addFoLink: incorrect rule graph"); + require(r->end!=NULL, "addFoLink: incorrect rule graph"); + require(r->end->jtype==EndRule, "addFoLink: incorrect rule graph"); + require(p!=NULL, "addFoLink: NULL FOLLOW link"); + + j = newJunction(); + j->rname = rname; /* rname on follow links point to target rule */ + j->p1 = p; /* link to other rule */ + j->p2 = (Node *) r->end->p1;/* point to head of list */ + r->end->p1 = (Node *) j; /* reset head to point to new node */ +} + +void +#ifdef __USE_PROTOS +GenCrossRef( Junction *p ) +#else +GenCrossRef( p ) +Junction *p; +#endif +{ + set a; + Junction *j; + RuleEntry *q; + unsigned e; + require(p!=NULL, "GenCrossRef: why are you passing me a null grammar?"); + + printf("Cross Reference:\n\n"); + a = empty; + for (; p!=NULL; p = (Junction *)p->p2) + { + printf("Rule %20s referenced by {", p->rname); + /* make a set of rules for uniqueness */ + for (j = (Junction *)(p->end)->p1; j!=NULL; j = (Junction *)j->p2) + { + q = (RuleEntry *) hash_get(Rname, j->rname); + require(q!=NULL, "GenCrossRef: FoLinks are screwed up"); + set_orel(q->rulenum, &a); + } + for (; !set_nil(a); set_rm(e, a)) + { + e = set_int(a); + printf(" %s", RulePtr[e]->rname); + } + printf(" }\n"); + } + set_free( a ); +} + +/* + The single argument is a pointer to the start of an element of a + C++ style function prototypet list. Given a pointer to the start of + an formal we must locate the comma (or the end of the string) + and locate the datatype, formal name, and initial value expression. + + The function returns a pointer to the character following the comma + which terminates the formal declaration, or a pointer to the end of + the string if none was found. + + I thought we were parsing specialists, how come I'm doing this by + hand written code ? + + Examples of input: + + Foo f, + Foo f = Foo(1), + Foo f = Foo(1,2), + Foo f = &farray[1,2], + Foo f = ",", + Foo f = ',', + TFoo f = TFoo(1,2), + + A non-zero value for nesting indicates a problem matching '(' and ')', + '[' and ']', '<' and '>', '{' and '}', or improperly terminated string + or character literal. + +*/ + + +/* + * Don't care if it is a valid string literal or not, just find the end + * Start with pointer to leading "\"" + */ + +#ifdef __USE_PROTOS +char * skipStringLiteral(char *pCurrent) +#else +char * skipStringLiteral(pCurrent) +char *pCurrent; +#endif +{ + char *p = pCurrent; + if (*p == 0) return p; + require (*p == '\"', "skipStringLiteral") + p++; + for (p = p; *p != 0; p++) { + if (*p == '\\') { + p++; + if (*p == 0) break; + p++; + } + if (*p == '\"') { + p++; + break; + } + } + return p; +} + +/* + * Don't care if it is a valid character literal or not, just find the end + * Start with pointer to leading "'" + */ + +#ifdef __USE_PROTOS +char * skipCharLiteral(char *pStart) +#else +char * skipCharLiteral(pStart) + char *pStart; +#endif +{ + char *p = pStart; + if (*p == 0) return p; + require (*p == '\'', "skipCharLiteral") + p++; + for (p = p; *p != 0; p++) { + if (*p == '\\') { + p++; + if (*p == 0) break; + p++; + } + if (*p == '\'') { + p++; + break; + } + } + return p; +} + +#ifdef __USE_PROTOS +char * skipSpaces(char *pStart) +#else +char * skipSpaces(pStart) +char * pStart; +#endif +{ + char *p = pStart; + while (*p != 0 && isspace(*p)) p++; + return p; +} + +#ifdef __USE_PROTOS +char * skipToSeparatorOrEqualSign(char *pStart, int *pNest) +#else +char * skipToSeparatorOrEqualSign(pStart, pNest) +char *pStart; +int *pNest; +#endif +{ + char *p = pStart; + + int nest = 0; + + *pNest = (-1); + + while (*p != 0) { + switch (*p) { + + case '(' : + case '[' : + case '<' : + case '{' : + nest++; + p++; + break; + + case ')' : + case ']' : + case '>' : + case '}' : + nest--; + p++; + break; + + case '"' : + p = skipStringLiteral(p); + break; + + case '\'' : + p = skipCharLiteral(p); + break; + + case '\\': + p++; + if (*p == 0) goto EXIT; + p++; + break; + + case ',': + case '=': + if (nest == 0) goto EXIT; + p++; + break; + + default: + p++; + } + } +EXIT: + *pNest = nest; + return p; +} + +#ifdef __USE_PROTOS +char * skipToSeparator(char *pStart, int *pNest) +#else +char * skipToSeparator(pStart, pNest) +char *pStart; +int *pNest; +#endif +{ + char * p = pStart; + for ( ; ; ) { + p = skipToSeparatorOrEqualSign(p, pNest); + if (*pNest != 0) return p; + if (*p == ',') return p; + if (*p == 0) return p; + p++; + } +} + +/* skip to just past the "=" separating the declaration from the initialization value */ + +#ifdef __USE_PROTOS +char * getInitializer(char *pStart) +#else +char * getInitializer(pStart) +char * pStart; +#endif +{ + char *p; + char *pDataType; + char *pSymbol; + char *pEqualSign; + char *pValue; + char *pSeparator; + int nest = 0; + + require(pStart!=NULL, "getInitializer: invalid string"); + + p = endFormal(pStart, + &pDataType, + &pSymbol, + &pEqualSign, + &pValue, + &pSeparator, + &nest); + if (nest != 0) return NULL; + if (pEqualSign == NULL) return NULL; + if (pValue == NULL) return NULL; + return strBetween(pValue, NULL, pSeparator); +} + +/* + Examines the string from pStart to pEnd-1. + If the string has 0 length or is entirely white space + returns 1. Otherwise 0. +*/ + +#ifdef __USE_PROTOS +int isWhiteString(const char *pStart, const char *pEnd) +#else +int isWhiteString(pStart, pEnd) +const char *pStart; +const char *pEnd; +#endif +{ + const char *p; + for (p = pStart; p < pEnd; p++) { + if (! isspace(*p)) return 0; + } + return 1; +} + +/* + This replaces HasComma() which couldn't distinguish + + foo ["a,b"] + + from: + + foo[a,b] + +*/ + +#ifdef __USE_PROTOS +int hasMultipleOperands(char *pStart) +#else +int hasMultipleOperands(pStart) +char *pStart; +#endif +{ + char *p = pStart; + int nest = 0; + + p = skipSpaces(p); + if (*p == 0) return 0; + p = skipToSeparator(p, &nest); + if (nest == 0 && *p == ',') return 1; + return 0; +} + + +#define MAX_STR_BETWEEN_WORK_AREA 1000 + +static char strBetweenWorkArea[MAX_STR_BETWEEN_WORK_AREA]; + + +/* + strBetween(pStart, pNext, pStop) + + Creates a null terminated string by copying the text between two pointers + to a work area. The start of the string is pStart. The end of the string + is the character before pNext, or if pNext is null then the character before + pStop. Trailing spaces are not included in the copy operation. + + This is used when a string contains several parts. The pNext part may be + optional. The pStop will stop the scan when the optional part is not present + (is a null pointer). +*/ + +#ifdef __USE_PROTOS +char *strBetween(char *pStart, char *pNext, char *pStop) +#else +char *strBetween(pStart, pNext, pStop) +char *pStart; +char *pNext; +char *pStop; +#endif +{ + char *p; + char *q = strBetweenWorkArea; + const char *pEnd; + + pEnd = (pNext != NULL) ? pNext : pStop; + + require (pEnd != NULL, "pEnd == NULL"); + require (pEnd >= pStart, "pEnd < pStart"); + for (pEnd--; pEnd >= pStart; pEnd--) { /* MR31 */ + if (! isspace(*pEnd)) break; + } + for (p = pStart; + p <= pEnd && q < &strBetweenWorkArea[MAX_STR_BETWEEN_WORK_AREA-2]; + p++, q++) { + *q = *p; + } + *q = 0; + return strBetweenWorkArea; +} + +/* + function Returns pointer to character following separator at + value which to continue search for next formal. If at the + end of the string a pointer to the null byte at the + end of the string is returned. + + pStart Pointer to the starting position of the formal list + + This may be the middle of a longer string, for example + when looking for the end of formal #3 starting from + the middle of the complete formal list. + + ppDataType Returns a pointer to the start of the data type in the + formal. Example: pointer to "Foo". + + ppSymbol Returns a pointer to the start of the formal symbol. + Example: pointer to "f". + + ppEqualSign Returns a pointer to the equal sign separating the + formal symbol from the initial value. If there is + no "=" then this will be NULL. + + ppValue Returns a pointer to the initial value part of the + formal declaration. Example: pointer to "&farray[1,2]" + + ppSeparator Returns a pointer to the character which terminated the + scan. This should be a pointer to a comma or a null + byte which terminates the string. + + pNest Returns the nesting level when a separator was found. + This is non-zero for any kind of error. This is zero + for a successful parse of this portion of the formal + list. + +*/ + +#ifdef __USE_PROTOS +char * endFormal(char *pStart, + char **ppDataType, + char **ppSymbol, + char **ppEqualSign, + char **ppValue, + char **ppSeparator, + int *pNest) +#else +char * endFormal(pStart, + ppDataType, + ppSymbol, + ppEqualSign, + ppValue, + ppSeparator, + pNest) +char *pStart; +char **ppDataType; +char **ppSymbol; +char **ppEqualSign; +char **ppValue; +char **ppSeparator; +int *pNest; + +#endif +{ + char *p = pStart; + char *q; + + *ppDataType = NULL; + *ppSymbol = NULL; + *ppEqualSign = NULL; + *ppValue = NULL; + *ppSeparator = NULL; + + *pNest = 0; + + /* The first non-blank is the start of the datatype */ + + p = skipSpaces(p); + if (*p == 0) goto EXIT; + *ppDataType = p; + + /* We are not looking for the symbol, we are looking + for the separator that follows the symbol. Then + we'll back up. + + Search for the ',' or '=" or null terminator. + */ + + p = skipToSeparatorOrEqualSign(p, pNest); + + if (*pNest != 0) goto EXIT; + + /* + Work backwards to find start of symbol + Skip spaces between the end of symbol and separator + Assume that there are no spaces in the formal, but + there is a space preceding the formal + */ + + for (q = &p[-1]; q >= *ppDataType; q--) { + if (! isspace(*q)) break; + } + if (q < *ppDataType) goto EXIT; + + /* + MR26 Handle things like: IIR_Bool (IIR_Decl::*constraint)() + Backup until we hit the end of a symbol string, then find the + start of the symbol string. This wont' work for functions + with prototypes, but works for the most common cases. For + others, use typedef names. + */ + +/* MR26 */ for (q = q; q >= *ppDataType; q--) { +/* MR26 */ if (isalpha(*q) || isdigit(*q) || *q == '_' || *q == '$') break; +/* MR26 */ } +/* MR26 */ if (q < *ppDataType) goto EXIT; + + for (q = q; q >= *ppDataType; q--) { + if ( ! (isalpha(*q) || isdigit(*q) || *q == '_' || *q == '$')) break; + } + + *ppSymbol = &q[1]; + + if (*p == ',' || *p == 0) { + *ppSeparator = p; + goto EXIT; + } + + *ppEqualSign = p; + p = skipSpaces(++p); + *ppValue = p; + if (*p == 0) goto EXIT; + + + while (*p != 0 && *pNest == 0 && *p != ',') { + p = skipToSeparator(p, pNest); + } + if (*pNest == 0) *ppSeparator = p; + +EXIT: + if (*p == ',') p++; + return p; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/mode.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/mode.h new file mode 100644 index 00000000..592e811c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/mode.h @@ -0,0 +1,12 @@ +#define START 0 +#define STRINGS 1 +#define ACTION_STRINGS 2 +#define ACTION_CHARS 3 +#define ACTION_COMMENTS 4 +#define TOK_DEF_COMMENTS 5 +#define TOK_DEF_CPP_COMMENTS 6 +#define ACTION_CPP_COMMENTS 7 +#define CPP_COMMENTS 8 +#define COMMENTS 9 +#define ACTIONS 10 +#define PARSE_ENUM_FILE 11 diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/mrhoist.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/mrhoist.c new file mode 100644 index 00000000..275cfc43 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/mrhoist.c @@ -0,0 +1,3030 @@ +/* + * mrhoist.c + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33MR10 + * + */ + +#include + +#include "pcctscfg.h" + +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" +#include + +#ifdef __USE_PROTOS +void dumppred(Predicate *); +#else +void dumppred(); +#endif + +/* + Try to determine whether predicate "first" is true for + all cases where "second" is true. Comparison takes place + without regard to context. + Assumes that predicate symbols have been expanded. + Assumes that there are no NAND or NOR nodes + +*/ + +#ifdef __USE_PROTOS +int MR_secondPredicateUnreachable(Predicate *first,Predicate *second) +#else +int MR_secondPredicateUnreachable(first,second) + Predicate *first; + Predicate *second; +#endif +{ + Predicate *f; + Predicate *s; + + if (first == NULL) { + return 1; + } else if (second == NULL) { + return 0; + } else if (first->down == NULL && second->down == NULL) { + if (first->source == second->source && + first->inverted == second->inverted) { + return 1; /* look identical - will never reach alt2 */ + } else { + return 0; /* look different */ + }; + } else if (first->down == NULL && second->down != NULL) { + + if (second->expr == PRED_AND_LIST) { + + /* unreachable if first covers any child of second */ + + for (s=second->down; s != NULL; s=s->right) { + if (MR_secondPredicateUnreachable(first,s)) { + return 1; + }; + }; + return 0; + } else if (second->expr == PRED_OR_LIST) { + + /* unreachable if first covers every child of second */ + + for (s=second->down; s != NULL; s=s->right) { + if (!MR_secondPredicateUnreachable(first,s)) { + return 0; + }; + }; + return 1; + } else { + require (0,"Illegal pred->expr"); + return 0; /* MR20 Make compiler happy */ + }; + } else if (first->down != NULL && second->down == NULL) { + if (first->expr == PRED_AND_LIST) { + + /* unreachable if every child of first covers second */ + + for (f=first->down; f != NULL; f=f->right) { + if (!MR_secondPredicateUnreachable(f,second)) { + return 0; + }; + }; + return 1; + } else if (first->expr == PRED_OR_LIST) { + + /* unreachable if any child of first covers second */ + + for (f=first->down; f != NULL; f=f->right) { + if (MR_secondPredicateUnreachable(f,second)) { + return 1; + }; + }; + return 0; + } else { + require (0,"Illegal predicate->expr"); + return 0; /* MR20 Make compiler happy */ + }; + } else { + + if (first->expr == PRED_AND_LIST && second->expr == PRED_AND_LIST) { + + /* unreachable if each child of first covers at least one child of second */ + + for (f=first->down; f != NULL ; f=f->right) { + for (s=second->down; s != NULL ; s=s->right) { + if (MR_secondPredicateUnreachable(f,s)) goto A_next_f; + }; + return 0; +A_next_f: + continue; + }; + return 1; + + } else if (first->expr == PRED_AND_LIST && second->expr == PRED_OR_LIST) { + + /* unreachable if each child of first covers ALL of second's children */ + + for (f=first->down; f != NULL ; f=f->right) { + for (s=second->down; s != NULL ; s=s->right) { + if (!MR_secondPredicateUnreachable(f,s)) return 0; + }; + }; + return 1; + + } else if (first->expr == PRED_OR_LIST && second->expr == PRED_AND_LIST) { + + /* unreachable if any child of second is covered by any child of first */ + + for (f=first->down; f != NULL ; f=f->right) { + for (s=second->down; s != NULL ; s=s->right) { + if (MR_secondPredicateUnreachable(f,s)) return 1; + }; + }; + return 0; + + } else if (first->expr == PRED_OR_LIST && second->expr == PRED_OR_LIST) { + + /* unreachable if every child of second is covered by some child of first */ + + for (f=first->down; f != NULL ; f=f->right) { + for (s=second->down; s != NULL ; s=s->right) { + if (MR_secondPredicateUnreachable(f,s)) goto B_next_f; + }; + return 0; +B_next_f: + continue; + }; + return 1; + + } else { + require (0,"Illegal predicate->expr"); + return 0; /* MR20 Make compiler happy */ + }; + }; + return 0; /* MR20 MSVC 5.0 complains about missing return statement */ +} + +#ifdef __USE_PROTOS +void MR_xxxIndent(FILE *f,int depth) +#else +void MR_xxxIndent(f,depth) + FILE *f; + int depth; +#endif +{ + int i; + + for (i=0; irname,rrn->line,FileStr[rrn->file],rrn->text); + }; + lastOne=MR_ruleReferenced(rrn); + if (lastOne != NULL) { + for (j=0; jrname,lastOne->line,FileStr[lastOne->file]); + }; +} + +#ifdef __USE_PROTOS +void MR_dumpTreeF(FILE *f,int depth,Tree *tree,int across) +#else +void MR_dumpTreeF(f,depth,tree,across) + FILE *f; + Tree *tree; + int depth; + int across; +#endif +{ + int newAcross=across; + + if (tree == NULL ) return; + if (tree->down != NULL ) { + fprintf(output,"\n"); + MR_outputIndent(depth); + fprintf(output, "(root ="); + }; + if (tree->token == ALT ) { + fprintf(output," %-16s","Alt"); + } else if (tree->token==EpToken ) { + fprintf(output,"(%d)%13s",tree->v.rk," "); + } else { + fprintf(output," %-16s",TerminalString(tree->token)); + }; + if (tree->down != NULL) { + fprintf(output,"\n"); + MR_outputIndent(depth+1); + MR_dumpTreeF(f,depth+1,tree->down,1); + newAcross=0; + fprintf(output,"\n"); + MR_outputIndent(depth); + fprintf(output,")"); + }; + if (newAcross > 3) { + fprintf(output,"\n"); + MR_outputIndent(depth); + newAcross=0; + }; + MR_dumpTreeF(f,depth,tree->right,newAcross+1); +} + +#ifdef __USE_PROTOS +void MR_dumpTreeX(int depth,Tree *tree,int across) +#else +void MR_dumpTreeX(depth,tree,across) + Tree *tree; + int depth; + int across; +#endif +{ + MR_dumpTreeF(output,depth,tree,across); +} + +#ifdef __USE_PROTOS +void MR_dumpTokenSet(FILE *f,int depth,set s) +#else +void MR_dumpTokenSet(f,depth,s) + FILE *f; + int depth; + set s; +#endif +{ + int i; + int j; + + unsigned *pdq; + + if (set_nil(s)) { + fprintf(f,"\n"); + MR_xxxIndent(f,depth+1); + fprintf(f,"nil\n"); + return; + }; + + pdq=set_pdq(s); + require(pdq != NULL,"set_pdq failed"); + i=0; + for (i=0 ; ; i=i+4) { + fprintf(f,"\n"); + MR_xxxIndent(f,depth+1); + for (j=0; j < 4 ; j++) { + if (pdq[i+j] == nil) break; + fprintf(f," %-16s",TerminalString(pdq[i+j])); + }; + if (pdq[i+j] == nil) break; + }; + fprintf(f,"\n"); + free( (char *) pdq); +} + +#ifdef __USE_PROTOS +void MR_dumpPred1(int depth,Predicate *p,int withContext) +#else +void MR_dumpPred1(depth,p,withContext) + int depth; + Predicate *p; + int withContext; +#endif +{ + unsigned k; + + if (p == NULL) { + MR_outputIndent(depth); + fprintf(output,"The predicate is empty (or always true)\n\n"); + return; + }; + if (p->down != NULL) { + MR_outputIndent(depth); + if (p->inverted) { + + /* MR14a Left out print expression in fprintf + Reported by Manuel Kessler (mlkessle@cip.physik.uni-wuerzburg.de) + */ + + if (p->expr == PRED_AND_LIST) fprintf(output,"%s NAND (not AND) expr\n\n",p->expr); + if (p->expr == PRED_OR_LIST) fprintf(output,"%s NOR (not OR) expr\n\n",p->expr); + } else { + fprintf(output,"%s expr\n\n",p->expr); + }; + } else { + MR_outputIndent(depth); + fprintf(output,"pred %s <<%s>>?\n", + (p->inverted ? " *not*" : ""), + (p->expr == NULL ? "null expr" : p->expr)); + MR_outputIndent(depth+1); + fprintf(output," "); + fprintf(output," depth=k=%d",p->k); + if (p->source != NULL && p->source->guardpred) { + fprintf(output," (\"=>\" guard)"); + } + if (p->source != NULL && p->source->ampersandPred != NULL) { + fprintf(output," (\"&&\" guard)"); + }; + k=set_int(p->completionSet); + if (k != nil) { + fprintf(output," Incomplete Set at k=%d !",k); + }; + k=set_int(p->completionTree); + if (k != nil) { + fprintf(output," Incomplete Tree at k=%d !",k); + }; + if (p->source != NULL) { + fprintf(output," rule %s line %d %s", + p->source->rname,p->source->line,FileStr[p->source->file]); + }; + fprintf(output,"\n"); + if (withContext && + (HoistPredicateContext || + ! set_nil(p->scontext[1]) || + p->tcontext != NULL)) { + if (p->k == 1) { + MR_outputIndent(depth+1); + fprintf(output,"set context: "); + MR_dumpTokenSet(output,depth+1,p->scontext[1]); + } + if (p->k != 1) { + MR_outputIndent(depth+1); + fprintf(output,"tree context:"); + if (p->tcontext == NULL) { + fprintf(output," null"); + } else { + MR_dumpTreeX(depth+2,p->tcontext,0); + }; + fprintf(output,"\n"); + }; + }; + fprintf(output,"\n"); + }; + if (p->down != NULL) { + MR_dumpPred1(depth+1,p->down,withContext); + }; + if (p->right != NULL) { + MR_dumpPred1(depth,p->right,withContext); + }; +} + +#ifdef __USE_PROTOS +void MR_dumpPred(Predicate *p,int withContext) +#else +void MR_dumpPred(p,withContext) + Predicate *p; + int withContext; +#endif +{ + MR_dumpPred1(0,p,withContext); +} + +#ifdef __USE_PROTOS +Tree * MR_make_tree_from_set(set s) +#else +Tree * MR_make_tree_from_set(s) + set s; +#endif +{ + Tree *t=NULL; + Tree *node; + Tree **tp=&t; + int i; + + unsigned *pdq=set_pdq(s); + + if (pdq != NULL) { + for (i=0 ; pdq[i] != nil ; i++) { + node=tnode( (int) pdq[i]); + *tp=node; + tp=&(node->right); + }; + *tp=NULL; + free ( (char *) pdq); + }; + return t; +} + +#ifdef __USE_PROTOS +void MR_check_pred_too_long(Predicate *p,set completion) +#else +void MR_check_pred_too_long(p,completion) + Predicate *p; + set completion; +#endif +{ + if (p != NULL && + p->source != NULL && + ! p->source->predTooLong) { + if ( !set_nil(completion)) { + p->source->predTooLong=1; +warnFL("It is unusual (but ok) for a semantic predicate to test context past the end of its own rule", + FileStr[p->source->file],p->source->line); + }; + }; +} + +#ifdef __USE_PROTOS +int MR_predicate_context_completed(Predicate *p) +#else +int MR_predicate_context_completed(p) + Predicate *p; +#endif +{ + if (p == NULL) return 1; + if (p->expr != PRED_AND_LIST && + p->expr != PRED_OR_LIST) { + if ( ! set_nil(p->completionSet)) return 0; + if ( ! set_nil(p->completionTree)) return 0; + }; + return MR_predicate_context_completed(p->down) & + MR_predicate_context_completed(p->right); +} + +#ifdef __USE_PROTOS +Node * MR_advance(Node *n) +#else +Node * MR_advance(n) + Node *n; +#endif +{ + if (n == NULL) return NULL; + switch (n->ntype) { + case nJunction: return ((Junction *)n)->p1; + case nToken: return ((TokNode *)n)->next; + case nRuleRef: return ((RuleRefNode *)n)->next; + case nAction: return ((ActionNode *)n)->next; + default: return NULL; + }; + return NULL; /* MSVC 5.0 complains about missing return statement */ +} + +#ifdef __USE_PROTOS +Junction * MR_find_endRule(Node *n) +#else +Junction * MR_find_endRule(n) + Node *n; +#endif +{ + Node *next; + if (n == NULL) return NULL; + for (next=n; next != NULL; next=MR_advance(next)) { + if (next->ntype == nJunction && + ( (Junction *) next)->jtype == EndRule) { + break; + }; + }; + return (Junction *)next; +} + +/* + Intersection: a branch which is shorter is chosen + over one which is longer: (A B C) intersect (A B) yields (A B). + + AND: a branch which is longer is chosen over the one + which is shorter: (A B C) AND (A B) yields (A B C) + +*/ + +#ifdef __USE_PROTOS +Tree *MR_computeTreeIntersection(Tree *l,Tree *r) +#else +Tree *MR_computeTreeIntersection(l,r) + Tree *l; + Tree *r; +#endif +{ + Tree *result=NULL; + Tree **tail; + Tree *p; + Tree *q; + Tree *match; + + if (l == NULL || r == NULL) return NULL; + for (p=l; p != NULL; p=p->right) { + require(p->token != EpToken,"MR_computeTreeIntersection: p->EpToken unexpected\n"); + require (p->token != ALT,"MR_computeTreeIntersection: p->ALT unexpected\n"); + }; + for (q=r; q != NULL; q=q->right) { + require(q->token != EpToken,"MR_computeTreeIntersection: q->EpToken unexpected\n"); + require(q->token != ALT,"MR_computeTreeIntersection: q->ALT unexpected\n"); + }; + + result=tnode(ALT); + tail=&(result->down); + + for (p=l; p != NULL ; p=p->right) { + for (q=r; q != NULL ; q=q->right) { + if (p->token == q->token) { + match=tnode(p->token); + match->down=MR_computeTreeIntersection(p->down,q->down); + *tail=match; + tail=&(match->right); + }; + }; + }; + + *tail=NULL; + result=tshrink(result); + result=tflatten( result ); + result=tleft_factor( result ); + return result; +} + +/* the predicates which are ANDed together have a common + context: they must all have common roots. Thus the + AND operation is more like an OR operation because + branches which are longer are grafted onto shorter + branches of the AND tree. For instance combining + (A B C) with (A B C D) gives (A B C D). There + should never be a case of (A B C) and (A B D) because + they have the same context. + + Actually, this may not be true once one throws in + guard predicates which are defined by the user, not + the context. +*/ + +/* requires input trees to be in "canonical" format */ + +#ifdef __USE_PROTOS +Tree *MR_computeTreeAND(Tree *l,Tree *r) +#else +Tree *MR_computeTreeAND(l,r) + Tree *l; + Tree *r; +#endif +{ + Tree *result=NULL; + Tree **tail; + Tree *p; + Tree *q; + Tree *match; + + if (l == NULL) return tdup(r); + if (r == NULL) return tdup(l); + + for (p=l; p != NULL; p=p->right) { +/**** require(p->token != EpToken,"MR_computeTreeAND: p->EpToken unexpected\n"); ****/ + require (p->token != ALT,"MR_computeTreeAND: p->ALT unexpected\n"); + }; + for (q=r; q != NULL; q=q->right) { +/**** require(q->token != EpToken,"MR_computeTreeAND: q->EpToken unexpected\n"); ****/ + require(q->token != ALT,"MR_computeTreeAND: q->ALT unexpected\n"); + }; + + result=tnode(ALT); + tail=&(result->down); + + for (p=l; p != NULL ; p=p->right) { + for (q=r; q != NULL ; q=q->right) { + if (p->token == q->token) { + match=tnode(p->token); + match->down=MR_computeTreeAND(p->down,q->down); + *tail=match; + tail=&(match->right); + }; + }; + }; + + *tail=NULL; + result=tshrink(result); + result=tflatten( result ); + result=tleft_factor( result ); + return result; +} + +#ifdef __USE_PROTOS +void MR_union_plain_sets1(Predicate *p,set *theUnion) +#else +void MR_union_plain_sets1(p,theUnion) + Predicate *p; + set *theUnion; +#endif +{ + if (p == NULL) return; + MR_union_plain_sets1(p->down,theUnion); + MR_union_plain_sets1(p->right,theUnion); + set_orin(theUnion,p->plainSet); + return; +} + +#ifdef __USE_PROTOS +set MR_union_plain_sets(Predicate *p) +#else +set MR_union_plain_sets(p) + Predicate *p; +#endif +{ + set theUnion; + + theUnion=empty; + + MR_union_plain_sets1(p,&theUnion); + return theUnion; +} + +/* does NOT left factor: do not want to merge + (A B) with (A) to get (A B) + in fact the opposite: (A B) with (A) gives (A) +*/ + +#ifdef __USE_PROTOS +Tree *MR_compute_pred_tree_ctxXX(Predicate *p) +#else +Tree *MR_compute_pred_tree_ctxXX(p) + Predicate *p; +#endif +{ + Tree *result=NULL; + Predicate *q; + Tree *t; + + if (p == NULL) return NULL; + +/* this appears strange: why do we OR the context + of and AND predicate ? It is because of the way + that predicates are evaluated: if the context is + wrong then it's the same as if the predicate was + true. That means that even when one leg of an + AND has unmatched context, if the other leg has + matched context and is true then the predicate + succeeds. It's only when all the legs have unmatched + context that this one can skip evaluation of the + predicates. +*/ + if (p->expr == PRED_OR_LIST || + p->expr == PRED_AND_LIST) { + for (q=p->down; q != NULL ; q=q->right) { + t=MR_compute_pred_tree_ctxXX(q); + result=tappend(result,t); + t=NULL; + }; + + result=tshrink(result); + result=tflatten( result ); + +/* does NOT left factor: do not want to merge + (A B) with (A) to get (A B) + in fact the opposite: (A B) with (A) gives (A) +*/ + +/**** result=tleft_factor( result ); ****/ + return result; + }; + +#if 0 +** if (p->expr == PRED_AND_LIST) { +** +** Predicate *l; +** Predicate *r; +** Tree *l1; +** Tree *r1; +** Tree *prevl1; +** +** l=p->down; +** require (l->right != NULL,"MR_compute_pred_tree - AND has only one child"); +** +**/* l1 and r1 should already be in "canonical" format */ +** +** l1=MR_compute_pred_tree(l); +** for (r=l->right; r != NULL; r=r->right) { +** r1=MR_compute_pred_tree(r); +** prevl1=l1; +** l1=MR_computeTreeAND(l1,r1); +** Tfree(r1); +** Tfree(prevl1); +** }; +** +**/* result from computeTreeAND should be in "canonical" format */ +** +** result=l1; +** +**/* result of MR_computeTreeAND should be in "canonical" format */ +** +** return result; +** }; +#endif + + if (p->k == 1) { + result=MR_make_tree_from_set(p->scontext[1]); + } else { + result=tdup(p->tcontext); + result=MR_remove_epsilon_from_tree(result); + result=tshrink(result); + result=tflatten(result); + result=tleft_factor(result); + }; + return result; +} + +#ifdef __USE_PROTOS +void MR_pred_depth(Predicate *p,int *maxDepth) +#else +void MR_pred_depth(p,maxDepth) + Predicate *p; + int *maxDepth; +#endif +{ + if (p == NULL) return; + if (p->expr != PRED_OR_LIST && + p->expr != PRED_AND_LIST) { + if (p->k > *maxDepth) *maxDepth=p->k; + }; + MR_pred_depth(p->down,maxDepth); + MR_pred_depth(p->right,maxDepth); +} + +/* this computes the OR of all the contexts */ + +#ifdef __USE_PROTOS +set MR_compute_pred_set(Predicate *p) +#else +set MR_compute_pred_set(p) + Predicate *p; +#endif +{ + set result; + Predicate *q; + + result=empty; + + if (p == NULL) return empty; + + if (p->expr == PRED_OR_LIST || + p->expr == PRED_AND_LIST) { /* yes, I do mean PRED_AND_LIST ! */ + /* remember: r1: (A)? => <

>? r2; */ + /* r2: (B)? => <>? r3; */ + set t; + + t=empty; + result=empty; + + for (q=p->down; q != NULL; q=q->right) { + t=MR_compute_pred_set(q); + set_orin(&result,t); + set_free(t); + }; + return result; + } else if (p->k > 1) { + return empty; + } else { + return set_dup(p->scontext[1]); + }; +} + +#ifdef __USE_PROTOS +set MR_First(int ck,Junction *j,set *incomplete) +#else +set MR_First(ck,j,incomplete) + int ck; + Junction *j; + set *incomplete; +#endif +{ + Junction *p; + set tokensUsed; + + tokensUsed=empty; + + require(j->ntype==nJunction, "MR_First: non junction passed"); + + p = analysis_point((Junction *)j->p1); + + REACH(p,ck,incomplete,tokensUsed); + + return tokensUsed; +} + +#ifdef __USE_PROTOS +void MR_cleanup_pred_trees(Predicate *p) +#else +void MR_cleanup_pred_trees(p) + Predicate *p; +#endif +{ + Tree *t; + + if (p == NULL) return; + if (p->expr != PRED_OR_LIST && + p->expr != PRED_AND_LIST) { + t=p->tcontext; + t=tshrink(t); + t=tflatten(t); + t=tleft_factor(t); + p->tcontext=t; + }; + MR_cleanup_pred_trees(p->down); + MR_cleanup_pred_trees(p->right); +} + +/* does NOT return canonical tree */ + +#ifdef __USE_PROTOS +Tree * MR_remove_epsilon_from_tree(Tree *t) +#else +Tree * MR_remove_epsilon_from_tree(t) + Tree *t; +#endif +{ + if (t == NULL) return NULL; + + /* I think ALT can be ignored as a special case */ + + if (t->token != EpToken) { + t->down=MR_remove_epsilon_from_tree(t->down); + t->right=MR_remove_epsilon_from_tree(t->right); + return t; + } else { + Tree *u; + u=MR_remove_epsilon_from_tree(t->right); + t->right=NULL; + Tfree(t); + return u; + }; +} + +#ifdef __USE_PROTOS +void MR_complete_set(int predDepth,set *tokensUsed,set *incomplete) +#else +void MR_complete_set(predDepth,tokensUsed,incomplete) + int predDepth; + set *tokensUsed; + set *incomplete; +#endif +{ + int i; + RuleRefNode *ruleRef; + set rk2; + set b; + int k2; + Junction *save_MR_RuleBlkWithHalt; + + if (set_int(*incomplete) > (unsigned) predDepth) { + return; + }; + + require(MR_PredRuleRefStack.count == MR_RuleBlkWithHaltStack.count, + "RuleRefStack and RuleBlkWithHaltStack not same size"); + + require(MR_RuleBlkWithHalt == NULL || + (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == TRUE), + "RuleBlkWithHalt has no halt set"); + + save_MR_RuleBlkWithHalt=MR_RuleBlkWithHalt; + + if (MR_RuleBlkWithHalt != NULL) { + MR_RuleBlkWithHalt->end->halt=FALSE; + }; + + for (i=MR_PredRuleRefStack.count-1; i >= 0 ; i--) { + ruleRef=(RuleRefNode *)MR_PredRuleRefStack.data[i]; + if (ruleRef == NULL) continue; + + MR_RuleBlkWithHalt=(Junction *)MR_RuleBlkWithHaltStack.data[i]; + if (MR_RuleBlkWithHalt != NULL) MR_RuleBlkWithHalt->end->halt=TRUE; + + rk2=empty; + b=empty; + + while ( !set_nil(*incomplete) ) { + k2=set_int(*incomplete); + if (k2 > predDepth) break; /* <=== another exit from loop */ + set_rm(k2,*incomplete); + REACH(ruleRef->next,k2,&rk2,b); + set_orin(tokensUsed,b); + set_free(b); + }; + + if (MR_RuleBlkWithHalt != NULL) MR_RuleBlkWithHalt->end->halt=FALSE; + + set_orin(incomplete,rk2); /* remember what we couldn't do */ + set_free(rk2); + if (set_int(*incomplete) > (unsigned) predDepth) break; /* <=== another exit from loop */ + }; + + MR_RuleBlkWithHalt=save_MR_RuleBlkWithHalt; + if (MR_RuleBlkWithHalt != NULL) { + MR_RuleBlkWithHalt->end->halt=TRUE; + }; +} + +#ifdef __USE_PROTOS +void MR_complete_tree(int predDepth,Tree **t,set *incomplete) +#else +void MR_complete_tree(predDepth,t,incomplete) + int predDepth; + Tree **t; + set *incomplete; +#endif +{ + int i; + RuleRefNode *ruleRef; + set rk2; + Tree *u; + unsigned k2; + Junction *save_MR_RuleBlkWithHalt; + int saveConstrainSearch; + + if (set_int(*incomplete) > (unsigned) predDepth) { + return; + }; + + require(MR_PredRuleRefStack.count == MR_RuleBlkWithHaltStack.count, + "RuleRefStack and RuleBlkWithHaltStack not same size"); + + require(MR_RuleBlkWithHalt == NULL || + (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == TRUE), + "RuleBlkWithHalt has no halt set"); + + save_MR_RuleBlkWithHalt=MR_RuleBlkWithHalt; + saveConstrainSearch=ConstrainSearch; + ConstrainSearch=0; + + if (MR_RuleBlkWithHalt != NULL) { + MR_RuleBlkWithHalt->end->halt=FALSE; + }; + + for (i=MR_PredRuleRefStack.count-1; i >= 0 ; i--) { + ruleRef=(RuleRefNode *)MR_PredRuleRefStack.data[i]; + if (ruleRef == NULL) continue; + + MR_RuleBlkWithHalt=(Junction *)MR_RuleBlkWithHaltStack.data[i]; + + if (MR_RuleBlkWithHalt != NULL) MR_RuleBlkWithHalt->end->halt=TRUE; + + rk2=empty; + + while ( !set_nil(*incomplete) ) { + k2 = set_int(*incomplete); + if (k2 > (unsigned) predDepth) break; /* <=== another exit from loop */ + set_rm(k2,*incomplete); + u = NULL; + + TRAV(ruleRef->next,k2,&rk2,u); + + /* any subtrees missing k2 tokens, add u onto end */ + + *t=tlink(*t,u,k2); + Tfree(u); + } + + set_orin(incomplete,rk2); /* remember what we couldn't do */ + set_free(rk2); + + if (MR_RuleBlkWithHalt != NULL) MR_RuleBlkWithHalt->end->halt=FALSE; + + if (set_int(*incomplete) > (unsigned) predDepth) break; /* <=== another exit from loop */ + }; + + MR_RuleBlkWithHalt=save_MR_RuleBlkWithHalt; + + if (MR_RuleBlkWithHalt != NULL) { + MR_RuleBlkWithHalt->end->halt=TRUE; + }; + ConstrainSearch=saveConstrainSearch; +} + +#ifdef __USE_PROTOS +void MR_complete_predicates(int predDepth,Predicate *pred) +#else +void MR_complete_predicates(predDepth,pred) + int predDepth; + Predicate *pred; +#endif +{ + if (pred == NULL) return; + if (pred->expr != PRED_AND_LIST && + pred->expr != PRED_OR_LIST) { + MR_complete_set(predDepth,&(pred->scontext[1]),&(pred->completionSet)); + MR_complete_tree(predDepth,&(pred->tcontext),&(pred->completionTree)); + }; + MR_complete_predicates(predDepth,pred->down); + MR_complete_predicates(predDepth,pred->right); +} + +#ifdef __USE_PROTOS +Junction * MR_junctionWithoutP2(Junction *j) +#else +Junction * MR_junctionWithoutP2(j) + Junction *j; +#endif +{ + Junction *thisAlt; + +/* don't want to follow p2 to the next alternative of this rule */ +/* insert a generic node with null p2 if necessary */ +/* however FIRST requires a junction */ + + thisAlt=j; + if (thisAlt->p2 != NULL) { + if (thisAlt->p1->ntype == nJunction) { + thisAlt=(Junction *) thisAlt->p1; + } else { + thisAlt=newJunction(); + thisAlt->p1=j->p1; + thisAlt->rname=j->rname; + thisAlt->file=j->file; + thisAlt->line=j->line; + j->p1=(Node *)thisAlt; + }; + }; + return thisAlt; +} + +#ifdef __USE_PROTOS +int MR_tree_equ(Tree *big, Tree *small) { +#else +int MR_tree_equ(big,small) + Tree *big; + Tree *small; +{ +#endif + + Tree *b; + Tree *s; + int bcount=0; + int scount=0; + + if (small == NULL && big == NULL) return 1; + if (small == NULL) return 0; + if (big == NULL) return 0; + + if (small->token == ALT) { + require(small->right == NULL, + "MR_tree_equ: small: ALT node has siblings"); + return MR_tree_equ(big,small->down); + }; + if (big->token == ALT) { + require(big->right == NULL, + "MR_tree_equ: big: ALT node has siblings"); + return MR_tree_equ(big->down,small); + }; + for (s=small; s != NULL; s=s->right) { + scount++; + require(s->token != EpToken,"MR_tree_equ: s->EpToken unexpected\n"); + }; + for (b=big; b != NULL; b=b->right) { + bcount++; + require(b->token != EpToken,"MR_tree_equ: b->EpToken unexpected\n"); + }; + + if (bcount != scount) return 0; + + for (s=small; s != NULL; s=s->right) { + for (b=big; b!= NULL; b=b->right) { + if (s->token == b->token) { + if (MR_tree_equ(b->down,s->down)) goto next_s; + }; + }; + return 0; +next_s: + continue; + }; + return 1; +} + +/* this does not compare sources - only contexts ! */ + +#ifdef __USE_PROTOS +int MR_identicalContext(Predicate *p,Predicate *q) +#else +int MR_identicalContext(p,q) + Predicate *p; + Predicate *q; +#endif +{ + if (p->k != q->k) return 0; + require ( (p->tcontext == NULL) == (q->tcontext == NULL), + "tcontext inconsistent"); + if (p->k == 1) { + return set_equ(p->scontext[1],q->scontext[1]); + } else { + return MR_tree_equ(p->tcontext,q->tcontext); + }; +} + +#ifdef __USE_PROTOS +void MR_reportSetSuppression(int predDepth, + set predSet,set plainSet,Junction *jPred,Junction *jPlain,Predicate *p) +#else +void MR_reportSetSuppression(predDepth,predSet,plainSet,jPred,jPlain,p) + int predDepth; + set predSet; + set plainSet; + Junction *jPred; + Junction *jPlain; + Predicate *p; +#endif +{ + if (InfoP) { + fprintf(output,"\n#if 0\n\n"); + fprintf(output,"Hoisting of predicate suppressed by alternative without predicate.\n"); + fprintf(output,"The alt without the predicate includes all cases where the predicate is false.\n\n"); + fprintf(output," WITH predicate: line %d %s\n",jPred->line,FileStr[jPred->file]); + if (jPlain != NULL) { + fprintf(output," WITHOUT predicate: line %d %s\n",jPlain->line,FileStr[jPlain->file]); + } else { + fprintf(output," WITHOUT predicate: all alternatives without predicates (combined)\n"); + }; + if (predDepth == 1) { + fprintf(output,"\nThe context set for the predicate:\n"); + MR_dumpTokenSet(output,1,predSet); + }; + fprintf(output,"\nThe lookahead set for the alt WITHOUT the semantic predicate:\n"); + MR_dumpTokenSet(output,1,plainSet); + fprintf(output,"\nThe predicate:\n\n"); + MR_dumpPred1(1,p,1); + fprintf(output,"Chain of referenced rules:\n\n"); + MR_dumpPredRuleRefStack(output,4); + fprintf(output,"\n#endif\n"); + }; +} + +#ifdef __USE_PROTOS +void MR_reportSetRestriction(int predDepth,set predSet,set plainSet, + Junction *jPred,Junction *jPlain,Predicate *origPred,Predicate *newPred) +#else +void MR_reportSetRestriction(predDepth,predSet,plainSet,jPred,jPlain,origPred,newPred) + int predDepth; + set predSet; + set plainSet; + Junction *jPred; + Junction *jPlain; + Predicate *origPred; + Predicate *newPred; +#endif +{ + set intersect; + + intersect=empty; + + if (! InfoP) return; + fprintf(output,"\n#if 0\n\n"); + fprintf(output,"Restricting the context of a predicate because of overlap in the lookahead set\n"); + fprintf(output," between the alternative with the semantic predicate and one without\n"); + fprintf(output,"Without this restriction the alternative without the predicate could not\n"); + fprintf(output," be reached when input matched the context of the predicate and the predicate\n"); + fprintf(output," was false.\n\n"); + + fprintf(output," WITH predicate: line %d %s\n",jPred->line,FileStr[jPred->file]); + if (jPlain != NULL) { + fprintf(output," WITHOUT predicate: line %d %s\n",jPlain->line,FileStr[jPlain->file]); + } else { + fprintf(output," WITHOUT predicate: all alternatives without predicates (combined)\n"); + }; + if (predDepth == 1) { + fprintf(output,"\nThe original context set for the predicate:\n"); + MR_dumpTokenSet(output,1,predSet); + }; + fprintf(output,"\nThe lookahead set for the alt WITHOUT the semantic predicate:\n"); + MR_dumpTokenSet(output,1,plainSet); + if (predDepth == 1) { + fprintf(output,"\nThe intersection of the two sets\n"); + intersect=set_and(predSet,plainSet); + MR_dumpTokenSet(output,1,intersect); + set_free(intersect); + }; + fprintf(output,"\nThe original predicate:\n\n"); + MR_dumpPred1(1,origPred,1); + fprintf(output,"The new (modified) form of the predicate:\n\n"); + MR_dumpPred1(1,newPred,1); + fprintf(output,"#endif\n"); +} + +/* don't use Pass3 by itself unless you know that inverted is not important */ + +#ifdef __USE_PROTOS +Predicate * MR_removeRedundantPredPass3(Predicate *p) +#else +Predicate * MR_removeRedundantPredPass3(p) + Predicate *p; +#endif +{ + Predicate *q; + + if (p == NULL) return NULL; + p->right=MR_removeRedundantPredPass3(p->right); + p->down=MR_removeRedundantPredPass3(p->down); + if (p->redundant) { + q=p->right; + p->right=NULL; + predicate_free(p); + return q; + }; + if (p->expr == PRED_AND_LIST || + p->expr == PRED_OR_LIST) { + if (p->down == NULL) { + q=p->right; + p->right=NULL; + predicate_free(p); + return q; + }; + if (p->down != NULL && p->down->right == NULL) { + q=p->down; + q->right=p->right; + p->right=NULL; + p->down=NULL; + return q; + }; + }; + return p; +} + +#ifdef __USE_PROTOS +void MR_removeRedundantPredPass2(Predicate *p) +#else +void MR_removeRedundantPredPass2(p) + Predicate *p; +#endif +{ + Predicate *q; + + if (p == NULL) return; + + if (p->expr == PRED_AND_LIST) { + for (q=p->down ; q != NULL ; q=q->right) { + MR_removeRedundantPredPass2(q); + if (q->isConst) { + if (q->constValue == 0) { + p->isConst=1; + p->constValue=0; + return; + } else { + q->redundant=1; + }; + }; + }; + }; + + if (p->expr == PRED_OR_LIST) { + for (q=p->down ; q != NULL ; q=q->right) { + MR_removeRedundantPredPass2(q); + if (q->isConst) { + if (q->constValue == 0) { + q->redundant=1; + } else { + p->isConst=1; + p->constValue=1; + return; + }; + }; + }; + }; + + return; +} + +#if 0 + this totally ignores the implications of guarded predicates + in which the part after the guard could possibly cover a predicate. + that would be much harder: + + rule : (A)? => <

>? sub1; /* 1 */ + | (B)? => <>? sub2 /* 2 */ + sub1 : (A)? => <>? A B /* 3 */ + | B /* 4 - suppresses line 2 */ + ; +#endif + +#ifdef __USE_PROTOS +void MR_apply_restriction1(Predicate *pred,set *plainSet,int *changed) +#else +void MR_apply_restriction1(pred,plainSet,changed) + Predicate *pred; + set *plainSet; + int *changed; +#endif +{ + if (pred == NULL) return; + MR_apply_restriction1(pred->right,plainSet,changed); + if (pred->down != NULL) { + MR_apply_restriction1(pred->down,plainSet,changed); + } else { + set t; + if (pred->k == 1) { + t=set_dif(pred->scontext[1],*plainSet); + if (*changed == 0 && + !set_equ(t,pred->scontext[1])) { + *changed=1; + }; + if (set_nil(t)) { + pred->redundant=1; + }; + set_free(pred->scontext[1]); + pred->scontext[1]=t; + }; + }; +} + +#ifdef __USE_PROTOS +void MR_orin_plainSet(Predicate *p,set plainSet) +#else +void MR_orin_plainSet(p,plainSet) + Predicate *p; + set plainSet; +#endif +{ + if (p == NULL) return; + MR_orin_plainSet(p->down,plainSet); + MR_orin_plainSet(p->right,plainSet); + set_orin(&p->plainSet,plainSet); +} + +Predicate *PRED_SUPPRESS; + +#ifdef __USE_PROTOS +Predicate * MR_find_in_aSubBlk(Junction *alt) +#else +Predicate * MR_find_in_aSubBlk(alt) + Junction *alt; +#endif +{ + Predicate *root=NULL; + Predicate **tail=NULL; + + Junction *p; + + int nAlts=0; + Junction **jList; + Predicate **predList; + int *matchList; + set predSet; + int i; + int j; + int m; + int predDepth; + set incomplete; + set union_plainSet; + set setChange; + int changed; + Predicate *newPred; + set setDif; + Predicate *origPred; + int depth1=1; /* const int */ + set *plainContext; + set plainSet; + + predSet=empty; + incomplete=empty; + union_plainSet=empty; + setChange=empty; + setDif=empty; + plainSet=empty; + + if (PRED_SUPPRESS == NULL) { + PRED_SUPPRESS=new_pred(); + PRED_SUPPRESS->expr="Predicate Suppressed"; + }; + + /* this section just counts the number of "interesting" alternatives */ + /* in order to allocate arrays */ + + for (p=alt; p!=NULL; p=(Junction *)p->p2) { + /* ignore empty alts */ + if ( p->p1->ntype != nJunction || + ((Junction *)p->p1)->jtype != EndBlk ) { + nAlts++; + }; + }; + + /* if this is a (...)+ block then don't count the last alt because + it can't be taken until at least one time through the block. + In other words it isn't a real choice until the (...)+ is entered + at which point the hoisting issue is moot. + Maybe look at "ignore" instead ? + */ + + if (alt->jtype == aPlusBlk) { + nAlts--; + }; + + jList=(Junction **)calloc(nAlts,sizeof(Junction *)); + require(jList!=NULL,"cannot allocate MR_find_in_aSubBlk jList"); + + plainContext=(set *)calloc(nAlts,sizeof(set)); + require(plainContext!=NULL,"cannot allocate MR_find_in_aSubBlk plainContext"); + for (m=0; m < nAlts; m++) plainContext[m]=empty; + + predList=(Predicate **)calloc(nAlts,sizeof(Predicate *)); + require(predList!=NULL,"cannot allocate MR_find_in_aSubBlk predList"); + + matchList=(int *)calloc(nAlts,sizeof(int)); + require(matchList!=NULL,"cannot allocate MR_find_in_aSubBlk matchList"); + + /* this section just fills in the arrays previously allocated */ + /* the most interesting one is matchList[] */ + /* */ + /* bit 0 => this alt has a semantic pred which is "covered" */ + /* by an alt without a semantic pred. Don't hoist. */ + + for (i=0,p=alt; + p!=NULL && ip2) { + + /* ignore empty alts */ + + if ( p->p1->ntype != nJunction || + ((Junction *)p->p1)->jtype != EndBlk ) { + jList[i]=MR_junctionWithoutP2(p); + predList[i]=find_predicates(p->p1); /* should be jList ????? */ + if (predList[i] != NULL) { + MR_cleanup_pred_trees(predList[i]); /* flatten & left factor */ + plainContext[i]=MR_union_plain_sets(predList[i]); + } else { + MR_set_reuse(&plainSet); + MR_set_reuse(&incomplete); + plainSet=MR_First(depth1,jList[i],&incomplete); + MR_complete_set(depth1,&plainSet,&incomplete); + require(set_nil(incomplete),"couldn't complete k=1"); + plainContext[i]=plainSet; + plainSet=empty; + }; + set_orin(&union_plainSet,plainContext[i]); + }; + }; + + if (nAlts == 1) { + goto EXIT_SIMPLE; + }; + +/* + * Looking for cases where alt i has a semantic pred and alt j does not. + * Don't care about cases where lookahead for semantic predicates overlap + * because normal predicate hoisting does the correct thing automatically. + * Don't care about cases where lookahead for alts without semantic predicates + * overlap because normal prediction does the correct thing automatically. + * + * When we find such a case check for one of three subcases: + * + * 1. if lookahead for alt i is contained in the lookahead for any + * alt j then ignore semantic predicate of alt i + * 2. if lookahead for alt i is not contained in the lookahead for + * any alt j then add add predicate i to the OR list to be hoisted + * 3. if lookahead for alt i overlaps the lookahead for some alt j then + * add a dummy semantic predicate for alt j + * + * There is an implicit assumption that the context of all alternatives following + * the rule being processed here are identical (but may vary from hoist to + * hoist depending on the place where the rule was invoked that led to hoisting + * these predicates. In othere words in the fragment: + * + * ( <>? a1 a2 a3 | <>? b1 b2 b3 ) + * + * both a3 and b3 have the same follow sets because they are both at the end of + * alternatives in the same block. + */ + + for (i=0; i < nAlts; i++) { + if (jList[i] == NULL) continue; + if (predList[i] == NULL) continue; + + /* if the predicate depth turns out to be one token only */ + /* then it is can be easily represented as a set and */ + /* compared to the junction set create by MR_First() */ + + predDepth=0; + MR_pred_depth(predList[i],&predDepth); + require (predDepth >= 1,"MR_find_in_aSubBlk: pred depth < 1"); + require (predDepth <= CLL_k,"MR_find_in_aSubBlk: predDepth > CLL_k"); + + /* complete predicates to predDepth + If completed to depth=1 then the context would be incomplete. + The context would be truncated and the predicate simplify routine + would have incomplete information. It would lead to + either false matches of failure to find true matches. + */ + + MR_complete_predicates(predDepth,predList[i]); + + if (predList[i] != NULL) { + MR_cleanup_pred_trees(predList[i]); /* flatten & left factor */ + }; + + /* If the predicate depth is 1 then it is possible to suppress + a predicate completely using a single plain alt. Check for suppression + by a single plain alt first because it gives better messages. If that + fails try the union of all the plain alts. + */ + + if (predDepth == 1) { + + MR_set_reuse(&predSet); + predSet=MR_compute_pred_set(predList[i]); /* ignores k>1 predicates */ + + for (j=0; j < nAlts; j++) { + if (jList[j] == NULL) continue; + if (j == i) continue; + + MR_set_reuse(&setDif); + setDif=set_dif(predSet,plainContext[j]); + if (set_nil(setDif)) { + matchList[i] |= 1; + MR_reportSetSuppression(predDepth,predSet,plainContext[j],jList[i],jList[j],predList[i]); + predicate_free(predList[i]); + predList[i]=PRED_SUPPRESS; + goto next_i; + }; + + }; /* end loop on j */ + + changed=0; + + /* predicate_dup is only to give good error messages */ + /* remember to do a predicate_free() */ + + origPred=predicate_dup(predList[i]); + MR_apply_restriction1(predList[i],&union_plainSet,&changed); + if (changed) { + + /* don't use Pass3 by itself unless you know that inverted is not important */ + + newPred=MR_removeRedundantPredPass3(predList[i]); + newPred=MR_predSimplifyALL(newPred); + if (newPred == NULL) { + matchList[i] |= 1; + MR_reportSetSuppression(predDepth,predSet,union_plainSet,jList[i], + NULL,origPred); + predList[i]=PRED_SUPPRESS; + } else { + MR_reportSetRestriction(predDepth,predSet,union_plainSet,jList[i], + NULL,origPred,newPred); + predList[i]=newPred; + }; + }; + predicate_free(origPred); + origPred=NULL; + }; + + /* + If the predicate depth is > 1 then it can't be suppressed completely + because the code doesn't support inspection of such things. They're + much messier than k=1 sets. + */ + + if (predDepth > 1 ) { + + changed=0; + + /* predicate_dup is only to give good error messages */ + /* remember to do a predicate_free() */ + + origPred=predicate_dup(predList[i]); + MR_apply_restriction1(predList[i],&union_plainSet,&changed); + if (changed) { + newPred=MR_removeRedundantPredPass3(predList[i]); + newPred=MR_predSimplifyALL(newPred); + if (newPred == NULL) { + matchList[i] |= 1; + MR_reportSetSuppression(predDepth,predSet,union_plainSet,jList[i], + NULL,origPred); + predList[i]=PRED_SUPPRESS; + } else { + MR_reportSetRestriction(predDepth,predSet,union_plainSet,jList[i], + NULL,origPred,newPred); + predList[i]=newPred; + }; + }; + predicate_free(origPred); + origPred=NULL; + }; +next_i: + continue; + }; + +EXIT_SIMPLE: + + root = new_pred(); + root->expr=PRED_OR_LIST; + tail = &(root->down); + + for (i=0 ; i< nAlts ; i++) { + if (jList[i] == NULL) continue; + + if (predList[i] == NULL) { + continue; + } else if ( (matchList[i] & 1) != 0) { + if (predList[i] != PRED_SUPPRESS) { + predicate_free(predList[i]); + }; + continue; + }; + + /* make an OR list of predicates */ + + *tail=predList[i]; + tail=&(predList[i]->right); + }; + + /* if just one pred, remove OR root */ + + if (root->down == NULL) { + predicate_free(root); + root=NULL; + } else if (root->down->right == NULL) { + Predicate *p=root->down; + root->down=NULL; + predicate_free(root); + root=p; + } + + root=MR_predSimplifyALL(root); + + MR_orin_plainSet(root,union_plainSet); + + set_free(predSet); + set_free(union_plainSet); + set_free(incomplete); + set_free(setChange); + set_free(setDif); + + for (m=0; m < nAlts; m++) set_free(plainContext[m]); + + free ( (char *) jList); + free ( (char *) predList); + free ( (char *) matchList); + free ( (char *) plainContext); + + return root; +} + +#ifdef __USE_PROTOS +void MR_predContextPresent(Predicate *p,int *allHaveContext,int *noneHaveContext) +#else +void MR_predContextPresent(p,allHaveContext,noneHaveContext) + Predicate *p; + int *allHaveContext; + int *noneHaveContext; +#endif +{ + if (p == NULL) return; + MR_predContextPresent(p->right,allHaveContext,noneHaveContext); + if (p->expr != PRED_AND_LIST && + p->expr != PRED_OR_LIST) { + if (set_nil(p->scontext[1]) == 0 || + (p->tcontext != NULL)) { + *noneHaveContext=0; + } else { + *allHaveContext=0; + }; + }; + MR_predContextPresent(p->down,allHaveContext,noneHaveContext); +} + +#ifdef __USE_PROTOS +int MR_pointerStackPush(PointerStack *ps,void *dataPointer) +#else +int MR_pointerStackPush(ps,dataPointer) + PointerStack *ps; + void *dataPointer; +#endif +{ + void **newStack; + int newSize; + int i; + + if (ps->count == ps->size) { + newSize=20+ps->size*2; + newStack=(void **)calloc(newSize,sizeof(void *)); + require (newStack != NULL,"cannot allocate PointerStack"); + for (i=0; i < ps->size; i++) { + newStack[i]=ps->data[i]; + }; + if (ps->data != NULL) free( (char *) ps->data); + ps->data=newStack; + ps->size=newSize; + }; + ps->data[ps->count]=dataPointer; + ps->count++; + return ps->count-1; +} + +#ifdef __USE_PROTOS +void * MR_pointerStackPop(PointerStack *ps) +#else +void * MR_pointerStackPop(ps) + PointerStack *ps; +#endif +{ + void *dataPointer; + + require(ps->count > 0,"MR_pointerStackPop underflow"); + + dataPointer=ps->data[ps->count-1]; + ps->data[ps->count-1]=NULL; + (ps->count)--; + return dataPointer; +} + +#ifdef __USE_PROTOS +void * MR_pointerStackTop(PointerStack *ps) +#else +void * MR_pointerStackTop(ps) + PointerStack *ps; +#endif +{ + require(ps->count > 0,"MR_pointerStackTop underflow"); + return ps->data[ps->count-1]; +} + +#ifdef __USE_PROTOS +void MR_pointerStackReset(PointerStack *ps) +#else +void MR_pointerStackReset(ps) + PointerStack *ps; +#endif +{ + int i; + if (ps->data != NULL) { + for (i=0; i < ps->count ; i++) { + ps->data[i]=NULL; + }; + }; + ps->count=0; +} + +#ifdef __USE_PROTOS +Junction *MR_nameToRuleBlk(char *name) +#else +Junction *MR_nameToRuleBlk(name) + char *name; +#endif +{ + RuleEntry *q; + + require (RulePtr != NULL,"MR_nameToRule: RulePtr not initialized"); + + if (name == NULL) return NULL; + + q = (RuleEntry *) hash_get(Rname,name); + + if ( q == NULL ) { + return NULL; + } else { + return RulePtr[q->rulenum]; + }; +} + +#ifdef __USE_PROTOS +Junction * MR_ruleReferenced(RuleRefNode *rrn) +#else +Junction * MR_ruleReferenced(rrn) + RuleRefNode *rrn; +#endif +{ + return MR_nameToRuleBlk(rrn->text); +} + +#ifdef __USE_PROTOS +void MR_comparePredLeaves(Predicate *me,Predicate *myParent,Predicate *him,Predicate *hisParent) +#else +void MR_comparePredLeaves(me,myParent,him,hisParent) + Predicate *me; + Predicate *myParent; + Predicate *him; + Predicate *hisParent; +#endif +{ + if (me == NULL) return; + if (me == him) { + MR_comparePredLeaves(me->right,myParent,him,hisParent); + return; + } else if (me->expr == PRED_AND_LIST || + me->expr == PRED_OR_LIST) { + MR_comparePredLeaves(me->down,me,him,hisParent); + MR_comparePredLeaves(me->right,myParent,him,hisParent); + return; + } else { + if (me->source != NULL) { + + /* predicate->invert can be set only in the predEntry predicates */ + /* thus they are only visible after the predEntry predicates have been "unfolded" */ + + int sameSource=(me->source == him->source); + int sameInvert=1 & + (1 + me->inverted + him->inverted + me->source->inverted + him->source->inverted); + int samePredEntry=(me->source->predEntry != NULL + && him->source->predEntry != NULL + && me->source->predEntry == him->source->predEntry); + if (sameInvert && (sameSource || samePredEntry)) { + if (MR_identicalContext(me,him)) { + + /* identical predicates */ + + if (hisParent->expr == PRED_OR_LIST && + myParent->expr == PRED_OR_LIST) { + me->redundant=1; + } else if (hisParent->expr == PRED_AND_LIST && + myParent->expr == PRED_AND_LIST) { + me->redundant=1; + } else if ( (hisParent->expr == PRED_OR_LIST && + myParent->expr == PRED_AND_LIST) + || + (hisParent->expr == PRED_AND_LIST && + myParent->expr == PRED_OR_LIST) + ) { + myParent->redundant=1; + } else { + require (0,"MR_comparePredLeaves: not both PRED_LIST"); + }; + }; + }; /* end same source or same predEntrr with same invert sense */ + + /* same predEntry but opposite invert sense */ + + if (!sameInvert && (sameSource || samePredEntry)) { + if (MR_identicalContext(me,him)) { + if (hisParent->expr == PRED_OR_LIST && + myParent->expr == PRED_OR_LIST) { + myParent->isConst=1; + myParent->constValue=1; + } else if (hisParent->expr == PRED_AND_LIST && + myParent->expr == PRED_AND_LIST) { + myParent->isConst=1; + myParent->constValue=0; + } else if ( (hisParent->expr == PRED_OR_LIST && + myParent->expr == PRED_AND_LIST) + || + (hisParent->expr == PRED_AND_LIST && + myParent->expr == PRED_OR_LIST) + ) { + me->redundant=1; + } else { + require (0,"MR_comparePredLeaves: not both PRED_LIST"); + }; + }; + }; /* end same predEntry with opposite invert sense */ + }; + + MR_comparePredLeaves(me->right,myParent,him,hisParent); + return; + }; +} + +#ifdef __USE_PROTOS +void MR_removeRedundantPredPass1(Predicate *me,Predicate *myParent) +#else +void MR_removeRedundantPredPass1(me,myParent) + Predicate *me; + Predicate *myParent; +#endif +{ + if (me == NULL) return; + if (me->redundant) { + MR_removeRedundantPredPass1(me->right,myParent); + return; + }; + if (me->expr == PRED_AND_LIST || + me->expr == PRED_OR_LIST) { + MR_removeRedundantPredPass1(me->down,me); + MR_removeRedundantPredPass1(me->right,myParent); + } else { + require (me->source != NULL,"me->source == NULL"); + if (myParent != NULL) { + MR_comparePredLeaves(myParent->down,myParent,me,myParent); + }; + MR_removeRedundantPredPass1(me->right,myParent); + }; +} + +/* pretty much ignores things with the inverted bit set */ + +#ifdef __USE_PROTOS +Predicate *MR_predFlatten(Predicate *p) +#else +Predicate *MR_predFlatten(p) + Predicate *p; +#endif +{ + if (p == NULL) return NULL; + if (p->expr == PRED_OR_LIST + || p->expr == PRED_AND_LIST) { + + Predicate *child; + Predicate *gchild; + Predicate **tail; + Predicate *next; + char *PRED_XXX_LIST=p->expr; + + require (p->down != NULL,"MR_predFlatten AND/OR no child"); + + + p->down=MR_predFlatten(p->down); + p->right=MR_predFlatten(p->right); + child=p->down; + if (child->right == NULL) { + child->right=p->right; + p->right=NULL; + p->down=NULL; + if (p->inverted) child->inverted=!child->inverted; + predicate_free(p); + return child; + }; + + /* make a single list of all children and grandchildren */ + + tail=&(p->down); + for (child=p->down; child != NULL; child=next) { + if (child->expr != PRED_XXX_LIST + || child->inverted + || child->predEntry != NULL) { + *tail=child; + tail=&(child->right); + next=child->right; + } else { + for (gchild=child->down; + gchild != NULL; + gchild=gchild->right) { + *tail=gchild; + tail=&(gchild->right); + }; + next=child->right; + child->right=NULL; + child->down=NULL; + predicate_free(child); + }; + }; + *tail=NULL; + return p; + } else { + p->right=MR_predFlatten(p->right); + return p; + }; +} + +static char *alwaysFalseWarning=NULL; + +#ifdef __USE_PROTOS +Predicate *checkPredicateConflict(Predicate *p) +#else +Predicate *checkPredicateConflict(p) + Predicate *p; +#endif +{ + if (p->isConst) { + if (p->constValue == 1) { + predicate_free(p); + return NULL; + } else { + if (InfoP && !p->conflictReported) { + p->conflictReported=1; + fprintf(output,"\n#if 0\n\n"); + fprintf(output,"The following predicate expression will always be false:\n\n"); + MR_dumpPred1(1,p,1); + fprintf(output,"\n#endif\n"); + }; + + if (alwaysFalseWarning != CurRule) { + alwaysFalseWarning=CurRule; + if (InfoP) { + warnNoFL(eMsg1("one (or more) predicate expression hoisted into rule \"%s\" are always false \ +- see output file for more information",CurRule)); + } else { + warnNoFL(eMsg1("one (or more) predicate expressions hoisted into rule \"%s\" are always false \ +- use \"-info p\" for more information",CurRule)); + }; + }; + }; + }; + return p; +} + + +#ifdef __USE_PROTOS +int MR_countPredNodes(Predicate *p) +#else +int MR_countPredNodes(p) + Predicate *p; +#endif +{ + if (p == NULL) return 0; + return 1 + MR_countPredNodes(p->down) + MR_countPredNodes(p->right); +} + +#ifdef __USE_PROTOS +Predicate *MR_predSimplifyALLX(Predicate *p,int skipPass3) +#else +Predicate *MR_predSimplifyALLX(p,skipPass3) + Predicate *p; + int skipPass3; +#endif +{ + int countBefore; + int countAfter; + + countAfter=MR_countPredNodes(p); + + do { + if (p == NULL) return NULL; + if (p->right == NULL && p->down == NULL) return p; + countBefore=countAfter; + MR_simplifyInverted(p,0); + p=MR_predFlatten(p); + MR_removeRedundantPredPass1(p,NULL); + MR_removeRedundantPredPass2(p); + if (! skipPass3) { + p=checkPredicateConflict(p); + p=MR_removeRedundantPredPass3(p); + }; + countAfter=MR_countPredNodes(p); + } while (countBefore != countAfter); + + return p; +} + +#ifdef __USE_PROTOS +Predicate *MR_predSimplifyALL(Predicate *p) +#else +Predicate *MR_predSimplifyALL(p) + Predicate *p; +#endif +{ + return MR_predSimplifyALLX(p,0); +} + +#ifdef __USE_PROTOS +void MR_releaseResourcesUsedInRule(Node *n) +#else +void MR_releaseResourcesUsedInRule(n) + Node *n; +#endif +{ + Node *next; + Junction *j; + int i; + + if (n == NULL) return; + if (n->ntype == nJunction) { + j=(Junction *) n; + + if (j->predicate != NULL) { + predicate_free(j->predicate); + j->predicate=NULL; + }; + for (i=0; i< CLL_k; i++) { + set_free(j->fset[i]); + j->fset[i]=empty; + }; + if (j->ftree != NULL) { + Tfree(j->ftree); + j->ftree=NULL; + }; + if (j->jtype == EndRule) return; + if (j->jtype != RuleBlk && j->jtype != EndBlk) { + if (j->p2 != NULL && !j->ignore) { /* MR11 */ + MR_releaseResourcesUsedInRule(j->p2); + }; + }; + }; + next=MR_advance(n); + MR_releaseResourcesUsedInRule(next); +} + +#ifdef __USE_PROTOS +int MR_allPredLeaves(Predicate *p) +#else +int MR_allPredLeaves(p) + Predicate *p; +#endif +{ + Predicate *q; + + if (p == NULL) return 1; + + for (q=p; q != NULL; q=q->right) { + if (q->down != NULL) return 0; + }; + return 1; +} + +/* make sure it works for the last rule in a file */ + +#ifdef __USE_PROTOS +int MR_offsetFromRule(Node *n) +#else +int MR_offsetFromRule(n) + Node *n; +#endif +{ + Junction *j; + int offset=(-1); + + for (j=SynDiag; j != NULL; j=(Junction *)j->p2) { + + require (j->ntype == nJunction && j->jtype == RuleBlk,"Not a rule block"); + + if (n->file < j->file) { + return offset; + }; + if (n->file == j->file) { + if (n->line < j->line) { + return (offset < 0) ? 0 : offset; + } else { + offset=n->line - j->line; + if (offset == 0) return 0; + }; + }; + }; + return offset; +} + +#define ruleNameMax 50 + +static char ruleNameStatic1[ruleNameMax]; +static char ruleNameStatic2[ruleNameMax+10]; + +#ifdef __USE_PROTOS +char * MR_ruleNamePlusOffset(Node *n) +#else +char * MR_ruleNamePlusOffset(n) + Node *n; +#endif +{ + int offset=MR_offsetFromRule(n); + + strncpy(ruleNameStatic1,n->rname,ruleNameMax); + if (offset < 0) { + sprintf(ruleNameStatic2,"%s/?",ruleNameStatic1); + } else { + sprintf(ruleNameStatic2,"%s/%d",ruleNameStatic1,offset+1); + }; + return ruleNameStatic2; +} + +#ifdef __USE_PROTOS +int MR_max_height_of_tree(Tree *t) +#else +int MR_max_height_of_tree(t) + Tree *t; +#endif +{ + int h; + int height=0; + Tree *u; + + if (t == NULL) return 0; + + require (t->token != ALT && t->token != EpToken,"MR_max_height_of_tree ALT or EpToken"); + + for (u=t; u != NULL; u=u->right) { + h=MR_max_height_of_tree(u->down)+1; + if (h > height) height=h; + }; + return height; +} + +#ifdef __USE_PROTOS +int MR_all_leaves_same_height(Tree *t,int depth) +#else +int MR_all_leaves_same_height(t,depth) + Tree *t; + int depth; +#endif +{ + if (t == NULL) { + return (depth==0); + }; + + require (t->token != ALT && t->token != EpToken,"MR_all_leaves_same_height ALT or EpToken"); + + if (depth == 0) { + return 0; + } else { + if ( ! MR_all_leaves_same_height(t->down,depth-1)) { + return 0; + }; + if (t->right == NULL) { + return 1; + } else { + return MR_all_leaves_same_height(t->right,depth); + }; + }; +} + +#ifdef __USE_PROTOS +void MR_projectTreeOntoSet(Tree *tree,int ck,set *ckset) +#else +void MR_projectTreeOntoSet(tree,ck,ckset) + Tree *tree; + int ck; + set *ckset; +#endif +{ + if (tree == NULL) return; + + require(tree->token != EpToken,"MR_projectTreeOntoSet: EpToken unexpected\n"); + + MR_projectTreeOntoSet(tree->right,ck,ckset); + if (tree->token == ALT) { + MR_projectTreeOntoSet(tree->down,ck,ckset); + } else { + if (ck > 1) { + MR_projectTreeOntoSet(tree->down,ck-1,ckset); + } else { + set_orel(tree->token,ckset); + }; + }; +} + +#ifdef __USE_PROTOS +int MR_comparePredicates(Predicate *a,Predicate *b) +#else +int MR_comparePredicates(a,b) + Predicate *a; + Predicate *b; +#endif +{ + Predicate *p; + Predicate *q; + + if (a == b) return 1; + if (a == NULL || b == NULL ) return 0; + if (a->down == NULL && b->down == NULL) { + + /* predicate->invert can be set only in the predEntry predicates */ + /* thus they are only visible after the predEntry predicates have been "unfolded" */ + + int sameSource=(a->source == b->source); + int sameInvert= 1 & (1 +a->inverted + b->inverted + + a->source->inverted + b->source->inverted); + int samePredEntry=(a->source->predEntry != NULL + && b->source->predEntry != NULL + && a->source->predEntry == b->source->predEntry); + if (sameInvert && (sameSource || samePredEntry)) { + if (MR_identicalContext(a,b)) { + return 1; + }; + }; + return 0; + }; + if (a->down == NULL || b->down == NULL) return 0; + if (a->expr != b->expr) return 0; + + for (p=a->down; p != NULL; p=p->right) { + for (q=b->down; q != NULL; q=q->right) { + if (MR_comparePredicates(p,q)) goto NEXT_P; + }; + return 0; +NEXT_P: + continue; + }; + return 1; +} + +/* + * action->inverted can be set only when a predicate symbol appears in + * a rule: "rule : <>? X". It cannot be set under any + * other circumstances. In particular it cannot be set by + * "#pred NotA !A" or by "#pred Nota <>?". The first case + * creates a predEntry and the predicate expression of that predEntry + * has inverted set. In the second case, the code for handling "!" + * is only present in buildAction, which is not called by the #pred + * semantic routines, only when a <<...>>? is recognized as part of + * a rule definition. + * + * predicate->inverted can only be set by a predicate created by a #pred + * expression, such as "#pred NotA !A" or "#pred NotXY ! (X && Y) or + * "#pred XbarY !(X && Y)". In particular, it cannot be set by any + * predicate expression occurring under any other circumstances. + * The #pred predicate expressions are stored with in predEntry->pred + * and do not normally appear anywhere else until the predicates are + * "unfolded" in order to recognize redundancies, conflicts, and + * tautologies. + * + * The unfold routine expands all references to #pred expressions. + * + * The simplifyInvert goes through and propagates the invert bit so that + * all OR and AND nodes are un-inverted. + * + * Note that !(A and B) => (!A or !B) + * !(A or B) => (!A and !B) + * + * MR_unfold() is called to expand predicate symbols by replacing predicates + * that reference predicate entries with the copies of the predicate entries. + * Each reference receives a duplicate of the original. This is necessary + * because the next phase involves simplification and removal of redundant + * predicate nodes. Anyway, the point I'm making is that predicate->invert + * should not be set in any predicate until it has been expanded. + * + * This is a recursive structure, but there is no need for "recursive expansion" + * by which I mean a predicate symbol refers to other predicate symbols which + * must also be expanded. + * + * Recursive expansion is *not* performed by this routine because it is not + * necessary. Expansion of references is performed by predPrimary when + * a new predicate symbol is created by referring to others in the pred expr. + */ + +#ifdef __USE_PROTOS +Predicate *MR_unfold(Predicate *pred) +#else +Predicate *MR_unfold(pred) + Predicate *pred; +#endif +{ + Predicate *result; + + if (pred == NULL) return NULL; + + pred->right=MR_unfold(pred->right); + + if (pred->down == NULL) { + if (pred->source->predEntry != NULL) { + if (pred->source->predEntry->pred == NULL) { + ; /* do nothing */ /* a reference to a literal #pred (perhaps with "!" */ + } else { + result=predicate_dup_without_context(pred->source->predEntry->pred); + if (pred->inverted) { + result->inverted=!result->inverted; + }; + if (pred->source->inverted) { + result->inverted=!result->inverted; + }; + result->right=pred->right; + pred->right=NULL; + predicate_free(pred); +/*** result=MR_unfold(result); *** not necessary */ /* recursive expansion */ + return result; + }; + } else { + ; /* do nothing */ /* an inline literal predicate */ + }; + } else { + pred->down=MR_unfold(pred->down); + }; + return pred; +} + +/* this should be called immediately after MR_unfold() and + at no other times +*/ + +#ifdef __USE_PROTOS +void MR_simplifyInverted(Predicate *pred,int inverted) +#else +void MR_simplifyInverted(pred,inverted) + Predicate *pred; + int inverted; +#endif +{ + int newInverted; + + if (pred == NULL) return; + + MR_simplifyInverted(pred->right,inverted); + + newInverted= 1 & (inverted + pred->inverted); + + if (pred->down == NULL) { + pred->inverted=newInverted; + } else { + if (newInverted != 0) { + if (pred->expr == PRED_AND_LIST) { + pred->expr=PRED_OR_LIST; + } else { + pred->expr=PRED_AND_LIST; + }; + }; + pred->inverted=0; + MR_simplifyInverted(pred->down,newInverted); + }; +} + +/* only remove it from AND and OR nodes, not leaves */ + +#ifdef __USE_PROTOS +void MR_clearPredEntry(Predicate *p) +#else +void MR_clearPredEntry(p) + Predicate *p; +#endif +{ + if (p == NULL) return; + MR_clearPredEntry(p->down); + MR_clearPredEntry(p->right); + if (p->down != NULL) p->predEntry=NULL; +} + + +#ifdef __USE_PROTOS +void MR_orphanRules(FILE *f) +#else +void MR_orphanRules(f) + FILE *f; +#endif +{ + set a; + Junction *p; + unsigned e; + RuleEntry *re; + + a=empty; + + if (! InfoO) return; + + for (p=SynDiag; p!=NULL; p = (Junction *)p->p2) { + if ( (Junction *) (p->end)->p1 == NULL) { + re=(RuleEntry *) hash_get(Rname,p->rname); + require (re != NULL,"RuleEntry == NULL"); + set_orel(re->rulenum, &a); + } + } + + if (set_deg(a) > 1) { + fprintf(f,"note: Start rules: {"); + for (; !set_nil(a); set_rm(e,a)) { + e=set_int(a); + fprintf(f," %s",RulePtr[e]->rname); + }; + fprintf(f," }\n"); + }; + set_free( a ); +} + +/* merge (X Y) and (X) to create (X) */ + +static int *mergeChain; +static Tree *mergeTree; + +#ifdef __USE_PROTOS +Tree *MR_merge_tree_contexts_client(Tree *t,int chain[]) +#else +Tree *MR_merge_tree_contexts_client(t,chain) + Tree *t; + int chain[]; +#endif +{ + if (t == NULL) return NULL; + if (chain[0] == 0) { + Tree *u=t->right; + t->right=NULL; + Tfree(t); + return MR_merge_tree_contexts_client(u,&chain[0]); + } + if (chain[0] == t->token) { + t->down=MR_merge_tree_contexts_client(t->down,&chain[1]); + }; + t->right=MR_merge_tree_contexts_client(t->right,&chain[0]); + return t; +} + +#ifdef __USE_PROTOS +void MR_iterateOverTreeContexts(Tree *t,int chain[]) +#else +void MR_iterateOverTreeContexts(t,chain) + Tree *t; + int chain[]; +#endif +{ + if (t == NULL) return; + chain[0]=t->token; + if (t->down != NULL) { + MR_iterateOverTreeContexts(t->down,&chain[1]); + } else { + MR_merge_tree_contexts_client(mergeTree,mergeChain); + }; + MR_iterateOverTreeContexts(t->right,&chain[0]); + chain[0]=0; +} + +#ifdef __USE_PROTOS +Tree *MR_merge_tree_contexts(Tree *t) +#else +Tree *MR_merge_tree_contexts(t) + Tree *t; +#endif +{ + int h=MR_max_height_of_tree(t); + + mergeTree=t; + mergeChain=(int *) calloc(h+1,sizeof(int)); + require (mergeChain != NULL,"MR_merge_tree_contexts: can't alloc chain"); + MR_iterateOverTreeContexts(t,mergeChain); + t=tshrink(t); + t=tflatten(t); + t=tleft_factor(t); + free ( (char *) mergeChain); + mergeChain=NULL; + return t; +} + +#ifdef __USE_PROTOS +Tree *MR_compute_pred_tree_context(Predicate *p) +#else +Tree *MR_compute_pred_tree_context(p) + Predicate *p; +#endif +{ + Tree *t; + + t=MR_compute_pred_tree_ctxXX(p); + MR_merge_tree_contexts(t); + return t; +} + +#ifdef __USE_PROTOS +void MR_guardPred_plainSet(ActionNode *anode,Predicate *pred) +#else +void MR_guardPred_plainSet(anode,pred) + ActionNode *anode; + Predicate *pred; +#endif +{ + Junction *j; + Predicate *workPred; + set maskSet; + + maskSet=empty; + + if (!MRhoisting) return; + + /* it doesn't really matter whether the predicate has + depth k=1 or k>1 because we're not really looking + at the predicate itself, just the stuff "behind" + the predicate. + */ + + /* shouldn't have to worry about REACHing off the end + of the rule containing the predicate because the + Rule->end->halt should have been set already by the + the code which handles RuleRef nodes. + + We don't want to REACH off the end of the rule because + this would give the "global" follow context rather than + the "local" context. + + r1a : (A)? => <

>? r2 (A|B) + r1b : (A)? => <

>? r2 (A|C) + r2 : (); + + For r1a we want follow of predicate = {A B} + we want plainSet = {B} + For r1b we want follow of predicate = {A C} + we want plainSet = {C} + */ + + require (anode->next->ntype == nJunction,"MR_guardpred_plainSet not Junction"); + j=(Junction *)(anode->next); + + workPred=predicate_dup_without_context(pred); + workPred->k=1; + workPred->scontext[1]=MR_First(1,j, &(workPred->completionSet) ); + MR_complete_predicates(1,workPred); + if (pred->k == 1) { + maskSet=pred->scontext[1]; + } else { + MR_projectTreeOntoSet(pred->tcontext,1,&maskSet); + } + pred->plainSet=set_dif(workPred->scontext[1],maskSet); + predicate_free(workPred); +} + +/*******************************************************************************/ + +static Tree * suppressTree; +static int * suppressChain; /* element 0 not used */ +static set * suppressSets; +static Node * suppressNode; +static int suppressChainLength; +int MR_SuppressSearch=0; +static int suppressSucceeded; +static Predicate * suppressPredicate; + +#ifdef __USE_PROTOS +int MR_isChain(Tree *t) +#else +int MR_isChain(t) + Tree *t; +#endif +{ + Tree *u; + + for (u=t; u != NULL; u=u->down) { + if (u->right != NULL) return 0; + } + return 1; +} + +#ifdef __USE_PROTOS +int MR_suppressK_client(Tree *tree,int tokensInChain[]) +#else +int MR_suppressK_client(tree,tokensInChain) + Tree *tree; + int tokensInChain[]; +#endif +{ + int i; + set *save_fset; + int save_ConstrainSearch; + set incomplete; + Tree *t; + + suppressSucceeded=0; /* volatile */ + + if (suppressSets == NULL) { + suppressSets=(set *) calloc (CLL_k+1,sizeof(set)); + require (suppressSets != NULL,"MR_suppressK_client: suppressSets alloc"); + }; + + for (suppressChainLength=1; + tokensInChain[suppressChainLength+1] != 0; + suppressChainLength++) {}; + + require (suppressChainLength != 0,"MR_suppressK_client: chain empty"); + + for (i=1 ; i <= suppressChainLength ; i++) { + set_clr(suppressSets[i]); + set_orel( (unsigned) tokensInChain[i], + &suppressSets[i]); + }; + + save_fset=fset; + save_ConstrainSearch=ConstrainSearch; + + fset=suppressSets; + + MR_SuppressSearch=1; + MR_AmbSourceSearch=1; + MR_MaintainBackTrace=1; + ConstrainSearch=1; + + maxk = suppressChainLength; + + incomplete=empty; + t=NULL; + +/*** constrain = &(fset[1]); ***/ + + MR_setConstrainPointer(&(fset[1])); /* MR18 */ + + MR_pointerStackReset(&MR_BackTraceStack); + + TRAV(suppressNode,maxk,&incomplete,t); + + Tfree(t); + + require (set_nil(incomplete),"MR_suppressK_client TRAV incomplete"); + require (MR_BackTraceStack.count == 0, + "MR_suppressK_client: MR_BackTraceStack.count != 0"); + set_free(incomplete); + + ConstrainSearch=save_ConstrainSearch; + fset=save_fset; + + MR_AmbSourceSearch=0; + MR_MaintainBackTrace=0; + MR_SuppressSearch=0; + return suppressSucceeded; +} + +#ifdef __USE_PROTOS +Tree * MR_iterateOverTreeSuppressK(Tree *t,int chain[]) +#else +Tree * MR_iterateOverTreeSuppressK(t,chain) + Tree *t; + int chain[]; +#endif +{ + if (t == NULL) return NULL; + t->right=MR_iterateOverTreeSuppressK(t->right,&chain[0]); + chain[0]=t->token; + if (t->down != NULL) { + t->down=MR_iterateOverTreeSuppressK(t->down,&chain[1]); + if (t->down == NULL) { + Tree *u=t->right; + t->right=NULL; + Tfree(t); + chain[0]=0; + return u; + }; + } else { + MR_suppressK_client(suppressTree,suppressChain); + if (suppressSucceeded) { + Tree *u=t->right; + t->right=NULL; + Tfree(t); + chain[0]=0; + return u; + }; + }; + chain[0]=0; + return t; +} + +/* @@@ */ + +#ifdef __USE_PROTOS +Predicate * MR_suppressK(Node *j,Predicate *p) +#else +Predicate * MR_suppressK(j,p) + Node *j; + Predicate *p; +#endif +{ + Predicate *result; + int guardPred=0; + int ampersandPred=0; + Node *nodePrime; + + if (! MRhoistingk) { + return p; + } + + if (! MRhoisting) return p; + if (CLL_k == 1) return p; + + if (suppressChain == NULL) { + suppressChain=(int *) calloc(CLL_k+2,sizeof(int)); + require (suppressChain != NULL,"MR_suppressK: can't allocate chain"); + } + + if (p == NULL) return NULL; + + if (j->ntype == nJunction) { + nodePrime=(Node *) MR_junctionWithoutP2( (Junction *) j); + } else { + nodePrime=j; + }; + + p->down=MR_suppressK(j,p->down); + p->right=MR_suppressK(j,p->right); + if (p->down != NULL) { + result=p; + goto EXIT; + }; + if (p->k == 1) { + result=p; + goto EXIT; + }; + + if (p->source != NULL) { + if (p->source->guardpred != NULL) guardPred=1; + if (p->source->ampersandPred != NULL) ampersandPred=1; + } + + suppressPredicate=p; + suppressNode=nodePrime; /* was j*/ + + suppressTree=p->tcontext; + + if (guardPred || ampersandPred) { + p->tcontext=MR_iterateOverTreeSuppressK(suppressTree,&suppressChain[1]); + if (p->tcontext == NULL) { + predicate_free(p); + result=NULL; + goto EXIT; + }; + } else { + if (MR_isChain(p->tcontext)) { + p->tcontext=MR_iterateOverTreeSuppressK(suppressTree,&suppressChain[1]); + if (p->tcontext == NULL) { + predicate_free(p); + result=NULL; + goto EXIT; + }; + } + } + result=p; +EXIT: + return result; +} + +#ifdef __USE_PROTOS +void MR_suppressSearchReport(void) +#else +void MR_suppressSearchReport() +#endif +{ + int i; + Node *p; + TokNode *tn; + int depth; + set setAnd; + + /* number of tokens in back trace stack matches length of chain */ + + depth=0; + for (i=0; i < MR_BackTraceStack.count ; i++) { + p=(Node *) MR_BackTraceStack.data[i]; + if (p->ntype == nToken) depth++; + }; + + require (depth == suppressChainLength,"depth > suppressChainLength"); + + /* token codes match chain */ + + depth=0; + for (i=0; i < MR_BackTraceStack.count ; i++) { + p=(Node *) MR_BackTraceStack.data[i]; + if (p->ntype != nToken) continue; + tn=(TokNode *) p; + depth++; + if (set_nil(tn->tset)) { + require(set_el( (unsigned) tn->token,fset[depth]), + "MR_suppressSearchReport: no match to #token in chain"); + } else { + setAnd=set_and(fset[depth],tn->tset); + require(!set_nil(setAnd), + "MR_suppressSearchReport: no match to #token set in chain"); + set_free(setAnd); + }; + }; + + /* have a match - now remove it from the predicate */ + + suppressSucceeded=1; + + if (suppressSucceeded) { + fprintf(output,"\n"); + fprintf(output,"#if 0\n"); + fprintf(output,"\n"); + fprintf(output,"Part (or all) of predicate with depth > 1 suppressed by "); + fprintf(output,"alternative without predicate\n\n"); + MR_dumpPred(suppressPredicate,1); + fprintf(output,"The token sequence which is suppressed:"); + fprintf(output," ("); + for (i=1; i <= suppressChainLength; i++) { + fprintf(output," %s",TerminalString(suppressChain[i])); + }; + fprintf(output," )\n"); + fprintf(output,"The sequence of references which generate that sequence of tokens:\n\n"); + + MR_backTraceDumpItemReset(); + + for (i=0; i < MR_BackTraceStack.count ; i++) { + MR_backTraceDumpItem(output,0,(Node *) MR_BackTraceStack.data[i]); + }; + fprintf(output,"\n"); + fprintf(output,"#endif\n"); + } +} + +#ifdef __USE_PROTOS +void MR_markCompromisedRule(Node *n) +#else +void MR_markCompromisedRule(n) + Node *n; +#endif +{ + RuleEntry *q; + Node *mark=NULL; + Junction *j; + + if (n->ntype == nRuleRef) { + mark=(Node *) MR_ruleReferenced( (RuleRefNode *) n); + } else if (n->ntype == nToken) { + mark=n; + } else if (n->ntype == nJunction) { + j=(Junction *)n; + switch (j->jtype) { + case aOptBlk: + case aLoopBlk: + case RuleBlk: + case EndRule: + case aPlusBlk: + case aLoopBegin: + mark=n; + break; + default: + break; + }; + } + + if (mark == NULL) return; + + require (RulePtr != NULL,"RulePtr not initialized"); + + q = (RuleEntry *) hash_get(Rname,mark->rname); + require (q != NULL,"RuleEntry not found"); + set_orel(q->rulenum,&MR_CompromisedRules); +} + +#ifdef __USE_PROTOS +void MR_alphaBetaTraceReport(void) +#else +void MR_alphaBetaTraceReport() +#endif +{ + int i; + + if (! AlphaBetaTrace) return; + + MR_AlphaBetaMessageCount++; + + fprintf(output,"\n"); + fprintf(output,"#if 0\n"); + fprintf(output,"\n"); + fprintf(output,"Trace of references leading to attempt to compute the follow set of\n"); + fprintf(output,"alpha in an \"(alpha)? beta\" block. It is not possible for antlr to\n"); + fprintf(output,"compute this follow set because it is not known what part of beta has\n"); + fprintf(output,"already been matched by alpha and what part remains to be matched.\n"); + fprintf(output,"\n"); + fprintf(output,"Rules which make use of the incorrect follow set will also be incorrect\n"); + fprintf(output,"\n"); + + MR_backTraceDumpItemReset(); + + for (i=0; i < MR_BackTraceStack.count ; i++) { + MR_backTraceDumpItem(output,0,(Node *) MR_BackTraceStack.data[i]); + if (i < MR_BackTraceStack.count-1) { + MR_markCompromisedRule( (Node *) MR_BackTraceStack.data[i]); + }; + }; + fprintf(output,"\n"); + fprintf(output,"#endif\n"); +} + +#ifdef __USE_PROTOS +void MR_dumpRuleSet(set s) +#else +void MR_dumpRuleSet(s) + set s; +#endif +{ + unsigned *cursor; + unsigned *origin=set_pdq(s); + + require(origin != NULL,"set_pdq failed"); + + if (RulePtr == NULL) { + fprintf(stderr,"RulePtr[] not yet initialized"); + } else { + for (cursor=origin; *cursor != nil ; cursor++) { +/**** if (cursor != origin) fprintf(stderr,","); ****/ + fprintf(stderr," %s",RulePtr[*cursor]->rname); + fprintf(stderr,"\n"); + }; + free( (char *) origin); + }; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/parser.dlg b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/parser.dlg new file mode 100644 index 00000000..6f043212 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/parser.dlg @@ -0,0 +1,1387 @@ +<< +/* parser.dlg -- DLG Description of scanner + * + * Generated from: antlr.g + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + */ + +#define ANTLR_VERSION 13333 +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include "pcctscfg.h" +#include "set.h" +#include +#include "syn.h" +#include "hash.h" +#include "generic.h" +#define zzcr_attr(attr,tok,t) +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +LOOKAHEAD + +void +#ifdef __USE_PROTOS +zzerraction(void) +#else +zzerraction() +#endif +{ + (*zzerr)("invalid token"); + zzadvance(); + zzskip(); +} +>> + +<<%%lexaction + +/* maintained, but not used for now */ +set AST_nodes_refd_in_actions = set_init; +int inAlt = 0; +set attribsRefdFromAction = set_init; /* MR20 */ +int UsedOldStyleAttrib = 0; +int UsedNewStyleLabel = 0; +#ifdef __USE_PROTOS +char *inline_set(char *); +#else +char *inline_set(); +#endif + +/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ +/* MR1 in DLG action */ + +int tokenActionActive=0; /* MR1 */ + + +>> + +<<%%lexaction + + +static char * +#ifdef __USE_PROTOS +getFileNameFromTheLineInfo(char *toStr, char *fromStr) +#else +getFileNameFromTheLineInfo(toStr, fromStr) +char *toStr, *fromStr; +#endif +{ + int i, j, k; + + if (!fromStr || !toStr) return toStr; + + /* find the first " */ + + for (i=0; + (i> + +<<%%lexaction + +#ifdef __USE_PROTOS +void mark_label_used_in_sem_pred(LabelEntry *le) /* MR10 */ +#else +void mark_label_used_in_sem_pred(le) /* MR10 */ +LabelEntry *le; +#endif +{ + TokNode *tn; + require (le->elem->ntype == nToken,"mark_label_used... ntype != nToken"); + tn=(TokNode *)le->elem; + require (tn->label != 0,"mark_label_used... TokNode has no label"); + tn->label_used_in_semantic_pred=1; +} +>> + + +%%START + +@ + << + NLA = Eof; + /* L o o k F o r A n o t h e r F i l e */ + { + FILE *new_input; + new_input = NextFile(); + if ( new_input == NULL ) { NLA=Eof; return; } + fclose( input ); + input = new_input; + zzrdstream( input ); + zzskip(); /* Skip the Eof (@) char i.e continue */ + } + >> + +[\t\ ]+ + << + NLA = 76; + zzskip(); + >> + +\n|\r|\r\n + << + NLA = 77; + zzline++; zzskip(); + >> + +\[ + << + NLA = 78; + zzmode(ACTIONS); zzmore(); + istackreset(); + pushint(']'); + >> + +\<\< + << + NLA = 79; + action_file=CurFile; action_line=zzline; + zzmode(ACTIONS); zzmore(); + list_free(&CurActionLabels,0); /* MR10 */ + numericActionLabel=0; /* MR10 */ + istackreset(); + pushint('>'); + >> + +\" + << + NLA = 80; + zzmode(STRINGS); zzmore(); + >> + +/\* + << + NLA = 81; + zzmode(COMMENTS); zzskip(); + >> + +\*/ + << + NLA = 82; + warn("Missing /*; found dangling */"); zzskip(); + >> + +// + << + NLA = 83; + zzmode(CPP_COMMENTS); zzskip(); + >> + +#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n) + << + NLA = 84; + + zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore(); + getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr); + >> + +#line ~[\n\r]* (\n|\r|\r\n) + << + NLA = 85; + + zzline++; zzmore(); + >> + +\>\> + << + NLA = 86; + warn("Missing <<; found dangling \>\>"); zzskip(); + >> + +. + << + NLA = WildCard; + >> + +\@ + << + NLA = 88; + FoundException = 1; /* MR6 */ + FoundAtOperator = 1; + >> + +{\\}#pragma + << + NLA = Pragma; + >> + +{\\}#FirstSetSymbol + << + NLA = FirstSetSymbol; + >> + +{\\}#header + << + NLA = 94; + >> + +{\\}#first + << + NLA = 95; + >> + +{\\}#parser + << + NLA = 96; + >> + +{\\}#tokdefs + << + NLA = 97; + >> + +\} + << + NLA = 98; + >> + +class + << + NLA = 99; + >> + +\{ + << + NLA = 102; + >> + +! + << + NLA = 103; + >> + +\< + << + NLA = 104; + >> + +\> + << + NLA = 105; + >> + +: + << + NLA = 106; + >> + +; + << + NLA = 107; + >> + +{\\}#lexaction + << + NLA = 108; + >> + +{\\}#lexmember + << + NLA = 109; + >> + +{\\}#lexprefix + << + NLA = 110; + >> + +{\\}#pred + << + NLA = 111; + >> + +\|\| + << + NLA = 112; + >> + +&& + << + NLA = 113; + >> + +\( + << + NLA = 114; + >> + +\) + << + NLA = 115; + >> + +{\\}#lexclass + << + NLA = 116; + >> + +{\\}#errclass + << + NLA = 117; + >> + +{\\}#tokclass + << + NLA = 118; + >> + +.. + << + NLA = 119; + >> + +{\\}#token + << + NLA = 120; + >> + += + << + NLA = 121; + >> + +[0-9]+ + << + NLA = 122; + >> + +\| + << + NLA = 123; + >> + +\~ + << + NLA = 124; + >> + +^ + << + NLA = 125; + >> + +approx + << + NLA = 126; + >> + +LL\(1\) + << + NLA = 127; + >> + +LL\(2\) + << + NLA = 128; + >> + +\* + << + NLA = 129; + >> + +\+ + << + NLA = 130; + >> + +? + << + NLA = 131; + >> + +=> + << + NLA = 132; + >> + +exception + << + NLA = 133; + >> + +default + << + NLA = 134; + >> + +catch + << + NLA = 135; + >> + +[a-z] [A-Za-z0-9_]* + << + NLA = NonTerminal; + + while ( zzchar==' ' || zzchar=='\t' ) { + zzadvance(); + } + if ( zzchar == ':' && inAlt ) NLA = LABEL; + >> + +[A-Z] [A-Za-z0-9_]* + << + NLA = TokenTerm; + + while ( zzchar==' ' || zzchar=='\t' ) { + zzadvance(); + } + if ( zzchar == ':' && inAlt ) NLA = LABEL; + >> + +{\\}#[A-Za-z0-9_]* + << + NLA = 136; + warn(eMsg1("unknown meta-op: %s",LATEXT(1))); zzskip(); + >> + + +%%STRINGS + +@ + << + NLA = Eof; + >> + +\" + << + NLA = QuotedTerm; + zzmode(START); + >> + +\n|\r|\r\n + << + NLA = 3; + + zzline++; + warn("eoln found in string"); + zzskip(); + >> + +\\(\n|\r|\r\n) + << + NLA = 4; + zzline++; zzmore(); + >> + +\\~[] + << + NLA = 5; + zzmore(); + >> + +~[\n\r\"\\]+ + << + NLA = 6; + zzmore(); + >> + + +%%ACTION_STRINGS + +@ + << + NLA = Eof; + >> + +\" + << + NLA = 7; + zzmode(ACTIONS); zzmore(); + >> + +\n|\r|\r\n + << + NLA = 8; + + zzline++; + warn("eoln found in string (in user action)"); + zzskip(); + >> + +\\(\n|\r|\r\n) + << + NLA = 9; + zzline++; zzmore(); + >> + +\\~[] + << + NLA = 10; + zzmore(); + >> + +~[\n\r\"\\]+ + << + NLA = 11; + zzmore(); + >> + + +%%ACTION_CHARS + +@ + << + NLA = Eof; + >> + +' + << + NLA = 12; + zzmode(ACTIONS); zzmore(); + >> + +\n|\r|\r\n + << + NLA = 13; + + zzline++; + warn("eoln found in char literal (in user action)"); + zzskip(); + >> + +\\~[] + << + NLA = 14; + zzmore(); + >> + +~[\n\r'\\]+ + << + NLA = 15; + zzmore(); + >> + + +%%ACTION_COMMENTS + +@ + << + NLA = Eof; + >> + +\*/ + << + NLA = 16; + zzmode(ACTIONS); zzmore(); + >> + +\* + << + NLA = 17; + zzmore(); + >> + +\n|\r|\r\n + << + NLA = 18; + zzline++; zzmore(); DAWDLE; + >> + +~[\n\r\*]+ + << + NLA = 19; + zzmore(); + >> + + +%%TOK_DEF_COMMENTS + +@ + << + NLA = Eof; + >> + +\*/ + << + NLA = 20; + zzmode(PARSE_ENUM_FILE); + zzmore(); + >> + +\* + << + NLA = 21; + zzmore(); + >> + +\n|\r|\r\n + << + NLA = 22; + zzline++; zzmore(); DAWDLE; + >> + +~[\n\r\*]+ + << + NLA = 23; + zzmore(); + >> + + +%%TOK_DEF_CPP_COMMENTS + +@ + << + NLA = Eof; + >> + +\n|\r|\r\n + << + NLA = 24; + zzline++; zzmode(PARSE_ENUM_FILE); zzskip(); DAWDLE; + >> + +~[\n\r]+ + << + NLA = 25; + zzskip(); + >> + + +%%ACTION_CPP_COMMENTS + +@ + << + NLA = Eof; + >> + +\n|\r|\r\n + << + NLA = 26; + zzline++; zzmode(ACTIONS); zzmore(); DAWDLE; + >> + +~[\n\r]+ + << + NLA = 27; + zzmore(); + >> + + +%%CPP_COMMENTS + +@ + << + NLA = Eof; + >> + +\n|\r|\r\n + << + NLA = 28; + zzline++; zzmode(START); zzskip(); DAWDLE; + >> + +~[\n\r]+ + << + NLA = 29; + zzskip(); + >> + + +%%COMMENTS + +@ + << + NLA = Eof; + >> + +\*/ + << + NLA = 30; + zzmode(START); zzskip(); + >> + +\* + << + NLA = 31; + zzskip(); + >> + +\n|\r|\r\n + << + NLA = 32; + zzline++; zzskip(); DAWDLE; + >> + +~[\n\r\*]+ + << + NLA = 33; + zzskip(); + >> + + +%%ACTIONS + +@ + << + NLA = Eof; + >> + +\>\> + << + NLA = Action; + /* these do not nest */ + zzmode(START); + NLATEXT[0] = ' '; + NLATEXT[1] = ' '; + zzbegexpr[0] = ' '; + zzbegexpr[1] = ' '; + if ( zzbufovf ) { + err( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE)); + } + +/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ + /* MR1 in DLG action */ + /* MR1 Doesn't matter what kind of action it is - reset*/ + + tokenActionActive=0; /* MR1 */ + >> + +\>\>? + << + NLA = Pred; + /* these do not nest */ + zzmode(START); + NLATEXT[0] = ' '; + NLATEXT[1] = ' '; + zzbegexpr[0] = '\0'; + if ( zzbufovf ) { + err( eMsgd("predicate buffer overflow; size %d",ZZLEXBUFSIZE)); + }; +#ifdef __cplusplus__ + /* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else +#ifdef __STDC__ + /* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else +#ifdef __USE_PROTOS + /* MRxx */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else + /* MR10 */ list_apply(CurActionLabels,mark_label_used_in_sem_pred); +#endif +#endif +#endif + >> + +\] + << + NLA = PassAction; + if ( topint() == ']' ) { + popint(); + if ( istackempty() ) /* terminate action */ + { + zzmode(START); + NLATEXT[0] = ' '; + zzbegexpr[0] = ' '; + if ( zzbufovf ) { + err( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE)); + } + } + else { + /* terminate $[..] and #[..] */ + if ( GenCC ) zzreplstr("))"); + else zzreplstr(")"); + zzmore(); + } + } + else if ( topint() == '|' ) { /* end of simple [...] */ + popint(); + zzmore(); + } + else zzmore(); + >> + +consumeUntil\( [\ \t]* \{~[\}]+\} [\ \t]* \) + << + NLA = 37; + + zzmore(); + zzreplstr(inline_set(zzbegexpr+ + strlen("consumeUntil("))); + >> + +consumeUntil\( ~[\)]+ \) + << + NLA = 38; + zzmore(); + >> + +\n|\r|\r\n + << + NLA = 39; + zzline++; zzmore(); DAWDLE; + >> + +\> + << + NLA = 40; + zzmore(); + >> + +$ + << + NLA = 41; + zzmore(); + >> + +$$ + << + NLA = 42; + if ( !GenCC ) {zzreplstr("zzaRet"); zzmore();} + else err("$$ use invalid in C++ mode"); + >> + +$\[\] + << + NLA = 43; + if ( !GenCC ) {zzreplstr("zzempty_attr"); zzmore();} + else err("$[] use invalid in C++ mode"); + >> + +$\[ + << + NLA = 44; + + pushint(']'); + if ( !GenCC ) zzreplstr("zzconstr_attr("); + else err("$[..] use invalid in C++ mode"); + zzmore(); + >> + +$[0-9]+ + << + NLA = 45; + { + static char buf[100]; + numericActionLabel=1; /* MR10 */ + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("$i attrib ref too big"); + set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction); + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s)", + BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"_t%d%s", + BlkLevel-1,zzbegexpr+1); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + >> + +$[0-9]+. + << + NLA = 46; + { + static char buf[100]; + numericActionLabel=1; /* MR10 */ + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("$i.field attrib ref too big"); + zzbegexpr[strlen(zzbegexpr)-1] = ' '; + set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction); + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s).", + BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"_t%d%s.", + BlkLevel-1,zzbegexpr+1); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + >> + +$[0-9]+.[0-9]+ + << + NLA = 47; + { + static char buf[100]; + static char i[20], j[20]; + char *p,*q; + numericActionLabel=1; /* MR10 */ + if (strlen(zzbegexpr)>(size_t)85) fatal("$i.j attrib ref too big"); + for (p=zzbegexpr+1,q= &i[0]; *p!='.'; p++) { + if ( q == &i[20] ) + fatalFL("i of $i.j attrib ref too big", + FileStr[CurFile], zzline ); + *q++ = *p; + } + *q = '\0'; + for (p++, q= &j[0]; *p!='\0'; p++) { + if ( q == &j[20] ) + fatalFL("j of $i.j attrib ref too big", + FileStr[CurFile], zzline ); + *q++ = *p; + } + *q = '\0'; + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%s,%s)",i,j); + else sprintf(buf,"_t%s%s",i,j); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + >> + +$[_a-zA-Z][_a-zA-Z0-9]* + << + NLA = 48; + { static char buf[300]; LabelEntry *el; + zzbegexpr[0] = ' '; + if ( CurRule != NULL && + strcmp(CurRule, &zzbegexpr[1])==0 ) { + if ( !GenCC ) zzreplstr("zzaRet"); + } + else if ( CurRetDef != NULL && + strmember(CurRetDef, &zzbegexpr[1])) { + if ( hasMultipleOperands( CurRetDef ) ) { + require (strlen(zzbegexpr)<=(size_t)285, + "$retval attrib ref too big"); + sprintf(buf,"_retv.%s",&zzbegexpr[1]); + zzreplstr(buf); + } + else zzreplstr("_retv"); + } + else if ( CurParmDef != NULL && + strmember(CurParmDef, &zzbegexpr[1])) { + ; + } + else if ( Elabel==NULL ) { + { err("$-variables in actions outside of rules are not allowed"); } + } else if ( (el=(LabelEntry *)hash_get(Elabel, &zzbegexpr[1]))!=NULL ) { + /* MR10 */ + /* MR10 */ /* element labels might exist without an elem when */ + /* MR10 */ /* it is a forward reference (to a rule) */ + /* MR10 */ + /* MR10 */ if ( GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) ) + /* MR10 */ { err(eMsg1("There are no token ptrs for rule references: '$%s'",&zzbegexpr[1])); } + /* MR10 */ + /* MR10 */ if ( !GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) && GenAST) { + /* MR10 */ err("You can no longer use attributes returned by rules when also using ASTs"); + /* MR10 */ err(" Use upward inheritance (\"rule >[Attrib a] : ... <<$a=...\>\>\")"); + /* MR10 */ }; + /* MR10 */ + /* MR10 */ /* keep track of <<... $label ...>> for semantic predicates in guess mode */ + /* MR10 */ /* element labels contain pointer to the owners node */ + /* MR10 */ + /* MR10 */ if (el->elem != NULL && el->elem->ntype == nToken) { + /* MR10 */ list_add(&CurActionLabels,el); + /* MR10 */ }; +} +else +warn(eMsg1("$%s not parameter, return value, (defined) element label",&zzbegexpr[1])); +} +zzmore(); + >> + +#0 + << + NLA = 49; + zzreplstr("(*_root)"); zzmore(); chkGTFlag(); + >> + +#\[\] + << + NLA = 50; + if ( GenCC ) { + if (NewAST) zzreplstr("(newAST)"); + else zzreplstr("(new AST)");} + else {zzreplstr("zzastnew()");} zzmore(); + chkGTFlag(); + >> + +#\(\) + << + NLA = 51; + zzreplstr("NULL"); zzmore(); chkGTFlag(); + >> + +#[0-9]+ + << + NLA = 52; + { + static char buf[100]; + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("#i AST ref too big"); + if ( GenCC ) sprintf(buf,"_ast%d%s",BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"zzastArg(%s)",zzbegexpr+1); + zzreplstr(buf); + zzmore(); + set_orel(atoi(zzbegexpr+1), &AST_nodes_refd_in_actions); + chkGTFlag(); + } + >> + +#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n) + << + NLA = 53; + + zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore(); + getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr); + >> + +#line ~[\n\r]* (\n|\r|\r\n) + << + NLA = 54; + + zzline++; zzmore(); + >> + +#[_a-zA-Z][_a-zA-Z0-9]* + << + NLA = 55; + + if ( !(strcmp(zzbegexpr, "#ifdef")==0 || + strcmp(zzbegexpr, "#if")==0 || + strcmp(zzbegexpr, "#else")==0 || + strcmp(zzbegexpr, "#endif")==0 || + strcmp(zzbegexpr, "#ifndef")==0 || + strcmp(zzbegexpr, "#define")==0 || + strcmp(zzbegexpr, "#pragma")==0 || + strcmp(zzbegexpr, "#undef")==0 || + strcmp(zzbegexpr, "#import")==0 || + strcmp(zzbegexpr, "#line")==0 || + strcmp(zzbegexpr, "#include")==0 || + strcmp(zzbegexpr, "#error")==0) ) + { + static char buf[100]; + sprintf(buf, "%s_ast", zzbegexpr+1); + /* MR27 */ list_add(&CurAstLabelsInActions, mystrdup(zzbegexpr+1)); + zzreplstr(buf); + chkGTFlag(); + } + zzmore(); + >> + +#\[ + << + NLA = 56; + + pushint(']'); + if ( GenCC ) { + if (NewAST) zzreplstr("(newAST("); + else zzreplstr("(new AST("); } + else zzreplstr("zzmk_ast(zzastnew(),"); + zzmore(); + chkGTFlag(); + >> + +#\( + << + NLA = 57; + + pushint('}'); + if ( GenCC ) { + if (tmakeInParser) { + zzreplstr("tmake("); + } + else { + zzreplstr("ASTBase::tmake("); + } + } + else { + zzreplstr("zztmake("); + } + zzmore(); + chkGTFlag(); + >> + +# + << + NLA = 58; + zzmore(); + >> + +\) + << + NLA = 59; + + if ( istackempty() ) + zzmore(); + else if ( topint()==')' ) { + popint(); + } + else if ( topint()=='}' ) { + popint(); + /* terminate #(..) */ + zzreplstr(", NULL)"); + } + zzmore(); + >> + +\[ + << + NLA = 60; + + pushint('|'); /* look for '|' to terminate simple [...] */ + zzmore(); + >> + +\( + << + NLA = 61; + + pushint(')'); + zzmore(); + >> + +\\\] + << + NLA = 62; + zzreplstr("]"); zzmore(); + >> + +\\\) + << + NLA = 63; + zzreplstr(")"); zzmore(); + >> + +\\> + << + NLA = 64; + if (! tokenActionActive) zzreplstr(">"); /* MR1 */ + zzmore(); /* MR1 */ + >> + +' + << + NLA = 65; + zzmode(ACTION_CHARS); zzmore(); + >> + +\" + << + NLA = 66; + zzmode(ACTION_STRINGS); zzmore(); + >> + +\\$ + << + NLA = 67; + zzreplstr("$"); zzmore(); + >> + +\\# + << + NLA = 68; + zzreplstr("#"); zzmore(); + >> + +\\(\n|\r|\r\n) + << + NLA = 69; + zzline++; zzmore(); + >> + +\\~[\]\)>$#] + << + NLA = 70; + zzmore(); + >> + +/ + << + NLA = 71; + zzmore(); + >> + +/\* + << + NLA = 72; + zzmode(ACTION_COMMENTS); zzmore(); + >> + +\*/ + << + NLA = 73; + warn("Missing /*; found dangling */ in action"); zzmore(); + >> + +// + << + NLA = 74; + zzmode(ACTION_CPP_COMMENTS); zzmore(); + >> + +~[\n\r\)\(\\$#\>\]\[\"'/]+ + << + NLA = 75; + zzmore(); + >> + + +%%PARSE_ENUM_FILE + +@ + << + NLA = Eof; + ; + >> + +[\t\ ]+ + << + NLA = 137; + zzskip(); + >> + +\n|\r|\r\n + << + NLA = 138; + zzline++; zzskip(); + >> + +// + << + NLA = 139; + zzmode(TOK_DEF_CPP_COMMENTS); zzmore(); + >> + +/\* + << + NLA = 140; + zzmode(TOK_DEF_COMMENTS); zzskip(); + >> + +#ifdef + << + NLA = 141; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + >> + +#if + << + NLA = 142; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + >> + +#ifndef + << + NLA = 143; + ; + >> + +#else + << + NLA = 144; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + >> + +#endif + << + NLA = 145; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + >> + +#undef + << + NLA = 146; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + >> + +#import + << + NLA = 147; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + >> + +#define + << + NLA = 149; + >> + +enum + << + NLA = 151; + >> + +\{ + << + NLA = 152; + >> + += + << + NLA = 153; + >> + +, + << + NLA = 154; + >> + +\} + << + NLA = 155; + >> + +; + << + NLA = 156; + >> + +[0-9]+ + << + NLA = INT; + >> + +[a-zA-Z_][_a-zA-Z0-9]* + << + NLA = ID; + >> + +%% diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/pred.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/pred.c new file mode 100644 index 00000000..2ee2dcc4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/pred.c @@ -0,0 +1,821 @@ +/* + * pred.c -- source for predicate detection, manipulation + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include "pcctscfg.h" +#include "set.h" +#include "syn.h" +#include "hash.h" +#include "generic.h" +#include "dlgdef.h" +#include + +#ifdef __USE_PROTOS +static void complete_context_sets(RuleRefNode *, Predicate *); +static void complete_context_trees(RuleRefNode *, Predicate *); +#else +static void complete_context_sets(); +static void complete_context_trees(); +#endif + +char *PRED_AND_LIST = "AND"; +char *PRED_OR_LIST = "OR"; + +/* + * In C mode, return the largest constant integer found as the + * sole argument to LATEXT(i). + * + * In C++ mode, return the largest constant integer found as the + * sole argument to LT(i) given that the char before is nonalpha. + */ + +int +#ifdef __USE_PROTOS +predicateLookaheadDepth(ActionNode *a) +#else +predicateLookaheadDepth(a) +ActionNode *a; +#endif +{ + int max_k=0; + + if (a->predEntry != NULL) { + MR_pred_depth(a->predEntry->pred,&max_k); + goto PREDENTRY_EXIT; + } + + if ( GenCC ) + { + /* scan for LT(i) */ + int k = 0; + char *p = a->action; + while ( p!=NULL ) + { + p = strstr(p, "LT("); + if ( p!=NULL ) + { + if ( p>=a->action && !isalpha(*(p-1)) ) + { + k = atoi(p+strlen("LT(")); + if ( k>max_k ) max_k=k; + } + p += strlen("LT("); + } + } + } + else { + /* scan for LATEXT(i) */ + int k = 0; + char *p = a->action; + while ( p!=NULL ) + { + p = strstr(p, "LATEXT("); + if ( p!=NULL ) + { + p += strlen("LATEXT("); + k = atoi(p); + if ( k>max_k ) max_k=k; + } + } + } + + if (max_k==0) { + max_k = 1; /* MR33 Badly designed if didn't set max_k when CLL_k = 1 */ + if (CLL_k > 1) /* MR27 Don't warn if max(k,ck) == 1 */ + { + if ( !a->frmwarned ) + { + a->frmwarned = 1; + warnFL(eMsg1("predicate: %s missing, bad, or with i=0; assuming i=1", + GenCC?"LT(i)":"LATEXT(i)"), + FileStr[a->file], a->line); + } + } + } + +/* MR10 */ if ( max_k > CLL_k) { +/* MR10 */ if ( !a->frmwarned ) +/* MR10 */ { +/* MR10 */ a->frmwarned = 1; +/* MR11 */ errFL(eMsgd2("predicate refers to lookahead token %d. Semantic lookahead is limited to max(k,ck)==%d", +/* MR10 */ max_k,CLL_k), +/* MR10 */ FileStr[a->file],a->line); +/* MR10 */ if (max_k >= OutputLL_k) { +/* MR10 */ if (!GenCC) { +/* MR10 */ errFL(eMsgd(" the lookahead buffer size in C mode is %d token(s) (including the one just recognized)", +/* MR10 */ OutputLL_k), +/* MR10 */ FileStr[a->file],a->line); +/* MR10 */ }; +/* MR10 */ }; +/* MR10 */ }; +/* MR10 */ max_k= CLL_k; +/* MR10 */ }; + +PREDENTRY_EXIT: + return max_k; +} + +/* Find all predicates in a block of alternatives. DO NOT find predicates + * behind the block because that predicate could depend on things set in + * one of the nonoptional blocks + */ + +Predicate * +#ifdef __USE_PROTOS +find_in_aSubBlk( Junction *alt ) +#else +find_in_aSubBlk( alt ) +Junction *alt; +#endif +{ + Predicate *a, *head=NULL, *tail=NULL, *root=NULL; + Junction *p = alt; + + if (MRhoisting) { + return MR_find_in_aSubBlk(alt); + }; + for (; p!=NULL; p=(Junction *)p->p2) + { + /* ignore empty alts */ + if ( p->p1->ntype != nJunction || + ((Junction *)p->p1)->jtype != EndBlk ) + { + a = find_predicates(p->p1); /* get preds for this alt */ + if ( a==NULL ) continue; + + /* make an OR list of predicates */ + if ( head==NULL ) + { + root = new_pred(); + root->expr = PRED_OR_LIST; + head = tail = a; + root->down = head; + } + else { + tail->right = a; + a->left = tail; + a->up = tail->up; + tail = a; + } + } + } + + /* if just one pred, remove OR root */ + if ( root!=NULL && root->down->right == NULL ) + { + Predicate *d = root->down; + free( (char *) root); + return d; + } + + return root; +} + +Predicate * +#ifdef __USE_PROTOS +find_in_aOptBlk( Junction *alt ) +#else +find_in_aOptBlk( alt ) +Junction *alt; +#endif +{ + return find_in_aSubBlk( alt ); +} + +Predicate * +#ifdef __USE_PROTOS +find_in_aLoopBegin( Junction *alt ) +#else +find_in_aLoopBegin( alt ) +Junction *alt; +#endif +{ + return find_in_aSubBlk( (Junction *) alt->p1 ); /* get preds in alts */ +} + +Predicate * +#ifdef __USE_PROTOS +find_in_aPlusBlk( Junction *alt ) +#else +find_in_aPlusBlk( alt ) +Junction *alt; +#endif +{ + require(alt!=NULL&&alt->p2!=NULL, "invalid aPlusBlk"); + return find_in_aSubBlk( alt ); +} + +/* Look for a predicate; + * + * Do not pass anything but Junction nodes; no Actions, Tokens, RuleRefs. + * This means that a "hoisting distance" of zero is the only distance + * allowable. Init actions are ignored. + * + * WARNING: + * Assumes no (..)? block after predicate for the moment. + * Does not check to see if pred is in production that can generate + * a sequence contained in the set of ambiguous tuples. + * + * Return the predicate found if any. + */ + + +Predicate * +#ifdef __USE_PROTOS +find_predicates( Node *alt ) +#else +find_predicates( alt ) +Node *alt; +#endif +{ +#ifdef DBG_PRED + Junction *j; + RuleRefNode *r; + TokNode *t; +#endif + Predicate *pred; + + if ( alt==NULL ) return NULL; + +#ifdef DBG_PRED + switch ( alt->ntype ) + { + case nJunction : + j = (Junction *) alt; + fprintf(stderr, "Junction(in %s)", j->rname); + switch ( j->jtype ) + { + case aSubBlk : + fprintf(stderr,"aSubBlk\n"); + break; + case aOptBlk : + fprintf(stderr,"aOptBlk\n"); + break; + case aLoopBegin : + fprintf(stderr,"aLoopBeginBlk\n"); + break; + case aLoopBlk : + fprintf(stderr,"aLoopBlk\n"); + break; + case aPlusBlk : + fprintf(stderr,"aPlusBlk\n"); + break; + case EndBlk : + fprintf(stderr,"EndBlk\n"); + break; + case RuleBlk : + fprintf(stderr,"RuleBlk\n"); + break; + case Generic : + fprintf(stderr,"Generic\n"); + break; + case EndRule : + fprintf(stderr,"EndRule\n"); + break; + } + break; + case nRuleRef : + r = (RuleRefNode *) alt; + fprintf(stderr, "RuleRef(in %s)\n", r->rname); + break; + case nToken : + t = (TokNode *) alt; + fprintf(stderr, "TokenNode(in %s)%s\n", t->rname, TokenString(t->token)); + break; + case nAction : + fprintf(stderr, "Action\n"); + break; + } +#endif + + switch ( alt->ntype ) + { + case nJunction : + { + Predicate *a, *b; + Junction *p = (Junction *) alt; + + /* lock nodes */ + if ( p->jtype==aLoopBlk || p->jtype==RuleBlk || + p->jtype==aPlusBlk || p->jtype==EndRule ) + { + require(p->pred_lock!=NULL, "rJunc: lock array is NULL"); + if ( p->pred_lock[1] ) + { + return NULL; + } + p->pred_lock[1] = TRUE; + } + + switch ( p->jtype ) + { + case aSubBlk : + a = find_in_aSubBlk(p); + return a; /* nothing is visible past this guy */ + case aOptBlk : + a = find_in_aOptBlk(p); + return a; + case aLoopBegin : + a = find_in_aLoopBegin(p); + return a; + case aLoopBlk : + a = find_in_aSubBlk(p); + p->pred_lock[1] = FALSE; + return a; + case aPlusBlk : + a = find_in_aPlusBlk(p); + p->pred_lock[1] = FALSE; + return a; /* nothing is visible past this guy */ + case RuleBlk : + a = find_predicates(p->p1); + p->pred_lock[1] = FALSE; + return a; + case Generic : + a = find_predicates(p->p1); + b = find_predicates(p->p2); + if ( p->pred_lock!=NULL ) p->pred_lock[1] = FALSE; + if ( a==NULL ) return b; + if ( b==NULL ) return a; + /* otherwise OR the two preds together */ + { + fatal_internal("hit unknown situation during predicate hoisting"); + } + case EndBlk : + case EndRule : /* Find no predicates after a rule ref */ + return NULL; + default: + fatal_internal("this cannot be printed\n"); + break; + } + } + case nAction : + { + ActionNode *p = (ActionNode *) alt; + if ( p->noHoist) return NULL; /* MR12c */ + if ( p->init_action ) return find_predicates(p->next); + if ( p->is_predicate ) + { + Tree *t=NULL; +#ifdef DBG_PRED + fprintf(stderr, "predicate: <<%s>>?\n", p->action); +#endif + if ( p->guardpred!=NULL ) + { + pred = predicate_dup(p->guardpred); + MR_guardPred_plainSet(p,pred); /* MR12c */ + } + else + { + pred = new_pred(); + pred->k = predicateLookaheadDepth(p); + pred->source = p; + pred->expr = p->action; + if ( HoistPredicateContext && pred->k > 1 ) + { + /* MR30 No need to use first_item_is_guess_block_extra + since we know this is an action, not a (...)* or + (...)+ block. + */ + + if ( first_item_is_guess_block((Junction *)p->next) ) + { + warnFL("cannot compute context of predicate in front of (..)? block", + FileStr[p->file], p->line); + } + else + { + ConstrainSearch = 0; +/* MR11 */ if (p->ampersandPred != NULL) { +/* MR11 */ TRAV(p, +/* MR11 */ pred->k, +/* MR11 */ &(pred->completionTree), t); +/* MR11 */ } else { + TRAV(p->next, + pred->k, + &(pred->completionTree), t); + }; + pred->tcontext = t; + MR_check_pred_too_long(pred,pred->completionTree); +#ifdef DBG_PRED + fprintf(stderr, "LL(%d) context:", pred->k); + preorder(t); + fprintf(stderr, "\n"); +#endif + } + } + else if ( HoistPredicateContext && pred->k == 1 ) + { + pred->scontext[1] = empty; + /* MR30 No need to use first_item_is_guess_block_extra + since we know this is an action. + */ + if ( first_item_is_guess_block((Junction *)p->next) ) + { + warnFL("cannot compute context of predicate in front of (..)? block", + FileStr[p->file], p->line); + } + else + { + REACH((Junction *)p->next, + 1, + &(pred->completionSet), + pred->scontext[1]); + MR_check_pred_too_long(pred,pred->completionSet); +#ifdef DBG_PRED + fprintf(stderr, "LL(1) context:"); + s_fprT(stderr, pred->scontext[1]); + fprintf(stderr, "\n"); +#endif + } + } + } + { + Predicate *d = find_predicates(p->next); + Predicate *root; + +/* Warning: Doesn't seem like the up pointers will all be set correctly; + * TJP: that's ok, we're not using them now. + */ + if ( d!=NULL ) + { + root = new_pred(); + root->expr = PRED_AND_LIST; + root->down = pred; + pred->right = d; + pred->up = root; + d->left = pred; + d->up = pred->up; + return root; + } + } + return pred; + } + return NULL; + } + case nRuleRef : + { + Predicate *a; + RuleRefNode *p = (RuleRefNode *) alt; + Junction *r; + Junction *save_MR_RuleBlkWithHalt; + + RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text); + if ( q == NULL ) + { + warnFL( eMsg1("rule %s not defined",p->text), FileStr[p->file], p->line ); + return NULL; + } + r = RulePtr[q->rulenum]; + if ( r->pred_lock[1] ) + { + /* infinite left-recursion; ignore 'cause LL sup 1 (k) analysis + * must have seen it earlier. + */ + return NULL; + } + + /* MR10 There should only be one halt set at a time. */ + /* MR10 Life would have been easier with a global variable */ + /* MR10 (at least for this particular need) */ + /* MR10 Unset the old one and set the new one, later undo. */ + + require(r->end->halt == FALSE,"should only have one halt at a time"); + +/* MR10 */ require(MR_RuleBlkWithHalt == NULL || +/* MR10 */ (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == TRUE), +/* MR10 */ "RuleBlkWithHalt->end not RuleBlk or does not have halt set"); +/* MR10 */ if (MR_RuleBlkWithHalt != NULL) { +/* MR10 */ MR_RuleBlkWithHalt->end->halt=FALSE; +/* MR10 */ }; + +/*** fprintf(stderr,"\nSetting halt on junction #%d\n",r->end->seq); ***/ + + require(r->end->halt == FALSE,"rule->end->halt already set"); + + save_MR_RuleBlkWithHalt=MR_RuleBlkWithHalt; + +/* MR10 */ MR_pointerStackPush(&MR_RuleBlkWithHaltStack,MR_RuleBlkWithHalt); +/* MR10 */ MR_pointerStackPush(&MR_PredRuleRefStack,p); + + r->end->halt = TRUE; +/* MR10 */ MR_RuleBlkWithHalt=r; + + a = find_predicates((Node *)r); + + require(r->end->halt == TRUE,"rule->end->halt not set"); + r->end->halt = FALSE; + +/* MR10 */ MR_pointerStackPop(&MR_PredRuleRefStack); +/* MR10 */ MR_RuleBlkWithHalt=(Junction *) MR_pointerStackPop(&MR_RuleBlkWithHaltStack); + + require (MR_RuleBlkWithHalt==save_MR_RuleBlkWithHalt, + "RuleBlkWithHaltStack not consistent"); + +/* MR10 */ require(MR_RuleBlkWithHalt == NULL || +/* MR10 */ (MR_RuleBlkWithHalt->jtype == RuleBlk && MR_RuleBlkWithHalt->end->halt == FALSE), +/* MR10 */ "RuleBlkWithHalt->end not RuleBlk or has no halt set"); +/* MR10 */ if (MR_RuleBlkWithHalt != NULL) { +/* MR10 */ MR_RuleBlkWithHalt->end->halt=TRUE; +/* MR10 */ }; + +/*** fprintf(stderr,"\nRestoring halt on junction #%d\n",r->end->seq); ***/ + + if ( a==NULL ) return NULL; + + /* attempt to compute the "local" FOLLOW just like in normal lookahead + * computation if needed + */ + + complete_context_sets(p,a); + complete_context_trees(p,a); + +/* MR10 */ MR_cleanup_pred_trees(a); + + return a; + } + case nToken : + break; + } + + return NULL; +} + +#ifdef __USE_PROTOS +Predicate *MR_find_predicates_and_supp(Node *alt) +#else +Predicate *MR_find_predicates_and_supp(alt) + Node *alt; +#endif +{ + Predicate *p; + + p=find_predicates(alt); + p=MR_suppressK(alt,p); + return p; +} + +Predicate * +#ifdef __USE_PROTOS +new_pred( void ) +#else +new_pred( ) +#endif +{ + Predicate *p = (Predicate *) calloc(1,sizeof(Predicate)); /* MR10 */ + require(p!=NULL, "new_pred: cannot alloc predicate"); + p->scontext[0]=empty; + p->scontext[1]=empty; + p->completionTree=empty; + p->completionSet=empty; + p->plainSet=empty; + return p; +} + +static void +#ifdef __USE_PROTOS +complete_context_sets( RuleRefNode *p, Predicate *a ) +#else +complete_context_sets( p, a ) +RuleRefNode *p; +Predicate *a; +#endif +{ + set rk2, b; + int k2; + +#ifdef DBG_PRED + fprintf(stderr, "enter complete_context_sets\n"); +#endif + for (; a!=NULL; a=a->right) + { + if ( a->expr == PRED_AND_LIST || a->expr == PRED_OR_LIST ) + { + complete_context_sets(p,a->down); + continue; + } + rk2 = b = empty; + while ( !set_nil(a->completionSet) ) + { + k2 = set_int(a->completionSet); + set_rm(k2, a->completionSet); + + REACH(p->next, k2, &rk2, b); + set_orin(&(a->scontext[1]), b); + set_free(b); + } + + set_orin(&(a->completionSet), rk2);/* remember what we couldn't do */ + set_free(rk2); +#ifdef DBG_PRED + fprintf(stderr, "LL(1) context for %s(addr 0x%x) after ruleref:", a->expr, a); + s_fprT(stderr, a->scontext[1]); + fprintf(stderr, "\n"); +#endif +/* complete_context_sets(p, a->down);*/ + } +#ifdef DBG_PRED + fprintf(stderr, "exit complete_context_sets\n"); +#endif +} + +static void +#ifdef __USE_PROTOS +complete_context_trees( RuleRefNode *p, Predicate *a ) +#else +complete_context_trees( p, a ) +RuleRefNode *p; +Predicate *a; +#endif +{ + set rk2; + int k2; + Tree *u; + +#ifdef DBG_PRED + fprintf(stderr, "enter complete_context_trees\n"); +#endif + for (; a!=NULL; a=a->right) + { + if ( a->expr == PRED_AND_LIST || a->expr == PRED_OR_LIST ) + { + complete_context_trees(p, a->down); + continue; + } + rk2 = empty; + + /* any k left to do? if so, link onto tree */ + while ( !set_nil(a->completionTree) ) + { + k2 = set_int(a->completionTree); + set_rm(k2, a->completionTree); + u = NULL; + + TRAV(p->next, k2, &rk2, u); + + /* any subtrees missing k2 tokens, add u onto end */ + a->tcontext = tlink(a->tcontext, u, k2); + Tfree(u); /* MR10 */ + } + set_orin(&(a->completionTree), rk2);/* remember what we couldn't do */ + set_free(rk2); +#ifdef DBG_PRED + fprintf(stderr, "LL(i<%d) context after ruleref:", LL_k); + preorder(a->tcontext); + fprintf(stderr, "\n"); +#endif +/* complete_context_trees(p, a->down);*/ + } +#ifdef DBG_PRED + fprintf(stderr, "exit complete_context_trees\n"); +#endif +} + +/* Walk a list of predicates and return the set of all tokens in scontext[1]'s */ +set +#ifdef __USE_PROTOS +covered_set( Predicate *p ) +#else +covered_set( p ) +Predicate *p; +#endif +{ + set a; + + a = empty; + for (; p!=NULL; p=p->right) + { + if ( p->expr == PRED_AND_LIST || p->expr == PRED_OR_LIST ) + { + set_orin(&a, covered_set(p->down)); + continue; + } + set_orin(&a, p->scontext[1]); + set_orin(&a, covered_set(p->down)); + } + return a; +} + +/* MR10 predicate_free() + MR10 Don't free the leaf nodes since they are part of the action node +*/ + +#ifdef __USE_PROTOS +void predicate_free(Predicate *p) +#else +void predicate_free(p) + Predicate *p; +#endif +{ + if (p == NULL) return; + predicate_free(p->right); + predicate_free(p->down); + if (p->cloned || + p->source == NULL || + p->source->guardpred == NULL || + p->expr == PRED_AND_LIST || + p->expr == PRED_OR_LIST) { + set_free(p->scontext[1]); + set_free(p->completionSet); + set_free(p->completionTree); + set_free(p->plainSet); + Tfree(p->tcontext); + free( (char *) p); + } else { + p->right=NULL; + p->down=NULL; /* MR13 *** debug */ + }; +} + +/* MR10 predicate_dup() */ + +#ifdef __USE_PROTOS +Predicate * predicate_dup_xxx(Predicate *p,int contextToo) +#else +Predicate * predicate_dup_xxx(p,contextToo) + Predicate *p; + int contextToo; +#endif +{ + Predicate *q; + + if (p == NULL) return NULL; + q=new_pred(); + q->down=predicate_dup(p->down); + q->right=predicate_dup(p->right); + + /* + don't replicate expr - it is read-only + and address comparison is used to look + for identical predicates. + */ + + q->expr=p->expr; + q->k=p->k; + q->source=p->source; + q->cloned=1; + q->ampersandStyle=p->ampersandStyle; + q->inverted=p->inverted; + q->predEntry=p->predEntry; + q->plainSet=set_dup(p->plainSet); + + if (contextToo) { + q->tcontext=tdup(p->tcontext); + q->scontext[0]=set_dup(p->scontext[0]); + q->scontext[1]=set_dup(p->scontext[1]); + q->completionTree=set_dup(p->completionTree); + q->completionSet=set_dup(p->completionSet); + }; + + /* don't need to dup "redundant" */ + + return q; + +} + +#ifdef __USE_PROTOS +Predicate * predicate_dup_without_context(Predicate *p) +#else +Predicate * predicate_dup_without_context(p) + Predicate *p; +#endif +{ + return predicate_dup_xxx(p,0); +} + +#ifdef __USE_PROTOS +Predicate * predicate_dup(Predicate *p) +#else +Predicate * predicate_dup(p) + Predicate *p; +#endif +{ + return predicate_dup_xxx(p,1); +} + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/proto.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/proto.h new file mode 100644 index 00000000..33f7b371 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/proto.h @@ -0,0 +1,857 @@ +/* + * proto.h -- function prototypes + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + + /* V a r i a b l e s */ + +extern int tp; +extern Junction *SynDiag; +extern char Version[]; +extern char VersionDef[]; +#ifdef __cplusplus +extern void (*fpPrint[])(...); +#else +extern void (*fpPrint[])(); +#endif +#ifdef __cplusplus +extern struct _set (*fpReach[])(...); +#else +extern struct _set (*fpReach[])(); +#endif +#ifdef __cplusplus +extern struct _tree *(*fpTraverse[])(...); +#else +extern struct _tree *(*fpTraverse[])(); +#endif +#ifdef __cplusplus +extern void (**fpTrans)(...); +#else +extern void (**fpTrans)(); +#endif +#ifdef __cplusplus +extern void (**fpJTrans)(...); +#else +extern void (**fpJTrans)(); +#endif +#ifdef __cplusplus +extern void (*C_Trans[NumNodeTypes+1])(...); +#else +extern void (*C_Trans[])(); +#endif +#ifdef __cplusplus +extern void (*C_JTrans[NumJuncTypes+1])(...); +#else +extern void (*C_JTrans[])(); +#endif +extern int BlkLevel; +extern int CurFile; +extern char *CurPredName; +extern char *CurRule; +extern int CurRuleDebug; /* MR13 */ +extern Junction *CurRuleBlk; +extern RuleEntry *CurRuleNode; +extern ListNode *CurElementLabels; +extern ListNode *CurAstLabelsInActions; /* MR27 */ +extern ListNode *ContextGuardPredicateList; /* MR13 */ +extern ListNode *CurActionLabels; +extern int numericActionLabel; /* MR10 << ... $1 ... >> or << ... $1 ... >>? */ +extern ListNode *NumericPredLabels; /* MR10 << ... $1 ... >>? ONLY */ +extern char *FileStr[]; +extern int NumFiles; +extern int EpToken; +extern int WildCardToken; +extern Entry **Tname, + **Texpr, + **Rname, + **Fcache, + **Tcache, + **Elabel, + **Sname, + **Pname; /* MR11 */ +extern ListNode *ExprOrder; +extern ListNode **Cycles; +extern int TokenNum; +extern int LastTokenCounted; +extern ListNode *BeforeActions, *AfterActions, *LexActions; + +/* MR1 */ +/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ +/* MR1 via #lexmember <<....>> & #lexprefix <<...>> */ +/* MR1 */ + +extern ListNode *LexMemberActions; /* MR1 */ +extern ListNode *LexPrefixActions; /* MR1 */ + +extern set *fset; /* for constrained search */ /* MR11 */ +extern int maxk; /* for constrained search */ /* MR11 */ +extern int Save_argc; /* MR10 */ +extern char **Save_argv; /* MR10 */ +extern ListNode *eclasses, *tclasses; +extern char *HdrAction; +extern char *FirstAction; /* MR11 */ +extern FILE *ErrFile; +extern char *RemapFileName; +extern char *ErrFileName; +extern char *DlgFileName; +extern char *DefFileName; +extern char *ModeFileName; +extern char *StdMsgName; +extern int NumRules; +extern Junction **RulePtr; +extern int LL_k; +extern int CLL_k; +extern char *decodeJType[]; +extern int PrintOut; +extern int PrintAnnotate; +extern int CodeGen; +extern int LexGen; +extern int esetnum; +extern int setnum; +extern int wordnum; +extern int GenAST; +extern int GenANSI; +extern int **FoStack; +extern int **FoTOS; +extern int GenExprSetsOpt; +extern FILE *DefFile; +extern int CannotContinue; +extern int GenCR; +extern int GenLineInfo; +extern int GenLineInfoMS; +extern int action_file, action_line; +extern int TraceGen; +extern int CurAmbigAlt1, CurAmbigAlt2, CurAmbigline, CurAmbigfile; +extern char *CurAmbigbtype; +extern int elevel; +extern int GenEClasseForRules; +extern FILE *input, *output; +extern char **TokenStr, **ExprStr; +extern int CurrentLexClass, NumLexClasses; +extern LClass lclass[]; +extern char LexStartSymbol[]; +extern char *CurRetDef; +extern char *CurParmDef; +extern int OutputLL_k; +extern int TreeResourceLimit; +extern int DemandLookahead; +extern char *RulePrefix; +extern int GenStdPccts; +extern char *stdpccts; +extern int ParseWithPredicates; +extern int ConstrainSearch; +extern int PURIFY; /* MR23 */ + +extern set MR_CompromisedRules; /* MR14 */ +extern int MR_AmbSourceSearch; /* MR11 */ +extern int MR_SuppressSearch; /* MR13 */ +extern int MR_AmbSourceSearchGroup; /* MR11 */ +extern int MR_AmbSourceSearchChoice; /* MR11 */ +extern int MR_AmbSourceSearchLimit; /* MR11 */ +extern int MR_usingPredNames; /* MR11 */ +extern int MR_ErrorSetComputationActive; /* MR14 */ +extern char *MR_AmbAidRule; /* MR11 */ +extern int MR_AmbAidLine; /* MR11 */ +extern int MR_AmbAidMultiple; /* MR11 */ +extern int MR_AmbAidDepth; /* MR11 */ +extern int MR_skipped_e3_report; /* MR11 */ +extern int MR_matched_AmbAidRule; /* MR11 */ +extern int MR_Inhibit_Tokens_h_Gen; /* MR13 */ +extern int NewAST; /* MR13 */ +extern int tmakeInParser; /* MR23 */ +extern int AlphaBetaTrace; /* MR14 */ +extern int MR_BlkErr; /* MR21 */ +extern int MR_AlphaBetaWarning; /* MR14 */ +extern int MR_AlphaBetaMessageCount; /* MR14 */ +extern int MR_MaintainBackTrace; /* MR14 */ +extern int MR_BadExprSets; /* MR13 */ +extern int FoundGuessBlk; +extern int FoundException; +extern int FoundAtOperator; /* MR6 */ +extern int FoundExceptionGroup; /* MR6 */ +extern int WarningLevel; +extern int UseStdout; /* MR6 */ +extern int TabWidth; /* MR6 */ +extern int pLevel; +extern int pAlt1; +extern int pAlt2; +extern int AImode; +extern int HoistPredicateContext; +extern int MRhoisting; /* MR9 */ +extern int MRhoistingk; /* MR13 */ +extern int MR_debugGenRule; /* MR11 */ +extern int GenCC; +extern char *ParserName; +extern char *StandardSymbols[]; +extern char *ASTSymbols[]; +extern set reserved_positions; +extern set all_tokens; +extern set imag_tokens; +extern set tokclasses; +extern ListNode *ForcedTokens; +extern int *TokenInd; +extern FILE *Parser_h, *Parser_c; +extern char CurrentClassName[]; +extern int no_classes_found; +extern char Parser_h_Name[]; +extern char Parser_c_Name[]; +extern char MRinfoFile_Name[]; /* MR10 */ +extern FILE *MRinfoFile; /* MR10 */ +extern int MRinfo; /* MR10 */ +extern int MRinfoSeq; /* MR10 */ +extern int InfoP; /* MR10 */ +extern int InfoT; /* MR10 */ +extern int InfoF; /* MR10 */ +extern int InfoM; /* MR10 */ +extern int InfoO; /* MR12 */ +extern int PotentialSuppression; /* MR10 */ +extern int PotentialDummy; /* MR10 */ +extern int TnodesInUse; /* MR10 */ +extern int TnodesPeak; /* MR10 */ +extern int TnodesReportThreshold; /* MR11 */ +extern int TnodesAllocated; /* MR10 */ +extern char *ClassDeclStuff; /* MR10 */ +extern char *BaseClassName; /* MR22 */ +extern ListNode *class_before_actions, *class_after_actions; +extern char *UserTokenDefsFile; +extern int UserDefdTokens; +extern ListNode *MetaTokenNodes; +extern char *OutputDirectory; +extern int DontCopyTokens; +extern int LTinTokenAction; /* MR23 */ +extern set AST_nodes_refd_in_actions; +extern ListNode *CurExGroups; +extern int CurBlockID; +extern int CurAltNum; +extern Junction *CurAltStart; +extern Junction *OuterAltStart; /* chain exception groups MR7 */ +extern ExceptionGroup *DefaultExGroup; +extern int NumSignals; +extern int ContextGuardTRAV; +extern Junction *MR_RuleBlkWithHalt; /* MR10 */ +extern PointerStack MR_BackTraceStack; /* MR10 */ +extern PointerStack MR_PredRuleRefStack; /* MR10 */ +extern PointerStack MR_RuleBlkWithHaltStack; /* MR10 */ + +/* */ +/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ +/* MR1 in DLG action */ +/* */ +extern int tokenActionActive; /* MR1 */ + +extern char *PRED_OR_LIST; /* MR10 */ +extern char *PRED_AND_LIST; /* MR10 */ + +#ifdef __VMS +#define STRICMP strcasecmp /* MR21 */ +#else +#define STRICMP stricmp /* MR21 */ +#endif + +/* MR26 */ +#ifdef PCCTS_USE_STDARG +extern Tree *tmake(Tree *root, ...); +#else +extern Tree *tmake(); +#endif + +#ifdef __USE_PROTOS +extern int STRICMP(const char*, const char*); +extern void istackreset(void); +extern int istacksize(void); +extern void pushint(int); +extern int popint( void ); +extern int istackempty( void ); +extern int topint( void ); +extern void NewSetWd( void ); +extern void DumpSetWd( void ); +extern void DumpSetWdForC( void ); +extern void DumpSetWdForCC( void ); +extern void NewSet( void ); +extern void FillSet( set ); +extern void ComputeErrorSets( void ); +extern void ComputeTokSets( void ); +extern void SubstErrorClass( set * ); +extern int DefErrSet( set *, int, char * ); +extern int DefErrSetForC( set *, int, char * ); +extern int DefErrSetForCC( set *, int, char * ); +extern int DefErrSet1(int, set *, int, char *); /* MR21 */ +extern int DefErrSetForC1(int, set *, int, char *, const char* ); /* MR21 */ +extern int DefErrSetForCC1(int, set *, int, char *, const char* ); /* MR21 */ +extern int DefErrSetWithSuffix(int, set *, int, char *, const char *); /* MR21 */ +extern void GenErrHdr( void ); +extern void dumpExpr( FILE *, char * ); +extern void addParm( Node *, char * ); +extern Graph buildAction( char *, int, int, int ); +extern Graph buildToken( char * ); +extern Graph buildWildCard( char * ); +extern Graph buildRuleRef( char * ); +extern Graph Or( Graph, Graph ); +extern Graph Cat( Graph, Graph ); +extern Graph makeOpt( Graph, int, char *); +extern Graph makeBlk( Graph, int, char *); +extern Graph makeLoop( Graph, int, char *); +extern Graph makePlus( Graph, int, char *); +extern Graph emptyAlt( void ); +extern Graph emptyAlt3( void ); +extern TokNode * newTokNode( void ); +extern RuleRefNode * newRNode( void ); +extern Junction * newJunction( void ); +extern ActionNode * newActionNode( void ); +extern char * makelocks( void ); +extern void preorder( Tree * ); +extern Tree * tnode( int ); +extern void _Tfree( Tree * ); +extern Tree * tdup( Tree * ); +extern int is_single_tuple( Tree * ); +extern Tree * tappend( Tree *, Tree * ); +extern void Tfree( Tree * ); +extern Tree * tlink( Tree *, Tree *, int ); +extern Tree * tshrink( Tree * ); +extern Tree * tflatten( Tree * ); +extern Tree * tJunc( Junction *, int, set * ); +extern Tree * tRuleRef( RuleRefNode *, int, set * ); +extern Tree * tToken( TokNode *, int, set * ); +extern Tree * tAction( ActionNode *, int, set * ); +extern int tmember( Tree *, Tree * ); +extern int tmember_constrained( Tree *, Tree * ); +extern Tree * tleft_factor( Tree * ); +extern Tree * trm_perm( Tree *, Tree * ); +extern void tcvt( set *, Tree * ); +extern Tree * permute( int, int ); +extern Tree * VerifyAmbig( Junction *, Junction *, unsigned **, set *, Tree **, Tree **, int * ); +extern set rJunc( Junction *, int, set * ); +extern set rRuleRef( RuleRefNode *, int, set * ); +extern set rToken( TokNode *, int, set * ); +extern set rAction( ActionNode *, int, set * ); +extern void HandleAmbiguity( Junction *, Junction *, Junction *, int ); +extern set First( Junction *, int, int, int * ); +extern void freeBlkFsets( Junction * ); +extern void genAction( ActionNode * ); +extern void genRuleRef( RuleRefNode * ); +extern void genToken( TokNode * ); +extern void genOptBlk( Junction * ); +extern void genLoopBlk( Junction *, Junction *, Junction *, int ); +extern void genLoopBegin( Junction * ); +extern void genPlusBlk( Junction * ); +extern void genSubBlk( Junction * ); +extern void genRule( Junction * ); +extern void genJunction( Junction * ); +extern void genEndBlk( Junction * ); +extern void genEndRule( Junction * ); +extern void genHdr( int ); +extern void genHdr1( int ); +extern void dumpAction( char *, FILE *, int, int, int, int ); +extern void dumpActionPlus(ActionNode*, char *, FILE *, int, int, int, int ); /* MR21 */ +extern Entry ** newHashTable( void ); +extern Entry * hash_add( Entry **, char *, Entry * ); +extern Entry * hash_get( Entry **, char * ); +extern void hashStat( Entry ** ); +extern char * mystrdup( char * ); +extern void genLexDescr( void ); +extern void dumpLexClasses( FILE * ); +extern void genDefFile( void ); +extern void DumpListOfParmNames( char *, FILE *, int ); /* MR5 janm 26-May-97 */ +extern int DumpNextNameInDef( char **, FILE * ); +extern void DumpOldStyleParms( char *, FILE * ); +extern void DumpType( char *, FILE * ); +extern int strmember( char *, char * ); +/* extern int HasComma( char * ); MR23 Replaced by hasMultipleOperands() */ +extern void DumpRetValStruct( FILE *, char *, int ); +extern char * StripQuotes( char * ); +extern int main( int, char *[] ); +extern void readDescr( void ); +extern FILE * NextFile( void ); +extern char * outnameX( char *, char *); +extern char * outname( char * ); +extern void fatalFL( char *, char *, int ); +extern void fatal_intern( char *, char *, int ); +#ifdef VBOX +# ifdef __GNUC__ +extern void __attribute__((noreturn)) fatal_intern( char *, char *, int ); +# endif +#endif +extern void cleanUp( void ); +extern char * eMsg3( char *, char *, char *, char * ); +extern char * eMsgd( char *, int ); +extern char * eMsgd2( char *, int, int ); +extern void s_fprT( FILE *, set ); +extern char * TerminalString( int ); +extern void lexclass( char * ); +extern void lexmode( int ); +extern int LexClassIndex( char * ); +extern int hasAction( char * ); +extern void setHasAction( char *, char * ); +extern int addTname( char * ); +extern int addTexpr( char * ); +extern int Tnum( char * ); +extern void Tklink( char *, char * ); +extern Entry * newEntry( char *, int ); +extern void list_add( ListNode **, void * ); +extern void list_free( ListNode **, int freeData ); /* MR10 */ +extern void list_apply( ListNode *, void (*)(void *) ); +extern int list_search_cstring (ListNode *, char *); /* MR27 */ +extern char * Fkey( char *, int, int ); +extern void FoPush( char *, int ); +extern void FoPop( int ); +extern void RegisterCycle( char *, int ); +extern void ResolveFoCycles( int ); +extern void pJunc( Junction * ); +extern void pRuleRef( RuleRefNode * ); +extern void pToken( TokNode * ); +extern void pAction( ActionNode * ); +extern void FoLink( Node * ); +extern void addFoLink( Node *, char *, Junction * ); +extern void GenCrossRef( Junction * ); +extern void defErr( char *, long, long, long, long, long, long ); +extern void genStdPCCTSIncludeFile(FILE *,char *); /* MR10 */ +extern char * pcctsBaseName(char *); /* MR32 */ +extern Predicate *find_predicates(Node *); /* MR10 */ +extern Predicate *MR_find_predicates_and_supp(Node *); /* MR13 */ +extern int predicateLookaheadDepth(ActionNode *); /* MR10 */ +extern void predicate_free(Predicate *); /* MR10 */ +extern Predicate * predicate_dup(Predicate *); /* MR10 */ +extern Predicate * predicate_dup_without_context(Predicate *); /* MR11 */ +extern void GenRulePrototypes(FILE *, Junction *); +extern Junction *first_item_is_guess_block(Junction *); +extern Junction *first_item_is_guess_block_extra(Junction * q); /* MR30 */ +extern Junction *analysis_point(Junction *); +extern Tree *make_tree_from_sets(set *, set *); +extern Tree *tdup_chain(Tree *); +extern Tree *tdif(Tree *, Predicate *, set *, set *); +extern set covered_set(Predicate *); +extern void AmbiguityDialog(Junction *, int, Junction *, Junction *, int *, int *); +extern void dumpAmbigMsg(set *, FILE *, int); +extern void GenRuleFuncRedefs(FILE *, Junction *); +extern void GenPredefinedSymbolRedefs(FILE *); +extern void GenASTSymbolRedefs(FILE *); +extern void GenRemapFile(void); +extern void GenSetRedefs(FILE *); +extern ForcedToken *newForcedToken(char *, int); +extern void RemapForcedTokens(void); +extern char *TokenOrExpr(int); +extern void setUpperRange(TokNode *, char *); +extern void GenParser_c_Hdr(void); +extern void GenParser_h_Hdr(void); +extern void GenRuleMemberDeclarationsForCC(FILE *, Junction *); +extern int addForcedTname( char *, int ); +extern char *OutMetaName(char *); +extern void OutFirstSetSymbol(Junction *q, char *); /* MR21 */ +extern void warnNoFL(char *err); +extern void warnFL(char *err,char *f,int l); +extern void warn(char *err); +extern void warnNoCR( char *err ); +extern void errNoFL(char *err); +extern void errFL(char *err,char *f,int l); +extern void err(char *err); +extern void errNoCR( char *err ); +extern void genPredTree( Predicate *p, Node *j, int ,int); +extern UserAction *newUserAction(char *); +extern char *gate_symbol(char *name); +extern char *makeAltID(int blockid, int altnum); +extern void DumpRemainingTokSets(void); +extern void DumpANSIFunctionArgDef(FILE *f, Junction *q, int bInit); /* MR23 */ +extern void DumpFormals(FILE *, char *, int bInit); /* MR23 */ +extern char* hideDefaultArgs(const char* pdecl); /* MR22 VHS */ +extern Predicate *computePredFromContextGuard(Graph,int *msgDone); /* MR21 */ +extern void recomputeContextGuard(Predicate *); /* MR13 */ +extern Predicate *new_pred(void); +extern void chkGTFlag(void); +extern void leAdd(LabelEntry *); /* MR7 */ +extern void leFixup(void); /* MR7 */ +extern void egAdd(ExceptionGroup *); /* MR7 */ +extern void egFixup(void); /* MR7 */ +extern void altAdd(Junction *); /* MR7 */ +extern void altFixup(void); /* MR7 */ +extern Predicate * MR_find_in_aSubBlk(Junction *alt); /* MR10 */ +extern Predicate * MR_predFlatten(Predicate *p); /* MR10 */ +extern Predicate * MR_predSimplifyALL(Predicate *p); /* MR10 */ +extern Predicate * MR_predSimplifyALLX(Predicate *p,int skipPass3); /* MR10 */ +extern int MR_allPredLeaves(Predicate *p); /* MR10 */ +extern void MR_cleanup_pred_trees(Predicate *p); /* MR10 */ +extern int MR_predicate_context_completed(Predicate *p); /* MR10 */ +extern void MR_check_pred_too_long(Predicate *p,set completion); /* MR10 */ +extern Tree * MR_remove_epsilon_from_tree(Tree *t); /* MR10 */ +extern Tree * MR_computeTreeAND(Tree *l,Tree *r); /* MR10 */ +extern int MR_tree_equ(Tree *big, Tree *small); /* MR10 */ +extern set MR_First(int ck,Junction *j,set *incomplete); /* MR10 */ +extern set MR_compute_pred_set(Predicate *p); /* MR10 */ +extern Tree * MR_compute_pred_tree_context(Predicate *p); /* MR10 */ +extern int MR_pointerStackPush(PointerStack *,void *); /* MR10 */ +extern void * MR_pointerStackPop(PointerStack *); /* MR10 */ +extern void * MR_pointerStackTop(PointerStack *); /* MR10 */ +extern void MR_pointerStackReset(PointerStack *); /* MR10 */ +extern void MR_backTraceReport(void); /* MR10 */ +extern void MR_alphaBetaTraceReport(void); /* MR14 */ +extern void MR_dumpRuleSet(set); /* MR14 */ +extern void MR_predContextPresent(Predicate *p,int *,int *); /* MR10 */ +extern void MR_dumpPred(Predicate *p,int withContext); /* MR10 */ +extern void MR_dumpPred1(int,Predicate *p,int withContext); /* MR10 */ +extern void MR_xxxIndent(FILE *f,int depth); /* MR11 */ +extern void MR_outputIndent(int depth); /* MR11 */ +extern void MR_stderrIndent(int depth); /* MR11 */ +extern Junction * MR_ruleReferenced(RuleRefNode *rrn); /* MR10 */ +extern Junction * MR_nameToRuleBlk(char *); /* MR10 */ +extern void MR_releaseResourcesUsedInRule(Node *); /* MR10 */ +extern void MR_dumpTreeX(int depth,Tree *t,int across); /* MR10 */ +extern void MR_dumpTreeF(FILE *f,int depth,Tree *t,int across); /* MR10 */ +extern void DumpFcache(void); /* MR10 */ +extern void MR_dumpTokenSet(FILE *f,int depth,set s); /* MR10 */ +extern void MR_traceAmbSource(set *,Junction *,Junction *); /* MR11 */ +extern void MR_traceAmbSourceK(Tree *,Junction *a1,Junction *a2); /* MR11 */ +extern void MR_traceAmbSourceKclient(void); /* MR20 */ +extern Node *MR_advance(Node *); /* MR11 */ +extern int MR_offsetFromRule(Node *); /* MR11 */ +extern char *MR_ruleNamePlusOffset(Node *); /* MR11 */ +extern int MR_max_height_of_tree(Tree *); /* MR11 */ +extern int MR_all_leaves_same_height(Tree *,int); /* MR11 */ +extern void MR_projectTreeOntoSet(Tree *t,int k,set *); /* MR11 */ +extern Tree *MR_make_tree_from_set(set); /* MR11 */ +extern Predicate *MR_removeRedundantPredPass3(Predicate *); /* MR11 */ +extern void MR_pred_depth(Predicate *,int *); /* MR11 */ +extern int MR_comparePredicates(Predicate *,Predicate *); /* MR11 */ +extern Predicate * MR_unfold(Predicate *); /* MR11 */ +extern void MR_simplifyInverted(Predicate *,int); /* MR11 */ +extern int MR_secondPredicateUnreachable /* MR11 */ + (Predicate *first,Predicate *second); /* MR11 */ +extern void MR_clearPredEntry(Predicate *); /* MR11 */ +extern void MR_orphanRules(FILE *); /* MR12 */ +extern void MR_merge_contexts(Tree *); /* MR12 */ +extern int ci_strequ(char *,char *); /* MR12 */ +extern void MR_guardPred_plainSet(ActionNode *anode,Predicate *); /* MR12c */ +extern void MR_suppressSearchReport(void); /* MR12c */ +extern Predicate * MR_suppressK(Node *,Predicate *); /* MR13 */ +extern void MR_backTraceDumpItem(FILE *,int skip,Node *n); /* MR13 */ +extern void MR_backTraceDumpItemReset(void); /* MR13 */ +extern Junction * MR_junctionWithoutP2(Junction *); /* MR13 */ +extern void MR_setConstrainPointer(set *); /* MR18 */ +extern void BlockPreambleOption(Junction *q, char * pSymbol); /* MR23 */ +extern char* getInitializer(char *); /* MR23 */ +extern char *endFormal(char *pStart, /* MR23 */ + char **ppDataType, /* MR23 */ + char **ppSymbol, /* MR23 */ + char **ppEqualSign, /* MR23 */ + char **ppValue, /* MR23 */ + char **ppSeparator, /* MR23 */ + int *pNext); /* MR23 */ +extern char *strBetween(char *pStart, /* MR23 */ + char *pNext, /* MR23 */ + char *pStop); /* MR23 */ +extern int hasMultipleOperands(char *); /* MR23 */ +extern void DumpInitializers(FILE*, RuleEntry*, char*); /* MR23 */ +extern int isTermEntryTokClass(TermEntry *); /* MR23 */ +extern int isEmptyAlt(Node *, Node *); /* MR23 */ +#else +extern int STRICMP(); +extern void istackreset(); +extern int istacksize(); +extern void pushint(); +extern int popint(); +extern int istackempty(); +extern int topint(); +extern void NewSetWd(); +extern void DumpSetWd(); +extern void DumpSetWdForC(); +extern void DumpSetWdForCC(); +extern void NewSet(); +extern void FillSet(); +extern void ComputeErrorSets(); +extern void ComputeTokSets(); +extern void SubstErrorClass(); +extern int DefErrSet(); +extern int DefErrSetForC(); +extern int DefErrSetForCC(); +extern int DefErrSet1(); +extern int DefErrSetForC1(); +extern int DefErrSetForCC1(); +extern int DefErrSetWithSuffix(); /* MR21 */ +extern void GenErrHdr(); +extern void dumpExpr(); +extern void addParm(); +extern Graph buildAction(); +extern Graph buildToken(); +extern Graph buildWildCard(); +extern Graph buildRuleRef(); +extern Graph Or(); +extern Graph Cat(); +extern Graph makeOpt(); +extern Graph makeBlk(); +extern Graph makeLoop(); +extern Graph makePlus(); +extern Graph emptyAlt(); +extern Graph emptyAlt3(); +extern TokNode * newTokNode(); +extern RuleRefNode * newRNode(); +extern Junction * newJunction(); +extern ActionNode * newActionNode(); +extern char * makelocks(); +extern void preorder(); +extern Tree * tnode(); +extern void _Tfree(); +extern Tree * tdup(); +extern int is_single_tuple(); +extern Tree * tappend(); +extern void Tfree(); +extern Tree * tlink(); +extern Tree * tshrink(); +extern Tree * tflatten(); +extern Tree * tJunc(); +extern Tree * tRuleRef(); +extern Tree * tToken(); +extern Tree * tAction(); +extern int tmember(); +extern int tmember_constrained(); +extern Tree * tleft_factor(); +extern Tree * trm_perm(); +extern void tcvt(); +extern Tree * permute(); +extern Tree * VerifyAmbig(); +extern set rJunc(); +extern set rRuleRef(); +extern set rToken(); +extern set rAction(); +extern void HandleAmbiguity(); +extern set First(); +extern void freeBlkFsets(); +extern void genAction(); +extern void genRuleRef(); +extern void genToken(); +extern void genOptBlk(); +extern void genLoopBlk(); +extern void genLoopBegin(); +extern void genPlusBlk(); +extern void genSubBlk(); +extern void genRule(); +extern void genJunction(); +extern void genEndBlk(); +extern void genEndRule(); +extern void genHdr(); +extern void genHdr1(); +extern void dumpAction(); +extern void dumpActionPlus(); /* MR21 */ +extern Entry ** newHashTable(); +extern Entry * hash_add(); +extern Entry * hash_get(); +extern void hashStat(); +extern char * mystrdup(); +extern void genLexDescr(); +extern void dumpLexClasses(); +extern void genDefFile(); +extern void DumpListOfParmNames(); /* MR5 janm 26-May-97 */ +extern int DumpNextNameInDef(); +extern void DumpOldStyleParms(); +extern void DumpType(); +extern int strmember(); +/* extern int HasComma(); MR23 Replaced by hasMultipleOperands() */ +extern void DumpRetValStruct(); +extern char * StripQuotes(); +extern int main(); +extern void readDescr(); +extern FILE * NextFile(); +extern char * outnameX(); +extern char * outname(); +extern void fatalFL(); +extern void fatal_intern(); +extern void cleanUp(); +extern char * eMsg3(); +extern char * eMsgd(); +extern char * eMsgd2(); +extern void s_fprT(); +extern char * TerminalString(); +extern void lexclass(); +extern void lexmode(); +extern int LexClassIndex(); +extern int hasAction(); +extern void setHasAction(); +extern int addTname(); +extern int addTexpr(); +extern int Tnum(); +extern void Tklink(); +extern Entry * newEntry(); +extern void list_add(); +extern void list_free(); /* MR10 */ +extern void list_apply(); +extern int list_search_cstring (); /* MR27 */ +extern char * Fkey(); +extern void FoPush(); +extern void FoPop(); +extern void RegisterCycle(); +extern void ResolveFoCycles(); +extern void pJunc(); +extern void pRuleRef(); +extern void pToken(); +extern void pAction(); +extern void FoLink(); +extern void addFoLink(); +extern void GenCrossRef(); +extern void defErr(); +extern void genStdPCCTSIncludeFile(); +extern char * pcctsBaseName(); /* MR32 */ +extern Predicate *find_predicates(); +extern Predicate *MR_find_predicates_and_supp(); /* MR13 */ +extern int predicateLookaheadDepth(); /* MR10 */ +extern void predicate_free(); /* MR10 */ +extern Predicate * predicate_dup(); /* MR10 */ +extern Predicate * predicate_dup_without_context(); /* MR11 */ +extern void GenRulePrototypes(); +extern Junction *first_item_is_guess_block(); +extern Junction *first_item_is_guess_block_extra(); /* MR30 */ +extern Junction *analysis_point(); +extern Tree *make_tree_from_sets(); +extern Tree *tdup_chain(); +extern Tree *tdif(); +extern set covered_set(); +extern void AmbiguityDialog(); +extern void dumpAmbigMsg(); +extern void GenRuleFuncRedefs(); +extern void GenPredefinedSymbolRedefs(); +extern void GenASTSymbolRedefs(); +extern void GenRemapFile(); +extern void GenSetRedefs(); +extern ForcedToken *newForcedToken(); +extern void RemapForcedTokens(); +extern char *TokenOrExpr(); +extern void setUpperRange(); +extern void GenParser_c_Hdr(); +extern void GenParser_h_Hdr(); +extern void GenRuleMemberDeclarationsForCC(); +extern int addForcedTname(); +extern char *OutMetaName(); +extern void OutFirstSetSymbol(); /* MR21 */ +extern void warnNoFL(); +extern void warnFL(); +extern void warn(); +extern void warnNoCR(); +extern void errNoFL(); +extern void errFL(); +extern void err(); +extern void errNoCR(); +extern void genPredTree(); +extern UserAction *newUserAction(); +extern char *gate_symbol(); +extern char *makeAltID(); +extern void DumpRemainingTokSets(); +extern void DumpANSIFunctionArgDef(); +extern void DumpFormals(); /* MR23 */ +extern char* hideDefaultArgs(); /* MR22 VHS */ +extern Predicate *computePredFromContextGuard(); +extern void recomputeContextGuard(); /* MR13 */ +extern Predicate *new_pred(); +extern void chkGTFlag(); +extern void leAdd(); /* MR7 */ +extern void leFixup(); /* MR7 */ +extern void egAdd(); /* MR7 */ +extern void egFixup(); /* MR7 */ +extern void altAdd(); /* MR7 */ +extern void altFixup(); /* MR7 */ +extern Predicate * MR_find_in_aSubBlk(); /* MR10 */ +extern Predicate * MR_predFlatten(); /* MR10 */ +extern Predicate * MR_predSimplifyALL(); /* MR10 */ +extern Predicate * MR_predSimplifyALLX(); /* MR10 */ +extern void MR_cleanup_pred_trees(); /* MR10 */ +extern int MR_allPredLeaves(); /* MR10 */ +extern int MR_predicate_context_completed(); /* MR10 */ +extern void MR_check_pred_too_long(); /* MR10 */ +extern Tree * MR_remove_epsilon_from_tree(); /* MR10 */ +extern Tree * MR_computeTreeAND(); /* MR10 */ +extern int MR_tree_equ(); /* MR10 */ +extern set MR_First(); /* MR10 */ +extern set MR_compute_pred_set(); /* MR10 */ +extern Tree * MR_compute_pred_tree_context(); /* MR10 */ +extern int MR_pointerStackPush(); /* MR10 */ +extern void * MR_pointerStackPop(); /* MR10 */ +extern void * MR_pointerStackTop(); /* MR10 */ +extern void MR_pointerStackReset(); /* MR10 */ +extern void MR_backTraceReport(); /* MR10 */ +extern void MR_alphaBetaTraceReport(); /* MR14 */ +extern void MR_dumpRuleSet(); /* MR14 */ +extern void MR_predContextPresent(); /* MR10 */ +extern void MR_dumpPred(); /* MR10 */ +extern void MR_dumpPred1(); /* MR10 */ +extern void MR_xxxIndent(); /* MR11 */ +extern void MR_stderrIndent(); /* MR11 */ +extern void MR_outputIndent(); /* MR11 */ +extern Junction * MR_ruleReferenced(); /* MR10 */ +extern void MR_releaseResourcesUsedInRule(); /* MR10 */ +extern void MR_dumpTreeX(); /* MR10 */ +extern void MR_dumpTreeF(); /* MR10 */ +extern void DumpFcache(); /* MR10 */ +extern void MR_dumpTokenSet(); /* MR10 */ +extern void MR_traceAmbSource(); /* MR11 */ +extern Node *MR_advance(); /* MR11 */ +extern int MR_offsetFromRule(); /* MR11 */ +extern char *MR_ruleNamePlusOffset(); /* MR11 */ +extern void MR_traceAmbSourceK(); /* MR11 */ +extern void MR_traceAmbSourceKclient(); /* [i_a] added */ +extern int MR_max_height_of_tree(); /* MR11 */ +extern int MR_all_leaves_same_height(); /* MR11 */ +extern void MR_projectTreeOntoSet(); /* MR11 */ +extern Tree *MR_make_tree_from_set(); /* MR11 */ +extern Predicate *MR_removeRedundantPredPass3(); /* MR11 */ +extern void MR_pred_depth(); /* MR11 */ +extern int MR_comparePredicates(); /* MR11 */ +extern Predicate * MR_unfold(); /* MR11 */ +extern void MR_simplifyInverted(); /* MR11 */ +extern int MR_secondPredicateUnreachable(); /* MR11 */ +extern Junction * MR_nameToRuleBlk(); /* MR10 */ +extern void MR_clearPredEntry(); /* MR11 */ +extern void MR_orphanRules(); /* MR12 */ +extern void MR_merge_contexts(); /* MR12 */ +extern int ci_strequ(); /* MR12 */ +extern void MR_guardPred_plainSet(); /* MR12c */ +extern void MR_suppressSearchReport(); /* MR12c */ +extern Predicate * MR_suppressK(); /* MR13 */ +extern void MR_backTraceDumpItem(); /* MR13 */ +extern void MR_backTraceDumpItemReset(); /* MR13 */ +extern Junction * MR_junctionWithoutP2(); /* MR13 */ +extern void MR_setConstrainPointer(); /* MR18 */ +extern void BlockPreambleOption(); /* MR23 */ +extern char* getInitializer(); /* MR23 */ +extern int hasMultipleOperands(); /* MR23 */ +extern char *endFormal(); /* MR23 */ +extern char *strBetween(); /* MR23 */ +extern void DumpInitializers(); /* MR23 */ +extern int isTermEntryTokClass(); /* MR23 */ +extern int isEmptyAlt(); + +#endif + +#ifdef __USE_PROTOS +#include +#endif + +/* MR20 G. Hobbelt Create proper externs for dlg variables */ + +extern set attribsRefdFromAction; +extern int inAlt; +extern int UsedOldStyleAttrib; +extern int UsedNewStyleLabel; + +#define MAX_BLK_LEVEL 100 /* MR23 */ +extern int CurBlockID_array[MAX_BLK_LEVEL]; /* MR23 */ +extern int CurAltNum_array[MAX_BLK_LEVEL]; /* MR23 */ diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/scan.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/scan.c new file mode 100644 index 00000000..24651f97 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/scan.c @@ -0,0 +1,5735 @@ + +/* parser.dlg -- DLG Description of scanner + * + * Generated from: antlr.g + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + */ + +#define ANTLR_VERSION 13333 +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include "pcctscfg.h" +#include "set.h" +#include +#include "syn.h" +#include "hash.h" +#include "generic.h" +#define zzcr_attr(attr,tok,t) /*vbox: */ memset((attr), 0, sizeof(*attr)) +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +LOOKAHEAD + +void +#ifdef __USE_PROTOS +zzerraction(void) +#else +zzerraction() +#endif +{ + (*zzerr)("invalid token"); + zzadvance(); + zzskip(); +} +/* + * D L G tables + * + * Generated from: parser.dlg + * + * 1989-2001 by Will Cohen, Terence Parr, and Hank Dietz + * Purdue University Electrical Engineering + * DLG Version 1.33MR33 + */ + +#include "mode.h" + + + + +/* maintained, but not used for now */ +set AST_nodes_refd_in_actions = set_init; +int inAlt = 0; +set attribsRefdFromAction = set_init; /* MR20 */ +int UsedOldStyleAttrib = 0; +int UsedNewStyleLabel = 0; +#ifdef __USE_PROTOS +char *inline_set(char *); +#else +char *inline_set(); +#endif + +/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ +/* MR1 in DLG action */ + +int tokenActionActive=0; /* MR1 */ + + + + + +static char * +#ifdef __USE_PROTOS +getFileNameFromTheLineInfo(char *toStr, char *fromStr) +#else +getFileNameFromTheLineInfo(toStr, fromStr) +char *toStr, *fromStr; +#endif +{ + int i, j, k; + + if (!fromStr || !toStr) return toStr; + + /* find the first " */ + + for (i=0; + (ielem->ntype == nToken,"mark_label_used... ntype != nToken"); + tn=(TokNode *)le->elem; + require (tn->label != 0,"mark_label_used... TokNode has no label"); + tn->label_used_in_semantic_pred=1; +} + +static void act1() +{ + NLA = Eof; + /* L o o k F o r A n o t h e r F i l e */ + { + FILE *new_input; + new_input = NextFile(); + if ( new_input == NULL ) { NLA=Eof; return; } + fclose( input ); + input = new_input; + zzrdstream( input ); + zzskip(); /* Skip the Eof (@) char i.e continue */ + } + } + + +static void act2() +{ + NLA = 76; + zzskip(); + } + + +static void act3() +{ + NLA = 77; + zzline++; zzskip(); + } + + +static void act4() +{ + NLA = 78; + zzmode(ACTIONS); zzmore(); + istackreset(); + pushint(']'); + } + + +static void act5() +{ + NLA = 79; + action_file=CurFile; action_line=zzline; + zzmode(ACTIONS); zzmore(); + list_free(&CurActionLabels,0); /* MR10 */ + numericActionLabel=0; /* MR10 */ + istackreset(); + pushint('>'); + } + + +static void act6() +{ + NLA = 80; + zzmode(STRINGS); zzmore(); + } + + +static void act7() +{ + NLA = 81; + zzmode(COMMENTS); zzskip(); + } + + +static void act8() +{ + NLA = 82; + warn("Missing /*; found dangling */"); zzskip(); + } + + +static void act9() +{ + NLA = 83; + zzmode(CPP_COMMENTS); zzskip(); + } + + +static void act10() +{ + NLA = 84; + + zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore(); + getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr); + } + + +static void act11() +{ + NLA = 85; + + zzline++; zzmore(); + } + + +static void act12() +{ + NLA = 86; + warn("Missing <<; found dangling >>"); zzskip(); + } + + +static void act13() +{ + NLA = WildCard; + } + + +static void act14() +{ + NLA = 88; + FoundException = 1; /* MR6 */ + FoundAtOperator = 1; + } + + +static void act15() +{ + NLA = Pragma; + } + + +static void act16() +{ + NLA = FirstSetSymbol; + } + + +static void act17() +{ + NLA = 94; + } + + +static void act18() +{ + NLA = 95; + } + + +static void act19() +{ + NLA = 96; + } + + +static void act20() +{ + NLA = 97; + } + + +static void act21() +{ + NLA = 98; + } + + +static void act22() +{ + NLA = 99; + } + + +static void act23() +{ + NLA = 102; + } + + +static void act24() +{ + NLA = 103; + } + + +static void act25() +{ + NLA = 104; + } + + +static void act26() +{ + NLA = 105; + } + + +static void act27() +{ + NLA = 106; + } + + +static void act28() +{ + NLA = 107; + } + + +static void act29() +{ + NLA = 108; + } + + +static void act30() +{ + NLA = 109; + } + + +static void act31() +{ + NLA = 110; + } + + +static void act32() +{ + NLA = 111; + } + + +static void act33() +{ + NLA = 112; + } + + +static void act34() +{ + NLA = 113; + } + + +static void act35() +{ + NLA = 114; + } + + +static void act36() +{ + NLA = 115; + } + + +static void act37() +{ + NLA = 116; + } + + +static void act38() +{ + NLA = 117; + } + + +static void act39() +{ + NLA = 118; + } + + +static void act40() +{ + NLA = 119; + } + + +static void act41() +{ + NLA = 120; + } + + +static void act42() +{ + NLA = 121; + } + + +static void act43() +{ + NLA = 122; + } + + +static void act44() +{ + NLA = 123; + } + + +static void act45() +{ + NLA = 124; + } + + +static void act46() +{ + NLA = 125; + } + + +static void act47() +{ + NLA = 126; + } + + +static void act48() +{ + NLA = 127; + } + + +static void act49() +{ + NLA = 128; + } + + +static void act50() +{ + NLA = 129; + } + + +static void act51() +{ + NLA = 130; + } + + +static void act52() +{ + NLA = 131; + } + + +static void act53() +{ + NLA = 132; + } + + +static void act54() +{ + NLA = 133; + } + + +static void act55() +{ + NLA = 134; + } + + +static void act56() +{ + NLA = 135; + } + + +static void act57() +{ + NLA = NonTerminal; + + while ( zzchar==' ' || zzchar=='\t' ) { + zzadvance(); + } + if ( zzchar == ':' && inAlt ) NLA = LABEL; + } + + +static void act58() +{ + NLA = TokenTerm; + + while ( zzchar==' ' || zzchar=='\t' ) { + zzadvance(); + } + if ( zzchar == ':' && inAlt ) NLA = LABEL; + } + + +static void act59() +{ + NLA = 136; + warn(eMsg1("unknown meta-op: %s",LATEXT(1))); zzskip(); + } + +static unsigned char shift0[257] = { + 0, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 1, 2, 58, 58, 3, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 1, 40, 6, 9, 58, 58, 45, + 58, 46, 47, 8, 52, 58, 58, 18, 7, 16, + 14, 15, 16, 16, 16, 16, 16, 16, 16, 41, + 42, 5, 48, 17, 53, 19, 56, 56, 56, 56, + 56, 26, 56, 56, 56, 56, 56, 51, 56, 56, + 56, 56, 56, 56, 29, 56, 56, 56, 56, 56, + 56, 56, 4, 20, 58, 50, 57, 58, 23, 31, + 38, 34, 13, 35, 24, 33, 11, 55, 36, 10, + 25, 12, 32, 21, 55, 22, 27, 28, 54, 55, + 55, 43, 30, 55, 39, 44, 37, 49, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58, 58, 58, 58, + 58, 58, 58, 58, 58, 58, 58 +}; + + +static void act60() +{ + NLA = Eof; + } + + +static void act61() +{ + NLA = QuotedTerm; + zzmode(START); + } + + +static void act62() +{ + NLA = 3; + + zzline++; + warn("eoln found in string"); + zzskip(); + } + + +static void act63() +{ + NLA = 4; + zzline++; zzmore(); + } + + +static void act64() +{ + NLA = 5; + zzmore(); + } + + +static void act65() +{ + NLA = 6; + zzmore(); + } + +static unsigned char shift1[257] = { + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 2, 5, 5, 3, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 1, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 +}; + + +static void act66() +{ + NLA = Eof; + } + + +static void act67() +{ + NLA = 7; + zzmode(ACTIONS); zzmore(); + } + + +static void act68() +{ + NLA = 8; + + zzline++; + warn("eoln found in string (in user action)"); + zzskip(); + } + + +static void act69() +{ + NLA = 9; + zzline++; zzmore(); + } + + +static void act70() +{ + NLA = 10; + zzmore(); + } + + +static void act71() +{ + NLA = 11; + zzmore(); + } + +static unsigned char shift2[257] = { + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 2, 5, 5, 3, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 1, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 +}; + + +static void act72() +{ + NLA = Eof; + } + + +static void act73() +{ + NLA = 12; + zzmode(ACTIONS); zzmore(); + } + + +static void act74() +{ + NLA = 13; + + zzline++; + warn("eoln found in char literal (in user action)"); + zzskip(); + } + + +static void act75() +{ + NLA = 14; + zzmore(); + } + + +static void act76() +{ + NLA = 15; + zzmore(); + } + +static unsigned char shift3[257] = { + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 2, 5, 5, 3, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 4, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 +}; + + +static void act77() +{ + NLA = Eof; + } + + +static void act78() +{ + NLA = 16; + zzmode(ACTIONS); zzmore(); + } + + +static void act79() +{ + NLA = 17; + zzmore(); + } + + +static void act80() +{ + NLA = 18; + zzline++; zzmore(); DAWDLE; + } + + +static void act81() +{ + NLA = 19; + zzmore(); + } + +static unsigned char shift4[257] = { + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 3, 5, 5, 4, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 1, 5, 5, 5, 5, 2, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 +}; + + +static void act82() +{ + NLA = Eof; + } + + +static void act83() +{ + NLA = 20; + zzmode(PARSE_ENUM_FILE); + zzmore(); + } + + +static void act84() +{ + NLA = 21; + zzmore(); + } + + +static void act85() +{ + NLA = 22; + zzline++; zzmore(); DAWDLE; + } + + +static void act86() +{ + NLA = 23; + zzmore(); + } + +static unsigned char shift5[257] = { + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 3, 5, 5, 4, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 1, 5, 5, 5, 5, 2, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 +}; + + +static void act87() +{ + NLA = Eof; + } + + +static void act88() +{ + NLA = 24; + zzline++; zzmode(PARSE_ENUM_FILE); zzskip(); DAWDLE; + } + + +static void act89() +{ + NLA = 25; + zzskip(); + } + +static unsigned char shift6[257] = { + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 1, 3, 3, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3 +}; + + +static void act90() +{ + NLA = Eof; + } + + +static void act91() +{ + NLA = 26; + zzline++; zzmode(ACTIONS); zzmore(); DAWDLE; + } + + +static void act92() +{ + NLA = 27; + zzmore(); + } + +static unsigned char shift7[257] = { + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 1, 3, 3, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3 +}; + + +static void act93() +{ + NLA = Eof; + } + + +static void act94() +{ + NLA = 28; + zzline++; zzmode(START); zzskip(); DAWDLE; + } + + +static void act95() +{ + NLA = 29; + zzskip(); + } + +static unsigned char shift8[257] = { + 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 1, 3, 3, 2, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3 +}; + + +static void act96() +{ + NLA = Eof; + } + + +static void act97() +{ + NLA = 30; + zzmode(START); zzskip(); + } + + +static void act98() +{ + NLA = 31; + zzskip(); + } + + +static void act99() +{ + NLA = 32; + zzline++; zzskip(); DAWDLE; + } + + +static void act100() +{ + NLA = 33; + zzskip(); + } + +static unsigned char shift9[257] = { + 0, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 3, 5, 5, 4, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 1, 5, 5, 5, 5, 2, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5 +}; + + +static void act101() +{ + NLA = Eof; + } + + +static void act102() +{ + NLA = Action; + /* these do not nest */ + zzmode(START); + NLATEXT[0] = ' '; + NLATEXT[1] = ' '; + zzbegexpr[0] = ' '; + zzbegexpr[1] = ' '; + if ( zzbufovf ) { + err( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE)); + } + +/* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ + /* MR1 in DLG action */ + /* MR1 Doesn't matter what kind of action it is - reset*/ + + tokenActionActive=0; /* MR1 */ + } + + +static void act103() +{ + NLA = Pred; + /* these do not nest */ + zzmode(START); + NLATEXT[0] = ' '; + NLATEXT[1] = ' '; + zzbegexpr[0] = '\0'; + if ( zzbufovf ) { + err( eMsgd("predicate buffer overflow; size %d",ZZLEXBUFSIZE)); + }; +#ifdef __cplusplus__ + /* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else +#ifdef __STDC__ + /* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else +#ifdef __USE_PROTOS + /* MRxx */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); +#else + /* MR10 */ list_apply(CurActionLabels,mark_label_used_in_sem_pred); +#endif +#endif +#endif + } + + +static void act104() +{ + NLA = PassAction; + if ( topint() == ']' ) { + popint(); + if ( istackempty() ) /* terminate action */ + { + zzmode(START); + NLATEXT[0] = ' '; + zzbegexpr[0] = ' '; + if ( zzbufovf ) { + err( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE)); + } + } + else { + /* terminate $[..] and #[..] */ + if ( GenCC ) zzreplstr("))"); + else zzreplstr(")"); + zzmore(); + } + } + else if ( topint() == '|' ) { /* end of simple [...] */ + popint(); + zzmore(); + } + else zzmore(); + } + + +static void act105() +{ + NLA = 37; + + zzmore(); + zzreplstr(inline_set(zzbegexpr+ + strlen("consumeUntil("))); + } + + +static void act106() +{ + NLA = 38; + zzmore(); + } + + +static void act107() +{ + NLA = 39; + zzline++; zzmore(); DAWDLE; + } + + +static void act108() +{ + NLA = 40; + zzmore(); + } + + +static void act109() +{ + NLA = 41; + zzmore(); + } + + +static void act110() +{ + NLA = 42; + if ( !GenCC ) {zzreplstr("zzaRet"); zzmore();} + else err("$$ use invalid in C++ mode"); + } + + +static void act111() +{ + NLA = 43; + if ( !GenCC ) {zzreplstr("zzempty_attr"); zzmore();} + else err("$[] use invalid in C++ mode"); + } + + +static void act112() +{ + NLA = 44; + + pushint(']'); + if ( !GenCC ) zzreplstr("zzconstr_attr("); + else err("$[..] use invalid in C++ mode"); + zzmore(); + } + + +static void act113() +{ + NLA = 45; + { + static char buf[100]; + numericActionLabel=1; /* MR10 */ + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("$i attrib ref too big"); + set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction); + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s)", + BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"_t%d%s", + BlkLevel-1,zzbegexpr+1); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + } + + +static void act114() +{ + NLA = 46; + { + static char buf[100]; + numericActionLabel=1; /* MR10 */ + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("$i.field attrib ref too big"); + zzbegexpr[strlen(zzbegexpr)-1] = ' '; + set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction); + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s).", + BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"_t%d%s.", + BlkLevel-1,zzbegexpr+1); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + } + + +static void act115() +{ + NLA = 47; + { + static char buf[100]; + static char i[20], j[20]; + char *p,*q; + numericActionLabel=1; /* MR10 */ + if (strlen(zzbegexpr)>(size_t)85) fatal("$i.j attrib ref too big"); + for (p=zzbegexpr+1,q= &i[0]; *p!='.'; p++) { + if ( q == &i[20] ) + fatalFL("i of $i.j attrib ref too big", + FileStr[CurFile], zzline ); + *q++ = *p; + } + *q = '\0'; + for (p++, q= &j[0]; *p!='\0'; p++) { + if ( q == &j[20] ) + fatalFL("j of $i.j attrib ref too big", + FileStr[CurFile], zzline ); + *q++ = *p; + } + *q = '\0'; + if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%s,%s)",i,j); + else sprintf(buf,"_t%s%s",i,j); + zzreplstr(buf); + zzmore(); + UsedOldStyleAttrib = 1; + if ( UsedNewStyleLabel ) + err("cannot mix old-style $i with new-style labels"); + } + } + + +static void act116() +{ + NLA = 48; + { static char buf[300]; LabelEntry *el; + zzbegexpr[0] = ' '; + if ( CurRule != NULL && + strcmp(CurRule, &zzbegexpr[1])==0 ) { + if ( !GenCC ) zzreplstr("zzaRet"); + } + else if ( CurRetDef != NULL && + strmember(CurRetDef, &zzbegexpr[1])) { + if ( hasMultipleOperands( CurRetDef ) ) { + require (strlen(zzbegexpr)<=(size_t)285, + "$retval attrib ref too big"); + sprintf(buf,"_retv.%s",&zzbegexpr[1]); + zzreplstr(buf); + } + else zzreplstr("_retv"); + } + else if ( CurParmDef != NULL && + strmember(CurParmDef, &zzbegexpr[1])) { + ; + } + else if ( Elabel==NULL ) { + { err("$-variables in actions outside of rules are not allowed"); } + } else if ( (el=(LabelEntry *)hash_get(Elabel, &zzbegexpr[1]))!=NULL ) { + /* MR10 */ + /* MR10 */ /* element labels might exist without an elem when */ + /* MR10 */ /* it is a forward reference (to a rule) */ + /* MR10 */ + /* MR10 */ if ( GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) ) + /* MR10 */ { err(eMsg1("There are no token ptrs for rule references: '$%s'",&zzbegexpr[1])); } + /* MR10 */ + /* MR10 */ if ( !GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) && GenAST) { + /* MR10 */ err("You can no longer use attributes returned by rules when also using ASTs"); + /* MR10 */ err(" Use upward inheritance (\"rule >[Attrib a] : ... <<$a=...>>\")"); + /* MR10 */ }; + /* MR10 */ + /* MR10 */ /* keep track of <<... $label ...>> for semantic predicates in guess mode */ + /* MR10 */ /* element labels contain pointer to the owners node */ + /* MR10 */ + /* MR10 */ if (el->elem != NULL && el->elem->ntype == nToken) { + /* MR10 */ list_add(&CurActionLabels,el); + /* MR10 */ }; +} +else +warn(eMsg1("$%s not parameter, return value, (defined) element label",&zzbegexpr[1])); +} +zzmore(); + } + + +static void act117() +{ + NLA = 49; + zzreplstr("(*_root)"); zzmore(); chkGTFlag(); + } + + +static void act118() +{ + NLA = 50; + if ( GenCC ) { + if (NewAST) zzreplstr("(newAST)"); + else zzreplstr("(new AST)");} + else {zzreplstr("zzastnew()");} zzmore(); + chkGTFlag(); + } + + +static void act119() +{ + NLA = 51; + zzreplstr("NULL"); zzmore(); chkGTFlag(); + } + + +static void act120() +{ + NLA = 52; + { + static char buf[100]; + if ( strlen(zzbegexpr)>(size_t)85 ) + fatal("#i AST ref too big"); + if ( GenCC ) sprintf(buf,"_ast%d%s",BlkLevel-1,zzbegexpr+1); + else sprintf(buf,"zzastArg(%s)",zzbegexpr+1); + zzreplstr(buf); + zzmore(); + set_orel(atoi(zzbegexpr+1), &AST_nodes_refd_in_actions); + chkGTFlag(); + } + } + + +static void act121() +{ + NLA = 53; + + zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore(); + getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr); + } + + +static void act122() +{ + NLA = 54; + + zzline++; zzmore(); + } + + +static void act123() +{ + NLA = 55; + + if ( !(strcmp(zzbegexpr, "#ifdef")==0 || + strcmp(zzbegexpr, "#if")==0 || + strcmp(zzbegexpr, "#else")==0 || + strcmp(zzbegexpr, "#endif")==0 || + strcmp(zzbegexpr, "#ifndef")==0 || + strcmp(zzbegexpr, "#define")==0 || + strcmp(zzbegexpr, "#pragma")==0 || + strcmp(zzbegexpr, "#undef")==0 || + strcmp(zzbegexpr, "#import")==0 || + strcmp(zzbegexpr, "#line")==0 || + strcmp(zzbegexpr, "#include")==0 || + strcmp(zzbegexpr, "#error")==0) ) + { + static char buf[100]; + sprintf(buf, "%s_ast", zzbegexpr+1); + /* MR27 */ list_add(&CurAstLabelsInActions, mystrdup(zzbegexpr+1)); + zzreplstr(buf); + chkGTFlag(); + } + zzmore(); + } + + +static void act124() +{ + NLA = 56; + + pushint(']'); + if ( GenCC ) { + if (NewAST) zzreplstr("(newAST("); + else zzreplstr("(new AST("); } + else zzreplstr("zzmk_ast(zzastnew(),"); + zzmore(); + chkGTFlag(); + } + + +static void act125() +{ + NLA = 57; + + pushint('}'); + if ( GenCC ) { + if (tmakeInParser) { + zzreplstr("tmake("); + } + else { + zzreplstr("ASTBase::tmake("); + } + } + else { + zzreplstr("zztmake("); + } + zzmore(); + chkGTFlag(); + } + + +static void act126() +{ + NLA = 58; + zzmore(); + } + + +static void act127() +{ + NLA = 59; + + if ( istackempty() ) + zzmore(); + else if ( topint()==')' ) { + popint(); + } + else if ( topint()=='}' ) { + popint(); + /* terminate #(..) */ + zzreplstr(", NULL)"); + } + zzmore(); + } + + +static void act128() +{ + NLA = 60; + + pushint('|'); /* look for '|' to terminate simple [...] */ + zzmore(); + } + + +static void act129() +{ + NLA = 61; + + pushint(')'); + zzmore(); + } + + +static void act130() +{ + NLA = 62; + zzreplstr("]"); zzmore(); + } + + +static void act131() +{ + NLA = 63; + zzreplstr(")"); zzmore(); + } + + +static void act132() +{ + NLA = 64; + if (! tokenActionActive) zzreplstr(">"); /* MR1 */ + zzmore(); /* MR1 */ + } + + +static void act133() +{ + NLA = 65; + zzmode(ACTION_CHARS); zzmore(); + } + + +static void act134() +{ + NLA = 66; + zzmode(ACTION_STRINGS); zzmore(); + } + + +static void act135() +{ + NLA = 67; + zzreplstr("$"); zzmore(); + } + + +static void act136() +{ + NLA = 68; + zzreplstr("#"); zzmore(); + } + + +static void act137() +{ + NLA = 69; + zzline++; zzmore(); + } + + +static void act138() +{ + NLA = 70; + zzmore(); + } + + +static void act139() +{ + NLA = 71; + zzmore(); + } + + +static void act140() +{ + NLA = 72; + zzmode(ACTION_COMMENTS); zzmore(); + } + + +static void act141() +{ + NLA = 73; + warn("Missing /*; found dangling */ in action"); zzmore(); + } + + +static void act142() +{ + NLA = 74; + zzmode(ACTION_CPP_COMMENTS); zzmore(); + } + + +static void act143() +{ + NLA = 75; + zzmore(); + } + +static unsigned char shift10[257] = { + 0, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 16, 19, 33, 33, 20, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 16, 33, 28, 27, 21, 33, 33, + 30, 15, 18, 32, 33, 33, 33, 25, 31, 23, + 24, 24, 24, 24, 24, 24, 24, 24, 24, 33, + 33, 33, 33, 1, 2, 33, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 11, 26, 26, 26, + 26, 26, 22, 29, 3, 33, 26, 33, 26, 26, + 4, 26, 10, 26, 26, 26, 13, 26, 26, 14, + 9, 6, 5, 26, 26, 26, 7, 12, 8, 26, + 26, 26, 26, 26, 17, 33, 34, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33 +}; + + +static void act144() +{ + NLA = Eof; + ; + } + + +static void act145() +{ + NLA = 137; + zzskip(); + } + + +static void act146() +{ + NLA = 138; + zzline++; zzskip(); + } + + +static void act147() +{ + NLA = 139; + zzmode(TOK_DEF_CPP_COMMENTS); zzmore(); + } + + +static void act148() +{ + NLA = 140; + zzmode(TOK_DEF_COMMENTS); zzskip(); + } + + +static void act149() +{ + NLA = 141; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + } + + +static void act150() +{ + NLA = 142; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + } + + +static void act151() +{ + NLA = 143; + ; + } + + +static void act152() +{ + NLA = 144; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + } + + +static void act153() +{ + NLA = 145; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + } + + +static void act154() +{ + NLA = 146; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + } + + +static void act155() +{ + NLA = 147; + zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); + } + + +static void act156() +{ + NLA = 149; + } + + +static void act157() +{ + NLA = 151; + } + + +static void act158() +{ + NLA = 152; + } + + +static void act159() +{ + NLA = 153; + } + + +static void act160() +{ + NLA = 154; + } + + +static void act161() +{ + NLA = 155; + } + + +static void act162() +{ + NLA = 156; + } + + +static void act163() +{ + NLA = INT; + } + + +static void act164() +{ + NLA = ID; + } + +static unsigned char shift11[257] = { + 0, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 1, 2, 27, 27, 3, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 1, 27, 27, 6, 27, 27, 27, + 27, 27, 27, 5, 27, 22, 27, 27, 4, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 27, + 24, 27, 21, 27, 27, 27, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 26, 27, 27, 27, 27, 26, 27, 26, 26, + 26, 9, 10, 8, 26, 26, 7, 26, 26, 12, + 15, 11, 17, 16, 26, 18, 13, 19, 14, 26, + 26, 26, 26, 26, 20, 27, 23, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 27, 27, 27, 27, 27, 27, 27 +}; + +#define DfaStates 436 +typedef unsigned short DfaState; + +static DfaState st0[60] = { + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 11, 11, 12, 13, 13, 13, 14, 15, 16, + 17, 11, 11, 18, 11, 11, 19, 11, 11, 19, + 11, 11, 11, 11, 20, 11, 11, 21, 22, 23, + 24, 25, 26, 11, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 11, 11, 19, 436, 436, 436 +}; + +static DfaState st1[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st2[60] = { + 436, 2, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st3[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st4[60] = { + 436, 436, 37, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st5[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st6[60] = { + 436, 436, 436, 436, 436, 38, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st7[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st8[60] = { + 436, 436, 436, 436, 436, 436, 436, 39, 40, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st9[60] = { + 436, 436, 436, 436, 436, 436, 436, 41, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st10[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 42, 43, 43, 44, 43, 43, 43, 436, 436, 436, + 436, 45, 43, 43, 43, 43, 46, 43, 47, 43, + 43, 43, 43, 48, 43, 49, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st11[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st12[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 51, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st13[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 13, 13, 13, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st14[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 52, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st15[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 53, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st16[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st17[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 54, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st18[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 55, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st19[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 56, 56, 56, 56, 56, 56, 56, 436, 436, 436, + 436, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 436, 56, 436, + 436, 436, 436, 56, 436, 436, 436, 436, 436, 436, + 436, 56, 436, 436, 56, 56, 56, 56, 436, 436 +}; + +static DfaState st20[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 57, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st21[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st22[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 58, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 59, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st23[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st24[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st25[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st26[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st27[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 60, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st28[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 61, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st29[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st30[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st31[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 62, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st32[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st33[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st34[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 56, 56, 56, 56, 56, 56, 56, 436, 436, 436, + 436, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 436, 56, 436, + 436, 436, 436, 56, 436, 436, 436, 436, 436, 436, + 436, 63, 436, 436, 56, 56, 56, 56, 436, 436 +}; + +static DfaState st35[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st36[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st37[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st38[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st39[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st40[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st41[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st42[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 64, 43, 65, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st43[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st44[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 66, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st45[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 67, 68, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st46[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 69, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st47[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 70, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st48[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 71, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st49[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 72, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st50[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st51[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 73, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st52[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st53[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st54[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 74, 43, 43, 44, 43, 43, 43, 436, 436, 436, + 436, 45, 43, 43, 43, 43, 46, 43, 47, 43, + 43, 43, 43, 48, 43, 49, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st55[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 75, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st56[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 56, 56, 56, 56, 56, 56, 56, 436, 436, 436, + 436, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 436, 56, 436, + 436, 436, 436, 56, 436, 436, 436, 436, 436, 436, + 436, 56, 436, 436, 56, 56, 56, 56, 436, 436 +}; + +static DfaState st57[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 76, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st58[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 77, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st59[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 78, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st60[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st61[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st62[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st63[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 56, 56, 56, 56, 56, 56, 56, 436, 436, 436, + 436, 56, 56, 56, 56, 56, 56, 56, 56, 56, + 56, 56, 56, 56, 56, 56, 56, 436, 56, 436, + 436, 436, 436, 56, 436, 436, 79, 436, 436, 436, + 436, 56, 436, 436, 56, 56, 56, 56, 436, 436 +}; + +static DfaState st64[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 80, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st65[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 81, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st66[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 82, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st67[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 83, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 84, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st68[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 85, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st69[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 86, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st70[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 87, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st71[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 88, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st72[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 89, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st73[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 90, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st74[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 65, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st75[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 91, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st76[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 92, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st77[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 93, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st78[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 94, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st79[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 95, 96, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st80[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 97, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st81[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 98, 43, 99, 43, 100, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 101, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st82[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 102, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st83[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 103, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st84[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 104, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st85[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 105, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st86[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 106, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st87[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 107, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 108, 43, 43, 436, 109, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st88[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 110, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st89[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 111, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st90[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 112, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st91[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 113, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st92[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 114, 50, 50, 50, 436, 436 +}; + +static DfaState st93[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 115, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st94[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 116, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st95[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 117, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st96[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 118, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st97[60] = { + 436, 119, 120, 121, 122, 122, 122, 122, 122, 122, + 123, 123, 123, 123, 124, 124, 124, 122, 122, 122, + 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 122, 123, 122, + 122, 122, 122, 123, 122, 122, 122, 122, 122, 122, + 122, 123, 122, 122, 123, 123, 123, 123, 122, 436 +}; + +static DfaState st98[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 125, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st99[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 126, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st100[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 127, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st101[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 128, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st102[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 129, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st103[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st104[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 130, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st105[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 131, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st106[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 132, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st107[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 133, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st108[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 134, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st109[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 135, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st110[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 136, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st111[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 137, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st112[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 138, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st113[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 139, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st114[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 140, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st115[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st116[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st117[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st118[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st119[60] = { + 436, 119, 120, 121, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 141, 141, 141, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 436 +}; + +static DfaState st120[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st121[60] = { + 436, 436, 142, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st122[60] = { + 436, 122, 120, 121, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 436 +}; + +static DfaState st123[60] = { + 436, 122, 120, 121, 122, 122, 122, 122, 122, 122, + 123, 123, 123, 123, 123, 123, 123, 122, 122, 122, + 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 122, 123, 122, + 122, 122, 122, 123, 122, 122, 122, 122, 122, 122, + 122, 123, 122, 122, 123, 123, 123, 123, 122, 436 +}; + +static DfaState st124[60] = { + 436, 143, 144, 145, 122, 122, 146, 122, 122, 122, + 123, 123, 123, 123, 124, 124, 124, 122, 122, 122, + 122, 123, 123, 123, 123, 123, 123, 123, 123, 123, + 123, 123, 123, 123, 123, 123, 123, 122, 123, 122, + 122, 122, 122, 123, 122, 122, 122, 122, 122, 122, + 122, 123, 122, 122, 123, 123, 123, 123, 122, 436 +}; + +static DfaState st125[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 147, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st126[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 148, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st127[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 149, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st128[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 150, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st129[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 151, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st130[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 152, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st131[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 153, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st132[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 154, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st133[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st134[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 155, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st135[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 156, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st136[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 157, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st137[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st138[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 158, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st139[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st140[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 159, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st141[60] = { + 436, 143, 144, 145, 122, 122, 146, 122, 122, 122, + 122, 122, 122, 122, 141, 141, 141, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 436 +}; + +static DfaState st142[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st143[60] = { + 436, 143, 120, 121, 122, 122, 146, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 436 +}; + +static DfaState st144[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st145[60] = { + 436, 436, 160, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st146[60] = { + 436, 161, 162, 163, 161, 161, 122, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 436 +}; + +static DfaState st147[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 164, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st148[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 165, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st149[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 166, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st150[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 167, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st151[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 168, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st152[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st153[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st154[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 169, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st155[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 170, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st156[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 171, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st157[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st158[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 172, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st159[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st160[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st161[60] = { + 436, 161, 162, 163, 161, 161, 173, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 161, + 161, 161, 161, 161, 161, 161, 161, 161, 161, 436 +}; + +static DfaState st162[60] = { + 436, 174, 174, 174, 174, 174, 175, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 436 +}; + +static DfaState st163[60] = { + 436, 174, 176, 174, 174, 174, 175, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 436 +}; + +static DfaState st164[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 177, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st165[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 178, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st166[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 179, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st167[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 180, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st168[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 181, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st169[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 182, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st170[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st171[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 183, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st172[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 184, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st173[60] = { + 436, 185, 144, 145, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 186, 186, 186, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 436 +}; + +static DfaState st174[60] = { + 436, 174, 174, 174, 174, 174, 175, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 436 +}; + +static DfaState st175[60] = { + 436, 187, 188, 189, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 190, 190, 190, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st176[60] = { + 436, 174, 174, 174, 174, 174, 175, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 174, + 174, 174, 174, 174, 174, 174, 174, 174, 174, 436 +}; + +static DfaState st177[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 191, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st178[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 192, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st179[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 193, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st180[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st181[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st182[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 194, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st183[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st184[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 50, 50, 50, 50, 50, 50, 50, 436, 436, 436, + 436, 50, 50, 50, 50, 50, 50, 50, 50, 50, + 50, 50, 50, 50, 50, 50, 50, 436, 50, 436, + 436, 436, 436, 50, 436, 436, 436, 436, 436, 436, + 436, 50, 436, 436, 50, 50, 50, 50, 436, 436 +}; + +static DfaState st185[60] = { + 436, 185, 144, 145, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 186, 186, 186, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 436 +}; + +static DfaState st186[60] = { + 436, 185, 144, 145, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 186, 186, 186, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 122, + 122, 122, 122, 122, 122, 122, 122, 122, 122, 436 +}; + +static DfaState st187[60] = { + 436, 187, 188, 189, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 190, 190, 190, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st188[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st189[60] = { + 436, 436, 195, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st190[60] = { + 436, 187, 188, 189, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 190, 190, 190, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st191[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st192[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st193[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st194[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 196, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st195[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st196[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 197, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st197[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 198, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st198[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 199, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st199[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 200, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st200[60] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 43, 43, 43, 43, 43, 43, 43, 436, 436, 436, + 436, 43, 43, 43, 43, 43, 43, 43, 43, 43, + 43, 43, 43, 43, 43, 43, 43, 436, 43, 436, + 436, 436, 436, 43, 436, 436, 436, 436, 436, 436, + 436, 43, 436, 436, 43, 43, 43, 43, 436, 436 +}; + +static DfaState st201[7] = { + 202, 203, 204, 205, 206, 207, 436 +}; + +static DfaState st202[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st203[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st204[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st205[7] = { + 436, 436, 208, 436, 436, 436, 436 +}; + +static DfaState st206[7] = { + 436, 209, 210, 211, 209, 209, 436 +}; + +static DfaState st207[7] = { + 436, 436, 436, 436, 436, 207, 436 +}; + +static DfaState st208[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st209[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st210[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st211[7] = { + 436, 436, 212, 436, 436, 436, 436 +}; + +static DfaState st212[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st213[7] = { + 214, 215, 216, 217, 218, 219, 436 +}; + +static DfaState st214[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st215[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st216[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st217[7] = { + 436, 436, 220, 436, 436, 436, 436 +}; + +static DfaState st218[7] = { + 436, 221, 222, 223, 221, 221, 436 +}; + +static DfaState st219[7] = { + 436, 436, 436, 436, 436, 219, 436 +}; + +static DfaState st220[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st221[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st222[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st223[7] = { + 436, 436, 224, 436, 436, 436, 436 +}; + +static DfaState st224[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st225[7] = { + 226, 227, 228, 229, 230, 231, 436 +}; + +static DfaState st226[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st227[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st228[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st229[7] = { + 436, 436, 232, 436, 436, 436, 436 +}; + +static DfaState st230[7] = { + 436, 233, 233, 233, 233, 233, 436 +}; + +static DfaState st231[7] = { + 436, 436, 436, 436, 436, 231, 436 +}; + +static DfaState st232[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st233[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st234[7] = { + 235, 236, 237, 238, 239, 237, 436 +}; + +static DfaState st235[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st236[7] = { + 436, 436, 240, 436, 436, 436, 436 +}; + +static DfaState st237[7] = { + 436, 436, 237, 436, 436, 237, 436 +}; + +static DfaState st238[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st239[7] = { + 436, 436, 436, 241, 436, 436, 436 +}; + +static DfaState st240[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st241[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st242[7] = { + 243, 244, 245, 246, 247, 245, 436 +}; + +static DfaState st243[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st244[7] = { + 436, 436, 248, 436, 436, 436, 436 +}; + +static DfaState st245[7] = { + 436, 436, 245, 436, 436, 245, 436 +}; + +static DfaState st246[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st247[7] = { + 436, 436, 436, 249, 436, 436, 436 +}; + +static DfaState st248[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st249[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st250[5] = { + 251, 252, 253, 254, 436 +}; + +static DfaState st251[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st252[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st253[5] = { + 436, 255, 436, 436, 436 +}; + +static DfaState st254[5] = { + 436, 436, 436, 254, 436 +}; + +static DfaState st255[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st256[5] = { + 257, 258, 259, 260, 436 +}; + +static DfaState st257[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st258[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st259[5] = { + 436, 261, 436, 436, 436 +}; + +static DfaState st260[5] = { + 436, 436, 436, 260, 436 +}; + +static DfaState st261[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st262[5] = { + 263, 264, 265, 266, 436 +}; + +static DfaState st263[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st264[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st265[5] = { + 436, 267, 436, 436, 436 +}; + +static DfaState st266[5] = { + 436, 436, 436, 266, 436 +}; + +static DfaState st267[5] = { + 436, 436, 436, 436, 436 +}; + +static DfaState st268[7] = { + 269, 270, 271, 272, 273, 271, 436 +}; + +static DfaState st269[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st270[7] = { + 436, 436, 274, 436, 436, 436, 436 +}; + +static DfaState st271[7] = { + 436, 436, 271, 436, 436, 271, 436 +}; + +static DfaState st272[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st273[7] = { + 436, 436, 436, 275, 436, 436, 436 +}; + +static DfaState st274[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st275[7] = { + 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st276[36] = { + 277, 278, 279, 280, 281, 279, 279, 279, 279, 279, + 279, 279, 279, 279, 279, 282, 279, 279, 283, 284, + 285, 286, 287, 279, 279, 279, 279, 288, 289, 290, + 291, 292, 293, 279, 279, 436 +}; + +static DfaState st277[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st278[36] = { + 436, 294, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st279[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 279, + 279, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st280[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st281[36] = { + 436, 436, 279, 436, 279, 295, 279, 279, 279, 279, + 279, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st282[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st283[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st284[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st285[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 296, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st286[36] = { + 436, 436, 436, 436, 297, 297, 297, 297, 297, 297, + 297, 297, 297, 297, 297, 436, 436, 436, 436, 436, + 436, 298, 299, 300, 300, 436, 297, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st287[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st288[36] = { + 436, 436, 436, 436, 301, 301, 301, 301, 301, 301, + 301, 301, 301, 301, 302, 303, 436, 436, 436, 436, + 436, 436, 304, 305, 306, 436, 301, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st289[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st290[36] = { + 436, 307, 308, 309, 308, 308, 308, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 308, 310, 311, + 312, 313, 308, 308, 308, 308, 308, 314, 308, 308, + 308, 308, 308, 308, 308, 436 +}; + +static DfaState st291[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st292[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 315, 316, 436, 436, 436 +}; + +static DfaState st293[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 279, + 279, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 317, 279, 279, 279, 436 +}; + +static DfaState st294[36] = { + 436, 436, 318, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st295[36] = { + 436, 436, 279, 436, 279, 279, 319, 279, 279, 279, + 279, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st296[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st297[36] = { + 436, 436, 436, 436, 320, 320, 320, 320, 320, 320, + 320, 320, 320, 320, 320, 436, 436, 436, 436, 436, + 436, 436, 436, 320, 320, 436, 320, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st298[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st299[36] = { + 436, 436, 436, 321, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st300[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 300, 300, 322, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st301[36] = { + 436, 436, 436, 436, 323, 323, 323, 323, 323, 323, + 323, 323, 323, 323, 323, 436, 436, 436, 436, 436, + 436, 436, 436, 323, 323, 436, 323, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st302[36] = { + 436, 436, 436, 436, 323, 323, 323, 323, 323, 323, + 323, 323, 323, 324, 323, 436, 436, 436, 436, 436, + 436, 436, 436, 323, 323, 436, 323, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st303[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 325, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st304[36] = { + 436, 436, 436, 326, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st305[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 306, 306, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st306[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 306, 306, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st307[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st308[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st309[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st310[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st311[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st312[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 327, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st313[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st314[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st315[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st316[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st317[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st318[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st319[36] = { + 436, 436, 279, 436, 279, 279, 279, 328, 279, 279, + 279, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st320[36] = { + 436, 436, 436, 436, 320, 320, 320, 320, 320, 320, + 320, 320, 320, 320, 320, 436, 436, 436, 436, 436, + 436, 436, 436, 320, 320, 436, 320, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st321[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st322[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 329, 329, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st323[36] = { + 436, 436, 436, 436, 323, 323, 323, 323, 323, 323, + 323, 323, 323, 323, 323, 436, 436, 436, 436, 436, + 436, 436, 436, 323, 323, 436, 323, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st324[36] = { + 436, 436, 436, 436, 323, 323, 330, 323, 323, 323, + 323, 323, 323, 323, 323, 436, 436, 436, 436, 436, + 436, 436, 436, 323, 323, 436, 323, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st325[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st326[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st327[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st328[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 331, 279, + 279, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st329[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 329, 329, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st330[36] = { + 436, 436, 436, 436, 323, 323, 323, 323, 323, 323, + 332, 323, 323, 323, 323, 436, 436, 436, 436, 436, + 436, 436, 436, 323, 323, 436, 323, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st331[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 333, + 279, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st332[36] = { + 436, 334, 334, 334, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 334, 336, 334, 334, 337, + 338, 334, 334, 339, 339, 334, 335, 334, 334, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st333[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 279, + 340, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st334[36] = { + 436, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 334, 334, 334, 337, + 338, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st335[36] = { + 436, 334, 334, 334, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 334, 334, 334, 334, 337, + 338, 334, 334, 335, 335, 334, 335, 334, 334, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st336[36] = { + 436, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 336, 334, 334, 337, + 338, 334, 334, 341, 341, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st337[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st338[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 342, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st339[36] = { + 436, 334, 334, 334, 335, 335, 335, 335, 335, 335, + 335, 335, 335, 335, 335, 334, 343, 334, 334, 344, + 345, 334, 334, 339, 339, 334, 335, 334, 346, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st340[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 279, + 279, 347, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st341[36] = { + 436, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 343, 334, 334, 344, + 345, 334, 334, 341, 341, 334, 334, 334, 346, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st342[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st343[36] = { + 436, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 343, 334, 334, 337, + 338, 334, 334, 334, 334, 334, 334, 334, 346, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st344[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st345[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 348, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st346[36] = { + 436, 349, 349, 349, 349, 349, 349, 349, 349, 349, + 349, 349, 349, 349, 349, 349, 349, 349, 349, 350, + 351, 349, 349, 349, 349, 349, 349, 349, 334, 349, + 349, 349, 349, 349, 349, 436 +}; + +static DfaState st347[36] = { + 436, 436, 279, 436, 279, 279, 352, 279, 279, 279, + 279, 279, 279, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st348[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st349[36] = { + 436, 349, 349, 349, 349, 349, 349, 349, 349, 349, + 349, 349, 349, 349, 349, 349, 349, 349, 349, 350, + 351, 349, 349, 349, 349, 349, 349, 349, 353, 349, + 349, 349, 349, 349, 349, 436 +}; + +static DfaState st350[36] = { + 436, 354, 354, 354, 354, 354, 354, 354, 354, 354, + 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, + 354, 354, 354, 354, 354, 354, 354, 354, 355, 354, + 354, 354, 354, 354, 354, 436 +}; + +static DfaState st351[36] = { + 436, 354, 354, 354, 354, 354, 354, 354, 354, 354, + 354, 354, 354, 354, 354, 354, 354, 354, 354, 356, + 354, 354, 354, 354, 354, 354, 354, 354, 355, 354, + 354, 354, 354, 354, 354, 436 +}; + +static DfaState st352[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 279, + 279, 279, 357, 279, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st353[36] = { + 436, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 358, 334, 334, 344, + 345, 334, 334, 359, 359, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st354[36] = { + 436, 354, 354, 354, 354, 354, 354, 354, 354, 354, + 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, + 354, 354, 354, 354, 354, 354, 354, 354, 355, 354, + 354, 354, 354, 354, 354, 436 +}; + +static DfaState st355[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 360, 436, 436, 361, + 362, 436, 436, 363, 363, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st356[36] = { + 436, 354, 354, 354, 354, 354, 354, 354, 354, 354, + 354, 354, 354, 354, 354, 354, 354, 354, 354, 354, + 354, 354, 354, 354, 354, 354, 354, 354, 355, 354, + 354, 354, 354, 354, 354, 436 +}; + +static DfaState st357[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 279, + 279, 279, 279, 364, 279, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st358[36] = { + 436, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 358, 334, 334, 344, + 345, 334, 334, 359, 359, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st359[36] = { + 436, 334, 334, 334, 334, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 334, 358, 334, 334, 344, + 345, 334, 334, 359, 359, 334, 334, 334, 334, 334, + 334, 334, 334, 334, 334, 436 +}; + +static DfaState st360[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 360, 436, 436, 361, + 362, 436, 436, 363, 363, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st361[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st362[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 365, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st363[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 360, 436, 436, 361, + 362, 436, 436, 363, 363, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st364[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 279, + 279, 279, 279, 279, 366, 436, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st365[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st366[36] = { + 436, 436, 279, 436, 279, 279, 279, 279, 279, 279, + 279, 279, 279, 279, 279, 367, 279, 279, 436, 436, + 436, 436, 436, 279, 279, 279, 279, 436, 436, 436, + 436, 436, 279, 279, 279, 436 +}; + +static DfaState st367[36] = { + 436, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 368, 369, 370, 436, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 436 +}; + +static DfaState st368[36] = { + 436, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 371, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 436 +}; + +static DfaState st369[36] = { + 436, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 368, 369, 370, 371, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 436 +}; + +static DfaState st370[36] = { + 436, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 373, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 368, 436 +}; + +static DfaState st371[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st372[36] = { + 436, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 373, 372, + 372, 372, 372, 372, 372, 372, 372, 372, 372, 372, + 372, 372, 372, 372, 374, 436 +}; + +static DfaState st373[36] = { + 436, 375, 375, 375, 375, 375, 375, 375, 375, 375, + 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, + 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, + 375, 375, 375, 375, 376, 436 +}; + +static DfaState st374[36] = { + 436, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 368, 377, 368, 378, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 436 +}; + +static DfaState st375[36] = { + 436, 375, 375, 375, 375, 375, 375, 375, 375, 375, + 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, + 375, 375, 375, 375, 375, 375, 375, 375, 375, 375, + 375, 375, 375, 375, 376, 436 +}; + +static DfaState st376[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 379, 436, 380, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st377[36] = { + 436, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 368, 377, 368, 378, 368, + 368, 368, 368, 368, 368, 368, 368, 368, 368, 368, + 368, 368, 368, 368, 368, 436 +}; + +static DfaState st378[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st379[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 379, 436, 380, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st380[36] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436 +}; + +static DfaState st381[28] = { + 382, 383, 384, 385, 386, 436, 387, 388, 388, 388, + 389, 388, 388, 388, 388, 388, 388, 388, 388, 388, + 390, 391, 392, 393, 394, 395, 388, 436 +}; + +static DfaState st382[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st383[28] = { + 436, 383, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st384[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st385[28] = { + 436, 436, 396, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st386[28] = { + 436, 436, 436, 436, 397, 398, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st387[28] = { + 436, 436, 436, 436, 436, 436, 436, 399, 436, 400, + 401, 436, 436, 436, 402, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st388[28] = { + 436, 436, 436, 436, 436, 436, 436, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 436, 436, 436, 436, 436, 403, 403, 436 +}; + +static DfaState st389[28] = { + 436, 436, 436, 436, 436, 436, 436, 403, 403, 403, + 403, 404, 403, 403, 403, 403, 403, 403, 403, 403, + 436, 436, 436, 436, 436, 403, 403, 436 +}; + +static DfaState st390[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st391[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st392[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st393[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st394[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st395[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 395, 436, 436 +}; + +static DfaState st396[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st397[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st398[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st399[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 405, 436, + 436, 436, 436, 436, 436, 406, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st400[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 407, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st401[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 408, 409, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st402[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 410, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st403[28] = { + 436, 436, 436, 436, 436, 436, 436, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 436, 436, 436, 436, 436, 403, 403, 436 +}; + +static DfaState st404[28] = { + 436, 436, 436, 436, 436, 436, 436, 403, 403, 403, + 403, 403, 403, 403, 411, 403, 403, 403, 403, 403, + 436, 436, 436, 436, 436, 403, 403, 436 +}; + +static DfaState st405[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 412, + 436, 413, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st406[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 414, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st407[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 415, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st408[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 416, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st409[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 417, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st410[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 418, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st411[28] = { + 436, 436, 436, 436, 436, 436, 436, 403, 403, 403, + 403, 403, 403, 403, 403, 419, 403, 403, 403, 403, + 436, 436, 436, 436, 436, 403, 403, 436 +}; + +static DfaState st412[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 420, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st413[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 421, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st414[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 422, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st415[28] = { + 436, 436, 436, 436, 436, 436, 436, 423, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st416[28] = { + 436, 436, 436, 436, 436, 436, 436, 424, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st417[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 425, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st418[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 426, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st419[28] = { + 436, 436, 436, 436, 436, 436, 436, 403, 403, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 436, 436, 436, 436, 436, 403, 403, 436 +}; + +static DfaState st420[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 427, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st421[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 428, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st422[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 429, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st423[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 430, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st424[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 431, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st425[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st426[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 432, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st427[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st428[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 433, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st429[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 434, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st430[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 435, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st431[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st432[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st433[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st434[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + +static DfaState st435[28] = { + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 436, 436, + 436, 436, 436, 436, 436, 436, 436, 436 +}; + + +DfaState *dfa[436] = { + st0, + st1, + st2, + st3, + st4, + st5, + st6, + st7, + st8, + st9, + st10, + st11, + st12, + st13, + st14, + st15, + st16, + st17, + st18, + st19, + st20, + st21, + st22, + st23, + st24, + st25, + st26, + st27, + st28, + st29, + st30, + st31, + st32, + st33, + st34, + st35, + st36, + st37, + st38, + st39, + st40, + st41, + st42, + st43, + st44, + st45, + st46, + st47, + st48, + st49, + st50, + st51, + st52, + st53, + st54, + st55, + st56, + st57, + st58, + st59, + st60, + st61, + st62, + st63, + st64, + st65, + st66, + st67, + st68, + st69, + st70, + st71, + st72, + st73, + st74, + st75, + st76, + st77, + st78, + st79, + st80, + st81, + st82, + st83, + st84, + st85, + st86, + st87, + st88, + st89, + st90, + st91, + st92, + st93, + st94, + st95, + st96, + st97, + st98, + st99, + st100, + st101, + st102, + st103, + st104, + st105, + st106, + st107, + st108, + st109, + st110, + st111, + st112, + st113, + st114, + st115, + st116, + st117, + st118, + st119, + st120, + st121, + st122, + st123, + st124, + st125, + st126, + st127, + st128, + st129, + st130, + st131, + st132, + st133, + st134, + st135, + st136, + st137, + st138, + st139, + st140, + st141, + st142, + st143, + st144, + st145, + st146, + st147, + st148, + st149, + st150, + st151, + st152, + st153, + st154, + st155, + st156, + st157, + st158, + st159, + st160, + st161, + st162, + st163, + st164, + st165, + st166, + st167, + st168, + st169, + st170, + st171, + st172, + st173, + st174, + st175, + st176, + st177, + st178, + st179, + st180, + st181, + st182, + st183, + st184, + st185, + st186, + st187, + st188, + st189, + st190, + st191, + st192, + st193, + st194, + st195, + st196, + st197, + st198, + st199, + st200, + st201, + st202, + st203, + st204, + st205, + st206, + st207, + st208, + st209, + st210, + st211, + st212, + st213, + st214, + st215, + st216, + st217, + st218, + st219, + st220, + st221, + st222, + st223, + st224, + st225, + st226, + st227, + st228, + st229, + st230, + st231, + st232, + st233, + st234, + st235, + st236, + st237, + st238, + st239, + st240, + st241, + st242, + st243, + st244, + st245, + st246, + st247, + st248, + st249, + st250, + st251, + st252, + st253, + st254, + st255, + st256, + st257, + st258, + st259, + st260, + st261, + st262, + st263, + st264, + st265, + st266, + st267, + st268, + st269, + st270, + st271, + st272, + st273, + st274, + st275, + st276, + st277, + st278, + st279, + st280, + st281, + st282, + st283, + st284, + st285, + st286, + st287, + st288, + st289, + st290, + st291, + st292, + st293, + st294, + st295, + st296, + st297, + st298, + st299, + st300, + st301, + st302, + st303, + st304, + st305, + st306, + st307, + st308, + st309, + st310, + st311, + st312, + st313, + st314, + st315, + st316, + st317, + st318, + st319, + st320, + st321, + st322, + st323, + st324, + st325, + st326, + st327, + st328, + st329, + st330, + st331, + st332, + st333, + st334, + st335, + st336, + st337, + st338, + st339, + st340, + st341, + st342, + st343, + st344, + st345, + st346, + st347, + st348, + st349, + st350, + st351, + st352, + st353, + st354, + st355, + st356, + st357, + st358, + st359, + st360, + st361, + st362, + st363, + st364, + st365, + st366, + st367, + st368, + st369, + st370, + st371, + st372, + st373, + st374, + st375, + st376, + st377, + st378, + st379, + st380, + st381, + st382, + st383, + st384, + st385, + st386, + st387, + st388, + st389, + st390, + st391, + st392, + st393, + st394, + st395, + st396, + st397, + st398, + st399, + st400, + st401, + st402, + st403, + st404, + st405, + st406, + st407, + st408, + st409, + st410, + st411, + st412, + st413, + st414, + st415, + st416, + st417, + st418, + st419, + st420, + st421, + st422, + st423, + st424, + st425, + st426, + st427, + st428, + st429, + st430, + st431, + st432, + st433, + st434, + st435 +}; + + +DfaState accepts[437] = { + 0, 1, 2, 3, 3, 4, 25, 6, 0, 50, + 59, 57, 57, 43, 26, 13, 14, 0, 57, 58, + 57, 21, 57, 23, 24, 27, 28, 44, 0, 35, + 36, 42, 45, 46, 58, 51, 52, 3, 5, 9, + 7, 8, 59, 59, 59, 59, 59, 59, 59, 59, + 57, 57, 12, 40, 59, 57, 58, 57, 57, 57, + 33, 34, 53, 58, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 57, 59, 57, 57, 57, 57, 0, + 59, 59, 59, 59, 59, 59, 59, 59, 59, 59, + 57, 57, 57, 57, 57, 0, 0, 59, 59, 59, + 59, 59, 59, 32, 59, 59, 59, 59, 59, 59, + 59, 59, 57, 57, 57, 22, 56, 48, 49, 0, + 11, 11, 0, 59, 59, 59, 59, 59, 59, 59, + 59, 59, 59, 41, 59, 59, 59, 18, 57, 47, + 57, 0, 11, 0, 10, 10, 0, 59, 59, 59, + 59, 59, 15, 19, 59, 59, 59, 17, 57, 55, + 10, 0, 11, 11, 59, 59, 59, 59, 59, 59, + 20, 59, 57, 0, 0, 0, 11, 59, 59, 59, + 37, 38, 59, 39, 54, 0, 0, 0, 10, 10, + 0, 31, 29, 30, 59, 10, 59, 59, 59, 59, + 16, 0, 60, 61, 62, 62, 0, 65, 62, 64, + 63, 63, 63, 0, 66, 67, 68, 68, 0, 71, + 68, 70, 69, 69, 69, 0, 72, 73, 74, 74, + 0, 76, 74, 75, 0, 77, 79, 81, 80, 80, + 78, 80, 0, 82, 84, 86, 85, 85, 83, 85, + 0, 87, 88, 88, 89, 88, 0, 90, 91, 91, + 92, 91, 0, 93, 94, 94, 95, 94, 0, 96, + 98, 100, 99, 99, 97, 99, 0, 101, 108, 143, + 104, 143, 129, 127, 107, 107, 109, 128, 126, 134, + 0, 133, 139, 143, 102, 143, 107, 116, 110, 112, + 113, 123, 123, 125, 124, 117, 120, 132, 138, 130, + 131, 137, 137, 135, 136, 142, 140, 141, 103, 143, + 116, 111, 114, 123, 123, 119, 118, 137, 143, 115, + 123, 143, 123, 143, 0, 123, 0, 122, 122, 123, + 143, 0, 122, 0, 121, 121, 0, 143, 121, 0, + 122, 122, 143, 0, 0, 0, 122, 143, 0, 0, + 0, 121, 121, 0, 143, 121, 143, 0, 0, 0, + 0, 106, 0, 106, 0, 0, 0, 0, 105, 0, + 105, 0, 144, 145, 146, 146, 0, 0, 164, 164, + 158, 159, 160, 161, 162, 163, 146, 147, 148, 0, + 0, 0, 0, 164, 164, 150, 0, 0, 0, 0, + 0, 164, 0, 0, 0, 0, 0, 0, 0, 157, + 0, 0, 0, 0, 0, 152, 0, 149, 0, 0, + 0, 153, 154, 151, 155, 156, 0 +}; + +void (*actions[165])() = { + zzerraction, + act1, + act2, + act3, + act4, + act5, + act6, + act7, + act8, + act9, + act10, + act11, + act12, + act13, + act14, + act15, + act16, + act17, + act18, + act19, + act20, + act21, + act22, + act23, + act24, + act25, + act26, + act27, + act28, + act29, + act30, + act31, + act32, + act33, + act34, + act35, + act36, + act37, + act38, + act39, + act40, + act41, + act42, + act43, + act44, + act45, + act46, + act47, + act48, + act49, + act50, + act51, + act52, + act53, + act54, + act55, + act56, + act57, + act58, + act59, + act60, + act61, + act62, + act63, + act64, + act65, + act66, + act67, + act68, + act69, + act70, + act71, + act72, + act73, + act74, + act75, + act76, + act77, + act78, + act79, + act80, + act81, + act82, + act83, + act84, + act85, + act86, + act87, + act88, + act89, + act90, + act91, + act92, + act93, + act94, + act95, + act96, + act97, + act98, + act99, + act100, + act101, + act102, + act103, + act104, + act105, + act106, + act107, + act108, + act109, + act110, + act111, + act112, + act113, + act114, + act115, + act116, + act117, + act118, + act119, + act120, + act121, + act122, + act123, + act124, + act125, + act126, + act127, + act128, + act129, + act130, + act131, + act132, + act133, + act134, + act135, + act136, + act137, + act138, + act139, + act140, + act141, + act142, + act143, + act144, + act145, + act146, + act147, + act148, + act149, + act150, + act151, + act152, + act153, + act154, + act155, + act156, + act157, + act158, + act159, + act160, + act161, + act162, + act163, + act164 +}; + +static DfaState dfa_base[] = { + 0, + 201, + 213, + 225, + 234, + 242, + 250, + 256, + 262, + 268, + 276, + 381 +}; + +static unsigned char *b_class_no[] = { + shift0, + shift1, + shift2, + shift3, + shift4, + shift5, + shift6, + shift7, + shift8, + shift9, + shift10, + shift11 +}; + + + +#define ZZSHIFT(c) (b_class_no[zzauto][1+c]) +#define MAX_MODE 12 +#include "dlgauto.h" diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/stdpccts.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/stdpccts.h new file mode 100644 index 00000000..fc861f1d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/stdpccts.h @@ -0,0 +1,31 @@ +#ifndef STDPCCTS_H +#define STDPCCTS_H +/* + * stdpccts.h -- P C C T S I n c l u d e + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + */ + +#ifndef ANTLR_VERSION +#define ANTLR_VERSION 13333 +#endif + +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include "pcctscfg.h" +#include "set.h" +#include +#include "syn.h" +#include "hash.h" +#include "generic.h" +#define zzcr_attr(attr,tok,t) /*vbox: */ memset((attr), 0, sizeof(*attr)) +#define zzSET_SIZE 20 +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +#include "mode.h" +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/syn.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/syn.h new file mode 100644 index 00000000..87d725e0 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/syn.h @@ -0,0 +1,390 @@ +/* + * syn.h + * + * This file includes definitions and macros associated with syntax diagrams + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include "set.h" + +#define NumNodeTypes 4 +#define NumJuncTypes 9 + +/* List the different node types */ +#define nJunction 1 +#define nRuleRef 2 +#define nToken 3 +#define nAction 4 + +/* Different types of junctions */ +#define aSubBlk 1 +#define aOptBlk 2 +#define aLoopBlk 3 +#define EndBlk 4 +#define RuleBlk 5 +#define Generic 6 /* just a junction--no unusual characteristics */ +#define EndRule 7 +#define aPlusBlk 8 +#define aLoopBegin 9 + +typedef int NodeType; + +#define TreeBlockAllocSize 500 +#define JunctionBlockAllocSize 200 +#define ActionBlockAllocSize 50 +#define RRefBlockAllocSize 100 +#define TokenBlockAllocSize 100 + +#ifdef __cplusplus +class ActionNode; +class Junction; +#endif + +/* note that 'right' is used by the tree node allocator as a ptr for linked list */ +typedef struct _tree { + struct _tree *down, *right; + int token; + union { + int rk; /* if token==EpToken, => how many more tokens req'd */ + struct _tree *tref; /* if token==TREE_REF */ + set sref; /* if token==SET */ + } v; +#ifdef TREE_DEBUG + int in_use; + int seq; +#endif + } Tree; + + +/* a predicate is defined to be a predicate action and a token tree with + * context info (if used); later, this struct may include the + * "hoisting distance" when we hoist past tokens. + * + * A tree is used to indicate && vs || + * + * p + * | + * q--r + * + * indicates p && (q||r). + * + * If expr is PRED_AND_LIST or PRED_OR_LIST, then it's an operation node + * and indicates the start of an && or || list. + */ + +typedef struct _Predicate { + struct _Predicate *down, *right; /* these have to be first */ + struct _Predicate *up, *left; /* doubly-link me */ + char *expr; + Tree *tcontext; /* used if lookahead depth of > one is needed (tree) */ + int k; /* lookahead depth for this tcontext */ + set scontext[2];/* used if lookahead depth of one is needed (set) */ + /* scontext[0] is not used; only needed so genExprSets() + routine works (it expects an array) + */ + set completionTree; /* which lookahead depths are required to complete tcontext? */ + set completionSet; /* MR10 separate completion set for sets and trees */ + struct _PredEntry *predEntry; /* MR11 */ + +#ifdef __cplusplus + ActionNode *source; /* where did this predicate come from? */ +#else + struct _anode *source; /* where did this predicate come from? */ +#endif + + char cloned; /* MR10 don't want to free original guard pred */ + char redundant; /* MR10 predicate tree simplification */ + char ampersandStyle; /* MR10 (g)? && <

>? */ + char inverted; /* MR11 ! predName */ + char isConst; /* MR11 */ + char constValue; /* MR11 */ + char conflictReported; /* MR11 */ + + set plainSet; /* MR12b */ + + /*** remember to change new_predicate() and predicate_dup() when changing this ***/ + +} Predicate; + +typedef struct _ExceptionHandler { + char *signalname; + char *action; + } ExceptionHandler; + +typedef struct _ExceptionGroup { + struct _ListNode *handlers; /* list of ExceptionHandler's */ + char *label; /* label==""; implies not attached to any + * particular rule ref. + */ + char *altID; /* which alt did it come from (blk#:alt#) */ + + struct _ExceptionGroup *pendingLink; /* for alternative EG MR7 */ + struct _ExceptionGroup *outerEG; /* for alternative EG MR7 */ + struct _LabelEntry *labelEntry; /* for alternative EG MR7 */ + int forRule; /* MR7 */ + int used; /* MR7 */ + } ExceptionGroup ; + + +#define TokenString(_i) ((TokenInd!=NULL)?TokenStr[TokenInd[_i]]:TokenStr[_i]) +#define ExprString(_i) ((TokenInd!=NULL)?ExprStr[TokenInd[_i]]:ExprStr[_i]) + + + /* M e s s a g e P a s s i n g T o N o d e s */ + +/* + * assumes a 'Junction *r' exists. This macro calls a function with + * the pointer to the node to operate on and a pointer to the rule + * in which it is enclosed. + */ +#define TRANS(p) {if ( (p)==NULL ) fatal("TRANS: NULL object"); \ + if ( (p)->ntype == nJunction ) (*(fpJTrans[((Junction *)(p))->jtype]))( p );\ + else (*(fpTrans[(p)->ntype]))( p );} + +#define PRINT(p) {if ( (p)==NULL ) fatal("PRINT: NULL object");\ + (*(fpPrint[(p)->ntype]))( p );} + +#define REACH(p,k,rk,a) {if ( (p)==NULL ) fatal("REACH: NULL object");\ + (a) = (*(fpReach[(p)->ntype]))( p, k, rk );} + +#define TRAV(p,k,rk,a) {if ( (p)==NULL ) {\ + if ( ContextGuardTRAV ) (a)=NULL; \ + else fatal("TRAV: NULL object");\ + } \ + else (a) = (*(fpTraverse[(p)->ntype]))( p, k, rk );} + +/** +*** #define TRAV(p,k,rk,a) {if ( (p)==NULL ) fatal("TRAV: NULL object");\ +*** (a) = (*(fpTraverse[(p)->ntype]))( p, k, rk );} +**/ + +/* All syntax diagram nodes derive from Node -- superclass + */ +#ifdef __cplusplus +class Node { +public: + NodeType ntype; + char *rname; /* what rule does this element live in? */ + int file; /* index in FileStr */ + int line; /* line number that element occurs on */ + }; +#else +typedef struct _node { + NodeType ntype; + char *rname; /* what rule does this element live in? */ + int file; /* index in FileStr */ + int line; /* line number that element occurs on */ + } Node; +#endif + +#ifdef __cplusplus +class ActionNode : public Node { +public: +#else +typedef struct _anode { + NodeType ntype; + char *rname; /* what rule does this action live in? */ + int file; /* index in FileStr (name of file with action) */ + int line; /* line number that action occurs on */ +#endif + Node *next; + char *action; + int is_predicate; /* true if action is a <<...>>? predicate action */ + int done; /* don't dump if action dumped (used for predicates) */ + int init_action; /* is this the 1st action of 1st prod of block? */ + char *pred_fail; /* what to do/print when predicate fails */ + Predicate *guardpred; /* if '(context)? =>' was present, already done */ + unsigned char frmwarned;/* have we dumped a warning for pred yet? */ + unsigned char ctxwarned;/* have we dumped a warning for pred yet? */ + unsigned char predTooLong; /* MR10 have we dumped warning for pred yet */ + unsigned char noHoist; /* MR12 literally "noHoist" */ + Predicate *ampersandPred; /* MR10 (g)? && <

>? expr */ +#ifdef __cplusplus + Junction *guardNodes; /* MR11 */ +#else + struct _junct *guardNodes; /* MR11 */ +#endif + struct _PredEntry *predEntry; /* MR11 */ + int inverted; /* MR11 <>? */ +#ifdef __cplusplus + }; +#else + } ActionNode; +#endif + +#ifdef __cplusplus +class TokNode : public Node { +public: +#else +typedef struct _toknode { + NodeType ntype; + char *rname; /* name of rule it's in */ + int file; /* index in FileStr (name of file with rule) */ + int line; /* line number that token occurs on */ +#endif + Node *next; + int token; + int astnode; /* leaf/root/excluded (used to build AST's) */ + unsigned char label;/* token label or expression ? */ + unsigned char remapped; + /* used if token id's are forced to certain positions; + * a function walks the tree reassigning token numbers */ + int upper_range; /* MR13 - was char */ + /* used only if Token is of type T1..T2; in this case, + * use token..upper_range as the range; else + * upper_range must be 0 */ + unsigned char wild_card; + /* indicates that the token is the "." wild-card; + * field token is ignored if wild_card is set + */ + unsigned int elnum; /* element number within the alternative */ +#ifdef __cplusplus + Junction *altstart; /* pointer to node that starts alt */ +#else + struct _junct *altstart; /* pointer to node that starts alt */ +#endif + struct _TCnode *tclass; /* token class if tokclass ref */ + set tset; /* set of tokens represented by meta token */ + char *el_label; /* el_label:toknode */ + unsigned char complement; /* complement the set? */ + ExceptionGroup *ex_group; /* any exception[el_label] attached? */ + unsigned char use_def_MT_handler; + unsigned char label_used_in_semantic_pred; /* MR10 */ +#ifdef __cplusplus + }; +#else + } TokNode; +#endif + +#ifdef __cplusplus +class RuleRefNode : public Node { +public: +#else +typedef struct _rrnode { + NodeType ntype; + char *rname; /* name of rule it's in */ + int file; /* index in FileStr (name of file with rule) + it's in */ + int line; /* line number that rule ref occurs on */ +#endif + Node *next; + char *text; /* reference to which rule */ + char *parms; /* point to parameters of rule invocation + (if present) */ + char *assign; /* point to left-hand-side of assignment + (if any) */ + int linked; /* Has a FoLink already been established? */ + int astnode; /* excluded? (used to build AST's) */ + unsigned int elnum; /* element number within the alternative */ +#ifdef __cplusplus + Junction *altstart; +#else + struct _junct *altstart; +#endif + char *el_label; /* el_label:rrnode */ + ExceptionGroup *ex_group; /* any exception[el_label] attached? */ +#ifdef __cplusplus + }; +#else + } RuleRefNode; +#endif + +#ifdef __cplusplus +class Junction : public Node { +public: +#else +typedef struct _junct { + NodeType ntype; + char *rname; /* name of rule junction is in */ + int file; /* index in FileStr (name of file with rule) + if blk == RuleBlk */ + int line; /* line number that rule occurs on */ +#endif + int seq; /* MR10 sequence number */ + char ignore; /* used by FIRST computation to ignore + empty alt added for the (...)+ blks */ + char visited; /* used by recursive routines to avoid + infinite recursion */ + char pvisited; /* used by print routines to avoid + infinite recursion */ + char fvisited; /* used by FoLink() to avoid + infinite recursion */ + char *lock; /* used by REACH to track infinite recursion */ + char *pred_lock; /* used by find_predicates to track infinite recursion */ + int altnum; /* used in subblocks. altnum==0 means not an + alt of subrule */ + int jtype; /* annotation for code-gen/FIRST/FOLLOW. + Junction type */ +#ifdef __cplusplus + Junction *end; /* pointer to node with EndBlk in it + if blk == a block type */ +#else + struct _junct *end; /* pointer to node with EndBlk in it + if blk == a block type */ +#endif + Node *p1, *p2; + char halt; /* never move past a junction with halt==TRUE */ /* MR10 was int */ + char *pdecl; /* point to declaration of parameters on rule + (if present) */ + char *parm; /* point to parameter of block invocation + (if present) */ + char predparm; /* indicates that the 'parm' is a predicate + * to be used in the while loop generated + * for blocks */ /* MR10 was int */ + char *ret; /* point to return type of rule (if present) */ + char *erraction; /* point to error action (if present) */ + int blockid; /* this is a unique ID */ + char *exception_label; /* goto label for this alt */ + set *fset; /* used for code generation */ + Tree *ftree; /* used for code generation */ + Predicate *predicate;/* predicate that can be used to disambiguate */ + char guess; /* true if (...)? block */ + char alpha_beta_guess_end; /* MR14 1 => end block of guess sub block */ + Node *guess_analysis_point; /* MR14 */ + char approx; /* limit block to use linear approx lookahead? */ + set tokrefs; /* if ith element of alt is tokref then i is member */ + set rulerefs; /* if ith element of alt is rule ref then i is member */ + struct _ListNode *exceptions; /* list of exceptions groups for rule */ + struct _ListNode *el_labels; /* list of element labels for rule */ + ExceptionGroup *outerEG; /* MR7 */ + int curAltNum; /* MR7 */ + char* pFirstSetSymbol; /* #pragma FirstSetSymbol(Foo) MR21 */ +#ifdef __cplusplus + Junction *pendingLink; /* MR7 */ +#else + struct _junct *pendingLink; /* MR7 */ +#endif + char overlap_warning; /* MR10 */ +#ifdef __cplusplus + }; +#else + } Junction; +#endif + +typedef struct { Node *left, *right;} Graph; + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/tokens.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/tokens.h new file mode 100644 index 00000000..2fb253f7 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/antlr/tokens.h @@ -0,0 +1,246 @@ +#ifndef tokens_h +#define tokens_h +/* tokens.h -- List of labelled tokens and stuff + * + * Generated from: antlr.g + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * ANTLR Version 1.33MR33 + */ +#define zzEOF_TOKEN 1 +#define Eof 1 +#define QuotedTerm 2 +#define Action 34 +#define Pred 35 +#define PassAction 36 +#define WildCard 87 +#define LABEL 89 +#define Pragma 92 +#define FirstSetSymbol 93 +#define NonTerminal 100 +#define TokenTerm 101 +#define ID 148 +#define INT 150 + +#ifdef __USE_PROTOS +void grammar(void); +#else +extern void grammar(); +#endif + +#ifdef __USE_PROTOS +void class_def(void); +#else +extern void class_def(); +#endif + +#ifdef __USE_PROTOS +void rule(void); +#else +extern void rule(); +#endif + +#ifdef __USE_PROTOS +void laction(void); +#else +extern void laction(); +#endif + +#ifdef __USE_PROTOS +void lmember(void); +#else +extern void lmember(); +#endif + +#ifdef __USE_PROTOS +void lprefix(void); +#else +extern void lprefix(); +#endif + +#ifdef __USE_PROTOS +void aPred(void); +#else +extern void aPred(); +#endif + +#ifdef __USE_PROTOS +extern Predicate * predOrExpr(void); +#else +extern Predicate * predOrExpr(); +#endif + +#ifdef __USE_PROTOS +extern Predicate * predAndExpr(void); +#else +extern Predicate * predAndExpr(); +#endif + +#ifdef __USE_PROTOS +extern Predicate * predPrimary(void); +#else +extern Predicate * predPrimary(); +#endif + +#ifdef __USE_PROTOS +void aLexclass(void); +#else +extern void aLexclass(); +#endif + +#ifdef __USE_PROTOS +void error(void); +#else +extern void error(); +#endif + +#ifdef __USE_PROTOS +void tclass(void); +#else +extern void tclass(); +#endif + +#ifdef __USE_PROTOS +void token(void); +#else +extern void token(); +#endif + +#ifdef __USE_PROTOS +void block(set * toksrefd,set * rulesrefd); +#else +extern void block(); +#endif + +#ifdef __USE_PROTOS +void alt(set * toksrefd,set * rulesrefd); +#else +extern void alt(); +#endif + +#ifdef __USE_PROTOS +extern LabelEntry * element_label(void); +#else +extern LabelEntry * element_label(); +#endif + +#ifdef __USE_PROTOS +extern Node * element(int old_not,int first_on_line,int use_def_MT_handler); +#else +extern Node * element(); +#endif + +#ifdef __USE_PROTOS +void default_exception_handler(void); +#else +extern void default_exception_handler(); +#endif + +#ifdef __USE_PROTOS +extern ExceptionGroup * exception_group(void); +#else +extern ExceptionGroup * exception_group(); +#endif + +#ifdef __USE_PROTOS +extern ExceptionHandler * exception_handler(void); +#else +extern ExceptionHandler * exception_handler(); +#endif + +#ifdef __USE_PROTOS +void enum_file(char * fname); +#else +extern void enum_file(); +#endif + +#ifdef __USE_PROTOS +void defines(char * fname); +#else +extern void defines(); +#endif + +#ifdef __USE_PROTOS +void enum_def(char * fname); +#else +extern void enum_def(); +#endif + +#endif +extern SetWordType zzerr1[]; +extern SetWordType zzerr2[]; +extern SetWordType zzerr3[]; +extern SetWordType zzerr4[]; +extern SetWordType setwd1[]; +extern SetWordType zzerr5[]; +extern SetWordType zzerr6[]; +extern SetWordType zzerr7[]; +extern SetWordType zzerr8[]; +extern SetWordType zzerr9[]; +extern SetWordType setwd2[]; +extern SetWordType zzerr10[]; +extern SetWordType zzerr11[]; +extern SetWordType zzerr12[]; +extern SetWordType zzerr13[]; +extern SetWordType setwd3[]; +extern SetWordType zzerr14[]; +extern SetWordType zzerr15[]; +extern SetWordType zzerr16[]; +extern SetWordType zzerr17[]; +extern SetWordType zzerr18[]; +extern SetWordType zzerr19[]; +extern SetWordType zzerr20[]; +extern SetWordType zzerr21[]; +extern SetWordType setwd4[]; +extern SetWordType zzerr22[]; +extern SetWordType zzerr23[]; +extern SetWordType zzerr24[]; +extern SetWordType zzerr25[]; +extern SetWordType zzerr26[]; +extern SetWordType setwd5[]; +extern SetWordType zzerr27[]; +extern SetWordType zzerr28[]; +extern SetWordType zzerr29[]; +extern SetWordType zzerr30[]; +extern SetWordType zzerr31[]; +extern SetWordType zzerr32[]; +extern SetWordType zzerr33[]; +extern SetWordType setwd6[]; +extern SetWordType zzerr34[]; +extern SetWordType zzerr35[]; +extern SetWordType zzerr36[]; +extern SetWordType zzerr37[]; +extern SetWordType zzerr38[]; +extern SetWordType zzerr39[]; +extern SetWordType zzerr40[]; +extern SetWordType zzerr41[]; +extern SetWordType zzerr42[]; +extern SetWordType setwd7[]; +extern SetWordType zzerr43[]; +extern SetWordType zzerr44[]; +extern SetWordType zzerr45[]; +extern SetWordType zzerr46[]; +extern SetWordType zzerr47[]; +extern SetWordType zzerr48[]; +extern SetWordType zzerr49[]; +extern SetWordType zzerr50[]; +extern SetWordType zzerr51[]; +extern SetWordType zzerr52[]; +extern SetWordType zzerr53[]; +extern SetWordType setwd8[]; +extern SetWordType zzerr54[]; +extern SetWordType zzerr55[]; +extern SetWordType zzerr56[]; +extern SetWordType zzerr57[]; +extern SetWordType setwd9[]; +extern SetWordType zzerr58[]; +extern SetWordType zzerr59[]; +extern SetWordType zzerr60[]; +extern SetWordType zzerr61[]; +extern SetWordType zzerr62[]; +extern SetWordType zzerr63[]; +extern SetWordType zzerr64[]; +extern SetWordType zzerr65[]; +extern SetWordType setwd10[]; +extern SetWordType setwd11[]; diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgDDK.mak b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgDDK.mak new file mode 100644 index 00000000..e14a2093 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgDDK.mak @@ -0,0 +1,121 @@ +# PCCTS directory + +# You will need to set the LIB variable similar to this. +# LIB="C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/lib;c:/Microsoft Visual Studio .NET 2003/Vc7/PlatformSDK/Lib" + +# PCCTS_HOME= +PCCTS_HOME=$(WORKSPACE)\Tools\CCode\Source\Pccts +DLG_SRC=$(PCCTS_HOME)\dlg +PCCTS_H=$(PCCTS_HOME)\h + + +# Support directories +SET=$(PCCTS_HOME)\support\set + + +# Compiler stuff +CC = cl +CFLAGS = /nologo -I "." -I "$(PCCTS_H)" -I "$(SET)" -D "USER_ZZSYN" -D "PC" \ + -D "ZZLEXBUFSIZE=65536" /D "LONGFILENAMES" /W3 /Zi + +DLG_OBJS = dlg_p.obj dlg_a.obj main.obj err.obj support.obj \ + output.obj relabel.obj automata.obj + +SUPPORT_OBJS = set.obj + +# Dependencies + +dlg.exe: $(DLG_OBJS) $(SUPPORT_OBJS) + $(CC) $(CFLAGS) -o dlg.exe bufferoverflowu.lib $(DLG_OBJS) $(SUPPORT_OBJS) + del *.obj + del *.ilk + del *.pdb + move dlg.exe $(WORKSPACE)\Tools\bin\. + +dlg_p.obj: $(DLG_SRC)\dlg_p.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + $(DLG_SRC)\mode.h \ + $(DLG_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\dlg_p.c + +dlg_a.obj: $(DLG_SRC)\dlg_a.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgauto.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + $(DLG_SRC)\mode.h \ + $(DLG_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\dlg_a.c + +main.obj: $(DLG_SRC)\main.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + $(DLG_SRC)\mode.h \ + $(DLG_SRC)\stdpccts.h \ + $(DLG_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\main.c + +err.obj: $(DLG_SRC)\err.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(PCCTS_H)\err.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + $(DLG_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\err.c + +support.obj: $(DLG_SRC)\support.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\support.c + +output.obj: $(DLG_SRC)\output.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\output.c + +relabel.obj: $(DLG_SRC)\relabel.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\relabel.c + +automata.obj: $(DLG_SRC)\automata.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\automata.c + + +set.obj: $(SET)\set.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + + $(CC) -c $(CFLAGS) $(SET)\set.c + +clean: + del *.obj + +distclean: + del *.obj + del $(WORKSPACE)\Tools\bin\dlg.exe diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgMS.mak b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgMS.mak new file mode 100644 index 00000000..e667f025 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgMS.mak @@ -0,0 +1,126 @@ +# PCCTS directory + +# You will need to set the LIB variable similar to this. +# LIB="C:/Program Files/Microsoft Visual Studio .NET 2003/Vc7/lib;c:/Microsoft Visual Studio .NET 2003/Vc7/PlatformSDK/Lib" + +# PCCTS_HOME= +PCCTS_HOME=$(BASE_TOOLS_PATH)\Source\C\VfrCompile\Pccts +DLG_SRC=$(PCCTS_HOME)\dlg +PCCTS_H=$(PCCTS_HOME)\h + + +# Support directories +SET=$(PCCTS_HOME)\support\set + + +# Compiler stuff +CC = cl +CFLAGS = /nologo -I "." -I "$(PCCTS_H)" -I "$(SET)" -D "USER_ZZSYN" -D "PC" \ + -D "ZZLEXBUFSIZE=65536" /D "LONGFILENAMES" /W3 /Zi \ + /D _CRT_SECURE_NO_DEPRECATE /D _CRT_NONSTDC_NO_DEPRECATE + +DLG_OBJS = dlg_p.obj dlg_a.obj main.obj err.obj support.obj \ + output.obj relabel.obj automata.obj + +SUPPORT_OBJS = set.obj + +# Dependencies + +$(EDK_TOOLS_PATH)\Bin\Win32\dlg.exe: $(DLG_OBJS) $(SUPPORT_OBJS) + $(CC) $(CFLAGS) -Fedlg.exe $(DLG_OBJS) $(SUPPORT_OBJS) + -@if not exist $(EDK_TOOLS_PATH)\Bin\Win32 mkdir $(EDK_TOOLS_PATH)\Bin\Win32 + copy dlg.exe $(EDK_TOOLS_PATH)\Bin\Win32 + +dlg_p.obj: $(DLG_SRC)\dlg_p.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + $(DLG_SRC)\mode.h \ + $(DLG_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\dlg_p.c + +dlg_a.obj: $(DLG_SRC)\dlg_a.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgauto.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + $(DLG_SRC)\mode.h \ + $(DLG_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\dlg_a.c + +main.obj: $(DLG_SRC)\main.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + $(DLG_SRC)\mode.h \ + $(DLG_SRC)\stdpccts.h \ + $(DLG_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\main.c + +err.obj: $(DLG_SRC)\err.c \ + $(PCCTS_H)\antlr.h \ + $(PCCTS_H)\config.h \ + $(PCCTS_H)\dlgdef.h \ + $(PCCTS_H)\err.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + $(DLG_SRC)\tokens.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\err.c + +support.obj: $(DLG_SRC)\support.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\support.c + +output.obj: $(DLG_SRC)\output.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\output.c + +relabel.obj: $(DLG_SRC)\relabel.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\relabel.c + +automata.obj: $(DLG_SRC)\automata.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + $(DLG_SRC)\dlg.h \ + + $(CC) -c $(CFLAGS) $(DLG_SRC)\automata.c + + +set.obj: $(SET)\set.c \ + $(PCCTS_H)\config.h \ + $(SET)\set.h \ + + $(CC) -c $(CFLAGS) $(SET)\set.c + +clean: + -del *.obj + -del *.ilk + -del *.pdb + +cleanall: + -del *.obj + -del *.ilk + -del *.pdb + -del *.exe + -del $(EDK_TOOLS_PATH)\Bin\Win32\dlg.exe + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgPPC.mak b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgPPC.mak new file mode 100644 index 00000000..2810a3b0 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/DlgPPC.mak @@ -0,0 +1,84 @@ +# File: dlgPPC.make +# Target: dlgPPC +# Sources: automata.c +# dlg_a.c +# dlg_p.c +# err.c +# main.c +# output.c +# relabel.c +# support.c +# ::support:set:set.c +# Created: Sunday, May 17, 1998 11:34:20 PM +# Author: Kenji Tanaka + + +MAKEFILE = dlgPPC.make +¥MondoBuild¥ = {MAKEFILE} # Make blank to avoid rebuilds when makefile is modified +Includes = ¶ + -i "::h:" ¶ + -i "::support:set:" +Sym¥PPC = +ObjDir¥PPC = ":Obj:" + +PPCCOptions = {Includes} {Sym¥PPC} -w off -d MPW -d __STDC__=1 -d USER_ZZSYN + +Objects¥PPC = ¶ + "{ObjDir¥PPC}automata.c.x" ¶ + "{ObjDir¥PPC}dlg_a.c.x" ¶ + "{ObjDir¥PPC}dlg_p.c.x" ¶ + "{ObjDir¥PPC}err.c.x" ¶ + "{ObjDir¥PPC}main.c.x" ¶ + "{ObjDir¥PPC}output.c.x" ¶ + "{ObjDir¥PPC}relabel.c.x" ¶ + "{ObjDir¥PPC}support.c.x" ¶ + "{ObjDir¥PPC}set.c.x" + + +dlgPPC ÄÄ {¥MondoBuild¥} {Objects¥PPC} + PPCLink ¶ + -o {Targ} {Sym¥PPC} ¶ + {Objects¥PPC} ¶ + -t 'MPST' ¶ + -c 'MPS ' ¶ + "{SharedLibraries}InterfaceLib" ¶ + "{SharedLibraries}StdCLib" ¶ + "{SharedLibraries}MathLib" ¶ + "{PPCLibraries}StdCRuntime.o" ¶ + "{PPCLibraries}PPCCRuntime.o" ¶ + "{PPCLibraries}PPCToolLibs.o" + + +"{ObjDir¥PPC}automata.c.x" Ä {¥MondoBuild¥} automata.c + {PPCC} automata.c -o {Targ} {PPCCOptions} + +"{ObjDir¥PPC}dlg_a.c.x" Ä {¥MondoBuild¥} dlg_a.c + {PPCC} dlg_a.c -o {Targ} {PPCCOptions} + +"{ObjDir¥PPC}dlg_p.c.x" Ä {¥MondoBuild¥} dlg_p.c + {PPCC} dlg_p.c -o {Targ} {PPCCOptions} + +"{ObjDir¥PPC}err.c.x" Ä {¥MondoBuild¥} err.c + {PPCC} err.c -o {Targ} {PPCCOptions} + +"{ObjDir¥PPC}main.c.x" Ä {¥MondoBuild¥} main.c + {PPCC} main.c -o {Targ} {PPCCOptions} + +"{ObjDir¥PPC}output.c.x" Ä {¥MondoBuild¥} output.c + {PPCC} output.c -o {Targ} {PPCCOptions} + +"{ObjDir¥PPC}relabel.c.x" Ä {¥MondoBuild¥} relabel.c + {PPCC} relabel.c -o {Targ} {PPCCOptions} + +"{ObjDir¥PPC}support.c.x" Ä {¥MondoBuild¥} support.c + {PPCC} support.c -o {Targ} {PPCCOptions} + +"{ObjDir¥PPC}set.c.x" Ä {¥MondoBuild¥} "::support:set:set.c" + {PPCC} "::support:set:set.c" -o {Targ} {PPCCOptions} + + +dlgPPC ÄÄ dlg.r + Rez dlg.r -o dlgPPC -a + +Install Ä dlgPPC + Duplicate -y dlgPPC "{MPW}"Tools:dlg diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/automata.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/automata.c new file mode 100644 index 00000000..399231ef --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/automata.c @@ -0,0 +1,353 @@ +/* Automata conversion functions for DLG + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * DLG 1.33 + * Will Cohen + * With mods by Terence Parr; AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include "pcctscfg.h" +#include "dlg.h" +#ifdef MEMCHK +#include "trax.h" +#else +#ifdef __STDC__ +#include +#else +#include +#endif /* __STDC__ */ +#endif + +#define hash_list struct _hash_list_ +hash_list{ + hash_list *next; /* next thing in list */ + dfa_node *node; + }; + +int dfa_allocated = 0; /* keeps track of number of dfa nodes */ +dfa_node **dfa_array; /* root of binary tree that stores dfa array */ +dfa_node *dfa_model_node; +hash_list *dfa_hash[HASH_SIZE]; /* used to quickly find */ + /* desired dfa node */ + +void +#ifdef __USE_PROTOS +make_dfa_model_node(int width) +#else +make_dfa_model_node(width) +int width; +#endif +{ + register int i; + dfa_model_node = (dfa_node*) malloc(sizeof(dfa_node) + + sizeof(int)*width); + dfa_model_node->node_no = -1; /* impossible value for real dfa node */ + dfa_model_node->dfa_set = 0; + dfa_model_node->alternatives = FALSE; + dfa_model_node->done = FALSE; + dfa_model_node->nfa_states = empty; + for(i = 0; itrans[i] = NIL_INDEX; + } +} + + +/* adds a new nfa to the binary tree and returns a pointer to it */ +dfa_node * +#ifdef __USE_PROTOS +new_dfa_node(set nfa_states) +#else +new_dfa_node(nfa_states) +set nfa_states; +#endif +{ + register int j; + register dfa_node *t; + static int dfa_size=0; /* elements dfa_array[] can hold */ + + ++dfa_allocated; + if (dfa_size<=dfa_allocated){ + /* need to redo array */ + if (!dfa_array){ + /* need some to do initial allocation */ + dfa_size=dfa_allocated+DFA_MIN; + dfa_array=(dfa_node **) malloc(sizeof(dfa_node*)* + dfa_size); + }else{ + /* need more space */ + dfa_size=2*(dfa_allocated+1); + dfa_array=(dfa_node **) realloc(dfa_array, + sizeof(dfa_node*)*dfa_size); + } + } + /* fill out entry in array */ + t = (dfa_node*) malloc(sizeof(nfa_node)+sizeof(int)*class_no); + *t = *dfa_model_node; + for (j=0; jtrans[j] = NIL_INDEX; + t->node_no = dfa_allocated; + t->nfa_states = set_dup(nfa_states); + dfa_array[dfa_allocated] = t; + return t; +} + + +/* past a pointer to the start of the nfa graph + * nfa_to_dfa convers this graph to dfa. The function returns + * a pointer to the first dfa state. + * NOTE: The function that prints out the table will have to figure out how + * to find the other dfa states given the first dfa_state and the number of dfa + * nodes allocated + */ +dfa_node ** +#ifdef __USE_PROTOS +nfa_to_dfa(nfa_node *start) +#else +nfa_to_dfa(start) +nfa_node *start; +#endif +{ + register dfa_node *d_state, *trans_d_state; + register int a; + set t; + int last_done; + unsigned *nfa_list; + unsigned *reach_list; + + reach_list = (unsigned *) malloc((2+nfa_allocated)*sizeof(unsigned)); + if (!start) return NULL; + t = set_of(NFA_NO(start)); + _set_pdq(t,reach_list); + closure(&t,reach_list); + /* Make t a dfa state */ + d_state = dfastate(t); + last_done = DFA_NO(d_state); + + do { + /* Mark dfa state x as "done" */ + d_state->done = TRUE; + nfa_list = set_pdq(d_state->nfa_states); + for (a = 0; at, labeled with a */ + d_state->trans[a] = DFA_NO(trans_d_state); + d_state->alternatives = TRUE; + } + } + free(nfa_list); + ++last_done; /* move forward in queue */ + /* And so forth until nothing isn't done */ + d_state = DFA(last_done); + } while (last_done<=dfa_allocated); + + free(reach_list); + set_free(t); + + /* returns pointer to the array that holds the automaton */ + return dfa_array; +} + +void +#ifdef __USE_PROTOS +clear_hash(void) +#else +clear_hash() +#endif +{ + register int i; + + for(i=0; inext; + } + total+=j; + fprintf(f,"bin[%d] has %d\n",i,j); + } + fprintf(f,"total = %d\n",total); +} +#endif + +/* Returns a pointer to a dfa node that has the same nfa nodes in it. + * This may or may not be a newly created node. + */ +dfa_node * +#ifdef __USE_PROTOS +dfastate(set nfa_states) +#else +dfastate(nfa_states) +set nfa_states; +#endif +{ + register hash_list *p; + int bin; + + /* hash using set and see if it exists */ + bin = set_hash(nfa_states,HASH_SIZE); + p = dfa_hash[bin]; + while(p && !set_equ(nfa_states,(p->node)->nfa_states)){ + p = p->next; + } + if(!p){ + /* next state to add to hash table */ + p = (hash_list*)malloc(sizeof(hash_list)); + p->node = new_dfa_node(nfa_states); + p->next = dfa_hash[bin]; + dfa_hash[bin] = p; + } + return (p->node); +} + + +/* this reach assumes the closure has been done already on set */ +int +#ifdef __USE_PROTOS +reach(unsigned *nfa_list, register int a, unsigned *reach_list) +#else +reach(nfa_list, a, reach_list) +unsigned *nfa_list; +register int a; +unsigned *reach_list; +#endif +{ + register unsigned *e; + register nfa_node *node; + int t=0; + + e = nfa_list; + if (e){ + while (*e != nil){ + node = NFA(*e); + if (set_el(a,node->label)){ + t=1; + *reach_list=NFA_NO(node->trans[0]); + ++reach_list; + } + ++e; + } + } + *reach_list=nil; + return t; +} + +/* finds all the nodes that can be reached by epsilon transitions + from the set of a nodes and returns puts them back in set b */ +set +#ifdef __USE_PROTOS +closure(set *b, unsigned *reach_list) +#else +closure(b, reach_list) +set *b; +unsigned *reach_list; +#endif +{ + register nfa_node *node,*n; /* current node being examined */ + register unsigned *e; + + ++operation_no; +#if 0 + t = e = set_pdq(*b); +#else + e=reach_list; +#endif + while (*e != nil){ + node = NFA(*e); + set_orel(NFA_NO(node),b); + /* mark it done */ + node->nfa_set = operation_no; + if ((n=node->trans[0]) != NIL_INDEX && set_nil(node->label) && + (n->nfa_set != operation_no)){ + /* put in b */ + set_orel(NFA_NO(n),b); + close1(n,operation_no,b); + } + if ((n=node->trans[1]) != NIL_INDEX && + (n->nfa_set != operation_no)){ + /* put in b */ + set_orel(NFA_NO(node->trans[1]),b); + close1(n,operation_no,b); + } + ++e; + } +#if 0 + free(t); +#endif + return *b; +} + +#ifdef __USE_PROTOS +void close1(nfa_node *node, int o, set *b) +#else +void close1(node,o,b) +nfa_node *node; +int o; /* marker to avoid cycles */ +set *b; +#endif +{ + register nfa_node *n; /* current node being examined */ + + /* mark it done */ + node->nfa_set = o; + if ((n=node->trans[0]) != NIL_INDEX && set_nil(node->label) && + (n->nfa_set != o)){ + /* put in b */ + set_orel(NFA_NO(n),b); + close1(n,o,b); + } + if ((n=node->trans[1]) != NIL_INDEX && + (n->nfa_set != o)){ + /* put in b */ + set_orel(NFA_NO(node->trans[1]),b); + close1(n,o,b); + } +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.1 b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.1 new file mode 100644 index 00000000..3a1694ee --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.1 @@ -0,0 +1,79 @@ +.TH dlg 1 "April 1994" "DLG" "PCCTS Manual Pages" +.SH NAME +dlg \- DFA Lexical Analyzer Generator +.SH SYNTAX +.LP +\fBdlg\fR [\fIoptions\fR] \fIlexical_spec\fR [\fIoutput_file\fR] +.SH DESCRIPTION +.B dlg +is a tool that produces fast deterministic finite automata for recognizing +regular expressions in input. +.SH OPTIONS +.IP "\fB-CC\fR" +Generate C++ output. The \fIoutput_file\fP is not specified in this +case. +.IP "\fB-C\fR[\fP level\fR] +Where \fPlevel\fR is the compression level used. 0 indications no +compression, 1 removes all unused characters from the transition from table, +and 2 maps equivalent characters into the same character classes. It is +suggested that level -C2 is used, since it will significantly reduce the size +of the dfa produced for lexical analyzer. +.IP "\fB-m\fP +Produces the header file for the lexical mode with a name other than +the default name of "mode.h". +.IP \fB-i\fP +An interactive, or as interactive as possible, parser is produced. A character +is only obtained when required to decide which state to go to. Some care +must be taken to obtain accept states that do not require look ahead at the +next character to determine if that is the stop state. Any regular expression +with a Kleene closure at the end is guaranteed to require another character +of look ahead. +.IP "\fB-cl\fP class +Specify a class name for DLG to generate. The default is DLGLexer. +'class' will be a subclass of DLGLexerBase; only used for -CC. +.IP \fB-ci\fP +The automaton will treat upper and lower case characters identically. +This is accomplished in the automaton; the characters in the lexical +buffer are unmodified. +.IP \fB-cs\fP +Upper and lower case characters are treated as distinct. This is the +default. +.IP "\fB-o\fP dir +Directory where output files should go (default="."). This is very +nice for keeping the source directory clear of ANTLR and DLG spawn. +.IP \fB-Wambiguity\fP +Warns if more than one regular expression could match the same character +sequence. The warnings give the numbers of the expressions in the dlg +lexical specification file. The numbering of the expressions starts at one. +Multiple warnings may be print for the same expressions. +.IP \- +Used in place of file names to get input from standard in or send output +to standard out. +.SH "SPECIAL CONSIDERATIONS" +.PP +\fIDlg\fP works... we think. There is no implicit guarantee of +anything. We reserve no \fBlegal\fP rights to the software known as +the Purdue Compiler Construction Tool Set (PCCTS) \(em PCCTS is in the +public domain. An individual or company may do whatever they wish +with source code distributed with PCCTS or the code generated by +PCCTS, including the incorporation of PCCTS, or its output, into +commercial software. We encourage users to develop software with +PCCTS. However, we do ask that credit is given to us for developing +PCCTS. By "credit", we mean that if you incorporate our source code +into one of your programs (commercial product, research project, or +otherwise) that you acknowledge this fact somewhere in the +documentation, research report, etc... If you like PCCTS and have +developed a nice tool with the output, please mention that you +developed it using PCCTS. As long as these guidelines are followed, we +expect to continue enhancing this system and expect to make other +tools available as they are completed. +.SH FILES +.B mode.h +, +.B dlgauto.h +, +.B dlgdef.h +.SH SEE ALSO +.BR antlr (1), +.BR pccts (1) +.SH BUGS diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.h new file mode 100644 index 00000000..030c2caa --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.h @@ -0,0 +1,250 @@ +/* dlg header file + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * DLG 1.33 + * Will Cohen + * With mods by Terence Parr; AHPCRC, University of Minnesota + * 1989-2001 + */ + +/* MR1 Move pcctscfg.h to top of file */ + +#include "pcctscfg.h" + +/* turn off warnings for unreferenced labels */ + +#ifdef _MSC_VER +#pragma warning(disable:4102) +#endif + +#include "set.h" + +#define TRUE 1 +#define FALSE 0 + +/***** output related stuff *******************/ +#define IN input_stream +#define OUT output_stream + +#define MAX_MODES 50 /* number of %%names allowed */ +#define MAX_ON_LINE 10 + +#define NFA_MIN 64 /* minimum nfa_array size */ +#define DFA_MIN 64 /* minimum dfa_array size */ + +#define DEFAULT_CLASSNAME "DLGLexer" + +/* these macros allow the size of the character set to be easily changed */ +/* NOTE: do NOT change MIN_CHAR since EOF is the lowest char, -1 */ +#define MIN_CHAR (-1) /* lowest possible character possible on input */ +#define MAX_CHAR 255 /* highest possible character possible on input */ +#define CHAR_RANGE (1+(MAX_CHAR) - (MIN_CHAR)) + +/* indicates that the not an "array" reference */ +#define NIL_INDEX 0 + +/* size of hash table used to find dfa_states quickly */ +#define HASH_SIZE 211 + +#define nfa_node struct _nfa_node +nfa_node { + int node_no; + int nfa_set; + int accept; /* what case to use */ + nfa_node *trans[2]; + set label; /* one arc always labelled with epsilon */ +}; + +#define dfa_node struct _dfa_node +dfa_node { + int node_no; + int dfa_set; + int alternatives; /* used for interactive mode */ + /* are more characters needed */ + int done; + set nfa_states; + int trans[1];/* size of transition table depends on + * number of classes required for automata. + */ + + +}; + +/******** macros for accessing the NFA and DFA nodes ****/ +#define NFA(x) (nfa_array[x]) +#define DFA(x) (dfa_array[x]) +#define DFA_NO(x) ( (x) ? (x)->node_no : NIL_INDEX) +#define NFA_NO(x) ( (x) ? (x)->node_no : NIL_INDEX) + +/******** wrapper for memory checking ***/ +/*#define malloc(x) dlg_malloc((x),__FILE__,__LINE__)*/ + +/*#define calloc(x,y) dlg_calloc((x),(y),__FILE__,__LINE__)*/ + +/******** antlr attributes *************/ +typedef struct { + unsigned char letter; + nfa_node *l,*r; + set label; + } Attrib; + +#define zzcr_attr(attr, token, text) { \ + (attr)->letter = text[0]; (attr)->l = NULL; \ + (attr)->r = NULL; (attr)->label = empty; \ +} +#define zzd_attr(a) set_free((a)->label); + +/******************** Variable ******************************/ +extern char program[]; /* tells what program this is */ +extern char version[]; /* tells what version this is */ +extern char *file_str[]; /* file names being used */ +extern int err_found; /* flag to indicate error occurred */ +extern int action_no; /* last action function printed */ +extern int func_action; /* should actions be turned into functions?*/ +extern set used_chars; /* used to label trans. arcs */ +extern set used_classes; /* classes or chars used to label trans. arcs */ +extern int class_no; /* number of classes used */ +extern set class_sets[]; /* shows char. in each class */ +extern set normal_chars; /* mask off unused portion of set */ +extern int comp_level; /* what compression level to use */ +extern int interactive; /* interactive scanner (avoid lookahead)*/ +extern int mode_counter; /* keeps track of the number of %%name */ +extern int dfa_basep[]; /* start of each group of dfa */ +extern int dfa_class_nop[];/* number of transition arcs in */ + /* each dfa in each mode */ +extern int nfa_allocated; +extern int dfa_allocated; +extern nfa_node **nfa_array; /* start of nfa "array" */ +extern dfa_node **dfa_array; /* start of dfa "array" */ +extern int operation_no; /* unique number for each operation */ +extern FILE *input_stream; /* where description read from */ +extern FILE *output_stream; /* where to put the output */ +extern FILE *mode_stream; /* where to put the mode output */ +extern FILE *class_stream; +extern char *mode_file; /* name of file for mode output */ +extern int gen_ansi; /* produce ansi compatible code */ +extern int case_insensitive;/* ignore case of input spec. */ +extern int warn_ambig; /* show if regular expressions ambiguous */ +extern int gen_cpp; +extern char *cl_file_str; +extern int firstLexMember; /* MR1 */ +extern char *OutputDirectory; +extern char *class_name; + +/******************** Functions ******************************/ +#ifdef __USE_PROTOS +extern char *dlg_malloc(int, char *, int); /* wrapper malloc */ +extern char *dlg_calloc(int, int, char *, int); /* wrapper calloc */ +extern int reach(unsigned *, register int, unsigned *); +extern set closure(set *, unsigned *); +extern dfa_node *new_dfa_node(set); +extern nfa_node *new_nfa_node(void); +extern dfa_node *dfastate(set); +extern dfa_node **nfa_to_dfa(nfa_node *); +extern void internal_error(char *, char *, int); /* MR9 23-Sep-97 */ +extern FILE *read_stream(char *); /* opens file for reading */ +extern FILE *write_stream(char *); /* opens file for writing */ +extern void make_nfa_model_node(void); +extern void make_dfa_model_node(int); +extern char *ClassName(char *); +extern char *OutMetaName(char *); +extern void error(char*, int); +extern void warning(char*, int); +extern void p_head(void); +extern void p_class_hdr(void); +extern void p_includes(void); +extern void p_tables(void); +extern void p_tail(void); /* MR1 */ +extern void p_class_def1(void); /* MR1 */ +extern void new_automaton_mode(void); /* MR1 */ +extern int relabel(nfa_node *,int); /* MR1 */ +extern void p_shift_table(int); /* MR1 */ +extern void p_bshift_table(void); /* MR1 */ +extern void p_class_table(void); /* MR1 */ +extern void p_mode_def(char *,int); /* MR1 */ +extern void init(void); /* MR1 */ +extern void p_class_def2(void); /* MR1 */ +extern void clear_hash(void); /* MR1 */ +extern void p_alternative_table(void); /* MR1 */ +extern void p_node_table(void); /* MR1 */ +extern void p_dfa_table(void); /* MR1 */ +extern void p_accept_table(void); /* MR1 */ +extern void p_action_table(void); /* MR1 */ +extern void p_base_table(void); /* MR1 */ +extern void p_single_node(int,int); /* MR1 */ +extern char * minsize(int); /* MR1 */ +extern void close1(nfa_node *,int,set *); /* MR1 */ +extern void partition(nfa_node *,int); /* MR1 */ +extern void intersect_nfa_labels(nfa_node *,set *); /* MR1 */ +extern void r_intersect(nfa_node *,set *); /* MR1 */ +extern void label_node(nfa_node *); /* MR1 */ +extern void label_with_classes(nfa_node *); /* MR1 */ + +#else +extern char *dlg_malloc(); /* wrapper malloc */ +extern char *dlg_calloc(); /* wrapper calloc */ +extern int reach(); +extern set closure(); +extern dfa_node *new_dfa_node(); +extern nfa_node *new_nfa_node(); +extern dfa_node *dfastate(); +extern dfa_node **nfa_to_dfa(); +extern void internal_error(); /* MR9 23-Sep-97 */ +extern FILE *read_stream(); /* opens file for reading */ +extern FILE *write_stream(); /* opens file for writing */ +extern void make_nfa_model_node(); +extern void make_dfa_model_node(); +extern char *ClassName(); +extern char *OutMetaName(); +extern void error(); +extern void warning(); +extern void p_head(); /* MR9 */ +extern void p_class_hdr(); /* MR9 */ +extern void p_includes(); /* MR9 */ +extern void p_tables(); /* MR9 */ +extern void p_tail(); /* MR1 */ +extern void p_class_def1(); /* MR1 */ +extern void new_automaton_mode(); /* MR1 */ +extern int relabel(); /* MR1 */ +extern void p_shift_table(); /* MR1 */ +extern void p_bshift_table(); /* MR1 */ +extern void p_class_table(); /* MR1 */ +extern void p_mode_def(); /* MR1 */ +extern void init(); /* MR1 */ +extern void p_class_def2(); /* MR1 */ +extern void clear_hash(); /* MR1 */ +extern void p_alternative_table(); /* MR1 */ +extern void p_node_table(); /* MR1 */ +extern void p_dfa_table(); /* MR1 */ +extern void p_accept_table(); /* MR1 */ +extern void p_action_table(); /* MR1 */ +extern void p_base_table(); /* MR1 */ +extern void p_single_node(); /* MR1 */ +extern char * minsize(); /* MR1 */ +extern void close1(); /* MR1 */ +extern void partition(); /* MR1 */ +extern void intersect_nfa_labels(); /* MR1 */ +extern void r_intersect(); /* MR1 */ +extern void label_node(); /* MR1 */ +extern void label_with_classes(); /* MR1 */ + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.r b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.r new file mode 100644 index 00000000..d2348385 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg.r @@ -0,0 +1,270 @@ +/* + File: dlgMPW.r + Target: dlg 133MR + Created: Monday, June 15, 1998 4:44:11 AM + Author: Kenji Tanaka (kentar@osa.att.ne.jp) +*/ + +#include "cmdo.r" + +resource 'cmdo' (128, "Dlg") { + { /* array dialogs: 1 elements */ + /* [1] */ + 295, + "DLG -- Purdue Compiler Construction Tool" + " Set (PCCTS) lexical analyzer generator.", + { /* array itemArray: 18 elements */ + /* [1] */ + NotDependent { + + }, + CheckOption { + NotSet, + {35, 175, 50, 225}, + "On", + "-CC", + "When this control is checked, DLG generates " + "a scanner using C++ classes rather than " + "C functions." + }, + /* [2] */ + Or { + { /* array OrArray: 1 elements */ + /* [1] */ + 1 + } + }, + RegularEntry { + "Lexer Class Name:", + {35, 225, 50, 355}, + {35, 355, 51, 450}, + "DLGLexer", + keepCase, + "-cl", + "This entry specifies the name DLG uses for the C++ lexer class." + }, + /* [3] */ + NotDependent { + + }, + TextBox { + gray, + {25, 165, 60, 460}, + "C++ Code Generation" + }, + /* [4] */ + NotDependent { + + }, + Files { + InputFile, + RequiredFile { + {37, 25, 56, 135}, + "Input File", + "", + "Choose the lexical description file for " + "DLG to process." + }, + Additional { + "", + "", + "", + "", + { /* array TypesArray: 1 elements */ + /* [1] */ + text + } + } + }, + /* [5] */ + Or { + { /* array OrArray: 1 elements */ + /* [1] */ + -1 + } + }, + Files { + OutputFile, + RequiredFile { + {66, 25, 85, 135}, + "Output File", + "", + "Choose the name of the file that will hold the DLG-produced scanner." + }, + NoMore { + + } + }, + /* [6] */ + Or { + { /* array OrArray: 2 elements */ + /* [1] */ + 1, + /* [2] */ + 5 + } + }, + Dummy { + + }, + /* [7] */ + NotDependent { + + }, + Redirection { + DiagnosticOutput, + {90, 25} + }, + /* [8] */ + NotDependent { + + }, + TextBox { + gray, + {25, 20, 132, 145}, + "Files" + }, + /* [9] */ + NotDependent { + + }, + Files { + DirOnly, + OptionalFile { + {68, 175, 84, 305}, + {88, 175, 107, 305}, + "Output Directory", + ":", + "-o", + "", + "Choose the directory where DLG will put " + "its output.", + dim, + "Output DirectoryI", + "", + "" + }, + NoMore { + + } + }, + /* [10] */ + NotDependent { + + }, + RegularEntry { + "Mode File Name:", + {68, 315, 83, 450}, + {88, 315, 104, 450}, + "mode.h", + keepCase, + "-m", + "This entry specifies the name DLG uses for its lexical mode output file." + }, + /* [11] */ + NotDependent { + + }, + RadioButtons { + { /* array radioArray: 3 elements */ + /* [1] */ + {134, 175, 149, 255}, "None", "", Set, "When this option is selected, DLG will not " + "compress its tables.", + /* [2] */ + {134, 265, 149, 345}, "Level 1", "-C1", NotSet, "When this option is selected, DLG will " + "remove all unused characters from the transition-from table.", + /* [3] */ + {134, 360, 149, 450}, "Level 2", "-C2", NotSet, "When this option is selected, DLG will " + "perform level 1 compression plus it will " + "map equivalent characters into the same " + "character classes." + } + }, + /* [12] */ + NotDependent { + + }, + TextBox { + gray, + {124, 165, 156, 460}, + "Table Compression" + }, + /* [13] */ + NotDependent { + + }, + CheckOption { + Set, + {165, 20, 180, 145}, + "Case Sensitive", + "-ci", + "When this control is checked, the DLG automaton " + "will treat upper and lower case " + "characters identically." + }, + /* [14] */ + NotDependent { + + }, + CheckOption { + NotSet, + {165, 150, 180, 300}, + "Interactive Scanner", + "-i", + "When this control is checked, DLG will generate " + "as interactive a scanner as possible." + }, + /* [15] */ + NotDependent { + + }, + CheckOption { + NotSet, + {165, 310, 180, 460}, + "Ambiguity Warnings", + "-Wambiguity", + "When this control is checked, DLG warns " + "if more than one regular expression could " + "match the same character sequence." + }, + /* [16] */ + NotDependent { + + }, + VersionDialog { + VersionString { + "1.33MR" + }, + "PCCTS was written by Terence Parr, Russell " + "Quong, Will Cohen, and Hank Dietz: 1989-1998. " + "MPW port by Scott Haney.", + noDialog + }, + /* [17] */ + And { + { /* array AndArray: 2 elements */ + /* [1] */ + 4, + /* [2] */ + 6 + } + }, + DoItButton { + + }, + /* [18] */ + NotDependent { + + }, + CheckOption { + NotSet, + {142, 20, 157, 148}, + "Generate ANSI C", + "-ga", + "When this control is checked, DLG generates " + "ANSI C compatible code." + } + } + } +}; + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg1.txt b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg1.txt new file mode 100644 index 00000000..79f6690a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg1.txt @@ -0,0 +1,132 @@ + + + +dlg(1) PCCTS Manual Pages dlg(1) + + + +NAME + dlg - DFA Lexical Analyzer Generator + +SYNTAX + dlg [_o_p_t_i_o_n_s] _l_e_x_i_c_a_l__s_p_e_c [_o_u_t_p_u_t__f_i_l_e] + +DESCRIPTION + dlg is a tool that produces fast deterministic finite auto- + mata for recognizing regular expressions in input. + +OPTIONS + -CC Generate C++ output. The _o_u_t_p_u_t__f_i_l_e is not specified + in this case. + + -C[ level] + Where level is the compression level used. 0 indica- + tions no compression, 1 removes all unused characters + from the transition from table, and 2 maps equivalent + characters into the same character classes. It is sug- + gested that level -C2 is used, since it will signifi- + cantly reduce the size of the dfa produced for lexical + analyzer. + + -m Produces the header file for the lexical mode with a + name other than the default name of "mode.h". + + -i An interactive, or as interactive as possible, parser + is produced. A character is only obtained when + required to decide which state to go to. Some care + must be taken to obtain accept states that do not + require look ahead at the next character to determine + if that is the stop state. Any regular expression with + a Kleene closure at the end is guaranteed to require + another character of look ahead. + + -cl class + Specify a class name for DLG to generate. The default + is DLGLexer. + + -ci The automaton will treat upper and lower case charac- + ters identically. This is accomplished in the automa- + ton; the characters in the lexical buffer are unmodi- + fied. + + -cs Upper and lower case characters are treated as dis- + tinct. This is the default. + + -o dir + Directory where output files should go (default="."). + This is very nice for keeping the source directory + clear of ANTLR and DLG spawn. + + -Wambiguity + Warns if more than one regular expression could match + the same character sequence. The warnings give the + numbers of the expressions in the dlg lexical specifi- + cation file. The numbering of the expressions starts + at one. Multiple warnings may be print for the same + expressions. + + - Used in place of file names to get input from standard + in or send output to standard out. + +SPECIAL CONSIDERATIONS + _D_l_g works... we think. There is no implicit guarantee of + anything. We reserve no legal rights to the software known + as the Purdue Compiler Construction Tool Set (PCCTS) - PCCTS + is in the public domain. An individual or company may do + whatever they wish with source code distributed with PCCTS + or the code generated by PCCTS, including the incorporation + of PCCTS, or its output, into commercial software. We + encourage users to develop software with PCCTS. However, we + do ask that credit is given to us for developing PCCTS. By + "credit", we mean that if you incorporate our source code + into one of your programs (commercial product, research pro- + ject, or otherwise) that you acknowledge this fact somewhere + in the documentation, research report, etc... If you like + PCCTS and have developed a nice tool with the output, please + mention that you developed it using PCCTS. As long as these + guidelines are followed, we expect to continue enhancing + this system and expect to make other tools available as they + are completed. + +FILES + mode.h , dlgauto.h , dlgdef.h + +SEE ALSO + antlr(1), pccts(1) + +BUGS + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_a.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_a.c new file mode 100644 index 00000000..c3d4e7b6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_a.c @@ -0,0 +1,1414 @@ + +/* parser.dlg -- DLG Description of scanner + * + * Generated from: dlg_p.g + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + */ + +#define ANTLR_VERSION 13333 +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include +#include "dlg.h" +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +LOOKAHEAD + +void +#ifdef __USE_PROTOS +zzerraction(void) +#else +zzerraction() +#endif +{ + (*zzerr)("invalid token"); + zzadvance(); + zzskip(); +} +/* + * D L G tables + * + * Generated from: parser.dlg + * + * 1989-2001 by Will Cohen, Terence Parr, and Hank Dietz + * Purdue University Electrical Engineering + * DLG Version 1.33MR33 + */ + +#include "mode.h" + + + + +int func_action; /* should actions be turned into functions?*/ +int lex_mode_counter = 0; /* keeps track of the number of %%names */ +/* MR1 */ +/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ +/* MR1 via <<%%lexmember...>> */ +/* MR1 */ +int lexMember = 0; /* <<%%lexmemeber ...>> MR1 */ +int lexAction = 0; /* <<%%lexaction ...>> MR1 */ +int parserClass = 0; /* <<%%parserclass ...>> MR1 */ +int lexPrefix = 0; /* <<%%lexprefix ...>> MR1 */ +char theClassName[100]; /* MR11 */ +char *pClassName=theClassName; /* MR11 */ +int firstLexMember=1; /* MR1 */ + +#ifdef __USE_PROTOS +void xxputc(int c) { /* MR1 */ +#else + void xxputc(c) /* MR1 */ + int c; /* MR1 */ + { /* MR1 */ +#endif + if (parserClass) { /* MR1 */ + *pClassName++=c; /* MR1 */ + *pClassName=0; /* MR1 */ + } else if (lexMember || lexPrefix) { /* MR1 */ + if (class_stream != NULL) fputc(c,class_stream); /* MR1 */ + } else { /* MR1 */ + fputc(c,OUT); /* MR1 */ + }; /* MR1 */ + } /* MR1 */ + +#ifdef __USE_PROTOS + void xxprintf(char *format,char *string) { /* MR1 */ +#else + void xxprintf(format,string) /* MR1 */ + char *format; /* MR1 */ + char *string; /* MR1 */ + { /* MR1 */ +#endif + if (lexMember || lexPrefix || parserClass) { /* MR1 */ + if (class_stream != NULL) /* MR1 */ + fprintf(class_stream,format,string); /* MR1 */ + } else { /* MR1 */ + fprintf(OUT,format,string); /* MR1 */ + }; /* MR1 */ + } /* MR1 */ + +static void act1() +{ + NLA = 1; + } + + +static void act2() +{ + NLA = 2; + zzskip(); + } + + +static void act3() +{ + NLA = 3; + zzline++; zzskip(); DAWDLE; + } + + +static void act4() +{ + NLA = L_EOF; + } + + +static void act5() +{ + NLA = PER_PER; + } + + +static void act6() +{ + NLA = NAME_PER_PER; + p_mode_def(&zzlextext[2],lex_mode_counter++); + } + + +static void act7() +{ + NLA = LEXMEMBER; + lexMember=1; /* MR1 */ + if (firstLexMember != 0) { /* MR1 */ + firstLexMember=0; /* MR1 */ + p_class_def1(); /* MR1 */ + }; /* MR1 */ + zzmode(ACT); /* MR1 */ + } + + +static void act8() +{ + NLA = LEXACTION; + lexAction=1;zzmode(ACT); + } + + +static void act9() +{ + NLA = PARSERCLASS; + parserClass=1; /* MR1 */ + zzmode(ACT); /* MR1 */ + } + + +static void act10() +{ + NLA = LEXPREFIX; + lexPrefix=1;zzmode(ACT); + } + + +static void act11() +{ + NLA = ACTION; + if (func_action) + fprintf(OUT,"\n%s %sact%d()\n{ ", + gen_cpp?"ANTLRTokenType":"static void", + gen_cpp?ClassName("::"):"", ++action_no); + zzmode(ACT); zzskip(); + } + + +static void act12() +{ + NLA = GREAT_GREAT; + } + + +static void act13() +{ + NLA = L_BRACE; + } + + +static void act14() +{ + NLA = R_BRACE; + } + + +static void act15() +{ + NLA = L_PAR; + } + + +static void act16() +{ + NLA = R_PAR; + } + + +static void act17() +{ + NLA = L_BRACK; + } + + +static void act18() +{ + NLA = R_BRACK; + } + + +static void act19() +{ + NLA = ZERO_MORE; + } + + +static void act20() +{ + NLA = ONE_MORE; + } + + +static void act21() +{ + NLA = OR; + } + + +static void act22() +{ + NLA = RANGE; + } + + +static void act23() +{ + NLA = NOT; + } + + +static void act24() +{ + NLA = OCTAL_VALUE; + {int t; sscanf(&zzlextext[1],"%o",&t); zzlextext[0] = t;} + } + + +static void act25() +{ + NLA = HEX_VALUE; + {int t; sscanf(&zzlextext[3],"%x",&t); zzlextext[0] = t;} + } + + +static void act26() +{ + NLA = DEC_VALUE; + {int t; sscanf(&zzlextext[1],"%d",&t); zzlextext[0] = t;} + } + + +static void act27() +{ + NLA = TAB; + zzlextext[0] = '\t'; + } + + +static void act28() +{ + NLA = NL; + zzlextext[0] = '\n'; + } + + +static void act29() +{ + NLA = CR; + zzlextext[0] = '\r'; + } + + +static void act30() +{ + NLA = BS; + zzlextext[0] = '\b'; + } + + +static void act31() +{ + NLA = CONTINUATION; + zzline++; zzskip(); + } + + +static void act32() +{ + NLA = LIT; + zzlextext[0] = zzlextext[1]; + } + + +static void act33() +{ + NLA = REGCHAR; + } + +static unsigned char shift0[257] = { + 0, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 1, 2, 40, 40, 1, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 1, 40, 40, 40, 40, 4, 40, + 40, 30, 31, 34, 35, 40, 37, 40, 40, 23, + 24, 24, 24, 24, 24, 24, 24, 25, 25, 40, + 40, 26, 40, 27, 40, 3, 21, 21, 21, 21, + 21, 21, 22, 22, 22, 22, 22, 22, 22, 22, + 22, 22, 22, 22, 22, 22, 22, 22, 22, 20, + 22, 22, 32, 39, 33, 40, 22, 40, 11, 9, + 12, 21, 6, 19, 22, 22, 14, 22, 22, 5, + 8, 16, 15, 17, 22, 10, 18, 13, 22, 22, + 22, 7, 22, 22, 28, 36, 29, 38, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40, 40, 40, 40, + 40, 40, 40, 40, 40, 40, 40 +}; + + +static void act34() +{ + NLA = 1; + error("unterminated action", zzline); zzmode(START); + } + + +static void act35() +{ + NLA = ACTION; + if (func_action) fprintf(OUT,"}\n\n"); + zzmode(START); + /* MR1 */ + /* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ + /* MR1 via <<%%lexmember ...>> */ + /* MR1 This is a consequence of not saving actions */ + /* MR1 */ + /* MR1 */ parserClass=0; + /* MR1 */ lexPrefix=0; + /* MR1 */ lexAction=0; + /* MR1 */ lexMember=0; + } + + +static void act36() +{ + NLA = 34; + xxputc(zzlextext[0]); zzskip(); + } + + +static void act37() +{ + NLA = 35; + xxputc('>'); zzskip(); + } + + +static void act38() +{ + NLA = 36; + xxputc('\\'); zzskip(); + } + + +static void act39() +{ + NLA = 37; + xxputc(zzlextext[0]); ++zzline; zzskip(); + } + + +static void act40() +{ + NLA = 38; + zzmode(ACTION_COMMENTS); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + } + + +static void act41() +{ + NLA = 39; + zzmode(ACTION_CPP_COMMENTS); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + } + + +static void act42() +{ + NLA = 40; + xxputc(zzlextext[0]); zzskip(); + } + +static unsigned char shift1[257] = { + 0, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 3, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 5, 6, 6, 6, 6, 4, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 1, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 2, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6 +}; + + +static void act43() +{ + NLA = 1; + } + + +static void act44() +{ + NLA = 41; + zzmode(ACT); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + } + + +static void act45() +{ + NLA = 42; + zzline++; xxputc(zzlextext[0]); zzskip(); + } + + +static void act46() +{ + NLA = 43; + xxputc(zzlextext[0]); zzskip(); + } + +static unsigned char shift2[257] = { + 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 3, 4, 4, 3, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 1, 4, 4, 4, 4, 2, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4 +}; + + +static void act47() +{ + NLA = 1; + } + + +static void act48() +{ + NLA = 44; + zzmode(ACT); zzline++; /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + } + + +static void act49() +{ + NLA = 45; + xxputc(zzlextext[0]); zzskip(); + } + +static unsigned char shift3[257] = { + 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 1, 2, 2, 1, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2 +}; + +#define DfaStates 94 +typedef unsigned char DfaState; + +static DfaState st0[42] = { + 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, + 6, 94 +}; + +static DfaState st1[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st2[42] = { + 94, 21, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st3[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st4[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st5[42] = { + 94, 94, 94, 94, 22, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st6[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st7[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 23, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st8[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 24, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st9[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st10[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st11[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st12[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st13[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st14[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st15[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st16[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st17[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st18[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st19[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st20[42] = { + 94, 25, 26, 25, 25, 25, 25, 25, 25, 27, + 28, 25, 25, 29, 25, 25, 30, 25, 25, 25, + 25, 25, 25, 31, 32, 32, 25, 25, 25, 25, + 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, + 25, 94 +}; + +static DfaState st21[42] = { + 94, 21, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st22[42] = { + 94, 94, 94, 94, 94, 33, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 33, 33, 33, 33, + 33, 33, 33, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st23[42] = { + 94, 94, 94, 94, 34, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st24[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st25[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st26[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st27[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st28[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st29[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st30[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st31[42] = { + 94, 94, 94, 94, 94, 94, 94, 35, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 35, 94, 94, 36, 36, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st32[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 37, 37, 37, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st33[42] = { + 94, 94, 94, 94, 94, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st34[42] = { + 94, 94, 94, 94, 39, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st35[42] = { + 94, 94, 94, 94, 94, 94, 40, 94, 94, 40, + 94, 40, 40, 94, 94, 94, 94, 94, 94, 40, + 94, 40, 94, 40, 40, 40, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st36[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 36, 36, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st37[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 37, 37, 37, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st38[42] = { + 94, 94, 94, 94, 94, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 38, 38, 38, 38, + 38, 38, 38, 38, 38, 38, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st39[42] = { + 94, 94, 94, 94, 94, 41, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 42, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st40[42] = { + 94, 94, 94, 94, 94, 94, 40, 94, 94, 40, + 94, 40, 40, 94, 94, 94, 94, 94, 94, 40, + 94, 40, 94, 40, 40, 40, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st41[42] = { + 94, 94, 94, 94, 94, 94, 43, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st42[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 44, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st43[42] = { + 94, 94, 94, 94, 94, 94, 94, 45, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st44[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 46, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st45[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 47, 94, + 94, 48, 94, 94, 94, 94, 94, 49, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st46[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 50, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st47[42] = { + 94, 94, 94, 94, 94, 94, 51, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st48[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 52, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st49[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 53, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st50[42] = { + 94, 94, 94, 94, 94, 94, 54, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st51[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 55, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st52[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 56, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st53[42] = { + 94, 94, 94, 94, 94, 94, 57, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st54[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 58, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st55[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 59, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st56[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 60, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st57[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 61, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st58[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 62, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st59[42] = { + 94, 94, 94, 94, 94, 94, 63, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st60[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 64, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st61[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 65, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st62[42] = { + 94, 94, 94, 94, 94, 66, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st63[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 67, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st64[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 68, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st65[42] = { + 94, 94, 94, 94, 94, 94, 94, 69, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st66[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 70, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st67[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st68[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st69[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st70[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 71, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st71[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 72, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st72[42] = { + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94, 94, 94, 94, 94, 94, 94, 94, 94, + 94, 94 +}; + +static DfaState st73[8] = { + 74, 75, 76, 77, 78, 79, 79, 94 +}; + +static DfaState st74[8] = { + 94, 94, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st75[8] = { + 94, 80, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st76[8] = { + 94, 81, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st77[8] = { + 94, 94, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st78[8] = { + 94, 94, 94, 94, 82, 83, 94, 94 +}; + +static DfaState st79[8] = { + 94, 94, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st80[8] = { + 94, 94, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st81[8] = { + 94, 94, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st82[8] = { + 94, 94, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st83[8] = { + 94, 94, 94, 94, 94, 94, 94, 94 +}; + +static DfaState st84[6] = { + 85, 86, 87, 88, 87, 94 +}; + +static DfaState st85[6] = { + 94, 94, 94, 94, 94, 94 +}; + +static DfaState st86[6] = { + 94, 94, 89, 94, 94, 94 +}; + +static DfaState st87[6] = { + 94, 94, 94, 94, 94, 94 +}; + +static DfaState st88[6] = { + 94, 94, 94, 94, 94, 94 +}; + +static DfaState st89[6] = { + 94, 94, 94, 94, 94, 94 +}; + +static DfaState st90[4] = { + 91, 92, 93, 94 +}; + +static DfaState st91[4] = { + 94, 94, 94, 94 +}; + +static DfaState st92[4] = { + 94, 94, 94, 94 +}; + +static DfaState st93[4] = { + 94, 94, 94, 94 +}; + + +DfaState *dfa[94] = { + st0, + st1, + st2, + st3, + st4, + st5, + st6, + st7, + st8, + st9, + st10, + st11, + st12, + st13, + st14, + st15, + st16, + st17, + st18, + st19, + st20, + st21, + st22, + st23, + st24, + st25, + st26, + st27, + st28, + st29, + st30, + st31, + st32, + st33, + st34, + st35, + st36, + st37, + st38, + st39, + st40, + st41, + st42, + st43, + st44, + st45, + st46, + st47, + st48, + st49, + st50, + st51, + st52, + st53, + st54, + st55, + st56, + st57, + st58, + st59, + st60, + st61, + st62, + st63, + st64, + st65, + st66, + st67, + st68, + st69, + st70, + st71, + st72, + st73, + st74, + st75, + st76, + st77, + st78, + st79, + st80, + st81, + st82, + st83, + st84, + st85, + st86, + st87, + st88, + st89, + st90, + st91, + st92, + st93 +}; + + +DfaState accepts[95] = { + 0, 1, 2, 3, 4, 33, 33, 33, 33, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 0, 2, 5, 11, 12, 32, 31, 30, 29, 27, + 28, 24, 26, 6, 0, 0, 24, 26, 6, 0, + 25, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 7, 8, 10, + 0, 0, 9, 0, 34, 36, 38, 39, 42, 42, + 35, 37, 41, 40, 0, 43, 46, 46, 45, 44, + 0, 47, 48, 49, 0 +}; + +void (*actions[50])() = { + zzerraction, + act1, + act2, + act3, + act4, + act5, + act6, + act7, + act8, + act9, + act10, + act11, + act12, + act13, + act14, + act15, + act16, + act17, + act18, + act19, + act20, + act21, + act22, + act23, + act24, + act25, + act26, + act27, + act28, + act29, + act30, + act31, + act32, + act33, + act34, + act35, + act36, + act37, + act38, + act39, + act40, + act41, + act42, + act43, + act44, + act45, + act46, + act47, + act48, + act49 +}; + +static DfaState dfa_base[] = { + 0, + 73, + 84, + 90 +}; + +static unsigned char *b_class_no[] = { + shift0, + shift1, + shift2, + shift3 +}; + + + +#define ZZSHIFT(c) (b_class_no[zzauto][1+c]) +#define MAX_MODE 4 +#include "dlgauto.h" diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_p.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_p.c new file mode 100644 index 00000000..d689afa0 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_p.c @@ -0,0 +1,970 @@ +/* + * A n t l r T r a n s l a t i o n H e a d e r + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + * + * ..\bin\antlr dlg_p.g -gh + * + */ + +#define ANTLR_VERSION 13333 +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include +#include "dlg.h" +#define zzSET_SIZE 8 +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +#include "mode.h" + +/* MR23 In order to remove calls to PURIFY use the antlr -nopurify option */ + +#ifndef PCCTS_PURIFY +#define PCCTS_PURIFY(r,s) memset((char *) &(r),'\0',(s)); +#endif + +ANTLR_INFO + + +/* MR20 G. Hobbelt +Fix for Borland C++ 4.x & 5.x compiling with ALL warnings enabled +*/ + +#ifdef __TURBOC__ +#pragma warn -aus /* unused assignment of 'xxx' */ +#endif + +#ifdef VBOX +# ifdef _MSC_VER +# pragma warning(disable : 4068) /* Unguarded '#pragma clang' below */ +# endif +# ifdef __GNUC__ +# pragma GCC diagnostic ignored "-Wunknown-pragmas" +# endif +#endif + +#pragma clang diagnostic ignored "-Wparentheses-equality" + +int action_no = 0; /* keep track of actions outputted */ +int nfa_allocated = 0; /* keeps track of number of nfa nodes */ +nfa_node **nfa_array = NULL;/* root of binary tree that stores nfa array */ +nfa_node nfa_model_node; /* model to initialize new nodes */ +set used_chars; /* used to label trans. arcs */ +set used_classes; /* classes or chars used to label trans. arcs */ +set normal_chars; /* mask to get rid elements that aren't used +in set */ +int flag_paren = FALSE; +int flag_brace = FALSE; +int mode_counter = 0; /* keep track of number of %%names */ + + + +void +#ifdef __USE_PROTOS +grammar(void) +#else +grammar() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + p_head(); p_class_hdr(); func_action = FALSE; + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (setwd1[LA(1)]&0x1) ) { + { + zzBLOCK(zztasp3); + zzMake0; + { + if ( (LA(1)==LEXACTION) ) { + zzmatch(LEXACTION); zzCONSUME; + } + else { + if ( (LA(1)==LEXMEMBER) ) { + zzmatch(LEXMEMBER); zzCONSUME; + } + else { + if ( (LA(1)==LEXPREFIX) ) { + zzmatch(LEXPREFIX); zzCONSUME; + } + else { + if ( (LA(1)==PARSERCLASS) ) { + zzmatch(PARSERCLASS); zzCONSUME; + } + else { + if ( (LA(1)==ACTION) ) { + } + else {zzFAIL(1,zzerr1,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + } + } + zzEXIT(zztasp3); + } + } + zzmatch(ACTION); zzCONSUME; + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + if ( gen_cpp ) p_includes(); + start_states(); + func_action = FALSE; p_tables(); p_tail(); + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==ACTION) ) { + zzmatch(ACTION); zzCONSUME; + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzmatch(1); + if (firstLexMember != 0) p_class_def1(); + zzCONSUME; + + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd1, 0x2); + } +} + +void +#ifdef __USE_PROTOS +start_states(void) +#else +start_states() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==PER_PER) ) { + zzmatch(PER_PER); zzCONSUME; + do_conversion(); + } + else { + if ( (LA(1)==NAME_PER_PER) ) { + zzmatch(NAME_PER_PER); zzCONSUME; + do_conversion(); + { + zzBLOCK(zztasp3); + zzMake0; + { + while ( (LA(1)==NAME_PER_PER) ) { + zzmatch(NAME_PER_PER); zzCONSUME; + do_conversion(); + zzLOOP(zztasp3); + } + zzEXIT(zztasp3); + } + } + } + else {zzFAIL(1,zzerr2,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + zzmatch(PER_PER); zzCONSUME; + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd1, 0x4); + } +} + +void +#ifdef __USE_PROTOS +do_conversion(void) +#else +do_conversion() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + new_automaton_mode(); func_action = TRUE; + rule_list(); + + dfa_class_nop[mode_counter] = + relabel(zzaArg(zztasp1,1 ).l,comp_level); + if (comp_level) + p_shift_table(mode_counter); + dfa_basep[mode_counter] = dfa_allocated+1; + make_dfa_model_node(dfa_class_nop[mode_counter]); + nfa_to_dfa(zzaArg(zztasp1,1 ).l); + ++mode_counter; + func_action = FALSE; +#ifdef HASH_STAT + fprint_hash_stats(stderr); +#endif + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd1, 0x8); + } +} + +void +#ifdef __USE_PROTOS +rule_list(void) +#else +rule_list() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + if ( (setwd1[LA(1)]&0x10) ) { + rule(); + zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r; + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (setwd1[LA(1)]&0x20) ) { + rule(); + {nfa_node *t1; + t1 = new_nfa_node(); + (t1)->trans[0]=zzaRet.l; + (t1)->trans[1]=zzaArg(zztasp2,1 ).l; + /* all accept nodes "dead ends" */ + zzaRet.l=t1; zzaRet.r=NULL; + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + } + else { + if ( (setwd1[LA(1)]&0x40) ) { + zzaRet.l = new_nfa_node(); zzaRet.r = NULL; + warning("no regular expressions", zzline); + } + else {zzFAIL(1,zzerr3,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd1, 0x80); + } +} + +void +#ifdef __USE_PROTOS +rule(void) +#else +rule() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + if ( (setwd2[LA(1)]&0x1) ) { + reg_expr(); + zzmatch(ACTION); + if (zzaArg(zztasp1,1 ).r != NULL) { + zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r; (zzaArg(zztasp1,1 ).r)->accept=action_no; + } + zzCONSUME; + + } + else { + if ( (LA(1)==ACTION) ) { + zzmatch(ACTION); + zzaRet.l = NULL; zzaRet.r = NULL; + error("no expression for action ", zzline); + zzCONSUME; + + } + else {zzFAIL(1,zzerr4,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd2, 0x2); + } +} + +void +#ifdef __USE_PROTOS +reg_expr(void) +#else +reg_expr() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + and_expr(); + zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r; + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (LA(1)==OR) ) { + zzmatch(OR); zzCONSUME; + and_expr(); + {nfa_node *t1, *t2; + t1 = new_nfa_node(); t2 = new_nfa_node(); + (t1)->trans[0]=zzaRet.l; + (t1)->trans[1]=zzaArg(zztasp2,2 ).l; + /* MR23 */ if (zzaRet.r != NULL) (zzaRet.r)->trans[1]=t2; + if (zzaArg(zztasp2,2 ).r) { + (zzaArg(zztasp2,2 ).r)->trans[1]=t2; /* MR20 */ + } + zzaRet.l=t1; zzaRet.r=t2; + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd2, 0x4); + } +} + +void +#ifdef __USE_PROTOS +and_expr(void) +#else +and_expr() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + repeat_expr(); + + zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r; + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (setwd2[LA(1)]&0x8) ) { + repeat_expr(); + if (zzaRet.r != NULL) { + (zzaRet.r)->trans[1]=zzaArg(zztasp2,1 ).l; + zzaRet.r=zzaArg(zztasp2,1 ).r; + } + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd2, 0x10); + } +} + +void +#ifdef __USE_PROTOS +repeat_expr(void) +#else +repeat_expr() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + if ( (setwd2[LA(1)]&0x20) ) { + expr(); + zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r; + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==ZERO_MORE) ) { + zzmatch(ZERO_MORE); + { nfa_node *t1,*t2; + /* MR23 */ if (zzaRet.r != NULL) (zzaRet.r)->trans[0] = zzaRet.l; + t1 = new_nfa_node(); t2 = new_nfa_node(); + t1->trans[0]=zzaRet.l; + t1->trans[1]=t2; + /* MR23 */ if (zzaRet.r != NULL) (zzaRet.r)->trans[1]=t2; + zzaRet.l=t1;zzaRet.r=t2; + } + zzCONSUME; + + } + else { + if ( (LA(1)==ONE_MORE) ) { + zzmatch(ONE_MORE); + if (zzaRet.r != NULL) (zzaRet.r)->trans[0] = zzaRet.l; + zzCONSUME; + + } + else { + if ( (setwd2[LA(1)]&0x40) ) { + } + else {zzFAIL(1,zzerr5,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp2); + } + } + } + else { + if ( (LA(1)==ZERO_MORE) ) { + zzmatch(ZERO_MORE); + error("no expression for *", zzline); + zzCONSUME; + + } + else { + if ( (LA(1)==ONE_MORE) ) { + zzmatch(ONE_MORE); + error("no expression for +", zzline); + zzCONSUME; + + } + else {zzFAIL(1,zzerr6,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd2, 0x80); + } +} + +void +#ifdef __USE_PROTOS +expr(void) +#else +expr() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + zzaRet.l = new_nfa_node(); + zzaRet.r = new_nfa_node(); + if ( (LA(1)==L_BRACK) ) { + zzmatch(L_BRACK); zzCONSUME; + atom_list(); + zzmatch(R_BRACK); + + /* MR23 */ if (zzaRet.l != NULL) { + (zzaRet.l)->trans[0] = zzaRet.r; + (zzaRet.l)->label = set_dup(zzaArg(zztasp1,2 ).label); + set_orin(&used_chars,(zzaRet.l)->label); + } + zzCONSUME; + + } + else { + if ( (LA(1)==NOT) ) { + zzmatch(NOT); zzCONSUME; + zzmatch(L_BRACK); zzCONSUME; + atom_list(); + zzmatch(R_BRACK); + + /* MR23 */ if (zzaRet.l != NULL) { + (zzaRet.l)->trans[0] = zzaRet.r; + (zzaRet.l)->label = set_dif(normal_chars,zzaArg(zztasp1,3 ).label); + set_orin(&used_chars,(zzaRet.l)->label); + } + zzCONSUME; + + } + else { + if ( (LA(1)==L_PAR) ) { + zzmatch(L_PAR); zzCONSUME; + reg_expr(); + zzmatch(R_PAR); + + /* MR23 */ if (zzaRet.l != NULL) { + (zzaRet.l)->trans[0] = zzaArg(zztasp1,2 ).l; + if (zzaArg(zztasp1,2 ).r) { + (zzaArg(zztasp1,2 ).r)->trans[1] = zzaRet.r; /* MR20 */ + } + } + zzCONSUME; + + } + else { + if ( (LA(1)==L_BRACE) ) { + zzmatch(L_BRACE); zzCONSUME; + reg_expr(); + zzmatch(R_BRACE); + + /* MR23 */ if (zzaRet.l != NULL) { + (zzaRet.l)->trans[0] = zzaArg(zztasp1,2 ).l; + (zzaRet.l)->trans[1] = zzaRet.r; + if (zzaArg(zztasp1,2 ).r) { + (zzaArg(zztasp1,2 ).r)->trans[1] = zzaRet.r; /* MR20 */ + } + } + zzCONSUME; + + } + else { + if ( (setwd3[LA(1)]&0x1) ) { + atom(); + + /* MR23 */ if (zzaRet.l != NULL) { + (zzaRet.l)->trans[0] = zzaRet.r; + (zzaRet.l)->label = set_dup(zzaArg(zztasp1,1 ).label); + set_orin(&used_chars,(zzaRet.l)->label); + } + } + else {zzFAIL(1,zzerr7,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + } + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x2); + } +} + +void +#ifdef __USE_PROTOS +atom_list(void) +#else +atom_list() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + set_free(zzaRet.label); + { + zzBLOCK(zztasp2); + zzMake0; + { + while ( (setwd3[LA(1)]&0x4) ) { + near_atom(); + set_orin(&(zzaRet.label),zzaArg(zztasp2,1 ).label); + zzLOOP(zztasp2); + } + zzEXIT(zztasp2); + } + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x8); + } +} + +void +#ifdef __USE_PROTOS +near_atom(void) +#else +near_atom() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + register int i; + register int i_prime; + anychar(); + zzaRet.letter=zzaArg(zztasp1,1 ).letter; zzaRet.label=set_of(zzaArg(zztasp1,1 ).letter); + i_prime = zzaArg(zztasp1,1 ).letter + MIN_CHAR; + if (case_insensitive && islower(i_prime)) + set_orel(toupper(i_prime)-MIN_CHAR, + &(zzaRet.label)); + if (case_insensitive && isupper(i_prime)) + set_orel(tolower(i_prime)-MIN_CHAR, + &(zzaRet.label)); + { + zzBLOCK(zztasp2); + zzMake0; + { + if ( (LA(1)==RANGE) ) { + zzmatch(RANGE); zzCONSUME; + anychar(); + if (case_insensitive){ + i_prime = zzaRet.letter+MIN_CHAR; + zzaRet.letter = (islower(i_prime) ? + toupper(i_prime) : i_prime)-MIN_CHAR; + i_prime = zzaArg(zztasp2,2 ).letter+MIN_CHAR; + zzaArg(zztasp2,2 ).letter = (islower(i_prime) ? + toupper(i_prime) : i_prime)-MIN_CHAR; + } + /* check to see if range okay */ + { + int debugLetter1 = zzaRet.letter; + int debugLetter2 = zzaArg(zztasp2,2 ).letter; + } + if (zzaRet.letter > zzaArg(zztasp2,2 ).letter + && zzaArg(zztasp2,2 ).letter != 0xff){ /* MR16 */ + error("invalid range ", zzline); + } + for (i=zzaRet.letter; i<= (int)zzaArg(zztasp2,2 ).letter; ++i){ + set_orel(i,&(zzaRet.label)); + i_prime = i+MIN_CHAR; + if (case_insensitive && islower(i_prime)) + set_orel(toupper(i_prime)-MIN_CHAR, + &(zzaRet.label)); + if (case_insensitive && isupper(i_prime)) + set_orel(tolower(i_prime)-MIN_CHAR, + &(zzaRet.label)); + } + } + else { + if ( (setwd3[LA(1)]&0x10) ) { + } + else {zzFAIL(1,zzerr8,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + zzEXIT(zztasp2); + } + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x20); + } +} + +void +#ifdef __USE_PROTOS +atom(void) +#else +atom() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + register int i_prime; + anychar(); + zzaRet.label = set_of(zzaArg(zztasp1,1 ).letter); + i_prime = zzaArg(zztasp1,1 ).letter + MIN_CHAR; + if (case_insensitive && islower(i_prime)) + set_orel(toupper(i_prime)-MIN_CHAR, + &(zzaRet.label)); + if (case_insensitive && isupper(i_prime)) + set_orel(tolower(i_prime)-MIN_CHAR, + &(zzaRet.label)); + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x40); + } +} + +void +#ifdef __USE_PROTOS +anychar(void) +#else +anychar() +#endif +{ + zzRULE; + zzBLOCK(zztasp1); + zzMake0; + { + if ( (LA(1)==REGCHAR) ) { + zzmatch(REGCHAR); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==OCTAL_VALUE) ) { + zzmatch(OCTAL_VALUE); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==HEX_VALUE) ) { + zzmatch(HEX_VALUE); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==DEC_VALUE) ) { + zzmatch(DEC_VALUE); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==TAB) ) { + zzmatch(TAB); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==NL) ) { + zzmatch(NL); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==CR) ) { + zzmatch(CR); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==BS) ) { + zzmatch(BS); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==LIT) ) { + zzmatch(LIT); + zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; + zzCONSUME; + + } + else { + if ( (LA(1)==L_EOF) ) { + zzmatch(L_EOF); + zzaRet.letter = 0; + zzCONSUME; + + } + else {zzFAIL(1,zzerr9,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} + } + } + } + } + } + } + } + } + } + zzEXIT(zztasp1); + return; +fail: + zzEXIT(zztasp1); + /* empty action */ + zzsyn(zzMissText, zzBadTok, (ANTLRChar *)"", zzMissSet, zzMissTok, zzErrk, zzBadText); + zzresynch(setwd3, 0x80); + } +} + +/* adds a new nfa to the binary tree and returns a pointer to it */ +nfa_node * +#ifdef __USE_PROTOS +new_nfa_node(void) +#else +new_nfa_node() +#endif +{ + register nfa_node *t; + static int nfa_size=0; /* elements nfa_array[] can hold */ + + ++nfa_allocated; + if (nfa_size<=nfa_allocated){ + /* need to redo array */ + if (!nfa_array){ + /* need some to do initial allocation */ + nfa_size=nfa_allocated+NFA_MIN; + nfa_array=(nfa_node **) malloc(sizeof(nfa_node*)* + nfa_size); + }else{ + /* need more space */ + nfa_size=2*(nfa_allocated+1); + nfa_array=(nfa_node **) realloc(nfa_array, + sizeof(nfa_node*)*nfa_size); + } + } + /* fill out entry in array */ + t = (nfa_node*) malloc(sizeof(nfa_node)); + nfa_array[nfa_allocated] = t; + *t = nfa_model_node; + t->node_no = nfa_allocated; + return t; +} + + +/* initialize the model node used to fill in newly made nfa_nodes */ +void +#ifdef __USE_PROTOS +make_nfa_model_node(void) +#else +make_nfa_model_node() +#endif +{ + nfa_model_node.node_no = -1; /* impossible value for real nfa node */ + nfa_model_node.nfa_set = 0; + nfa_model_node.accept = 0; /* error state default*/ + nfa_model_node.trans[0] = NULL; + nfa_model_node.trans[1] = NULL; + nfa_model_node.label = empty; +} + +#if defined(DEBUG) || defined(_DEBUG) + +/* print out the pointer value and the node_number */ +void +#ifdef __USE_PROTOS +fprint_dfa_pair(FILE *f, nfa_node *p) +#else +fprint_dfa_pair(f, p) +FILE *f; +nfa_node *p; +#endif +{ + if (p){ + fprintf(f, "%x (%d)", p, p->node_no); + }else{ + fprintf(f, "(nil)"); + } +} + +/* print out interest information on a set */ +void +#ifdef __USE_PROTOS +fprint_set(FILE *f, set s) +#else +fprint_set(f,s) +FILE *f; +set s; +#endif +{ + unsigned int *x; + + fprintf(f, "n = %d,", s.n); + if (s.setword){ + fprintf(f, "setword = %x, ", s.setword); + /* print out all the elements in the set */ + x = set_pdq(s); + while (*x!=nil){ + fprintf(f, "%d ", *x); + ++x; + } + }else{ + fprintf(f, "setword = (nil)"); + } +} + +/* code to be able to dump out the nfas +return 0 if okay dump +return 1 if screwed up +*/ +int +#ifdef __USE_PROTOS +dump_nfas(int first_node, int last_node) +#else +dump_nfas(first_node, last_node) +int first_node; +int last_node; +#endif +{ + register int i; + nfa_node *t; + + for (i=first_node; i<=last_node; ++i){ + t = NFA(i); + if (!t) break; + fprintf(stderr, "nfa_node %d {\n", t->node_no); + fprintf(stderr, "\n\tnfa_set = %d\n", t->nfa_set); + fprintf(stderr, "\taccept\t=\t%d\n", t->accept); + fprintf(stderr, "\ttrans\t=\t("); + fprint_dfa_pair(stderr, t->trans[0]); + fprintf(stderr, ","); + fprint_dfa_pair(stderr, t->trans[1]); + fprintf(stderr, ")\n"); + fprintf(stderr, "\tlabel\t=\t{ "); + fprint_set(stderr, t->label); + fprintf(stderr, "\t}\n"); + fprintf(stderr, "}\n\n"); + } + return 0; +} +#endif + +/* DLG-specific syntax error message generator +* (define USER_ZZSYN when compiling so don't get 2 definitions) +*/ +void +#ifdef __USE_PROTOS +zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, int k, char *bad_text) +#else +zzsyn(text, tok, egroup, eset, etok, k, bad_text) +char *text, *egroup, *bad_text; +int tok; +int etok; +int k; +SetWordType *eset; +#endif +{ +fprintf(stderr, ErrHdr, file_str[0]!=NULL?file_str[0]:"stdin", zzline); +fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text); +if ( !etok && !eset ) {fprintf(stderr, "\n"); return;} +if ( k==1 ) fprintf(stderr, " missing"); +else +{ +fprintf(stderr, "; \"%s\" not", bad_text); +if ( zzset_deg(eset)>1 ) fprintf(stderr, " in"); +} +if ( zzset_deg(eset)>0 ) zzedecode(eset); +else fprintf(stderr, " %s", zztokens[etok]); +if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup); +fprintf(stderr, "\n"); +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_p.g b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_p.g new file mode 100644 index 00000000..10154fb5 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg_p.g @@ -0,0 +1,616 @@ +/* This is the parser for the dlg + * This is a part of the Purdue Compiler Construction Tool Set + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * DLG 1.33 + * Will Cohen + * With mods by Terence Parr; AHPCRC, University of Minnesota + * 1989-1995 + */ + +#header << +#include +#include "dlg.h" +>> + +<< + +/* MR20 G. Hobbelt + Fix for Borland C++ 4.x & 5.x compiling with ALL warnings enabled +*/ + +#ifdef __TURBOC__ +#pragma warn -aus /* unused assignment of 'xxx' */ +#endif + +#pragma clang diagnostic ignored "-Wparentheses-equality" + +int action_no = 0; /* keep track of actions outputted */ +int nfa_allocated = 0; /* keeps track of number of nfa nodes */ +nfa_node **nfa_array = NULL;/* root of binary tree that stores nfa array */ +nfa_node nfa_model_node; /* model to initialize new nodes */ +set used_chars; /* used to label trans. arcs */ +set used_classes; /* classes or chars used to label trans. arcs */ +set normal_chars; /* mask to get rid elements that aren't used + in set */ +int flag_paren = FALSE; +int flag_brace = FALSE; +int mode_counter = 0; /* keep track of number of %%names */ + +>> + +#lexaction << +int func_action; /* should actions be turned into functions?*/ +int lex_mode_counter = 0; /* keeps track of the number of %%names */ +/* MR1 */ +/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ +/* MR1 via <<%%lexmember...>> */ +/* MR1 */ +int lexMember = 0; /* <<%%lexmemeber ...>> MR1 */ +int lexAction = 0; /* <<%%lexaction ...>> MR1 */ +int parserClass = 0; /* <<%%parserclass ...>> MR1 */ +int lexPrefix = 0; /* <<%%lexprefix ...>> MR1 */ +char theClassName[100]; /* MR11 */ +char *pClassName=theClassName; /* MR11 */ +int firstLexMember=1; /* MR1 */ + +#ifdef __USE_PROTOS +void xxputc(int c) { /* MR1 */ +#else +void xxputc(c) /* MR1 */ + int c; /* MR1 */ +{ /* MR1 */ +#endif + if (parserClass) { /* MR1 */ + *pClassName++=c; /* MR1 */ + *pClassName=0; /* MR1 */ + } else if (lexMember || lexPrefix) { /* MR1 */ + if (class_stream != NULL) fputc(c,class_stream); /* MR1 */ + } else { /* MR1 */ + fputc(c,OUT); /* MR1 */ + }; /* MR1 */ +} /* MR1 */ + +#ifdef __USE_PROTOS +void xxprintf(char *format,char *string) { /* MR1 */ +#else +void xxprintf(format,string) /* MR1 */ + char *format; /* MR1 */ + char *string; /* MR1 */ +{ /* MR1 */ +#endif + if (lexMember || lexPrefix || parserClass) { /* MR1 */ + if (class_stream != NULL) /* MR1 */ + fprintf(class_stream,format,string); /* MR1 */ + } else { /* MR1 */ + fprintf(OUT,format,string); /* MR1 */ + }; /* MR1 */ +} /* MR1 */ +>> + +#token "[\r\t\ ]+" << zzskip(); >> /* Ignore white */ +#token "\n" << zzline++; zzskip(); DAWDLE; >> /* Track Line # */ +#token L_EOF "\@" +#token PER_PER "\%\%" +#token NAME_PER_PER "\%\%[a-zA-Z_][a-zA-Z0-9_]*" + << p_mode_def(&zzlextext[2],lex_mode_counter++); >> + +#token LEXMEMBER "\<\<\%\%lexmember" /* MR1 */ + <> /* MR1 */ +#token LEXACTION "\<\<\%\%lexaction" /* MR1 */ + <> /* MR1 */ +#token PARSERCLASS "\<\<\%\%parserclass" /* MR1 */ + <> /* MR1 */ +#token LEXPREFIX "\<\<\%\%lexprefix" /* MR1 */ + <> /* MR1 */ + +#token ACTION "\<\<" + << if (func_action) + fprintf(OUT,"\n%s %sact%d()\n{ ", + gen_cpp?"ANTLRTokenType":"static void", + gen_cpp?ClassName("::"):"", ++action_no); + zzmode(ACT); zzskip(); + >> +#token GREAT_GREAT "\>\>" +#token L_BRACE "\{" +#token R_BRACE "\}" +#token L_PAR "\(" +#token R_PAR "\)" +#token L_BRACK "\[" +#token R_BRACK "\]" +#token ZERO_MORE "\*" +#token ONE_MORE "\+" +#token OR "\|" +#token RANGE "\-" +#token NOT "\~" +#token OCTAL_VALUE "\\0[0-7]*" + << {int t; sscanf(&zzlextext[1],"%o",&t); zzlextext[0] = t;}>> +#token HEX_VALUE "\\0[Xx][0-9a-fA-F]+" + << {int t; sscanf(&zzlextext[3],"%x",&t); zzlextext[0] = t;}>> +#token DEC_VALUE "\\[1-9][0-9]*" + << {int t; sscanf(&zzlextext[1],"%d",&t); zzlextext[0] = t;}>> +#token TAB "\\t" << zzlextext[0] = '\t';>> +#token NL "\\n" << zzlextext[0] = '\n';>> +#token CR "\\r" << zzlextext[0] = '\r';>> +#token BS "\\b" << zzlextext[0] = '\b';>> + +/* MR1 */ +/* MR1 10-Apr-97 MR1 Allow #token regular expressions to cross lines */ +/* MR1 */ +#token CONTINUATION "\\ \n" << zzline++; zzskip();>> /* MR1 */ + +/* NOTE: this takes ANYTHING after the \ */ +#token LIT "\\~[tnrb]" << zzlextext[0] = zzlextext[1];>> + +/* NOTE: this takes ANYTHING that doesn't match the other tokens */ +#token REGCHAR "~[\\]" + + +grammar : << p_head(); p_class_hdr(); func_action = FALSE;>> + ( {LEXACTION | LEXMEMBER | LEXPREFIX | PARSERCLASS } ACTION)* /* MR1 */ + <> + start_states + << func_action = FALSE; p_tables(); p_tail(); >> + (ACTION)* "@" + << if (firstLexMember != 0) p_class_def1(); >> /* MR1 */ + ; + +start_states : ( PER_PER do_conversion + | NAME_PER_PER do_conversion (NAME_PER_PER do_conversion)*) + PER_PER + ; + +do_conversion : <> + rule_list + << + dfa_class_nop[mode_counter] = + relabel($1.l,comp_level); + if (comp_level) + p_shift_table(mode_counter); + dfa_basep[mode_counter] = dfa_allocated+1; + make_dfa_model_node(dfa_class_nop[mode_counter]); + nfa_to_dfa($1.l); + ++mode_counter; + func_action = FALSE; +#ifdef HASH_STAT + fprint_hash_stats(stderr); +#endif + >> + ; + +rule_list : rule <<$$.l=$1.l; $$.r=$1.r;>> + (rule + <<{nfa_node *t1; + t1 = new_nfa_node(); + (t1)->trans[0]=$$.l; + (t1)->trans[1]=$1.l; + /* all accept nodes "dead ends" */ + $$.l=t1; $$.r=NULL; + } + >> + )* + | /* empty */ + <<$$.l = new_nfa_node(); $$.r = NULL; + warning("no regular expressions", zzline); + >> + ; + +rule : reg_expr ACTION +/* MR23 */ << if ($1.r != NULL) { + $$.l=$1.l; $$.r=$1.r; ($1.r)->accept=action_no; + } + >> + | ACTION + <<$$.l = NULL; $$.r = NULL; + error("no expression for action ", zzline); + >> + ; + +reg_expr : and_expr <<$$.l=$1.l; $$.r=$1.r;>> + (OR and_expr + <<{nfa_node *t1, *t2; + t1 = new_nfa_node(); t2 = new_nfa_node(); + (t1)->trans[0]=$$.l; + (t1)->trans[1]=$2.l; +/* MR23 */ if ($$.r != NULL) ($$.r)->trans[1]=t2; + if ($2.r) { + ($2.r)->trans[1]=t2; /* MR20 */ + } + $$.l=t1; $$.r=t2; + } + >> + )* + ; + +and_expr : repeat_expr + << + $$.l=$1.l; $$.r=$1.r; + >> + (repeat_expr +/* MR23 */ << if ($$.r != NULL) { + ($$.r)->trans[1]=$1.l; + $$.r=$1.r; + } + >> + )* + ; + +repeat_expr : expr <<$$.l=$1.l; $$.r=$1.r;>> + { ZERO_MORE + <<{ nfa_node *t1,*t2; +/* MR23 */ if ($$.r != NULL) ($$.r)->trans[0] = $$.l; + t1 = new_nfa_node(); t2 = new_nfa_node(); + t1->trans[0]=$$.l; + t1->trans[1]=t2; +/* MR23 */ if ($$.r != NULL) ($$.r)->trans[1]=t2; + $$.l=t1;$$.r=t2; + } + >> + | ONE_MORE +/* MR23 */ <trans[0] = $$.l;>> + } + | ZERO_MORE + << error("no expression for *", zzline);>> + | ONE_MORE + << error("no expression for +", zzline);>> + ; + +expr : << $$.l = new_nfa_node(); + $$.r = new_nfa_node(); + >> + L_BRACK atom_list R_BRACK + << +/* MR23 */ if ($$.l != NULL) { + ($$.l)->trans[0] = $$.r; + ($$.l)->label = set_dup($2.label); + set_orin(&used_chars,($$.l)->label); + } + >> + | NOT L_BRACK atom_list R_BRACK + << +/* MR23 */ if ($$.l != NULL) { + ($$.l)->trans[0] = $$.r; + ($$.l)->label = set_dif(normal_chars,$3.label); + set_orin(&used_chars,($$.l)->label); + } + >> + | L_PAR reg_expr R_PAR + << +/* MR23 */ if ($$.l != NULL) { + ($$.l)->trans[0] = $2.l; + if ($2.r) { + ($2.r)->trans[1] = $$.r; /* MR20 */ + } + } + >> + | L_BRACE reg_expr R_BRACE + << +/* MR23 */ if ($$.l != NULL) { + ($$.l)->trans[0] = $2.l; + ($$.l)->trans[1] = $$.r; + if ($2.r) { + ($2.r)->trans[1] = $$.r; /* MR20 */ + } + } + >> + | atom + << +/* MR23 */ if ($$.l != NULL) { + ($$.l)->trans[0] = $$.r; + ($$.l)->label = set_dup($1.label); + set_orin(&used_chars,($$.l)->label); + } + >> + ; + +atom_list : << set_free($$.label); >> + (near_atom <>)* + ; + +near_atom : << register int i; + register int i_prime; + >> + anychar + <<$$.letter=$1.letter; $$.label=set_of($1.letter); + i_prime = $1.letter + MIN_CHAR; + if (case_insensitive && islower(i_prime)) + set_orel(toupper(i_prime)-MIN_CHAR, + &($$.label)); + if (case_insensitive && isupper(i_prime)) + set_orel(tolower(i_prime)-MIN_CHAR, + &($$.label)); + >> + { RANGE anychar + << if (case_insensitive){ + i_prime = $$.letter+MIN_CHAR; + $$.letter = (islower(i_prime) ? + toupper(i_prime) : i_prime)-MIN_CHAR; + i_prime = $2.letter+MIN_CHAR; + $2.letter = (islower(i_prime) ? + toupper(i_prime) : i_prime)-MIN_CHAR; + } + /* check to see if range okay */ + { + int debugLetter1 = $$.letter; + int debugLetter2 = $2.letter; + } + if ($$.letter > $2.letter + && $2.letter != 0xff){ /* MR16 */ + error("invalid range ", zzline); + } + for (i=$$.letter; i<= (int)$2.letter; ++i){ + set_orel(i,&($$.label)); + i_prime = i+MIN_CHAR; + if (case_insensitive && islower(i_prime)) + set_orel(toupper(i_prime)-MIN_CHAR, + &($$.label)); + if (case_insensitive && isupper(i_prime)) + set_orel(tolower(i_prime)-MIN_CHAR, + &($$.label)); + } + >> + } + ; + +atom : << register int i_prime;>> + anychar + <<$$.label = set_of($1.letter); + i_prime = $1.letter + MIN_CHAR; + if (case_insensitive && islower(i_prime)) + set_orel(toupper(i_prime)-MIN_CHAR, + &($$.label)); + if (case_insensitive && isupper(i_prime)) + set_orel(tolower(i_prime)-MIN_CHAR, + &($$.label)); + >> + ; + +anychar : REGCHAR <<$$.letter = $1.letter - MIN_CHAR;>> + | OCTAL_VALUE <<$$.letter = $1.letter - MIN_CHAR;>> + | HEX_VALUE <<$$.letter = $1.letter - MIN_CHAR;>> + | DEC_VALUE <<$$.letter = $1.letter - MIN_CHAR;>> + | TAB <<$$.letter = $1.letter - MIN_CHAR;>> + | NL <<$$.letter = $1.letter - MIN_CHAR;>> + | CR <<$$.letter = $1.letter - MIN_CHAR;>> + | BS <<$$.letter = $1.letter - MIN_CHAR;>> + | LIT <<$$.letter = $1.letter - MIN_CHAR;>> + /* NOTE: LEX_EOF is ALWAYS shifted to 0 = MIN_CHAR - MIN_CHAR*/ + | L_EOF <<$$.letter = 0;>> + ; + +<> + +#lexclass ACT +#token "@" << error("unterminated action", zzline); zzmode(START); >> +#token ACTION "\>\>" + << if (func_action) fprintf(OUT,"}\n\n"); + zzmode(START); +/* MR1 */ +/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ +/* MR1 via <<%%lexmember ...>> */ +/* MR1 This is a consequence of not saving actions */ +/* MR1 */ +/* MR1 */ parserClass=0; +/* MR1 */ lexPrefix=0; +/* MR1 */ lexAction=0; +/* MR1 */ lexMember=0; + >> +#token "\>" << xxputc(zzlextext[0]); zzskip(); >> /* MR1 */ +#token "\\\>" << xxputc('>'); zzskip(); >> /* MR1 */ +#token "\\" << xxputc('\\'); zzskip(); >> /* MR1 */ +#token "\n" << xxputc(zzlextext[0]); ++zzline; zzskip(); >> /* MR1 */ +#token "/\*" << zzmode(ACTION_COMMENTS); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + >> /* MR1 */ +#token "//" << zzmode(ACTION_CPP_COMMENTS); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + >> /* MR1 */ +#token "~[]" << xxputc(zzlextext[0]); zzskip(); >> /* MR1 */ + /* MR1 */ +#lexclass ACTION_COMMENTS /* MR1 */ +#token "\*/" << zzmode(ACT); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + >> /* MR1 */ +#token "[\n\r]" << zzline++; xxputc(zzlextext[0]); zzskip();>> /* MR1 */ +#token "~[]" << xxputc(zzlextext[0]); zzskip();>> /* MR1 */ + /* MR1 */ +#lexclass ACTION_CPP_COMMENTS /* MR1 */ +#token "[\n\r]" << zzmode(ACT); zzline++; /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + >> /* MR1 */ +#token "~[]" << xxputc(zzlextext[0]); zzskip();>> /* MR1 */ + +<< +/* adds a new nfa to the binary tree and returns a pointer to it */ +nfa_node * +#ifdef __USE_PROTOS +new_nfa_node(void) +#else +new_nfa_node() +#endif +{ + register nfa_node *t; + static int nfa_size=0; /* elements nfa_array[] can hold */ + + ++nfa_allocated; + if (nfa_size<=nfa_allocated){ + /* need to redo array */ + if (!nfa_array){ + /* need some to do initial allocation */ + nfa_size=nfa_allocated+NFA_MIN; + nfa_array=(nfa_node **) malloc(sizeof(nfa_node*)* + nfa_size); + }else{ + /* need more space */ + nfa_size=2*(nfa_allocated+1); + nfa_array=(nfa_node **) realloc(nfa_array, + sizeof(nfa_node*)*nfa_size); + } + } + /* fill out entry in array */ + t = (nfa_node*) malloc(sizeof(nfa_node)); + nfa_array[nfa_allocated] = t; + *t = nfa_model_node; + t->node_no = nfa_allocated; + return t; +} + + +/* initialize the model node used to fill in newly made nfa_nodes */ +void +#ifdef __USE_PROTOS +make_nfa_model_node(void) +#else +make_nfa_model_node() +#endif +{ + nfa_model_node.node_no = -1; /* impossible value for real nfa node */ + nfa_model_node.nfa_set = 0; + nfa_model_node.accept = 0; /* error state default*/ + nfa_model_node.trans[0] = NULL; + nfa_model_node.trans[1] = NULL; + nfa_model_node.label = empty; +} +>> + +<< +#if defined(DEBUG) || defined(_DEBUG) + +/* print out the pointer value and the node_number */ +void +#ifdef __USE_PROTOS +fprint_dfa_pair(FILE *f, nfa_node *p) +#else +fprint_dfa_pair(f, p) +FILE *f; +nfa_node *p; +#endif +{ + if (p){ + fprintf(f, "%x (%d)", p, p->node_no); + }else{ + fprintf(f, "(nil)"); + } +} + +/* print out interest information on a set */ +void +#ifdef __USE_PROTOS +fprint_set(FILE *f, set s) +#else +fprint_set(f,s) +FILE *f; +set s; +#endif +{ + unsigned int *x; + + fprintf(f, "n = %d,", s.n); + if (s.setword){ + fprintf(f, "setword = %x, ", s.setword); + /* print out all the elements in the set */ + x = set_pdq(s); + while (*x!=nil){ + fprintf(f, "%d ", *x); + ++x; + } + }else{ + fprintf(f, "setword = (nil)"); + } +} + +/* code to be able to dump out the nfas + return 0 if okay dump + return 1 if screwed up + */ +int +#ifdef __USE_PROTOS +dump_nfas(int first_node, int last_node) +#else +dump_nfas(first_node, last_node) +int first_node; +int last_node; +#endif +{ + register int i; + nfa_node *t; + + for (i=first_node; i<=last_node; ++i){ + t = NFA(i); + if (!t) break; + fprintf(stderr, "nfa_node %d {\n", t->node_no); + fprintf(stderr, "\n\tnfa_set = %d\n", t->nfa_set); + fprintf(stderr, "\taccept\t=\t%d\n", t->accept); + fprintf(stderr, "\ttrans\t=\t("); + fprint_dfa_pair(stderr, t->trans[0]); + fprintf(stderr, ","); + fprint_dfa_pair(stderr, t->trans[1]); + fprintf(stderr, ")\n"); + fprintf(stderr, "\tlabel\t=\t{ "); + fprint_set(stderr, t->label); + fprintf(stderr, "\t}\n"); + fprintf(stderr, "}\n\n"); + } + return 0; +} +#endif +>> + +<< +/* DLG-specific syntax error message generator + * (define USER_ZZSYN when compiling so don't get 2 definitions) + */ +void +#ifdef __USE_PROTOS +zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, int k, char *bad_text) +#else +zzsyn(text, tok, egroup, eset, etok, k, bad_text) +char *text, *egroup, *bad_text; +int tok; +int etok; +int k; +SetWordType *eset; +#endif +{ + fprintf(stderr, ErrHdr, file_str[0]!=NULL?file_str[0]:"stdin", zzline); + fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text); + if ( !etok && !eset ) {fprintf(stderr, "\n"); return;} + if ( k==1 ) fprintf(stderr, " missing"); + else + { + fprintf(stderr, "; \"%s\" not", bad_text); + if ( zzset_deg(eset)>1 ) fprintf(stderr, " in"); + } + if ( zzset_deg(eset)>0 ) zzedecode(eset); + else fprintf(stderr, " %s", zztokens[etok]); + if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup); + fprintf(stderr, "\n"); +} +>> diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/err.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/err.c new file mode 100644 index 00000000..896c4477 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/err.c @@ -0,0 +1,99 @@ +/* + * A n t l r S e t s / E r r o r F i l e H e a d e r + * + * Generated from: dlg_p.g + * + * Terence Parr, Russell Quong, Will Cohen, and Hank Dietz: 1989-2001 + * Parr Research Corporation + * with Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + */ + +#define ANTLR_VERSION 13333 +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include +#include "dlg.h" +#define zzSET_SIZE 8 +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +#include "err.h" + +ANTLRChar *zztokens[46]={ + /* 00 */ "Invalid", + /* 01 */ "@", + /* 02 */ "[\\r\\t\\ ]+", + /* 03 */ "\\n", + /* 04 */ "L_EOF", + /* 05 */ "PER_PER", + /* 06 */ "NAME_PER_PER", + /* 07 */ "LEXMEMBER", + /* 08 */ "LEXACTION", + /* 09 */ "PARSERCLASS", + /* 10 */ "LEXPREFIX", + /* 11 */ "ACTION", + /* 12 */ "GREAT_GREAT", + /* 13 */ "L_BRACE", + /* 14 */ "R_BRACE", + /* 15 */ "L_PAR", + /* 16 */ "R_PAR", + /* 17 */ "L_BRACK", + /* 18 */ "R_BRACK", + /* 19 */ "ZERO_MORE", + /* 20 */ "ONE_MORE", + /* 21 */ "OR", + /* 22 */ "RANGE", + /* 23 */ "NOT", + /* 24 */ "OCTAL_VALUE", + /* 25 */ "HEX_VALUE", + /* 26 */ "DEC_VALUE", + /* 27 */ "TAB", + /* 28 */ "NL", + /* 29 */ "CR", + /* 30 */ "BS", + /* 31 */ "CONTINUATION", + /* 32 */ "LIT", + /* 33 */ "REGCHAR", + /* 34 */ "\\>", + /* 35 */ "\\\\>", + /* 36 */ "\\", + /* 37 */ "\\n", + /* 38 */ "/\\*", + /* 39 */ "//", + /* 40 */ "~[]", + /* 41 */ "\\*/", + /* 42 */ "[\\n\\r]", + /* 43 */ "~[]", + /* 44 */ "[\\n\\r]", + /* 45 */ "~[]" +}; +SetWordType zzerr1[8] = {0x80,0xf,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr2[8] = {0x60,0x0,0x0,0x0, 0x0,0x0,0x0,0x0}; +SetWordType zzerr3[8] = {0x70,0xa8,0x9a,0x7f, 0x3,0x0,0x0,0x0}; +SetWordType setwd1[46] = {0x0,0x6,0x0,0x0,0x30,0xc8,0xc8, + 0x1,0x1,0x1,0x1,0x35,0x0,0x30,0x0, + 0x30,0x0,0x30,0x0,0x30,0x30,0x0,0x0, + 0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30, + 0x0,0x30,0x30,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr4[8] = {0x10,0xa8,0x9a,0x7f, 0x3,0x0,0x0,0x0}; +SetWordType zzerr5[8] = {0x10,0xe8,0xbb,0x7f, 0x3,0x0,0x0,0x0}; +SetWordType zzerr6[8] = {0x10,0xa0,0x9a,0x7f, 0x3,0x0,0x0,0x0}; +SetWordType setwd2[46] = {0x0,0x0,0x0,0x0,0xeb,0x2,0x2, + 0x0,0x0,0x0,0x0,0xd6,0x0,0xeb,0xd4, + 0xeb,0xd4,0xeb,0x0,0xcb,0xcb,0xd0,0x0, + 0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb,0xeb, + 0x0,0xeb,0xeb,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0}; +SetWordType zzerr7[8] = {0x10,0xa0,0x82,0x7f, 0x3,0x0,0x0,0x0}; +SetWordType zzerr8[8] = {0x10,0x0,0x44,0x7f, 0x3,0x0,0x0,0x0}; +SetWordType zzerr9[8] = {0x10,0x0,0x0,0x7f, 0x3,0x0,0x0,0x0}; +SetWordType setwd3[46] = {0x0,0x0,0x0,0x0,0xf7,0x0,0x0, + 0x0,0x0,0x0,0x0,0xc2,0x0,0xc2,0xc2, + 0xc2,0xc2,0xc2,0xb8,0xc2,0xc2,0xc2,0x80, + 0xc2,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7,0xf7, + 0x0,0xf7,0xf7,0x0,0x0,0x0,0x0,0x0, + 0x0,0x0,0x0,0x0,0x0,0x0,0x0}; diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/main.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/main.c new file mode 100644 index 00000000..20d0bffe --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/main.c @@ -0,0 +1,281 @@ +/* Main function for dlg version + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * DLG 1.33 + * Will Cohen + * With mods by Terence Parr; AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include "stdpccts.h" + +char program[] = "dlg"; +char version[] = "1.33MR33"; /* MRXXX */ +int numfiles = 0; +char *file_str[2] = {NULL, NULL}; +char *mode_file = "mode.h"; +char *class_name = DEFAULT_CLASSNAME; +char *OutputDirectory = TopDirectory; + +/* Option variables */ +int comp_level = 0; +int interactive = FALSE; +int case_insensitive = FALSE; +int warn_ambig = FALSE; +int gen_cpp = FALSE; + +#ifdef __USE_PROTOS +static int ci_strequ(char *a,char *b) +#else +static int ci_strequ(a,b) + char *a; + char *b; +#endif +{ + for ( ;*a != 0 && *b != 0; a++, b++) { + if (toupper(*a) != toupper(*b)) return 0; + } + return (*a == *b); +} + +/* Option List Stuff */ +#ifdef __USE_PROTOS +void p_comp0(void) {comp_level = 0;} +void p_comp1(void) {comp_level = 1;} +void p_comp2(void) {comp_level = 2;} +void p_stdio(void) { file_str[numfiles++] = NULL;} +void p_file(char *s) { file_str[numfiles++] = s;} +void p_cl_name(char *s, char *t) + { + if ( gen_cpp ) { + class_name = t; + } + else { + warning("-cl only valid in C++ mode; -cl ignored...",0); + } + } +void p_mode_file(char *s, char *t){mode_file=t;} +void p_outdir(char *s,char *t) {OutputDirectory=t;} +void p_ansi(void) {gen_ansi = TRUE;} +void p_interactive(void) {interactive = TRUE;} +void p_case_s(void) { case_insensitive = FALSE; } +void p_case_i(void) { case_insensitive = TRUE; } +void p_warn_ambig(void) { warn_ambig = TRUE; } +void p_cpp(void) { gen_cpp = TRUE; } +#else +void p_comp0() {comp_level = 0;} +void p_comp1() {comp_level = 1;} +void p_comp2() {comp_level = 2;} +void p_stdio() { file_str[numfiles++] = NULL;} +void p_file(s) char *s; { file_str[numfiles++] = s;} +void p_cl_name(s,t) + char *s, *t; + { + if ( gen_cpp ) { + class_name = t; + } + else { + warning("-cl only valid in C++ mode; -cl ignored...",0); + } + } +void p_mode_file(s,t) char *s,*t;{mode_file=t;} +void p_outdir(s,t) char *s,*t;{OutputDirectory=t;} +void p_ansi() {gen_ansi = TRUE;} +void p_interactive() {interactive = TRUE;} +void p_case_s() { case_insensitive = FALSE; } +void p_case_i() { case_insensitive = TRUE; } +void p_warn_ambig() { warn_ambig = TRUE; } +void p_cpp() { gen_cpp = TRUE; } +#endif + +#ifdef __cplusplus +typedef void (*WildFunc)(...); +#else +typedef void (*WildFunc)(); +#endif + +typedef struct { + char *option; + int arg; + WildFunc process; + char *descr; + } Opt; + +Opt options[] = { + { "-CC", 0, (WildFunc)p_cpp, "Generate C++ output" }, + { "-C0", 0, (WildFunc)p_comp0, "No compression (default)" }, + { "-C1", 0, (WildFunc)p_comp1, "Compression level 1" }, + { "-C2", 0, (WildFunc)p_comp2, "Compression level 2" }, + { "-ga", 0, (WildFunc)p_ansi, "Generate ansi C"}, + { "-Wambiguity", 0, (WildFunc)p_warn_ambig, "Warn if expressions ambiguous"}, + { "-m", 1, (WildFunc)p_mode_file, "Rename lexical mode output file"}, + { "-i", 0, (WildFunc)p_interactive, "Build interactive scanner (not valid for C++ mode)"}, + { "-ci", 0, (WildFunc)p_case_i, "Make lexical analyzer case insensitive"}, + { "-cl", 1, (WildFunc)p_cl_name, "Rename lexer class (DLGLexer); only used for -CC"}, + { "-cs", 0, (WildFunc)p_case_s, "Make lexical analyzer case sensitive (default)"}, + { "-o", 1, (WildFunc)p_outdir, OutputDirectoryOption}, + { "-", 0, (WildFunc)p_stdio, "Use standard i/o rather than file"}, + { "*", 0, (WildFunc)p_file, ""}, /* anything else is a file */ + { NULL, 0, NULL } + }; + +#ifdef __USE_PROTOS +void ProcessArgs(int argc, char **argv, Opt *options) +#else +void ProcessArgs(argc, argv, options) +int argc; +char **argv; +Opt *options; +#endif +{ + Opt *p; + + while ( argc-- > 0 ) + { + p = options; + while ( p->option != NULL ) + { + if ( strcmp(p->option, "*") == 0 || + ci_strequ(p->option,*argv) ) + { + if ( p->arg ) + { + (*p->process)( *argv, *(argv+1) ); + argv++; + argc--; + } + else + (*p->process)( *argv ); + break; + } + p++; + } + argv++; + } +} + +#ifdef __USE_PROTOS +int main(int argc, char *argv[]) +#else +int main(argc, argv) +int argc; +char *argv[]; +#endif +{ + init(); + fprintf(stderr, "%s Version %s 1989-2001\n", &(program[0]), + &(version[0])); + if ( argc == 1 ) + { + Opt *p = options; + fprintf(stderr, "%s [options] f1 f2 ... fn\n",argv[0]); + while ( *(p->option) != '*' ) + { + fprintf(stderr, "\t%s %s\t%s\n", + p->option, + (p->arg)?"___":" ", + p->descr); + p++; + } + }else{ + ProcessArgs(argc-1, &(argv[1]), options); + if (interactive && gen_cpp) { + fprintf(stderr,"\n"); +/*** MR21a This statement is wrong ! ***/ +#if 0 +*** fprintf(stderr,"Interactive lexer option (\"-i\") has no effect when in C++ mode\n"); +*** fprintf(stderr,"because of extra buffering provided by ANTLRTokenBuffer class.\n"); +*** fprintf(stderr,"\n"); +#endif + } + input_stream = read_stream(file_str[0]); + if (input_stream) { + /* don't overwrite unless input okay */ + if ( gen_cpp ) { + output_stream = write_stream(ClassName(CPP_FILE_SUFFIX)); + if ( file_str[1]!=NULL ) { + warning("output file implicit in C++ mode; ignored...",0); + } + class_stream = write_stream(ClassName(".h")); + mode_stream = class_stream; + } + else { + output_stream = write_stream(file_str[1]); + mode_stream = write_stream(mode_file); + } + } + /* make sure that error reporting routines in grammar + know what the file really is */ + /* make sure that reading and writing somewhere */ + if (input_stream && output_stream && mode_stream){ + ANTLR(grammar(), input_stream); + } + p_class_def2(); /* MR1 */ + } + if ( output_stream!=NULL ) fclose(output_stream); + if ( !gen_cpp && mode_stream!=NULL ) fclose(mode_stream); + if ( class_stream!=NULL ) fclose(class_stream); + exit(PCCTS_EXIT_SUCCESS); + return 0; /* get rid of warning message MR1 */ +} + +/* initialize all the variables */ +void +#ifdef __USE_PROTOS +init(void) +#else +init() +#endif +{ + register int i; + +#ifdef SPECIAL_INITS + special_inits(); /* MR1 */ +#endif + used_chars = empty; + used_classes = empty; + /* make the valid character set */ + normal_chars = empty; + /* NOTE: MIN_CHAR is EOF */ + /* NOTE: EOF is not quite a valid char, it is special. Skip it*/ + for (i = 1; i +#include +#include "dlg.h" +#ifdef MEMCHK +#include "trax.h" +#else +#ifdef __STDC__ +#include +#else +#include +#endif /* __STDC__ */ +#endif + +#ifdef VBOX +void p_set(set label); +void s_p_nfa(nfa_node *p); +#endif /* VBOX */ + +static char *mode_name[MAX_MODES]; +static int mode_number[MAX_MODES]; +static int cur_mode=0; + +int operation_no = 0; /* used to mark nodes so that infinite loops avoided */ +int dfa_basep[MAX_MODES]; /* start of each group of states */ +int dfa_class_nop[MAX_MODES]; /* number of elements in each group of states*/ + +int gen_ansi = FALSE; /* allows ansi code to be generated */ + +FILE *input_stream; /* where to read description from */ +FILE *output_stream; /* where to put the output */ +FILE *mode_stream; /* where to put the mode.h stuff */ +FILE *class_stream; /* where to put the scan.h stuff (if gen_cpp) */ + +/* NOTE: This section is MACHINE DEPENDENT */ +#define DIF_SIZE 4 +#if defined(PC) && !defined(PC32) +unsigned long typesize[DIF_SIZE] = { 0x7f, 0x7fff, 0x7ffful, 0x7ffffffful }; /* MR20 */ +char t0[] = "unsigned char"; +char t1[] = "unsigned short"; +char t2[] = "unsigned int"; +char t3[] = "unsigned long"; +char *typevar[DIF_SIZE] = { t0, t1, t2, t3}; +#else +unsigned long typesize[DIF_SIZE] = { 0x7f, 0x7fff, 0x7ffffffful, 0x7ffffffful }; /* MR20 */ +char t0[] = "unsigned char"; +char t1[] = "unsigned short"; +char t2[] = "unsigned int"; +char t3[] = "unsigned long"; +char *typevar[DIF_SIZE] = { t0, t1, t2, t3}; +#endif + +/* Added by TJP August 1994 */ +/* Take in MyLexer and return MyLexer_h */ + +static char * +#ifdef __USE_PROTOS +gate_symbol(char *name) +#else +gate_symbol(name) +char *name; +#endif +{ + static char buf[100]; + sprintf(buf, "%s_h", name); + return buf; +} + +/* Added by TJP August 1994 */ +static char * +#ifdef __USE_PROTOS +mystrdup(char *s) +#else +mystrdup(s) +char *s; +#endif +{ + char *p = (char *)malloc(strlen(s)+1); + strcpy(p, s); + return p; +} + +#ifdef __USE_PROTOS +void p_class_hdr(void) +#else +void p_class_hdr() +#endif +{ + if ( class_stream == NULL ) return; + fprintf(class_stream, "#ifndef %s\n", gate_symbol(ClassName(""))); + fprintf(class_stream, "#define %s\n", gate_symbol(ClassName(""))); + fprintf(class_stream, "/*\n"); + fprintf(class_stream, " * D L G L e x e r C l a s s D e f i n i t i o n\n"); + fprintf(class_stream, " *\n"); + fprintf(class_stream, " * Generated from:"); + fprintf(class_stream, " %s", file_str[0]); + fprintf(class_stream, "\n"); + fprintf(class_stream, " *\n"); + fprintf(class_stream, " * 1989-2001 by Will Cohen, Terence Parr, and Hank Dietz\n"); + fprintf(class_stream, " * Purdue University Electrical Engineering\n"); + fprintf(class_stream, " * DLG Version %s\n", version); + fprintf(class_stream, " */\n\n"); + fprintf(class_stream, "\n"); + fprintf(class_stream, "#include \"%s\"\n", DLEXERBASE_H); +} + +/* MR1 */ +/* MR1 16-Apr-97 Split printing of class header up into several parts */ +/* MR1 so that #lexprefix <<...>>and #lexmember <<...>> */ +/* MR1 can be inserted in the appropriate spots */ +/* MR1 */ + +#ifdef __USE_PROTOS +void p_class_def1(void) +#else +void p_class_def1() +#endif +{ + if ( class_stream == NULL ) return; + fprintf(class_stream, "\nclass %s : public DLGLexerBase {\n", ClassName("")); + fprintf(class_stream, "public:\n"); +} + +#ifdef __USE_PROTOS +void p_class_def2(void) +#else +void p_class_def2() +#endif +{ + int i, m; + if ( class_stream == NULL ) return; + fprintf(class_stream, "public:\n"); + fprintf(class_stream, "\tstatic const int MAX_MODE;\n"); + fprintf(class_stream, "\tstatic const int DfaStates;\n"); + for (i=0; i> */ +/* MR1 */ +/* MR1 */ fprintf(class_stream,"//\n"); +/* MR1 */ fprintf(class_stream, +/* MR1 */ "// 133MR1 Deprecated feature to allow inclusion of "); +/* MR1 */ fprintf(class_stream, +/* MR1 */ "user-defined code in DLG class header\n"); +/* MR1 */ fprintf(class_stream,"//\n"); +/* MR1 */ +/* MR1 */ fprintf(class_stream,"#ifdef DLGLexerIncludeFile\n"); +/* MR1 */ fprintf(class_stream,"#include DLGLexerIncludeFile\n"); +/* MR1 */ fprintf(class_stream,"#endif\n"); + + fprintf(class_stream, "};\n"); + + fprintf(class_stream, "typedef ANTLRTokenType (%s::*Ptr%sMemberFunc)();\n", + ClassName(""), ClassName("")); + + fprintf(class_stream, "#endif\n"); +} + +/* generate required header on output */ + +#ifdef __USE_PROTOS +void p_head(void) +#else +void p_head() +#endif +{ + fprintf(OUT, "/*\n"); + fprintf(OUT, " * D L G tables\n"); + fprintf(OUT, " *\n"); + fprintf(OUT, " * Generated from:"); + fprintf(OUT, " %s", file_str[0]); + fprintf(OUT, "\n"); + fprintf(OUT, " *\n"); + fprintf(OUT, " * 1989-2001 by Will Cohen, Terence Parr, and Hank Dietz\n"); + fprintf(OUT, " * Purdue University Electrical Engineering\n"); + fprintf(OUT, " * DLG Version %s\n", version); + fprintf(OUT, " */\n\n"); + if ( gen_cpp) fprintf(OUT, "#include \"pcctscfg.h\"\n"); + if ( gen_cpp ) fprintf(OUT, "#include \"pccts_stdio.h\"\n"); + if ( !gen_cpp ) fprintf(OUT, "#include \"%s\"\n\n", mode_file); + fprintf(OUT,"\n"); +} + +#ifdef __USE_PROTOS +void p_includes(void) +#else +void p_includes() +#endif +{ + fprintf(OUT, "#include \"%s\"\n", APARSER_H); + fprintf(OUT, "#include \"%s\"\n", DLEXERBASE_H); + fprintf(OUT, "#include \"%s\"\n", ClassName(".h")); +} + +/* generate code to tie up any loose ends */ + +#ifdef __USE_PROTOS +void p_tail(void) /* MR1 */ +#else +void p_tail() /* MR1 */ +#endif +{ + if ( gen_cpp ) { + if ( strcmp(ClassName(""), DEFAULT_CLASSNAME)!=0 ) + fprintf(OUT, "#define DLGLexer %s\n", ClassName("")); + fprintf(OUT, "#include \"%s\"\n", DLEXER_H); /* MR23 Rename DLexer.cpp to DLexer.h */ + return; + } + fprintf(OUT, "\n"); + fprintf(OUT, "\n"); + if (comp_level) + fprintf(OUT, "#define ZZSHIFT(c) (b_class_no[zzauto][1+c])\n"); + else + fprintf(OUT, "#define ZZSHIFT(c) (1+c)\n"); + if ( !gen_cpp ) fprintf(OUT, "#define MAX_MODE %d\n",mode_counter); + fprintf(OUT, "#include \"dlgauto.h\"\n"); +} + + +/* output the table of DFA for general use */ + +#ifdef __USE_PROTOS +void p_tables() +#else +void p_tables() +#endif +{ + if ( !gen_cpp ) { + fprintf(OUT, "#define DfaStates\t%d\n", dfa_allocated); + fprintf(OUT, "typedef %s DfaState;\n\n", minsize(dfa_allocated)); + } + + if ( gen_cpp ) { + int i; + fprintf(OUT, "\n"); + fprintf(OUT, "const int %s::MAX_MODE=%d;\n", + ClassName(""), + mode_counter); + fprintf(OUT, "const int %s::DfaStates=%d;\n", + ClassName(""), + dfa_allocated); + for (i=0; i typesize[i]) /* MR20 */ + ++i; + return typevar[i]; +} + + +#ifdef __USE_PROTOS +void p_node_table(void) +#else +void p_node_table() +#endif +{ + register int i; + register int m = 0; + + for(m=0; m<(mode_counter-1); ++m){ + for(i=dfa_basep[m]; itrans[j]; + if (trans == NIL_INDEX) + trans = dfa_allocated+1; + /* all of DFA moved down one in array */ + fprintf(OUT, "%d", trans-1); + fprintf(OUT, ", "); + if (!(--items_on_line)){ + fprintf(OUT, "\n "); + items_on_line = MAX_ON_LINE; + } + } +#if 1 + /* put in jump to error state */ + fprintf(OUT, "%d\n};\n\n", dfa_allocated); +#else + fprintf(OUT, "\n};\n\n"); +#endif +} + + +#ifdef __USE_PROTOS +void p_dfa_table(void) +#else +void p_dfa_table() +#endif +{ + register int i; + + fprintf(OUT, "\n%sDfaState *%sdfa[%d] = {\n", + gen_cpp?ClassName("::"):"",gen_cpp?ClassName("::"):"", dfa_allocated); + for (i=0; i<(dfa_allocated-1); ++i){ + fprintf(OUT, "\tst%d,\n", i); + } + fprintf(OUT, "\tst%d\n", i); + fprintf(OUT, "};\n\n"); +} + + +#ifdef __USE_PROTOS +void p_accept_table(void) +#else +void p_accept_table() +#endif +{ + register int i = 1; + register int items_on_line = 0; + int true_interactive = TRUE; + + /* make sure element for one past (zzerraction) -WEC 12/16/92 */ + fprintf(OUT,"\n%sDfaState %saccepts[%d] = {\n ", + gen_cpp?ClassName("::"):"", + gen_cpp?ClassName("::"):"", + dfa_allocated+1); + /* don't do anything if no dfa nodes */ + if (i>dfa_allocated) goto skip_accepts; + for (;;) { + int accept=0; /* MR14a - Manuel Kessler (mlkessle@cip.physik.uni-wuerzburg.de) */ + set accept_set; + set nfa_states; + unsigned int *t, *nfa_i; + unsigned int *q, *regular_expr; + + accept_set = empty; + nfa_states = DFA(i)->nfa_states; + t = nfa_i = set_pdq(nfa_states); + /* NOTE: picks lowest accept because accepts monotonic */ + /* with respect to nfa node numbers and set_pdq */ + /* returns in that order */ + while((*nfa_i != nil) && (!(accept = NFA(*nfa_i)->accept))){ + nfa_i++; + } + + /* figure out if more than one accept state there */ + if (warn_ambig ){ + set_orel(accept, &accept_set); + while(*nfa_i != nil){ + set_orel(NFA(*nfa_i)->accept, &accept_set); + nfa_i++; + } + /* remove error action from consideration */ + set_rm(0, accept_set); + + if( set_deg(accept_set)>1){ + fprintf(stderr, "dlg warning: ambiguous regular expression "); + q = regular_expr = set_pdq(accept_set); + while(*regular_expr != nil){ + fprintf(stderr," %d ", *regular_expr); + ++regular_expr; + } + fprintf(stderr, "\n"); + free(q); + } + } + + if ((DFA(i)->alternatives) && (accept != 0)){ + true_interactive = FALSE; + } + fprintf(OUT, "%d, ", accept); + + /* free up memory before we "break" below -ATG 4/6/95 */ + free(t); + set_free(accept_set); + + if ((++i)>dfa_allocated) + break; + if ((++items_on_line)>=MAX_ON_LINE){ + fprintf(OUT,"\n "); + items_on_line = 0; + } +/* + free(t); + set_free(accept_set); +*/ + } + /* make sure element for one past (zzerraction) -WEC 12/16/92 */ +skip_accepts: + fprintf(OUT, "0\n};\n\n"); +} + + +#ifdef __USE_PROTOS +void p_action_table(void) +#else +void p_action_table() +#endif +{ + register int i; + char* theClassName = ClassName(""); + + if ( gen_cpp ) + fprintf(OUT, "Ptr%sMemberFunc %s::actions[%d] = {\n", theClassName, + theClassName, action_no+1); + else + fprintf(OUT, "void (*actions[%d])() = {\n", action_no+1); + if ( gen_cpp ) +/* fprintf(OUT, "\t(Ptr%sMemberFunc)&%s::erraction,\n", theClassName, theClassName);*/ + fprintf(OUT, "\t&%s::erraction,\n", theClassName); + else + fprintf(OUT, "\tzzerraction,\n"); + for (i=1; i=CHAR_RANGE) + break; + fprintf(OUT,", "); + if ((++items_on_line)>=MAX_ON_LINE){ + fprintf(OUT,"\n "); + items_on_line = 0; + } + } + fprintf(OUT, "\n};\n\n"); +} + + +#ifdef __USE_PROTOS +void p_base_table(void) +#else +void p_base_table() +#endif +{ + register int m; + + fprintf(OUT, "%sDfaState %sdfa_base[] = {\n", + gen_cpp?ClassName("::"):"static ", + gen_cpp?ClassName("::"):""); + for(m=0; m<(mode_counter-1); ++m) + fprintf(OUT, "\t%d,\n", dfa_basep[m]-1); + fprintf(OUT, "\t%d\n};\n\n", dfa_basep[m]-1); +} + + +#ifdef __USE_PROTOS +void p_class_table(void) /* MR1 */ +#else +void p_class_table() /* MR1 */ +#endif +{ +#if 0 + register int m; + + fprintf(OUT,"%s int %sdfa_class_no[] = {\n", + gen_cpp?"":"static", + gen_cpp?ClassName("::"):""); + for(m=0; m<(mode_counter-1); ++m) + fprintf(OUT,"\t%d,\n", dfa_class_nop[m]); + fprintf(OUT,"\t%d\n};\n\n", dfa_class_nop[m]); +#endif +} + + +#ifdef __USE_PROTOS +void p_bshift_table(void) /* MR1 */ +#else +void p_bshift_table() /* MR1 */ +#endif +{ + register int m; + + fprintf(OUT,"%s unsigned char *%sb_class_no[] = {\n", + gen_cpp?"":"static", + gen_cpp?ClassName("::"):""); + for(m=0; m<(mode_counter-1); ++m) + fprintf(OUT, "\tshift%d,\n", m); + fprintf(OUT, "\tshift%d\n};\n\n", m); +} + + +#ifdef __USE_PROTOS +void p_alternative_table(void) /* MR1 */ +#else +void p_alternative_table() /* MR1 */ +#endif +{ + register int i; + + if ( !gen_cpp ) fprintf(OUT, "#define ZZINTERACTIVE\n\n"); + if ( gen_cpp ) + fprintf(OUT, "DLGChar %salternatives[%d] = {\n", /* mr23 vhs %sDfaStates+1 */ + ClassName("::"), + dfa_allocated+1); /* vhs ClassName("::")); */ + else + fprintf(OUT, "static %s zzalternatives[DfaStates+1] = {\n", + minsize(dfa_allocated)); + + for(i=1; i<=dfa_allocated; ++i) + fprintf(OUT, "\t%d,\n", DFA(i)->alternatives); + fprintf(OUT, "/* must have 0 for zzalternatives[DfaStates] */\n"); + fprintf(OUT, "\t0\n};\n\n"); +} + + +#ifdef __USE_PROTOS +void p_mode_def(char *s,int m) /* MR1 */ +#else +void p_mode_def(s,m) /* MR1 */ +char *s; +int m; +#endif +{ + if ( gen_cpp ) + { + mode_name[cur_mode] = mystrdup(s); + mode_number[cur_mode] = m; + cur_mode++; + } + else + fprintf(mode_stream, "#define %s %d\n", s, m); +} + +#ifdef __USE_PROTOS +char * ClassName(char *suffix) +#else +char * ClassName(suffix) +char *suffix; +#endif +{ + static char buf[200]; + extern char *class_name; + + sprintf(buf, "%s%s", class_name, suffix); + return buf; +} + +#ifdef DEBUG + +/* print out a particular nfa node that is pointed to by p */ + +#ifdef __USE_PROTOS +void p_nfa_node(nfa_node *p) +#else +void p_nfa_node(p) +nfa_node *p; +#endif +{ +#ifndef VBOX + register nfa_node *t; +#endif + + if (p != NIL_INDEX){ + printf("NFA state : %d\naccept state : %d\n", + NFA_NO(p),p->accept); + if (p->trans[0] != NIL_INDEX){ + printf("trans[0] => %d on ", NFA_NO(p->trans[0])); + p_set(p->label); + printf("\n"); + } + else + printf("trans[0] => nil\n"); + if (p->trans[1] != NIL_INDEX) + printf("trans[1] => %d on epsilon\n", + NFA_NO(p->trans[1])); + else + printf("trans[1] => nil\n"); + printf("\n"); + } +} +#endif + +#ifdef DEBUG + +/* code to print out special structures when using a debugger */ + +#ifdef __USE_PROTOS +# ifdef VBOX +void p_nfa(nfa_node *p) +# else +void p_nfa(p) +# endif +#else +void p_nfa(nfa_node *p) +nfa_node *p; /* state number also index into array */ +#endif +{ +/* each node has a marker on it so it only gets printed once */ + + operation_no++; /* get new number */ + s_p_nfa(p); +} + +#ifdef __USE_PROTOS +void s_p_nfa(nfa_node *p) +#else +void s_p_nfa(p) +nfa_node *p; /* state number also index into array */ +#endif +{ + if ((p != NIL_INDEX) && (p->nfa_set != operation_no)){ + /* so it is only printed once */ + p->nfa_set = operation_no; + p_nfa_node(p); + s_p_nfa(p->trans[0]); + s_p_nfa(p->trans[1]); + } +} + +#ifdef __USE_PROTOS +void p_dfa_node(dfa_node *p) +#else +void p_dfa_node(p) +dfa_node *p; +#endif +{ + int i; + + if (p != NIL_INDEX){ + printf("DFA state :%d\n",NFA_NO(p)); + if (p->done) + printf("done\n"); + else + printf("undone\n"); + printf("from nfa states : "); + p_set(p->nfa_states); + printf("\n"); + /* NOTE: trans arcs stored as ints rather than pointer*/ + for (i=0; itrans[i]); + } + printf("\n\n"); + } +} + +#ifdef __USE_PROTOS +void p_dfa(void) +#else +void p_dfa() +#endif +{ +/* prints out all the dfa nodes actually allocated */ + + int i; + + for (i = 1; i<=dfa_allocated; i++) +#ifdef VBOX + p_dfa_node(DFA(i)); +#else + p_dfa_node(NFA(i)); +#endif +} + + +/* print out numbers in the set label */ + +#ifdef __USE_PROTOS +void p_set(set label) +#else +void p_set(label) +set label; +#endif +{ + unsigned *t, *e; + + if (set_nil(label)){ + printf("epsilon\n"); + }else{ + t = e = set_pdq(label); + while(*e != nil){ + printf("%d ", (*e+MIN_CHAR)); + e++; + } + printf("\n"); + free(t); + } + +} +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/parser.dlg b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/parser.dlg new file mode 100644 index 00000000..6cae5af4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/parser.dlg @@ -0,0 +1,398 @@ +<< +/* parser.dlg -- DLG Description of scanner + * + * Generated from: dlg_p.g + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + */ + +#define ANTLR_VERSION 13333 +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include +#include "dlg.h" +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +LOOKAHEAD + +void +#ifdef __USE_PROTOS +zzerraction(void) +#else +zzerraction() +#endif +{ + (*zzerr)("invalid token"); + zzadvance(); + zzskip(); +} +>> + +<<%%lexaction + +int func_action; /* should actions be turned into functions?*/ +int lex_mode_counter = 0; /* keeps track of the number of %%names */ +/* MR1 */ +/* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ +/* MR1 via <<%%lexmember...>> */ +/* MR1 */ +int lexMember = 0; /* <<%%lexmemeber ...>> MR1 */ +int lexAction = 0; /* <<%%lexaction ...>> MR1 */ +int parserClass = 0; /* <<%%parserclass ...>> MR1 */ +int lexPrefix = 0; /* <<%%lexprefix ...>> MR1 */ +char theClassName[100]; /* MR11 */ +char *pClassName=theClassName; /* MR11 */ +int firstLexMember=1; /* MR1 */ + +#ifdef __USE_PROTOS +void xxputc(int c) { /* MR1 */ +#else + void xxputc(c) /* MR1 */ + int c; /* MR1 */ + { /* MR1 */ +#endif + if (parserClass) { /* MR1 */ + *pClassName++=c; /* MR1 */ + *pClassName=0; /* MR1 */ + } else if (lexMember || lexPrefix) { /* MR1 */ + if (class_stream != NULL) fputc(c,class_stream); /* MR1 */ + } else { /* MR1 */ + fputc(c,OUT); /* MR1 */ + }; /* MR1 */ + } /* MR1 */ + +#ifdef __USE_PROTOS + void xxprintf(char *format,char *string) { /* MR1 */ +#else + void xxprintf(format,string) /* MR1 */ + char *format; /* MR1 */ + char *string; /* MR1 */ + { /* MR1 */ +#endif + if (lexMember || lexPrefix || parserClass) { /* MR1 */ + if (class_stream != NULL) /* MR1 */ + fprintf(class_stream,format,string); /* MR1 */ + } else { /* MR1 */ + fprintf(OUT,format,string); /* MR1 */ + }; /* MR1 */ + } /* MR1 */ +>> + + +%%START + +@ + << + NLA = 1; + >> + +[\r\t\ ]+ + << + NLA = 2; + zzskip(); + >> + +\n + << + NLA = 3; + zzline++; zzskip(); DAWDLE; + >> + +\@ + << + NLA = L_EOF; + >> + +\%\% + << + NLA = PER_PER; + >> + +\%\%[a-zA-Z_][a-zA-Z0-9_]* + << + NLA = NAME_PER_PER; + p_mode_def(&zzlextext[2],lex_mode_counter++); + >> + +\<\<\%\%lexmember + << + NLA = LEXMEMBER; + lexMember=1; /* MR1 */ + if (firstLexMember != 0) { /* MR1 */ + firstLexMember=0; /* MR1 */ + p_class_def1(); /* MR1 */ + }; /* MR1 */ + zzmode(ACT); /* MR1 */ + >> + +\<\<\%\%lexaction + << + NLA = LEXACTION; + lexAction=1;zzmode(ACT); + >> + +\<\<\%\%parserclass + << + NLA = PARSERCLASS; + parserClass=1; /* MR1 */ + zzmode(ACT); /* MR1 */ + >> + +\<\<\%\%lexprefix + << + NLA = LEXPREFIX; + lexPrefix=1;zzmode(ACT); + >> + +\<\< + << + NLA = ACTION; + if (func_action) + fprintf(OUT,"\n%s %sact%d()\n{ ", + gen_cpp?"ANTLRTokenType":"static void", + gen_cpp?ClassName("::"):"", ++action_no); + zzmode(ACT); zzskip(); + >> + +\>\> + << + NLA = GREAT_GREAT; + >> + +\{ + << + NLA = L_BRACE; + >> + +\} + << + NLA = R_BRACE; + >> + +\( + << + NLA = L_PAR; + >> + +\) + << + NLA = R_PAR; + >> + +\[ + << + NLA = L_BRACK; + >> + +\] + << + NLA = R_BRACK; + >> + +\* + << + NLA = ZERO_MORE; + >> + +\+ + << + NLA = ONE_MORE; + >> + +\| + << + NLA = OR; + >> + +\- + << + NLA = RANGE; + >> + +\~ + << + NLA = NOT; + >> + +\\0[0-7]* + << + NLA = OCTAL_VALUE; + {int t; sscanf(&zzlextext[1],"%o",&t); zzlextext[0] = t;} + >> + +\\0[Xx][0-9a-fA-F]+ + << + NLA = HEX_VALUE; + {int t; sscanf(&zzlextext[3],"%x",&t); zzlextext[0] = t;} + >> + +\\[1-9][0-9]* + << + NLA = DEC_VALUE; + {int t; sscanf(&zzlextext[1],"%d",&t); zzlextext[0] = t;} + >> + +\\t + << + NLA = TAB; + zzlextext[0] = '\t'; + >> + +\\n + << + NLA = NL; + zzlextext[0] = '\n'; + >> + +\\r + << + NLA = CR; + zzlextext[0] = '\r'; + >> + +\\b + << + NLA = BS; + zzlextext[0] = '\b'; + >> + +\\ \n + << + NLA = CONTINUATION; + zzline++; zzskip(); + >> + +\\~[tnrb] + << + NLA = LIT; + zzlextext[0] = zzlextext[1]; + >> + +~[\\] + << + NLA = REGCHAR; + >> + + +%%ACT + +@ + << + NLA = 1; + error("unterminated action", zzline); zzmode(START); + >> + +\>\> + << + NLA = ACTION; + if (func_action) fprintf(OUT,"}\n\n"); + zzmode(START); + /* MR1 */ + /* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ + /* MR1 via <<%%lexmember ...>> */ + /* MR1 This is a consequence of not saving actions */ + /* MR1 */ + /* MR1 */ parserClass=0; + /* MR1 */ lexPrefix=0; + /* MR1 */ lexAction=0; + /* MR1 */ lexMember=0; + >> + +\> + << + NLA = 34; + xxputc(zzlextext[0]); zzskip(); + >> + +\\\> + << + NLA = 35; + xxputc('>'); zzskip(); + >> + +\\ + << + NLA = 36; + xxputc('\\'); zzskip(); + >> + +\n + << + NLA = 37; + xxputc(zzlextext[0]); ++zzline; zzskip(); + >> + +/\* + << + NLA = 38; + zzmode(ACTION_COMMENTS); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + >> + +// + << + NLA = 39; + zzmode(ACTION_CPP_COMMENTS); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + >> + +~[] + << + NLA = 40; + xxputc(zzlextext[0]); zzskip(); + >> + + +%%ACTION_COMMENTS + +@ + << + NLA = 1; + >> + +\*/ + << + NLA = 41; + zzmode(ACT); /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + >> + +[\n\r] + << + NLA = 42; + zzline++; xxputc(zzlextext[0]); zzskip(); + >> + +~[] + << + NLA = 43; + xxputc(zzlextext[0]); zzskip(); + >> + + +%%ACTION_CPP_COMMENTS + +@ + << + NLA = 1; + >> + +[\n\r] + << + NLA = 44; + zzmode(ACT); zzline++; /* MR1 */ + xxprintf("%s", &(zzlextext[0])); zzskip(); /* MR1 */ + >> + +~[] + << + NLA = 45; + xxputc(zzlextext[0]); zzskip(); + >> + +%% diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/relabel.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/relabel.c new file mode 100644 index 00000000..1a5ac448 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/relabel.c @@ -0,0 +1,217 @@ +/* This group of functions does the character class compression. + It goes over the dfa and relabels the arcs with the partitions + of characters in the NFA. The partitions are stored in the + array class. + + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * DLG 1.33 + * Will Cohen + * With mods by Terence Parr; AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include "dlg.h" +#ifdef MEMCHK +#include "trax.h" +#else +#ifdef __STDC__ +#include +#else +#include +#endif /* __STDC__ */ +#endif + +int class_no = CHAR_RANGE; /* number of classes for labels */ +int first_el[CHAR_RANGE]; /* first element in each class partition */ +set class_sets[CHAR_RANGE]; /* array holds partitions from class */ + /* compression */ + +/* goes through labels on NFA graph and partitions the characters into + * character classes. This reduces the amount of space required for each + * dfa node, since only one arc is required each class instead of one arc + * for each character + * level: + * 0 no compression done + * 1 remove unused characters from classes + * 2 compress equivalent characters into same class + * + * returns the number of character classes required + */ +#ifdef __USE_PROTOS +int relabel(nfa_node* start,int level) +#else +int relabel(start,level) +int level; +nfa_node *start; +#endif +{ + if (level){ + set_free(used_classes); + partition(start,level); + label_with_classes(start); + }else{ + /* classes equivalent to all characters in alphabet */ + class_no = CHAR_RANGE; + } + return class_no; +} + +/* makes character class sets for new labels */ +#ifdef __USE_PROTOS +void partition(nfa_node* start,int level) +#else +void partition(start,level) +nfa_node *start; /* beginning of nfa graph */ +int level; /* compression level to uses */ +#endif +{ + set current_class; + set unpart_chars; + set temp; + + unpart_chars = set_dup(used_chars); +#if 0 + /* EOF (-1+1) alway in class 0 */ + class_sets[0] = set_of(0); + first_el[0] = 0; + used_classes = set_of(0); + temp = set_dif(unpart_chars, class_sets[0]); + set_free(unpart_chars); + unpart_chars = temp; + class_no = 1; +#else + class_no = 0; +#endif + while (!set_nil(unpart_chars)){ + /* don't look for equivalent labels if c <= 1 */ + if (level <= 1){ + current_class = set_of(set_int(unpart_chars)); + }else{ + current_class = set_dup(unpart_chars); + intersect_nfa_labels(start,¤t_class); + } + set_orel(class_no,&used_classes); + first_el[class_no] = set_int(current_class); + class_sets[class_no] = current_class; + temp = set_dif(unpart_chars,current_class); + set_free(unpart_chars); + unpart_chars = temp; + ++class_no; + } + + /* free unpart_chars -ATG 5/6/95 */ + set_free(unpart_chars); + +#if 0 + /* group all the other unused characters into a class */ + set_orel(class_no,&used_classes); + first_el[class_no] = set_int(current_class); + class_sets[class_no] = set_dif(normal_chars,used_chars); + ++class_no; +#endif +} + + +/* given pointer to beginning of graph and recursively walks it trying + * to find a maximal partition. This partition in returned in maximal_class + */ +#ifdef __USE_PROTOS +void intersect_nfa_labels(nfa_node* start,set* maximal_class) +#else +void intersect_nfa_labels(start,maximal_class) +nfa_node *start; +set *maximal_class; +#endif +{ + /* pick a new operation number */ + ++operation_no; + r_intersect(start,maximal_class); +} + +#ifdef __USE_PROTOS +void r_intersect(nfa_node* start,set* maximal_class) +#else +void r_intersect(start,maximal_class) +nfa_node *start; +set * maximal_class; +#endif +{ + set temp; + + if(start && start->nfa_set != operation_no) + { + start->nfa_set = operation_no; + temp = set_and(*maximal_class,start->label); + if (!set_nil(temp)) + { + set_free(*maximal_class); + *maximal_class = temp; + }else{ + set_free(temp); + } + r_intersect(start->trans[0],maximal_class); + r_intersect(start->trans[1],maximal_class); + } +} + + +/* puts class labels in place of old character labels */ +#ifdef __USE_PROTOS +void label_with_classes(nfa_node* start) +#else +void label_with_classes(start) +nfa_node *start; +#endif +{ + ++operation_no; + label_node(start); +} + +#ifdef __USE_PROTOS +void label_node(nfa_node *start) +#else +void label_node(start) +nfa_node *start; +#endif +{ + set new_label; + register int i; + + /* only do node if it hasn't been done before */ + if (start && start->nfa_set != operation_no){ + start->nfa_set = operation_no; + new_label = empty; + for (i = 0; ilabel)) + set_orel(i,&new_label); + } + set_free(start->label); + start->label = new_label; + /* do any nodes that can be reached from this one */ + label_node(start->trans[0]); + label_node(start->trans[1]); + } +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/stdpccts.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/stdpccts.h new file mode 100644 index 00000000..12c1c769 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/stdpccts.h @@ -0,0 +1,26 @@ +#ifndef STDPCCTS_H +#define STDPCCTS_H +/* + * stdpccts.h -- P C C T S I n c l u d e + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * With AHPCRC, University of Minnesota + * ANTLR Version 1.33MR33 + */ + +#ifndef ANTLR_VERSION +#define ANTLR_VERSION 13333 +#endif + +#include "pcctscfg.h" +#include "pccts_stdio.h" + +#include +#include "dlg.h" +#define zzSET_SIZE 8 +#include "antlr.h" +#include "tokens.h" +#include "dlgdef.h" +#include "mode.h" +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/support.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/support.c new file mode 100644 index 00000000..47879da9 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/support.c @@ -0,0 +1,240 @@ +/* + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * DLG 1.33 + * Will Cohen + * With mods by Terence Parr; AHPCRC, University of Minnesota + * 1989-2001 + */ + +#include +#include +#include "dlg.h" +#ifdef MEMCHK +#include "trax.h" +#else +#ifdef __STDC__ +#include +#else +#include +#endif /* __STDC__ */ +#endif + +int err_found = 0; /* indicates whether problem found */ + +#ifdef __USE_PROTOS +void internal_error(char *s, char *file,int line) /* MR9 23-Sep-97 */ +#else +void internal_error(s,file,line) /* MR9 23-Sep-97 */ +char *s,*file; +int line; +#endif +{ + fprintf(stderr,s,file,line); + exit(PCCTS_EXIT_FAILURE); +} + +#ifdef __USE_PROTOS +char *dlg_malloc(int bytes,char *file,int line) +#else +char *dlg_malloc(bytes,file,line) +int bytes; +char *file; +int line; +#endif +{ + char *t; + + t = (char *) malloc(bytes); + if (!t){ + /* error */ + internal_error("%s(%d): unable to allocate memory\n", + file,line); + } + return t; +} + + +#ifdef __USE_PROTOS +char *dlg_calloc(int n,int bytes,char *file,int line) +#else +char *dlg_calloc(n,bytes,file,line) +int n,bytes; +char *file; +int line; +#endif +{ + char *t; + + t = (char *) calloc(n,bytes); + if (!t){ + /* error */ + internal_error("%s(%d): unable to allocate memory\n", + file,line); + } + return t; +} + + +#ifdef __USE_PROTOS +FILE *read_stream(char *name) +#else +FILE *read_stream(name) +char *name; +#endif +{ + FILE *f; + + if (name){ + if (name[0] == '-') { + fprintf(stderr, "dlg: invalid option: '%s'\n", name); + f = NULL; + }else{ + f = fopen(name, "r"); + if (f == NULL){ + /* couldn't open file */ + fprintf(stderr, + "dlg: Warning: Can't read file %s.\n", + name); + } + } + }else{ + /* open stdin if nothing there */ + f = stdin; + } + return f; +} + +#ifdef __USE_PROTOS +FILE *write_stream(char *name) +#else +FILE *write_stream(name) +char *name; +#endif +{ + FILE *f; + + if (name){ + if (name[0] == '-') { + fprintf(stderr, "dlg: invalid option: '%s'\n", name); + f = NULL; + }else{ + f = fopen(OutMetaName(name), "w"); + if (f == NULL){ + /* couldn't open file */ + fprintf(stderr, + "dlg: Warning: Can't write to file %s.\n", + name); + } + else +#ifdef SPECIAL_FOPEN + special_fopen_actions(OutMetaName(name)); /* MR1 */ +#else + ; /* MR1 */ +#endif + } + }else{ + /* open stdout if nothing there */ + f = stdout; + } + return f; +} + + +#ifdef __USE_PROTOS +void fatal(char *message,int line_no) +#else +void fatal(message,line_no) +char *message; +int line_no; +#endif +{ + fprintf(stderr,ErrHdr, + (file_str[0] ? file_str[0] : "stdin"), line_no); + fprintf(stderr, " Fatal: %s\n", message); + exit(PCCTS_EXIT_FAILURE); +} + +#ifdef __USE_PROTOS +void error(char *message,int line_no) +#else +void error(message,line_no) +char *message; +int line_no; +#endif +{ + fprintf(stderr,ErrHdr, + (file_str[0] ? file_str[0] : "stdin"), line_no); + fprintf(stderr, " Error: %s\n", message); + err_found = 1; +} + +#ifdef __USE_PROTOS +void warning(char *message,int line_no) +#else +void warning(message,line_no) +char *message; +int line_no; +#endif +{ + fprintf(stderr,ErrHdr, + (file_str[0] ? file_str[0] : "stdin"), line_no); + fprintf(stderr, " Warning: %s\n", message); +} + +/* MR10: Jeff Vincent + MR10: Changed to remove directory information from n only if + MR10: if OutputDirectory was changed by user (-o option) +*/ + +#ifdef __USE_PROTOS +char *OutMetaName(char *n) +#else +char *OutMetaName(n) +char *n; +#endif +{ + static char *dir_sym = DirectorySymbol; + static char newname[MaxFileName+1]; + char *p; + + /* If OutputDirectory is same as TopDirectory (platform default) then leave n alone. */ + if (strcmp(OutputDirectory, TopDirectory) == 0) + return n; + + /* p will point to filename without path information */ + if ((p = strrchr(n, *dir_sym)) != NULL) + p++; + else + p = n; + + /* Copy new output directory into newname[] */ + strcpy(newname, OutputDirectory); + + /* if new output directory does not have trailing dir_sym, add it! */ + if (newname[strlen(newname)-1] != *dir_sym) + strcat(newname, dir_sym); + + /* contatenate FILE NAME ONLY to new output directory */ + strcat(newname, p); + + return newname; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/tokens.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/tokens.h new file mode 100644 index 00000000..bfa5b474 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/dlg/tokens.h @@ -0,0 +1,133 @@ +#ifndef tokens_h +#define tokens_h +/* tokens.h -- List of labelled tokens and stuff + * + * Generated from: dlg_p.g + * + * Terence Parr, Will Cohen, and Hank Dietz: 1989-2001 + * Purdue University Electrical Engineering + * ANTLR Version 1.33MR33 + */ +#define zzEOF_TOKEN 1 +#define L_EOF 4 +#define PER_PER 5 +#define NAME_PER_PER 6 +#define LEXMEMBER 7 +#define LEXACTION 8 +#define PARSERCLASS 9 +#define LEXPREFIX 10 +#define ACTION 11 +#define GREAT_GREAT 12 +#define L_BRACE 13 +#define R_BRACE 14 +#define L_PAR 15 +#define R_PAR 16 +#define L_BRACK 17 +#define R_BRACK 18 +#define ZERO_MORE 19 +#define ONE_MORE 20 +#define OR 21 +#define RANGE 22 +#define NOT 23 +#define OCTAL_VALUE 24 +#define HEX_VALUE 25 +#define DEC_VALUE 26 +#define TAB 27 +#define NL 28 +#define CR 29 +#define BS 30 +#define CONTINUATION 31 +#define LIT 32 +#define REGCHAR 33 + +#ifdef __USE_PROTOS +void grammar(void); +#else +extern void grammar(); +#endif + +#ifdef __USE_PROTOS +void start_states(void); +#else +extern void start_states(); +#endif + +#ifdef __USE_PROTOS +void do_conversion(void); +#else +extern void do_conversion(); +#endif + +#ifdef __USE_PROTOS +void rule_list(void); +#else +extern void rule_list(); +#endif + +#ifdef __USE_PROTOS +void rule(void); +#else +extern void rule(); +#endif + +#ifdef __USE_PROTOS +void reg_expr(void); +#else +extern void reg_expr(); +#endif + +#ifdef __USE_PROTOS +void and_expr(void); +#else +extern void and_expr(); +#endif + +#ifdef __USE_PROTOS +void repeat_expr(void); +#else +extern void repeat_expr(); +#endif + +#ifdef __USE_PROTOS +void expr(void); +#else +extern void expr(); +#endif + +#ifdef __USE_PROTOS +void atom_list(void); +#else +extern void atom_list(); +#endif + +#ifdef __USE_PROTOS +void near_atom(void); +#else +extern void near_atom(); +#endif + +#ifdef __USE_PROTOS +void atom(void); +#else +extern void atom(); +#endif + +#ifdef __USE_PROTOS +void anychar(void); +#else +extern void anychar(); +#endif + +#endif +extern SetWordType zzerr1[]; +extern SetWordType zzerr2[]; +extern SetWordType zzerr3[]; +extern SetWordType setwd1[]; +extern SetWordType zzerr4[]; +extern SetWordType zzerr5[]; +extern SetWordType zzerr6[]; +extern SetWordType setwd2[]; +extern SetWordType zzerr7[]; +extern SetWordType zzerr8[]; +extern SetWordType zzerr9[]; +extern SetWordType setwd3[]; diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/AParser.cpp b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/AParser.cpp new file mode 100644 index 00000000..85e668fe --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/AParser.cpp @@ -0,0 +1,871 @@ +/* ANTLRParser.C + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#include "pcctscfg.h" + +#include "pccts_stdlib.h" +#include "pccts_stdarg.h" +#include "pccts_string.h" +#include "pccts_stdio.h" + +PCCTS_NAMESPACE_STD + +/* I have to put this here due to C++ limitation + * that you can't have a 'forward' decl for enums. + * I hate C++!!!!!!!!!!!!!!! + * Of course, if I could use real templates, this would go away. + */ +// MR1 +// MR1 10-Apr-97 133MR1 Prevent use of varying sizes for the +// MR1 ANTLRTokenType enum +// MR1 + +enum ANTLRTokenType { TER_HATES_CPP=0, ITS_TOO_COMPLICATED=9999}; // MR1 + +#define ANTLR_SUPPORT_CODE + +#include ATOKEN_H +#include ATOKENBUFFER_H +#include APARSER_H + +static const int zzINF_DEF_TOKEN_BUFFER_SIZE = 2000; /* MR14 */ +static const int zzINF_BUFFER_TOKEN_CHUNK_SIZE = 1000; /* MR14 */ + + /* L o o k a h e a d M a c r o s */ + +/* maximum of 32 bits/unsigned int and must be 8 bits/byte; + * we only use 8 bits of it. + */ +SetWordType ANTLRParser::bitmask[sizeof(SetWordType)*8] = { + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080 +}; + +char ANTLRParser::eMsgBuffer[500] = ""; + +ANTLRParser:: +~ANTLRParser() +{ + delete [] token_type; + delete [] zzFAILtext; // MR16 Manfred Kogler +} + +ANTLRParser:: +ANTLRParser(ANTLRTokenBuffer *_inputTokens, + int k, + int use_inf_look, + int dlook, + int ssize) +{ + LLk = k; + can_use_inf_look = use_inf_look; +/* MR14 */ if (dlook != 0) { +/* MR14 */ panic("ANTLRParser::ANTLRParser - Demand lookahead not supported in C++ mode"); +/* MR14 */ +/* MR14 */ }; + demand_look = 0; /* demand_look = dlook; */ + bsetsize = ssize; + guessing = 0; + token_tbl = NULL; + eofToken = (ANTLRTokenType)1; + + // allocate lookahead buffer + token_type = new ANTLRTokenType[LLk]; + lap = 0; + labase = 0; +#ifdef ZZDEFER_FETCH + stillToFetch = 0; // MR19 +#endif + dirty = 0; + inf_labase = 0; // MR7 + inf_last = 0; // MR7 + /* prime lookahead buffer, point to inputTokens */ + this->inputTokens = _inputTokens; + this->inputTokens->setMinTokens(k); + _inputTokens->setParser(this); // MR1 + resynchConsumed=1; // MR8 + zzFAILtext=NULL; // MR9 + traceOptionValueDefault=0; // MR10 + traceReset(); // MR10 + zzGuessSeq=0; // MR10 + syntaxErrCount=0; // MR11 +} + +void ANTLRParser::init() +{ + prime_lookahead(); + resynchConsumed=1; // MR8 + traceReset(); // MR10 +} + +void ANTLRParser::traceReset() +{ + traceOptionValue=traceOptionValueDefault; + traceGuessOptionValue=1; + traceCurrentRuleName=NULL; + traceDepth=0; +} + + +#ifdef _MSC_VER // MR23 +//Turn off warning: +//interaction between '_setjmp' and C++ object destruction is non-portable +#pragma warning(disable : 4611) +#endif +int ANTLRParser:: +guess(ANTLRParserState *st) +{ + saveState(st); + guessing = 1; + return setjmp(guess_start.state); +} +#ifdef _MSC_VER // MR23 +#pragma warning(default: 4611) +#endif + +void ANTLRParser:: +saveState(ANTLRParserState *buf) +{ + buf->guess_start = guess_start; + buf->guessing = guessing; + buf->inf_labase = inf_labase; + buf->inf_last = inf_last; + buf->dirty = dirty; + buf->traceOptionValue=traceOptionValue; /* MR10 */ + buf->traceGuessOptionValue=traceGuessOptionValue; /* MR10 */ + buf->traceCurrentRuleName=traceCurrentRuleName; /* MR10 */ + buf->traceDepth=traceDepth; /* MR10 */ +} + +void ANTLRParser:: +restoreState(ANTLRParserState *buf) +{ + int i; + int prevTraceOptionValue; + + guess_start = buf->guess_start; + guessing = buf->guessing; + inf_labase = buf->inf_labase; + inf_last = buf->inf_last; + dirty = buf->dirty; + + // restore lookahead buffer from k tokens before restored TokenBuffer position + // if demand_look, then I guess we don't look backwards for these tokens. + for (i=1; i<=LLk; i++) token_type[i-1] = + inputTokens->bufferedToken(i-LLk)->getType(); + lap = 0; + labase = 0; + + /* MR10 */ + + prevTraceOptionValue=traceOptionValue; + traceOptionValue=buf->traceOptionValue; + if ( (prevTraceOptionValue > 0) != + (traceOptionValue > 0)) { + if (traceCurrentRuleName != NULL) { /* MR21 */ + if (traceOptionValue > 0) { + /* MR23 */ printMessage(stderr, + "trace enable restored in rule %s depth %d\n", + traceCurrentRuleName, + traceDepth); + }; + if (traceOptionValue <= 0) { + /* MR23 */ printMessage(stderr, + "trace disable restored in rule %s depth %d\n", + traceCurrentRuleName, /* MR21 */ + traceDepth); + }; + } + }; + traceGuessOptionValue=buf->traceGuessOptionValue; + traceCurrentRuleName=buf->traceCurrentRuleName; + traceDepth=buf->traceDepth; + traceGuessDone(buf); +} + +/* Get the next symbol from the input stream; put it into lookahead buffer; + * fill token_type[] fast reference cache also. NLA is the next place where + * a lookahead ANTLRAbstractToken should go. + */ +void ANTLRParser:: +consume() +{ + +#ifdef ZZDEBUG_CONSUME_ACTION + zzdebug_consume_action(); +#endif + +// MR19 V.H. Simonis +// Defer Fetch feature +// Moves action of consume() into LA() function + +#ifdef ZZDEFER_FETCH + stillToFetch++; +#else + NLA = inputTokens->getToken()->getType(); + dirty--; + lap = (lap+1)&(LLk-1); +#endif + +} + +_ANTLRTokenPtr ANTLRParser:: +LT(int i) +{ + +// MR19 V.H. Simonis +// Defer Fetch feature +// Moves action of consume() into LA() function + +#ifdef ZZDEFER_FETCH + undeferFetch(); +#endif + +#ifdef DEBUG_TOKENBUFFER + if ( i >= inputTokens->bufferSize() || inputTokens->minTokens() < LLk ) /* MR20 Was "<=" */ + { + char buf[2000]; /* MR20 Was "static" */ + sprintf(buf, "The minimum number of tokens you requested that the\nANTLRTokenBuffer buffer is not enough to satisfy your\nLT(%d) request; increase 'k' argument to constructor for ANTLRTokenBuffer\n", i); + panic(buf); + } +#endif + return inputTokens->bufferedToken(i-LLk); +} + +void +ANTLRParser:: +look(int k) +{ + int i, c = k - (LLk-dirty); + for (i=1; i<=c; i++) consume(); +} + +/* fill the lookahead buffer up with k symbols (even if DEMAND_LOOK); + */ +void +ANTLRParser:: +prime_lookahead() +{ + int i; + for(i=1;i<=LLk; i++) consume(); + dirty=0; + // lap = 0; // MR14 Sinan Karasu (sinan.karasu@boeing.com) + // labase = 0; // MR14 + labase=lap; // MR14 +} + +/* check to see if the current input symbol matches '_t'. + * During NON demand lookahead mode, dirty will always be 0 and + * hence the extra code for consuming tokens in _match is never + * executed; the same routine can be used for both modes. + */ +int ANTLRParser:: +_match(ANTLRTokenType _t, ANTLRChar **MissText, + ANTLRTokenType *MissTok, _ANTLRTokenPtr *BadTok, + SetWordType **MissSet) +{ + if ( dirty==LLk ) { + consume(); + } + if ( LA(1)!=_t ) { + *MissText=NULL; + *MissTok= _t; + *BadTok = LT(1); + *MissSet=NULL; + return 0; + } + dirty++; + labase = (labase+1)&(LLk-1); // labase maintained even if !demand look + return 1; +} + +/* check to see if the current input symbol matches '_t'. + * Used during exception handling. + */ +int ANTLRParser:: +_match_wsig(ANTLRTokenType _t) +{ + if ( dirty==LLk ) { + consume(); + } + if ( LA(1)!=_t ) return 0; + dirty++; + labase = (labase+1)&(LLk-1); // labase maintained even if !demand look + return 1; +} + +/* check to see if the current input symbol matches any token in a set. + * During NON demand lookahead mode, dirty will always be 0 and + * hence the extra code for consuming tokens in _match is never + * executed; the same routine can be used for both modes. + */ +int ANTLRParser:: +_setmatch(SetWordType *tset, ANTLRChar **MissText, + ANTLRTokenType *MissTok, _ANTLRTokenPtr *BadTok, + SetWordType **MissSet, SetWordType *tokclassErrset) +{ + if ( dirty==LLk ) { + consume(); + } + if ( !set_el(LA(1), tset) ) { + *MissText=NULL; /* MR23 */ + *MissTok=(ANTLRTokenType) 0; /* MR23 */ + *BadTok=LT(1); /* MR23 */ + *MissSet=tokclassErrset; /* MR23 */ + return 0; + } + dirty++; + labase = (labase+1)&(LLk-1); // labase maintained even if !demand look + return 1; +} + +int ANTLRParser:: +_setmatch_wsig(SetWordType *tset) +{ + if ( dirty==LLk ) { + consume(); + } + if ( !set_el(LA(1), tset) ) return 0; + dirty++; + labase = (labase+1)&(LLk-1); // labase maintained even if !demand look + return 1; +} + + /* Exception handling routines */ +// +// 7-Apr-97 133MR1 +// Change suggested by Eli Sternheim (eli@interhdl.com) +// +void ANTLRParser:: +consumeUntil(SetWordType *st) +{ + ANTLRTokenType tmp; // MR1 + const int Eof=1; // MR1 + while ( !set_el( (tmp=LA(1)), st) && tmp!=Eof) { consume(); } // MR1 +} + +// +// 7-Apr-97 133MR1 +// Change suggested by Eli Sternheim (eli@interhdl.com) +// +void ANTLRParser:: +consumeUntilToken(int t) +{ + int tmp; // MR1 + const int Eof=1; // MR1 + while ( (tmp=LA(1)) !=t && tmp!=Eof) { consume(); } // MR1 +} + + + /* Old error stuff */ + +void ANTLRParser:: +resynch(SetWordType *wd,SetWordType mask) +{ + +/* MR8 S.Bochnak@microtool.com.pl */ +/* MR8 Change file scope static "consumed" to instance var */ + + /* if you enter here without having consumed a token from last resynch + * force a token consumption. + */ +/* MR8 */ if ( !resynchConsumed ) {consume(); resynchConsumed=1; return;} + + /* if current token is in resynch set, we've got what we wanted */ + +/* MR8 */ if ( wd[LA(1)]&mask || LA(1) == eofToken ) {resynchConsumed=0; return;} + + /* scan until we find something in the resynch set */ + + while ( !(wd[LA(1)]&mask) && LA(1) != eofToken ) {consume();} + +/* MR8 */ resynchConsumed=1; +} + +/* standard error reporting function that assumes DLG-based scanners; + * you should redefine in subclass to change it or if you use your + * own scanner. + */ + +/* MR23 THM There appears to be a parameter "badText" passed to syn() + which is not present in the parameter list. This may be + because in C mode there is no attribute function which + returns the text, so the text representation of the token + must be passed explicitly. I think. +*/ + +void ANTLRParser:: +syn(_ANTLRTokenPtr /*tok MR23*/, ANTLRChar *egroup, SetWordType *eset, + ANTLRTokenType etok, int k) +{ + int line; + + line = LT(1)->getLine(); + + syntaxErrCount++; /* MR11 */ + + /* MR23 If the token is not an EOF token, then use the ->getText() value. + + If the token is the EOF token the text returned by ->getText() + may be garbage. If the text from the token table is "@" use + "" instead, because end-users don't know what "@" means. + If the text is not "@" then use that text, which must have been + supplied by the grammar writer. + */ + const char * errorAt = LT(1)->getText(); + if (LA(1) == eofToken) { + errorAt = parserTokenName(LA(1)); + if (errorAt[0] == '@') errorAt = ""; + } + /* MR23 */ printMessage(stderr, "line %d: syntax error at \"%s\"", + line, errorAt); + if ( !etok && !eset ) {/* MR23 */ printMessage(stderr, "\n"); return;} + if ( k==1 ) /* MR23 */ printMessage(stderr, " missing"); + else + { + /* MR23 */ printMessage(stderr, "; \"%s\" not", LT(k)->getText()); // MR23 use LT(k) since k>1 + if ( set_deg(eset)>1 ) /* MR23 */ printMessage(stderr, " in"); + } + if ( set_deg(eset)>0 ) edecode(eset); + else /* MR23 */ printMessage(stderr, " %s", token_tbl[etok]); + if ( strlen(egroup) > 0 ) /* MR23 */ printMessage(stderr, " in %s", egroup); + /* MR23 */ printMessage(stderr, "\n"); +} + +/* is b an element of set p? */ +int ANTLRParser:: +set_el(ANTLRTokenType b, SetWordType *p) +{ + return( p[DIVWORD(b)] & bitmask[MODWORD(b)] ); +} + +int ANTLRParser:: +set_deg(SetWordType *a) +{ + /* Fast compute degree of a set... the number + of elements present in the set. Assumes + that all word bits are used in the set + */ + register SetWordType *p = a; + register SetWordType *endp = &(a[bsetsize]); + register int degree = 0; + + if ( a == NULL ) return 0; + while ( p < endp ) + { + register SetWordType t = *p; + register SetWordType *b = &(bitmask[0]); + do { + if (t & *b) ++degree; + } while (++b < &(bitmask[sizeof(SetWordType)*8])); + p++; + } + + return(degree); +} + +void ANTLRParser:: +edecode(SetWordType *a) +{ + register SetWordType *p = a; + register SetWordType *endp = &(p[bsetsize]); + register unsigned e = 0; + + if ( set_deg(a)>1 ) /* MR23 */ printMessage(stderr, " {"); + do { + register SetWordType t = *p; + register SetWordType *b = &(bitmask[0]); + do { + if ( t & *b ) /* MR23 */ printMessage(stderr, " %s", token_tbl[e]); + e++; + } while (++b < &(bitmask[sizeof(SetWordType)*8])); + } while (++p < endp); + if ( set_deg(a)>1 ) /* MR23 */ printMessage(stderr, " }"); +} + +/* input looks like: + * zzFAIL(k, e1, e2, ...,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk) + * where the zzMiss stuff is set here to the token that did not match + * (and which set wasn't it a member of). + */ + +// MR9 29-Sep-97 Stan Bochnak (S.Bochnak@microTool.com.pl) +// MR9 Original fix to static allocated text didn't +// MR9 work because a pointer to it was passed back +// MR9 to caller. Replace with instance variable. + +const int SETWORDCOUNT=20; + +void +ANTLRParser::FAIL(int k, ...) +{ +// +// MR1 10-Apr-97 +// + + if (zzFAILtext == NULL) zzFAILtext=new char [1000]; // MR9 + SetWordType **f=new SetWordType *[SETWORDCOUNT]; // MR1 // MR9 + SetWordType **miss_set; + ANTLRChar **miss_text; + _ANTLRTokenPtr *bad_tok; + ANTLRChar **bad_text; +// +// 7-Apr-97 133MR1 +// err_k is passed as a "int *", not "unsigned *" +// + int *err_k; // MR1 + int i; + va_list ap; + + va_start(ap, k); + + zzFAILtext[0] = '\0'; + if ( k > SETWORDCOUNT ) panic("FAIL: overflowed buffer"); + for (i=1; i<=k; i++) /* collect all lookahead sets */ + { + f[i-1] = va_arg(ap, SetWordType *); + } + for (i=1; i<=k; i++) /* look for offending token */ + { + if ( i>1 ) strcat(zzFAILtext, " "); + strcat(zzFAILtext, LT(i)->getText()); + if ( !set_el(LA(i), f[i-1]) ) break; + } + miss_set = va_arg(ap, SetWordType **); + miss_text = va_arg(ap, ANTLRChar **); + bad_tok = va_arg(ap, _ANTLRTokenPtr *); + bad_text = va_arg(ap, ANTLRChar **); + err_k = va_arg(ap, int *); // MR1 + if ( i>k ) + { + /* bad; lookahead is permutation that cannot be matched, + * but, the ith token of lookahead is valid at the ith position + * (The old LL sub 1 (k) versus LL(k) parsing technique) + */ + *miss_set = NULL; + *miss_text = LT(1)->getText(); + *bad_tok = LT(1); + *bad_text = (*bad_tok)->getText(); + *err_k = k; +// +// MR4 20-May-97 erroneously deleted contents of f[] +// MR4 reported by Bruce Guenter (bruceg@qcc.sk.ca) +// MR1 10-Apr-97 release temporary storage +// + delete [] f; // MR1 + return; // MR1 + } +/* MR23 printMessage(stderr, "%s not in %dth set\n", zztokens[LA(i)], i);*/ + *miss_set = f[i-1]; + *miss_text = zzFAILtext; + *bad_tok = LT(i); + *bad_text = (*bad_tok)->getText(); + if ( i==1 ) *err_k = 1; + else *err_k = k; +// +// MR4 20-May-97 erroneously deleted contents of f[] +// MR4 reported by Bruce Guenter (bruceg@qcc.sk.ca) +// MR1 10-Apr-97 release temporary storage +// + delete [] f; // MR1 + return; // MR1 +} + +int ANTLRParser:: +_match_wdfltsig(ANTLRTokenType tokenWanted, SetWordType *whatFollows) +{ + if ( dirty==LLk ) consume(); + + if ( LA(1)!=tokenWanted ) + { + syntaxErrCount++; /* MR11 */ + /* MR23 */ printMessage(stderr, + "line %d: syntax error at \"%s\" missing %s\n", + LT(1)->getLine(), + (LA(1)==eofToken && LT(1)->getText()[0] == '@')?"":LT(1)->getText(), /* MR21a */ + token_tbl[tokenWanted]); + consumeUntil( whatFollows ); + return 0; + } + else { + dirty++; + labase = (labase+1)&(LLk-1); // labase maintained even if !demand look +/* if ( !demand_look ) consume(); */ + return 1; + } +} + + +int ANTLRParser:: +_setmatch_wdfltsig(SetWordType *tokensWanted, + ANTLRTokenType tokenTypeOfSet, + SetWordType *whatFollows) +{ + if ( dirty==LLk ) consume(); + if ( !set_el(LA(1), tokensWanted) ) + { + syntaxErrCount++; /* MR11 */ + /* MR23 */ printMessage(stderr, + "line %d: syntax error at \"%s\" missing %s\n", + LT(1)->getLine(), + (LA(1)==eofToken && LT(1)->getText()[0] == '@')?"":LT(1)->getText(), /* MR21a */ + token_tbl[tokenTypeOfSet]); + consumeUntil( whatFollows ); + return 0; + } + else { + dirty++; + labase = (labase+1)&(LLk-1); // labase maintained even if !demand look +/* if ( !demand_look ) consume(); */ + return 1; + } +} + +char *ANTLRParser:: +eMsgd(char *err,int d) +{ + sprintf(eMsgBuffer, err, d); // dangerous, but I don't care + return eMsgBuffer; +} + +char *ANTLRParser:: +eMsg(char *err, char *s) +{ + sprintf(eMsgBuffer, err, s); + return eMsgBuffer; +} + +char *ANTLRParser:: +eMsg2(char *err,char *s, char *t) +{ + sprintf(eMsgBuffer, err, s, t); + return eMsgBuffer; +} + +void ANTLRParser:: +panic(const char *msg) // MR20 const +{ + /* MR23 */ printMessage(stderr, "ANTLR panic: %s\n", msg); + exit(PCCTS_EXIT_FAILURE); // MR1 +} + +const ANTLRChar *ANTLRParser:: // MR1 +parserTokenName(int tok) { // MR1 + return token_tbl[tok]; // MR1 +} // MR1 + +void ANTLRParser::traceGuessDone(const ANTLRParserState *state) { + + int doIt=0; + + if (traceCurrentRuleName == NULL) return; + + if (traceOptionValue <= 0) { + doIt=0; + } else if (traceGuessOptionValue <= 0) { + doIt=0; + } else { + doIt=1; + }; + + if (doIt) { + /* MR23 */ printMessage(stderr,"guess done - returning to rule %s {\"%s\"} at depth %d", + state->traceCurrentRuleName, + LT(1)->getType() == eofToken ? "@" : LT(1)->getText(), + state->traceDepth); + if (state->guessing != 0) { + /* MR23 */ printMessage(stderr," (guess mode continues - an enclosing guess is still active)"); + } else { + /* MR23 */ printMessage(stderr," (guess mode ends)"); + }; + /* MR23 */ printMessage(stderr,"\n"); + }; +} + +void ANTLRParser::traceGuessFail() { + + int doIt=0; + + if (traceCurrentRuleName == NULL) return; /* MR21 */ + + if (traceOptionValue <= 0) { + doIt=0; + } else if (guessing && traceGuessOptionValue <= 0) { + doIt=0; + } else { + doIt=1; + }; + + if (doIt) { + /* MR23 */ printMessage(stderr,"guess failed in %s\n",traceCurrentRuleName); + }; +} + +/* traceOption: + zero value turns off trace +*/ + +void ANTLRParser::tracein(const ANTLRChar * rule) { + + int doIt=0; + + traceDepth++; + traceCurrentRuleName=rule; + + if (traceOptionValue <= 0) { + doIt=0; + } else if (guessing && traceGuessOptionValue <= 0) { + doIt=0; + } else { + doIt=1; + }; + + if (doIt) { + /* MR23 */ printMessage(stderr,"enter rule %s {\"%s\"} depth %d", + rule, + LT(1)->getType() == eofToken ? "@" : LT(1)->getText(), + traceDepth); + if (guessing) /* MR23 */ printMessage(stderr," guessing"); + /* MR23 */ printMessage(stderr,"\n"); + }; + return; +} + +void ANTLRParser::traceout(const ANTLRChar * rule) { + + int doIt=0; + + traceDepth--; + + if (traceOptionValue <= 0) { + doIt=0; + } else if (guessing && traceGuessOptionValue <= 0) { + doIt=0; + } else { + doIt=1; + }; + + if (doIt) { + /* MR23 */ printMessage(stderr,"exit rule %s {\"%s\"} depth %d", + rule, + LT(1)->getType() == eofToken ? "@" : LT(1)->getText(), + traceDepth+1); + if (guessing) /* MR23 */ printMessage(stderr," guessing"); + /* MR23 */ printMessage(stderr,"\n"); + }; +} + +int ANTLRParser::traceOption(int delta) { + + int prevValue=traceOptionValue; + + traceOptionValue=traceOptionValue+delta; + + if (traceCurrentRuleName != NULL) { + if (prevValue <= 0 && traceOptionValue > 0) { + /* MR23 */ printMessage(stderr,"trace enabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth); + }; + if (prevValue > 0 && traceOptionValue <= 0) { + /* MR23 */ printMessage(stderr,"trace disabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth); + }; + }; + + return prevValue; +} + +int ANTLRParser::traceGuessOption(int delta) { + + int prevValue=traceGuessOptionValue; + + traceGuessOptionValue=traceGuessOptionValue+delta; + + if (traceCurrentRuleName != NULL) { + if (prevValue <= 0 && traceGuessOptionValue > 0) { + /* MR23 */ printMessage(stderr,"guess trace enabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth); + }; + if (prevValue > 0 && traceGuessOptionValue <= 0) { + /* MR23 */ printMessage(stderr,"guess trace disabled in rule %s depth %d\n",traceCurrentRuleName,traceDepth); + }; + }; + return prevValue; +} + +// MR19 V.H. Simonis Defer Fetch feature + +void ANTLRParser::undeferFetch() +{ + +#ifdef ZZDEFER_FETCH + if (stillToFetch) { + for (int stillToFetch_x = 0; stillToFetch_x < stillToFetch; ++stillToFetch_x) { + NLA = inputTokens->getToken()->getType(); + dirty--; + lap = (lap+1)&(LLk-1); + } + stillToFetch = 0; + } +#else + return; +#endif + +} + +int ANTLRParser::isDeferFetchEnabled() +{ +#ifdef ZZDEFER_FETCH + return 1; +#else + return 0; +#endif +} + +//MR23 +int ANTLRParser::printMessage(FILE* pFile, const char* pFormat, ...) +{ + va_list marker; + va_start( marker, pFormat ); + int iRet = printMessageV(pFile, pFormat, marker); + va_end( marker ); + return iRet; +} + +int ANTLRParser::printMessageV(FILE* pFile, const char* pFormat, va_list arglist) // MR23 +{ + return vfprintf(pFile, pFormat, arglist); +} + +// MR23 Move semantic predicate error handling from macro to virtual function +// +// Called by the zzfailed_pred + +void ANTLRParser::failedSemanticPredicate(const char* predicate) +{ + printMessage(stdout,"line %d: semantic error; failed predicate: '%s'\n", + LT(1)->getLine(), predicate); +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/AParser.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/AParser.h new file mode 100644 index 00000000..659f8b2c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/AParser.h @@ -0,0 +1,376 @@ +/* ANTLRParser.h + * + * Define the generic ANTLRParser superclass, which is subclassed to + * define an actual parser. + * + * Before entry into this file: ANTLRTokenType must be set. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef APARSER_H_GATE +#define APARSER_H_GATE + +#include "pcctscfg.h" + +#include "pccts_stdio.h" +#include "pccts_setjmp.h" + +PCCTS_NAMESPACE_STD + +#include ATOKEN_H +#include ATOKENBUFFER_H + +#ifdef ZZCAN_GUESS +#ifndef ZZINF_LOOK +#define ZZINF_LOOK +#endif +#endif + + +#define NLA (token_type[lap&(LLk-1)])/* --> next LA */ + +typedef unsigned char SetWordType; + +/* Define external bit set stuff (for SetWordType) */ +#define EXT_WORDSIZE (sizeof(char)*8) +#define EXT_LOGWORDSIZE 3 + + /* s y n t a c t i c p r e d i c a t e s t u f f */ + +#ifndef zzUSER_GUESS_HOOK +#define zzUSER_GUESS_HOOK(seqFrozen,zzrv) +#endif + +#ifndef zzUSER_GUESS_DONE_HOOK +#define zzUSER_GUESS_DONE_HOOK(seqFrozen) +#endif + +/* MR14 Add zzUSER_GUESS_FAIL_HOOK and related code */ + +#define zzUSER_GUESS_FAIL_HOOK_INTERNAL zzUSER_GUESS_FAIL_HOOK(SeqFrozen) +#ifndef zzUSER_GUESS_FAIL_HOOK +#define zzUSER_GUESS_FAIL_HOOK(zzGuessSeq) +#endif + + +typedef struct _zzjmp_buf { + jmp_buf state; + } zzjmp_buf; + +/* these need to be macros not member functions */ +#define zzGUESS_BLOCK ANTLRParserState zzst; int zzrv; int _marker; int zzGuessSeqFrozen; +#define zzNON_GUESS_MODE if ( !guessing ) +#define zzGUESS_FAIL guess_fail(); + +/* Note: zzGUESS_DONE does not execute longjmp() */ + +#define zzGUESS_DONE {zzrv=1; inputTokens->rewind(_marker); guess_done(&zzst);zzUSER_GUESS_DONE_HOOK(zzGuessSeqFrozen) } +#define zzGUESS saveState(&zzst); \ + guessing = 1; \ + zzGuessSeqFrozen = ++zzGuessSeq; \ + _marker = inputTokens->mark(); \ + zzrv = setjmp(guess_start.state); \ + zzUSER_GUESS_HOOK(zzGuessSeqFrozen,zzrv) \ + if ( zzrv ) zzGUESS_DONE + +#define zzTRACEdata const ANTLRChar *zzTracePrevRuleName = NULL; + +#ifndef zzTRACEIN +#define zzTRACEIN(r) zzTracePrevRuleName=traceCurrentRuleName;tracein(r); +#endif +#ifndef zzTRACEOUT +#define zzTRACEOUT(r) traceout(r);traceCurrentRuleName=zzTracePrevRuleName; +#endif + + /* a n t l r p a r s e r d e f */ + +struct ANTLRParserState { + /* class variables */ + zzjmp_buf guess_start; + int guessing; + + int inf_labase; + int inf_last; + + int dirty; + + int traceOptionValue; // MR10 + int traceGuessOptionValue; // MR10 + const ANTLRChar *traceCurrentRuleName; // MR10 + int traceDepth; // MR10 + +}; + +/* notes: + * + * multiple inheritance is a cool way to include what stuff is needed + * in this structure (like guess stuff). however, i'm not convinced that + * multiple inheritance works correctly on all platforms. not that + * much space is used--just include all possibly useful members. + * + * the class should also be a template with arguments for the lookahead + * depth and so on. that way, more than one parser can be defined (as + * each will probably have different lookahead requirements). however, + * am i sure that templates work? no, i'm not sure. + * + * no attributes are maintained and, hence, the 'asp' variable is not + * needed. $i can still be referenced, but it refers to the token + * associated with that rule element. question: where are the token's + * stored if not on the software stack? in local variables created + * and assigned to by antlr. + */ +class ANTLRParser { +protected: + /* class variables */ + static SetWordType bitmask[sizeof(SetWordType)*8]; + static char eMsgBuffer[500]; + +protected: + int LLk; // number of lookahead symbols (old LL_K) + int demand_look; + ANTLRTokenType eofToken; // when do I stop during resynch()s + int bsetsize; // size of bitsets created by ANTLR in + // units of SetWordType + + ANTLRTokenBuffer *inputTokens; //place to get input tokens + + zzjmp_buf guess_start; // where to jump back to upon failure + int guessing; // if guessing (using (...)? predicate) + + // infinite lookahead stuff + int can_use_inf_look; // set by subclass (generated by ANTLR) + int inf_lap; + int inf_labase; + int inf_last; + int *_inf_line; + + const ANTLRChar **token_tbl; // pointer to table of token type strings MR20 const + + int dirty; // used during demand lookahead + + ANTLRTokenType *token_type; // fast reference cache of token.getType() +// ANTLRLightweightToken **token; // the token with all its attributes + int lap; + int labase; +#ifdef ZZDEFER_FETCH + int stillToFetch; // MR19 V.H. Simonis +#endif + +private: + void fill_inf_look(); + +protected: + virtual void guess_fail() { // MR9 27-Sep-97 make virtual + traceGuessFail(); // MR10 + longjmp(guess_start.state, 1); } // MR9 + virtual void guess_done(ANTLRParserState *st) { // MR9 27-Sep-97 make virtual + restoreState(st); } // MR9 + virtual int guess(ANTLRParserState *); // MR9 27-Sep-97 make virtual + void look(int); + int _match(ANTLRTokenType, ANTLRChar **, ANTLRTokenType *, + _ANTLRTokenPtr *, SetWordType **); + int _setmatch(SetWordType *, ANTLRChar **, ANTLRTokenType *, + _ANTLRTokenPtr *, SetWordType **, + SetWordType * tokclassErrset /* MR23 */); + int _match_wsig(ANTLRTokenType); + int _setmatch_wsig(SetWordType *); + virtual void consume(); + virtual void resynch(SetWordType *wd,SetWordType mask); // MR21 + void prime_lookahead(); + virtual void tracein(const ANTLRChar *r); // MR10 + virtual void traceout(const ANTLRChar *r); // MR10 + static unsigned MODWORD(unsigned x) {return x & (EXT_WORDSIZE-1);} // x % EXT_WORDSIZE // MR9 + static unsigned DIVWORD(unsigned x) {return x >> EXT_LOGWORDSIZE;} // x / EXT_WORDSIZE // MR9 + int set_deg(SetWordType *); + int set_el(ANTLRTokenType, SetWordType *); + virtual void edecode(SetWordType *); // MR1 + virtual void FAIL(int k, ...); // MR1 + int traceOptionValue; // MR10 + int traceGuessOptionValue; // MR10 + const ANTLRChar *traceCurrentRuleName; // MR10 + int traceDepth; // MR10 + void traceReset(); // MR10 + virtual void traceGuessFail(); // MR10 + virtual void traceGuessDone(const ANTLRParserState *); // MR10 + int zzGuessSeq; // MR10 + +public: + ANTLRParser(ANTLRTokenBuffer *, + int k=1, + int use_inf_look=0, + int demand_look=0, + int bsetsize=1); + virtual ~ANTLRParser(); + + virtual void init(); + + ANTLRTokenType LA(int i) + { +// +// MR14 demand look will always be 0 for C++ mode +// +//// return demand_look ? token_type[(labase+(i)-1)&(LLk-1)] : +//// token_type[(lap+(i)-1)&(LLk-1)]; + +// MR19 V.H. Simonis Defer fetch feature + +#ifdef ZZDEFER_FETCH + undeferFetch(); +#endif + return token_type[(lap+(i)-1)&(LLk-1)]; + } + _ANTLRTokenPtr LT(int i); + + void setEofToken(ANTLRTokenType t) { eofToken = t; } + ANTLRTokenType getEofToken() const { return eofToken; } // MR14 + + void noGarbageCollectTokens() { inputTokens->noGarbageCollectTokens(); } + void garbageCollectTokens() { inputTokens->garbageCollectTokens(); } + + virtual void syn(_ANTLRTokenPtr tok, ANTLRChar *egroup, + SetWordType *eset, ANTLRTokenType etok, int k); + virtual void saveState(ANTLRParserState *); // MR9 27-Sep-97 make virtual + virtual void restoreState(ANTLRParserState *); // MR9 27-Sep-97 make virtual + + virtual void panic(const char *msg); // MR20 const + + static char *eMsgd(char *,int); + static char *eMsg(char *,char *); + static char *eMsg2(char *,char *,char *); + + virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23 + virtual int printMessageV(FILE* pFile, const char* pFormat, va_list arglist); // MR23 + + void consumeUntil(SetWordType *st); + void consumeUntilToken(int t); + + virtual int _setmatch_wdfltsig(SetWordType *tokensWanted, + ANTLRTokenType tokenTypeOfSet, + SetWordType *whatFollows); + virtual int _match_wdfltsig(ANTLRTokenType tokenWanted, + SetWordType *whatFollows); + + const ANTLRChar * parserTokenName(int tok); // MR1 + + int traceOptionValueDefault; // MR11 + int traceOption(int delta); // MR11 + int traceGuessOption(int delta); // MR11 + +// MR8 5-Aug-97 S.Bochnak@microtool.com.pl +// MR8 Move resynch static local variable +// MR8 to class instance + + int syntaxErrCount; // MR12 + ANTLRTokenStream *getLexer() const { // MR12 + return inputTokens ? inputTokens->getLexer() : 0; } // MR12 +protected: // MR8 + int resynchConsumed; // MR8 + char *zzFAILtext; // workarea required by zzFAIL // MR9 + void undeferFetch(); // MR19 V.H. Simonis + int isDeferFetchEnabled(); // MR19 V.H. Simonis + virtual void failedSemanticPredicate(const char* predicate); /* MR23 */ +}; + +#define zzmatch(_t) \ + if ( !_match((ANTLRTokenType)_t, &zzMissText, &zzMissTok, \ + (_ANTLRTokenPtr *) &zzBadTok, &zzMissSet) ) goto fail; + +#define zzmatch_wsig(_t,handler) \ + if ( !_match_wsig((ANTLRTokenType)_t) ) if ( guessing ) zzGUESS_FAIL else {_signal=MismatchedToken; goto handler;} + +#define zzsetmatch(_ts,_tokclassErrset) \ + if ( !_setmatch(_ts, &zzMissText, &zzMissTok, \ + (_ANTLRTokenPtr *) &zzBadTok, &zzMissSet, _tokclassErrset) ) goto fail; + +#define zzsetmatch_wsig(_ts, handler) \ + if ( !_setmatch_wsig(_ts) ) if ( guessing ) zzGUESS_FAIL else {_signal=MismatchedToken; goto handler;} + +/* For the dflt signal matchers, a FALSE indicates that an error occurred + * just like the other matchers, but in this case, the routine has already + * recovered--we do NOT want to consume another token. However, when + * the match was successful, we do want to consume hence _signal=0 so that + * a token is consumed by the "if (!_signal) consume(); _signal=NoSignal;" + * preamble. + */ +#define zzsetmatch_wdfltsig(tokensWanted, tokenTypeOfSet, whatFollows) \ + if ( !_setmatch_wdfltsig(tokensWanted, tokenTypeOfSet, whatFollows) ) \ + _signal = MismatchedToken; + +#define zzmatch_wdfltsig(tokenWanted, whatFollows) \ + if ( !_match_wdfltsig(tokenWanted, whatFollows) ) _signal = MismatchedToken; + + +// MR1 10-Apr-97 zzfailed_pred() macro does not backtrack in guess mode. +// MR1 Identification and correction due to J. Lilley +// +// MR23 Call virtual method to report error. +// MR23 Provide more control over failed predicate action +// without any need for user to worry about guessing internals. + +#ifndef zzfailed_pred +#define zzfailed_pred(_p,_hasuseraction,_useraction) \ + if (guessing) { \ + zzGUESS_FAIL; \ + } else { \ + zzfailed_pred_action(_p,_hasuseraction,_useraction) \ + } +#endif + +// MR23 Provide more control over failed predicate action +// without any need for user to worry about guessing internals. +// _hasuseraction == 0 => no user specified error action +// _hasuseraction == 1 => user specified error action + +#ifndef zzfailed_pred_action +#define zzfailed_pred_action(_p,_hasuseraction,_useraction) \ + if (_hasuseraction) { _useraction } else { failedSemanticPredicate(_p); } +#endif + +#define zzRULE \ + SetWordType *zzMissSet=NULL; ANTLRTokenType zzMissTok=(ANTLRTokenType)0; \ + _ANTLRTokenPtr zzBadTok=NULL; ANTLRChar *zzBadText=(ANTLRChar *)""; \ + int zzErrk=1,zzpf=0; \ + zzTRACEdata \ + ANTLRChar *zzMissText=(ANTLRChar *)""; + +#endif + + /* S t a n d a r d E x c e p t i o n S i g n a l s */ + +#define NoSignal 0 +#define MismatchedToken 1 +#define NoViableAlt 2 +#define NoSemViableAlt 3 + +/* MR7 Allow more control over signalling */ +/* by adding "Unwind" and "SetSignal" */ + +#define Unwind 4 +#define setSignal(newValue) *_retsignal=_signal=(newValue) +#define suppressSignal *_retsignal=_signal=0 +#define exportSignal *_retsignal=_signal diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ASTBase.cpp b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ASTBase.cpp new file mode 100644 index 00000000..a3cf8c0a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ASTBase.cpp @@ -0,0 +1,256 @@ +/* Abstract syntax tree manipulation functions + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#include "pcctscfg.h" + +#include "pccts_stdio.h" +#include "pccts_stdarg.h" + +PCCTS_NAMESPACE_STD + +#define ANTLR_SUPPORT_CODE + +#include "ASTBase.h" + +/* ensure that tree manipulation variables are current after a rule + * reference + */ +void +ASTBase::link(ASTBase **_root, ASTBase **_sibling, ASTBase **_tail) +{ + if ( *_sibling == NULL ) return; + if ( *_root == NULL ) *_root = *_sibling; + else if ( *_root != *_sibling ) (*_root)->_down = *_sibling; + if ( *_tail==NULL ) *_tail = *_sibling; + while ( (*_tail)->_right != NULL ) *_tail = (*_tail)->_right; +} + +/* add a child node to the current sibling list */ +void +ASTBase::subchild(ASTBase **_root, ASTBase **_sibling, ASTBase **_tail) +{ + if ( *_tail != NULL ) (*_tail)->_right = this; + else { + *_sibling = this; + if ( *_root != NULL ) (*_root)->_down = *_sibling; + } + *_tail = this; + if ( *_root == NULL ) *_root = *_sibling; +} + +/* make a new AST node. Make the newly-created + * node the root for the current sibling list. If a root node already + * exists, make the newly-created node the root of the current root. + */ +void +ASTBase::subroot(ASTBase **_root, ASTBase **_sibling, ASTBase **_tail) +{ + if ( *_root != NULL ) + if ( (*_root)->_down == *_sibling ) *_sibling = *_tail = *_root; + *_root = this; + (*_root)->_down = *_sibling; +} + +/* Apply preorder_action(), etc.. to root then each sibling */ +// +// 7-Apr-97 133MR1 +// Fix suggested by Ron House (house@helios.usq.edu.au) +// +void +ASTBase::preorder(void* pData /*= NULL*/ /* MR23 */) +{ + ASTBase *tree = this; + + while ( tree!= NULL ) + { + if ( tree->_down != NULL ) { + tree->preorder_before_action(pData); // MR1 + }; + tree->preorder_action(pData); + if ( tree->_down!=NULL ) + { + tree->_down->preorder(pData); + tree->preorder_after_action(pData); // MR1 + } + tree = tree->_right; + } +} + +/* free all AST nodes in tree; apply func to each before freeing */ +void +ASTBase::destroy() +{ + ASTBase* tree = this; + while (tree) { + if (tree->_down) tree->_down->destroy(); + + ASTBase* cur = tree; + tree = tree->_right; + delete cur; + } +} + +/* build a tree (root child1 child2 ... NULL) + * If root is NULL, simply make the children siblings and return ptr + * to 1st sibling (child1). If root is not single node, return NULL. + * + * Siblings that are actually siblins lists themselves are handled + * correctly. For example #( NULL, #( NULL, A, B, C), D) results + * in the tree ( NULL A B C D ). + * + * Requires at least two parameters with the last one being NULL. If + * both are NULL, return NULL. + */ +ASTBase * +ASTBase::tmake(ASTBase *root, ...) +{ + va_list ap; + register ASTBase *child, *sibling=NULL, *tail=NULL /*MR23*/, *w; + + va_start(ap, root); + + if ( root != NULL ) + if ( root->_down != NULL ) { + root->reportOverwriteOfDownPointer(); /* MR21 Report problem which almost always an error */ + return NULL; + } + child = va_arg(ap, ASTBase *); + while ( child != NULL ) + { + for (w=child; w->_right!=NULL; w=w->_right) {;} /* find end of child */ + if ( sibling == NULL ) {sibling = child; tail = w;} + else {tail->_right = child; tail = w;} + child = va_arg(ap, ASTBase *); + } + if ( root==NULL ) root = sibling; + else root->_down = sibling; + va_end(ap); + return root; +} + +#ifndef PCCTS_NOT_USING_SOR + +/* tree duplicate */ +// forgot to check for NULL this (TJP July 23,1995) +ASTBase * +ASTBase::dup() +{ + ASTBase *u, *t=this; + + if ( t == NULL ) return NULL; +/* + u = new ASTBase; + *u = *t; +*/ + u = (ASTBase *)this->shallowCopy(); + if ( t->_right!=NULL ) u->_right = t->_right->dup(); + else u->_right = NULL; + if ( t->_down!=NULL ) u->_down = t->_down->dup(); + else u->_down = NULL; + return u; +} +#endif + +// +// 7-Apr-97 133MR1 +// Fix suggested by Asgeir Olafsson (olafsson@cstar.ac.com) +// +/* tree duplicate */ + +#ifndef PCCTS_NOT_USING_SOR + +ASTBase * +ASTDoublyLinkedBase::dup() +{ + ASTDoublyLinkedBase *u, *t=this; + + if ( t == NULL ) return NULL; + u = (ASTDoublyLinkedBase *)this->shallowCopy(); + u->_up = NULL; /* set by calling invocation */ + u->_left = NULL; + if (t->_right!=NULL) { // MR1 + u->_right=t->_right->dup(); // MR1 + ((ASTDoublyLinkedBase *)u->_right)->_left = u; // MR1 + } else { // MR1 + u->_right = NULL; // MR1 + }; // MR1 + if (t->_down!=NULL) { // MR1 + u->_down = t->_down->dup(); // MR1 + ((ASTDoublyLinkedBase *)u->_down)->_up = u; // MR1 + } else { // MR1 + u->_down = NULL; // MR1 + }; // MR1 + return u; +} + +#endif + +/* + * Set the 'up', and 'left' pointers of all nodes in 't'. + * Initial call is double_link(your_tree, NULL, NULL). + */ +void +ASTDoublyLinkedBase::double_link(ASTBase *left, ASTBase *up) +{ + ASTDoublyLinkedBase *t = this; + + t->_left = (ASTDoublyLinkedBase *) left; + t->_up = (ASTDoublyLinkedBase *) up; + if (t->_down != NULL) + ((ASTDoublyLinkedBase *)t->_down)->double_link(NULL, t); + if (t->_right != NULL) + ((ASTDoublyLinkedBase *)t->_right)->double_link(t, up); +} + +// MR21 ASTBase::reportOverwriteOfDownPointer + +void ASTBase::reportOverwriteOfDownPointer() +{ + panic("Attempt to overwrite down pointer in ASTBase::tmake"); +} + +// MR21 ASTBase::panic + +void ASTBase::panic(const char *msg) +{ + /* MR23 */ printMessage(stderr,"ASTBase panic: %s\n", msg); + exit(PCCTS_EXIT_FAILURE); +} + +#ifdef PCCTS_NOT_USING_SOR +//MR23 +int ASTBase::printMessage(FILE* pFile, const char* pFormat, ...) +{ + va_list marker; + va_start( marker, pFormat ); + int iRet = vfprintf(pFile, pFormat, marker); + va_end( marker ); + return iRet; +} +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ASTBase.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ASTBase.h new file mode 100644 index 00000000..9085fe57 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ASTBase.h @@ -0,0 +1,122 @@ +/* Abstract syntax tree + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ASTBase_H +#define ASTBase_H + +#include "pcctscfg.h" + +#include "pccts_stdio.h" +#include "pccts_stdlib.h" + +PCCTS_NAMESPACE_STD + +#ifndef PCCTS_NOT_USING_SOR +#include "PCCTSAST.h" +#endif + +/* + * Notes: + * + * To specify a copy constructor, subclass one of these classes and + * give the copy constructor. To use dup(), you must define shallowCopy(). + * shallowCopy() can use either a copy constructor or just copy the node + * itself. + */ + +#ifdef PCCTS_NOT_USING_SOR +class DllExportPCCTS ASTBase { +#else +class DllExportPCCTS ASTBase : public PCCTS_AST { +#endif + +protected: + ASTBase *_right, *_down; + +public: + +#ifdef PCCTS_NOT_USING_SOR + ASTBase *right() { return _right; } + ASTBase *down() { return _down; } + void setRight(ASTBase *t) { _right = (ASTBase *)t; } + void setDown(ASTBase *t) { _down = (ASTBase *)t; } +#else + PCCTS_AST *right() { return _right; } // define the SORCERER interface + PCCTS_AST *down() { return _down; } + void setRight(PCCTS_AST *t) { _right = (ASTBase *)t; } + void setDown(PCCTS_AST *t) { _down = (ASTBase *)t; } +#endif + ASTBase() { _right = _down = NULL; } + virtual ~ASTBase() { ; } +#ifndef PCCTS_NOT_USING_SOR + virtual ASTBase *dup(); +#endif + void destroy(); + void preorder(void* pData = NULL /* MR23 */); + static ASTBase *tmake(ASTBase *, ...); + static void link(ASTBase **, ASTBase **, ASTBase **); + void subchild(ASTBase **, ASTBase **, ASTBase **); + void subroot(ASTBase **, ASTBase **, ASTBase **); + virtual void preorder_action(void* /*pData*/ = NULL /* MR23 */) { ; } + virtual void preorder_before_action(void* /*pData*/ = NULL /* MR23 */) { /* MR23 */ printMessage(stdout, " ("); } + virtual void preorder_after_action(void* /*pData*/ = NULL /* MR23 */) { /* MR23 */ printMessage(stdout, " )"); } + virtual void panic(const char *msg); /* MR21 */ + virtual void reportOverwriteOfDownPointer(); /* MR21 */ +#ifdef PCCTS_NOT_USING_SOR + virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23 +#endif +}; + +class DllExportPCCTS ASTDoublyLinkedBase : public ASTBase { +protected: + ASTDoublyLinkedBase *_left, *_up; + +public: + void double_link(ASTBase *left, ASTBase *up); + +#ifndef PCCTS_NOT_USING_SOR + virtual ASTBase *dup(); +#endif + +#ifdef PCCTS_NOT_USING_SOR + ASTBase *left() { return _left; } + ASTBase *up() { return _up; } + void setLeft(ASTBase *t) { _left = (ASTDoublyLinkedBase *)t; } // MR6 + void setUp(ASTBase *t) { _up = (ASTDoublyLinkedBase *)t; } // MR6 +#else + PCCTS_AST *left() { return _left; } + PCCTS_AST *up() { return _up; } + void setLeft(PCCTS_AST *t) { _left = (ASTDoublyLinkedBase *)t; } // MR6 + void setUp(PCCTS_AST *t) { _up = (ASTDoublyLinkedBase *)t; } // MR6 +#endif + +}; + +class AST; // announce that this class will be coming along shortly +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokPtr.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokPtr.h new file mode 100644 index 00000000..5ccc8376 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokPtr.h @@ -0,0 +1,88 @@ +/* ATokPtr.h + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Written by Russell Quong June 30, 1995 + * Adapted by Terence Parr to ANTLR stuff + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ATokPtr_h +#define ATokPtr_h + +#include "pcctscfg.h" + +#include "pccts_stdio.h" + +PCCTS_NAMESPACE_STD + +// pointer to a reference counted object +// robust in that an unused ANTLRTokenPtr can point to NULL. + +class ANTLRAbstractToken; + +class DllExportPCCTS ANTLRTokenPtr { +public: + ANTLRTokenPtr(ANTLRAbstractToken *addr=NULL){ptr_ = addr; ref();} + ANTLRTokenPtr(const ANTLRTokenPtr &lhs) {ptr_ = lhs.ptr_; lhs.ref();} + ~ANTLRTokenPtr(); + + // use ANTLRTokenPtr as a pointer to ANTLRToken +// +// 8-Apr-97 MR1 Make operator -> a const member function +// as well as some other member functions +// + ANTLRAbstractToken *operator-> () const { return ptr_; } // MR1 +// +// 7-Apr-97 133MR1 +// Fix suggested by Andreas Magnusson +// (Andreas.Magnusson@mailbox.swipnet.se) + ANTLRTokenPtr& operator = (const ANTLRTokenPtr & lhs); // MR1 + ANTLRTokenPtr& operator = (ANTLRAbstractToken *addr); + int operator != (const ANTLRTokenPtr &q) const // MR1 // MR11 unsigned -> int + { return this->ptr_ != q.ptr_; } + int operator == (const ANTLRTokenPtr &q) const // MR1 // MR11 unsigned -> int + { return this->ptr_ == q.ptr_; } + int operator == (const ANTLRAbstractToken *addr) const // MR11 + { return this->ptr_ == addr; } + int operator != (const ANTLRAbstractToken *addr) const // MR11 + { return this->ptr_ != addr; } + + void ref() const; + void deref(); + +protected: + ANTLRAbstractToken *ptr_; +}; + +//typedef ANTLRTokenPtr _ANTLRTokenPtr; + +/* + * Since you cannot redefine operator->() to return one of the user's + * token object types, we must down cast. This is a drag. Here's + * a macro that helps. template: "mytoken(a-smart-ptr)->myfield". + */ +#define mytoken(tk) ((ANTLRToken *)(tk.operator->())) + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokPtrImpl.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokPtrImpl.h new file mode 100644 index 00000000..48d2e18a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokPtrImpl.h @@ -0,0 +1,90 @@ +/* + * ATokPtrImpl.h (formerly ATokPtr.cpp) + * + * This is #included in ATokBuffer.cpp for historical reasons. + * It has been renamed because of problems with the .cpp extension + * when used with IDE. + * + * + * ANTLRToken MUST be defined before entry to this file. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Written by Russell Quong June 30, 1995 + * Adapted by Terence Parr to ANTLR stuff + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#include "pcctscfg.h" + +PCCTS_NAMESPACE_STD + +#include "ATokPtr.h" + +void ANTLRTokenPtr::ref() const +{ + if (ptr_ != NULL) { + ptr_->ref(); + } +} + +void ANTLRTokenPtr::deref() +{ + if (ptr_ != NULL) + { + ptr_->deref(); + if ( ptr_->nref()==0 ) + { + delete ptr_; + ptr_ = NULL; + } + } +} + +ANTLRTokenPtr::~ANTLRTokenPtr() +{ + deref(); +} + +// +// 8-Apr-97 MR1 Make operator -> a const member function +// as well as some other member functions +// +ANTLRTokenPtr& ANTLRTokenPtr::operator = (const ANTLRTokenPtr & lhs) // MR1 +{ + lhs.ref(); // protect against "xp = xp"; ie same underlying object + deref(); + ptr_ = lhs.ptr_; + return *this; +} + +ANTLRTokenPtr& ANTLRTokenPtr::operator = (ANTLRAbstractToken *addr) +{ + if (addr != NULL) { + addr->ref(); + } + deref(); + ptr_ = addr; + return *this; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/AToken.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/AToken.h new file mode 100644 index 00000000..a6360124 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/AToken.h @@ -0,0 +1,325 @@ +/* ANTLRToken.h + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ATOKEN_H_GATE +#define ATOKEN_H_GATE + +#include "pcctscfg.h" + +#include "pccts_string.h" +#include "pccts_stdio.h" +#include "pccts_stdlib.h" +#include "pccts_stdarg.h" // MR23 + +PCCTS_NAMESPACE_STD + +// MR9 RJV (JVincent@novell.com) Not needed for variable length strings + +//// MR9 #ifndef ANTLRCommonTokenTEXTSIZE +//// MR9 #define ANTLRCommonTokenTEXTSIZE 100 +//// MR9 #endif + + +/* must define what a char looks like; can make this a class too */ +typedef char ANTLRChar; + +/* D E F I N E S M A R T P O I N T E R S */ + +//#include ATOKPTR_H not tested yet, leave out +class ANTLRAbstractToken; +typedef ANTLRAbstractToken *_ANTLRTokenPtr; + +class ANTLRAbstractToken { +public: + virtual ~ANTLRAbstractToken() {;} + virtual ANTLRTokenType getType() const = 0; + virtual void setType(ANTLRTokenType t) = 0; + virtual int getLine() const = 0; + virtual void setLine(int line) = 0; + virtual ANTLRChar *getText() const = 0; + virtual void setText(const ANTLRChar *) = 0; + + /* This function will disappear when I can use templates */ + virtual ANTLRAbstractToken *makeToken(ANTLRTokenType tt, + ANTLRChar *text, + int line) = 0; + + /* define to satisfy ANTLRTokenBuffer's need to determine whether or + not a token object can be destroyed. If nref()==0, no one has + a reference, and the object may be destroyed. This function defaults + to 1, hence, if you use deleteTokens() message with a token object + not derived from ANTLRCommonRefCountToken, the parser will compile + but will not delete objects after they leave the token buffer. + */ + + virtual unsigned nref() const { return 1; } // MR11 + virtual void ref() {;} + virtual void deref() {;} + + virtual void panic(const char *msg) // MR20 const + { + /* MR23 */ printMessage(stderr, "ANTLRAbstractToken panic: %s\n", msg); + exit(PCCTS_EXIT_FAILURE); + } + + virtual int printMessage(FILE* pFile, const char* pFormat, ...) // MR23 + { + va_list marker; + va_start( marker, pFormat ); + int iRet = vfprintf(pFile, pFormat, marker); + va_end( marker ); + return iRet; + } +}; + +/* This class should be subclassed. It cannot store token type or text */ + +class ANTLRRefCountToken : public ANTLRAbstractToken { +public: +#ifdef DBG_REFCOUNTTOKEN + static int ctor; + static int dtor; +#endif +protected: + unsigned refcnt_; +#ifdef DBG_REFCOUNTTOKEN + char object[200]; +#endif + +public: + + // MR23 - No matter what you do, you're hammered. + // Don't give names to formals something breaks. + // Give names to formals and don't use them it breaks. + +#ifndef DBG_REFCOUNTTOKEN + ANTLRRefCountToken(ANTLRTokenType /* t MR23 */, const ANTLRChar * /* s MR23 */) +#else + ANTLRRefCountToken(ANTLRTokenType t, const ANTLRChar * s) +#endif + +#ifndef DBG_REFCOUNTTOKEN + { + refcnt_ = 0; + } +#else + { + ctor++; + refcnt_ = 0; + if ( t==1 ) sprintf(object,"tok_EOF"); + else sprintf(object,"tok_%s",s); + /* MR23 */ printMessage(stderr, "ctor %s #%d\n",object,ctor); + } +#endif + ANTLRRefCountToken() +#ifndef DBG_REFCOUNTTOKEN + { refcnt_ = 0; } +#else + { + ctor++; + refcnt_ = 0; + sprintf(object,"tok_blank"); + /* MR23 */ printMessage(stderr, "ctor %s #%d\n",object,ctor); + } + virtual ~ANTLRRefCountToken() + { + dtor++; + if ( dtor>ctor ) /* MR23 */ printMessage(stderr, "WARNING: dtor>ctor\n"); + /* MR23 */ printMessage(stderr, "dtor %s #%d\n", object, dtor); + object[0]='\0'; + } +#endif + + // reference counting stuff needed by ANTLRTokenPtr. + // User should not access these; for C++ language reasons, we had + // to make these public. Yuck. + + void ref() { refcnt_++; } + void deref() { refcnt_--; } + unsigned nref() const { return refcnt_; } // MR11 + + virtual ANTLRAbstractToken *makeToken(ANTLRTokenType /*tt MR23*/, + ANTLRChar * /*txt MR23*/, + int /*line MR23*/) + { + panic("call to ANTLRRefCountToken::makeToken()\n"); + return NULL; + } +}; + +class ANTLRCommonNoRefCountToken : public ANTLRAbstractToken { +protected: + ANTLRTokenType _type; + int _line; + ANTLRChar *_text; // MR9 RJV + +public: + ANTLRCommonNoRefCountToken(ANTLRTokenType t, const ANTLRChar *s) + { setType(t); _line = 0; _text = NULL; setText(s); } + ANTLRCommonNoRefCountToken() + { setType((ANTLRTokenType)0); _line = 0; _text = NULL; setText(""); } + + ~ANTLRCommonNoRefCountToken() { if (_text) delete [] _text; } // MR9 RJV: Added Destructor to remove string + + ANTLRTokenType getType() const { return _type; } + void setType(ANTLRTokenType t) { _type = t; } + virtual int getLine() const { return _line; } + void setLine(int line) { _line = line; } + ANTLRChar *getText() const { return _text; } + int getLength() const { return strlen(getText()); } // MR11 + +// MR9 RJV: Added code for variable length strings to setText() + + void setText(const ANTLRChar *s) + { if (s != _text) { + if (_text) delete [] _text; + if (s != NULL) { + _text = new ANTLRChar[strlen(s)+1]; + if (_text == NULL) panic("ANTLRCommonNoRefCountToken::setText new failed"); + strcpy(_text,s); + } else { + _text = new ANTLRChar[1]; + if (_text == NULL) panic("ANTLRCommonNoRefCountToken::setText new failed"); + strcpy(_text,""); + }; + }; + } + + virtual ANTLRAbstractToken *makeToken(ANTLRTokenType tt, + ANTLRChar *txt, + int line) + { + ANTLRAbstractToken *t = new ANTLRCommonNoRefCountToken; + t->setType(tt); t->setText(txt); t->setLine(line); + return t; + } + +// MR9 THM Copy constructor required when heap allocated string is used with copy semantics + + ANTLRCommonNoRefCountToken (const ANTLRCommonNoRefCountToken& from) : + ANTLRAbstractToken(from) { + setType(from._type); + setLine(from._line); + _text=NULL; + setText(from._text); + }; + +// MR9 THM operator =() required when heap allocated string is used with copy semantics + + virtual ANTLRCommonNoRefCountToken& operator =(const ANTLRCommonNoRefCountToken& rhs) { + +////// MR15 WatCom can't hack use of operator =() +////// Use this: *( (ANTRLAbstractToken *) this)=rhs; + + *( (ANTLRAbstractToken *) this ) = rhs; + + setType(rhs._type); + setLine(rhs._line); + setText(rhs._text); + return *this; + }; +}; + +class ANTLRCommonToken : public ANTLRRefCountToken { +protected: + ANTLRTokenType _type; + int _line; + ANTLRChar *_text; // MR9 RJV:Added + +public: + ANTLRCommonToken(ANTLRTokenType t, const ANTLRChar *s) : ANTLRRefCountToken(t,s) + { setType(t); _line = 0; _text = NULL; setText(s); } // MR9 + ANTLRCommonToken() + { setType((ANTLRTokenType)0); _line = 0; _text = NULL; setText(""); } // MR9 + + virtual ~ANTLRCommonToken() { if (_text) delete [] _text; } // MR9 RJV: Added Destructor to remove string + + ANTLRTokenType getType() const { return _type; } + void setType(ANTLRTokenType t) { _type = t; } + virtual int getLine() const { return _line; } + void setLine(int line) { _line = line; } + ANTLRChar *getText() const { return _text; } + int getLength() const { return strlen(getText()); } // MR11 + +// MR9 RJV: Added code for variable length strings to setText() + + void setText(const ANTLRChar *s) + { if (s != _text) { + if (_text) delete [] _text; + if (s != NULL) { + _text = new ANTLRChar[strlen(s)+1]; + if (_text == NULL) panic("ANTLRCommonToken::setText new failed"); + strcpy(_text,s); + } else { + _text = new ANTLRChar[1]; + if (_text == NULL) panic("ANTLRCommonToken::setText new failed"); + strcpy(_text,""); + }; + }; + } + + virtual ANTLRAbstractToken *makeToken(ANTLRTokenType tt, + ANTLRChar *txt, + int line) + { + ANTLRAbstractToken *t = new ANTLRCommonToken(tt,txt); + t->setLine(line); + return t; + } + +// MR9 THM Copy constructor required when heap allocated string is used with copy semantics + + ANTLRCommonToken (const ANTLRCommonToken& from) : + ANTLRRefCountToken(from) { + setType(from._type); + setLine(from._line); + _text=NULL; + setText(from._text); + }; + +// MR9 THM operator =() required when heap allocated string is used with copy semantics + + virtual ANTLRCommonToken& operator =(const ANTLRCommonToken& rhs) { + +////// MR15 WatCom can't hack use of operator =() +////// Use this instead: *( (ANTRLRRefCountToken *) this)=rhs; + + *( (ANTLRRefCountToken *) this) = rhs; + + setType(rhs._type); + setLine(rhs._line); + setText(rhs._text); + return *this; + }; +}; + +// used for backward compatibility +typedef ANTLRCommonToken ANTLRCommonBacktrackingToken; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenBuffer.cpp b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenBuffer.cpp new file mode 100644 index 00000000..86073d54 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenBuffer.cpp @@ -0,0 +1,374 @@ +/* ANTLRTokenBuffer.cpp + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +typedef int ANTLRTokenType; // fool AToken.h into compiling + +class ANTLRParser; /* MR1 */ + +#define ANTLR_SUPPORT_CODE + +#include "pcctscfg.h" + +#include ATOKENBUFFER_H +#include APARSER_H // MR23 + +typedef ANTLRAbstractToken *_ANTLRTokenPtr; + +#if defined(DBG_TBUF)||defined(DBG_TBUF_MARK_REW) +static unsigned char test[1000]; +#endif + +#ifdef DBG_REFCOUNTTOKEN +int ANTLRRefCountToken::ctor = 0; /* MR23 */ +int ANTLRRefCountToken::dtor = 0; /* MR23 */ +#endif + +ANTLRTokenBuffer:: +ANTLRTokenBuffer(ANTLRTokenStream *_input, int _k, int _chunk_size_formal) /* MR14 */ +{ + this->input = _input; + this->k = _k; + buffer_size = chunk_size = _chunk_size_formal; + buffer = (_ANTLRTokenPtr *) + calloc(chunk_size+1,sizeof(_ANTLRTokenPtr )); + if ( buffer == NULL ) { + panic("cannot alloc token buffer"); + } + buffer++; // leave the first elem empty so tp-1 is valid ptr + + tp = &buffer[0]; + last = tp-1; + next = &buffer[0]; + num_markers = 0; + end_of_buffer = &buffer[buffer_size-1]; + threshold = &buffer[(int)(buffer_size/2)]; // MR23 - Used to be 1.0/2.0 ! + _deleteTokens = 1; // assume we delete tokens + parser=NULL; // MR5 - uninitialized reference +} + +static void f() {;} +ANTLRTokenBuffer:: +~ANTLRTokenBuffer() +{ + f(); + // Delete all remaining tokens (from 0..last inclusive) + if ( _deleteTokens ) + { + _ANTLRTokenPtr *z; + for (z=buffer; z<=last; z++) + { + (*z)->deref(); +// z->deref(); +#ifdef DBG_REFCOUNTTOKEN + /* MR23 */ printMessage(stderr, "##########dtor: deleting token '%s' (ref %d)\n", + ((ANTLRCommonToken *)*z)->getText(), (*z)->nref()); +#endif + if ( (*z)->nref()==0 ) + { + delete (*z); + } + } + } + + if ( buffer!=NULL ) free((char *)(buffer-1)); +} + +#if defined(DBG_TBUF)||defined(DBG_TBUF_MARK_REW) +#include "pccts_stdio.h" +PCCTS_NAMESPACE_STD +#endif + +_ANTLRTokenPtr ANTLRTokenBuffer:: +getToken() +{ + if ( tp <= last ) // is there any buffered lookahead still to be read? + { + return *tp++; // read buffered lookahead + } + // out of buffered lookahead, get some more "real" + // input from getANTLRToken() + if ( num_markers==0 ) + { + if( next > threshold ) + { +#ifdef DBG_TBUF +/* MR23 */ printMessage(stderr,"getToken: next > threshold (high water is %d)\n", threshold-buffer); +#endif + makeRoom(); + } + } + else { + if ( next > end_of_buffer ) + { +#ifdef DBG_TBUF +/* MR23 */ printMessage(stderr,"getToken: next > end_of_buffer (size is %d)\n", buffer_size); +#endif + extendBuffer(); + } + } + *next = getANTLRToken(); + (*next)->ref(); // say we have a copy of this pointer in buffer + last = next; + next++; + tp = last; + return *tp++; +} + +void ANTLRTokenBuffer:: +rewind(int pos) +{ +#if defined(DBG_TBUF)||defined(DBG_TBUF_MARK_REW) + /* MR23 */ printMessage(stderr, "rewind(%d)[nm=%d,from=%d,%d.n=%d]\n", pos, num_markers, tp-buffer,pos,test[pos]); + test[pos]--; +#endif + tp = &buffer[pos]; + num_markers--; +} + +/* + * This function is used to specify that the token pointers read + * by the ANTLRTokenBuffer should be buffered up (to be reused later). + */ +int ANTLRTokenBuffer:: +mark() +{ +#if defined(DBG_TBUF)||defined(DBG_TBUF_MARK_REW) + test[tp-buffer]++; + /* MR23 */ printMessage(stderr,"mark(%d)[nm=%d,%d.n=%d]\n",tp-buffer,num_markers+1,tp-buffer,test[tp-buffer]); +#endif + num_markers++; + return tp - buffer; +} + +/* + * returns the token pointer n positions ahead. + * This implies that bufferedToken(1) gets the NEXT symbol of lookahead. + * This is used in conjunction with the ANTLRParser lookahead buffer. + * + * No markers are set or anything. A bunch of input is buffered--that's all. + * The tp pointer is left alone as the lookahead has not been advanced + * with getToken(). The next call to getToken() will find a token + * in the buffer and won't have to call getANTLRToken(). + * + * If this is called before a consume() is done, how_many_more_i_need is + * set to 'n'. + */ +_ANTLRTokenPtr ANTLRTokenBuffer:: +bufferedToken(int n) +{ +// int how_many_more_i_need = (last-tp < 0) ? n : n-(last-tp)-1; + int how_many_more_i_need = (tp > last) ? n : n-(last-tp)-1; + // Make sure that at least n tokens are available in the buffer +#ifdef DBG_TBUF + /* MR23 */ printMessage(stderr, "bufferedToken(%d)\n", n); +#endif + for (int i=1; i<=how_many_more_i_need; i++) + { + if ( next > end_of_buffer ) // buffer overflow? + { + extendBuffer(); + } + *next = getANTLRToken(); + (*next)->ref(); // say we have a copy of this pointer in buffer + last = next; + next++; + } + return tp[n - 1]; +} + +/* If no markers are set, the none of the input needs to be saved (except + * for the lookahead Token pointers). We save only k-1 token pointers as + * we are guaranteed to do a getANTLRToken() right after this because otherwise + * we wouldn't have needed to extend the buffer. + * + * If there are markers in the buffer, we need to save things and so + * extendBuffer() is called. + */ +void ANTLRTokenBuffer:: +makeRoom() +{ +#ifdef DBG_TBUF + /* MR23 */ printMessage(stderr, "in makeRoom.................\n"); + /* MR23 */ printMessage(stderr, "num_markers==%d\n", num_markers); +#endif +/* + if ( num_markers == 0 ) + { +*/ +#ifdef DBG_TBUF + /* MR23 */ printMessage(stderr, "moving lookahead and resetting next\n"); + + _ANTLRTokenPtr *r; + /* MR23 */ printMessage(stderr, "tbuf = ["); + for (r=buffer; r<=last; r++) + { + if ( *r==NULL ) /* MR23 */ printMessage(stderr, " xxx"); + else /* MR23 */ printMessage(stderr, " '%s'", ((ANTLRCommonToken *)*r)->getText()); + } + /* MR23 */ printMessage(stderr, " ]\n"); + + /* MR23 */ printMessage(stderr, + "before: tp=%d, last=%d, next=%d, threshold=%d\n",tp-buffer,last-buffer,next-buffer,threshold-buffer); +#endif + + // Delete all tokens from 0..last-(k-1) inclusive + if ( _deleteTokens ) + { + _ANTLRTokenPtr *z; + for (z=buffer; z<=last-(k-1); z++) + { + (*z)->deref(); +// z->deref(); +#ifdef DBG_REFCOUNTTOKEN + /* MR23 */ printMessage(stderr, "##########makeRoom: deleting token '%s' (ref %d)\n", + ((ANTLRCommonToken *)*z)->getText(), (*z)->nref()); +#endif + if ( (*z)->nref()==0 ) + { + delete (*z); + } + } + } + + // reset the buffer to initial conditions, but move k-1 symbols + // to the beginning of buffer and put new input symbol at k + _ANTLRTokenPtr *p = buffer, *q = last-(k-1)+1; +// ANTLRAbstractToken **p = buffer, **q = end_of_buffer-(k-1)+1; +#ifdef DBG_TBUF + /* MR23 */ printMessage(stderr, "lookahead buffer = ["); +#endif + for (int i=1; i<=(k-1); i++) + { + *p++ = *q++; +#ifdef DBG_TBUF + /* MR23 */ printMessage(stderr, + " '%s'", ((ANTLRCommonToken *)buffer[i-1])->getText()); +#endif + } +#ifdef DBG_TBUF + /* MR23 */ printMessage(stderr, " ]\n"); +#endif + next = &buffer[k-1]; + tp = &buffer[k-1]; // tp points to what will be filled in next + last = tp-1; +#ifdef DBG_TBUF + /* MR23 */ printMessage(stderr, + "after: tp=%d, last=%d, next=%d\n", + tp-buffer, last-buffer, next-buffer); +#endif +/* + } + else { + extendBuffer(); + } +*/ +} + +/* This function extends 'buffer' by chunk_size and returns with all + * pointers at the same relative positions in the buffer (the buffer base + * address could have changed in realloc()) except that 'next' comes + * back set to where the next token should be stored. All other pointers + * are untouched. + */ +void +ANTLRTokenBuffer:: +extendBuffer() +{ + int save_last = last-buffer, save_tp = tp-buffer, save_next = next-buffer; +#ifdef DBG_TBUF + /* MR23 */ printMessage(stderr, "extending physical buffer\n"); +#endif + buffer_size += chunk_size; + buffer = (_ANTLRTokenPtr *) + realloc((char *)(buffer-1), + (buffer_size+1)*sizeof(_ANTLRTokenPtr )); + if ( buffer == NULL ) { + panic("cannot alloc token buffer"); + } + buffer++; // leave the first elem empty so tp-1 is valid ptr + + tp = buffer + save_tp; // put the pointers back to same relative position + last = buffer + save_last; + next = buffer + save_next; + end_of_buffer = &buffer[buffer_size-1]; + threshold = &buffer[(int)(buffer_size*(1.0/2.0))]; + +/* + // zero out new token ptrs so we'll know if something to delete in buffer + ANTLRAbstractToken **p = end_of_buffer-chunk_size+1; + for (; p<=end_of_buffer; p++) *p = NULL; +*/ +} + +ANTLRParser * ANTLRTokenBuffer:: // MR1 +setParser(ANTLRParser *p) { // MR1 + ANTLRParser *old=parser; // MR1 + parser=p; // MR1 + input->setParser(p); // MR1 + return old; // MR1 +} // MR1 + // MR1 +ANTLRParser * ANTLRTokenBuffer:: // MR1 +getParser() { // MR1 + return parser; // MR1 +} // MR1 + +void ANTLRTokenBuffer::panic(const char *msg) // MR23 +{ + if (parser) //MR23 + parser->panic(msg); //MR23 + else //MR23 + exit(PCCTS_EXIT_FAILURE); +} + +//MR23 +int ANTLRTokenBuffer::printMessage(FILE* pFile, const char* pFormat, ...) +{ + va_list marker; + va_start( marker, pFormat ); + + int iRet = 0; + if (parser) + parser->printMessageV(pFile, pFormat, marker); + else + iRet = vfprintf(pFile, pFormat, marker); + + va_end( marker ); + return iRet; +} + +/* to avoid having to link in another file just for the smart token ptr + * stuff, we include it here. Ugh. + * + * MR23 This causes nothing but problems for IDEs. + * Change from .cpp to .h + * + */ + +#include ATOKPTR_IMPL_H diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenBuffer.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenBuffer.h new file mode 100644 index 00000000..a6bec639 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenBuffer.h @@ -0,0 +1,109 @@ +/* ANTLRTokenBuffer.h + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ATOKENBUFFER_H_GATE +#define ATOKENBUFFER_H_GATE + +#include "pcctscfg.h" + +#include "pccts_stdlib.h" + +PCCTS_NAMESPACE_STD + +#include ATOKEN_H +#include ATOKENSTREAM_H + +/* + * The parser is "attached" to an ANTLRTokenBuffer via interface + * functions: getToken() and bufferedToken(). The object that actually + * consumes characters and constructs tokens is connected to the + * ANTLRTokenBuffer via interface function ANTLRTokenStream::getToken(); + * where ANTLRTokenStream is really just a behavior (class with no data). + * C++ does not have this abstraction and hence we simply have come up + * with a fancy name for "void *". See the note in ANTLRTokenStream.h on + * the "behavior" of ANTLRTokenStream. + */ + +class ANTLRParser; // MR1 + +class DllExportPCCTS ANTLRTokenBuffer { +protected: + ANTLRTokenStream *input; // where do I get tokens + int buffer_size; + int chunk_size; + int num_markers; + int k; // Need at least this many tokens in buffer + _ANTLRTokenPtr *buffer; // buffer used for arbitrary lookahead + _ANTLRTokenPtr *tp; // pts into buffer; current token ptr + _ANTLRTokenPtr *last; // pts to last valid token in buffer + _ANTLRTokenPtr *next; // place to put token from getANTLRToken() + _ANTLRTokenPtr *end_of_buffer; + /* when you try to write a token past this and there are no markers + set, then move k-1 tokens back to the beginning of the buffer. + We want to stay away from the end of the buffer because we have + to extend it if a marker is set and we reach the end (we cannot + move tokens to the beginning of the buffer in this case). + */ + _ANTLRTokenPtr *threshold; + unsigned char _deleteTokens; + + // This function is filled in by the subclass; it initiates fetch of input + virtual _ANTLRTokenPtr getANTLRToken() { return input->getToken(); } + void makeRoom(); + void extendBuffer(); + +public: + ANTLRTokenBuffer(ANTLRTokenStream *in, int k=1, int chksz=50); + virtual ~ANTLRTokenBuffer(); + virtual _ANTLRTokenPtr getToken(); + virtual void rewind(int pos); + virtual int mark(); + virtual _ANTLRTokenPtr bufferedToken(int i); + + void noGarbageCollectTokens() { _deleteTokens=0; } + void garbageCollectTokens() { _deleteTokens=1; } + + virtual int bufferSize() { return buffer_size; } + virtual int minTokens() { return k; } + virtual void setMinTokens(int k_new) { k = k_new; } + + virtual void panic(const char *msg); /* MR20 const */ + + virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23 + +protected: // MR1 + ANTLRParser *parser; // MR1 +public: // MR1 + ANTLRParser *setParser(ANTLRParser *p); // MR1 + ANTLRParser *getParser(); // MR1 + ANTLRTokenStream *getLexer() const { // MR12 + return input;} // MR12 +}; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenStream.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenStream.h new file mode 100644 index 00000000..3df6385d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ATokenStream.h @@ -0,0 +1,51 @@ +/* ANTLRTokenStream.h + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ATOKENSTREAM_H_GATE +#define ATOKENSTREAM_H_GATE + +#include "pcctscfg.h" + +/* This is really a behavior or protocol; it merely indicates the behavior + * required of the input and output of an ANTLRTokenBuffer. You could + * subclass it, but you can also just pass any old pointer to ANTLRTokenBuffer + * with a type cast (in which case, your getANTLRToken() would have to + * explicitly cast the input pointer to your REAL type (typically your lexer)). + */ + +class ANTLRParser; // MR1 + +class DllExportPCCTS ANTLRTokenStream { +public: + virtual _ANTLRTokenPtr getToken() = 0; + virtual ANTLRParser * setParser(ANTLRParser * /*p MR23*/) {return 0; }; // MR12 + virtual ANTLRParser * getParser() { return 0; }; // MR12 +}; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/BufFileInput.cpp b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/BufFileInput.cpp new file mode 100644 index 00000000..738d47cc --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/BufFileInput.cpp @@ -0,0 +1,100 @@ +// FILE: BufFileInput.cpp +// AUTHOR: Alexey Demakov (AVD) demakov@kazbek.ispras.ru +// CREATION: 26-JAN-1998 +// DESCRIPTION: File Input Stream with lookahead for Scanner. +// See file BufFileInput.h for details + +// Change History: +// +// 22-Jun-1998 assert.h -> PCCTS_ASSERT_H +// string.h -> PCCTS_STRING_H +// +// 28-May-1998 Add virtual destructor to release buffer. +// +// Add dummy definition for ANTLRTokenType +// to allow compilation without knowing +// token type codes. +// +// Manfred Kogler (km@cast.uni-linz.ac.at) +// (1.33MR14) +// +// 20-Jul-1998 MR14a - Reorder initialization list for ctor. +// + +enum ANTLRTokenType {TER_HATES_CPP=0, SO_DO_OTHERS=9999 }; + +#include "pcctscfg.h" +#include "pccts_assert.h" +#include "pccts_string.h" + +PCCTS_NAMESPACE_STD + +#include "BufFileInput.h" + +BufFileInput::BufFileInput( FILE *f, int buf_size ) +: input( f ), + buf( new int[buf_size] ), + size( buf_size ), + start( 0 ), + len( 0 ) +{ +} + +BufFileInput::~BufFileInput() +{ + delete [] buf; +} + +int BufFileInput::nextChar( void ) +{ + if( len > 0 ) + { + // get char from buffer + int c = buf[start]; + + if( c != EOF ) + { + start++; start %= size; + len--; + } + return c; + } else { + // get char from file + int c = getc( input ); + + if( c == EOF ) + { + // if EOF - put it in the buffer as indicator + buf[start] = EOF; + len++; + } + return c; + } +} + +int BufFileInput::lookahead( char* s ) +{ + int l = strlen( s ); + + assert( 0 < l && l <= size ); + + while( len < l ) + { + int c = getc( input ); + + buf[ (start+len) % size ] = c; + + len++; + + if( c == EOF ) return 0; + } + + for( int i = 0; i < l; i++ ) + { + if( s[i] != buf[ (start+i) % size ] ) return 0; + } + return 1; +} + +// End of file BufFileInput.cpp + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/BufFileInput.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/BufFileInput.h new file mode 100644 index 00000000..d53340e3 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/BufFileInput.h @@ -0,0 +1,53 @@ +// FILE: BufFileInput.h +// AUTHOR: Alexey Demakov (AVD) demakov@kazbek.ispras.ru +// CREATION: 26-JAN-1998 +// DESCRIPTION: File Input Stream with lookahead for Scanner +// Tested under Win32 with ANTLR 1.33 MR10 and MSVC 5.0 + +// Change History: +// +// 28-May-1998 Add virtual destructor to release buffer +// Manfred Kogler (km@cast.uni-linz.ac.at) +// (1.33MR14) + +#ifndef BufFileInput_h +#define BufFileInput_h + +#include "pcctscfg.h" + +#include "pccts_stdio.h" + +PCCTS_NAMESPACE_STD + +#include "DLexerBase.h" + +class DllExportPCCTS BufFileInput : public DLGInputStream +{ +public: + // constructor + // f - input stream + // buf_size - size of buffer (maximal length for string in is_in) + + BufFileInput(FILE *f, int buf_size = 8 ); + + virtual ~BufFileInput(); + + // gets next char from stream + + virtual int nextChar( void ); + + // looks in stream and compares next l characters with s + // returns the result of comparision + + int lookahead( char* s ); + +private: + FILE *input; // input stream; + int* buf; // buffer + int size; // size of buffer + int start; // position of the first symbol in buffer + int len; // count of characters in buffers +}; + +#endif +// end of file BufFileInput.h diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/DLG_stream_input.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/DLG_stream_input.h new file mode 100644 index 00000000..e7972f1e --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/DLG_stream_input.h @@ -0,0 +1,98 @@ + +/************************************************************/ +/* */ +/* Predefined char stream: Input from (c++) stream. */ +/* */ +/* By Hubert Holin (Hubert.Holin@Bigfoot.com), 1998. */ +/* */ +/* This is completely free stuff, do whatever you want with */ +/* it (but then, I will take no responsibility for whatever */ +/* may happen if you do either... caveat emptor!). */ +/* */ +/************************************************************/ + +#ifndef _DLG_STREAM_INPUT_H +#define _DLG_STREAM_INPUT_H + +#include "pccts_istream.h" + +PCCTS_NAMESPACE_STD + +#ifndef DLGX_H +#include "DLexerBase.h" +#endif + + +// NOTES: The semantics of the copy constructor +// and the affectation operator may be unwarranted... +// and the stream may not be reset. +// +// It would have been so much nicer for nextChar() +// to throw (of for the DLGInputStream to change status) +// upon hitting EOF than to return an "int"... + +template < + class E, + class T = ::std::char_traits + > +class DLG_stream_input : public DLGInputStream +{ +public: + + DLG_stream_input(::std::basic_istream * p_input_stream) + : input(p_input_stream) + { + // nothing to do! + }; + + DLG_stream_input(const DLG_stream_input & a_recopier) + : input(a_recopier.input) + { + // nothing to do! + }; + + virtual ~DLG_stream_input() + { + this->purge(); // bloody templarized lookup... + }; + + DLG_stream_input operator = (const DLG_stream_input & a_affecter) + { + if (this != &a_affecter) + { + input = a_affecter.input; + } + + return(*this); + }; + + virtual int nextChar() + { + E extracted_stuff; + + input->get(extracted_stuff); + + if (*input) + { + return(int(extracted_stuff)); + } + else + { + return(EOF); + } + }; + +protected: + + ::std::basic_istream * input; + +private: + + void purge() + { + // nothing to do! + }; +}; + +#endif /* _DLG_STREAM_INPUT_H */ + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/DLexer.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/DLexer.h new file mode 100644 index 00000000..afc172ae --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/DLexer.h @@ -0,0 +1,194 @@ +/* DLexer.h (formerly DLexer.cpp) + * + * This was renamed because the use of the .cpp extension caused problems + * with IDEs. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#include + +#define ZZINC {if ( track_columns ) (++_endcol);} + +#define ZZGETC {ch = input->nextChar(); cl = ZZSHIFT(ch);} + +#define ZZNEWSTATE (newstate = dfa[state][cl]) + +#ifndef ZZCOPY +#define ZZCOPY \ + /* Truncate matching buffer to size (not an error) */ \ + if (nextpos < lastpos){ \ + *(nextpos++) = ch; \ + }else{ \ + bufovf = 1; \ + } +#endif + +void DLGLexer:: +mode( int m ) +{ + /* points to base of dfa table */ + if (m*actions[accepts[state]])(); + +// MR1 +// MR1 11-Apr-97 Help for tracking DLG results +// MR1 + +#ifdef DEBUG_LEXER + +/* MR1 */ if (debugLexerFlag) { +/* MR1 */ if (parser != NULL) { +/* MR1 */ /* MR23 */ printMessage(stdout, "\ntoken name=%s",parser->parserTokenName(tk)); +/* MR1 */ } else { +/* MR1 */ /* MR23 */ printMessage(stdout, "\ntoken nnumber=%d",tk); +/* MR1 */ }; +/* MR1 */ /* MR23 */ printMessage(stdout, " lextext=(%s) mode=%d", +/* MR1 */ (_lextext[0]=='\n' && _lextext[1]==0) ? +/* MR1 */ "newline" : _lextext, +/* MR1 */ automaton); +/* MR1 */ if (interactive && !charfull) { +/* MR1 */ /* MR23 */ printMessage(stdout, " char=empty"); +/* MR1 */ } else { +/* MR1 */ if (ch=='\n') { +/* MR1 */ /* MR23 */ printMessage(stdout, " char=newline"); +/* MR1 */ } else { +/* MR1 */ /* MR23 */ printMessage(stdout, " char=(%c)",ch); +/* MR1 */ }; +/* MR1 */ }; +/* MR1 */ /* MR23 */ printMessage(stdout, " %s\n", +/* MR1 */ (add_erase==1 ? "skip()" : +/* MR1 */ add_erase==2 ? "more()" : +/* MR1 */ "")); +/* MR1 */ }; + +#endif + + switch (add_erase) { + case 1: goto skip; + case 2: goto more; + } + return tk; +} + +void DLGLexer:: +advance() +{ + if ( input==NULL ) err_in(); + ZZGETC; charfull = 1; ZZINC; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/DLexerBase.cpp b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/DLexerBase.cpp new file mode 100644 index 00000000..87b29208 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/DLexerBase.cpp @@ -0,0 +1,302 @@ +/* DLGLexerBase.c + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#include "pcctscfg.h" + +#include "pccts_stdio.h" +#include "pccts_stdlib.h" + +PCCTS_NAMESPACE_STD + +/* I have to put this here due to C++ limitation + * that you can't have a 'forward' decl for enums. + * I hate C++!!!!!!!!!!!!!!! + */ + +// MR1 +// MR1 10-Apr-97 133MR1 Prevent use of varying sizes for the +// MR1 ANTLRTokenType enum +// MR1 + +enum ANTLRTokenType { TER_HATES_CPP=0, ITS_UTTER_GARBAGE, // MR1 + WITH_SOME_GOOD_IDEAS=9999}; // MR1 + +#define ANTLR_SUPPORT_CODE + +#include "pcctscfg.h" +#include DLEXERBASE_H +#include APARSER_H // MR23 + +DLGLexerBase:: +DLGLexerBase(DLGInputStream *in, + unsigned bufsize, + int _interactive, + int _track_columns) +{ + this->_bufsize = bufsize; + this->_lextext = new DLGChar[_bufsize]; + if ( this->_lextext==NULL ) { + panic("text buffer is NULL"); + } + this->_begexpr = this->_endexpr = NULL; + this->ch = this->bufovf = 0; + this->nextpos = NULL; + this->cl = 0; + this->add_erase = 0; + this->input = in; + this->_begcol = 0; + this->_endcol = 0; + this->_line = 1; + this->charfull = 0; + this->automaton = 0; + this->token_to_fill = NULL; + this->interactive = _interactive; + this->track_columns = _track_columns; + this->debugLexerFlag = 0; // MR1 + this->parser = NULL; // MR1 + this->lexErrCount=0; // MR11 +} + +// MR19 THM + +void DLGLexerBase::reset() +{ + this->charfull = 0; + this->_begcol = 0; + this->_endcol = 0; + this->automaton = 0; + this->_line=1; + this->lexErrCount=0; +} + +void DLGLexerBase:: +setInputStream( DLGInputStream *in ) +{ + this->input = in; + _line = 1; + charfull = 0; +} + +/* saves dlg state, but not what feeds dlg (such as file position) */ +void DLGLexerBase:: +saveState(DLGState *state) +{ + state->input = input; + state->interactive = interactive; + state->track_columns = track_columns; + state->auto_num = automaton; + state->add_erase = add_erase; + state->lookc = ch; + state->char_full = charfull; + state->begcol = _begcol; + state->endcol = _endcol; + state->line = _line; + state->lextext = _lextext; + state->begexpr = _begexpr; + state->endexpr = _endexpr; + state->bufsize = _bufsize; + state->bufovf = bufovf; + state->nextpos = nextpos; + state->class_num = cl; + state->debugLexerFlag = debugLexerFlag; // MR1 + state->parser = parser; // MR1 +} + +void DLGLexerBase:: +restoreState(DLGState *state) +{ + input = state->input; + interactive = state->interactive; + track_columns = state->track_columns; + automaton = state->auto_num; + add_erase = state->add_erase; + ch = state->lookc; + charfull = state->char_full; + _begcol = state->begcol; + _endcol = state->endcol; + _line = state->line; + _lextext = state->lextext; + _begexpr = state->begexpr; + _endexpr = state->endexpr; + _bufsize = state->bufsize; + bufovf = state->bufovf; + nextpos = state->nextpos; + cl = state->class_num; + debugLexerFlag = state->debugLexerFlag; // MR1 + parser = state->parser; // MR1 +} + +/* erase what is currently in the buffer, and get a new reg. expr */ +void DLGLexerBase:: +skip() +{ + add_erase = 1; +} + +/* don't erase what is in the lextext buffer, add on to it */ +void DLGLexerBase:: +more() +{ + add_erase = 2; +} + +/* substitute c for the reg. expr last matched and is in the buffer */ +void DLGLexerBase:: +replchar(DLGChar c) +{ + /* can't allow overwriting null at end of string */ + if (_begexpr < &_lextext[_bufsize-1]){ + *_begexpr = c; + *(_begexpr+1) = '\0'; + } + _endexpr = _begexpr; + if (c != '\0') { + nextpos = _begexpr + 1; + } + else { + nextpos = _begexpr; /* MR30 Zero terminates string. */ + } +} + +/* replace the string s for the reg. expr last matched and in the buffer */ + +#ifdef _MSC_VER // MR23 +//Turn off "assignment within conditional expression" warning +#pragma warning(disable : 4706) +#endif +void DLGLexerBase:: +replstr(const DLGChar *s) /* MR20 const */ +{ + register DLGChar *l= &_lextext[_bufsize -1]; + + nextpos = _begexpr; + if (s){ + while ((nextpos <= l) && (*(nextpos++) = *(s++))){ + /* empty */ + } + /* correct for NULL at end of string */ + nextpos--; + } + if ((nextpos <= l) && (*(--s) == 0)){ + bufovf = 0; + }else{ + bufovf = 1; + } + *(nextpos) = '\0'; + _endexpr = nextpos - 1; +} +#ifdef _MSC_VER // MR23 +#pragma warning(default: 4706) +#endif + +void DLGLexerBase:: +errstd(const char *s) /* MR20 const */ +{ + lexErrCount++; /* MR11 */ + /* MR23 */ printMessage(stderr, + "%s near line %d (text was '%s')\n", + ((s == NULL) ? "Lexical error" : s), + _line,_lextext); +} + +int DLGLexerBase:: +err_in() +{ + /* MR23 */ printMessage(stderr,"No input stream, function, or string\n"); + /* return eof to get out gracefully */ + return EOF; +} + +ANTLRTokenType DLGLexerBase:: +erraction() +{ + errstd("invalid token"); + advance(); + skip(); + return (ANTLRTokenType) 0; // bogus, but satisfies compiler +} + +_ANTLRTokenPtr DLGLexerBase:: +getToken() +{ + if ( token_to_fill==NULL ) panic("NULL token_to_fill"); + ANTLRTokenType tt = nextTokenType(); + _ANTLRTokenPtr tk = token_to_fill->makeToken(tt, _lextext,_line); + return tk; +} + +void DLGLexerBase:: +panic(const char *msg) /* MR20 const */ +{ + if (parser) //MR23 + parser->panic(msg); //MR23 + else //MR23 + { + /* MR23 */ printMessage(stderr, "DLG panic: %s\n", msg); + // + // 7-Apr-97 133MR1 + // + exit(PCCTS_EXIT_FAILURE); // MR1 + } +} + +ANTLRParser * DLGLexerBase:: // MR1 +setParser(ANTLRParser *p) { // MR1 + ANTLRParser *oldValue=parser; // MR1 + parser=p; // MR1 + return oldValue; // MR1 +} // MR1 + // MR1 +ANTLRParser * DLGLexerBase:: // MR1 +getParser() { // MR1 + return parser; // MR1 +} // MR1 + // MR1 +int DLGLexerBase:: // MR1 +debugLexer(int newValue) { // MR1 + int oldValue=debugLexerFlag; // MR1 + debugLexerFlag=newValue; // MR1 + return oldValue; // MR1 +} // MR1 + +//MR23 +int DLGLexerBase::printMessage(FILE* pFile, const char* pFormat, ...) +{ + va_list marker; + va_start( marker, pFormat ); + + int iRet = 0; + if (parser) + parser->printMessageV(pFile, pFormat, marker); + else + iRet = vfprintf(pFile, pFormat, marker); + + va_end( marker ); + return iRet; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/DLexerBase.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/DLexerBase.h new file mode 100644 index 00000000..c30f2277 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/DLexerBase.h @@ -0,0 +1,202 @@ +/* DLGLexerBase.h + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef DLGX_H +#define DLGX_H + +#include "pcctscfg.h" +#include "pccts_stdio.h" + +PCCTS_NAMESPACE_STD + +#include ATOKEN_H +#include ATOKENSTREAM_H + +class ANTLRParser; // MR1 + +/* must define what a char looks like; can make this a class too */ +typedef char DLGChar; + +/* Can have it as a class too: (ack this looks weird; is it right?) +class DllExportPCCTS DLGChar { +private: + int c; +public: + DLGChar(int ch) { c = ch; } + int atom() { return c; } +}; +*/ + +/* user must subclass this */ +class DllExportPCCTS DLGInputStream { +public: + virtual int nextChar() = 0; + virtual ~DLGInputStream() {}; +}; + +/* Predefined char stream: Input from FILE */ +class DllExportPCCTS DLGFileInput : public DLGInputStream { +private: + int found_eof; + FILE *input; +public: + DLGFileInput(FILE *f) { input = f; found_eof = 0; } + int nextChar() { + int c; + if ( found_eof ) return EOF; + else { + c=getc(input); + if ( c==EOF ) found_eof = 1; + return c; + } + } + void DLGFileReset(FILE *f) {input=f; found_eof = 0; }; // MR11 +}; + +// MR9 Suggested by Bruce Guenter (bruceg@qcc.sk.ca) +// MR9 Make DLGStringInput const correct + +/* Predefined char stream: Input from string */ +class DllExportPCCTS DLGStringInput : public DLGInputStream { +private: + const DLGChar *input; // MR9 + const DLGChar *p; // MR9 +public: + DLGStringInput(const DLGChar *s) { input = s; p = &input[0];} // MR9 + int nextChar() + { + if (*p) return (int) (unsigned char) *p++; // MR14 + else return EOF; + } + + void DLGStringReset(const DLGChar *s) {input=s; p= &input[0]; }; // MR11 // MR16 +}; + +class DllExportPCCTS DLGState { +public: + DLGInputStream *input; + int interactive; + int track_columns; + int auto_num; + int add_erase; + int lookc; + int char_full; + int begcol, endcol; + int line; + DLGChar *lextext, *begexpr, *endexpr; + int bufsize; + int bufovf; + DLGChar *nextpos; + int class_num; + int debugLexerFlag; // MR1 + ANTLRParser *parser; // MR1 +}; + +/* user must subclass this */ +class DllExportPCCTS DLGLexerBase : public ANTLRTokenStream { +private: + DLGLexerBase(const DLGLexerBase&); // Prevent copy-construction + DLGLexerBase& operator=(const DLGLexerBase&); // Prevent assignment +public: + virtual ANTLRTokenType erraction(); + +protected: + DLGInputStream *input; + int interactive; + int track_columns; + DLGChar *_lextext; /* text of most recently matched token */ + DLGChar *_begexpr; /* beginning of last reg expr recogn. */ + DLGChar *_endexpr; /* beginning of last reg expr recogn. */ + int _bufsize; /* number of characters in lextext */ + int _begcol; /* column that first character of token is in*/ + int _endcol; /* column that last character of token is in */ + int _line; /* line current token is on */ + int ch; /* character to determine next state */ + int bufovf; /* indicates that buffer too small for text */ + int charfull; + DLGChar *nextpos; /* points to next available position in lextext*/ + int cl; + int automaton; + int add_erase; + DLGChar ebuf[70]; + _ANTLRTokenPtr token_to_fill; + + int debugLexerFlag; // MR1 + ANTLRParser *parser; // MR1 +public: + virtual _ANTLRTokenPtr getToken(); // MR12 public + virtual void advance(void) = 0; + void skip(void); /* erase lextext, look for antoher token */ + void more(void); /* keep lextext, look for another token */ + void mode(int k); /* switch to automaton 'k' */ + void saveState(DLGState *); + void restoreState(DLGState *); + virtual ANTLRTokenType nextTokenType(void)=0;/* get next token */ + void replchar(DLGChar c); /* replace last recognized reg. expr. with + a character */ + void replstr(const DLGChar *s); /* replace last recognized reg. expr. with + a string */ /* MR20 const */ + virtual int err_in(); // MR1 + virtual void errstd(const char *); // MR1 MR20 const + int line() { return _line; } + void set_line(int newValue) { _line=newValue; }; // MR1 + virtual void newline() { _line++; } + DLGChar *lextext() { return _lextext; } + + int begcol() { return _begcol; } + int endcol() { return _endcol; } + void set_begcol(int a) { _begcol=a; } + void set_endcol(int a) { _endcol=a; } + DLGChar *begexpr() { return _begexpr; } + DLGChar *endexpr() { return _endexpr; } + int bufsize() { return _bufsize; } + + void setToken(ANTLRAbstractToken *t) { token_to_fill = t; } + + void setInputStream(DLGInputStream *); + DLGLexerBase(DLGInputStream *in, + unsigned bufsize=2000, + int interactive=0, + int track_columns=0); + void reset(); // MR19 + virtual ~DLGLexerBase() { delete [] _lextext; } + virtual void panic(const char *msg); // MR1 MR20 const + void trackColumns() { + track_columns = 1; + this->_begcol = 0; + this->_endcol = 0; + }; + virtual ANTLRParser *setParser(ANTLRParser *p); // MR1 + virtual ANTLRParser *getParser(); // MR1 + virtual int debugLexer(int value); // MR1 + int lexErrCount; // MR12 + virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23 +}; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/PBlackBox.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/PBlackBox.h new file mode 100644 index 00000000..6d201601 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/PBlackBox.h @@ -0,0 +1,134 @@ +#ifndef PBLACKBOX_H +#define PBLACKBOX_H + +/* + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +/* Completely rewritten by Chris Uzdavinis (chris@atdesk.com) for MR23 */ + +#include "pcctscfg.h" + +#include "pccts_iostream.h" + +PCCTS_NAMESPACE_STD + +// MR20 Added #include for "DLexerBase.h" + +#include "DLexerBase.h" + +// +// The default buffer size of the lexer is given by the +// second argument of the lexer's ctor. It is optional +// and defaults to 2000 +// + +template +class DllExportPCCTS ParserBlackBox { +private: + // no copy construction allowed + ParserBlackBox(ParserBlackBox const &); + + // no copy assignment allowed + ParserBlackBox & operator=(ParserBlackBox const &); + +protected: + DLGFileInput *in; + Lexer *scan; + _ANTLRTokenPtr tok; + ANTLRTokenBuffer *pipe; + Parser *_parser; + FILE *file; + int openByBlackBox; /* MR21 Don't close what we haven't opened */ +public: + + ParserBlackBox(FILE *f) + : in(0) + , scan(0) + , tok(0) + , pipe(0) + , _parser(0) + , file(0) + , openByBlackBox(0) + { + if (f == NULL) + { + cerr << "invalid file pointer\n"; + } + else + { + openByBlackBox = 0; /* MR21a */ + file = f; + in = new DLGFileInput(f); + scan = new Lexer(in); + pipe = new ANTLRTokenBuffer(scan); + tok = new Token; + scan->setToken(tok); + _parser = new Parser(pipe); + _parser->init(); + } + } + ParserBlackBox(char *fname) + : in(0) + , scan(0) + , tok(0) + , pipe(0) + , _parser(0) + , file(0) + , openByBlackBox(0) + { + FILE *f = fopen(fname, "r"); + if ( f==NULL ) { + openByBlackBox = 0; + cerr << "cannot open " << fname << "\n"; return; + } + else { + openByBlackBox = 1; + file = f; + in = new DLGFileInput(f); + scan = new Lexer(in); + pipe = new ANTLRTokenBuffer(scan); + tok = new Token; + scan->setToken(tok); + _parser = new Parser(pipe); + _parser->init(); + } + } + + ~ParserBlackBox() + { + delete in; delete scan; delete pipe; delete _parser; delete tok; + if (1 == openByBlackBox) { + fclose(file); + } + } + + Parser *parser() { return _parser; } + Lexer *getLexer() { return scan; } +}; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/PCCTSAST.cpp b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/PCCTSAST.cpp new file mode 100644 index 00000000..c29b69fa --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/PCCTSAST.cpp @@ -0,0 +1,684 @@ +/* + * PCCTSAST.C + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to SORCERER -- SORCERER is in the public + * domain. An individual or company may do whatever they wish with + * source code distributed with SORCERER or the code generated by + * SORCERER, including the incorporation of SORCERER, or its output, into + * commerical software. + * + * We encourage users to develop software with SORCERER. However, we do + * ask that credit is given to us for developing SORCERER. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like SORCERER and have developed a nice tool with the + * output, please mention that you developed it using SORCERER. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * SORCERER 1.00B14 and ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * AHPCRC, University of Minnesota + * 1992-2000 + */ + +#define ANTLR_SUPPORT_CODE + +#include "pcctscfg.h" + +#include "PCCTSAST.h" +#include "pccts_stdarg.h" + +PCCTS_NAMESPACE_STD + +#include + +//#include "SList.h" + + /* String Scanning/Parsing Stuff */ + +const char *PCCTS_AST::scan_token_tbl[] = { /* MR20 const */ + "invalid", /* 0 */ + "LPAREN", /* 1 */ + "RPAREN", /* 2 */ + "PERCENT", /* 3 */ + "INT", /* 4 */ + "COLON", /* 5 */ + "POUND", /* 6 */ + "PERIOD", /* 7 */ +}; + +void PCCTS_AST:: +addChild(PCCTS_AST *t) +{ + if ( t==NULL ) return; + PCCTS_AST *s = down(); + if ( s!=NULL ) + { + while ( s->right()!=NULL ) s = s->right(); + s->setRight(t); + } + else + this->setDown(t); +} + +void PCCTS_AST:: +lisp(FILE *f) +{ + if ( down() != NULL ) /* MR23 */ printMessage(f," ("); + lisp_action(f); + if ( down()!=NULL ) down()->lisp(f); + if ( down() != NULL ) /* MR23 */ printMessage(f," )"); + if ( right()!=NULL ) right()->lisp(f); +} + +/* build a tree (root child1 child2 ... NULL) + * If root is NULL, simply make the children siblings and return ptr + * to 1st sibling (child1). If root is not single node, return NULL. + * + * Siblings that are actually sibling lists themselves are handled + * correctly. For example #( NULL, #( NULL, A, B, C), D) results + * in the tree ( NULL A B C D ). + * + * Requires at least two parameters with the last one being NULL. If + * both are NULL, return NULL. + * + * The down() and right() down/right pointers are used to make the tree. + */ +PCCTS_AST *PCCTS_AST:: +make(PCCTS_AST *rt, ...) +{ + va_list ap; + register PCCTS_AST *child, *sibling=NULL, *tail=NULL /*MR23*/, *w; + PCCTS_AST *root; + + va_start(ap, rt); + root = rt; + + if ( root != NULL ) + if ( root->down() != NULL ) return NULL; + child = va_arg(ap, PCCTS_AST *); + while ( child != NULL ) + { + /* find end of child */ + for (w=child; w->right()!=NULL; w=w->right()) {;} + if ( sibling == NULL ) {sibling = child; tail = w;} + else {tail->setRight(child); tail = w;} + child = va_arg(ap, PCCTS_AST *); + } + if ( root==NULL ) root = sibling; + else root->setDown(sibling); + va_end(ap); + return root; +} + +/* The following push and pop routines are only used by ast_find_all() */ + +void PCCTS_AST:: +_push(PCCTS_AST **st, int *sp, PCCTS_AST *e) +{ + (*sp)--; + require((*sp)>=0, "stack overflow"); + st[(*sp)] = e; +} + +PCCTS_AST *PCCTS_AST:: +_pop(PCCTS_AST **st, int *sp) +{ + PCCTS_AST *e = st[*sp]; + (*sp)++; + require((*sp)<=MaxTreeStackDepth, "stack underflow"); + return e; +} + +/* Find all occurrences of u in t. + * 'cursor' must be initialized to 't'. It eventually + * returns NULL when no more occurrences of 'u' are found. + */ +PCCTS_AST *PCCTS_AST:: +ast_find_all(PCCTS_AST *u, PCCTS_AST **cursor) +{ + PCCTS_AST *sib; + /*** static ***/ PCCTS_AST *template_stack[MaxTreeStackDepth]; /* MR23 Remove "static" */ + /*** static ***/ int tsp = MaxTreeStackDepth; /* MR23 Remove "static" */ + +////static int nesting = 0; /* MR23 Not referenced */ + + if ( *cursor == NULL ) return NULL; + if ( *cursor!=this ) sib = *cursor; + else { + /* else, first time--start at top of template 't' */ + tsp = MaxTreeStackDepth; + sib = this; + /* bottom of stack is always a NULL--"cookie" indicates "done" */ + _push(template_stack, &tsp, NULL); + } + +keep_looking: + if ( sib==NULL ) /* hit end of sibling list */ + { + sib = _pop(template_stack, &tsp); + if ( sib == NULL ) { *cursor = NULL; return NULL; } + } + + if ( sib->type() != u->type() ) + { + /* look for another match */ + if ( sib->down()!=NULL ) + { + if ( sib->right()!=NULL ) _push(template_stack, &tsp, sib->right()); + sib=sib->down(); + goto keep_looking; + } + /* nothing below to try, try next sibling */ + sib=sib->right(); + goto keep_looking; + } + + /* found a matching root node, try to match what's below */ + if ( match_partial(sib, u) ) + { + /* record sibling cursor so we can pick up next from there */ + if ( sib->down()!=NULL ) + { + if ( sib->right()!=NULL ) _push(template_stack, &tsp, sib->right()); + *cursor = sib->down(); + } + else if ( sib->right()!=NULL ) *cursor = sib->right(); + else *cursor = _pop(template_stack, &tsp); + return sib; + } + + /* no match, keep searching */ + if ( sib->down()!=NULL ) + { + if ( sib->right()!=NULL ) _push(template_stack, &tsp, sib->right()); + sib=sib->down(); + } + else sib = sib->right(); /* else, try to right if zip below */ + goto keep_looking; +} + +/* are two trees exactly alike? */ +int PCCTS_AST:: +match(PCCTS_AST *u) +{ + PCCTS_AST *t = this; + PCCTS_AST *sib; + + if ( u==NULL ) return 0; + + for (sib=t; sib!=NULL&&u!=NULL; sib=sib->right(), u=u->right()) + { + if ( sib->type() != u->type() ) return 0; + if ( sib->down()!=NULL ) + if ( !sib->down()->match(u->down()) ) return 0; + } + return 1; +} + +/* Is 'u' a subtree of 't' beginning at the root? */ +int PCCTS_AST:: +match_partial(PCCTS_AST *t, PCCTS_AST *u) +{ + PCCTS_AST *sib; + + if ( u==NULL ) return 1; + if ( t==NULL ) return 0; /* MR23 removed unreachable code */ + + for (sib=t; sib!=NULL&&u!=NULL; sib=sib->right(), u=u->right()) + { + if ( sib->type() != u->type() ) return 0; + if ( sib->down()!=NULL ) + if ( !match_partial(sib->down(), u->down()) ) return 0; + } + return 1; +} + +#ifdef _MSC_VER // MR23 +//Turn off "unreachable code" warning +#pragma warning(disable : 4702) +#endif +/* Walk the template tree 't' (matching against 'this'), filling in the + * 'labels' array, and setting 'n' according to how many labels were matched. + */ +int PCCTS_AST:: +scanmatch(ScanAST *t, PCCTS_AST **labels[], int *n) +{ + ScanAST *sib; + PCCTS_AST *u = this; + + if ( u==NULL ) return 0; + + for (sib=t; sib!=NULL&&u!=NULL; sib=sib->right(), u=u->right()) + { + /* make sure tokens match; token of '0' means wildcard match */ + if ( sib->type() != u->type() && sib->type()!=0 ) return 0; + /* we have a matched token here; set label pointers if exists */ + if ( sib->label_num>0 ) + { + require(labels!=NULL, "label found in template, but no array of labels"); + (*n)++; + *(labels[sib->label_num-1]) = u; + } + /* match what's below if something there and current node is not wildcard */ + if ( sib->down()!=NULL && sib->type()!=0 ) + { + if ( sib->down()==NULL ) + { + if ( u->down()!=NULL ) + return 0; + else + return 1; + } + if ( !u->down()->scanmatch(sib->down(), labels, n) ) return 0; + } + } + return 1; +} +#ifdef _MSC_VER // MR23 +#pragma warning(default : 4702) +#endif + +void PCCTS_AST:: +insert_after(PCCTS_AST *b) +{ + PCCTS_AST *end; + if ( b==NULL ) return; + /* find end of b's child list */ + for (end=b; end->right()!=NULL; end=end->right()) {;} + end->setRight(this->right()); + this->setRight(b); +} + +void PCCTS_AST:: +append(PCCTS_AST *b) +{ + PCCTS_AST *end; + require(b!=NULL, "append: NULL input tree"); + /* find end of child list */ + for (end=this; end->right()!=NULL; end=end->right()) {;} + end->setRight(b); +} + +PCCTS_AST *PCCTS_AST:: +tail() +{ + PCCTS_AST *end; + /* find end of child list */ + for (end=this; end->right()!=NULL; end=end->right()) {;} + return end; +} + +PCCTS_AST *PCCTS_AST:: +bottom() +{ + PCCTS_AST *end; + /* find end of child list */ + for (end=this; end->down()!=NULL; end=end->down()) {;} + return end; +} + +PCCTS_AST *PCCTS_AST:: +cut_between(PCCTS_AST *a, PCCTS_AST *b) +{ + PCCTS_AST *end, *ret; + if (a==NULL||b==NULL) return NULL; + /* find node pointing to b */ + for (end=a; end->right()!=NULL&&end->right()!=b; end=end->right()) + {;} + if (end->right()==NULL) return NULL; //ast_cut_between: a,b not connected + end->setRight(NULL); /* don't want it point to 'b' anymore */ + ret = a->right(); + a->setRight(b); + return ret; +} + +#ifdef NOT_YET +SList *PCCTS_AST:: +to_slist() +{ + SList *list = new SList; + PCCTS_AST *p; + + for (p=this; p!=NULL; p=p->right()) + { + list->add(p); + } + return list; +} +#endif + +void PCCTS_AST:: +tfree() +{ + PCCTS_AST *t = this; + if ( t->down()!=NULL ) t->down()->tfree(); + if ( t->right()!=NULL ) t->right()->tfree(); + delete t; +} + +int PCCTS_AST:: +nsiblings() +{ + PCCTS_AST *t = this; + int n=0; + + while ( t!=NULL ) + { + n++; + t = t->right(); + } + return n; +} + +PCCTS_AST *PCCTS_AST:: +sibling_index(int i) +{ + PCCTS_AST *t = this; + int j=1; + require(i>0, "sibling_index: i<=0"); + + while ( t!=NULL ) + { + if ( j==i ) return t; + j++; + t = t->right(); + } + return NULL; +} + +/* Assume this is a root node of a tree-- + * duplicate that node and what's below; ignore siblings of root node. + */ + +// MR9 23-Sep-97 RJV +// MR9 +// MR9 RJV: Original version only duplicated the node and down elements. +// MR9 Made copies of the pointers to sibling. +// MR9 Changed call "down()->deepCopy()" to "down()->deepCopyBushy()" +// MR9 + +PCCTS_AST *PCCTS_AST:: +deepCopy() +{ + PCCTS_AST *u = this->shallowCopy(); + if ( down()!=NULL ) u->setDown(down()->deepCopyBushy()); + u->setRight(NULL); + return u; +} + +/* Copy all nodes including siblings of root. */ +PCCTS_AST *PCCTS_AST:: +deepCopyBushy() +{ + PCCTS_AST *u = this->shallowCopy(); + /* copy the rest of the tree */ + if ( down()!=NULL ) u->setDown(down()->deepCopyBushy()); + if ( right()!=NULL ) u->setRight(right()->deepCopyBushy()); + return u; +} + +void PCCTS_AST:: +scanast_free(ScanAST *t) +{ + if ( t == NULL ) return; + scanast_free( t->down() ); + scanast_free( t->right() ); + free( (char *) t ); // MR1 +} + +/* + * scan + * + * This function is like scanf(): it attempts to match a template + * against an input tree. A variable number of tree pointers + * may be set according to the '%i' labels in the template string. + * For example: + * + * t->ast_scan("#( 6 #(5 %1:4 %2:3) #(1 %3:3 %4:3) )", + * &w, &x, &y, &z); + * + * Naturally, you'd want this converted from + * + * t->ast_scan("#( RangeOp #(Minus %1:IConst %2:Var) #(Plus %3:Var %4Var) )", + * &w, &x, &y, &z); + * + * by SORCERER. + * + * This function call must be done withing a SORCERER file because SORCERER + * must convert the token references to the associated token number. + * + * This functions parses the template and creates trees which are then + * matched against the input tree. The labels are set as they are + * encountered; hence, partial matches may leave some pointers set + * and some NULL. This routines initializes all argument pointers to NULL + * at the beginning. + * + * This function returns the number of labels matched. + */ +int PCCTS_AST:: +ast_scan(char *templ, ...) +{ + va_list ap; + ScanAST *tmpl; + int n, i, found=0; + PCCTS_AST ***label_ptrs=NULL; + + va_start(ap, templ); + + /* make a ScanAST tree out of the template */ + tmpl = stringparser_parse_scanast(templ, &n); + + /* make an array out of the labels */ + if ( n>0 ) + { + label_ptrs = (PCCTS_AST ***) calloc(n, sizeof(PCCTS_AST **)); + require(label_ptrs!=NULL, "scan: out of memory"); + for (i=1; i<=n; i++) + { + label_ptrs[i-1] = va_arg(ap, PCCTS_AST **); + *(label_ptrs[i-1]) = NULL; + } + } + + /* match the input tree against the template */ + scanmatch(tmpl, label_ptrs, &found); + + scanast_free(tmpl); + free( (char *) label_ptrs); // MR1 + + return found; +} + +ScanAST *PCCTS_AST:: +new_scanast(int tok) +{ + ScanAST *p = (ScanAST *) calloc(1, sizeof(ScanAST)); +// +// 7-Apr-97 133MR1 +// + if ( p == NULL ) + panic("out of memory\n"); // MR23 + p->_token = tok; + return p; +} + +ScanAST *PCCTS_AST:: +stringparser_parse_scanast(char *templ, int *num_labels) +{ + StringLexer lex; + StringParser parser; + ScanAST *t; + + stringlexer_init(&lex, templ); + stringparser_init(&parser, &lex); + t = stringparser_parse_tree(&parser); + *num_labels = parser.num_labels; + return t; +} + +void PCCTS_AST:: +stringparser_match(StringParser *parser, int token) +{ + if ( parser->token != token ) panic("bad tree in scan()"); +} + +/* + * Match a tree of the form: + * (root child1 child2 ... childn) + * or, + * node + * + * where the elements are integers or labeled integers. + */ +ScanAST *PCCTS_AST:: +stringparser_parse_tree(StringParser *parser) +{ + ScanAST *t=NULL, *root, *child, *last=NULL /*MR23*/; + + if ( parser->token != __POUND ) + { + return stringparser_parse_element(parser); + } + stringparser_match(parser,__POUND); + parser->token = stringscan_gettok(parser->lexer); + stringparser_match(parser,__LPAREN); + parser->token = stringscan_gettok(parser->lexer); + root = stringparser_parse_element(parser); + while ( parser->token != __RPAREN ) + { + child = stringparser_parse_element(parser); + if ( t==NULL ) { t = child; last = t; } + else { last->_right = child; last = child; } + } + stringparser_match(parser,__RPAREN); + parser->token = stringscan_gettok(parser->lexer); + root->_down = t; + return root; +} + +ScanAST *PCCTS_AST:: +stringparser_parse_element(StringParser *parser) +{ + char ebuf[100]; + int label = 0; + + if ( parser->token == __POUND ) + { + return stringparser_parse_tree(parser); + } + if ( parser->token == __PERCENT ) + { + parser->token = stringscan_gettok(parser->lexer); + stringparser_match(parser,__INT); + label = atoi(parser->lexer->text); + parser->num_labels++; + if ( label==0 ) panic("%%0 is an invalid label"); + parser->token = stringscan_gettok(parser->lexer); + stringparser_match(parser,__COLON); + parser->token = stringscan_gettok(parser->lexer); + /* can label tokens and wildcards */ + if ( parser->token != __INT && parser->token != __PERIOD ) + panic("can only label tokens"); + } + if ( parser->token == __INT ) + { + ScanAST *p = new_scanast(atoi(parser->lexer->text)); + parser->token = stringscan_gettok(parser->lexer); + p->label_num = label; + return p; + } + if ( parser->token == __PERIOD ) + { + ScanAST *p = new_scanast(0); /* token of 0 is wildcard */ + parser->token = stringscan_gettok(parser->lexer); + p->label_num = label; + return p; + } + sprintf(ebuf, "mismatch token in scan(): %s", scan_token_str(parser->token)); + panic(ebuf); + return NULL; +} + +void PCCTS_AST:: +stringparser_init(StringParser *parser, StringLexer *input) +{ + parser->lexer = input; + parser->token = stringscan_gettok(parser->lexer); + parser->num_labels = 0; +} + +void PCCTS_AST:: +stringlexer_init(StringLexer *scanner, char *input) +{ + scanner->text[0]='\0'; + scanner->input = input; + scanner->p = input; + stringscan_advance(scanner); +} + +void PCCTS_AST:: +stringscan_advance(StringLexer *scanner) +{ + if ( *(scanner->p) == '\0' ) scanner->c = __StringScanEOF; + scanner->c = *(scanner->p)++; +} + +int PCCTS_AST:: +stringscan_gettok(StringLexer *scanner) +{ + char *index = &scanner->text[0]; + char ebuf[100]; /* MR23 Remove static */ + + while ( isspace(scanner->c) ) { stringscan_advance(scanner); } + if ( isdigit(scanner->c) ) + { + int tok = __INT; + while ( isdigit(scanner->c) ) { + *index++ = (char) /* static_cast */ (scanner->c); // MR23 + stringscan_advance(scanner); + } + *index = '\0'; + return tok; + } + switch ( scanner->c ) + { + case '#' : stringscan_advance(scanner); return __POUND; + case '(' : stringscan_advance(scanner); return __LPAREN; + case ')' : stringscan_advance(scanner); return __RPAREN; + case '%' : stringscan_advance(scanner); return __PERCENT; + case ':' : stringscan_advance(scanner); return __COLON; + case '.' : stringscan_advance(scanner); return __PERIOD; + case '\0' : return __StringScanEOF; + case __StringScanEOF : return __StringScanEOF; + default : + sprintf(ebuf, "invalid char in scan: '%c'", scanner->c); + panic(ebuf); + } + return __StringScanEOF; // never reached +} + +const char *PCCTS_AST:: /* MR20 const */ +scan_token_str(int t) +{ + if ( VALID_SCAN_TOKEN(t) ) return scan_token_tbl[t]; + else if ( t==__StringScanEOF ) return ""; + else return ""; +} + +//MR23 +int PCCTS_AST::printMessage(FILE* pFile, const char* pFormat, ...) +{ + va_list marker; + va_start( marker, pFormat ); + int iRet = vfprintf(pFile, pFormat, marker); + va_end( marker ); + return iRet; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/PCCTSAST.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/PCCTSAST.h new file mode 100644 index 00000000..9fb3fd7a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/PCCTSAST.h @@ -0,0 +1,143 @@ +/* Abstract syntax tree + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef PCCTSAST_H +#define PCCTSAST_H + +#include "pcctscfg.h" + +#include "pccts_stdio.h" +#include "pccts_stdlib.h" + +PCCTS_NAMESPACE_STD + +//class SList; + +#define StringScanMaxText 50 +#define MaxTreeStackDepth 400 + +// +// 7-Apr-97 133MR1 signed int not accepted by AT&T cfront +// +typedef struct stringlexer { + int c; // MR1 + char *input; + char *p; + char text[StringScanMaxText]; + } StringLexer; + +/* Define the structures needed for ast_scan() */ +typedef struct stringparser { + int token; + StringLexer *lexer; + int num_labels; + } StringParser; + +typedef struct _scanast { + struct _scanast *_right, *_down; + int _token; + int label_num; + int type() { return _token; } + struct _scanast *right() { return _right; } + struct _scanast *down() { return _down; } + } ScanAST; + +#define VALID_SCAN_TOKEN(t) (t>=__LPAREN && t<=__PERIOD) + +class DllExportPCCTS PCCTS_AST { +protected: + static const char *scan_token_tbl[]; /* MR20 const */ + enum { + __LPAREN=1, + __RPAREN=2, + __PERCENT=3, + __INT=4, + __COLON=5, + __POUND=6, + __PERIOD=7, + __StringScanEOF=-1}; + +protected: + const char *scan_token_str(int t); /* MR20 const */ + void stringlexer_init(StringLexer *scanner, char *input); + void stringparser_init(StringParser *, StringLexer *); + ScanAST *stringparser_parse_scanast(char *templ, int *n); + ScanAST *stringparser_parse_tree(StringParser *parser); + ScanAST *stringparser_parse_element(StringParser *parser); + void stringscan_advance(StringLexer *scanner); + int stringscan_gettok(StringLexer *scanner); + void _push(PCCTS_AST **st, int *sp, PCCTS_AST *e); + PCCTS_AST *_pop(PCCTS_AST **st, int *sp); + int match_partial(PCCTS_AST *t, PCCTS_AST *u); + int scanmatch(ScanAST *t, PCCTS_AST **labels[], int *n); + void scanast_free(ScanAST *t); + ScanAST *new_scanast(int tok); + void stringparser_match(StringParser *parser, int type); + virtual PCCTS_AST *deepCopyBushy(); + +public: + PCCTS_AST() {;} + virtual ~PCCTS_AST() {;} + + /* This group must be defined for SORCERER to work correctly */ + virtual PCCTS_AST *right() = 0; + virtual PCCTS_AST *down() = 0; + virtual void setRight(PCCTS_AST *t) = 0; + virtual void setDown(PCCTS_AST *t) = 0; +// we define these so ANTLR doesn't have to + virtual int type() { return 0; } + virtual void setType(int /*t MR23 */) {;} + virtual PCCTS_AST *shallowCopy() {panic("no shallowCopy() defined"); return NULL;} + + /* These are not needed by ANTLR, but are support functions */ + virtual PCCTS_AST *deepCopy(); // used by SORCERER in transform mode + virtual void addChild(PCCTS_AST *t); + virtual void lisp_action(FILE * /*f MR23 */) {;} + virtual void lisp(FILE *f); + static PCCTS_AST *make(PCCTS_AST *rt, ...); + virtual PCCTS_AST *ast_find_all(PCCTS_AST *u, PCCTS_AST **cursor); + virtual int match(PCCTS_AST *u); + virtual void insert_after(PCCTS_AST *b); + virtual void append(PCCTS_AST *b); + virtual PCCTS_AST *tail(); + virtual PCCTS_AST *bottom(); + static PCCTS_AST *cut_between(PCCTS_AST *a, PCCTS_AST *b); +// virtual SList *to_slist(); + virtual void tfree(); + int ast_scan(char *templ, ...); + virtual int nsiblings(); + virtual PCCTS_AST *sibling_index(int i); + + void require(int e,const char *err){ if ( !e ) panic(err); } /* MR20 const */ + virtual void panic(const char *err) // MR20 const + { /* MR23 */ printMessage(stderr, "PCCTS_AST: %s\n", err); exit(PCCTS_EXIT_FAILURE); } + virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23 +}; + +#endif /* PCCTSAST_H */ diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/SList.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/SList.h new file mode 100644 index 00000000..34354ccd --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/SList.h @@ -0,0 +1,72 @@ +#ifndef SList_h +#define SList_h + +/* + * SList.h + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to SORCERER -- SORCERER is in the public + * domain. An individual or company may do whatever they wish with + * source code distributed with SORCERER or the code generated by + * SORCERER, including the incorporation of SORCERER, or its output, into + * commerical software. + * + * We encourage users to develop software with SORCERER. However, we do + * ask that credit is given to us for developing SORCERER. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like SORCERER and have developed a nice tool with the + * output, please mention that you developed it using SORCERER. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * PCCTS 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1992-2000 + */ + +#include "pcctscfg.h" + +#include "pccts_stdio.h" +#include "pccts_stdlib.h" + +PCCTS_NAMESPACE_STD + +#include "PCCTSAST.h" + +class PCCTS_AST; + +class SListNode { +protected: + void *_elem; /* pointer to any kind of element */ + SListNode *_next; +public: + SListNode() {_elem=_next=NULL;} + virtual ~SListNode() {_elem=_next=NULL;} + void *elem() { return _elem; } + void setElem(void *e) { _elem = e; } + void setNext(SListNode *t) { _next = t; } + SListNode *next() { return _next; } +}; + +class SList { + SListNode *head, *tail; +public: + SList() {head=tail=NULL;} + virtual ~SList() {head=tail=NULL;} + virtual void *iterate(SListNode **); + virtual void add(void *e); + virtual void lfree(); + virtual PCCTS_AST *to_ast(SList list); + virtual void require(int e,char *err){ if ( !e ) panic(err); } + virtual void panic(char *err){ /* MR23 */ printMessage(stderr, "SList panic: %s\n", err); exit(PCCTS_EXIT_FAILURE); } + virtual int printMessage(FILE* pFile, const char* pFormat, ...); // MR23 +}; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/antlr.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/antlr.h new file mode 100644 index 00000000..9d50bd83 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/antlr.h @@ -0,0 +1,807 @@ +/* antlr.h + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ANTLR_H +#define ANTLR_H + +#include "pcctscfg.h" + +#include "pccts_stdio.h" + +/* turn off warnings for unreferenced labels */ + +#ifdef _MSC_VER +#pragma warning(disable:4102) +#endif + +/* + * Define all of the stack setup and manipulation of $i, #i variables. + * + * Notes: + * The type 'Attrib' must be defined before entry into this .h file. + */ + + +#ifdef __USE_PROTOS +#include "pccts_stdlib.h" +#else +#ifdef VAXC +#include +#else +#include +#endif +#endif +#include "pccts_string.h" + +#if 0 +#include "set.h" +#endif + + +typedef int ANTLRTokenType; +typedef unsigned char SetWordType; + +typedef char ANTLRChar; + + /* G u e s s S t u f f */ + +#ifdef ZZCAN_GUESS +#ifndef ZZINF_LOOK +#define ZZINF_LOOK +#endif +#endif + +#ifdef ZZCAN_GUESS +typedef struct _zzjmp_buf { + jmp_buf state; + } zzjmp_buf; +#endif + + +/* can make this a power of 2 for more efficient lookup */ + +#ifndef ZZLEXBUFSIZE +#define ZZLEXBUFSIZE 8000 /* MR22 raise from 2k to 8k */ +#endif + +#define zzOvfChk \ + if ( zzasp <= 0 ) \ + { \ + fprintf(stderr, zzStackOvfMsg, __FILE__, __LINE__); \ + exit(PCCTS_EXIT_FAILURE); \ + } + +#ifndef ZZA_STACKSIZE +#define ZZA_STACKSIZE 400 +#endif +#ifndef ZZAST_STACKSIZE +#define ZZAST_STACKSIZE 400 +#endif + +#ifndef zzfailed_pred +#ifdef ZZCAN_GUESS +#define zzfailed_pred(_p,_hasuseraction,_useraction) \ + if (zzguessing) { \ + zzGUESS_FAIL; \ + } else { \ + zzfailed_pred_action(_p,_hasuseraction,_useraction); \ + } +#else +#define zzfailed_pred(_p,_hasuseraction,_useraction) \ + zzfailed_pred_action(_p,_hasuseraction,_useraction); +#endif +#endif + +/* MR23 Provide more control over failed predicate action + without any need for user to worry about guessing internals. + _hasuseraction == 0 => no user specified error action + _hasuseraction == 1 => user specified error action +*/ + +#ifndef zzfailed_pred_action +#define zzfailed_pred_action(_p,_hasuseraction,_useraction) \ + if (_hasuseraction) { _useraction } \ + else { fprintf(stderr, "semantic error; failed predicate: '%s'\n",_p); } +#endif + +/* MR19 zzchar_t additions */ + +#ifdef LL_K +#define LOOKAHEAD \ + int zztokenLA[LL_K]; \ + zzchar_t zztextLA[LL_K][ZZLEXBUFSIZE]; \ + int zzlap = 0, zzlabase=0; /* labase only used for DEMAND_LOOK */ +#else +#define LOOKAHEAD \ + int zztoken; +#endif + +#ifndef zzcr_ast +#define zzcr_ast(ast,attr,tok,text) +#endif + +#ifdef DEMAND_LOOK +#define DemandLookData int zzdirty=1; +#else +#define DemandLookData +#endif + +#ifndef zzUSER_GUESS_HOOK +#define zzUSER_GUESS_HOOK(seqFrozen,zzrv) +#endif + +#ifndef zzUSER_GUESS_DONE_HOOK +#define zzUSER_GUESS_DONE_HOOK(seqFrozen) +#endif + + /* S t a t e S t u f f */ + +#ifdef ZZCAN_GUESS +#define zzGUESS_BLOCK zzantlr_state zzst; int zzrv; int zzGuessSeqFrozen; + +/* MR10 change zzGUESS: do zzGUESS_DONE when zzrv==1 after longjmp as in C++ mode */ + +#define zzGUESS zzsave_antlr_state(&zzst); \ + zzguessing = 1; \ + zzGuessSeqFrozen=++zzGuessSeq; \ + zzrv = setjmp(zzguess_start.state); \ + zzUSER_GUESS_HOOK(zzGuessSeqFrozen,zzrv) \ + if (zzrv) zzGUESS_DONE; +#ifdef zzTRACE_RULES +#define zzGUESS_FAIL { zzTraceGuessFail(); longjmp(zzguess_start.state, 1); } +#else +#define zzGUESS_FAIL longjmp(zzguess_start.state, 1) +#endif + +/* MR10 change zzGUESS_DONE: zzrv=1 to simulate longjmp() return value as in C++ mode */ + +#define zzGUESS_DONE { zzrestore_antlr_state(&zzst); zzrv=1; zzUSER_GUESS_DONE_HOOK(zzGuessSeqFrozen) } +#define zzNON_GUESS_MODE if ( !zzguessing ) +#define zzGuessData \ + zzjmp_buf zzguess_start; \ + int zzguessing; +#else +#define zzGUESS_BLOCK +#define zzGUESS +#define zzGUESS_FAIL +#define zzGUESS_DONE +#define zzNON_GUESS_MODE +#define zzGuessData +#endif + +typedef struct _zzantlr_state { +#ifdef ZZCAN_GUESS + zzjmp_buf guess_start; + int guessing; +#endif + int asp; + int ast_sp; +#ifdef ZZINF_LOOK + int inf_lap; /* not sure we need to save this one */ + int inf_labase; + int inf_last; + +/* MR6 Gunnar Rxnning (gunnar@candleweb.no) */ +/* MR6 Additional state needs to be saved/restored */ +/* MR6 Matching changes in err.h */ + + int *inf_tokens; /* MR6 */ + char **inf_text; /* MR6 */ + char *inf_text_buffer; /* MR6 */ + int *inf_line; /* MR6 */ +#endif +#ifdef DEMAND_LOOK + int dirty; +#endif + +#ifdef LL_K + int tokenLA[LL_K]; + char textLA[LL_K][ZZLEXBUFSIZE]; + int lap; + int labase; +#else + int token; + char text[ZZLEXBUFSIZE]; +#endif +#ifdef zzTRACE_RULES + int traceOptionValue; /* MR10 */ + int traceGuessOptionValue; /* MR10 */ + char *traceCurrentRuleName; /* MR10 */ + int traceDepth; /* MR10 */ +#endif + + } zzantlr_state; + +#ifdef zzTRACE_RULES +extern int zzTraceOptionValueDefault; +extern int zzTraceOptionValue; +extern int zzTraceGuessOptionValue; +extern char *zzTraceCurrentRuleName; +extern int zzTraceDepth; +#endif + +extern int zzGuessSeq; /* MR10 */ +extern int zzSyntaxErrCount; /* MR11 */ +extern int zzLexErrCount; /* MR11 */ + + /* I n f i n i t e L o o k a h e a d */ + + +#ifdef ZZINF_LOOK +#define InfLookData \ + int *zzinf_tokens; \ + char **zzinf_text; \ + char *zzinf_text_buffer; \ + int *zzinf_line; \ + int zzinf_labase; \ + int zzinf_last; +#else +#define InfLookData +#endif + +#ifdef ZZINF_LOOK + +#ifndef ZZINF_DEF_TEXT_BUFFER_SIZE +#define ZZINF_DEF_TEXT_BUFFER_SIZE 20000 +#endif +#ifndef ZZINF_DEF_TOKEN_BUFFER_SIZE +#define ZZINF_DEF_TOKEN_BUFFER_SIZE 2000 +#endif +/* WARNING!!!!!! + * ZZINF_BUFFER_TEXT_CHUNK_SIZE must be > sizeof(text) largest possible token. + */ +#ifndef ZZINF_BUFFER_TEXT_CHUNK_SIZE +#define ZZINF_BUFFER_TEXT_CHUNK_SIZE 5000 +#endif +#ifndef ZZINF_BUFFER_TOKEN_CHUNK_SIZE +#define ZZINF_BUFFER_TOKEN_CHUNK_SIZE 1000 +#endif + +#if ZZLEXBUFSIZE > ZZINF_BUFFER_TEXT_CHUNK_SIZE +#define ZZINF_BUFFER_TEXT_CHUNK_SIZE ZZLEXBUFSIZE+5 +#endif + +/* make inf_look user-access macros */ +#ifdef LL_K +#define ZZINF_LA_VALID(i) (((zzinf_labase+i-1)-LL_K+1) <= zzinf_last) +#define ZZINF_LA(i) zzinf_tokens[(zzinf_labase+i-1)-LL_K+1] +#define ZZINF_LATEXT(i) zzinf_text[(zzinf_labase+i-1)-LL_K+1] +/* MR6 In 1.33 vanilla the #define ZZINF_LINE(i) is was commented out */ +#define ZZINF_LINE(i) zzinf_line[(zzinf_labase+i-1)-LL_K+1] +#else +#define ZZINF_LA_VALID(i) (((zzinf_labase+i-1)) <= zzinf_last) +#define ZZINF_LA(i) zzinf_tokens[(zzinf_labase+i-1)] +#define ZZINF_LATEXT(i) zzinf_text[(zzinf_labase+i-1)] +#endif + +#define inf_zzgettok _inf_zzgettok() +extern void _inf_zzgettok(); + +#endif /* ZZINF_LOOK */ + + +#ifdef LL_K + +#ifdef __USE_PROTOS +#define ANTLR_INFO \ + Attrib zzempty_attr(void) {static Attrib a; return a;} \ + Attrib zzconstr_attr(int _tok, char *_text) \ + {Attrib a; zzcr_attr((&a),_tok,_text); return a;} \ + int zzasp=ZZA_STACKSIZE; \ + char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n"; \ + Attrib zzaStack[ZZA_STACKSIZE]; DemandLookData \ + InfLookData \ + zzGuessData +#else +#define ANTLR_INFO \ + Attrib zzempty_attr() {static Attrib a; return a;} \ + Attrib zzconstr_attr(_tok, _text) int _tok; char *_text; \ + {Attrib a; zzcr_attr((&a),_tok,_text); return a;} \ + int zzasp=ZZA_STACKSIZE; \ + char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n"; \ + Attrib zzaStack[ZZA_STACKSIZE]; DemandLookData \ + InfLookData \ + zzGuessData +#endif + +#else + +#ifdef __USE_PROTOS +#define ANTLR_INFO \ + Attrib zzempty_attr(void) {static Attrib a; return a;} \ + Attrib zzconstr_attr(int _tok, char *_text) \ + {Attrib a; zzcr_attr((&a),_tok,_text); return a;} \ + int zzasp=ZZA_STACKSIZE; \ + char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n"; \ + Attrib zzaStack[ZZA_STACKSIZE]; DemandLookData \ + InfLookData \ + zzGuessData +#else +#define ANTLR_INFO \ + Attrib zzempty_attr() {static Attrib a; return a;} \ + Attrib zzconstr_attr(_tok, _text) int _tok; char *_text; \ + {Attrib a; zzcr_attr((&a),_tok,_text); return a;} \ + int zzasp=ZZA_STACKSIZE; \ + char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n"; \ + Attrib zzaStack[ZZA_STACKSIZE]; DemandLookData \ + InfLookData \ + zzGuessData +#endif + +#endif /* LL_k */ + + +#ifdef ZZINF_LOOK + +#ifdef LL_K +#ifdef DEMAND_LOOK +#define zzPrimeLookAhead {zzdirty=LL_K; zzlap = zzlabase = 0;} +#else +#define zzPrimeLookAhead {zzlap = zzlabase = 0; zzfill_inf_look();\ + {int _i; for(_i=1;_i<=LL_K; _i++) \ + {zzCONSUME;} zzlap = zzlabase = 0;}} +#endif + +#else /* LL_K */ + +#ifdef DEMAND_LOOK +#define zzPrimeLookAhead zzfill_inf_look(); zzdirty=1 +#else +#define zzPrimeLookAhead zzfill_inf_look(); inf_zzgettok + +#endif +#endif /* LL_K */ + +#else /* ZZINF_LOOK */ + +#ifdef LL_K +#ifdef DEMAND_LOOK +#define zzPrimeLookAhead {zzdirty=LL_K; zzlap = zzlabase = 0;} +#else +#define zzPrimeLookAhead {int _i; zzlap = 0; for(_i=1;_i<=LL_K; _i++) \ + {zzCONSUME;} zzlap = 0;} +#endif + +#else + +#ifdef DEMAND_LOOK +#define zzPrimeLookAhead zzdirty=1 +#else +#define zzPrimeLookAhead zzgettok() +#endif +#endif /* LL_K */ + +#endif /* ZZINF_LOOK */ + + +#ifdef LL_K +#define zzenterANTLRs(s) \ + zzlextext = &(zztextLA[0][0]); zzrdstr( s ); zzPrimeLookAhead; +#define zzenterANTLRf(f) \ + zzlextext = &(zztextLA[0][0]); zzrdfunc( f ); zzPrimeLookAhead; +#define zzenterANTLR(f) \ + zzlextext = &(zztextLA[0][0]); zzrdstream( f ); zzPrimeLookAhead; +#ifdef ZZINF_LOOK +#define zzleaveANTLR(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line); +#define zzleaveANTLRf(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line); +#define zzleaveANTLRs(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line); +#else +#define zzleaveANTLR(f) +#define zzleaveANTLRf(f) +#define zzleaveANTLRs(f) +#endif + +#else + +#define zzenterANTLRs(s) \ + {static char zztoktext[ZZLEXBUFSIZE]; \ + zzlextext = zztoktext; zzrdstr( s ); zzPrimeLookAhead;} +#define zzenterANTLRf(f) \ + {static char zztoktext[ZZLEXBUFSIZE]; \ + zzlextext = zztoktext; zzrdfunc( f ); zzPrimeLookAhead;} +#define zzenterANTLR(f) \ + {static char zztoktext[ZZLEXBUFSIZE]; \ + zzlextext = zztoktext; zzrdstream( f ); zzPrimeLookAhead;} +#ifdef ZZINF_LOOK +#define zzleaveANTLR(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line); +#define zzleaveANTLRf(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line); +#define zzleaveANTLRs(f) free(zzinf_text_buffer); free(zzinf_text); free(zzinf_tokens); free(zzinf_line); +#else +#define zzleaveANTLR(f) +#define zzleaveANTLRf(f) +#define zzleaveANTLRs(f) +#endif + +#endif + +/* MR19 Paul D. Smith (psmith@baynetworks.com) + Need to adjust AST stack pointer at exit. + Referenced in ANTLRx macros. +*/ + +#ifdef GENAST +#define ZZAST_ADJUST ++zzast_sp; +#else +#define ZZAST_ADJUST +#endif + +#define ANTLR(st, f) zzbufsize = ZZLEXBUFSIZE; \ + zzenterANTLR(f); \ + { \ + zzBLOCK(zztasp1); \ + st; /* ++zzasp; Removed MR20 G. Hobbelt */ \ + /* ZZAST_ADJUST Removed MR20 G. Hobbelt */ \ + /* MR20 G. Hobbelt. Kill the top' attribute (+AST stack corr.) */ \ + zzEXIT_ANTLR(zztasp1 + 1); \ + } \ + zzleaveANTLR(f); + +#define ANTLRm(st, f, _m) zzbufsize = ZZLEXBUFSIZE; \ + zzmode(_m); \ + zzenterANTLR(f); \ + { \ + zzBLOCK(zztasp1); \ + st; /* ++zzasp; Removed MR20 G. Hobbelt */ \ + /* ZZAST_ADJUST Removed MR20 G. Hobbelt */ \ + /* MR20 G. Hobbelt. Kill the top' attribute (+AST stack corr.) */ \ + zzEXIT_ANTLR(zztasp1 + 1); \ + } \ + zzleaveANTLR(f); + +#define ANTLRf(st, f) zzbufsize = ZZLEXBUFSIZE; \ + zzenterANTLRf(f); \ + { \ + zzBLOCK(zztasp1); \ + st; /* ++zzasp; Removed MR20 G. Hobbelt */ \ + /* ZZAST_ADJUST Removed MR20 G. Hobbelt */ \ + /* MR20 G. Hobbelt. Kill the top' attribute (+AST stack corr.) */ \ + zzEXIT_ANTLR(zztasp1 + 1); \ + } \ + zzleaveANTLRf(f); + +#define ANTLRs(st, s) zzbufsize = ZZLEXBUFSIZE; \ + zzenterANTLRs(s); \ + { \ + zzBLOCK(zztasp1); \ + st; /* ++zzasp; Removed MR20 G. Hobbelt */ \ + /* ZZAST_ADJUST Removed MR20 G. Hobbelt */ \ + /* MR20 G. Hobbelt. Kill the top' attribute (+AST stack corr.) */ \ + zzEXIT_ANTLR(zztasp1 + 1); \ + } \ + zzleaveANTLRs(s); + +#ifdef LL_K +#define zztext (&(zztextLA[zzlap][0])) +#else +#define zztext zzlextext +#endif + + + /* A r g u m e n t A c c e s s */ + +#define zzaCur (zzaStack[zzasp]) +#define zzaRet (*zzaRetPtr) +#define zzaArg(v,n) zzaStack[v-n] +#define zzMakeAttr { zzNON_GUESS_MODE {zzOvfChk; --zzasp; zzcr_attr(&(zzaStack[zzasp]),LA(1),LATEXT(1));}} +#ifdef zzdef0 +#define zzMake0 { zzOvfChk; --zzasp; zzdef0(&(zzaStack[zzasp]));} +#else +#define zzMake0 { zzOvfChk; --zzasp;} +#endif +#define zzaPush(_v) { zzOvfChk; zzaStack[--zzasp] = _v;} +#ifndef zzd_attr +#define zzREL(t) zzasp=(t); /* Restore state of stack */ +#else +#define zzREL(t) for (; zzasp<(t); zzasp++) \ + { zzd_attr(&(zzaStack[zzasp])); } +#endif + + +#define zzsetmatch(_es,_tokclassErrset) \ + if ( !_zzsetmatch(_es, &zzBadText, &zzMissText, &zzMissTok, &zzBadTok, &zzMissSet, _tokclassErrset) ) goto fail; /* MR23 */ + +#ifdef ZZCAN_GUESS +#define zzsetmatch_wsig(_es, handler) \ + if ( !_zzsetmatch_wsig(_es) ) if (zzguessing) { zzGUESS_FAIL; } else {_signal=MismatchedToken; goto handler;} +#else +#define zzsetmatch_wsig(_es, handler) \ + if ( !_zzsetmatch_wsig(_es) ) {_signal=MismatchedToken; goto handler;} +#endif + +#ifdef __USE_PROTOS +extern int _zzsetmatch(SetWordType *, char **, char **, int *, int *, SetWordType **, SetWordType * /* MR23 */); +extern int _zzsetmatch_wsig(SetWordType *); +#else +extern int _zzsetmatch(); +extern int _zzsetmatch_wsig(); +#endif + +#define zzmatch(_t) \ + if ( !_zzmatch(_t, &zzBadText, &zzMissText, &zzMissTok, &zzBadTok, &zzMissSet) ) goto fail; + +#ifdef ZZCAN_GUESS +#define zzmatch_wsig(_t,handler) \ + if ( !_zzmatch_wsig(_t) ) if (zzguessing) { zzGUESS_FAIL; } else {_signal=MismatchedToken; goto handler;} +#else +#define zzmatch_wsig(_t,handler) \ + if ( !_zzmatch_wsig(_t) ) {_signal=MismatchedToken; goto handler;} +#endif + +#ifdef __USE_PROTOS +extern int _zzmatch(int, char **, char **, int *, int *, SetWordType **); +extern int _zzmatch_wsig(int); +#else +extern int _zzmatch(); +extern int _zzmatch_wsig(); +#endif + +#define zzmatch_wdfltsig(_t,_f) \ + if ( !_zzmatch_wdfltsig(_t,_f) ) _signal=MismatchedToken; +#define zzsetmatch_wdfltsig(tw,tt,wf) \ + if ( !_zzsetmatch_wdfltsig(tw,tt,wf) ) _signal=MismatchedToken; + +#ifdef __USE_PROTOS +extern int _zzmatch_wdfltsig(int, SetWordType *); +extern int _zzsetmatch_wdfltsig(SetWordType *tokensWanted, + int tokenTypeOfSet, + SetWordType *whatFollows); +#else +extern int _zzmatch_wdfltsig(); +extern int _zzsetmatch_wdfltsig(); +#endif + +#ifdef GENAST +#define zzRULE Attrib *zzaRetPtr = &(zzaStack[zzasp-1]); \ + SetWordType *zzMissSet=NULL; int zzMissTok=0; \ + int zzBadTok=0; char *zzBadText=""; \ + int zzErrk=1,zzpf=0; \ + zzTRACEdata \ + char *zzMissText=""; zzASTVars +#else +#define zzRULE Attrib *zzaRetPtr = &(zzaStack[zzasp-1]); \ + int zzBadTok=0; char *zzBadText=""; \ + int zzErrk=1,zzpf=0; \ + zzTRACEdata \ + SetWordType *zzMissSet=NULL; int zzMissTok=0; char *zzMissText="" +#endif + +#ifdef GENAST +#define zzBLOCK(i) int i = zzasp - 1; int zztsp = zzast_sp +#define zzEXIT(i) zzREL(i); zzastREL; zzNON_GUESS_MODE { zzastPush(*_root); } +#define zzEXIT_ANTLR(i) zzREL(i); zzastREL /* [i_a] added as we want this for the ANTLRx() macros */ +#define zzLOOP(i) zzREL(i); zzastREL +#else +#define zzBLOCK(i) int i = zzasp - 1 +#define zzEXIT(i) zzREL(i) +#define zzEXIT_ANTLR(i) zzREL(i) /* [i_a] added as we want this for the ANTLRx() macros */ +#define zzLOOP(i) zzREL(i) +#endif + +#ifdef LL_K + +#ifdef DEMAND_LOOK +#define LOOK(_k) {int i,stop=_k-(LL_K-zzdirty); for (i=1; i<=stop; i++) \ + zzCONSUME;} +#define zzCONSUME {zzgettok(); zzdirty--; \ + zzlap = (zzlap+1)&(LL_K-1); \ + zzlextext = &(zztextLA[zzlap][0]);} +#else +#ifdef ZZINF_LOOK +#define zzCONSUME {inf_zzgettok; \ + zzlap = (zzlap+1)&(LL_K-1); \ + zzlextext = &(zztextLA[zzlap][0]); \ + } +#else +#define zzCONSUME {zzgettok(); \ + zzlap = (zzlap+1)&(LL_K-1); \ + zzlextext = &(zztextLA[zzlap][0]);} +#endif /* ZZINF_LOOK */ +#endif /* DEMAND_LOOK */ + +#else /* LL_K */ + +#ifdef DEMAND_LOOK +#define LOOK(_k) if ( zzdirty) zzCONSUME; +#ifdef ZZINF_LOOK +#define zzCONSUME inf_zzgettok; zzdirty=0; +#else +#define zzCONSUME zzgettok(); zzdirty=0; +#endif /* ZZINF_LOOK */ + +#else /* DEMAND_LOOK */ + +#ifdef ZZINF_LOOK +#define zzCONSUME inf_zzgettok +#else +#define zzCONSUME zzgettok(); +#endif + +#endif /* DEMAND_LOOK */ + +#endif /* LL_K */ + +#ifdef LL_K +#define NLA zztokenLA[zzlap&(LL_K-1)] /* --> next LA */ +#define NLATEXT zztextLA[zzlap&(LL_K-1)] /* --> next text of LA */ +#ifdef DEMAND_LOOK +#define LA(i) zztokenLA[(zzlabase+(i)-1)&(LL_K-1)] +#define LATEXT(i) (&(zztextLA[(zzlabase+(i)-1)&(LL_K-1)][0])) +#else +#define LA(i) zztokenLA[(zzlap+(i)-1)&(LL_K-1)] +#define LATEXT(i) (&(zztextLA[(zzlap+(i)-1)&(LL_K-1)][0])) +#endif +#else +#define NLA zztoken +#define NLATEXT zztext +#define LA(i) zztoken +#define LATEXT(i) zztext +#endif + + + /* S t a n d a r d S i g n a l s */ + +#define NoSignal 0 +#define MismatchedToken 1 +#define NoViableAlt 2 +#define NoSemViableAlt 3 + +/* MR7 Allow more control over signalling */ +/* by adding "Unwind" and "zzsetSignal" */ + +#define Unwind 4 +#define zzsetSignal(newValue) *_retsignal=_signal=(newValue) +#define zzsuppressSignal *_retsignal=_signal=0 +#define zzexportSignal *_retsignal=_signal + + /* F u n c t i o n T r a c i n g */ + +#ifndef zzTRACE_RULES +#define zzTRACEdata +#else +#ifndef zzTRACEdata +#define zzTRACEdata ANTLRChar *zzTracePrevRuleName = NULL; +#endif +#endif + +#ifndef zzTRACEIN +#define zzTRACEIN(r) zzTracePrevRuleName=zzTraceCurrentRuleName;zzTraceIn(r); +#endif +#ifndef zzTRACEOUT +#define zzTRACEOUT(r) zzTraceOut(r);zzTraceCurrentRuleName=zzTracePrevRuleName; +#endif + +/* MR19 zzchar_t additions */ + +#ifndef zzchar_t +#ifdef ZZWCHAR_T +#define zzchar_t wchar_t +#else +#define zzchar_t char +#endif +#endif + + +/* MR26 */ + +#ifdef PCCTS_USE_STDARG +extern void zzFAIL(int k, ...); +#else +extern void zzFAIL(); +#endif + /* E x t e r n D e f s */ + +#ifdef __USE_PROTOS +extern Attrib zzempty_attr(void); +extern Attrib zzconstr_attr(int, char *); +extern void zzsyn(char *, int, char *, SetWordType *, int, int, char *); +extern int zzset_el(unsigned, SetWordType *); +extern int zzset_deg(SetWordType *); +extern void zzedecode(SetWordType *); + +extern void zzresynch(SetWordType *, SetWordType); +extern void zzsave_antlr_state(zzantlr_state *); +extern void zzrestore_antlr_state(zzantlr_state *); +extern void zzfill_inf_look(void); +extern void zzconsumeUntil(SetWordType *st); /* MR7 */ +extern void zzconsumeUntilToken(int t); /* MR7 */ +extern void zzTraceIn(char * ruleName); /* MR10 */ +extern void zzTraceOut(char * ruleName); /* MR10 */ +extern int zzTraceOption(int delta); /* MR10 */ +extern int zzTraceGuessOption(int delta); /* MR10 */ +extern void zzTraceReset(void); /* MR10 */ +extern void zzTraceGuessFail(void); /* MR10 */ +#ifdef EXCEPTION_HANDLING +extern void zzdflthandlers(int, int *); +#endif +#else +extern Attrib zzempty_attr(); +extern Attrib zzconstr_attr(); +extern void zzsyn(); +extern int zzset_el(); +extern int zzset_deg(); +extern void zzedecode(); +extern void zzresynch(); +extern void zzsave_antlr_state(); +extern void zzrestore_antlr_state(); +extern void zzfill_inf_look(); +extern void zzconsumeUntil(); /* MR7 */ +extern void zzconsumeUntilToken(); /* MR7 */ +extern void zzTraceIn(); /* MR10 */ +extern void zzTraceOut(); /* MR10 */ +extern int zzTraceOption(); /* MR10 */ +extern int zzTraceGuessOption(); /* MR10 */ +extern void zzTraceReset(); /* MR10 */ +extern void zzTraceGuessFail(); /* MR10 */ +#ifdef EXCEPTION_HANDLING +extern void zzdflthandlers(); +#endif +#endif + + /* G l o b a l V a r i a b l e s */ + +/* Define a parser; user should do a "#parser myname" in their grammar file */ +/*extern struct pccts_parser zzparser;*/ + +extern char *zztokens[]; +#ifdef LL_K +extern int zztokenLA[]; +extern zzchar_t zztextLA[][ZZLEXBUFSIZE]; +extern int zzlap; +extern int zzlabase; +#else +extern int zztoken; +#endif + +extern char zzStackOvfMsg[]; +extern int zzasp; +extern Attrib zzaStack[]; +#ifdef ZZINF_LOOK +extern int *zzinf_tokens; +extern char **zzinf_text; +extern char *zzinf_text_buffer; +extern int *zzinf_line; +extern int zzinf_labase; +extern int zzinf_last; +#endif +#ifdef DEMAND_LOOK +extern int zzdirty; +#endif +#ifdef ZZCAN_GUESS +extern int zzguessing; +extern zzjmp_buf zzguess_start; +#endif + +/* Define global variables that refer to values exported by the scanner. + * These declarations duplicate those in dlgdef.h, but are needed + * if ANTLR is not to generate a .dlg file (-gx); PS, this is a hack. + */ +extern zzchar_t *zzlextext; /* text of most recently matched token */ +extern int zzbufsize; /* how long zzlextext is */ + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ast.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ast.c new file mode 100644 index 00000000..45007e35 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ast.c @@ -0,0 +1,345 @@ +/* Abstract syntax tree manipulation functions + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#include "pcctscfg.h" + +#ifdef PCCTS_USE_STDARG +#include "pccts_stdarg.h" +#else +#include +#endif + +/* ensure that tree manipulation variables are current after a rule + * reference + */ + +void +#ifdef __USE_PROTOS +zzlink(AST **_root, AST **_sibling, AST **_tail) +#else +zzlink(_root, _sibling, _tail) +AST **_root, **_sibling, **_tail; +#endif +{ + if ( *_sibling == NULL ) return; + if ( *_root == NULL ) *_root = *_sibling; + else if ( *_root != *_sibling ) (*_root)->down = *_sibling; + if ( *_tail==NULL ) *_tail = *_sibling; + while ( (*_tail)->right != NULL ) *_tail = (*_tail)->right; +} + +AST * +#ifdef __USE_PROTOS +zzastnew(void) +#else +zzastnew() +#endif +{ + AST *p = (AST *) calloc(1, sizeof(AST)); + if ( p == NULL ) fprintf(stderr,"%s(%d): cannot allocate AST node\n",__FILE__,__LINE__); + return p; +} + +/* add a child node to the current sibling list */ +void +#ifdef __USE_PROTOS +zzsubchild(AST **_root, AST **_sibling, AST **_tail) +#else +zzsubchild(_root, _sibling, _tail) +AST **_root, **_sibling, **_tail; +#endif +{ + AST *n; + zzNON_GUESS_MODE { + n = zzastnew(); +#ifdef DEMAND_LOOK + zzcr_ast(n, &(zzaCur), LA(0), LATEXT(0)); +#else + zzcr_ast(n, &(zzaCur), LA(1), LATEXT(1)); +#endif + zzastPush( n ); + if ( *_tail != NULL ) (*_tail)->right = n; + else { + *_sibling = n; + if ( *_root != NULL ) (*_root)->down = *_sibling; + } + *_tail = n; + if ( *_root == NULL ) *_root = *_sibling; + } +} + +/* make a new AST node. Make the newly-created + * node the root for the current sibling list. If a root node already + * exists, make the newly-created node the root of the current root. + */ +void +#ifdef __USE_PROTOS +zzsubroot(AST **_root, AST **_sibling, AST **_tail) +#else +zzsubroot(_root, _sibling, _tail) +AST **_root, **_sibling, **_tail; +#endif +{ + AST *n; + zzNON_GUESS_MODE { + n = zzastnew(); +#ifdef DEMAND_LOOK + zzcr_ast(n, &(zzaCur), LA(0), LATEXT(0)); +#else + zzcr_ast(n, &(zzaCur), LA(1), LATEXT(1)); +#endif + zzastPush( n ); + if ( *_root != NULL ) + if ( (*_root)->down == *_sibling ) *_sibling = *_tail = *_root; + *_root = n; + (*_root)->down = *_sibling; + } +} + +/* Apply function to root then each sibling + * example: print tree in child-sibling LISP-format (AST has token field) + * + * void show(tree) + * AST *tree; + * { + * if ( tree == NULL ) return; + * printf(" %s", zztokens[tree->token]); + * } + * + * void before() { printf(" ("); } + * void after() { printf(" )"); } + * + * LISPdump() { zzpre_ast(tree, show, before, after); } + * + */ +void +#ifdef __USE_PROTOS +zzpre_ast( + AST *tree, + void (*func)(AST *), /* apply this to each tree node */ + void (*before)(AST *), /* apply this to root of subtree before preordering it */ + void (*after)(AST *)) /* apply this to root of subtree after preordering it */ +#else +zzpre_ast(tree, func, before, after) +AST *tree; +void (*func)(), /* apply this to each tree node */ + (*before)(), /* apply this to root of subtree before preordering it */ + (*after)(); /* apply this to root of subtree after preordering it */ +#endif +{ + while ( tree!= NULL ) + { + if ( tree->down != NULL ) (*before)(tree); + (*func)(tree); + zzpre_ast(tree->down, func, before, after); + if ( tree->down != NULL ) (*after)(tree); + tree = tree->right; + } +} + +/* free all AST nodes in tree; apply func to each before freeing */ + +#if 0 +////void +////#ifdef __USE_PROTOS +////zzfree_ast(AST *tree) +////#else +////zzfree_ast(tree) +////AST *tree; +////#endif +////{ +//// if ( tree == NULL ) return; +//// zzfree_ast( tree->down ); +//// zzfree_ast( tree->right ); +//// zztfree( tree ); +////} +#endif + +/* + MR19 Optimize freeing of the following structure to limit recursion + SAKAI Kiyotaka (ksakai@isr.co.jp) +*/ + +/* + NULL o + / \ + NULL o + / \ + NULL NULL +*/ + +/* + MR21 Another refinement to replace recursion with iteration + NAKAJIMA Mutsuki (muc@isr.co.jp). +*/ + +void +#ifdef __USE_PROTOS +zzfree_ast(AST *tree) +#else +zzfree_ast(tree) +AST *tree; +#endif +{ + + AST *otree; + + if (tree == NULL) return; + + while (tree->down == NULL || tree->right == NULL) { + + if (tree->down == NULL && tree->right == NULL) { + zztfree(tree); + return; + } + + otree = tree; + if (tree->down == NULL) { + tree = tree->right; + } else { + tree = tree->down; + } + zztfree( otree ); + } + + while (tree != NULL) { + zzfree_ast(tree->down); + otree = tree; + tree = otree->right; + zztfree(otree); + } +} + +/* build a tree (root child1 child2 ... NULL) + * If root is NULL, simply make the children siblings and return ptr + * to 1st sibling (child1). If root is not single node, return NULL. + * + * Siblings that are actually siblins lists themselves are handled + * correctly. For example #( NULL, #( NULL, A, B, C), D) results + * in the tree ( NULL A B C D ). + * + * Requires at least two parameters with the last one being NULL. If + * both are NULL, return NULL. + */ +#ifdef PCCTS_USE_STDARG +AST *zztmake(AST *rt, ...) +#else +AST *zztmake(va_alist) +va_dcl +#endif +{ + va_list ap; + register AST *child, *sibling=NULL, *tail=NULL /* MR20 */, *w; + AST *root; + +#ifdef PCCTS_USE_STDARG + va_start(ap, rt); + root = rt; +#else + va_start(ap); + root = va_arg(ap, AST *); +#endif + + if ( root != NULL ) + if ( root->down != NULL ) return NULL; + child = va_arg(ap, AST *); + while ( child != NULL ) + { + for (w=child; w->right!=NULL; w=w->right) {;} /* find end of child */ + if ( sibling == NULL ) {sibling = child; tail = w;} + else {tail->right = child; tail = w;} + child = va_arg(ap, AST *); + } + if ( root==NULL ) root = sibling; + else root->down = sibling; + va_end(ap); + return root; +} + +/* tree duplicate */ +AST * +#ifdef __USE_PROTOS +zzdup_ast(AST *t) +#else +zzdup_ast(t) +AST *t; +#endif +{ + AST *u; + + if ( t == NULL ) return NULL; + u = zzastnew(); + *u = *t; +#ifdef zzAST_DOUBLE + u->up = NULL; /* set by calling invocation */ + u->left = NULL; +#endif + u->right = zzdup_ast(t->right); + u->down = zzdup_ast(t->down); +#ifdef zzAST_DOUBLE + if ( u->right!=NULL ) u->right->left = u; + if ( u->down!=NULL ) u->down->up = u; +#endif + return u; +} + +void +#ifdef __USE_PROTOS +zztfree(AST *t) +#else +zztfree(t) +AST *t; +#endif +{ +#ifdef zzd_ast + zzd_ast( t ); +#endif + free( t ); +} + +#ifdef zzAST_DOUBLE +/* + * Set the 'up', and 'left' pointers of all nodes in 't'. + * Initial call is double_link(your_tree, NULL, NULL). + */ +void +#ifdef __USE_PROTOS +zzdouble_link(AST *t, AST *left, AST *up) +#else +zzdouble_link(t, left, up) +AST *t, *left, *up; +#endif +{ + if ( t==NULL ) return; + t->left = left; + t->up = up; + zzdouble_link(t->down, NULL, t); + zzdouble_link(t->right, t, up); +} +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ast.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ast.h new file mode 100644 index 00000000..911f913d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/ast.h @@ -0,0 +1,121 @@ +/* Abstract syntax tree + * + * Macros, definitions + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ZZAST_H +#define ZZAST_H + +#define zzastOvfChk \ + if ( zzast_sp <= 0 ) \ + { \ + fprintf(stderr, zzStackOvfMsg, __FILE__, __LINE__); \ + exit(PCCTS_EXIT_FAILURE); \ + } + +#ifndef USER_DEFINED_AST +#ifndef AST_FIELDS +#define AST_FIELDS +#endif + +typedef struct _ast { + struct _ast *right, *down; +#ifdef zzAST_DOUBLE + struct _ast *left, *up; +#endif + AST_FIELDS +} AST; + +#else + +#ifdef zzAST_DOUBLE +#define AST_REQUIRED_FIELDS struct _ast *right, *down, *left, *up; +#else +#define AST_REQUIRED_FIELDS struct _ast *right, *down; +#endif + +#endif + + +/* N o d e a c c e s s m a c r o s */ +#define zzchild(t) (((t)==NULL)? (AST *) NULL:(t->down)) /* MR19 */ +#define zzsibling(t) (((t)==NULL)? (AST *) NULL:(t->right)) /* MR19 */ + + +/* define global variables needed by #i stack */ +#define zzASTgvars \ + AST *zzastStack[ZZAST_STACKSIZE]; \ + int zzast_sp = ZZAST_STACKSIZE; + +#define zzASTVars AST *_ast = NULL, *_sibling = NULL, *_tail = NULL +#define zzSTR ( (_tail==NULL)?(&_sibling):(&(_tail->right)) ) +#define zzastCur (zzastStack[zzast_sp]) +#define zzastArg(i) (zzastStack[zztsp-i]) +#define zzastPush(p) zzastOvfChk; zzastStack[--zzast_sp] = p; +#define zzastDPush --zzast_sp +#define zzastMARK zztsp=zzast_sp; /* Save state of stack */ +#define zzastREL zzast_sp=zztsp; /* Return state of stack */ +#define zzrm_ast {zzfree_ast(*_root); _tail = _sibling = (*_root)=NULL;} + +extern int zzast_sp; +extern AST *zzastStack[]; + +/* MR26 */ + +#ifdef PCCTS_USE_STDARG +AST *zztmake(AST *, ...); +#else +AST *zztmake(); +#endif + +#ifdef __USE_PROTOS +void zzlink(AST **, AST **, AST **); +void zzsubchild(AST **, AST **, AST **); +void zzsubroot(AST **, AST **, AST **); +void zzpre_ast(AST *, void (*)(AST *), void (*)(AST *), void (*)(AST *)); +void zzfree_ast(AST *); +AST *zzdup_ast(AST *); +void zztfree(AST *); +void zzdouble_link(AST *, AST *, AST *); +AST *zzastnew(void); + +#else + +void zzlink(); +AST *zzastnew(); +void zzsubchild(); +void zzsubroot(); +void zzpre_ast(); +void zzfree_ast(); +AST *zzdup_ast(); +void zztfree(); +void zzdouble_link(); +#endif + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/charbuf.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/charbuf.h new file mode 100644 index 00000000..e10ba67d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/charbuf.h @@ -0,0 +1,46 @@ +/* ANTLR attribute definition -- constant width text + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ZZCHARBUF_H +#define ZZCHARBUF_H + +#include "pcctscfg.h" + +#include "pccts_string.h" + +#ifndef D_TextSize +#define D_TextSize 30 +#endif + +typedef struct { char text[D_TextSize]; } Attrib; + +#define zzcr_attr(a,tok,t) strncpy((a)->text, t, D_TextSize-1); \ + (a)->text[D_TextSize-1] = '\0'; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/charptr.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/charptr.c new file mode 100644 index 00000000..15a51766 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/charptr.c @@ -0,0 +1,58 @@ +/* + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#include "pcctscfg.h" + +#ifdef __STDC__ +#include "pccts_stdlib.h" +#else +#include +#endif +#include "pccts_string.h" + +/* 133MR1 include stdio.h for fprintf in charptr.c */ + +#include "pccts_stdio.h" + +/* 133MR1 include charptr.h for Attrib in charptr.c */ + +#include "charptr.h" + +#ifdef __USE_PROTOS +zzcr_attr(Attrib *a,int token,char *text) +#else +zzcr_attr(a,token,text) +Attrib *a; +int token; +char *text; +#endif +{ + *a = (char *) malloc(strlen(text)+1); /* MR6 */ + if ( *a == NULL ) {fprintf(stderr, "zzcr_attr: out of memory!\n"); exit(-1);} + strcpy(*a, text); +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/charptr.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/charptr.h new file mode 100644 index 00000000..2cc36d8d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/charptr.h @@ -0,0 +1,48 @@ +/* + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +/* + * WARNING!!!!: charptr.h does NOT make copies and the + * memory is freed after the attribute scope exits. + */ + +#ifndef ZZCHARPTR_H +#define ZZCHARPTR_H + +typedef char *Attrib; +#define zzdef0(a) {*(a)=NULL;} +/* MR8 Jens Tingleff (jensting@imaginet.fr) */ +/* Set memory pointer to null after free() */ +#define zzd_attr(a) {if ( *(a)!=NULL ) {free(*(a)); *(a)=NULL; }; } + +#ifdef __STDC__ +extern zzcr_attr(Attrib *,int,char *); +#endif + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/config.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/config.h new file mode 100644 index 00000000..1cc4fbcd --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/config.h @@ -0,0 +1 @@ +#include "pcctscfg.h" diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/dlgauto.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/dlgauto.h new file mode 100644 index 00000000..2bf640bf --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/dlgauto.h @@ -0,0 +1,504 @@ +/* dlgauto.h automaton + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Will Cohen and Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ZZDEFAUTO_H +#define ZZDEFAUTO_H + +/* 10-Apr-97 133MR1 Uses __USE_PROTOS show should #include pcctscfg.h */ + +#include "pcctscfg.h" + +zzchar_t *zzlextext; /* text of most recently matched token */ +zzchar_t *zzbegexpr; /* beginning of last reg expr recogn. */ +zzchar_t *zzendexpr; /* beginning of last reg expr recogn. */ +int zzbufsize = 0; /* number of characters in zzlextext */ /* MR7 */ +int zzbegcol = 0; /* column that first character of token is in*/ +int zzendcol = 0; /* column that last character of token is in */ +int zzline = 1; /* line current token is on */ +int zzreal_line=1; /* line of 1st portion of token that is not skipped */ +int zzchar; /* character to determine next state */ +int zzbufovf; /* indicates that buffer too small for text */ +int zzcharfull = 0; +static zzchar_t *zznextpos;/* points to next available position in zzlextext*/ +static int zzclass; + +#ifdef __USE_PROTOS +void zzerrstd(const char *); +void (*zzerr)(const char *)=zzerrstd;/* pointer to error reporting function */ +extern int zzerr_in(void); +static int (*zzfunc_in)(void) = zzerr_in; /* MR20 */ +#else +void zzerrstd(); +void (*zzerr)()=zzerrstd; /* pointer to error reporting function */ +extern int zzerr_in(); +static int (*zzfunc_in)() = zzerr_in; /* MR20 */ +#endif + +static FILE *zzstream_in=0; +static zzchar_t *zzstr_in=0; + +#ifdef USER_ZZMODE_STACK +int zzauto = 0; +#else +static int zzauto = 0; +#endif +static int zzadd_erase; +static char zzebuf[70]; + +#ifdef ZZCOL +#define ZZINC (++zzendcol) +#else +#define ZZINC +#endif + + +#define ZZGETC_STREAM {zzchar = getc(zzstream_in); zzclass = ZZSHIFT(zzchar);} +#define ZZGETC_FUNC {zzchar = (*zzfunc_in)(); zzclass = ZZSHIFT(zzchar);} +#define ZZGETC_STR { \ + if (*zzstr_in){ \ + zzchar = *zzstr_in; \ + ++zzstr_in; \ + }else{ \ + zzchar = EOF; \ + } \ + zzclass = ZZSHIFT(zzchar); \ +} + +#define ZZNEWSTATE (newstate = dfa[state][zzclass]) + +#ifndef ZZCOPY +#define ZZCOPY \ + /* Truncate matching buffer to size (not an error) */ \ + if (zznextpos < lastpos){ \ + *(zznextpos++) = zzchar; \ + }else{ \ + zzbufovf = 1; \ + } +#endif + +void +#ifdef __USE_PROTOS +zzrdstream( FILE *f ) +#else +zzrdstream( f ) +FILE *f; +#endif +{ + /* make sure that it is really set to something, otherwise just + leave it be. + */ + if (f){ + /* make sure that there is always someplace to get input + before closing zzstream_in + */ +#if 0 + if (zzstream_in && zzstream_in!=stdin) fclose( zzstream_in ); +#endif + zzline = 1; + zzstream_in = f; + zzfunc_in = NULL; + zzstr_in = 0; + zzcharfull = 0; + } +} + +void +#ifdef __USE_PROTOS +zzrdfunc( int (*f)(void) ) +#else +zzrdfunc( f ) +int (*f)(); +#endif +{ + /* make sure that it is really set to something, otherwise just + leave it be. + */ + if (f){ + /* make sure that there is always someplace to get input + before closing zzstream_in + */ +#if 0 + if (zzstream_in && zzstream_in!=stdin) fclose( zzstream_in ); +#endif + zzline = 1; + zzstream_in = NULL; + zzfunc_in = f; + zzstr_in = 0; + zzcharfull = 0; + } +} + + +void +#ifdef __USE_PROTOS +zzrdstr( zzchar_t *s ) +#else +zzrdstr( s ) +zzchar_t *s; +#endif +{ + /* make sure that it is really set to something, otherwise just + leave it be. + */ + if (s){ + /* make sure that there is always someplace to get input + before closing zzstream_in + */ +#if 0 + if (zzstream_in && zzstream_in!=stdin) fclose( zzstream_in ); +#endif + zzline = 1; + zzstream_in = NULL; + zzfunc_in = 0; + zzstr_in = s; + zzcharfull = 0; + } +} + + +#ifdef __USE_PROTOS +void zzclose_stream(void) +#else +void zzclose_stream() +#endif +{ +#if 0 + fclose( zzstream_in ); + zzstream_in = NULL; + zzfunc_in = NULL; +#endif +} + +/* saves dlg state, but not what feeds dlg (such as file position) */ +void +#ifdef __USE_PROTOS +zzsave_dlg_state(struct zzdlg_state *state) +#else +zzsave_dlg_state(state) +struct zzdlg_state *state; +#endif +{ + state->stream = zzstream_in; + state->func_ptr = zzfunc_in; + state->str = zzstr_in; + state->auto_num = zzauto; + state->add_erase = zzadd_erase; + state->lookc = zzchar; + state->char_full = zzcharfull; + state->begcol = zzbegcol; + state->endcol = zzendcol; + state->line = zzline; + state->lextext = zzlextext; + state->begexpr = zzbegexpr; + state->endexpr = zzendexpr; + state->bufsize = zzbufsize; + state->bufovf = zzbufovf; + state->nextpos = zznextpos; + state->class_num = zzclass; +} + +void +#ifdef __USE_PROTOS +zzrestore_dlg_state(struct zzdlg_state *state) +#else +zzrestore_dlg_state(state) +struct zzdlg_state *state; +#endif +{ + zzstream_in = state->stream; + zzfunc_in = state->func_ptr; + zzstr_in = state->str; + zzauto = state->auto_num; + zzadd_erase = state->add_erase; + zzchar = state->lookc; + zzcharfull = state->char_full; + zzbegcol = state->begcol; + zzendcol = state->endcol; + zzline = state->line; + zzlextext = state->lextext; + zzbegexpr = state->begexpr; + zzendexpr = state->endexpr; + zzbufsize = state->bufsize; + zzbufovf = state->bufovf; + zznextpos = state->nextpos; + zzclass = state->class_num; +} + +void +#ifdef __USE_PROTOS +zzmode( int m ) +#else +zzmode( m ) +int m; +#endif +{ + /* points to base of dfa table */ + if (m +#include + +/* */ +/* 7-Apr-97 133MR1 */ +/* Proper choice of STDC and cplusplus pre-processor symbols (?) */ +/* */ +#include "pccts_string.h" + +#ifdef PCCTS_USE_STDARG +#include "pccts_stdarg.h" +#else +#include +#endif + +#ifdef DUM +/* Define usable bits per unsigned int word (used for set stuff) */ +#ifdef PC +#define BSETWORDSIZE 16 +#define BSETLOGWORDSIZE 4 +#else +#define BSETWORDSIZE 32 +#define BSETLOGWORDSIZE 5 +#endif +#endif + +#define BSETWORDSIZE 8 +#define BSETLOGWORDSIZE 3 /* SetWordType is 8bits */ + +#define BSETMODWORD(x) ((x) & (BSETWORDSIZE-1)) /* x % BSETWORDSIZE */ +#define BSETDIVWORD(x) ((x) >> BSETLOGWORDSIZE) /* x / BSETWORDSIZE */ + +/* This is not put into the global pccts_parser structure because it is + * hidden and does not need to be saved during a "save state" operation + */ +/* maximum of 32 bits/unsigned int and must be 8 bits/byte */ +static SetWordType bitmask[] = { + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080 +}; + +#ifdef zzTRACE_RULES +int zzTraceOptionValueDefault=1; +int zzTraceOptionValue=1; +int zzTraceGuessOptionValue=1; +char *zzTraceCurrentRuleName=NULL; +int zzTraceDepth=0; +#endif + +int zzGuessSeq=0; /* MR10 */ +int zzSyntaxErrCount=0; /* MR11 */ +int zzLexErrCount=0; /* MR11 */ + +void +#ifdef __USE_PROTOS +zzresynch(SetWordType *wd,SetWordType mask) +#else +zzresynch(wd,mask) +SetWordType *wd, mask; +#endif +{ + static int consumed = 1; + + /* if you enter here without having consumed a token from last resynch + * force a token consumption. + */ + if ( !consumed ) {zzCONSUME; consumed=1; return;} /* MR10 */ + + /* if current token is in resynch set, we've got what we wanted */ + if ( wd[LA(1)]&mask || LA(1) == zzEOF_TOKEN ) {consumed=0; return;} + + /* scan until we find something in the resynch set */ + while ( !(wd[LA(1)]&mask) && LA(1) != zzEOF_TOKEN ) {zzCONSUME;} + consumed=1; +} + +/* */ +/* 7-Apr-97 133MR1 for C++ and MR7 for C */ +/* Change suggested by Eli Sternheim (eli@interhdl.com) */ +/* */ + +void +#ifdef __USE_PROTOS +zzconsumeUntil(SetWordType *st) +#else +zzconsumeUntil(st) +SetWordType *st; +#endif +{ + int tmp; /* MR7 */ + while ( !zzset_el( (tmp=LA(1)), st) && tmp!=1 /* Eof */) { /* MR7 */ + zzCONSUME; } /* MR7 */ +} + +/* */ +/* 7-Apr-97 133MR1 for C++ and MR7 for C */ +/* Change suggested by Eli Sternheim (eli@interhdl.com) */ +/* */ + +void +#ifdef __USE_PROTOS +zzconsumeUntilToken(int t) +#else +zzconsumeUntilToken(t) +int t; +#endif +{ + int tmp; /* MR7 */ + while ( (tmp=LA(1)) !=t && tmp!=1 /* Eof */) { zzCONSUME; } /* MR7 */ +} + +/* input looks like: + * zzFAIL(k, e1, e2, ...,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText) + * where the zzMiss stuff is set here to the token that did not match + * (and which set wasn't it a member of). + */ + +#ifdef PCCTS_USE_STDARG +void zzFAIL(int k, ...) +#else +void zzFAIL(va_alist) +va_dcl +#endif +{ +#ifdef LL_K + static char text[LL_K*ZZLEXBUFSIZE+1]; + SetWordType *f[LL_K]; +#else + static char text[ZZLEXBUFSIZE+1]; + SetWordType *f[1]; +#endif + SetWordType **miss_set; + char **miss_text; + int *bad_tok; + char **bad_text; + int *err_k; + int i; + va_list ap; +#ifndef PCCTS_USE_STDARG /* MR20 */ + int k; +#endif +#ifdef PCCTS_USE_STDARG /* MR20 */ + va_start(ap, k); +#else + va_start(ap); + k = va_arg(ap, int); /* how many lookahead sets? */ +#endif + assert(k <= sizeof(f)/sizeof(f[0])); /* MR20 G. Hobbelt */ + text[0] = '\0'; +#ifdef VBOX + memset(f, 0, sizeof(f)); +#endif + for (i=1; i<=k; i++) /* collect all lookahead sets */ + { + f[i-1] = va_arg(ap, SetWordType *); + } + for (i=1; i<=k; i++) /* look for offending token */ + { + if ( i>1 ) strcat(text, " "); + strcat(text, LATEXT(i)); + if ( !zzset_el((unsigned)LA(i), f[i-1]) ) break; + } + miss_set = va_arg(ap, SetWordType **); + miss_text = va_arg(ap, char **); + bad_tok = va_arg(ap, int *); + bad_text = va_arg(ap, char **); + err_k = va_arg(ap, int *); + if ( i>k ) + { + /* bad; lookahead is permutation that cannot be matched, + * but, the ith token of lookahead is valid at the ith position + * (The old LL sub 1 (k) versus LL(k) parsing technique) + */ + *miss_set = NULL; + *miss_text = zzlextext; + *bad_tok = LA(1); + *bad_text = LATEXT(1); + *err_k = k; + return; + } +/* fprintf(stderr, "%s not in %dth set\n", zztokens[LA(i)], i);*/ + *miss_set = f[i-1]; + *miss_text = text; + *bad_tok = LA(i); + *bad_text = LATEXT(i); + if ( i==1 ) *err_k = 1; + else *err_k = k; +} + +#ifdef __USE_PROTOS +void zzTraceGuessDone(zzantlr_state *state) +#else +void zzTraceGuessDone(state) + zzantlr_state *state; +#endif +{ +#ifdef zzTRACE_RULES +#ifdef ZZCAN_GUESS + + int doIt=0; + + if (zzTraceCurrentRuleName == NULL) return; + + if (zzTraceOptionValue <= 0) { + doIt=0; + } else if (zzTraceGuessOptionValue <= 0) { + doIt=0; + } else { + doIt=1; + }; + + if (doIt) { + fprintf(stderr,"guess done - returning to rule %s {\"%s\"} at depth %d", + state->traceCurrentRuleName, + LATEXT(1), + state->traceDepth); + if (state->guessing != 0) { + fprintf(stderr," (guess mode continues - an enclosing guess is still active)"); + } else { + fprintf(stderr," (guess mode ends)"); + }; + fprintf(stderr,"\n"); + }; +#endif +#endif +} + +void +#ifdef __USE_PROTOS +zzsave_antlr_state(zzantlr_state *buf) +#else +zzsave_antlr_state(buf) +zzantlr_state *buf; +#endif +{ +#ifdef LL_K + int i; +#endif + +#ifdef ZZCAN_GUESS + buf->guess_start = zzguess_start; + buf->guessing = zzguessing; +#endif + buf->asp = zzasp; +#ifdef GENAST + buf->ast_sp = zzast_sp; +#endif +#ifdef ZZINF_LOOK + buf->inf_labase = zzinf_labase; + buf->inf_last = zzinf_last; + +/* MR6 Gunnar Rxnning (gunnar@candleweb.no) */ +/* MR6 Additional state needs to be saved/restored */ + + buf->inf_tokens = zzinf_tokens; /* MR6 */ + buf->inf_text = zzinf_text; /* MR6 */ + buf->inf_text_buffer = zzinf_text_buffer; /* MR6 */ + buf->inf_line = zzinf_line; /* MR6 */ + +#endif +#ifdef DEMAND_LOOK + buf->dirty = zzdirty; +#endif +#ifdef LL_K + for (i=0; itokenLA[i] = zztokenLA[i]; + for (i=0; itextLA[i], zztextLA[i]); + buf->lap = zzlap; + buf->labase = zzlabase; +#else + buf->token = zztoken; + strcpy(buf->text, zzlextext); +#endif +#ifdef zzTRACE_RULES + + /* MR10 */ + + buf->traceOptionValue=zzTraceOptionValue; + buf->traceGuessOptionValue=zzTraceGuessOptionValue; + buf->traceCurrentRuleName=zzTraceCurrentRuleName; + buf->traceDepth=zzTraceDepth; +#endif +} + +void +#ifdef __USE_PROTOS +zzrestore_antlr_state(zzantlr_state *buf) +#else +zzrestore_antlr_state(buf) +zzantlr_state *buf; +#endif +{ + +#ifdef zzTRACE_RULES + int prevTraceOptionValue; +#endif + +#ifdef LL_K + int i; +#endif + +#ifdef ZZCAN_GUESS + zzguess_start = buf->guess_start; + zzguessing = buf->guessing; +#endif + zzasp = buf->asp; +#ifdef GENAST + zzast_sp = buf->ast_sp; +#endif +#ifdef ZZINF_LOOK + zzinf_labase = buf->inf_labase; + zzinf_last = buf->inf_last; + +/* MR6 Gunnar Rxnning (gunnar@candleweb.no) */ +/* MR6 Additional state needs to be saved/restored */ + + zzinf_tokens = buf->inf_tokens; /* MR6 */ + zzinf_text = buf->inf_text; /* MR6 */ + zzinf_text_buffer = buf->inf_text_buffer; /* MR6 */ + zzinf_line = buf->inf_line; /* MR6 */ +#endif +#ifdef DEMAND_LOOK + zzdirty = buf->dirty; +#endif +#ifdef LL_K + for (i=0; itokenLA[i]; + for (i=0; itextLA[i]); + zzlap = buf->lap; + zzlabase = buf->labase; +#else + zztoken = buf->token; + strcpy(zzlextext, buf->text); +#endif +#ifdef zzTRACE_RULES + + prevTraceOptionValue=zzTraceOptionValue; + zzTraceOptionValue=buf->traceOptionValue; + if ( (prevTraceOptionValue > 0) != + (zzTraceOptionValue > 0)) { + if (zzTraceOptionValue > 0) { + fprintf(stderr,"trace enable restored in rule %s depth %d\n", + zzTraceCurrentRuleName,zzTraceDepth); + }; + if (zzTraceOptionValue <= 0) { + fprintf(stderr,"trace disable restored in rule %s depth %d\n", + zzTraceCurrentRuleName,zzTraceDepth); + }; + }; + + zzTraceOptionValue=buf->traceOptionValue; /* MR10 */ + zzTraceGuessOptionValue=buf->traceGuessOptionValue; /* MR10 */ + zzTraceCurrentRuleName=buf->traceCurrentRuleName; /* MR10 */ + zzTraceDepth=buf->traceDepth; /* MR10 */ + zzTraceGuessDone(buf); /* MR10 */ +#endif +} + +void +#ifdef __USE_PROTOS +zzedecode(SetWordType *a) +#else +zzedecode(a) +SetWordType *a; +#endif +{ + register SetWordType *p = a; + register SetWordType *endp = &(p[zzSET_SIZE]); + register unsigned e = 0; + + if ( zzset_deg(a)>1 ) fprintf(stderr, " {"); + do { + register SetWordType t = *p; + register SetWordType *b = &(bitmask[0]); + do { + if ( t & *b ) fprintf(stderr, " %s", zztokens[e]); + e++; + } while (++b < &(bitmask[sizeof(SetWordType)*8])); + } while (++p < endp); + if ( zzset_deg(a)>1 ) fprintf(stderr, " }"); +} + +#ifndef USER_ZZSYN +/* standard error reporting function */ +void +#ifdef __USE_PROTOS +zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, int k, char *bad_text) +#else +zzsyn(text, tok, egroup, eset, etok, k, bad_text) +char *text, *egroup, *bad_text; +int tok; +int etok; +int k; +SetWordType *eset; +#endif +{ + + zzSyntaxErrCount++; /* MR11 */ + fprintf(stderr, "line %d: syntax error at \"%s\"", zzline, (tok==zzEOF_TOKEN)?"EOF":bad_text); + if ( !etok && !eset ) {fprintf(stderr, "\n"); return;} + if ( k==1 ) fprintf(stderr, " missing"); + else + { + fprintf(stderr, "; \"%s\" not", bad_text); + if ( zzset_deg(eset)>1 ) fprintf(stderr, " in"); + } + if ( zzset_deg(eset)>0 ) zzedecode(eset); + else fprintf(stderr, " %s", zztokens[etok]); + if ( strlen(egroup) > 0 ) fprintf(stderr, " in %s", egroup); + fprintf(stderr, "\n"); +} +#endif + +/* is b an element of set p? */ +int +#ifdef __USE_PROTOS +zzset_el(unsigned b, SetWordType *p) +#else +zzset_el(b,p) +unsigned b; +SetWordType *p; +#endif +{ + return( p[BSETDIVWORD(b)] & bitmask[BSETMODWORD(b)] ); +} + +int +#ifdef __USE_PROTOS +zzset_deg(SetWordType *a) +#else +zzset_deg(a) +SetWordType *a; +#endif +{ + /* Fast compute degree of a set... the number + of elements present in the set. Assumes + that all word bits are used in the set + */ + register SetWordType *p = a; + register SetWordType *endp = &(a[zzSET_SIZE]); + register int degree = 0; + + if ( a == NULL ) return 0; + while ( p < endp ) + { + register SetWordType t = *p; + register SetWordType *b = &(bitmask[0]); + do { + if (t & *b) ++degree; + } while (++b < &(bitmask[sizeof(SetWordType)*8])); + p++; + } + + return(degree); +} + +#ifdef DEMAND_LOOK + +#ifdef LL_K +int +#ifdef __USE_PROTOS +_zzmatch(int _t, char **zzBadText, char **zzMissText, + int *zzMissTok, int *zzBadTok, + SetWordType **zzMissSet) +#else +_zzmatch(_t, zzBadText, zzMissText, zzMissTok, zzBadTok, zzMissSet) +int _t; +char **zzBadText; +char **zzMissText; +int *zzMissTok, *zzBadTok; +SetWordType **zzMissSet; +#endif +{ + if ( zzdirty==LL_K ) { + zzCONSUME; + } + if ( LA(1)!=_t ) { + *zzBadText = *zzMissText=LATEXT(1); + *zzMissTok= _t; *zzBadTok=LA(1); + *zzMissSet=NULL; + return 0; + } + zzMakeAttr + zzdirty++; + zzlabase++; + return 1; +} + +int +#ifdef __USE_PROTOS +_zzmatch_wsig(int _t) +#else +_zzmatch_wsig(_t) +int _t; +#endif +{ + if ( zzdirty==LL_K ) { + zzCONSUME; + } + if ( LA(1)!=_t ) { + return 0; + } + zzMakeAttr + zzdirty++; + zzlabase++; + return 1; +} + +#else + +int +#ifdef __USE_PROTOS +_zzmatch(int _t, char **zzBadText, char **zzMissText, + int *zzMissTok, int *zzBadTok, SetWordType **zzMissSet) +#else +_zzmatch(_t, zzBadText, zzMissText, zzMissTok, zzBadTok, zzMissSet) +int _t; +char **zzBadText; +char **zzMissText; +int *zzMissTok, *zzBadTok; +SetWordType **zzMissSet; +#endif +{ + if ( zzdirty ) {zzCONSUME;} + if ( LA(1)!=_t ) { + *zzBadText = *zzMissText=LATEXT(1); + *zzMissTok= _t; *zzBadTok=LA(1); + *zzMissSet=NULL; + return 0; + } + zzdirty = 1; + zzMakeAttr + return 1; +} + +int +#ifdef __USE_PROTOS +_zzmatch_wsig(int _t) +#else +_zzmatch_wsig(_t) +int _t; +#endif +{ + if ( zzdirty ) {zzCONSUME;} + if ( LA(1)!=_t ) { + return 0; + } + zzdirty = 1; + zzMakeAttr + return 1; +} + +#endif /*LL_K*/ + +#else + +int +#ifdef __USE_PROTOS +_zzmatch(int _t, char **zzBadText, char **zzMissText, + int *zzMissTok, int *zzBadTok, + SetWordType **zzMissSet) +#else +_zzmatch(_t, zzBadText, zzMissText, zzMissTok, zzBadTok, zzMissSet) +int _t; +char **zzBadText; +char **zzMissText; +int *zzMissTok, *zzBadTok; +SetWordType **zzMissSet; +#endif +{ + if ( LA(1)!=_t ) { + *zzBadText = *zzMissText=LATEXT(1); + *zzMissTok= _t; *zzBadTok=LA(1); + *zzMissSet=NULL; + return 0; + } + zzMakeAttr + return 1; +} + +int +#ifdef __USE_PROTOS +_zzmatch_wsig(int _t) +#else +_zzmatch_wsig(_t) +int _t; +#endif +{ + if ( LA(1)!=_t ) return 0; + zzMakeAttr + return 1; +} + +#endif /*DEMAND_LOOK*/ + +#ifdef ZZINF_LOOK +void +#ifdef __USE_PROTOS +_inf_zzgettok(void) +#else +_inf_zzgettok() +#endif +{ + if ( zzinf_labase >= zzinf_last ) + {NLA = zzEOF_TOKEN; strcpy(NLATEXT, "");} + else { + NLA = zzinf_tokens[zzinf_labase]; + zzline = zzinf_line[zzinf_labase]; /* wrong in 1.21 */ + strcpy(NLATEXT, zzinf_text[zzinf_labase]); + zzinf_labase++; + } +} +#endif + +#ifdef ZZINF_LOOK +/* allocate default size text,token and line arrays; + * then, read all of the input reallocing the arrays as needed. + * Once the number of total tokens is known, the LATEXT(i) array (zzinf_text) + * is allocated and its pointers are set to the tokens in zzinf_text_buffer. + */ +void +#ifdef __USE_PROTOS +zzfill_inf_look(void) +#else +zzfill_inf_look() +#endif +{ + int tok, line; + int zzinf_token_buffer_size = ZZINF_DEF_TOKEN_BUFFER_SIZE; + int zzinf_text_buffer_size = ZZINF_DEF_TEXT_BUFFER_SIZE; + int zzinf_text_buffer_index = 0; + int zzinf_lap = 0; + + /* allocate text/token buffers */ + zzinf_text_buffer = (char *) malloc(zzinf_text_buffer_size); + if ( zzinf_text_buffer == NULL ) + { + fprintf(stderr, "cannot allocate lookahead text buffer (%d bytes)\n", + zzinf_text_buffer_size); + exit(PCCTS_EXIT_FAILURE); + } + zzinf_tokens = (int *) calloc(zzinf_token_buffer_size,sizeof(int)); + if ( zzinf_tokens == NULL ) + { + fprintf(stderr, "cannot allocate token buffer (%d tokens)\n", + zzinf_token_buffer_size); + exit(PCCTS_EXIT_FAILURE); + } + zzinf_line = (int *) calloc(zzinf_token_buffer_size,sizeof(int)); + if ( zzinf_line == NULL ) + { + fprintf(stderr, "cannot allocate line buffer (%d ints)\n", + zzinf_token_buffer_size); + exit(PCCTS_EXIT_FAILURE); + } + + /* get tokens, copying text to text buffer */ + zzinf_text_buffer_index = 0; + do { + zzgettok(); + line = zzreal_line; + while ( zzinf_lap>=zzinf_token_buffer_size ) + { + zzinf_token_buffer_size += ZZINF_BUFFER_TOKEN_CHUNK_SIZE; + zzinf_tokens = (int *) realloc(zzinf_tokens, + zzinf_token_buffer_size*sizeof(int)); + if ( zzinf_tokens == NULL ) + { + fprintf(stderr, "cannot allocate lookahead token buffer (%d tokens)\n", + zzinf_token_buffer_size); + exit(PCCTS_EXIT_FAILURE); + } + zzinf_line = (int *) realloc(zzinf_line, + zzinf_token_buffer_size*sizeof(int)); + if ( zzinf_line == NULL ) + { + fprintf(stderr, "cannot allocate lookahead line buffer (%d ints)\n", + zzinf_token_buffer_size); + exit(PCCTS_EXIT_FAILURE); + } + + } + while ( (zzinf_text_buffer_index+strlen(NLATEXT)+1) >= zzinf_text_buffer_size ) + { + zzinf_text_buffer_size += ZZINF_BUFFER_TEXT_CHUNK_SIZE; + zzinf_text_buffer = (char *) realloc(zzinf_text_buffer, + zzinf_text_buffer_size); + if ( zzinf_text_buffer == NULL ) + { + fprintf(stderr, "cannot allocate lookahead text buffer (%d bytes)\n", + zzinf_text_buffer_size); + exit(PCCTS_EXIT_FAILURE); + } + } + /* record token and text and line of input symbol */ + tok = zzinf_tokens[zzinf_lap] = NLA; + strcpy(&zzinf_text_buffer[zzinf_text_buffer_index], NLATEXT); + zzinf_text_buffer_index += strlen(NLATEXT)+1; + zzinf_line[zzinf_lap] = line; + zzinf_lap++; + } while (tok!=zzEOF_TOKEN); + zzinf_labase = 0; + zzinf_last = zzinf_lap-1; + + /* allocate ptrs to text of ith token */ + zzinf_text = (char **) calloc(zzinf_last+1,sizeof(char *)); + if ( zzinf_text == NULL ) + { + fprintf(stderr, "cannot allocate lookahead text buffer (%d)\n", + zzinf_text_buffer_size); + exit(PCCTS_EXIT_FAILURE); + } + zzinf_text_buffer_index = 0; + zzinf_lap = 0; + /* set ptrs so that zzinf_text[i] is the text of the ith token found on input */ + while (zzinf_lap<=zzinf_last) + { + zzinf_text[zzinf_lap++] = &zzinf_text_buffer[zzinf_text_buffer_index]; + zzinf_text_buffer_index += strlen(&zzinf_text_buffer[zzinf_text_buffer_index])+1; + } +} +#endif + +int +#ifdef __USE_PROTOS +_zzsetmatch(SetWordType *e, char **zzBadText, char **zzMissText, + int *zzMissTok, int *zzBadTok, + SetWordType **zzMissSet, + SetWordType *zzTokclassErrset /* MR23 */) +#else +_zzsetmatch(e, zzBadText, zzMissText, zzMissTok, zzBadTok, zzMissSet, zzTokclassErrset /* MR23 */) +SetWordType *e; +char **zzBadText; +char **zzMissText; +int *zzMissTok, *zzBadTok; +SetWordType **zzMissSet; +SetWordType *zzTokclassErrset; +#endif +{ +#ifdef DEMAND_LOOK +#ifdef LL_K + if ( zzdirty==LL_K ) {zzCONSUME;} +#else + if ( zzdirty ) {zzCONSUME;} +#endif +#endif + if ( !zzset_el((unsigned)LA(1), e) ) { + *zzBadText = LATEXT(1); *zzMissText=NULL; + *zzMissTok= 0; *zzBadTok=LA(1); + *zzMissSet=zzTokclassErrset; /* MR23 */ + return 0; + } + zzMakeAttr /* MR14 Ger Hobbelt (hobbelt@axa.nl) */ +#ifdef DEMAND_LOOK +#ifdef LL_K + zzdirty++; + zzlabase++; /* MR14 Ger Hobbelt (hobbelt@axa.nl) */ +#else + zzdirty = 1; +#endif +#endif + return 1; +} + +int +#ifdef __USE_PROTOS +_zzmatch_wdfltsig(int tokenWanted, SetWordType *whatFollows) +#else +_zzmatch_wdfltsig(tokenWanted, whatFollows) +int tokenWanted; +SetWordType *whatFollows; +#endif +{ +#ifdef DEMAND_LOOK +#ifdef LL_K + if ( zzdirty==LL_K ) { + zzCONSUME; + } +#else + if ( zzdirty ) {zzCONSUME;} +#endif +#endif + + if ( LA(1)!=tokenWanted ) + { + zzSyntaxErrCount++; /* MR11 */ + fprintf(stderr, + "line %d: syntax error at \"%s\" missing %s\n", + zzline, + (LA(1)==zzEOF_TOKEN)?"":(char *)LATEXT(1), + zztokens[tokenWanted]); + zzconsumeUntil( whatFollows ); + return 0; + } + else { + zzMakeAttr +#ifdef DEMAND_LOOK +#ifdef LL_K + zzdirty++; + zzlabase++; +#else + zzdirty = 1; +#endif +#else +/* zzCONSUME; consume if not demand lookahead */ +#endif + return 1; + } +} + +int +#ifdef __USE_PROTOS +_zzsetmatch_wdfltsig(SetWordType *tokensWanted, + int tokenTypeOfSet, + SetWordType *whatFollows) +#else +_zzsetmatch_wdfltsig(tokensWanted, tokenTypeOfSet, whatFollows) +SetWordType *tokensWanted; +int tokenTypeOfSet; +SetWordType *whatFollows; +#endif +{ +#ifdef DEMAND_LOOK +#ifdef LL_K + if ( zzdirty==LL_K ) {zzCONSUME;} +#else + if ( zzdirty ) {zzCONSUME;} +#endif +#endif + if ( !zzset_el((unsigned)LA(1), tokensWanted) ) + { + zzSyntaxErrCount++; /* MR11 */ + fprintf(stderr, + "line %d: syntax error at \"%s\" missing %s\n", + zzline, + (LA(1)==zzEOF_TOKEN)?"":(char *)LATEXT(1), + zztokens[tokenTypeOfSet]); + zzconsumeUntil( whatFollows ); + return 0; + } + else { + zzMakeAttr +#ifdef DEMAND_LOOK +#ifdef LL_K + zzdirty++; + zzlabase++; +#else + zzdirty = 1; +#endif +#else +/* zzCONSUME; consume if not demand lookahead */ +#endif + return 1; + } +} + +int +#ifdef __USE_PROTOS +_zzsetmatch_wsig(SetWordType *e) +#else +_zzsetmatch_wsig(e) +SetWordType *e; +#endif +{ +#ifdef DEMAND_LOOK +#ifdef LL_K + if ( zzdirty==LL_K ) {zzCONSUME;} +#else + if ( zzdirty ) {zzCONSUME;} +#endif +#endif + if ( !zzset_el((unsigned)LA(1), e) ) return 0; + zzMakeAttr /* MR14 Ger Hobbelt (hobbelt@axa.nl) */ +#ifdef DEMAND_LOOK +#ifdef LL_K + zzdirty++; + zzlabase++; /* MR14 Ger Hobbelt (hobbelt@axa.nl) */ +#else + zzdirty = 1; +#endif +#endif + return 1; +} + +#ifdef USER_ZZMODE_STACK +static int zzmstk[ZZMAXSTK] = { -1 }; +static int zzmdep = 0; +static char zzmbuf[70]; + +void +#ifdef __USE_PROTOS +zzmpush( int m ) +#else +zzmpush( m ) +int m; +#endif +{ + if(zzmdep == ZZMAXSTK - 1) { + sprintf(zzmbuf, "Mode stack overflow "); + zzerr(zzmbuf); + } else { + zzmstk[zzmdep++] = zzauto; + zzmode(m); + } +} + +void +#ifdef __USE_PROTOS +zzmpop( void ) +#else +zzmpop( ) +#endif +{ + if(zzmdep == 0) + { sprintf(zzmbuf, "Mode stack underflow "); + zzerr(zzmbuf); + } + else + { zzmdep--; + zzmode(zzmstk[zzmdep]); + } +} + +void +#ifdef __USE_PROTOS +zzsave_mode_stack( int modeStack[], int *modeLevel ) +#else +zzsave_mode_stack( modeStack, modeLevel ) +int modeStack[]; +int *modeLevel; +#endif +{ + int i; + memcpy(modeStack, zzmstk, sizeof(zzmstk)); + *modeLevel = zzmdep; + zzmdep = 0; + + return; +} + +void +#ifdef __USE_PROTOS +zzrestore_mode_stack( int modeStack[], int *modeLevel ) +#else +zzrestore_mode_stack( modeStack, modeLevel ) +int modeStack[]; +int *modeLevel; +#endif +{ + int i; + + memcpy(zzmstk, modeStack, sizeof(zzmstk)); + zzmdep = *modeLevel; + + return; +} +#endif /* USER_ZZMODE_STACK */ + +#ifdef __USE_PROTOS +void zzTraceReset(void) +#else +void zzTraceReset() +#endif +{ +#ifdef zzTRACE_RULES + zzTraceOptionValue=zzTraceOptionValueDefault; + zzTraceGuessOptionValue=1; + zzTraceCurrentRuleName=NULL; + zzTraceDepth=0; +#endif +} + +#ifdef __USE_PROTOS +void zzTraceGuessFail(void) +#else +void zzTraceGuessFail() +#endif +{ + +#ifdef zzTRACE_RULES +#ifdef ZZCAN_GUESS + + int doIt=0; + + if (zzTraceOptionValue <= 0) { + doIt=0; + } else if (zzguessing && zzTraceGuessOptionValue <= 0) { + doIt=0; + } else { + doIt=1; + }; + + if (doIt) { + fprintf(stderr,"guess failed\n"); + }; +#endif +#endif +} + +/* zzTraceOption: + zero value turns off trace +*/ + +#ifdef __USE_PROTOS +void zzTraceIn(char * rule) +#else +void zzTraceIn(rule) + char *rule; +#endif +{ +#ifdef zzTRACE_RULES + + int doIt=0; + + zzTraceDepth++; + zzTraceCurrentRuleName=rule; + + if (zzTraceOptionValue <= 0) { + doIt=0; +#ifdef ZZCAN_GUESS + } else if (zzguessing && zzTraceGuessOptionValue <= 0) { + doIt=0; +#endif + } else { + doIt=1; + }; + + if (doIt) { + fprintf(stderr,"enter rule %s {\"%s\"} depth %d", + rule, + LA(1)==1 ? "@" : (char *) LATEXT(1), /* MR19 */ + zzTraceDepth); +#ifdef ZZCAN_GUESS + if (zzguessing) fprintf(stderr," guessing"); +#endif + fprintf(stderr,"\n"); + }; +#endif + return; +} + +#ifdef __USE_PROTOS +void zzTraceOut(char * rule) +#else +void zzTraceOut(rule) + char *rule; +#endif +{ +#ifdef zzTRACE_RULES + int doIt=0; + + zzTraceDepth--; + + if (zzTraceOptionValue <= 0) { + doIt=0; +#ifdef ZZCAN_GUESS + } else if (zzguessing && zzTraceGuessOptionValue <= 0) { + doIt=0; +#endif + } else { + doIt=1; + }; + + if (doIt) { + fprintf(stderr,"exit rule %s {\"%s\"} depth %d", + rule, + LA(1)==1 ? "@" : (char *) LATEXT(1), /* MR19 */ + zzTraceDepth+1); +#ifdef ZZCAN_GUESS + if (zzguessing) fprintf(stderr," guessing"); +#endif + fprintf(stderr,"\n"); + }; +#endif +} + +#ifdef __USE_PROTOS +int zzTraceOption(int delta) +#else +int zzTraceOption(delta) + int delta; +#endif +{ +#ifdef zzTRACE_RULES + int prevValue=zzTraceOptionValue; + + zzTraceOptionValue=zzTraceOptionValue+delta; + + if (zzTraceCurrentRuleName != NULL) { + if (prevValue <= 0 && zzTraceOptionValue > 0) { + fprintf(stderr,"trace enabled in rule %s depth %d\n", + zzTraceCurrentRuleName,zzTraceDepth); + }; + if (prevValue > 0 && zzTraceOptionValue <= 0) { + fprintf(stderr,"trace disabled in rule %s depth %d\n", + zzTraceCurrentRuleName,zzTraceDepth); + }; + }; + return prevValue; +#else + return 0; +#endif +} + +#ifdef __USE_PROTOS +int zzTraceGuessOption(int delta) +#else +int zzTraceGuessOption(delta) + int delta; +#endif +{ +#ifdef zzTRACE_RULES +#ifdef ZZCAN_GUESS + int prevValue=zzTraceGuessOptionValue; + + zzTraceGuessOptionValue=zzTraceGuessOptionValue+delta; + + if (zzTraceCurrentRuleName != NULL) { + if (prevValue <= 0 && zzTraceGuessOptionValue > 0) { + fprintf(stderr,"guess trace enabled in rule %s depth %d\n", + zzTraceCurrentRuleName,zzTraceDepth); + }; + if (prevValue > 0 && zzTraceGuessOptionValue <= 0) { + fprintf(stderr,"guess trace disabled in rule %s depth %d\n", + zzTraceCurrentRuleName,zzTraceDepth); + }; + }; + return prevValue; +#else + return 0; +#endif +#else + return 0; +#endif +} + +#endif /* ERR_H */ diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/int.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/int.h new file mode 100644 index 00000000..cebe16c5 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/int.h @@ -0,0 +1,37 @@ +/* ANTLR attribute definition -- long integers + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * ANTLR 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +#ifndef ZZINT_H +#define ZZINT_H + +typedef long Attrib; + +#define zzcr_attr(a,tok,t) *(a) = atol(t); + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_assert.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_assert.h new file mode 100644 index 00000000..13d133ab --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_assert.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_ASSERT_H__ +#define __PCCTS_ASSERT_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_iostream.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_iostream.h new file mode 100644 index 00000000..24aee39f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_iostream.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_IOSTREAM_H__ +#define __PCCTS_IOSTREAM_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_istream.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_istream.h new file mode 100644 index 00000000..54e1461d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_istream.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_ISTREAM_H__ +#define __PCCTS_ISTREAM_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_setjmp.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_setjmp.h new file mode 100644 index 00000000..a6e925d1 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_setjmp.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_SETJMP_H__ +#define __PCCTS_SETJMP_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdarg.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdarg.h new file mode 100644 index 00000000..25b3f1c9 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdarg.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_STDARG_H__ +#define __PCCTS_STDARG_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdio.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdio.h new file mode 100644 index 00000000..0e9fc5b4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdio.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_STDIO_H__ +#define __PCCTS_STDIO_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdlib.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdlib.h new file mode 100644 index 00000000..d929e29c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_stdlib.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_STDLIB_H__ +#define __PCCTS_STDLIB_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_string.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_string.h new file mode 100644 index 00000000..5ebd368a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pccts_string.h @@ -0,0 +1,10 @@ +#ifndef __PCCTS_STRING_H__ +#define __PCCTS_STRING_H__ + +#ifdef PCCTS_USE_NAMESPACE_STD +#include +#else +#include +#endif + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pcctscfg.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pcctscfg.h new file mode 100644 index 00000000..64637536 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pcctscfg.h @@ -0,0 +1,359 @@ +#ifndef PCCTS_CONFIG_H +#define PCCTS_CONFIG_H +/* + * pcctscfg.h (formerly config.h) (for ANTLR, DLG, and SORCERER) + * + * This is a simple configuration file that doesn't have config stuff + * in it, but it's a start. + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to the Purdue Compiler Construction Tool + * Set (PCCTS) -- PCCTS is in the public domain. An individual or + * company may do whatever they wish with source code distributed with + * PCCTS or the code generated by PCCTS, including the incorporation of + * PCCTS, or its output, into commerical software. + * + * We encourage users to develop software with PCCTS. However, we do ask + * that credit is given to us for developing PCCTS. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like PCCTS and have developed a nice tool with the + * output, please mention that you developed it using PCCTS. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * Used by PCCTS 1.33 (SORCERER 1.00B11 and up) + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1989-2000 + */ + +/* This file knows about the following ``environments'' + UNIX (default) + DOS (use #define PC) + MAC (use #define MPW; has a few things for THINK C, Metrowerks) + MS/C++ (MR14 Microsoft Visual C++ environment uses symbol _MSC_VER) + + */ + +/* should test __STDC__ for 1, but some compilers don't set value, just def */ + +#ifndef __USE_PROTOS +#ifdef __STDC__ +#define __USE_PROTOS +#endif +#ifdef __cplusplus +#define __USE_PROTOS +#endif +#endif + +#ifdef PCCTS_USE_NAMESPACE_STD +#define PCCTS_NAMESPACE_STD namespace std {}; using namespace std; +#else +#define PCCTS_NAMESPACE_STD +#endif + +#include "pccts_stdio.h" +#include "pccts_stdlib.h" + +/* largest file name size */ + +#ifdef _MAX_PATH +#define MaxFileName _MAX_PATH /* MR9 RJV: MAX_PATH defined in stdlib.h (MSVC++ 5.0) */ +#else +#define MaxFileName 300 +#endif + +/* +* Define PC32 if in a 32-bit PC environment (e.g. extended DOS or Win32). +* The macros tested here are defined by Watcom, Microsoft, Borland, +* and djgpp, respectively, when they are used as 32-bit compilers. +* Users of these compilers *must* be sure to define PC in their +* makefiles for this to work correctly. +*/ +#ifdef PC +# if (defined(__WATCOMC__) || defined(_WIN32) || defined(__WIN32__) || \ + defined(__GNUC__) || defined(__GNUG__)) +# ifndef PC32 +# define PC32 +# endif +# endif +#endif + +/* MR1 10-Apr-97 Default for PC is short file names */ +/* MR1 Default for non-PC is long file names */ +/* MR1 Can override via command line option LONGFILENAMES */ + +#ifndef LONGFILENAMES +#ifndef PC +#define LONGFILENAMES +#endif +#endif + +#ifndef LONGFILENAMES +#define ATOKEN_H "AToken.h" +#define ATOKPTR_H "ATokPtr.h" +#define ATOKPTR_IMPL_H "ATokPtrIm.h" +#define ATOKENBUFFER_H "ATokBuf.h" +#define ATOKENBUFFER_C "ATokBuf.cpp" +#define ATOKENSTREAM_H "ATokStr.h" +#define APARSER_H "AParser.h" +#define APARSER_C "AParser.cpp" +#define ASTBASE_H "ASTBase.h" +#define ASTBASE_C "ASTBase.cpp" +#define PCCTSAST_C "PCCTSAST.cpp" +#define LIST_C "List.cpp" +#define DLEXERBASE_H "DLexBase.h" +#define DLEXERBASE_C "DLexBase.cpp" +#define DLEXER_H "DLexer.h" +#define STREESUPPORT_C "STreeSup.C" +#else +#define ATOKEN_H "AToken.h" +#define ATOKPTR_H "ATokPtr.h" +#define ATOKPTR_IMPL_H "ATokPtrImpl.h" +#define ATOKENBUFFER_H "ATokenBuffer.h" +#define ATOKENBUFFER_C "ATokenBuffer.cpp" +#define ATOKENSTREAM_H "ATokenStream.h" +#define APARSER_H "AParser.h" +#define APARSER_C "AParser.cpp" +#define ASTBASE_H "ASTBase.h" +#define ASTBASE_C "ASTBase.cpp" +#define PCCTSAST_C "PCCTSAST.cpp" +#define LIST_C "List.cpp" +#define DLEXERBASE_H "DLexerBase.h" +#define DLEXERBASE_C "DLexerBase.cpp" +#define DLEXER_H "DLexer.h" +#define STREESUPPORT_C "STreeSupport.cpp" +#endif + +/* SORCERER Stuff */ + +/* MR8 6-Aug-97 Change from ifdef PC to ifndef LONGFILENAMES */ + +#ifndef LONGFILENAMES +#define STPARSER_H "STreePar.h" +#define STPARSER_C "STreePar.C" +#else +#define STPARSER_H "STreeParser.h" +#define STPARSER_C "STreeParser.cpp" +#endif + +#ifdef MPW +#define CPP_FILE_SUFFIX ".cp" +#define CPP_FILE_SUFFIX_NO_DOT "cp" +#define OBJ_FILE_SUFFIX ".o" +#else +#ifdef PC +#define CPP_FILE_SUFFIX ".cpp" +#define CPP_FILE_SUFFIX_NO_DOT "cpp" +#define OBJ_FILE_SUFFIX ".obj" +#else +#ifdef __VMS +#define CPP_FILE_SUFFIX ".cpp" +#define CPP_FILE_SUFFIX_NO_DOT "cpp" +#define OBJ_FILE_SUFFIX ".obj" +#else +#define CPP_FILE_SUFFIX ".cpp" +#define CPP_FILE_SUFFIX_NO_DOT "cpp" +#define OBJ_FILE_SUFFIX ".o" +#endif +#endif +#endif + +/* User may redefine how line information looks */ /* make it #line MR7 */ +/* MR21 Use #ifndef */ + +#ifndef LineInfoFormatStr +#define LineInfoFormatStr "#line %d \"%s\"\n" +#endif + +#ifdef MPW /* Macintosh Programmer's Workshop */ +#define ErrHdr "File \"%s\"; Line %d #" +#else +#ifdef _MSC_VER /* MR14 Microsoft Visual C++ environment */ +#define ErrHdr "%s(%d) :" +#else +#define ErrHdr "%s, line %d:" /* default */ +#endif +#endif + +/* must assume old K&R cpp here, can't use #if defined(..)... */ + +#ifdef MPW +#define TopDirectory ":" +#define DirectorySymbol ":" +#define OutputDirectoryOption "Directory where all output files should go (default=\":\")" +#else +#ifdef PC +#define TopDirectory "." +#define DirectorySymbol "\\" +#define OutputDirectoryOption "Directory where all output files should go (default=\".\")" +#else +#ifdef __VMS +#define TopDirectory "[000000]" +#define DirectorySymbol "]" +#define OutputDirectoryOption "Directory where all output files should go (default=\"[]\")" +#else +#define TopDirectory "." +#define DirectorySymbol "/" +#define OutputDirectoryOption "Directory where all output files should go (default=\".\")" +#endif +#endif +#endif + +#ifdef MPW + +/* Make sure we have prototypes for all functions under MPW */ + +#include "pccts_string.h" +#include "pccts_stdlib.h" + +/* MR6 2-Jun-97 Fixes false dependency caused by VC++ #include scanner */ +/* MR6 Reported by Brad Schick (schick@interaccess.com) */ +#define MPW_CursorCtl_Header +#include MPW_CursorCtl_Header +#ifdef __cplusplus +extern "C" { +#endif +extern void fsetfileinfo (const char *filename, unsigned long newcreator, unsigned long newtype); +#ifdef __cplusplus +} +#endif + +/* File creators for various popular development environments */ + +#define MAC_FILE_CREATOR 'MPS ' /* MPW Text files */ +#if 0 +#define MAC_FILE_CREATOR 'KAHL' /* THINK C/Symantec C++ Text files */ +#endif +#if 0 +#define MAC_FILE_CREATOR 'CWIE' /* Metrowerks C/C++ Text files */ +#endif + +#endif + +#ifdef MPW +#define DAWDLE SpinCursor(1) +#else +#define DAWDLE +#endif + +#ifdef MPW +#define SPECIAL_INITS +#define SPECIAL_FOPEN +#endif + +#ifdef MPW +#ifdef __cplusplus +inline +#else +static +#endif +void special_inits() +{ + InitCursorCtl((acurHandle) 0); +} +#endif + +#ifdef MPW +#ifdef __cplusplus +inline +#else +static +#endif +void special_fopen_actions(char * s) +{ + fsetfileinfo (s, MAC_FILE_CREATOR, 'TEXT'); +} +#endif + +/* Define usable bits for set.c stuff */ +#define BytesPerWord sizeof(unsigned) +#define WORDSIZE (sizeof(unsigned)*8) +#define LogWordSize (WORDSIZE==16?4:5) + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +#if defined(VAXC) || defined(__VMS) +#include +#define PCCTS_EXIT_SUCCESS 1 +#define PCCTS_EXIT_FAILURE SS$_ABORT +#define zzDIE return SS$_ABORT; +#define zzDONE return 1; + +#else /* !VAXC and !__VMS */ + +#define PCCTS_EXIT_SUCCESS 0 +#define PCCTS_EXIT_FAILURE 1 +#define zzDIE return 1; +#define zzDONE return 0; + +#endif + +#ifdef USER_ZZMODE_STACK +# ifndef ZZSTACK_MAX_MODE +# define ZZSTACK_MAX_MODE 32 +# endif +# define ZZMAXSTK (ZZSTACK_MAX_MODE * 2) +#endif + +#ifndef DllExportPCCTS +#define DllExportPCCTS +#endif + +#ifdef PC +#ifndef PCCTS_CASE_INSENSITIVE_FILE_NAME +#define PCCTS_CASE_INSENSITIVE_FILE_NAME +#endif +#endif + +#ifdef PC32 +#ifndef PCCTS_CASE_INSENSITIVE_FILE_NAME +#define PCCTS_CASE_INSENSITIVE_FILE_NAME +#endif +#endif + +#ifdef __VMS +#ifndef PCCTS_CASE_INSENSITIVE_FILE_NAME +#define PCCTS_CASE_INSENSITIVE_FILE_NAME +#endif +#endif + +#ifdef __USE_PROTOS +#ifndef PCCTS_USE_STDARG +#define PCCTS_USE_STDARG +#endif +#endif + +#ifdef __STDC__ +#ifndef PCCTS_USE_STDARG +#define PCCTS_USE_STDARG +#endif +#endif + +#ifdef __cplusplus +#ifndef PCCTS_USE_STDARG +#define PCCTS_USE_STDARG +#endif +#endif + +#ifdef _MSC_VER +/*Turn off the warnings for: + unreferenced inline/local function has been removed +*/ +#pragma warning(disable : 4514) +/* function not expanded */ +#pragma warning(disable : 4710) +#endif + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pcnames.bat b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pcnames.bat new file mode 100644 index 00000000..8784aee9 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/pcnames.bat @@ -0,0 +1,11 @@ +ren aparser.c aparser.cpp +ren astbase.c astbase.cpp +ren atokenbu.c atokbuf.cpp +ren atokenbu.h atokbuf.h +ren atokenst.h atokstr.h +ren dlexerba.c dlexbase.cpp +ren dlexerba.h dlexbase.h +ren dlexer.c dlexer.cpp +ren list.c list.cpp +ren pblackbo.h pblckbox.h +ren pcctsast.c pcctsast.cpp diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/slist.cpp b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/slist.cpp new file mode 100644 index 00000000..eceacc47 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/h/slist.cpp @@ -0,0 +1,116 @@ +/* + * SList.C + * + * SOFTWARE RIGHTS + * + * We reserve no LEGAL rights to SORCERER -- SORCERER is in the public + * domain. An individual or company may do whatever they wish with + * source code distributed with SORCERER or the code generated by + * SORCERER, including the incorporation of SORCERER, or its output, into + * commerical software. + * + * We encourage users to develop software with SORCERER. However, we do + * ask that credit is given to us for developing SORCERER. By "credit", + * we mean that if you incorporate our source code into one of your + * programs (commercial product, research project, or otherwise) that you + * acknowledge this fact somewhere in the documentation, research report, + * etc... If you like SORCERER and have developed a nice tool with the + * output, please mention that you developed it using SORCERER. In + * addition, we ask that this header remain intact in our source code. + * As long as these guidelines are kept, we expect to continue enhancing + * this system and expect to make other tools available as they are + * completed. + * + * PCCTS 1.33 + * Terence Parr + * Parr Research Corporation + * with Purdue University and AHPCRC, University of Minnesota + * 1992-2000 + */ + +#define ANTLR_SUPPORT_CODE + +#include "SList.h" +#include "pccts_stdarg.h" // MR23 + +/* Iterate over a list of elements; returns ptr to a new element + * in list upon every call and NULL when no more are left. + * Very useful like this: + * + * cursor = mylist; + * while ( (p=mylist->iterate(&cursor)) ) { + * // place with element p + * } + * + * The cursor must be initialized to point to the list to iterate over. + */ +void *SList:: +iterate(SListNode **cursor) +{ + void *e; + + if ( cursor == NULL || *cursor==NULL ) return NULL; + if ( head == *cursor ) { *cursor = (*cursor)->next(); } + e = (*cursor)->elem(); + (*cursor) = (*cursor)->next(); + return e; +} + +/* add an element to end of list. */ +void SList:: +add(void *e) +{ + SListNode *p, *tail=NULL; + require(e!=NULL, "slist_add: attempting to add NULL list element"); + + p = new SListNode; + require(p!=NULL, "add: cannot alloc new list node"); + p->setElem(e); + if ( head == NULL ) + { + head = tail = p; + } + else /* find end of list */ + { + tail->setNext(p); + tail = p; + } +} + +void SList:: +lfree() +{ + SListNode *p,*q; + + if ( head==NULL ) return; /* empty list */ + for (p = head; p!=NULL; p=q) + { + q = p->next(); + free(p); + } +} + +PCCTS_AST *SList:: +to_ast(SList list) +{ + PCCTS_AST *t=NULL, *last=NULL; + SListNode *p; + + for (p = head; p!=NULL; p=p->next()) + { + PCCTS_AST *u = (PCCTS_AST *)p->elem(); + if ( last==NULL ) last = t = u; + else { last->setRight(u); last = u; } + } + return t; +} + +// MR23 +int SList::printMessage(FILE* pFile, const char* pFormat, ...) +{ + va_list marker; + va_start( marker, pFormat ); + int iRet = vfprintf(pFile, pFormat, marker); + va_end( marker ); + return iRet; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/history.ps b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/history.ps new file mode 100644 index 00000000..e2600d51 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/history.ps @@ -0,0 +1,473 @@ +%!PS-Adobe-3.0 +%%Creator: groff version 1.06 +%%DocumentNeededResources: font Times-Roman +%%+ font Times-Italic +%%+ font Courier +%%DocumentSuppliedResources: procset grops 1.06 0 +%%Pages: 3 +%%PageOrder: Ascend +%%Orientation: Portrait +%%EndComments +%%BeginProlog +%%BeginResource: procset grops 1.06 0 + +/setpacking where { + pop + currentpacking + true setpacking +} if + +/grops 120 dict dup begin + +% The ASCII code of the space character. +/SC 32 def + +/A /show load def +/B { 0 SC 3 -1 roll widthshow } bind def +/C { 0 exch ashow } bind def +/D { 0 exch 0 SC 5 2 roll awidthshow } bind def +/E { 0 rmoveto show } bind def +/F { 0 rmoveto 0 SC 3 -1 roll widthshow } bind def +/G { 0 rmoveto 0 exch ashow } bind def +/H { 0 rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def +/I { 0 exch rmoveto show } bind def +/J { 0 exch rmoveto 0 SC 3 -1 roll widthshow } bind def +/K { 0 exch rmoveto 0 exch ashow } bind def +/L { 0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def +/M { rmoveto show } bind def +/N { rmoveto 0 SC 3 -1 roll widthshow } bind def +/O { rmoveto 0 exch ashow } bind def +/P { rmoveto 0 exch 0 SC 5 2 roll awidthshow } bind def +/Q { moveto show } bind def +/R { moveto 0 SC 3 -1 roll widthshow } bind def +/S { moveto 0 exch ashow } bind def +/T { moveto 0 exch 0 SC 5 2 roll awidthshow } bind def + +% name size font SF - + +/SF { + findfont exch + [ exch dup 0 exch 0 exch neg 0 0 ] makefont + dup setfont + [ exch /setfont cvx ] cvx bind def +} bind def + +% name a c d font MF - + +/MF { + findfont + [ 5 2 roll + 0 3 1 roll % b + neg 0 0 ] makefont + dup setfont + [ exch /setfont cvx ] cvx bind def +} bind def + +/level0 0 def +/RES 0 def +/PL 0 def +/LS 0 def + +% Guess the page length. +% This assumes that the imageable area is vertically centered on the page. +% PLG - length + +/PLG { + gsave newpath clippath pathbbox grestore + exch pop add exch pop +} bind def + +% BP - + +/BP { + /level0 save def + 1 setlinecap + 1 setlinejoin + 72 RES div dup scale + LS { + 90 rotate + } { + 0 PL translate + } ifelse + 1 -1 scale +} bind def + +/EP { + level0 restore + showpage +} bind def + + +% centerx centery radius startangle endangle DA - + +/DA { + newpath arcn stroke +} bind def + +% x y SN - x' y' +% round a position to nearest (pixel + (.25,.25)) + +/SN { + transform + .25 sub exch .25 sub exch + round .25 add exch round .25 add exch + itransform +} bind def + +% endx endy startx starty DL - +% we round the endpoints of the line, so that parallel horizontal +% and vertical lines will appear even + +/DL { + SN + moveto + SN + lineto stroke +} bind def + +% centerx centery radius DC - + +/DC { + newpath 0 360 arc closepath +} bind def + + +/TM matrix def + +% width height centerx centery DE - + +/DE { + TM currentmatrix pop + translate scale newpath 0 0 .5 0 360 arc closepath + TM setmatrix +} bind def + +% these are for splines + +/RC /rcurveto load def +/RL /rlineto load def +/ST /stroke load def +/MT /moveto load def +/CL /closepath load def + +% fill the last path + +% amount FL - + +/FL { + currentgray exch setgray fill setgray +} bind def + +% fill with the ``current color'' + +/BL /fill load def + +/LW /setlinewidth load def +% new_font_name encoding_vector old_font_name RE - + +/RE { + findfont + dup maxlength dict begin + { + 1 index /FID ne { def } { pop pop } ifelse + } forall + /Encoding exch def + dup /FontName exch def + currentdict end definefont pop +} bind def + +/DEFS 0 def + +% hpos vpos EBEGIN - + +/EBEGIN { + moveto + DEFS begin +} bind def + +/EEND /end load def + +/CNT 0 def +/level1 0 def + +% llx lly newwid wid newht ht newllx newlly PBEGIN - + +/PBEGIN { + /level1 save def + translate + div 3 1 roll div exch scale + neg exch neg exch translate + % set the graphics state to default values + 0 setgray + 0 setlinecap + 1 setlinewidth + 0 setlinejoin + 10 setmiterlimit + [] 0 setdash + /setstrokeadjust where { + pop + false setstrokeadjust + } if + /setoverprint where { + pop + false setoverprint + } if + newpath + /CNT countdictstack def + userdict begin + /showpage {} def +} bind def + +/PEND { + clear + countdictstack CNT sub { end } repeat + level1 restore +} bind def + +end def + +/setpacking where { + pop + setpacking +} if +%%EndResource +%%IncludeResource: font Times-Roman +%%IncludeResource: font Times-Italic +%%IncludeResource: font Courier +grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72 def/PL +792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron/scaron/zcaron +/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef +/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/space +/exclam/quotedbl/numbersign/dollar/percent/ampersand/quoteright/parenleft +/parenright/asterisk/plus/comma/hyphen/period/slash/zero/one/two/three/four +/five/six/seven/eight/nine/colon/semicolon/less/equal/greater/question/at/A/B/C +/D/E/F/G/H/I/J/K/L/M/N/O/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash +/bracketright/circumflex/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q +/r/s/t/u/v/w/x/y/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase +/guillemotleft/guillemotright/bullet/florin/fraction/perthousand/dagger +/daggerdbl/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut +/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash +/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen/brokenbar +/section/dieresis/copyright/ordfeminine/guilsinglleft/logicalnot/minus +/registered/macron/degree/plusminus/twosuperior/threesuperior/acute/mu +/paragraph/periodcentered/cedilla/onesuperior/ordmasculine/guilsinglright +/onequarter/onehalf/threequarters/questiondown/Agrave/Aacute/Acircumflex/Atilde +/Adieresis/Aring/AE/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute +/Icircumflex/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis +/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn/germandbls +/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla/egrave/eacute +/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis/eth/ntilde/ograve +/oacute/ocircumflex/otilde/odieresis/divide/oslash/ugrave/uacute/ucircumflex +/udieresis/yacute/thorn/ydieresis]def/Courier@0 ENC0/Courier RE/Times-Italic@0 +ENC0/Times-Italic RE/Times-Roman@0 ENC0/Times-Roman RE +%%EndProlog +%%Page: 1 1 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 13/Times-Roman@0 SF(The History of PCCTS)228.232 84 Q/F1 11/Times-Roman@0 +SF(The Purdue Compiler)190.468 108 Q(-Construction T)-.22 E(ool Set)-.88 E/F2 +10/Times-Italic@0 SF -.92(Te)262.245 144 S -.37(re).92 G(nce P).37 E(arr)-.8 E +/F3 10/Times-Roman@0 SF -.15(Pa)234.755 156 S(rr Research Corporation).15 E +(Minneapolis, Minnesota)239.39 168 Q(and)280.78 180 Q(Uni)239.315 192 Q -.15 +(ve)-.25 G(rsity of Minnesota).15 E +(Army High Performance Computing Research Center)180.38 204 Q F2 +([Updated 8-7-94])252.31 228 Q F1 .084(The PCCTS project be)97 259.6 R -.055 +(ga)-.165 G 2.834(na).055 G 2.833(sap)220.547 259.6 S(arser)240.876 259.6 Q +.083(-generator project for a graduate course at Purdue Uni-)-.22 F -.165(ve)72 +275.6 S 1.085(rsity in the F).165 F 1.086 +(all of 1988 taught by Hank Dietz\212 translator)-.165 F 1.086 +(-writing systems.)-.22 F 1.086(Under the guid-)6.586 F .627 +(ance of Professor Dietz, the parser generator)72 291.6 R 3.377(,A)-.44 G .626 +(NTLR \(originally called YUCC\), continued after)285.18 291.6 R .253 +(the termination of the course and e)72 307.6 R -.165(ve)-.275 G .254 +(ntually became the subject of T).165 F .254(erence P)-.77 F(arr')-.165 E 3.004 +(sM)-.605 G(aster')445.083 307.6 Q 3.004(st)-.605 G(hesis.)479.25 307.6 Q +(Originally)72 323.6 Q 4.092(,l)-.715 G -.165(ex)126.406 323.6 S 1.342 +(ical analysis w).165 F 1.342(as performed via ALX which w)-.11 F 1.342 +(as soon replaced by W)-.11 F 1.341(ill Cohen')-.44 F(s)-.605 E .594 +(DLG in the F)72 339.6 R .594(all of 1989 \(DF)-.165 F .595(A-based le)-.814 F +.595(xical-analyzer generator)-.165 F 3.345(,a)-.44 G .595(lso an of)367.188 +339.6 R .595(fshoot of the graduate)-.275 F(translation course\).)72 355.6 Q +.877(The alpha v)97 375.2 R .877(ersion of ANTLR w)-.165 F .877(as totally re) +-.11 F .876(written resulting in 1.00B.)-.275 F -1.221(Ve)6.376 G .876 +(rsion 1.00B w)1.221 F(as)-.11 E 1.577(released via an internet ne)72 391.2 R +1.577(wsgroup \(comp.compilers\) posting in February of 1990 and quickly)-.275 +F -.055(ga)72 407.2 S .356(thered a lar).055 F .356(ge follo)-.198 F 3.106 +(wing. 1.00B)-.275 F .356(generated only LL\(1\) parsers, b)3.106 F .356 +(ut allo)-.22 F .356(wed the mer)-.275 F .356(ged descrip-)-.198 F 1.859 +(tion of le)72 423.2 R 1.859(xical and syntactic analysis.)-.165 F 1.86 +(It had rudimentary attrib)7.359 F 1.86(ute handling similar to that of)-.22 F +-.55 -1.32(YA C)72 439.2 T 3.549(Ca)1.32 G .799 +(nd did not incorporate rule parameters or return v)109.231 439.2 R .798 +(alues; do)-.275 F(wnw)-.275 E .798(ard inheritance w)-.11 F .798(as v)-.11 F +(ery)-.165 E -.165(aw)72 455.2 S(kw).165 E 6.433(ard. 1.00B-generated)-.11 F +3.684(parsers terminated upon the \214rst syntax error)6.433 F 9.184(.L)-.605 G +-.165(ex)440.916 455.2 S 3.684(ical classes).165 F(\(modes\) were not allo)72 +471.2 Q(wed and DLG did not ha)-.275 E .33 -.165(ve a)-.22 H 2.75(ni).165 G +(nteracti)305.959 471.2 Q .33 -.165(ve m)-.275 H(ode.).165 E .831 +(Upon starting his Ph.D. at Purdue in the F)97 490.8 R .83(all of 1990, T)-.165 +F .83(erence P)-.77 F .83(arr be)-.165 F -.055(ga)-.165 G 3.58(nt).055 G .83 +(he second total)436.351 490.8 R(re)72 506.8 Q 1.646(write of ANTLR.)-.275 F +1.646(The method by which grammars may be practically analyzed to generate) +7.146 F/F4 11/Times-Italic@0 SF(LL)72.638 522.8 Q F1(\().583 E F4(k).396 E F1 +3.849(\)l).737 G 1.099(ookahead information w)105.703 522.8 R 1.099(as disco) +-.11 F -.165(ve)-.165 G 1.099(red in August of 1990 just before his return.) +.165 F -1.221(Ve)6.598 G(rsion)1.221 E .626 +(1.00 incorporated this algorithm and included the AST mechanism, le)72 538.8 R +.626(xical classes, error classes,)-.165 F .354(and automatic error reco)72 +554.8 R -.165(ve)-.165 G .353(ry; code quality and portability were higher).165 +F 5.853(.I)-.605 G 3.103(nF)395.965 554.8 S .353(ebruary of 1992 1.00)410.684 +554.8 R -.11(wa)72 570.8 S 2.76(sr).11 G .01 +(eleased via an article in SIGPLAN Notices.)95.418 570.8 R .01 +(Peter Dahl, Ph.D. candidate, and Professor Matt)5.51 F(O'K)72 586.8 Q 2.074 +(eefe \(both at the Uni)-.275 F -.165(ve)-.275 G 2.073 +(rsity of Minnesota\) tested this v).165 F 2.073(ersion e)-.165 F(xtensi)-.165 +E -.165(ve)-.275 G(ly).165 E 7.573(.D)-.715 G 2.073(ana Hogg)448.522 586.8 R +(att)-.055 E .078(\(Micro Data Base Systems, Inc.\) came up with the idea of e\ +rror grouping \(strings attached to non-)72 602.8 R +(terminals\) and tested 1.00 hea)72 618.8 Q(vily)-.22 E(.)-.715 E -1.221(Ve)97 +638.4 S .878(rsion 1.06 w)1.221 F .877 +(as released in December 1992 and represented a lar)-.11 F .877 +(ge feature enhancement)-.198 F -.165(ove)72 654.4 S 3.648(r1).165 G 3.648 +(.00. F)100.365 654.4 R .898(or e)-.165 F .899 +(xample, rudimentary semantic predicates were introduced, error messages were) +-.165 F 2.281(signi\214cantly impro)72 670.4 R -.165(ve)-.165 G 5.031(df).165 G +(or)181.953 670.4 Q F4(k)5.427 E F1 2.281 +(>1 lookahead and ANTLR parsers could indicate that lookahead).737 F 1.381 +(fetches were to occur only when necessary for the parse \(normally)72 686.4 R +4.131(,t)-.715 G 1.381(he lookahead `)387.051 686.4 R(`pipe')-.814 E 4.132('w) +-.814 G(as)494.837 686.4 Q 1.182(constantly full\).)72 702.4 R 1.182 +(Russell Quong joined the project in the Spring of 1992 to aid in the semantic) +6.682 F .681(predicate design.)72 718.4 R(Be)6.181 E .681(ginning and adv)-.165 +F .682(anced tutorials were created and released as well.)-.275 F 3.432(Am) +6.182 G(ak)485.179 718.4 Q(e-)-.11 E .993(\214le generator w)72 734.4 R .993 +(as included that sets up dependencies and such correctly for ANTLR and DLG.) +-.11 F EP +%%Page: 2 2 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 11/Times-Roman@0 SF 2.75(-2-)278.837 52 S -1.221(Ve)72 88 S 1.414(ry fe) +1.221 F 4.164(w1)-.275 G 1.414(.00 incompatibilities were introduced \(1.00 w) +122.81 88 R 1.415(as quite dif)-.11 F 1.415(ferent from 1.00B in some)-.275 F +(areas\).)72 104 Q 1.089(1.10 w)97 123.6 R 1.088 +(as released on August 31, 1993 and incorporated b)-.11 F 1.088(ug \214x)-.22 F +1.088(es, a fe)-.165 F 3.838(wf)-.275 G 1.088(eature enhance-)433.59 123.6 R +3.112(ments and a major ne)72 139.6 R 5.863(wc)-.275 G(apability \212)196.957 +139.6 Q 3.113(an arbitrary lookahead operator \(syntactic predicate\),)5.863 F +/F1 11/Courier@0 SF(\(alpha\)?beta)72 155.6 Q F0 6.754(.T)C 1.254 +(his feature w)167.425 155.6 R 1.254 +(as co-designed with Professor Russell Quong also at Purdue.)-.11 F 3.297 -.88 +(To s)72 171.6 T 1.537 +(upport in\214nite lookahead, a preprocessor \215ag, ZZINF_LOOK, w).88 F 1.537 +(as created that forced the)-.11 F .21(ANTLR\(\) macro to tok)72 187.6 R .21 +(enize all input prior to parsing.)-.11 F .209(Hence, at an)5.709 F 2.959(ym) +-.165 G .209(oment, an action or predi-)389.215 187.6 R .936 +(cate can see the entire input sentence.)72 203.6 R .936 +(The predicate mechanism of 1.06 w)6.436 F .937(as e)-.11 F .937 +(xtended to allo)-.165 F(w)-.275 E .55 +(multiple predicates to be hoisted; the syntactic conte)72 219.6 R .55 +(xt of a predicate w)-.165 F .55(as also mo)-.11 F -.165(ve)-.165 G 3.299(da) +.165 G .549(long with)461.585 219.6 R(the predicate.)72 235.6 Q .754 +(In February of 1994, SORCERER \(a simple tree-parser generator\) w)97 255.2 R +.755(as released.)-.11 F .755(This tool)6.255 F(allo)72 271.2 Q .6(ws the user\ + to parse child-sibling trees by specifying a grammar rather than b)-.275 F +.599(uilding a recur)-.22 F(-)-.22 E(si)72 287.2 Q -.165(ve)-.275 G 1.39 +(-descent tree w).165 F(alk)-.11 E 1.391(er by hand.)-.11 F -.88(Wo)6.891 G +1.391(rk to).88 F -.11(wa)-.275 G 1.391 +(rds a library of tree transformations is underw).11 F(ay)-.11 E(.)-.715 E .581 +(Aaron Sa)72 303.2 R(wde)-.165 E 3.331(ya)-.165 G 3.331(tT)145.531 303.2 S .581 +(he Uni)158.641 303.2 R -.165(ve)-.275 G .58 +(rsity of Minnesota became a second author of SORCERER after the).165 F +(initial release.)72 319.2 Q .627(On April 1, 1994, PCCTS 1.20 w)97 338.8 R +.627(as released.)-.11 F .627(This w)6.127 F .627(as the \214rst v)-.11 F .627 +(ersion to acti)-.165 F -.165(ve)-.275 G .627(ly support).165 F 1.664 +(C++ output.)72 354.8 R 1.664(It also included important \214x)7.164 F 1.663 +(es re)-.165 F -.055(ga)-.165 G 1.663 +(rding semantic predicates and \(..\)+ subrules.).055 F(This v)72 370.8 Q +(ersion also introduced tok)-.165 E(en classes, the `)-.11 E(`)-.814 E/F2 11 +/Times-Italic@0 SF(not)A F0 1.628 -.814('' o)D(perator).814 E 2.75(,a)-.44 G +(nd tok)355.294 370.8 Q(en ranges.)-.11 E .764 +(On June 19, 1994, SORCERER 1.00B9 w)97 390.4 R .765(as released.)-.11 F .765 +(Gary Funck of Intrepid T)6.265 F(echnology)-.77 E .807 +(joined the SORCERER team and pro)72 406.4 R .807(vided v)-.165 F .807(ery v) +-.165 F .807(aluable suggestions re)-.275 F -.055(ga)-.165 G .806(rding the `) +.055 F(`transform')-.814 E(')-.814 E(mode of SORCERER.)72 422.4 Q 1.137 +(On August 8, 1994, PCCTS 1.21 w)97 442 R 1.137(as released.)-.11 F 1.138 +(It mainly cleaned up the C++ output and)6.637 F(included a number of b)72 458 +Q(ug \214x)-.22 E(es.)-.165 E .316(From the 1.21 release forw)97 477.6 R .316 +(ard, the maintenance and support of all PCCTS tools will be pri-)-.11 F 1.557 +(marily pro)72 493.6 R 1.557(vided by P)-.165 F 1.557 +(arr Research Corporation, Minneapolis MN---an or)-.165 F -.055(ga)-.198 G +1.558(nization founded on).055 F 1.616(the principles of e)72 509.6 R 1.616 +(xcellence in research and inte)-.165 F 1.616(grity in b)-.165 F 1.616 +(usiness; we are de)-.22 F -.22(vo)-.275 G 1.616(ted to pro).22 F(viding)-.165 +E 1.202(really cool softw)72 525.6 R 1.202(are tools.)-.11 F 1.202 +(Please see \214le PCCTS.FUTURE for more information.)6.702 F 1.203(All PCCTS) +6.703 F(tools currently in the public domain will continue to be in the public\ + domain.)72 541.6 Q 1.198(Looking to)97 561.2 R -.11(wa)-.275 G 1.198 +(rds the future, a graphical user).11 F(-interf)-.22 E 1.197 +(ace is in the design phase.)-.11 F 1.197(This w)6.697 F(ould)-.11 E(allo)72 +577.2 Q 2.753(wu)-.275 G .003(sers to vie)104.42 577.2 R 2.753(wt)-.275 G .004 +(he syntax diagram representation of their grammars and w)162.509 577.2 R .004 +(ould highlight non-)-.11 F 1.181(deterministic productions.)72 593.2 R -.165 +(Pa)6.681 G 1.18(rsing can be traced graphically as well.).165 F 1.18 +(This system will be b)6.68 F(uilt)-.22 E .167(using a multiplatform windo)72 +609.2 R 2.917(wl)-.275 G(ibrary)211.73 609.2 Q 5.667(.W)-.715 G 2.917(ea) +255.204 609.2 S .168(lso anticipate the introduction of a sophisticated error) +267.889 609.2 R(handling mechanism called `)72 625.2 Q(`parser e)-.814 E +(xception handling')-.165 E 2.75('i)-.814 G 2.75(nan)327.431 625.2 S +(ear future release.)348.815 625.2 Q(Currently)97 644.8 Q 3.019(,P)-.715 G .269 +(CCTS is used at o)150.333 644.8 R -.165(ve)-.165 G 3.019(r1).165 G .269 +(000 kno)253.098 644.8 R .268(wn academic, go)-.275 F -.165(ve)-.165 G .268 +(rnment, and commercial sites).165 F .859(in 37 countries.)72 660.8 R .859 +(Of course, the true number of users is unkno)6.359 F .859(wn due to the lar) +-.275 F .859(ge number of ftp)-.198 F(sites.)72 676.8 Q EP +%%Page: 3 3 +%%BeginPageSetup +BP +%%EndPageSetup +/F0 11/Times-Roman@0 SF 2.75(-3-)278.837 52 S(Credits)272.11 88 Q .44 LW +472.162 103.75 103.838 103.75 DL(Idea/T)134.236 117 Q 52.987(ool Coder)-.88 F +(Co-designer\(s\))345.436 117 Q 281.334 103.75 281.334 124.75 DL 209.273 103.75 +209.273 124.75 DL 209.273 124.75 103.838 124.75 DL 103.838 126.75 209.273 +126.75 DL 281.334 124.75 209.273 124.75 DL 209.273 126.75 281.334 126.75 DL +472.162 124.75 281.334 124.75 DL 281.334 126.75 472.162 126.75 DL(ANTLR 1.00A) +109.338 140 Q -.77(Te)217.523 140 S(rence P).77 E 13.75(arr Hank)-.165 F(Dietz) +2.75 E 82.83(ALX T)109.338 156 R(erence P)-.77 E 13.75(arr Hank)-.165 F(Dietz) +2.75 E(ANTLR 1.00B)109.338 172 Q -.77(Te)217.523 172 S(rence P).77 E 13.75 +(arr Hank)-.165 F(Dietz, W)2.75 E(ill Cohen)-.44 E(DLG 1.00B)109.338 188 Q -.44 +(Wi)217.523 188 S(ll Cohen).44 E -.77(Te)289.584 188 S(rence P).77 E(arr)-.165 +E 2.75(,H)-.44 G(ank Dietz)358.147 188 Q(NF)109.338 204 Q 2.75(AR)-.814 G +30.778(elabelling W)140.611 204 R(ill Cohen)-.44 E/F1 11/Times-Italic@0 SF(LL) +109.976 220 Q F0(\().583 E F1(k).396 E F0 2.75(\)a).737 G 40.447(nalysis T) +143.768 220 R(erence P)-.77 E 13.75(arr Hank)-.165 F(Dietz)2.75 E(ANTLR 1.00) +109.338 236 Q -.77(Te)217.523 236 S(rence P).77 E 13.75(arr Hank)-.165 F +(Dietz, W)2.75 E(ill Cohen)-.44 E(DLG 1.00)109.338 252 Q -.44(Wi)217.523 252 S +(ll Cohen).44 E -.77(Te)289.584 252 S(rence P).77 E(arr)-.165 E 2.75(,H)-.44 G +(ank Dietz)358.147 252 Q(ANTLR 1.06)109.338 268 Q -.77(Te)217.523 268 S +(rence P).77 E 13.75(arr W)-.165 F(ill Cohen, Russell Quong, Hank Dietz)-.44 E +(DLG 1.06)109.338 284 Q -.44(Wi)217.523 284 S(ll Cohen).44 E -.77(Te)289.584 +284 S(rence P).77 E(arr)-.165 E 2.75(,H)-.44 G(ank Dietz)358.147 284 Q +(ANTLR 1.10)109.338 300 Q -.77(Te)217.523 300 S(rence P).77 E 13.75(arr W)-.165 +F(ill Cohen, Russell Quong)-.44 E(ANTLR 1.20)109.338 316 Q -.77(Te)217.523 316 +S(rence P).77 E 13.75(arr W)-.165 F(ill Cohen, Russell Quong)-.44 E(ANTLR 1.21) +109.338 332 Q -.77(Te)217.523 332 S(rence P).77 E 13.75(arr Russell)-.165 F +(Quong)2.75 E(DLG 1.10)109.338 348 Q -.44(Wi)217.523 348 S(ll Cohen).44 E -.77 +(Te)289.584 348 S(rence P).77 E(arr)-.165 E(DLG 1.20)109.338 364 Q -.44(Wi) +217.523 364 S(ll Cohen).44 E -.77(Te)289.584 364 S(rence P).77 E(arr)-.165 E +(DLG 1.21)109.338 380 Q -.77(Te)217.523 380 S(rence P).77 E(arr)-.165 E +(Semantic predicates)109.338 396 Q -.77(Te)217.523 396 S(rence P).77 E 13.75 +(arr Russell)-.165 F(Quonq)2.75 E(Syntactic predicates)109.338 412 Q -.77(Te) +217.523 412 S(rence P).77 E 13.75(arr Russell)-.165 F(Quonq)2.75 E +(SORCERER 1.00A)109.338 428 Q -.77(Te)217.523 428 S(rence P).77 E(arr)-.165 E +(SORCERER 1.00B)109.338 444 Q -.77(Te)217.523 444 S(rence P).77 E 13.75 +(arr Aaron)-.165 F(Sa)2.75 E(wde)-.165 E(y)-.165 E(SORCERER 1.00B9)109.338 460 +Q -.77(Te)217.523 460 S(rence P).77 E 13.75(arr Aaron)-.165 F(Sa)2.75 E(wde) +-.165 E 1.43 -.715(y, G)-.165 H(ary Funck).715 E 472.162 467.75 103.838 467.75 +DL 472.162 103.75 472.162 467.75 DL 103.838 103.75 103.838 467.75 DL EP +%%Trailer +end +%%EOF diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/history.txt b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/history.txt new file mode 100644 index 00000000..96d66d3c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/history.txt @@ -0,0 +1,186 @@ + + + + The History of PCCTS + + The Purdue Compiler-Construction Tool Set + + + Terence Parr + Parr Research Corporation + Minneapolis, Minnesota + and + University of Minnesota + Army High Performance Computing Research Center + + [Updated 8-7-94] + + + The PCCTS project began as a parser-generator project for a gra- +duate course at Purdue University in the Fall of 1988 taught by Hank +Dietz- translator-writing systems. Under the guidance of Professor +Dietz, the parser generator, ANTLR (originally called YUCC), continued +after the termination of the course and eventually became the subject +of Terence Parr's Master's thesis. Originally, lexical analysis was +performed via ALX which was soon replaced by Will Cohen's DLG in the +Fall of 1989 (DFA-based lexical-analyzer generator, also an offshoot +of the graduate translation course). + + The alpha version of ANTLR was totally rewritten resulting in +1.00B. Version 1.00B was released via an internet newsgroup +(comp.compilers) posting in February of 1990 and quickly gathered a +large following. 1.00B generated only LL(1) parsers, but allowed the +merged description of lexical and syntactic analysis. It had rudimen- +tary attribute handling similar to that of YACC and did not incor- +porate rule parameters or return values; downward inheritance was very +awkward. 1.00B-generated parsers terminated upon the first syntax +error. Lexical classes (modes) were not allowed and DLG did not have +an interactive mode. + + Upon starting his Ph.D. at Purdue in the Fall of 1990, Terence +Parr began the second total rewrite of ANTLR. The method by which +grammars may be practically analyzed to generate LL(k) lookahead +information was discovered in August of 1990 just before his return. +Version 1.00 incorporated this algorithm and included the AST mechan- +ism, lexical classes, error classes, and automatic error recovery; +code quality and portability were higher. In February of 1992 1.00 +was released via an article in SIGPLAN Notices. Peter Dahl, Ph.D. +candidate, and Professor Matt O'Keefe (both at the University of Min- +nesota) tested this version extensively. Dana Hoggatt (Micro Data +Base Systems, Inc.) came up with the idea of error grouping (strings +attached to non-terminals) and tested 1.00 heavily. + + Version 1.06 was released in December 1992 and represented a +large feature enhancement over 1.00. For example, rudimentary seman- +tic predicates were introduced, error messages were significantly +improved for k>1 lookahead and ANTLR parsers could indicate that loo- +kahead fetches were to occur only when necessary for the parse + + + + Page 1 + + PCCTS + + +(normally, the lookahead "pipe" was constantly full). Russell Quong +joined the project in the Spring of 1992 to aid in the semantic predi- +cate design. Beginning and advanced tutorials were created and +released as well. A makefile generator was included that sets up +dependencies and such correctly for ANTLR and DLG. Very few 1.00 +incompatibilities were introduced (1.00 was quite different from 1.00B +in some areas). + + 1.10 was released on August 31, 1993 and incorporated bug fixes, +a few feature enhancements and a major new capability - an arbitrary +lookahead operator (syntactic predicate), (alpha)?beta. This feature +was co-designed with Professor Russell Quong also at Purdue. To sup- +port infinite lookahead, a preprocessor flag, ZZINF_LOOK, was created +that forced the ANTLR() macro to tokenize all input prior to parsing. +Hence, at any moment, an action or predicate can see the entire input +sentence. The predicate mechanism of 1.06 was extended to allow mul- +tiple predicates to be hoisted; the syntactic context of a predicate +was also moved along with the predicate. + + In February of 1994, SORCERER (a simple tree-parser generator) +was released. This tool allows the user to parse child-sibling trees +by specifying a grammar rather than building a recursive-descent tree +walker by hand. Work towards a library of tree transformations is +underway. Aaron Sawdey at The University of Minnesota became a second +author of SORCERER after the initial release. + + On April 1, 1994, PCCTS 1.20 was released. This was the first +version to actively support C++ output. It also included important +fixes regarding semantic predicates and (..)+ subrules. This version +also introduced token classes, the "not" operator, and token ranges. + + On June 19, 1994, SORCERER 1.00B9 was released. Gary Funck of +Intrepid Technology joined the SORCERER team and provided very valu- +able suggestions regarding the "transform" mode of SORCERER. + + On August 8, 1994, PCCTS 1.21 was released. It mainly cleaned up +the C++ output and included a number of bug fixes. + + From the 1.21 release forward, the maintenance and support of all +PCCTS tools will be primarily provided by Parr Research Corporation, +Minneapolis MN---an organization founded on the principles of excel- +lence in research and integrity in business; we are devoted to provid- +ing really cool software tools. Please see file PCCTS.FUTURE for more +information. All PCCTS tools currently in the public domain will con- +tinue to be in the public domain. + + Looking towards the future, a graphical user-interface is in the +design phase. This would allow users to view the syntax diagram +representation of their grammars and would highlight nondeterministic +productions. Parsing can be traced graphically as well. This system +will be built using a multiplatform window library. We also antici- +pate the introduction of a sophisticated error handling mechanism +called "parser exception handling" in a near future release. + + + + + Page 2 + + PCCTS + + + Currently, PCCTS is used at over 1000 known academic, government, +and commercial sites in 37 countries. Of course, the true number of +users is unknown due to the large number of ftp sites. + Credits + +_____________________________________________________________________________ +_____________________________________________________________________________ +|ANTLR 1.00A Terence Parr Hank Dietz | +|ALX Terence Parr Hank Dietz | +|ANTLR 1.00B Terence Parr Hank Dietz, Will Cohen | +|DLG 1.00B Will Cohen Terence Parr, Hank Dietz | +|NFA Relabelling Will Cohen | +|LL(k) analysis Terence Parr Hank Dietz | +|ANTLR 1.00 Terence Parr Hank Dietz, Will Cohen | +|DLG 1.00 Will Cohen Terence Parr, Hank Dietz | +|ANTLR 1.06 Terence Parr Will Cohen, Russell Quong, Hank Dietz| +|DLG 1.06 Will Cohen Terence Parr, Hank Dietz | +|ANTLR 1.10 Terence Parr Will Cohen, Russell Quong | +|ANTLR 1.20 Terence Parr Will Cohen, Russell Quong | +|ANTLR 1.21 Terence Parr Russell Quong | +|DLG 1.10 Will Cohen Terence Parr | +|DLG 1.20 Will Cohen Terence Parr | +|DLG 1.21 Terence Parr | +|Semantic predicates Terence Parr Russell Quonq | +|Syntactic predicates Terence Parr Russell Quonq | +|SORCERER 1.00A Terence Parr | +|SORCERER 1.00B Terence Parr Aaron Sawdey | +|SORCERER 1.00B9 Terence Parr Aaron Sawdey, Gary Funck | +|___________________________________________________________________________| + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Page 3 + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/makefile.old b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/makefile.old new file mode 100644 index 00000000..d8f7f6f7 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/makefile.old @@ -0,0 +1,66 @@ +# +# Main makefile for PCCTS 1.33MR33 /* MRXXX */ +# +# Terence Parr +# Parr Research Corporation +# +# verbosity versus silence... +PSss= +# +# this can be set to /user/local/bin etc... +BINDIR=bin +# This part added by Thomas Herter, M"unchen, Germany. See also manpages +# target. +MANDIR=$(HOME)/man +MANEXT=1 +MANFILES=dlg/dlg.1 antlr/antlr.1 + +#CC=cc +#CC=gcc +#COPT=-O2 + +pccts: + @echo " " + @echo " Welcome to PCCTS 1.33MR33 installation" + @echo " " + @echo " (Version 1.33 Maintenance Release #33)" # mrxxx + @echo " " + @echo " Released 19 April 2002" + @echo " " + @echo " Featuring" + @echo " ANTLR -- ANother Tool for Language Recognition" + @echo " DLG -- DFA-based Lexical Analyzer Generator" + @echo " SORCERER -- Source-to-source translator (tree walker)" + @echo " " + @echo " http://www.antlr.org" + @echo " " + @echo " Trouble reports to tmoog@polhode.com" + @echo " Additional PCCTS 1.33 information at" + @echo " http://www.polhode.com" + @echo + @echo + @echo "To substitute gcc for CC to invoke compiler: make CC=gcc" + @echo "If there are problems with cr and lf try: unzip -a ..." + @echo +# + @if [ ! -d $(BINDIR) ] ; then mkdir $(BINDIR) ; fi + @echo Making executables... + (cd ./antlr; $(MAKE) CC="$(CC)" COPT="$(COPT)") + @echo antlr executable now in $(BINDIR) + (cd ./dlg; $(MAKE) CC="$(CC)" COPT="$(COPT)") + @echo dlg executable now in $(BINDIR) + @echo + @echo " PCCTS 1.33MR33 installation complete" # MRXXX + +clean: + (cd ./antlr; $(MAKE) -s clean) + (cd ./dlg; $(MAKE) -s clean) + + +manpages: + # mkdir -p $(MANDIR)/man$(MANEXT) + if [ ! -d $(MANDIR) ] ; then \ + mkdir $(MANDIR) ; fi + if [ ! -d $(MANDIR)/man$(MANEXT) ] ; then \ + mkdir $(MANDIR)/man$(MANEXT); fi + cp -p $(MANFILES) $(MANDIR)/man$(MANEXT) diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/genmk.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/genmk.c new file mode 100644 index 00000000..800a1121 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/genmk.c @@ -0,0 +1,1063 @@ +/* + * genmk -- a program to make makefiles for PCCTS + * + * ANTLR 1.33MR23 + * Terence John Parr 1989 - 2000 + * Purdue University + * U of MN + */ + +#include +#include +#include "pcctscfg.h" /* be sensitive to what ANTLR/DLG call the files */ + +#ifdef VAXC +#define DIE return 0; +#define DONE return 1; +#else +#define DIE return 1; +#define DONE return 0; +#endif + +#ifndef require +#define require(expr, err) {if ( !(expr) ) fatal(err);} +#endif + +#define MAX_FILES 50 +#define MAX_CFILES 1600 +#define MAX_SFILES 50 +#define MAX_SORS 50 +#define MAX_CLASSES 50 + +char *RENAME_OBJ_FLAG="-o", + *RENAME_EXE_FLAG="-o"; + +char *dlg = "parser.dlg"; +char *err = "err.c"; +char *hdr = "stdpccts.h"; +char *tok = "tokens.h"; +char *mode = "mode.h"; +char *scan = "scan"; + +char ATOKENBUFFER_O[100]; +char APARSER_O[100]; +char ASTBASE_O[100]; +char PCCTSAST_O[100]; +char LIST_O[100]; +char DLEXERBASE_O[100]; + +/* Option flags */ +static char *project="t", *files[MAX_FILES], *classes[MAX_CLASSES]; +static char *cfiles[MAX_CFILES]; +static char *sfiles[MAX_SORS][MAX_SFILES],*sclasses[MAX_SORS]; +static int num_sfiles[MAX_SORS]; /*sorcerer files in group */ +static int num_sors = 0; /*sorcerer groups */ +static int num_files = 0; /* grammar files */ +static int num_cfiles = 0; /* additional C/C++ files */ +static int num_classes = 0; /* ANTLR classes */ +static int user_lexer = 0; +static char *user_token_types = NULL; +static int gen_CPP = 0; +static char *outdir="."; +static char *dlg_class = "DLGLexer"; +static int gen_trees = 0; +static int gen_hoist = 0; +static int nondef_comp = 0; /* 1=compiler is non default */ +static char *compilerCCC="CC"; +static char *compilerCC="cc"; +static char *pccts_path="/usr/local/pccts"; + +#ifdef __STDC__ +void help(void); +void mk(char *project, char **files, int n, int argc, char **argv); +void pfiles(char **files, int n, char *suffix); +void fatal(char *msg); +void warn(char *msg); +#else +void help(); +void mk(); +void pfiles(); +void fatal(); +void warn(); +#endif + +typedef struct _Opt { + char *option; + int arg; +#ifdef __cplusplus + void (*process)(...); +#else + void (*process)(); +#endif + char *descr; + } Opt; + +#ifdef __STDC__ +static void ProcessArgs(int, char **, Opt *); +#else +static void ProcessArgs(); +#endif + +static void +#ifdef __STDC__ +pProj(char *s, char *t ) +#else +pProj( s, t ) +char *s; +char *t; +#endif +{ + project = t; +} + +static void +#ifdef __STDC__ +pUL( char *s ) +#else +pUL( s ) +char *s; +#endif +{ + user_lexer = 1; +} + +static void +#ifdef __STDC__ +pCPP( char *s ) +#else +pCPP( s ) +char *s; +#endif +{ + gen_CPP = 1; +} + +static void +#ifdef __STDC__ +pUT( char *s, char *t ) +#else +pUT( s, t ) +char *s; +char *t; +#endif +{ + user_token_types = t; +} + +static void +#ifdef __STDC__ +pTrees( char *s ) +#else +pTrees( s ) +char *s; +#endif +{ + gen_trees = 1; +} + +static void +#ifdef __STDC__ +pHoist( char *s ) +#else +pHoist( s ) +char *s; +#endif +{ + gen_hoist = 1; +} + +static void +#ifdef __STDC__ +pSor( char *s ) +#else +pSor( s ) +char *s; +#endif +{ + require(num_sors0 ) { + warn("can't define classes w/o C++ mode; turning on C++ mode...\n"); + gen_CPP=1; + } + if (!gen_CPP && num_sors) { + warn("can't define sorcerer group in C mode (yet); turning on C++ mode...\n"); + gen_CPP=1; + } + if ( gen_CPP && num_classes==0 ) { + fatal("must define classes >0 grammar classes in C++ mode\n"); + } + + mk(project, files, num_files, argc, argv); + DONE; +} + +#ifdef __STDC__ +void help(void) +#else +void help() +#endif +{ + Opt *p = options; + static char buf[1000+1]; + + fprintf(stderr, "genmk [options] f1.g ... fn.g\n"); + while ( p->option!=NULL && *(p->option) != '*' ) + { + buf[0]='\0'; + if ( p->arg ) sprintf(buf, "%s ___", p->option); + else strcpy(buf, p->option); + fprintf(stderr, "\t%-16s %s\n", buf, p->descr); + p++; + } +} + +#ifdef __STDC__ +void mk(char *project, char **files, int n, int argc, char **argv) +#else +void mk(project, files, n, argc, argv) +char *project; +char **files; +int n; +int argc; +char **argv; +#endif +{ + int i,j; + + printf("#\n"); + printf("# PCCTS makefile for: "); + pfiles(files, n, NULL); + printf("\n"); + printf("#\n"); + printf("# Created from:"); + for (i=0; i0) { + printf("SOR_H = $(PCCTS)%ssorcerer%sh\n", DirectorySymbol, DirectorySymbol); + printf("SOR_LIB = $(PCCTS)%ssorcerer%slib\n", + DirectorySymbol, DirectorySymbol); + } + printf("BIN = $(PCCTS)%sbin\n", DirectorySymbol); + printf("ANTLR = $(BIN)%santlr\n", DirectorySymbol); + printf("DLG = $(BIN)%sdlg\n", DirectorySymbol); + if (num_sors>0) printf("SOR = $(BIN)%ssor\n", DirectorySymbol); + printf("CFLAGS = -I. -I$(ANTLR_H)"); + if (num_sors>0) printf(" -I$(SOR_H)"); + if ( strcmp(outdir, ".")!=0 ) printf(" -I%s", outdir); + printf(" $(COTHER)"); + printf("\n"); + printf("AFLAGS ="); + if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir); + if ( user_lexer ) printf(" -gx"); + if ( gen_CPP ) printf(" -CC"); + if ( strcmp(hdr,"stdpccts.h")!=0 ) printf(" -gh %s", hdr); + if ( gen_trees ) printf(" -gt"); + if ( gen_hoist ) { + printf(" -mrhoist on") ; + } else { + printf(" -mrhoist off"); + }; + printf(" $(AOTHER)"); + printf("\n"); + printf("DFLAGS = -C2 -i"); + if ( gen_CPP ) printf(" -CC"); + if ( strcmp(dlg_class,"DLGLexer")!=0 ) printf(" -cl %s", dlg_class); + if ( strcmp(outdir,".")!=0 ) printf(" -o %s", outdir); + printf(" $(DOTHER)"); + printf("\n"); + if (num_sors>0) + { + printf("SFLAGS = -CPP"); + if ( strcmp(outdir,".")!=0 ) printf(" -out-dir %s", outdir); + printf(" $(SOTHER)\n"); + } + printf("GRM = "); + pfiles(files, n, NULL); + printf("\n"); + printf("SRC = "); + if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT); + else pfiles(files, n, "c"); + if ( gen_CPP ) { + printf(" \\\n\t"); + pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT); + printf(" \\\n\t"); + printf("$(ANTLR_H)%s%s", DirectorySymbol, APARSER_C); + if ( !user_lexer ) printf(" $(ANTLR_H)%s%s", DirectorySymbol, DLEXERBASE_C); + if ( gen_trees ) { + printf(" \\\n\t"); + printf("$(ANTLR_H)%s%s", DirectorySymbol, ASTBASE_C); + printf(" $(ANTLR_H)%s%s", DirectorySymbol, PCCTSAST_C); +/* printf(" $(ANTLR_H)%s%s", DirectorySymbol, LIST_C); */ + printf(" \\\n\t"); + } + printf(" $(ANTLR_H)%s%s", DirectorySymbol, ATOKENBUFFER_C); + } + if ( !user_lexer ) { + if ( gen_CPP ) printf(" $(SCAN)%s", CPP_FILE_SUFFIX); + else printf(" %s$(SCAN).c", DIR()); + } + if ( !gen_CPP ) printf(" $(ERR).c"); + for (i=0;i0) + printf(" \\\n\t$(SOR_LIB)%sSTreeParser.cpp", DirectorySymbol); + if (num_cfiles>0) + { + printf(" \\\n\t"); + pfiles(cfiles,num_cfiles,NULL); + } + printf("\n\n"); + printf("OBJ = "); + pfiles(files, n, "o"); + if ( gen_CPP ) { + printf(" \\\n\t"); + pclasses(classes, num_classes, "o"); + printf(" \\\n\t"); + printf("%s%s", DIR(), APARSER_O); + if ( !user_lexer ) { + printf(" %s%s", DIR(), DLEXERBASE_O); + } + if ( gen_trees ) { + printf(" \\\n\t"); + printf("%s%s", DIR(), ASTBASE_O); + printf(" %s%s", DIR(), PCCTSAST_O); +/* printf(" %s%s", DIR(), LIST_O); */ + printf(" \\\n\t"); + } + printf(" %s%s", DIR(), ATOKENBUFFER_O); + } + if ( !user_lexer ) { + if ( gen_CPP ) printf(" $(SCAN)%s", OBJ_FILE_SUFFIX); + else printf(" %s$(SCAN)%s", DIR(), OBJ_FILE_SUFFIX); + } + if ( !gen_CPP ) printf(" $(ERR)%s", OBJ_FILE_SUFFIX); + for (i=0;i0) printf(" \\\n\tSTreeParser.o"); + if (num_cfiles>0) + { + printf(" \\\n\t"); + pfiles(cfiles,num_cfiles,"o"); + } + printf("\n\n"); + + printf("ANTLR_SPAWN = "); + if ( gen_CPP ) pfiles(files, n, CPP_FILE_SUFFIX_NO_DOT); + else pfiles(files, n, "c"); + if ( gen_CPP ) { + printf(" "); + pclasses(classes, num_classes, CPP_FILE_SUFFIX_NO_DOT); + printf(" \\\n\t\t"); + pclasses(classes, num_classes, "h"); + if ( strcmp(hdr,"stdpccts.h")!=0 ) { + printf(" \\\n\t\t"); + printf("$(HDR_FILE) stdpccts.h"); + } + } + if ( user_lexer ) { + if ( !user_token_types ) printf(" $(TOKENS)"); + } + else { + printf(" $(DLG_FILE)"); + if ( !user_token_types ) printf(" $(TOKENS)"); + } + if ( !gen_CPP ) printf(" $(ERR).c"); + printf("\n"); + + if ( !user_lexer ) { + if ( gen_CPP ) printf("DLG_SPAWN = $(SCAN)%s", CPP_FILE_SUFFIX); + else printf("DLG_SPAWN = %s$(SCAN).c", DIR()); + if ( gen_CPP ) printf(" $(SCAN).h"); + if ( !gen_CPP ) printf(" $(MOD_FILE)"); + printf("\n"); + } + + if ( gen_CPP ) { + if ( !nondef_comp ) + printf("ifdef CXX\nCCC = $(CXX)\nendif\n\nifndef CCC\n"); + printf("CCC = %s\n",compilerCCC); + if ( !nondef_comp ) printf("endif\n\n"); + } + else + { + if ( !nondef_comp ) printf("ifndef CC\n"); + printf("CC = %s\n",compilerCC); + if ( !nondef_comp ) printf("endif\n\n"); + } + + /* set up dependencies */ + printf("\n%s : $(SRC) $(OBJ)\n", project); + printf("\t%s %s %s $(CFLAGS) $(OBJ)\n", + gen_CPP?"$(CCC)":"$(CC)", + RENAME_EXE_FLAG, + project); + printf("\n"); + + /* implicit rules */ + +/* if(gen_CPP) + printf("%%.o : %%.cpp\n\t$(CCC) -c $(CFLAGS) $<\n\n"); + + printf("%%.o : %%.c\n\t%s -c $(CFLAGS) $<\n\n", + gen_CPP?"$(CCC)":"$(CC)"); +*/ + /* how to compile parser files */ + + for (i=0; i0) + { + printf("STreeParser%s : $(SOR_LIB)%sSTreeParser.cpp\n", + OBJ_FILE_SUFFIX,DirectorySymbol); + printf("\t%s -c $(CFLAGS) %s ", + gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG); + printf("STreeParser%s ",OBJ_FILE_SUFFIX); + printf("$(SOR_LIB)%sSTreeParser.cpp\n\n",DirectorySymbol); + } + + printf("$(ANTLR_SPAWN) : $(GRM)\n"); + printf("\t$(ANTLR) $(AFLAGS) $(GRM)\n"); + + if ( !user_lexer ) + { + printf("\n"); + printf("$(DLG_SPAWN) : $(DLG_FILE)\n"); + if ( gen_CPP ) printf("\t$(DLG) $(DFLAGS) $(DLG_FILE)\n"); + else printf("\t$(DLG) $(DFLAGS) $(DLG_FILE) $(SCAN).c\n"); + } + + /* do the makes for ANTLR/DLG support */ + if ( gen_CPP ) { + printf("\n"); + printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C); + printf("\t%s -c $(CFLAGS) %s ", + gen_CPP?"$(CCC)":"$(CC)", + RENAME_OBJ_FLAG); + printf("%s%s $(ANTLR_H)%s%s\n", DIR(), APARSER_O, DirectorySymbol, APARSER_C); + printf("\n"); + printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C); + printf("\t%s -c $(CFLAGS) %s ", + gen_CPP?"$(CCC)":"$(CC)", + RENAME_OBJ_FLAG); + printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ATOKENBUFFER_O, DirectorySymbol, ATOKENBUFFER_C); + if ( !user_lexer ) { + printf("\n"); + printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C); + printf("\t%s -c $(CFLAGS) %s ", + gen_CPP?"$(CCC)":"$(CC)", + RENAME_OBJ_FLAG); + printf("%s%s $(ANTLR_H)%s%s\n", DIR(), DLEXERBASE_O, DirectorySymbol, DLEXERBASE_C); + } + if ( gen_trees ) { + printf("\n"); + printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C); + printf("\t%s -c $(CFLAGS) %s ", + gen_CPP?"$(CCC)":"$(CC)", + RENAME_OBJ_FLAG); + printf("%s%s $(ANTLR_H)%s%s\n", DIR(), ASTBASE_O, DirectorySymbol, ASTBASE_C); + printf("\n"); + printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C); + printf("\t%s -c $(CFLAGS) %s ", + gen_CPP?"$(CCC)":"$(CC)", + RENAME_OBJ_FLAG); + printf("%s%s $(ANTLR_H)%s%s\n", DIR(), PCCTSAST_O, DirectorySymbol, PCCTSAST_C); + printf("\n"); +/* + printf("%s%s : $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C); + printf("\t%s -c $(CFLAGS) %s ", + gen_CPP?"$(CCC)":"$(CC)",RENAME_OBJ_FLAG); + printf("%s%s $(ANTLR_H)%s%s\n", DIR(), LIST_O, DirectorySymbol, LIST_C); +*/ + } + } + + /* clean and scrub targets */ + + printf("\nclean:\n"); + printf("\trm -f *%s core %s", OBJ_FILE_SUFFIX, project); + if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX); + printf("\n"); + + printf("\nscrub: clean\n"); +/* printf("\trm -f *%s core %s", OBJ_FILE_SUFFIX, project); */ +/* if ( strcmp(outdir, ".")!=0 ) printf(" %s*%s", DIR(), OBJ_FILE_SUFFIX); */ + printf("\trm -f $(ANTLR_SPAWN)"); + if ( !user_lexer ) printf(" $(DLG_SPAWN)"); + for (i=0;i0 ) + { + char *p = &(*files)[strlen(*files)-1]; + if ( !first ) putchar(' '); + first=0; + while ( p > *files && *p != '.' ) --p; + if ( p == *files ) + { + fprintf(stderr, + "genmk: filenames must be file.suffix format: %s\n", + *files); + exit(-1); + } + if ( suffix == NULL ) printf("%s", *files); + else + { + *p = '\0'; + printf("%s", DIR()); + if ( strcmp(suffix, "o")==0 ) printf("%s%s", *files, OBJ_FILE_SUFFIX); + else printf("%s.%s", *files, suffix); + *p = '.'; + } + files++; + --n; + } +} + +#ifdef __STDC__ +pclasses(char **classes, int n, char *suffix) +#else +pclasses(classes, n, suffix) +char **classes; +int n; +char *suffix; +#endif +{ + int first=1; + + while ( n>0 ) + { + if ( !first ) putchar(' '); + first=0; + if ( suffix == NULL ) printf("%s", *classes); + else { + printf("%s", DIR()); + if ( strcmp(suffix, "o")==0 ) printf("%s%s", *classes, OBJ_FILE_SUFFIX); + else printf("%s.%s", *classes, suffix); + } + classes++; + --n; + } +} + +static void +#ifdef __STDC__ +ProcessArgs( int argc, char **argv, Opt *options ) +#else +ProcessArgs( argc, argv, options ) +int argc; +char **argv; +Opt *options; +#endif +{ + Opt *p; + require(argv!=NULL, "ProcessArgs: command line NULL"); + + while ( argc-- > 0 ) + { + p = options; + while ( p->option != NULL ) + { + if ( strcmp(p->option, "*") == 0 || + strcmp(p->option, *argv) == 0 ) + { + if ( p->arg ) + { + (*p->process)( *argv, *(argv+1) ); + argv++; + argc--; + } + else + (*p->process)( *argv ); + break; + } + p++; + } + argv++; + } +} + +#ifdef __STDC__ +void fatal( char *err_) +#else +void fatal( err_) +char *err_; +#endif +{ + fprintf(stderr, "genmk: %s\n", err_); + exit(1); +} + +#ifdef __STDC__ +void warn( char *err_) +#else +void warn( err_) +char *err_; +#endif +{ + fprintf(stderr, "genmk: %s\n", err_); +} + +#ifdef __STDC__ +char *DIR(void) +#else +char *DIR() +#endif +{ + static char buf[200+1]; + + if ( strcmp(outdir,TopDirectory)==0 ) return ""; + sprintf(buf, "%s%s", outdir, DirectorySymbol); + return buf; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/genmk_old.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/genmk_old.c new file mode 100644 index 00000000..19858cb6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/genmk_old.c @@ -0,0 +1,762 @@ +/* + * genmk -- a program to make makefiles for PCCTS + * + * ANTLR 1.33MR10 + * Terence John Parr 1989 - 1998 + * Purdue University + * U of MN + */ + +#include +#include "pcctscfg.h" /* be sensitive to what ANTLR/DLG call the files */ + +#ifdef VAXC +#define DIE return 0; +#define DONE return 1; +#else +#define DIE return 1; +#define DONE return 0; +#endif + +#ifndef require +#define require(expr, err) {if ( !(expr) ) fatal(err);} +#endif + +#define MAX_FILES 50 +#define MAX_CLASSES 50 + +char *RENAME_OBJ_FLAG="-o", + *RENAME_EXE_FLAG="-o"; + +char *dlg = "parser.dlg"; +char *err = "err.c"; +char *hdr = "stdpccts.h"; +char *tok = "tokens.h"; +char *mode = "mode.h"; +char *scan = "scan"; + +char ATOKENBUFFER_O[100]; +char APARSER_O[100]; +char ASTBASE_O[100]; +char PCCTSAST_O[100]; +char LIST_O[100]; +char DLEXERBASE_O[100]; + +/* Option flags */ +static char *project="t", *files[MAX_FILES], *classes[MAX_CLASSES]; +static int num_files = 0; +static int num_classes = 0; +static int user_lexer = 0; +static char *user_token_types = NULL; +static int gen_CPP = 0; +static char *outdir="."; +static char *dlg_class = "DLGLexer"; +static int gen_trees = 0; +static int gen_hoist = 0; +static char cfiles[1600]=""; +static char *compilerCCC="CC"; +static char *compilerCC="cc"; +static char *pccts_path="/usr/local/pccts"; + +void help(); +void mk(); +void pfiles(); +void pclasses(); +void fatal(); +void warn(); + +typedef struct _Opt { + char *option; + int arg; +#ifdef __cplusplus + void (*process)(...); +#else + void (*process)(); +#endif + char *descr; + } Opt; + +#ifdef __STDC__ +static void ProcessArgs(int, char **, Opt *); +#else +static void ProcessArgs(); +#endif + +static void +pProj( s, t ) +char *s; +char *t; +{ + project = t; +} + +static void +pUL( s ) +char *s; +{ + user_lexer = 1; +} + +static void +pCPP( s ) +char *s; +{ + gen_CPP = 1; +} + +static void +pUT( s, t ) +char *s; +char *t; +{ + user_token_types = t; +} + +static void +pTrees( s ) +char *s; +{ + gen_trees = 1; +} + +static void +pHoist( s ) +char *s; +{ + gen_hoist = 1; +} + +static void +#ifdef __STDC__ +pFile( char *s ) +#else +pFile( s ) +char *s; +#endif +{ + if ( *s=='-' ) + { + fprintf(stderr, "invalid option: '%s'; ignored...",s); + return; + } + + require(num_files0 ) { + warn("can't define classes w/o C++ mode; turning on C++ mode...\n"); + gen_CPP=1; + } + if ( gen_CPP && num_classes==0 ) { + fatal("must define classes >0 grammar classes in C++ mode\n"); + } + + mk(project, files, num_files, argc, argv); + DONE; +} + +void help() +{ + Opt *p = options; + static char buf[1000+1]; + + fprintf(stderr, "genmk [options] f1.g ... fn.g\n"); + while ( p->option!=NULL && *(p->option) != '*' ) + { + buf[0]='\0'; + if ( p->arg ) sprintf(buf, "%s ___", p->option); + else strcpy(buf, p->option); + fprintf(stderr, "\t%-16s %s\n", buf, p->descr); + p++; + } +} + +void mk(project, files, n, argc, argv) +char *project; +char **files; +int n; +int argc; +char **argv; +{ + int i; + + printf("#\n"); + printf("# PCCTS makefile for: "); + pfiles(files, n, NULL); + printf("\n"); + printf("#\n"); + printf("# Created from:"); + for (i=0; i0 ) + { + char *p = &(*files)[strlen(*files)-1]; + if ( !first ) putchar(' '); + first=0; + while ( p > *files && *p != '.' ) --p; + if ( p == *files ) + { + fprintf(stderr, + "genmk: filenames must be file.suffix format: %s\n", + *files); + exit(-1); + } + if ( suffix == NULL ) printf("%s", *files); + else + { + *p = '\0'; + printf("%s", DIR()); + if ( strcmp(suffix, "o")==0 ) printf("%s%s", *files, OBJ_FILE_SUFFIX); + else printf("%s.%s", *files, suffix); + *p = '.'; + } + files++; + --n; + } +} + +void pclasses(classes, n, suffix) +char **classes; +int n; +char *suffix; +{ + int first=1; + + while ( n>0 ) + { + if ( !first ) putchar(' '); + first=0; + if ( suffix == NULL ) printf("%s", *classes); + else { + printf("%s", DIR()); + if ( strcmp(suffix, "o")==0 ) printf("%s%s", *classes, OBJ_FILE_SUFFIX); + else printf("%s.%s", *classes, suffix); + } + classes++; + --n; + } +} + +static void +#ifdef __STDC__ +ProcessArgs( int argc, char **argv, Opt *options ) +#else +ProcessArgs( argc, argv, options ) +int argc; +char **argv; +Opt *options; +#endif +{ + Opt *p; + require(argv!=NULL, "ProcessArgs: command line NULL"); + + while ( argc-- > 0 ) + { + p = options; + while ( p->option != NULL ) + { + if ( strcmp(p->option, "*") == 0 || + strcmp(p->option, *argv) == 0 ) + { + if ( p->arg ) + { + (*p->process)( *argv, *(argv+1) ); + argv++; + argc--; + } + else + (*p->process)( *argv ); + break; + } + p++; + } + argv++; + } +} + +void fatal( err_) +char *err_; +{ + fprintf(stderr, "genmk: %s\n", err_); + exit(1); +} + +void warn( err_) +char *err_; +{ + fprintf(stderr, "genmk: %s\n", err_); +} + +char *DIR() +{ + static char buf[200+1]; + + if ( strcmp(outdir,TopDirectory)==0 ) return ""; + sprintf(buf, "%s%s", outdir, DirectorySymbol); + return buf; +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/makefile new file mode 100644 index 00000000..1631f74a --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/genmk/makefile @@ -0,0 +1,29 @@ +## +## 7-Apr-97 +## added support/genmk/makefile to pccts 1.33MR1 distribution kit +## (support/genmk/makefile" omitted from 1.33 distribution kit) +## +SRC=genmk.c +OBJ=genmk.o +# Define PC if you use a PC OS (changes directory symbol and object file extension) +# see pccts/h/pcctscfg.h +CC=cc +COPT=-O +#CFLAGS=-I../../h -DPC +CFLAGS=$(COPT) -I../../h +BAG=../../bin/bag + +genmk: $(OBJ) $(SRC) ../../h/pcctscfg.h + $(CC) -o genmk $(OBJ) + +clean: + rm -rf core *.o + +scrub: + rm -rf genmk core *.o + +shar: + shar genmk.c makefile > genmk.shar + +archive: + $(BAG) genmk.c makefile > genmk.bag diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/makefile new file mode 100644 index 00000000..c0f343e0 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/makefile @@ -0,0 +1,19 @@ +BAG=../../bin/bag +SRC=test.c rexpr.c +OBJ=test.o rexpr.o +CFLAGS = -g + +test: $(OBJ) $(SRC) + cc -g -o texpr $(OBJ) + +shar: + shar makefile test.c rexpr.c rexpr.h > rexpr.shar + +archive: + $(BAG) makefile test.c rexpr.c rexpr.h > rexpr.bag + +clean: + rm -rf *.o core texpr + +scrub: + rm -rf *.o core texpr diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/rexpr.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/rexpr.c new file mode 100644 index 00000000..9d284b77 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/rexpr.c @@ -0,0 +1,586 @@ +/* + * This file contains code for + * + * int rexpr(char *expr, char *s); + * + * which answers + * + * 1 if 's' is in the language described by the regular expression 'expr' + * 0 if it is not + * -1 if the regular expression is invalid + * + * Language membership is determined by constructing a non-deterministic + * finite automata (NFA) from the regular expression. A depth- + * first-search is performed on the NFA (graph) to check for a match of 's'. + * Each non-epsilon arc consumes one character from 's'. Backtracking is + * performed to check all possible paths through the NFA. + * + * Regular expressions follow the meta-language: + * + * ::= ( '|' )* + * + * ::= ( )* + * + * ::= {'~'} '[' ']' + * | '(' ')' + * | '{' '}' + * | + * + * ::= { '*' | '+' } + * + * ::= ( )* + * | { } '-' { } + * + * ::= Token[Atom] + * + * Notes: + * ~ means complement the set in [..]. i.e. all characters not listed + * * means match 0 or more times (can be on expression or atom) + * + means match 1 or more times (can be on expression or atom) + * {} optional + * () grouping + * [] set of atoms + * x-y all characters from x to y (found only in [..]) + * \xx the character with value xx + * + * Examples: + * [a-z]+ + * match 1 or more lower-case letters (e.g. variable) + * + * 0x[0-9A-Fa-f]+ + * match a hex number with 0x on front (e.g. 0xA1FF) + * + * [0-9]+.[0-9]+{e[0-9]+} + * match a floating point number (e.g. 3.14e21) + * + * Code example: + * if ( rexpr("[a-zA-Z][a-zA-Z0-9]+", str) ) then str is keyword + * + * Terence Parr + * Purdue University + * April 1991 + */ + +#include +#include +#ifdef __STDC__ +#include +#else +#include +#endif +#include "rexpr.h" + +#ifdef __USE_PROTOS +static int regExpr( GraphPtr g ); +static int andExpr( GraphPtr g ); +static int expr( GraphPtr g ); +static int repeatSymbol( GraphPtr g ); +static int atomList( char *p, int complement ); +static void next( void ); +static ArcPtr newGraphArc( void ); +static NodePtr newNode( void ); +static int ArcBetweenGraphNode( NodePtr i, NodePtr j, int label ); +static Graph BuildNFA_atom( int label ); +static Graph BuildNFA_AB( Graph A, Graph B ); +static Graph BuildNFA_AorB( Graph A, Graph B ); +static Graph BuildNFA_set( char *s ); +static Graph BuildNFA_Astar( Graph A ); +static Graph BuildNFA_Aplus( Graph A ); +static Graph BuildNFA_Aoptional( Graph A ); +#else +static int regExpr(); +static int andExpr(); +static int expr(); +static int repeatSymbol(); +static int atomList(); +static void next(); +static ArcPtr newGraphArc(); +static NodePtr newNode(); +static int ArcBetweenGraphNode(); +static Graph BuildNFA_atom(); +static Graph BuildNFA_AB(); +static Graph BuildNFA_AorB(); +static Graph BuildNFA_set(); +static Graph BuildNFA_Astar(); +static Graph BuildNFA_Aplus(); +static Graph BuildNFA_Aoptional(); +#endif + +static char *_c; +static int token, tokchar; +static NodePtr accept; +static NodePtr freelist = NULL; + +/* + * return 1 if s in language described by expr + * 0 if s is not + * -1 if expr is an invalid regular expression + */ +#ifdef __USE_PROTOS +static int rexpr(char *expr,char *s) +#else +static int rexpr(expr, s) +char *expr, *s; +#endif +{ + NodePtr p,q; + Graph nfa; + int result; + + fprintf(stderr, "rexpr(%s,%s);\n", expr,s); + freelist = NULL; + _c = expr; + next(); + if ( regExpr(&nfa) == -1 ) return -1; + accept = nfa.right; + result = match(nfa.left, s); + /* free all your memory */ + p = q = freelist; + while ( p!=NULL ) { q = p->track; free(p); p = q; } + return result; +} + +/* + * do a depth-first-search on the NFA looking for a path from start to + * accept state labelled with the characters of 's'. + */ + +#ifdef __USE_PROTOS +static int match(NodePtr automaton,char *s) +#else +static int match(automaton, s) +NodePtr automaton; +char *s; +#endif +{ + ArcPtr p; + + if ( automaton == accept && *s == '\0' ) return 1; /* match */ + + for (p=automaton->arcs; p!=NULL; p=p->next) /* try all arcs */ + { + if ( p->label == Epsilon ) + { + if ( match(p->target, s) ) return 1; + } + else if ( p->label == *s ) + if ( match(p->target, s+1) ) return 1; + } + return 0; +} + +/* + * ::= ( '|' {} )* + * + * Return -1 if syntax error + * Return 0 if none found + * Return 1 if a regExrp was found + */ + +#ifdef __USE_PROTOS +static int regExpr(GraphPtr g) +#else +static int regExpr(g) +GraphPtr g; +#endif +{ + Graph g1, g2; + + if ( andExpr(&g1) == -1 ) + { + return -1; + } + + while ( token == '|' ) + { + int a; + next(); + a = andExpr(&g2); + if ( a == -1 ) return -1; /* syntax error below */ + else if ( !a ) return 1; /* empty alternative */ + g1 = BuildNFA_AorB(g1, g2); + } + + if ( token!='\0' ) return -1; + + *g = g1; + return 1; +} + +/* + * ::= ( )* + */ + +#ifdef __USE_PROTOS +static int andExpr(GraphPtr g) +#else +static int andExpr(g) +GraphPtr g; +#endif +{ + Graph g1, g2; + + if ( expr(&g1) == -1 ) + { + return -1; + } + + while ( token==Atom || token=='{' || token=='(' || token=='~' || token=='[' ) + { + if (expr(&g2) == -1) return -1; + g1 = BuildNFA_AB(g1, g2); + } + + *g = g1; + return 1; +} + +/* + * ::= {'~'} '[' ']' + * | '(' ')' + * | '{' '}' + * | + */ + +#ifdef __USE_PROTOS +static int expr(GraphPtr g) +#else +static int expr(g) +GraphPtr g; +#endif +{ + int complement = 0; + char s[257]; /* alloc space for string of char in [] */ + + if ( token == '~' || token == '[' ) + { + if ( token == '~' ) {complement = 1; next();} + if ( token != '[' ) return -1; + next(); + if ( atomList( s, complement ) == -1 ) return -1; + *g = BuildNFA_set( s ); + if ( token != ']' ) return -1; + next(); + repeatSymbol( g ); + return 1; + } + if ( token == '(' ) + { + next(); + if ( regExpr( g ) == -1 ) return -1; + if ( token != ')' ) return -1; + next(); + repeatSymbol( g ); + return 1; + } + if ( token == '{' ) + { + next(); + if ( regExpr( g ) == -1 ) return -1; + if ( token != '}' ) return -1; + next(); + /* S p e c i a l C a s e O p t i o n a l { } */ + if ( token != '*' && token != '+' ) + { + *g = BuildNFA_Aoptional( *g ); + } + repeatSymbol( g ); + return 1; + } + if ( token == Atom ) + { + *g = BuildNFA_atom( tokchar ); + next(); + repeatSymbol( g ); + return 1; + } + + return -1; +} + +/* + * ::= { '*' | '+' } + */ +#ifdef __USE_PROTOS +static int repeatSymbol(GraphPtr g) +#else +static int repeatSymbol(g) +GraphPtr g; +#endif +{ + switch ( token ) + { + case '*' : *g = BuildNFA_Astar( *g ); next(); break; + case '+' : *g = BuildNFA_Aplus( *g ); next(); break; + } + return 1; +} + +/* + * ::= { }* + * { } '-' { } + * + * a-b is same as ab + * q-a is same as q + */ + +#ifdef __USE_PROTOS +static int atomList(char *p, int complement) +#else +static int atomList(p, complement) +char *p; +int complement; +#endif +{ + static unsigned char set[256]; /* no duplicates */ + int first, last, i; + char *s = p; + + if ( token != Atom ) return -1; + + for (i=0; i<256; i++) set[i] = 0; + while ( token == Atom ) + { + if ( !set[tokchar] ) *s++ = tokchar; + set[tokchar] = 1; /* Add atom to set */ + next(); + if ( token == '-' ) /* have we found '-' */ + { + first = *(s-1); /* Get last char */ + next(); + if ( token != Atom ) return -1; + else + { + last = tokchar; + } + for (i = first+1; i <= last; i++) + { + if ( !set[tokchar] ) *s++ = i; + set[i] = 1; /* Add atom to set */ + } + next(); + } + } + *s = '\0'; + if ( complement ) + { + for (i=0; i<256; i++) set[i] = !set[i]; + for (i=1,s=p; i<256; i++) if ( set[i] ) *s++ = i; + *s = '\0'; + } + return 1; +} + +/* a somewhat stupid lexical analyzer */ + +#ifdef __USE_PROTOS +static void next(void) +#else +static void next() +#endif +{ + while ( *_c==' ' || *_c=='\t' || *_c=='\n' ) _c++; + if ( *_c=='\\' ) + { + _c++; + if ( isdigit(*_c) ) + { + int n=0; + while ( isdigit(*_c) ) + { + n = n*10 + (*_c++ - '0'); + } + if ( n>255 ) n=255; + tokchar = n; + } + else + { + switch (*_c) + { + case 'n' : tokchar = '\n'; break; + case 't' : tokchar = '\t'; break; + case 'r' : tokchar = '\r'; break; + default : tokchar = *_c; + } + _c++; + } + token = Atom; + } + else if ( isgraph(*_c) && *_c!='[' && *_c!='(' && *_c!='{' && + *_c!='-' && *_c!='}' && *_c!=')' && *_c!=']' && + *_c!='+' && *_c!='*' && *_c!='~' && *_c!='|' ) + { + token = Atom; + tokchar = *_c++; + } + else + { + token = tokchar = *_c++; + } +} + +/* N F A B u i l d i n g R o u t i n e s */ + +#ifdef __USE_PROTOS +static ArcPtr newGraphArc(void) +#else +static ArcPtr newGraphArc() +#endif +{ + ArcPtr p; + p = (ArcPtr) calloc(1, sizeof(Arc)); + if ( p==NULL ) {fprintf(stderr,"rexpr: out of memory\n"); exit(-1);} + if ( freelist != NULL ) p->track = (ArcPtr) freelist; + freelist = (NodePtr) p; + return p; +} + +#ifdef __USE_PROTOS +static NodePtr newNode(void) +#else +static NodePtr newNode() +#endif +{ + NodePtr p; + p = (NodePtr) calloc(1, sizeof(Node)); + if ( p==NULL ) {fprintf(stderr,"rexpr: out of memory\n"); exit(-1);} + if ( freelist != NULL ) p->track = freelist; + freelist = p; + return p; +} + +#ifdef __USE_PROTOS +static void ArcBetweenGraphNodes(NodePtr i,NodePtr j,int label) +#else +static void ArcBetweenGraphNodes(i, j, label) +NodePtr i, j; +int label; +#endif +{ + ArcPtr a; + + a = newGraphArc(); + if ( i->arcs == NULL ) i->arctail = i->arcs = a; + else {(i->arctail)->next = a; i->arctail = a;} + a->label = label; + a->target = j; +} + +#ifdef __USE_PROTOS +static Graph BuildNFA_atom(int label) +#else +static Graph BuildNFA_atom(label) +int label; +#endif +{ + Graph g; + + g.left = newNode(); + g.right = newNode(); + ArcBetweenGraphNodes(g.left, g.right, label); + return( g ); +} + +#ifdef __USE_PROTOS +static Graph BuildNFA_AB(Graph A,Graph B) +#else +static Graph BuildNFA_AB(A, B) +Graph A, B; +#endif +{ + Graph g; + + ArcBetweenGraphNodes(A.right, B.left, Epsilon); + g.left = A.left; + g.right = B.right; + return( g ); +} + +#ifdef __USE_PROTOS +static Graph BuildNFA_AorB(Graph A,Graph B) +#else +static Graph BuildNFA_AorB(A, B) +Graph A, B; +#endif +{ + Graph g; + + g.left = newNode(); + ArcBetweenGraphNodes(g.left, A.left, Epsilon); + ArcBetweenGraphNodes(g.left, B.left, Epsilon); + g.right = newNode(); + ArcBetweenGraphNodes(A.right, g.right, Epsilon); + ArcBetweenGraphNodes(B.right, g.right, Epsilon); + return( g ); +} + +#ifdef __USE_PROTOS +static Graph BuildNFA_set(char *s) +#else +static Graph BuildNFA_set( s ) +char *s; +#endif +{ + Graph g; + + if ( s == NULL ) return g; + + g.left = newNode(); + g.right = newNode(); + while ( *s != '\0' ) + { + ArcBetweenGraphNodes(g.left, g.right, *s++); + } + return g; +} + +#ifdef __USE_PROTOS +static Graph BuildNFA_Astar(Graph A) +#else +static Graph BuildNFA_Astar( A ) +Graph A; +#endif +{ + Graph g; + + g.left = newNode(); + g.right = newNode(); + + ArcBetweenGraphNodes(g.left, A.left, Epsilon); + ArcBetweenGraphNodes(g.left, g.right, Epsilon); + ArcBetweenGraphNodes(A.right, g.right, Epsilon); + ArcBetweenGraphNodes(A.right, A.left, Epsilon); + + return( g ); +} + +#ifdef __USE_PROTOS +static Graph BuildNFA_Aplus(Graph A) +#else +static Graph BuildNFA_Aplus( A ) +Graph A; +#endif +{ + ArcBetweenGraphNodes(A.right, A.left, Epsilon); + + return( A ); +} + +#ifdef __USE_PROTOS +static Graph BuildNFA_Aoptional(Graph A) +#else +static Graph BuildNFA_Aoptional( A ) +Graph A; +#endif +{ + Graph g; + + g.left = newNode(); + g.right = newNode(); + + ArcBetweenGraphNodes(g.left, A.left, Epsilon); + ArcBetweenGraphNodes(g.left, g.right, Epsilon); + ArcBetweenGraphNodes(A.right, g.right, Epsilon); + + return( g ); +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/rexpr.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/rexpr.h new file mode 100644 index 00000000..4507330d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/rexpr.h @@ -0,0 +1,30 @@ +#define Atom 256 /* token Atom (an impossible char value) */ +#define Epsilon 257 /* epsilon arc (an impossible char value) */ + +/* track field must be same for all node types */ +typedef struct _a { + struct _a *track; /* track mem allocation */ + int label; + struct _a *next; + struct _n *target; + } Arc, *ArcPtr; + +typedef struct _n { + struct _n *track; + ArcPtr arcs, arctail; + } Node, *NodePtr; + +typedef struct { + NodePtr left, + right; + } Graph, *GraphPtr; + +#ifdef __USE_PROTOS +int rexpr( char *expr, char *s ); +int match( NodePtr automaton, char *s ); +#else +int rexpr(); +int match(); +#endif + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/test.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/test.c new file mode 100644 index 00000000..e159cc41 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/rexpr/test.c @@ -0,0 +1,19 @@ +#include +#include "rexpr.h" + +/* + * test for rexpr(). + * To make this test: + * cc -o rexpr test.c rexpr.c + * Then from command line type: + * rexpr r string + * where r is the regular expression that decribes a language + * and string is the string to verify. + */ +main(argc,argv) +int argc; +char *argv[]; +{ + if ( argc!=3 ) fprintf(stderr,"rexpr: expr s\n"); + else printf("%d\n", rexpr(argv[1], argv[2])); +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/set/set.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/set/set.c new file mode 100644 index 00000000..b90005a8 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/set/set.c @@ -0,0 +1,816 @@ +/* set.c + + The following is a general-purpose set library originally developed + by Hank Dietz and enhanced by Terence Parr to allow dynamic sets. + + Sets are now structs containing the #words in the set and + a pointer to the actual set words. + + Generally, sets need not be explicitly allocated. They are + created/extended/shrunk when appropriate (e.g. in set_of()). + HOWEVER, sets need to be destroyed (free()ed) when they go out of scope + or are otherwise no longer needed. A routine is provided to + free a set. + + Sets can be explicitly created with set_new(s, max_elem). + + Sets can be declared to have minimum size to reduce realloc traffic. + Default minimum size = 1. + + Sets can be explicitly initialized to have no elements (set.n == 0) + by using the 'empty' initializer: + + Examples: + set a = empty; -- set_deg(a) == 0 + + return( empty ); + + Example set creation and destruction: + + set + set_of2(e,g) + unsigned e,g; + { + set a,b,c; + + b = set_of(e); -- Creates space for b and sticks in e + set_new(c, g); -- set_new(); set_orel() ==> set_of() + set_orel(g, &c); + a = set_or(b, c); + . + . + . + set_free(b); + set_free(c); + return( a ); + } + + 1987 by Hank Dietz + + Modified by: + Terence Parr + Purdue University + October 1989 + + Made it smell less bad to C++ 7/31/93 -- TJP +*/ + +#include +#include "pcctscfg.h" +#ifdef __STDC__ +#include +#else +#include +#endif +#include + +#include "set.h" + +#define MIN(i,j) ( (i) > (j) ? (j) : (i)) +#define MAX(i,j) ( (i) < (j) ? (j) : (i)) + +/* elems can be a maximum of 32 bits */ +static unsigned bitmask[] = { + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x00000100, 0x00000200, 0x00000400, 0x00000800, + 0x00001000, 0x00002000, 0x00004000, 0x00008000, +#if !defined(PC) || defined(PC32) + 0x00010000, 0x00020000, 0x00040000, 0x00080000, + 0x00100000, 0x00200000, 0x00400000, 0x00800000, + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000 +#endif +}; + +set empty = set_init; +static unsigned min=1; + +#define StrSize 200 + +#ifdef MEMCHK +#define CHK(a) \ + if ( a.setword != NULL ) \ + if ( !valid(a.setword) ) \ + {fprintf(stderr, "%s(%d): invalid set\n",__FILE__,__LINE__); exit(-1);} +#else +#define CHK(a) +#endif + +/* + * Set the minimum size (in words) of a set to reduce realloc calls + */ +void +#ifdef __USE_PROTOS +set_size( unsigned n ) +#else +set_size( n ) +unsigned n; +#endif +{ + min = n; +} + +unsigned int +#ifdef __USE_PROTOS +set_deg( set a ) +#else +set_deg( a ) +set a; +#endif +{ + /* Fast compute degree of a set... the number + of elements present in the set. Assumes + that all word bits are used in the set + and that SETSIZE(a) is a multiple of WORDSIZE. + */ + register unsigned *p = &(a.setword[0]); + register unsigned *endp = NULL; /* MR27 Avoid false memory check report */ + register unsigned degree = 0; + + CHK(a); + if ( a.n == 0 ) return(0); + endp = &(a.setword[a.n]); + while ( p < endp ) + { + register unsigned t = *p; + register unsigned *b = &(bitmask[0]); + do { + if (t & *b) ++degree; + } while (++b < &(bitmask[WORDSIZE])); + p++; + } + + return(degree); +} + +set +#ifdef __USE_PROTOS +set_or( set b, set c ) +#else +set_or( b, c ) +set b; +set c; +#endif +{ + /* Fast set union operation */ + /* resultant set size is max(b, c); */ + set *big; + set t; + unsigned int m,n; + register unsigned *r, *p, *q, *endp; + + CHK(b); CHK(c); + t = empty; + if (b.n > c.n) {big= &b; m=b.n; n=c.n;} else {big= &c; m=c.n; n=b.n;} + set_ext(&t, m); + r = t.setword; + + /* Or b,c until max of smaller set */ + q = c.setword; + p = b.setword; + endp = &(b.setword[n]); + while ( p < endp ) *r++ = *p++ | *q++; + + /* Copy rest of bigger set into result */ + p = &(big->setword[n]); + endp = &(big->setword[m]); + while ( p < endp ) *r++ = *p++; + + return(t); +} + +set +#ifdef __USE_PROTOS +set_and( set b, set c ) +#else +set_and( b, c ) +set b; +set c; +#endif +{ + /* Fast set intersection operation */ + /* resultant set size is min(b, c); */ + set t; + unsigned int n; + register unsigned *r, *p, *q, *endp; + + CHK(b); CHK(c); + t = empty; + n = (b.n > c.n) ? c.n : b.n; + if ( n == 0 ) return t; /* TJP 4-27-92 fixed for empty set */ + set_ext(&t, n); + r = t.setword; + + /* & b,c until max of smaller set */ + q = c.setword; + p = b.setword; + endp = &(b.setword[n]); + while ( p < endp ) *r++ = *p++ & *q++; + + return(t); +} + +set +#ifdef __USE_PROTOS +set_dif( set b, set c ) +#else +set_dif( b, c ) +set b; +set c; +#endif +{ + /* Fast set difference operation b - c */ + /* resultant set size is size(b) */ + set t; + unsigned int n; + register unsigned *r, *p, *q, *endp; + + CHK(b); CHK(c); + t = empty; + n = (b.n <= c.n) ? b.n : c.n ; + if ( b.n == 0 ) return t; /* TJP 4-27-92 fixed for empty set */ + /* WEC 12-1-92 fixed for c.n = 0 */ + set_ext(&t, b.n); + r = t.setword; + + /* Dif b,c until smaller set size */ + q = c.setword; + p = b.setword; + endp = &(b.setword[n]); + while ( p < endp ) *r++ = *p++ & (~ *q++); + + /* Copy rest of b into result if size(b) > c */ + if ( b.n > n ) + { + p = &(b.setword[n]); + endp = &(b.setword[b.n]); + while ( p < endp ) *r++ = *p++; + } + + return(t); +} + +set +#ifdef __USE_PROTOS +set_of( unsigned b ) +#else +set_of( b ) +unsigned b; +#endif +{ + /* Fast singleton set constructor operation */ + static set a; + + if ( b == nil ) return( empty ); + set_new(a, b); + a.setword[DIVWORD(b)] = bitmask[MODWORD(b)]; + + return(a); +} + +/* + * Extend (or shrink) the set passed in to have n words. + * + * if n is smaller than the minimum, boost n to have the minimum. + * if the new set size is the same as the old one, do nothing. + * + * TJP 4-27-92 Fixed so won't try to alloc 0 bytes + */ +void +#ifdef __USE_PROTOS +set_ext( set *a, unsigned int n ) +#else +set_ext( a, n ) +set *a; +unsigned int n; +#endif +{ + register unsigned *p; + register unsigned *endp; + unsigned int size; + + CHK((*a)); + if ( a->n == 0 ) + { + if ( n == 0 ) return; + if (a->setword != NULL) { + free (a->setword); /* MR20 */ + } + a->setword = (unsigned *) calloc(n, BytesPerWord); + if ( a->setword == NULL ) + { + fprintf(stderr, "set_ext(%d words): cannot allocate set\n", n); + exit(-1); + } + a->n = n; + return; + } + if ( n < min ) n = min; + if ( a->n == n || n == 0 ) return; + size = a->n; + a->n = n; + a->setword = (unsigned *) realloc( (char *)a->setword, (n*BytesPerWord) ); + if ( a->setword == NULL ) + { + fprintf(stderr, "set_ext(%d words): cannot allocate set\n", n); + exit(-1); + } + + p = &(a->setword[size]); /* clear from old size to new size */ + endp = &(a->setword[a->n]); + do { + *p++ = 0; + } while ( p < endp ); +} + +set +#ifdef __USE_PROTOS +set_not( set a ) +#else +set_not( a ) +set a; +#endif +{ + /* Fast not of set a (assumes all bits used) */ + /* size of resultant set is size(a) */ + /* ~empty = empty cause we don't know how bit to make set */ + set t; + register unsigned *r; + register unsigned *p = a.setword; + register unsigned *endp = &(a.setword[a.n]); + + CHK(a); + t = empty; + if ( a.n == 0 ) return( empty ); + set_ext(&t, a.n); + r = t.setword; + + do { + *r++ = (~ *p++); + } while ( p < endp ); + + return(t); +} + +int +#ifdef __USE_PROTOS +set_equ( set a, set b ) +#else +set_equ( a, b ) +set a; +set b; +#endif +{ +/* 8-Nov-97 Make it work with sets of different sizes */ +/* Easy to understand, too. Probably faster. */ +/* Check for a equal to b */ + + unsigned int count; /* MR11 */ + unsigned int i; /* MR11 */ + + CHK(a); CHK(b); + + count=MIN(a.n,b.n); + if (count == 0) return 1; + for (i=0; i < count; i++) { + if (a.setword[i] != b.setword[i]) return 0; + }; + if (a.n < b.n) { + for (i=count; i < b.n; i++) { + if (b.setword[i] != 0) return 0; + } + return 1; + } else if (a.n > b.n) { + for (i=count; i < a.n; i++) { + if (a.setword[i] != 0) return 0; + } + return 1; + } else { + return 1; + }; +} + +int +#ifdef __USE_PROTOS +set_sub( set a, set b ) +#else +set_sub( a, b ) +set a; +set b; +#endif +{ + +/* 8-Nov-97 Make it work with sets of different sizes */ +/* Easy to understand, too. Probably faster. */ +/* Check for a is a PROPER subset of b */ + + unsigned int count; + unsigned int i; + + CHK(a); CHK(b); + + if (a.n == 0) return 1; + count=MIN(a.n,b.n); + for (i=0; i < count; i++) { + if (a.setword[i] & ~b.setword[i]) return 0; + }; + if (a.n <= b.n) { + return 1; + } else { + for (i=count; i a.n ) return(0); + + /* Otherwise, we have to check */ + return( a.setword[DIVWORD(b)] & bitmask[MODWORD(b)] ); +} + +int +#ifdef __USE_PROTOS +set_nil( set a ) +#else +set_nil( a ) +set a; +#endif +{ + /* Fast check for nil set */ + register unsigned *p = a.setword; + register unsigned *endp; + + CHK(a); + if ( a.n == 0 ) return(1); + endp = &(a.setword[a.n]); + + /* The set is not empty if any word used to store + the set is non-zero. This means one must be a + bit careful about doing things like negation. + */ + do { + if (*p) return(0); + } while (++p < endp); + + return(1); +} + +char * +#ifdef __USE_PROTOS +set_str( set a ) +#else +set_str( a ) +set a; +#endif +{ + /* Fast convert set a into ASCII char string... + assumes that all word bits are used in the set + and that SETSIZE is a multiple of WORDSIZE. + Trailing 0 bits are removed from the string. + if no bits are on or set is empty, "" is returned. + */ + register unsigned *p = a.setword; + register unsigned *endp = &(a.setword[a.n]); + static char str_tmp[StrSize+1]; + register char *q = &(str_tmp[0]); + + CHK(a); + if ( a.n==0 ) {*q=0; return( &(str_tmp[0]) );} + do { + register unsigned t = *p; + register unsigned *b = &(bitmask[0]); + do { + *(q++) = (char) ((t & *b) ? '1' : '0'); + } while (++b < &(bitmask[WORDSIZE])); + } while (++p < endp); + + /* Trim trailing 0s & NULL terminate the string */ + while ((q > &(str_tmp[0])) && (*(q-1) != '1')) --q; + *q = 0; + + return(&(str_tmp[0])); +} + +set +#ifdef __USE_PROTOS +set_val( register char *s ) +#else +set_val( s ) +register char *s; +#endif +{ + /* Fast convert set ASCII char string into a set. + If the string ends early, the remaining set bits + are all made zero. + The resulting set size is just big enough to hold all elements. + */ + static set a; + register unsigned *p, *endp; + + set_new(a, (unsigned) strlen(s)); + p = a.setword; + endp = &(a.setword[a.n]); + do { + register unsigned *b = &(bitmask[0]); + /* Start with a word with no bits on */ + *p = 0; + do { + if (*s) { + if (*s == '1') { + /* Turn-on this bit */ + *p |= *b; + } + ++s; + } + } while (++b < &(bitmask[WORDSIZE])); + } while (++p < endp); + + return(a); +} + +/* + * Or element e into set a. a can be empty. + */ +void +#ifdef __USE_PROTOS +set_orel( unsigned e, set *a ) +#else +set_orel( e, a ) +unsigned e; +set *a; +#endif +{ + CHK((*a)); + if ( e == nil ) return; + if ( NumWords(e) > a->n ) set_ext(a, NumWords(e)); + a->setword[DIVWORD(e)] |= bitmask[MODWORD(e)]; +} + +/* + * Or set b into set a. a can be empty. does nothing if b empty. + */ +void +#ifdef __USE_PROTOS +set_orin( set *a, set b ) +#else +set_orin( a, b ) +set *a; +set b; +#endif +{ + /* Fast set union operation */ + /* size(a) is max(a, b); */ + unsigned int m; + register unsigned *p, + *q = b.setword, + *endq; /* MR20 */ + + CHK((*a)); CHK(b); + if ( b.n == 0 ) return; + endq = &(b.setword[b.n]); /* MR20 */ + m = (a->n > b.n) ? a->n : b.n; + set_ext(a, m); + p = a->setword; + do { + *p++ |= *q++; + } while ( q < endq ); +} + +/* + * And set b into set a. a can be empty. does nothing if b empty. + */ +void +#ifdef __USE_PROTOS +set_andin( set *a, set b ) +#else +set_andin( a, b ) +set *a; +set b; +#endif +{ + /* Fast set intersection operation */ + /* size(a) is max(a, b); */ + unsigned int m; + register unsigned *p, + *q = b.setword, + *endq = &(b.setword[b.n]); + + CHK((*a)); CHK(b); + if ( b.n == 0 ) return; + m = (a->n > b.n) ? a->n : b.n; + set_ext(a, m); + p = a->setword; + do { + *p++ &= *q++; + } while ( q < endq ); +} + +void +#ifdef __USE_PROTOS +set_rm( unsigned e, set a ) +#else +set_rm( e, a ) +unsigned e; +set a; +#endif +{ + /* Does not effect size of set */ + CHK(a); + if ( (e == nil) || (NumWords(e) > a.n) ) return; + a.setword[DIVWORD(e)] ^= (a.setword[DIVWORD(e)]&bitmask[MODWORD(e)]); +} + +void +#ifdef __USE_PROTOS +set_clr( set a ) +#else +set_clr( a ) +set a; +#endif +{ + /* Does not effect size of set */ + register unsigned *p = a.setword; + register unsigned *endp; + + CHK(a); + if ( a.n == 0 ) return; + endp = &(a.setword[a.n]); + do { + *p++ = 0; + } while ( p < endp ); +} + +set +#ifdef __USE_PROTOS +set_dup( set a ) +#else +set_dup( a ) +set a; +#endif +{ + set b; + register unsigned *p, + *q = a.setword, + *endq; /* MR20 */ + + CHK(a); + b = empty; + if ( a.n == 0 ) return( empty ); + endq = &(a.setword[a.n]); /* MR20 */ + set_ext(&b, a.n); + p = b.setword; + do { + *p++ = *q++; + } while ( q < endq ); + + return(b); +} + +/* + * Return a nil terminated list of unsigned ints that represents all + * "on" bits in the bit set. + * + * e.g. {011011} --> {1, 2, 4, 5, nil} + * + * _set_pdq and set_pdq are useful when an operation is required on each element + * of a set. Normally, the sequence is: + * + * while ( set_deg(a) > 0 ) { + * e = set_int(a); + * set_rm(e, a); + * ...process e... + * } + * Now, + * + * t = e = set_pdq(a); + * while ( *e != nil ) { + * ...process *e... + * e++; + * } + * free( t ); + * + * We have saved many set calls and have not destroyed set a. + */ +void +#ifdef __USE_PROTOS +_set_pdq( set a, register unsigned *q ) +#else +_set_pdq( a, q ) +set a; +register unsigned *q; +#endif +{ + register unsigned *p = a.setword, + *endp = &(a.setword[a.n]); + register unsigned e=0; + + CHK(a); + /* are there any space (possibility of elements)? */ + if ( a.n == 0 ) return; + do { + register unsigned t = *p; + register unsigned *b = &(bitmask[0]); + do { + if ( t & *b ) *q++ = e; + ++e; + } while (++b < &(bitmask[WORDSIZE])); + } while (++p < endp); + *q = nil; +} + +/* + * Same as _set_pdq except allocate memory. set_pdq is the natural function + * to use. + */ +unsigned * +#ifdef __USE_PROTOS +set_pdq( set a ) +#else +set_pdq( a ) +set a; +#endif +{ + unsigned *q; + int max_deg; + + CHK(a); + max_deg = WORDSIZE*a.n; + /* assume a.n!=0 & no elements is rare, but still ok */ + if ( a.n == 0 ) return(NULL); + q = (unsigned *) malloc((max_deg+1)*BytesPerWord); + if ( q == NULL ) return( NULL ); + _set_pdq(a, q); + return( q ); +} + +/* a function that produces a hash number for the set + */ +unsigned int +#ifdef __USE_PROTOS +set_hash( set a, register unsigned int mod ) +#else +set_hash( a, mod ) +set a; +register unsigned int mod; +#endif +{ + /* Fast hash of set a (assumes all bits used) */ + register unsigned *p = &(a.setword[0]); + register unsigned *endp = &(a.setword[a.n]); + register unsigned i = 0; + + CHK(a); + while (p> LogWordSize) /* x / WORDSIZE */ +#define nil (~((unsigned) 0)) /* An impossible set member all bits on (big!) */ + +typedef struct _set { + unsigned int n; /* Number of words in set */ + unsigned *setword; + } set; + +#define set_init {0, NULL} +#define set_null(a) ((a).setword==NULL) + +#define NumBytes(x) (((x)>>3)+1) /* Num bytes to hold x */ +#define NumWords(x) ((((unsigned)(x))>>LogWordSize)+1) /* Num words to hold x */ + + +/* M a c r o s */ + +/* make arg1 a set big enough to hold max elem # of arg2 */ +#define set_new(a,_max) \ +if (((a).setword=(unsigned *)calloc(NumWords(_max),BytesPerWord))==NULL) \ + fprintf(stderr, "set_new: Cannot allocate set with max of %d\n", _max); \ + (a).n = NumWords(_max); + +#define set_free(a) \ + {if ( (a).setword != NULL ) free((char *)((a).setword)); \ + (a) = empty;} + +#ifdef __USE_PROTOS +extern void set_size( unsigned ); +extern unsigned int set_deg( set ); +extern set set_or( set, set ); +extern set set_and( set, set ); +extern set set_dif( set, set ); +extern set set_of( unsigned ); +extern void set_ext( set *, unsigned int ); +extern set set_not( set ); +extern int set_equ( set, set ); +extern int set_sub( set, set ); +extern unsigned set_int( set ); +extern int set_el( unsigned, set ); +extern int set_nil( set ); +extern char * set_str( set ); +extern set set_val( register char * ); +extern void set_orel( unsigned, set * ); +extern void set_orin( set *, set ); +extern void set_andin( set *, set ); +extern void set_rm( unsigned, set ); +extern void set_clr( set ); +extern set set_dup( set ); +extern void set_PDQ( set, register unsigned * ); +extern unsigned *set_pdq( set ); +extern void _set_pdq( set a, register unsigned *q ); +extern unsigned int set_hash( set, register unsigned int ); +#else +extern void set_size(); +extern unsigned int set_deg(); +extern set set_or(); +extern set set_and(); +extern set set_dif(); +extern set set_of(); +extern void set_ext(); +extern set set_not(); +extern int set_equ(); +extern int set_sub(); +extern unsigned set_int(); +extern int set_el(); +extern int set_nil(); +extern char * set_str(); +extern set set_val(); +extern void set_orel(); +extern void set_orin(); +extern void set_andin(); +extern void set_rm(); +extern void set_clr(); +extern set set_dup(); +extern void set_PDQ(); +extern unsigned *set_pdq(); +extern void _set_pdq(); +extern unsigned int set_hash(); +#endif + +extern set empty; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/sym/sym.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/sym/sym.c new file mode 100644 index 00000000..69eb2b47 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/sym/sym.c @@ -0,0 +1,402 @@ +/* + * Simple symbol table manager using coalesced chaining to resolve collisions + * + * Doubly-linked lists are used for fast removal of entries. + * + * 'sym.h' must have a definition for typedef "Sym". Sym must include at + * minimum the following fields: + * + * ... + * char *symbol; + * struct ... *next, *prev, **head, *scope; + * unsigned int hash; + * ... + * + * 'template.h' can be used as a template to create a 'sym.h'. + * + * 'head' is &(table[hash(itself)]). + * The hash table is not resizable at run-time. + * The scope field is used to link all symbols of a current scope together. + * Scope() sets the current scope (linked list) to add symbols to. + * Any number of scopes can be handled. The user passes the address of + * a pointer to a symbol table + * entry (INITIALIZED TO NULL first time). + * + * Available Functions: + * + * zzs_init(s1,s2) -- Create hash table with size s1, string table size s2. + * zzs_done() -- Free hash and string table created with zzs_init(). + * zzs_add(key,rec)-- Add 'rec' with key 'key' to the symbol table. + * zzs_newadd(key) -- create entry; add using 'key' to the symbol table. + * zzs_get(key) -- Return pointer to last record entered under 'key' + * Else return NULL + * zzs_del(p) -- Unlink the entry associated with p. This does + * NOT free 'p' and DOES NOT remove it from a scope + * list. If it was a part of your intermediate code + * tree or another structure. It will still be there. + * It is only removed from further consideration + * by the symbol table. + * zzs_keydel(s) -- Unlink the entry associated with key s. + * Calls zzs_del(p) to unlink. + * zzs_scope(sc) -- Specifies that everything added to the symbol + * table with zzs_add() is added to the list (scope) + * 'sc'. 'sc' is of 'Sym **sc' type and must be + * initialized to NULL before trying to add anything + * to it (passing it to zzs_scope()). Scopes can be + * switched at any time and merely links a set of + * symbol table entries. If a NULL pointer is + * passed, the current scope is returned. + * zzs_rmscope(sc) -- Remove (zzs_del()) all elements of scope 'sc' + * from the symbol table. The entries are NOT + * free()'d. A pointer to the first + * element in the "scope" is returned. The user + * can then manipulate the list as he/she chooses + * (such as freeing them all). NOTE that this + * function sets your scope pointer to NULL, + * but returns a pointer to the list for you to use. + * zzs_stat() -- Print out the symbol table and some relevant stats. + * zzs_new(key) -- Create a new record with calloc() of type Sym. + * Add 'key' to the string table and make the new + * records 'symbol' pointer point to it. + * zzs_strdup(s) -- Add s to the string table and return a pointer + * to it. Very fast allocation routine + * and does not require strlen() nor calloc(). + * + * Example: + * + * #include + * #include "sym.h" + * + * main() + * { + * Sym *scope1=NULL, *scope2=NULL, *a, *p; + * + * zzs_init(101, 100); + * + * a = zzs_new("Apple"); zzs_add(a->symbol, a); -- No scope + * zzs_scope( &scope1 ); -- enter scope 1 + * a = zzs_new("Plum"); zzs_add(a->symbol, a); + * zzs_scope( &scope2 ); -- enter scope 2 + * a = zzs_new("Truck"); zzs_add(a->symbol, a); + * + * p = zzs_get("Plum"); + * if ( p == NULL ) fprintf(stderr, "Hmmm...Can't find 'Plum'\n"); + * + * p = zzs_rmscope(&scope1) + * for (; p!=NULL; p=p->scope) {printf("Scope1: %s\n", p->symbol);} + * p = zzs_rmscope(&scope2) + * for (; p!=NULL; p=p->scope) {printf("Scope2: %s\n", p->symbol);} + * } + * + * Terence Parr + * Purdue University + * February 1990 + * + * CHANGES + * + * Terence Parr + * May 1991 + * Renamed functions to be consistent with ANTLR + * Made HASH macro + * Added zzs_keydel() + * Added zzs_newadd() + * Fixed up zzs_stat() + * + * July 1991 + * Made symbol table entry save its hash code for fast comparison + * during searching etc... + */ + +#include +#if defined(__STDC__) || defined(__USE_PROTOS) +#include +#include +#else +#include +#endif +#include "sym.h" + +#define StrSame 0 + +static Sym **CurScope = NULL; +static unsigned size = 0; +static Sym **table=NULL; +static char *strings; +static char *strp; +static int strsize = 0; + +#ifdef __USE_PROTOS +void zzs_init(int sz,int strs) +#else +void zzs_init(sz, strs) +int sz, strs; +#endif +{ + if ( sz <= 0 || strs <= 0 ) return; + table = (Sym **) calloc(sz, sizeof(Sym *)); + if ( table == NULL ) + { + fprintf(stderr, "Cannot allocate table of size %d\n", sz); + exit(1); + } + strings = (char *) calloc(strs, sizeof(char)); + if ( strings == NULL ) + { + fprintf(stderr, "Cannot allocate string table of size %d\n", strs); + exit(1); + } + size = sz; + strsize = strs; + strp = strings; +} + +#ifdef __USE_PROTOS +void zzs_done(void) +#else +void zzs_done() +#endif +{ + if ( table != NULL ) free( table ); + if ( strings != NULL ) free( strings ); +} + +#ifdef __USE_PROTOS +void zzs_add(char *key,Sym rec) +#else +void zzs_add(key, rec) +char *key; +register Sym *rec; +#endif +{ + register unsigned int h=0; + register char *p=key; + + HASH(p, h); + rec->hash = h; /* save hash code for fast comp later */ + h %= size; + + if ( CurScope != NULL ) {rec->scope = *CurScope; *CurScope = rec;} + rec->next = table[h]; /* Add to doubly-linked list */ + rec->prev = NULL; + if ( rec->next != NULL ) (rec->next)->prev = rec; + table[h] = rec; + rec->head = &(table[h]); +} + +#ifdef __USE_PROTOS +Sym * zzs_get(char *key) +#else +Sym * zzs_get(key) +char *key; +#endif +{ + register unsigned int h=0; + register char *p=key; + register Sym *q; + + HASH(p, h); + + for (q = table[h%size]; q != NULL; q = q->next) + { + if ( q->hash == h ) /* do we even have a chance of matching? */ + if ( strcmp(key, q->symbol) == StrSame ) return( q ); + } + return( NULL ); +} + +/* + * Unlink p from the symbol table. Hopefully, it's actually in the + * symbol table. + * + * If p is not part of a bucket chain of the symbol table, bad things + * will happen. + * + * Will do nothing if all list pointers are NULL + */ +#ifdef __USE_PROTOS +void zzs_del(Sym *p) +#else +void zzs_del(p) +register Sym *p; +#endif +{ + if ( p == NULL ) {fprintf(stderr, "zzs_del(NULL)\n"); exit(1);} + if ( p->prev == NULL ) /* Head of list */ + { + register Sym **t = p->head; + + if ( t == NULL ) return; /* not part of symbol table */ + (*t) = p->next; + if ( (*t) != NULL ) (*t)->prev = NULL; + } + else + { + (p->prev)->next = p->next; + if ( p->next != NULL ) (p->next)->prev = p->prev; + } + p->next = p->prev = NULL; /* not part of symbol table anymore */ + p->head = NULL; +} + +#ifdef __USE_PROTOS +void zzs_keydel(char *key) +#else +void zzs_keydel(key) +char *key; +#endif +{ + Sym *p = zzs_get(key); + + if ( p != NULL ) zzs_del( p ); +} + +/* S c o p e S t u f f */ + +/* Set current scope to 'scope'; return current scope if 'scope' == NULL */ + +#ifdef __USE_PROTOS +Sym ** zzs_scope(Sym **scope) +#else +Sym ** zzs_scope(scope) +Sym **scope; +#endif +{ + if ( scope == NULL ) return( CurScope ); + CurScope = scope; + return( scope ); +} + +/* Remove a scope described by 'scope'. Return pointer to 1st element in scope */ + +#ifdef __USE_PROTOS +Sym * zzs_rmscope(Sym **scope) +#else +Sym * zzs_rmscope(scope) +register Sym **scope; +#endif +{ + register Sym *p; + Sym *start; + + if ( scope == NULL ) return(NULL); + start = p = *scope; + for (; p != NULL; p=p->scope) { zzs_del( p ); } + *scope = NULL; + return( start ); +} + +#ifdef __USE_PROTOS +void zzs_stat(void) +#else +void zzs_stat() +#endif +{ + static unsigned short count[20]; + unsigned int i,n=0,low=0, hi=0; + register Sym **p; + float avg=0.0; + + for (i=0; i<20; i++) count[i] = 0; + for (p=table; p<&(table[size]); p++) + { + register Sym *q = *p; + unsigned int len; + + if ( q != NULL && low==0 ) low = p-table; + len = 0; + if ( q != NULL ) printf("[%d]", p-table); + while ( q != NULL ) + { + len++; + n++; + printf(" %s", q->symbol); + q = q->next; + if ( q == NULL ) printf("\n"); + } + if ( len>=20 ) printf("zzs_stat: count table too small\n"); + else count[len]++; + if ( *p != NULL ) hi = p-table; + } + + printf("Storing %d recs used %d hash positions out of %d\n", + n, size-count[0], size); + printf("%f %% utilization\n", + ((float)(size-count[0]))/((float)size)); + for (i=0; i<20; i++) + { + if ( count[i] != 0 ) + { + avg += (((float)(i*count[i]))/((float)n)) * i; + printf("Buckets of len %d == %d (%f %% of recs)\n", + i, count[i], 100.0*((float)(i*count[i]))/((float)n)); + } + } + printf("Avg bucket length %f\n", avg); + printf("Range of hash function: %d..%d\n", low, hi); +} + +/* + * Given a string, this function allocates and returns a pointer to a + * symbol table record whose "symbol" pointer is reset to a position + * in the string table. + */ + +#ifdef __USE_PROTOS +Sym * zzs_new(char *text) +#else +Sym * zzs_new(text) +char *text; +#endif +{ + Sym *p; + + if ( (p = (Sym *) calloc(1,sizeof(Sym))) == 0 ) + { + fprintf(stderr,"Out of memory\n"); + exit(1); + } + p->symbol = zzs_strdup(text); + + return p; +} + +/* create a new symbol table entry and add it to the symbol table */ + +#ifdef __USE_PROTOS +Sym * zzs_newadd(char *text) +#else +Sym * zzs_newadd(text) +char *text; +#endif +{ + Sym *p = zzs_new(text); + if ( p != NULL ) zzs_add(text, p); + return p; +} + +/* Add a string to the string table and return a pointer to it. + * Bump the pointer into the string table to next avail position. + */ + +#ifdef __USE_PROTOS +char * zzs_strdup(char *s) +#else +char * zzs_strdup(s) +register char *s; +#endif +{ + register char *start=strp; + + while ( *s != '\0' ) + { + if ( strp >= &(strings[strsize-2]) ) + { + fprintf(stderr, "sym: string table overflow (%d chars)\n", strsize); + exit(-1); + } + *strp++ = *s++; + } + *strp++ = '\0'; + + return( start ); +} diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/sym/template.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/sym/template.h new file mode 100644 index 00000000..49ce0660 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/Pccts/support/sym/template.h @@ -0,0 +1,41 @@ +/* T e m p l a t e F o r S y m b o l T a b l e M a n a g e r */ + +/* define some hash function */ +#ifndef HASH +#define HASH(p, h) while ( *p != '\0' ) h = (h<<1) + *p++; +#endif + +/* minimum symbol table record */ +typedef struct _sym { + char *symbol; + struct _sym *next, *prev, **head, *scope; + unsigned int hash; + } Sym, *SymPtr; + +#ifdef __USE_PROTOS +void zzs_init(int, int); +void zzs_done(void); +void zzs_add(char *, Sym *); +Sym *zzs_get(char *); +void zzs_del(Sym *); +void zzs_keydel(char *); +Sym **zzs_scope(Sym **); +Sym *zzs_rmscope(Sym **); +void zzs_stat(void); +Sym *zzs_new(char *); +Sym *zzs_newadd(char *); +char *zzs_strdup(char *); +#else +void zzs_init(); +void zzs_done(); +void zzs_add(); +Sym *zzs_get(); +void zzs_del(); +void zzs_keydel(); +Sym **zzs_scope(); +Sym *zzs_rmscope(); +void zzs_stat(); +Sym *zzs_new(); +Sym *zzs_newadd(); +char *zzs_strdup(); +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrCompiler.cpp b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrCompiler.cpp new file mode 100644 index 00000000..2bdd5cb4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrCompiler.cpp @@ -0,0 +1,941 @@ +/** @file + + VfrCompiler main class and main function. + +Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "VfrCompiler.h" +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" + +PACKAGE_DATA gCBuffer; +PACKAGE_DATA gRBuffer; +CVfrStringDB gCVfrStringDB; + +VOID +CVfrCompiler::DebugError ( + IN CHAR8 *FileName, + IN UINT32 LineNumber, + IN UINT32 MessageCode, + IN CONST CHAR8 *Text, + IN CONST CHAR8 *MsgFmt, + ... + ) +{ + va_list List; + va_start (List, MsgFmt); + PrintMessage ((CHAR8 *) "ERROR", FileName, LineNumber, MessageCode, (CHAR8 *) Text, (CHAR8 *) MsgFmt, List); + va_end (List); +} + +VOID +CVfrCompiler::SET_RUN_STATUS ( + IN COMPILER_RUN_STATUS Status + ) +{ + mRunStatus = Status; +} + +BOOLEAN +CVfrCompiler::IS_RUN_STATUS ( + IN COMPILER_RUN_STATUS Status + ) +{ + return mRunStatus == Status; +} + +VOID +CVfrCompiler::OptionInitialization ( + IN INT32 Argc, + IN CHAR8 **Argv + ) +{ + INT32 Index; + EFI_STATUS Status; + + Status = EFI_SUCCESS; + SetUtilityName ((CHAR8*) PROGRAM_NAME); + + mOptions.VfrFileName = NULL; + mOptions.RecordListFile = NULL; + mOptions.CreateRecordListFile = FALSE; + mOptions.CreateIfrPkgFile = FALSE; + mOptions.PkgOutputFileName = NULL; + mOptions.COutputFileName = NULL; + mOptions.OutputDirectory = NULL; + mOptions.PreprocessorOutputFileName = NULL; + mOptions.VfrBaseFileName = NULL; + mOptions.IncludePaths = NULL; + mOptions.SkipCPreprocessor = TRUE; + mOptions.CPreprocessorOptions = NULL; + mOptions.HasOverrideClassGuid = FALSE; + mOptions.WarningAsError = FALSE; + mOptions.AutoDefault = FALSE; + mOptions.CheckDefault = FALSE; + memset (&mOptions.OverrideClassGuid, 0, sizeof (EFI_GUID)); + + if (Argc == 1) { + Usage (); + SET_RUN_STATUS (STATUS_DEAD); + return; + } + + for (Index = 1; (Index < Argc) && (Argv[Index][0] == '-'); Index++) { + if ((stricmp(Argv[Index], "-h") == 0) || (stricmp(Argv[Index], "--help") == 0)) { + Usage (); + SET_RUN_STATUS (STATUS_DEAD); + return; + } else if (stricmp(Argv[Index], "--version") == 0) { + Version (); + SET_RUN_STATUS (STATUS_DEAD); + return; + } else if (stricmp(Argv[Index], "-l") == 0) { + mOptions.CreateRecordListFile = TRUE; + gCIfrRecordInfoDB.TurnOn (); + } else if (stricmp(Argv[Index], "-i") == 0) { + Index++; + if ((Index >= Argc) || (Argv[Index][0] == '-')) { + DebugError (NULL, 0, 1001, "Missing option", "-i missing path argument"); + goto Fail; + } + + AppendIncludePath(Argv[Index]); + } else if (stricmp(Argv[Index], "-o") == 0 || stricmp(Argv[Index], "--output-directory") == 0 || stricmp(Argv[Index], "-od") == 0) { + Index++; + if ((Index >= Argc) || (Argv[Index][0] == '-')) { + DebugError (NULL, 0, 1001, "Missing option", "-o missing output directory name"); + goto Fail; + } + + mOptions.OutputDirectory = (CHAR8 *) malloc (strlen (Argv[Index]) + strlen ("\\") + 1); + if (mOptions.OutputDirectory == NULL) { + DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL); + goto Fail; + } + strcpy (mOptions.OutputDirectory, Argv[Index]); + + CHAR8 lastChar = mOptions.OutputDirectory[strlen(mOptions.OutputDirectory) - 1]; + if ((lastChar != '/') && (lastChar != '\\')) { + if (strchr(mOptions.OutputDirectory, '/') != NULL) { + strcat (mOptions.OutputDirectory, "/"); + } else { + strcat (mOptions.OutputDirectory, "\\"); + } + } + DebugMsg (NULL, 0, 9, (CHAR8 *) "Output Directory", (CHAR8 *) "%s", mOptions.OutputDirectory); + } else if (stricmp(Argv[Index], "-b") == 0 || stricmp(Argv[Index], "--create-ifr-package") == 0 || stricmp(Argv[Index], "-ibin") == 0) { + mOptions.CreateIfrPkgFile = TRUE; + } else if (stricmp(Argv[Index], "-n") == 0 || stricmp(Argv[Index], "--no-pre-processing") == 0 || stricmp(Argv[Index], "-nopp") == 0) { + mOptions.SkipCPreprocessor = TRUE; + } else if (stricmp(Argv[Index], "-f") == 0 || stricmp(Argv[Index], "--pre-processing-flag") == 0 || stricmp(Argv[Index], "-ppflag") == 0) { + Index++; + if ((Index >= Argc) || (Argv[Index][0] == '-')) { + DebugError (NULL, 0, 1001, "Missing option", "-od - missing C-preprocessor argument"); + goto Fail; + } + + AppendCPreprocessorOptions (Argv[Index]); + } else if (stricmp(Argv[Index], "-s") == 0|| stricmp(Argv[Index], "--string-db") == 0) { + Index++; + if ((Index >= Argc) || (Argv[Index][0] == '-')) { + DebugError (NULL, 0, 1001, "Missing option", "-s missing input string file name"); + goto Fail; + } + gCVfrStringDB.SetStringFileName(Argv[Index]); + DebugMsg (NULL, 0, 9, (CHAR8 *) "Input string file path", (CHAR8 *) "%s", Argv[Index]); + } else if ((stricmp (Argv[Index], "-g") == 0) || (stricmp (Argv[Index], "--guid") == 0)) { + Index++; + Status = StringToGuid (Argv[Index], &mOptions.OverrideClassGuid); + if (EFI_ERROR (Status)) { + DebugError (NULL, 0, 1000, "Invalid format:", "%s", Argv[Index]); + goto Fail; + } + mOptions.HasOverrideClassGuid = TRUE; + } else if (stricmp(Argv[Index], "-w") == 0 || stricmp(Argv[Index], "--warning-as-error") == 0) { + mOptions.WarningAsError = TRUE; + } else if (stricmp(Argv[Index], "-a") == 0 ||stricmp(Argv[Index], "--autodefault") == 0) { + mOptions.AutoDefault = TRUE; + } else if (stricmp(Argv[Index], "-d") == 0 ||stricmp(Argv[Index], "--checkdefault") == 0) { + mOptions.CheckDefault = TRUE; + } else { + DebugError (NULL, 0, 1000, "Unknown option", "unrecognized option %s", Argv[Index]); + goto Fail; + } + } + + if (Index != Argc - 1) { + DebugError (NULL, 0, 1001, "Missing option", "VFR file name is not specified."); + goto Fail; + } else { + mOptions.VfrFileName = (CHAR8 *) malloc (strlen (Argv[Index]) + 1); + if (mOptions.VfrFileName == NULL) { + DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL); + goto Fail; + } + strcpy (mOptions.VfrFileName, Argv[Index]); + + if (mOptions.OutputDirectory == NULL) { + mOptions.OutputDirectory = (CHAR8 *) malloc (1); + if (mOptions.OutputDirectory == NULL) { + DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL); + goto Fail; + } + mOptions.OutputDirectory[0] = '\0'; + } + } + + if (SetBaseFileName() != 0) { + goto Fail; + } + if (SetPkgOutputFileName () != 0) { + goto Fail; + } + if (SetCOutputFileName() != 0) { + goto Fail; + } + if (SetPreprocessorOutputFileName () != 0) { + goto Fail; + } + if (SetRecordListFileName () != 0) { + goto Fail; + } + return; + +Fail: + SET_RUN_STATUS (STATUS_DEAD); + + mOptions.CreateRecordListFile = FALSE; + mOptions.CreateIfrPkgFile = FALSE; + + if (mOptions.VfrFileName != NULL) { + free (mOptions.VfrFileName); + mOptions.VfrFileName = NULL; + } + if (mOptions.VfrBaseFileName != NULL) { + free (mOptions.VfrBaseFileName); + mOptions.VfrBaseFileName = NULL; + } + if (mOptions.OutputDirectory != NULL) { + free (mOptions.OutputDirectory); + mOptions.OutputDirectory = NULL; + } + if (mOptions.PkgOutputFileName != NULL) { + free (mOptions.PkgOutputFileName); + mOptions.PkgOutputFileName = NULL; + } + if (mOptions.COutputFileName != NULL) { + free (mOptions.COutputFileName); + mOptions.COutputFileName = NULL; + } + if (mOptions.PreprocessorOutputFileName != NULL) { + free (mOptions.PreprocessorOutputFileName); + mOptions.PreprocessorOutputFileName = NULL; + } + if (mOptions.RecordListFile != NULL) { + free (mOptions.RecordListFile); + mOptions.RecordListFile = NULL; + } + if (mOptions.IncludePaths != NULL) { + delete mOptions.IncludePaths; + mOptions.IncludePaths = NULL; + } + if (mOptions.CPreprocessorOptions != NULL) { + delete mOptions.CPreprocessorOptions; + mOptions.CPreprocessorOptions = NULL; + } +} + +VOID +CVfrCompiler::AppendIncludePath ( + IN CHAR8 *PathStr + ) +{ + UINT32 Len = 0; + CHAR8 *IncludePaths = NULL; + + Len = strlen (" -I ") + strlen (PathStr) + 1; + if (mOptions.IncludePaths != NULL) { + Len += strlen (mOptions.IncludePaths); + } + IncludePaths = new CHAR8[Len]; + if (IncludePaths == NULL) { + DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL); + return; + } + IncludePaths[0] = '\0'; + if (mOptions.IncludePaths != NULL) { + strcat (IncludePaths, mOptions.IncludePaths); + } + strcat (IncludePaths, " -I "); + strcat (IncludePaths, PathStr); + if (mOptions.IncludePaths != NULL) { + delete[] mOptions.IncludePaths; + } + mOptions.IncludePaths = IncludePaths; +} + +VOID +CVfrCompiler::AppendCPreprocessorOptions ( + IN CHAR8 *Options + ) +{ + UINT32 Len = 0; + CHAR8 *Opt = NULL; + + Len = strlen (Options) + strlen (" ") + 1; + if (mOptions.CPreprocessorOptions != NULL) { + Len += strlen (mOptions.CPreprocessorOptions); + } + Opt = new CHAR8[Len]; + if (Opt == NULL) { + DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL); + return; + } + Opt[0] = 0; + if (mOptions.CPreprocessorOptions != NULL) { + strcat (Opt, mOptions.CPreprocessorOptions); + } + strcat (Opt, " "); + strcat (Opt, Options); + if (mOptions.CPreprocessorOptions != NULL) { + delete[] mOptions.CPreprocessorOptions; + } + mOptions.CPreprocessorOptions = Opt; +} + +INT8 +CVfrCompiler::SetBaseFileName ( + VOID + ) +{ + CHAR8 *pFileName, *pPath, *pExt; + + if (mOptions.VfrFileName == NULL) { + return -1; + } + + pFileName = mOptions.VfrFileName; + while ( + ((pPath = strchr (pFileName, '\\')) != NULL) || + ((pPath = strchr (pFileName, '/')) != NULL) + ) + { + pFileName = pPath + 1; + } + + if (pFileName == NULL) { + return -1; + } + + if ((pExt = strchr (pFileName, '.')) == NULL) { + return -1; + } + + *pExt = '\0'; + + mOptions.VfrBaseFileName = (CHAR8 *) malloc (strlen (pFileName) + 1); + if (mOptions.VfrBaseFileName == NULL) { + *pExt = '.'; + return -1; + } + + strcpy (mOptions.VfrBaseFileName, pFileName); + *pExt = '.'; + + return 0; +} + +INT8 +CVfrCompiler::SetPkgOutputFileName ( + VOID + ) +{ + INTN Length; + + if (mOptions.VfrBaseFileName == NULL) { + return -1; + } + + Length = strlen (mOptions.OutputDirectory) + + strlen (mOptions.VfrBaseFileName) + + strlen (VFR_PACKAGE_FILENAME_EXTENSION) + + 1; + + mOptions.PkgOutputFileName = (CHAR8 *) malloc (Length); + if (mOptions.PkgOutputFileName == NULL) { + return -1; + } + + strcpy (mOptions.PkgOutputFileName, mOptions.OutputDirectory); + strcat (mOptions.PkgOutputFileName, mOptions.VfrBaseFileName); + strcat (mOptions.PkgOutputFileName, VFR_PACKAGE_FILENAME_EXTENSION); + + return 0; +} + +INT8 +CVfrCompiler::SetCOutputFileName ( + VOID + ) +{ + INTN Length; + + if (mOptions.VfrBaseFileName == NULL) { + return -1; + } + + Length = strlen (mOptions.OutputDirectory) + + strlen (mOptions.VfrBaseFileName) + + strlen (".c") + + 1; + + mOptions.COutputFileName = (CHAR8 *) malloc (Length); + if (mOptions.COutputFileName == NULL) { + return -1; + } + + strcpy (mOptions.COutputFileName, mOptions.OutputDirectory); + strcat (mOptions.COutputFileName, mOptions.VfrBaseFileName); + strcat (mOptions.COutputFileName, ".c"); + + return 0; +} + +INT8 +CVfrCompiler::SetPreprocessorOutputFileName ( + VOID + ) +{ + INTN Length; + + if (mOptions.VfrBaseFileName == NULL) { + return -1; + } + + Length = strlen (mOptions.OutputDirectory) + + strlen (mOptions.VfrBaseFileName) + + strlen (VFR_PREPROCESS_FILENAME_EXTENSION) + + 1; + + mOptions.PreprocessorOutputFileName = (CHAR8 *) malloc (Length); + if (mOptions.PreprocessorOutputFileName == NULL) { + return -1; + } + + strcpy (mOptions.PreprocessorOutputFileName, mOptions.OutputDirectory); + strcat (mOptions.PreprocessorOutputFileName, mOptions.VfrBaseFileName); + strcat (mOptions.PreprocessorOutputFileName, VFR_PREPROCESS_FILENAME_EXTENSION); + + return 0; +} + +INT8 +CVfrCompiler::SetRecordListFileName ( + VOID + ) +{ + INTN Length; + + if (mOptions.VfrBaseFileName == NULL) { + return -1; + } + + Length = strlen (mOptions.OutputDirectory) + + strlen (mOptions.VfrBaseFileName) + + strlen (VFR_RECORDLIST_FILENAME_EXTENSION) + + 1; + + mOptions.RecordListFile = (CHAR8 *) malloc (Length); + if (mOptions.RecordListFile == NULL) { + return -1; + } + + strcpy (mOptions.RecordListFile, mOptions.OutputDirectory); + strcat (mOptions.RecordListFile, mOptions.VfrBaseFileName); + strcat (mOptions.RecordListFile, VFR_RECORDLIST_FILENAME_EXTENSION); + + return 0; +} + +CVfrCompiler::CVfrCompiler ( + IN INT32 Argc, + IN CHAR8 **Argv + ) +{ + mPreProcessCmd = (CHAR8 *) PREPROCESSOR_COMMAND; + mPreProcessOpt = (CHAR8 *) PREPROCESSOR_OPTIONS; + + SET_RUN_STATUS (STATUS_STARTED); + + OptionInitialization(Argc, Argv); + + if ((IS_RUN_STATUS(STATUS_FAILED)) || (IS_RUN_STATUS(STATUS_DEAD))) { + return; + } + + SET_RUN_STATUS(STATUS_INITIALIZED); +} + +CVfrCompiler::~CVfrCompiler ( + VOID + ) +{ + if (mOptions.VfrFileName != NULL) { + free (mOptions.VfrFileName); + mOptions.VfrFileName = NULL; + } + + if (mOptions.VfrBaseFileName != NULL) { + free (mOptions.VfrBaseFileName); + mOptions.VfrBaseFileName = NULL; + } + + if (mOptions.OutputDirectory != NULL) { + free (mOptions.OutputDirectory); + mOptions.OutputDirectory = NULL; + } + + if (mOptions.PkgOutputFileName != NULL) { + free (mOptions.PkgOutputFileName); + mOptions.PkgOutputFileName = NULL; + } + + if (mOptions.COutputFileName != NULL) { + free (mOptions.COutputFileName); + mOptions.COutputFileName = NULL; + } + + if (mOptions.PreprocessorOutputFileName != NULL) { + free (mOptions.PreprocessorOutputFileName); + mOptions.PreprocessorOutputFileName = NULL; + } + + if (mOptions.RecordListFile != NULL) { + free (mOptions.RecordListFile); + mOptions.RecordListFile = NULL; + } + + if (mOptions.IncludePaths != NULL) { + delete[] mOptions.IncludePaths; + mOptions.IncludePaths = NULL; + } + + if (mOptions.CPreprocessorOptions != NULL) { + delete[] mOptions.CPreprocessorOptions; + mOptions.CPreprocessorOptions = NULL; + } + + SET_RUN_STATUS(STATUS_DEAD); +} + +VOID +CVfrCompiler::Usage ( + VOID + ) +{ + UINT32 Index; + CONST CHAR8 *Help[] = { + " ", + "VfrCompile version " VFR_COMPILER_VERSION "Build " __BUILD_VERSION, + "Copyright (c) 2004-2016 Intel Corporation. All rights reserved.", + " ", + "Usage: VfrCompile [options] VfrFile", + " ", + "Options:", + " -h, --help prints this help", + " --version prints version info", + " -l create an output IFR listing file", + " -o DIR, --output-directory DIR", + " deposit all output files to directory OutputDir", + " default is current directory", + " -b, --create-ifr-package", + " create an IFR HII pack file", + " -n, --no-pre-processing", + " do not preprocessing input file", + " -s, --string-db", + " input uni string package file", + " -g, --guid", + " override class guid input", + " format is xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", + " -w --warning-as-error", + " treat warning as an error", + " -a --autodefaut generate default value for question opcode if some default is missing", + " -d --checkdefault check the default information in a question opcode", + NULL + }; + for (Index = 0; Help[Index] != NULL; Index++) { + fprintf (stdout, "%s\n", Help[Index]); + } +} + +VOID +CVfrCompiler::Version ( + VOID + ) +{ + UINT32 Index; + CONST CHAR8 *Help[] = { + "VfrCompile version " VFR_COMPILER_VERSION "Build " __BUILD_VERSION, + NULL + }; + for (Index = 0; Help[Index] != NULL; Index++) { + fprintf (stdout, "%s\n", Help[Index]); + } +} + +VOID +CVfrCompiler::PreProcess ( + VOID + ) +{ + FILE *pVfrFile = NULL; + UINT32 CmdLen = 0; + CHAR8 *PreProcessCmd = NULL; + + if (!IS_RUN_STATUS(STATUS_INITIALIZED)) { + goto Fail; + } + + if (mOptions.SkipCPreprocessor == TRUE) { + goto Out; + } + + if ((pVfrFile = fopen (LongFilePath (mOptions.VfrFileName), "r")) == NULL) { + DebugError (NULL, 0, 0001, "Error opening the input VFR file", "%s", mOptions.VfrFileName); + goto Fail; + } + fclose (pVfrFile); + + CmdLen = strlen (mPreProcessCmd) + strlen (mPreProcessOpt) + + strlen (mOptions.VfrFileName) + strlen (mOptions.PreprocessorOutputFileName); + if (mOptions.CPreprocessorOptions != NULL) { + CmdLen += strlen (mOptions.CPreprocessorOptions); + } + if (mOptions.IncludePaths != NULL) { + CmdLen += strlen (mOptions.IncludePaths); + } + + PreProcessCmd = new CHAR8[CmdLen + 10]; + if (PreProcessCmd == NULL) { + DebugError (NULL, 0, 4001, "Resource: memory can't be allocated", NULL); + goto Fail; + } + strcpy (PreProcessCmd, mPreProcessCmd), strcat (PreProcessCmd, " "); + strcat (PreProcessCmd, mPreProcessOpt), strcat (PreProcessCmd, " "); + if (mOptions.IncludePaths != NULL) { + strcat (PreProcessCmd, mOptions.IncludePaths), strcat (PreProcessCmd, " "); + } + if (mOptions.CPreprocessorOptions != NULL) { + strcat (PreProcessCmd, mOptions.CPreprocessorOptions), strcat (PreProcessCmd, " "); + } + strcat (PreProcessCmd, mOptions.VfrFileName), strcat (PreProcessCmd, " > "); + strcat (PreProcessCmd, mOptions.PreprocessorOutputFileName); + + if (system (PreProcessCmd) != 0) { + DebugError (NULL, 0, 0003, "Error parsing file", "failed to spawn C preprocessor on VFR file %s\n", PreProcessCmd); + goto Fail; + } + + delete[] PreProcessCmd; + +Out: + SET_RUN_STATUS (STATUS_PREPROCESSED); + return; + +Fail: + if (!IS_RUN_STATUS(STATUS_DEAD)) { + SET_RUN_STATUS (STATUS_FAILED); + } + delete[] PreProcessCmd; +} + +extern UINT8 VfrParserStart (IN FILE *, IN INPUT_INFO_TO_SYNTAX *); + +VOID +CVfrCompiler::Compile ( + VOID + ) +{ + FILE *pInFile = NULL; + CHAR8 *InFileName = NULL; + INPUT_INFO_TO_SYNTAX InputInfo; + + if (!IS_RUN_STATUS(STATUS_PREPROCESSED)) { + goto Fail; + } + + InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName; + + gCVfrErrorHandle.SetInputFile (InFileName); + gCVfrErrorHandle.SetWarningAsError(mOptions.WarningAsError); + + if ((pInFile = fopen (LongFilePath (InFileName), "r")) == NULL) { + DebugError (NULL, 0, 0001, "Error opening the input file", "%s", InFileName); + goto Fail; + } + + if (mOptions.HasOverrideClassGuid) { + InputInfo.OverrideClassGuid = &mOptions.OverrideClassGuid; + } else { + InputInfo.OverrideClassGuid = NULL; + } + + if (VfrParserStart (pInFile, &InputInfo) != 0) { + goto Fail; + } + + fclose (pInFile); + pInFile = NULL; + + if (gCFormPkg.HavePendingUnassigned () == TRUE) { + gCFormPkg.PendingAssignPrintAll (); + goto Fail; + } + + SET_RUN_STATUS (STATUS_COMPILEED); + return; + +Fail: + if (!IS_RUN_STATUS(STATUS_DEAD)) { + DebugError (NULL, 0, 0003, "Error parsing", "compile error in file %s", InFileName); + SET_RUN_STATUS (STATUS_FAILED); + } + if (pInFile != NULL) { + fclose (pInFile); + } +} + +VOID +CVfrCompiler::AdjustBin ( + VOID + ) +{ + EFI_VFR_RETURN_CODE Status; + + if (!IS_RUN_STATUS(STATUS_COMPILEED)) { + return; + } + + if (gNeedAdjustOpcode) { + // + // When parsing the Vfr, has created some opcodes, now need to update the record info. + // + gCIfrRecordInfoDB.IfrUpdateRecordInfoForDynamicOpcode (FALSE); + } + + // + // Check whether need to check default info for question or auto add default for question. + // + if (mOptions.AutoDefault || mOptions.CheckDefault) { + gCIfrRecordInfoDB.IfrCheckAddDefaultRecord (mOptions.AutoDefault, mOptions.CheckDefault); + } + + // + // Check Binary Code consistent between Form and IfrRecord + // + + // + // Get Package Data and IfrRecord Data + // + gCFormPkg.BuildPkg (gCBuffer); + gCIfrRecordInfoDB.IfrRecordOutput (gRBuffer); + + // + // Compare Form and Record data + // + if (gCBuffer.Buffer != NULL && gRBuffer.Buffer != NULL) { + UINT32 Index; + if (gCBuffer.Size != gRBuffer.Size) { + DebugError (NULL, 0, 0001, "Error parsing vfr file", " %s. FormBinary Size 0x%X is not same to RecordBuffer Size 0x%X", mOptions.VfrFileName, gCBuffer.Size, gRBuffer.Size); + } + for (Index = 0; Index < gCBuffer.Size; Index ++) { + if (gCBuffer.Buffer[Index] != gRBuffer.Buffer[Index]) { + break; + } + } + if (Index != gCBuffer.Size) { + DebugError (NULL, 0, 0001, "Error parsing vfr file", " %s. the 0x%X byte is different between Form and Record", mOptions.VfrFileName, Index); + } + DebugMsg (NULL, 0, 9, (CHAR8 *) "IFR Buffer", (CHAR8 *) "Form Buffer same to Record Buffer and Size is 0x%X", Index); + } else if (gCBuffer.Buffer == NULL && gRBuffer.Buffer == NULL) { + //ok + } else { + DebugError (NULL, 0, 0001, "Error parsing vfr file", " %s.Buffer not allocated.", mOptions.VfrFileName); + } + + return; +} + +VOID +CVfrCompiler::GenBinary ( + VOID + ) +{ + FILE *pFile = NULL; + + if (!IS_RUN_STATUS(STATUS_COMPILEED)) { + goto Fail; + } + + if (mOptions.CreateIfrPkgFile == TRUE) { + if ((pFile = fopen (LongFilePath (mOptions.PkgOutputFileName), "wb")) == NULL) { + DebugError (NULL, 0, 0001, "Error opening file", "%s", mOptions.PkgOutputFileName); + goto Fail; + } + if (gCFormPkg.BuildPkg (pFile, &gRBuffer) != VFR_RETURN_SUCCESS) { + fclose (pFile); + goto Fail; + } + fclose (pFile); + } + + SET_RUN_STATUS (STATUS_GENBINARY); + + return; + +Fail: + if (!IS_RUN_STATUS(STATUS_DEAD)) { + SET_RUN_STATUS (STATUS_FAILED); + } +} + +static const char *gSourceFileHeader[] = { + "//", + "// DO NOT EDIT -- auto-generated file", + "//", + "// This file is generated by the vfrcompiler utility", + "//", + NULL +}; + +VOID +CVfrCompiler::GenCFile ( + VOID + ) +{ + FILE *pFile; + UINT32 Index; + + if (!IS_RUN_STATUS(STATUS_GENBINARY)) { + goto Fail; + } + + if (!mOptions.CreateIfrPkgFile) { + if ((pFile = fopen (LongFilePath (mOptions.COutputFileName), "w")) == NULL) { + DebugError (NULL, 0, 0001, "Error opening output C file", "%s", mOptions.COutputFileName); + goto Fail; + } + + for (Index = 0; gSourceFileHeader[Index] != NULL; Index++) { + fprintf (pFile, "%s\n", gSourceFileHeader[Index]); + } + + if (gCFormPkg.GenCFile (mOptions.VfrBaseFileName, pFile, &gRBuffer) != VFR_RETURN_SUCCESS) { + fclose (pFile); + goto Fail; + } + fclose (pFile); + } + + SET_RUN_STATUS (STATUS_FINISHED); + return; + +Fail: + if (!IS_RUN_STATUS(STATUS_DEAD)) { + SET_RUN_STATUS (STATUS_FAILED); + } +} + +VOID +CVfrCompiler::GenRecordListFile ( + VOID + ) +{ + CHAR8 *InFileName = NULL; + FILE *pInFile = NULL; + FILE *pOutFile = NULL; + CHAR8 LineBuf[MAX_VFR_LINE_LEN]; + UINT32 LineNo; + + InFileName = (mOptions.SkipCPreprocessor == TRUE) ? mOptions.VfrFileName : mOptions.PreprocessorOutputFileName; + + if (mOptions.CreateRecordListFile == TRUE && InFileName != NULL && mOptions.RecordListFile != NULL) { + if ((InFileName[0] == '\0') || (mOptions.RecordListFile[0] == '\0')) { + return; + } + + if ((pInFile = fopen (LongFilePath (InFileName), "r")) == NULL) { + DebugError (NULL, 0, 0001, "Error opening the input VFR preprocessor output file", "%s", InFileName); + return; + } + + if ((pOutFile = fopen (LongFilePath (mOptions.RecordListFile), "w")) == NULL) { + DebugError (NULL, 0, 0001, "Error opening the record list file", "%s", mOptions.RecordListFile); + goto Err1; + } + + fprintf (pOutFile, "//\n// VFR compiler version " VFR_COMPILER_VERSION __BUILD_VERSION "\n//\n"); + LineNo = 0; + while (!feof (pInFile)) { + if (fgets (LineBuf, MAX_VFR_LINE_LEN, pInFile) != NULL) { + fprintf (pOutFile, "%s", LineBuf); + LineNo++; + gCIfrRecordInfoDB.IfrRecordOutput (pOutFile, LineNo); + } + } + + fprintf (pOutFile, "\n//\n// All Opcode Record List \n//\n"); + gCIfrRecordInfoDB.IfrRecordOutput (pOutFile, 0); + gCVfrVarDataTypeDB.Dump(pOutFile); + + fclose (pOutFile); + fclose (pInFile); + } + + return; + +Err1: + fclose (pInFile); +} + +int +main ( + IN int Argc, + IN char **Argv + ) +{ + COMPILER_RUN_STATUS Status; + + SetPrintLevel(WARNING_LOG_LEVEL); + CVfrCompiler Compiler(Argc, Argv); + + Compiler.PreProcess(); + Compiler.Compile(); + Compiler.AdjustBin(); + Compiler.GenBinary(); + Compiler.GenCFile(); + Compiler.GenRecordListFile (); + + Status = Compiler.RunStatus (); + if ((Status == STATUS_DEAD) || (Status == STATUS_FAILED)) { + return 2; + } + + if (gCBuffer.Buffer != NULL) { + delete[] gCBuffer.Buffer; + } + + if (gRBuffer.Buffer != NULL) { + delete[] gRBuffer.Buffer; + } + + return GetUtilityStatus (); +} + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrCompiler.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrCompiler.h new file mode 100644 index 00000000..ce10a58b --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrCompiler.h @@ -0,0 +1,108 @@ +/** @file + + VfrCompiler internal definitions. + +Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _VFRCOMPILER_H_ +#define _VFRCOMPILER_H_ + +#include "Common/UefiBaseTypes.h" +#include "EfiVfr.h" +#include "VfrFormPkg.h" +#include "VfrUtilityLib.h" +#include "ParseInf.h" + +#define PROGRAM_NAME "VfrCompile" +#define VFR_COMPILER_VERSION " 2.01 (UEFI 2.4) " +// +// This is how we invoke the C preprocessor on the VFR source file +// to resolve #defines, #includes, etc. To make C source files +// shareable between VFR and drivers, define VFRCOMPILE so that +// #ifdefs can be used in shared .h files. +// +#define PREPROCESSOR_COMMAND "cl " +#define PREPROCESSOR_OPTIONS "/nologo /E /TC /DVFRCOMPILE " + +// +// Specify the filename extensions for the files we generate. +// +#define VFR_PREPROCESS_FILENAME_EXTENSION ".i" +#define VFR_PACKAGE_FILENAME_EXTENSION ".hpk" +#define VFR_RECORDLIST_FILENAME_EXTENSION ".lst" + +typedef struct { + CHAR8 *VfrFileName; + CHAR8 *RecordListFile; + CHAR8 *PkgOutputFileName; + CHAR8 *COutputFileName; + bool CreateRecordListFile; + bool CreateIfrPkgFile; + CHAR8 *OutputDirectory; + CHAR8 *PreprocessorOutputFileName; + CHAR8 *VfrBaseFileName; // name of input VFR file with no path or extension + CHAR8 *IncludePaths; + bool SkipCPreprocessor; + CHAR8 *CPreprocessorOptions; + BOOLEAN HasOverrideClassGuid; + EFI_GUID OverrideClassGuid; + BOOLEAN WarningAsError; + BOOLEAN AutoDefault; + BOOLEAN CheckDefault; +} OPTIONS; + +typedef enum { + STATUS_STARTED = 0, + STATUS_INITIALIZED, + STATUS_PREPROCESSED, + STATUS_COMPILEED, + STATUS_GENBINARY, + STATUS_FINISHED, + STATUS_FAILED, + STATUS_DEAD, +} COMPILER_RUN_STATUS; + +class CVfrCompiler { +private: + COMPILER_RUN_STATUS mRunStatus; + OPTIONS mOptions; + CHAR8 *mPreProcessCmd; + CHAR8 *mPreProcessOpt; + + VOID OptionInitialization (IN INT32 , IN CHAR8 **); + VOID AppendIncludePath (IN CHAR8 *); + VOID AppendCPreprocessorOptions (IN CHAR8 *); + INT8 SetBaseFileName (VOID); + INT8 SetPkgOutputFileName (VOID); + INT8 SetCOutputFileName(VOID); + INT8 SetPreprocessorOutputFileName (VOID); + INT8 SetRecordListFileName (VOID); + + VOID SET_RUN_STATUS (IN COMPILER_RUN_STATUS); + BOOLEAN IS_RUN_STATUS (IN COMPILER_RUN_STATUS); + +public: + COMPILER_RUN_STATUS RunStatus (VOID) { + return mRunStatus; + } + +public: + CVfrCompiler (IN INT32 , IN CHAR8 **); + ~CVfrCompiler (); + + VOID Usage (VOID); + VOID Version (VOID); + + VOID PreProcess (VOID); + VOID Compile (VOID); + VOID AdjustBin (VOID); + VOID GenBinary (VOID); + VOID GenCFile (VOID); + VOID GenRecordListFile (VOID); + VOID DebugError (IN CHAR8*, IN UINT32, IN UINT32, IN CONST CHAR8*, IN CONST CHAR8*, ...); +}; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrError.cpp b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrError.cpp new file mode 100644 index 00000000..46055604 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrError.cpp @@ -0,0 +1,297 @@ +/** @file + + VfrCompiler error handler. + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "stdio.h" +#include "string.h" +#include "stdlib.h" +#include "VfrError.h" +#include "EfiUtilityMsgs.h" + +static SVFR_ERROR_HANDLE VFR_ERROR_HANDLE_TABLE [] = { + { VFR_RETURN_SUCCESS, NULL }, + { VFR_RETURN_ERROR_SKIPED, NULL }, + { VFR_RETURN_FATAL_ERROR, ": fatal error!!" }, + + { VFR_RETURN_MISMATCHED, ": unexpected token" }, + { VFR_RETURN_INVALID_PARAMETER, ": invalid parameter" }, + { VFR_RETURN_OUT_FOR_RESOURCES, ": system out of memory" }, + { VFR_RETURN_UNSUPPORTED, ": unsupported" }, + { VFR_RETURN_REDEFINED, ": already defined" }, + { VFR_RETURN_FORMID_REDEFINED, ": form id already defined" }, + { VFR_RETURN_QUESTIONID_REDEFINED, ": question id already defined" }, + { VFR_RETURN_VARSTOREID_REDEFINED, ": varstore id already defined" }, + { VFR_RETURN_UNDEFINED, ": undefined" }, + { VFR_RETURN_VAR_NOTDEFINED_BY_QUESTION, ": some variable has not defined by a question"}, + { VFR_RETURN_VARSTORE_DATATYPE_REDEFINED_ERROR, ": Data Structure is defined by more than one varstores, it can't be referred as varstore, only varstore name could be used."}, + { VFR_RETURN_GET_EFIVARSTORE_ERROR, ": get efi varstore error"}, + { VFR_RETURN_EFIVARSTORE_USE_ERROR, ": can not use the efi varstore like this" }, + { VFR_RETURN_EFIVARSTORE_SIZE_ERROR, ": unsupport efi varstore size should be <= 8 bytes" }, + { VFR_RETURN_GET_NVVARSTORE_ERROR, ": get name value varstore error" }, + { VFR_RETURN_QVAR_REUSE, ": variable reused by more than one question" }, + { VFR_RETURN_FLAGS_UNSUPPORTED, ": flags unsupported" }, + { VFR_RETURN_ERROR_ARRARY_NUM, ": array number error, the valid value is in (0 ~ MAX_INDEX-1) for UEFI vfr and in (1 ~ MAX_INDEX) for Framework Vfr" }, + { VFR_RETURN_DATA_STRING_ERROR, ": data field string error or not support"}, + { VFR_RETURN_DEFAULT_VALUE_REDEFINED, ": default value re-defined with different value"}, + { VFR_RETURN_CONSTANT_ONLY, ": only constant is allowed in the expression"}, + { VFR_RETURN_VARSTORE_NAME_REDEFINED_ERROR, ": Varstore name is defined by more than one varstores, it can't be referred as varstore, only varstore structure name could be used."}, + { VFR_RETURN_BIT_WIDTH_ERROR, ": bit width must be <= sizeof (type) * 8 and the max width can not > 32" }, + { VFR_RETURN_STRING_TO_UINT_OVERFLOW, ": String to UINT* Overflow"}, + { VFR_RETURN_CODEUNDEFINED, ": undefined Error Code" } +}; + +static SVFR_WARNING_HANDLE VFR_WARNING_HANDLE_TABLE [] = { + { VFR_WARNING_DEFAULT_VALUE_REDEFINED, ": default value re-defined with different value"}, + { VFR_WARNING_ACTION_WITH_TEXT_TWO, ": Action opcode should not have TextTwo part"}, + { VFR_WARNING_OBSOLETED_FRAMEWORK_OPCODE, ": Not recommend to use obsoleted framework opcode"}, + { VFR_WARNING_CODEUNDEFINED, ": undefined Warning Code" } +}; + +CVfrErrorHandle::CVfrErrorHandle ( + VOID + ) +{ + mInputFileName = NULL; + mScopeRecordListHead = NULL; + mScopeRecordListTail = NULL; + mVfrErrorHandleTable = VFR_ERROR_HANDLE_TABLE; + mVfrWarningHandleTable = VFR_WARNING_HANDLE_TABLE; + mWarningAsError = FALSE; +} + +CVfrErrorHandle::~CVfrErrorHandle ( + VOID + ) +{ + SVfrFileScopeRecord *pNode = NULL; + + if (mInputFileName != NULL) { + delete[] mInputFileName; + } + + while (mScopeRecordListHead != NULL) { + pNode = mScopeRecordListHead; + mScopeRecordListHead = mScopeRecordListHead->mNext; + delete pNode; + } + + mScopeRecordListHead = NULL; + mScopeRecordListTail = NULL; + mVfrErrorHandleTable = NULL; + mVfrWarningHandleTable = NULL; +} + +VOID +CVfrErrorHandle::SetWarningAsError ( + IN BOOLEAN WarningAsError + ) +{ + mWarningAsError = WarningAsError; +} + +VOID +CVfrErrorHandle::SetInputFile ( + IN CHAR8 *InputFile + ) +{ + if (InputFile != NULL) { + mInputFileName = new CHAR8[strlen(InputFile) + 1]; + strcpy (mInputFileName, InputFile); + } +} + +SVfrFileScopeRecord::SVfrFileScopeRecord ( + IN CHAR8 *Record, + IN UINT32 LineNum + ) +{ + UINT32 Index; + CHAR8 *FileName = NULL; + CHAR8 *Str = NULL; + + mWholeScopeLine = LineNum; + mNext = NULL; + + Str = strchr (Record, ' '); + mScopeLineStart = atoi (++Str); + + Str = strchr (Str, '\"'); + FileName = ++Str; + + while((Str = strstr (FileName, "\\\\")) != NULL) { + FileName = Str + 2; + } + if ((mFileName = new CHAR8[strlen(FileName)]) != NULL) { + for (Index = 0; FileName[Index] != '\"'; Index++) { + mFileName[Index] = FileName[Index]; + } + mFileName[Index] = '\0'; + } + + return; +} + +SVfrFileScopeRecord::~SVfrFileScopeRecord ( + VOID + ) +{ + if (mFileName != NULL) { + delete[] mFileName; + } +} + +VOID +CVfrErrorHandle::ParseFileScopeRecord ( + IN CHAR8 *Record, + IN UINT32 WholeScopeLine + ) +{ + SVfrFileScopeRecord *pNode = NULL; + + if (Record == NULL) { + return; + } + + if ((pNode = new SVfrFileScopeRecord(Record, WholeScopeLine)) == NULL) { + return; + } + + if (mScopeRecordListHead == NULL) { + mScopeRecordListTail = mScopeRecordListHead = pNode; + } else { + mScopeRecordListTail->mNext = pNode; + mScopeRecordListTail = pNode; + } +} + +VOID +CVfrErrorHandle::GetFileNameLineNum ( + IN UINT32 LineNum, + OUT CHAR8 **FileName, + OUT UINT32 *FileLine + ) +{ + SVfrFileScopeRecord *pNode = NULL; + + if ((FileName == NULL) || (FileLine == NULL)) { + return; + } + + *FileName = NULL; + *FileLine = 0xFFFFFFFF; + + // + // Some errors occur before scope record list been built. + // + if (mScopeRecordListHead == NULL) { + *FileLine = LineNum; + *FileName = mInputFileName; + return ; + } + + for (pNode = mScopeRecordListHead; pNode->mNext != NULL; pNode = pNode->mNext) { + if ((LineNum > pNode->mWholeScopeLine) && (pNode->mNext->mWholeScopeLine > LineNum)) { + *FileName = pNode->mFileName; + *FileLine = LineNum - pNode->mWholeScopeLine + pNode->mScopeLineStart - 1; + return ; + } + } + + *FileName = pNode->mFileName; + *FileLine = LineNum - pNode->mWholeScopeLine + pNode->mScopeLineStart - 1; +} + +VOID +CVfrErrorHandle::PrintMsg ( + IN UINT32 LineNum, + IN CHAR8 *TokName, + IN CONST CHAR8 *MsgType, + IN CONST CHAR8 *ErrorMsg + ) +{ + CHAR8 *FileName = NULL; + UINT32 FileLine; + + if (strncmp ("Warning", MsgType, strlen ("Warning")) == 0) { + VerboseMsg ((CHAR8 *) ErrorMsg); + return; + } + GetFileNameLineNum (LineNum, &FileName, &FileLine); + Error (FileName, FileLine, 0x3000, TokName, (CHAR8 *) "\t%s\n", (CHAR8 *) ErrorMsg); +} + +UINT8 +CVfrErrorHandle::HandleError ( + IN EFI_VFR_RETURN_CODE ErrorCode, + IN UINT32 LineNum, + IN CHAR8 *TokName + ) +{ + UINT32 Index; + CHAR8 *FileName = NULL; + UINT32 FileLine; + CONST CHAR8 *ErrorMsg = NULL; + + if (mVfrErrorHandleTable == NULL) { + return 1; + } + + for (Index = 0; mVfrErrorHandleTable[Index].mErrorCode != VFR_RETURN_CODEUNDEFINED; Index++) { + if (ErrorCode == mVfrErrorHandleTable[Index].mErrorCode) { + ErrorMsg = mVfrErrorHandleTable[Index].mErrorMsg; + break; + } + } + + if (ErrorMsg != NULL) { + GetFileNameLineNum (LineNum, &FileName, &FileLine); + Error (FileName, FileLine, 0x3000, TokName, (CHAR8 *) "\t%s\n", (CHAR8 *) ErrorMsg); + return 1; + } else { + return 0; + } +} + +UINT8 +CVfrErrorHandle::HandleWarning ( + IN EFI_VFR_WARNING_CODE WarningCode, + IN UINT32 LineNum, + IN CHAR8 *TokName + ) +{ + UINT32 Index; + CHAR8 *FileName = NULL; + UINT32 FileLine; + CONST CHAR8 *WarningMsg = NULL; + + if (mVfrWarningHandleTable == NULL) { + return 1; + } + + GetFileNameLineNum (LineNum, &FileName, &FileLine); + + if (mWarningAsError) { + Error (FileName, FileLine, 0x2220, (CHAR8 *) "warning treated as error", NULL); + } + + for (Index = 0; mVfrWarningHandleTable[Index].mWarningCode != VFR_WARNING_CODEUNDEFINED; Index++) { + if (WarningCode == mVfrWarningHandleTable[Index].mWarningCode) { + WarningMsg = mVfrWarningHandleTable[Index].mWarningMsg; + break; + } + } + + if (WarningMsg != NULL) { + Warning (FileName, FileLine, 0, TokName, (CHAR8 *) "\t%s\n", (CHAR8 *) WarningMsg); + return 1; + } else { + return 0; + } +} + +CVfrErrorHandle gCVfrErrorHandle; diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrError.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrError.h new file mode 100644 index 00000000..04a26d93 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrError.h @@ -0,0 +1,107 @@ +/** @file + + VfrCompiler Error definition + +Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _VFRERROR_H_ +#define _VFRERROR_H_ + +#include "Common/UefiBaseTypes.h" + +typedef enum { + VFR_RETURN_SUCCESS = 0, + VFR_RETURN_ERROR_SKIPED, + VFR_RETURN_FATAL_ERROR, + VFR_RETURN_MISMATCHED, + VFR_RETURN_INVALID_PARAMETER, + VFR_RETURN_OUT_FOR_RESOURCES, + VFR_RETURN_UNSUPPORTED, + VFR_RETURN_REDEFINED, + VFR_RETURN_FORMID_REDEFINED, + VFR_RETURN_QUESTIONID_REDEFINED, + VFR_RETURN_VARSTOREID_REDEFINED, + VFR_RETURN_UNDEFINED, + VFR_RETURN_VAR_NOTDEFINED_BY_QUESTION, + VFR_RETURN_VARSTORE_DATATYPE_REDEFINED_ERROR, + VFR_RETURN_GET_EFIVARSTORE_ERROR, + VFR_RETURN_EFIVARSTORE_USE_ERROR, + VFR_RETURN_EFIVARSTORE_SIZE_ERROR, + VFR_RETURN_GET_NVVARSTORE_ERROR, + VFR_RETURN_QVAR_REUSE, + VFR_RETURN_FLAGS_UNSUPPORTED, + VFR_RETURN_ERROR_ARRARY_NUM, + VFR_RETURN_DATA_STRING_ERROR, + VFR_RETURN_DEFAULT_VALUE_REDEFINED, + VFR_RETURN_CONSTANT_ONLY, + VFR_RETURN_VARSTORE_NAME_REDEFINED_ERROR, + VFR_RETURN_BIT_WIDTH_ERROR, + VFR_RETURN_STRING_TO_UINT_OVERFLOW, + VFR_RETURN_CODEUNDEFINED +} EFI_VFR_RETURN_CODE; + +typedef enum { + VFR_WARNING_DEFAULT_VALUE_REDEFINED = 0, + VFR_WARNING_ACTION_WITH_TEXT_TWO, + VFR_WARNING_OBSOLETED_FRAMEWORK_OPCODE, + VFR_WARNING_CODEUNDEFINED +} EFI_VFR_WARNING_CODE; + +typedef struct _SVFR_ERROR_HANDLE { + EFI_VFR_RETURN_CODE mErrorCode; + CONST CHAR8 *mErrorMsg; +} SVFR_ERROR_HANDLE; + +typedef struct _SVFR_WARNING_HANDLE { + EFI_VFR_WARNING_CODE mWarningCode; + CONST CHAR8 *mWarningMsg; +} SVFR_WARNING_HANDLE; + +struct SVfrFileScopeRecord { + CHAR8 *mFileName; + UINT32 mWholeScopeLine; + UINT32 mScopeLineStart; + SVfrFileScopeRecord *mNext; + + SVfrFileScopeRecord (IN CHAR8 *, IN UINT32); + ~SVfrFileScopeRecord(); + +private: + SVfrFileScopeRecord (IN CONST SVfrFileScopeRecord&); // Prevent copy-construction + SVfrFileScopeRecord& operator= (IN CONST SVfrFileScopeRecord&); // Prevent assignment +}; + +class CVfrErrorHandle { +private: + CHAR8 *mInputFileName; + SVFR_ERROR_HANDLE *mVfrErrorHandleTable; + SVFR_WARNING_HANDLE *mVfrWarningHandleTable; + SVfrFileScopeRecord *mScopeRecordListHead; + SVfrFileScopeRecord *mScopeRecordListTail; + BOOLEAN mWarningAsError; + +public: + CVfrErrorHandle (VOID); + ~CVfrErrorHandle (VOID); + + VOID SetWarningAsError (IN BOOLEAN); + VOID SetInputFile (IN CHAR8 *); + VOID ParseFileScopeRecord (IN CHAR8 *, IN UINT32); + VOID GetFileNameLineNum (IN UINT32, OUT CHAR8 **, OUT UINT32 *); + UINT8 HandleError (IN EFI_VFR_RETURN_CODE, IN UINT32 LineNum = 0, IN CHAR8 *TokName = NULL); + UINT8 HandleWarning (IN EFI_VFR_WARNING_CODE, IN UINT32 LineNum = 0, IN CHAR8 *TokName = NULL); + VOID PrintMsg (IN UINT32 LineNum = 0, IN CHAR8 *TokName = NULL, IN CONST CHAR8 *MsgType = "Error", IN CONST CHAR8 *ErrorMsg = ""); + +private: + CVfrErrorHandle (IN CONST CVfrErrorHandle&); // Prevent copy-construction + CVfrErrorHandle& operator= (IN CONST CVfrErrorHandle&); // Prevent assignment +}; + +#define CHECK_ERROR_RETURN(f, v) do { EFI_VFR_RETURN_CODE r; if ((r = (f)) != (v)) { return r; } } while (0) + +extern CVfrErrorHandle gCVfrErrorHandle; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp new file mode 100644 index 00000000..e80426f6 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrFormPkg.cpp @@ -0,0 +1,2457 @@ +/** @file + + The definition of CFormPkg's member function + +Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "stdio.h" +#include "assert.h" +#include "VfrFormPkg.h" + +/* + * The definition of CFormPkg's member function + */ + +SPendingAssign::SPendingAssign ( + IN CHAR8 *Key, + IN VOID *Addr, + IN UINT32 Len, + IN UINT32 LineNo, + IN CONST CHAR8 *Msg + ) +{ + mKey = NULL; + mAddr = Addr; + mLen = Len; + mFlag = PENDING; + mLineNo = LineNo; + mMsg = NULL; + mNext = NULL; + if (Key != NULL) { + mKey = new CHAR8[strlen (Key) + 1]; + if (mKey != NULL) { + strcpy (mKey, Key); + } + } + + if (Msg != NULL) { + mMsg = new CHAR8[strlen (Msg) + 1]; + if (mMsg != NULL) { + strcpy (mMsg, Msg); + } + } +} + +SPendingAssign::~SPendingAssign ( + VOID + ) +{ + if (mKey != NULL) { + delete[] mKey; + } + mAddr = NULL; + mLen = 0; + mLineNo = 0; + if (mMsg != NULL) { + delete[] mMsg; + } + mNext = NULL; +} + +VOID +SPendingAssign::SetAddrAndLen ( + IN VOID *Addr, + IN UINT32 LineNo + ) +{ + mAddr = Addr; + mLineNo = LineNo; +} + +VOID +SPendingAssign::AssignValue ( + IN VOID *Addr, + IN UINT32 Len + ) +{ + memmove (mAddr, Addr, (mLen < Len ? mLen : Len)); + mFlag = ASSIGNED; +} + +CHAR8 * +SPendingAssign::GetKey ( + VOID + ) +{ + return mKey; +} + +CFormPkg::CFormPkg ( + IN UINT32 BufferSize + ) +{ + CHAR8 *BufferStart; + CHAR8 *BufferEnd; + SBufferNode *Node; + + mPkgLength = 0; + mBufferSize = 0; + mBufferNodeQueueHead = NULL; + mBufferNodeQueueTail = NULL; + mCurrBufferNode = NULL; + mReadBufferNode = NULL; + mReadBufferOffset = 0; + PendingAssignList = NULL; + + Node = new SBufferNode; + if (Node == NULL) { + return ; + } + BufferStart = new CHAR8[BufferSize]; + if (BufferStart == NULL) { + delete Node; + return; + } + BufferEnd = BufferStart + BufferSize; + + memset (BufferStart, 0, BufferSize); + Node->mBufferStart = BufferStart; + Node->mBufferEnd = BufferEnd; + Node->mBufferFree = BufferStart; + Node->mNext = NULL; + + mBufferSize = BufferSize; + mBufferNodeQueueHead = Node; + mBufferNodeQueueTail = Node; + mCurrBufferNode = Node; +} + +CFormPkg::~CFormPkg () +{ + SBufferNode *pBNode; + SPendingAssign *pPNode; + + while (mBufferNodeQueueHead != NULL) { + pBNode = mBufferNodeQueueHead; + mBufferNodeQueueHead = mBufferNodeQueueHead->mNext; + if (pBNode->mBufferStart != NULL) { + delete[] pBNode->mBufferStart; + delete pBNode; + } + } + mBufferNodeQueueTail = NULL; + mCurrBufferNode = NULL; + + while (PendingAssignList != NULL) { + pPNode = PendingAssignList; + PendingAssignList = PendingAssignList->mNext; + delete pPNode; + } + PendingAssignList = NULL; +} + +SBufferNode * +CFormPkg::CreateNewNode ( + VOID + ) +{ + SBufferNode *Node; + + Node = new SBufferNode; + if (Node == NULL) { + return NULL; + } + + Node->mBufferStart = new CHAR8[mBufferSize]; + if (Node->mBufferStart == NULL) { + delete Node; + return NULL; + } else { + memset (Node->mBufferStart, 0, mBufferSize); + Node->mBufferEnd = Node->mBufferStart + mBufferSize; + Node->mBufferFree = Node->mBufferStart; + Node->mNext = NULL; + } + + return Node; +} + +CHAR8 * +CFormPkg::IfrBinBufferGet ( + IN UINT32 Len + ) +{ + CHAR8 *BinBuffer = NULL; + SBufferNode *Node = NULL; + + if ((Len == 0) || (Len > mBufferSize)) { + return NULL; + } + + if ((mCurrBufferNode->mBufferFree + Len) <= mCurrBufferNode->mBufferEnd) { + BinBuffer = mCurrBufferNode->mBufferFree; + mCurrBufferNode->mBufferFree += Len; + } else { + Node = CreateNewNode (); + if (Node == NULL) { + return NULL; + } + + if (mBufferNodeQueueTail == NULL) { + mBufferNodeQueueHead = mBufferNodeQueueTail = Node; + } else { + mBufferNodeQueueTail->mNext = Node; + mBufferNodeQueueTail = Node; + } + mCurrBufferNode = Node; + + // + // Now try again. + // + BinBuffer = mCurrBufferNode->mBufferFree; + mCurrBufferNode->mBufferFree += Len; + } + + mPkgLength += Len; + + return BinBuffer; +} + +inline +UINT32 +CFormPkg::GetPkgLength ( + VOID + ) +{ + return mPkgLength; +} + +VOID +CFormPkg::Open ( + VOID + ) +{ + mReadBufferNode = mBufferNodeQueueHead; + mReadBufferOffset = 0; +} + +VOID +CFormPkg::Close ( + VOID + ) +{ + mReadBufferNode = NULL; + mReadBufferOffset = 0; +} + +UINT32 +CFormPkg::Read ( + IN CHAR8 *Buffer, + IN UINT32 Size + ) +{ + UINT32 Index; + + if ((Size == 0) || (Buffer == NULL)) { + return 0; + } + + if (mReadBufferNode == NULL) { + return 0; + } + + for (Index = 0; Index < Size; Index++) { + if ((mReadBufferNode->mBufferStart + mReadBufferOffset) < mReadBufferNode->mBufferFree) { + Buffer[Index] = mReadBufferNode->mBufferStart[mReadBufferOffset++]; + } else { + if ((mReadBufferNode = mReadBufferNode->mNext) == NULL) { + return Index; + } else { + mReadBufferOffset = 0; + Index --; + } + } + } + + return Size; +} + +EFI_VFR_RETURN_CODE +CFormPkg::BuildPkgHdr ( + OUT EFI_HII_PACKAGE_HEADER **PkgHdr + ) +{ + if (PkgHdr == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + if (((*PkgHdr) = new EFI_HII_PACKAGE_HEADER) == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + + (*PkgHdr)->Type = EFI_HII_PACKAGE_FORM; + (*PkgHdr)->Length = mPkgLength + sizeof (EFI_HII_PACKAGE_HEADER); + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CFormPkg::BuildPkg ( + OUT PACKAGE_DATA &TBuffer + ) +{ + + CHAR8 *Temp; + UINT32 Size; + CHAR8 Buffer[1024]; + + if (TBuffer.Buffer != NULL) { + delete TBuffer.Buffer; + } + + TBuffer.Size = mPkgLength; + TBuffer.Buffer = NULL; + if (TBuffer.Size != 0) { + TBuffer.Buffer = new CHAR8[TBuffer.Size]; + } else { + return VFR_RETURN_SUCCESS; + } + + Temp = TBuffer.Buffer; + Open (); + while ((Size = Read (Buffer, 1024)) != 0) { + memcpy (Temp, Buffer, Size); + Temp += Size; + } + Close (); + return VFR_RETURN_SUCCESS; +} + + +EFI_VFR_RETURN_CODE +CFormPkg::BuildPkg ( + IN FILE *Output, + IN PACKAGE_DATA *PkgData + ) +{ + EFI_VFR_RETURN_CODE Ret; + CHAR8 Buffer[1024]; + UINT32 Size; + EFI_HII_PACKAGE_HEADER *PkgHdr; + + if (Output == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) { + return Ret; + } + fwrite (PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER), 1, Output); + delete PkgHdr; + + if (PkgData == NULL) { + Open (); + while ((Size = Read (Buffer, 1024)) != 0) { + fwrite (Buffer, Size, 1, Output); + } + Close (); + } else { + fwrite (PkgData->Buffer, PkgData->Size, 1, Output); + } + + return VFR_RETURN_SUCCESS; +} + +VOID +CFormPkg::_WRITE_PKG_LINE ( + IN FILE *pFile, + IN UINT32 LineBytes, + IN CONST CHAR8 *LineHeader, + IN CHAR8 *BlkBuf, + IN UINT32 BlkSize + ) +{ + UINT32 Index; + + if ((pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) { + return; + } + + for (Index = 0; Index < BlkSize; Index++) { + if ((Index % LineBytes) == 0) { + fprintf (pFile, "\n%s", LineHeader); + } + fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]); + } +} + +VOID +CFormPkg::_WRITE_PKG_END ( + IN FILE *pFile, + IN UINT32 LineBytes, + IN CONST CHAR8 *LineHeader, + IN CHAR8 *BlkBuf, + IN UINT32 BlkSize + ) +{ + UINT32 Index; + + if ((BlkSize == 0) || (pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) { + return; + } + + for (Index = 0; Index < BlkSize - 1; Index++) { + if ((Index % LineBytes) == 0) { + fprintf (pFile, "\n%s", LineHeader); + } + fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]); + } + + if ((Index % LineBytes) == 0) { + fprintf (pFile, "\n%s", LineHeader); + } + fprintf (pFile, "0x%02X\n", (UINT8)BlkBuf[Index]); +} + +#define BYTES_PRE_LINE 0x10 +UINT32 gAdjustOpcodeOffset = 0; +BOOLEAN gNeedAdjustOpcode = FALSE; +UINT32 gAdjustOpcodeLen = 0; + +EFI_VFR_RETURN_CODE +CFormPkg::GenCFile ( + IN CHAR8 *BaseName, + IN FILE *pFile, + IN PACKAGE_DATA *PkgData + ) +{ + EFI_VFR_RETURN_CODE Ret; + CHAR8 Buffer[BYTES_PRE_LINE * 8]; + EFI_HII_PACKAGE_HEADER *PkgHdr; + UINT32 PkgLength = 0; + UINT32 ReadSize = 0; + + if ((BaseName == NULL) || (pFile == NULL)) { + return VFR_RETURN_FATAL_ERROR; + } + + fprintf (pFile, "\nunsigned char %sBin[] = {\n", BaseName); + + if ((Ret = BuildPkgHdr(&PkgHdr)) != VFR_RETURN_SUCCESS) { + return Ret; + } + + + fprintf (pFile, " // ARRAY LENGTH\n"); + PkgLength = PkgHdr->Length + sizeof (UINT32); + _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&PkgLength, sizeof (UINT32)); + + fprintf (pFile, "\n\n // PACKAGE HEADER\n"); + _WRITE_PKG_LINE(pFile, BYTES_PRE_LINE, " ", (CHAR8 *)PkgHdr, sizeof (EFI_HII_PACKAGE_HEADER)); + PkgLength = sizeof (EFI_HII_PACKAGE_HEADER); + + fprintf (pFile, "\n\n // PACKAGE DATA\n"); + + if (PkgData == NULL) { + Open (); + while ((ReadSize = Read ((CHAR8 *)Buffer, BYTES_PRE_LINE * 8)) != 0) { + PkgLength += ReadSize; + if (PkgLength < PkgHdr->Length) { + _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, " ", Buffer, ReadSize); + } else { + _WRITE_PKG_END (pFile, BYTES_PRE_LINE, " ", Buffer, ReadSize); + } + } + Close (); + } else { + if (PkgData->Size % BYTES_PRE_LINE != 0) { + PkgLength = PkgData->Size - (PkgData->Size % BYTES_PRE_LINE); + _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer, PkgLength); + _WRITE_PKG_END (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer + PkgLength, PkgData->Size % BYTES_PRE_LINE); + } else { + PkgLength = PkgData->Size - BYTES_PRE_LINE; + _WRITE_PKG_LINE (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer, PkgLength); + _WRITE_PKG_END (pFile, BYTES_PRE_LINE, " ", PkgData->Buffer + PkgLength, BYTES_PRE_LINE); + } + } + + delete PkgHdr; + fprintf (pFile, "\n};\n"); + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CFormPkg::AssignPending ( + IN CHAR8 *Key, + IN VOID *ValAddr, + IN UINT32 ValLen, + IN UINT32 LineNo, + IN CONST CHAR8 *Msg + ) +{ + SPendingAssign *pNew; + + pNew = new SPendingAssign (Key, ValAddr, ValLen, LineNo, Msg); + if (pNew == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + + pNew->mNext = PendingAssignList; + PendingAssignList = pNew; + return VFR_RETURN_SUCCESS; +} + +VOID +CFormPkg::DoPendingAssign ( + IN CHAR8 *Key, + IN VOID *ValAddr, + IN UINT32 ValLen + ) +{ + SPendingAssign *pNode; + + if ((Key == NULL) || (ValAddr == NULL)) { + return; + } + + for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mKey, Key) == 0) { + pNode->AssignValue (ValAddr, ValLen); + } + } +} + +bool +CFormPkg::HavePendingUnassigned ( + VOID + ) +{ + SPendingAssign *pNode; + + for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mFlag == PENDING) { + return TRUE; + } + } + + return FALSE; +} + +VOID +CFormPkg::PendingAssignPrintAll ( + VOID + ) +{ + SPendingAssign *pNode; + + for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mFlag == PENDING) { + gCVfrErrorHandle.PrintMsg (pNode->mLineNo, pNode->mKey, "Error", pNode->mMsg); + } + } +} + +SBufferNode * +CFormPkg::GetBinBufferNodeForAddr ( + IN CHAR8 *BinBuffAddr + ) +{ + SBufferNode *TmpNode; + + TmpNode = mBufferNodeQueueHead; + + while (TmpNode != NULL) { + if (TmpNode->mBufferStart <= BinBuffAddr && TmpNode->mBufferFree >= BinBuffAddr) { + return TmpNode; + } + + TmpNode = TmpNode->mNext; + } + + return NULL; +} + +SBufferNode * +CFormPkg::GetNodeBefore( + IN SBufferNode *CurrentNode + ) +{ + SBufferNode *FirstNode = mBufferNodeQueueHead; + SBufferNode *LastNode = mBufferNodeQueueHead; + + while (FirstNode != NULL) { + if (FirstNode == CurrentNode) { + break; + } + + LastNode = FirstNode; + FirstNode = FirstNode->mNext; + } + + if (FirstNode == NULL) { + LastNode = NULL; + } + + return LastNode; +} + +EFI_VFR_RETURN_CODE +CFormPkg::InsertNodeBefore( + IN SBufferNode *CurrentNode, + IN SBufferNode *NewNode + ) +{ + SBufferNode *LastNode = GetNodeBefore (CurrentNode); + + if (LastNode == NULL) { + return VFR_RETURN_MISMATCHED; + } + + NewNode->mNext = LastNode->mNext; + LastNode->mNext = NewNode; + + return VFR_RETURN_SUCCESS; +} + +CHAR8 * +CFormPkg::GetBufAddrBaseOnOffset ( + IN UINT32 Offset + ) +{ + SBufferNode *TmpNode; + UINT32 TotalBufLen; + UINT32 CurrentBufLen; + + TotalBufLen = 0; + + for (TmpNode = mBufferNodeQueueHead; TmpNode != NULL; TmpNode = TmpNode->mNext) { + CurrentBufLen = TmpNode->mBufferFree - TmpNode->mBufferStart; + if (Offset >= TotalBufLen && Offset < TotalBufLen + CurrentBufLen) { + return TmpNode->mBufferStart + (Offset - TotalBufLen); + } + + TotalBufLen += CurrentBufLen; + } + + return NULL; +} + +EFI_VFR_RETURN_CODE +CFormPkg::AdjustDynamicInsertOpcode ( + IN CHAR8 *InserPositionAddr, + IN CHAR8 *InsertOpcodeAddr, + IN BOOLEAN CreateOpcodeAfterParsingVfr + ) +{ + SBufferNode *InserPositionNode; + SBufferNode *InsertOpcodeNode; + SBufferNode *NewRestoreNodeBegin; + SBufferNode *NewRestoreNodeEnd; + SBufferNode *NewLastEndNode; + SBufferNode *TmpNode; + UINT32 NeedRestoreCodeLen; + + NewRestoreNodeEnd = NULL; + + InserPositionNode = GetBinBufferNodeForAddr(InserPositionAddr); + InsertOpcodeNode = GetBinBufferNodeForAddr(InsertOpcodeAddr); + assert (InserPositionNode != NULL); + assert (InsertOpcodeNode != NULL); + + if (InserPositionNode == InsertOpcodeNode) { + // + // Create New Node to save the restore opcode. + // + NeedRestoreCodeLen = InsertOpcodeAddr - InserPositionAddr; + gAdjustOpcodeLen = NeedRestoreCodeLen; + NewRestoreNodeBegin = CreateNewNode (); + if (NewRestoreNodeBegin == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + memcpy (NewRestoreNodeBegin->mBufferFree, InserPositionAddr, NeedRestoreCodeLen); + NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen; + + // + // Override the restore buffer data. + // + memmove (InserPositionAddr, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr); + InsertOpcodeNode->mBufferFree -= NeedRestoreCodeLen; + memset (InsertOpcodeNode->mBufferFree, 0, NeedRestoreCodeLen); + } else { + // + // Create New Node to save the restore opcode. + // + NeedRestoreCodeLen = InserPositionNode->mBufferFree - InserPositionAddr; + gAdjustOpcodeLen = NeedRestoreCodeLen; + NewRestoreNodeBegin = CreateNewNode (); + if (NewRestoreNodeBegin == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + memcpy (NewRestoreNodeBegin->mBufferFree, InserPositionAddr, NeedRestoreCodeLen); + NewRestoreNodeBegin->mBufferFree += NeedRestoreCodeLen; + // + // Override the restore buffer data. + // + InserPositionNode->mBufferFree -= NeedRestoreCodeLen; + // + // Link the restore data to new node. + // + NewRestoreNodeBegin->mNext = InserPositionNode->mNext; + + // + // Count the Adjust opcode len. + // + TmpNode = InserPositionNode->mNext; + while (TmpNode != InsertOpcodeNode) { + gAdjustOpcodeLen += TmpNode->mBufferFree - TmpNode->mBufferStart; + TmpNode = TmpNode->mNext; + } + + // + // Create New Node to save the last node of restore opcode. + // + NeedRestoreCodeLen = InsertOpcodeAddr - InsertOpcodeNode->mBufferStart; + gAdjustOpcodeLen += NeedRestoreCodeLen; + if (NeedRestoreCodeLen > 0) { + NewRestoreNodeEnd = CreateNewNode (); + if (NewRestoreNodeEnd == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + memcpy (NewRestoreNodeEnd->mBufferFree, InsertOpcodeNode->mBufferStart, NeedRestoreCodeLen); + NewRestoreNodeEnd->mBufferFree += NeedRestoreCodeLen; + // + // Override the restore buffer data. + // + memmove (InsertOpcodeNode->mBufferStart, InsertOpcodeAddr, InsertOpcodeNode->mBufferFree - InsertOpcodeAddr); + InsertOpcodeNode->mBufferFree -= InsertOpcodeAddr - InsertOpcodeNode->mBufferStart; + + // + // Insert the last restore data node. + // + TmpNode = GetNodeBefore (InsertOpcodeNode); + assert (TmpNode != NULL); + + if (TmpNode == InserPositionNode) { + NewRestoreNodeBegin->mNext = NewRestoreNodeEnd; + } else { + TmpNode->mNext = NewRestoreNodeEnd; + } + // + // Connect the dynamic opcode node to the node after InserPositionNode. + // + InserPositionNode->mNext = InsertOpcodeNode; + } + } + + if (CreateOpcodeAfterParsingVfr) { + // + // Th new opcodes were created after Parsing Vfr file, + // so the content in mBufferNodeQueueTail must be the new created opcodes. + // So connet the NewRestoreNodeBegin to the tail and update the tail node. + // + mBufferNodeQueueTail->mNext = NewRestoreNodeBegin; + if (NewRestoreNodeEnd != NULL) { + mBufferNodeQueueTail = NewRestoreNodeEnd; + } else { + mBufferNodeQueueTail = NewRestoreNodeBegin; + } + } else { + if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart > 2) { + // + // End form set opcode all in the mBufferNodeQueueTail node. + // + NewLastEndNode = CreateNewNode (); + if (NewLastEndNode == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + NewLastEndNode->mBufferStart[0] = 0x29; + NewLastEndNode->mBufferStart[1] = 0x02; + NewLastEndNode->mBufferFree += 2; + + mBufferNodeQueueTail->mBufferFree -= 2; + + mBufferNodeQueueTail->mNext = NewRestoreNodeBegin; + if (NewRestoreNodeEnd != NULL) { + NewRestoreNodeEnd->mNext = NewLastEndNode; + } else { + NewRestoreNodeBegin->mNext = NewLastEndNode; + } + + mBufferNodeQueueTail = NewLastEndNode; + } else if (mBufferNodeQueueTail->mBufferFree - mBufferNodeQueueTail->mBufferStart == 2) { + TmpNode = GetNodeBefore(mBufferNodeQueueTail); + assert (TmpNode != NULL); + + TmpNode->mNext = NewRestoreNodeBegin; + if (NewRestoreNodeEnd != NULL) { + NewRestoreNodeEnd->mNext = mBufferNodeQueueTail; + } else { + NewRestoreNodeBegin->mNext = mBufferNodeQueueTail; + } + } + } + mCurrBufferNode = mBufferNodeQueueTail; + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CFormPkg::DeclarePendingQuestion ( + IN CVfrVarDataTypeDB &lCVfrVarDataTypeDB, + IN CVfrDataStorage &lCVfrDataStorage, + IN CVfrQuestionDB &lCVfrQuestionDB, + IN EFI_GUID *LocalFormSetGuid, + IN UINT32 LineNo, + OUT CHAR8 **InsertOpcodeAddr + ) +{ + SPendingAssign *pNode; + CHAR8 *VarStr; + UINT32 ArrayIdx; + CHAR8 FName[MAX_NAME_LEN]; + CHAR8 *SName; + CHAR8 *NewStr; + UINT32 ShrinkSize = 0; + EFI_VFR_RETURN_CODE ReturnCode; + EFI_VFR_VARSTORE_TYPE VarStoreType = EFI_VFR_VARSTORE_INVALID; + UINT8 LFlags; + UINT32 MaxValue; + CIfrGuid *GuidObj = NULL; + + // + // Declare all questions as Numeric in DisableIf True + // + // DisableIf + CIfrDisableIf DIObj; + DIObj.SetLineNo (LineNo); + *InsertOpcodeAddr = DIObj.GetObjBinAddr(); + + //TrueOpcode + CIfrTrue TObj (LineNo); + + // Declare Numeric qeustion for each undefined question. + for (pNode = PendingAssignList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mFlag == PENDING) { + EFI_VARSTORE_INFO Info; + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + // + // Register this question, assume it is normal question, not date or time question + // + VarStr = pNode->mKey; + ReturnCode = lCVfrQuestionDB.RegisterQuestion (NULL, VarStr, QId); + if (ReturnCode != VFR_RETURN_SUCCESS) { + gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey); + return ReturnCode; + } + +#ifdef VFREXP_DEBUG + printf ("Undefined Question name is %s and Id is 0x%x\n", VarStr, QId); +#endif + // + // Get Question Info, framework vfr VarName == StructName + // + ReturnCode = lCVfrVarDataTypeDB.ExtractFieldNameAndArrary (VarStr, FName, ArrayIdx); + if (ReturnCode != VFR_RETURN_SUCCESS) { + gCVfrErrorHandle.PrintMsg (pNode->mLineNo, pNode->mKey, "Error", "Var string is not the valid C variable"); + return ReturnCode; + } + // + // Get VarStoreType + // + ReturnCode = lCVfrDataStorage.GetVarStoreId (FName, &Info.mVarStoreId); + if (ReturnCode != VFR_RETURN_SUCCESS) { + gCVfrErrorHandle.PrintMsg (pNode->mLineNo, FName, "Error", "Var Store Type is not defined"); + return ReturnCode; + } + VarStoreType = lCVfrDataStorage.GetVarStoreType (Info.mVarStoreId); + + if (*VarStr == '\0' && ArrayIdx != INVALID_ARRAY_INDEX) { + ReturnCode = lCVfrDataStorage.GetNameVarStoreInfo (&Info, ArrayIdx); + } else { + if (VarStoreType == EFI_VFR_VARSTORE_EFI) { + ReturnCode = lCVfrDataStorage.GetEfiVarStoreInfo (&Info); + } else if (VarStoreType == EFI_VFR_VARSTORE_BUFFER || VarStoreType == EFI_VFR_VARSTORE_BUFFER_BITS) { + VarStr = pNode->mKey; + //convert VarStr with store name to VarStr with structure name + ReturnCode = lCVfrDataStorage.GetBufferVarStoreDataTypeName (Info.mVarStoreId, &SName); + if (ReturnCode == VFR_RETURN_SUCCESS) { + NewStr = new CHAR8[strlen (VarStr) + strlen (SName) + 1]; + NewStr[0] = '\0'; + strcpy (NewStr, SName); + strcat (NewStr, VarStr + strlen (FName)); + ReturnCode = lCVfrVarDataTypeDB.GetDataFieldInfo (NewStr, Info.mInfo.mVarOffset, Info.mVarType, Info.mVarTotalSize, Info.mIsBitVar); + delete[] NewStr; + } + } else { + ReturnCode = VFR_RETURN_UNSUPPORTED; + } + } + if (ReturnCode != VFR_RETURN_SUCCESS) { + gCVfrErrorHandle.HandleError (ReturnCode, pNode->mLineNo, pNode->mKey); + return ReturnCode; + } + // + // If the storage is bit fields, create Guid opcode to wrap the numeric opcode. + // + if (Info.mIsBitVar) { + GuidObj = new CIfrGuid(0); + GuidObj->SetGuid (&gEdkiiIfrBitVarGuid); + GuidObj->SetLineNo(LineNo); + } + + CIfrNumeric CNObj; + CNObj.SetLineNo (LineNo); + CNObj.SetPrompt (0x0); + CNObj.SetHelp (0x0); + CNObj.SetQuestionId (QId); + CNObj.SetVarStoreInfo (&Info); + + // + // Set Min/Max/Step Data and flags for the question with bit fields.Min/Max/Step Data are saved as UINT32 type for bit question. + // + if (Info.mIsBitVar) { + MaxValue = (1 << Info.mVarTotalSize) -1; + CNObj.SetMinMaxStepData ((UINT32) 0, MaxValue, (UINT32) 0); + ShrinkSize = 12; + LFlags = (EDKII_IFR_NUMERIC_SIZE_BIT & Info.mVarTotalSize); + CNObj.SetFlagsForBitField (0, LFlags); + } else { + // + // Numeric doesn't support BOOLEAN data type. + // BOOLEAN type has the same data size to UINT8. + // + if (Info.mVarType == EFI_IFR_TYPE_BOOLEAN) { + Info.mVarType = EFI_IFR_TYPE_NUM_SIZE_8; + } + CNObj.SetFlags (0, Info.mVarType); + // + // Use maximum value not to limit the valid value for the undefined question. + // + switch (Info.mVarType) { + case EFI_IFR_TYPE_NUM_SIZE_64: + CNObj.SetMinMaxStepData ((UINT64) 0, (UINT64) -1 , (UINT64) 0); + ShrinkSize = 0; + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + CNObj.SetMinMaxStepData ((UINT32) 0, (UINT32) -1 , (UINT32) 0); + ShrinkSize = 12; + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + CNObj.SetMinMaxStepData ((UINT16) 0, (UINT16) -1 , (UINT16) 0); + ShrinkSize = 18; + break; + case EFI_IFR_TYPE_NUM_SIZE_8: + CNObj.SetMinMaxStepData ((UINT8) 0, (UINT8) -1 , (UINT8) 0); + ShrinkSize = 21; + break; + default: + break; + } + } + CNObj.ShrinkBinSize (ShrinkSize); + + // + // For undefined Efi VarStore type question + // Append the extended guided opcode to contain VarName + // + if (VarStoreType == EFI_VFR_VARSTORE_EFI) { + CIfrVarEqName CVNObj (QId, Info.mInfo.mVarName); + CVNObj.SetLineNo (LineNo); + } + + // + // End for Numeric + // + CIfrEnd CEObj; + CEObj.SetLineNo (LineNo); + // + // End for Guided opcode + // + if (GuidObj != NULL) { + CIfrEnd CEObjGuid; + CEObjGuid.SetLineNo (LineNo); + GuidObj->SetScope(1); + delete GuidObj; + GuidObj = NULL; + } + } + } + + // + // End for DisableIf + // + CIfrEnd SEObj; + SEObj.SetLineNo (LineNo); + + return VFR_RETURN_SUCCESS; +} + +CFormPkg gCFormPkg; + +SIfrRecord::SIfrRecord ( + VOID + ) +{ + mIfrBinBuf = NULL; + mBinBufLen = 0; + mLineNo = 0xFFFFFFFF; + mOffset = 0xFFFFFFFF; + mNext = NULL; +} + +SIfrRecord::~SIfrRecord ( + VOID + ) +{ + if (mIfrBinBuf != NULL) { + //delete mIfrBinBuf; + mIfrBinBuf = NULL; + } + mLineNo = 0xFFFFFFFF; + mOffset = 0xFFFFFFFF; + mBinBufLen = 0; + mNext = NULL; +} + +CIfrRecordInfoDB::CIfrRecordInfoDB ( + VOID + ) +{ + mSwitch = TRUE; + mRecordCount = EFI_IFR_RECORDINFO_IDX_START; + mIfrRecordListHead = NULL; + mIfrRecordListTail = NULL; + mAllDefaultTypeCount = 0; + for (UINT8 i = 0; i < EFI_HII_MAX_SUPPORT_DEFAULT_TYPE; i++) { + mAllDefaultIdArray[i] = 0xffff; + } +} + +CIfrRecordInfoDB::~CIfrRecordInfoDB ( + VOID + ) +{ + SIfrRecord *pNode; + + while (mIfrRecordListHead != NULL) { + pNode = mIfrRecordListHead; + mIfrRecordListHead = mIfrRecordListHead->mNext; + delete pNode; + } +} + +SIfrRecord * +CIfrRecordInfoDB::GetRecordInfoFromIdx ( + IN UINT32 RecordIdx + ) +{ + UINT32 Idx; + SIfrRecord *pNode = NULL; + + if (RecordIdx == EFI_IFR_RECORDINFO_IDX_INVALUD) { + return NULL; + } + + for (Idx = (EFI_IFR_RECORDINFO_IDX_START + 1), pNode = mIfrRecordListHead; + (Idx != RecordIdx) && (pNode != NULL); + Idx++, pNode = pNode->mNext) + ; + + return pNode; +} + +UINT32 +CIfrRecordInfoDB::IfrRecordRegister ( + IN UINT32 LineNo, + IN CHAR8 *IfrBinBuf, + IN UINT8 BinBufLen, + IN UINT32 Offset + ) +{ + SIfrRecord *pNew; + + if (mSwitch == FALSE) { + return EFI_IFR_RECORDINFO_IDX_INVALUD; + } + + if ((pNew = new SIfrRecord) == NULL) { + return EFI_IFR_RECORDINFO_IDX_INVALUD; + } + + if (mIfrRecordListHead == NULL) { + mIfrRecordListHead = pNew; + mIfrRecordListTail = pNew; + } else { + mIfrRecordListTail->mNext = pNew; + mIfrRecordListTail = pNew; + } + mRecordCount++; + + return mRecordCount; +} + +VOID +CIfrRecordInfoDB::IfrRecordInfoUpdate ( + IN UINT32 RecordIdx, + IN UINT32 LineNo, + IN CHAR8 *BinBuf, + IN UINT8 BinBufLen, + IN UINT32 Offset + ) +{ + SIfrRecord *pNode; + SIfrRecord *Prev; + + if ((pNode = GetRecordInfoFromIdx (RecordIdx)) == NULL) { + return; + } + + if (LineNo == 0) { + // + // Line number is not specified explicitly, try to use line number of previous opcode + // + Prev = GetRecordInfoFromIdx (RecordIdx - 1); + if (Prev != NULL) { + LineNo = Prev->mLineNo; + } + } + + pNode->mLineNo = LineNo; + pNode->mOffset = Offset; + pNode->mBinBufLen = BinBufLen; + pNode->mIfrBinBuf = BinBuf; + +} + +VOID +CIfrRecordInfoDB::IfrRecordOutput ( + OUT PACKAGE_DATA &TBuffer + ) +{ + CHAR8 *Temp; + SIfrRecord *pNode; + + if (TBuffer.Buffer != NULL) { + delete[] TBuffer.Buffer; + } + + TBuffer.Size = 0; + TBuffer.Buffer = NULL; + + + if (mSwitch == FALSE) { + return; + } + + for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) { + TBuffer.Size += pNode->mBinBufLen; + } + + if (TBuffer.Size != 0) { + TBuffer.Buffer = new CHAR8[TBuffer.Size]; + } else { + return; + } + + Temp = TBuffer.Buffer; + + for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mIfrBinBuf != NULL) { + memcpy (Temp, pNode->mIfrBinBuf, pNode->mBinBufLen); + Temp += pNode->mBinBufLen; + } + } + + return; +} + +VOID +CIfrRecordInfoDB::IfrRecordOutput ( + IN FILE *File, + IN UINT32 LineNo + ) +{ + SIfrRecord *pNode; + UINT8 Index; + UINT32 TotalSize; + + if (mSwitch == FALSE) { + return; + } + + if (File == NULL) { + return; + } + + TotalSize = 0; + + for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mLineNo == LineNo || LineNo == 0) { + fprintf (File, ">%08X: ", pNode->mOffset); + TotalSize += pNode->mBinBufLen; + if (pNode->mIfrBinBuf != NULL) { + for (Index = 0; Index < pNode->mBinBufLen; Index++) { + fprintf (File, "%02X ", (UINT8)(pNode->mIfrBinBuf[Index])); + } + } + fprintf (File, "\n"); + } + } + + if (LineNo == 0) { + fprintf (File, "\nTotal Size of all record is 0x%08X\n", TotalSize); + } +} + +// +// for framework vfr file +// adjust opcode sequence for uefi IFR format +// adjust inconsistent and varstore into the right position. +// +BOOLEAN +CIfrRecordInfoDB::CheckQuestionOpCode ( + IN UINT8 OpCode + ) +{ + switch (OpCode) { + case EFI_IFR_CHECKBOX_OP: + case EFI_IFR_NUMERIC_OP: + case EFI_IFR_PASSWORD_OP: + case EFI_IFR_ONE_OF_OP: + case EFI_IFR_ACTION_OP: + case EFI_IFR_STRING_OP: + case EFI_IFR_DATE_OP: + case EFI_IFR_TIME_OP: + case EFI_IFR_ORDERED_LIST_OP: + case EFI_IFR_REF_OP: + return TRUE; + default: + return FALSE; + } +} + +BOOLEAN +CIfrRecordInfoDB::CheckIdOpCode ( + IN UINT8 OpCode + ) +{ + switch (OpCode) { + case EFI_IFR_EQ_ID_VAL_OP: + case EFI_IFR_EQ_ID_ID_OP: + case EFI_IFR_EQ_ID_VAL_LIST_OP: + case EFI_IFR_QUESTION_REF1_OP: + return TRUE; + default: + return FALSE; + } +} + +EFI_QUESTION_ID +CIfrRecordInfoDB::GetOpcodeQuestionId ( + IN EFI_IFR_OP_HEADER *OpHead + ) +{ + EFI_IFR_QUESTION_HEADER *QuestionHead; + + QuestionHead = (EFI_IFR_QUESTION_HEADER *) (OpHead + 1); + + return QuestionHead->QuestionId; +} + +SIfrRecord * +CIfrRecordInfoDB::GetRecordInfoFromOffset ( + IN UINT32 Offset + ) +{ + SIfrRecord *pNode = NULL; + + for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mOffset == Offset) { + return pNode; + } + } + + return pNode; +} + +/** + Add just the op code position. + + Case1 (CreateOpcodeAfterParsingVfr == FALSE): The dynamic opcodes were created before the formset opcode, + so pDynamicOpcodeNodes is before mIfrRecordListTail. + + From + + |mIfrRecordListHead + ...+ pAdjustNode + pDynamicOpcodeNodes + mIfrRecordListTail| + + To + + |mIfrRecordListHead + ...+ pDynamicOpcodeNodes + pAdjustNode + mIfrRecordListTail| + + Case2 (CreateOpcodeAfterParsingVfr == TRUE): The dynamic opcodes were created after paring the vfr file, + so new records are appennded to the end of OriginalIfrRecordListTail. + + From + + |mIfrRecordListHead + ...+ pAdjustNode + ... + OriginalIfrRecordListTail + pDynamicOpcodeNodes| + + To + + |mIfrRecordListHead + ...+ pDynamicOpcodeNodes + pAdjustNode + ... + OriginalIfrRecordListTail| + + + @param CreateOpcodeAfterParsingVfr Whether create the dynamic opcode after parsing the VFR file. + +**/ +BOOLEAN +CIfrRecordInfoDB::IfrAdjustDynamicOpcodeInRecords ( + IN BOOLEAN CreateOpcodeAfterParsingVfr + ) +{ + UINT32 OpcodeOffset; + SIfrRecord *pNode, *pPreNode; + SIfrRecord *pAdjustNode, *pNodeBeforeAdjust; + SIfrRecord *pNodeBeforeDynamic; + + pPreNode = NULL; + pAdjustNode = NULL; + pNodeBeforeDynamic = NULL; + OpcodeOffset = 0; + + // + // Base on the gAdjustOpcodeOffset and gAdjustOpcodeLen to find the pAdjustNod, the node before pAdjustNode, + // and the node before pDynamicOpcodeNode. + // + for (pNode = mIfrRecordListHead; pNode!= NULL; pNode = pNode->mNext) { + if (OpcodeOffset == gAdjustOpcodeOffset) { + pAdjustNode = pNode; + pNodeBeforeAdjust = pPreNode; + } else if (OpcodeOffset == gAdjustOpcodeOffset + gAdjustOpcodeLen) { + pNodeBeforeDynamic = pPreNode; + } + if (pNode->mNext != NULL) { + pPreNode = pNode; + } + OpcodeOffset += pNode->mBinBufLen; + } + + // + // Check the nodes whether exist. + // + if (pNodeBeforeDynamic == NULL || pAdjustNode == NULL || pNodeBeforeAdjust == NULL) { + return FALSE; + } + + // + // Adjust the node. pPreNode save the Node before mIfrRecordListTail + // + pNodeBeforeAdjust->mNext = pNodeBeforeDynamic->mNext; + if (CreateOpcodeAfterParsingVfr) { + // + // mIfrRecordListTail is the end of pDynamicNode (Case2). + // + mIfrRecordListTail->mNext = pAdjustNode; + mIfrRecordListTail = pNodeBeforeDynamic; + mIfrRecordListTail->mNext = NULL; + } else { + // + //pPreNode is the end of pDynamicNode(Case1). + // + pPreNode->mNext = pAdjustNode; + pNodeBeforeDynamic->mNext = mIfrRecordListTail; + } + + return TRUE; +} + +/** + Update the record info(the position in the record list, offset and mIfrBinBuf) for new created record. + + @param CreateOpcodeAfterParsingVfr Whether create the dynamic opcode after parsing the VFR file. + +**/ +VOID +CIfrRecordInfoDB::IfrUpdateRecordInfoForDynamicOpcode ( + IN BOOLEAN CreateOpcodeAfterParsingVfr + ) +{ + SIfrRecord *pRecord; + + // + // Base on the original offset info to update the record list. + // + if (!IfrAdjustDynamicOpcodeInRecords(CreateOpcodeAfterParsingVfr)) { + gCVfrErrorHandle.PrintMsg (0, (CHAR8 *)"Error", (CHAR8 *)"Can not find the adjust offset in the record."); + } + + // + // Base on the opcode binary length to recalculate the offset for each opcode. + // + IfrAdjustOffsetForRecord(); + + // + // Base on the offset to find the binary address. + // + pRecord = GetRecordInfoFromOffset(gAdjustOpcodeOffset); + while (pRecord != NULL) { + pRecord->mIfrBinBuf = gCFormPkg.GetBufAddrBaseOnOffset(pRecord->mOffset); + pRecord = pRecord->mNext; + } +} + + +VOID +CIfrRecordInfoDB::IfrAdjustOffsetForRecord ( + VOID + ) +{ + UINT32 OpcodeOffset; + SIfrRecord *pNode; + + OpcodeOffset = 0; + for (pNode = mIfrRecordListHead; pNode != NULL; pNode = pNode->mNext) { + pNode->mOffset = OpcodeOffset; + OpcodeOffset += pNode->mBinBufLen; + } +} + +EFI_VFR_RETURN_CODE +CIfrRecordInfoDB::IfrRecordAdjust ( + VOID + ) +{ + SIfrRecord *pNode, *preNode; + SIfrRecord *uNode, *tNode; + EFI_IFR_OP_HEADER *OpHead, *tOpHead; + EFI_QUESTION_ID QuestionId; + UINT32 StackCount; + UINT32 QuestionScope; + CHAR8 ErrorMsg[MAX_STRING_LEN] = {0, }; + EFI_VFR_RETURN_CODE Status; + + // + // Init local variable + // + Status = VFR_RETURN_SUCCESS; + pNode = mIfrRecordListHead; + preNode = pNode; + QuestionScope = 0; + while (pNode != NULL) { + OpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf; + + // + // make sure the inconsistent opcode in question scope + // + if (QuestionScope > 0) { + QuestionScope += OpHead->Scope; + if (OpHead->OpCode == EFI_IFR_END_OP) { + QuestionScope --; + } + } + + if (CheckQuestionOpCode (OpHead->OpCode)) { + QuestionScope = 1; + } + // + // for the inconsistent opcode not in question scope, adjust it + // + if (OpHead->OpCode == EFI_IFR_INCONSISTENT_IF_OP && QuestionScope == 0) { + // + // for inconsistent opcode not in question scope + // + + // + // Count inconsistent opcode Scope + // + StackCount = OpHead->Scope; + QuestionId = EFI_QUESTION_ID_INVALID; + tNode = pNode; + while (tNode != NULL && StackCount > 0) { + tNode = tNode->mNext; + tOpHead = (EFI_IFR_OP_HEADER *) tNode->mIfrBinBuf; + // + // Calculate Scope Number + // + StackCount += tOpHead->Scope; + if (tOpHead->OpCode == EFI_IFR_END_OP) { + StackCount --; + } + // + // by IdEqual opcode to get QuestionId + // + if (QuestionId == EFI_QUESTION_ID_INVALID && + CheckIdOpCode (tOpHead->OpCode)) { + QuestionId = *(EFI_QUESTION_ID *) (tOpHead + 1); + } + } + if (tNode == NULL || QuestionId == EFI_QUESTION_ID_INVALID) { + // + // report error; not found + // + sprintf (ErrorMsg, "Inconsistent OpCode Record list invalid QuestionId is 0x%X", QuestionId); + gCVfrErrorHandle.PrintMsg (0, NULL, "Error", ErrorMsg); + Status = VFR_RETURN_MISMATCHED; + break; + } + // + // extract inconsistent opcode list + // pNode is Inconsistent opcode, tNode is End Opcode + // + + // + // insert inconsistent opcode list into the right question scope by questionid + // + for (uNode = mIfrRecordListHead; uNode != NULL; uNode = uNode->mNext) { + tOpHead = (EFI_IFR_OP_HEADER *) uNode->mIfrBinBuf; + if (CheckQuestionOpCode (tOpHead->OpCode) && + (QuestionId == GetOpcodeQuestionId (tOpHead))) { + break; + } + } + // + // insert inconsistent opcode list and check LATE_CHECK flag + // + if (uNode != NULL) { + if ((((EFI_IFR_QUESTION_HEADER *)(tOpHead + 1))->Flags & 0x20) != 0) { + // + // if LATE_CHECK flag is set, change inconsistent to nosumbit + // + OpHead->OpCode = EFI_IFR_NO_SUBMIT_IF_OP; + } + + // + // skip the default storage for Date and Time + // + if ((uNode->mNext != NULL) && (*uNode->mNext->mIfrBinBuf == EFI_IFR_DEFAULT_OP)) { + uNode = uNode->mNext; + } + + preNode->mNext = tNode->mNext; + tNode->mNext = uNode->mNext; + uNode->mNext = pNode; + // + // reset pNode to head list, scan the whole list again. + // + pNode = mIfrRecordListHead; + preNode = pNode; + QuestionScope = 0; + continue; + } else { + // + // not found matched question id, report error + // + sprintf (ErrorMsg, "QuestionId required by Inconsistent OpCode is not found. QuestionId is 0x%X", QuestionId); + gCVfrErrorHandle.PrintMsg (0, NULL, "Error", ErrorMsg); + Status = VFR_RETURN_MISMATCHED; + break; + } + } else if (OpHead->OpCode == EFI_IFR_VARSTORE_OP || + OpHead->OpCode == EFI_IFR_VARSTORE_EFI_OP) { + // + // for new added group of varstore opcode + // + tNode = pNode; + while (tNode->mNext != NULL) { + tOpHead = (EFI_IFR_OP_HEADER *) tNode->mNext->mIfrBinBuf; + if (tOpHead->OpCode != EFI_IFR_VARSTORE_OP && + tOpHead->OpCode != EFI_IFR_VARSTORE_EFI_OP) { + break; + } + tNode = tNode->mNext; + } + + if (tNode->mNext == NULL) { + // + // invalid IfrCode, IfrCode end by EndOpCode + // + gCVfrErrorHandle.PrintMsg (0, NULL, "Error", "No found End Opcode in the end"); + Status = VFR_RETURN_MISMATCHED; + break; + } + + if (tOpHead->OpCode != EFI_IFR_END_OP) { + // + // not new added varstore, which are not needed to be adjust. + // + preNode = tNode; + pNode = tNode->mNext; + continue; + } else { + // + // move new added varstore opcode to the position befor form opcode + // varstore opcode between pNode and tNode + // + + // + // search form opcode from begin + // + for (uNode = mIfrRecordListHead; uNode->mNext != NULL; uNode = uNode->mNext) { + tOpHead = (EFI_IFR_OP_HEADER *) uNode->mNext->mIfrBinBuf; + if (tOpHead->OpCode == EFI_IFR_FORM_OP) { + break; + } + } + // + // Insert varstore opcode beform form opcode if form opcode is found + // + if (uNode->mNext != NULL) { + preNode->mNext = tNode->mNext; + tNode->mNext = uNode->mNext; + uNode->mNext = pNode; + // + // reset pNode to head list, scan the whole list again. + // + pNode = mIfrRecordListHead; + preNode = pNode; + QuestionScope = 0; + continue; + } else { + // + // not found form, continue scan IfrRecord list + // + preNode = tNode; + pNode = tNode->mNext; + continue; + } + } + } + // + // next node + // + preNode = pNode; + pNode = pNode->mNext; + } + + // + // Update Ifr Opcode Offset + // + if (Status == VFR_RETURN_SUCCESS) { + IfrAdjustOffsetForRecord (); + } + return Status; +} + +/** + When the Varstore of the question is EFI_VFR_VARSTORE_BUFFER and the default value is not + given by expression, should save the default info for the Buffer VarStore. + + @param DefaultId The default id. + @param pQuestionNode Point to the question opcode node. + @param Value The default value. +**/ +VOID +CIfrRecordInfoDB::IfrAddDefaultToBufferConfig ( + IN UINT16 DefaultId, + IN SIfrRecord *pQuestionNode, + IN EFI_IFR_TYPE_VALUE Value + ) +{ + CHAR8 *VarStoreName = NULL; + EFI_VFR_VARSTORE_TYPE VarStoreType = EFI_VFR_VARSTORE_INVALID; + EFI_GUID *VarGuid = NULL; + EFI_VARSTORE_INFO VarInfo; + EFI_IFR_QUESTION_HEADER *QuestionHead; + EFI_IFR_OP_HEADER *pQuestionOpHead; + + pQuestionOpHead = (EFI_IFR_OP_HEADER *) pQuestionNode->mIfrBinBuf; + QuestionHead = (EFI_IFR_QUESTION_HEADER *) (pQuestionOpHead + 1); + + // + // Get the Var Store name and type. + // + gCVfrDataStorage.GetVarStoreName (QuestionHead->VarStoreId, &VarStoreName); + VarGuid= gCVfrDataStorage.GetVarStoreGuid (QuestionHead->VarStoreId); + VarStoreType = gCVfrDataStorage.GetVarStoreType (QuestionHead->VarStoreId); + + // + // Only for Buffer storage need to save the default info in the storage. + // Other type storage, just return. + // + if (VarStoreType != EFI_VFR_VARSTORE_BUFFER) { + return; + } else { + VarInfo.mInfo.mVarOffset = QuestionHead->VarStoreInfo.VarOffset; + VarInfo.mVarStoreId = QuestionHead->VarStoreId; + } + + // + // Get the buffer storage info about this question. + // + gCVfrDataStorage.GetBufferVarStoreFieldInfo (&VarInfo); + + // + // Add action. + // + gCVfrDefaultStore.BufferVarStoreAltConfigAdd ( + DefaultId, + VarInfo, + VarStoreName, + VarGuid, + VarInfo.mVarType, + Value + ); +} + +/** + Record the number and default id of all defaultstore opcode. + +**/ +VOID +CIfrRecordInfoDB::IfrGetDefaultStoreInfo ( + VOID + ) +{ + SIfrRecord *pNode; + EFI_IFR_OP_HEADER *pOpHead; + EFI_IFR_DEFAULTSTORE *DefaultStore; + + pNode = mIfrRecordListHead; + mAllDefaultTypeCount = 0; + + while (pNode != NULL) { + pOpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf; + + if (pOpHead->OpCode == EFI_IFR_DEFAULTSTORE_OP){ + DefaultStore = (EFI_IFR_DEFAULTSTORE *) pNode->mIfrBinBuf; + mAllDefaultIdArray[mAllDefaultTypeCount++] = DefaultStore->DefaultId; + } + pNode = pNode->mNext; + } +} + +/** + Create new default opcode record. + + @param Size The new default opcode size. + @param DefaultId The new default id. + @param Type The new default type. + @param LineNo The line number of the new record. + @param Value The new default value. + +**/ +VOID +CIfrRecordInfoDB::IfrCreateDefaultRecord( + IN UINT8 Size, + IN UINT16 DefaultId, + IN UINT8 Type, + IN UINT32 LineNo, + IN EFI_IFR_TYPE_VALUE Value + ) +{ + CIfrDefault *DObj; + CIfrDefault2 *DObj2; + + DObj = NULL; + DObj2 = NULL; + + if (Type == EFI_IFR_TYPE_OTHER) { + DObj2 = new CIfrDefault2 (Size); + DObj2->SetDefaultId(DefaultId); + DObj2->SetType(Type); + DObj2->SetLineNo(LineNo); + DObj2->SetScope (1); + delete DObj2; + } else { + DObj = new CIfrDefault (Size); + DObj->SetDefaultId(DefaultId); + DObj->SetType(Type); + DObj->SetLineNo(LineNo); + DObj->SetValue (Value); + delete DObj; + } +} + +/** + Create new default opcode for question base on the QuestionDefaultInfo. + + @param pQuestionNode Point to the question opcode Node. + @param QuestionDefaultInfo Point to the QuestionDefaultInfo for current question. + +**/ +VOID +CIfrRecordInfoDB::IfrCreateDefaultForQuestion ( + IN SIfrRecord *pQuestionNode, + IN QuestionDefaultRecord *QuestionDefaultInfo + ) +{ + EFI_IFR_OP_HEADER *pOpHead; + EFI_IFR_DEFAULT *Default; + SIfrRecord *pSNode; + SIfrRecord *pENode; + SIfrRecord *pDefaultNode; + CIfrObj *Obj; + CHAR8 *ObjBinBuf; + UINT8 ScopeCount; + UINT8 OpcodeNumber; + UINT8 OpcodeCount; + UINT8 DefaultSize; + EFI_IFR_ONE_OF_OPTION *DefaultOptionOpcode; + EFI_IFR_TYPE_VALUE CheckBoxDefaultValue; + + CheckBoxDefaultValue.b = 1; + pOpHead = (EFI_IFR_OP_HEADER *) pQuestionNode->mIfrBinBuf; + ScopeCount = 0; + OpcodeCount = 0; + Obj = NULL; + + // + // Record the offset of node which need to be adjust, will move the new created default opcode to this offset. + // + gAdjustOpcodeOffset = pQuestionNode->mNext->mOffset; + // + // Case 1: + // For oneof, the default with smallest default id is given by the option flag. + // So create the missing defaults base on the oneof option value(mDefaultValueRecord). + // + if (pOpHead->OpCode == EFI_IFR_ONE_OF_OP && !QuestionDefaultInfo->mIsDefaultOpcode) { + DefaultOptionOpcode = (EFI_IFR_ONE_OF_OPTION *)QuestionDefaultInfo->mDefaultValueRecord->mIfrBinBuf; + DefaultSize = QuestionDefaultInfo->mDefaultValueRecord->mBinBufLen - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value); + DefaultSize += OFFSET_OF (EFI_IFR_DEFAULT, Value); + for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) { + if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { + IfrCreateDefaultRecord (DefaultSize, mAllDefaultIdArray[i], DefaultOptionOpcode->Type, pQuestionNode->mLineNo, DefaultOptionOpcode->Value); + // + // Save the new created default in the buffer storage. + // + IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, DefaultOptionOpcode->Value); + } + } + return; + } + + // + // Case2: + // For checkbox, the default with smallest default id is given by the question flag. + // And create the missing defaults with true value. + // + if (pOpHead-> OpCode == EFI_IFR_CHECKBOX_OP && !QuestionDefaultInfo->mIsDefaultOpcode) { + DefaultSize = OFFSET_OF (EFI_IFR_DEFAULT, Value) + sizeof (BOOLEAN); + for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) { + if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { + IfrCreateDefaultRecord (DefaultSize, mAllDefaultIdArray[i], EFI_IFR_TYPE_BOOLEAN, pQuestionNode->mLineNo, CheckBoxDefaultValue); + // + // Save the new created default. + // + IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, CheckBoxDefaultValue); + } + } + return; + } + + // + // Case3: + // The default with smallest default id is given by the default opcode. + // So create the missing defaults base on the value in the default opcode. + // + + // + // pDefaultNode point to the mDefaultValueRecord in QuestionDefaultInfo. + // + pDefaultNode = QuestionDefaultInfo->mDefaultValueRecord; + Default = (EFI_IFR_DEFAULT *)pDefaultNode->mIfrBinBuf; + // + // Record the offset of node which need to be adjust, will move the new created default opcode to this offset. + // + gAdjustOpcodeOffset = pDefaultNode->mNext->mOffset; + + if (Default->Type == EFI_IFR_TYPE_OTHER) { + // + // EFI_IFR_DEFAULT_2 opcode. + // + // Point to the first expression opcode. + // + pSNode = pDefaultNode->mNext; + pENode = NULL; + ScopeCount++; + // + // Get opcode number behind the EFI_IFR_DEFAULT_2 until reach its END opcode (including the END opcode of EFI_IFR_DEFAULT_2) + // + while (pSNode != NULL && pSNode->mNext != NULL && ScopeCount != 0) { + pOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf; + if (pOpHead->Scope == 1) { + ScopeCount++; + } + if (pOpHead->OpCode == EFI_IFR_END_OP) { + ScopeCount--; + } + pENode = pSNode; + pSNode = pSNode->mNext; + OpcodeCount++; + } + + assert (pSNode); + assert (pENode); + + // + // Record the offset of node which need to be adjust, will move the new created default opcode to this offset. + // + gAdjustOpcodeOffset = pSNode->mOffset; + // + // Create new default opcode node for missing default. + // + for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) { + OpcodeNumber = OpcodeCount; + if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { + IfrCreateDefaultRecord (Default->Header.Length, mAllDefaultIdArray[i], Default->Type, pENode->mLineNo, Default->Value); + // + // Point to the first expression opcode node. + // + pSNode = pDefaultNode->mNext; + // + // Create the expression opcode and end opcode for the new created EFI_IFR_DEFAULT_2 opcode. + // + while (pSNode != NULL && pSNode->mNext != NULL && OpcodeNumber-- != 0) { + pOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf; + Obj = new CIfrObj (pOpHead->OpCode, NULL, pSNode->mBinBufLen, FALSE); + assert (Obj != NULL); + Obj->SetLineNo (pSNode->mLineNo); + ObjBinBuf = Obj->GetObjBinAddr(); + memcpy (ObjBinBuf, pSNode->mIfrBinBuf, (UINTN)pSNode->mBinBufLen); + delete Obj; + pSNode = pSNode->mNext; + } + } + } + } else { + // + // EFI_IFR_DEFAULT opcode. + // + // Create new default opcode node for missing default. + // + for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) { + if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { + IfrCreateDefaultRecord (Default->Header.Length, mAllDefaultIdArray[i], Default->Type, pDefaultNode->mLineNo, Default->Value); + // + // Save the new created default in the buffer storage.. + // + IfrAddDefaultToBufferConfig (mAllDefaultIdArray[i], pQuestionNode, Default->Value); + } + } + } +} + +/** + Parse the default information in a question, get the QuestionDefaultInfo. + + @param pQuestionNode Point to the question record Node. + @param QuestionDefaultInfo On return, point to the QuestionDefaultInfo. +**/ +VOID +CIfrRecordInfoDB::IfrParseDefaulInfoInQuestion( + IN SIfrRecord *pQuestionNode, + OUT QuestionDefaultRecord *QuestionDefaultInfo + ) +{ + SIfrRecord *pSNode; + EFI_IFR_ONE_OF_OPTION *OneofOptionOpcode; + EFI_IFR_OP_HEADER *pSOpHead; + EFI_IFR_CHECKBOX *CheckBoxOpcode; + EFI_IFR_DEFAULT *DefaultOpcode; + BOOLEAN IsOneOfOpcode; + UINT16 SmallestDefaultId; + UINT8 ScopeCount; + + SmallestDefaultId = 0xffff; + IsOneOfOpcode = FALSE; + ScopeCount = 0; + pSNode = pQuestionNode; + + // + // Parse all the opcodes in the Question. + // + while (pSNode != NULL) { + pSOpHead = (EFI_IFR_OP_HEADER *) pSNode->mIfrBinBuf; + // + // For a question, its scope bit must be set, the scope exists until it reaches a corresponding EFI_IFR_END_OP. + // Scopes may be nested within other scopes. + // When finishing parsing a question, the scope count must be zero. + // + if (pSOpHead->Scope == 1) { + ScopeCount++; + } + if (pSOpHead->OpCode == EFI_IFR_END_OP) { + ScopeCount--; + } + // + // Check whether finishing parsing a question. + // + if (ScopeCount == 0) { + break; + } + + // + // Record the default information in the question. + // + switch (pSOpHead->OpCode) { + case EFI_IFR_ONE_OF_OP: + IsOneOfOpcode = TRUE; + break; + case EFI_IFR_CHECKBOX_OP: + // + // The default info of check box may be given by flag. + // So need to check the flag of check box. + // + CheckBoxOpcode = (EFI_IFR_CHECKBOX *)pSNode->mIfrBinBuf; + if ((CheckBoxOpcode->Flags & EFI_IFR_CHECKBOX_DEFAULT) != 0) { + // + // Check whether need to update the smallest default id. + // + if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) { + SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD; + } + // + // Update the QuestionDefaultInfo. + // + for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) { + if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_STANDARD) { + if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { + QuestionDefaultInfo->mDefaultNumber ++; + QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE; + } + break; + } + } + } + if ((CheckBoxOpcode->Flags & EFI_IFR_CHECKBOX_DEFAULT_MFG) != 0) { + // + // Check whether need to update the smallest default id. + // + if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) { + SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING; + } + // + // Update the QuestionDefaultInfo. + // + for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) { + if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) { + if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { + QuestionDefaultInfo->mDefaultNumber ++; + QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE; + } + break; + } + } + } + break; + case EFI_IFR_ONE_OF_OPTION_OP: + if (!IsOneOfOpcode) { + // + // Only check the option in oneof. + // + break; + } + OneofOptionOpcode = (EFI_IFR_ONE_OF_OPTION *)pSNode->mIfrBinBuf; + if ((OneofOptionOpcode->Flags & EFI_IFR_OPTION_DEFAULT) != 0) { + // + // The option is used as the standard default. + // Check whether need to update the smallest default id and QuestionDefaultInfo. + // + if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_STANDARD) { + SmallestDefaultId = EFI_HII_DEFAULT_CLASS_STANDARD; + QuestionDefaultInfo->mDefaultValueRecord = pSNode; + } + // + // Update the IsDefaultIdExist array in QuestionDefaultInfo. + // + for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) { + if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_STANDARD) { + if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { + QuestionDefaultInfo->mDefaultNumber ++; + QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE; + } + break; + } + } + } + if ((OneofOptionOpcode->Flags & EFI_IFR_OPTION_DEFAULT_MFG) != 0) { + // + // This option is used as the manufacture default. + // Check whether need to update the smallest default id and QuestionDefaultInfo. + // + if (SmallestDefaultId > EFI_HII_DEFAULT_CLASS_MANUFACTURING) { + SmallestDefaultId = EFI_HII_DEFAULT_CLASS_MANUFACTURING; + QuestionDefaultInfo->mDefaultValueRecord = pSNode; + } + // + // Update the QuestionDefaultInfo. + // + for (UINT8 i = 0; i < mAllDefaultTypeCount; i++) { + if (mAllDefaultIdArray[i] == EFI_HII_DEFAULT_CLASS_MANUFACTURING) { + if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { + QuestionDefaultInfo->mDefaultNumber ++; + QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE; + } + break; + } + } + } + break; + case EFI_IFR_DEFAULT_OP: + DefaultOpcode = (EFI_IFR_DEFAULT *) pSNode->mIfrBinBuf; + // + // Check whether need to update the smallest default id and QuestionDefaultInfo. + // + if (SmallestDefaultId >= DefaultOpcode->DefaultId ) { + SmallestDefaultId = DefaultOpcode->DefaultId; + QuestionDefaultInfo->mDefaultValueRecord= pSNode; + QuestionDefaultInfo->mIsDefaultOpcode= TRUE; + } + // + // Update the QuestionDefaultInfo. + // + for (UINT8 i = 0; i < mAllDefaultTypeCount; i++){ + if (mAllDefaultIdArray[i] == ((EFI_IFR_DEFAULT *)pSNode->mIfrBinBuf)->DefaultId) { + if (!QuestionDefaultInfo->mIsDefaultIdExist[i]) { + QuestionDefaultInfo->mDefaultNumber ++; + QuestionDefaultInfo->mIsDefaultIdExist[i] = TRUE; + } + break; + } + } + break; + default: + break; + } + // + // Parse next opcode in this question. + // + pSNode = pSNode->mNext; + } +} + +/** + Check or add default for question if need. + + This function will check the default info for question. + If the question has default, but the default number < defaultstore opcode number. + will do following two action : + + 1. if (AutoDefault) will add default for question to support all kinds of defaults. + 2. if (CheckDefault) will generate an error to tell user the question misses some default value. + + We assume that the two options can not be TRUE at same time. + If they are TRUE at same time, only do the action corresponding to AutoDefault option. + + @param AutoDefault Add default for question if needed + @param CheckDefault Check the default info, if missing default, generates an error. + +**/ +VOID +CIfrRecordInfoDB::IfrCheckAddDefaultRecord ( + BOOLEAN AutoDefault, + BOOLEAN CheckDefault + ) +{ + SIfrRecord *pNode; + SIfrRecord *pTailNode; + SIfrRecord *pStartAdjustNode; + EFI_IFR_OP_HEADER *pOpHead; + QuestionDefaultRecord QuestionDefaultInfo; + UINT8 MissingDefaultCount; + CHAR8 Msg[MAX_STRING_LEN] = {0, }; + + pNode = mIfrRecordListHead; + + // + // Record the number and default id of all defaultstore opcode. + // + IfrGetDefaultStoreInfo (); + + while (pNode != NULL) { + pOpHead = (EFI_IFR_OP_HEADER *) pNode->mIfrBinBuf; + // + // Check whether is question opcode. + // + if (CheckQuestionOpCode (pOpHead->OpCode)) { + // + // Initialize some local variables here, because they vary with question. + // Record the mIfrRecordListTail for each question, because may create default node for question after mIfrRecordListTail. + // + memset (&QuestionDefaultInfo, 0, sizeof (QuestionDefaultRecord)); + pTailNode = mIfrRecordListTail; + // + // Get the QuestionDefaultInfo for current question. + // + IfrParseDefaulInfoInQuestion (pNode, &QuestionDefaultInfo); + + if (QuestionDefaultInfo.mDefaultNumber != mAllDefaultTypeCount && QuestionDefaultInfo.mDefaultNumber != 0) { + if (AutoDefault) { + // + // Create default for question which misses default. + // + IfrCreateDefaultForQuestion (pNode, &QuestionDefaultInfo); + + // + // Adjust the buffer content. + // pStartAdjustNode->mIfrBinBuf points to the insert position. + // pTailNode->mNext->mIfrBinBuf points to the inset opcodes. + // + pStartAdjustNode =GetRecordInfoFromOffset (gAdjustOpcodeOffset); + gCFormPkg.AdjustDynamicInsertOpcode (pStartAdjustNode->mIfrBinBuf, pTailNode->mNext->mIfrBinBuf, TRUE); + + // + // Update the record info. + // + IfrUpdateRecordInfoForDynamicOpcode (TRUE); + } else if (CheckDefault) { + // + // Generate an error for question which misses default. + // + MissingDefaultCount = mAllDefaultTypeCount - QuestionDefaultInfo.mDefaultNumber; + sprintf (Msg, "The question misses %d default, the question's opcode is %d", MissingDefaultCount, pOpHead->OpCode); + gCVfrErrorHandle.PrintMsg (pNode->mLineNo, NULL, "Error", Msg); + } + } + } + // + // parse next opcode. + // + pNode = pNode->mNext; + } +} + +CIfrRecordInfoDB gCIfrRecordInfoDB; + +VOID +CIfrObj::_EMIT_PENDING_OBJ ( + VOID + ) +{ + CHAR8 *ObjBinBuf = NULL; + + // + // do nothing + // + if (!mDelayEmit || !gCreateOp) { + return; + } + + mPkgOffset = gCFormPkg.GetPkgLength (); + // + // update data buffer to package data + // + ObjBinBuf = gCFormPkg.IfrBinBufferGet (mObjBinLen); + if (ObjBinBuf != NULL) { + memmove (ObjBinBuf, mObjBinBuf, mObjBinLen); + } + + // + // update bin buffer to package data buffer + // + if (mObjBinBuf != NULL) { + delete[] mObjBinBuf; + mObjBinBuf = ObjBinBuf; + } + + mDelayEmit = FALSE; +} + +/* + * The definition of CIfrObj's member function + */ +static struct { + UINT8 mSize; + UINT8 mScope; +} gOpcodeSizesScopeTable[] = { + { 0, 0 }, // EFI_IFR_INVALID - 0x00 + { sizeof (EFI_IFR_FORM), 1 }, // EFI_IFR_FORM_OP + { sizeof (EFI_IFR_SUBTITLE), 1 }, // EFI_IFR_SUBTITLE_OP + { sizeof (EFI_IFR_TEXT), 0 }, // EFI_IFR_TEXT_OP + { sizeof (EFI_IFR_IMAGE), 0 }, // EFI_IFR_IMAGE_OP + { sizeof (EFI_IFR_ONE_OF), 1 }, // EFI_IFR_ONE_OF_OP - 0x05 + { sizeof (EFI_IFR_CHECKBOX), 1}, // EFI_IFR_CHECKBOX_OP + { sizeof (EFI_IFR_NUMERIC), 1 }, // EFI_IFR_NUMERIC_OP + { sizeof (EFI_IFR_PASSWORD), 1 }, // EFI_IFR_PASSWORD_OP + { sizeof (EFI_IFR_ONE_OF_OPTION), 0 }, // EFI_IFR_ONE_OF_OPTION_OP + { sizeof (EFI_IFR_SUPPRESS_IF), 1 }, // EFI_IFR_SUPPRESS_IF - 0x0A + { sizeof (EFI_IFR_LOCKED), 0 }, // EFI_IFR_LOCKED_OP + { sizeof (EFI_IFR_ACTION), 1 }, // EFI_IFR_ACTION_OP + { sizeof (EFI_IFR_RESET_BUTTON), 1 }, // EFI_IFR_RESET_BUTTON_OP + { sizeof (EFI_IFR_FORM_SET), 1 }, // EFI_IFR_FORM_SET_OP -0xE + { sizeof (EFI_IFR_REF), 0 }, // EFI_IFR_REF_OP + { sizeof (EFI_IFR_NO_SUBMIT_IF), 1}, // EFI_IFR_NO_SUBMIT_IF_OP -0x10 + { sizeof (EFI_IFR_INCONSISTENT_IF), 1 }, // EFI_IFR_INCONSISTENT_IF_OP + { sizeof (EFI_IFR_EQ_ID_VAL), 0 }, // EFI_IFR_EQ_ID_VAL_OP + { sizeof (EFI_IFR_EQ_ID_ID), 0 }, // EFI_IFR_EQ_ID_ID_OP + { sizeof (EFI_IFR_EQ_ID_VAL_LIST), 0 }, // EFI_IFR_EQ_ID_LIST_OP - 0x14 + { sizeof (EFI_IFR_AND), 0 }, // EFI_IFR_AND_OP + { sizeof (EFI_IFR_OR), 0 }, // EFI_IFR_OR_OP + { sizeof (EFI_IFR_NOT), 0 }, // EFI_IFR_NOT_OP + { sizeof (EFI_IFR_RULE), 1 }, // EFI_IFR_RULE_OP + { sizeof (EFI_IFR_GRAY_OUT_IF), 1 }, // EFI_IFR_GRAYOUT_IF_OP - 0x19 + { sizeof (EFI_IFR_DATE), 1 }, // EFI_IFR_DATE_OP + { sizeof (EFI_IFR_TIME), 1 }, // EFI_IFR_TIME_OP + { sizeof (EFI_IFR_STRING), 1 }, // EFI_IFR_STRING_OP + { sizeof (EFI_IFR_REFRESH), 0 }, // EFI_IFR_REFRESH_OP + { sizeof (EFI_IFR_DISABLE_IF), 1 }, // EFI_IFR_DISABLE_IF_OP - 0x1E + { 0, 0 }, // 0x1F + { sizeof (EFI_IFR_TO_LOWER), 0 }, // EFI_IFR_TO_LOWER_OP - 0x20 + { sizeof (EFI_IFR_TO_UPPER), 0 }, // EFI_IFR_TO_UPPER_OP - 0x21 + { sizeof (EFI_IFR_MAP), 1 }, // EFI_IFR_MAP - 0x22 + { sizeof (EFI_IFR_ORDERED_LIST), 1 }, // EFI_IFR_ORDERED_LIST_OP - 0x23 + { sizeof (EFI_IFR_VARSTORE), 0 }, // EFI_IFR_VARSTORE_OP + { sizeof (EFI_IFR_VARSTORE_NAME_VALUE), 0 }, // EFI_IFR_VARSTORE_NAME_VALUE_OP + { sizeof (EFI_IFR_VARSTORE_EFI), 0 }, // EFI_IFR_VARSTORE_EFI_OP + { sizeof (EFI_IFR_VARSTORE_DEVICE), 1 }, // EFI_IFR_VARSTORE_DEVICE_OP + { sizeof (EFI_IFR_VERSION), 0 }, // EFI_IFR_VERSION_OP - 0x28 + { sizeof (EFI_IFR_END), 0 }, // EFI_IFR_END_OP + { sizeof (EFI_IFR_MATCH), 0 }, // EFI_IFR_MATCH_OP - 0x2A + { sizeof (EFI_IFR_GET), 0 }, // EFI_IFR_GET - 0x2B + { sizeof (EFI_IFR_SET), 0 }, // EFI_IFR_SET - 0x2C + { sizeof (EFI_IFR_READ), 0 }, // EFI_IFR_READ - 0x2D + { sizeof (EFI_IFR_WRITE), 0 }, // EFI_IFR_WRITE - 0x2E + { sizeof (EFI_IFR_EQUAL), 0 }, // EFI_IFR_EQUAL_OP - 0x2F + { sizeof (EFI_IFR_NOT_EQUAL), 0 }, // EFI_IFR_NOT_EQUAL_OP + { sizeof (EFI_IFR_GREATER_THAN), 0 }, // EFI_IFR_GREATER_THAN_OP + { sizeof (EFI_IFR_GREATER_EQUAL), 0 }, // EFI_IFR_GREATER_EQUAL_OP + { sizeof (EFI_IFR_LESS_THAN), 0 }, // EFI_IFR_LESS_THAN_OP + { sizeof (EFI_IFR_LESS_EQUAL), 0 }, // EFI_IFR_LESS_EQUAL_OP - 0x34 + { sizeof (EFI_IFR_BITWISE_AND), 0 }, // EFI_IFR_BITWISE_AND_OP + { sizeof (EFI_IFR_BITWISE_OR), 0 }, // EFI_IFR_BITWISE_OR_OP + { sizeof (EFI_IFR_BITWISE_NOT), 0 }, // EFI_IFR_BITWISE_NOT_OP + { sizeof (EFI_IFR_SHIFT_LEFT), 0 }, // EFI_IFR_SHIFT_LEFT_OP + { sizeof (EFI_IFR_SHIFT_RIGHT), 0 }, // EFI_IFR_SHIFT_RIGHT_OP + { sizeof (EFI_IFR_ADD), 0 }, // EFI_IFR_ADD_OP - 0x3A + { sizeof (EFI_IFR_SUBTRACT), 0 }, // EFI_IFR_SUBTRACT_OP + { sizeof (EFI_IFR_MULTIPLY), 0 }, // EFI_IFR_MULTIPLY_OP + { sizeof (EFI_IFR_DIVIDE), 0 }, // EFI_IFR_DIVIDE_OP + { sizeof (EFI_IFR_MODULO), 0 }, // EFI_IFR_MODULO_OP - 0x3E + { sizeof (EFI_IFR_RULE_REF), 0 }, // EFI_IFR_RULE_REF_OP + { sizeof (EFI_IFR_QUESTION_REF1), 0 }, // EFI_IFR_QUESTION_REF1_OP + { sizeof (EFI_IFR_QUESTION_REF2), 0 }, // EFI_IFR_QUESTION_REF2_OP - 0x41 + { sizeof (EFI_IFR_UINT8), 0}, // EFI_IFR_UINT8 + { sizeof (EFI_IFR_UINT16), 0}, // EFI_IFR_UINT16 + { sizeof (EFI_IFR_UINT32), 0}, // EFI_IFR_UINT32 + { sizeof (EFI_IFR_UINT64), 0}, // EFI_IFR_UTNT64 + { sizeof (EFI_IFR_TRUE), 0 }, // EFI_IFR_TRUE_OP - 0x46 + { sizeof (EFI_IFR_FALSE), 0 }, // EFI_IFR_FALSE_OP + { sizeof (EFI_IFR_TO_UINT), 0 }, // EFI_IFR_TO_UINT_OP + { sizeof (EFI_IFR_TO_STRING), 0 }, // EFI_IFR_TO_STRING_OP + { sizeof (EFI_IFR_TO_BOOLEAN), 0 }, // EFI_IFR_TO_BOOLEAN_OP + { sizeof (EFI_IFR_MID), 0 }, // EFI_IFR_MID_OP + { sizeof (EFI_IFR_FIND), 0 }, // EFI_IFR_FIND_OP + { sizeof (EFI_IFR_TOKEN), 0 }, // EFI_IFR_TOKEN_OP + { sizeof (EFI_IFR_STRING_REF1), 0 }, // EFI_IFR_STRING_REF1_OP - 0x4E + { sizeof (EFI_IFR_STRING_REF2), 0 }, // EFI_IFR_STRING_REF2_OP + { sizeof (EFI_IFR_CONDITIONAL), 0 }, // EFI_IFR_CONDITIONAL_OP + { sizeof (EFI_IFR_QUESTION_REF3), 0 }, // EFI_IFR_QUESTION_REF3_OP + { sizeof (EFI_IFR_ZERO), 0 }, // EFI_IFR_ZERO_OP + { sizeof (EFI_IFR_ONE), 0 }, // EFI_IFR_ONE_OP + { sizeof (EFI_IFR_ONES), 0 }, // EFI_IFR_ONES_OP + { sizeof (EFI_IFR_UNDEFINED), 0 }, // EFI_IFR_UNDEFINED_OP + { sizeof (EFI_IFR_LENGTH), 0 }, // EFI_IFR_LENGTH_OP + { sizeof (EFI_IFR_DUP), 0 }, // EFI_IFR_DUP_OP - 0x57 + { sizeof (EFI_IFR_THIS), 0 }, // EFI_IFR_THIS_OP + { sizeof (EFI_IFR_SPAN), 0 }, // EFI_IFR_SPAN_OP + { sizeof (EFI_IFR_VALUE), 1 }, // EFI_IFR_VALUE_OP + { sizeof (EFI_IFR_DEFAULT), 0 }, // EFI_IFR_DEFAULT_OP + { sizeof (EFI_IFR_DEFAULTSTORE), 0 }, // EFI_IFR_DEFAULTSTORE_OP - 0x5C + { sizeof (EFI_IFR_FORM_MAP), 1}, // EFI_IFR_FORM_MAP_OP - 0x5D + { sizeof (EFI_IFR_CATENATE), 0 }, // EFI_IFR_CATENATE_OP + { sizeof (EFI_IFR_GUID), 0 }, // EFI_IFR_GUID_OP + { sizeof (EFI_IFR_SECURITY), 0 }, // EFI_IFR_SECURITY_OP - 0x60 + { sizeof (EFI_IFR_MODAL_TAG), 0}, // EFI_IFR_MODAL_TAG_OP - 0x61 + { sizeof (EFI_IFR_REFRESH_ID), 0}, // EFI_IFR_REFRESH_ID_OP - 0x62 + { sizeof (EFI_IFR_WARNING_IF), 1}, // EFI_IFR_WARNING_IF_OP - 0x63 + { sizeof (EFI_IFR_MATCH2), 0 }, // EFI_IFR_MATCH2_OP - 0x64 +}; + +#ifdef CIFROBJ_DEUBG +static struct { + CHAR8 *mIfrName; +} gIfrObjPrintDebugTable[] = { + "EFI_IFR_INVALID", "EFI_IFR_FORM", "EFI_IFR_SUBTITLE", "EFI_IFR_TEXT", "EFI_IFR_IMAGE", "EFI_IFR_ONE_OF", + "EFI_IFR_CHECKBOX", "EFI_IFR_NUMERIC", "EFI_IFR_PASSWORD", "EFI_IFR_ONE_OF_OPTION", "EFI_IFR_SUPPRESS_IF", "EFI_IFR_LOCKED", + "EFI_IFR_ACTION", "EFI_IFR_RESET_BUTTON", "EFI_IFR_FORM_SET", "EFI_IFR_REF", "EFI_IFR_NO_SUBMIT_IF", "EFI_IFR_INCONSISTENT_IF", + "EFI_IFR_EQ_ID_VAL", "EFI_IFR_EQ_ID_ID", "EFI_IFR_EQ_ID_LIST", "EFI_IFR_AND", "EFI_IFR_OR", "EFI_IFR_NOT", + "EFI_IFR_RULE", "EFI_IFR_GRAY_OUT_IF", "EFI_IFR_DATE", "EFI_IFR_TIME", "EFI_IFR_STRING", "EFI_IFR_REFRESH", + "EFI_IFR_DISABLE_IF", "EFI_IFR_INVALID", "EFI_IFR_TO_LOWER", "EFI_IFR_TO_UPPER", "EFI_IFR_MAP", "EFI_IFR_ORDERED_LIST", + "EFI_IFR_VARSTORE", "EFI_IFR_VARSTORE_NAME_VALUE", "EFI_IFR_VARSTORE_EFI", "EFI_IFR_VARSTORE_DEVICE", "EFI_IFR_VERSION", "EFI_IFR_END", + "EFI_IFR_MATCH", "EFI_IFR_GET", "EFI_IFR_SET", "EFI_IFR_READ", "EFI_IFR_WRITE", "EFI_IFR_EQUAL", + "EFI_IFR_NOT_EQUAL", "EFI_IFR_GREATER_THAN", "EFI_IFR_GREATER_EQUAL", "EFI_IFR_LESS_THAN", "EFI_IFR_LESS_EQUAL", "EFI_IFR_BITWISE_AND", + "EFI_IFR_BITWISE_OR", "EFI_IFR_BITWISE_NOT", "EFI_IFR_SHIFT_LEFT", "EFI_IFR_SHIFT_RIGHT", "EFI_IFR_ADD", "EFI_IFR_SUBTRACT", + "EFI_IFR_MULTIPLY", "EFI_IFR_DIVIDE", "EFI_IFR_MODULO", "EFI_IFR_RULE_REF", "EFI_IFR_QUESTION_REF1", "EFI_IFR_QUESTION_REF2", + "EFI_IFR_UINT8", "EFI_IFR_UINT16", "EFI_IFR_UINT32", "EFI_IFR_UINT64", "EFI_IFR_TRUE", "EFI_IFR_FALSE", + "EFI_IFR_TO_UINT", "EFI_IFR_TO_STRING", "EFI_IFR_TO_BOOLEAN", "EFI_IFR_MID", "EFI_IFR_FIND", "EFI_IFR_TOKEN", + "EFI_IFR_STRING_REF1","EFI_IFR_STRING_REF2", "EFI_IFR_CONDITIONAL", "EFI_IFR_QUESTION_REF3", "EFI_IFR_ZERO", "EFI_IFR_ONE", + "EFI_IFR_ONES", "EFI_IFR_UNDEFINED", "EFI_IFR_LENGTH", "EFI_IFR_DUP", "EFI_IFR_THIS", "EFI_IFR_SPAN", + "EFI_IFR_VALUE", "EFI_IFR_DEFAULT", "EFI_IFR_DEFAULTSTORE", "EFI_IFR_FORM_MAP", "EFI_IFR_CATENATE", "EFI_IFR_GUID", + "EFI_IFR_SECURITY", "EFI_IFR_MODAL_TAG", "EFI_IFR_REFRESH_ID", "EFI_IFR_WARNING_IF", "EFI_IFR_MATCH2", +}; + +VOID +CIFROBJ_DEBUG_PRINT ( + IN UINT8 OpCode + ) +{ + printf ("======Create IFR [%s]\n", gIfrObjPrintDebugTable[OpCode].mIfrName); +} +#else + +#define CIFROBJ_DEBUG_PRINT(OpCode) + +#endif + +BOOLEAN gCreateOp = TRUE; + +CIfrObj::CIfrObj ( + IN UINT8 OpCode, + OUT CHAR8 **IfrObj, + IN UINT8 ObjBinLen, + IN BOOLEAN DelayEmit + ) +{ + mDelayEmit = DelayEmit; + mPkgOffset = gCFormPkg.GetPkgLength (); + mObjBinLen = (ObjBinLen == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : ObjBinLen; + mObjBinBuf = ((DelayEmit == FALSE) && (gCreateOp == TRUE)) ? gCFormPkg.IfrBinBufferGet (mObjBinLen) : new CHAR8[EFI_IFR_MAX_LENGTH]; + mRecordIdx = (gCreateOp == TRUE) ? gCIfrRecordInfoDB.IfrRecordRegister (0xFFFFFFFF, mObjBinBuf, mObjBinLen, mPkgOffset) : EFI_IFR_RECORDINFO_IDX_INVALUD; + mLineNo = 0; + + assert (mObjBinBuf != NULL); + + if (IfrObj != NULL) { + *IfrObj = mObjBinBuf; + } + + CIFROBJ_DEBUG_PRINT (OpCode); +} + +CIfrObj::~CIfrObj ( + VOID + ) +{ + if ((mDelayEmit == TRUE) && ((gCreateOp == TRUE))) { + _EMIT_PENDING_OBJ (); + } + + gCIfrRecordInfoDB.IfrRecordInfoUpdate (mRecordIdx, mLineNo, mObjBinBuf, mObjBinLen, mPkgOffset); +} + +/* + * The definition of CIfrObj's member function + */ +UINT8 gScopeCount = 0; + +CIfrOpHeader::CIfrOpHeader ( + IN UINT8 OpCode, + IN VOID *StartAddr, + IN UINT8 Length + ) : mHeader ((EFI_IFR_OP_HEADER *)StartAddr) +{ + mHeader->OpCode = OpCode; + mHeader->Length = (Length == 0) ? gOpcodeSizesScopeTable[OpCode].mSize : Length; + mHeader->Scope = (gOpcodeSizesScopeTable[OpCode].mScope + gScopeCount > 0) ? 1 : 0; +} + +CIfrOpHeader::CIfrOpHeader ( + IN CIfrOpHeader &OpHdr + ) +{ + mHeader = OpHdr.mHeader; +} + +UINT32 CIfrFormId::FormIdBitMap[EFI_FREE_FORM_ID_BITMAP_SIZE] = {0, }; diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrFormPkg.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrFormPkg.h new file mode 100644 index 00000000..d412de12 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrFormPkg.h @@ -0,0 +1,2776 @@ +/** @file + + The definition of CFormPkg's member function + +Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _EFIIFRCLASS_H_ +#define _EFIIFRCLASS_H_ + +#include "string.h" +#include "EfiVfr.h" +#include "VfrError.h" +#include "VfrUtilityLib.h" + +#define NO_QST_REFED "no question refered" + +struct PACKAGE_DATA { + CHAR8 *Buffer; + UINT32 Size; +}; + +/* + * The functions below are used for flags setting + */ +static inline BOOLEAN _FLAGS_ZERO ( + IN UINT8 &Flags + ) +{ + return Flags == 0; +} + +static inline VOID _FLAG_CLEAR ( + IN UINT8 &Flags, + IN UINT8 Mask + ) +{ + Flags &= (~Mask); +} + +static inline UINT8 _FLAG_TEST_AND_CLEAR ( + IN UINT8 &Flags, + IN UINT8 Mask + ) +{ + UINT8 Ret = Flags & Mask; + Flags &= (~Mask); + return Ret; +} + +static inline UINT8 _IS_EQUAL ( + IN UINT8 &Flags, + IN UINT8 Value + ) +{ + return Flags == Value; +} + +/* + * The definition of CIfrBin + */ +typedef enum { + PENDING, + ASSIGNED +} ASSIGN_FLAG; + +struct SPendingAssign { + CHAR8 *mKey; // key ! unique + VOID *mAddr; + UINT32 mLen; + ASSIGN_FLAG mFlag; + UINT32 mLineNo; + CHAR8 *mMsg; + struct SPendingAssign *mNext; + + SPendingAssign (IN CHAR8 *, IN VOID *, IN UINT32, IN UINT32, IN CONST CHAR8 *); + ~SPendingAssign (); + + VOID SetAddrAndLen (IN VOID *, IN UINT32); + VOID AssignValue (IN VOID *, IN UINT32); + CHAR8 * GetKey (VOID); + +private: + SPendingAssign (IN CONST SPendingAssign&); // Prevent copy-construction + SPendingAssign& operator= (IN CONST SPendingAssign&); // Prevent assignment +}; + +struct SBufferNode { + CHAR8 *mBufferStart; + CHAR8 *mBufferEnd; + CHAR8 *mBufferFree; + struct SBufferNode *mNext; +}; + +typedef struct { + EFI_GUID *OverrideClassGuid; +} INPUT_INFO_TO_SYNTAX; + +class CFormPkg { +private: + UINT32 mBufferSize; + SBufferNode *mBufferNodeQueueHead; + SBufferNode *mBufferNodeQueueTail; + SBufferNode *mCurrBufferNode; + + SBufferNode *mReadBufferNode; + UINT32 mReadBufferOffset; + + UINT32 mPkgLength; + + VOID _WRITE_PKG_LINE (IN FILE *, IN UINT32 , IN CONST CHAR8 *, IN CHAR8 *, IN UINT32); + VOID _WRITE_PKG_END (IN FILE *, IN UINT32 , IN CONST CHAR8 *, IN CHAR8 *, IN UINT32); + SBufferNode * GetBinBufferNodeForAddr (IN CHAR8 *); + SBufferNode * CreateNewNode (); + SBufferNode * GetNodeBefore (IN SBufferNode *); + EFI_VFR_RETURN_CODE InsertNodeBefore (IN SBufferNode *, IN SBufferNode *); + +private: + SPendingAssign *PendingAssignList; + +public: + CFormPkg (IN UINT32 BufferSize = 4096); + ~CFormPkg (); + + CHAR8 * IfrBinBufferGet (IN UINT32); + inline UINT32 GetPkgLength (VOID); + + VOID Open (); + UINT32 Read (IN CHAR8 *, IN UINT32); + VOID Close (); + + EFI_VFR_RETURN_CODE BuildPkgHdr (OUT EFI_HII_PACKAGE_HEADER **); + EFI_VFR_RETURN_CODE BuildPkg (IN FILE *, IN PACKAGE_DATA *PkgData = NULL); + EFI_VFR_RETURN_CODE BuildPkg (OUT PACKAGE_DATA &); + EFI_VFR_RETURN_CODE GenCFile (IN CHAR8 *, IN FILE *, IN PACKAGE_DATA *PkgData = NULL); + +private: + CFormPkg (IN CONST CFormPkg&); // Prevent copy-construction + CFormPkg& operator= (IN CONST CFormPkg&); // Prevent assignment + +public: + EFI_VFR_RETURN_CODE AssignPending (IN CHAR8 *, IN VOID *, IN UINT32, IN UINT32, IN CONST CHAR8 *Msg = NULL); + VOID DoPendingAssign (IN CHAR8 *, IN VOID *, IN UINT32); + bool HavePendingUnassigned (VOID); + VOID PendingAssignPrintAll (VOID); + EFI_VFR_RETURN_CODE DeclarePendingQuestion ( + IN CVfrVarDataTypeDB &lCVfrVarDataTypeDB, + IN CVfrDataStorage &lCVfrDataStorage, + IN CVfrQuestionDB &lCVfrQuestionDB, + IN EFI_GUID *LocalFormSetGuid, + IN UINT32 LineNo, + OUT CHAR8 **InsertOpcodeAddr + ); + EFI_VFR_RETURN_CODE AdjustDynamicInsertOpcode ( + IN CHAR8 *LastFormEndAddr, + IN CHAR8 *InsertOpcodeAddr, + IN BOOLEAN CreateOpcodeAfterParsingVfr + ); + CHAR8 * GetBufAddrBaseOnOffset ( + IN UINT32 Offset + ); +}; + +extern CFormPkg gCFormPkg; +extern CVfrStringDB gCVfrStringDB; +extern UINT32 gAdjustOpcodeOffset; +extern BOOLEAN gNeedAdjustOpcode; + +struct SIfrRecord { + UINT32 mLineNo; + CHAR8 *mIfrBinBuf; + UINT8 mBinBufLen; + UINT32 mOffset; + SIfrRecord *mNext; + + SIfrRecord (VOID); + ~SIfrRecord (VOID); +}; + + +#define EFI_IFR_RECORDINFO_IDX_INVALUD 0xFFFFFF +#define EFI_IFR_RECORDINFO_IDX_START 0x0 +#define EFI_HII_MAX_SUPPORT_DEFAULT_TYPE 0x08 + +struct QuestionDefaultRecord { + BOOLEAN mIsDefaultIdExist[EFI_HII_MAX_SUPPORT_DEFAULT_TYPE]; // Record the default id in mAllDefaultIdArray[EFI_HII_MAX_SUPPORT_DEFAULT_TYPE] + // whether exists in current question. + + SIfrRecord *mDefaultValueRecord; // Point to the default value record in RecordList which has smallest default Id. + // (for checkbox it may be NULL, because the dedault value is always true when the flag is set.) + + BOOLEAN mIsDefaultOpcode; // whether the default value with smallest default id is given by default opcode. + // (for oneof and checkbox default info may be given by flag.) + + UINT16 mDefaultNumber; // The default number of this question. +}; + +class CIfrRecordInfoDB { +private: + bool mSwitch; + UINT32 mRecordCount; + SIfrRecord *mIfrRecordListHead; + SIfrRecord *mIfrRecordListTail; + UINT8 mAllDefaultTypeCount; + UINT16 mAllDefaultIdArray[EFI_HII_MAX_SUPPORT_DEFAULT_TYPE]; + + SIfrRecord * GetRecordInfoFromIdx (IN UINT32); + BOOLEAN CheckQuestionOpCode (IN UINT8); + BOOLEAN CheckIdOpCode (IN UINT8); + EFI_QUESTION_ID GetOpcodeQuestionId (IN EFI_IFR_OP_HEADER *); +public: + CIfrRecordInfoDB (VOID); + ~CIfrRecordInfoDB (VOID); + + inline VOID TurnOn (VOID) { + mSwitch = TRUE; + } + + inline VOID TurnOff (VOID) { + mSwitch = FALSE; + } + + SIfrRecord * GetRecordInfoFromOffset (IN UINT32); + VOID IfrAdjustOffsetForRecord (VOID); + BOOLEAN IfrAdjustDynamicOpcodeInRecords (IN BOOLEAN); + + UINT32 IfrRecordRegister (IN UINT32, IN CHAR8 *, IN UINT8, IN UINT32); + VOID IfrRecordInfoUpdate (IN UINT32, IN UINT32, IN CHAR8*, IN UINT8, IN UINT32); + VOID IfrRecordOutput (IN FILE *, IN UINT32 LineNo); + VOID IfrRecordOutput (OUT PACKAGE_DATA &); + EFI_VFR_RETURN_CODE IfrRecordAdjust (VOID); + VOID IfrUpdateRecordInfoForDynamicOpcode (IN BOOLEAN); + VOID IfrCheckAddDefaultRecord (IN BOOLEAN, IN BOOLEAN); + VOID IfrGetDefaultStoreInfo (); + VOID IfrCreateDefaultRecord (IN UINT8 Size,IN UINT16 DefaultId,IN UINT8 Type,IN UINT32 LineNo,IN EFI_IFR_TYPE_VALUE Value); + VOID IfrCreateDefaultForQuestion (IN SIfrRecord *, IN QuestionDefaultRecord *); + VOID IfrParseDefaulInfoInQuestion (IN SIfrRecord *, OUT QuestionDefaultRecord *); + VOID IfrAddDefaultToBufferConfig (IN UINT16, IN SIfrRecord *,IN EFI_IFR_TYPE_VALUE); + +private: + CIfrRecordInfoDB (IN CONST CIfrRecordInfoDB&); // Prevent copy-construction + CIfrRecordInfoDB& operator= (IN CONST CIfrRecordInfoDB&); // Prevent assignment +}; + +extern CIfrRecordInfoDB gCIfrRecordInfoDB; + +/* + * The definition of CIfrObj + */ +extern BOOLEAN gCreateOp; + +class CIfrObj { +private: + BOOLEAN mDelayEmit; + + CHAR8 *mObjBinBuf; + UINT8 mObjBinLen; + UINT32 mLineNo; + UINT32 mRecordIdx; + UINT32 mPkgOffset; + +public: + CIfrObj (IN UINT8 OpCode, OUT CHAR8 **IfrObj = NULL, IN UINT8 ObjBinLen = 0, IN BOOLEAN DelayEmit = FALSE); + virtual ~CIfrObj(VOID); + + VOID _EMIT_PENDING_OBJ (VOID); + + inline VOID SetLineNo (IN UINT32 LineNo) { + mLineNo = LineNo; + } + + template + inline T * GetObjBinAddr (VOID) { + return reinterpret_cast(mObjBinBuf); + } + + inline UINT32 GetObjBinOffset (VOID) { + return mPkgOffset; + } + + inline UINT8 GetObjBinLen (VOID) { + return mObjBinLen; + } + + inline bool ExpendObjBin (IN UINT8 Size) { + if ((mDelayEmit == TRUE) && ((mObjBinLen + Size) > mObjBinLen)) { + mObjBinLen = mObjBinLen + Size; + return TRUE; + } else { + return FALSE; + } + } + + inline bool ShrinkObjBin (IN UINT8 Size) { + if ((mDelayEmit == TRUE) && (mObjBinLen > Size)) { + mObjBinLen -= Size; + return TRUE; + } else { + return FALSE; + } + } +}; + +/* + * The definition of CIfrOpHeader + */ +class CIfrOpHeader { +private: + EFI_IFR_OP_HEADER *mHeader; + +public: + CIfrOpHeader (IN UINT8 OpCode, IN VOID *StartAddr, IN UINT8 Length = 0); + CIfrOpHeader (IN CIfrOpHeader &); + CIfrOpHeader& operator=(IN CONST CIfrOpHeader &); + + VOID IncLength (UINT8 Size) { + if ((mHeader->Length + Size) > mHeader->Length) { + mHeader->Length = mHeader->Length + Size; + } + } + + VOID DecLength (UINT8 Size) { + if (mHeader->Length >= Size) { + mHeader->Length -= Size; + } + } + + UINT8 GetLength () { + return mHeader->Length; + } + + UINT8 GetScope () { + return mHeader->Scope; + } + + VOID SetScope (IN UINT8 Scope) { + mHeader->Scope = Scope; + } + + VOID UpdateHeader (IN EFI_IFR_OP_HEADER *Header) { + mHeader = Header; + } + + UINT8 GetOpCode () { + return mHeader->OpCode; + } +}; + +extern UINT8 gScopeCount; + +/* + * The definition of CIfrStatementHeader + */ +class CIfrStatementHeader { +private: + EFI_IFR_STATEMENT_HEADER *mHeader; + +public: + CIfrStatementHeader ( + IN EFI_IFR_STATEMENT_HEADER *StartAddr + ) : mHeader ((EFI_IFR_STATEMENT_HEADER *)StartAddr) { + mHeader = StartAddr; + mHeader->Help = EFI_STRING_ID_INVALID; + mHeader->Prompt = EFI_STRING_ID_INVALID; + } + + EFI_IFR_STATEMENT_HEADER *GetStatementHeader () { + return mHeader; + } + + VOID SetPrompt (IN EFI_STRING_ID Prompt) { + mHeader->Prompt = Prompt; + } + + VOID SetHelp (IN EFI_STRING_ID Help) { + mHeader->Help = Help; + } +}; + +/* + * The definition of CIfrQuestionHeader + */ +#define EFI_IFR_QUESTION_FLAG_DEFAULT 0 + +class CIfrQuestionHeader : public CIfrStatementHeader { +private: + EFI_IFR_QUESTION_HEADER *mHeader; + + EFI_IFR_STATEMENT_HEADER * QH2SH (EFI_IFR_QUESTION_HEADER *Qheader) { + return &(Qheader)->Header; + } + +public: + EFI_QUESTION_ID QUESTION_ID (VOID) { + return mHeader->QuestionId; + } + + EFI_VARSTORE_ID VARSTORE_ID (VOID) { + return mHeader->VarStoreId; + } + + VOID VARSTORE_INFO (OUT EFI_VARSTORE_INFO *Info) { + if (Info != NULL) { + Info->mVarStoreId = mHeader->VarStoreId; + memmove (&Info->mVarStoreId, &mHeader->VarStoreInfo, sizeof (Info->mVarStoreId)); + } + } + + UINT8 FLAGS (VOID) { + return mHeader->Flags; + } + +public: + CIfrQuestionHeader ( + IN EFI_IFR_QUESTION_HEADER *StartAddr, + IN UINT8 Flags = EFI_IFR_QUESTION_FLAG_DEFAULT + ) : CIfrStatementHeader (QH2SH(StartAddr)) { + mHeader = StartAddr; + mHeader->QuestionId = EFI_QUESTION_ID_INVALID; + mHeader->VarStoreId = EFI_VARSTORE_ID_INVALID; + mHeader->VarStoreInfo.VarName = EFI_STRING_ID_INVALID; + mHeader->VarStoreInfo.VarOffset = EFI_VAROFFSET_INVALID; + mHeader->Flags = Flags; + } + + VOID SetQuestionId (IN EFI_QUESTION_ID QuestionId) { + mHeader->QuestionId = QuestionId; + } + + VOID SetVarStoreInfo (IN EFI_VARSTORE_INFO *Info) { + mHeader->VarStoreId = Info->mVarStoreId; + mHeader->VarStoreInfo.VarName = Info->mInfo.mVarName; + mHeader->VarStoreInfo.VarOffset = Info->mInfo.mVarOffset; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 Flags) { + if (_FLAG_TEST_AND_CLEAR (Flags, EFI_IFR_FLAG_READ_ONLY)) { + mHeader->Flags |= EFI_IFR_FLAG_READ_ONLY; + } + + _FLAG_CLEAR (Flags, 0x02); + + if (_FLAG_TEST_AND_CLEAR (Flags, EFI_IFR_FLAG_CALLBACK)) { + mHeader->Flags |= EFI_IFR_FLAG_CALLBACK; + } + + // + // ignore NVAccessFlag + // + _FLAG_CLEAR (Flags, 0x08); + + if (_FLAG_TEST_AND_CLEAR (Flags, EFI_IFR_FLAG_RESET_REQUIRED)) { + mHeader->Flags |= EFI_IFR_FLAG_RESET_REQUIRED; + } + + if (_FLAG_TEST_AND_CLEAR (Flags, EFI_IFR_FLAG_RECONNECT_REQUIRED)) { + mHeader->Flags |= EFI_IFR_FLAG_RECONNECT_REQUIRED; + } + + // + // Set LateCheck Flag to compatible for framework flag + // but it uses 0x20 as its flag, if in the future UEFI may take this flag + // + if (_FLAG_TEST_AND_CLEAR (Flags, 0x20)) { + mHeader->Flags |= 0x20; + } + + if (_FLAG_TEST_AND_CLEAR (Flags, EFI_IFR_FLAG_OPTIONS_ONLY)) { + mHeader->Flags |= EFI_IFR_FLAG_OPTIONS_ONLY; + } + + return _FLAGS_ZERO (Flags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } + + VOID UpdateCIfrQuestionHeader (IN EFI_IFR_QUESTION_HEADER *Header) { + mHeader = Header; + } +}; + +/* + * The definition of CIfrMinMaxStepData + */ +class CIfrMinMaxStepData { +private: + MINMAXSTEP_DATA *mMinMaxStepData; + BOOLEAN ValueIsSet; + BOOLEAN IsNumeric; + +public: + CIfrMinMaxStepData (MINMAXSTEP_DATA *DataAddr, BOOLEAN NumericOpcode=FALSE) : mMinMaxStepData (DataAddr) { + mMinMaxStepData->u64.MinValue = 0; + mMinMaxStepData->u64.MaxValue = 0; + mMinMaxStepData->u64.Step = 0; + ValueIsSet = FALSE; + IsNumeric = NumericOpcode; + } + + VOID SetMinMaxStepData (IN UINT64 MinValue, IN UINT64 MaxValue, IN UINT64 Step) { + if (!ValueIsSet) { + mMinMaxStepData->u64.MinValue = MinValue; + mMinMaxStepData->u64.MaxValue = MaxValue; + ValueIsSet = TRUE; + } else { + if (MinValue < mMinMaxStepData->u64.MinValue) { + mMinMaxStepData->u64.MinValue = MinValue; + } + if (MaxValue > mMinMaxStepData->u64.MaxValue) { + mMinMaxStepData->u64.MaxValue = MaxValue; + } + } + mMinMaxStepData->u64.Step = Step; + } + + VOID SetMinMaxStepData (IN UINT32 MinValue, IN UINT32 MaxValue, IN UINT32 Step) { + if (!ValueIsSet) { + mMinMaxStepData->u32.MinValue = MinValue; + mMinMaxStepData->u32.MaxValue = MaxValue; + ValueIsSet = TRUE; + } else { + if (MinValue < mMinMaxStepData->u32.MinValue) { + mMinMaxStepData->u32.MinValue = MinValue; + } + if (MaxValue > mMinMaxStepData->u32.MaxValue) { + mMinMaxStepData->u32.MaxValue = MaxValue; + } + } + mMinMaxStepData->u32.Step = Step; + } + + VOID SetMinMaxStepData (IN UINT16 MinValue, IN UINT16 MaxValue, IN UINT16 Step) { + if (!ValueIsSet) { + mMinMaxStepData->u16.MinValue = MinValue; + mMinMaxStepData->u16.MaxValue = MaxValue; + ValueIsSet = TRUE; + } else { + if (MinValue < mMinMaxStepData->u16.MinValue) { + mMinMaxStepData->u16.MinValue = MinValue; + } + if (MaxValue > mMinMaxStepData->u16.MaxValue) { + mMinMaxStepData->u16.MaxValue = MaxValue; + } + } + mMinMaxStepData->u16.Step = Step; + } + + VOID SetMinMaxStepData (IN UINT8 MinValue, IN UINT8 MaxValue, IN UINT8 Step) { + if (!ValueIsSet) { + mMinMaxStepData->u8.MinValue = MinValue; + mMinMaxStepData->u8.MaxValue = MaxValue; + ValueIsSet = TRUE; + } else { + if (MinValue < mMinMaxStepData->u8.MinValue) { + mMinMaxStepData->u8.MinValue = MinValue; + } + if (MaxValue > mMinMaxStepData->u8.MaxValue) { + mMinMaxStepData->u8.MaxValue = MaxValue; + } + } + mMinMaxStepData->u8.Step = Step; + } + + UINT64 GetMinData (UINT8 VarType, BOOLEAN IsBitVar) { + UINT64 MinValue = 0; + if (IsBitVar) { + MinValue = mMinMaxStepData->u32.MinValue; + return MinValue; + } + switch (VarType) { + case EFI_IFR_TYPE_NUM_SIZE_64: + MinValue = mMinMaxStepData->u64.MinValue; + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + MinValue = (UINT64) mMinMaxStepData->u32.MinValue; + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + MinValue = (UINT64) mMinMaxStepData->u16.MinValue; + break; + case EFI_IFR_TYPE_NUM_SIZE_8: + MinValue = (UINT64) mMinMaxStepData->u8.MinValue; + break; + default: + break; + } + return MinValue; + } + + UINT64 GetMaxData (UINT8 VarType, BOOLEAN IsBitVar) { + UINT64 MaxValue = 0; + if (IsBitVar) { + MaxValue = mMinMaxStepData->u32.MaxValue; + return MaxValue; + } + switch (VarType) { + case EFI_IFR_TYPE_NUM_SIZE_64: + MaxValue = mMinMaxStepData->u64.MaxValue; + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + MaxValue = (UINT64) mMinMaxStepData->u32.MaxValue; + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + MaxValue = (UINT64) mMinMaxStepData->u16.MaxValue; + break; + case EFI_IFR_TYPE_NUM_SIZE_8: + MaxValue = (UINT64) mMinMaxStepData->u8.MaxValue; + break; + default: + break; + } + return MaxValue; + } + + UINT64 GetStepData (UINT8 VarType, BOOLEAN IsBitVar) { + UINT64 MaxValue = 0; + if (IsBitVar) { + MaxValue = mMinMaxStepData->u32.Step; + return MaxValue; + } + switch (VarType) { + case EFI_IFR_TYPE_NUM_SIZE_64: + MaxValue = mMinMaxStepData->u64.Step; + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + MaxValue = (UINT64) mMinMaxStepData->u32.Step; + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + MaxValue = (UINT64) mMinMaxStepData->u16.Step; + break; + case EFI_IFR_TYPE_NUM_SIZE_8: + MaxValue = (UINT64) mMinMaxStepData->u8.Step; + break; + default: + break; + } + return MaxValue; + } + + BOOLEAN IsNumericOpcode () { + return IsNumeric; + } + + VOID UpdateCIfrMinMaxStepData (IN MINMAXSTEP_DATA *MinMaxStepData) { + mMinMaxStepData = MinMaxStepData; + } +}; + +static CIfrQuestionHeader *gCurrentQuestion = NULL; +static CIfrMinMaxStepData *gCurrentMinMaxData = NULL; +static BOOLEAN gIsOrderedList = FALSE; +static BOOLEAN gIsStringOp = FALSE; + +/* + * The definition of all of the UEFI IFR Objects + */ +class CIfrFormSet : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_FORM_SET *mFormSet; + EFI_GUID *mClassGuid; + +public: + CIfrFormSet (UINT8 Size) : CIfrObj (EFI_IFR_FORM_SET_OP, (CHAR8 **)NULL, Size), + CIfrOpHeader (EFI_IFR_FORM_SET_OP, &(GetObjBinAddr())->Header, Size), mFormSet(GetObjBinAddr()) { + mFormSet->Help = EFI_STRING_ID_INVALID; + mFormSet->FormSetTitle = EFI_STRING_ID_INVALID; + mFormSet->Flags = 0; + memset (&mFormSet->Guid, 0, sizeof (EFI_GUID)); + mClassGuid = (EFI_GUID *) (mFormSet + 1); + } + + VOID SetGuid (IN EFI_GUID *Guid) { + memmove (&mFormSet->Guid, Guid, sizeof (EFI_GUID)); + } + + VOID SetFormSetTitle (IN EFI_STRING_ID FormSetTitle) { + mFormSet->FormSetTitle = FormSetTitle; + } + + VOID SetHelp (IN EFI_STRING_ID Help) { + mFormSet->Help = Help; + } + + VOID SetClassGuid (IN EFI_GUID *Guid) { + memmove (&(mClassGuid[mFormSet->Flags++]), Guid, sizeof (EFI_GUID)); + } + + UINT8 GetFlags() { + return mFormSet->Flags; + } +}; + +class CIfrEnd : public CIfrObj, public CIfrOpHeader { +public: + CIfrEnd () : CIfrObj (EFI_IFR_END_OP), + CIfrOpHeader (EFI_IFR_END_OP, &(GetObjBinAddr())->Header) {} +}; + +class CIfrDefaultStore : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_DEFAULTSTORE *mDefaultStore; + +public: + CIfrDefaultStore () : CIfrObj (EFI_IFR_DEFAULTSTORE_OP), + CIfrOpHeader (EFI_IFR_DEFAULTSTORE_OP, &(GetObjBinAddr())->Header), mDefaultStore(GetObjBinAddr()) { + mDefaultStore->DefaultId = EFI_VARSTORE_ID_INVALID; + mDefaultStore->DefaultName = EFI_STRING_ID_INVALID; + } + + VOID SetDefaultName (IN EFI_STRING_ID DefaultName) { + mDefaultStore->DefaultName = DefaultName; + } + + VOID SetDefaultId (IN UINT16 DefaultId) { + mDefaultStore->DefaultId = DefaultId; + } +}; + +#define EFI_FORM_ID_MAX 0xFFFF +#define EFI_FREE_FORM_ID_BITMAP_SIZE ((EFI_FORM_ID_MAX + 1) / EFI_BITS_PER_UINT32) + +class CIfrFormId { +public: + STATIC UINT32 FormIdBitMap[EFI_FREE_FORM_ID_BITMAP_SIZE]; + + STATIC BOOLEAN ChekFormIdFree (IN EFI_FORM_ID FormId) { + UINT32 Index = (FormId / EFI_BITS_PER_UINT32); + UINT32 Offset = (FormId % EFI_BITS_PER_UINT32); + + return (FormIdBitMap[Index] & (0x80000000 >> Offset)) == 0; + } + + STATIC VOID MarkFormIdUsed (IN EFI_FORM_ID FormId) { + UINT32 Index = (FormId / EFI_BITS_PER_UINT32); + UINT32 Offset = (FormId % EFI_BITS_PER_UINT32); + + FormIdBitMap[Index] |= (0x80000000 >> Offset); + } +}; + +class CIfrForm : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_FORM *mForm; + +public: + CIfrForm () : CIfrObj (EFI_IFR_FORM_OP), + CIfrOpHeader (EFI_IFR_FORM_OP, &(GetObjBinAddr())->Header), mForm(GetObjBinAddr()) { + mForm->FormId = 0; + mForm->FormTitle = EFI_STRING_ID_INVALID; + } + + EFI_VFR_RETURN_CODE SetFormId (IN EFI_FORM_ID FormId) { + if (FormId == 0) { + // + // FormId can't be 0. + // + return VFR_RETURN_INVALID_PARAMETER; + } + if (CIfrFormId::ChekFormIdFree (FormId) == FALSE) { + return VFR_RETURN_FORMID_REDEFINED; + } + mForm->FormId = FormId; + CIfrFormId::MarkFormIdUsed (FormId); + return VFR_RETURN_SUCCESS; + } + + VOID SetFormTitle (IN EFI_STRING_ID FormTitle) { + mForm->FormTitle = FormTitle; + } +}; + +class CIfrFormMap : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_FORM_MAP *mFormMap; + EFI_IFR_FORM_MAP_METHOD *mMethodMap; + +public: + CIfrFormMap () : CIfrObj (EFI_IFR_FORM_MAP_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_FORM_MAP), TRUE), + CIfrOpHeader (EFI_IFR_FORM_MAP_OP, &(GetObjBinAddr())->Header), mFormMap(GetObjBinAddr()) { + mFormMap->FormId = 0; + mMethodMap = (EFI_IFR_FORM_MAP_METHOD *) (mFormMap + 1); + } + + EFI_VFR_RETURN_CODE SetFormId (IN EFI_FORM_ID FormId) { + if (FormId == 0) { + // + // FormId can't be 0. + // + return VFR_RETURN_INVALID_PARAMETER; + } + if (CIfrFormId::ChekFormIdFree (FormId) == FALSE) { + return VFR_RETURN_FORMID_REDEFINED; + } + mFormMap->FormId = FormId; + CIfrFormId::MarkFormIdUsed (FormId); + return VFR_RETURN_SUCCESS; + } + + VOID SetFormMapMethod (IN EFI_STRING_ID MethodTitle, IN EFI_GUID *MethodGuid) { + if (ExpendObjBin (sizeof (EFI_IFR_FORM_MAP_METHOD))) { + IncLength (sizeof (EFI_IFR_FORM_MAP_METHOD)); + + mMethodMap->MethodTitle = MethodTitle; + memmove (&(mMethodMap->MethodIdentifier), MethodGuid, sizeof (EFI_GUID)); + mMethodMap ++; + } + } +}; + +class CIfrVarStore : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_VARSTORE *mVarStore; + +public: + CIfrVarStore () : CIfrObj (EFI_IFR_VARSTORE_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_VARSTORE), TRUE), + CIfrOpHeader (EFI_IFR_VARSTORE_OP, &(GetObjBinAddr())->Header), mVarStore(GetObjBinAddr()) { + mVarStore->VarStoreId = EFI_VARSTORE_ID_INVALID; + mVarStore->Size = 0; + memset (&mVarStore->Guid, 0, sizeof (EFI_GUID)); + mVarStore->Name[0] = '\0'; + } + + VOID SetGuid (IN EFI_GUID *Guid) { + memmove (&mVarStore->Guid, Guid, sizeof (EFI_GUID)); + } + + VOID SetVarStoreId (IN EFI_VARSTORE_ID VarStoreId) { + mVarStore->VarStoreId = VarStoreId; + } + + VOID SetSize (IN UINT16 Size) { + mVarStore->Size = Size; + } + + VOID SetName (IN CHAR8 *Name) { + UINT8 Len; + + if (Name != NULL) { + Len = (UINT8) strlen (Name); + if (Len != 0) { + if (ExpendObjBin (Len) == TRUE) { + IncLength (Len); + strcpy ((CHAR8 *)(mVarStore->Name), Name); + } + } + } + } +}; + +class CIfrVarStoreEfi : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_VARSTORE_EFI *mVarStoreEfi; + +public: + CIfrVarStoreEfi () : CIfrObj (EFI_IFR_VARSTORE_EFI_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_VARSTORE_EFI), TRUE), + CIfrOpHeader (EFI_IFR_VARSTORE_EFI_OP, &(GetObjBinAddr())->Header), mVarStoreEfi(GetObjBinAddr()) { + mVarStoreEfi->VarStoreId = EFI_VAROFFSET_INVALID; + mVarStoreEfi->Size = 0; + memset (&mVarStoreEfi->Guid, 0, sizeof (EFI_GUID)); + mVarStoreEfi->Name[0] = '\0'; + } + + VOID SetGuid (IN EFI_GUID *Guid) { + memmove (&mVarStoreEfi->Guid, Guid, sizeof (EFI_GUID)); + } + + VOID SetVarStoreId (IN UINT16 VarStoreId) { + mVarStoreEfi->VarStoreId = VarStoreId; + } + + VOID SetAttributes (IN UINT32 Attributes) { + mVarStoreEfi->Attributes = Attributes; + } + VOID SetSize (IN UINT16 Size) { + mVarStoreEfi->Size = Size; + } + + VOID SetName (IN CHAR8 *Name) { + UINT8 Len; + + if (Name != NULL) { + Len = (UINT8) strlen (Name); + if (Len != 0) { + if (ExpendObjBin (Len) == TRUE) { + IncLength (Len); + strcpy ((CHAR8 *)(mVarStoreEfi->Name), Name); + } + } + } + } + + VOID SetBinaryLength (IN UINT16 Size) { + UINT16 Len; + + Len = sizeof (EFI_IFR_VARSTORE_EFI); + if (Size > Len) { + ExpendObjBin(Size - Len); + IncLength(Size - Len); + } else { + ShrinkObjBin(Len - Size); + DecLength(Len - Size); + } + } +}; + +class CIfrVarStoreNameValue : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_VARSTORE_NAME_VALUE *mVarStoreNameValue; + +public: + CIfrVarStoreNameValue () : CIfrObj (EFI_IFR_VARSTORE_NAME_VALUE_OP), + CIfrOpHeader (EFI_IFR_VARSTORE_NAME_VALUE_OP, &(GetObjBinAddr())->Header), mVarStoreNameValue(GetObjBinAddr()) { + mVarStoreNameValue->VarStoreId = EFI_VAROFFSET_INVALID; + memset (&mVarStoreNameValue->Guid, 0, sizeof (EFI_GUID)); + } + + VOID SetGuid (IN EFI_GUID *Guid) { + memmove (&mVarStoreNameValue->Guid, Guid, sizeof (EFI_GUID)); + } + + VOID SetVarStoreId (IN UINT16 VarStoreId) { + mVarStoreNameValue->VarStoreId = VarStoreId; + } +}; + +class CIfrImage : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_IMAGE *mImage; + +public: + CIfrImage () : CIfrObj (EFI_IFR_IMAGE_OP), + CIfrOpHeader (EFI_IFR_IMAGE_OP, &(GetObjBinAddr())->Header), mImage(GetObjBinAddr()) { + mImage->Id = EFI_IMAGE_ID_INVALID; + } + + VOID SetImageId (IN EFI_IMAGE_ID ImageId) { + mImage->Id = ImageId; + } +}; + +class CIfrModal : public CIfrObj, public CIfrOpHeader { +public: + CIfrModal () : CIfrObj (EFI_IFR_MODAL_TAG_OP), + CIfrOpHeader (EFI_IFR_MODAL_TAG_OP, &(GetObjBinAddr())->Header) { + } +}; + + +class CIfrLocked : public CIfrObj, public CIfrOpHeader { +public: + CIfrLocked () : CIfrObj (EFI_IFR_LOCKED_OP), + CIfrOpHeader (EFI_IFR_LOCKED_OP, &(GetObjBinAddr())->Header) {} +}; + +class CIfrRule : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_RULE *mRule; + +public: + CIfrRule () : CIfrObj (EFI_IFR_RULE_OP), + CIfrOpHeader (EFI_IFR_RULE_OP, &(GetObjBinAddr())->Header), mRule(GetObjBinAddr()) { + mRule->RuleId = EFI_RULE_ID_INVALID; + } + + VOID SetRuleId (IN UINT8 RuleId) { + mRule->RuleId = RuleId; + } +}; + +static EFI_IFR_TYPE_VALUE gZeroEfiIfrTypeValue = {0, }; + +class CIfrDefault : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_DEFAULT *mDefault; + +public: + CIfrDefault ( + IN UINT8 Size, + IN UINT16 DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD, + IN UINT8 Type = EFI_IFR_TYPE_OTHER, + IN EFI_IFR_TYPE_VALUE Value = gZeroEfiIfrTypeValue + ) : CIfrObj (EFI_IFR_DEFAULT_OP, (CHAR8 **)NULL, Size), + CIfrOpHeader (EFI_IFR_DEFAULT_OP, &(GetObjBinAddr())->Header, Size), mDefault(GetObjBinAddr()) { + mDefault->Type = Type; + mDefault->DefaultId = DefaultId; + memmove (&(mDefault->Value), &Value, Size - OFFSET_OF (EFI_IFR_DEFAULT, Value)); + } + + VOID SetDefaultId (IN UINT16 DefaultId) { + mDefault->DefaultId = DefaultId; + } + + VOID SetType (IN UINT8 Type) { + mDefault->Type = Type; + } + + VOID SetValue (IN EFI_IFR_TYPE_VALUE Value) { + memmove (&mDefault->Value, &Value, mDefault->Header.Length - OFFSET_OF (EFI_IFR_DEFAULT, Value)); + } +}; + +class CIfrDefault2 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_DEFAULT_2 *mDefault; + +public: + CIfrDefault2 ( + IN UINT16 DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD, + IN UINT8 Type = EFI_IFR_TYPE_OTHER + ) : CIfrObj (EFI_IFR_DEFAULT_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_DEFAULT_2)), + CIfrOpHeader (EFI_IFR_DEFAULT_OP, &(GetObjBinAddr())->Header, sizeof (EFI_IFR_DEFAULT_2)), mDefault(GetObjBinAddr()) { + mDefault->Type = Type; + mDefault->DefaultId = DefaultId; + } + + VOID SetDefaultId (IN UINT16 DefaultId) { + mDefault->DefaultId = DefaultId; + } + + VOID SetType (IN UINT8 Type) { + mDefault->Type = Type; + } +}; + +class CIfrValue : public CIfrObj, public CIfrOpHeader{ +public: + CIfrValue () : CIfrObj (EFI_IFR_VALUE_OP), + CIfrOpHeader (EFI_IFR_VALUE_OP, &(GetObjBinAddr())->Header) {} + +}; + +class CIfrRead : public CIfrObj, public CIfrOpHeader{ +public: + CIfrRead () : CIfrObj (EFI_IFR_READ_OP), + CIfrOpHeader (EFI_IFR_READ_OP, &(GetObjBinAddr())->Header) {} + +}; + +class CIfrWrite : public CIfrObj, public CIfrOpHeader{ +public: + CIfrWrite () : CIfrObj (EFI_IFR_WRITE_OP), + CIfrOpHeader (EFI_IFR_WRITE_OP, &(GetObjBinAddr())->Header) {} + +}; + +class CIfrGet : public CIfrObj, public CIfrOpHeader{ +private: + EFI_IFR_GET *mGet; + +public: + CIfrGet ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_GET_OP), + CIfrOpHeader (EFI_IFR_GET_OP, &(GetObjBinAddr())->Header), mGet(GetObjBinAddr()) { + SetLineNo (LineNo); + } + + VOID SetVarInfo (IN EFI_VARSTORE_INFO *Info) { + mGet->VarStoreId = Info->mVarStoreId; + mGet->VarStoreInfo.VarName = Info->mInfo.mVarName; + mGet->VarStoreInfo.VarOffset = Info->mInfo.mVarOffset; + mGet->VarStoreType = Info->mVarType; + } +}; + +class CIfrSet : public CIfrObj, public CIfrOpHeader{ +private: + EFI_IFR_SET *mSet; + +public: + CIfrSet ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_SET_OP), + CIfrOpHeader (EFI_IFR_SET_OP, &(GetObjBinAddr())->Header), mSet(GetObjBinAddr()) { + SetLineNo (LineNo); + } + + VOID SetVarInfo (IN EFI_VARSTORE_INFO *Info) { + mSet->VarStoreId = Info->mVarStoreId; + mSet->VarStoreInfo.VarName = Info->mInfo.mVarName; + mSet->VarStoreInfo.VarOffset = Info->mInfo.mVarOffset; + mSet->VarStoreType = Info->mVarType; + } +}; + +class CIfrSubtitle : public CIfrObj, public CIfrOpHeader, public CIfrStatementHeader { +private: + EFI_IFR_SUBTITLE *mSubtitle; + +public: + CIfrSubtitle () : CIfrObj (EFI_IFR_SUBTITLE_OP), + CIfrOpHeader (EFI_IFR_SUBTITLE_OP, &(GetObjBinAddr())->Header), + CIfrStatementHeader (&(GetObjBinAddr())->Statement), mSubtitle(GetObjBinAddr()) { + mSubtitle->Flags = 0; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 LFlags) { + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_FLAGS_HORIZONTAL)) { + mSubtitle->Flags |= EFI_IFR_FLAGS_HORIZONTAL; + } + + return _FLAGS_ZERO (LFlags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } +}; + +class CIfrText : public CIfrObj, public CIfrOpHeader, public CIfrStatementHeader { +private: + EFI_IFR_TEXT *mText; + +public: + CIfrText () : CIfrObj (EFI_IFR_TEXT_OP), + CIfrOpHeader (EFI_IFR_TEXT_OP, &(GetObjBinAddr())->Header), + CIfrStatementHeader (&(GetObjBinAddr())->Statement), mText(GetObjBinAddr()) { + mText->TextTwo = EFI_STRING_ID_INVALID; + } + + VOID SetTextTwo (IN EFI_STRING_ID StringId) { + mText->TextTwo = StringId; + } +}; + +class CIfrRef : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_REF *mRef; + +public: + CIfrRef () : CIfrObj (EFI_IFR_REF_OP), + CIfrOpHeader (EFI_IFR_REF_OP, &(GetObjBinAddr())->Header), + CIfrQuestionHeader (&(GetObjBinAddr())->Question), mRef(GetObjBinAddr()) { + mRef->FormId = 0; + } + + VOID SetFormId (IN EFI_FORM_ID FormId) { + mRef->FormId = FormId; + } +}; + +class CIfrRef2 : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_REF2 *mRef2; + +public: + CIfrRef2 () : CIfrObj (EFI_IFR_REF_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_REF2)), + CIfrOpHeader (EFI_IFR_REF_OP, &(GetObjBinAddr())->Header, sizeof (EFI_IFR_REF2)), + CIfrQuestionHeader (&(GetObjBinAddr())->Question), mRef2(GetObjBinAddr()) { + mRef2->FormId = 0; + mRef2->QuestionId = EFI_QUESTION_ID_INVALID; + } + + VOID SetFormId (IN EFI_FORM_ID FormId) { + mRef2->FormId = FormId; + } + + VOID SetQuestionId (IN EFI_QUESTION_ID QuestionId) { + mRef2->QuestionId = QuestionId; + } +}; + +class CIfrRef3 : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_REF3 *mRef3; + +public: + CIfrRef3 () : CIfrObj (EFI_IFR_REF_OP, (CHAR8 **)NULL, sizeof(EFI_IFR_REF3)), + CIfrOpHeader (EFI_IFR_REF_OP, &(GetObjBinAddr())->Header, sizeof (EFI_IFR_REF3)), + CIfrQuestionHeader (&(GetObjBinAddr())->Question), mRef3(GetObjBinAddr()) { + mRef3->FormId = 0; + mRef3->QuestionId = EFI_QUESTION_ID_INVALID; + memset (&mRef3->FormSetId, 0, sizeof (EFI_GUID)); + } + + VOID SetFormId (IN EFI_FORM_ID FormId) { + mRef3->FormId = FormId; + } + + VOID SetQuestionId (IN EFI_QUESTION_ID QuestionId) { + mRef3->QuestionId = QuestionId; + } + + VOID SetFormSetId (IN EFI_GUID FormSetId) { + mRef3->FormSetId = FormSetId; + } +}; + +class CIfrRef4 : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_REF4 *mRef4; + +public: + CIfrRef4 () : CIfrObj (EFI_IFR_REF_OP, (CHAR8 **)NULL, sizeof(EFI_IFR_REF4)), + CIfrOpHeader (EFI_IFR_REF_OP, &(GetObjBinAddr())->Header, sizeof(EFI_IFR_REF4)), + CIfrQuestionHeader (&(GetObjBinAddr())->Question), mRef4(GetObjBinAddr()) { + mRef4->FormId = 0; + mRef4->QuestionId = EFI_QUESTION_ID_INVALID; + memset (&mRef4->FormSetId, 0, sizeof (EFI_GUID)); + mRef4->DevicePath = EFI_STRING_ID_INVALID; + } + + VOID SetFormId (IN EFI_FORM_ID FormId) { + mRef4->FormId = FormId; + } + + VOID SetQuestionId (IN EFI_QUESTION_ID QuestionId) { + mRef4->QuestionId = QuestionId; + } + + VOID SetFormSetId (IN EFI_GUID FormSetId) { + mRef4->FormSetId = FormSetId; + } + + VOID SetDevicePath (IN EFI_STRING_ID DevicePath) { + mRef4->DevicePath = DevicePath; + } +}; + +class CIfrRef5 : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +public: + CIfrRef5 () : CIfrObj (EFI_IFR_REF_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_REF5)), + CIfrOpHeader (EFI_IFR_REF_OP, &(GetObjBinAddr())->Header, sizeof (EFI_IFR_REF5)), + CIfrQuestionHeader (&(GetObjBinAddr())->Question) { + } +}; + +class CIfrResetButton : public CIfrObj, public CIfrOpHeader, public CIfrStatementHeader { +private: + EFI_IFR_RESET_BUTTON *mResetButton; + +public: + CIfrResetButton () : CIfrObj (EFI_IFR_RESET_BUTTON_OP), + CIfrOpHeader (EFI_IFR_RESET_BUTTON_OP, &(GetObjBinAddr())->Header), + CIfrStatementHeader (&(GetObjBinAddr())->Statement), mResetButton(GetObjBinAddr()) { + mResetButton->DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD; + } + + VOID SetDefaultId (IN UINT16 DefaultId) { + mResetButton->DefaultId = DefaultId; + } +}; + +class CIfrCheckBox : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_CHECKBOX *mCheckBox; + +public: + CIfrCheckBox () : CIfrObj (EFI_IFR_CHECKBOX_OP), + CIfrOpHeader (EFI_IFR_CHECKBOX_OP, &(GetObjBinAddr())->Header), + CIfrQuestionHeader (&(GetObjBinAddr())->Question), mCheckBox(GetObjBinAddr()) { + mCheckBox->Flags = 0; + gCurrentQuestion = this; + } + + ~CIfrCheckBox () { + gCurrentQuestion = NULL; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 HFlags, UINT8 LFlags) { + EFI_VFR_RETURN_CODE Ret; + + Ret = CIfrQuestionHeader::SetFlags (HFlags); + if (Ret != VFR_RETURN_SUCCESS) { + return Ret; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_CHECKBOX_DEFAULT)) { + mCheckBox->Flags |= EFI_IFR_CHECKBOX_DEFAULT; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_CHECKBOX_DEFAULT_MFG)) { + mCheckBox->Flags |= EFI_IFR_CHECKBOX_DEFAULT_MFG; + } + + return _FLAGS_ZERO (LFlags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } + + UINT8 GetFlags (VOID) { + return mCheckBox->Flags; + } +}; + +class CIfrAction : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_ACTION *mAction; + +public: + CIfrAction () : CIfrObj (EFI_IFR_ACTION_OP), + CIfrOpHeader (EFI_IFR_ACTION_OP, &(GetObjBinAddr())->Header), + CIfrQuestionHeader (&(GetObjBinAddr())->Question), mAction(GetObjBinAddr()) { + mAction->QuestionConfig = EFI_STRING_ID_INVALID; + } + + VOID SetQuestionConfig (IN EFI_STRING_ID QuestionConfig) { + mAction->QuestionConfig = QuestionConfig; + } +}; + +class CIfrDate : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_DATE *mDate; + +public: + CIfrDate () : CIfrObj (EFI_IFR_DATE_OP), + CIfrOpHeader (EFI_IFR_DATE_OP, &(GetObjBinAddr())->Header), + CIfrQuestionHeader (&(GetObjBinAddr())->Question), mDate(GetObjBinAddr()) { + mDate->Flags = 0; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 HFlags, IN UINT8 LFlags) { + EFI_VFR_RETURN_CODE Ret; + + Ret = CIfrQuestionHeader::SetFlags (HFlags); + if (Ret != VFR_RETURN_SUCCESS) { + return Ret; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_QF_DATE_YEAR_SUPPRESS)) { + mDate->Flags |= EFI_QF_DATE_YEAR_SUPPRESS; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_QF_DATE_MONTH_SUPPRESS)) { + mDate->Flags |= EFI_QF_DATE_MONTH_SUPPRESS; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_QF_DATE_DAY_SUPPRESS)) { + mDate->Flags |= EFI_QF_DATE_DAY_SUPPRESS; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, QF_DATE_STORAGE_NORMAL)) { + mDate->Flags |= QF_DATE_STORAGE_NORMAL; + } else if (_FLAG_TEST_AND_CLEAR (LFlags, QF_DATE_STORAGE_TIME)) { + mDate->Flags |= QF_DATE_STORAGE_TIME; + } else if (_FLAG_TEST_AND_CLEAR (LFlags, QF_DATE_STORAGE_WAKEUP)) { + mDate->Flags |= QF_DATE_STORAGE_WAKEUP; + } + + return _FLAGS_ZERO (LFlags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } +}; + +class CIfrNumeric : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader, public CIfrMinMaxStepData { +private: + EFI_IFR_NUMERIC *mNumeric; + +public: + CIfrNumeric () : CIfrObj (EFI_IFR_NUMERIC_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_NUMERIC), TRUE), + CIfrOpHeader (EFI_IFR_NUMERIC_OP, &(GetObjBinAddr())->Header), + CIfrQuestionHeader (&(GetObjBinAddr())->Question), + CIfrMinMaxStepData (&(GetObjBinAddr())->data, TRUE), mNumeric(GetObjBinAddr()) { + mNumeric->Flags = EFI_IFR_NUMERIC_SIZE_1 | EFI_IFR_DISPLAY_UINT_DEC; + gCurrentQuestion = this; + gCurrentMinMaxData = this; + } + + ~CIfrNumeric () { + gCurrentQuestion = NULL; + gCurrentMinMaxData = NULL; + } + + VOID ShrinkBinSize (IN UINT16 Size) { + // + // Update the buffer size which is truly be used later. + // + ShrinkObjBin(Size); + DecLength(Size); + + // + // Allocate buffer in gCFormPkg. + // + _EMIT_PENDING_OBJ(); + + // + // Update the buffer pointer used by other class. + // + mNumeric = GetObjBinAddr(); + UpdateHeader (&mNumeric->Header); + UpdateCIfrQuestionHeader(&mNumeric->Question); + UpdateCIfrMinMaxStepData(&mNumeric->data); + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 HFlags, IN UINT8 LFlags, BOOLEAN DisplaySettingsSpecified = FALSE) { + EFI_VFR_RETURN_CODE Ret; + + Ret = CIfrQuestionHeader::SetFlags (HFlags); + if (Ret != VFR_RETURN_SUCCESS) { + return Ret; + } + + if (DisplaySettingsSpecified == FALSE) { + mNumeric->Flags = LFlags | EFI_IFR_DISPLAY_UINT_DEC; + } else { + mNumeric->Flags = LFlags; + } + return VFR_RETURN_SUCCESS; + } + + EFI_VFR_RETURN_CODE SetFlagsForBitField (IN UINT8 HFlags, IN UINT8 LFlags, BOOLEAN DisplaySettingsSpecified = FALSE) { + EFI_VFR_RETURN_CODE Ret; + + Ret = CIfrQuestionHeader::SetFlags (HFlags); + if (Ret != VFR_RETURN_SUCCESS) { + return Ret; + } + + if (DisplaySettingsSpecified == FALSE) { + mNumeric->Flags = LFlags | EDKII_IFR_DISPLAY_UINT_DEC_BIT; + } else { + mNumeric->Flags = LFlags; + } + return VFR_RETURN_SUCCESS; + } + + UINT8 GetNumericFlags () { + return mNumeric->Flags; + } +}; + +class CIfrOneOf : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader, public CIfrMinMaxStepData { +private: + EFI_IFR_ONE_OF *mOneOf; + +public: + CIfrOneOf () : CIfrObj (EFI_IFR_ONE_OF_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_ONE_OF), TRUE), + CIfrOpHeader (EFI_IFR_ONE_OF_OP, &(GetObjBinAddr())->Header), + CIfrQuestionHeader (&(GetObjBinAddr())->Question), + CIfrMinMaxStepData (&(GetObjBinAddr())->data), mOneOf(GetObjBinAddr()) { + mOneOf->Flags = 0; + gCurrentQuestion = this; + gCurrentMinMaxData = this; + } + + ~CIfrOneOf () { + gCurrentQuestion = NULL; + gCurrentMinMaxData = NULL; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 HFlags, IN UINT8 LFlags) { + EFI_VFR_RETURN_CODE Ret; + + Ret = CIfrQuestionHeader::SetFlags (HFlags); + if (Ret != VFR_RETURN_SUCCESS) { + return Ret; + } + + if (LFlags & EFI_IFR_DISPLAY) { + mOneOf->Flags = LFlags; + } else { + mOneOf->Flags = LFlags | EFI_IFR_DISPLAY_UINT_DEC; + } + return VFR_RETURN_SUCCESS; + } + + EFI_VFR_RETURN_CODE SetFlagsForBitField (IN UINT8 HFlags, IN UINT8 LFlags) { + EFI_VFR_RETURN_CODE Ret; + + Ret = CIfrQuestionHeader::SetFlags (HFlags); + if (Ret != VFR_RETURN_SUCCESS) { + return Ret; + } + + if (LFlags & EFI_IFR_DISPLAY) { + mOneOf->Flags = LFlags; + } else { + mOneOf->Flags = LFlags | EDKII_IFR_DISPLAY_UINT_DEC_BIT; + } + return VFR_RETURN_SUCCESS; + } + + VOID ShrinkBinSize (IN UINT16 Size) { + // + // Update the buffer size which is truly be used later. + // + ShrinkObjBin(Size); + DecLength(Size); + + // + // Allocate buffer in gCFormPkg. + // + _EMIT_PENDING_OBJ(); + + // + // Update the buffer pointer used by other class. + // + mOneOf = GetObjBinAddr(); + UpdateHeader (&mOneOf->Header); + UpdateCIfrQuestionHeader(&mOneOf->Question); + UpdateCIfrMinMaxStepData(&mOneOf->data); + } +}; + +class CIfrString : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_STRING *mString; + +public: + CIfrString () : CIfrObj (EFI_IFR_STRING_OP), + CIfrOpHeader (EFI_IFR_STRING_OP, &(GetObjBinAddr())->Header), + CIfrQuestionHeader (&(GetObjBinAddr())->Question), mString(GetObjBinAddr()) { + mString->Flags = 0; + mString->MinSize = 0; + mString->MaxSize = 0; + gCurrentQuestion = this; + } + + ~CIfrString () { + gCurrentQuestion = NULL; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 HFlags, IN UINT8 LFlags) { + EFI_VFR_RETURN_CODE Ret; + + Ret = CIfrQuestionHeader::SetFlags (HFlags); + if (Ret != VFR_RETURN_SUCCESS) { + return Ret; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_STRING_MULTI_LINE)) { + mString->Flags |= EFI_IFR_STRING_MULTI_LINE; + } + + return _FLAGS_ZERO (LFlags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } + + VOID SetMinSize (IN UINT8 Flags) { + mString->MinSize = Flags; + } + + VOID SetMaxSize (IN UINT8 MaxSize) { + mString->MaxSize = MaxSize; + } +}; + +class CIfrPassword : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_PASSWORD *mPassword; + +public: + CIfrPassword () : CIfrObj (EFI_IFR_PASSWORD_OP), + CIfrOpHeader (EFI_IFR_PASSWORD_OP, &(GetObjBinAddr())->Header), + CIfrQuestionHeader (&(GetObjBinAddr())->Question), mPassword(GetObjBinAddr()) { + mPassword->MinSize = 0; + mPassword->MaxSize = 0; + gCurrentQuestion = this; + } + + ~CIfrPassword () { + gCurrentQuestion = NULL; + } + + VOID SetMinSize (IN UINT16 MinSize) { + mPassword->MinSize = MinSize; + } + + VOID SetMaxSize (IN UINT16 MaxSize) { + mPassword->MaxSize = MaxSize; + } +}; + +class CIfrOrderedList : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_ORDERED_LIST *mOrderedList; + +public: + CIfrOrderedList () : CIfrObj (EFI_IFR_ORDERED_LIST_OP), + CIfrOpHeader (EFI_IFR_ORDERED_LIST_OP, &(GetObjBinAddr())->Header), + CIfrQuestionHeader (&(GetObjBinAddr())->Question), mOrderedList(GetObjBinAddr()) { + mOrderedList->MaxContainers = 0; + mOrderedList->Flags = 0; + gCurrentQuestion = this; + } + + ~CIfrOrderedList () { + gCurrentQuestion = NULL; + } + + VOID SetMaxContainers (IN UINT8 MaxContainers) { + mOrderedList->MaxContainers = MaxContainers; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 HFlags, IN UINT8 LFlags) { + EFI_VFR_RETURN_CODE Ret; + + Ret = CIfrQuestionHeader::SetFlags (HFlags); + if (Ret != VFR_RETURN_SUCCESS) { + return Ret; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_UNIQUE_SET)) { + mOrderedList->Flags |= EFI_IFR_UNIQUE_SET; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_NO_EMPTY_SET)) { + mOrderedList->Flags |= EFI_IFR_NO_EMPTY_SET; + } + + return _FLAGS_ZERO (LFlags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } +}; + +class CIfrTime : public CIfrObj, public CIfrOpHeader, public CIfrQuestionHeader { +private: + EFI_IFR_TIME *mTime; + +public: + CIfrTime () : CIfrObj (EFI_IFR_TIME_OP), + CIfrOpHeader (EFI_IFR_TIME_OP, &(GetObjBinAddr())->Header), + CIfrQuestionHeader (&(GetObjBinAddr())->Question), mTime(GetObjBinAddr()) { + mTime->Flags = 0; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 HFlags, IN UINT8 LFlags) { + EFI_VFR_RETURN_CODE Ret; + + Ret = CIfrQuestionHeader::SetFlags (HFlags); + if (Ret != VFR_RETURN_SUCCESS) { + return Ret; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, QF_TIME_HOUR_SUPPRESS)) { + mTime->Flags |= QF_TIME_HOUR_SUPPRESS; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, QF_TIME_MINUTE_SUPPRESS)) { + mTime->Flags |= QF_TIME_MINUTE_SUPPRESS; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, QF_TIME_SECOND_SUPPRESS)) { + mTime->Flags |= QF_TIME_SECOND_SUPPRESS; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, QF_TIME_STORAGE_NORMAL)) { + mTime->Flags |= QF_TIME_STORAGE_NORMAL; + } else if (_FLAG_TEST_AND_CLEAR (LFlags, QF_TIME_STORAGE_TIME)) { + mTime->Flags |= QF_TIME_STORAGE_TIME; + } else if (_FLAG_TEST_AND_CLEAR (LFlags, QF_TIME_STORAGE_WAKEUP)) { + mTime->Flags |= QF_TIME_STORAGE_WAKEUP; + } + + return _FLAGS_ZERO (LFlags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } +}; + +class CIfrDisableIf : public CIfrObj, public CIfrOpHeader { +public: + CIfrDisableIf () : CIfrObj (EFI_IFR_DISABLE_IF_OP), + CIfrOpHeader (EFI_IFR_DISABLE_IF_OP, &(GetObjBinAddr())->Header) {} +}; + +class CIfrSuppressIf : public CIfrObj, public CIfrOpHeader { +public: + CIfrSuppressIf () : CIfrObj (EFI_IFR_SUPPRESS_IF_OP), + CIfrOpHeader (EFI_IFR_SUPPRESS_IF_OP, &(GetObjBinAddr())->Header) {} +}; + +class CIfrGrayOutIf : public CIfrObj, public CIfrOpHeader { +public: + CIfrGrayOutIf () : CIfrObj (EFI_IFR_GRAY_OUT_IF_OP), + CIfrOpHeader (EFI_IFR_GRAY_OUT_IF_OP, &(GetObjBinAddr())->Header) {} +}; + +class CIfrInconsistentIf : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_INCONSISTENT_IF *mInconsistentIf; + +public: + CIfrInconsistentIf () : CIfrObj (EFI_IFR_INCONSISTENT_IF_OP), + CIfrOpHeader (EFI_IFR_INCONSISTENT_IF_OP, &(GetObjBinAddr())->Header), mInconsistentIf(GetObjBinAddr()) { + mInconsistentIf->Error = EFI_STRING_ID_INVALID; + } + + VOID SetError (IN EFI_STRING_ID Error) { + mInconsistentIf->Error = Error; + } +}; + +class CIfrWarningIf : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_WARNING_IF *mWarningIf; + +public: + CIfrWarningIf () : CIfrObj (EFI_IFR_WARNING_IF_OP), + CIfrOpHeader (EFI_IFR_WARNING_IF_OP, &(GetObjBinAddr())->Header), mWarningIf(GetObjBinAddr()) { + mWarningIf->Warning = EFI_STRING_ID_INVALID; + mWarningIf->TimeOut = 0; + } + + VOID SetWarning (IN EFI_STRING_ID Warning) { + mWarningIf->Warning = Warning; + } + + VOID SetTimeOut (IN UINT8 TimeOut) { + mWarningIf->TimeOut = TimeOut; + } +}; + +class CIfrNoSubmitIf : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_NO_SUBMIT_IF *mNoSubmitIf; + +public: + CIfrNoSubmitIf () : CIfrObj (EFI_IFR_NO_SUBMIT_IF_OP), + CIfrOpHeader (EFI_IFR_NO_SUBMIT_IF_OP, &(GetObjBinAddr())->Header), mNoSubmitIf(GetObjBinAddr()) { + mNoSubmitIf->Error = EFI_STRING_ID_INVALID; + } + + VOID SetError (IN EFI_STRING_ID Error) { + mNoSubmitIf->Error = Error; + } +}; + +class CIfrRefresh : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_REFRESH *mRefresh; + +public: + CIfrRefresh () : CIfrObj (EFI_IFR_REFRESH_OP), + CIfrOpHeader (EFI_IFR_REFRESH_OP, &(GetObjBinAddr())->Header), mRefresh(GetObjBinAddr()) { + mRefresh->RefreshInterval = 0; + } + + VOID SetRefreshInterval (IN UINT8 RefreshInterval) { + mRefresh->RefreshInterval = RefreshInterval; + } +}; + +class CIfrRefreshId : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_REFRESH_ID *mRefreshId; + +public: + CIfrRefreshId () : CIfrObj (EFI_IFR_REFRESH_ID_OP), + CIfrOpHeader (EFI_IFR_REFRESH_ID_OP, &(GetObjBinAddr())->Header), mRefreshId(GetObjBinAddr()) { + memset (&mRefreshId->RefreshEventGroupId, 0, sizeof (EFI_GUID)); + } + + VOID SetRefreshEventGroutId (IN EFI_GUID *RefreshEventGroupId) { + memmove (&mRefreshId->RefreshEventGroupId, RefreshEventGroupId, sizeof (EFI_GUID)); + } +}; + +class CIfrVarStoreDevice : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_VARSTORE_DEVICE *mVarStoreDevice; + +public: + CIfrVarStoreDevice () : CIfrObj (EFI_IFR_VARSTORE_DEVICE_OP), + CIfrOpHeader (EFI_IFR_VARSTORE_DEVICE_OP, &(GetObjBinAddr())->Header), mVarStoreDevice(GetObjBinAddr()) { + mVarStoreDevice->DevicePath = EFI_STRING_ID_INVALID; + } + + VOID SetDevicePath (IN EFI_STRING_ID DevicePath) { + mVarStoreDevice->DevicePath = DevicePath; + } +}; + +class CIfrOneOfOption : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_ONE_OF_OPTION *mOneOfOption; + +public: + CIfrOneOfOption (UINT8 Size) : CIfrObj (EFI_IFR_ONE_OF_OPTION_OP, (CHAR8 **)NULL, Size), + CIfrOpHeader (EFI_IFR_ONE_OF_OPTION_OP, &(GetObjBinAddr())->Header, Size), mOneOfOption(GetObjBinAddr()) { + mOneOfOption->Flags = 0; + mOneOfOption->Option = EFI_STRING_ID_INVALID; + mOneOfOption->Type = EFI_IFR_TYPE_OTHER; + memset (&mOneOfOption->Value, 0, Size - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value)); + } + + VOID SetOption (IN EFI_STRING_ID Option) { + mOneOfOption->Option = Option; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 LFlags) { + mOneOfOption->Flags = 0; + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_OPTION_DEFAULT)) { + mOneOfOption->Flags |= EFI_IFR_OPTION_DEFAULT; + } + + if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_OPTION_DEFAULT_MFG)) { + mOneOfOption->Flags |= EFI_IFR_OPTION_DEFAULT_MFG; + } + + if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_NUM_SIZE_8)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_NUM_SIZE_8); + mOneOfOption->Flags |= EFI_IFR_TYPE_NUM_SIZE_8; + } else if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_NUM_SIZE_16)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_NUM_SIZE_16); + mOneOfOption->Flags |= EFI_IFR_TYPE_NUM_SIZE_16; + } else if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_NUM_SIZE_32)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_NUM_SIZE_32); + mOneOfOption->Flags |= EFI_IFR_TYPE_NUM_SIZE_32; + } else if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_NUM_SIZE_64)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_NUM_SIZE_64); + mOneOfOption->Flags |= EFI_IFR_TYPE_NUM_SIZE_64; + } else if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_BOOLEAN)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_BOOLEAN); + mOneOfOption->Flags |= EFI_IFR_TYPE_BOOLEAN; + } else if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_TIME)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_TIME); + mOneOfOption->Flags |= EFI_IFR_TYPE_TIME; + } else if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_DATE)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_DATE); + mOneOfOption->Flags |= EFI_IFR_TYPE_DATE; + } else if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_STRING)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_STRING); + mOneOfOption->Flags |= EFI_IFR_TYPE_STRING; + } else if (_IS_EQUAL (LFlags, EFI_IFR_TYPE_OTHER)) { + _FLAG_CLEAR (LFlags, EFI_IFR_TYPE_OTHER); + mOneOfOption->Flags |= EFI_IFR_TYPE_OTHER; + } + + return _FLAGS_ZERO (LFlags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } + + VOID SetType (IN UINT8 Type) { + mOneOfOption->Type = Type; + } + + VOID SetValue (IN EFI_IFR_TYPE_VALUE Value) { + memmove (&mOneOfOption->Value, &Value, mOneOfOption->Header.Length - OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value)); + } + + UINT8 GetFlags (VOID) { + return mOneOfOption->Flags; + } +}; + +static EFI_GUID IfrTianoGuid = EFI_IFR_TIANO_GUID; +static EFI_GUID IfrFrameworkGuid = EFI_IFR_FRAMEWORK_GUID; + +class CIfrClass : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GUID_CLASS *mClass; + +public: + CIfrClass () : CIfrObj (EFI_IFR_GUID_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_GUID_CLASS)), + CIfrOpHeader (EFI_IFR_GUID_OP, &(GetObjBinAddr())->Header, sizeof (EFI_IFR_GUID_CLASS)), mClass(GetObjBinAddr()) { + mClass->ExtendOpCode = EFI_IFR_EXTEND_OP_CLASS; + mClass->Guid = IfrTianoGuid; + mClass->Class = EFI_NON_DEVICE_CLASS; + } + + VOID SetClass (IN UINT16 Class) { + mClass->Class = Class; + } +}; + +class CIfrSubClass : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GUID_SUBCLASS *mSubClass; + +public: + CIfrSubClass () : CIfrObj (EFI_IFR_GUID_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_GUID_SUBCLASS)), + CIfrOpHeader (EFI_IFR_GUID_OP, &(GetObjBinAddr())->Header, sizeof (EFI_IFR_GUID_SUBCLASS)), mSubClass(GetObjBinAddr()) { + mSubClass->ExtendOpCode = EFI_IFR_EXTEND_OP_SUBCLASS; + mSubClass->Guid = IfrTianoGuid; + mSubClass->SubClass = EFI_SETUP_APPLICATION_SUBCLASS; + } + + VOID SetSubClass (IN UINT16 SubClass) { + mSubClass->SubClass = SubClass; + } +}; + +class CIfrLabel : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GUID_LABEL *mLabel; + +public: + CIfrLabel () : CIfrObj (EFI_IFR_GUID_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_GUID_LABEL)), + CIfrOpHeader (EFI_IFR_GUID_OP, &(GetObjBinAddr())->Header, sizeof (EFI_IFR_GUID_LABEL)), mLabel(GetObjBinAddr()) { + mLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + mLabel->Guid = IfrTianoGuid; + } + + VOID SetNumber (IN UINT16 Number) { + mLabel->Number = Number; + } +}; + +class CIfrBanner : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GUID_BANNER *mBanner; + +public: + CIfrBanner () : CIfrObj (EFI_IFR_GUID_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_GUID_BANNER)), + CIfrOpHeader (EFI_IFR_GUID_OP, &(GetObjBinAddr())->Header, sizeof (EFI_IFR_GUID_BANNER)), mBanner(GetObjBinAddr()) { + mBanner->ExtendOpCode = EFI_IFR_EXTEND_OP_BANNER; + mBanner->Guid = IfrTianoGuid; + } + + VOID SetTitle (IN EFI_STRING_ID StringId) { + mBanner->Title = StringId; + } + + VOID SetLine (IN UINT16 Line) { + mBanner->LineNumber = Line; + } + + VOID SetAlign (IN UINT8 Align) { + mBanner->Alignment = Align; + } +}; + +class CIfrOptionKey : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GUID_OPTIONKEY *mOptionKey; + +public: + CIfrOptionKey ( + IN EFI_QUESTION_ID QuestionId, + IN EFI_IFR_TYPE_VALUE &OptionValue, + IN EFI_QUESTION_ID KeyValue + ) : CIfrObj (EFI_IFR_GUID_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_GUID_OPTIONKEY)), + CIfrOpHeader (EFI_IFR_GUID_OP, &(GetObjBinAddr())->Header, sizeof (EFI_IFR_GUID_OPTIONKEY)), mOptionKey(GetObjBinAddr()) { + mOptionKey->ExtendOpCode = EFI_IFR_EXTEND_OP_OPTIONKEY; + mOptionKey->Guid = IfrFrameworkGuid; + mOptionKey->QuestionId = QuestionId; + mOptionKey->OptionValue = OptionValue; + mOptionKey->KeyValue = KeyValue; + } +}; + +class CIfrVarEqName : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GUID_VAREQNAME *mVarEqName; + +public: + CIfrVarEqName ( + IN EFI_QUESTION_ID QuestionId, + IN EFI_STRING_ID NameId + ) : CIfrObj (EFI_IFR_GUID_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_GUID_VAREQNAME)), + CIfrOpHeader (EFI_IFR_GUID_OP, &(GetObjBinAddr())->Header, sizeof (EFI_IFR_GUID_VAREQNAME)), mVarEqName(GetObjBinAddr()) { + mVarEqName->ExtendOpCode = EFI_IFR_EXTEND_OP_VAREQNAME; + mVarEqName->Guid = IfrFrameworkGuid; + mVarEqName->QuestionId = QuestionId; + mVarEqName->NameId = NameId; + } +}; + +class CIfrTimeout : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GUID_TIMEOUT *mTimeout; + +public: + CIfrTimeout (IN UINT16 Timeout = 0) : CIfrObj (EFI_IFR_GUID_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_GUID_TIMEOUT)), + CIfrOpHeader (EFI_IFR_GUID_OP, &(GetObjBinAddr())->Header, sizeof (EFI_IFR_GUID_TIMEOUT)), mTimeout(GetObjBinAddr()) { + mTimeout->ExtendOpCode = EFI_IFR_EXTEND_OP_TIMEOUT; + mTimeout->Guid = IfrTianoGuid; + mTimeout->TimeOut = Timeout; + } + + VOID SetTimeout (IN UINT16 Timeout) { + mTimeout->TimeOut = Timeout; + } +}; + +class CIfrGuid : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_GUID *mGuid; + +public: + CIfrGuid (UINT8 Size) : CIfrObj (EFI_IFR_GUID_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_GUID)+Size), + CIfrOpHeader (EFI_IFR_GUID_OP, &(GetObjBinAddr())->Header, sizeof (EFI_IFR_GUID)+Size), mGuid(GetObjBinAddr()) { + memset (&mGuid->Guid, 0, sizeof (EFI_GUID)); + } + + VOID SetGuid (IN EFI_GUID *Guid) { + memmove (&mGuid->Guid, Guid, sizeof (EFI_GUID)); + } + + VOID SetData (IN UINT8* DataBuff, IN UINT8 Size) { + memmove ((UINT8 *)mGuid + sizeof (EFI_IFR_GUID), DataBuff, Size); + } +}; + +class CIfrDup : public CIfrObj, public CIfrOpHeader { +public: + CIfrDup ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_DUP_OP), + CIfrOpHeader (EFI_IFR_DUP_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrEqIdId : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_EQ_ID_ID *mEqIdId; + +public: + CIfrEqIdId ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_EQ_ID_ID_OP), + CIfrOpHeader (EFI_IFR_EQ_ID_ID_OP, &(GetObjBinAddr())->Header), mEqIdId(GetObjBinAddr()) { + SetLineNo (LineNo); + mEqIdId->QuestionId1 = EFI_QUESTION_ID_INVALID; + mEqIdId->QuestionId2 = EFI_QUESTION_ID_INVALID; + } + + VOID SetQuestionId1 ( + IN EFI_QUESTION_ID QuestionId, + IN CHAR8 *VarIdStr, + IN UINT32 LineNo + ) { + if (QuestionId != EFI_QUESTION_ID_INVALID) { + mEqIdId->QuestionId1 = QuestionId; + } else { + gCFormPkg.AssignPending (VarIdStr, (VOID *)(&mEqIdId->QuestionId1), sizeof (EFI_QUESTION_ID), LineNo, NO_QST_REFED); + } + } + + VOID SetQuestionId2 ( + IN EFI_QUESTION_ID QuestionId, + IN CHAR8 *VarIdStr, + IN UINT32 LineNo + ) { + if (QuestionId != EFI_QUESTION_ID_INVALID) { + mEqIdId->QuestionId2 = QuestionId; + } else { + gCFormPkg.AssignPending (VarIdStr, (VOID *)(&mEqIdId->QuestionId2), sizeof (EFI_QUESTION_ID), LineNo, NO_QST_REFED); + } + } +}; + +class CIfrEqIdVal : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_EQ_ID_VAL *mEqIdVal; + +public: + CIfrEqIdVal ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_EQ_ID_VAL_OP), + CIfrOpHeader (EFI_IFR_EQ_ID_VAL_OP, &(GetObjBinAddr())->Header), mEqIdVal(GetObjBinAddr()) { + SetLineNo (LineNo); + mEqIdVal->QuestionId = EFI_QUESTION_ID_INVALID; + } + + VOID SetQuestionId ( + IN EFI_QUESTION_ID QuestionId, + IN CHAR8 *VarIdStr, + IN UINT32 LineNo + ) { + if (QuestionId != EFI_QUESTION_ID_INVALID) { + mEqIdVal->QuestionId = QuestionId; + } else { + gCFormPkg.AssignPending (VarIdStr, (VOID *)(&mEqIdVal->QuestionId), sizeof (EFI_QUESTION_ID), LineNo, NO_QST_REFED); + } + } + + VOID SetValue (IN UINT16 Value) { + mEqIdVal->Value = Value; + } +}; + +class CIfrEqIdList : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_EQ_ID_VAL_LIST *mEqIdVList; + +public: + CIfrEqIdList ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_EQ_ID_VAL_LIST_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_EQ_ID_VAL_LIST), TRUE), + CIfrOpHeader (EFI_IFR_EQ_ID_VAL_LIST_OP, &(GetObjBinAddr())->Header), mEqIdVList(GetObjBinAddr()) { + SetLineNo (LineNo); + mEqIdVList->QuestionId = EFI_QUESTION_ID_INVALID; + mEqIdVList->ListLength = 0; + mEqIdVList->ValueList[0] = 0; + } + + VOID UpdateIfrBuffer ( + ) { + _EMIT_PENDING_OBJ(); + mEqIdVList = GetObjBinAddr(); + UpdateHeader (&mEqIdVList->Header); + } + + VOID SetQuestionId ( + IN EFI_QUESTION_ID QuestionId, + IN CHAR8 *VarIdStr, + IN UINT32 LineNo + ) { + if (QuestionId != EFI_QUESTION_ID_INVALID) { + mEqIdVList->QuestionId = QuestionId; + } else { + gCFormPkg.AssignPending (VarIdStr, (VOID *)(&mEqIdVList->QuestionId), sizeof (EFI_QUESTION_ID), LineNo, NO_QST_REFED); + } + } + + VOID SetListLength (IN UINT16 ListLength) { + mEqIdVList->ListLength = ListLength; + } + + VOID SetValueList (IN UINT16 Index, IN UINT16 Value) { + if (Index == 0) { + mEqIdVList->ValueList[0] = Value; + return; + } + + if (ExpendObjBin (sizeof (UINT16)) ==TRUE) { + IncLength (sizeof (UINT16)); + mEqIdVList->ValueList[Index] = Value; + } + } +}; + +class CIfrQuestionRef1 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_QUESTION_REF1 *mQuestionRef1; + +public: + CIfrQuestionRef1 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_QUESTION_REF1_OP), + CIfrOpHeader (EFI_IFR_QUESTION_REF1_OP, &(GetObjBinAddr())->Header), mQuestionRef1(GetObjBinAddr()) { + SetLineNo (LineNo); + mQuestionRef1->QuestionId = EFI_QUESTION_ID_INVALID; + } + + VOID SetQuestionId ( + IN EFI_QUESTION_ID QuestionId, + IN CHAR8 *VarIdStr, + IN UINT32 LineNo + ) { + if (QuestionId != EFI_QUESTION_ID_INVALID) { + mQuestionRef1->QuestionId = QuestionId; + } else { + gCFormPkg.AssignPending (VarIdStr, (VOID *)(&mQuestionRef1->QuestionId), sizeof (EFI_QUESTION_ID), LineNo, NO_QST_REFED); + } + } +}; + +class CIfrQuestionRef2 : public CIfrObj, public CIfrOpHeader { +public: + CIfrQuestionRef2 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_QUESTION_REF2_OP), + CIfrOpHeader (EFI_IFR_QUESTION_REF2_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrQuestionRef3 : public CIfrObj, public CIfrOpHeader { +public: + CIfrQuestionRef3 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_QUESTION_REF3_OP), + CIfrOpHeader (EFI_IFR_QUESTION_REF3_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrQuestionRef3_2 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_QUESTION_REF3_2 *mQuestionRef3_2; + +public: + CIfrQuestionRef3_2 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_QUESTION_REF3_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_QUESTION_REF3_2)), + CIfrOpHeader (EFI_IFR_QUESTION_REF3_OP, &(GetObjBinAddr())->Header, sizeof (EFI_IFR_QUESTION_REF3_2)), mQuestionRef3_2(GetObjBinAddr()) { + SetLineNo (LineNo); + mQuestionRef3_2->DevicePath = EFI_STRING_ID_INVALID; + } + + VOID SetDevicePath (IN EFI_STRING_ID DevicePath) { + mQuestionRef3_2->DevicePath = DevicePath; + } +}; + +class CIfrQuestionRef3_3 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_QUESTION_REF3_3 *mQuestionRef3_3; + +public: + CIfrQuestionRef3_3 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_QUESTION_REF3_OP, (CHAR8 **)NULL, sizeof (EFI_IFR_QUESTION_REF3_3)), + CIfrOpHeader (EFI_IFR_QUESTION_REF3_OP, &(GetObjBinAddr())->Header, sizeof (EFI_IFR_QUESTION_REF3_3)), mQuestionRef3_3(GetObjBinAddr()) { + SetLineNo (LineNo); + mQuestionRef3_3->DevicePath = EFI_STRING_ID_INVALID; + memset (&mQuestionRef3_3->Guid, 0, sizeof (EFI_GUID)); + } + + VOID SetDevicePath (IN EFI_STRING_ID DevicePath) { + mQuestionRef3_3->DevicePath = DevicePath; + } + + VOID SetGuid (IN EFI_GUID *Guid) { + mQuestionRef3_3->Guid = *Guid; + } +}; + +class CIfrRuleRef : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_RULE_REF *mRuleRef; + +public: + CIfrRuleRef ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_RULE_REF_OP), + CIfrOpHeader (EFI_IFR_RULE_REF_OP, &(GetObjBinAddr())->Header), mRuleRef(GetObjBinAddr()) { + SetLineNo (LineNo); + mRuleRef->RuleId = EFI_RULE_ID_INVALID; + } + + VOID SetRuleId (IN UINT8 RuleId) { + mRuleRef->RuleId = RuleId; + } +}; + +class CIfrStringRef1 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_STRING_REF1 *mStringRef1; + +public: + CIfrStringRef1 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_STRING_REF1_OP), + CIfrOpHeader (EFI_IFR_STRING_REF1_OP, &(GetObjBinAddr())->Header), mStringRef1(GetObjBinAddr()) { + SetLineNo (LineNo); + mStringRef1->StringId = EFI_STRING_ID_INVALID; + } + + VOID SetStringId (IN EFI_STRING_ID StringId) { + mStringRef1->StringId = StringId; + } +}; + +class CIfrStringRef2 : public CIfrObj, public CIfrOpHeader { +public: + CIfrStringRef2 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_STRING_REF2_OP), + CIfrOpHeader (EFI_IFR_STRING_REF2_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrThis : public CIfrObj, public CIfrOpHeader { +public: + CIfrThis ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_THIS_OP), + CIfrOpHeader (EFI_IFR_THIS_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrSecurity : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_SECURITY *mSecurity; + +public: + CIfrSecurity ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_SECURITY_OP), + CIfrOpHeader (EFI_IFR_SECURITY_OP, &(GetObjBinAddr())->Header), mSecurity(GetObjBinAddr()) { + SetLineNo (LineNo); + memset (&mSecurity->Permissions, 0, sizeof (EFI_GUID)); + } + + VOID SetPermissions (IN EFI_GUID *Permissions) { + memmove (&mSecurity->Permissions, Permissions, sizeof (EFI_GUID)); + } +}; + +class CIfrUint8 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_UINT8 *mUint8; + +public: + CIfrUint8 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_UINT8_OP), + CIfrOpHeader (EFI_IFR_UINT8_OP, &(GetObjBinAddr())->Header), mUint8(GetObjBinAddr()) { + SetLineNo (LineNo); + } + + VOID SetValue (IN UINT8 Value) { + mUint8->Value = Value; + } +}; + +class CIfrUint16 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_UINT16 *mUint16; + +public: + CIfrUint16 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_UINT16_OP), + CIfrOpHeader (EFI_IFR_UINT16_OP, &(GetObjBinAddr())->Header), mUint16(GetObjBinAddr()) { + SetLineNo (LineNo); + } + + VOID SetValue (IN UINT16 Value) { + mUint16->Value = Value; + } +}; + +class CIfrUint32 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_UINT32 *mUint32; + +public: + CIfrUint32 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_UINT32_OP), + CIfrOpHeader (EFI_IFR_UINT32_OP, &(GetObjBinAddr())->Header), mUint32(GetObjBinAddr()) { + SetLineNo (LineNo); + } + + VOID SetValue (IN UINT32 Value) { + mUint32->Value = Value; + } +}; + +class CIfrUint64 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_UINT64 *mUint64; + +public: + CIfrUint64 ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_UINT64_OP), + CIfrOpHeader (EFI_IFR_UINT64_OP, &(GetObjBinAddr())->Header), mUint64(GetObjBinAddr()) { + SetLineNo (LineNo); + } + + VOID SetValue (IN UINT64 Value) { + mUint64->Value = Value; + } +}; + +class CIfrTrue : public CIfrObj, public CIfrOpHeader { +public: + CIfrTrue ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_TRUE_OP), + CIfrOpHeader (EFI_IFR_TRUE_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrFalse : public CIfrObj, public CIfrOpHeader { +public: + CIfrFalse ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_FALSE_OP), + CIfrOpHeader (EFI_IFR_FALSE_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrOne : public CIfrObj, public CIfrOpHeader { +public: + CIfrOne ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_ONE_OP), + CIfrOpHeader (EFI_IFR_ONE_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrOnes : public CIfrObj, public CIfrOpHeader { +public: + CIfrOnes ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_ONES_OP), + CIfrOpHeader (EFI_IFR_ONES_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrZero : public CIfrObj, public CIfrOpHeader { +public: + CIfrZero ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_ZERO_OP), + CIfrOpHeader (EFI_IFR_ZERO_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrUndefined : public CIfrObj, public CIfrOpHeader { +public: + CIfrUndefined ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_UNDEFINED_OP), + CIfrOpHeader (EFI_IFR_UNDEFINED_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrVersion : public CIfrObj, public CIfrOpHeader { +public: + CIfrVersion ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_VERSION_OP), + CIfrOpHeader (EFI_IFR_VERSION_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrLength : public CIfrObj, public CIfrOpHeader { +public: + CIfrLength ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_LENGTH_OP), + CIfrOpHeader (EFI_IFR_LENGTH_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrNot : public CIfrObj, public CIfrOpHeader { +public: + CIfrNot ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_NOT_OP), + CIfrOpHeader (EFI_IFR_NOT_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrBitWiseNot : public CIfrObj, public CIfrOpHeader { +public: + CIfrBitWiseNot ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_BITWISE_NOT_OP), + CIfrOpHeader (EFI_IFR_BITWISE_NOT_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrToBoolean : public CIfrObj, public CIfrOpHeader { +public: + CIfrToBoolean ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_TO_BOOLEAN_OP), + CIfrOpHeader (EFI_IFR_TO_BOOLEAN_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrToString : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_TO_STRING *mToString; + +public: + CIfrToString ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_TO_STRING_OP), + CIfrOpHeader (EFI_IFR_TO_STRING_OP, &(GetObjBinAddr())->Header), mToString(GetObjBinAddr()) { + SetLineNo (LineNo); + } + + VOID SetFormat (IN UINT8 Format) { + mToString->Format = Format; + } +}; + +class CIfrToUint : public CIfrObj, public CIfrOpHeader { +public: + CIfrToUint ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_TO_UINT_OP), + CIfrOpHeader (EFI_IFR_TO_UINT_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrToUpper : public CIfrObj, public CIfrOpHeader { +public: + CIfrToUpper ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_TO_UPPER_OP), + CIfrOpHeader (EFI_IFR_TO_UPPER_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrToLower : public CIfrObj, public CIfrOpHeader { +public: + CIfrToLower ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_TO_LOWER_OP), + CIfrOpHeader (EFI_IFR_TO_LOWER_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrAdd : public CIfrObj, public CIfrOpHeader { +public: + CIfrAdd ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_ADD_OP), + CIfrOpHeader (EFI_IFR_ADD_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrBitWiseAnd : public CIfrObj, public CIfrOpHeader { +public: + CIfrBitWiseAnd ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_BITWISE_AND_OP), + CIfrOpHeader (EFI_IFR_BITWISE_AND_OP, &(GetObjBinAddr())->Header) { + SetLineNo(LineNo); + } +}; + +class CIfrBitWiseOr : public CIfrObj, public CIfrOpHeader { +public: + CIfrBitWiseOr ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_BITWISE_OR_OP), + CIfrOpHeader (EFI_IFR_BITWISE_OR_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrAnd : public CIfrObj, public CIfrOpHeader { +public: + CIfrAnd ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_AND_OP), + CIfrOpHeader (EFI_IFR_AND_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrCatenate : public CIfrObj, public CIfrOpHeader { +public: + CIfrCatenate ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_CATENATE_OP), + CIfrOpHeader (EFI_IFR_CATENATE_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrDivide : public CIfrObj, public CIfrOpHeader { +public: + CIfrDivide ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_DIVIDE_OP), + CIfrOpHeader (EFI_IFR_DIVIDE_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrEqual : public CIfrObj, public CIfrOpHeader { +public: + CIfrEqual ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_EQUAL_OP), + CIfrOpHeader (EFI_IFR_EQUAL_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrGreaterEqual : public CIfrObj, public CIfrOpHeader { +public: + CIfrGreaterEqual ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_GREATER_EQUAL_OP), + CIfrOpHeader (EFI_IFR_GREATER_EQUAL_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrGreaterThan : public CIfrObj, public CIfrOpHeader { +public: + CIfrGreaterThan ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_GREATER_THAN_OP), + CIfrOpHeader (EFI_IFR_GREATER_THAN_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrLessEqual : public CIfrObj, public CIfrOpHeader { +public: + CIfrLessEqual ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_LESS_EQUAL_OP), + CIfrOpHeader (EFI_IFR_LESS_EQUAL_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrLessThan : public CIfrObj, public CIfrOpHeader { +public: + CIfrLessThan ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_LESS_THAN_OP), + CIfrOpHeader (EFI_IFR_LESS_THAN_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrMap : public CIfrObj, public CIfrOpHeader{ +public: + CIfrMap ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_MAP_OP), + CIfrOpHeader (EFI_IFR_MAP_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrMatch : public CIfrObj, public CIfrOpHeader { +public: + CIfrMatch ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_MATCH_OP), + CIfrOpHeader (EFI_IFR_MATCH_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrMatch2 : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_MATCH2 *mMatch2; + +public: + CIfrMatch2 ( + IN UINT32 LineNo, + IN EFI_GUID *Guid + ) : CIfrObj (EFI_IFR_MATCH2_OP), + CIfrOpHeader (EFI_IFR_MATCH2_OP, &(GetObjBinAddr())->Header), mMatch2(GetObjBinAddr()) { + SetLineNo (LineNo); + memmove (&mMatch2->SyntaxType, Guid, sizeof (EFI_GUID)); + } +}; + +class CIfrMultiply : public CIfrObj, public CIfrOpHeader { +public: + CIfrMultiply ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_MULTIPLY_OP), + CIfrOpHeader (EFI_IFR_MULTIPLY_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrModulo : public CIfrObj, public CIfrOpHeader { +public: + CIfrModulo ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_MODULO_OP), + CIfrOpHeader (EFI_IFR_MODULO_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrNotEqual : public CIfrObj, public CIfrOpHeader { +public: + CIfrNotEqual ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_NOT_EQUAL_OP), + CIfrOpHeader (EFI_IFR_NOT_EQUAL_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrOr : public CIfrObj, public CIfrOpHeader { +public: + CIfrOr ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_OR_OP), + CIfrOpHeader (EFI_IFR_OR_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrShiftLeft : public CIfrObj, public CIfrOpHeader { +public: + CIfrShiftLeft ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_SHIFT_LEFT_OP), + CIfrOpHeader (EFI_IFR_SHIFT_LEFT_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrShiftRight : public CIfrObj, public CIfrOpHeader { +public: + CIfrShiftRight ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_SHIFT_RIGHT_OP), + CIfrOpHeader (EFI_IFR_SHIFT_RIGHT_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrSubtract : public CIfrObj, public CIfrOpHeader { +public: + CIfrSubtract ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_SUBTRACT_OP), + CIfrOpHeader (EFI_IFR_SUBTRACT_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrConditional : public CIfrObj, public CIfrOpHeader { +public: + CIfrConditional ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_CONDITIONAL_OP), + CIfrOpHeader (EFI_IFR_CONDITIONAL_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrFind : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_FIND *mFind; + +public: + CIfrFind ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_FIND_OP), + CIfrOpHeader (EFI_IFR_FIND_OP, &(GetObjBinAddr())->Header), mFind(GetObjBinAddr()) { + SetLineNo (LineNo); + } + + VOID SetFormat (IN UINT8 Format) { + mFind->Format = Format; + } +}; + +class CIfrMid : public CIfrObj, public CIfrOpHeader { +public: + CIfrMid ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_MID_OP), + CIfrOpHeader (EFI_IFR_MID_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrToken : public CIfrObj, public CIfrOpHeader { +public: + CIfrToken ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_TOKEN_OP), + CIfrOpHeader (EFI_IFR_TOKEN_OP, &(GetObjBinAddr())->Header) { + SetLineNo (LineNo); + } +}; + +class CIfrSpan : public CIfrObj, public CIfrOpHeader { +private: + EFI_IFR_SPAN *mSpan; + +public: + CIfrSpan ( + IN UINT32 LineNo + ) : CIfrObj (EFI_IFR_SPAN_OP), + CIfrOpHeader (EFI_IFR_SPAN_OP, &(GetObjBinAddr())->Header), mSpan(GetObjBinAddr()) { + SetLineNo (LineNo); + mSpan->Flags = EFI_IFR_FLAGS_FIRST_MATCHING; + } + + EFI_VFR_RETURN_CODE SetFlags (IN UINT8 LFlags) { + if (_IS_EQUAL (LFlags, EFI_IFR_FLAGS_FIRST_MATCHING)) { + mSpan->Flags |= EFI_IFR_FLAGS_FIRST_MATCHING; + } else if (_FLAG_TEST_AND_CLEAR (LFlags, EFI_IFR_FLAGS_FIRST_NON_MATCHING)) { + mSpan->Flags |= EFI_IFR_FLAGS_FIRST_NON_MATCHING; + } + + return _FLAGS_ZERO (LFlags) ? VFR_RETURN_SUCCESS : VFR_RETURN_FLAGS_UNSUPPORTED; + } +}; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrSyntax.g b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrSyntax.g new file mode 100644 index 00000000..21bf1cbe --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrSyntax.g @@ -0,0 +1,5708 @@ +/*++ @file +Vfr Syntax + +Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +--*/ + +#header<< + +#include "EfiVfr.h" +#include "VfrFormPkg.h" +#include "VfrError.h" +#include "VfrUtilityLib.h" +#include "AToken.h" +#include "ATokPtr.h" +>> + +<< +#ifdef UINT8_MAX +#undef UINT8_MAX +#endif +#include "stdio.h" +#include "PBlackBox.h" +#include "DLexerBase.h" +#include "VfrLexer.h" +#include "AToken.h" + +#define GET_LINENO(Obj) ((Obj)->getLine()) +#define SET_LINE_INFO(Obj, L) do {(Obj).SetLineNo((L)->getLine());} while (0) +#define CRT_END_OP(Obj) do {CIfrEnd EObj; if (Obj != NULL) EObj.SetLineNo ((Obj)->getLine());} while (0) + +typedef ANTLRCommonToken ANTLRToken; + +class CVfrDLGLexer : public VfrLexer +{ +public: + CVfrDLGLexer (DLGFileInput *F) : VfrLexer (F) {}; + void errstd (const char *Text) + { + printf ("unrecognized input '%s'\n", Text); + } +}; + +UINT8 +VfrParserStart ( + IN FILE *File, + IN INPUT_INFO_TO_SYNTAX *InputInfo + ) +{ + ParserBlackBox VfrParser(File); + VfrParser.parser()->SetOverrideClassGuid (InputInfo->OverrideClassGuid); + return VfrParser.parser()->vfrProgram(); +} +>> + +// +// Define a lexical class for parsing quoted strings. Basically +// starts with a double quote, and ends with a double quote that +// is not preceded with a backslash. +// +#lexclass QUOTED_STRING +#token TheString "~[\"]*\"" << mode (START); >> + +// +// Define a lexclass for skipping over C++ style comments +// +#lexclass CPP_COMMENT +#token "~[\n]*" << skip (); >> +#token "\n" << skip (); mode (START); newline (); >> + +// +// Standard lexclass is START +// +#lexclass START + +// +// Find start of C++ style comments +// +#token "//" << skip (); mode (CPP_COMMENT); >> + +// +// Skip whitespace +// +#token "[\ \t]" << skip (); >> + +// +// Skip over newlines, but count them +// +#token "\n" << skip (); newline (); >> + +// +// Skip over 'extern' in any included .H file +// +#token "extern" << skip (); mode (CPP_COMMENT); >> + +// +// Tokens for the different keywords. Syntax is: +// TokenName("ErrorMessageText") "TokenString" +// where: +// TokenName is the token name (must be capitalized) that is used in the rules +// ErrorMessageText is the string the compiler emits when it detects a syntax error +// TokenString is the actual matching string used in the user script +// +#token FormPkgType("formpkgtype") "formpkgtype" +#token OpenBrace("{") "\{" +#token CloseBrace("}") "\}" +#token OpenParen("(") "\(" +#token CloseParen(")") "\)" +#token OpenBracket("[") "\[" +#token CloseBracket("]") "\]" + +#token LineDefinition "#line\ [0-9]+\ \"~[\"]+\"[\ \t]*\n" << gCVfrErrorHandle.ParseFileScopeRecord (begexpr (), line ()); skip (); newline (); >> +#token DevicePath("devicepath") "devicepath" +#token FormSet("formset") "formset" +#token FormSetId("formsetid") "formsetid" +#token EndFormSet("endformset") "endformset" +#token Title("title") "title" +#token FormId("formid") "formid" +#token OneOf("oneof") "oneof" +#token EndOneOf("endoneof") "endoneof" +#token Prompt("prompt") "prompt" +#token OrderedList("orderedlist") "orderedlist" +#token MaxContainers("maxcontainers") "maxcontainers" +#token EndList("endlist") "endlist" +#token EndForm("endform") "endform" +#token Form("form") "form" +#token FormMap("formmap") "formmap" +#token MapTitle("maptitle") "maptitle" +#token MapGuid("mapguid") "mapguid" +#token Subtitle("subtitle") "subtitle" +#token EndSubtitle("endsubtitle") "endsubtitle" +#token Help("help") "help" +#token Text("text") "text" +#token Option("option") "option" +#token FLAGS("flags") "flags" +#token Date("date") "date" +#token EndDate("enddate") "enddate" +#token Year("year") "year" +#token Month("month") "month" +#token Day("day") "day" +#token Time("time") "time" +#token EndTime("endtime") "endtime" +#token Hour("hour") "hour" +#token Minute("minute") "minute" +#token Second("second") "second" +#token GrayOutIf("grayoutif") "grayoutif" +#token Label("label") "label" +#token Timeout("timeout") "timeout" +#token Inventory("inventory") "inventory" +#token NonNvDataMap("_NON_NV_DATA_MAP") "_NON_NV_DATA_MAP" +#token Struct("struct") "struct" +#token Union("union") "union" +#token Boolean("BOOLEAN") "BOOLEAN" +#token Uint64("UINT64") "UINT64" +#token Uint32("UINT32") "UINT32" +#token Uint16("UINT16") "UINT16" +#token Char16("CHAR16") "CHAR16" +#token Uint8("UINT8") "UINT8" +#token Uuid("guid") "guid" +#token CheckBox("checkbox") "checkbox" +#token EndCheckBox("endcheckbox") "endcheckbox" +#token Numeric("numeric") "numeric" +#token EndNumeric("endnumeric") "endnumeric" +#token Minimum("minimum") "minimum" +#token Maximum("maximum") "maximum" +#token STEP("step") "step" +#token Default("default") "default" +#token Password("password") "password" +#token EndPassword("endpassword") "endpassword" +#token String("string") "string" +#token EndString("endstring") "endstring" +#token MinSize("minsize") "minsize" +#token MaxSize("maxsize") "maxsize" +#token Encoding("encoding") "encoding" +#token SuppressIf("suppressif") "suppressif" +#token DisableIf("disableif") "disableif" +#token Hidden("hidden") "hidden" +#token Goto("goto") "goto" +#token FormSetGuid("formsetguid") "formsetguid" +#token InconsistentIf("inconsistentif") "inconsistentif" +#token WarningIf("warningif") "warningif" +#token NoSubmitIf("nosubmitif") "nosubmitif" +#token EndIf("endif") "endif" +#token Key("key") "key" +#token DefaultFlag("DEFAULT") "DEFAULT" +#token ManufacturingFlag("MANUFACTURING") "MANUFACTURING" +#token InteractiveFlag("INTERACTIVE") "INTERACTIVE" +#token NVAccessFlag("NV_ACCESS") "NV_ACCESS" +#token ResetRequiredFlag("RESET_REQUIRED") "RESET_REQUIRED" +#token ReconnectRequiredFlag("RECONNECT_REQUIRED") "RECONNECT_REQUIRED" +#token LateCheckFlag("LATE_CHECK") "LATE_CHECK" +#token ReadOnlyFlag("READ_ONLY") "READ_ONLY" +#token OptionOnlyFlag("OPTIONS_ONLY") "OPTIONS_ONLY" +#token RestStyleFlag("REST_STYLE") "REST_STYLE" +#token Class("class") "class" +#token Subclass("subclass") "subclass" +#token ClassGuid("classguid") "classguid" +#token TypeDef("typedef") "typedef" +#token Restore("restore") "restore" +#token Save("save") "save" +#token Defaults("defaults") "defaults" +#token Banner("banner") "banner" +#token Align("align") "align" +#token Left("left") "left" +#token Right("right") "right" +#token Center("center") "center" +#token Line("line") "line" +#token Name("name") "name" + +#token VarId("varid") "varid" +#token Question("question") "question" +#token QuestionId("questionid") "questionid" +#token Image("image") "image" +#token Locked("locked") "locked" +#token Rule("rule") "rule" +#token EndRule("endrule") "endrule" +#token Value("value") "value" +#token Read("read") "read" +#token Write("write") "write" +#token ResetButton("resetbutton") "resetbutton" +#token EndResetButton("endresetbutton") "endresetbutton" +#token DefaultStore("defaultstore") "defaultstore" +#token Attribute("attribute") "attribute" +#token Varstore("varstore") "varstore" +#token Efivarstore("efivarstore") "efivarstore" +#token VarSize("varsize") "varsize" +#token NameValueVarStore("namevaluevarstore") "namevaluevarstore" +#token Action("action") "action" +#token Config("config") "config" +#token EndAction("endaction") "endaction" +#token Refresh("refresh") "refresh" +#token Interval("interval") "interval" +#token VarstoreDevice("varstoredevice") "varstoredevice" +#token GuidOp("guidop") "guidop" +#token EndGuidOp("endguidop") "endguidop" +#token DataType("datatype") "datatype" +#token Data("data") "data" +#token Modal("modal") "modal" + +// +// Define the class and subclass tokens +// +#token ClassNonDevice("NONDEVICE") "NON_DEVICE" +#token ClassDiskDevice("DISK_DEVICE") "DISK_DEVICE" +#token ClassVideoDevice("VIDEO_DEVICE") "VIDEO_DEVICE" +#token ClassNetworkDevice("NETWORK_DEVICE") "NETWORK_DEVICE" +#token ClassInputDevice("INPUT_DEVICE") "INPUT_DEVICE" +#token ClassOnBoardDevice("ONBOARD_DEVICE") "ONBOARD_DEVICE" +#token ClassOtherDevice("OTHER_DEVICE") "OTHER_DEVICE" + +#token SubclassSetupApplication("SETUP_APPLICATION") "SETUP_APPLICATION" +#token SubclassGeneralApplication("GENERAL_APPLICATION") "GENERAL_APPLICATION" +#token SubclassFrontPage("FRONT_PAGE") "FRONT_PAGE" +#token SubclassSingleUse("SINGLE_USE") "SINGLE_USE" + +// +// This is the overall definition of a VFR form definition script. +// + +vfrProgram > [UINT8 Return] : + << + mParserStatus = 0; + mCIfrOpHdrIndex = 0; + mConstantOnlyInExpression = FALSE; + >> + ( + vfrPragmaPackDefinition + | vfrDataStructDefinition + | vfrDataUnionDefinition + )* + vfrFormSetDefinition + << $Return = mParserStatus; >> + ; + +pragmaPackShowDef : + L:"show" << gCVfrVarDataTypeDB.Pack (L->getLine(), VFR_PACK_SHOW); >> + ; + +pragmaPackStackDef : + << + UINT32 LineNum; + UINT8 PackAction; + CHAR8 *Identifier = NULL; + UINT32 PackNumber = DEFAULT_PACK_ALIGN; + >> + ( + L1:"push" << LineNum = L1->getLine(); PackAction = VFR_PACK_PUSH; >> + | L2:"pop" << LineNum = L2->getLine(); PackAction = VFR_PACK_POP; >> + ) + { + "," ID:StringIdentifier << Identifier = ID->getText(); >> + } + { + "," N:Number << PackAction |= VFR_PACK_ASSIGN; PackNumber = _STOU32(N->getText(), N->getLine()); >> + } + << gCVfrVarDataTypeDB.Pack (LineNum, PackAction, Identifier, PackNumber); >> + ; + +pragmaPackNumber : + << + UINT32 LineNum; + UINT32 PackNumber = DEFAULT_PACK_ALIGN; + >> + N:Number << LineNum = N->getLine(); PackNumber = _STOU32(N->getText(), N->getLine()); >> + << gCVfrVarDataTypeDB.Pack (LineNum, VFR_PACK_ASSIGN, NULL, PackNumber); >> + ; + +vfrPragmaPackDefinition : + "\#pragma" "pack" "\(" + { + pragmaPackShowDef + | pragmaPackStackDef + | pragmaPackNumber + } + "\)" + ; + + vfrDataUnionDefinition : + { TypeDef } Union << gCVfrVarDataTypeDB.DeclareDataTypeBegin (); >> + { NonNvDataMap } + { + N1:StringIdentifier << _PCATCH(gCVfrVarDataTypeDB.SetNewTypeName (N1->getText()), N1); >> + } + OpenBrace + vfrDataStructFields[TRUE] + CloseBrace + { + N2:StringIdentifier << _PCATCH(gCVfrVarDataTypeDB.SetNewTypeName (N2->getText()), N2); >> + } + ";" << gCVfrVarDataTypeDB.DeclareDataTypeEnd ();>> + ; + +vfrDataStructDefinition : + { TypeDef } Struct << gCVfrVarDataTypeDB.DeclareDataTypeBegin (); >> + { NonNvDataMap } + { + N1:StringIdentifier << _PCATCH(gCVfrVarDataTypeDB.SetNewTypeName (N1->getText()), N1); >> + } + OpenBrace + vfrDataStructFields[FALSE] + CloseBrace + { + N2:StringIdentifier << _PCATCH(gCVfrVarDataTypeDB.SetNewTypeName (N2->getText()), N2); >> + } + ";" << gCVfrVarDataTypeDB.DeclareDataTypeEnd (); >> + ; + +vfrDataStructFields [BOOLEAN FieldInUnion]: + ( + dataStructField64 [FieldInUnion] | + dataStructField32 [FieldInUnion] | + dataStructField16 [FieldInUnion] | + dataStructField8 [FieldInUnion] | + dataStructFieldBool [FieldInUnion] | + dataStructFieldString [FieldInUnion]| + dataStructFieldDate [FieldInUnion] | + dataStructFieldTime [FieldInUnion] | + dataStructFieldRef [FieldInUnion] | + dataStructFieldUser [FieldInUnion] | + dataStructBitField64 [FieldInUnion] | + dataStructBitField32 [FieldInUnion] | + dataStructBitField16 [FieldInUnion] | + dataStructBitField8 [FieldInUnion] + )* + ; + +dataStructField64 [BOOLEAN FieldInUnion]: + << UINT32 ArrayNum = 0; >> + D:"UINT64" + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText(), I->getLine()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), D->getText(), ArrayNum, FieldInUnion), N); >> + ; + +dataStructField32 [BOOLEAN FieldInUnion]: + << UINT32 ArrayNum = 0; >> + D:"UINT32" + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText(), I->getLine()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), D->getText(), ArrayNum, FieldInUnion), N); >> + ; + +dataStructField16 [BOOLEAN FieldInUnion]: + << + UINT32 ArrayNum = 0; + >> + ("UINT16" | "CHAR16") + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText(), I->getLine()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), (CHAR8 *) "UINT16", ArrayNum, FieldInUnion), N); >> + ; + +dataStructField8 [BOOLEAN FieldInUnion]: + << UINT32 ArrayNum = 0; >> + D:"UINT8" + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText(), I->getLine()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), D->getText(), ArrayNum, FieldInUnion), N); >> + ; + +dataStructFieldBool [BOOLEAN FieldInUnion]: + << UINT32 ArrayNum = 0; >> + D:"BOOLEAN" + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText(), I->getLine()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), D->getText(), ArrayNum, FieldInUnion), N); >> + ; + +dataStructFieldString [BOOLEAN FieldInUnion]: + << UINT32 ArrayNum = 0; >> + D:"EFI_STRING_ID" + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText(), I->getLine()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), D->getText(), ArrayNum, FieldInUnion), N); >> + ; + +dataStructFieldDate [BOOLEAN FieldInUnion]: + << UINT32 ArrayNum = 0; >> + D:"EFI_HII_DATE" + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText(), I->getLine()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), D->getText(), ArrayNum, FieldInUnion), N); >> + ; + +dataStructFieldTime [BOOLEAN FieldInUnion]: + << UINT32 ArrayNum = 0; >> + D:"EFI_HII_TIME" + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText(), I->getLine()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), D->getText(), ArrayNum, FieldInUnion), N); >> + ; + +dataStructFieldRef [BOOLEAN FieldInUnion]: + << UINT32 ArrayNum = 0; >> + D:"EFI_HII_REF" + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText(), I->getLine()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), D->getText(), ArrayNum, FieldInUnion), N); >> + ; + +dataStructFieldUser [BOOLEAN FieldInUnion]: + << UINT32 ArrayNum = 0; >> + T:StringIdentifier + N:StringIdentifier + { + OpenBracket I:Number CloseBracket << ArrayNum = _STOU32(I->getText(), I->getLine()); >> + } + ";" << _PCATCH(gCVfrVarDataTypeDB.DataTypeAddField (N->getText(), T->getText(), ArrayNum, FieldInUnion), T); >> + ; + +dataStructBitField64[BOOLEAN FieldInUnion]: + << + UINT32 Width = 0; + BOOLEAN HasBitFieldName = FALSE; + >> + D:"UINT64" + { + N:StringIdentifier << HasBitFieldName = TRUE;>> + } + ":" I:Number << Width = _STOU32(I->getText(), I->getLine());>> + + ";" << if (HasBitFieldName) { + _PCATCH(gCVfrVarDataTypeDB.DataTypeAddBitField (N->getText(), D->getText(), Width, FieldInUnion), N); + } else { + _PCATCH(gCVfrVarDataTypeDB.DataTypeAddBitField (NULL, D->getText(), Width, FieldInUnion), D); + } + >> + ; + +dataStructBitField32[BOOLEAN FieldInUnion]: + << + UINT32 Width = 0; + BOOLEAN HasBitFieldName = FALSE; + >> + D:"UINT32" + { + N:StringIdentifier << HasBitFieldName = TRUE;>> + } + + ":" I:Number << Width = _STOU32(I->getText(), I->getLine());>> + + ";" << if (HasBitFieldName) { + _PCATCH(gCVfrVarDataTypeDB.DataTypeAddBitField (N->getText(), D->getText(), Width, FieldInUnion), N); + } else { + _PCATCH(gCVfrVarDataTypeDB.DataTypeAddBitField (NULL, D->getText(), Width, FieldInUnion), D); + } + >> + ; + +dataStructBitField16[BOOLEAN FieldInUnion]: + << + UINT32 Width = 0; + BOOLEAN HasBitFieldName = FALSE; + >> + D:"UINT16" + { + N:StringIdentifier << HasBitFieldName = TRUE;>> + } + ":" I:Number << Width = _STOU32(I->getText(), I->getLine());>> + + ";" << if (HasBitFieldName) { + _PCATCH(gCVfrVarDataTypeDB.DataTypeAddBitField (N->getText(), D->getText(), Width, FieldInUnion), N); + } else { + _PCATCH(gCVfrVarDataTypeDB.DataTypeAddBitField (NULL, D->getText(), Width, FieldInUnion), D); + } + >> + ; + +dataStructBitField8[BOOLEAN FieldInUnion]: + << + UINT32 Width = 0; + BOOLEAN HasBitFieldName = FALSE; + >> + D:"UINT8" + { + N:StringIdentifier << HasBitFieldName = TRUE;>> + } + ":" I:Number << Width = _STOU32(I->getText(), I->getLine());>> + + ";" << if (HasBitFieldName) { + _PCATCH(gCVfrVarDataTypeDB.DataTypeAddBitField (N->getText(), D->getText(), Width, FieldInUnion), N); + } else { + _PCATCH(gCVfrVarDataTypeDB.DataTypeAddBitField (NULL, D->getText(), Width, FieldInUnion), D); + } + >> + ; + +//***************************************************************************** +// +// the syntax of GUID definition +// +guidSubDefinition [EFI_GUID &Guid] : + G4:Number "," G5:Number "," G6:Number "," G7:Number "," G8:Number "," G9:Number "," G10:Number "," G11:Number + << + Guid.Data4[0] = _STOU8(G4->getText(), G4->getLine()); + Guid.Data4[1] = _STOU8(G5->getText(), G5->getLine()); + Guid.Data4[2] = _STOU8(G6->getText(), G6->getLine()); + Guid.Data4[3] = _STOU8(G7->getText(), G7->getLine()); + Guid.Data4[4] = _STOU8(G8->getText(), G8->getLine()); + Guid.Data4[5] = _STOU8(G9->getText(), G9->getLine()); + Guid.Data4[6] = _STOU8(G10->getText(), G10->getLine()); + Guid.Data4[7] = _STOU8(G11->getText(), G11->getLine()); + >> + ; + +guidDefinition [EFI_GUID &Guid] : + OpenBrace + G1:Number "," G2:Number "," G3:Number "," + << + Guid.Data1 = _STOU32 (G1->getText(), G1->getLine()); + Guid.Data2 = _STOU16 (G2->getText(), G2->getLine()); + Guid.Data3 = _STOU16 (G3->getText(), G3->getLine()); + >> + ( + OpenBrace guidSubDefinition[Guid] CloseBrace + | guidSubDefinition[Guid] + ) + CloseBrace + ; + +//***************************************************************************** +// +// the syntax of form set definition +// +vfrFormSetDefinition : + << + EFI_GUID Guid; + EFI_GUID DefaultClassGuid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID; + EFI_GUID ClassGuid1, ClassGuid2, ClassGuid3, ClassGuid4; + UINT8 ClassGuidNum = 0; + CIfrFormSet *FSObj = NULL; + UINT16 C, SC; + CHAR8* InsertOpcodeAddr = NULL; + >> + L:FormSet + Uuid "=" guidDefinition[Guid] "," + Title "=" "STRING_TOKEN" "\(" S1:Number "\)" "," + Help "=" "STRING_TOKEN" "\(" S2:Number "\)" "," + { + ClassGuid "=" guidDefinition[ClassGuid1] << ++ClassGuidNum; >> + { + "\|" guidDefinition[ClassGuid2] << ++ClassGuidNum; >> + { + "\|" guidDefinition[ClassGuid3] << ++ClassGuidNum; >> + { + "\|" guidDefinition[ClassGuid4] << ++ClassGuidNum; >> + } + } + } + "," + } + << + if (mOverrideClassGuid != NULL && ClassGuidNum >= 4) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, L->getLine(), "Already has 4 class guids, can't add extra class guid!"); + } + switch (ClassGuidNum) { + case 0: + if (mOverrideClassGuid != NULL) { + ClassGuidNum = 2; + } else { + ClassGuidNum = 1; + } + FSObj = new CIfrFormSet(sizeof(EFI_IFR_FORM_SET) + ClassGuidNum * sizeof(EFI_GUID)); + FSObj->SetClassGuid(&DefaultClassGuid); + if (mOverrideClassGuid != NULL) { + FSObj->SetClassGuid(mOverrideClassGuid); + } + break; + case 1: + if (mOverrideClassGuid != NULL) { + ClassGuidNum ++; + } + FSObj = new CIfrFormSet(sizeof(EFI_IFR_FORM_SET) + ClassGuidNum * sizeof(EFI_GUID)); + FSObj->SetClassGuid(&ClassGuid1); + if (mOverrideClassGuid != NULL) { + FSObj->SetClassGuid(mOverrideClassGuid); + } + break; + case 2: + if (mOverrideClassGuid != NULL) { + ClassGuidNum ++; + } + FSObj = new CIfrFormSet(sizeof(EFI_IFR_FORM_SET) + ClassGuidNum * sizeof(EFI_GUID)); + FSObj->SetClassGuid(&ClassGuid1); + FSObj->SetClassGuid(&ClassGuid2); + if (mOverrideClassGuid != NULL) { + FSObj->SetClassGuid(mOverrideClassGuid); + } + break; + case 3: + if (mOverrideClassGuid != NULL) { + ClassGuidNum ++; + } + FSObj = new CIfrFormSet(sizeof(EFI_IFR_FORM_SET) + ClassGuidNum * sizeof(EFI_GUID)); + FSObj->SetClassGuid(&ClassGuid1); + FSObj->SetClassGuid(&ClassGuid2); + FSObj->SetClassGuid(&ClassGuid3); + if (mOverrideClassGuid != NULL) { + FSObj->SetClassGuid(mOverrideClassGuid); + } + break; + case 4: + FSObj = new CIfrFormSet(sizeof(EFI_IFR_FORM_SET) + ClassGuidNum * sizeof(EFI_GUID)); + FSObj->SetClassGuid(&ClassGuid1); + FSObj->SetClassGuid(&ClassGuid2); + FSObj->SetClassGuid(&ClassGuid3); + FSObj->SetClassGuid(&ClassGuid4); + break; + default: + break; + } + + SET_LINE_INFO (*FSObj, L); + FSObj->SetGuid (&Guid); + FSObj->SetFormSetTitle (_STOSID(S1->getText(), S1->getLine())); + FSObj->SetHelp (_STOSID(S2->getText(), S2->getLine())); + >> + { + FC:Class "=" classDefinition[C] "," << {CIfrClass CObj;SET_LINE_INFO (CObj, FC); CObj.SetClass(C);} >> + } + { + FSC:Subclass "=" subclassDefinition[SC] "," << {CIfrSubClass SCObj; SET_LINE_INFO (SCObj, FSC); SCObj.SetSubClass(SC);} >> + } + << + _DeclareStandardDefaultStorage (GET_LINENO (L)); + >> + vfrFormSetList + E:EndFormSet << + // + // Declare undefined Question so that they can be used in expression. + // + if (gCFormPkg.HavePendingUnassigned()) { + mParserStatus += gCFormPkg.DeclarePendingQuestion ( + gCVfrVarDataTypeDB, + gCVfrDataStorage, + mCVfrQuestionDB, + &mFormsetGuid, + E->getLine(), + &InsertOpcodeAddr + ); + gNeedAdjustOpcode = TRUE; + } + + CRT_END_OP (E); + + // + // Adjust the pending question position. + // Move the position from current to before the end of the last form in the form set. + // + if (gNeedAdjustOpcode) { + gCFormPkg.AdjustDynamicInsertOpcode ( + mLastFormEndAddr, + InsertOpcodeAddr, + FALSE + ); + } + + if (FSObj != NULL) { + delete FSObj; + } + >> + ";" + ; + +vfrFormSetList : + ( + vfrFormDefinition | + vfrFormMapDefinition | + vfrStatementImage | + vfrStatementVarStoreLinear | + vfrStatementVarStoreEfi | + vfrStatementVarStoreNameValue | + vfrStatementDefaultStore | + vfrStatementDisableIfFormSet | + vfrStatementSuppressIfFormSet | + vfrStatementExtension + )* + ; + +vfrStatementExtension: + << + EFI_GUID Guid; + CIfrGuid *GuidObj = NULL; + CHAR8 *TypeName = NULL; + UINT32 TypeSize = 0; + UINT8 *DataBuff = NULL; + UINT32 Size = 0; + UINT8 Idx = 0; + UINT32 LineNum; + BOOLEAN IsStruct = FALSE; + UINT32 ArrayNum = 0; + >> + L:GuidOp + Uuid "=" guidDefinition[Guid] + {"," DataType "=" + ( + U64:"UINT64" {OpenBracket AN1:Number CloseBracket <getText(), AN1->getLine());>>} + << TypeName = U64->getText(); LineNum = U64->getLine(); >> + | U32:"UINT32" {OpenBracket AN2:Number CloseBracket <getText(), AN2->getLine());>>} + << TypeName = U32->getText(); LineNum = U32->getLine(); >> + | U16:"UINT16" {OpenBracket AN3:Number CloseBracket <getText(), AN3->getLine());>>} + << TypeName = U16->getText(); LineNum = U16->getLine(); >> + | U8:"UINT8" {OpenBracket AN4:Number CloseBracket <getText(), AN4->getLine());>>} + << TypeName = U8->getText(); LineNum = U8->getLine(); >> + | BL:"BOOLEAN" {OpenBracket AN5:Number CloseBracket <getText(), AN5->getLine());>>} + << TypeName = BL->getText(); LineNum = BL->getLine(); >> + | SI:"EFI_STRING_ID" {OpenBracket AN6:Number CloseBracket <getText(), AN6->getLine());>>} + << TypeName = SI->getText(); LineNum = SI->getLine(); >> + | D:"EFI_HII_DATE" {OpenBracket AN7:Number CloseBracket <getText(), AN7->getLine());>>} + << TypeName = D->getText(); LineNum = D->getLine(); IsStruct = TRUE;>> + | T:"EFI_HII_TIME" {OpenBracket AN8:Number CloseBracket <getText(), AN8->getLine());>>} + << TypeName = T->getText(); LineNum = T->getLine(); IsStruct = TRUE;>> + | R:"EFI_HII_REF" {OpenBracket AN9:Number CloseBracket <getText(), AN9->getLine());>>} + << TypeName = R->getText(); LineNum = R->getLine(); IsStruct = TRUE;>> + | TN:StringIdentifier {OpenBracket AN10:Number CloseBracket <getText(), AN10->getLine());>>} + << TypeName = TN->getText(); LineNum = TN->getLine(); IsStruct = TRUE;>> + ) + << + _PCATCH(gCVfrVarDataTypeDB.GetDataTypeSize(TypeName, &TypeSize), LineNum); + if (ArrayNum > 0) { + Size = TypeSize*ArrayNum; + } else { + Size = TypeSize; + } + if (Size > (128 - sizeof (EFI_IFR_GUID))) return; + DataBuff = (UINT8 *)malloc(Size); + for (Idx = 0; Idx < Size; Idx++) { + DataBuff[Idx] = 0; + } + >> + vfrExtensionData [DataBuff, Size, TypeName, TypeSize, IsStruct, ArrayNum] + } + << + { + GuidObj = new CIfrGuid(Size); + if (GuidObj != NULL) { + GuidObj->SetLineNo(L->getLine()); + GuidObj->SetGuid (&Guid); + } + } + if (TypeName != NULL) { + GuidObj->SetData(DataBuff, Size); + } + >> + {"," + ( + vfrStatementExtension + )* + E:EndGuidOp << GuidObj->SetScope(1); CRT_END_OP (E); >> + } + << + if (GuidObj != NULL) delete GuidObj; + if (DataBuff != NULL) free(DataBuff); + >> + ";" +; + +vfrExtensionData[UINT8 *DataBuff, UINT32 Size, CHAR8 *TypeName, UINT32 TypeSize, BOOLEAN IsStruct, UINT32 ArrayNum]: + << + CHAR8 *TFName = NULL; + UINT32 ArrayIdx = 0; + UINT16 FieldOffset; + UINT8 FieldType; + UINT32 FieldSize; + UINT64 Data_U64 = 0; + UINT32 Data_U32 = 0; + UINT16 Data_U16 = 0; + UINT8 Data_U8 = 0; + BOOLEAN Data_BL = 0; + EFI_STRING_ID Data_SID = 0; + BOOLEAN IsArray = FALSE; + UINT8 *ByteOffset = NULL; + BOOLEAN BitField = FALSE; + UINT64 Value; + UINT64 Mask; + UINT16 Offset; + UINT8 PreBits; + >> +( + ("," "data" {OpenBracket IDX1:Number CloseBracket <>} + << + ArrayIdx = 0; + if (IsArray == TRUE) { + ArrayIdx = _STOU8(IDX1->getText(), IDX1->getLine()); + if (ArrayIdx >= ArrayNum) return; + IsArray = FALSE; + } + ByteOffset = DataBuff + (ArrayIdx * TypeSize); + if (IsStruct == TRUE) { + _STRCAT(&TFName, TypeName); + } + >> + ("." FN:StringIdentifier + << + if (IsStruct == TRUE) { + _STRCAT(&TFName, "."); + _STRCAT(&TFName, FN->getText()); + } + >> + { + OpenBracket IDX2:Number CloseBracket + << + if (IsStruct == TRUE) { + _STRCAT(&TFName, "["); + _STRCAT(&TFName, IDX2->getText()); + _STRCAT(&TFName, "]"); + } + >> + } + )* + "=" RD:Number + << + if (IsStruct == FALSE) { + if (strcmp ("UINT64", TypeName) == 0) { + Data_U64 = _STOU64(RD->getText(), RD->getLine()); + memcpy (ByteOffset, &Data_U64, TypeSize); + }else if (strcmp ("UINT32", TypeName) == 0) { + Data_U32 = _STOU32(RD->getText(), RD->getLine()); + memcpy (ByteOffset, &Data_U32, TypeSize); + }else if (strcmp ("UINT16", TypeName) == 0) { + Data_U16 = _STOU16(RD->getText(), RD->getLine()); + memcpy (ByteOffset, &Data_U16, TypeSize); + }else if (strcmp ("UINT8", TypeName) == 0) { + Data_U8 = _STOU8(RD->getText(), RD->getLine()); + memcpy (ByteOffset, &Data_U8, TypeSize); + }else if (strcmp ("BOOLEAN", TypeName)== 0) { + Data_BL = _STOU8(RD->getText(), RD->getLine()); + memcpy (ByteOffset, &Data_BL, TypeSize); + }else if (strcmp ("EFI_STRING_ID", TypeName) == 0) { + Data_SID = _STOSID(RD->getText(), RD->getLine()); + memcpy (ByteOffset, &Data_SID, TypeSize); + } + } else { + gCVfrVarDataTypeDB.GetDataFieldInfo(TFName, FieldOffset, FieldType, FieldSize, BitField); + if (BitField) { + Mask = (1 << FieldSize) - 1; + Offset = FieldOffset / 8; + PreBits = FieldOffset % 8; + Mask <<= PreBits; + } + switch (FieldType) { + case EFI_IFR_TYPE_NUM_SIZE_8: + Data_U8 = _STOU8(RD->getText(), RD->getLine()); + if (BitField) { + // + // Set the value to the bit fileds. + // + Value = *(UINT8*) (ByteOffset + Offset); + Data_U8 <<= PreBits; + Value = (Value & (~Mask)) | Data_U8; + memcpy (ByteOffset + Offset, &Value, sizeof (UINT8)); + } else { + memcpy (ByteOffset + FieldOffset, &Data_U8, FieldSize); + } + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + Data_U16 = _STOU16(RD->getText(), RD->getLine()); + if (BitField) { + // + // Set the value to the bit fileds. + // + Value = *(UINT16*) (ByteOffset + Offset); + Data_U16 <<= PreBits; + Value = (Value & (~Mask)) | Data_U16; + memcpy (ByteOffset + Offset, &Value, sizeof (UINT16)); + } else { + memcpy (ByteOffset + FieldOffset, &Data_U16, FieldSize); + } + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + Data_U32 = _STOU32(RD->getText(), RD->getLine()); + if (BitField) { + // + // Set the value to the bit fileds. + // + Value = *(UINT32*) (ByteOffset + Offset); + Data_U32 <<= PreBits; + Value = (Value & (~Mask)) | Data_U32; + memcpy (ByteOffset + Offset, &Value, sizeof (UINT32)); + } else { + memcpy (ByteOffset + FieldOffset, &Data_U32, FieldSize); + } + break; + case EFI_IFR_TYPE_NUM_SIZE_64: + Data_U64 = _STOU64(RD->getText(), RD->getLine()); + if (BitField) { + // + // Set the value to the bit fileds. + // + Value = *(UINT64*) (ByteOffset + Offset); + Data_U64 <<= PreBits; + Value = (Value & (~Mask)) | Data_U64; + memcpy (ByteOffset + Offset, &Value, sizeof (UINT64)); + } else { + memcpy (ByteOffset + FieldOffset, &Data_U64, FieldSize); + } + break; + case EFI_IFR_TYPE_BOOLEAN: + Data_BL = _STOU8(RD->getText(), RD->getLine()); + memcpy (ByteOffset + FieldOffset, &Data_BL, FieldSize); + break; + case EFI_IFR_TYPE_STRING: + Data_SID = _STOSID(RD->getText(), RD->getLine()); + memcpy (ByteOffset + FieldOffset, &Data_SID, FieldSize); + break; + default: + break; + } + } + if (TFName != NULL) { delete[] TFName; TFName = NULL; } + >> + )* +) +; + + +vfrStatementDefaultStore : + << UINT16 DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD; >> + D:DefaultStore N:StringIdentifier "," + Prompt "=" "STRING_TOKEN" "\(" S:Number "\)" + { + "," Attribute "=" A:Number << DefaultId = _STOU16(A->getText(), A->getLine()); >> + } + << + if (gCVfrDefaultStore.DefaultIdRegistered (DefaultId) == FALSE) { + CIfrDefaultStore DSObj; + _PCATCH(gCVfrDefaultStore.RegisterDefaultStore (DSObj.GetObjBinAddr(), N->getText(), _STOSID(S->getText(), S->getLine()), DefaultId)), D->getLine(); + DSObj.SetLineNo(D->getLine()); + DSObj.SetDefaultName (_STOSID(S->getText(), S->getLine())); + DSObj.SetDefaultId (DefaultId); + } else { + _PCATCH(gCVfrDefaultStore.ReRegisterDefaultStoreById (DefaultId, N->getText(), _STOSID(S->getText(), S->getLine()))), D->getLine(); + } + >> + ";" + ; + +vfrStatementVarStoreLinear : + << + EFI_GUID Guid; + CIfrVarStore VSObj; + CHAR8 *TypeName; + CHAR8 *StoreName; + UINT32 LineNum; + EFI_VARSTORE_ID VarStoreId = EFI_VARSTORE_ID_INVALID; + UINT32 Size; + BOOLEAN IsBitVarStore = FALSE; + >> + V:Varstore << VSObj.SetLineNo(V->getLine()); >> + ( + TN:StringIdentifier "," << TypeName = TN->getText(); LineNum = TN->getLine(); IsBitVarStore = gCVfrVarDataTypeDB.DataTypeHasBitField (TN->getText());>> + | U8:"UINT8" "," << TypeName = U8->getText(); LineNum = U8->getLine(); >> + | U16:"UINT16" "," << TypeName = U16->getText(); LineNum = U16->getLine(); >> + | C16:"CHAR16" "," << TypeName = (CHAR8 *) "UINT16"; LineNum = C16->getLine(); >> + | U32:"UINT32" "," << TypeName = U32->getText(); LineNum = U32->getLine(); >> + | U64:"UINT64" "," << TypeName = U64->getText(); LineNum = U64->getLine(); >> + | D:"EFI_HII_DATE" "," << TypeName = D->getText(); LineNum = D->getLine(); >> + | T:"EFI_HII_TIME" "," << TypeName = T->getText(); LineNum = T->getLine(); >> + | R:"EFI_HII_REF" "," << TypeName = R->getText(); LineNum = R->getLine(); >> + ) + { + VarId "=" ID:Number "," << + _PCATCH( + (INTN)(VarStoreId = _STOU16(ID->getText(), ID->getLine())) != 0, + (INTN)TRUE, + ID, + "varid 0 is not allowed." + ); + >> + } + Name "=" SN:StringIdentifier "," + Uuid "=" guidDefinition[Guid] + << + + StoreName = SN->getText(); + _PCATCH(gCVfrDataStorage.DeclareBufferVarStore ( + StoreName, + &Guid, + &gCVfrVarDataTypeDB, + TypeName, + VarStoreId, + IsBitVarStore + ), LineNum); + VSObj.SetGuid (&Guid); + _PCATCH(gCVfrDataStorage.GetVarStoreId(StoreName, &VarStoreId, &Guid), SN); + VSObj.SetVarStoreId (VarStoreId); + _PCATCH(gCVfrVarDataTypeDB.GetDataTypeSize(TypeName, &Size), LineNum); + VSObj.SetSize ((UINT16) Size); + VSObj.SetName (SN->getText()); + >> + ";" + ; + +vfrStatementVarStoreEfi : + << + BOOLEAN IsUEFI23EfiVarstore = TRUE; + EFI_GUID Guid; + CIfrVarStoreEfi VSEObj; + EFI_VARSTORE_ID VarStoreId = EFI_VARSTORE_ID_INVALID; + UINT32 Attr = 0; + UINT32 Size; + CHAR8 *TypeName; + UINT32 LineNum; + CHAR8 *StoreName = NULL; + BOOLEAN CustomizedName = FALSE; + BOOLEAN IsBitVarStore = FALSE; + >> + E:Efivarstore << VSEObj.SetLineNo(E->getLine()); >> + ( + TN:StringIdentifier "," << TypeName = TN->getText(); LineNum = TN->getLine(); CustomizedName = TRUE; IsBitVarStore = gCVfrVarDataTypeDB.DataTypeHasBitField (TN->getText());>> + | U8:"UINT8" "," << TypeName = U8->getText(); LineNum = U8->getLine(); >> + | U16:"UINT16" "," << TypeName = U16->getText(); LineNum = U16->getLine(); >> + | C16:"CHAR16" "," << TypeName = (CHAR8 *) "UINT16"; LineNum = C16->getLine(); >> + | U32:"UINT32" "," << TypeName = U32->getText(); LineNum = U32->getLine(); >> + | U64:"UINT64" "," << TypeName = U64->getText(); LineNum = U64->getLine(); >> + | D:"EFI_HII_DATE" "," << TypeName = D->getText(); LineNum = D->getLine(); >> + | T:"EFI_HII_TIME" "," << TypeName = T->getText(); LineNum = T->getLine(); >> + | R:"EFI_HII_REF" "," << TypeName = R->getText(); LineNum = R->getLine(); >> + ) + { + VarId "=" ID:Number "," << + _PCATCH( + (INTN)(VarStoreId = _STOU16(ID->getText(), ID->getLine())) != 0, + (INTN)TRUE, + ID, + "varid 0 is not allowed." + ); + >> + } + Attribute "=" vfrVarStoreEfiAttr[Attr] ( "\|" vfrVarStoreEfiAttr[Attr] )* "," + << VSEObj.SetAttributes (Attr); >> + + ( + Name "=" SN:StringIdentifier "," << StoreName = SN->getText(); >> + | + Name "=" "STRING_TOKEN" "\(" VN:Number "\)" "," + VarSize "=" N:Number "," << + IsUEFI23EfiVarstore = FALSE; + StoreName = gCVfrStringDB.GetVarStoreNameFormStringId(_STOSID(VN->getText(), VN->getLine())); + if (StoreName == NULL) { + _PCATCH (VFR_RETURN_UNSUPPORTED, VN->getLine(), "Can't get varstore name for this StringId!"); + } + if (!CustomizedName) { + _PCATCH (VFR_RETURN_UNSUPPORTED, E->getLine(), "Old style efivarstore must have String Identifier!"); + return; + } + Size = _STOU32(N->getText(), N->getLine()); + switch (Size) { + case 1: + TypeName = (CHAR8 *) "UINT8"; + break; + case 2: + TypeName = (CHAR8 *) "UINT16"; + break; + case 4: + TypeName = (CHAR8 *) "UINT32"; + break; + case 8: + TypeName = (CHAR8 *) "UINT64"; + break; + default: + _PCATCH (VFR_RETURN_UNSUPPORTED, N); + break; + } + >> + ) + + Uuid "=" guidDefinition[Guid] << + if (IsUEFI23EfiVarstore) { + _PCATCH(gCVfrDataStorage.DeclareBufferVarStore ( + StoreName, + &Guid, + &gCVfrVarDataTypeDB, + TypeName, + VarStoreId, + IsBitVarStore + ), LineNum); + _PCATCH(gCVfrDataStorage.GetVarStoreId(StoreName, &VarStoreId, &Guid), SN); + _PCATCH(gCVfrVarDataTypeDB.GetDataTypeSize(TypeName, &Size), LineNum); + } else { + _PCATCH(gCVfrDataStorage.DeclareBufferVarStore ( + TN->getText(), + &Guid, + &gCVfrVarDataTypeDB, + TypeName, + VarStoreId, + FALSE + ), LineNum); + _PCATCH(gCVfrDataStorage.GetVarStoreId(TN->getText(), &VarStoreId, &Guid), VN); + _PCATCH(gCVfrVarDataTypeDB.GetDataTypeSize(TypeName, &Size), N->getLine()); + } + VSEObj.SetGuid (&Guid); + VSEObj.SetVarStoreId (VarStoreId); + + VSEObj.SetSize ((UINT16) Size); + VSEObj.SetName (StoreName); + if (IsUEFI23EfiVarstore == FALSE && StoreName != NULL) { + delete[] StoreName; + } + >> + ";" + ; + +vfrVarStoreEfiAttr [UINT32 & Attr] : + N:Number << $Attr |= _STOU32(N->getText(), N->getLine()); >> + ; + +vfrStatementVarStoreNameValue : + << + EFI_GUID Guid; + CIfrVarStoreNameValue VSNVObj; + EFI_VARSTORE_ID VarStoreId = EFI_VARSTORE_ID_INVALID; + BOOLEAN Created = FALSE; + >> + L:NameValueVarStore << VSNVObj.SetLineNo(L->getLine()); >> + SN:StringIdentifier "," + { + VarId "=" ID:Number "," << + _PCATCH( + (INTN)(VarStoreId = _STOU16(ID->getText(), ID->getLine())) != 0, + (INTN)TRUE, + ID, + "varid 0 is not allowed." + ); + >> + } + ( + Name "=" "STRING_TOKEN" "\(" N:Number "\)" "," << + if (!Created) { + _PCATCH(gCVfrDataStorage.DeclareNameVarStoreBegin (SN->getText(), VarStoreId), SN); + Created = TRUE; + } + _PCATCH(gCVfrDataStorage.NameTableAddItem (_STOSID(N->getText(), N->getLine())), SN); + >> + )+ + Uuid "=" guidDefinition[Guid] << _PCATCH(gCVfrDataStorage.DeclareNameVarStoreEnd (&Guid), SN); >> + << + VSNVObj.SetGuid (&Guid); + _PCATCH(gCVfrDataStorage.GetVarStoreId(SN->getText(), &VarStoreId, &Guid), SN); + VSNVObj.SetVarStoreId (VarStoreId); + >> + ";" + ; + +// +// keep classDefinition and validClassNames for compatibility but not generate +// any IFR object +// +classDefinition[UINT16 & Class] : + << $Class = 0; >> + validClassNames[$Class] ( "\|" validClassNames[$Class] )* + ; + +validClassNames[UINT16 & Class] : + ClassNonDevice << $Class |= EFI_NON_DEVICE_CLASS; >> + | ClassDiskDevice << $Class |= EFI_DISK_DEVICE_CLASS; >> + | ClassVideoDevice << $Class |= EFI_VIDEO_DEVICE_CLASS; >> + | ClassNetworkDevice << $Class |= EFI_NETWORK_DEVICE_CLASS; >> + | ClassInputDevice << $Class |= EFI_INPUT_DEVICE_CLASS; >> + | ClassOnBoardDevice << $Class |= EFI_ON_BOARD_DEVICE_CLASS; >> + | ClassOtherDevice << $Class |= EFI_OTHER_DEVICE_CLASS; >> + | N:Number << $Class |= _STOU16(N->getText(), N->getLine()); >> + ; + +subclassDefinition[UINT16 & SubClass] : + << $SubClass = 0; >> + SubclassSetupApplication << $SubClass |= EFI_SETUP_APPLICATION_SUBCLASS; >> + | SubclassGeneralApplication << $SubClass |= EFI_GENERAL_APPLICATION_SUBCLASS; >> + | SubclassFrontPage << $SubClass |= EFI_FRONT_PAGE_SUBCLASS; >> + | SubclassSingleUse << $SubClass |= EFI_SINGLE_USE_SUBCLASS; >> + | N:Number << $SubClass |= _STOU16(N->getText(), N->getLine()); >> + ; + +vfrStatementDisableIfFormSet : + << + CIfrDisableIf DIObj; + mConstantOnlyInExpression = TRUE; + >> + D:DisableIf << DIObj.SetLineNo(D->getLine()); >> + vfrStatementExpression[0] ";" << mConstantOnlyInExpression = FALSE; >> + vfrFormSetList + E:EndIf << CRT_END_OP (E); >> + ";" + ; + +vfrStatementSuppressIfFormSet : + << CIfrSuppressIf SIObj;>> + L:SuppressIf << + SIObj.SetLineNo(L->getLine()); + >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] ";" + vfrFormSetList + E: EndIf + ";" << CRT_END_OP (E); >> + ; + +//***************************************************************************** +// +// the syntax of question header and statement header +// +vfrStatementHeader[CIfrStatementHeader *SHObj] : + Prompt "=" "STRING_TOKEN" "\(" S1:Number "\)" "," << $SHObj->SetPrompt (_STOSID(S1->getText(), S1->getLine())); >> + Help "=" "STRING_TOKEN" "\(" S2:Number "\)" << $SHObj->SetHelp (_STOSID(S2->getText(), S2->getLine())); >> + ; + +vfrQuestionBaseInfo[EFI_VARSTORE_INFO & Info, EFI_QUESTION_ID & QId, EFI_QUESION_TYPE QType = QUESTION_NORMAL]: + << + CHAR8 *QName = NULL; + CHAR8 *VarIdStr = NULL; + mUsedDefaultCount = 0; + >> + { + Name "=" QN:StringIdentifier "," << + QName = QN->getText(); + _PCATCH(mCVfrQuestionDB.FindQuestion (QName), VFR_RETURN_UNDEFINED, QN, "has already been used please used anther name"); + >> + } + { V:VarId "=" vfrStorageVarId[Info, VarIdStr] "," } + { + QuestionId "=" ID:Number "," << + QId = _STOQID(ID->getText(), ID->getLine()); + _PCATCH(mCVfrQuestionDB.FindQuestion (QId), VFR_RETURN_UNDEFINED, ID, "has already been used please assign another number"); + >> + } + << + switch (QType) { + case QUESTION_NORMAL: + mCVfrQuestionDB.RegisterQuestion (QName, VarIdStr, QId); + break; + case QUESTION_DATE: + mCVfrQuestionDB.RegisterNewDateQuestion (QName, VarIdStr, QId); + break; + case QUESTION_TIME: + mCVfrQuestionDB.RegisterNewTimeQuestion (QName, VarIdStr, QId); + break; + case QUESTION_REF: + // + // VarIdStr != NULL stand for question with storagae. + // + if (VarIdStr != NULL) { + mCVfrQuestionDB.RegisterRefQuestion (QName, VarIdStr, QId); + } else { + mCVfrQuestionDB.RegisterQuestion (QName, NULL, QId); + } + break; + default: + _PCATCH(VFR_RETURN_FATAL_ERROR); + } + >> + << + if (VarIdStr != NULL) { + delete[] VarIdStr; + } + _SAVE_CURRQEST_VARINFO (Info); + >> + ; + +vfrQuestionHeader[CIfrQuestionHeader & QHObj, EFI_QUESION_TYPE QType = QUESTION_NORMAL]: + << + EFI_VARSTORE_INFO Info; + Info.mVarType = EFI_IFR_TYPE_OTHER; + Info.mVarTotalSize = 0; + Info.mInfo.mVarOffset = EFI_VAROFFSET_INVALID; + Info.mVarStoreId = EFI_VARSTORE_ID_INVALID; + Info.mIsBitVar = FALSE; + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + >> + vfrQuestionBaseInfo[Info, QId, QType] + << $QHObj.SetQuestionId (QId); + if (Info.mVarStoreId != EFI_VARSTORE_ID_INVALID) { + $QHObj.SetVarStoreInfo (&Info); + } + >> + vfrStatementHeader[&$QHObj] + ; + +questionheaderFlagsField[UINT8 & Flags] : + ReadOnlyFlag << $Flags |= 0x01; >> + | InteractiveFlag << $Flags |= 0x04; >> + | ResetRequiredFlag << $Flags |= 0x10; >> + | RestStyleFlag << $Flags |= 0x20; >> + | ReconnectRequiredFlag << $Flags |= 0x40; >> + | O:OptionOnlyFlag << + gCVfrErrorHandle.HandleWarning ( + VFR_WARNING_OBSOLETED_FRAMEWORK_OPCODE, + O->getLine(), + O->getText() + ); + >> + | N:NVAccessFlag << + gCVfrErrorHandle.HandleWarning ( + VFR_WARNING_OBSOLETED_FRAMEWORK_OPCODE, + N->getLine(), + N->getText() + ); + >> + | L:LateCheckFlag << + gCVfrErrorHandle.HandleWarning ( + VFR_WARNING_OBSOLETED_FRAMEWORK_OPCODE, + L->getLine(), + L->getText() + ); + >> + ; + +vfrStorageVarId[EFI_VARSTORE_INFO & Info, CHAR8 *&QuestVarIdStr, BOOLEAN CheckFlag = TRUE] : + << + UINT32 Idx; + UINT32 LineNo; + EFI_VFR_VARSTORE_TYPE VarStoreType = EFI_VFR_VARSTORE_INVALID; + CHAR8 *VarIdStr = NULL; + CHAR8 *VarStr = NULL; + CHAR8 *SName = NULL; + CHAR8 *TName = NULL; + EFI_VFR_RETURN_CODE VfrReturnCode = VFR_RETURN_SUCCESS; + EFI_IFR_TYPE_VALUE Dummy = gZeroEfiIfrTypeValue; + EFI_GUID *VarGuid = NULL; + >> + ( + SN1:StringIdentifier << SName = SN1->getText(); _STRCAT(&VarIdStr, SN1->getText()); >> + OpenBracket I1:Number CloseBracket << + Idx = _STOU32(I1->getText(), I1->getLine()); + _STRCAT(&VarIdStr, "["); + _STRCAT(&VarIdStr, I1->getText()); + _STRCAT(&VarIdStr, "]"); + >> + << + VfrReturnCode = gCVfrDataStorage.GetVarStoreId(SName, &$Info.mVarStoreId); + if (CheckFlag || VfrReturnCode == VFR_RETURN_SUCCESS) { + _PCATCH(VfrReturnCode, SN1); + _PCATCH(gCVfrDataStorage.GetNameVarStoreInfo (&$Info, Idx), SN1); + } + + QuestVarIdStr = VarIdStr; + >> + ) + | + ( + SN2:StringIdentifier << SName = SN2->getText(); _STRCAT(&VarIdStr, SName); >> + << + VfrReturnCode = gCVfrDataStorage.GetVarStoreId(SName, &$Info.mVarStoreId); + if (CheckFlag || VfrReturnCode == VFR_RETURN_SUCCESS) { + _PCATCH(VfrReturnCode, SN2); + VarStoreType = gCVfrDataStorage.GetVarStoreType ($Info.mVarStoreId); + if (VarStoreType == EFI_VFR_VARSTORE_BUFFER || VarStoreType == EFI_VFR_VARSTORE_BUFFER_BITS) { + _PCATCH(gCVfrDataStorage.GetBufferVarStoreDataTypeName(Info.mVarStoreId, &TName), SN2); + _STRCAT(&VarStr, TName); + } + } + >> + + ( + "." << + if (CheckFlag || VfrReturnCode == VFR_RETURN_SUCCESS) { + _PCATCH((((VarStoreType != EFI_VFR_VARSTORE_BUFFER) && (VarStoreType != EFI_VFR_VARSTORE_BUFFER_BITS))? VFR_RETURN_EFIVARSTORE_USE_ERROR : VFR_RETURN_SUCCESS), SN2); + } + _STRCAT(&VarIdStr, "."); _STRCAT(&VarStr, "."); + >> + SF:StringIdentifier << _STRCAT(&VarIdStr, SF->getText()); _STRCAT(&VarStr, SF->getText()); >> + { + OpenBracket I2:Number CloseBracket << + Idx = _STOU32(I2->getText(), I2->getLine()); + if (Idx > 0) { + // + // Idx == 0, [0] can be ignored. + // Array[0] is same to Array for unify the varid name to cover [0] + // + _STRCAT(&VarIdStr, "["); + _STRCAT(&VarIdStr, I2->getText()); + _STRCAT(&VarIdStr, "]"); + } + _STRCAT(&VarStr, "["); + _STRCAT(&VarStr, I2->getText()); + _STRCAT(&VarStr, "]"); + >> + } + )* << + switch (VarStoreType) { + case EFI_VFR_VARSTORE_EFI: + _PCATCH(gCVfrDataStorage.GetEfiVarStoreInfo (&$Info), SN2); + break; + case EFI_VFR_VARSTORE_BUFFER: + case EFI_VFR_VARSTORE_BUFFER_BITS: + _PCATCH(gCVfrVarDataTypeDB.GetDataFieldInfo (VarStr, $Info.mInfo.mVarOffset, $Info.mVarType, $Info.mVarTotalSize, $Info.mIsBitVar), SN2->getLine(), VarStr); + VarGuid = gCVfrDataStorage.GetVarStoreGuid($Info.mVarStoreId); + _PCATCH((EFI_VFR_RETURN_CODE)gCVfrBufferConfig.Register ( + SName, + VarGuid, + NULL), + SN2->getLine()); + _PCATCH((EFI_VFR_RETURN_CODE)gCVfrBufferConfig.Write ( + 'a', + SName, + VarGuid, + NULL, + $Info.mVarType, + $Info.mInfo.mVarOffset, + $Info.mVarTotalSize, + Dummy), + SN2->getLine()); + _PCATCH(gCVfrDataStorage.AddBufferVarStoreFieldInfo(&$Info ),SN2->getLine()); + break; + case EFI_VFR_VARSTORE_NAME: + default: break; + } + + QuestVarIdStr = VarIdStr; + if (VarStr != NULL) {delete[] VarStr;} + >> + ) + ; + +vfrQuestionDataFieldName [EFI_QUESTION_ID &QId, UINT32 &Mask, CHAR8 *&VarIdStr, UINT32 &LineNo] : + << + UINT32 Idx; + VarIdStr = NULL; LineNo = 0; + >> + ( + SN1:StringIdentifier << _STRCAT(&VarIdStr, SN1->getText()); LineNo = SN1->getLine(); >> + OpenBracket I1:Number CloseBracket << + _STRCAT(&VarIdStr, "["); + _STRCAT(&VarIdStr, I1->getText()); + _STRCAT(&VarIdStr, "]"); + mCVfrQuestionDB.GetQuestionId (NULL, VarIdStr, $QId, $Mask); + if (mConstantOnlyInExpression) { + _PCATCH(VFR_RETURN_CONSTANT_ONLY, LineNo); + } + >> + ) + | + ( + SN2:StringIdentifier << _STRCAT (&VarIdStr, SN2->getText()); LineNo = SN2->getLine(); >> + ( + "." << + _STRCAT (&VarIdStr, "."); + if (mConstantOnlyInExpression) { + _PCATCH(VFR_RETURN_CONSTANT_ONLY, LineNo); + } + >> + SF:StringIdentifier << _STRCAT (&VarIdStr, SF->getText()); >> + { + OpenBracket I2:Number CloseBracket << + Idx = _STOU32(I2->getText(), I2->getLine()); + if (Idx > 0) { + // + // Idx == 0, [0] can be ignored. + // Array[0] is same to Array + // + _STRCAT(&VarIdStr, "["); + _STRCAT(&VarIdStr, I2->getText()); + _STRCAT(&VarIdStr, "]"); + } + >> + } + )* + << mCVfrQuestionDB.GetQuestionId (NULL, VarIdStr, $QId, $Mask); >> + ) + ; + +vfrConstantValueField[UINT8 Type, EFI_IFR_TYPE_VALUE &Value, BOOLEAN &ListType] : + << + EFI_GUID Guid; + BOOLEAN Negative = FALSE; + BOOLEAN IntDecStyle = FALSE; + CIfrNumeric *NumericQst = NULL; + if (gCurrentMinMaxData != NULL && gCurrentMinMaxData->IsNumericOpcode()) { + NumericQst = (CIfrNumeric *) gCurrentQuestion; + IntDecStyle = (NumericQst->GetNumericFlags() & EFI_IFR_DISPLAY) == 0 ? TRUE : FALSE; + } + UINT8 *Type8 = (UINT8 *) &Value; + UINT16 *Type16 = (UINT16 *) &Value; + UINT32 *Type32 = (UINT32 *) &Value; + UINT64 *Type64 = (UINT64 *) &Value; + UINT16 Index = 0; + ListType = FALSE; + >> + { + "\-" << Negative = TRUE; >> + } + N1:Number << + // + // The value stored in bit fields is always set to UINT32 type. + // + if (_GET_CURRQEST_VARTINFO().mIsBitVar) { + $Value.u32 = _STOU32(N1->getText(), N1->getLine()); + } else { + switch ($Type) { + case EFI_IFR_TYPE_NUM_SIZE_8 : + $Value.u8 = _STOU8(N1->getText(), N1->getLine()); + if (IntDecStyle) { + if (Negative) { + if ($Value.u8 > 0x80) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, N1->getLine(), "INT8 type can't big than 0x7F, small than -0x80"); + } + } else { + if ($Value.u8 > 0x7F) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, N1->getLine(), "INT8 type can't big than 0x7F, small than -0x80"); + } + } + } + if (Negative) { + $Value.u8 = ~$Value.u8 + 1; + } + break; + case EFI_IFR_TYPE_NUM_SIZE_16 : + $Value.u16 = _STOU16(N1->getText(), N1->getLine()); + if (IntDecStyle) { + if (Negative) { + if ($Value.u16 > 0x8000) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, N1->getLine(), "INT16 type can't big than 0x7FFF, small than -0x8000"); + } + } else { + if ($Value.u16 > 0x7FFF) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, N1->getLine(), "INT16 type can't big than 0x7FFF, small than -0x8000"); + } + } + } + if (Negative) { + $Value.u16 = ~$Value.u16 + 1; + } + break; + case EFI_IFR_TYPE_NUM_SIZE_32 : + $Value.u32 = _STOU32(N1->getText(), N1->getLine()); + if (IntDecStyle) { + if (Negative) { + if ($Value.u32 > 0x80000000) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, N1->getLine(), "INT32 type can't big than 0x7FFFFFFF, small than -0x80000000"); + } + } else { + if ($Value.u32 > 0X7FFFFFFF) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, N1->getLine(), "INT32 type can't big than 0x7FFFFFFF, small than -0x80000000"); + } + } + } + if (Negative) { + $Value.u32 = ~$Value.u32 + 1; + } + break; + case EFI_IFR_TYPE_NUM_SIZE_64 : + $Value.u64 = _STOU64(N1->getText(), N1->getLine()); + if (IntDecStyle) { + if (Negative) { + if ($Value.u64 > 0x8000000000000000) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, N1->getLine(), "INT64 type can't big than 0x7FFFFFFFFFFFFFFF, small than -0x8000000000000000"); + } + } else { + if ($Value.u64 > 0x7FFFFFFFFFFFFFFF) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, N1->getLine(), "INT64 type can't big than 0x7FFFFFFFFFFFFFFF, small than -0x8000000000000000"); + } + } + } + if (Negative) { + $Value.u64 = ~$Value.u64 + 1; + } + break; + case EFI_IFR_TYPE_BOOLEAN : + $Value.b = _STOU8(N1->getText(), N1->getLine()); + break; + case EFI_IFR_TYPE_STRING : + $Value.string = _STOU16(N1->getText(), N1->getLine()); + break; + case EFI_IFR_TYPE_TIME : + case EFI_IFR_TYPE_DATE : + case EFI_IFR_TYPE_REF : + default : + break; + } + } + >> + | B1:True << $Value.b = TRUE; >> + | B2:False << $Value.b = FALSE; >> + | O1:One << $Value.u8 = _STOU8(O1->getText(), O1->getLine()); >> + | O2:Ones << $Value.u64 = _STOU64(O2->getText(), O2->getLine()); >> + | Z:Zero << $Value.u8 = _STOU8(Z->getText(), Z->getLine()); >> + | HOUR:Number ":" MINUTE:Number ":" SECOND:Number << $Value.time = _STOT(HOUR->getText(), MINUTE->getText(),SECOND->getText(), HOUR->getLine()); >> + | YEAR:Number "/" MONTH:Number "/" DAY:Number << $Value.date = _STOD(YEAR->getText(), MONTH->getText(), DAY->getText(), YEAR->getLine()); >> + | QI:Number";" FI:Number";" guidDefinition[Guid] ";" "STRING_TOKEN" "\(" DP:Number "\)" + << $Value.ref = _STOR(QI->getText(), FI->getText(), &Guid, DP->getText(), QI->getLine()); >> + | "STRING_TOKEN" "\(" S1:Number "\)" << $Value.string = _STOSID(S1->getText(), S1->getLine()); >> + | "\{" << ListType = TRUE; >> + L1:Number << + switch (Type) { + case EFI_IFR_TYPE_NUM_SIZE_8 : + Type8[Index] = _STOU8(L1->getText(), L1->getLine()); + break; + case EFI_IFR_TYPE_NUM_SIZE_16 : + Type16[Index] = _STOU16(L1->getText(), L1->getLine()); + break; + case EFI_IFR_TYPE_NUM_SIZE_32 : + Type32[Index] = _STOU32(L1->getText(), L1->getLine()); + break; + case EFI_IFR_TYPE_NUM_SIZE_64 : + Type64[Index] = _STOU64(L1->getText(), L1->getLine()); + break; + default: + break; + } + Index++; + >> + ( + "," + L2:Number << + switch (Type) { + case EFI_IFR_TYPE_NUM_SIZE_8 : + Type8[Index] = _STOU8(L2->getText(), L2->getLine()); + break; + case EFI_IFR_TYPE_NUM_SIZE_16 : + Type16[Index] = _STOU16(L2->getText(), L2->getLine()); + break; + case EFI_IFR_TYPE_NUM_SIZE_32 : + Type32[Index] = _STOU32(L2->getText(), L2->getLine()); + break; + case EFI_IFR_TYPE_NUM_SIZE_64 : + Type64[Index] = _STOU64(L2->getText(), L2->getLine()); + break; + default: + break; + } + Index++; + >> + )* + "\}" + ; + +//***************************************************************************** +// +// the syntax of form definition +// +vfrFormDefinition : + << CIfrForm FObj; >> + F:Form << FObj.SetLineNo(F->getLine()); >> + FormId "=" S1:Number "," << _PCATCH(FObj.SetFormId (_STOFID(S1->getText(), S1->getLine())), S1); >> + Title "=" "STRING_TOKEN" "\(" S2:Number "\)" ";" << FObj.SetFormTitle (_STOSID(S2->getText(), S2->getLine())); >> + ( + vfrStatementImage | + vfrStatementLocked | + vfrStatementRules | + vfrStatementDefault | + vfrStatementStat | + vfrStatementQuestions | + vfrStatementConditional | + vfrStatementLabel | + vfrStatementBanner | + // Just for framework vfr compatibility + vfrStatementInvalid | + vfrStatementExtension | + vfrStatementModal | + vfrStatementRefreshEvent ";" + )* + E:EndForm << + {CIfrEnd EObj; EObj.SetLineNo (E->getLine()); mLastFormEndAddr = EObj.GetObjBinAddr(); gAdjustOpcodeOffset = EObj.GetObjBinOffset ();} + >> + ";" + ; + +vfrFormMapDefinition : + << + CIfrFormMap *FMapObj = NULL; + UINT32 FormMapMethodNumber = 0; + EFI_GUID Guid; + >> + F:FormMap << FMapObj = new CIfrFormMap(); FMapObj->SetLineNo(F->getLine()); >> + FormId "=" S1:Number "," << _PCATCH(FMapObj->SetFormId (_STOFID(S1->getText(), S1->getLine())), S1); >> + ( + MapTitle "=" "STRING_TOKEN" "\(" S2:Number "\)" ";" + MapGuid "=" guidDefinition[Guid] ";" << FMapObj->SetFormMapMethod (_STOFID(S2->getText(), S2->getLine()), &Guid); FormMapMethodNumber ++; >> + )* << if (FormMapMethodNumber == 0) {_PCATCH (VFR_RETURN_INVALID_PARAMETER, F->getLine(), "No MapMethod is set for FormMap!");} delete FMapObj;>> + ( + vfrStatementImage | + vfrStatementLocked | + vfrStatementRules | + vfrStatementDefault | + vfrStatementStat | + vfrStatementQuestions | + vfrStatementConditional | + vfrStatementLabel | + vfrStatementBanner | + vfrStatementExtension | + vfrStatementModal | + vfrStatementRefreshEvent ";" + )* + E:EndForm << CRT_END_OP (E); >> + ";" + ; + +vfrStatementRules : + << CIfrRule RObj; >> + R:Rule << RObj.SetLineNo(R->getLine()); >> + S1:StringIdentifier "," << + mCVfrRulesDB.RegisterRule (S1->getText()); + RObj.SetRuleId (mCVfrRulesDB.GetRuleId(S1->getText())); + >> + vfrStatementExpression[0] + E:EndRule << CRT_END_OP (E); >> + ";" + ; + +vfrStatementDefault : + << + BOOLEAN IsExp = FALSE; + UINT64 ValueList[EFI_IFR_MAX_LENGTH] = {0,}; + EFI_IFR_TYPE_VALUE *Val = (EFI_IFR_TYPE_VALUE *) ValueList; + CIfrDefault *DObj = NULL; + CIfrDefault2 *DObj2 = NULL; + EFI_DEFAULT_ID DefaultId = EFI_HII_DEFAULT_CLASS_STANDARD; + CHAR8 *VarStoreName = NULL; + EFI_VFR_VARSTORE_TYPE VarStoreType = EFI_VFR_VARSTORE_INVALID; + UINT32 Size = 0; + EFI_GUID *VarGuid = NULL; + BOOLEAN ArrayType = FALSE; + UINT8 *Type8 = (UINT8 *) ValueList; + UINT16 *Type16 = (UINT16 *) ValueList; + UINT32 *Type32 = (UINT32 *) ValueList; + UINT64 *Type64 = (UINT64 *) ValueList; + CIfrNumeric *NumericQst = NULL; + + >> + D:Default + ( + ( + "=" vfrConstantValueField[_GET_CURRQEST_DATATYPE(), *Val, ArrayType] "," + << + if (gCurrentMinMaxData != NULL && gCurrentMinMaxData->IsNumericOpcode()) { + //check default value is valid for Numeric Opcode + NumericQst = (CIfrNumeric *) gCurrentQuestion; + if ((NumericQst->GetNumericFlags() & EFI_IFR_DISPLAY) == 0 && !(_GET_CURRQEST_VARTINFO().mIsBitVar)) { + switch (_GET_CURRQEST_DATATYPE()) { + case EFI_IFR_TYPE_NUM_SIZE_8: + if (((INT8) Val->u8 < (INT8) gCurrentMinMaxData->GetMinData(_GET_CURRQEST_DATATYPE(), FALSE)) || + ((INT8) Val->u8 > (INT8) gCurrentMinMaxData->GetMaxData(_GET_CURRQEST_DATATYPE(), FALSE))) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, D->getLine(), "Numeric default value must be between MinValue and MaxValue."); + } + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + if (((INT16) Val->u16 < (INT16) gCurrentMinMaxData->GetMinData(_GET_CURRQEST_DATATYPE(), FALSE)) || + ((INT16) Val->u16 > (INT16) gCurrentMinMaxData->GetMaxData(_GET_CURRQEST_DATATYPE(), FALSE))) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, D->getLine(), "Numeric default value must be between MinValue and MaxValue."); + } + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + if (((INT32) Val->u32 < (INT32) gCurrentMinMaxData->GetMinData(_GET_CURRQEST_DATATYPE(), FALSE)) || + ((INT32) Val->u32 > (INT32) gCurrentMinMaxData->GetMaxData(_GET_CURRQEST_DATATYPE(), FALSE))) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, D->getLine(), "Numeric default value must be between MinValue and MaxValue."); + } + break; + case EFI_IFR_TYPE_NUM_SIZE_64: + if (((INT64) Val->u64 < (INT64) gCurrentMinMaxData->GetMinData(_GET_CURRQEST_DATATYPE(), FALSE)) || + ((INT64) Val->u64 > (INT64) gCurrentMinMaxData->GetMaxData(_GET_CURRQEST_DATATYPE(), FALSE))) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, D->getLine(), "Numeric default value must be between MinValue and MaxValue."); + } + break; + default: + break; + } + } else { + // + // Value for question stored in bit fields is always set to UINT32 type. + // + if (_GET_CURRQEST_VARTINFO().mIsBitVar) { + if (Val->u32 < gCurrentMinMaxData->GetMinData(_GET_CURRQEST_DATATYPE(), TRUE) || Val->u32 > gCurrentMinMaxData->GetMaxData(_GET_CURRQEST_DATATYPE(), TRUE)) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, D->getLine(), "Numeric default value must be between MinValue and MaxValue."); + } + } else { + if (Val->u64 < gCurrentMinMaxData->GetMinData(_GET_CURRQEST_DATATYPE(), FALSE) || Val->u64 > gCurrentMinMaxData->GetMaxData(_GET_CURRQEST_DATATYPE(), FALSE)) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, D->getLine(), "Numeric default value must be between MinValue and MaxValue."); + } + } + } + } + if (_GET_CURRQEST_DATATYPE() == EFI_IFR_TYPE_OTHER) { + _PCATCH (VFR_RETURN_FATAL_ERROR, D->getLine(), "Default data type error."); + Size = sizeof (EFI_IFR_TYPE_VALUE); + } else if (ArrayType) { + switch (_GET_CURRQEST_DATATYPE()) { + case EFI_IFR_TYPE_NUM_SIZE_8 : + while (Type8[Size] != 0) { + Size++; + } + break; + case EFI_IFR_TYPE_NUM_SIZE_16 : + while (Type16[Size] != 0) { + Size++; + } + Size *= sizeof (UINT16); + break; + + case EFI_IFR_TYPE_NUM_SIZE_32 : + while (Type32[Size] != 0) { + Size++; + } + Size *= sizeof (UINT32); + break; + + case EFI_IFR_TYPE_NUM_SIZE_64 : + while (Type64[Size] != 0) { + Size++; + } + Size *= sizeof (UINT64); + break; + + default: + break; + } + } else { + if (_GET_CURRQEST_VARTINFO().mIsBitVar) { + Size = sizeof (UINT32); + } else { + _PCATCH (gCVfrVarDataTypeDB.GetDataTypeSize (_GET_CURRQEST_DATATYPE(), &Size), D->getLine()); + } + } + Size += OFFSET_OF (EFI_IFR_DEFAULT, Value); + DObj = new CIfrDefault ((UINT8)Size); + DObj->SetLineNo(D->getLine()); + if (ArrayType) { + DObj->SetType (EFI_IFR_TYPE_BUFFER); + } else if (gIsStringOp) { + DObj->SetType (EFI_IFR_TYPE_STRING); + } else { + if (_GET_CURRQEST_VARTINFO().mIsBitVar) { + DObj->SetType (EFI_IFR_TYPE_NUM_SIZE_32); + } else { + DObj->SetType (_GET_CURRQEST_DATATYPE()); + } + } + DObj->SetValue(*Val); + >> + | << IsExp = TRUE; DObj2 = new CIfrDefault2; DObj2->SetLineNo(D->getLine()); DObj2->SetScope (1); >> + vfrStatementValue "," << CIfrEnd EndObj1; EndObj1.SetLineNo(D->getLine()); >> + ) + { + DefaultStore "=" SN:StringIdentifier "," << + _PCATCH(gCVfrDefaultStore.GetDefaultId (SN->getText(), &DefaultId), SN); + if (DObj != NULL) { + DObj->SetDefaultId (DefaultId); + } + + if (DObj2 != NULL) { + DObj2->SetDefaultId (DefaultId); + } + >> + } + << + CheckDuplicateDefaultValue (DefaultId, D); + if (_GET_CURRQEST_VARTINFO().mVarStoreId != EFI_VARSTORE_ID_INVALID) { + _PCATCH(gCVfrDataStorage.GetVarStoreName (_GET_CURRQEST_VARTINFO().mVarStoreId, &VarStoreName), D->getLine()); + VarGuid = gCVfrDataStorage.GetVarStoreGuid(_GET_CURRQEST_VARTINFO().mVarStoreId); + VarStoreType = gCVfrDataStorage.GetVarStoreType (_GET_CURRQEST_VARTINFO().mVarStoreId); + if ((IsExp == FALSE) && (VarStoreType == EFI_VFR_VARSTORE_BUFFER)) { + _PCATCH(gCVfrDefaultStore.BufferVarStoreAltConfigAdd ( + DefaultId, + _GET_CURRQEST_VARTINFO(), + VarStoreName, + VarGuid, + _GET_CURRQEST_DATATYPE (), + *Val), + D->getLine() + ); + } + } + if (DObj != NULL) {delete DObj;} + if (DObj2 != NULL) {delete DObj2;} + >> + ) + ; + +vfrStatementStat : + vfrStatementSubTitle | + vfrStatementStaticText | + vfrStatementCrossReference + ; + +vfrStatementQuestions : + vfrStatementBooleanType | + vfrStatementDate | + vfrStatementNumericType | + vfrStatementStringType | + vfrStatementOrderedList | + vfrStatementTime + ; + +vfrStatementConditional : + vfrStatementDisableIfStat | + vfrStatementSuppressIfStat | //enhance to be compatible for framework endif + vfrStatementGrayOutIfStat | + vfrStatementInconsistentIfStat //to be compatible for framework + ; + +vfrStatementConditionalNew : + vfrStatementDisableIfStat | + vfrStatementSuppressIfStatNew | + vfrStatementGrayOutIfStatNew | + vfrStatementInconsistentIfStat //to be compatible for framework + ; + +vfrStatementSuppressIfStat : + vfrStatementSuppressIfStatNew + ; + +vfrStatementGrayOutIfStat : + vfrStatementGrayOutIfStatNew + ; + +vfrStatementInvalid : + ( + vfrStatementInvalidHidden | + vfrStatementInvalidInventory | + vfrStatementInvalidSaveRestoreDefaults + ) + << _CRT_OP (TRUE); >> + ; + +flagsField : + Number + | InteractiveFlag + | ManufacturingFlag + | DefaultFlag + | ResetRequiredFlag + | ReconnectRequiredFlag + | N:NVAccessFlag << + gCVfrErrorHandle.HandleWarning ( + VFR_WARNING_OBSOLETED_FRAMEWORK_OPCODE, + N->getLine(), + N->getText() + ); + >> + | L:LateCheckFlag << + gCVfrErrorHandle.HandleWarning ( + VFR_WARNING_OBSOLETED_FRAMEWORK_OPCODE, + L->getLine(), + L->getText() + ); + >> + ; + +vfrStatementValue : + << CIfrValue VObj; >> + V:Value << VObj.SetLineNo(V->getLine()); >> + "=" vfrStatementExpression[0] << {CIfrEnd EndObj; EndObj.SetLineNo(V->getLine());} >> + ; + +vfrStatementRead : + << CIfrRead RObj; >> + R:Read << RObj.SetLineNo(R->getLine()); >> + vfrStatementExpression[0] ";" + ; + +vfrStatementWrite : + << CIfrWrite WObj; >> + W:Write << WObj.SetLineNo(W->getLine()); >> + vfrStatementExpression[0] ";" + ; + +vfrStatementSubTitle : + << CIfrSubtitle SObj; >> + L:Subtitle << SObj.SetLineNo(L->getLine()); >> + Text "=" "STRING_TOKEN" "\(" S:Number "\)" << SObj.SetPrompt (_STOSID(S->getText(), S->getLine())); >> + { + "," FLAGS "=" vfrSubtitleFlags[SObj] + } + ( + {vfrStatementStatTagList "," } + E:";" << CRT_END_OP (E); >> + | + { "," vfrStatementStatTagList} + { "," (vfrStatementStat | vfrStatementQuestions)*} + D: EndSubtitle ";" << CRT_END_OP (D); >> + ) + ; + +vfrSubtitleFlags [CIfrSubtitle & SObj] : + << UINT8 LFlags = 0; >> + subtitleFlagsField[LFlags] ( "\|" subtitleFlagsField[LFlags] )* + << _PCATCH(SObj.SetFlags (LFlags)); >> + ; + +subtitleFlagsField [UINT8 & Flags] : + N:Number << $Flags |= _STOU8(N->getText(), N->getLine()); >> + | "HORIZONTAL" << $Flags |= 0x01; >> + ; + +vfrStatementStaticText : + << + UINT8 Flags = 0; + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + EFI_STRING_ID TxtTwo = EFI_STRING_ID_INVALID; + >> + T:Text + Help "=" "STRING_TOKEN" "\(" S1:Number "\)" "," + Text "=" "STRING_TOKEN" "\(" S2:Number "\)" + { + "," Text "=" "STRING_TOKEN" "\(" S3:Number "\)" << TxtTwo = _STOSID(S3->getText(), S3->getLine()); >> + } + { + "," F:FLAGS "=" staticTextFlagsField[Flags] ( "\|" staticTextFlagsField[Flags] )* + "," Key "=" KN:Number + } + << + if (Flags & EFI_IFR_FLAG_CALLBACK) { + if (TxtTwo != EFI_STRING_ID_INVALID) { + gCVfrErrorHandle.HandleWarning ( + VFR_WARNING_ACTION_WITH_TEXT_TWO, + S3->getLine(), + S3->getText() + ); + } + CIfrAction AObj; + mCVfrQuestionDB.RegisterQuestion (NULL, NULL, QId); + AObj.SetLineNo (F->getLine()); + AObj.SetQuestionId (QId); + AObj.SetPrompt (_STOSID(S2->getText(), S2->getLine())); + AObj.SetHelp (_STOSID(S1->getText(), S1->getLine())); + _PCATCH(AObj.SetFlags (Flags), F->getLine()); + AssignQuestionKey (AObj, KN); + CRT_END_OP (KN); + } else { + CIfrText TObj; + TObj.SetLineNo (T->getLine()); + TObj.SetHelp (_STOSID(S1->getText(), S1->getLine())); + TObj.SetPrompt (_STOSID(S2->getText(), S2->getLine())); + TObj.SetTextTwo (TxtTwo); + } + >> + { "," vfrStatementStatTagList } + ";" + ; + +staticTextFlagsField[UINT8 & HFlags] : + N:Number << _PCATCH(_STOU8(N->getText(), N->getLine()) == 0 ? VFR_RETURN_SUCCESS : VFR_RETURN_UNSUPPORTED, N->getLine()); >> + | questionheaderFlagsField[HFlags] + ; + +vfrStatementCrossReference : + vfrStatementGoto | + vfrStatementResetButton + ; + +vfrStatementGoto : + << + UINT8 RefType = 5; + EFI_STRING_ID DevPath = EFI_STRING_ID_INVALID; + EFI_GUID FSId = {0,}; + EFI_FORM_ID FId; + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + UINT32 BitMask; + CIfrQuestionHeader *QHObj = NULL; + CIfrOpHeader *OHObj = NULL; + CIfrRef *R1Obj = NULL; + CIfrRef2 *R2Obj = NULL; + CIfrRef3 *R3Obj = NULL; + CIfrRef4 *R4Obj = NULL; + CIfrRef5 *R5Obj = NULL; + >> + G:Goto + { + ( + DevicePath "=" "STRING_TOKEN" "\(" P:Number "\)" "," + FormSetGuid "=" guidDefinition[FSId] "," + FormId "=" F1:Number "," + Question "=" QN1:Number "," + << + RefType = 4; + DevPath = _STOSID(P->getText(), P->getLine()); + FId = _STOFID(F1->getText(), F1->getLine()); + QId = _STOQID(QN1->getText(), QN1->getLine()); + >> + ) + | + ( + FormSetGuid "=" guidDefinition[FSId] "," + FormId "=" F2:Number "," + Question "=" QN2:Number "," + << + RefType = 3; + FId = _STOFID(F2->getText(), F2->getLine()); + QId = _STOQID(QN2->getText(), QN2->getLine()); + >> + ) + | + ( + FormId "=" F3:Number "," << RefType = 2; FId = _STOFID(F3->getText(), F3->getLine()); >> + Question "=" + ( + QN3:StringIdentifier "," << + mCVfrQuestionDB.GetQuestionId (QN3->getText (), NULL, QId, BitMask); + if (QId == EFI_QUESTION_ID_INVALID) { + _PCATCH(VFR_RETURN_UNDEFINED, QN3); + } + >> + | QN4:Number "," << QId = _STOQID(QN4->getText(), QN4->getLine()); >> + ) + ) + | + ( + F4:Number "," << + RefType = 1; + FId = _STOFID(F4->getText(), F4->getLine()); + >> + ) + } + << + switch (RefType) { + case 5: + { + R5Obj = new CIfrRef5; + QHObj = R5Obj; + OHObj = R5Obj; + R5Obj->SetLineNo(G->getLine()); + break; + } + case 4: + { + R4Obj = new CIfrRef4; + QHObj = R4Obj; + OHObj = R4Obj; + R4Obj->SetLineNo(G->getLine()); + R4Obj->SetDevicePath (DevPath); + R4Obj->SetFormSetId (FSId); + R4Obj->SetFormId (FId); + R4Obj->SetQuestionId (QId); + break; + } + case 3: + { + R3Obj = new CIfrRef3; + QHObj = R3Obj; + OHObj = R3Obj; + R3Obj->SetLineNo(G->getLine()); + R3Obj->SetFormSetId (FSId); + R3Obj->SetFormId (FId); + R3Obj->SetQuestionId (QId); + break; + } + case 2: + { + R2Obj = new CIfrRef2; + QHObj = R2Obj; + OHObj = R2Obj; + R2Obj->SetLineNo(G->getLine()); + R2Obj->SetFormId (FId); + R2Obj->SetQuestionId (QId); + break; + } + case 1: + { + R1Obj = new CIfrRef; + QHObj = R1Obj; + OHObj = R1Obj; + R1Obj->SetLineNo(G->getLine()); + R1Obj->SetFormId (FId); + break; + } + default: break; + } + >> + vfrQuestionHeader[*QHObj, QUESTION_REF] << + if (_GET_CURRQEST_DATATYPE() == EFI_IFR_TYPE_OTHER) { + _GET_CURRQEST_VARTINFO().mVarType = EFI_IFR_TYPE_REF; + } + >> + { "," F:FLAGS "=" vfrGotoFlags[QHObj, F->getLine()] } + { + "," Key "=" KN:Number << AssignQuestionKey (*QHObj, KN); >> + } + { + E:"," + vfrStatementQuestionOptionList << OHObj->SetScope(1); CRT_END_OP (E);>> + } + ";" << if (R1Obj != NULL) {delete R1Obj;} if (R2Obj != NULL) {delete R2Obj;} if (R3Obj != NULL) {delete R3Obj;} if (R4Obj != NULL) {delete R4Obj;} if (R5Obj != NULL) {delete R5Obj;}>> + ; + +vfrGotoFlags [CIfrQuestionHeader *QHObj, UINT32 LineNum] : + << UINT8 HFlags = 0; >> + gotoFlagsField[HFlags] ( "\|" gotoFlagsField[HFlags] )* + << _PCATCH(QHObj->SetFlags (HFlags), LineNum); >> + ; + +gotoFlagsField[UINT8 & HFlags] : + N:Number << _PCATCH(_STOU8(N->getText(), N->getLine()) == 0 ? VFR_RETURN_SUCCESS : VFR_RETURN_UNSUPPORTED, N->getLine()); >> + | questionheaderFlagsField[HFlags] + ; + +getStringId : + "STRING_TOKEN" "\(" + IdVal:Number + "\)" + ; + +vfrStatementResetButton : + << + CIfrResetButton RBObj; + UINT16 DefaultId; + >> + L:ResetButton << RBObj.SetLineNo(L->getLine()); >> + DefaultStore + "=" N:StringIdentifier "," << + _PCATCH(gCVfrDefaultStore.GetDefaultId (N->getText(), &DefaultId), N->getLine()); + RBObj.SetDefaultId (DefaultId); + >> + vfrStatementHeader[&RBObj] "," + { vfrStatementStatTagList "," } + E:EndResetButton << CRT_END_OP (E); >> + ";" + ; + +vfrStatementBooleanType : + vfrStatementCheckBox | + vfrStatementAction + ; + +//***************************************************** +// Syntax of checkbox +// +// Example: +// checkbox +// varid = MySTestData.mField1, +// prompt = STRING_TOKEN(STR_CHECK_BOX_PROMPT), +// help = STRING_TOKEN(STR_CHECK_BOX_HELP), +// flags = CHECKBOX_DEFAULT | CALLBACK, +// default value = TRUE, defaultstore = MyDefaultStore, +// endcheckbox; +// +vfrStatementCheckBox : + << + CIfrCheckBox *CBObj = NULL; + EFI_IFR_TYPE_VALUE Val = gZeroEfiIfrTypeValue; + CHAR8 *VarStoreName = NULL; + UINT32 DataTypeSize; + EFI_GUID *VarStoreGuid = NULL; + CIfrGuid *GuidObj = NULL; + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID;; + EFI_VARSTORE_INFO Info; + Info.mVarType = EFI_IFR_TYPE_OTHER; + Info.mVarTotalSize = 0; + Info.mInfo.mVarOffset = EFI_VAROFFSET_INVALID; + Info.mVarStoreId = EFI_VARSTORE_ID_INVALID; + Info.mIsBitVar = FALSE; + >> + L:CheckBox + vfrQuestionBaseInfo[Info, QId] << + // + // Create a GUID opcode to wrap the checkbox opcode, if it refer to bit varstore. + // + if (_GET_CURRQEST_VARTINFO().mIsBitVar) { + GuidObj = new CIfrGuid(0); + GuidObj->SetGuid (&gEdkiiIfrBitVarGuid); + GuidObj->SetLineNo(L->getLine()); + } + CBObj = new CIfrCheckBox; + CBObj->SetLineNo(L->getLine()); + CBObj->SetQuestionId (QId); + CBObj->SetVarStoreInfo (&Info); + >> + vfrStatementHeader[CBObj]"," << //check data type + if (_GET_CURRQEST_DATATYPE() == EFI_IFR_TYPE_OTHER) { + _GET_CURRQEST_VARTINFO().mVarType = EFI_IFR_TYPE_BOOLEAN; + } + if (_GET_CURRQEST_VARTINFO().mVarStoreId != EFI_VARSTORE_ID_INVALID) { + // + // Check whether the question refers to a bit field, if yes. create a Guid to indicate the question refers to a bit field. + // + if (_GET_CURRQEST_VARTINFO ().mIsBitVar) { + _PCATCH (gCVfrVarDataTypeDB.GetDataTypeSize (_GET_CURRQEST_DATATYPE(), &DataTypeSize), L->getLine(), "CheckBox varid is not the valid data type"); + if ((gCVfrDataStorage.GetVarStoreType (_GET_CURRQEST_VARTINFO().mVarStoreId) == EFI_VFR_VARSTORE_BUFFER_BITS) && + (_GET_CURRQEST_VARSIZE() != 1)) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, L->getLine(), "CheckBox varid only occupy 1 bit in Bit Varstore"); + } + } else { + _PCATCH (gCVfrVarDataTypeDB.GetDataTypeSize (_GET_CURRQEST_DATATYPE(), &DataTypeSize), L->getLine(), "CheckBox varid is not the valid data type"); + if (DataTypeSize != 0 && DataTypeSize != _GET_CURRQEST_VARSIZE()) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, L->getLine(), "CheckBox varid doesn't support array"); + } else if ((gCVfrDataStorage.GetVarStoreType (_GET_CURRQEST_VARTINFO().mVarStoreId) == EFI_VFR_VARSTORE_BUFFER) && + (_GET_CURRQEST_VARSIZE() != sizeof (BOOLEAN))) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, L->getLine(), "CheckBox varid only support BOOLEAN data type"); + } + } + } + >> + { + F:FLAGS "=" vfrCheckBoxFlags[*CBObj, F->getLine()] "," + << + if (_GET_CURRQEST_VARTINFO().mVarStoreId != EFI_VARSTORE_ID_INVALID) { + _PCATCH(gCVfrDataStorage.GetVarStoreName (_GET_CURRQEST_VARTINFO().mVarStoreId, &VarStoreName), VFR_RETURN_SUCCESS, L, "Failed to retrieve varstore name"); + VarStoreGuid = gCVfrDataStorage.GetVarStoreGuid(_GET_CURRQEST_VARTINFO().mVarStoreId); + Val.b = TRUE; + if (CBObj->GetFlags () & 0x01) { + CheckDuplicateDefaultValue (EFI_HII_DEFAULT_CLASS_STANDARD, F); + _PCATCH( + gCVfrDefaultStore.BufferVarStoreAltConfigAdd ( + EFI_HII_DEFAULT_CLASS_STANDARD, + _GET_CURRQEST_VARTINFO(), + VarStoreName, + VarStoreGuid, + _GET_CURRQEST_DATATYPE (), + Val + ), + VFR_RETURN_SUCCESS, + L, + "No standard default storage found" + ); + } + if (CBObj->GetFlags () & 0x02) { + CheckDuplicateDefaultValue (EFI_HII_DEFAULT_CLASS_MANUFACTURING, F); + _PCATCH( + gCVfrDefaultStore.BufferVarStoreAltConfigAdd ( + EFI_HII_DEFAULT_CLASS_MANUFACTURING, + _GET_CURRQEST_VARTINFO(), + VarStoreName, + VarStoreGuid, + _GET_CURRQEST_DATATYPE (), + Val + ), + VFR_RETURN_SUCCESS, + L, + "No manufacturing default storage found" + ); + } + } + >> + } + { + Key "=" KN:Number "," << AssignQuestionKey (*CBObj, KN); >> + } + vfrStatementQuestionOptionList + E:EndCheckBox << CRT_END_OP (E); + if (GuidObj != NULL) { + GuidObj->SetScope(1); + CRT_END_OP (E); + delete GuidObj; + } + if (CBObj != NULL) delete CBObj; + >> + ";" + ; + +vfrCheckBoxFlags [CIfrCheckBox & CBObj, UINT32 LineNum] : + << + UINT8 LFlags = 0; + UINT8 HFlags = 0; + >> + checkboxFlagsField[LFlags, HFlags] ( "\|" checkboxFlagsField[LFlags, HFlags] )* + << _PCATCH(CBObj.SetFlags (HFlags, LFlags), LineNum); >> + ; + +checkboxFlagsField[UINT8 & LFlags, UINT8 & HFlags] : + N:Number << + _PCATCH(_STOU8(N->getText(), N->getLine()) == 0 ? VFR_RETURN_SUCCESS : VFR_RETURN_UNSUPPORTED, N->getLine()); + >> + | D:"DEFAULT" << + _PCATCH (VFR_RETURN_UNSUPPORTED, D); + >> + | M:"MANUFACTURING" << + _PCATCH (VFR_RETURN_UNSUPPORTED, M); + >> + | "CHECKBOX_DEFAULT" << $LFlags |= 0x01; >> + | "CHECKBOX_DEFAULT_MFG" << $LFlags |= 0x02; >> + | questionheaderFlagsField[HFlags] + ; + +//***************************************************** +// Syntax of action +// +// Example: +// action +// prompt = STRING_TOKEN(STR_ACTION_PROMPT), +// help = STRING_TOKEN(STR_ACTION_HELP), +// flags = CALLBACK, +// config = STRING_TOKEN(STR_ACTION_CONFIG), +// endaction; +// +vfrStatementAction : + << CIfrAction AObj; >> + L:Action << AObj.SetLineNo(L->getLine()); >> + vfrQuestionHeader[AObj] "," + { F:FLAGS "=" vfrActionFlags[AObj, F->getLine()] "," } + Config "=" "STRING_TOKEN" "\(" S:Number "\)" "," << AObj.SetQuestionConfig (_STOSID(S->getText(), S->getLine())); >> + vfrStatementQuestionTagList + E:EndAction << CRT_END_OP (E); >> + ";" + ; + +vfrActionFlags[CIfrAction & AObj, UINT32 LineNum] : + << UINT8 HFlags = 0; >> + actionFlagsField[HFlags] ( "\|" actionFlagsField[HFlags] )* + << _PCATCH(AObj.SetFlags (HFlags), LineNum); >> + ; + +actionFlagsField[UINT8 & HFlags] : + N:Number << _PCATCH(_STOU8(N->getText(), N->getLine()) == 0 ? VFR_RETURN_SUCCESS : VFR_RETURN_UNSUPPORTED, N->getLine()); >> + | questionheaderFlagsField[HFlags] + ; + +vfrStatementDate : + << + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + CHAR8 *VarIdStr[3] = {NULL, }; + CIfrDate DObj; + EFI_IFR_TYPE_VALUE Val = gZeroEfiIfrTypeValue; + UINT8 Size = OFFSET_OF (EFI_IFR_DEFAULT, Value) + sizeof (EFI_HII_DATE); + >> + L:Date << DObj.SetLineNo(L->getLine()); >> + ( + ( + vfrQuestionHeader[DObj, QUESTION_DATE] "," << + if (_GET_CURRQEST_DATATYPE() == EFI_IFR_TYPE_OTHER) { + _GET_CURRQEST_VARTINFO().mVarType = EFI_IFR_TYPE_DATE; + } + >> + { F:FLAGS "=" vfrDateFlags[DObj, F->getLine()] "," } + vfrStatementQuestionOptionList + ) + | + ( + Year VarId "=" D1:StringIdentifier "." D1Y:StringIdentifier "," + << _STRCAT(&VarIdStr[0], D1->getText()); _STRCAT(&VarIdStr[0], "."); _STRCAT(&VarIdStr[0], D1Y->getText()); >> + Prompt "=" "STRING_TOKEN" "\(" YP:Number "\)" "," + Help "=" "STRING_TOKEN" "\(" YH:Number "\)" "," + minMaxDateStepDefault[Val.date, 0] + + Month VarId "=" D2:StringIdentifier "." D2M:StringIdentifier "," + << _STRCAT(&VarIdStr[1], D2->getText()); _STRCAT(&VarIdStr[1], "."); _STRCAT(&VarIdStr[1], D2M->getText()); >> + Prompt "=" "STRING_TOKEN" "\(" MP:Number "\)" "," + Help "=" "STRING_TOKEN" "\(" MH:Number "\)" "," + minMaxDateStepDefault[Val.date, 1] + + Day VarId "=" D3:StringIdentifier "." D3D:StringIdentifier "," + << _STRCAT(&VarIdStr[2], D3->getText()); _STRCAT(&VarIdStr[2], "."); _STRCAT(&VarIdStr[2], D3D->getText()); >> + Prompt "=" "STRING_TOKEN" "\(" DP:Number "\)" "," + Help "=" "STRING_TOKEN" "\(" DH:Number "\)" "," + minMaxDateStepDefault[Val.date, 2] + { G:FLAGS "=" vfrDateFlags[DObj, G->getLine()] "," } + << + mCVfrQuestionDB.RegisterOldDateQuestion (VarIdStr[0], VarIdStr[1], VarIdStr[2], QId); + DObj.SetQuestionId (QId); + DObj.SetFlags (EFI_IFR_QUESTION_FLAG_DEFAULT, QF_DATE_STORAGE_TIME); + DObj.SetPrompt (_STOSID(YP->getText(), YP->getLine())); + DObj.SetHelp (_STOSID(YH->getText(), YH->getLine())); + if (VarIdStr[0] != NULL) { delete VarIdStr[0]; } if (VarIdStr[1] != NULL) { delete VarIdStr[1]; } if (VarIdStr[2] != NULL) { delete VarIdStr[2]; } + >> + << {CIfrDefault DefaultObj(Size, EFI_HII_DEFAULT_CLASS_STANDARD, EFI_IFR_TYPE_DATE, Val); DefaultObj.SetLineNo(L->getLine());} >> + ) + ( vfrStatementInconsistentIf )* + ) + E:EndDate << CRT_END_OP (E); >> + ";" + ; + +minMaxDateStepDefault[EFI_HII_DATE & D, UINT8 KeyValue] : + Minimum "=" MinN:Number "," + Maximum "=" MaxN:Number "," + { "step" "=" Number "," } + { + "default" "=" N:Number "," << + switch (KeyValue) { + case 0: + D.Year = _STOU16(N->getText(), N->getLine()); + if (D.Year < _STOU16 (MinN->getText(), MinN->getLine()) || D.Year > _STOU16 (MaxN->getText(), MaxN->getLine())) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, N->getLine(), "Year default value must be between Min year and Max year."); + } + break; + case 1: + D.Month = _STOU8(N->getText(), N->getLine()); + if (D.Month < 1 || D.Month > 12) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, N->getLine(), "Month default value must be between 1 and 12."); + } + break; + case 2: + D.Day = _STOU8(N->getText(), N->getLine()); + if (D.Day < 1 || D.Day > 31) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, N->getLine(), "Day default value must be between 1 and 31."); + } + break; + } + >> + } + ; + +vfrDateFlags [CIfrDate & DObj, UINT32 LineNum] : + << UINT8 LFlags = 0; >> + dateFlagsField[LFlags] ( "\|" dateFlagsField[LFlags] )* + << _PCATCH(DObj.SetFlags (EFI_IFR_QUESTION_FLAG_DEFAULT, LFlags), LineNum); >> + ; + +dateFlagsField [UINT8 & Flags] : + N:Number << $Flags |= _STOU8(N->getText(), N->getLine()); >> + | "YEAR_SUPPRESS" << $Flags |= 0x01; >> + | "MONTH_SUPPRESS" << $Flags |= 0x02; >> + | "DAY_SUPPRESS" << $Flags |= 0x04; >> + | "STORAGE_NORMAL" << $Flags |= 0x00; >> + | "STORAGE_TIME" << $Flags |= 0x10; >> + | "STORAGE_WAKEUP" << $Flags |= 0x20; >> + ; + +vfrStatementNumericType : + vfrStatementNumeric | + vfrStatementOneOf + ; + +vfrSetMinMaxStep[CIfrMinMaxStepData & MMSDObj] : + << + UINT64 MaxU8 = 0, MinU8 = 0, StepU8 = 0; + UINT32 MaxU4 = 0, MinU4 = 0, StepU4 = 0; + UINT16 MaxU2 = 0, MinU2 = 0, StepU2 = 0; + UINT8 MaxU1 = 0, MinU1 = 0, StepU1 = 0; + BOOLEAN IntDecStyle = FALSE; + CIfrNumeric *NObj = (CIfrNumeric *) (&MMSDObj); + if (((_GET_CURRQEST_VARTINFO().mIsBitVar) && (NObj->GetOpCode() == EFI_IFR_NUMERIC_OP) && ((NObj->GetNumericFlags() & EDKII_IFR_DISPLAY_BIT) == 0)) || + (!(_GET_CURRQEST_VARTINFO().mIsBitVar) && (NObj->GetOpCode() == EFI_IFR_NUMERIC_OP) && ((NObj->GetNumericFlags() & EFI_IFR_DISPLAY) == 0))) { + IntDecStyle = TRUE; + } + BOOLEAN MinNegative = FALSE; + BOOLEAN MaxNegative = FALSE; + >> + Minimum "=" + { + "\-" << MinNegative = TRUE; >> + } + I:Number "," << + if (!IntDecStyle && MinNegative) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, I->getLine(), "\"-\" can't be used when not in int decimal type. "); + } + // + // Value for question stored in bit fields is always set to UINT32 type. + // + if (_GET_CURRQEST_VARTINFO().mIsBitVar) { + MinU4 = _STOU32(I->getText(), I->getLine()); + if (!IntDecStyle && MinU4 > (1<< _GET_CURRQEST_VARTINFO().mVarTotalSize) -1) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, I->getLine(), "BIT type minimum can't small than 0, bigger than 2^BitWidth -1"); + } + } else { + switch (_GET_CURRQEST_DATATYPE()) { + case EFI_IFR_TYPE_NUM_SIZE_64 : + MinU8 = _STOU64(I->getText(), I->getLine()); + if (IntDecStyle) { + if (MinNegative) { + if (MinU8 > 0x8000000000000000) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, I->getLine(), "INT64 type minimum can't small than -0x8000000000000000, big than 0x7FFFFFFFFFFFFFFF"); + } + } else { + if (MinU8 > 0x7FFFFFFFFFFFFFFF) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, I->getLine(), "INT64 type minimum can't small than -0x8000000000000000, big than 0x7FFFFFFFFFFFFFFF"); + } + } + } + if (MinNegative) { + MinU8 = ~MinU8 + 1; + } + break; + case EFI_IFR_TYPE_NUM_SIZE_32 : + MinU4 = _STOU32(I->getText(), I->getLine()); + if (IntDecStyle) { + if (MinNegative) { + if (MinU4 > 0x80000000) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, I->getLine(), "INT32 type minimum can't small than -0x80000000, big than 0x7FFFFFFF"); + } + } else { + if (MinU4 > 0x7FFFFFFF) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, I->getLine(), "INT32 type minimum can't small than -0x80000000, big than 0x7FFFFFFF"); + } + } + } + if (MinNegative) { + MinU4 = ~MinU4 + 1; + } + break; + case EFI_IFR_TYPE_NUM_SIZE_16 : + MinU2 = _STOU16(I->getText(), I->getLine()); + if (IntDecStyle) { + if (MinNegative) { + if (MinU2 > 0x8000) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, I->getLine(), "INT16 type minimum can't small than -0x8000, big than 0x7FFF"); + } + } else { + if (MinU2 > 0x7FFF) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, I->getLine(), "INT16 type minimum can't small than -0x8000, big than 0x7FFF"); + } + } + } + if (MinNegative) { + MinU2 = ~MinU2 + 1; + } + break; + case EFI_IFR_TYPE_NUM_SIZE_8 : + MinU1 = _STOU8(I->getText(), I->getLine()); + if (IntDecStyle) { + if (MinNegative) { + if (MinU1 > 0x80) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, I->getLine(), "INT8 type minimum can't small than -0x80, big than 0x7F"); + } + } else { + if (MinU1 > 0x7F) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, I->getLine(), "INT8 type minimum can't small than -0x80, big than 0x7F"); + } + } + } + if (MinNegative) { + MinU1 = ~MinU1 + 1; + } + break; + } + } + >> + Maximum "=" + { + "\-" << MaxNegative = TRUE; >> + } + A:Number "," << + if (!IntDecStyle && MaxNegative) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "\"-\" can't be used when not in int decimal type. "); + } + if (_GET_CURRQEST_VARTINFO().mIsBitVar) { + MaxU4 = _STOU32(A->getText(), A->getLine()); + if (!IntDecStyle && MaxU4 > (1<< _GET_CURRQEST_VARTINFO().mVarTotalSize) -1) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "BIT type maximum can't bigger than 2^BitWidth -1"); + } + } else { + switch (_GET_CURRQEST_DATATYPE()) { + case EFI_IFR_TYPE_NUM_SIZE_64 : + MaxU8 = _STOU64(A->getText(), A->getLine()); + if (IntDecStyle) { + if (MaxNegative) { + if (MaxU8 > 0x8000000000000000) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "INT64 type maximum can't small than -0x8000000000000000, big than 0x7FFFFFFFFFFFFFFF"); + } + } else { + if (MaxU8 > 0x7FFFFFFFFFFFFFFF) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "INT64 type maximum can't small than -0x8000000000000000, big than 0x7FFFFFFFFFFFFFFF"); + } + } + } + if (MaxNegative) { + MaxU8 = ~MaxU8 + 1; + } + if (IntDecStyle) { + if ((INT64) MaxU8 < (INT64) MinU8) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "Maximum can't be less than Minimum"); + } + } else { + if (MaxU8 < MinU8) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "Maximum can't be less than Minimum"); + } + } + break; + case EFI_IFR_TYPE_NUM_SIZE_32 : + MaxU4 = _STOU32(A->getText(), A->getLine()); + if (IntDecStyle) { + if (MaxNegative) { + if (MaxU4 > 0x80000000) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "INT32 type maximum can't small than -0x80000000, big than 0x7FFFFFFF"); + } + } else { + if (MaxU4 > 0x7FFFFFFF) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "INT32 type maximum can't small than -0x80000000, big than 0x7FFFFFFF"); + } + } + } + if (MaxNegative) { + MaxU4 = ~MaxU4 + 1; + } + if (IntDecStyle) { + if ((INT32) MaxU4 < (INT32) MinU4) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "Maximum can't be less than Minimum"); + } + } else { + if (MaxU4 < MinU4) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "Maximum can't be less than Minimum"); + } + } + break; + case EFI_IFR_TYPE_NUM_SIZE_16 : + MaxU2 = _STOU16(A->getText(), A->getLine()); + if (IntDecStyle) { + if (MaxNegative) { + if (MaxU2 > 0x8000) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "INT16 type maximum can't small than -0x8000, big than 0x7FFF"); + } + } else { + if (MaxU2 > 0x7FFF) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "INT16 type maximum can't small than -0x8000, big than 0x7FFF"); + } + } + } + if (MaxNegative) { + MaxU2 = ~MaxU2 + 1; + } + if (IntDecStyle) { + if ((INT16) MaxU2 < (INT16) MinU2) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "Maximum can't be less than Minimum"); + } + } else { + if (MaxU2 < MinU2) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "Maximum can't be less than Minimum"); + } + } + break; + case EFI_IFR_TYPE_NUM_SIZE_8 : + MaxU1 = _STOU8(A->getText(), A->getLine()); + if (IntDecStyle) { + if (MaxNegative) { + if (MaxU1 > 0x80) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "INT8 type maximum can't small than -0x80, big than 0x7F"); + } + } else { + if (MaxU1 > 0x7F) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "INT8 type maximum can't small than -0x80, big than 0x7F"); + } + } + } + if (MaxNegative) { + MaxU1 = ~MaxU1 + 1; + } + if (IntDecStyle) { + if ((INT8) MaxU1 < (INT8) MinU1) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "Maximum can't be less than Minimum"); + } + } else { + if (MaxU1 < MinU1) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, A->getLine(), "Maximum can't be less than Minimum"); + } + } + break; + } + } + >> + { + STEP "=" S:Number "," + << + if (_GET_CURRQEST_VARTINFO().mIsBitVar) { + StepU4 = _STOU32(S->getText(), S->getLine()); + } else { + switch (_GET_CURRQEST_DATATYPE()) { + case EFI_IFR_TYPE_NUM_SIZE_64 : StepU8 = _STOU64(S->getText(), S->getLine()); break; + case EFI_IFR_TYPE_NUM_SIZE_32 : StepU4 = _STOU32(S->getText(), S->getLine()); break; + case EFI_IFR_TYPE_NUM_SIZE_16 : StepU2 = _STOU16(S->getText(), S->getLine()); break; + case EFI_IFR_TYPE_NUM_SIZE_8 : StepU1 = _STOU8(S->getText(), S->getLine()); break; + } + } + >> + } + << + if (_GET_CURRQEST_VARTINFO().mIsBitVar) { + $MMSDObj.SetMinMaxStepData (MinU4, MaxU4, StepU4); + } else { + switch (_GET_CURRQEST_DATATYPE()) { + case EFI_IFR_TYPE_NUM_SIZE_64 : $MMSDObj.SetMinMaxStepData (MinU8, MaxU8, StepU8); break; + case EFI_IFR_TYPE_NUM_SIZE_32 : $MMSDObj.SetMinMaxStepData (MinU4, MaxU4, StepU4); break; + case EFI_IFR_TYPE_NUM_SIZE_16 : $MMSDObj.SetMinMaxStepData (MinU2, MaxU2, StepU2); break; + case EFI_IFR_TYPE_NUM_SIZE_8 : $MMSDObj.SetMinMaxStepData (MinU1, MaxU1, StepU1); break; + } + } + >> + ; + +vfrStatementNumeric : + << + CIfrNumeric *NObj = NULL; + UINT32 DataTypeSize; + BOOLEAN IsSupported = TRUE; + UINT8 ShrinkSize = 0; + CIfrGuid *GuidObj = NULL; + UINT8 LFlags = _GET_CURRQEST_DATATYPE() & EFI_IFR_NUMERIC_SIZE; + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + EFI_VARSTORE_INFO Info; + Info.mVarType = EFI_IFR_TYPE_OTHER; + Info.mVarTotalSize = 0; + Info.mInfo.mVarOffset = EFI_VAROFFSET_INVALID; + Info.mVarStoreId = EFI_VARSTORE_ID_INVALID; + Info.mIsBitVar = FALSE; + >> + L:Numeric + vfrQuestionBaseInfo[Info, QId] << + // + // Create a GUID opcode to wrap the numeric opcode, if it refer to bit varstore. + // + if (_GET_CURRQEST_VARTINFO().mIsBitVar) { + GuidObj = new CIfrGuid(0); + GuidObj->SetGuid (&gEdkiiIfrBitVarGuid); + GuidObj->SetLineNo(L->getLine()); + } + NObj = new CIfrNumeric; + NObj->SetLineNo(L->getLine()); + NObj->SetQuestionId (QId); + NObj->SetVarStoreInfo (&Info); + >> + vfrStatementHeader[NObj]"," + << + // check data type + if (_GET_CURRQEST_VARTINFO().mVarStoreId != EFI_VARSTORE_ID_INVALID) { + if (_GET_CURRQEST_VARTINFO().mIsBitVar) { + LFlags = (EDKII_IFR_NUMERIC_SIZE_BIT & (_GET_CURRQEST_VARSIZE())); + _PCATCH(NObj->SetFlagsForBitField (NObj->FLAGS(), LFlags), L->getLine()); + } else { + _PCATCH (gCVfrVarDataTypeDB.GetDataTypeSize (_GET_CURRQEST_DATATYPE(), &DataTypeSize), L->getLine(), "Numeric varid is not the valid data type"); + if (DataTypeSize != 0 && DataTypeSize != _GET_CURRQEST_VARSIZE()) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, L->getLine(), "Numeric varid doesn't support array"); + } + _PCATCH(NObj->SetFlags (NObj->FLAGS(), _GET_CURRQEST_DATATYPE()), L->getLine()); + } + } + >> + { F:FLAGS "=" vfrNumericFlags[*NObj, F->getLine()] "," } + { + Key "=" KN:Number "," << AssignQuestionKey (*NObj, KN); >> + } + vfrSetMinMaxStep[*NObj] << + if (!_GET_CURRQEST_VARTINFO().mIsBitVar) { + switch (_GET_CURRQEST_DATATYPE()) { + // + // Base on the type to know the actual used size,shrink the buffer + // size allocate before. + // + case EFI_IFR_TYPE_NUM_SIZE_8: ShrinkSize = 21;break; + case EFI_IFR_TYPE_NUM_SIZE_16:ShrinkSize = 18;break; + case EFI_IFR_TYPE_NUM_SIZE_32:ShrinkSize = 12;break; + case EFI_IFR_TYPE_NUM_SIZE_64:break; + default: + IsSupported = FALSE; + break; + } + } else { + // + // Question stored in bit fields saved as UINT32 type, so the ShrinkSize same as EFI_IFR_TYPE_NUM_SIZE_32. + // + ShrinkSize = 12; + } + NObj->ShrinkBinSize (ShrinkSize); + + if (!IsSupported) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, L->getLine(), "Numeric question only support UINT8, UINT16, UINT32 and UINT64 data type."); + } + >> + vfrStatementQuestionOptionList + E:EndNumeric << + CRT_END_OP (E); + if (GuidObj != NULL) { + GuidObj->SetScope(1); + CRT_END_OP (E); + delete GuidObj; + } + if (NObj != NULL) delete NObj; + >> + ";" + ; + +vfrNumericFlags [CIfrNumeric & NObj, UINT32 LineNum] : + << + UINT8 LFlags = _GET_CURRQEST_DATATYPE() & EFI_IFR_NUMERIC_SIZE; + UINT8 HFlags = 0; + BOOLEAN IsSetType = FALSE; + BOOLEAN IsDisplaySpecified = FALSE; + EFI_VFR_VARSTORE_TYPE VarStoreType = gCVfrDataStorage.GetVarStoreType (_GET_CURRQEST_VARTINFO().mVarStoreId); + >> + numericFlagsField[HFlags, LFlags, IsSetType, IsDisplaySpecified, LineNum] ( "\|" numericFlagsField[HFlags, LFlags, IsSetType, IsDisplaySpecified, LineNum] )* + << + //check data type flag + if (!_GET_CURRQEST_VARTINFO().mIsBitVar) { + if (_GET_CURRQEST_VARTINFO().mVarStoreId != EFI_VARSTORE_ID_INVALID) { + if (VarStoreType == EFI_VFR_VARSTORE_BUFFER || VarStoreType == EFI_VFR_VARSTORE_EFI) { + if (_GET_CURRQEST_DATATYPE() != (LFlags & EFI_IFR_NUMERIC_SIZE)) { + _PCATCH(VFR_RETURN_INVALID_PARAMETER, LineNum, "Numeric Flag is not same to Numeric VarData type"); + } + } else { + // update data type for name/value store + UINT32 DataTypeSize; + _GET_CURRQEST_VARTINFO().mVarType = LFlags & EFI_IFR_NUMERIC_SIZE; + gCVfrVarDataTypeDB.GetDataTypeSize (_GET_CURRQEST_DATATYPE(), &DataTypeSize); + _GET_CURRQEST_VARTINFO().mVarTotalSize = DataTypeSize; + } + } else if (IsSetType){ + _GET_CURRQEST_VARTINFO().mVarType = LFlags & EFI_IFR_NUMERIC_SIZE; + } + _PCATCH(NObj.SetFlags (HFlags, LFlags, IsDisplaySpecified), LineNum); + } else if ((_GET_CURRQEST_VARTINFO().mVarStoreId != EFI_VARSTORE_ID_INVALID) && (_GET_CURRQEST_VARTINFO().mIsBitVar)) { + LFlags |= (EDKII_IFR_NUMERIC_SIZE_BIT & (_GET_CURRQEST_VARSIZE())); + _PCATCH(NObj.SetFlagsForBitField (HFlags, LFlags, IsDisplaySpecified), LineNum); + } + >> + ; + +numericFlagsField [UINT8 & HFlags, UINT8 & LFlags, BOOLEAN & IsSetType, BOOLEAN & IsDisplaySpecified, UINT32 LineNum] : + N:Number << _PCATCH(_STOU8(N->getText(), N->getLine()) == 0 ? VFR_RETURN_SUCCESS : VFR_RETURN_UNSUPPORTED, N->getLine()); >> + | "NUMERIC_SIZE_1" << if (!_GET_CURRQEST_VARTINFO().mIsBitVar) { + $LFlags = ($LFlags & ~EFI_IFR_NUMERIC_SIZE) | EFI_IFR_NUMERIC_SIZE_1;IsSetType = TRUE; + } else { + _PCATCH(VFR_RETURN_INVALID_PARAMETER, LineNum, "Can not specify the size of the numeric value for BIT field"); + } + >> + | "NUMERIC_SIZE_2" << if (!_GET_CURRQEST_VARTINFO().mIsBitVar) { + $LFlags = ($LFlags & ~EFI_IFR_NUMERIC_SIZE) | EFI_IFR_NUMERIC_SIZE_2;IsSetType = TRUE; + } else { + _PCATCH(VFR_RETURN_INVALID_PARAMETER, LineNum, "Can not specify the size of the numeric value for BIT field"); + } + >> + | "NUMERIC_SIZE_4" << if (!_GET_CURRQEST_VARTINFO().mIsBitVar) { + $LFlags = ($LFlags & ~EFI_IFR_NUMERIC_SIZE) | EFI_IFR_NUMERIC_SIZE_4; IsSetType = TRUE; + } else { + _PCATCH(VFR_RETURN_INVALID_PARAMETER, LineNum, "Can not specify the size of the numeric value for BIT field"); + } + >> + | "NUMERIC_SIZE_8" << if (!_GET_CURRQEST_VARTINFO().mIsBitVar) { + $LFlags = ($LFlags & ~EFI_IFR_NUMERIC_SIZE) | EFI_IFR_NUMERIC_SIZE_8; IsSetType = TRUE; + } else { + _PCATCH(VFR_RETURN_INVALID_PARAMETER, LineNum, "Can not specify the size of the numeric value for BIT field"); + } + >> + | "DISPLAY_INT_DEC" << if (!_GET_CURRQEST_VARTINFO().mIsBitVar) { + $LFlags = ($LFlags & ~EFI_IFR_DISPLAY) | EFI_IFR_DISPLAY_INT_DEC; + } else { + $LFlags = ($LFlags & ~EDKII_IFR_DISPLAY_BIT) | EDKII_IFR_DISPLAY_INT_DEC_BIT; + } + IsDisplaySpecified = TRUE; + >> + | "DISPLAY_UINT_DEC" << if (!_GET_CURRQEST_VARTINFO().mIsBitVar) { + $LFlags = ($LFlags & ~EFI_IFR_DISPLAY) | EFI_IFR_DISPLAY_UINT_DEC; + } else { + $LFlags = ($LFlags & ~EDKII_IFR_DISPLAY_BIT) | EDKII_IFR_DISPLAY_UINT_DEC_BIT; + } + IsDisplaySpecified = TRUE; + >> + | "DISPLAY_UINT_HEX" << if (!_GET_CURRQEST_VARTINFO().mIsBitVar) { + $LFlags = ($LFlags & ~EFI_IFR_DISPLAY) | EFI_IFR_DISPLAY_UINT_HEX; + } else { + $LFlags = ($LFlags & ~EDKII_IFR_DISPLAY_BIT) | EDKII_IFR_DISPLAY_UINT_HEX_BIT; + } + IsDisplaySpecified = TRUE; + >> + | questionheaderFlagsField[HFlags] + ; + +vfrStatementOneOf : + << + CIfrOneOf *OObj = NULL; + UINT32 DataTypeSize; + BOOLEAN IsSupported = TRUE; + UINT8 ShrinkSize = 0; + CIfrGuid *GuidObj = NULL; + UINT8 LFlags = _GET_CURRQEST_DATATYPE() & EFI_IFR_NUMERIC_SIZE; + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID;; + EFI_VARSTORE_INFO Info; + Info.mVarType = EFI_IFR_TYPE_OTHER; + Info.mVarTotalSize = 0; + Info.mInfo.mVarOffset = EFI_VAROFFSET_INVALID; + Info.mVarStoreId = EFI_VARSTORE_ID_INVALID; + Info.mIsBitVar = FALSE; + >> + L:OneOf + vfrQuestionBaseInfo[Info, QId] << + // + // Create a GUID opcode to wrap the oneof opcode, if it refer to bit varstore. + // + if (_GET_CURRQEST_VARTINFO().mIsBitVar) { + GuidObj = new CIfrGuid(0); + GuidObj->SetGuid (&gEdkiiIfrBitVarGuid); + GuidObj->SetLineNo(L->getLine()); + } + OObj = new CIfrOneOf; + OObj->SetLineNo(L->getLine()); + OObj->SetQuestionId (QId); + OObj->SetVarStoreInfo (&Info); + >> + vfrStatementHeader[OObj]"," + << //check data type + if (_GET_CURRQEST_VARTINFO().mVarStoreId != EFI_VARSTORE_ID_INVALID) { + if (_GET_CURRQEST_VARTINFO().mIsBitVar) { + LFlags = (EDKII_IFR_NUMERIC_SIZE_BIT & (_GET_CURRQEST_VARSIZE())); + _PCATCH(OObj->SetFlagsForBitField (OObj->FLAGS(), LFlags), L->getLine()); + } else { + _PCATCH (gCVfrVarDataTypeDB.GetDataTypeSize (_GET_CURRQEST_DATATYPE(), &DataTypeSize), L->getLine(), "OneOf varid is not the valid data type"); + if (DataTypeSize != 0 && DataTypeSize != _GET_CURRQEST_VARSIZE()) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, L->getLine(), "OneOf varid doesn't support array"); + } + _PCATCH(OObj->SetFlags (OObj->FLAGS(), _GET_CURRQEST_DATATYPE()), L->getLine()); + } + } + >> + { F:FLAGS "=" vfrOneofFlagsField[*OObj, F->getLine()] "," } + { + vfrSetMinMaxStep[*OObj] + } + << + if (!_GET_CURRQEST_VARTINFO().mIsBitVar) { + switch (_GET_CURRQEST_DATATYPE()) { + // + // Base on the type to know the actual used size,shrink the buffer + // size allocate before. + // + case EFI_IFR_TYPE_NUM_SIZE_8: ShrinkSize = 21;break; + case EFI_IFR_TYPE_NUM_SIZE_16:ShrinkSize = 18;break; + case EFI_IFR_TYPE_NUM_SIZE_32:ShrinkSize = 12;break; + case EFI_IFR_TYPE_NUM_SIZE_64:break; + default: + IsSupported = FALSE; + break; + } + } else { + // + // Question stored in bit fields saved as UINT32 type, so the ShrinkSize same as EFI_IFR_TYPE_NUM_SIZE_32. + // + ShrinkSize = 12; + } + OObj->ShrinkBinSize (ShrinkSize); + + if (!IsSupported) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, L->getLine(), "OneOf question only support UINT8, UINT16, UINT32 and UINT64 data type."); + } + >> + vfrStatementQuestionOptionList + E:EndOneOf << + CRT_END_OP (E); + if (GuidObj != NULL) { + GuidObj->SetScope(1); + CRT_END_OP (E); + delete GuidObj; + } + if (OObj != NULL) delete OObj; + >> + ";" + ; + +vfrOneofFlagsField [CIfrOneOf & OObj, UINT32 LineNum] : + << + UINT8 LFlags = _GET_CURRQEST_DATATYPE() & EFI_IFR_NUMERIC_SIZE; + UINT8 HFlags = 0; + BOOLEAN IsSetType = FALSE; + BOOLEAN IsDisplaySpecified = FALSE; + EFI_VFR_VARSTORE_TYPE VarStoreType = gCVfrDataStorage.GetVarStoreType (_GET_CURRQEST_VARTINFO().mVarStoreId); + >> + numericFlagsField[HFlags, LFlags, IsSetType, IsDisplaySpecified, LineNum] ( "\|" numericFlagsField[HFlags, LFlags, IsSetType, IsDisplaySpecified, LineNum] )* + << + //check data type flag + if (!_GET_CURRQEST_VARTINFO().mIsBitVar) { + if (_GET_CURRQEST_VARTINFO().mVarStoreId != EFI_VARSTORE_ID_INVALID) { + if (VarStoreType == EFI_VFR_VARSTORE_BUFFER || VarStoreType == EFI_VFR_VARSTORE_EFI) { + if (_GET_CURRQEST_DATATYPE() != (LFlags & EFI_IFR_NUMERIC_SIZE)) { + _PCATCH(VFR_RETURN_INVALID_PARAMETER, LineNum, "Numeric Flag is not same to Numeric VarData type"); + } + } else { + // update data type for Name/Value store + UINT32 DataTypeSize; + _GET_CURRQEST_VARTINFO().mVarType = LFlags & EFI_IFR_NUMERIC_SIZE; + gCVfrVarDataTypeDB.GetDataTypeSize (_GET_CURRQEST_DATATYPE(), &DataTypeSize); + _GET_CURRQEST_VARTINFO().mVarTotalSize = DataTypeSize; + } + } else if (IsSetType){ + _GET_CURRQEST_VARTINFO().mVarType = LFlags & EFI_IFR_NUMERIC_SIZE; + } + _PCATCH(OObj.SetFlags (HFlags, LFlags), LineNum); + } else if (_GET_CURRQEST_VARTINFO().mVarStoreId != EFI_VARSTORE_ID_INVALID) { + _PCATCH(OObj.SetFlagsForBitField (HFlags, LFlags), LineNum); + } + >> + ; + +vfrStatementStringType : + vfrStatementString | + vfrStatementPassword + ; + +vfrStatementString : + << + CIfrString SObj; + UINT32 VarArraySize; + UINT8 StringMinSize; + UINT8 StringMaxSize; + >> + L:String << SObj.SetLineNo(L->getLine()); gIsStringOp = TRUE;>> + vfrQuestionHeader[SObj] "," + { F:FLAGS "=" vfrStringFlagsField[SObj, F->getLine()] "," } + { + Key "=" KN:Number "," << AssignQuestionKey (SObj, KN); >> + } + MinSize "=" MIN:Number "," << + VarArraySize = _GET_CURRQEST_ARRAY_SIZE(); + StringMinSize = _STOU8(MIN->getText(), MIN->getLine()); + if (_STOU64(MIN->getText(), MIN->getLine()) > StringMinSize) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, MIN->getLine(), "String MinSize takes only one byte, which can't be larger than 0xFF."); + } else if (VarArraySize != 0 && StringMinSize > VarArraySize) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, MIN->getLine(), "String MinSize can't be larger than the max number of elements in string array."); + } + SObj.SetMinSize (StringMinSize); + >> + MaxSize "=" MAX:Number "," << + StringMaxSize = _STOU8(MAX->getText(), MAX->getLine()); + if (_STOU64(MAX->getText(), MAX->getLine()) > StringMaxSize) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, MAX->getLine(), "String MaxSize takes only one byte, which can't be larger than 0xFF."); + } else if (VarArraySize != 0 && StringMaxSize > VarArraySize) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, MAX->getLine(), "String MaxSize can't be larger than the max number of elements in string array."); + } else if (StringMaxSize < StringMinSize) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, MAX->getLine(), "String MaxSize can't be less than String MinSize."); + } + SObj.SetMaxSize (StringMaxSize); + >> + vfrStatementQuestionOptionList + E:EndString << CRT_END_OP (E); gIsStringOp = FALSE;>> + ";" + ; + +vfrStringFlagsField [CIfrString & SObj, UINT32 LineNum] : + << + UINT8 LFlags = 0; + UINT8 HFlags = 0; + >> + stringFlagsField[HFlags, LFlags] ( "\|" stringFlagsField[HFlags, LFlags] )* + << _PCATCH(SObj.SetFlags (HFlags, LFlags), LineNum); >> + ; + +stringFlagsField [UINT8 & HFlags, UINT8 & LFlags] : + N:Number << _PCATCH(_STOU8(N->getText(), N->getLine()) == 0 ? VFR_RETURN_SUCCESS : VFR_RETURN_UNSUPPORTED, N->getLine()); >> + | "MULTI_LINE" << $LFlags = 0x01; >> + | questionheaderFlagsField[HFlags] + ; + +vfrStatementPassword : + << + CIfrPassword PObj; + UINT32 VarArraySize; + UINT16 PasswordMinSize; + UINT16 PasswordMaxSize; + >> + L:Password << PObj.SetLineNo(L->getLine()); >> + vfrQuestionHeader[PObj] "," + { F:FLAGS "=" vfrPasswordFlagsField[PObj, F->getLine()] "," } + { + Key "=" KN:Number "," << AssignQuestionKey (PObj, KN); >> + } + MinSize "=" MIN:Number "," << + VarArraySize = _GET_CURRQEST_ARRAY_SIZE(); + PasswordMinSize = _STOU16(MIN->getText(), MIN->getLine()); + if (_STOU64(MIN->getText(), MIN->getLine()) > PasswordMinSize) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, MIN->getLine(), "Password MinSize takes only two byte, which can't be larger than 0xFFFF."); + } else if (VarArraySize != 0 && PasswordMinSize > VarArraySize) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, MIN->getLine(), "Password MinSize can't be larger than the max number of elements in password array."); + } + PObj.SetMinSize (PasswordMinSize); + >> + MaxSize "=" MAX:Number "," << + PasswordMaxSize = _STOU16(MAX->getText(), MAX->getLine()); + if (_STOU64(MAX->getText(), MAX->getLine()) > PasswordMaxSize) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, MAX->getLine(), "Password MaxSize takes only two byte, which can't be larger than 0xFFFF."); + } else if (VarArraySize != 0 && PasswordMaxSize > VarArraySize) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, MAX->getLine(), "Password MaxSize can't be larger than the max number of elements in password array."); + } else if (PasswordMaxSize < PasswordMinSize) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, MAX->getLine(), "Password MaxSize can't be less than Password MinSize."); + } + PObj.SetMaxSize (PasswordMaxSize); + >> + { Encoding "=" Number "," } + vfrStatementQuestionOptionList + E:EndPassword << CRT_END_OP (E); >> + ";" + ; + +vfrPasswordFlagsField [CIfrPassword & PObj, UINT32 LineNum] : + << UINT8 HFlags = 0; >> + passwordFlagsField[HFlags] ( "\|" passwordFlagsField[HFlags] )* + << _PCATCH(PObj.SetFlags(HFlags), LineNum); >> + ; + +passwordFlagsField [UINT8 & HFlags] : + N:Number << _PCATCH(_STOU8(N->getText(), N->getLine()) == 0 ? VFR_RETURN_SUCCESS : VFR_RETURN_UNSUPPORTED, N->getLine()); >> + | questionheaderFlagsField[HFlags] + ; + +vfrStatementOrderedList : + << + CIfrOrderedList OLObj; + UINT32 VarArraySize; + >> + L:OrderedList << OLObj.SetLineNo(L->getLine()); gIsOrderedList = TRUE;>> + vfrQuestionHeader[OLObj] "," + << + VarArraySize = _GET_CURRQEST_ARRAY_SIZE(); + OLObj.SetMaxContainers ((UINT8) (VarArraySize > 0xFF ? 0xFF : VarArraySize)); + >> + { + MaxContainers "=" M:Number "," << + if (_STOU64(M->getText(), M->getLine()) > _STOU8(M->getText(), M->getLine())) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, M->getLine(), "OrderedList MaxContainers takes only one byte, which can't be larger than 0xFF."); + } else if (VarArraySize != 0 && _STOU8(M->getText(), M->getLine()) > VarArraySize) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, M->getLine(), "OrderedList MaxContainers can't be larger than the max number of elements in array."); + } + OLObj.SetMaxContainers (_STOU8(M->getText(), M->getLine())); + >> + } + { F:FLAGS "=" vfrOrderedListFlags[OLObj, F->getLine()] {","}} + vfrStatementQuestionOptionList + E:EndList << CRT_END_OP (E); gIsOrderedList = FALSE;>> + ";" + ; + +vfrOrderedListFlags [CIfrOrderedList & OLObj, UINT32 LineNum] : + << + UINT8 HFlags = 0; + UINT8 LFlags = 0; + >> + orderedlistFlagsField[HFlags, LFlags] ( "\|" orderedlistFlagsField[HFlags, LFlags] )* + << _PCATCH(OLObj.SetFlags (HFlags, LFlags), LineNum); >> + ; + +orderedlistFlagsField [UINT8 & HFlags, UINT8 & LFlags] : + N:Number << _PCATCH(_STOU8(N->getText(), N->getLine()) == 0 ? VFR_RETURN_SUCCESS : VFR_RETURN_UNSUPPORTED, N->getLine()); >> + | "UNIQUE" << $LFlags |= 0x01; >> + | "NOEMPTY" << $LFlags |= 0x02; >> + | questionheaderFlagsField[HFlags] + ; + +vfrStatementTime : + << + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + CHAR8 *VarIdStr[3] = {NULL, }; + CIfrTime TObj; + EFI_IFR_TYPE_VALUE Val = gZeroEfiIfrTypeValue; + UINT8 Size = OFFSET_OF (EFI_IFR_DEFAULT, Value) + sizeof (EFI_HII_TIME); + >> + L:Time << TObj.SetLineNo(L->getLine()); >> + ( + ( + vfrQuestionHeader[TObj, QUESTION_TIME] "," << + if (_GET_CURRQEST_DATATYPE() == EFI_IFR_TYPE_OTHER) { + _GET_CURRQEST_VARTINFO().mVarType = EFI_IFR_TYPE_TIME; + } + >> + { F:FLAGS "=" vfrTimeFlags[TObj, F->getLine()] "," } + vfrStatementQuestionOptionList + ) + | + ( + Hour VarId "=" T1:StringIdentifier "." T1H:StringIdentifier "," + << _STRCAT(&VarIdStr[0], T1->getText()); _STRCAT(&VarIdStr[0], "."); _STRCAT(&VarIdStr[0], T1H->getText()); >> + Prompt "=" "STRING_TOKEN" "\(" HP:Number "\)" "," + Help "=" "STRING_TOKEN" "\(" HH:Number "\)" "," + minMaxTimeStepDefault[Val.time, 0] + + Minute VarId "=" T2:StringIdentifier "." T2M:StringIdentifier "," + << _STRCAT(&VarIdStr[1], T2->getText()); _STRCAT(&VarIdStr[1], "."); _STRCAT(&VarIdStr[1], T2M->getText()); >> + Prompt "=" "STRING_TOKEN" "\(" MP:Number "\)" "," + Help "=" "STRING_TOKEN" "\(" MH:Number "\)" "," + minMaxTimeStepDefault[Val.time, 1] + + Second VarId "=" T3:StringIdentifier "." T3S:StringIdentifier "," + << _STRCAT(&VarIdStr[2], T3->getText()); _STRCAT(&VarIdStr[2], "."); _STRCAT(&VarIdStr[2], T3S->getText()); >> + Prompt "=" "STRING_TOKEN" "\(" SP:Number "\)" "," + Help "=" "STRING_TOKEN" "\(" SH:Number "\)" "," + minMaxTimeStepDefault[Val.time, 2] + { G:FLAGS "=" vfrTimeFlags[TObj, G->getLine()] "," } + << + mCVfrQuestionDB.RegisterOldTimeQuestion (VarIdStr[0], VarIdStr[1], VarIdStr[2], QId); + TObj.SetQuestionId (QId); + TObj.SetFlags (EFI_IFR_QUESTION_FLAG_DEFAULT, QF_TIME_STORAGE_TIME); + TObj.SetPrompt (_STOSID(HP->getText(), HP->getLine())); + TObj.SetHelp (_STOSID(HH->getText(), HH->getLine())); + if (VarIdStr[0] != NULL) { delete VarIdStr[0]; } if (VarIdStr[1] != NULL) { delete VarIdStr[1]; } if (VarIdStr[2] != NULL) { delete VarIdStr[2]; } + >> + << {CIfrDefault DefaultObj(Size, EFI_HII_DEFAULT_CLASS_STANDARD, EFI_IFR_TYPE_TIME, Val); DefaultObj.SetLineNo(L->getLine());} >> + ) + ( vfrStatementInconsistentIf )* + ) + E:EndTime << CRT_END_OP (E); >> + ";" + ; + +minMaxTimeStepDefault[EFI_HII_TIME & T, UINT8 KeyValue] : + Minimum "=" Number "," + Maximum "=" Number "," + { "step" "=" Number "," } + { + "default" "=" N:Number "," << + switch (KeyValue) { + case 0: + T.Hour = _STOU8(N->getText(), N->getLine()); + if (T.Hour > 23) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, N->getLine(), "Hour default value must be between 0 and 23."); + } + break; + case 1: + T.Minute = _STOU8(N->getText(), N->getLine()); + if (T.Minute > 59) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, N->getLine(), "Minute default value must be between 0 and 59."); + } + break; + case 2: + T.Second = _STOU8(N->getText(), N->getLine()); + if (T.Second > 59) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, N->getLine(), "Second default value must be between 0 and 59."); + } + break; + } + >> + } + ; + +vfrTimeFlags [CIfrTime & TObj, UINT32 LineNum] : + << UINT8 LFlags = 0; >> + timeFlagsField[LFlags] ( "\|" timeFlagsField[LFlags] )* + << _PCATCH(TObj.SetFlags(EFI_IFR_QUESTION_FLAG_DEFAULT, LFlags), LineNum); >> + ; + +timeFlagsField [UINT8 & Flags] : + N:Number << $Flags |= _STOU8(N->getText(), N->getLine()); >> + | "HOUR_SUPPRESS" << $Flags |= 0x01; >> + | "MINUTE_SUPPRESS" << $Flags |= 0x02; >> + | "SECOND_SUPPRESS" << $Flags |= 0x04; >> + | "STORAGE_NORMAL" << $Flags |= 0x00; >> + | "STORAGE_TIME" << $Flags |= 0x10; >> + | "STORAGE_WAKEUP" << $Flags |= 0x20; >> + ; + +vfrStatementQuestionTag : + vfrStatementStatTag "," | + vfrStatementInconsistentIf | + vfrStatementNoSubmitIf | + vfrStatementDisableIfQuest | + vfrStatementRefresh | + vfrStatementVarstoreDevice | + vfrStatementExtension | + vfrStatementRefreshEvent "," | + vfrStatementWarningIf + ; + +vfrStatementQuestionTagList : + ( vfrStatementQuestionTag )* + ; + +vfrStatementQuestionOptionTag : + vfrStatementSuppressIfQuest | + vfrStatementGrayOutIfQuest | + vfrStatementValue | + vfrStatementDefault | + vfrStatementRead | + vfrStatementWrite | + vfrStatementOptions + ; + +vfrStatementQuestionOptionList : + ( + vfrStatementQuestionTag | + vfrStatementQuestionOptionTag + )* + ; + +vfrStatementStatList : + vfrStatementStat | + vfrStatementQuestions | + vfrStatementConditionalNew | + vfrStatementLabel | + vfrStatementExtension | + // Just for framework vfr compatibility + vfrStatementInvalid + ; + +vfrStatementStatListOld : + vfrStatementStat | + vfrStatementQuestions | + vfrStatementLabel | + // Just for framework vfr compatibility + vfrStatementInvalid + ; + +vfrStatementDisableIfStat : + << + CIfrDisableIf DIObj; + >> + L:DisableIf << DIObj.SetLineNo(L->getLine()); >> + vfrStatementExpression[0] ";" + ( vfrStatementStatList )* + E:EndIf << CRT_END_OP (E); >> + ";" + ; + +vfrStatementInconsistentIfStat : + << CIfrInconsistentIf IIObj; >> + L:InconsistentIf << + _PCATCH (VFR_RETURN_UNSUPPORTED, L); + IIObj.SetLineNo(L->getLine()); + >> + Prompt "=" "STRING_TOKEN" "\(" S:Number "\)" "," << IIObj.SetError (_STOSID(S->getText(), S->getLine())); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + E:EndIf << CRT_END_OP (E); >> + ";" + ; + +// +// Compatible for framework vfr file +// +vfrStatementgrayoutIfSuppressIf: + << CIfrSuppressIf SIObj; >> + L:SuppressIf << SIObj.SetLineNo(L->getLine()); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + ";" + ; + +vfrStatementsuppressIfGrayOutIf: + << CIfrGrayOutIf GOIObj; >> + L:GrayOutIf << GOIObj.SetLineNo(L->getLine()); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + ";" + ; + +vfrStatementSuppressIfStatNew : + << CIfrSuppressIf SIObj;>> + L:SuppressIf << SIObj.SetLineNo(L->getLine()); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + ";" + ( vfrStatementStatList )* + E: EndIf ";" << CRT_END_OP (E); >> + ; + +vfrStatementGrayOutIfStatNew : + << CIfrGrayOutIf GOIObj;>> + L:GrayOutIf << GOIObj.SetLineNo(L->getLine()); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + ";" + ( vfrStatementStatList )* + E: EndIf ";" << CRT_END_OP (E); >> + ; + +vfrImageTag : + << CIfrImage IObj; >> + L:Image "=" "IMAGE_TOKEN" "\(" S1:Number "\)" << IObj.SetImageId (_STOSID(S1->getText(), S1->getLine())); IObj.SetLineNo(L->getLine()); >> + ; + +vfrLockedTag : + << CIfrLocked LObj; >> + L:Locked << LObj.SetLineNo(L->getLine()); >> + ; + +vfrModalTag : + << CIfrModal MObj; >> + L:Modal << MObj.SetLineNo(L->getLine()); >> + ; + +vfrStatementStatTag : + vfrImageTag | + vfrLockedTag + ; + +vfrStatementStatTagList : + vfrStatementStatTag ( "," vfrStatementStatTag )* + ; + +vfrStatementImage : + vfrImageTag + ";" + ; + +vfrStatementModal : + vfrModalTag + ";" + ; + +vfrStatementLocked : + vfrLockedTag + ";" + ; + +vfrStatementInconsistentIf : + << CIfrInconsistentIf IIObj; >> + L:InconsistentIf << IIObj.SetLineNo(L->getLine()); >> + Prompt "=" "STRING_TOKEN" "\(" S:Number "\)" "," << IIObj.SetError (_STOSID(S->getText(), S->getLine())); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + E:EndIf {";"} << CRT_END_OP (E); >> + ; + +vfrStatementNoSubmitIf : + << CIfrNoSubmitIf NSIObj; >> + L:NoSubmitIf << NSIObj.SetLineNo(L->getLine()); >> + Prompt "=" "STRING_TOKEN" "\(" S:Number "\)" "," << NSIObj.SetError (_STOSID(S->getText(), S->getLine())); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + E:EndIf {";"} << CRT_END_OP (E); >> + ; + +vfrStatementWarningIf : + << CIfrWarningIf WIObj; >> + L:WarningIf << WIObj.SetLineNo(L->getLine()); >> + Prompt "=" "STRING_TOKEN" "\(" S:Number "\)" "," << WIObj.SetWarning (_STOSID(S->getText(), S->getLine())); >> + {Timeout "=" T:Number "," << WIObj.SetTimeOut (_STOU8(T->getText(), T->getLine())); >>} + vfrStatementExpression[0] + E:EndIf {";"} << CRT_END_OP (E); >> + ; + +vfrStatementDisableIfQuest : + << + CIfrDisableIf DIObj; + >> + L:DisableIf << DIObj.SetLineNo(L->getLine()); >> + vfrStatementExpression[0] ";" + vfrStatementQuestionOptionList + E:EndIf {";"} << CRT_END_OP (E); >> + ; + +vfrStatementRefresh : + << CIfrRefresh RObj; >> + L:Refresh << RObj.SetLineNo(L->getLine()); >> + Interval "=" I:Number << RObj.SetRefreshInterval (_STOU8(I->getText(), I->getLine())); >> + ; + +vfrStatementRefreshEvent : + << + CIfrRefreshId RiObj; + EFI_GUID Guid; + >> + L:RefreshGuid << RiObj.SetLineNo(L->getLine()); >> + "=" guidDefinition[Guid] << RiObj.SetRefreshEventGroutId (&Guid); >> + ; + +vfrStatementVarstoreDevice : + << CIfrVarStoreDevice VDObj; >> + L:VarstoreDevice << VDObj.SetLineNo(L->getLine()); >> + "=" "STRING_TOKEN" "\(" S:Number "\)" "," << VDObj.SetDevicePath (_STOSID(S->getText(), S->getLine())); >> + ; + +vfrStatementSuppressIfQuest : + << CIfrSuppressIf SIObj; >> + L:SuppressIf << SIObj.SetLineNo(L->getLine()); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] ";" + vfrStatementQuestionOptionList + E:EndIf {";"} << CRT_END_OP (E); >> + ; + +vfrStatementGrayOutIfQuest : + << CIfrGrayOutIf GOIObj; >> + L:GrayOutIf << GOIObj.SetLineNo(L->getLine()); >> + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] ";" + vfrStatementQuestionOptionList + E:EndIf {";"} << CRT_END_OP (E); >> + ; + +vfrStatementOptions : + vfrStatementOneOfOption + ; + +vfrStatementOneOfOption : + << + UINT8 ValueList[EFI_IFR_MAX_LENGTH] = {0,}; + EFI_IFR_TYPE_VALUE *Val = (EFI_IFR_TYPE_VALUE *) ValueList; + CHAR8 *VarStoreName = NULL; + UINT32 Size = 0; + BOOLEAN TypeError = FALSE; + EFI_VFR_RETURN_CODE ReturnCode = VFR_RETURN_SUCCESS; + EFI_GUID *VarStoreGuid = NULL; + BOOLEAN ArrayType = FALSE; + CIfrOneOfOption *OOOObj; + UINT8 *Type8 = (UINT8 *) ValueList; + UINT16 *Type16 = (UINT16 *) ValueList; + UINT32 *Type32 = (UINT32 *) ValueList; + UINT64 *Type64 = (UINT64 *) ValueList; + >> + L:Option << + if (_GET_CURRQEST_DATATYPE() == EFI_IFR_TYPE_OTHER) { + _PCATCH (VFR_RETURN_FATAL_ERROR, L->getLine(), "Get data type error."); + } + + >> + Text "=" "STRING_TOKEN" "\(" S:Number "\)" "," + Value "=" vfrConstantValueField[_GET_CURRQEST_DATATYPE(), *Val, ArrayType] "," + << + if (gCurrentMinMaxData != NULL) { + //set min/max value for oneof opcode + UINT64 Step = gCurrentMinMaxData->GetStepData(_GET_CURRQEST_DATATYPE(), _GET_CURRQEST_VARTINFO().mIsBitVar); + if (_GET_CURRQEST_VARTINFO().mIsBitVar) { + gCurrentMinMaxData->SetMinMaxStepData(Val->u32, Val->u32, (UINT32) Step); + } else { + switch (_GET_CURRQEST_DATATYPE()) { + case EFI_IFR_TYPE_NUM_SIZE_64: + gCurrentMinMaxData->SetMinMaxStepData(Val->u64, Val->u64, Step); + break; + case EFI_IFR_TYPE_NUM_SIZE_32: + gCurrentMinMaxData->SetMinMaxStepData(Val->u32, Val->u32, (UINT32) Step); + break; + case EFI_IFR_TYPE_NUM_SIZE_16: + gCurrentMinMaxData->SetMinMaxStepData(Val->u16, Val->u16, (UINT16) Step); + break; + case EFI_IFR_TYPE_NUM_SIZE_8: + gCurrentMinMaxData->SetMinMaxStepData(Val->u8, Val->u8, (UINT8) Step); + break; + default: + break; + } + } + } + if (_GET_CURRQEST_DATATYPE() == EFI_IFR_TYPE_OTHER) { + Size = sizeof (EFI_IFR_TYPE_VALUE); + } else if (ArrayType) { + switch (_GET_CURRQEST_DATATYPE()) { + case EFI_IFR_TYPE_NUM_SIZE_8 : + while (Type8[Size] != 0) { + Size++; + } + break; + case EFI_IFR_TYPE_NUM_SIZE_16 : + while (Type16[Size] != 0) { + Size++; + } + Size *= sizeof (UINT16); + break; + case EFI_IFR_TYPE_NUM_SIZE_32 : + while (Type32[Size] != 0) { + Size++; + } + Size *= sizeof (UINT32); + break; + case EFI_IFR_TYPE_NUM_SIZE_64 : + while (Type64[Size] != 0) { + Size++; + } + Size *= sizeof (UINT64); + break; + default: + break; + } + } else { + // + // For the oneof stored in bit fields, set the option type as UINT32. + // + if (_GET_CURRQEST_VARTINFO().mIsBitVar) { + Size = sizeof (UINT32); + } else { + ReturnCode = gCVfrVarDataTypeDB.GetDataTypeSize (_GET_CURRQEST_DATATYPE(), &Size); + } + } + if (ReturnCode != VFR_RETURN_SUCCESS) { + _PCATCH (ReturnCode, L->getLine()); + } + + Size += OFFSET_OF (EFI_IFR_ONE_OF_OPTION, Value); + OOOObj = new CIfrOneOfOption((UINT8)Size); + OOOObj->SetLineNo(L->getLine()); + OOOObj->SetOption (_STOSID(S->getText(), S->getLine())); + if (ArrayType) { + OOOObj->SetType (EFI_IFR_TYPE_BUFFER); + } else { + if (_GET_CURRQEST_VARTINFO().mIsBitVar) { + OOOObj->SetType ( EFI_IFR_TYPE_NUM_SIZE_32); + } else { + OOOObj->SetType (_GET_CURRQEST_DATATYPE()); + } + } + OOOObj->SetValue (*Val); + >> + F:FLAGS "=" vfrOneOfOptionFlags[*OOOObj, F->getLine()] + << + // + // Array type only for default type OneOfOption. + // + if ((OOOObj->GetFlags () & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG)) == 0 && ArrayType) { + _PCATCH (VFR_RETURN_FATAL_ERROR, L->getLine(), "Default keyword should with array value type!"); + } + + // + // Clear the default flag if the option not use array value but has default flag. + // + if ((OOOObj->GetFlags () & (EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG)) != 0 && !ArrayType && gIsOrderedList) { + OOOObj->SetFlags(OOOObj->GetFlags () & ~(EFI_IFR_OPTION_DEFAULT | EFI_IFR_OPTION_DEFAULT_MFG)); + } + + if (_GET_CURRQEST_VARTINFO().mVarStoreId != EFI_VARSTORE_ID_INVALID) { + _PCATCH(gCVfrDataStorage.GetVarStoreName (_GET_CURRQEST_VARTINFO().mVarStoreId, &VarStoreName), L->getLine()); + VarStoreGuid = gCVfrDataStorage.GetVarStoreGuid(_GET_CURRQEST_VARTINFO().mVarStoreId); + if (OOOObj->GetFlags () & EFI_IFR_OPTION_DEFAULT) { + CheckDuplicateDefaultValue (EFI_HII_DEFAULT_CLASS_STANDARD, F); + _PCATCH(gCVfrDefaultStore.BufferVarStoreAltConfigAdd ( + EFI_HII_DEFAULT_CLASS_STANDARD, + _GET_CURRQEST_VARTINFO(), + VarStoreName, + VarStoreGuid, + _GET_CURRQEST_DATATYPE (), + *Val + ), L->getLine()); + } + if (OOOObj->GetFlags () & EFI_IFR_OPTION_DEFAULT_MFG) { + CheckDuplicateDefaultValue (EFI_HII_DEFAULT_CLASS_MANUFACTURING, F); + _PCATCH(gCVfrDefaultStore.BufferVarStoreAltConfigAdd ( + EFI_HII_DEFAULT_CLASS_MANUFACTURING, + _GET_CURRQEST_VARTINFO(), + VarStoreName, + VarStoreGuid, + _GET_CURRQEST_DATATYPE (), + *Val + ), L->getLine()); + } + } + >> + { + "," Key "=" KN:Number << + _PCATCH (VFR_RETURN_UNSUPPORTED, KN); + // + // Guid Option Key + // + CIfrOptionKey IfrOptionKey ( + gCurrentQuestion->QUESTION_ID(), + *Val, + _STOQID(KN->getText(), KN->getLine()) + ); + SET_LINE_INFO (IfrOptionKey, KN); + >> + } + ( + T:"," vfrImageTag << OOOObj->SetScope (1); CRT_END_OP (T); >> + )* + ";" << if (OOOObj != NULL) {delete OOOObj;} >> + ; + +vfrOneOfOptionFlags [CIfrOneOfOption & OOOObj, UINT32 LineNum] : + << + UINT8 LFlags = _GET_CURRQEST_DATATYPE(); + UINT8 HFlags = 0; + >> + oneofoptionFlagsField[HFlags, LFlags] ( "\|" oneofoptionFlagsField[HFlags, LFlags] )* + << _PCATCH(gCurrentQuestion->SetFlags(HFlags), LineNum); >> + << _PCATCH(OOOObj.SetFlags(LFlags), LineNum); >> + ; + +oneofoptionFlagsField [UINT8 & HFlags, UINT8 & LFlags] : + N:Number << $LFlags |= _STOU8(N->getText(), N->getLine()); >> + | "OPTION_DEFAULT" << $LFlags |= 0x10; >> + | "OPTION_DEFAULT_MFG" << $LFlags |= 0x20; >> + | InteractiveFlag << $HFlags |= 0x04; >> + | ResetRequiredFlag << $HFlags |= 0x10; >> + | RestStyleFlag << $HFlags |= 0x20; >> + | ReconnectRequiredFlag << $HFlags |= 0x40; >> + | ManufacturingFlag << $LFlags |= 0x20; >> + | DefaultFlag << $LFlags |= 0x10; >> + | A:NVAccessFlag << + gCVfrErrorHandle.HandleWarning ( + VFR_WARNING_OBSOLETED_FRAMEWORK_OPCODE, + A->getLine(), + A->getText() + ); + >> + | L:LateCheckFlag << + gCVfrErrorHandle.HandleWarning ( + VFR_WARNING_OBSOLETED_FRAMEWORK_OPCODE, + L->getLine(), + L->getText() + ); + >> + ; + +vfrStatementLabel : + L:Label + N:Number << + { + CIfrLabel LObj2; + LObj2.SetLineNo(L->getLine()); + LObj2.SetNumber (_STOU16(N->getText(), N->getLine())); + } + >> + ";" + ; + +vfrStatementBanner : + << CIfrBanner BObj; >> + B:Banner { "," } << BObj.SetLineNo(B->getLine()); >> + Title "=" "STRING_TOKEN" "\(" S:Number "\)" "," << BObj.SetTitle (_STOSID(S->getText(), S->getLine())); >> + ( + ( + Line L:Number "," << BObj.SetLine (_STOU16(L->getText(), L->getLine())); >> + Align + ( + Left << BObj.SetAlign (0); >> + | Center << BObj.SetAlign (1); >> + | Right << BObj.SetAlign (2); >> + ) ";" + ) + | + ( + Timeout "=" T:Number ";" << {CIfrTimeout TObj(_STOU16(T->getText(), T->getLine()));} >> + ) + ) + ; + +//****************************************************************************** +// +// keep some syntax for compatibility but not generate any IFR object +// +vfrStatementInvalidHidden : + L:Hidden << + _PCATCH (VFR_RETURN_UNSUPPORTED, L); + >> + Value "=" Number "," + Key "=" Number ";" + ; + +vfrStatementInvalidInconsistentIf : + InconsistentIf + Prompt "=" "STRING_TOKEN" "\(" S:Number "\)" "," + { FLAGS "=" flagsField ( "\|" flagsField )* "," } + vfrStatementExpression[0] + EndIf + ";" + ; + +vfrStatementInvalidInventory : + L:Inventory << + _PCATCH (VFR_RETURN_UNSUPPORTED, L); + >> + Help "=" "STRING_TOKEN" "\(" Number "\)" "," + Text "=" "STRING_TOKEN" "\(" Number "\)" "," + { + Text "=" "STRING_TOKEN" "\(" Number "\)" + } + ";" + ; + +vfrStatementInvalidSaveRestoreDefaults : + ( + L:Save << + _PCATCH (VFR_RETURN_UNSUPPORTED, L); + >> + | + K:Restore << + _PCATCH (VFR_RETURN_UNSUPPORTED, K); + >> + ) + Defaults "," + FormId "=" Number "," + Prompt "=" "STRING_TOKEN" "\(" Number "\)" "," + Help "=" "STRING_TOKEN" "\(" Number "\)" + { "," FLAGS "=" flagsField ( "\|" flagsField )* } + { "," Key "=" Number } + ";" + ; + +//****************************************************************************** +// +// The syntax of expression +// +#token Dup("dup") "dup" +#token VarEqVal("vareqval") "vareqval" +#token Var("var") "var" +#token IdEqVal("ideqval") "ideqval" +#token IdEqId("ideqid") "ideqid" +#token IdEqValList("ideqvallist") "ideqvallist" +#token QuestionRef("questionref") "questionref" +#token RuleRef("ruleref") "ruleref" +#token StringRef("stringref") "stringref" +#token PushThis("pushthis") "pushthis" +#token Security("security") "security" +#token Get("get") "get" +#token True("TRUE") "TRUE" +#token False("FALSE") "FALSE" +#token One("ONE") "ONE" +#token Ones("ONES") "ONES" +#token Zero("ZERO") "ZERO" +#token Undefined("UNDEFINED") "UNDEFINED" +#token Version("VERSION") "VERSION" +#token Length("length") "length" +#token AND("AND") "AND" +#token OR("OR") "OR" +#token NOT("NOT") "NOT" +#token Set("set") "set" +#token BitWiseNot("~") "\~" +#token BoolVal("boolval") "boolval" +#token StringVal("stringval") "stringval" +#token UnIntVal("unintval") "unintval" +#token ToUpper("toupper") "toupper" +#token ToLower("tolower") "tolower" +#token Match("match") "match" +#token Match2("match2") "match2" +#token Catenate("catenate") "catenate" +#token QuestionRefVal("questionrefval") "questionrefval" +#token StringRefVal("stringrefval") "stringrefval" +#token Map("map") "map" +#token RefreshGuid("refreshguid") "refreshguid" + +// +// Root expression extension function called by other function. +// +vfrStatementExpression [UINT32 RootLevel, UINT32 ExpOpCount = 0] : + << + if ($RootLevel == 0) { + mCIfrOpHdrIndex ++; + if (mCIfrOpHdrIndex >= MAX_IFR_EXPRESSION_DEPTH) { + _PCATCH (VFR_RETURN_INVALID_PARAMETER, 0, "The depth of expression exceeds the max supported level 8!"); + } + _INIT_OPHDR_COND (); + } + >> + andTerm[$RootLevel, $ExpOpCount] + ( + L:OR andTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrOr OObj(L->getLine()); >> + )* + << + // + // Extend OpCode Scope only for the root expression. + // + if ($ExpOpCount > 1 && $RootLevel == 0) { + if (_SET_SAVED_OPHDR_SCOPE()) { + CIfrEnd EObj; + if (mCIfrOpHdrLineNo[mCIfrOpHdrIndex] != 0) { + EObj.SetLineNo (mCIfrOpHdrLineNo[mCIfrOpHdrIndex]); + } + } + } + + if ($RootLevel == 0) { + _CLEAR_SAVED_OPHDR (); + mCIfrOpHdrIndex --; + } + >> + ; + +// +// Add new sub function for the sub expression extension to remember the ExpOpCount +// This function is only called by sub expression. +// +vfrStatementExpressionSub [UINT32 RootLevel, UINT32 & ExpOpCount] : + andTerm[$RootLevel, $ExpOpCount] + ( + L:OR andTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrOr OObj(L->getLine()); >> + )* + ; + +andTerm[UINT32 & RootLevel, UINT32 & ExpOpCount] : + bitwiseorTerm[$RootLevel, $ExpOpCount] + ( + L:AND bitwiseorTerm [$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrAnd AObj(L->getLine()); >> + )* + ; + +bitwiseorTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + bitwiseandTerm[$RootLevel, $ExpOpCount] + ( + L:"\|" bitwiseandTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrBitWiseOr BWOObj(L->getLine()); >> + )* + ; + +bitwiseandTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + equalTerm[$RootLevel, $ExpOpCount] + ( + L:"&" equalTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrBitWiseAnd BWAObj(L->getLine()); >> + )* + ; + +equalTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + compareTerm[$RootLevel, $ExpOpCount] + ( + ( + L1:"==" compareTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrEqual EObj(L1->getLine()); >> + ) + | + ( + L2:"!=" compareTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrNotEqual NEObj(L2->getLine()); >> + ) + )* + ; + +compareTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + shiftTerm[$RootLevel, $ExpOpCount] + ( + ( + L1:"<" shiftTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrLessThan LTObj(L1->getLine()); >> + ) + | + ( + L2:"<=" shiftTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrLessEqual LEObj(L2->getLine()); >> + ) + | + ( + L3:">" shiftTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrGreaterThan GTObj(L3->getLine()); >> + ) + | + ( + L4:">=" shiftTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrGreaterEqual GEObj(L4->getLine()); >> + ) + )* + ; + +shiftTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + addMinusTerm[$RootLevel, $ExpOpCount] + ( + ( + L1:"\<<" addMinusTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrShiftLeft SLObj(L1->getLine()); >> + ) + | + ( + L2:"\>>" addMinusTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrShiftRight SRObj(L2->getLine()); >> + ) + )* + ; + +addMinusTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + multdivmodTerm[$RootLevel, $ExpOpCount] + ( + ( + L1:"\+" multdivmodTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrAdd AObj(L1->getLine()); >> + ) + | + ( + L2:"\-" multdivmodTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrSubtract SObj(L2->getLine()); >> + ) + )* + ; + +multdivmodTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + castTerm[$RootLevel, $ExpOpCount] + ( + ( + L1:"\*" castTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrMultiply MObj(L1->getLine()); >> + ) + | + ( + L2:"/" castTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrDivide DObj(L2->getLine()); >> + ) + | + ( + L3:"%" castTerm[$RootLevel, $ExpOpCount] << $ExpOpCount++; CIfrModulo MObj(L3->getLine()); >> + ) + )* + ; + +castTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + << UINT8 CastType = 0xFF; >> + ( + L:"\(" + ( + Boolean << CastType = 0; >> + | Uint64 << CastType = 1; >> + | Uint32 << CastType = 1; >> + | Uint16 << CastType = 1; >> + | Uint8 << CastType = 1; >> + ) + "\)" + )* + atomTerm[$RootLevel, $ExpOpCount] + << + switch (CastType) { + case 0: { CIfrToBoolean TBObj(L->getLine()); $ExpOpCount++; } break; + case 1: { CIfrToUint TUObj(L->getLine()); $ExpOpCount++; } break; + } + >> + ; + +atomTerm [UINT32 & RootLevel, UINT32 & ExpOpCount]: + vfrExpressionCatenate[$RootLevel, $ExpOpCount] + | vfrExpressionMatch[$RootLevel, $ExpOpCount] + | vfrExpressionMatch2[$RootLevel, $ExpOpCount] + | vfrExpressionParen[$RootLevel, $ExpOpCount] + | vfrExpressionBuildInFunction[$RootLevel, $ExpOpCount] + | vfrExpressionConstant[$RootLevel, $ExpOpCount] + | vfrExpressionUnaryOp[$RootLevel, $ExpOpCount] + | vfrExpressionTernaryOp[$RootLevel, $ExpOpCount] + | vfrExpressionMap[$RootLevel, $ExpOpCount] + | ( + L:NOT + atomTerm[$RootLevel, $ExpOpCount] << { CIfrNot NObj(L->getLine()); $ExpOpCount++; } >> + ) + ; + +vfrExpressionCatenate [UINT32 & RootLevel, UINT32 & ExpOpCount]: + L:Catenate + "\(" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" << { CIfrCatenate CObj(L->getLine()); $ExpOpCount++; } >> + ; + +vfrExpressionMatch [UINT32 & RootLevel, UINT32 & ExpOpCount]: + L:Match + "\(" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" << { CIfrMatch MObj(L->getLine()); $ExpOpCount++; } >> + ; + +vfrExpressionMatch2 [UINT32 & RootLevel, UINT32 & ExpOpCount]: + << + EFI_GUID Guid; + >> + L:Match2 + "\(" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + guidDefinition[Guid] + "\)" << { CIfrMatch2 M2Obj(L->getLine(), &Guid); $ExpOpCount++; } >> + ; + +vfrExpressionParen [UINT32 & RootLevel, UINT32 & ExpOpCount]: + "\(" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" + ; + +vfrExpressionBuildInFunction [UINT32 & RootLevel, UINT32 & ExpOpCount] : + dupExp[$RootLevel, $ExpOpCount] + | vareqvalExp[$RootLevel, $ExpOpCount] //Compatible for Framework vareqval + | ideqvalExp[$RootLevel, $ExpOpCount] + | ideqidExp[$RootLevel, $ExpOpCount] + | ideqvallistExp[$RootLevel, $ExpOpCount] + | questionref1Exp[$RootLevel, $ExpOpCount] + | rulerefExp[$RootLevel, $ExpOpCount] + | stringref1Exp[$RootLevel, $ExpOpCount] + | pushthisExp[$RootLevel, $ExpOpCount] + | securityExp[$RootLevel, $ExpOpCount] + | getExp[$RootLevel, $ExpOpCount] + ; + +dupExp [UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:Dup << { CIfrDup DObj(L->getLine()); _SAVE_OPHDR_COND(DObj, ($ExpOpCount == 0), L->getLine()); $ExpOpCount++; } >> + ; + +vareqvalExp [UINT32 & RootLevel, UINT32 & ExpOpCount] : + << + EFI_QUESTION_ID QId; + UINT32 Mask; + UINT16 ConstVal; + CHAR8 *VarIdStr; + UINT32 LineNo; + EFI_VFR_RETURN_CODE VfrReturnCode = VFR_RETURN_SUCCESS; + EFI_VARSTORE_ID VarStoreId = EFI_VARSTORE_ID_INVALID; + >> + L:VarEqVal << + _PCATCH (VFR_RETURN_UNSUPPORTED, L); + >> + VK:Var + OpenParen + VN:Number << + VarIdStr = NULL; _STRCAT(&VarIdStr, VK->getText()); _STRCAT(&VarIdStr, VN->getText()); + VfrReturnCode = gCVfrDataStorage.GetVarStoreId (VarIdStr, &VarStoreId); + if (VfrReturnCode == VFR_RETURN_UNDEFINED) { + _PCATCH (gCVfrDataStorage.DeclareEfiVarStore ( + VarIdStr, + &mFormsetGuid, + _STOSID(VN->getText(), VN->getLine()), + 0x2, //default type is UINT16 + FALSE + ), VN); + } else { + _PCATCH (VfrReturnCode, VN); + } + mCVfrQuestionDB.GetQuestionId (NULL, VarIdStr, QId, Mask); + LineNo = GET_LINENO(VN); + >> + CloseParen + ( + ( + "==" + V1:Number << ConstVal = _STOU16(V1->getText(), V1->getLine()); >> + << + if (Mask == 0) { + CIfrEqIdVal EIVObj (L->getLine()); + _SAVE_OPHDR_COND (EIVObj, ($ExpOpCount == 0), L->getLine()); + EIVObj.SetQuestionId (QId, VarIdStr, LineNo); + EIVObj.SetValue (ConstVal); + $ExpOpCount++; + } else { + IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, EQUAL); + } + >> + ) + | + ( + "<=" + V2:Number << ConstVal = _STOU16(V2->getText(), V2->getLine()); >> + << IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, LESS_EQUAL); >> + ) + | + ( + "<" + V3:Number << ConstVal = _STOU16(V3->getText(), V3->getLine()); >> + << IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, LESS_THAN); >> + ) + | + ( + ">=" + V4:Number << ConstVal = _STOU16(V4->getText(), V4->getLine()); >> + << IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, GREATER_EQUAL); >> + ) + | + ( + ">" + V5:Number << ConstVal = _STOU16(V5->getText(), V5->getLine()); >> + << IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, GREATER_THAN); >> + ) + ) + << + if (VarIdStr != NULL) { + delete[] VarIdStr; + VarIdStr = NULL; + } + >> + ; + +ideqvalExp [UINT32 & RootLevel, UINT32 & ExpOpCount] : + << + EFI_QUESTION_ID QId; + UINT32 Mask; + UINT16 ConstVal; + CHAR8 *VarIdStr; + UINT32 LineNo; + >> + L:IdEqVal + vfrQuestionDataFieldName[QId, Mask, VarIdStr, LineNo] + ( + ( + "==" + V1:Number << ConstVal = _STOU16(V1->getText(), V1->getLine()); >> + << + if (Mask == 0) { + CIfrEqIdVal EIVObj (L->getLine()); + _SAVE_OPHDR_COND (EIVObj, ($ExpOpCount == 0), L->getLine()); + EIVObj.SetQuestionId (QId, VarIdStr, LineNo); + EIVObj.SetValue (ConstVal); + $ExpOpCount++; + } else { + IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, EQUAL); + } + >> + ) + | + ( + "<=" + V2:Number << ConstVal = _STOU16(V2->getText(), V2->getLine()); >> + << IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, LESS_EQUAL); >> + ) + | + ( + "<" + V3:Number << ConstVal = _STOU16(V3->getText(), V3->getLine()); >> + << IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, LESS_THAN); >> + ) + | + ( + ">=" + V4:Number << ConstVal = _STOU16(V4->getText(), V4->getLine()); >> + << IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, GREATER_EQUAL); >> + ) + | + ( + ">" + V5:Number << ConstVal = _STOU16(V5->getText(), V5->getLine()); >> + << IdEqValDoSpecial ($ExpOpCount, L->getLine(), QId, VarIdStr, Mask, ConstVal, GREATER_THAN); >> + ) + ) + << + if (VarIdStr != NULL) { + delete[] VarIdStr; + VarIdStr = NULL; + } + >> + ; + +ideqidExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + << + EFI_QUESTION_ID QId[2]; + UINT32 Mask[2]; + CHAR8 *VarIdStr[2]; + UINT32 LineNo[2]; + >> + L:IdEqId + vfrQuestionDataFieldName[QId[0], Mask[0], VarIdStr[0], LineNo[0]] + ( + ( + "==" + vfrQuestionDataFieldName[QId[1], Mask[1], VarIdStr[1], LineNo[1]] + << + if (Mask[0] & Mask[1]) { + IdEqIdDoSpecial ($ExpOpCount, L->getLine(), QId[0], VarIdStr[0], Mask[0], QId[1], VarIdStr[1], Mask[1], EQUAL); + } else { + CIfrEqIdId EIIObj(L->getLine()); + _SAVE_OPHDR_COND (EIIObj, ($ExpOpCount == 0), L->getLine()); + EIIObj.SetQuestionId1 (QId[0], VarIdStr[0], LineNo[0]); + EIIObj.SetQuestionId2 (QId[1], VarIdStr[1], LineNo[1]); + $ExpOpCount++; + } + >> + ) + | + ( + "<=" + vfrQuestionDataFieldName[QId[1], Mask[1], VarIdStr[1], LineNo[1]] + << IdEqIdDoSpecial ($ExpOpCount, L->getLine(), QId[0], VarIdStr[0], Mask[0], QId[1], VarIdStr[1], Mask[1], LESS_EQUAL); >> + ) + | + ( + "<" + vfrQuestionDataFieldName[QId[1], Mask[1], VarIdStr[1], LineNo[1]] + << IdEqIdDoSpecial ($ExpOpCount, L->getLine(), QId[0], VarIdStr[0], Mask[0], QId[1], VarIdStr[1], Mask[1], LESS_THAN); >> + ) + | + ( + ">=" + vfrQuestionDataFieldName[QId[1], Mask[1], VarIdStr[1], LineNo[1]] + << IdEqIdDoSpecial ($ExpOpCount, L->getLine(), QId[0], VarIdStr[0], Mask[0], QId[1], VarIdStr[1], Mask[1], GREATER_EQUAL); >> + ) + | + ( + ">" + vfrQuestionDataFieldName[QId[1], Mask[1], VarIdStr[1], LineNo[1]] + << IdEqIdDoSpecial ($ExpOpCount, L->getLine(), QId[0], VarIdStr[0], Mask[0], QId[1], VarIdStr[1], Mask[1], GREATER_THAN); >> + ) + ) + << + if (VarIdStr[0] != NULL) { + delete[] VarIdStr[0]; + VarIdStr[0] = NULL; + } + if (VarIdStr[1] != NULL) { + delete[] VarIdStr[1]; + VarIdStr[1] = NULL; + } + >> + ; + +ideqvallistExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + << + UINT16 ListLen = 0; + EFI_QUESTION_ID QId; + UINT32 Mask; + UINT16 ValueList[EFI_IFR_MAX_LENGTH] = {0,}; + CHAR8 *VarIdStr; + UINT32 LineNo; + >> + L:IdEqValList + vfrQuestionDataFieldName[QId, Mask, VarIdStr, LineNo] + "==" + ( + V:Number << ValueList[ListLen] = _STOU16(V->getText(), V->getLine()); ListLen++; >> + )+ + << + if (Mask != 0) { + IdEqListDoSpecial ($ExpOpCount, LineNo, QId, VarIdStr, Mask, ListLen, ValueList); + } else { + UINT16 Index; + CIfrEqIdList EILObj(L->getLine()); + if (QId != EFI_QUESTION_ID_INVALID) { + EILObj.SetQuestionId (QId, VarIdStr, LineNo); + } + EILObj.SetListLength (ListLen); + for (Index = 0; Index < ListLen; Index++) { + EILObj.SetValueList (Index, ValueList[Index]); + } + + EILObj.UpdateIfrBuffer(); + _SAVE_OPHDR_COND (EILObj, ($ExpOpCount == 0), L->getLine()); + + if (QId == EFI_QUESTION_ID_INVALID) { + EILObj.SetQuestionId (QId, VarIdStr, LineNo); + } + $ExpOpCount++; + } + if (VarIdStr != NULL) { + delete[] VarIdStr; + VarIdStr = NULL; + } + >> + ; + +questionref1Exp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + << + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + UINT32 BitMask; + CHAR8 *QName = NULL; + UINT32 LineNo = 0; + >> + L:QuestionRef + "\(" + ( + QN:StringIdentifier << + QName = QN->getText(); + LineNo = QN->getLine(); + mCVfrQuestionDB.GetQuestionId (QN->getText(), NULL, QId, BitMask); + >> + | ID:Number << QId = _STOQID(ID->getText(), ID->getLine()); >> + ) + "\)" + << + { CIfrQuestionRef1 QR1Obj(L->getLine()); _SAVE_OPHDR_COND (QR1Obj, ($ExpOpCount == 0), L->getLine()); QR1Obj.SetQuestionId (QId, QName, LineNo); } $ExpOpCount++; >> + ; + +rulerefExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:RuleRef + "\(" RN:StringIdentifier "\)" << { CIfrRuleRef RRObj(L->getLine()); _SAVE_OPHDR_COND (RRObj, ($ExpOpCount == 0), L->getLine()); RRObj.SetRuleId (mCVfrRulesDB.GetRuleId (RN->getText())); } $ExpOpCount++; >> + ; + +//****************************************************** +// PARSE: +// stringref (STR_FORM_SET_TITLE) +// +stringref1Exp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + << + EFI_STRING_ID RefStringId = EFI_STRING_ID_INVALID; + >> + L:StringRef + "\(" + ( + "STRING_TOKEN" + "\(" + S:Number << RefStringId = _STOSID(S->getText(), S->getLine()); >> + "\)" + | I:Number << RefStringId = _STOSID(I->getText(), I->getLine()); >> + ) + "\)" << { CIfrStringRef1 SR1Obj(L->getLine()); _SAVE_OPHDR_COND (SR1Obj, ($ExpOpCount == 0), L->getLine()); SR1Obj.SetStringId (RefStringId); $ExpOpCount++; } >> + ; + +pushthisExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:PushThis << { CIfrThis TObj(L->getLine()); _SAVE_OPHDR_COND (TObj, ($ExpOpCount == 0), L->getLine()); $ExpOpCount++; } >> + ; + +securityExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + << + EFI_GUID Guid; + >> + L:Security + "\(" guidDefinition[Guid] "\)" << { CIfrSecurity SObj(L->getLine()); _SAVE_OPHDR_COND (SObj, ($ExpOpCount == 0), L->getLine()); SObj.SetPermissions (&Guid); } $ExpOpCount++; >> + ; + +numericVarStoreType [UINT8 & VarType] : + "NUMERIC_SIZE_1" << $VarType = EFI_IFR_NUMERIC_SIZE_1; >> + | "NUMERIC_SIZE_2" << $VarType = EFI_IFR_NUMERIC_SIZE_2; >> + | "NUMERIC_SIZE_4" << $VarType = EFI_IFR_NUMERIC_SIZE_4; >> + | "NUMERIC_SIZE_8" << $VarType = EFI_IFR_NUMERIC_SIZE_8; >> + ; + +getExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + << + EFI_VARSTORE_INFO Info; + CHAR8 *VarIdStr = NULL; + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + UINT32 Mask = 0; + EFI_QUESION_TYPE QType = QUESTION_NORMAL; + UINT8 VarType = EFI_IFR_TYPE_UNDEFINED; + UINT32 VarSize = 0; + Info.mVarStoreId = 0; + >> + L:Get + "\(" + vfrStorageVarId[Info, VarIdStr, FALSE] + {"\|" FLAGS "=" numericVarStoreType [VarType] } + "\)" << + { + if (Info.mVarStoreId == 0) { + // support Date/Time question + mCVfrQuestionDB.GetQuestionId (NULL, VarIdStr, QId, Mask, &QType); + if (QId == EFI_QUESTION_ID_INVALID || Mask == 0 || QType == QUESTION_NORMAL) { + _PCATCH(VFR_RETURN_UNSUPPORTED, L->getLine(), "Get/Set opcode can't get the enough varstore information"); + } + if (QType == QUESTION_DATE) { + Info.mVarType = EFI_IFR_TYPE_DATE; + } else if (QType == QUESTION_TIME) { + Info.mVarType = EFI_IFR_TYPE_TIME; + } + switch (Mask) { + case DATE_YEAR_BITMASK: + Info.mInfo.mVarOffset = 0; + break; + case DATE_DAY_BITMASK: + Info.mInfo.mVarOffset = 3; + break; + case TIME_HOUR_BITMASK: + Info.mInfo.mVarOffset = 0; + break; + case TIME_MINUTE_BITMASK: + Info.mInfo.mVarOffset = 1; + break; + case TIME_SECOND_BITMASK: + Info.mInfo.mVarOffset = 2; + break; + default: + _PCATCH(VFR_RETURN_UNSUPPORTED, L->getLine(), "Get/Set opcode can't get the enough varstore information"); + break; + } + } else { + if ((gCVfrDataStorage.GetVarStoreType(Info.mVarStoreId) == EFI_VFR_VARSTORE_NAME) && (VarType == EFI_IFR_TYPE_UNDEFINED)) { + _PCATCH(VFR_RETURN_UNSUPPORTED, L->getLine(), "Get/Set opcode don't support name string"); + } + if (VarType != EFI_IFR_TYPE_UNDEFINED) { + Info.mVarType = VarType; + _PCATCH(gCVfrVarDataTypeDB.GetDataTypeSize (Info.mVarType, &VarSize), L->getLine(), "Get/Set opcode can't get var type size"); + Info.mVarTotalSize = VarSize; + } + _PCATCH(gCVfrVarDataTypeDB.GetDataTypeSize (Info.mVarType, &VarSize), L->getLine(), "Get/Set opcode can't get var type size"); + if (VarSize != Info.mVarTotalSize) { + _PCATCH(VFR_RETURN_UNSUPPORTED, L->getLine(), "Get/Set opcode don't support data array"); + } + } + CIfrGet GObj(L->getLine()); + _SAVE_OPHDR_COND (GObj, ($ExpOpCount == 0), L->getLine()); + GObj.SetVarInfo (&Info); + delete[] VarIdStr; + $ExpOpCount++; + } + >> + ; + +vfrExpressionConstant[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L1:True << CIfrTrue TObj(L1->getLine()); _SAVE_OPHDR_COND (TObj, ($ExpOpCount == 0), L1->getLine()); $ExpOpCount++; >> + | L2:False << CIfrFalse FObj(L2->getLine()); _SAVE_OPHDR_COND (FObj, ($ExpOpCount == 0), L2->getLine()); $ExpOpCount++; >> + | L3:One << CIfrOne OObj(L3->getLine()); _SAVE_OPHDR_COND (OObj, ($ExpOpCount == 0), L3->getLine()); $ExpOpCount++; >> + | L4:Ones << CIfrOnes OObj(L4->getLine()); _SAVE_OPHDR_COND (OObj, ($ExpOpCount == 0), L4->getLine()); $ExpOpCount++; >> + | L5:Zero << CIfrZero ZObj(L5->getLine()); _SAVE_OPHDR_COND (ZObj, ($ExpOpCount == 0), L5->getLine()); $ExpOpCount++; >> + | L6:Undefined << CIfrUndefined UObj(L6->getLine()); _SAVE_OPHDR_COND (UObj, ($ExpOpCount == 0), L6->getLine()); $ExpOpCount++; >> + | L7:Version << CIfrVersion VObj(L7->getLine()); _SAVE_OPHDR_COND (VObj, ($ExpOpCount == 0), L7->getLine()); $ExpOpCount++; >> + | V:Number << CIfrUint64 U64Obj(V->getLine()); U64Obj.SetValue (_STOU64(V->getText(), V->getLine())); _SAVE_OPHDR_COND (U64Obj, ($ExpOpCount == 0), V->getLine()); $ExpOpCount++; >> + ; + +vfrExpressionUnaryOp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + lengthExp[$RootLevel, $ExpOpCount] + | bitwisenotExp[$RootLevel, $ExpOpCount] + | question23refExp[$RootLevel, $ExpOpCount] + | stringref2Exp[$RootLevel, $ExpOpCount] + | toboolExp[$RootLevel, $ExpOpCount] + | tostringExp[$RootLevel, $ExpOpCount] + | unintExp[$RootLevel, $ExpOpCount] + | toupperExp[$RootLevel, $ExpOpCount] + | tolwerExp[$RootLevel, $ExpOpCount] + | setExp[$RootLevel, $ExpOpCount] + ; + +lengthExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:Length + "\(" vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] "\)" + << { CIfrLength LObj(L->getLine()); $ExpOpCount++; } >> + ; + +bitwisenotExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:BitWiseNot + "\(" vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] "\)" + << { CIfrBitWiseNot BWNObj(L->getLine()); $ExpOpCount++; } >> + ; + +question23refExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + << + UINT8 Type = 0x1; + EFI_STRING_ID DevPath = EFI_STRING_ID_INVALID; + EFI_GUID Guid = {0,}; + >> + L:QuestionRefVal + "\(" + { + DevicePath "=" "STRING_TOKEN" "\(" S:Number "\)" "," << Type = 0x2; DevPath = _STOSID(S->getText(), S->getLine()); >> + } + { + Uuid "=" guidDefinition[Guid] "," << Type = 0x3; >> + } + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" + << + switch (Type) { + case 0x1: {CIfrQuestionRef2 QR2Obj(L->getLine()); _SAVE_OPHDR_COND (QR2Obj, ($ExpOpCount == 0), L->getLine()); break;} + case 0x2: {CIfrQuestionRef3_2 QR3_2Obj(L->getLine()); _SAVE_OPHDR_COND (QR3_2Obj, ($ExpOpCount == 0), L->getLine()); QR3_2Obj.SetDevicePath (DevPath); break;} + case 0x3: {CIfrQuestionRef3_3 QR3_3Obj(L->getLine()); _SAVE_OPHDR_COND (QR3_3Obj, ($ExpOpCount == 0), L->getLine()); QR3_3Obj.SetDevicePath (DevPath); QR3_3Obj.SetGuid (&Guid); break;} + } + $ExpOpCount++; + >> + ; + +stringref2Exp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:StringRefVal + "\(" vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] "\)" + << { CIfrStringRef2 SR2Obj(L->getLine()); $ExpOpCount++; } >> + ; + +toboolExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:BoolVal + "\(" vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] "\)" + << { CIfrToBoolean TBObj(L->getLine()); $ExpOpCount++; } >> + ; + +tostringExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + << UINT8 Fmt = 0; >> + L:StringVal + { + Format "=" F:Number "," << Fmt = _STOU8(F->getText(), F->getLine()); >> + } + "\(" vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] "\)" + << { CIfrToString TSObj(L->getLine()); TSObj.SetFormat (Fmt); $ExpOpCount++; } >> + ; + +unintExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:UnIntVal + "\(" vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] "\)" + << { CIfrToUint TUObj(L->getLine()); $ExpOpCount++; } >> + ; + +toupperExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:ToUpper + "\(" vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] "\)" + << { CIfrToUpper TUObj(L->getLine()); $ExpOpCount++; } >> + ; + +tolwerExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:ToLower + "\(" vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] "\)" + << { CIfrToLower TLObj(L->getLine()); $ExpOpCount++; } >> + ; + +setExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + << + EFI_VARSTORE_INFO Info; + CHAR8 *VarIdStr = NULL; + EFI_QUESTION_ID QId = EFI_QUESTION_ID_INVALID; + UINT32 Mask = 0; + EFI_QUESION_TYPE QType = QUESTION_NORMAL; + UINT8 VarType = EFI_IFR_TYPE_UNDEFINED; + UINT32 VarSize = 0; + Info.mVarStoreId = 0; + >> + L:Set + "\(" + vfrStorageVarId[Info, VarIdStr, FALSE] + {"\|" FLAG "=" numericVarStoreType [VarType] } + "," vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" + << + { + if (Info.mVarStoreId == 0) { + // support Date/Time question + mCVfrQuestionDB.GetQuestionId (NULL, VarIdStr, QId, Mask, &QType); + if (QId == EFI_QUESTION_ID_INVALID || Mask == 0 || QType == QUESTION_NORMAL) { + _PCATCH(VFR_RETURN_UNSUPPORTED, L->getLine(), "Get/Set opcode can't get the enough varstore information"); + } + if (QType == QUESTION_DATE) { + Info.mVarType = EFI_IFR_TYPE_DATE; + } else if (QType == QUESTION_TIME) { + Info.mVarType = EFI_IFR_TYPE_TIME; + } + switch (Mask) { + case DATE_YEAR_BITMASK: + Info.mInfo.mVarOffset = 0; + break; + case DATE_DAY_BITMASK: + Info.mInfo.mVarOffset = 3; + break; + case TIME_HOUR_BITMASK: + Info.mInfo.mVarOffset = 0; + break; + case TIME_MINUTE_BITMASK: + Info.mInfo.mVarOffset = 1; + break; + case TIME_SECOND_BITMASK: + Info.mInfo.mVarOffset = 2; + break; + default: + _PCATCH(VFR_RETURN_UNSUPPORTED, L->getLine(), "Get/Set opcode can't get the enough varstore information"); + break; + } + } else { + if ((gCVfrDataStorage.GetVarStoreType(Info.mVarStoreId) == EFI_VFR_VARSTORE_NAME) && (VarType == EFI_IFR_TYPE_UNDEFINED)) { + _PCATCH(VFR_RETURN_UNSUPPORTED, L->getLine(), "Get/Set opcode don't support name string"); + } + if (VarType != EFI_IFR_TYPE_UNDEFINED) { + Info.mVarType = VarType; + _PCATCH(gCVfrVarDataTypeDB.GetDataTypeSize (Info.mVarType, &VarSize), L->getLine(), "Get/Set opcode can't get var type size"); + Info.mVarTotalSize = VarSize; + } + _PCATCH(gCVfrVarDataTypeDB.GetDataTypeSize (Info.mVarType, &VarSize), L->getLine(), "Get/Set opcode can't get var type size"); + if (VarSize != Info.mVarTotalSize) { + _PCATCH(VFR_RETURN_UNSUPPORTED, L->getLine(), "Get/Set opcode don't support data array"); + } + } + CIfrSet TSObj(L->getLine()); + TSObj.SetVarInfo (&Info); + delete[] VarIdStr; + $ExpOpCount++; + } + >> + ; + +vfrExpressionTernaryOp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + conditionalExp[$RootLevel, $ExpOpCount] + | findExp[$RootLevel, $ExpOpCount] + | midExp[$RootLevel, $ExpOpCount] + | tokenExp[$RootLevel, $ExpOpCount] + | spanExp[$RootLevel, $ExpOpCount] + ; + +#token Cond("cond") "cond" +#token Find("find") "find" +#token Mid("mid") "mid" +#token Tok("token") "token" +#token Span("span") "span" + +conditionalExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:Cond "\(" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "?" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + ":" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" << { CIfrConditional CObj(L->getLine()); $ExpOpCount++; } >> + ; + +findExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + << UINT8 Format; >> + L:Find "\(" + findFormat[Format] ( "\|" findFormat[Format] )* + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" << { CIfrFind FObj(L->getLine()); FObj.SetFormat (Format); $ExpOpCount++; } >> + ; + +findFormat [UINT8 & Format] : + "SENSITIVE" << $Format = 0x00; >> + | "INSENSITIVE" << $Format = 0x01; >> + ; + +midExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:Mid "\(" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" << { CIfrMid MObj(L->getLine()); $ExpOpCount++; } >> + ; + +tokenExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + L:Tok "\(" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" << { CIfrToken TObj(L->getLine()); $ExpOpCount++; } >> + ; + +spanExp[UINT32 & RootLevel, UINT32 & ExpOpCount] : + << UINT8 Flags = 0; >> + S:Span "\(" + FLAGS "=" spanFlags[Flags] ( "\|" spanFlags[Flags] )* + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "," + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + "\)" << { CIfrSpan SObj(S->getLine()); SObj.SetFlags(Flags); $ExpOpCount++; } >> + ; + +vfrExpressionMap [UINT32 & RootLevel, UINT32 & ExpOpCount]: + L:Map + "\(" + vfrStatementExpressionSub[$RootLevel + 1, $ExpOpCount] + ":" << { CIfrMap MObj(L->getLine()); } >> + ( + vfrStatementExpression[0] + "," + vfrStatementExpression[0] + ";" + ) * + E:"\)" << { CIfrEnd EObj; EObj.SetLineNo(E->getLine()); $ExpOpCount++; } >> + ; + +spanFlags [UINT8 & Flags] : + N:Number << $Flags |= _STOU8(N->getText(), N->getLine()); >> + | "LAST_NON_MATCH" << $Flags |= 0x00; >> + | "FIRST_NON_MATCH" << $Flags |= 0x01; >> + ; + +#token StringIdentifier("string identifier") "[A-Za-z_][A-Za-z_0-9]*" +#token Number("numeric value") "(0x[0-9A-Fa-f]+) | [0-9]+" + +//****************************************************************************** +// +// Parser class definition. +// +class EfiVfrParser { +<< +private: + UINT8 mParserStatus; + BOOLEAN mConstantOnlyInExpression; + + CVfrQuestionDB mCVfrQuestionDB; + CVfrRulesDB mCVfrRulesDB; + + CIfrOpHeader * mCIfrOpHdr[MAX_IFR_EXPRESSION_DEPTH]; + UINT32 mCIfrOpHdrLineNo[MAX_IFR_EXPRESSION_DEPTH]; + UINT8 mCIfrOpHdrIndex; + VOID _SAVE_OPHDR_COND (IN CIfrOpHeader &, IN BOOLEAN, UINT32 LineNo = 0); + VOID _CLEAR_SAVED_OPHDR (VOID); + VOID _INIT_OPHDR_COND (VOID); + BOOLEAN _SET_SAVED_OPHDR_SCOPE (VOID); + + + EFI_VARSTORE_INFO mCurrQestVarInfo; + EFI_GUID *mOverrideClassGuid; + CHAR8* mLastFormEndAddr; + +// +// Whether the question already has default value. +// + UINT16 mUsedDefaultArray[EFI_IFR_MAX_DEFAULT_TYPE]; + UINT16 mUsedDefaultCount; + + EFI_GUID mFormsetGuid; + + VOID _CRT_OP (IN BOOLEAN); + + VOID _SAVE_CURRQEST_VARINFO (IN EFI_VARSTORE_INFO &); + EFI_VARSTORE_INFO & _GET_CURRQEST_VARTINFO (VOID); + + UINT8 _GET_CURRQEST_DATATYPE (); + UINT32 _GET_CURRQEST_VARSIZE (); + UINT32 _GET_CURRQEST_ARRAY_SIZE(); + VOID CheckDuplicateDefaultValue (IN EFI_DEFAULT_ID, IN ANTLRTokenPtr); + +public: + VOID _PCATCH (IN INTN, IN INTN, IN ANTLRTokenPtr, IN CONST CHAR8 *); + VOID _PCATCH (IN EFI_VFR_RETURN_CODE); + VOID _PCATCH (IN EFI_VFR_RETURN_CODE, IN ANTLRTokenPtr); + VOID _PCATCH (IN EFI_VFR_RETURN_CODE, IN UINT32); + VOID _PCATCH (IN EFI_VFR_RETURN_CODE, IN UINT32, IN CONST CHAR8 *); + + VOID syn (ANTLRAbstractToken *, ANTLRChar *, SetWordType *, ANTLRTokenType, INT32); + + CHAR8* TrimHex (IN CHAR8 *, OUT BOOLEAN *); + CHAR8* _U32TOS (IN UINT32); + UINT8 _STOU8 (IN CHAR8 *, IN UINT32); + UINT16 _STOU16 (IN CHAR8 *, IN UINT32); + UINT32 _STOU32 (IN CHAR8 *, IN UINT32); + UINT64 _STOU64 (IN CHAR8 *, IN UINT32); + EFI_HII_DATE _STOD (IN CHAR8 *, IN CHAR8 *, IN CHAR8 *, IN UINT32); + EFI_HII_TIME _STOT (IN CHAR8 *, IN CHAR8 *, IN CHAR8 *, IN UINT32); + EFI_HII_REF _STOR (IN CHAR8 *, IN CHAR8 *, IN EFI_GUID *, IN CHAR8 *, IN UINT32); + + EFI_STRING_ID _STOSID (IN CHAR8 *, IN UINT32); + EFI_FORM_ID _STOFID (IN CHAR8 *, IN UINT32); + EFI_QUESTION_ID _STOQID (IN CHAR8 *, IN UINT32); + + VOID _STRCAT (IN OUT CHAR8 **, IN CONST CHAR8 *); + + VOID _DeclareDefaultLinearVarStore (IN UINT32); + VOID _DeclareStandardDefaultStorage (IN UINT32); + + VOID AssignQuestionKey (IN CIfrQuestionHeader &, IN ANTLRTokenPtr); + + VOID ConvertIdExpr (IN UINT32 &, IN UINT32, IN EFI_QUESTION_ID, IN CHAR8 *, IN UINT32); + VOID IdEqValDoSpecial (IN UINT32 &, IN UINT32, IN EFI_QUESTION_ID, IN CHAR8 *, IN UINT32, IN UINT16, IN EFI_COMPARE_TYPE); + VOID IdEqIdDoSpecial (IN UINT32 &, IN UINT32, IN EFI_QUESTION_ID, IN CHAR8 *, IN UINT32, IN EFI_QUESTION_ID, IN CHAR8 *, IN UINT32, IN EFI_COMPARE_TYPE); + VOID IdEqListDoSpecial (IN UINT32 &, IN UINT32, IN EFI_QUESTION_ID, IN CHAR8 *, IN UINT32, IN UINT16, IN UINT16 *); + VOID SetOverrideClassGuid (IN EFI_GUID *); +>> +} + +<< +VOID +EfiVfrParser::_SAVE_OPHDR_COND ( + IN CIfrOpHeader &OpHdr, + IN BOOLEAN Cond, + IN UINT32 LineNo + ) +{ + if (Cond == TRUE) { + if (mCIfrOpHdr[mCIfrOpHdrIndex] != NULL) { + return ; + } + mCIfrOpHdr[mCIfrOpHdrIndex] = new CIfrOpHeader(OpHdr); + mCIfrOpHdrLineNo[mCIfrOpHdrIndex] = LineNo; + } +} + +VOID +EfiVfrParser::_INIT_OPHDR_COND ( + VOID + ) +{ + mCIfrOpHdr[mCIfrOpHdrIndex] = NULL; + mCIfrOpHdrLineNo[mCIfrOpHdrIndex] = 0; +} + +VOID +EfiVfrParser::_CLEAR_SAVED_OPHDR ( + VOID + ) +{ + if (mCIfrOpHdr[mCIfrOpHdrIndex] != NULL) { + delete mCIfrOpHdr[mCIfrOpHdrIndex]; + mCIfrOpHdr[mCIfrOpHdrIndex] = NULL; + } +} + +BOOLEAN +EfiVfrParser::_SET_SAVED_OPHDR_SCOPE ( + VOID + ) +{ + if (mCIfrOpHdr[mCIfrOpHdrIndex] != NULL) { + mCIfrOpHdr[mCIfrOpHdrIndex]->SetScope (1); + return TRUE; + } + + // + // IfrOpHdr is not set, FALSE is return. + // + return FALSE; +} + +VOID +EfiVfrParser::_CRT_OP ( + IN BOOLEAN Crt + ) +{ + gCreateOp = Crt; +} + +VOID +EfiVfrParser::_SAVE_CURRQEST_VARINFO ( + IN EFI_VARSTORE_INFO &Info + ) +{ + mCurrQestVarInfo = Info; +} + +EFI_VARSTORE_INFO & +EfiVfrParser::_GET_CURRQEST_VARTINFO ( + VOID + ) +{ + return mCurrQestVarInfo; +} + +UINT32 +EfiVfrParser::_GET_CURRQEST_ARRAY_SIZE ( + VOID + ) +{ + UINT8 Size = 1; + + switch (mCurrQestVarInfo.mVarType) { + case EFI_IFR_TYPE_NUM_SIZE_8: + Size = 1; + break; + + case EFI_IFR_TYPE_NUM_SIZE_16: + Size = 2; + break; + + case EFI_IFR_TYPE_NUM_SIZE_32: + Size = 4; + break; + + case EFI_IFR_TYPE_NUM_SIZE_64: + Size = 8; + break; + + default: + break; + } + + return (mCurrQestVarInfo.mVarTotalSize / Size); +} + +UINT8 +EfiVfrParser::_GET_CURRQEST_DATATYPE ( + VOID + ) +{ + return mCurrQestVarInfo.mVarType; +} + +UINT32 +EfiVfrParser::_GET_CURRQEST_VARSIZE ( + VOID + ) +{ + return mCurrQestVarInfo.mVarTotalSize; +} + +VOID +EfiVfrParser::_PCATCH ( + IN INTN ReturnCode, + IN INTN ExpectCode, + IN ANTLRTokenPtr Tok, + IN CONST CHAR8 *ErrorMsg + ) +{ + if (ReturnCode != ExpectCode) { + mParserStatus++; + gCVfrErrorHandle.PrintMsg (Tok->getLine(), Tok->getText(), "Error", ErrorMsg); + } +} + +VOID +EfiVfrParser::_PCATCH ( + IN EFI_VFR_RETURN_CODE ReturnCode + ) +{ + mParserStatus = mParserStatus + gCVfrErrorHandle.HandleError (ReturnCode); +} + +VOID +EfiVfrParser::_PCATCH ( + IN EFI_VFR_RETURN_CODE ReturnCode, + IN ANTLRTokenPtr Tok + ) +{ + mParserStatus = mParserStatus + gCVfrErrorHandle.HandleError (ReturnCode, Tok->getLine(), Tok->getText()); +} + +VOID +EfiVfrParser::_PCATCH ( + IN EFI_VFR_RETURN_CODE ReturnCode, + IN UINT32 LineNum + ) +{ + mParserStatus = mParserStatus + gCVfrErrorHandle.HandleError (ReturnCode, LineNum); +} + +VOID +EfiVfrParser::_PCATCH ( + IN EFI_VFR_RETURN_CODE ReturnCode, + IN UINT32 LineNum, + IN CONST CHAR8 *ErrorMsg + ) +{ + mParserStatus = mParserStatus + gCVfrErrorHandle.HandleError (ReturnCode, LineNum, (CHAR8 *) ErrorMsg); +} + +VOID +EfiVfrParser::syn ( + ANTLRAbstractToken *Tok, + ANTLRChar *Egroup, + SetWordType *Eset, + ANTLRTokenType ETok, + INT32 Huh + ) +{ + gCVfrErrorHandle.HandleError (VFR_RETURN_MISMATCHED, Tok->getLine(), Tok->getText()); + + mParserStatus += 1; +} + +CHAR8 * +EfiVfrParser::TrimHex ( + IN CHAR8 *Str, + OUT BOOLEAN *IsHex + ) +{ + *IsHex = FALSE; + + while (*Str && *Str == ' ') { + Str++; + } + while (*Str && *Str == '0') { + Str++; + } + if (*Str && (*Str == 'x' || *Str == 'X')) { + Str++; + *IsHex = TRUE; + } + + return Str; +} + +CHAR8 * +EfiVfrParser::_U32TOS ( + IN UINT32 Value + ) +{ + CHAR8 *Str; + Str = new CHAR8[20]; + sprintf (Str, "%d", Value); + return Str; +} + +UINT8 +EfiVfrParser::_STOU8 ( + IN CHAR8 *Str, + IN UINT32 LineNum + ) +{ + BOOLEAN IsHex; + UINT8 Value; + CHAR8 c; + + UINT8 PreviousValue; + CHAR8 *OrigString = Str; + CHAR8 ErrorMsg[100]; + + Str = TrimHex (Str, &IsHex); + for (Value = 0; (c = *Str) != '\0'; Str++) { + PreviousValue = Value; + (IsHex == TRUE) ? (Value <<= 4) : (Value *= 10); + + if ((IsHex == TRUE) && (c >= 'a') && (c <= 'f')) { + Value += (c - 'a' + 10); + } + if ((IsHex == TRUE) && (c >= 'A') && (c <= 'F')) { + Value += (c - 'A' + 10); + } + if (c >= '0' && c <= '9') { + Value += (c - '0'); + } + if((IsHex && ((Value/16) != PreviousValue)) || (!IsHex && ((Value/10) != PreviousValue))) { + sprintf(ErrorMsg, "Overflow: Value %s is too large to store in a UINT8", OrigString); + mParserStatus = mParserStatus + gCVfrErrorHandle.HandleError (VFR_RETURN_STRING_TO_UINT_OVERFLOW, LineNum, ErrorMsg); + } + } + + return Value; +} + +UINT16 +EfiVfrParser::_STOU16 ( + IN CHAR8 *Str, + IN UINT32 LineNum + ) +{ + BOOLEAN IsHex; + UINT16 Value; + CHAR8 c; + + UINT16 PreviousValue; + CHAR8 *OrigString = Str; + CHAR8 ErrorMsg[100]; + + Str = TrimHex (Str, &IsHex); + for (Value = 0; (c = *Str) != '\0'; Str++) { + PreviousValue = Value; + (IsHex == TRUE) ? (Value <<= 4) : (Value *= 10); + + if ((IsHex == TRUE) && (c >= 'a') && (c <= 'f')) { + Value += (c - 'a' + 10); + } + if ((IsHex == TRUE) && (c >= 'A') && (c <= 'F')) { + Value += (c - 'A' + 10); + } + if (c >= '0' && c <= '9') { + Value += (c - '0'); + } + if((IsHex && ((Value/16) != PreviousValue)) || (!IsHex && ((Value/10) != PreviousValue))) { + sprintf(ErrorMsg, "Overflow: Value %s is too large to store in a UINT16", OrigString); + mParserStatus = mParserStatus + gCVfrErrorHandle.HandleError (VFR_RETURN_STRING_TO_UINT_OVERFLOW, LineNum, ErrorMsg); + } + } + + return Value; +} + +UINT32 +EfiVfrParser::_STOU32 ( + IN CHAR8 *Str, + IN UINT32 LineNum + ) +{ + BOOLEAN IsHex; + UINT32 Value; + CHAR8 c; + + UINT32 PreviousValue; + CHAR8 *OrigString = Str; + CHAR8 ErrorMsg[100]; + + Str = TrimHex (Str, &IsHex); + for (Value = 0; (c = *Str) != '\0'; Str++) { + PreviousValue = Value; + (IsHex == TRUE) ? (Value <<= 4) : (Value *= 10); + + if ((IsHex == TRUE) && (c >= 'a') && (c <= 'f')) { + Value += (c - 'a' + 10); + } + if ((IsHex == TRUE) && (c >= 'A') && (c <= 'F')) { + Value += (c - 'A' + 10); + } + if (c >= '0' && c <= '9') { + Value += (c - '0'); + } + if((IsHex && ((Value/16) != PreviousValue)) || (!IsHex && ((Value/10) != PreviousValue ))) { + sprintf(ErrorMsg, "Overflow: Value %s is too large to store in a UINT32", OrigString); + mParserStatus = mParserStatus + gCVfrErrorHandle.HandleError (VFR_RETURN_STRING_TO_UINT_OVERFLOW, LineNum, ErrorMsg); + } + } + + return Value; +} + +UINT64 +EfiVfrParser::_STOU64 ( + IN CHAR8 *Str, + IN UINT32 LineNum + ) +{ + BOOLEAN IsHex; + UINT64 Value; + CHAR8 c; + UINT64 PreviousValue; + CHAR8 *OrigString = Str; + CHAR8 ErrorMsg[100]; + + Str = TrimHex (Str, &IsHex); + for (Value = 0; (c = *Str) != '\0'; Str++) { + PreviousValue = Value; + (IsHex == TRUE) ? (Value <<= 4) : (Value *= 10); + + if ((IsHex == TRUE) && (c >= 'a') && (c <= 'f')) { + Value += (c - 'a' + 10); + } + if ((IsHex == TRUE) && (c >= 'A') && (c <= 'F')) { + Value += (c - 'A' + 10); + } + if (c >= '0' && c <= '9') { + Value += (c - '0'); + } + if((IsHex && ((Value/16) != PreviousValue)) || ((!IsHex && (Value/10) != PreviousValue))) { + sprintf(ErrorMsg, "Overflow: Value %s is too large to store in a UINT64", OrigString); + mParserStatus = mParserStatus + gCVfrErrorHandle.HandleError (VFR_RETURN_STRING_TO_UINT_OVERFLOW, LineNum, ErrorMsg); + } + } + + return Value; +} + +EFI_HII_DATE +EfiVfrParser::_STOD ( + IN CHAR8 *Year, + IN CHAR8 *Month, + IN CHAR8 *Day, + IN UINT32 LineNum + ) +{ + EFI_HII_DATE Date; + + Date.Year = _STOU16 (Year, LineNum); + Date.Month = _STOU8 (Month, LineNum); + Date.Day = _STOU8 (Day, LineNum); + + return Date; +} + +EFI_HII_TIME +EfiVfrParser::_STOT ( + IN CHAR8 *Hour, + IN CHAR8 *Minute, + IN CHAR8 *Second, + IN UINT32 LineNum + ) +{ + EFI_HII_TIME Time; + + Time.Hour = _STOU8 (Hour, LineNum); + Time.Minute = _STOU8 (Minute, LineNum); + Time.Second = _STOU8 (Second, LineNum); + + return Time; +} + +EFI_STRING_ID +EfiVfrParser::_STOSID ( + IN CHAR8 *Str, + IN UINT32 LineNum + ) +{ + return (EFI_STRING_ID)_STOU16(Str, LineNum); +} + +EFI_FORM_ID +EfiVfrParser::_STOFID ( + IN CHAR8 *Str, + IN UINT32 LineNum + ) +{ + return (EFI_FORM_ID)_STOU16(Str, LineNum); +} + +EFI_QUESTION_ID +EfiVfrParser::_STOQID ( + IN CHAR8 *Str, + IN UINT32 LineNum + ) +{ + return (EFI_QUESTION_ID)_STOU16(Str, LineNum); +} + +VOID +EfiVfrParser::_STRCAT ( + IN OUT CHAR8 **Dest, + IN CONST CHAR8 *Src + ) +{ + CHAR8 *NewStr; + UINT32 Len; + + if ((Dest == NULL) || (Src == NULL)) { + return; + } + + Len = (*Dest == NULL) ? 0 : strlen (*Dest); + Len += strlen (Src); + if ((NewStr = new CHAR8[Len + 1]) == NULL) { + return; + } + NewStr[0] = '\0'; + if (*Dest != NULL) { + strcpy (NewStr, *Dest); + delete[] *Dest; + } + strcat (NewStr, Src); + + *Dest = NewStr; +} + +EFI_HII_REF +EfiVfrParser::_STOR ( + IN CHAR8 *QuestionId, + IN CHAR8 *FormId, + IN EFI_GUID *FormSetGuid, + IN CHAR8 *DevicePath, + IN UINT32 LineNum + ) +{ + EFI_HII_REF Ref; + UINT32 Index; + + memcpy (&Ref.FormSetGuid, FormSetGuid, sizeof (EFI_GUID)); + Ref.QuestionId = _STOQID (QuestionId, LineNum); + Ref.FormId = _STOFID (FormId, LineNum); + Ref.DevicePath = _STOSID (DevicePath, LineNum); + + return Ref; +} + +VOID +EfiVfrParser::_DeclareDefaultLinearVarStore ( + IN UINT32 LineNo + ) +{ + UINT32 Index; + CHAR8 **TypeNameList; + UINT32 ListSize; + CONST CHAR8 DateName[] = "Date"; + CONST CHAR8 TimeName[] = "Time"; + CONST CHAR8 DateType[] = "EFI_HII_DATE"; + CONST CHAR8 TimeType[] = "EFI_HII_TIME"; + + gCVfrVarDataTypeDB.GetUserDefinedTypeNameList (&TypeNameList, &ListSize); + + for (Index = 0; Index < ListSize; Index++) { + UINT32 Size; + EFI_VARSTORE_ID VarStoreId; + CIfrVarStore VSObj; + + VSObj.SetLineNo (LineNo); + gCVfrDataStorage.DeclareBufferVarStore ( + TypeNameList[Index], + &mFormsetGuid, + &gCVfrVarDataTypeDB, + TypeNameList[Index], + EFI_VARSTORE_ID_INVALID, + FALSE + ); + gCVfrDataStorage.GetVarStoreId(TypeNameList[Index], &VarStoreId, &mFormsetGuid); + VSObj.SetVarStoreId (VarStoreId); + gCVfrVarDataTypeDB.GetDataTypeSize(TypeNameList[Index], &Size); + VSObj.SetSize ((UINT16) Size); + VSObj.SetName (TypeNameList[Index]); + VSObj.SetGuid (&mFormsetGuid); + } + +// +// not required to declare Date and Time VarStore, +// because code to support old format Data and Time +// + if (gCVfrVarDataTypeDB.IsTypeNameDefined ((CHAR8 *) DateName) == FALSE) { + UINT32 Size; + EFI_VARSTORE_ID VarStoreId; + CIfrVarStore VSObj; + + VSObj.SetLineNo (LineNo); + gCVfrDataStorage.DeclareBufferVarStore ( + (CHAR8 *) DateName, + &mFormsetGuid, + &gCVfrVarDataTypeDB, + (CHAR8 *) DateType, + EFI_VARSTORE_ID_INVALID, + FALSE + ); + gCVfrDataStorage.GetVarStoreId((CHAR8 *) DateName, &VarStoreId, &mFormsetGuid); + VSObj.SetVarStoreId (VarStoreId); + gCVfrVarDataTypeDB.GetDataTypeSize((CHAR8 *) DateType, &Size); + VSObj.SetSize ((UINT16) Size); + VSObj.SetName ((CHAR8 *) DateName); + VSObj.SetGuid (&mFormsetGuid); + } + + if (gCVfrVarDataTypeDB.IsTypeNameDefined ((CHAR8 *) TimeName) == FALSE) { + UINT32 Size; + EFI_VARSTORE_ID VarStoreId; + CIfrVarStore VSObj; + + VSObj.SetLineNo (LineNo); + gCVfrDataStorage.DeclareBufferVarStore ( + (CHAR8 *) TimeName, + &mFormsetGuid, + &gCVfrVarDataTypeDB, + (CHAR8 *) TimeType, + EFI_VARSTORE_ID_INVALID, + FALSE + ); + gCVfrDataStorage.GetVarStoreId((CHAR8 *) TimeName, &VarStoreId, &mFormsetGuid); + VSObj.SetVarStoreId (VarStoreId); + gCVfrVarDataTypeDB.GetDataTypeSize((CHAR8 *) TimeType, &Size); + VSObj.SetSize ((UINT16) Size); + VSObj.SetName ((CHAR8 *) TimeName); + VSObj.SetGuid (&mFormsetGuid); + } +} + +VOID +EfiVfrParser::_DeclareStandardDefaultStorage ( + IN UINT32 LineNo + ) +{ + // + // Default Store is declared. + // + CIfrDefaultStore DSObj; + + gCVfrDefaultStore.RegisterDefaultStore (DSObj.GetObjBinAddr(), (CHAR8 *) "Standard Defaults", EFI_STRING_ID_INVALID, EFI_HII_DEFAULT_CLASS_STANDARD); + DSObj.SetLineNo (LineNo); + DSObj.SetDefaultName (EFI_STRING_ID_INVALID); + DSObj.SetDefaultId (EFI_HII_DEFAULT_CLASS_STANDARD); + + // + // Default MANUFACTURING Store is declared. + // + CIfrDefaultStore DSObjMF; + + gCVfrDefaultStore.RegisterDefaultStore (DSObjMF.GetObjBinAddr(), (CHAR8 *) "Standard ManuFacturing", EFI_STRING_ID_INVALID, EFI_HII_DEFAULT_CLASS_MANUFACTURING); + DSObjMF.SetLineNo (LineNo); + DSObjMF.SetDefaultName (EFI_STRING_ID_INVALID); + DSObjMF.SetDefaultId (EFI_HII_DEFAULT_CLASS_MANUFACTURING); +} + +VOID +EfiVfrParser::AssignQuestionKey ( + IN CIfrQuestionHeader &QHObj, + IN ANTLRTokenPtr KeyTok + ) +{ + UINT16 KeyValue; + + if (KeyTok == NULL) { + return; + } + + KeyValue = _STOU16 (KeyTok->getText(), KeyTok->getLine()); + + if (QHObj.FLAGS () & EFI_IFR_FLAG_CALLBACK) { + /* + * if the question is not CALLBACK ignore the key. + */ + _PCATCH(mCVfrQuestionDB.UpdateQuestionId (QHObj.QUESTION_ID(), KeyValue), KeyTok); + QHObj.SetQuestionId (KeyValue); + } +} + +VOID +EfiVfrParser::ConvertIdExpr ( + IN UINT32 &ExpOpCount, + IN UINT32 LineNo, + IN EFI_QUESTION_ID QId, + IN CHAR8 *VarIdStr, + IN UINT32 BitMask + ) +{ + CIfrQuestionRef1 QR1Obj(LineNo); + QR1Obj.SetQuestionId (QId, VarIdStr, LineNo); + _SAVE_OPHDR_COND (QR1Obj, (ExpOpCount == 0)); + + if (BitMask != 0) { + CIfrUint32 U32Obj(LineNo); + U32Obj.SetValue (BitMask); + + CIfrBitWiseAnd BWAObj(LineNo); + + CIfrUint8 U8Obj(LineNo); + switch (BitMask) { + case DATE_YEAR_BITMASK : U8Obj.SetValue (0); break; + case TIME_SECOND_BITMASK : U8Obj.SetValue (0x10); break; + case DATE_DAY_BITMASK : U8Obj.SetValue (0x18); break; + case TIME_HOUR_BITMASK : U8Obj.SetValue (0); break; + case TIME_MINUTE_BITMASK : U8Obj.SetValue (0x8); break; + } + + CIfrShiftRight SRObj(LineNo); + } + + ExpOpCount += 4; +} + +VOID +EfiVfrParser::IdEqValDoSpecial ( + IN UINT32 &ExpOpCount, + IN UINT32 LineNo, + IN EFI_QUESTION_ID QId, + IN CHAR8 *VarIdStr, + IN UINT32 BitMask, + IN UINT16 ConstVal, + IN EFI_COMPARE_TYPE CompareType + ) +{ + ConvertIdExpr (ExpOpCount, LineNo, QId, VarIdStr, BitMask); + + if (ConstVal > 0xFF) { + CIfrUint16 U16Obj(LineNo); + U16Obj.SetValue (ConstVal); + } else { + CIfrUint8 U8Obj(LineNo); + U8Obj.SetValue ((UINT8)ConstVal); + } + + switch (CompareType) { + case EQUAL : + { + CIfrEqual EObj(LineNo); + break; + } + case LESS_EQUAL : + { + CIfrLessEqual LEObj(LineNo); + break; + } + case LESS_THAN : + { + CIfrLessThan LTObj(LineNo); + break; + } + case GREATER_EQUAL : + { + CIfrGreaterEqual GEObj(LineNo); + break; + } + case GREATER_THAN : + { + CIfrGreaterThan GTObj(LineNo); + break; + } + } + + ExpOpCount += 2; +} + +VOID +EfiVfrParser::IdEqIdDoSpecial ( + IN UINT32 &ExpOpCount, + IN UINT32 LineNo, + IN EFI_QUESTION_ID QId1, + IN CHAR8 *VarId1Str, + IN UINT32 BitMask1, + IN EFI_QUESTION_ID QId2, + IN CHAR8 *VarId2Str, + IN UINT32 BitMask2, + IN EFI_COMPARE_TYPE CompareType + ) +{ + ConvertIdExpr (ExpOpCount, LineNo, QId1, VarId1Str, BitMask1); + ConvertIdExpr (ExpOpCount, LineNo, QId2, VarId2Str, BitMask2); + + switch (CompareType) { + case EQUAL : + { + CIfrEqual EObj(LineNo); + break; + } + case LESS_EQUAL : + { + CIfrLessEqual LEObj(LineNo); + break; + } + case LESS_THAN : + { + CIfrLessThan LTObj(LineNo); + break; + } + case GREATER_EQUAL : + { + CIfrGreaterEqual GEObj(LineNo); + break; + } + case GREATER_THAN : + { + CIfrGreaterThan GTObj(LineNo); + break; + } + } + + ExpOpCount++; +} + +VOID +EfiVfrParser::IdEqListDoSpecial ( + IN UINT32 &ExpOpCount, + IN UINT32 LineNo, + IN EFI_QUESTION_ID QId, + IN CHAR8 *VarIdStr, + IN UINT32 BitMask, + IN UINT16 ListLen, + IN UINT16 *ValueList + ) +{ + UINT16 Index; + + if (ListLen == 0) { + return; + } + + IdEqValDoSpecial (ExpOpCount, LineNo, QId, VarIdStr, BitMask, ValueList[0], EQUAL); + for (Index = 1; Index < ListLen; Index++) { + IdEqValDoSpecial (ExpOpCount, LineNo, QId, VarIdStr, BitMask, ValueList[Index], EQUAL); + CIfrOr OObj (LineNo); + ExpOpCount++; + } +} + +VOID +EfiVfrParser::SetOverrideClassGuid (IN EFI_GUID *OverrideClassGuid) +{ + mOverrideClassGuid = OverrideClassGuid; +} + +VOID +EfiVfrParser::CheckDuplicateDefaultValue ( + IN EFI_DEFAULT_ID DefaultId, + IN ANTLRTokenPtr Tok + ) +{ + UINT16 Index; + + for(Index = 0; Index < mUsedDefaultCount; Index++) { + if (mUsedDefaultArray[Index] == DefaultId) { + gCVfrErrorHandle.HandleWarning (VFR_WARNING_DEFAULT_VALUE_REDEFINED, Tok->getLine(), Tok->getText()); + } + } + + if (mUsedDefaultCount >= EFI_IFR_MAX_DEFAULT_TYPE - 1) { + gCVfrErrorHandle.HandleError (VFR_RETURN_FATAL_ERROR, Tok->getLine(), Tok->getText()); + } + + mUsedDefaultArray[mUsedDefaultCount++] = DefaultId; +} +>> diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp new file mode 100644 index 00000000..899f7123 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrUtilityLib.cpp @@ -0,0 +1,3921 @@ +/** @file + + Vfr common library functions. + +Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "stdio.h" +#include "stdlib.h" +#include "assert.h" +#include "CommonLib.h" +#include "VfrUtilityLib.h" +#include "VfrFormPkg.h" + +VOID +CVfrBinaryOutput::WriteLine ( + IN FILE *pFile, + IN UINT32 LineBytes, + IN CONST CHAR8 *LineHeader, + IN CHAR8 *BlkBuf, + IN UINT32 BlkSize + ) +{ + UINT32 Index; + + if ((pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) { + return; + } + + for (Index = 0; Index < BlkSize; Index++) { + if ((Index % LineBytes) == 0) { + fprintf (pFile, "\n%s", LineHeader); + } + fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]); + } +} + +VOID +CVfrBinaryOutput::WriteEnd ( + IN FILE *pFile, + IN UINT32 LineBytes, + IN CONST CHAR8 *LineHeader, + IN CHAR8 *BlkBuf, + IN UINT32 BlkSize + ) +{ + UINT32 Index; + + if ((BlkSize == 0) || (pFile == NULL) || (LineHeader == NULL) || (BlkBuf == NULL)) { + return; + } + + for (Index = 0; Index < BlkSize - 1; Index++) { + if ((Index % LineBytes) == 0) { + fprintf (pFile, "\n%s", LineHeader); + } + fprintf (pFile, "0x%02X, ", (UINT8)BlkBuf[Index]); + } + + if ((Index % LineBytes) == 0) { + fprintf (pFile, "\n%s", LineHeader); + } + fprintf (pFile, "0x%02X\n", (UINT8)BlkBuf[Index]); +} + +SConfigInfo::SConfigInfo ( + IN UINT8 Type, + IN UINT16 Offset, + IN UINT32 Width, + IN EFI_IFR_TYPE_VALUE Value + ) +{ + mNext = NULL; + mOffset = Offset; + mWidth = (UINT16)Width; + mValue = new UINT8[mWidth]; + if (mValue == NULL) { + return; + } + + switch (Type) { + case EFI_IFR_TYPE_NUM_SIZE_8 : + memcpy (mValue, &Value.u8, mWidth); + break; + case EFI_IFR_TYPE_NUM_SIZE_16 : + memcpy (mValue, &Value.u16, mWidth); + break; + case EFI_IFR_TYPE_NUM_SIZE_32 : + memcpy (mValue, &Value.u32, mWidth); + break; + case EFI_IFR_TYPE_NUM_SIZE_64 : + memcpy (mValue, &Value.u64, mWidth); + break; + case EFI_IFR_TYPE_BOOLEAN : + memcpy (mValue, &Value.b, mWidth); + break; + case EFI_IFR_TYPE_TIME : + memcpy (mValue, &Value.time, mWidth); + break; + case EFI_IFR_TYPE_DATE : + memcpy (mValue, &Value.date, mWidth); + break; + case EFI_IFR_TYPE_STRING : + memcpy (mValue, &Value.string, mWidth); + break; + case EFI_IFR_TYPE_BUFFER : + memcpy (mValue, &Value.u8, mWidth); + break; + + case EFI_IFR_TYPE_OTHER : + return; + } +} + +SConfigInfo::~SConfigInfo ( + VOID + ) +{ + ARRAY_SAFE_FREE (mValue); +} + +SConfigItem::SConfigItem ( + IN CHAR8 *Name, + IN EFI_GUID *Guid, + IN CHAR8 *Id + ) +{ + mName = NULL; + mGuid = NULL; + mId = NULL; + mInfoStrList = NULL; + mNext = NULL; + + if (Name != NULL) { + if ((mName = new CHAR8[strlen (Name) + 1]) != NULL) { + strcpy (mName, Name); + } + } + + if (Guid != NULL) { + if ((mGuid = (EFI_GUID *) new CHAR8[sizeof (EFI_GUID)]) != NULL) { + memcpy (mGuid, Guid, sizeof (EFI_GUID)); + } + } + + if (Id != NULL) { + if ((mId = new CHAR8[strlen (Id) + 1]) != NULL) { + strcpy (mId, Id); + } + } +} + +SConfigItem::SConfigItem ( + IN CHAR8 *Name, + IN EFI_GUID *Guid, + IN CHAR8 *Id, + IN UINT8 Type, + IN UINT16 Offset, + IN UINT16 Width, + IN EFI_IFR_TYPE_VALUE Value + ) +{ + mName = NULL; + mGuid = NULL; + mId = NULL; + mInfoStrList = NULL; + mNext = NULL; + + if (Name != NULL) { + if ((mName = new CHAR8[strlen (Name) + 1]) != NULL) { + strcpy (mName, Name); + } + } + + if (Guid != NULL) { + if ((mGuid = (EFI_GUID *) new CHAR8[sizeof (EFI_GUID)]) != NULL) { + memcpy (mGuid, Guid, sizeof (EFI_GUID)); + } + } + + if (Id != NULL) { + if ((mId = new CHAR8[strlen (Id) + 1]) != NULL) { + strcpy (mId, Id); + } + } + + mInfoStrList = new SConfigInfo(Type, Offset, Width, Value); +} + +SConfigItem::~SConfigItem ( + VOID + ) +{ + SConfigInfo *Info; + + ARRAY_SAFE_FREE (mName); + ARRAY_SAFE_FREE (mGuid); + ARRAY_SAFE_FREE (mId); + while (mInfoStrList != NULL) { + Info = mInfoStrList; + mInfoStrList = mInfoStrList->mNext; + + BUFFER_SAFE_FREE (Info); + } +} + +UINT8 +CVfrBufferConfig::Register ( + IN CHAR8 *Name, + IN EFI_GUID *Guid, + IN CHAR8 *Id + ) +{ + SConfigItem *pNew; + + if (Select (Name, Guid) == 0) { + return 1; + } + + if ((pNew = new SConfigItem (Name, Guid, Id)) == NULL) { + return 2; + } + + if (mItemListHead == NULL) { + mItemListHead = pNew; + mItemListTail = pNew; + } else { + mItemListTail->mNext = pNew; + mItemListTail = pNew; + } + mItemListPos = pNew; + + return 0; +} + +VOID +CVfrBufferConfig::Open ( + VOID + ) +{ + mItemListPos = mItemListHead; +} + +BOOLEAN +CVfrBufferConfig::Eof( + VOID + ) +{ + return (mItemListPos == NULL) ? TRUE : FALSE; +} + +UINT8 +CVfrBufferConfig::Select ( + IN CHAR8 *Name, + IN EFI_GUID *Guid, + IN CHAR8 *Id + ) +{ + SConfigItem *p; + + if (Name == NULL || Guid == NULL) { + mItemListPos = mItemListHead; + return 0; + } else { + for (p = mItemListHead; p != NULL; p = p->mNext) { + if ((strcmp (p->mName, Name) != 0) || (memcmp (p->mGuid, Guid, sizeof (EFI_GUID)) != 0)) { + continue; + } + + if (Id != NULL) { + if (p->mId == NULL || strcmp (p->mId, Id) != 0) { + continue; + } + } else if (p->mId != NULL) { + continue; + } + + mItemListPos = p; + return 0; + } + } + + return 1; +} + +UINT8 +CVfrBufferConfig::Write ( + IN CONST CHAR8 Mode, + IN CHAR8 *Name, + IN EFI_GUID *Guid, + IN CHAR8 *Id, + IN UINT8 Type, + IN UINT16 Offset, + IN UINT32 Width, + IN EFI_IFR_TYPE_VALUE Value + ) +{ + UINT8 Ret; + SConfigItem *pItem; + SConfigInfo *pInfo; + + if ((Ret = Select (Name, Guid)) != 0) { + return Ret; + } + + switch (Mode) { + case 'a' : // add + if (Select (Name, Guid, Id) != 0) { + if ((pItem = new SConfigItem (Name, Guid, Id, Type, Offset, (UINT16) Width, Value)) == NULL) { + return 2; + } + if (mItemListHead == NULL) { + mItemListHead = pItem; + mItemListTail = pItem; + } else { + mItemListTail->mNext = pItem; + mItemListTail = pItem; + } + mItemListPos = pItem; + } else { + // tranverse the list to find out if there's already the value for the same offset + for (pInfo = mItemListPos->mInfoStrList; pInfo != NULL; pInfo = pInfo->mNext) { + if (pInfo->mOffset == Offset) { + return 0; + } + } + if((pInfo = new SConfigInfo (Type, Offset, Width, Value)) == NULL) { + return 2; + } + pInfo->mNext = mItemListPos->mInfoStrList; + mItemListPos->mInfoStrList = pInfo; + } + break; + + case 'd' : // delete + if (mItemListHead == mItemListPos) { + mItemListHead = mItemListPos->mNext; + delete mItemListPos; + break; + } + + for (pItem = mItemListHead; pItem->mNext != mItemListPos; pItem = pItem->mNext) + ; + + pItem->mNext = mItemListPos->mNext; + if (mItemListTail == mItemListPos) { + mItemListTail = pItem; + } + delete mItemListPos; + mItemListPos = pItem->mNext; + break; + + case 'i' : // set info + if (mItemListPos->mId != NULL) { + delete[] mItemListPos->mId; + } + mItemListPos->mId = NULL; + if (Id != NULL) { + if ((mItemListPos->mId = new CHAR8[strlen (Id) + 1]) == NULL) { + return 2; + } + strcpy (mItemListPos->mId, Id); + } + break; + + default : + return 1; + } + + return 0; +} + + +VOID +CVfrBufferConfig::Close ( + VOID + ) +{ + mItemListPos = NULL; +} + +#define BYTES_PRE_LINE 0x10 + +VOID +CVfrBufferConfig::OutputCFile ( + IN FILE *pFile, + IN CHAR8 *BaseName + ) +{ + CVfrBinaryOutput Output; + SConfigItem *Item; + SConfigInfo *Info; + UINT32 TotalLen; + + if (pFile == NULL) { + return; + } + + for (Item = mItemListHead; Item != NULL; Item = Item->mNext) { + if (Item->mId != NULL || Item->mInfoStrList == NULL) { + continue; + } + fprintf (pFile, "\nunsigned char %s%sBlockName[] = {", BaseName, Item->mName); + + TotalLen = sizeof (UINT32); + for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) { + TotalLen += sizeof (UINT16) * 2; + } + Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&TotalLen, sizeof (UINT32)); + + for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) { + fprintf (pFile, "\n"); + Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mOffset, sizeof (UINT16)); + Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mWidth, sizeof (UINT16)); + } + fprintf (pFile, "\n};\n"); + } + + for (Item = mItemListHead; Item != NULL; Item = Item->mNext) { + if (Item->mId != NULL && Item->mInfoStrList != NULL) { + fprintf (pFile, "\nunsigned char %s%sDefault%s[] = {", BaseName, Item->mName, Item->mId); + + TotalLen = sizeof (UINT32); + for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) { + TotalLen += Info->mWidth + sizeof (UINT16) * 2; + } + Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&TotalLen, sizeof (UINT32)); + + for (Info = Item->mInfoStrList; Info != NULL; Info = Info->mNext) { + fprintf (pFile, "\n"); + Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mOffset, sizeof (UINT16)); + Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)&Info->mWidth, sizeof (UINT16)); + if (Info->mNext == NULL) { + Output.WriteEnd (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)Info->mValue, Info->mWidth); + } else { + Output.WriteLine (pFile, BYTES_PRE_LINE, " ", (CHAR8 *)Info->mValue, Info->mWidth); + } + } + fprintf (pFile, "\n};\n"); + } + } +} + +CVfrBufferConfig::CVfrBufferConfig ( + VOID + ) +{ + mItemListHead = NULL; + mItemListTail = NULL; + mItemListPos = NULL; +} + +CVfrBufferConfig::~CVfrBufferConfig ( + VOID + ) +{ + SConfigItem *p; + + while (mItemListHead != NULL) { + p = mItemListHead; + mItemListHead = mItemListHead->mNext; + delete p; + } + + mItemListHead = NULL; + mItemListTail = NULL; + mItemListPos = NULL; +} + +CVfrBufferConfig gCVfrBufferConfig; + +static struct { + CONST CHAR8 *mTypeName; + UINT8 mType; + UINT32 mSize; + UINT32 mAlign; +} gInternalTypesTable [] = { + {"UINT64", EFI_IFR_TYPE_NUM_SIZE_64, sizeof (UINT64), sizeof (UINT64)}, + {"UINT32", EFI_IFR_TYPE_NUM_SIZE_32, sizeof (UINT32), sizeof (UINT32)}, + {"UINT16", EFI_IFR_TYPE_NUM_SIZE_16, sizeof (UINT16), sizeof (UINT16)}, + {"UINT8", EFI_IFR_TYPE_NUM_SIZE_8, sizeof (UINT8), sizeof (UINT8)}, + {"BOOLEAN", EFI_IFR_TYPE_BOOLEAN, sizeof (BOOLEAN), sizeof (BOOLEAN)}, + {"EFI_HII_DATE", EFI_IFR_TYPE_DATE, sizeof (EFI_HII_DATE), sizeof (UINT16)}, + {"EFI_STRING_ID", EFI_IFR_TYPE_STRING, sizeof (EFI_STRING_ID),sizeof (EFI_STRING_ID)}, + {"EFI_HII_TIME", EFI_IFR_TYPE_TIME, sizeof (EFI_HII_TIME), sizeof (UINT8)}, + {"EFI_HII_REF", EFI_IFR_TYPE_REF, sizeof (EFI_HII_REF), sizeof (EFI_GUID)}, + {NULL, EFI_IFR_TYPE_OTHER, 0, 0} +}; + +STATIC +BOOLEAN +_IS_INTERNAL_TYPE ( + IN CHAR8 *TypeName + ) +{ + UINT32 Index; + + if (TypeName == NULL) { + return FALSE; + } + + for (Index = 0; gInternalTypesTable[Index].mTypeName != NULL; Index++) { + if (strcmp (TypeName, gInternalTypesTable[Index].mTypeName) == 0) { + return TRUE; + } + } + + return FALSE; +} + +STATIC +CHAR8 * +TrimHex ( + IN CHAR8 *Str, + OUT bool *IsHex + ) +{ + *IsHex = FALSE; + + while (*Str && *Str == ' ') { + Str++; + } + while (*Str && *Str == '0') { + Str++; + } + if (*Str && (*Str == 'x' || *Str == 'X')) { + Str++; + *IsHex = TRUE; + } + + return Str; +} + +UINT32 +_STR2U32 ( + IN CHAR8 *Str + ) +{ + bool IsHex; + UINT32 Value; + CHAR8 c; + + Str = TrimHex (Str, &IsHex); + for (Value = 0; (c = *Str) != '\0'; Str++) { + // + // BUG: does not handle overflow here + // + (IsHex == TRUE) ? (Value <<= 4) : (Value *= 10); + + if ((IsHex == TRUE) && (c >= 'a') && (c <= 'f')) { + Value += (c - 'a' + 10); + } + if ((IsHex == TRUE) && (c >= 'A') && (c <= 'F')) { + Value += (c - 'A' + 10); + } + if (c >= '0' && c <= '9') { + Value += (c - '0'); + } + } + + return Value; +} + +VOID +CVfrVarDataTypeDB::RegisterNewType ( + IN SVfrDataType *New + ) +{ + New->mNext = mDataTypeList; + mDataTypeList = New; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::ExtractStructTypeName ( + IN CHAR8 *&VarStr, + OUT CHAR8 *TName + ) +{ + if (TName == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + while((*VarStr != '\0') && (*VarStr != '.')) { + *TName = *VarStr; + VarStr++; + TName++; + } + *TName = '\0'; + if (*VarStr == '.') { + VarStr++; + } + + return VFR_RETURN_SUCCESS; +} + +/** + Check whether the DataType contain bit field. + + @param TypeName The name of the type. + +**/ +BOOLEAN +CVfrVarDataTypeDB::DataTypeHasBitField ( + IN CHAR8 *TypeName + ) +{ + SVfrDataType *pType = NULL; + SVfrDataField *pTmp; + + GetDataType (TypeName, &pType); + + if (pType == NULL){ + return FALSE; + } + for (pTmp = pType->mMembers; pTmp!= NULL; pTmp = pTmp->mNext) { + if (pTmp->mIsBitField) { + return TRUE; + } + } + return FALSE; +} + +/** + Check whether the field is bit field or not. + + @param VarStr Point to the field name which may contain the structure name. + +**/ +BOOLEAN +CVfrVarDataTypeDB::IsThisBitField ( + IN CHAR8 *VarStr + ) +{ + CHAR8 FName[MAX_NAME_LEN]; + CHAR8 TName[MAX_NAME_LEN]; + UINT32 ArrayIdx; + SVfrDataType *pType = NULL; + SVfrDataField *pField = NULL; + + CHECK_ERROR_RETURN (ExtractStructTypeName (VarStr, TName), VFR_RETURN_SUCCESS); + CHECK_ERROR_RETURN (GetDataType (TName, &pType), VFR_RETURN_SUCCESS); + + while (*VarStr != '\0') { + CHECK_ERROR_RETURN(ExtractFieldNameAndArrary(VarStr, FName, ArrayIdx), VFR_RETURN_SUCCESS); + CHECK_ERROR_RETURN(GetTypeField (FName, pType, pField), VFR_RETURN_SUCCESS); + pType = pField->mFieldType; + } + if (pField != NULL && pField->mIsBitField) { + return TRUE; + } else { + return FALSE; + } +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::ExtractFieldNameAndArrary ( + IN CHAR8 *&VarStr, + IN CHAR8 *FName, + OUT UINT32 &ArrayIdx + ) +{ + UINT32 Idx; + CHAR8 ArrayStr[MAX_NAME_LEN + 1]; + + ArrayIdx = INVALID_ARRAY_INDEX; + + if (FName == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + while((*VarStr != '\0') && + (*VarStr != '.') && + (*VarStr != '[') && + (*VarStr != ']')) { + *FName = *VarStr; + VarStr++; + FName++; + } + *FName = '\0'; + + switch (*VarStr) { + case '.' : + VarStr++; + /* fall through */ + case '\0': + return VFR_RETURN_SUCCESS; + case '[' : + VarStr++; + for (Idx = 0; (Idx < MAX_NAME_LEN) && (*VarStr != '\0') && (*VarStr != ']'); VarStr++, Idx++) { + ArrayStr[Idx] = *VarStr; + } + ArrayStr[Idx] = '\0'; + + if ((*VarStr != ']') && (ArrayStr[0] == '\0')) { + return VFR_RETURN_DATA_STRING_ERROR; + } + ArrayIdx = _STR2U32 (ArrayStr); + if (*VarStr == ']') { + VarStr++; + } + if (*VarStr == '.') { + VarStr++; + } + return VFR_RETURN_SUCCESS; + case ']': + return VFR_RETURN_DATA_STRING_ERROR; + } + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::GetTypeField ( + IN CONST CHAR8 *FName, + IN SVfrDataType *Type, + OUT SVfrDataField *&Field + ) +{ + SVfrDataField *pField = NULL; + + if ((FName == NULL) || (Type == NULL)) { + return VFR_RETURN_FATAL_ERROR; + } + + for (pField = Type->mMembers; pField != NULL; pField = pField->mNext) { + // + // For type EFI_IFR_TYPE_TIME, because field name is not correctly wrote, + // add code to adjust it. + // + if (Type->mType == EFI_IFR_TYPE_TIME) { + if (strcmp (FName, "Hour") == 0) { + FName = "Hours"; + } else if (strcmp (FName, "Minute") == 0) { + FName = "Minuts"; + } else if (strcmp (FName, "Second") == 0) { + FName = "Seconds"; + } + } + + if (strcmp (pField->mFieldName, FName) == 0) { + Field = pField; + return VFR_RETURN_SUCCESS; + } + } + + return VFR_RETURN_UNDEFINED; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::GetFieldOffset ( + IN SVfrDataField *Field, + IN UINT32 ArrayIdx, + OUT UINT32 &Offset, + IN BOOLEAN IsBitField + ) +{ + if (Field == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + if ((ArrayIdx != INVALID_ARRAY_INDEX) && ((Field->mArrayNum == 0) || (Field->mArrayNum <= ArrayIdx))) { + return VFR_RETURN_ERROR_ARRARY_NUM; + } + + // + // Be compatible with the current usage + // If ArraryIdx is not specified, the first one is used. + // + // if ArrayNum is larger than zero, ArraryIdx must be specified. + // + // if ((ArrayIdx == INVALID_ARRAY_INDEX) && (Field->mArrayNum > 0)) { + // return VFR_RETURN_ERROR_ARRARY_NUM; + // } + // + if (IsBitField) { + Offset = Field->mBitOffset + Field->mFieldType->mTotalSize * ((ArrayIdx == INVALID_ARRAY_INDEX) ? 0 : ArrayIdx) * 8; + } else { + Offset = Field->mOffset + Field->mFieldType->mTotalSize * ((ArrayIdx == INVALID_ARRAY_INDEX) ? 0 : ArrayIdx); + } + return VFR_RETURN_SUCCESS; +} + +UINT8 +CVfrVarDataTypeDB::GetFieldWidth ( + IN SVfrDataField *Field + ) +{ + if (Field == NULL) { + return 0; + } + + return Field->mFieldType->mType; +} + +UINT32 +CVfrVarDataTypeDB::GetFieldSize ( + IN SVfrDataField *Field, + IN UINT32 ArrayIdx, + IN BOOLEAN BitField + ) +{ + if (Field == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + if ((ArrayIdx == INVALID_ARRAY_INDEX) && (Field->mArrayNum != 0)) { + return Field->mFieldType->mTotalSize * Field->mArrayNum; + } else { + if (BitField) { + return Field->mBitWidth; + } else { + return Field->mFieldType->mTotalSize; + } + } +} + +VOID +CVfrVarDataTypeDB::InternalTypesListInit ( + VOID + ) +{ + SVfrDataType *New = NULL; + UINT32 Index; + + for (Index = 0; gInternalTypesTable[Index].mTypeName != NULL; Index++) { + New = new SVfrDataType; + if (New != NULL) { + assert (strlen (gInternalTypesTable[Index].mTypeName) < MAX_NAME_LEN); + strncpy (New->mTypeName, gInternalTypesTable[Index].mTypeName, MAX_NAME_LEN - 1); + New->mTypeName[MAX_NAME_LEN - 1] = 0; + New->mType = gInternalTypesTable[Index].mType; + New->mAlign = gInternalTypesTable[Index].mAlign; + New->mTotalSize = gInternalTypesTable[Index].mSize; + if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_DATE") == 0) { + SVfrDataField *pYearField = new SVfrDataField; + SVfrDataField *pMonthField = new SVfrDataField; + SVfrDataField *pDayField = new SVfrDataField; + + strcpy (pYearField->mFieldName, "Year"); + GetDataType ((CHAR8 *)"UINT16", &pYearField->mFieldType); + pYearField->mOffset = 0; + pYearField->mNext = pMonthField; + pYearField->mArrayNum = 0; + pYearField->mIsBitField = FALSE; + + strcpy (pMonthField->mFieldName, "Month"); + GetDataType ((CHAR8 *)"UINT8", &pMonthField->mFieldType); + pMonthField->mOffset = 2; + pMonthField->mNext = pDayField; + pMonthField->mArrayNum = 0; + pMonthField->mIsBitField = FALSE; + + strcpy (pDayField->mFieldName, "Day"); + GetDataType ((CHAR8 *)"UINT8", &pDayField->mFieldType); + pDayField->mOffset = 3; + pDayField->mNext = NULL; + pDayField->mArrayNum = 0; + pDayField->mIsBitField = FALSE; + + New->mMembers = pYearField; + } else if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_TIME") == 0) { + SVfrDataField *pHoursField = new SVfrDataField; + SVfrDataField *pMinutesField = new SVfrDataField; + SVfrDataField *pSecondsField = new SVfrDataField; + + strcpy (pHoursField->mFieldName, "Hours"); + GetDataType ((CHAR8 *)"UINT8", &pHoursField->mFieldType); + pHoursField->mOffset = 0; + pHoursField->mNext = pMinutesField; + pHoursField->mArrayNum = 0; + pHoursField->mIsBitField = FALSE; + + strcpy (pMinutesField->mFieldName, "Minutes"); + GetDataType ((CHAR8 *)"UINT8", &pMinutesField->mFieldType); + pMinutesField->mOffset = 1; + pMinutesField->mNext = pSecondsField; + pMinutesField->mArrayNum = 0; + pMinutesField->mIsBitField = FALSE; + + strcpy (pSecondsField->mFieldName, "Seconds"); + GetDataType ((CHAR8 *)"UINT8", &pSecondsField->mFieldType); + pSecondsField->mOffset = 2; + pSecondsField->mNext = NULL; + pSecondsField->mArrayNum = 0; + pSecondsField->mIsBitField = FALSE; + + New->mMembers = pHoursField; + } else if (strcmp (gInternalTypesTable[Index].mTypeName, "EFI_HII_REF") == 0) { + SVfrDataField *pQuestionIdField = new SVfrDataField; + SVfrDataField *pFormIdField = new SVfrDataField; + SVfrDataField *pFormSetGuidField = new SVfrDataField; + SVfrDataField *pDevicePathField = new SVfrDataField; + + strcpy (pQuestionIdField->mFieldName, "QuestionId"); + GetDataType ((CHAR8 *)"UINT16", &pQuestionIdField->mFieldType); + pQuestionIdField->mOffset = 0; + pQuestionIdField->mNext = pFormIdField; + pQuestionIdField->mArrayNum = 0; + pQuestionIdField->mIsBitField = FALSE; + + strcpy (pFormIdField->mFieldName, "FormId"); + GetDataType ((CHAR8 *)"UINT16", &pFormIdField->mFieldType); + pFormIdField->mOffset = 2; + pFormIdField->mNext = pFormSetGuidField; + pFormIdField->mArrayNum = 0; + pFormIdField->mIsBitField = FALSE; + + strcpy (pFormSetGuidField->mFieldName, "FormSetGuid"); + GetDataType ((CHAR8 *)"EFI_GUID", &pFormSetGuidField->mFieldType); + pFormSetGuidField->mOffset = 4; + pFormSetGuidField->mNext = pDevicePathField; + pFormSetGuidField->mArrayNum = 0; + pFormSetGuidField->mIsBitField = FALSE; + + strcpy (pDevicePathField->mFieldName, "DevicePath"); + GetDataType ((CHAR8 *)"EFI_STRING_ID", &pDevicePathField->mFieldType); + pDevicePathField->mOffset = 20; + pDevicePathField->mNext = NULL; + pDevicePathField->mArrayNum = 0; + pDevicePathField->mIsBitField = FALSE; + + New->mMembers = pQuestionIdField; + } else { + New->mMembers = NULL; + } + New->mNext = NULL; + RegisterNewType (New); + New = NULL; + } + } +} + +CVfrVarDataTypeDB::CVfrVarDataTypeDB ( + VOID + ) +{ + mDataTypeList = NULL; + mNewDataType = NULL; + mCurrDataField = NULL; + mPackAlign = DEFAULT_PACK_ALIGN; + mPackStack = NULL; + mFirstNewDataTypeName = NULL; + mCurrDataType = NULL; + + InternalTypesListInit (); +} + +CVfrVarDataTypeDB::~CVfrVarDataTypeDB ( + VOID + ) +{ + SVfrDataType *pType; + SVfrDataField *pField; + SVfrPackStackNode *pPack; + + if (mNewDataType != NULL) { + delete mNewDataType; + } + + while (mDataTypeList != NULL) { + pType = mDataTypeList; + mDataTypeList = mDataTypeList->mNext; + while(pType->mMembers != NULL) { + pField = pType->mMembers; + pType->mMembers = pType->mMembers->mNext; + delete pField; + } + delete pType; + } + + while (mPackStack != NULL) { + pPack = mPackStack; + mPackStack = mPackStack->mNext; + delete pPack; + } +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::Pack ( + IN UINT32 LineNum, + IN UINT8 Action, + IN CHAR8 *Identifier, + IN UINT32 Number + ) +{ + UINT32 PackAlign; + CHAR8 Msg[MAX_STRING_LEN] = {0, }; + + if (Action & VFR_PACK_SHOW) { + sprintf (Msg, "value of pragma pack(show) == %d", mPackAlign); + gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Warning", Msg); + } + + if (Action & VFR_PACK_PUSH) { + SVfrPackStackNode *pNew = NULL; + + if ((pNew = new SVfrPackStackNode (Identifier, mPackAlign)) == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + pNew->mNext = mPackStack; + mPackStack = pNew; + } + + if (Action & VFR_PACK_POP) { + SVfrPackStackNode *pNode = NULL; + + if (mPackStack == NULL) { + gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Error", "#pragma pack(pop...) : more pops than pushes"); + } + + for (pNode = mPackStack; pNode != NULL; pNode = pNode->mNext) { + if (pNode->Match (Identifier) == TRUE) { + mPackAlign = pNode->mNumber; + mPackStack = pNode->mNext; + } + } + } + + if (Action & VFR_PACK_ASSIGN) { + PackAlign = (Number > 1) ? Number + Number % 2 : Number; + if ((PackAlign == 0) || (PackAlign > 16)) { + gCVfrErrorHandle.PrintMsg (LineNum, NULL, "Error", "expected pragma parameter to be '1', '2', '4', '8', or '16'"); + } else { + mPackAlign = PackAlign; + } + } + + return VFR_RETURN_SUCCESS; +} + +VOID +CVfrVarDataTypeDB::DeclareDataTypeBegin ( + VOID + ) +{ + SVfrDataType *pNewType = NULL; + + pNewType = new SVfrDataType; + pNewType->mTypeName[0] = '\0'; + pNewType->mType = EFI_IFR_TYPE_OTHER; + pNewType->mAlign = DEFAULT_ALIGN; + pNewType->mTotalSize = 0; + pNewType->mMembers = NULL; + pNewType->mNext = NULL; + pNewType->mHasBitField = FALSE; + + mNewDataType = pNewType; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::SetNewTypeName ( + IN CHAR8 *TypeName + ) +{ + SVfrDataType *pType; + + if (mNewDataType == NULL) { + return VFR_RETURN_ERROR_SKIPED; + } + if (TypeName == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + if (strlen(TypeName) >= MAX_NAME_LEN) { + return VFR_RETURN_INVALID_PARAMETER; + } + + for (pType = mDataTypeList; pType != NULL; pType = pType->mNext) { + if (strcmp(pType->mTypeName, TypeName) == 0) { + return VFR_RETURN_REDEFINED; + } + } + + strncpy(mNewDataType->mTypeName, TypeName, MAX_NAME_LEN - 1); + mNewDataType->mTypeName[MAX_NAME_LEN - 1] = 0; + return VFR_RETURN_SUCCESS; +} + +/** + Record the bit field info in the data type. + + @param FieldName Point to the field name. + @param TypeName Point to the type name. + @param Width The bit width. + @param FieldInUnion The filed is in Union type or Structure type. + +**/ +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::DataTypeAddBitField ( + IN CHAR8 *FieldName, + IN CHAR8 *TypeName, + IN UINT32 Width, + IN BOOLEAN FieldInUnion + ) +{ + SVfrDataField *pNewField = NULL; + SVfrDataType *pFieldType = NULL; + SVfrDataField *pTmp; + UINT32 Align; + UINT32 MaxDataTypeSize; + BOOLEAN UpdateTotalSize; + + CHECK_ERROR_RETURN (GetDataType (TypeName, &pFieldType), VFR_RETURN_SUCCESS); + + if (Width > MAX_BIT_WIDTH) { + return VFR_RETURN_BIT_WIDTH_ERROR; + } + + if (Width > pFieldType->mTotalSize * 8) { + return VFR_RETURN_BIT_WIDTH_ERROR; + } + + if (FieldName != NULL && strlen (FieldName) >= MAX_NAME_LEN) { + return VFR_RETURN_INVALID_PARAMETER; + } + + if (Width == 0 && FieldName != NULL) { + return VFR_RETURN_INVALID_PARAMETER; + } + + for (pTmp = mNewDataType->mMembers; pTmp != NULL; pTmp = pTmp->mNext) { + if (FieldName != NULL && strcmp (pTmp->mFieldName, FieldName) == 0) { + return VFR_RETURN_REDEFINED; + } + } + + Align = MIN (mPackAlign, pFieldType->mAlign); + UpdateTotalSize = FALSE; + + if ((pNewField = new SVfrDataField) == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + + MaxDataTypeSize = mNewDataType->mTotalSize; + if (FieldName != NULL) { + strncpy (pNewField->mFieldName, FieldName, MAX_NAME_LEN - 1); + pNewField->mFieldName[MAX_NAME_LEN - 1] = 0; + } + pNewField->mFieldType = pFieldType; + pNewField->mIsBitField = TRUE; + pNewField->mBitWidth = Width; + pNewField->mArrayNum = 0; + pNewField->mBitOffset = 0; + pNewField->mOffset = 0; + + if (mNewDataType->mMembers == NULL) { + mNewDataType->mMembers = pNewField; + pNewField->mNext = NULL; + } else { + for (pTmp = mNewDataType->mMembers; pTmp->mNext != NULL; pTmp = pTmp->mNext) + ; + pTmp->mNext = pNewField; + pNewField->mNext = NULL; + } + + if (FieldInUnion) { + pNewField->mOffset = 0; + if (MaxDataTypeSize < pNewField->mFieldType->mTotalSize) { + mNewDataType->mTotalSize = pNewField->mFieldType->mTotalSize; + } + } else { + // + // Check whether the bit fields can be contained within one FieldType. + // + if (pTmp != NULL && pTmp->mIsBitField && strcmp (pTmp->mFieldType->mTypeName, pNewField->mFieldType->mTypeName) == 0 && + (pTmp->mBitOffset - pTmp->mOffset * 8) + pTmp->mBitWidth + pNewField->mBitWidth <= pNewField->mFieldType->mTotalSize * 8) { + pNewField->mBitOffset = pTmp->mBitOffset + pTmp->mBitWidth; + pNewField->mOffset = pTmp->mOffset; + // + // If BitWidth=0,used to force alignment at the next word boundary. + // So make this bit field occupy the remaing bit width of current field type. + // + if (pNewField->mBitWidth == 0) { + pNewField->mBitWidth = pNewField->mFieldType->mTotalSize * 8 - (pNewField->mBitOffset - pTmp->mOffset * 8); + } + } else { + // + // The bit filed start a new memory + // + pNewField->mBitOffset = mNewDataType->mTotalSize * 8; + UpdateTotalSize = TRUE; + } + } + + if (UpdateTotalSize){ + if ((mNewDataType->mTotalSize % Align) == 0) { + pNewField->mOffset = mNewDataType->mTotalSize; + } else { + pNewField->mOffset = mNewDataType->mTotalSize + ALIGN_STUFF(mNewDataType->mTotalSize, Align); + } + mNewDataType->mTotalSize = pNewField->mOffset + (pNewField->mFieldType->mTotalSize); + } + + mNewDataType->mAlign = MIN (mPackAlign, MAX (pFieldType->mAlign, mNewDataType->mAlign)); + mNewDataType->mHasBitField = TRUE; + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::DataTypeAddField ( + IN CHAR8 *FieldName, + IN CHAR8 *TypeName, + IN UINT32 ArrayNum, + IN BOOLEAN FieldInUnion + ) +{ + SVfrDataField *pNewField = NULL; + SVfrDataType *pFieldType = NULL; + SVfrDataField *pTmp; + UINT32 Align; + UINT32 MaxDataTypeSize; + + CHECK_ERROR_RETURN (GetDataType (TypeName, &pFieldType), VFR_RETURN_SUCCESS); + MaxDataTypeSize = mNewDataType->mTotalSize; + + if (strlen (FieldName) >= MAX_NAME_LEN) { + return VFR_RETURN_INVALID_PARAMETER; + } + + for (pTmp = mNewDataType->mMembers; pTmp != NULL; pTmp = pTmp->mNext) { + if (strcmp (pTmp->mFieldName, FieldName) == 0) { + return VFR_RETURN_REDEFINED; + } + } + + Align = MIN (mPackAlign, pFieldType->mAlign); + + if ((pNewField = new SVfrDataField) == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + strncpy (pNewField->mFieldName, FieldName, MAX_NAME_LEN - 1); + pNewField->mFieldName[MAX_NAME_LEN - 1] = 0; + pNewField->mFieldType = pFieldType; + pNewField->mArrayNum = ArrayNum; + pNewField->mIsBitField = FALSE; + if ((mNewDataType->mTotalSize % Align) == 0) { + pNewField->mOffset = mNewDataType->mTotalSize; + } else { + pNewField->mOffset = mNewDataType->mTotalSize + ALIGN_STUFF(mNewDataType->mTotalSize, Align); + } + if (mNewDataType->mMembers == NULL) { + mNewDataType->mMembers = pNewField; + pNewField->mNext = NULL; + } else { + for (pTmp = mNewDataType->mMembers; pTmp->mNext != NULL; pTmp = pTmp->mNext) + ; + pTmp->mNext = pNewField; + pNewField->mNext = NULL; + } + + mNewDataType->mAlign = MIN (mPackAlign, MAX (pFieldType->mAlign, mNewDataType->mAlign)); + + if (FieldInUnion) { + if (MaxDataTypeSize < pNewField->mFieldType->mTotalSize) { + mNewDataType->mTotalSize = pNewField->mFieldType->mTotalSize; + } + pNewField->mOffset = 0; + } else { + mNewDataType->mTotalSize = pNewField->mOffset + (pNewField->mFieldType->mTotalSize) * ((ArrayNum == 0) ? 1 : ArrayNum); + } + + return VFR_RETURN_SUCCESS; +} + +VOID +CVfrVarDataTypeDB::DeclareDataTypeEnd ( + VOID + ) +{ + if (mNewDataType->mTypeName[0] == '\0') { + return; + } + + if ((mNewDataType->mTotalSize % mNewDataType->mAlign) !=0) { + mNewDataType->mTotalSize += ALIGN_STUFF (mNewDataType->mTotalSize, mNewDataType->mAlign); + } + + RegisterNewType (mNewDataType); + if (mFirstNewDataTypeName == NULL) { + mFirstNewDataTypeName = mNewDataType->mTypeName; + } + + mNewDataType = NULL; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::GetDataType ( + IN CHAR8 *TypeName, + OUT SVfrDataType **DataType + ) +{ + SVfrDataType *pDataType = NULL; + + if (TypeName == NULL) { + return VFR_RETURN_ERROR_SKIPED; + } + + if (DataType == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + *DataType = NULL; + + for (pDataType = mDataTypeList; pDataType != NULL; pDataType = pDataType->mNext) { + if (strcmp (TypeName, pDataType->mTypeName) == 0) { + *DataType = pDataType; + return VFR_RETURN_SUCCESS; + } + } + + return VFR_RETURN_UNDEFINED; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::GetDataTypeSize ( + IN UINT8 DataType, + OUT UINT32 *Size + ) +{ + SVfrDataType *pDataType = NULL; + + if (Size == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + *Size = 0; + DataType = DataType & 0x0F; + + // + // For user defined data type, the size can't be got by this function. + // + if (DataType == EFI_IFR_TYPE_OTHER) { + return VFR_RETURN_SUCCESS; + } + + for (pDataType = mDataTypeList; pDataType != NULL; pDataType = pDataType->mNext) { + if (DataType == pDataType->mType) { + *Size = pDataType->mTotalSize; + return VFR_RETURN_SUCCESS; + } + } + + return VFR_RETURN_UNDEFINED; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::GetDataTypeSize ( + IN CHAR8 *TypeName, + OUT UINT32 *Size + ) +{ + SVfrDataType *pDataType = NULL; + + if (Size == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + *Size = 0; + + for (pDataType = mDataTypeList; pDataType != NULL; pDataType = pDataType->mNext) { + if (strcmp (TypeName, pDataType->mTypeName) == 0) { + *Size = pDataType->mTotalSize; + return VFR_RETURN_SUCCESS; + } + } + + return VFR_RETURN_UNDEFINED; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::GetDataFieldInfo ( + IN CHAR8 *VarStr, + OUT UINT16 &Offset, + OUT UINT8 &Type, + OUT UINT32 &Size, + OUT BOOLEAN &BitField + ) +{ + CHAR8 TName[MAX_NAME_LEN], FName[MAX_NAME_LEN]; + UINT32 ArrayIdx, Tmp; + SVfrDataType *pType = NULL; + SVfrDataField *pField = NULL; + CHAR8 *VarStrName; + + Offset = 0; + Type = EFI_IFR_TYPE_OTHER; + Size = 0; + VarStrName = VarStr; + + CHECK_ERROR_RETURN (ExtractStructTypeName (VarStr, TName), VFR_RETURN_SUCCESS); + CHECK_ERROR_RETURN (GetDataType (TName, &pType), VFR_RETURN_SUCCESS); + + BitField = IsThisBitField (VarStrName); + + // + // if it is not struct data type + // + Type = pType->mType; + Size = pType->mTotalSize; + + while (*VarStr != '\0') { + CHECK_ERROR_RETURN(ExtractFieldNameAndArrary(VarStr, FName, ArrayIdx), VFR_RETURN_SUCCESS); + CHECK_ERROR_RETURN(GetTypeField (FName, pType, pField), VFR_RETURN_SUCCESS); + pType = pField->mFieldType; + CHECK_ERROR_RETURN(GetFieldOffset (pField, ArrayIdx, Tmp, pField->mIsBitField), VFR_RETURN_SUCCESS); + if (BitField && !pField->mIsBitField) { + Offset = (UINT16) (Offset + Tmp * 8); + } else { + Offset = (UINT16) (Offset + Tmp); + } + Type = GetFieldWidth (pField); + Size = GetFieldSize (pField, ArrayIdx, BitField); + } + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrVarDataTypeDB::GetUserDefinedTypeNameList ( + OUT CHAR8 ***NameList, + OUT UINT32 *ListSize + ) +{ + UINT32 Index; + SVfrDataType *pType; + + if ((NameList == NULL) || (ListSize == NULL)) { + return VFR_RETURN_FATAL_ERROR; + } + + *NameList = NULL; + *ListSize = 0; + + for (pType = mDataTypeList; pType != NULL; pType = pType->mNext) { + if (_IS_INTERNAL_TYPE(pType->mTypeName) == FALSE) { + (*ListSize)++; + } + } + + if (*ListSize == 0) { + return VFR_RETURN_SUCCESS; + } + + if ((*NameList = new CHAR8*[*ListSize]) == NULL) { + *ListSize = 0; + return VFR_RETURN_OUT_FOR_RESOURCES; + } + + for (Index = 0, pType = mDataTypeList; pType != NULL; pType = pType->mNext, Index++) { + if (_IS_INTERNAL_TYPE(pType->mTypeName) == FALSE) { + (*NameList)[Index] = pType->mTypeName; + } + } + return VFR_RETURN_SUCCESS; +} + +BOOLEAN +CVfrVarDataTypeDB::IsTypeNameDefined ( + IN CHAR8 *TypeName + ) +{ + SVfrDataType *pType; + + if (TypeName == NULL) { + return FALSE; + } + + for (pType = mDataTypeList; pType != NULL; pType = pType->mNext) { + if (strcmp (pType->mTypeName, TypeName) == 0) { + return TRUE; + } + } + + return FALSE; +} + +VOID +CVfrVarDataTypeDB::Dump ( + IN FILE *File + ) +{ + SVfrDataType *pTNode; + SVfrDataField *pFNode; + + fprintf (File, "\n\n***************************************************************\n"); + fprintf (File, "\t\tmPackAlign = %x\n", mPackAlign); + for (pTNode = mDataTypeList; pTNode != NULL; pTNode = pTNode->mNext) { + fprintf (File, "\t\tstruct %s : mAlign [%d] mTotalSize [0x%x]\n\n", pTNode->mTypeName, pTNode->mAlign, pTNode->mTotalSize); + fprintf (File, "\t\tstruct %s {\n", pTNode->mTypeName); + for (pFNode = pTNode->mMembers; pFNode != NULL; pFNode = pFNode->mNext) { + if (pFNode->mArrayNum > 0) { + fprintf (File, "\t\t\t+%08d[%08x] %s[%d] <%s>\n", pFNode->mOffset, pFNode->mOffset, + pFNode->mFieldName, pFNode->mArrayNum, pFNode->mFieldType->mTypeName); + } else { + fprintf (File, "\t\t\t+%08d[%08x] %s <%s>\n", pFNode->mOffset, pFNode->mOffset, + pFNode->mFieldName, pFNode->mFieldType->mTypeName); + } + } + fprintf (File, "\t\t};\n"); + fprintf (File, "---------------------------------------------------------------\n"); + } + fprintf (File, "***************************************************************\n"); +} + +#ifdef CVFR_VARDATATYPEDB_DEBUG +VOID +CVfrVarDataTypeDB::ParserDB ( + VOID + ) +{ + SVfrDataType *pTNode; + SVfrDataField *pFNode; + + printf ("***************************************************************\n"); + printf ("\t\tmPackAlign = %x\n", mPackAlign); + for (pTNode = mDataTypeList; pTNode != NULL; pTNode = pTNode->mNext) { + printf ("\t\tstruct %s : mAlign [%x] mTotalSize [%x]\n\n", pTNode->mTypeName, pTNode->mAlign, pTNode->mTotalSize); + printf ("\t\tstruct %s {\n", pTNode->mTypeName); + for (pFNode = pTNode->mMembers; pFNode != NULL; pFNode = pFNode->mNext) { + printf ("\t\t\t%s\t%s\n", pFNode->mFieldType->mTypeName, pFNode->mFieldName); + } + printf ("\t\t};\n"); + printf ("---------------------------------------------------------------\n"); + } + printf ("***************************************************************\n"); +} +#endif + +SVfrVarStorageNode::SVfrVarStorageNode ( + IN EFI_GUID *Guid, + IN CHAR8 *StoreName, + IN EFI_VARSTORE_ID VarStoreId, + IN EFI_STRING_ID VarName, + IN UINT32 VarSize, + IN BOOLEAN Flag + ) +{ + if (Guid != NULL) { + mGuid = *Guid; + } else { + memset (&mGuid, 0, sizeof (EFI_GUID)); + } + if (StoreName != NULL) { + mVarStoreName = new CHAR8[strlen(StoreName) + 1]; + strcpy (mVarStoreName, StoreName); + } else { + mVarStoreName = NULL; + } + mNext = NULL; + mVarStoreId = VarStoreId; + mVarStoreType = EFI_VFR_VARSTORE_EFI; + mStorageInfo.mEfiVar.mEfiVarName = VarName; + mStorageInfo.mEfiVar.mEfiVarSize = VarSize; + mAssignedFlag = Flag; +} + +SVfrVarStorageNode::SVfrVarStorageNode ( + IN EFI_GUID *Guid, + IN CHAR8 *StoreName, + IN EFI_VARSTORE_ID VarStoreId, + IN SVfrDataType *DataType, + IN BOOLEAN BitsVarstore, + IN BOOLEAN Flag + ) +{ + if (Guid != NULL) { + mGuid = *Guid; + } else { + memset (&mGuid, 0, sizeof (EFI_GUID)); + } + if (StoreName != NULL) { + mVarStoreName = new CHAR8[strlen(StoreName) + 1]; + strcpy (mVarStoreName, StoreName); + } else { + mVarStoreName = NULL; + } + mNext = NULL; + mVarStoreId = VarStoreId; + if (BitsVarstore) { + mVarStoreType = EFI_VFR_VARSTORE_BUFFER_BITS; + } else { + mVarStoreType = EFI_VFR_VARSTORE_BUFFER; + } + mStorageInfo.mDataType = DataType; + mAssignedFlag = Flag; +} + +SVfrVarStorageNode::SVfrVarStorageNode ( + IN CHAR8 *StoreName, + IN EFI_VARSTORE_ID VarStoreId + ) +{ + memset (&mGuid, 0, sizeof (EFI_GUID)); + if (StoreName != NULL) { + mVarStoreName = new CHAR8[strlen(StoreName) + 1]; + strcpy (mVarStoreName, StoreName); + } else { + mVarStoreName = NULL; + } + mNext = NULL; + mVarStoreId = VarStoreId; + mVarStoreType = EFI_VFR_VARSTORE_NAME; + mStorageInfo.mNameSpace.mNameTable = new EFI_VARSTORE_ID[DEFAULT_NAME_TABLE_ITEMS]; + mStorageInfo.mNameSpace.mTableSize = 0; + mAssignedFlag = FALSE; +} + +SVfrVarStorageNode::~SVfrVarStorageNode ( + VOID + ) +{ + if (mVarStoreName != NULL) { + delete[] mVarStoreName; + } + + if (mVarStoreType == EFI_VFR_VARSTORE_NAME) { + delete[] mStorageInfo.mNameSpace.mNameTable; + } +} + +CVfrDataStorage::CVfrDataStorage ( + VOID + ) +{ + UINT32 Index; + + for (Index = 0; Index < EFI_FREE_VARSTORE_ID_BITMAP_SIZE; Index++) { + mFreeVarStoreIdBitMap[Index] = 0; + } + + // Question ID 0 is reserved. + mFreeVarStoreIdBitMap[0] = 0x80000000; + + mBufferVarStoreList = NULL; + mEfiVarStoreList = NULL; + mNameVarStoreList = NULL; + mCurrVarStorageNode = NULL; + mNewVarStorageNode = NULL; + mBufferFieldInfoListHead = NULL; + mBufferFieldInfoListTail = NULL; +} + +CVfrDataStorage::~CVfrDataStorage ( + VOID + ) +{ + SVfrVarStorageNode *pNode; + + while (mBufferVarStoreList != NULL) { + pNode = mBufferVarStoreList; + mBufferVarStoreList = mBufferVarStoreList->mNext; + delete pNode; + } + while (mEfiVarStoreList != NULL) { + pNode = mEfiVarStoreList; + mEfiVarStoreList = mEfiVarStoreList->mNext; + delete pNode; + } + while (mNameVarStoreList != NULL) { + pNode = mNameVarStoreList; + mNameVarStoreList = mNameVarStoreList->mNext; + delete pNode; + } + if (mNewVarStorageNode != NULL) { + delete mNewVarStorageNode; + } +} + +EFI_VARSTORE_ID +CVfrDataStorage::GetFreeVarStoreId ( + EFI_VFR_VARSTORE_TYPE VarType + ) +{ + UINT32 Index, Mask, Offset; + + Index = 0; + + for (; Index < EFI_FREE_VARSTORE_ID_BITMAP_SIZE; Index++) { + if (mFreeVarStoreIdBitMap[Index] != 0xFFFFFFFF) { + break; + } + } + + if (Index == EFI_FREE_VARSTORE_ID_BITMAP_SIZE) { + return EFI_VARSTORE_ID_INVALID; + } + + for (Offset = 0, Mask = 0x80000000; Mask != 0; Mask >>= 1, Offset++) { + if ((mFreeVarStoreIdBitMap[Index] & Mask) == 0) { + mFreeVarStoreIdBitMap[Index] |= Mask; + return (EFI_VARSTORE_ID)((Index << EFI_BITS_SHIFT_PER_UINT32) + Offset); + } + } + + return EFI_VARSTORE_ID_INVALID; +} + +BOOLEAN +CVfrDataStorage::ChekVarStoreIdFree ( + IN EFI_VARSTORE_ID VarStoreId + ) +{ + UINT32 Index = (VarStoreId / EFI_BITS_PER_UINT32); + UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32); + + return (mFreeVarStoreIdBitMap[Index] & (0x80000000 >> Offset)) == 0; +} + +VOID +CVfrDataStorage::MarkVarStoreIdUsed ( + IN EFI_VARSTORE_ID VarStoreId + ) +{ + UINT32 Index = (VarStoreId / EFI_BITS_PER_UINT32); + UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32); + + mFreeVarStoreIdBitMap[Index] |= (0x80000000 >> Offset); +} + +VOID +CVfrDataStorage::MarkVarStoreIdUnused ( + IN EFI_VARSTORE_ID VarStoreId + ) +{ + UINT32 Index = (VarStoreId / EFI_BITS_PER_UINT32); + UINT32 Offset = (VarStoreId % EFI_BITS_PER_UINT32); + + mFreeVarStoreIdBitMap[Index] &= ~(0x80000000 >> Offset); +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::DeclareNameVarStoreBegin ( + IN CHAR8 *StoreName, + IN EFI_VARSTORE_ID VarStoreId + ) +{ + SVfrVarStorageNode *pNode = NULL; + EFI_VARSTORE_ID TmpVarStoreId; + + if (StoreName == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + if (GetVarStoreId (StoreName, &TmpVarStoreId) == VFR_RETURN_SUCCESS) { + return VFR_RETURN_REDEFINED; + } + + if (VarStoreId == EFI_VARSTORE_ID_INVALID) { + VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_NAME); + } else { + if (ChekVarStoreIdFree (VarStoreId) == FALSE) { + return VFR_RETURN_VARSTOREID_REDEFINED; + } + MarkVarStoreIdUsed (VarStoreId); + } + + if ((pNode = new SVfrVarStorageNode (StoreName, VarStoreId)) == NULL) { + return VFR_RETURN_UNDEFINED; + } + + mNewVarStorageNode = pNode; + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::NameTableAddItem ( + IN EFI_STRING_ID Item + ) +{ + EFI_VARSTORE_ID *NewTable, *OldTable; + UINT32 TableSize; + + OldTable = mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable; + TableSize = mNewVarStorageNode->mStorageInfo.mNameSpace.mTableSize; + + if ((TableSize != 0) && ((TableSize % DEFAULT_NAME_TABLE_ITEMS) == 0)) { + if ((NewTable = new EFI_VARSTORE_ID[TableSize + DEFAULT_NAME_TABLE_ITEMS]) == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + memcpy (NewTable, OldTable, TableSize); + mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable = NewTable; + } + + mNewVarStorageNode->mStorageInfo.mNameSpace.mNameTable[TableSize++] = Item; + mNewVarStorageNode->mStorageInfo.mNameSpace.mTableSize = TableSize; + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::DeclareNameVarStoreEnd ( + IN EFI_GUID *Guid + ) +{ + mNewVarStorageNode->mGuid = *Guid; + mNewVarStorageNode->mNext = mNameVarStoreList; + mNameVarStoreList = mNewVarStorageNode; + + mNewVarStorageNode = NULL; + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::DeclareEfiVarStore ( + IN CHAR8 *StoreName, + IN EFI_GUID *Guid, + IN EFI_STRING_ID NameStrId, + IN UINT32 VarSize, + IN BOOLEAN Flag + ) +{ + SVfrVarStorageNode *pNode; + EFI_VARSTORE_ID VarStoreId; + + if ((StoreName == NULL) || (Guid == NULL)) { + return VFR_RETURN_FATAL_ERROR; + } + + if (VarSize > sizeof (UINT64)) { + return VFR_RETURN_EFIVARSTORE_SIZE_ERROR; + } + + if (GetVarStoreId (StoreName, &VarStoreId, Guid) == VFR_RETURN_SUCCESS) { + return VFR_RETURN_REDEFINED; + } + + VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_EFI); + if ((pNode = new SVfrVarStorageNode (Guid, StoreName, VarStoreId, NameStrId, VarSize, Flag)) == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + + pNode->mNext = mEfiVarStoreList; + mEfiVarStoreList = pNode; + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::DeclareBufferVarStore ( + IN CHAR8 *StoreName, + IN EFI_GUID *Guid, + IN CVfrVarDataTypeDB *DataTypeDB, + IN CHAR8 *TypeName, + IN EFI_VARSTORE_ID VarStoreId, + IN BOOLEAN IsBitVarStore, + IN BOOLEAN Flag + ) +{ + SVfrVarStorageNode *pNew = NULL; + SVfrDataType *pDataType = NULL; + EFI_VARSTORE_ID TempVarStoreId; + + if ((StoreName == NULL) || (Guid == NULL) || (DataTypeDB == NULL)) { + return VFR_RETURN_FATAL_ERROR; + } + + if (GetVarStoreId (StoreName, &TempVarStoreId, Guid) == VFR_RETURN_SUCCESS) { + return VFR_RETURN_REDEFINED; + } + + CHECK_ERROR_RETURN(DataTypeDB->GetDataType (TypeName, &pDataType), VFR_RETURN_SUCCESS); + + if (VarStoreId == EFI_VARSTORE_ID_INVALID) { + VarStoreId = GetFreeVarStoreId (EFI_VFR_VARSTORE_BUFFER); + } else { + if (ChekVarStoreIdFree (VarStoreId) == FALSE) { + return VFR_RETURN_VARSTOREID_REDEFINED; + } + MarkVarStoreIdUsed (VarStoreId); + } + + if ((pNew = new SVfrVarStorageNode (Guid, StoreName, VarStoreId, pDataType, IsBitVarStore, Flag)) == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + + pNew->mNext = mBufferVarStoreList; + mBufferVarStoreList = pNew; + + if (gCVfrBufferConfig.Register(StoreName, Guid) != 0) { + return VFR_RETURN_FATAL_ERROR; + } + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::GetVarStoreByDataType ( + IN CHAR8 *DataTypeName, + OUT SVfrVarStorageNode **VarNode, + IN EFI_GUID *VarGuid + ) +{ + SVfrVarStorageNode *pNode; + SVfrVarStorageNode *MatchNode; + + MatchNode = NULL; + for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mStorageInfo.mDataType->mTypeName, DataTypeName) != 0) { + continue; + } + + if ((VarGuid != NULL)) { + if (memcmp (VarGuid, &pNode->mGuid, sizeof (EFI_GUID)) == 0) { + *VarNode = pNode; + return VFR_RETURN_SUCCESS; + } + } else { + if (MatchNode == NULL) { + MatchNode = pNode; + } else { + // + // More than one varstores referred the same data structures. + // + return VFR_RETURN_VARSTORE_DATATYPE_REDEFINED_ERROR; + } + } + } + + if (MatchNode == NULL) { + return VFR_RETURN_UNDEFINED; + } + + *VarNode = MatchNode; + return VFR_RETURN_SUCCESS; +} + +EFI_VARSTORE_ID +CVfrDataStorage::CheckGuidField ( + IN SVfrVarStorageNode *pNode, + IN EFI_GUID *StoreGuid, + IN BOOLEAN *HasFoundOne, + OUT EFI_VFR_RETURN_CODE *ReturnCode + ) +{ + if (StoreGuid != NULL) { + // + // If has guid info, compare the guid filed. + // + if (memcmp (StoreGuid, &pNode->mGuid, sizeof (EFI_GUID)) == 0) { + // + // Both name and guid are same, this this varstore. + // + mCurrVarStorageNode = pNode; + *ReturnCode = VFR_RETURN_SUCCESS; + return TRUE; + } + } else { + // + // Not has Guid field, check whether this name is the only one. + // + if (*HasFoundOne) { + // + // The name has conflict, return name redefined. + // + *ReturnCode = VFR_RETURN_VARSTORE_NAME_REDEFINED_ERROR; + return TRUE; + } + + *HasFoundOne = TRUE; + mCurrVarStorageNode = pNode; + } + + return FALSE; +} + +/** + Base on the input store name and guid to find the varstore id. + + If both name and guid are inputed, base on the name and guid to + found the varstore. If only name inputed, base on the name to + found the varstore and go on to check whether more than one varstore + has the same name. If only has found one varstore, return this + varstore; if more than one varstore has same name, return varstore + name redefined error. If no varstore found by varstore name, call + function GetVarStoreByDataType and use inputed varstore name as + data type name to search. +**/ +EFI_VFR_RETURN_CODE +CVfrDataStorage::GetVarStoreId ( + IN CHAR8 *StoreName, + OUT EFI_VARSTORE_ID *VarStoreId, + IN EFI_GUID *StoreGuid + ) +{ + EFI_VFR_RETURN_CODE ReturnCode; + SVfrVarStorageNode *pNode; + BOOLEAN HasFoundOne = FALSE; + + mCurrVarStorageNode = NULL; + + for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mVarStoreName, StoreName) == 0) { + if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) { + *VarStoreId = mCurrVarStorageNode->mVarStoreId; + return ReturnCode; + } + } + } + + for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mVarStoreName, StoreName) == 0) { + if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) { + *VarStoreId = mCurrVarStorageNode->mVarStoreId; + return ReturnCode; + } + } + } + + for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mVarStoreName, StoreName) == 0) { + if (CheckGuidField(pNode, StoreGuid, &HasFoundOne, &ReturnCode)) { + *VarStoreId = mCurrVarStorageNode->mVarStoreId; + return ReturnCode; + } + } + } + + if (HasFoundOne) { + *VarStoreId = mCurrVarStorageNode->mVarStoreId; + return VFR_RETURN_SUCCESS; + } + + *VarStoreId = EFI_VARSTORE_ID_INVALID; + + // + // Assume that Data structure name is used as StoreName, and check again. + // + ReturnCode = GetVarStoreByDataType (StoreName, &pNode, StoreGuid); + if (pNode != NULL) { + mCurrVarStorageNode = pNode; + *VarStoreId = pNode->mVarStoreId; + } + + return ReturnCode; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::GetBufferVarStoreDataTypeName ( + IN EFI_VARSTORE_ID VarStoreId, + OUT CHAR8 **DataTypeName + ) +{ + SVfrVarStorageNode *pNode; + + if (VarStoreId == EFI_VARSTORE_ID_INVALID) { + return VFR_RETURN_FATAL_ERROR; + } + + for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + *DataTypeName = pNode->mStorageInfo.mDataType->mTypeName; + return VFR_RETURN_SUCCESS; + } + } + + return VFR_RETURN_UNDEFINED; +} + +EFI_VFR_VARSTORE_TYPE +CVfrDataStorage::GetVarStoreType ( + IN EFI_VARSTORE_ID VarStoreId + ) +{ + SVfrVarStorageNode *pNode; + EFI_VFR_VARSTORE_TYPE VarStoreType; + + VarStoreType = EFI_VFR_VARSTORE_INVALID; + + if (VarStoreId == EFI_VARSTORE_ID_INVALID) { + return VarStoreType; + } + + for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + VarStoreType = pNode->mVarStoreType; + return VarStoreType; + } + } + + for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + VarStoreType = pNode->mVarStoreType; + return VarStoreType; + } + } + + for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + VarStoreType = pNode->mVarStoreType; + return VarStoreType; + } + } + + return VarStoreType; +} + +EFI_GUID * +CVfrDataStorage::GetVarStoreGuid ( + IN EFI_VARSTORE_ID VarStoreId + ) +{ + SVfrVarStorageNode *pNode; + EFI_GUID *VarGuid; + + VarGuid = NULL; + + if (VarStoreId == EFI_VARSTORE_ID_INVALID) { + return VarGuid; + } + + for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + VarGuid = &pNode->mGuid; + return VarGuid; + } + } + + for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + VarGuid = &pNode->mGuid; + return VarGuid; + } + } + + for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + VarGuid = &pNode->mGuid; + return VarGuid; + } + } + + return VarGuid; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::GetVarStoreName ( + IN EFI_VARSTORE_ID VarStoreId, + OUT CHAR8 **VarStoreName + ) +{ + SVfrVarStorageNode *pNode; + + if (VarStoreName == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + for (pNode = mBufferVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + *VarStoreName = pNode->mVarStoreName; + return VFR_RETURN_SUCCESS; + } + } + + for (pNode = mEfiVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + *VarStoreName = pNode->mVarStoreName; + return VFR_RETURN_SUCCESS; + } + } + + for (pNode = mNameVarStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mVarStoreId == VarStoreId) { + *VarStoreName = pNode->mVarStoreName; + return VFR_RETURN_SUCCESS; + } + } + + *VarStoreName = NULL; + return VFR_RETURN_UNDEFINED; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::GetEfiVarStoreInfo ( + IN OUT EFI_VARSTORE_INFO *Info + ) +{ + if (Info == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + if (mCurrVarStorageNode == NULL) { + return VFR_RETURN_GET_EFIVARSTORE_ERROR; + } + + Info->mInfo.mVarName = mCurrVarStorageNode->mStorageInfo.mEfiVar.mEfiVarName; + Info->mVarTotalSize = mCurrVarStorageNode->mStorageInfo.mEfiVar.mEfiVarSize; + switch (Info->mVarTotalSize) { + case 1: + Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_8; + break; + case 2: + Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_16; + break; + case 4: + Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_32; + break; + case 8: + Info->mVarType = EFI_IFR_TYPE_NUM_SIZE_64; + break; + default : + return VFR_RETURN_FATAL_ERROR; + } + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::AddBufferVarStoreFieldInfo ( + IN EFI_VARSTORE_INFO *Info + ) +{ + BufferVarStoreFieldInfoNode *pNew; + + if ((pNew = new BufferVarStoreFieldInfoNode(Info)) == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + if (mBufferFieldInfoListHead == NULL) { + mBufferFieldInfoListHead = pNew; + mBufferFieldInfoListTail= pNew; + } else { + mBufferFieldInfoListTail->mNext = pNew; + mBufferFieldInfoListTail = pNew; + } + + return VFR_RETURN_SUCCESS; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::GetBufferVarStoreFieldInfo ( + IN OUT EFI_VARSTORE_INFO *Info + ) +{ + BufferVarStoreFieldInfoNode *pNode; + + pNode = mBufferFieldInfoListHead; + while (pNode != NULL) { + if (Info->mVarStoreId == pNode->mVarStoreInfo.mVarStoreId && + Info->mInfo.mVarOffset == pNode->mVarStoreInfo.mInfo.mVarOffset) { + Info->mVarTotalSize = pNode->mVarStoreInfo.mVarTotalSize; + Info->mVarType = pNode->mVarStoreInfo.mVarType; + return VFR_RETURN_SUCCESS; + } + pNode = pNode->mNext; + } + return VFR_RETURN_FATAL_ERROR; +} + +EFI_VFR_RETURN_CODE +CVfrDataStorage::GetNameVarStoreInfo ( + OUT EFI_VARSTORE_INFO *Info, + IN UINT32 Index + ) +{ + if (Info == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + if (mCurrVarStorageNode == NULL) { + return VFR_RETURN_GET_NVVARSTORE_ERROR; + } + + Info->mInfo.mVarName = mCurrVarStorageNode->mStorageInfo.mNameSpace.mNameTable[Index]; + + return VFR_RETURN_SUCCESS; +} + +SVfrDefaultStoreNode::SVfrDefaultStoreNode ( + IN EFI_IFR_DEFAULTSTORE *ObjBinAddr, + IN CHAR8 *RefName, + IN EFI_STRING_ID DefaultStoreNameId, + IN UINT16 DefaultId + ) +{ + mObjBinAddr = ObjBinAddr; + + if (RefName != NULL) { + mRefName = new CHAR8[strlen (RefName) + 1]; + strcpy (mRefName, RefName); + } else { + mRefName = NULL; + } + + mNext = NULL; + mDefaultId = DefaultId; + mDefaultStoreNameId = DefaultStoreNameId; +} + +SVfrDefaultStoreNode::~SVfrDefaultStoreNode ( + VOID + ) +{ + if (mRefName != NULL) { + delete[] mRefName; + } +} + +CVfrDefaultStore::CVfrDefaultStore ( + VOID + ) +{ + mDefaultStoreList = NULL; +} + +CVfrDefaultStore::~CVfrDefaultStore ( + VOID + ) +{ + SVfrDefaultStoreNode *pTmp = NULL; + + while (mDefaultStoreList != NULL) { + pTmp = mDefaultStoreList; + mDefaultStoreList = mDefaultStoreList->mNext; + delete pTmp; + } +} + +EFI_VFR_RETURN_CODE +CVfrDefaultStore::RegisterDefaultStore ( + IN CHAR8 *ObjBinAddr, + IN CHAR8 *RefName, + IN EFI_STRING_ID DefaultStoreNameId, + IN UINT16 DefaultId + ) +{ + SVfrDefaultStoreNode *pNode = NULL; + + if (RefName == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mRefName, RefName) == 0) { + return VFR_RETURN_REDEFINED; + } + } + + if ((pNode = new SVfrDefaultStoreNode ((EFI_IFR_DEFAULTSTORE *)ObjBinAddr, RefName, DefaultStoreNameId, DefaultId)) == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + + pNode->mNext = mDefaultStoreList; + mDefaultStoreList = pNode; + + return VFR_RETURN_SUCCESS; +} + +/* + * assign new reference name or new default store name id only if + * the original is invalid + */ +EFI_VFR_RETURN_CODE +CVfrDefaultStore::ReRegisterDefaultStoreById ( + IN UINT16 DefaultId, + IN CHAR8 *RefName, + IN EFI_STRING_ID DefaultStoreNameId + ) +{ + SVfrDefaultStoreNode *pNode = NULL; + + for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mDefaultId == DefaultId) { + break; + } + } + + if (pNode == NULL) { + return VFR_RETURN_UNDEFINED; + } else { + if (pNode->mDefaultStoreNameId == EFI_STRING_ID_INVALID) { + pNode->mDefaultStoreNameId = DefaultStoreNameId; + if (pNode->mObjBinAddr != NULL) { + pNode->mObjBinAddr->DefaultName = DefaultStoreNameId; + } + } else { + return VFR_RETURN_REDEFINED; + } + + if (RefName != NULL) { + delete pNode->mRefName; + pNode->mRefName = new CHAR8[strlen (RefName) + 1]; + if (pNode->mRefName != NULL) { + strcpy (pNode->mRefName, RefName); + } + } + } + + return VFR_RETURN_SUCCESS; +} + +BOOLEAN +CVfrDefaultStore::DefaultIdRegistered ( + IN UINT16 DefaultId + ) +{ + SVfrDefaultStoreNode *pNode = NULL; + + for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mDefaultId == DefaultId) { + return TRUE; + } + } + + return FALSE; +} + +EFI_VFR_RETURN_CODE +CVfrDefaultStore::GetDefaultId ( + IN CHAR8 *RefName, + OUT UINT16 *DefaultId + ) +{ + SVfrDefaultStoreNode *pTmp = NULL; + + if (DefaultId == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + for (pTmp = mDefaultStoreList; pTmp != NULL; pTmp = pTmp->mNext) { + if (strcmp (pTmp->mRefName, RefName) == 0) { + *DefaultId = pTmp->mDefaultId; + return VFR_RETURN_SUCCESS; + } + } + + return VFR_RETURN_UNDEFINED; +} + +EFI_VFR_RETURN_CODE +CVfrDefaultStore::BufferVarStoreAltConfigAdd ( + IN EFI_VARSTORE_ID DefaultId, + IN EFI_VARSTORE_INFO &Info, + IN CHAR8 *VarStoreName, + IN EFI_GUID *VarStoreGuid, + IN UINT8 Type, + IN EFI_IFR_TYPE_VALUE Value + ) +{ + SVfrDefaultStoreNode *pNode = NULL; + CHAR8 NewAltCfg[2 * 2 * sizeof (UINT16) + 1] = {0,}; + INTN Returnvalue = 0; + + if (VarStoreName == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + for (pNode = mDefaultStoreList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mDefaultId == DefaultId) { + break; + } + } + + if (pNode == NULL) { + return VFR_RETURN_UNDEFINED; + } + + gCVfrBufferConfig.Open (); + + sprintf (NewAltCfg, "%04x", pNode->mDefaultId); + if ((Returnvalue = gCVfrBufferConfig.Select(VarStoreName, VarStoreGuid)) == 0) { + if ((Returnvalue = gCVfrBufferConfig.Write ('a', VarStoreName, VarStoreGuid, NewAltCfg, Type, Info.mInfo.mVarOffset, Info.mVarTotalSize, Value)) != 0) { + goto WriteError; + } + } + + gCVfrBufferConfig.Close (); + + return VFR_RETURN_SUCCESS; + +WriteError: + gCVfrBufferConfig.Close (); + return (EFI_VFR_RETURN_CODE)Returnvalue; +} + +SVfrRuleNode::SVfrRuleNode ( + IN CHAR8 *RuleName, + IN UINT8 RuleId + ) +{ + if (RuleName != NULL) { + mRuleName = new CHAR8[strlen (RuleName) + 1]; + strcpy (mRuleName, RuleName); + } else { + mRuleName = NULL; + } + + mNext = NULL; + mRuleId = RuleId; +} + +SVfrRuleNode::~SVfrRuleNode ( + VOID + ) +{ + if (mRuleName != NULL) { + delete[] mRuleName; + } +} + +CVfrRulesDB::CVfrRulesDB () +{ + mRuleList = NULL; + mFreeRuleId = EFI_VARSTORE_ID_START; +} + +CVfrRulesDB::~CVfrRulesDB () +{ + SVfrRuleNode *pNode; + + while(mRuleList != NULL) { + pNode = mRuleList; + mRuleList = mRuleList->mNext; + delete pNode; + } +} + +VOID +CVfrRulesDB::RegisterRule ( + IN CHAR8 *RuleName + ) +{ + SVfrRuleNode *pNew; + + if (RuleName == NULL) { + return ; + } + + if ((pNew = new SVfrRuleNode (RuleName, mFreeRuleId)) == NULL) { + return ; + } + + mFreeRuleId++; + + pNew->mNext = mRuleList; + mRuleList = pNew; +} + +UINT8 +CVfrRulesDB::GetRuleId ( + IN CHAR8 *RuleName + ) +{ + SVfrRuleNode *pNode; + + if (RuleName == NULL) { + return EFI_RULE_ID_INVALID; + } + + for (pNode = mRuleList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mRuleName, RuleName) == 0) { + return pNode->mRuleId; + } + } + + return EFI_RULE_ID_INVALID; +} + +CVfrRulesDB gCVfrRulesDB; + +EFI_VARSTORE_INFO::EFI_VARSTORE_INFO ( + VOID + ) +{ + mVarStoreId = EFI_VARSTORE_ID_INVALID; + mInfo.mVarName = EFI_STRING_ID_INVALID; + mInfo.mVarOffset = EFI_VAROFFSET_INVALID; + mVarType = EFI_IFR_TYPE_OTHER; + mVarTotalSize = 0; + mIsBitVar = FALSE; +} + +EFI_VARSTORE_INFO::EFI_VARSTORE_INFO ( + IN EFI_VARSTORE_INFO &Info + ) +{ + mVarStoreId = Info.mVarStoreId; + mInfo.mVarName = Info.mInfo.mVarName; + mInfo.mVarOffset = Info.mInfo.mVarOffset; + mVarType = Info.mVarType; + mVarTotalSize = Info.mVarTotalSize; + mIsBitVar = Info.mIsBitVar; +} + +EFI_VARSTORE_INFO& +EFI_VARSTORE_INFO::operator= ( + IN CONST EFI_VARSTORE_INFO &Info + ) +{ + if (this != &Info) { + mVarStoreId = Info.mVarStoreId; + mInfo.mVarName = Info.mInfo.mVarName; + mInfo.mVarOffset = Info.mInfo.mVarOffset; + mVarType = Info.mVarType; + mVarTotalSize = Info.mVarTotalSize; + mIsBitVar = Info.mIsBitVar; + } + + return *this; +} + +BOOLEAN +EFI_VARSTORE_INFO::operator == ( + IN EFI_VARSTORE_INFO *Info + ) +{ + if ((mVarStoreId == Info->mVarStoreId) && + (mInfo.mVarName == Info->mInfo.mVarName) && + (mInfo.mVarOffset == Info->mInfo.mVarOffset) && + (mVarType == Info->mVarType) && + (mVarTotalSize == Info->mVarTotalSize) && + (mIsBitVar == Info->mIsBitVar)) { + return TRUE; + } + + return FALSE; +} + +BufferVarStoreFieldInfoNode::BufferVarStoreFieldInfoNode( + IN EFI_VARSTORE_INFO *Info + ) +{ + mVarStoreInfo.mVarType = Info->mVarType; + mVarStoreInfo.mVarTotalSize = Info->mVarTotalSize; + mVarStoreInfo.mInfo.mVarOffset = Info->mInfo.mVarOffset; + mVarStoreInfo.mVarStoreId = Info->mVarStoreId; + mNext = NULL; +} + +BufferVarStoreFieldInfoNode::~BufferVarStoreFieldInfoNode () +{ + mVarStoreInfo.mVarType = EFI_IFR_TYPE_OTHER; + mVarStoreInfo.mVarTotalSize = 0; + mVarStoreInfo.mInfo.mVarOffset = EFI_VAROFFSET_INVALID; + mVarStoreInfo.mVarStoreId = EFI_VARSTORE_ID_INVALID; + mNext = NULL; +} + +static EFI_VARSTORE_INFO gEfiInvalidVarStoreInfo; + +EFI_QUESTION_ID +CVfrQuestionDB::GetFreeQuestionId ( + VOID + ) +{ + UINT32 Index, Mask, Offset; + + for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) { + if (mFreeQIdBitMap[Index] != 0xFFFFFFFF) { + break; + } + } + + if (Index == EFI_FREE_QUESTION_ID_BITMAP_SIZE) { + return EFI_QUESTION_ID_INVALID; + } + + for (Offset = 0, Mask = 0x80000000; Mask != 0; Mask >>= 1, Offset++) { + if ((mFreeQIdBitMap[Index] & Mask) == 0) { + mFreeQIdBitMap[Index] |= Mask; + return (EFI_QUESTION_ID)((Index << EFI_BITS_SHIFT_PER_UINT32) + Offset); + } + } + + return EFI_QUESTION_ID_INVALID; +} + +BOOLEAN +CVfrQuestionDB::ChekQuestionIdFree ( + IN EFI_QUESTION_ID QId + ) +{ + UINT32 Index = (QId / EFI_BITS_PER_UINT32); + UINT32 Offset = (QId % EFI_BITS_PER_UINT32); + + return (mFreeQIdBitMap[Index] & (0x80000000 >> Offset)) == 0; +} + +VOID +CVfrQuestionDB::MarkQuestionIdUsed ( + IN EFI_QUESTION_ID QId + ) +{ + UINT32 Index = (QId / EFI_BITS_PER_UINT32); + UINT32 Offset = (QId % EFI_BITS_PER_UINT32); + + mFreeQIdBitMap[Index] |= (0x80000000 >> Offset); +} + +VOID +CVfrQuestionDB::MarkQuestionIdUnused ( + IN EFI_QUESTION_ID QId + ) +{ + UINT32 Index = (QId / EFI_BITS_PER_UINT32); + UINT32 Offset = (QId % EFI_BITS_PER_UINT32); + + mFreeQIdBitMap[Index] &= ~(0x80000000 >> Offset); +} + +SVfrQuestionNode::SVfrQuestionNode ( + IN CHAR8 *Name, + IN CHAR8 *VarIdStr, + IN UINT32 BitMask + ) +{ + mName = NULL; + mVarIdStr = NULL; + mQuestionId = EFI_QUESTION_ID_INVALID; + mBitMask = BitMask; + mNext = NULL; + mQtype = QUESTION_NORMAL; + + if (Name == NULL) { + mName = new CHAR8[strlen ("$DEFAULT") + 1]; + strcpy (mName, "$DEFAULT"); + } else { + mName = new CHAR8[strlen (Name) + 1]; + strcpy (mName, Name); + } + + if (VarIdStr != NULL) { + mVarIdStr = new CHAR8[strlen (VarIdStr) + 1]; + strcpy (mVarIdStr, VarIdStr); + } else { + mVarIdStr = new CHAR8[strlen ("$") + 1]; + strcpy (mVarIdStr, "$"); + } +} + +SVfrQuestionNode::~SVfrQuestionNode ( + VOID + ) +{ + if (mName != NULL) { + delete[] mName; + } + + if (mVarIdStr != NULL) { + delete[] mVarIdStr; + } +} + +CVfrQuestionDB::CVfrQuestionDB () +{ + UINT32 Index; + + for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) { + mFreeQIdBitMap[Index] = 0; + } + + // Question ID 0 is reserved. + mFreeQIdBitMap[0] = 0x80000000; + mQuestionList = NULL; +} + +CVfrQuestionDB::~CVfrQuestionDB () +{ + SVfrQuestionNode *pNode; + + while (mQuestionList != NULL) { + pNode = mQuestionList; + mQuestionList = mQuestionList->mNext; + delete pNode; + } +} + +// +// Reset to init state +// +VOID +CVfrQuestionDB::ResetInit( + IN VOID + ) +{ + UINT32 Index; + SVfrQuestionNode *pNode; + + while (mQuestionList != NULL) { + pNode = mQuestionList; + mQuestionList = mQuestionList->mNext; + delete pNode; + } + + for (Index = 0; Index < EFI_FREE_QUESTION_ID_BITMAP_SIZE; Index++) { + mFreeQIdBitMap[Index] = 0; + } + + // Question ID 0 is reserved. + mFreeQIdBitMap[0] = 0x80000000; + mQuestionList = NULL; +} + +VOID +CVfrQuestionDB::PrintAllQuestion ( + VOID + ) +{ + SVfrQuestionNode *pNode = NULL; + + for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) { + printf ("Question VarId is %s and QuestionId is 0x%x\n", pNode->mVarIdStr, pNode->mQuestionId); + } +} + +EFI_VFR_RETURN_CODE +CVfrQuestionDB::RegisterQuestion ( + IN CHAR8 *Name, + IN CHAR8 *VarIdStr, + IN OUT EFI_QUESTION_ID &QuestionId + ) +{ + SVfrQuestionNode *pNode = NULL; + + if ((Name != NULL) && (FindQuestion(Name) == VFR_RETURN_SUCCESS)) { + return VFR_RETURN_REDEFINED; + } + + if ((pNode = new SVfrQuestionNode (Name, VarIdStr)) == NULL) { + return VFR_RETURN_OUT_FOR_RESOURCES; + } + + if (QuestionId == EFI_QUESTION_ID_INVALID) { + QuestionId = GetFreeQuestionId (); + } else { + if (ChekQuestionIdFree (QuestionId) == FALSE) { + delete pNode; + return VFR_RETURN_QUESTIONID_REDEFINED; + } + MarkQuestionIdUsed (QuestionId); + } + pNode->mQuestionId = QuestionId; + + pNode->mNext = mQuestionList; + mQuestionList = pNode; + + gCFormPkg.DoPendingAssign (VarIdStr, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + + return VFR_RETURN_SUCCESS; +} + +VOID +CVfrQuestionDB::RegisterOldDateQuestion ( + IN CHAR8 *YearVarId, + IN CHAR8 *MonthVarId, + IN CHAR8 *DayVarId, + IN OUT EFI_QUESTION_ID &QuestionId + ) +{ + SVfrQuestionNode *pNode[3] = {NULL, }; + UINT32 Index; + + if ((YearVarId == NULL) || (MonthVarId == NULL) || (DayVarId == NULL)) { + return; + } + + if ((pNode[0] = new SVfrQuestionNode (NULL, YearVarId, DATE_YEAR_BITMASK)) == NULL) { + goto Err; + } + if ((pNode[1] = new SVfrQuestionNode (NULL, MonthVarId, DATE_MONTH_BITMASK)) == NULL) { + goto Err; + } + if ((pNode[2] = new SVfrQuestionNode (NULL, DayVarId, DATE_DAY_BITMASK)) == NULL) { + goto Err; + } + + if (QuestionId == EFI_QUESTION_ID_INVALID) { + QuestionId = GetFreeQuestionId (); + } else { + if (ChekQuestionIdFree (QuestionId) == FALSE) { + goto Err; + } + MarkQuestionIdUsed (QuestionId); + } + + pNode[0]->mQuestionId = QuestionId; + pNode[1]->mQuestionId = QuestionId; + pNode[2]->mQuestionId = QuestionId; + pNode[0]->mQtype = QUESTION_DATE; + pNode[1]->mQtype = QUESTION_DATE; + pNode[2]->mQtype = QUESTION_DATE; + pNode[0]->mNext = pNode[1]; + pNode[1]->mNext = pNode[2]; + pNode[2]->mNext = mQuestionList; + mQuestionList = pNode[0]; + + gCFormPkg.DoPendingAssign (YearVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (MonthVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (DayVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + + return; + +Err: + for (Index = 0; Index < 3; Index++) { + if (pNode[Index] != NULL) { + delete pNode[Index]; + } + } + QuestionId = EFI_QUESTION_ID_INVALID; +} + +VOID +CVfrQuestionDB::RegisterNewDateQuestion ( + IN CHAR8 *Name, + IN CHAR8 *BaseVarId, + IN OUT EFI_QUESTION_ID &QuestionId + ) +{ + SVfrQuestionNode *pNode[3] = {NULL, }; + UINT32 Len; + CHAR8 *VarIdStr[3] = {NULL, }; + CHAR8 Index; + + if (BaseVarId == NULL && Name == NULL) { + if (QuestionId == EFI_QUESTION_ID_INVALID) { + QuestionId = GetFreeQuestionId (); + } else { + if (ChekQuestionIdFree (QuestionId) == FALSE) { + goto Err; + } + MarkQuestionIdUsed (QuestionId); + } + return; + } + + if (BaseVarId != NULL) { + Len = strlen (BaseVarId); + + VarIdStr[0] = new CHAR8[Len + strlen (".Year") + 1]; + if (VarIdStr[0] != NULL) { + strcpy (VarIdStr[0], BaseVarId); + strcat (VarIdStr[0], ".Year"); + } + VarIdStr[1] = new CHAR8[Len + strlen (".Month") + 1]; + if (VarIdStr[1] != NULL) { + strcpy (VarIdStr[1], BaseVarId); + strcat (VarIdStr[1], ".Month"); + } + VarIdStr[2] = new CHAR8[Len + strlen (".Day") + 1]; + if (VarIdStr[2] != NULL) { + strcpy (VarIdStr[2], BaseVarId); + strcat (VarIdStr[2], ".Day"); + } + } else { + Len = strlen (Name); + + VarIdStr[0] = new CHAR8[Len + strlen (".Year") + 1]; + if (VarIdStr[0] != NULL) { + strcpy (VarIdStr[0], Name); + strcat (VarIdStr[0], ".Year"); + } + VarIdStr[1] = new CHAR8[Len + strlen (".Month") + 1]; + if (VarIdStr[1] != NULL) { + strcpy (VarIdStr[1], Name); + strcat (VarIdStr[1], ".Month"); + } + VarIdStr[2] = new CHAR8[Len + strlen (".Day") + 1]; + if (VarIdStr[2] != NULL) { + strcpy (VarIdStr[2], Name); + strcat (VarIdStr[2], ".Day"); + } + } + + if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0], DATE_YEAR_BITMASK)) == NULL) { + goto Err; + } + if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1], DATE_MONTH_BITMASK)) == NULL) { + goto Err; + } + if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2], DATE_DAY_BITMASK)) == NULL) { + goto Err; + } + + if (QuestionId == EFI_QUESTION_ID_INVALID) { + QuestionId = GetFreeQuestionId (); + } else { + if (ChekQuestionIdFree (QuestionId) == FALSE) { + goto Err; + } + MarkQuestionIdUsed (QuestionId); + } + + pNode[0]->mQuestionId = QuestionId; + pNode[1]->mQuestionId = QuestionId; + pNode[2]->mQuestionId = QuestionId; + pNode[0]->mQtype = QUESTION_DATE; + pNode[1]->mQtype = QUESTION_DATE; + pNode[2]->mQtype = QUESTION_DATE; + pNode[0]->mNext = pNode[1]; + pNode[1]->mNext = pNode[2]; + pNode[2]->mNext = mQuestionList; + mQuestionList = pNode[0]; + + for (Index = 0; Index < 3; Index++) { + if (VarIdStr[Index] != NULL) { + delete[] VarIdStr[Index]; + VarIdStr[Index] = NULL; + } + } + + gCFormPkg.DoPendingAssign (VarIdStr[0], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (VarIdStr[1], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (VarIdStr[2], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + + return; + +Err: + for (Index = 0; Index < 3; Index++) { + if (pNode[Index] != NULL) { + delete pNode[Index]; + } + + if (VarIdStr[Index] != NULL) { + delete[] VarIdStr [Index]; + VarIdStr [Index] = NULL; + } + } +} + +VOID +CVfrQuestionDB::RegisterOldTimeQuestion ( + IN CHAR8 *HourVarId, + IN CHAR8 *MinuteVarId, + IN CHAR8 *SecondVarId, + IN OUT EFI_QUESTION_ID &QuestionId + ) +{ + SVfrQuestionNode *pNode[3] = {NULL, }; + UINT32 Index; + + if ((HourVarId == NULL) || (MinuteVarId == NULL) || (SecondVarId == NULL)) { + return; + } + + if ((pNode[0] = new SVfrQuestionNode (NULL, HourVarId, TIME_HOUR_BITMASK)) == NULL) { + goto Err; + } + if ((pNode[1] = new SVfrQuestionNode (NULL, MinuteVarId, TIME_MINUTE_BITMASK)) == NULL) { + goto Err; + } + if ((pNode[2] = new SVfrQuestionNode (NULL, SecondVarId, TIME_SECOND_BITMASK)) == NULL) { + goto Err; + } + + if (QuestionId == EFI_QUESTION_ID_INVALID) { + QuestionId = GetFreeQuestionId (); + } else { + if (ChekQuestionIdFree (QuestionId) == FALSE) { + goto Err; + } + MarkQuestionIdUsed (QuestionId); + } + + pNode[0]->mQuestionId = QuestionId; + pNode[1]->mQuestionId = QuestionId; + pNode[2]->mQuestionId = QuestionId; + pNode[0]->mQtype = QUESTION_TIME; + pNode[1]->mQtype = QUESTION_TIME; + pNode[2]->mQtype = QUESTION_TIME; + pNode[0]->mNext = pNode[1]; + pNode[1]->mNext = pNode[2]; + pNode[2]->mNext = mQuestionList; + mQuestionList = pNode[0]; + + gCFormPkg.DoPendingAssign (HourVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (MinuteVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (SecondVarId, (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + + return; + +Err: + for (Index = 0; Index < 3; Index++) { + if (pNode[Index] != NULL) { + delete pNode[Index]; + } + } + QuestionId = EFI_QUESTION_ID_INVALID; +} + +VOID +CVfrQuestionDB::RegisterNewTimeQuestion ( + IN CHAR8 *Name, + IN CHAR8 *BaseVarId, + IN OUT EFI_QUESTION_ID &QuestionId + ) +{ + SVfrQuestionNode *pNode[3] = {NULL, }; + UINT32 Len; + CHAR8 *VarIdStr[3] = {NULL, }; + CHAR8 Index; + + if (BaseVarId == NULL && Name == NULL) { + if (QuestionId == EFI_QUESTION_ID_INVALID) { + QuestionId = GetFreeQuestionId (); + } else { + if (ChekQuestionIdFree (QuestionId) == FALSE) { + goto Err; + } + MarkQuestionIdUsed (QuestionId); + } + return; + } + + if (BaseVarId != NULL) { + Len = strlen (BaseVarId); + + VarIdStr[0] = new CHAR8[Len + strlen (".Hour") + 1]; + if (VarIdStr[0] != NULL) { + strcpy (VarIdStr[0], BaseVarId); + strcat (VarIdStr[0], ".Hour"); + } + VarIdStr[1] = new CHAR8[Len + strlen (".Minute") + 1]; + if (VarIdStr[1] != NULL) { + strcpy (VarIdStr[1], BaseVarId); + strcat (VarIdStr[1], ".Minute"); + } + VarIdStr[2] = new CHAR8[Len + strlen (".Second") + 1]; + if (VarIdStr[2] != NULL) { + strcpy (VarIdStr[2], BaseVarId); + strcat (VarIdStr[2], ".Second"); + } + } else { + Len = strlen (Name); + + VarIdStr[0] = new CHAR8[Len + strlen (".Hour") + 1]; + if (VarIdStr[0] != NULL) { + strcpy (VarIdStr[0], Name); + strcat (VarIdStr[0], ".Hour"); + } + VarIdStr[1] = new CHAR8[Len + strlen (".Minute") + 1]; + if (VarIdStr[1] != NULL) { + strcpy (VarIdStr[1], Name); + strcat (VarIdStr[1], ".Minute"); + } + VarIdStr[2] = new CHAR8[Len + strlen (".Second") + 1]; + if (VarIdStr[2] != NULL) { + strcpy (VarIdStr[2], Name); + strcat (VarIdStr[2], ".Second"); + } + } + + if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0], TIME_HOUR_BITMASK)) == NULL) { + goto Err; + } + if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1], TIME_MINUTE_BITMASK)) == NULL) { + goto Err; + } + if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2], TIME_SECOND_BITMASK)) == NULL) { + goto Err; + } + + if (QuestionId == EFI_QUESTION_ID_INVALID) { + QuestionId = GetFreeQuestionId (); + } else { + if (ChekQuestionIdFree (QuestionId) == FALSE) { + goto Err; + } + MarkQuestionIdUsed (QuestionId); + } + + pNode[0]->mQuestionId = QuestionId; + pNode[1]->mQuestionId = QuestionId; + pNode[2]->mQuestionId = QuestionId; + pNode[0]->mQtype = QUESTION_TIME; + pNode[1]->mQtype = QUESTION_TIME; + pNode[2]->mQtype = QUESTION_TIME; + pNode[0]->mNext = pNode[1]; + pNode[1]->mNext = pNode[2]; + pNode[2]->mNext = mQuestionList; + mQuestionList = pNode[0]; + + for (Index = 0; Index < 3; Index++) { + if (VarIdStr[Index] != NULL) { + delete[] VarIdStr[Index]; + VarIdStr[Index] = NULL; + } + } + + gCFormPkg.DoPendingAssign (VarIdStr[0], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (VarIdStr[1], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (VarIdStr[2], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + + return; + +Err: + for (Index = 0; Index < 3; Index++) { + if (pNode[Index] != NULL) { + delete pNode[Index]; + } + + if (VarIdStr[Index] != NULL) { + delete[] VarIdStr[Index]; + VarIdStr[Index] = NULL; + } + } +} + +VOID +CVfrQuestionDB::RegisterRefQuestion ( + IN CHAR8 *Name, + IN CHAR8 *BaseVarId, + IN OUT EFI_QUESTION_ID &QuestionId + ) +{ + SVfrQuestionNode *pNode[4] = {NULL, }; + UINT32 Len; + CHAR8 *VarIdStr[4] = {NULL, }; + CHAR8 Index; + + if (BaseVarId == NULL && Name == NULL) { + return; + } + + if (BaseVarId != NULL) { + Len = strlen (BaseVarId); + + VarIdStr[0] = new CHAR8[Len + strlen (".QuestionId") + 1]; + if (VarIdStr[0] != NULL) { + strcpy (VarIdStr[0], BaseVarId); + strcat (VarIdStr[0], ".QuestionId"); + } + VarIdStr[1] = new CHAR8[Len + strlen (".FormId") + 1]; + if (VarIdStr[1] != NULL) { + strcpy (VarIdStr[1], BaseVarId); + strcat (VarIdStr[1], ".FormId"); + } + VarIdStr[2] = new CHAR8[Len + strlen (".FormSetGuid") + 1]; + if (VarIdStr[2] != NULL) { + strcpy (VarIdStr[2], BaseVarId); + strcat (VarIdStr[2], ".FormSetGuid"); + } + VarIdStr[3] = new CHAR8[Len + strlen (".DevicePath") + 1]; + if (VarIdStr[3] != NULL) { + strcpy (VarIdStr[3], BaseVarId); + strcat (VarIdStr[3], ".DevicePath"); + } + } else { + Len = strlen (Name); + + VarIdStr[0] = new CHAR8[Len + strlen (".QuestionId") + 1]; + if (VarIdStr[0] != NULL) { + strcpy (VarIdStr[0], Name); + strcat (VarIdStr[0], ".QuestionId"); + } + VarIdStr[1] = new CHAR8[Len + strlen (".FormId") + 1]; + if (VarIdStr[1] != NULL) { + strcpy (VarIdStr[1], Name); + strcat (VarIdStr[1], ".FormId"); + } + VarIdStr[2] = new CHAR8[Len + strlen (".FormSetGuid") + 1]; + if (VarIdStr[2] != NULL) { + strcpy (VarIdStr[2], Name); + strcat (VarIdStr[2], ".FormSetGuid"); + } + VarIdStr[3] = new CHAR8[Len + strlen (".DevicePath") + 1]; + if (VarIdStr[3] != NULL) { + strcpy (VarIdStr[3], Name); + strcat (VarIdStr[3], ".DevicePath"); + } + } + + if ((pNode[0] = new SVfrQuestionNode (Name, VarIdStr[0])) == NULL) { + goto Err; + } + if ((pNode[1] = new SVfrQuestionNode (Name, VarIdStr[1])) == NULL) { + goto Err; + } + if ((pNode[2] = new SVfrQuestionNode (Name, VarIdStr[2])) == NULL) { + goto Err; + } + if ((pNode[3] = new SVfrQuestionNode (Name, VarIdStr[3])) == NULL) { + goto Err; + } + + if (QuestionId == EFI_QUESTION_ID_INVALID) { + QuestionId = GetFreeQuestionId (); + } else { + if (ChekQuestionIdFree (QuestionId) == FALSE) { + goto Err; + } + MarkQuestionIdUsed (QuestionId); + } + + pNode[0]->mQuestionId = QuestionId; + pNode[1]->mQuestionId = QuestionId; + pNode[2]->mQuestionId = QuestionId; + pNode[3]->mQuestionId = QuestionId; + pNode[0]->mQtype = QUESTION_REF; + pNode[1]->mQtype = QUESTION_REF; + pNode[2]->mQtype = QUESTION_REF; + pNode[3]->mQtype = QUESTION_REF; + pNode[0]->mNext = pNode[1]; + pNode[1]->mNext = pNode[2]; + pNode[2]->mNext = pNode[3]; + pNode[3]->mNext = mQuestionList; + mQuestionList = pNode[0]; + + gCFormPkg.DoPendingAssign (VarIdStr[0], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (VarIdStr[1], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (VarIdStr[2], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + gCFormPkg.DoPendingAssign (VarIdStr[3], (VOID *)&QuestionId, sizeof(EFI_QUESTION_ID)); + + return; + + Err: + for (Index = 0; Index < 4; Index++) { + if (pNode[Index] != NULL) { + delete pNode[Index]; + } + + if (VarIdStr[Index] != NULL) { + delete VarIdStr[Index]; + } + } +} + +EFI_VFR_RETURN_CODE +CVfrQuestionDB::UpdateQuestionId ( + IN EFI_QUESTION_ID QId, + IN EFI_QUESTION_ID NewQId + ) +{ + SVfrQuestionNode *pNode = NULL; + + if (QId == NewQId) { + // don't update + return VFR_RETURN_SUCCESS; + } + + if (ChekQuestionIdFree (NewQId) == FALSE) { + return VFR_RETURN_REDEFINED; + } + + for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mQuestionId == QId) { + break; + } + } + + if (pNode == NULL) { + return VFR_RETURN_UNDEFINED; + } + + MarkQuestionIdUnused (QId); + pNode->mQuestionId = NewQId; + MarkQuestionIdUsed (NewQId); + + gCFormPkg.DoPendingAssign (pNode->mVarIdStr, (VOID *)&NewQId, sizeof(EFI_QUESTION_ID)); + + return VFR_RETURN_SUCCESS; +} + +VOID +CVfrQuestionDB::GetQuestionId ( + IN CHAR8 *Name, + IN CHAR8 *VarIdStr, + OUT EFI_QUESTION_ID &QuestionId, + OUT UINT32 &BitMask, + OUT EFI_QUESION_TYPE *QType + ) +{ + SVfrQuestionNode *pNode; + + QuestionId = EFI_QUESTION_ID_INVALID; + BitMask = 0x00000000; + if (QType != NULL) { + *QType = QUESTION_NORMAL; + } + + if ((Name == NULL) && (VarIdStr == NULL)) { + return ; + } + + for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) { + if (Name != NULL) { + if (strcmp (pNode->mName, Name) != 0) { + continue; + } + } + + if (VarIdStr != NULL) { + if (strcmp (pNode->mVarIdStr, VarIdStr) != 0) { + continue; + } + } + + QuestionId = pNode->mQuestionId; + BitMask = pNode->mBitMask; + if (QType != NULL) { + *QType = pNode->mQtype; + } + break; + } + + return ; +} + +EFI_VFR_RETURN_CODE +CVfrQuestionDB::FindQuestion ( + IN EFI_QUESTION_ID QuestionId + ) +{ + SVfrQuestionNode *pNode; + + if (QuestionId == EFI_QUESTION_ID_INVALID) { + return VFR_RETURN_INVALID_PARAMETER; + } + + for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) { + if (pNode->mQuestionId == QuestionId) { + return VFR_RETURN_SUCCESS; + } + } + + return VFR_RETURN_UNDEFINED; +} + +EFI_VFR_RETURN_CODE +CVfrQuestionDB::FindQuestion ( + IN CHAR8 *Name + ) +{ + SVfrQuestionNode *pNode; + + if (Name == NULL) { + return VFR_RETURN_FATAL_ERROR; + } + + for (pNode = mQuestionList; pNode != NULL; pNode = pNode->mNext) { + if (strcmp (pNode->mName, Name) == 0) { + return VFR_RETURN_SUCCESS; + } + } + + return VFR_RETURN_UNDEFINED; +} + +CVfrStringDB::CVfrStringDB () +{ + mStringFileName = NULL; +} + +CVfrStringDB::~CVfrStringDB () +{ + if (mStringFileName != NULL) { + delete[] mStringFileName; + } + mStringFileName = NULL; +} + + +VOID +CVfrStringDB::SetStringFileName(IN CHAR8 *StringFileName) +{ + UINT32 FileLen = 0; + + if (StringFileName == NULL) { + return; + } + + if (mStringFileName != NULL) { + delete[] mStringFileName; + } + + FileLen = strlen (StringFileName) + 1; + mStringFileName = new CHAR8[FileLen]; + if (mStringFileName == NULL) { + return; + } + + strcpy (mStringFileName, StringFileName); + mStringFileName[FileLen - 1] = '\0'; +} + + +/** + Returns TRUE or FALSE whether SupportedLanguages contains the best matching language + from a set of supported languages. + + @param[in] SupportedLanguages A pointer to a Null-terminated ASCII string that + contains a set of language codes. + @param[in] Language A variable that contains pointers to Null-terminated + ASCII strings that contain one language codes. + + @retval FALSE The best matching language could not be found in SupportedLanguages. + @retval TRUE The best matching language could be found in SupportedLanguages. + +**/ +BOOLEAN +CVfrStringDB::GetBestLanguage ( + IN CONST CHAR8 *SupportedLanguages, + IN CHAR8 *Language + ) +{ + UINTN CompareLength; + UINTN LanguageLength; + CONST CHAR8 *Supported; + + if (SupportedLanguages == NULL || Language == NULL){ + return FALSE; + } + + // + // Determine the length of the first RFC 4646 language code in Language + // + for (LanguageLength = 0; Language[LanguageLength] != 0 && Language[LanguageLength] != ';'; LanguageLength++); + + // + // Trim back the length of Language used until it is empty + // + while (LanguageLength > 0) { + // + // Loop through all language codes in SupportedLanguages + // + for (Supported = SupportedLanguages; *Supported != '\0'; Supported += CompareLength) { + // + // Skip ';' characters in Supported + // + for (; *Supported != '\0' && *Supported == ';'; Supported++); + // + // Determine the length of the next language code in Supported + // + for (CompareLength = 0; Supported[CompareLength] != 0 && Supported[CompareLength] != ';'; CompareLength++); + // + // If Language is longer than the Supported, then skip to the next language + // + if (LanguageLength > CompareLength) { + continue; + } + + // + // See if the first LanguageLength characters in Supported match Language + // + if (strncmp (Supported, Language, LanguageLength) == 0) { + return TRUE; + } + } + + // + // Trim Language from the right to the next '-' character + // + for (LanguageLength--; LanguageLength > 0 && Language[LanguageLength] != '-'; LanguageLength--); + } + + // + // No matches were found + // + return FALSE; +} + + +CHAR8 * +CVfrStringDB::GetVarStoreNameFormStringId ( + IN EFI_STRING_ID StringId + ) +{ + FILE *pInFile = NULL; + UINT32 NameOffset; + INT32 Length; + UINT8 *StringPtr; + CHAR8 *StringName; + CHAR16 *UnicodeString; + CHAR8 *VarStoreName = NULL; + CHAR8 *DestTmp; + UINT8 *Current; + EFI_STATUS Status; + CHAR8 LineBuf[EFI_IFR_MAX_LENGTH]; + UINT8 BlockType; + EFI_HII_STRING_PACKAGE_HDR *PkgHeader; + + if (mStringFileName == NULL) { + return NULL; + } + + if ((pInFile = fopen (LongFilePath (mStringFileName), "rb")) == NULL) { + return NULL; + } + + // + // Get file length. + // + fseek (pInFile, 0, SEEK_END); + Length = ftell (pInFile); + fseek (pInFile, 0, SEEK_SET); + + // + // Get file data. + // + StringPtr = new UINT8[Length]; + if (StringPtr == NULL) { + fclose (pInFile); + return NULL; + } + fread ((char *)StringPtr, sizeof (UINT8), Length, pInFile); + fclose (pInFile); + + PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) StringPtr; + // + // Check the String package. + // + if (PkgHeader->Header.Type != EFI_HII_PACKAGE_STRINGS) { + delete[] StringPtr; + return NULL; + } + + // + // Search the language, get best language base on RFC 4647 matching algorithm. + // + Current = StringPtr; + while (!GetBestLanguage ("en", PkgHeader->Language)) { + Current += PkgHeader->Header.Length; + PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) Current; + // + // If can't find string package base on language, just return the first string package. + // + if (Current - StringPtr >= Length) { + Current = StringPtr; + PkgHeader = (EFI_HII_STRING_PACKAGE_HDR *) StringPtr; + break; + } + } + + Current += PkgHeader->HdrSize; + // + // Find the string block according the stringId. + // + Status = FindStringBlock(Current, StringId, &NameOffset, &BlockType); + if (Status != EFI_SUCCESS) { + delete[] StringPtr; + return NULL; + } + + // + // Get varstore name according the string type. + // + switch (BlockType) { + case EFI_HII_SIBT_STRING_SCSU: + case EFI_HII_SIBT_STRING_SCSU_FONT: + case EFI_HII_SIBT_STRINGS_SCSU: + case EFI_HII_SIBT_STRINGS_SCSU_FONT: + StringName = (CHAR8*)(Current + NameOffset); + VarStoreName = new CHAR8[strlen(StringName) + 1]; + strcpy (VarStoreName, StringName); + break; + case EFI_HII_SIBT_STRING_UCS2: + case EFI_HII_SIBT_STRING_UCS2_FONT: + case EFI_HII_SIBT_STRINGS_UCS2: + case EFI_HII_SIBT_STRINGS_UCS2_FONT: + UnicodeString = (CHAR16*)(Current + NameOffset); + Length = GetUnicodeStringTextSize ((UINT8*)UnicodeString) ; + DestTmp = new CHAR8[Length / 2 + 1]; + VarStoreName = DestTmp; + while (*UnicodeString != '\0') { + *(DestTmp++) = (CHAR8) *(UnicodeString++); + } + *DestTmp = '\0'; + break; + default: + break; + } + + delete[] StringPtr; + + return VarStoreName; +} + +EFI_STATUS +CVfrStringDB::FindStringBlock ( + IN UINT8 *StringData, + IN EFI_STRING_ID StringId, + OUT UINT32 *StringTextOffset, + OUT UINT8 *BlockType + ) +{ + UINT8 *BlockHdr; + EFI_STRING_ID CurrentStringId; + UINT32 BlockSize; + UINT32 Index; + UINT8 *StringTextPtr; + UINT32 Offset; + UINT16 StringCount; + UINT16 SkipCount; + UINT8 Length8; + EFI_HII_SIBT_EXT2_BLOCK Ext2; + UINT32 Length32; + UINT32 StringSize; + + CurrentStringId = 1; + + // + // Parse the string blocks to get the string text and font. + // + BlockHdr = StringData; + BlockSize = 0; + Offset = 0; + while (*BlockHdr != EFI_HII_SIBT_END) { + switch (*BlockHdr) { + case EFI_HII_SIBT_STRING_SCSU: + Offset = sizeof (EFI_HII_STRING_BLOCK); + StringTextPtr = BlockHdr + Offset; + BlockSize += Offset + strlen ((CHAR8 *) StringTextPtr) + 1; + CurrentStringId++; + break; + + case EFI_HII_SIBT_STRING_SCSU_FONT: + Offset = sizeof (EFI_HII_SIBT_STRING_SCSU_FONT_BLOCK) - sizeof (UINT8); + StringTextPtr = BlockHdr + Offset; + BlockSize += Offset + strlen ((CHAR8 *) StringTextPtr) + 1; + CurrentStringId++; + break; + + case EFI_HII_SIBT_STRINGS_SCSU: + memcpy (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16)); + StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_BLOCK) - sizeof (UINT8); + BlockSize += StringTextPtr - BlockHdr; + + for (Index = 0; Index < StringCount; Index++) { + BlockSize += strlen ((CHAR8 *) StringTextPtr) + 1; + if (CurrentStringId == StringId) { + *BlockType = *BlockHdr; + *StringTextOffset = StringTextPtr - StringData; + return EFI_SUCCESS; + } + StringTextPtr = StringTextPtr + strlen ((CHAR8 *) StringTextPtr) + 1; + CurrentStringId++; + } + break; + + case EFI_HII_SIBT_STRINGS_SCSU_FONT: + memcpy ( + &StringCount, + BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8), + sizeof (UINT16) + ); + StringTextPtr = BlockHdr + sizeof (EFI_HII_SIBT_STRINGS_SCSU_FONT_BLOCK) - sizeof (UINT8); + BlockSize += StringTextPtr - BlockHdr; + + for (Index = 0; Index < StringCount; Index++) { + BlockSize += strlen ((CHAR8 *) StringTextPtr) + 1; + if (CurrentStringId == StringId) { + *BlockType = *BlockHdr; + *StringTextOffset = StringTextPtr - StringData; + return EFI_SUCCESS; + } + StringTextPtr = StringTextPtr + strlen ((CHAR8 *) StringTextPtr) + 1; + CurrentStringId++; + } + break; + + case EFI_HII_SIBT_STRING_UCS2: + Offset = sizeof (EFI_HII_STRING_BLOCK); + StringTextPtr = BlockHdr + Offset; + // + // Use StringSize to store the size of the specified string, including the NULL + // terminator. + // + StringSize = GetUnicodeStringTextSize (StringTextPtr); + BlockSize += Offset + StringSize; + CurrentStringId++; + break; + + case EFI_HII_SIBT_STRING_UCS2_FONT: + Offset = sizeof (EFI_HII_SIBT_STRING_UCS2_FONT_BLOCK) - sizeof (CHAR16); + StringTextPtr = BlockHdr + Offset; + // + // Use StrSize to store the size of the specified string, including the NULL + // terminator. + // + StringSize = GetUnicodeStringTextSize (StringTextPtr); + BlockSize += Offset + StringSize; + CurrentStringId++; + break; + + case EFI_HII_SIBT_STRINGS_UCS2: + Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_BLOCK) - sizeof (CHAR16); + StringTextPtr = BlockHdr + Offset; + BlockSize += Offset; + memcpy (&StringCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16)); + for (Index = 0; Index < StringCount; Index++) { + StringSize = GetUnicodeStringTextSize (StringTextPtr); + BlockSize += StringSize; + if (CurrentStringId == StringId) { + *BlockType = *BlockHdr; + *StringTextOffset = StringTextPtr - StringData; + return EFI_SUCCESS; + } + StringTextPtr = StringTextPtr + StringSize; + CurrentStringId++; + } + break; + + case EFI_HII_SIBT_STRINGS_UCS2_FONT: + Offset = sizeof (EFI_HII_SIBT_STRINGS_UCS2_FONT_BLOCK) - sizeof (CHAR16); + StringTextPtr = BlockHdr + Offset; + BlockSize += Offset; + memcpy ( + &StringCount, + BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8), + sizeof (UINT16) + ); + for (Index = 0; Index < StringCount; Index++) { + StringSize = GetUnicodeStringTextSize (StringTextPtr); + BlockSize += StringSize; + if (CurrentStringId == StringId) { + *BlockType = *BlockHdr; + *StringTextOffset = StringTextPtr - StringData; + return EFI_SUCCESS; + } + StringTextPtr = StringTextPtr + StringSize; + CurrentStringId++; + } + break; + + case EFI_HII_SIBT_DUPLICATE: + if (CurrentStringId == StringId) { + // + // Incoming StringId is an id of a duplicate string block. + // Update the StringId to be the previous string block. + // Go back to the header of string block to search. + // + memcpy ( + &StringId, + BlockHdr + sizeof (EFI_HII_STRING_BLOCK), + sizeof (EFI_STRING_ID) + ); + CurrentStringId = 1; + BlockSize = 0; + } else { + BlockSize += sizeof (EFI_HII_SIBT_DUPLICATE_BLOCK); + CurrentStringId++; + } + break; + + case EFI_HII_SIBT_SKIP1: + SkipCount = (UINT16) (*(BlockHdr + sizeof (EFI_HII_STRING_BLOCK))); + CurrentStringId = (UINT16) (CurrentStringId + SkipCount); + BlockSize += sizeof (EFI_HII_SIBT_SKIP1_BLOCK); + break; + + case EFI_HII_SIBT_SKIP2: + memcpy (&SkipCount, BlockHdr + sizeof (EFI_HII_STRING_BLOCK), sizeof (UINT16)); + CurrentStringId = (UINT16) (CurrentStringId + SkipCount); + BlockSize += sizeof (EFI_HII_SIBT_SKIP2_BLOCK); + break; + + case EFI_HII_SIBT_EXT1: + memcpy ( + &Length8, + BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8), + sizeof (UINT8) + ); + BlockSize += Length8; + break; + + case EFI_HII_SIBT_EXT2: + memcpy (&Ext2, BlockHdr, sizeof (EFI_HII_SIBT_EXT2_BLOCK)); + BlockSize += Ext2.Length; + break; + + case EFI_HII_SIBT_EXT4: + memcpy ( + &Length32, + BlockHdr + sizeof (EFI_HII_STRING_BLOCK) + sizeof (UINT8), + sizeof (UINT32) + ); + + BlockSize += Length32; + break; + + default: + break; + } + + if (StringId > 0 && StringId != (EFI_STRING_ID)(-1)) { + *StringTextOffset = BlockHdr - StringData + Offset; + *BlockType = *BlockHdr; + + if (StringId == CurrentStringId - 1) { + // + // if only one skip item, return EFI_NOT_FOUND. + // + if(*BlockType == EFI_HII_SIBT_SKIP2 || *BlockType == EFI_HII_SIBT_SKIP1) { + return EFI_NOT_FOUND; + } else { + return EFI_SUCCESS; + } + } + + if (StringId < CurrentStringId - 1) { + return EFI_NOT_FOUND; + } + } + BlockHdr = StringData + BlockSize; + } + + return EFI_NOT_FOUND; +} + +UINT32 +CVfrStringDB::GetUnicodeStringTextSize ( + IN UINT8 *StringSrc + ) +{ + UINT32 StringSize; + CHAR16 *StringPtr; + + StringSize = sizeof (CHAR16); + StringPtr = (UINT16*)StringSrc; + while (*StringPtr++ != L'\0') { + StringSize += sizeof (CHAR16); + } + + return StringSize; +} + +CVfrVarDataTypeDB gCVfrVarDataTypeDB; +CVfrDefaultStore gCVfrDefaultStore; +CVfrDataStorage gCVfrDataStorage; + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrUtilityLib.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrUtilityLib.h new file mode 100644 index 00000000..bb91653f --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VfrCompile/VfrUtilityLib.h @@ -0,0 +1,538 @@ +/** @file + + Vfr common library functions. + +Copyright (c) 2004 - 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _VFRUTILITYLIB_H_ +#define _VFRUTILITYLIB_H_ + +#include "string.h" +#include "Common/UefiBaseTypes.h" +#include "EfiVfr.h" +#include "VfrError.h" + +static EFI_GUID gEdkiiIfrBitVarGuid = EDKII_IFR_BIT_VARSTORE_GUID; + +#define MAX_BIT_WIDTH 32 +#define MAX_NAME_LEN 64 +#define MAX_STRING_LEN 0x100 +#define DEFAULT_ALIGN 1 +#define DEFAULT_PACK_ALIGN 0x8 +#define DEFAULT_NAME_TABLE_ITEMS 1024 + +#define EFI_BITS_SHIFT_PER_UINT32 0x5 +#define EFI_BITS_PER_UINT32 (1 << EFI_BITS_SHIFT_PER_UINT32) + +#define BUFFER_SAFE_FREE(Buf) do { if ((Buf) != NULL) { delete (Buf); } } while (0); +#define ARRAY_SAFE_FREE(Buf) do { if ((Buf) != NULL) { delete[] (Buf); } } while (0); + + +class CVfrBinaryOutput { +public: + virtual VOID WriteLine (IN FILE *, IN UINT32, IN CONST CHAR8 *, IN CHAR8 *, IN UINT32); + virtual VOID WriteEnd (IN FILE *, IN UINT32, IN CONST CHAR8 *, IN CHAR8 *, IN UINT32); +}; + +UINT32 +_STR2U32 ( + IN CHAR8 *Str + ); + +struct SConfigInfo { + UINT16 mOffset; + UINT16 mWidth; + UINT8 *mValue; + SConfigInfo *mNext; + + SConfigInfo (IN UINT8, IN UINT16, IN UINT32, IN EFI_IFR_TYPE_VALUE); + ~SConfigInfo (VOID); + +private: + SConfigInfo (IN CONST SConfigInfo&); // Prevent copy-construction + SConfigInfo& operator= (IN CONST SConfigInfo&); // Prevent assignment +}; + +struct SConfigItem { + CHAR8 *mName; // varstore name + EFI_GUID *mGuid; // varstore guid, varstore name + guid deside one varstore + CHAR8 *mId; // default ID + SConfigInfo *mInfoStrList; // list of Offset/Value in the varstore + SConfigItem *mNext; + +public: + SConfigItem (IN CHAR8 *, IN EFI_GUID *, IN CHAR8 *); + SConfigItem (IN CHAR8 *, IN EFI_GUID *, IN CHAR8 *, IN UINT8, IN UINT16, IN UINT16, IN EFI_IFR_TYPE_VALUE); + virtual ~SConfigItem (); + +private: + SConfigItem (IN CONST SConfigItem&); // Prevent copy-construction + SConfigItem& operator= (IN CONST SConfigItem&); // Prevent assignment +}; + +class CVfrBufferConfig { +private: + SConfigItem *mItemListHead; + SConfigItem *mItemListTail; + SConfigItem *mItemListPos; + +public: + CVfrBufferConfig (VOID); + virtual ~CVfrBufferConfig (VOID); + + virtual UINT8 Register (IN CHAR8 *, IN EFI_GUID *,IN CHAR8 *Info = NULL); + virtual VOID Open (VOID); + virtual BOOLEAN Eof(VOID); + virtual UINT8 Select (IN CHAR8 *, IN EFI_GUID *, IN CHAR8 *Info = NULL); + virtual UINT8 Write (IN CONST CHAR8, IN CHAR8 *, IN EFI_GUID *, IN CHAR8 *, IN UINT8, IN UINT16, IN UINT32, IN EFI_IFR_TYPE_VALUE); +#if 0 + virtual UINT8 Read (OUT CHAR8 **, OUT CHAR8 **, OUT CHAR8 **, OUT CHAR8 **, OUT CHAR8 **); +#endif + virtual VOID Close (VOID); + virtual VOID OutputCFile (IN FILE *, IN CHAR8 *); + +private: + CVfrBufferConfig (IN CONST CVfrBufferConfig&); // Prevent copy-construction + CVfrBufferConfig& operator= (IN CONST CVfrBufferConfig&); // Prevent assignment +}; + +extern CVfrBufferConfig gCVfrBufferConfig; + +#define ALIGN_STUFF(Size, Align) ((Align) - (Size) % (Align)) +#define INVALID_ARRAY_INDEX 0xFFFFFFFF + +struct SVfrDataType; + +struct SVfrDataField { + CHAR8 mFieldName[MAX_NAME_LEN]; + SVfrDataType *mFieldType; + UINT32 mOffset; + UINT32 mArrayNum; + BOOLEAN mIsBitField; + UINT8 mBitWidth; + UINT32 mBitOffset; + SVfrDataField *mNext; +}; + +struct SVfrDataType { + CHAR8 mTypeName[MAX_NAME_LEN]; + UINT8 mType; + UINT32 mAlign; + UINT32 mTotalSize; + BOOLEAN mHasBitField; + SVfrDataField *mMembers; + SVfrDataType *mNext; +}; + +#define VFR_PACK_ASSIGN 0x01 +#define VFR_PACK_SHOW 0x02 +#define VFR_PACK_PUSH 0x04 +#define VFR_PACK_POP 0x08 + +#define PACKSTACK_MAX_SIZE 0x400 + +struct SVfrPackStackNode { + CHAR8 *mIdentifier; + UINT32 mNumber; + SVfrPackStackNode *mNext; + + SVfrPackStackNode (IN CHAR8 *Identifier, IN UINT32 Number) { + mIdentifier = NULL; + mNumber = Number; + mNext = NULL; + + if (Identifier != NULL) { + mIdentifier = new CHAR8[strlen (Identifier) + 1]; + strcpy (mIdentifier, Identifier); + } + } + + ~SVfrPackStackNode (VOID) { + if (mIdentifier != NULL) { + delete[] mIdentifier; + } + mNext = NULL; + } + + bool Match (IN CHAR8 *Identifier) { + if (Identifier == NULL) { + return TRUE; + } else if (mIdentifier == NULL) { + return FALSE; + } else if (strcmp (Identifier, mIdentifier) == 0) { + return TRUE; + } else { + return FALSE; + } + } + +private: + SVfrPackStackNode (IN CONST SVfrPackStackNode&); // Prevent copy-construction + SVfrPackStackNode& operator= (IN CONST SVfrPackStackNode&); // Prevent assignment +}; + +class CVfrVarDataTypeDB { +private: + UINT32 mPackAlign; + SVfrPackStackNode *mPackStack; + +public: + EFI_VFR_RETURN_CODE Pack (IN UINT32, IN UINT8, IN CHAR8 *Identifier = NULL, IN UINT32 Number = DEFAULT_PACK_ALIGN); + +private: + SVfrDataType *mDataTypeList; + + SVfrDataType *mNewDataType; + SVfrDataType *mCurrDataType; + SVfrDataField *mCurrDataField; + + VOID InternalTypesListInit (VOID); + VOID RegisterNewType (IN SVfrDataType *); + + EFI_VFR_RETURN_CODE ExtractStructTypeName (IN CHAR8 *&, OUT CHAR8 *); + EFI_VFR_RETURN_CODE GetTypeField (IN CONST CHAR8 *, IN SVfrDataType *, IN SVfrDataField *&); + EFI_VFR_RETURN_CODE GetFieldOffset (IN SVfrDataField *, IN UINT32, OUT UINT32 &, IN BOOLEAN); + UINT8 GetFieldWidth (IN SVfrDataField *); + UINT32 GetFieldSize (IN SVfrDataField *, IN UINT32, IN BOOLEAN); + +public: + CVfrVarDataTypeDB (VOID); + ~CVfrVarDataTypeDB (VOID); + + VOID DeclareDataTypeBegin (VOID); + EFI_VFR_RETURN_CODE SetNewTypeName (IN CHAR8 *); + EFI_VFR_RETURN_CODE DataTypeAddField (IN CHAR8 *, IN CHAR8 *, IN UINT32, IN BOOLEAN); + EFI_VFR_RETURN_CODE DataTypeAddBitField (IN CHAR8 *, IN CHAR8 *, IN UINT32, IN BOOLEAN); + VOID DeclareDataTypeEnd (VOID); + + EFI_VFR_RETURN_CODE GetDataType (IN CHAR8 *, OUT SVfrDataType **); + EFI_VFR_RETURN_CODE GetDataTypeSize (IN CHAR8 *, OUT UINT32 *); + EFI_VFR_RETURN_CODE GetDataTypeSize (IN UINT8, OUT UINT32 *); + EFI_VFR_RETURN_CODE GetDataFieldInfo (IN CHAR8 *, OUT UINT16 &, OUT UINT8 &, OUT UINT32 &, OUT BOOLEAN &); + + EFI_VFR_RETURN_CODE GetUserDefinedTypeNameList (OUT CHAR8 ***, OUT UINT32 *); + EFI_VFR_RETURN_CODE ExtractFieldNameAndArrary (IN CHAR8 *&, OUT CHAR8 *, OUT UINT32 &); + BOOLEAN DataTypeHasBitField (IN CHAR8 *); + BOOLEAN IsThisBitField (IN CHAR8 *); + + BOOLEAN IsTypeNameDefined (IN CHAR8 *); + + VOID Dump(IN FILE *); + // + // First the declared + // + CHAR8 *mFirstNewDataTypeName; +#ifdef CVFR_VARDATATYPEDB_DEBUG + VOID ParserDB (); +#endif + +private: + CVfrVarDataTypeDB (IN CONST CVfrVarDataTypeDB&); // Prevent copy-construction + CVfrVarDataTypeDB& operator= (IN CONST CVfrVarDataTypeDB&); // Prevent assignment +}; + +extern CVfrVarDataTypeDB gCVfrVarDataTypeDB; + +typedef enum { + EFI_VFR_VARSTORE_INVALID, + EFI_VFR_VARSTORE_BUFFER, + EFI_VFR_VARSTORE_EFI, + EFI_VFR_VARSTORE_NAME, + EFI_VFR_VARSTORE_BUFFER_BITS +} EFI_VFR_VARSTORE_TYPE; + +struct SVfrVarStorageNode { + EFI_GUID mGuid; + CHAR8 *mVarStoreName; + EFI_VARSTORE_ID mVarStoreId; + BOOLEAN mAssignedFlag; //Create varstore opcode + struct SVfrVarStorageNode *mNext; + + EFI_VFR_VARSTORE_TYPE mVarStoreType; + union { + // EFI Variable + struct { + EFI_STRING_ID mEfiVarName; + UINT32 mEfiVarSize; + } mEfiVar; + + // Buffer Storage + SVfrDataType *mDataType; + + // NameValue Storage + struct { + EFI_STRING_ID *mNameTable; + UINT32 mTableSize; + } mNameSpace; + } mStorageInfo; + +public: + SVfrVarStorageNode (IN EFI_GUID *, IN CHAR8 *, IN EFI_VARSTORE_ID, IN EFI_STRING_ID, IN UINT32, IN BOOLEAN Flag = TRUE); + SVfrVarStorageNode (IN EFI_GUID *, IN CHAR8 *, IN EFI_VARSTORE_ID, IN SVfrDataType *,IN BOOLEAN, IN BOOLEAN Flag = TRUE); + SVfrVarStorageNode (IN CHAR8 *, IN EFI_VARSTORE_ID); + ~SVfrVarStorageNode (VOID); + +private: + SVfrVarStorageNode (IN CONST SVfrVarStorageNode&); // Prevent copy-construction + SVfrVarStorageNode& operator= (IN CONST SVfrVarStorageNode&); // Prevent assignment +}; + +struct EFI_VARSTORE_INFO { + EFI_VARSTORE_ID mVarStoreId; + union { + EFI_STRING_ID mVarName; + UINT16 mVarOffset; + } mInfo; + UINT8 mVarType; + UINT32 mVarTotalSize; + BOOLEAN mIsBitVar; + + EFI_VARSTORE_INFO (VOID); + EFI_VARSTORE_INFO (IN EFI_VARSTORE_INFO &); + EFI_VARSTORE_INFO& operator=(IN CONST EFI_VARSTORE_INFO &); + BOOLEAN operator == (IN EFI_VARSTORE_INFO *); +}; + +struct BufferVarStoreFieldInfoNode { + EFI_VARSTORE_INFO mVarStoreInfo; + struct BufferVarStoreFieldInfoNode *mNext; + + BufferVarStoreFieldInfoNode( IN EFI_VARSTORE_INFO *Info ); + ~BufferVarStoreFieldInfoNode (); +}; + +#define EFI_VARSTORE_ID_MAX 0xFFFF +#define EFI_FREE_VARSTORE_ID_BITMAP_SIZE ((EFI_VARSTORE_ID_MAX + 1) / EFI_BITS_PER_UINT32) + +class CVfrDataStorage { +private: + UINT32 mFreeVarStoreIdBitMap[EFI_FREE_VARSTORE_ID_BITMAP_SIZE]; + + struct SVfrVarStorageNode *mBufferVarStoreList; + struct SVfrVarStorageNode *mEfiVarStoreList; + struct SVfrVarStorageNode *mNameVarStoreList; + + struct SVfrVarStorageNode *mCurrVarStorageNode; + struct SVfrVarStorageNode *mNewVarStorageNode; + BufferVarStoreFieldInfoNode *mBufferFieldInfoListHead; + BufferVarStoreFieldInfoNode *mBufferFieldInfoListTail; + +private: + + EFI_VARSTORE_ID GetFreeVarStoreId (EFI_VFR_VARSTORE_TYPE VarType = EFI_VFR_VARSTORE_BUFFER); + BOOLEAN ChekVarStoreIdFree (IN EFI_VARSTORE_ID); + VOID MarkVarStoreIdUsed (IN EFI_VARSTORE_ID); + VOID MarkVarStoreIdUnused (IN EFI_VARSTORE_ID); + EFI_VARSTORE_ID CheckGuidField (IN SVfrVarStorageNode *, + IN EFI_GUID *, + IN BOOLEAN *, + OUT EFI_VFR_RETURN_CODE *); + +public: + CVfrDataStorage (); + ~CVfrDataStorage (); + + SVfrVarStorageNode * GetBufferVarStoreList () { + return mBufferVarStoreList; + } + SVfrVarStorageNode * GetEfiVarStoreList () { + return mEfiVarStoreList; + } + EFI_VFR_RETURN_CODE DeclareNameVarStoreBegin (CHAR8 *, EFI_VARSTORE_ID); + EFI_VFR_RETURN_CODE NameTableAddItem (EFI_STRING_ID); + EFI_VFR_RETURN_CODE DeclareNameVarStoreEnd (EFI_GUID *); + + EFI_VFR_RETURN_CODE DeclareEfiVarStore (IN CHAR8 *, IN EFI_GUID *, IN EFI_STRING_ID, IN UINT32, IN BOOLEAN Flag = TRUE); + + EFI_VFR_RETURN_CODE DeclareBufferVarStore (IN CHAR8 *, IN EFI_GUID *, IN CVfrVarDataTypeDB *, IN CHAR8 *, IN EFI_VARSTORE_ID, IN BOOLEAN, IN BOOLEAN Flag = TRUE); + + EFI_VFR_RETURN_CODE GetVarStoreId (IN CHAR8 *, OUT EFI_VARSTORE_ID *, IN EFI_GUID *VarGuid = NULL); + EFI_VFR_VARSTORE_TYPE GetVarStoreType (IN EFI_VARSTORE_ID); + EFI_GUID * GetVarStoreGuid (IN EFI_VARSTORE_ID); + EFI_VFR_RETURN_CODE GetVarStoreName (IN EFI_VARSTORE_ID, OUT CHAR8 **); + EFI_VFR_RETURN_CODE GetVarStoreByDataType (IN CHAR8 *, OUT SVfrVarStorageNode **, IN EFI_GUID *VarGuid = NULL); + + EFI_VFR_RETURN_CODE GetBufferVarStoreDataTypeName (IN EFI_VARSTORE_ID, OUT CHAR8 **); + EFI_VFR_RETURN_CODE GetEfiVarStoreInfo (IN EFI_VARSTORE_INFO *); + EFI_VFR_RETURN_CODE GetNameVarStoreInfo (IN EFI_VARSTORE_INFO *, IN UINT32); + EFI_VFR_RETURN_CODE AddBufferVarStoreFieldInfo (IN EFI_VARSTORE_INFO *); + EFI_VFR_RETURN_CODE GetBufferVarStoreFieldInfo (IN OUT EFI_VARSTORE_INFO *); + +private: + CVfrDataStorage (IN CONST CVfrDataStorage&); // Prevent copy-construction + CVfrDataStorage& operator= (IN CONST CVfrDataStorage&); // Prevent assignment +}; + +extern CVfrDataStorage gCVfrDataStorage; + +#define EFI_QUESTION_ID_MAX 0xFFFF +#define EFI_FREE_QUESTION_ID_BITMAP_SIZE ((EFI_QUESTION_ID_MAX + 1) / EFI_BITS_PER_UINT32) +#define EFI_QUESTION_ID_INVALID 0x0 + +#define DATE_YEAR_BITMASK 0x0000FFFF +#define DATE_MONTH_BITMASK 0x00FF0000 +#define DATE_DAY_BITMASK 0xFF000000 +#define TIME_HOUR_BITMASK 0x000000FF +#define TIME_MINUTE_BITMASK 0x0000FF00 +#define TIME_SECOND_BITMASK 0x00FF0000 + +struct SVfrQuestionNode { + CHAR8 *mName; + CHAR8 *mVarIdStr; + EFI_QUESTION_ID mQuestionId; + UINT32 mBitMask; + SVfrQuestionNode *mNext; + EFI_QUESION_TYPE mQtype; + + SVfrQuestionNode (IN CHAR8 *, IN CHAR8 *, IN UINT32 BitMask = 0); + ~SVfrQuestionNode (); + +private: + SVfrQuestionNode (IN CONST SVfrQuestionNode&); // Prevent copy-construction + SVfrQuestionNode& operator= (IN CONST SVfrQuestionNode&); // Prevent assignment +}; + +class CVfrQuestionDB { +private: + SVfrQuestionNode *mQuestionList; + UINT32 mFreeQIdBitMap[EFI_FREE_QUESTION_ID_BITMAP_SIZE]; + +private: + EFI_QUESTION_ID GetFreeQuestionId (VOID); + BOOLEAN ChekQuestionIdFree (IN EFI_QUESTION_ID); + VOID MarkQuestionIdUsed (IN EFI_QUESTION_ID); + VOID MarkQuestionIdUnused (IN EFI_QUESTION_ID); + +public: + CVfrQuestionDB (); + ~CVfrQuestionDB(); + + EFI_VFR_RETURN_CODE RegisterQuestion (IN CHAR8 *, IN CHAR8 *, IN OUT EFI_QUESTION_ID &); + VOID RegisterOldDateQuestion (IN CHAR8 *, IN CHAR8 *, IN CHAR8 *, IN OUT EFI_QUESTION_ID &); + VOID RegisterNewDateQuestion (IN CHAR8 *, IN CHAR8 *, IN OUT EFI_QUESTION_ID &); + VOID RegisterOldTimeQuestion (IN CHAR8 *, IN CHAR8 *, IN CHAR8 *, IN OUT EFI_QUESTION_ID &); + VOID RegisterNewTimeQuestion (IN CHAR8 *, IN CHAR8 *, IN OUT EFI_QUESTION_ID &); + VOID RegisterRefQuestion (IN CHAR8 *, IN CHAR8 *, IN OUT EFI_QUESTION_ID &); + EFI_VFR_RETURN_CODE UpdateQuestionId (IN EFI_QUESTION_ID, IN EFI_QUESTION_ID); + VOID GetQuestionId (IN CHAR8 *, IN CHAR8 *, OUT EFI_QUESTION_ID &, OUT UINT32 &, OUT EFI_QUESION_TYPE *QType = NULL); + EFI_VFR_RETURN_CODE FindQuestion (IN EFI_QUESTION_ID); + EFI_VFR_RETURN_CODE FindQuestion (IN CHAR8 *); + VOID PrintAllQuestion (IN VOID); + VOID ResetInit (IN VOID); + +private: + CVfrQuestionDB (IN CONST CVfrQuestionDB&); // Prevent copy-construction + CVfrQuestionDB& operator= (IN CONST CVfrQuestionDB&); // Prevent assignment +}; + +struct SVfrDefaultStoreNode { + EFI_IFR_DEFAULTSTORE *mObjBinAddr; + CHAR8 *mRefName; + EFI_STRING_ID mDefaultStoreNameId; + UINT16 mDefaultId; + + SVfrDefaultStoreNode *mNext; + + SVfrDefaultStoreNode (IN EFI_IFR_DEFAULTSTORE *, IN CHAR8 *, IN EFI_STRING_ID, IN UINT16); + ~SVfrDefaultStoreNode(); + +private: + SVfrDefaultStoreNode (IN CONST SVfrDefaultStoreNode&); // Prevent copy-construction + SVfrDefaultStoreNode& operator= (IN CONST SVfrDefaultStoreNode&); // Prevent assignment +}; + +class CVfrDefaultStore { +private: + SVfrDefaultStoreNode *mDefaultStoreList; + +public: + CVfrDefaultStore (); + ~CVfrDefaultStore (); + + EFI_VFR_RETURN_CODE RegisterDefaultStore (IN CHAR8 *, IN CHAR8 *, IN EFI_STRING_ID, IN UINT16); + EFI_VFR_RETURN_CODE ReRegisterDefaultStoreById (IN UINT16, IN CHAR8 *, IN EFI_STRING_ID); + BOOLEAN DefaultIdRegistered (IN UINT16); + EFI_VFR_RETURN_CODE GetDefaultId (IN CHAR8 *, OUT UINT16 *); + EFI_VFR_RETURN_CODE BufferVarStoreAltConfigAdd (IN EFI_VARSTORE_ID, IN EFI_VARSTORE_INFO &, IN CHAR8 *, IN EFI_GUID *, IN UINT8, IN EFI_IFR_TYPE_VALUE); + +private: + CVfrDefaultStore (IN CONST CVfrDefaultStore&); // Prevent copy-construction + CVfrDefaultStore& operator= (IN CONST CVfrDefaultStore&); // Prevent assignment +}; + +extern CVfrDefaultStore gCVfrDefaultStore; + +#define EFI_RULE_ID_START 0x01 +#define EFI_RULE_ID_INVALID 0x00 + +struct SVfrRuleNode { + UINT8 mRuleId; + CHAR8 *mRuleName; + SVfrRuleNode *mNext; + + SVfrRuleNode(IN CHAR8 *, IN UINT8); + ~SVfrRuleNode(); + +private: + SVfrRuleNode (IN CONST SVfrRuleNode&); // Prevent copy-construction + SVfrRuleNode& operator= (IN CONST SVfrRuleNode&); // Prevent assignment +}; + +class CVfrRulesDB { +private: + SVfrRuleNode *mRuleList; + UINT8 mFreeRuleId; + +public: + CVfrRulesDB (); + ~CVfrRulesDB(); + + VOID RegisterRule (IN CHAR8 *); + UINT8 GetRuleId (IN CHAR8 *); + +private: + CVfrRulesDB (IN CONST CVfrRulesDB&); // Prevent copy-construction + CVfrRulesDB& operator= (IN CONST CVfrRulesDB&); // Prevent assignment +}; + +class CVfrStringDB { +private: + CHAR8 *mStringFileName; + + EFI_STATUS FindStringBlock ( + IN UINT8 *StringData, + IN EFI_STRING_ID StringId, + OUT UINT32 *StringTextOffset, + OUT UINT8 *BlockType + ); + + UINT32 GetUnicodeStringTextSize ( + IN UINT8 *StringSrc + ); + + BOOLEAN GetBestLanguage ( + IN CONST CHAR8 *SupportedLanguages, + IN CHAR8 *Language + ); + +public: + CVfrStringDB (); + ~CVfrStringDB (); + + VOID SetStringFileName ( + IN CHAR8 *StringFileName + ); + + CHAR8 * GetVarStoreNameFormStringId ( + IN EFI_STRING_ID StringId + ); + +private: + CVfrStringDB (IN CONST CVfrStringDB&); // Prevent copy-construction + CVfrStringDB& operator= (IN CONST CVfrStringDB&); // Prevent assignment +}; + +#endif diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/GNUmakefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/GNUmakefile new file mode 100644 index 00000000..8d6fa7bc --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/GNUmakefile @@ -0,0 +1,17 @@ +## @file +# GNU/Linux makefile for 'VolInfo' module build. +# +# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +MAKEROOT ?= .. + +APPNAME = VolInfo + +OBJECTS = VolInfo.o + +include $(MAKEROOT)/Makefiles/app.makefile + +LIBS = -lCommon + + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/Makefile b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/Makefile new file mode 100644 index 00000000..09611c6d --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/Makefile @@ -0,0 +1,16 @@ +## @file +# Windows makefile for 'VolInfo' module build. +# +# Copyright (c) 2007 - 2010, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +!INCLUDE ..\Makefiles\ms.common + +APPNAME = VolInfo + +LIBS = $(LIB_PATH)\Common.lib + +OBJECTS = VolInfo.obj + +!INCLUDE ..\Makefiles\ms.app + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/Makefile.kmk b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/Makefile.kmk new file mode 100644 index 00000000..2e2f8015 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/Makefile.kmk @@ -0,0 +1,45 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-makefile for the EFI VolInfo build tool. +# + +# +# Copyright (C) 2013-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# 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, in version 3 of the +# License. +# +# 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 . +# +# The contents of this file may alternatively be used under the terms +# of the Common Development and Distribution License Version 1.0 +# (CDDL), a copy of it is provided in the "COPYING.CDDL" file included +# in the VirtualBox distribution, in which case the provisions of the +# CDDL are applicable instead of those of the GPL. +# +# You may elect to license modified versions of this file under the +# terms and conditions of either the GPL or the CDDL or both. +# +# SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0 +# + +SUB_DEPTH = ../../../../../../../../.. +include $(KBUILD_PATH)/subheader.kmk + +BLDPROGS += VolInfo +VolInfo_TEMPLATE = VBoxEfiBldProg +VolInfo_SOURCES = VolInfo.c + +include $(FILE_KBUILD_SUB_FOOTER) + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/VolInfo.c b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/VolInfo.c new file mode 100644 index 00000000..9f9d92f4 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/VolInfo.c @@ -0,0 +1,2440 @@ +/** @file +The tool dumps the contents of a firmware volume + +Copyright (c) 1999 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#ifdef __GNUC__ +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Compress.h" +#include "Decompress.h" +#include "VolInfo.h" +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" +#include "FirmwareVolumeBufferLib.h" +#include "OsPath.h" +#include "ParseGuidedSectionTools.h" +#include "StringFuncs.h" +#include "ParseInf.h" +#include "PeCoffLib.h" + +#ifdef VBOX +# include +#endif +/* + +#ifdef __GNUC__ +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif +*/ +// +// Utility global variables +// + +EFI_GUID gEfiCrc32GuidedSectionExtractionProtocolGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID; + +#define UTILITY_MAJOR_VERSION 1 +#define UTILITY_MINOR_VERSION 0 + +#define UTILITY_NAME "VolInfo" + +#define EFI_SECTION_ERROR EFIERR (100) + +#define MAX_BASENAME_LEN 60 // not good to hardcode, but let's be reasonable + +// +// Structure to keep a list of guid-to-basenames +// +typedef struct _GUID_TO_BASENAME { + struct _GUID_TO_BASENAME *Next; + INT8 Guid[PRINTED_GUID_BUFFER_SIZE]; + INT8 BaseName[MAX_BASENAME_LEN]; +} GUID_TO_BASENAME; + +static GUID_TO_BASENAME *mGuidBaseNameList = NULL; + +// +// Store GUIDed Section guid->tool mapping +// +EFI_HANDLE mParsedGuidedSectionTools = NULL; + +CHAR8* mUtilityFilename = NULL; + +BOOLEAN EnableHash = FALSE; +CHAR8 *OpenSslPath = NULL; + +EFI_STATUS +ParseGuidBaseNameFile ( + CHAR8 *FileName + ); + +EFI_STATUS +FreeGuidBaseNameList ( + VOID + ); + +EFI_STATUS +PrintGuidName ( + IN UINT8 *GuidStr + ); + +EFI_STATUS +ParseSection ( + IN UINT8 *SectionBuffer, + IN UINT32 BufferLength + ); + +EFI_STATUS +DumpDepexSection ( + IN UINT8 *Ptr, + IN UINT32 SectionLength + ); + +STATIC +EFI_STATUS +ReadHeader ( + IN FILE *InputFile, + OUT UINT32 *FvSize, + OUT BOOLEAN *ErasePolarity + ); + +STATIC +EFI_STATUS +PrintFileInfo ( + EFI_FIRMWARE_VOLUME_HEADER *FvImage, + EFI_FFS_FILE_HEADER *FileHeader, + BOOLEAN ErasePolarity + ); + +static +EFI_STATUS +PrintFvInfo ( + IN VOID *Fv, + IN BOOLEAN IsChildFv + ); + +static +VOID +LoadGuidedSectionToolsTxt ( + IN CHAR8* FirmwareVolumeFilename + ); + +EFI_STATUS +CombinePath ( + IN CHAR8* DefaultPath, + IN CHAR8* AppendPath, + OUT CHAR8* NewPath +); + +void +Usage ( + VOID + ); + +UINT32 +UnicodeStrLen ( + IN CHAR16 *String + ) + /*++ + + Routine Description: + + Returns the length of a null-terminated unicode string. + + Arguments: + + String - The pointer to a null-terminated unicode string. + + Returns: + + N/A + + --*/ +{ + UINT32 Length; + + for (Length = 0; *String != L'\0'; String++, Length++) { + ; + } + return Length; +} + +VOID +Unicode2AsciiString ( + IN CHAR16 *Source, + OUT CHAR8 *Destination + ) + /*++ + + Routine Description: + + Convert a null-terminated unicode string to a null-terminated ascii string. + + Arguments: + + Source - The pointer to the null-terminated input unicode string. + Destination - The pointer to the null-terminated output ascii string. + + Returns: + + N/A + + --*/ +{ + while (*Source != '\0') { + *(Destination++) = (CHAR8) *(Source++); + } + // + // End the ascii with a NULL. + // + *Destination = '\0'; +} + +int +main ( + int argc, + char *argv[] + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + argc - GC_TODO: add argument description + ] - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + FILE *InputFile; + int BytesRead; + EFI_FIRMWARE_VOLUME_HEADER *FvImage; + UINT32 FvSize; + EFI_STATUS Status; + int Offset; + BOOLEAN ErasePolarity; + UINT64 LogLevel; + CHAR8 *OpenSslEnv; + CHAR8 *OpenSslCommand; + + SetUtilityName (UTILITY_NAME); + // + // Print utility header + // + printf ("%s Version %d.%d Build %s\n", + UTILITY_NAME, + UTILITY_MAJOR_VERSION, + UTILITY_MINOR_VERSION, + __BUILD_VERSION + ); + + if (argc == 1) { + Usage (); + return -1; + } + + argc--; + argv++; + LogLevel = 0; + Offset = 0; + + // + // Look for help options + // + if ((strcmp(argv[0], "-h") == 0) || (strcmp(argv[0], "--help") == 0) || + (strcmp(argv[0], "-?") == 0) || (strcmp(argv[0], "/?") == 0)) { + Usage(); + return STATUS_SUCCESS; + } + // + // Version has already be printed, so just return success + // + if (strcmp(argv[0], "--version") == 0) { + return STATUS_SUCCESS; + } + + // + // If they specified -x xref guid/basename cross-reference files, process it. + // This will print the basename beside each file guid. To use it, specify + // -x xref_filename to processdsc, then use xref_filename as a parameter + // here. + // + while (argc > 0) { + if ((strcmp(argv[0], "-x") == 0) || (strcmp(argv[0], "--xref") == 0)) { + ParseGuidBaseNameFile (argv[1]); + printf("ParseGuidBaseNameFile: %s\n", argv[1]); + argc -= 2; + argv += 2; + continue; + } + if (strcmp(argv[0], "--offset") == 0) { + // + // Hex or decimal? + // + if ((argv[1][0] == '0') && (tolower ((int)argv[1][1]) == 'x')) { + if (sscanf (argv[1], "%x", &Offset) != 1) { + Error (NULL, 0, 1003, "Invalid option value", "Offset = %s", argv[1]); + return GetUtilityStatus (); + } + } else { + if (sscanf (argv[1], "%d", &Offset) != 1) { + Error (NULL, 0, 1003, "Invalid option value", "Offset = %s", argv[1]); + return GetUtilityStatus (); + } + // + // See if they said something like "64K" + // + if (tolower ((int)argv[1][strlen (argv[1]) - 1]) == 'k') { + Offset *= 1024; + } + } + + argc -= 2; + argv += 2; + continue; + } + if ((stricmp (argv[0], "--hash") == 0)) { + if (EnableHash == TRUE) { + // + // --hash already given in the option, ignore this one + // + argc --; + argv ++; + continue; + } + EnableHash = TRUE; + OpenSslCommand = "openssl"; + OpenSslEnv = getenv("OPENSSL_PATH"); + if (OpenSslEnv == NULL) { + OpenSslPath = OpenSslCommand; + } else { + // + // We add quotes to the Openssl Path in case it has space characters + // + OpenSslPath = malloc(2+strlen(OpenSslEnv)+strlen(OpenSslCommand)+1); + if (OpenSslPath == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return GetUtilityStatus (); + } + CombinePath(OpenSslEnv, OpenSslCommand, OpenSslPath); + } + if (OpenSslPath == NULL){ + Error (NULL, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL); + return GetUtilityStatus (); + } + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-v") == 0) || (stricmp (argv[0], "--verbose") == 0)) { + SetPrintLevel (VERBOSE_LOG_LEVEL); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) { + SetPrintLevel (KEY_LOG_LEVEL); + argc --; + argv ++; + continue; + } + + if ((stricmp (argv[0], "-d") == 0) || (stricmp (argv[0], "--debug") == 0)) { + Status = AsciiStringToUint64 (argv[1], FALSE, &LogLevel); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 1003, "Invalid option value", "%s = %s", argv[0], argv[1]); + return -1; + } + if (LogLevel > 9) { + Error (NULL, 0, 1003, "Invalid option value", "Debug Level range is 0-9, current input level is %d", (int) LogLevel); + return -1; + } + SetPrintLevel (LogLevel); + DebugMsg (NULL, 0, 9, "Debug Mode Set", "Debug Output Mode Level %s is set!", argv[1]); + argc -= 2; + argv += 2; + continue; + } + + mUtilityFilename = argv[0]; + argc --; + argv ++; + } + + // + // Open the file containing the FV + // + if (mUtilityFilename == NULL) { + Error (NULL, 0, 1001, "Missing option", "Input files are not specified"); + return GetUtilityStatus (); + } + InputFile = fopen (LongFilePath (mUtilityFilename), "rb"); + if (InputFile == NULL) { + Error (NULL, 0, 0001, "Error opening the input file", mUtilityFilename); + return GetUtilityStatus (); + } + // + // Skip over pad bytes if specified. This is used if they prepend 0xff + // data to the FV image binary. + // + if (Offset != 0) { + fseek (InputFile, Offset, SEEK_SET); + } + // + // Determine size of FV + // + Status = ReadHeader (InputFile, &FvSize, &ErasePolarity); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "error parsing FV image", "%s Header is invalid", mUtilityFilename); + fclose (InputFile); + return GetUtilityStatus (); + } + // + // Allocate a buffer for the FV image + // + FvImage = malloc (FvSize); + if (FvImage == NULL) { + Error (NULL, 0, 4001, "Resource: Memory can't be allocated", NULL); + fclose (InputFile); + return GetUtilityStatus (); + } + // + // Seek to the start of the image, then read the entire FV to the buffer + // + fseek (InputFile, Offset, SEEK_SET); + BytesRead = fread (FvImage, 1, FvSize, InputFile); + fclose (InputFile); + if ((unsigned int) BytesRead != FvSize) { + Error (NULL, 0, 0004, "error reading FvImage from", mUtilityFilename); + free (FvImage); + return GetUtilityStatus (); + } + + LoadGuidedSectionToolsTxt (mUtilityFilename); + + PrintFvInfo (FvImage, FALSE); + + // + // Clean up + // + free (FvImage); + FreeGuidBaseNameList (); + return GetUtilityStatus (); +} + + +static +EFI_STATUS +PrintFvInfo ( + IN VOID *Fv, + IN BOOLEAN IsChildFv + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + Fv - Firmware Volume to print information about + IsChildFv - Flag specifies whether the input FV is a child FV. + +Returns: + + EFI_STATUS + +--*/ +{ + EFI_STATUS Status; + UINTN NumberOfFiles; + BOOLEAN ErasePolarity; + UINTN FvSize; + EFI_FFS_FILE_HEADER *CurrentFile; + UINTN Key; + + Status = FvBufGetSize (Fv, &FvSize); + + NumberOfFiles = 0; + ErasePolarity = + (((EFI_FIRMWARE_VOLUME_HEADER*)Fv)->Attributes & EFI_FVB2_ERASE_POLARITY) ? + TRUE : FALSE; + + // + // Get the first file + // + Key = 0; + Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "error parsing FV image", "cannot find the first file in the FV image"); + return GetUtilityStatus (); + } + // + // Display information about files found + // + while (CurrentFile != NULL) { + // + // Increment the number of files counter + // + NumberOfFiles++; + + // + // Display info about this file + // + Status = PrintFileInfo (Fv, CurrentFile, ErasePolarity); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "error parsing FV image", "failed to parse a file in the FV"); + return GetUtilityStatus (); + } + // + // Get the next file + // + Status = FvBufFindNextFile (Fv, &Key, (VOID **) &CurrentFile); + if (Status == EFI_NOT_FOUND) { + CurrentFile = NULL; + } else if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "error parsing FV image", "cannot find the next file in the FV image"); + return GetUtilityStatus (); + } + } + + if (IsChildFv) { + printf ("There are a total of %d files in the child FV\n", (int) NumberOfFiles); + } else { + printf ("There are a total of %d files in this FV\n", (int) NumberOfFiles); + } + + return EFI_SUCCESS; +} + +UINT32 +GetOccupiedSize ( + IN UINT32 ActualSize, + IN UINT32 Alignment + ) +/*++ + +Routine Description: + + This function returns the next larger size that meets the alignment + requirement specified. + +Arguments: + + ActualSize The size. + Alignment The desired alignment. + +Returns: + + EFI_SUCCESS Function completed successfully. + EFI_ABORTED The function encountered an error. + +--*/ +{ + UINT32 OccupiedSize; + + OccupiedSize = ActualSize; + while ((OccupiedSize & (Alignment - 1)) != 0) { + OccupiedSize++; + } + + return OccupiedSize; +} + +static +CHAR8 * +SectionNameToStr ( + IN EFI_SECTION_TYPE Type + ) +/*++ + +Routine Description: + + Converts EFI Section names to Strings + +Arguments: + + Type - The EFI Section type + +Returns: + + CHAR8* - Pointer to the String containing the section name. + +--*/ +{ + CHAR8 *SectionStr; + CHAR8 *SectionTypeStringTable[] = { + // + // 0X00 + // + "EFI_SECTION_ALL", + // + // 0x01 + // + "EFI_SECTION_COMPRESSION", + // + // 0x02 + // + "EFI_SECTION_GUID_DEFINED", + // + // 0x03 + // + "Unknown section type - Reserved 0x03", + // + // 0x04 + // + "Unknown section type - Reserved 0x04", + // + // 0x05 + // + "Unknown section type - Reserved 0x05", + // + // 0x06 + // + "Unknown section type - Reserved 0x06", + // + // 0x07 + // + "Unknown section type - Reserved 0x07", + // + // 0x08 + // + "Unknown section type - Reserved 0x08", + // + // 0x09 + // + "Unknown section type - Reserved 0x09", + // + // 0x0A + // + "Unknown section type - Reserved 0x0A", + // + // 0x0B + // + "Unknown section type - Reserved 0x0B", + // + // 0x0C + // + "Unknown section type - Reserved 0x0C", + // + // 0x0D + // + "Unknown section type - Reserved 0x0D", + // + // 0x0E + // + "Unknown section type - Reserved 0x0E", + // + // 0x0F + // + "Unknown section type - Reserved 0x0E", + // + // 0x10 + // + "EFI_SECTION_PE32", + // + // 0x11 + // + "EFI_SECTION_PIC", + // + // 0x12 + // + "EFI_SECTION_TE", + // + // 0x13 + // + "EFI_SECTION_DXE_DEPEX", + // + // 0x14 + // + "EFI_SECTION_VERSION", + // + // 0x15 + // + "EFI_SECTION_USER_INTERFACE", + // + // 0x16 + // + "EFI_SECTION_COMPATIBILITY16", + // + // 0x17 + // + "EFI_SECTION_FIRMWARE_VOLUME_IMAGE ", + // + // 0x18 + // + "EFI_SECTION_FREEFORM_SUBTYPE_GUID ", + // + // 0x19 + // + "EFI_SECTION_RAW", + // + // 0x1A + // + "Unknown section type - 0x1A", + // + // 0x1B + // + "EFI_SECTION_PEI_DEPEX", + // + // 0x1C + // + "EFI_SECTION_SMM_DEPEX", + // + // 0x1C+ + // + "Unknown section type - Reserved - beyond last defined section" + }; + + if (Type > EFI_SECTION_LAST_SECTION_TYPE) { + Type = EFI_SECTION_LAST_SECTION_TYPE + 1; + } + + SectionStr = malloc (100); + if (SectionStr == NULL) { + printf ("Error: Out of memory resources.\n"); + return SectionStr; + } + strcpy (SectionStr, SectionTypeStringTable[Type]); + return SectionStr; +} + +STATIC +EFI_STATUS +ReadHeader ( + IN FILE *InputFile, + OUT UINT32 *FvSize, + OUT BOOLEAN *ErasePolarity + ) +/*++ + +Routine Description: + + This function determines the size of the FV and the erase polarity. The + erase polarity is the FALSE value for file state. + +Arguments: + + InputFile The file that contains the FV image. + FvSize The size of the FV. + ErasePolarity The FV erase polarity. + +Returns: + + EFI_SUCCESS Function completed successfully. + EFI_INVALID_PARAMETER A required parameter was NULL or is out of range. + EFI_ABORTED The function encountered an error. + +--*/ +{ + EFI_FIRMWARE_VOLUME_HEADER VolumeHeader; + EFI_FV_BLOCK_MAP_ENTRY BlockMap; + UINTN Signature[2]; + UINTN BytesRead; + UINT32 Size; + size_t ReadSize; + + BytesRead = 0; + Size = 0; + // + // Check input parameters + // + if (InputFile == NULL || FvSize == NULL || ErasePolarity == NULL) { + Error (__FILE__, __LINE__, 0, "application error", "invalid parameter to function"); + return EFI_INVALID_PARAMETER; + } + // + // Read the header + // + ReadSize = fread (&VolumeHeader, sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile); + if (ReadSize != 1) { + return EFI_ABORTED; + } + BytesRead = sizeof (EFI_FIRMWARE_VOLUME_HEADER) - sizeof (EFI_FV_BLOCK_MAP_ENTRY); + Signature[0] = VolumeHeader.Signature; + Signature[1] = 0; + + // + // Print FV header information + // + printf ("Signature: %s (%X)\n", (char *) Signature, (unsigned) VolumeHeader.Signature); + printf ("Attributes: %X\n", (unsigned) VolumeHeader.Attributes); + + if (VolumeHeader.Attributes & EFI_FVB2_READ_DISABLED_CAP) { + printf (" EFI_FVB2_READ_DISABLED_CAP\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_READ_ENABLED_CAP) { + printf (" EFI_FVB2_READ_ENABLED_CAP\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_READ_STATUS) { + printf (" EFI_FVB2_READ_STATUS\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_WRITE_DISABLED_CAP) { + printf (" EFI_FVB2_WRITE_DISABLED_CAP\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_WRITE_ENABLED_CAP) { + printf (" EFI_FVB2_WRITE_ENABLED_CAP\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_WRITE_STATUS) { + printf (" EFI_FVB2_WRITE_STATUS\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_LOCK_CAP) { + printf (" EFI_FVB2_LOCK_CAP\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_LOCK_STATUS) { + printf (" EFI_FVB2_LOCK_STATUS\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_STICKY_WRITE) { + printf (" EFI_FVB2_STICKY_WRITE\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_MEMORY_MAPPED) { + printf (" EFI_FVB2_MEMORY_MAPPED\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ERASE_POLARITY) { + printf (" EFI_FVB2_ERASE_POLARITY\n"); + *ErasePolarity = TRUE; + } + +#if (PI_SPECIFICATION_VERSION < 0x00010000) + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT) { + printf (" EFI_FVB2_ALIGNMENT\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2) { + printf (" EFI_FVB2_ALIGNMENT_2\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4) { + printf (" EFI_FVB2_ALIGNMENT_4\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8) { + printf (" EFI_FVB2_ALIGNMENT_8\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16) { + printf (" EFI_FVB2_ALIGNMENT_16\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32) { + printf (" EFI_FVB2_ALIGNMENT_32\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64) { + printf (" EFI_FVB2_ALIGNMENT_64\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128) { + printf (" EFI_FVB2_ALIGNMENT_128\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256) { + printf (" EFI_FVB2_ALIGNMENT_256\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512) { + printf (" EFI_FVB2_ALIGNMENT_512\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1K) { + printf (" EFI_FVB2_ALIGNMENT_1K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2K) { + printf (" EFI_FVB2_ALIGNMENT_2K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4K) { + printf (" EFI_FVB2_ALIGNMENT_4K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8K) { + printf (" EFI_FVB2_ALIGNMENT_8K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16K) { + printf (" EFI_FVB2_ALIGNMENT_16K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32K) { + printf (" EFI_FVB2_ALIGNMENT_32K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) { + printf (" EFI_FVB2_ALIGNMENT_64K\n"); + } + +#else + + if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_CAP) { + printf (" EFI_FVB2_READ_LOCK_CAP\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_READ_LOCK_STATUS) { + printf (" EFI_FVB2_READ_LOCK_STATUS\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_WRITE_LOCK_CAP) { + printf (" EFI_FVB2_WRITE_LOCK_CAP\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_WRITE_LOCK_STATUS) { + printf (" EFI_FVB2_WRITE_LOCK_STATUS\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1) { + printf (" EFI_FVB2_ALIGNMENT_1\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2) { + printf (" EFI_FVB2_ALIGNMENT_2\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4) { + printf (" EFI_FVB2_ALIGNMENT_4\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8) { + printf (" EFI_FVB2_ALIGNMENT_8\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16) { + printf (" EFI_FVB2_ALIGNMENT_16\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32) { + printf (" EFI_FVB2_ALIGNMENT_32\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64) { + printf (" EFI_FVB2_ALIGNMENT_64\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128) { + printf (" EFI_FVB2_ALIGNMENT_128\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256) { + printf (" EFI_FVB2_ALIGNMENT_256\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512) { + printf (" EFI_FVB2_ALIGNMENT_512\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1K) { + printf (" EFI_FVB2_ALIGNMENT_1K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2K) { + printf (" EFI_FVB2_ALIGNMENT_2K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4K) { + printf (" EFI_FVB2_ALIGNMENT_4K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8K) { + printf (" EFI_FVB2_ALIGNMENT_8K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16K) { + printf (" EFI_FVB2_ALIGNMENT_16K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32K) { + printf (" EFI_FVB2_ALIGNMENT_32K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64K) { + printf (" EFI_FVB2_ALIGNMENT_64K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128K) { + printf (" EFI_FVB2_ALIGNMENT_128K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256K) { + printf (" EFI_FVB2_ALIGNMENT_256K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512K) { + printf (" EFI_FVB2_ALIGNMENT_512K\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1M) { + printf (" EFI_FVB2_ALIGNMENT_1M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2M) { + printf (" EFI_FVB2_ALIGNMENT_2M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_4M) { + printf (" EFI_FVB2_ALIGNMENT_4M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_8M) { + printf (" EFI_FVB2_ALIGNMENT_8M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_16M) { + printf (" EFI_FVB2_ALIGNMENT_16M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_32M) { + printf (" EFI_FVB2_ALIGNMENT_32M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64M) { + printf (" EFI_FVB2_ALIGNMENT_64M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128M) { + printf (" EFI_FVB2_ALIGNMENT_128M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_64M) { + printf (" EFI_FVB2_ALIGNMENT_64M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_128M) { + printf (" EFI_FVB2_ALIGNMENT_128M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_256M) { + printf (" EFI_FVB2_ALIGNMENT_256M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_512M) { + printf (" EFI_FVB2_ALIGNMENT_512M\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_1G) { + printf (" EFI_FVB2_ALIGNMENT_1G\n"); + } + + if (VolumeHeader.Attributes & EFI_FVB2_ALIGNMENT_2G) { + printf (" EFI_FVB2_ALIGNMENT_2G\n"); + } + +#endif + printf ("Header Length: 0x%08X\n", VolumeHeader.HeaderLength); + printf ("File System ID: "); + PrintGuid (&VolumeHeader.FileSystemGuid); + // + // printf ("\n"); + // + printf ("Revision: 0x%04X\n", VolumeHeader.Revision); + + do { + ReadSize = fread (&BlockMap, sizeof (EFI_FV_BLOCK_MAP_ENTRY), 1, InputFile); + if (ReadSize != 1) { + return EFI_ABORTED; + } + BytesRead += sizeof (EFI_FV_BLOCK_MAP_ENTRY); + + if (BlockMap.NumBlocks != 0) { + printf ("Number of Blocks: 0x%08X\n", (unsigned) BlockMap.NumBlocks); + printf ("Block Length: 0x%08X\n", (unsigned) BlockMap.Length); + Size += BlockMap.NumBlocks * BlockMap.Length; + } + + } while (!(BlockMap.NumBlocks == 0 && BlockMap.Length == 0)); + + if (BytesRead != VolumeHeader.HeaderLength) { + printf ("ERROR: Header length not consistent with Block Maps!\n"); + return EFI_ABORTED; + } + + if (VolumeHeader.FvLength != Size) { + printf ("ERROR: Volume Size not consistent with Block Maps!\n"); + return EFI_ABORTED; + } + + printf ("Total Volume Size: 0x%08X\n", (unsigned) Size); + + *FvSize = Size; + + // + // rewind (InputFile); + // + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +PrintFileInfo ( + EFI_FIRMWARE_VOLUME_HEADER *FvImage, + EFI_FFS_FILE_HEADER *FileHeader, + BOOLEAN ErasePolarity + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + FvImage - GC_TODO: add argument description + FileHeader - GC_TODO: add argument description + ErasePolarity - GC_TODO: add argument description + +Returns: + + EFI_SUCCESS - GC_TODO: Add description for return value + EFI_ABORTED - GC_TODO: Add description for return value + +--*/ +{ + UINT32 FileLength; + UINT8 FileState; + UINT8 Checksum; + EFI_FFS_FILE_HEADER2 BlankHeader; + EFI_STATUS Status; + UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE]; + UINT32 HeaderSize; +#if (PI_SPECIFICATION_VERSION < 0x00010000) + UINT16 *Tail; +#endif + // + // Check if we have free space + // + HeaderSize = FvBufGetFfsHeaderSize(FileHeader); + if (ErasePolarity) { + memset (&BlankHeader, -1, HeaderSize); + } else { + memset (&BlankHeader, 0, HeaderSize); + } + + if (memcmp (&BlankHeader, FileHeader, HeaderSize) == 0) { + return EFI_SUCCESS; + } + // + // Print file information. + // + printf ("============================================================\n"); + + printf ("File Name: "); + PrintGuidToBuffer (&FileHeader->Name, GuidBuffer, sizeof (GuidBuffer), TRUE); + printf ("%s ", GuidBuffer); + PrintGuidName (GuidBuffer); + printf ("\n"); + + // + // PrintGuid (&FileHeader->Name); + // printf ("\n"); + // + FileLength = FvBufGetFfsFileSize (FileHeader); + printf ("File Offset: 0x%08X\n", (unsigned) ((UINTN) FileHeader - (UINTN) FvImage)); + printf ("File Length: 0x%08X\n", (unsigned) FileLength); + printf ("File Attributes: 0x%02X\n", FileHeader->Attributes); + printf ("File State: 0x%02X\n", FileHeader->State); + + // + // Print file state + // + FileState = GetFileState (ErasePolarity, FileHeader); + + switch (FileState) { + + case EFI_FILE_HEADER_CONSTRUCTION: + printf (" EFI_FILE_HEADER_CONSTRUCTION\n"); + return EFI_SUCCESS; + + case EFI_FILE_HEADER_INVALID: + printf (" EFI_FILE_HEADER_INVALID\n"); + return EFI_SUCCESS; + + case EFI_FILE_HEADER_VALID: + printf (" EFI_FILE_HEADER_VALID\n"); + Checksum = CalculateSum8 ((UINT8 *) FileHeader, HeaderSize); + Checksum = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File); + Checksum = (UINT8) (Checksum - FileHeader->State); + if (Checksum != 0) { + printf ("ERROR: Header checksum invalid.\n"); + return EFI_ABORTED; + } + + return EFI_SUCCESS; + + case EFI_FILE_DELETED: + printf (" EFI_FILE_DELETED\n"); +#ifdef VBOX + RT_FALL_THRU(); +#endif + case EFI_FILE_MARKED_FOR_UPDATE: + printf (" EFI_FILE_MARKED_FOR_UPDATE\n"); +#ifdef VBOX + RT_FALL_THRU(); +#endif + case EFI_FILE_DATA_VALID: + printf (" EFI_FILE_DATA_VALID\n"); + + // + // Calculate header checksum + // + Checksum = CalculateSum8 ((UINT8 *) FileHeader, HeaderSize); + Checksum = (UINT8) (Checksum - FileHeader->IntegrityCheck.Checksum.File); + Checksum = (UINT8) (Checksum - FileHeader->State); + if (Checksum != 0) { + Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum", GuidBuffer); + return EFI_ABORTED; + } + + FileLength = FvBufGetFfsFileSize (FileHeader); + + if (FileHeader->Attributes & FFS_ATTRIB_CHECKSUM) { + // + // Calculate file checksum + // + Checksum = CalculateSum8 ((UINT8 *)FileHeader + HeaderSize, FileLength - HeaderSize); + Checksum = Checksum + FileHeader->IntegrityCheck.Checksum.File; + if (Checksum != 0) { + Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid file checksum", GuidBuffer); + return EFI_ABORTED; + } + } else { + if (FileHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) { + Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has invalid header checksum -- not set to fixed value of 0xAA", GuidBuffer); + return EFI_ABORTED; + } + } +#if (PI_SPECIFICATION_VERSION < 0x00010000) + // + // Verify tail if present + // + if (FileHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + // + // Verify tail is complement of integrity check field in the header. + // + Tail = (UINT16 *) ((UINTN) FileHeader + GetLength (FileHeader->Size) - sizeof (EFI_FFS_INTEGRITY_CHECK)); + if (FileHeader->IntegrityCheck.TailReference != (UINT16)~(*Tail)) { + Error (NULL, 0, 0003, "error parsing FFS file", \ + "FFS file with Guid %s failed in the integrity check, tail is not the complement of the header field", GuidBuffer); + return EFI_ABORTED; + } + } + #endif + break; + + default: + Error (NULL, 0, 0003, "error parsing FFS file", "FFS file with Guid %s has the invalid/unrecognized file state bits", GuidBuffer); + return EFI_ABORTED; + } + + printf ("File Type: 0x%02X ", FileHeader->Type); + + switch (FileHeader->Type) { + + case EFI_FV_FILETYPE_RAW: + printf ("EFI_FV_FILETYPE_RAW\n"); + break; + + case EFI_FV_FILETYPE_FREEFORM: + printf ("EFI_FV_FILETYPE_FREEFORM\n"); + break; + + case EFI_FV_FILETYPE_SECURITY_CORE: + printf ("EFI_FV_FILETYPE_SECURITY_CORE\n"); + break; + + case EFI_FV_FILETYPE_PEI_CORE: + printf ("EFI_FV_FILETYPE_PEI_CORE\n"); + break; + + case EFI_FV_FILETYPE_DXE_CORE: + printf ("EFI_FV_FILETYPE_DXE_CORE\n"); + break; + + case EFI_FV_FILETYPE_PEIM: + printf ("EFI_FV_FILETYPE_PEIM\n"); + break; + + case EFI_FV_FILETYPE_DRIVER: + printf ("EFI_FV_FILETYPE_DRIVER\n"); + break; + + case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: + printf ("EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER\n"); + break; + + case EFI_FV_FILETYPE_APPLICATION: + printf ("EFI_FV_FILETYPE_APPLICATION\n"); + break; + + case EFI_FV_FILETYPE_SMM: + printf ("EFI_FV_FILETYPE_SMM\n"); + break; + + case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: + printf ("EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE\n"); + break; + + case EFI_FV_FILETYPE_COMBINED_SMM_DXE: + printf ("EFI_FV_FILETYPE_COMBINED_SMM_DXE\n"); + break; + + case EFI_FV_FILETYPE_SMM_CORE: + printf ("EFI_FV_FILETYPE_SMM_CORE\n"); + break; + + case EFI_FV_FILETYPE_MM_STANDALONE: + printf ("EFI_FV_FILETYPE_MM_STANDALONE\n"); + break; + + case EFI_FV_FILETYPE_MM_CORE_STANDALONE: + printf ("EFI_FV_FILETYPE_MM_CORE_STANDALONE\n"); + break; + + case EFI_FV_FILETYPE_FFS_PAD: + printf ("EFI_FV_FILETYPE_FFS_PAD\n"); + break; + + default: + printf ("\nERROR: Unrecognized file type %X.\n", FileHeader->Type); + return EFI_ABORTED; + break; + } + + switch (FileHeader->Type) { + + case EFI_FV_FILETYPE_ALL: + case EFI_FV_FILETYPE_RAW: + case EFI_FV_FILETYPE_FFS_PAD: + break; + + default: + // + // All other files have sections + // + Status = ParseSection ( + (UINT8 *) ((UINTN) FileHeader + HeaderSize), + FvBufGetFfsFileSize (FileHeader) - HeaderSize + ); + if (EFI_ERROR (Status)) { + // + // printf ("ERROR: Parsing the FFS file.\n"); + // + return EFI_ABORTED; + } + break; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +RebaseImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINT32 *ReadSize, + OUT VOID *Buffer + ) +/*++ + +Routine Description: + + Support routine for the PE/COFF Loader that reads a buffer from a PE/COFF file + +Arguments: + + FileHandle - The handle to the PE/COFF file + + FileOffset - The offset, in bytes, into the file to read + + ReadSize - The number of bytes to read from the file starting at FileOffset + + Buffer - A pointer to the buffer to read the data into. + +Returns: + + EFI_SUCCESS - ReadSize bytes of data were read into Buffer from the PE/COFF file starting at FileOffset + +--*/ +{ + CHAR8 *Destination8; + CHAR8 *Source8; + UINT32 Length; + + Destination8 = Buffer; + Source8 = (CHAR8 *) ((UINTN) FileHandle + FileOffset); + Length = *ReadSize; + while (Length--) { + *(Destination8++) = *(Source8++); + } + + return EFI_SUCCESS; +} + +EFI_STATUS +SetAddressToSectionHeader ( + IN CHAR8 *FileName, + IN OUT UINT8 *FileBuffer, + IN UINT64 NewPe32BaseAddress + ) +/*++ + +Routine Description: + + Set new base address into the section header of PeImage + +Arguments: + + FileName - Name of file + FileBuffer - Pointer to PeImage. + NewPe32BaseAddress - New Base Address for PE image. + +Returns: + + EFI_SUCCESS Set new base address into this image successfully. + +--*/ +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + UINTN Index; + EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + + // + // Initialize context + // + memset (&ImageContext, 0, sizeof (ImageContext)); + ImageContext.Handle = (VOID *) FileBuffer; + ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead; + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName); + return Status; + } + + if (ImageContext.RelocationsStripped) { + Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName); + return Status; + } + + // + // Get PeHeader pointer + // + ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset); + + // + // Get section header list + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN) ImgHdr + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader + ); + + // + // Set base address into the first section header that doesn't point to code section. + // + for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + if ((SectionHeader->Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) { + *(UINT64 *) &SectionHeader->PointerToRelocations = NewPe32BaseAddress; + break; + } + } + + // + // BaseAddress is set to section header. + // + return EFI_SUCCESS; +} + +EFI_STATUS +RebaseImage ( + IN CHAR8 *FileName, + IN OUT UINT8 *FileBuffer, + IN UINT64 NewPe32BaseAddress + ) +/*++ + +Routine Description: + + Set new base address into PeImage, and fix up PeImage based on new address. + +Arguments: + + FileName - Name of file + FileBuffer - Pointer to PeImage. + NewPe32BaseAddress - New Base Address for PE image. + +Returns: + + EFI_INVALID_PARAMETER - BaseAddress is not valid. + EFI_SUCCESS - Update PeImage is correctly. + +--*/ +{ + EFI_STATUS Status; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + UINTN Index; + EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; + UINT8 *MemoryImagePointer; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + + // + // Initialize context + // + memset (&ImageContext, 0, sizeof (ImageContext)); + ImageContext.Handle = (VOID *) FileBuffer; + ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) RebaseImageRead; + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "The input PeImage %s is not valid", FileName); + return Status; + } + + if (ImageContext.RelocationsStripped) { + Error (NULL, 0, 3000, "Invalid", "The input PeImage %s has no relocation to be fixed up", FileName); + return Status; + } + + // + // Get PeHeader pointer + // + ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(FileBuffer + ImageContext.PeCoffHeaderOffset); + + // + // Load and Relocate Image Data + // + MemoryImagePointer = (UINT8 *) malloc ((UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment); + if (MemoryImagePointer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated on rebase of %s", FileName); + return EFI_OUT_OF_RESOURCES; + } + memset ((VOID *) MemoryImagePointer, 0, (UINTN) ImageContext.ImageSize + ImageContext.SectionAlignment); + ImageContext.ImageAddress = ((UINTN) MemoryImagePointer + ImageContext.SectionAlignment - 1) & (~((INT64)ImageContext.SectionAlignment - 1)); + + Status = PeCoffLoaderLoadImage (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "LocateImage() call failed on rebase of %s", FileName); + free ((VOID *) MemoryImagePointer); + return Status; + } + + ImageContext.DestinationAddress = NewPe32BaseAddress; + Status = PeCoffLoaderRelocateImage (&ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 3000, "Invalid", "RelocateImage() call failed on rebase of %s", FileName); + free ((VOID *) MemoryImagePointer); + return Status; + } + + // + // Copy Relocated data to raw image file. + // + SectionHeader = (EFI_IMAGE_SECTION_HEADER *) ( + (UINTN) ImgHdr + + sizeof (UINT32) + + sizeof (EFI_IMAGE_FILE_HEADER) + + ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader + ); + + for (Index = 0; Index < ImgHdr->Pe32.FileHeader.NumberOfSections; Index ++, SectionHeader ++) { + CopyMem ( + FileBuffer + SectionHeader->PointerToRawData, + (VOID*) (UINTN) (ImageContext.ImageAddress + SectionHeader->VirtualAddress), + SectionHeader->SizeOfRawData + ); + } + + free ((VOID *) MemoryImagePointer); + + // + // Update Image Base Address + // + if (ImgHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + ImgHdr->Pe32.OptionalHeader.ImageBase = (UINT32) NewPe32BaseAddress; + } else if (ImgHdr->Pe32Plus.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + ImgHdr->Pe32Plus.OptionalHeader.ImageBase = NewPe32BaseAddress; + } else { + Error (NULL, 0, 3000, "Invalid", "unknown PE magic signature %X in PE32 image %s", + ImgHdr->Pe32.OptionalHeader.Magic, + FileName + ); + return EFI_ABORTED; + } + + // + // Set new base address into section header + // + Status = SetAddressToSectionHeader (FileName, FileBuffer, NewPe32BaseAddress); + + return Status; +} + +EFI_STATUS +CombinePath ( + IN CHAR8* DefaultPath, + IN CHAR8* AppendPath, + OUT CHAR8* NewPath +) +{ + UINT32 DefaultPathLen; + UINT64 Index; + CHAR8 QuotesStr[] = "\""; + strcpy(NewPath, QuotesStr); + DefaultPathLen = strlen(DefaultPath); + strcat(NewPath, DefaultPath); + Index = 0; + for (; Index < DefaultPathLen + 1; Index ++) { + if (NewPath[Index] == '\\' || NewPath[Index] == '/') { + if (NewPath[Index + 1] != '\0') { + NewPath[Index] = '/'; + } + } + } + if (NewPath[Index -1] != '/') { + NewPath[Index] = '/'; + NewPath[Index + 1] = '\0'; + } + strcat(NewPath, AppendPath); + strcat(NewPath, QuotesStr); + return EFI_SUCCESS; +} + +EFI_STATUS +ParseSection ( + IN UINT8 *SectionBuffer, + IN UINT32 BufferLength + ) +/*++ + +Routine Description: + + Parses EFI Sections + +Arguments: + + SectionBuffer - Buffer containing the section to parse. + BufferLength - Length of SectionBuffer + +Returns: + + EFI_SECTION_ERROR - Problem with section parsing. + (a) compression errors + (b) unrecognized section + EFI_UNSUPPORTED - Do not know how to parse the section. + EFI_SUCCESS - Section successfully parsed. + EFI_OUT_OF_RESOURCES - Memory allocation failed. + +--*/ +{ + EFI_SECTION_TYPE Type; + UINT8 *Ptr; + UINT32 SectionLength; + UINT32 SectionHeaderLen; + CHAR8 *SectionName; + EFI_STATUS Status; + UINT32 ParsedLength; + UINT8 *CompressedBuffer; + UINT32 CompressedLength; + UINT8 *UncompressedBuffer; + UINT32 UncompressedLength; + UINT8 *ToolOutputBuffer; + UINT32 ToolOutputLength; + UINT8 CompressionType; + UINT32 DstSize; + UINT32 ScratchSize; + UINT8 *ScratchBuffer; + DECOMPRESS_FUNCTION DecompressFunction; + GETINFO_FUNCTION GetInfoFunction; + // CHAR16 *name; + CHAR8 *ExtractionTool; + CHAR8 *ToolInputFile; + CHAR8 *ToolOutputFile; + CHAR8 *SystemCommand; + EFI_GUID *EfiGuid; + UINT16 DataOffset; + UINT16 Attributes; + UINT32 RealHdrLen; + CHAR8 *ToolInputFileName; + CHAR8 *ToolOutputFileName; + CHAR8 *UIFileName; + + ParsedLength = 0; + ToolInputFileName = NULL; + ToolOutputFileName = NULL; + + while (ParsedLength < BufferLength) { + Ptr = SectionBuffer + ParsedLength; + + SectionLength = GetLength (((EFI_COMMON_SECTION_HEADER *) Ptr)->Size); + Type = ((EFI_COMMON_SECTION_HEADER *) Ptr)->Type; + + // + // This is sort of an odd check, but is necessary because FFS files are + // padded to a QWORD boundary, meaning there is potentially a whole section + // header worth of 0xFF bytes. + // + if (SectionLength == 0xffffff && Type == 0xff) { + ParsedLength += 4; + continue; + } + + // + // Get real section file size + // + SectionLength = GetSectionFileLength ((EFI_COMMON_SECTION_HEADER *) Ptr); + SectionHeaderLen = GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr); + + SectionName = SectionNameToStr (Type); + if (SectionName != NULL) { + printf ("------------------------------------------------------------\n"); + printf (" Type: %s\n Size: 0x%08X\n", SectionName, (unsigned) SectionLength); + free (SectionName); + } + + switch (Type) { + case EFI_SECTION_RAW: + case EFI_SECTION_PIC: + case EFI_SECTION_TE: + // default is no more information + break; + + case EFI_SECTION_PE32: + if (EnableHash) { + ToolInputFileName = "edk2Temp_InputEfi.tmp"; + ToolOutputFileName = "edk2Temp_OutputHash.tmp"; + RebaseImage(ToolInputFileName, (UINT8*)Ptr + SectionHeaderLen, 0); + PutFileImage ( + ToolInputFileName, + (CHAR8*)Ptr + SectionHeaderLen, + SectionLength - SectionHeaderLen + ); + + SystemCommand = malloc ( + strlen (OPENSSL_COMMAND_FORMAT_STRING) + + strlen (OpenSslPath) + + strlen (ToolInputFileName) + + strlen (ToolOutputFileName) + + 1 + ); + if (SystemCommand == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return EFI_OUT_OF_RESOURCES; + } + sprintf ( + SystemCommand, + OPENSSL_COMMAND_FORMAT_STRING, + OpenSslPath, + ToolOutputFileName, + ToolInputFileName + ); + + if (system (SystemCommand) != EFI_SUCCESS) { + Error (NULL, 0, 3000, "Open SSL command not available. Please verify PATH or set OPENSSL_PATH.", NULL); + } + else { + FILE *fp; + CHAR8 *StrLine; + CHAR8 *NewStr; + UINT32 nFileLen; + if((fp = fopen(ToolOutputFileName,"r")) == NULL) { + Error (NULL, 0, 0004, "Hash the PE32 image failed.", NULL); + } + else { + fseek(fp,0,SEEK_SET); + fseek(fp,0,SEEK_END); + nFileLen = ftell(fp); + fseek(fp,0,SEEK_SET); + StrLine = malloc(nFileLen); + if (StrLine == NULL) { + fclose(fp); + free (SystemCommand); + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return EFI_OUT_OF_RESOURCES; + } + fgets(StrLine, nFileLen, fp); + NewStr = strrchr (StrLine, '='); + printf (" SHA1: %s\n", NewStr + 1); + free (StrLine); + fclose(fp); + } + } + remove(ToolInputFileName); + remove(ToolOutputFileName); + free (SystemCommand); + } + break; + + case EFI_SECTION_USER_INTERFACE: + UIFileName = (CHAR8 *) malloc (UnicodeStrLen (((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString) + 1); + if (UIFileName == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return EFI_OUT_OF_RESOURCES; + } + Unicode2AsciiString (((EFI_USER_INTERFACE_SECTION *) Ptr)->FileNameString, UIFileName); + printf (" String: %s\n", UIFileName); + free (UIFileName); + break; + + case EFI_SECTION_FIRMWARE_VOLUME_IMAGE: + Status = PrintFvInfo (Ptr + SectionHeaderLen, TRUE); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "printing of FV section contents failed", NULL); + return EFI_SECTION_ERROR; + } + break; + + case EFI_SECTION_COMPATIBILITY16: + case EFI_SECTION_FREEFORM_SUBTYPE_GUID: + // + // Section does not contain any further header information. + // + break; + + case EFI_SECTION_PEI_DEPEX: + case EFI_SECTION_DXE_DEPEX: + case EFI_SECTION_SMM_DEPEX: + DumpDepexSection (Ptr, SectionLength); + break; + + case EFI_SECTION_VERSION: + printf (" Build Number: 0x%02X\n", *(UINT16 *)(Ptr + SectionHeaderLen)); + printf (" Version Strg: %s\n", (char*) (Ptr + SectionHeaderLen + sizeof (UINT16))); + break; + + case EFI_SECTION_COMPRESSION: + UncompressedBuffer = NULL; + if (SectionHeaderLen == sizeof (EFI_COMMON_SECTION_HEADER)) { + RealHdrLen = sizeof(EFI_COMPRESSION_SECTION); + UncompressedLength = ((EFI_COMPRESSION_SECTION *)Ptr)->UncompressedLength; + CompressionType = ((EFI_COMPRESSION_SECTION *)Ptr)->CompressionType; + } else { + RealHdrLen = sizeof(EFI_COMPRESSION_SECTION2); + UncompressedLength = ((EFI_COMPRESSION_SECTION2 *)Ptr)->UncompressedLength; + CompressionType = ((EFI_COMPRESSION_SECTION2 *)Ptr)->CompressionType; + } + CompressedLength = SectionLength - RealHdrLen; + printf (" Uncompressed Length: 0x%08X\n", (unsigned) UncompressedLength); + + if (CompressionType == EFI_NOT_COMPRESSED) { + printf (" Compression Type: EFI_NOT_COMPRESSED\n"); + if (CompressedLength != UncompressedLength) { + Error ( + NULL, + 0, + 0, + "file is not compressed, but the compressed length does not match the uncompressed length", + NULL + ); + return EFI_SECTION_ERROR; + } + + UncompressedBuffer = Ptr + RealHdrLen; + } else if (CompressionType == EFI_STANDARD_COMPRESSION) { + GetInfoFunction = EfiGetInfo; + DecompressFunction = EfiDecompress; + printf (" Compression Type: EFI_STANDARD_COMPRESSION\n"); + + CompressedBuffer = Ptr + RealHdrLen; + + Status = GetInfoFunction (CompressedBuffer, CompressedLength, &DstSize, &ScratchSize); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "error getting compression info from compression section", NULL); + return EFI_SECTION_ERROR; + } + + if (DstSize != UncompressedLength) { + Error (NULL, 0, 0003, "compression error in the compression section", NULL); + return EFI_SECTION_ERROR; + } + + ScratchBuffer = malloc (ScratchSize); + if (ScratchBuffer == NULL) { + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return EFI_OUT_OF_RESOURCES; + } + UncompressedBuffer = malloc (UncompressedLength); + if (UncompressedBuffer == NULL) { + free (ScratchBuffer); + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return EFI_OUT_OF_RESOURCES; + } + Status = DecompressFunction ( + CompressedBuffer, + CompressedLength, + UncompressedBuffer, + UncompressedLength, + ScratchBuffer, + ScratchSize + ); + free (ScratchBuffer); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "decompress failed", NULL); + free (UncompressedBuffer); + return EFI_SECTION_ERROR; + } + } else { + Error (NULL, 0, 0003, "unrecognized compression type", "type 0x%X", CompressionType); + return EFI_SECTION_ERROR; + } + + Status = ParseSection (UncompressedBuffer, UncompressedLength); + + if (CompressionType == EFI_STANDARD_COMPRESSION) { + // + // We need to deallocate Buffer + // + free (UncompressedBuffer); + } + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "failed to parse section", NULL); + return EFI_SECTION_ERROR; + } + break; + + case EFI_SECTION_GUID_DEFINED: + if (SectionHeaderLen == sizeof(EFI_COMMON_SECTION_HEADER)) { + EfiGuid = &((EFI_GUID_DEFINED_SECTION *) Ptr)->SectionDefinitionGuid; + DataOffset = ((EFI_GUID_DEFINED_SECTION *) Ptr)->DataOffset; + Attributes = ((EFI_GUID_DEFINED_SECTION *) Ptr)->Attributes; + } else { + EfiGuid = &((EFI_GUID_DEFINED_SECTION2 *) Ptr)->SectionDefinitionGuid; + DataOffset = ((EFI_GUID_DEFINED_SECTION2 *) Ptr)->DataOffset; + Attributes = ((EFI_GUID_DEFINED_SECTION2 *) Ptr)->Attributes; + } + printf (" SectionDefinitionGuid: "); + PrintGuid (EfiGuid); + printf ("\n"); + printf (" DataOffset: 0x%04X\n", (unsigned) DataOffset); + printf (" Attributes: 0x%04X\n", (unsigned) Attributes); + + ExtractionTool = + LookupGuidedSectionToolPath ( + mParsedGuidedSectionTools, + EfiGuid + ); + + if (ExtractionTool != NULL) { + #ifndef __GNUC__ + ToolInputFile = CloneString (tmpnam (NULL)); + ToolOutputFile = CloneString (tmpnam (NULL)); + #else + char tmp1[] = "/tmp/fileXXXXXX"; + char tmp2[] = "/tmp/fileXXXXXX"; + int fd1; + int fd2; + fd1 = mkstemp(tmp1); + fd2 = mkstemp(tmp2); + ToolInputFile = CloneString(tmp1); + ToolOutputFile = CloneString(tmp2); + close(fd1); + close(fd2); + #endif + + if ((ToolInputFile == NULL) || (ToolOutputFile == NULL)) { + if (ToolInputFile != NULL) { + free (ToolInputFile); + } + if (ToolOutputFile != NULL) { + free (ToolOutputFile); + } + free (ExtractionTool); + + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return EFI_OUT_OF_RESOURCES; + } + + // + // Construction 'system' command string + // + SystemCommand = malloc ( + strlen (EXTRACT_COMMAND_FORMAT_STRING) + + strlen (ExtractionTool) + + strlen (ToolInputFile) + + strlen (ToolOutputFile) + + 1 + ); + if (SystemCommand == NULL) { + free (ToolInputFile); + free (ToolOutputFile); + free (ExtractionTool); + + Error (NULL, 0, 4001, "Resource", "memory cannot be allocated!"); + return EFI_OUT_OF_RESOURCES; + } + sprintf ( + SystemCommand, + EXTRACT_COMMAND_FORMAT_STRING, + ExtractionTool, + ToolOutputFile, + ToolInputFile + ); + free (ExtractionTool); + + Status = + PutFileImage ( + ToolInputFile, + (CHAR8*) SectionBuffer + DataOffset, + BufferLength - DataOffset + ); + + system (SystemCommand); + remove (ToolInputFile); + free (ToolInputFile); + + Status = + GetFileImage ( + ToolOutputFile, + (CHAR8 **)&ToolOutputBuffer, + &ToolOutputLength + ); + remove (ToolOutputFile); + free (ToolOutputFile); + free (SystemCommand); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0004, "unable to read decoded GUIDED section", NULL); + return EFI_SECTION_ERROR; + } + + Status = ParseSection ( + ToolOutputBuffer, + ToolOutputLength + ); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "parse of decoded GUIDED section failed", NULL); + return EFI_SECTION_ERROR; + } + + // + // Check for CRC32 sections which we can handle internally if needed. + // + } else if (!CompareGuid ( + EfiGuid, + &gEfiCrc32GuidedSectionExtractionProtocolGuid + ) + ) { + // + // CRC32 guided section + // + Status = ParseSection ( + SectionBuffer + DataOffset, + BufferLength - DataOffset + ); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0003, "parse of CRC32 GUIDED section failed", NULL); + return EFI_SECTION_ERROR; + } + } else { + // + // We don't know how to parse it now. + // + Error (NULL, 0, 0003, "Error parsing section", \ + "EFI_SECTION_GUID_DEFINED cannot be parsed at this time. Tool to decode this section should have been defined in GuidedSectionTools.txt (built in the FV directory)."); + return EFI_UNSUPPORTED; + } + break; + + default: + // + // Unknown section, return error + // + Error (NULL, 0, 0003, "unrecognized section type found", "section type = 0x%X", Type); + return EFI_SECTION_ERROR; + } + + ParsedLength += SectionLength; + // + // We make then next section begin on a 4-byte boundary + // + ParsedLength = GetOccupiedSize (ParsedLength, 4); + } + + if (ParsedLength < BufferLength) { + Error (NULL, 0, 0003, "sections do not completely fill the sectioned buffer being parsed", NULL); + return EFI_SECTION_ERROR; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +DumpDepexSection ( + IN UINT8 *Ptr, + IN UINT32 SectionLength + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + Ptr - GC_TODO: add argument description + SectionLength - GC_TODO: add argument description + +Returns: + + EFI_SUCCESS - GC_TODO: Add description for return value + +--*/ +{ + UINT8 GuidBuffer[PRINTED_GUID_BUFFER_SIZE]; + + // + // Need at least a section header + data + // + if (SectionLength <= sizeof (EFI_COMMON_SECTION_HEADER)) { + return EFI_SUCCESS; + } + + Ptr += GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr); + SectionLength -= GetSectionHeaderLength((EFI_COMMON_SECTION_HEADER *)Ptr); + while (SectionLength > 0) { + printf (" "); + switch (*Ptr) { + case EFI_DEP_BEFORE: + printf ("BEFORE\n"); + Ptr++; + SectionLength--; + break; + + case EFI_DEP_AFTER: + printf ("AFTER\n"); + Ptr++; + SectionLength--; + break; + + case EFI_DEP_PUSH: + printf ("PUSH\n "); + PrintGuidToBuffer ((EFI_GUID *) (Ptr + 1), GuidBuffer, sizeof (GuidBuffer), TRUE); + printf ("%s ", GuidBuffer); + PrintGuidName (GuidBuffer); + printf ("\n"); + // + // PrintGuid ((EFI_GUID *)(Ptr + 1)); + // + Ptr += 17; + SectionLength -= 17; + break; + + case EFI_DEP_AND: + printf ("AND\n"); + Ptr++; + SectionLength--; + break; + + case EFI_DEP_OR: + printf ("OR\n"); + Ptr++; + SectionLength--; + break; + + case EFI_DEP_NOT: + printf ("NOT\n"); + Ptr++; + SectionLength--; + break; + + case EFI_DEP_TRUE: + printf ("TRUE\n"); + Ptr++; + SectionLength--; + break; + + case EFI_DEP_FALSE: + printf ("FALSE\n"); + Ptr++; + SectionLength--; + break; + + case EFI_DEP_END: + printf ("END DEPEX\n"); + Ptr++; + SectionLength--; + break; + + case EFI_DEP_SOR: + printf ("SOR\n"); + Ptr++; + SectionLength--; + break; + + default: + printf ("Unrecognized byte in depex: 0x%X\n", *Ptr); + return EFI_SUCCESS; + } + } + + return EFI_SUCCESS; +} + +EFI_STATUS +PrintGuidName ( + IN UINT8 *GuidStr + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + GuidStr - GC_TODO: add argument description + +Returns: + + EFI_SUCCESS - GC_TODO: Add description for return value + EFI_INVALID_PARAMETER - GC_TODO: Add description for return value + +--*/ +{ + GUID_TO_BASENAME *GPtr; + // + // If we have a list of guid-to-basenames, then go through the list to + // look for a guid string match. If found, print the basename to stdout, + // otherwise return a failure. + // + GPtr = mGuidBaseNameList; + while (GPtr != NULL) { + if (_stricmp ((CHAR8*) GuidStr, (CHAR8*) GPtr->Guid) == 0) { + printf ("%s", GPtr->BaseName); + return EFI_SUCCESS; + } + + GPtr = GPtr->Next; + } + + return EFI_INVALID_PARAMETER; +} + +EFI_STATUS +ParseGuidBaseNameFile ( + CHAR8 *FileName + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + FileName - GC_TODO: add argument description + +Returns: + + EFI_DEVICE_ERROR - GC_TODO: Add description for return value + EFI_OUT_OF_RESOURCES - GC_TODO: Add description for return value + EFI_SUCCESS - GC_TODO: Add description for return value + +--*/ +{ + FILE *Fptr; + CHAR8 Line[MAX_LINE_LEN]; + CHAR8 FormatString[MAX_LINE_LEN]; + GUID_TO_BASENAME *GPtr; + + if ((Fptr = fopen (LongFilePath (FileName), "r")) == NULL) { + printf ("ERROR: Failed to open input cross-reference file '%s'\n", FileName); + return EFI_DEVICE_ERROR; + } + + // + // Generate the format string for fscanf + // + sprintf ( + FormatString, + "%%%us %%%us", + (unsigned) sizeof (GPtr->Guid) - 1, + (unsigned) sizeof (GPtr->BaseName) - 1 + ); + + while (fgets (Line, sizeof (Line), Fptr) != NULL) { + // + // Allocate space for another guid/basename element + // + GPtr = malloc (sizeof (GUID_TO_BASENAME)); + if (GPtr == NULL) { + fclose (Fptr); + return EFI_OUT_OF_RESOURCES; + } + + memset ((char *) GPtr, 0, sizeof (GUID_TO_BASENAME)); + if (sscanf (Line, FormatString, GPtr->Guid, GPtr->BaseName) == 2) { + GPtr->Next = mGuidBaseNameList; + mGuidBaseNameList = GPtr; + } else { + // + // Some sort of error. Just continue. + // + free (GPtr); + } + } + + fclose (Fptr); + return EFI_SUCCESS; +} + +EFI_STATUS +FreeGuidBaseNameList ( + VOID + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + None + +Returns: + + EFI_SUCCESS - GC_TODO: Add description for return value + +--*/ +{ + GUID_TO_BASENAME *Next; + + while (mGuidBaseNameList != NULL) { + Next = mGuidBaseNameList->Next; + free (mGuidBaseNameList); + mGuidBaseNameList = Next; + } + + return EFI_SUCCESS; +} + + +static +VOID +LoadGuidedSectionToolsTxt ( + IN CHAR8* FirmwareVolumeFilename + ) +{ + CHAR8* PeerFilename; + CHAR8* Places[] = { + NULL, + //NULL, + }; + UINTN Index; + + Places[0] = FirmwareVolumeFilename; + //Places[1] = mUtilityFilename; + + mParsedGuidedSectionTools = NULL; + + for (Index = 0; Index < (sizeof(Places)/sizeof(Places[0])); Index++) { + PeerFilename = OsPathPeerFilePath (Places[Index], "GuidedSectionTools.txt"); + //printf("Loading %s...\n", PeerFilename); + if (OsPathExists (PeerFilename)) { + mParsedGuidedSectionTools = ParseGuidedSectionToolsFile (PeerFilename); + } + free (PeerFilename); + if (mParsedGuidedSectionTools != NULL) { + return; + } + } +} + + +void +Usage ( + VOID + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + None + +Returns: + + GC_TODO: add return values + +--*/ +{ + // + // Summary usage + // + fprintf (stdout, "Usage: %s [options] \n\n", UTILITY_NAME); + + // + // Copyright declaration + // + fprintf (stdout, "Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.\n\n"); + fprintf (stdout, " Display Tiano Firmware Volume FFS image information\n\n"); + + // + // Details Option + // + fprintf (stdout, "optional arguments:\n"); + fprintf (stdout, " -h, --help\n\ + Show this help message and exit\n"); + fprintf (stdout, " --version\n\ + Show program's version number and exit\n"); + fprintf (stdout, " -d [DEBUG], --debug [DEBUG]\n\ + Output DEBUG statements, where DEBUG_LEVEL is 0 (min) - 9 (max)\n"); + fprintf (stdout, " -v, --verbose\n\ + Print informational statements\n"); + fprintf (stdout, " -q, --quiet\n\ + Returns the exit code, error messages will be displayed\n"); + fprintf (stdout, " -s, --silent\n\ + Returns only the exit code; informational and error\n\ + messages are not displayed\n"); + fprintf (stdout, " -x XREF_FILENAME, --xref XREF_FILENAME\n\ + Parse the basename to file-guid cross reference file(s)\n"); + fprintf (stdout, " -f OFFSET, --offset OFFSET\n\ + The offset from the start of the input file to start \n\ + processing an FV\n"); + fprintf (stdout, " --hash\n\ + Generate HASH value of the entire PE image\n"); + fprintf (stdout, " --sfo\n\ + Reserved for future use\n"); +} + diff --git a/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/VolInfo.h b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/VolInfo.h new file mode 100644 index 00000000..5ae388f8 --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/BaseTools/Source/C/VolInfo/VolInfo.h @@ -0,0 +1,31 @@ +/** @file +Local Definitions for the VolInfo utility + +Copyright (c) 1999 - 2016, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _VOLINFO_H_ +#define _VOLINFO_H_ 1 + +#define PI_SPECIFICATION_VERSION 0x00010000 + +#define EFI_DEP_BEFORE 0x00 +#define EFI_DEP_AFTER 0x01 +#define EFI_DEP_PUSH 0x02 +#define EFI_DEP_AND 0x03 +#define EFI_DEP_OR 0x04 +#define EFI_DEP_NOT 0x05 +#define EFI_DEP_TRUE 0x06 +#define EFI_DEP_FALSE 0x07 +#define EFI_DEP_END 0x08 +#define EFI_DEP_SOR 0x09 + +#define EFI_SECTION_LAST_LEAF_SECTION_TYPE 0x1B +#define EFI_SECTION_LAST_SECTION_TYPE 0x1B + +#define OPENSSL_COMMAND_FORMAT_STRING "%s sha1 -out %s %s" +#define EXTRACT_COMMAND_FORMAT_STRING "%s -d -o %s %s" + +#endif -- cgit v1.2.3