From 3eb9473ea9a949badfe06ae61d2d3fcfa53651c7 Mon Sep 17 00:00:00 2001 From: qwang12 Date: Thu, 28 Jun 2007 07:00:39 +0000 Subject: Add in the 1st version of ECP. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@2832 6f19259b-4bc3-4df7-8a09-765794883524 --- EdkCompatibilityPkg/Sample/CommonTools.env | 672 +++ EdkCompatibilityPkg/Sample/Include/Efi2WinNT.h | 59 + .../Sample/Include/EfiCompNameSupport.h | 58 + EdkCompatibilityPkg/Sample/Include/EfiWinNt.h | 46 + .../Sample/Library/Dxe/WinNt/WinNtLib.c | 75 + .../Sample/Library/Dxe/WinNt/WinNtLib.inf | 49 + EdkCompatibilityPkg/Sample/LocalTools.env | 95 + EdkCompatibilityPkg/Sample/Platform/Common.dsc | 1522 +++++++ EdkCompatibilityPkg/Sample/Platform/CommonIa32.dsc | 558 +++ EdkCompatibilityPkg/Sample/Platform/CommonIpf.dsc | 391 ++ EdkCompatibilityPkg/Sample/Platform/CommonX64.dsc | 558 +++ .../Sample/Platform/EdkIIGlueLib32.dsc | 39 + .../Sample/Platform/EdkIIGlueLibAll.dsc | 54 + EdkCompatibilityPkg/Sample/Platform/EdkLib32.dsc | 36 + EdkCompatibilityPkg/Sample/Platform/EdkLibAll.dsc | 63 + .../Platform/Nt32/Protocol/EdkNt32ProtocolLib.inf | 46 + .../Platform/Nt32/Protocol/WinNtIo/WinNtIo.c | 40 + .../Platform/Nt32/Protocol/WinNtIo/WinNtIo.h | 163 + .../Platform/Nt32/Protocol/WinNtThunk/WinNtThunk.c | 28 + .../Platform/Nt32/Protocol/WinNtThunk/WinNtThunk.h | 1276 ++++++ .../Sample/Tools/Source/BootsectImage/Makefile | 97 + .../Tools/Source/BootsectImage/bootsectimage.c | 881 ++++ .../Sample/Tools/Source/BootsectImage/fat.h | 158 + .../Sample/Tools/Source/BootsectImage/mbr.h | 64 + .../Sample/Tools/Source/Common/CommonLib.c | 497 ++ .../Sample/Tools/Source/Common/CommonLib.h | 120 + .../Sample/Tools/Source/Common/Compress.h | 90 + .../Sample/Tools/Source/Common/Crc32.c | 327 ++ .../Sample/Tools/Source/Common/Crc32.h | 51 + .../Sample/Tools/Source/Common/Decompress.c | 995 +++++ .../Sample/Tools/Source/Common/Decompress.h | 174 + .../Sample/Tools/Source/Common/EfiCompress.c | 1600 +++++++ .../Tools/Source/Common/EfiCustomizedCompress.h | 138 + .../Sample/Tools/Source/Common/EfiUtilityMsgs.c | 756 ++++ .../Sample/Tools/Source/Common/EfiUtilityMsgs.h | 135 + .../Sample/Tools/Source/Common/FvLib.c | 786 ++++ .../Sample/Tools/Source/Common/FvLib.h | 177 + .../Sample/Tools/Source/Common/Makefile | 145 + .../Sample/Tools/Source/Common/MyAlloc.c | 516 +++ .../Sample/Tools/Source/Common/MyAlloc.h | 222 + .../Sample/Tools/Source/Common/ParseInf.c | 625 +++ .../Sample/Tools/Source/Common/ParseInf.h | 233 + .../Sample/Tools/Source/Common/SimpleFileParsing.c | 1456 ++++++ .../Sample/Tools/Source/Common/SimpleFileParsing.h | 118 + .../Sample/Tools/Source/Common/TianoCompress.c | 1765 ++++++++ .../Source/CustomizedCompress/CustomizedCompress.c | 146 + .../Tools/Source/CustomizedCompress/makefile | 82 + .../Tools/Source/EfiCompress/EfiCompressMain.c | 386 ++ .../Sample/Tools/Source/EfiCompress/makefile | 89 + .../Sample/Tools/Source/EfiRom/EfiRom.c | 1545 +++++++ .../Sample/Tools/Source/EfiRom/Makefile | 85 + .../Sample/Tools/Source/EfildrImage/Makefile | 96 + .../Sample/Tools/Source/EfildrImage/efildrimage.c | 188 + .../Sample/Tools/Source/FwImage/Makefile | 86 + .../Sample/Tools/Source/FwImage/fwimage.c | 587 +++ .../Tools/Source/GenAprioriFile/GenAprioriFile.c | 467 ++ .../Sample/Tools/Source/GenAprioriFile/Makefile | 78 + .../Tools/Source/GenBootsector/GetDrvNumOffset.c | 58 + .../Sample/Tools/Source/GenBootsector/fat.h | 158 + .../Tools/Source/GenBootsector/genbootsector.c | 652 +++ .../Sample/Tools/Source/GenBootsector/makefile | 99 + .../Tools/Source/GenCRC32Section/GenCRC32Section.c | 299 ++ .../Tools/Source/GenCRC32Section/GenCRC32Section.h | 43 + .../Sample/Tools/Source/GenCRC32Section/makefile | 85 + .../Sample/Tools/Source/GenDepex/DepexParser.c | 890 ++++ .../Sample/Tools/Source/GenDepex/DepexParser.h | 26 + .../Sample/Tools/Source/GenDepex/GenDepex.c | 912 ++++ .../Sample/Tools/Source/GenDepex/GenDepex.h | 67 + .../Sample/Tools/Source/GenDepex/makefile | 100 + .../Sample/Tools/Source/GenFfsFile/GenFfsFile.c | 2681 +++++++++++ .../Sample/Tools/Source/GenFfsFile/GenFfsFile.h | 35 + .../Sample/Tools/Source/GenFfsFile/makefile | 88 + .../Sample/Tools/Source/GenFvImage/GenFvImageExe.c | 299 ++ .../Sample/Tools/Source/GenFvImage/GenFvImageExe.h | 98 + .../Sample/Tools/Source/GenFvImage/GenFvImageLib.c | 3054 +++++++++++++ .../Sample/Tools/Source/GenFvImage/GenFvImageLib.h | 140 + .../Source/GenFvImage/GenFvImageLibInternal.h | 212 + .../Sample/Tools/Source/GenFvImage/Makefile | 109 + .../Sample/Tools/Source/GenPage/Makefile | 95 + .../Sample/Tools/Source/GenPage/VirtualMemory.h | 127 + .../Sample/Tools/Source/GenPage/genpage.c | 344 ++ .../Sample/Tools/Source/GenSection/GenSection.c | 1000 +++++ .../Sample/Tools/Source/GenSection/GenSection.h | 42 + .../Sample/Tools/Source/GenSection/makefile | 82 + .../Sample/Tools/Source/GuidChk/CommonUtils.h | 57 + .../Sample/Tools/Source/GuidChk/FileSearch.c | 285 ++ .../Sample/Tools/Source/GuidChk/FileSearch.h | 108 + .../Sample/Tools/Source/GuidChk/GuidChk.c | 2417 ++++++++++ .../Sample/Tools/Source/GuidChk/GuidList.c | 188 + .../Sample/Tools/Source/GuidChk/Makefile | 96 + .../Sample/Tools/Source/GuidChk/UtilsMsgs.c | 489 ++ .../Sample/Tools/Source/GuidChk/UtilsMsgs.h | 106 + .../Sample/Tools/Source/MakeDeps/MakeDeps.c | 1316 ++++++ .../Sample/Tools/Source/MakeDeps/Makefile | 69 + EdkCompatibilityPkg/Sample/Tools/Source/Makefile | 79 + .../Sample/Tools/Source/ModifyInf/Makefile | 82 + .../Sample/Tools/Source/ModifyInf/ModifyInf.c | 322 ++ .../Sample/Tools/Source/ProcessDsc/Common.h | 123 + .../Sample/Tools/Source/ProcessDsc/DscFile.c | 534 +++ .../Sample/Tools/Source/ProcessDsc/DscFile.h | 109 + .../Sample/Tools/Source/ProcessDsc/Exceptions.c | 141 + .../Sample/Tools/Source/ProcessDsc/Exceptions.h | 57 + .../Sample/Tools/Source/ProcessDsc/FWVolume.c | 1566 +++++++ .../Sample/Tools/Source/ProcessDsc/FWVolume.h | 76 + .../Sample/Tools/Source/ProcessDsc/Makefile | 102 + .../Sample/Tools/Source/ProcessDsc/ProcessDsc.c | 4726 ++++++++++++++++++++ .../Sample/Tools/Source/SetStamp/Makefile | 88 + .../Sample/Tools/Source/SetStamp/SetStamp.c | 475 ++ .../Sample/Tools/Source/SplitFile/Makefile | 94 + .../Sample/Tools/Source/SplitFile/splitfile.c | 136 + .../Sample/Tools/Source/StrGather/Makefile | 89 + .../Sample/Tools/Source/StrGather/StrGather.c | 2574 +++++++++++ .../Sample/Tools/Source/StrGather/StrGather.h | 84 + .../Sample/Tools/Source/StrGather/StringDB.c | 2808 ++++++++++++ .../Sample/Tools/Source/StrGather/StringDB.h | 136 + .../Sample/Tools/Source/VcCheck/VcCheck.c | 121 + .../Sample/Tools/Source/VcCheck/makefile | 92 + .../Sample/Tools/Source/VfrCompile/EfiVfr.h | 178 + .../Sample/Tools/Source/VfrCompile/VfrCompile.g | 3463 ++++++++++++++ .../Sample/Tools/Source/VfrCompile/VfrServices.cpp | 754 ++++ .../Sample/Tools/Source/VfrCompile/VfrServices.h | 227 + .../Sample/Tools/Source/VfrCompile/makefile | 172 + EdkCompatibilityPkg/Sample/Version.env | 34 + 123 files changed, 58157 insertions(+) create mode 100644 EdkCompatibilityPkg/Sample/CommonTools.env create mode 100644 EdkCompatibilityPkg/Sample/Include/Efi2WinNT.h create mode 100644 EdkCompatibilityPkg/Sample/Include/EfiCompNameSupport.h create mode 100644 EdkCompatibilityPkg/Sample/Include/EfiWinNt.h create mode 100644 EdkCompatibilityPkg/Sample/Library/Dxe/WinNt/WinNtLib.c create mode 100644 EdkCompatibilityPkg/Sample/Library/Dxe/WinNt/WinNtLib.inf create mode 100644 EdkCompatibilityPkg/Sample/LocalTools.env create mode 100644 EdkCompatibilityPkg/Sample/Platform/Common.dsc create mode 100644 EdkCompatibilityPkg/Sample/Platform/CommonIa32.dsc create mode 100644 EdkCompatibilityPkg/Sample/Platform/CommonIpf.dsc create mode 100644 EdkCompatibilityPkg/Sample/Platform/CommonX64.dsc create mode 100644 EdkCompatibilityPkg/Sample/Platform/EdkIIGlueLib32.dsc create mode 100644 EdkCompatibilityPkg/Sample/Platform/EdkIIGlueLibAll.dsc create mode 100644 EdkCompatibilityPkg/Sample/Platform/EdkLib32.dsc create mode 100644 EdkCompatibilityPkg/Sample/Platform/EdkLibAll.dsc create mode 100644 EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/EdkNt32ProtocolLib.inf create mode 100644 EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtIo/WinNtIo.c create mode 100644 EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtIo/WinNtIo.h create mode 100644 EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtThunk/WinNtThunk.c create mode 100644 EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtThunk/WinNtThunk.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/Makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/bootsectimage.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/fat.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/mbr.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/CommonLib.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/CommonLib.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/Compress.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/Crc32.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/Crc32.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/Decompress.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/Decompress.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiCompress.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiCustomizedCompress.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiUtilityMsgs.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiUtilityMsgs.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/FvLib.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/FvLib.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/Makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/MyAlloc.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/MyAlloc.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/ParseInf.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/ParseInf.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/SimpleFileParsing.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/SimpleFileParsing.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Common/TianoCompress.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/CustomizedCompress/CustomizedCompress.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/CustomizedCompress/makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/EfiCompress/EfiCompressMain.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/EfiCompress/makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/EfiRom/EfiRom.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/EfiRom/Makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/EfildrImage/Makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/EfildrImage/efildrimage.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/FwImage/Makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/FwImage/fwimage.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenAprioriFile/GenAprioriFile.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenAprioriFile/Makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/GetDrvNumOffset.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/fat.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/genbootsector.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenCRC32Section/GenCRC32Section.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenCRC32Section/GenCRC32Section.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenCRC32Section/makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/DepexParser.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/DepexParser.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/GenDepex.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/GenDepex.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/GenFfsFile.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/GenFfsFile.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageExe.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageExe.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLibInternal.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/Makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenPage/Makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenPage/VirtualMemory.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenPage/genpage.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenSection/GenSection.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenSection/GenSection.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GenSection/makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/CommonUtils.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/FileSearch.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/FileSearch.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/GuidChk.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/GuidList.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/Makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/UtilsMsgs.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/UtilsMsgs.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/MakeDeps/MakeDeps.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/MakeDeps/Makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/Makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/ModifyInf/Makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/ModifyInf/ModifyInf.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Common.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/DscFile.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/DscFile.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Exceptions.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Exceptions.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/FWVolume.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/FWVolume.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/ProcessDsc.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/SetStamp/Makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/SetStamp/SetStamp.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/SplitFile/Makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/SplitFile/splitfile.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/StrGather/Makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StrGather.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StrGather.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StringDB.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StringDB.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/VcCheck/VcCheck.c create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/VcCheck/makefile create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/EfiVfr.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrCompile.g create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrServices.cpp create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrServices.h create mode 100644 EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/makefile create mode 100644 EdkCompatibilityPkg/Sample/Version.env (limited to 'EdkCompatibilityPkg/Sample') diff --git a/EdkCompatibilityPkg/Sample/CommonTools.env b/EdkCompatibilityPkg/Sample/CommonTools.env new file mode 100644 index 0000000000..2d97156a02 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/CommonTools.env @@ -0,0 +1,672 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CommonTools.env +# +# Abstract: +# +# This file should not need to be customized. Customizations should +# be done in LocalTools.env if at all possible. +# +# This file can be included by other makefiles. +# +# It defines variables used by the different toolchains. It first includes +# the user-customized LocalTools.env, and then uses those defines to +# define other variables. +# +# It basically has sections for different toolchains which define variables +# used to build. +# +#--*/ + +# +# Everything depends on EDK_SOURCE. Make sure it's defined +# +!IFNDEF EDK_SOURCE +!ERROR EDK_SOURCE environmental variable not set +!ENDIF + +# +# Tools depend on BUILD_DIR. Make sure it's defined +# +!IFNDEF BUILD_DIR +!ERROR BUILD_DIR environmental variable not set. Should be set in PlatformTools.env +!ENDIF + +# +# This include file gets customized by the developer. Get the customizations. +# +!INCLUDE $(EDK_SOURCE)\Sample\LocalTools.env + +################################################################################ +# +# Define paths for EFI build tools +# +################################################################################ +!IFNDEF EDK_TOOLS_PATH +EDK_TOOLS_BIN = $(EDK_SOURCE)\Tools\Bin +!ELSE +EDK_TOOLS_BIN = $(EDK_TOOLS_PATH)\Bin +!ENDIF +EDK_TOOLS_DIR = $(EDK_SOURCE)\Sample\Tools +EDK_TOOLS_SOURCE = $(EDK_TOOLS_DIR)\Source +EDK_TOOLS_COMMON = $(EDK_TOOLS_DIR)\Source\Common +EDK_TOOLS_OUTPUT = $(BUILD_DIR)\Tools +PCCTS_DIR = $(EDK_SOURCE)\Other\Maintained\Tools\Pccts + +# +# This include file gets some version info. +# +!INCLUDE $(EDK_SOURCE)\Sample\Version.env + +# +# Macros to define the build tools +# +ANTLR = $(PCCTS_DIR)\bin\antlr +DLG = $(PCCTS_DIR)\bin\dlg +FWIMAGE = $(EDK_TOOLS_OUTPUT)\FwImage +GENDEPEX = $(EDK_TOOLS_OUTPUT)\GenDepex +GENFDIMAGE = $(EDK_TOOLS_OUTPUT)\GenFdImage +GENFFSFILE = $(EDK_TOOLS_OUTPUT)\GenFfsFile +GENFVIMAGE = $(EDK_TOOLS_OUTPUT)\GenFvImage +GENSECTION = $(EDK_TOOLS_OUTPUT)\GenSection +GUIDCHK = $(EDK_TOOLS_OUTPUT)\GuidChk +MAKEDEPS = $(EDK_TOOLS_OUTPUT)\MakeDeps +PROCESSDSC = $(EDK_TOOLS_OUTPUT)\ProcessDsc +STRGATHER = $(EDK_TOOLS_OUTPUT)\StrGather +SETSTAMP = $(EDK_TOOLS_OUTPUT)\SetStamp +VFRCOMPILE = $(EDK_TOOLS_OUTPUT)\VfrCompile +GENAPRIORI = $(EDK_TOOLS_OUTPUT)\GenAprioriFile +MODIFYINF = $(EDK_TOOLS_OUTPUT)\ModifyInf + +MAKE = nmake -nologo + +# +# Everything else requires that TOOLCHAIN be defined. This should be defined +# by the calling makefile. +# +!IFNDEF TOOLCHAIN +!ERROR TOOLCHAIN not defined for $(EDK_SOURCE)\Sample\CommonTools.env +!ENDIF + +############################################################################### +# +# Specify the path and macros for ASL tools +# +############################################################################### +!IF "$(EFI_ASL_LOCAL)" == "YES" +ASL = $(ASLPATH)\Iasl +!ELSE +ASL = $(EDK_TOOLS_BIN)\Iasl +!ENDIF + +ASL_FLAGS = +C_FLAGS_ASL = /nologo /EP /C + +############################################################################### +# +# Specify the path and macros for IA32 tools +# +############################################################################### + +!IF "$(TOOLCHAIN)" == "TOOLCHAIN_IA32" + +# +# Globally relevant flags. Options not appropriate for all builds may be +# appropriate in the processor architecture specific macros (xxx_ARCH_FLAGS) or +# in the platform specific macros (xxx_PROJ_FLAGS) +# +C_STD_INCLUDE = /X +!IF "$(EFI_GENERATE_INTERMEDIATE_FILE)" == "YES" +!IF "$(USE_VC8)" == "YES" +C_STD_FLAGS = /nologo /W4 /WX /EHsc /Gy /GS- /D USE_VC8 /c /Fa$* /FAsc /Fo$@ /FR$(@R).SBR $(INC) +!ELSE +C_STD_FLAGS = /nologo /W4 /WX /GX /Gy /c /Fa$* /FAsc /Fo$@ /FR$(@R).SBR $(INC) +!ENDIF +!ELSE +!IF "$(USE_VC8)" == "YES" +C_STD_FLAGS = /nologo /W4 /WX /EHsc /Gy /GS- /D USE_VC8 /c /Fo$@ $(INC) +!ELSE +C_STD_FLAGS = /nologo /W4 /WX /GX /Gy /c /Fo$@ $(INC) +!ENDIF +!ENDIF +ASM_STD_FLAGS = /nologo $(INC) +LINK_STD_FLAGS = /nologo /SUBSYSTEM:CONSOLE /NODEFAULTLIB /MAP /OPT:REF /BASE:0 /IGNORE:4001,4078,4086,4096,4108 $(BUILD_DIR)\IA32\CompilerStub.lib +LIB_STD_FLAGS = /nologo + +# +# Build type specific flags. Globally relevant flags belong in the standard +# macros, xxx_STD_FLAGS defined above. Platform specific macros belong in the +# PlatformTools.env file in macros named xxx_PROJ_FLAGS. +# +C_ARCH_FLAGS = /D EFI32 +ASM_ARCH_FLAGS = /W3 /WX /c /coff /Fo$@ /DEFI32 +LINK_ARCH_FLAGS = /MACHINE:I386 +LIB_ARCH_FLAGS = + +ASM16_FLAGS = /nologo /c /omf /Fo$@ +ASMLINK16_FLAGS = + +# +# Build tools +# +CC = cl +LINK = link +LIB = lib +# +# When using VS ml to compile 16bit code, please add /omf compiler option +# +ASM = ml + +!IF "$(EFI_ASSEMBLER_NAME)" == "" +ASM16 = $(MASMPATH)\bin\ml +ASMLINK16 = $(MASMPATH)\binr\link +ASMLINK = $(MASMPATH)\binr\link +!ELSE +ASM16 = $(EDK_TOOLS_BIN)\Ia32\$(EFI_ASSEMBLER_NAME)\bin\ml +ASMLINK16 = $(EDK_TOOLS_BIN)\Ia32\$(EFI_ASSEMBLER_NAME)\binr\link +ASMLINK = $(EDK_TOOLS_BIN)\Ia32\$(EFI_ASSEMBLER_NAME)\binr\link +!ENDIF + +BSCMAKE = bscmake + +!IF "$(EFI_SYMBOLIC_DEBUG)" == "YES" +ASM_ARCH_FLAGS = $(ASM_ARCH_FLAGS) /Zi /DDEBUG +C_STD_FLAGS = $(C_STD_FLAGS) /Zi /Gm /Fd$(DEST_DIR)\$(BASE_NAME)Obj +LINK_STD_FLAGS = $(LINK_STD_FLAGS) /DEBUG +!ENDIF + +# END OF TOOLCHAIN_IA32 +############################################################################### + +############################################################################### +# +# Specify the path and macros for the X64 (also called x86-64, EM64T, AMD64) tools +# +############################################################################### + +!ELSEIF "$(TOOLCHAIN)" == "TOOLCHAIN_X64" + +# +# Globally relevant flags. Options not appropriate for all builds may be +# appropriate in the processor architecture specific macros (xxx_ARCH_FLAGS) or +# in the platform specific macros (xxx_PROJ_FLAGS) +# +C_STD_INCLUDE = /X +!IF "$(EFI_GENERATE_INTERMEDIATE_FILE)" == "YES" +C_STD_FLAGS = /nologo /W4 /WX /Gy /c /GS- /Fa$* /FAsc /Fo$@ /FR$(@R).SBR $(INC) +!ELSE +C_STD_FLAGS = /nologo /W4 /WX /Gy /c /GS- /Fo$@ $(INC) +!ENDIF +ASM_STD_FLAGS = /nologo $(INC) +LINK_STD_FLAGS = /nologo /SUBSYSTEM:CONSOLE /NODEFAULTLIB /MAP /OPT:REF /BASE:0 /IGNORE:4001,4078,4086,4096,4108 $(BUILD_DIR)\X64\CompilerStub.lib +LIB_STD_FLAGS = /nologo + +# +# Build type specific flags. Globally relevant flags belong in the standard +# macros, xxx_STD_FLAGS defined above. Platform specific macros belong in the +# PlatformTools.env file in macros named xxx_PROJ_FLAGS. +# +C_ARCH_FLAGS = /D EFIX64 +ASM_ARCH_FLAGS = /W3 /WX /c /Fo$@ /DEFIX64 +LINK_ARCH_FLAGS = /Machine:AMD64 +LIB_ARCH_FLAGS = + +ASM16_FLAGS = /nologo /c /omf /Fo$@ +ASMLINK16_FLAGS = + +# +# Build tools +# +!IF "$(EFI_COMPILER_X64_NAME)" == "" +!IF "$(USE_VC8_X64)" == "YES" +# +# Use VC8 as X64 compiler +# +CC = "$(VC8_X64_PATH)\cl" +LINK = "$(VC8_X64_PATH)\link" +LIB = "$(VC8_X64_PATH)\lib" +ASM = "$(VC8_X64_PATH)\ml64" +!ELSE +# +# Use DDK as X64 compiler +# +CC = $(WIN_DDK_X64_PATH)\cl +LINK = $(WIN_DDK_X64_PATH)\link +LIB = $(WIN_DDK_X64_PATH)\lib +ASM = $(WIN_DDK_X64_PATH)\ml64 +!ENDIF +!ELSE +CC = $(EDK_TOOLS_BIN)\X64\$(EFI_COMPILER_X64_NAME)\cl +LINK = $(EDK_TOOLS_BIN)\X64\$(EFI_COMPILER_X64_NAME)\link +LIB = $(EDK_TOOLS_BIN)\X64\$(EFI_COMPILER_X64_NAME)\lib +ASM = $(EDK_TOOLS_BIN)\X64\$(EFI_COMPILER_X64_NAME)\ml64 +!ENDIF + +!IF "$(EFI_ASSEMBLER_NAME)" == "" +ASM16 = $(MASMPATH)\bin\ml +ASMLINK16 = $(MASMPATH)\binr\link +ASMLINK = $(MASMPATH)\binr\link +!ELSE +ASM16 = $(EDK_TOOLS_BIN)\Ia32\$(EFI_ASSEMBLER_NAME)\bin\ml +ASMLINK16 = $(EDK_TOOLS_BIN)\Ia32\$(EFI_ASSEMBLER_NAME)\binr\link +ASMLINK = $(EDK_TOOLS_BIN)\Ia32\$(EFI_ASSEMBLER_NAME)\binr\link +!ENDIF + +BSCMAKE = bscmake + +!IF "$(EFI_SYMBOLIC_DEBUG)" == "YES" +ASM_ARCH_FLAGS = $(ASM_ARCH_FLAGS) /Zi /DDEBUG +C_STD_FLAGS = $(C_STD_FLAGS) /Zi /Gm /Fd$(DEST_DIR)\$(BASE_NAME)Obj +LINK_STD_FLAGS = $(LINK_STD_FLAGS) /DEBUG +!ENDIF + +# END OF TOOLCHAIN_X64 +############################################################################### + +############################################################################### +# +# Specify the path and macros for the IPF tools +# +############################################################################### + +!ELSEIF "$(TOOLCHAIN)" == "TOOLCHAIN_IPF" + +# +# Globally relevant flags. Options not appropriate for all builds may be +# appropriate in the processor architecture specific macros (xxx_ARCH_FLAGS) or +# in the platform specific macros (xxx_PROJ_FLAGS) +# +C_STD_INCLUDE = /X +!IF "$(EFI_GENERATE_INTERMEDIATE_FILE)" == "YES" +!IF "$(USE_VC8_IPF)" == "YES" +C_STD_FLAGS = /nologo /W4 /WX /EHsc /Gy /GS- /c /Fa$* /FAsc /Fo$@ /FR$(@R).SBR $(INC) +!ELSE +!IF "$(USE_NEWDDK)" == "YES" +C_STD_FLAGS = /nologo /W4 /WX /EHsc /Gy /GS- /c /Fa$* /FAsc /Fo$@ /FR$(@R).SBR $(INC) +!ELSE +C_STD_FLAGS = /nologo /W4 /WX /GX /Gy /c /Fa$* /FAsc /Fo$@ /FR$(@R).SBR $(INC) +!ENDIF +!ENDIF +!ELSE +!IF "$(USE_VC8_IPF)" == "YES" +C_STD_FLAGS = /nologo /W4 /WX /EHsc /Gy /GS- /c /Fo$@ $(INC) +!ELSE +!IF "$(USE_NEWDDK)" == "YES" +C_STD_FLAGS = /nologo /W4 /WX /EHsc /Gy /GS- /c /Fo$@ $(INC) +!ELSE +C_STD_FLAGS = /nologo /W4 /WX /GX /Gy /c /Fo$@ $(INC) +!ENDIF +!ENDIF +!ENDIF + +ASM_STD_FLAGS = $(INC) +LINK_STD_FLAGS = /nologo /SUBSYSTEM:CONSOLE /NODEFAULTLIB /MAP /OPT:REF /BASE:0 /IGNORE:4001,4078,4086,4096,4108 +LIB_STD_FLAGS = /nologo + +# +# Build type specific flags. Globally relevant flags belong in the standard +# macros, xxx_STD_FLAGS defined above. Platform specific macros belong in the +# PlatformTools.env file in macros named xxx_PROJ_FLAGS. +# +C_ARCH_FLAGS = /D EFI64 +ASM_ARCH_FLAGS = -N us -X explicit -M ilp64 -N so -W4 -o $@ +LINK_ARCH_FLAGS = /MACHINE:IA64 +LIB_ARCH_FLAGS = + +# +# This is used for preprocessing IPF Assembly files +# +C_FLAGS_PRO = /nologo /EP /C $(C_STD_FLAGS) $(C_ARCH_FLAGS) $(C_PROJ_FLAGS) $(C_STD_INCLUDE) + +!IF "$(EFI_DEBUG)" == "YES" +ASM_ARCH_FLAGS = $(ASM_ARCH_FLAGS) -d debug +!ENDIF + +# +# Build tools +# +!IF "$(EFI_COMPILER_NAME)" == "" +!IF "$(USE_VC8_IPF)" == "YES" +CC = "$(VC8_IPF_PATH)\cl" +LINK = "$(VC8_IPF_PATH)\link" +LIB = "$(VC8_IPF_PATH)\lib" +!ELSE +CC = $(EFI_IA64TOOLPATH)\cl +LINK = $(EFI_IA64TOOLPATH)\link +LIB = $(EFI_IA64TOOLPATH)\lib +!ENDIF +!ELSE +CC = $(EDK_TOOLS_BIN)\Ipf\$(EFI_COMPILER_NAME)\cl +LINK = $(EDK_TOOLS_BIN)\Ipf\$(EFI_COMPILER_NAME)\link +LIB = $(EDK_TOOLS_BIN)\Ipf\$(EFI_COMPILER_NAME)\lib +!ENDIF + +!IF "$(EFI_ASSEMBLER_NAME)" == "" +!IF "$(USE_VC8_IPF)" == "YES" +ASM = "$(VC8_IPF_PATH)\ias" +ASMLINK = "$(VC8_IPF_PATH)\link" +!ELSE +ASM = $(EFI_IA64ASMPATH)\ias +ASMLINK = $(EFI_IA64ASMPATH)\link +!ENDIF +!ELSE +ASM = $(EDK_TOOLS_BIN)\Ipf\$(EFI_ASSEMBLER_NAME)\ias +ASMLINK = $(EDK_TOOLS_BIN)\Ipf\$(EFI_ASSEMBLER_NAME)\link +!ENDIF + +BSCMAKE = bscmake + +!IF "$(EFI_SYMBOLIC_DEBUG)" == "YES" +C_STD_FLAGS = $(C_STD_FLAGS) /Zi /Gm /Fd$(DEST_DIR)\$(BASE_NAME)Obj +LINK_STD_FLAGS = $(LINK_STD_FLAGS) /DEBUG +!ENDIF + +# END TOOLCHAIN_IPF +############################################################################### + +############################################################################### +# +# Define toolchain for building the EFI tools on an IA32 system. +# +############################################################################### + +!ELSEIF "$(TOOLCHAIN)" == "TOOLCHAIN_MSVC" + +# +# Globally relevant flags. Options not appropriate for all builds may be +# appropriate in the processor architecture specific macros (xxx_ARCH_FLAGS) or +# in the platform specific macros (xxx_PROJ_FLAGS) +# +!IF "$(EFI_GENERATE_INTERMEDIATE_FILE)" == "YES" +!IF "$(USE_VC8)" == "YES" +C_STD_FLAGS = /nologo /W4 /WX /EHsc /Gy /D _CRT_SECURE_NO_DEPRECATE /D USE_VC8 /c /Fa$* /FAsc /Fo$@ /FR$(@R).SBR $(INC) +!ELSE +C_STD_FLAGS = /nologo /W4 /WX /GX /Gy /c /Fa$* /FAsc /Fo$@ /FR$(@R).SBR $(INC) +!ENDIF +!ELSE +!IF "$(USE_VC8)" == "YES" +C_STD_FLAGS = /nologo /W4 /WX /EHsc /Gy /D _CRT_SECURE_NO_DEPRECATE /D USE_VC8 /c /Fo$@ $(INC) +!ELSE +C_STD_FLAGS = /nologo /W4 /WX /GX /Gy /c /Fo$@ $(INC) +!ENDIF +!ENDIF +ASM_STD_FLAGS = /nologo $(INC) +LINK_STD_FLAGS = /nologo /SUBSYSTEM:CONSOLE /NODEFAULTLIB /MAP /OPT:REF +LIB_STD_FLAGS = /nologo + +MSVS_LINK_LIBPATHS = + +# +# Build type specific flags. Globally relevant flags belong in the standard +# macros, xxx_STD_FLAGS defined above. Platform specific macros belong in the +# PlatformTools.env file in macros named xxx_PROJ_FLAGS. +# + +# +# Add a define to skip inclusion of Microsoft include file rpcasync.h, which +# results in a compile warning at W4. +# +C_ARCH_FLAGS = /Od /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D __RPCASYNC_H__ +ASM_ARCH_FLAGS = +LINK_ARCH_FLAGS = /MACHINE:i386 +LIB_ARCH_FLAGS = + +# +# Always turn on debug for the build tools so that we can debug problems +# quickly. +# NOTE: Ideally all the tools makefiles should be updated to use LINK_FLAGS_EXE +# instead of L_FLAGS for linking. When this happens we can get rid of +# the L_FLAGS definition here. +# + +#!IF "$(EFI_SYMBOLIC_DEBUG)" == "YES" +C_STD_FLAGS = $(C_STD_FLAGS) /Zi /Gm /Fd$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Obj +LINK_ARCH_FLAGS = $(LINK_ARCH_FLAGS) /DEBUG +L_FLAGS = $(L_FLAGS) /DEBUG +#!ENDIF + +# +# Clear any project flags when building tools +# +C_PROJ_FLAGS = +ASM_PROJ_FLAGS = +LINK_PROJ_FLAGS = +LIB_PROJ_FLAGS = +EBC_C_PROJ_FLAGS = +EBC_LINK_PROJ_FLAGS = +EBC_LIB_PROJ_FLAGS = + +# +# Build tools +# +CC = cl +LINK = link +BSCMAKE = bscmake +ASM = ml +ASMLINK = link +# +# Use a different macro name for tools build to avoid conflict with environment +# variable LIB +# +LIB_EXE = lib + +INC = -I $(EDK_SOURCE)\Foundation \ + -I $(EDK_SOURCE)\Foundation\Efi \ + -I $(EDK_SOURCE)\Foundation\Framework \ + -I $(EDK_SOURCE)\Sample\Platform\Nt32 \ + -I $(EDK_SOURCE)\Foundation\Core\Dxe \ + -I $(EDK_SOURCE)\Foundation\Include \ + -I $(EDK_SOURCE)\Foundation\Efi\Include \ + -I $(EDK_SOURCE)\Foundation\Framework\Include \ + -I $(EDK_SOURCE)\Foundation\Include\IndustryStandard \ + -I $(EDK_SOURCE)\Foundation\Include\Ia32 \ + -I $(EDK_SOURCE)\Foundation\Include\Pei \ + -I $(EDK_SOURCE)\Foundation\Library\Pei\Include \ + -I $(EDK_SOURCE)\Sample\Include \ + -I "$(EDK_TOOLS_COMMON)" + +# END TOOLCHAIN_MSVC +############################################################################### + +############################################################################### +# +# Specify the path and macros for the EBC tools +# +############################################################################### + +!ELSEIF "$(TOOLCHAIN)" == "TOOLCHAIN_EBC" + +!IF "$(EFI_GENERATE_INTERMEDIATE_FILE)" == "YES" +EBC_C_STD_FLAGS = /nologo /W3 /WX /c /Fa$* /FAsc /Fo$@ $(INC) /X +!ELSE +EBC_C_STD_FLAGS = /nologo /W3 /WX /c /Fo$@ $(INC) /X +!ENDIF + +# +# All EBC entry point functions must be called EfiMain. Redefine it. +# +!IF "$(IMAGE_ENTRY_POINT)" == "" +IMAGE_ENTRY_POINT = EfiMain +!ENDIF +EBC_C_STD_FLAGS = $(EBC_C_STD_FLAGS) /D $(IMAGE_ENTRY_POINT)=EfiMain +EBC_LINK_STD_FLAGS = /nologo /MACHINE:EBC /BASE:0 /OPT:REF /NODEFAULTLIB +EBC_LIB_STD_FLAGS = /nologo /MACHINE:EBC + +# +# EBC tools path should be defined in LocalTools.env. +# +EBC_CC = $(EBC_TOOLS_PATH)\Bin\Iec +EBC_LINK = $(EBC_TOOLS_PATH)\Bin\Link +EBC_LIB = $(EBC_TOOLS_PATH)\Bin\Link /lib + +!IF "$(EFI_SYMBOLIC_DEBUG)" == "YES" +EBC_C_STD_FLAGS = $(EBC_C_STD_FLAGS) /Zd /Zi +EBC_LINK_STD_FLAGS = $(EBC_LINK_STD_FLAGS) /DEBUG +!ENDIF + +# END TOOLCHAIN_EBC + +############################################################################### +# +# Let the caller define a NULL toolchain if they don't care. This way you can +# pick up at least some defines. +# +############################################################################### + +!ELSEIF "$(TOOLCHAIN)" == "" + +############################################################################### +# +# You get this if the calling makefile did not define TOOLCHAIN_xxx before +# including this file. +# +############################################################################### + +!ELSE +!ERROR Unknown toolchain $(TOOLCHAIN) defined for $(EDK_SOURCE)\Sample\CommonTools.env use +!ENDIF + + +############################################################################### +# +# These are standard settings for all tool chains +# +############################################################################### + +# +# These are standard build options +# +VERSION_FLAGS = /D EFI_SPECIFICATION_VERSION=$(EFI_SPECIFICATION_VERSION) \ + /D PI_SPECIFICATION_VERSION=$(PI_SPECIFICATION_VERSION) \ + /D TIANO_RELEASE_VERSION=$(TIANO_RELEASE_VERSION) +C_STD_FLAGS = $(C_STD_FLAGS) $(VERSION_FLAGS) +EBC_C_STD_FLAGS = $(EBC_C_STD_FLAGS) $(VERSION_FLAGS) +VFRCOMPILE_FLAGS = $(VFRCOMPILE_FLAGS) -ppflag "$(VERSION_FLAGS)" + +!IF "$(EFI_DEBUG)" == "YES" +C_STD_FLAGS = $(C_STD_FLAGS) /D EFI_DEBUG +EBC_C_STD_FLAGS = $(EBC_C_STD_FLAGS) /D EFI_DEBUG +VFRCOMPILE_FLAGS = $(VFRCOMPILE_FLAGS) -ppflag "/D EFI_DEBUG" +!ENDIF + +!IF "$(EFI_DEBUG_CLEAR_MEMORY)" == "YES" +C_STD_FLAGS = $(C_STD_FLAGS) /D EFI_DEBUG_CLEAR_MEMORY +!ENDIF + +!IF "$(EFI_PEI_PERFORMANCE)" == "YES" +C_STD_FLAGS = $(C_STD_FLAGS) /D EFI_PEI_PERFORMANCE /D EFI_DXE_PERFORMANCE +!ENDIF + +!IF "$(EFI_ADDTIONAL_DRIVERS)" == "YES" +C_STD_FLAGS = $(C_STD_FLAGS) /D EFI_ADDTIONAL_DRIVERS +!ENDIF + +!IF "$(EFI_USE_CUSTOM_COMPRESS)" == "YES" +C_STD_FLAGS = $(C_STD_FLAGS) /D EFI_USE_CUSTOM_COMPRESS +!ENDIF + +!IF "$(EFI_UNLOCK_FWH)" == "YES" +C_STD_FLAGS = $(C_STD_FLAGS) /D EFI_UNLOCK_FWH +!ENDIF + +!IF "$(EFI_DXE_PERFORMANCE)" == "YES" +C_STD_FLAGS = $(C_STD_FLAGS) /D EFI_DXE_PERFORMANCE +!ENDIF + +!IF "$(EFI_DEBUG_SERIAL_PRINT)" == "YES" +C_STD_FLAGS = $(C_STD_FLAGS) /D EFI_DEBUG_SERIAL_PRINT +!ENDIF + +!IF "$(EFI_S3_RESUME)" == "YES" +C_STD_FLAGS = $(C_STD_FLAGS) /D EFI_S3_RESUME +!ENDIF + +!IF "$(EFI_PEI_REPORT_STATUS_CODE)" == "YES" +C_STD_FLAGS = $(C_STD_FLAGS) /D EFI_PEI_REPORT_STATUS_CODE_ON +!ENDIF + +############################################################################### + +############################################################################### +# +# Collect final build flags for components. These flags are used to build +# any standard component and some non-standard components. +# +############################################################################### +C_FLAGS = $(C_STD_FLAGS) $(C_ARCH_FLAGS) $(C_PROJ_FLAGS) $(C_STD_INCLUDE) +ASM_FLAGS = $(ASM_STD_FLAGS) $(ASM_ARCH_FLAGS) $(ASM_PROJ_FLAGS) +LINK_FLAGS_DLL = $(LINK_STD_FLAGS) $(LINK_ARCH_FLAGS) $(LINK_PROJ_FLAGS) /DLL +LINK_FLAGS_EXE = $(LINK_STD_FLAGS) $(LINK_ARCH_FLAGS) $(LINK_PROJ_FLAGS) +LIB_FLAGS = $(LIB_STD_FLAGS) $(LIB_ARCH_FLAGS) $(LIB_PROJ_FLAGS) +EBC_C_FLAGS = $(EBC_C_STD_FLAGS) $(EBC_C_ARCH_FLAGS) $(EBC_C_PROJ_FLAGS) +EBC_LINK_FLAGS = $(EBC_LINK_STD_FLAGS) $(EBC_LINK_ARCH_FLAGS) $(EBC_LINK_PROJ_FLAGS) +EBC_LIB_FLAGS = $(EBC_LIB_STD_FLAGS) $(EBC_LIB_ARCH_FLAGS) $(EBC_LIB_PROJ_FLAGS) + +############################################################################### +# +# define X64 denpendant driver files +# +############################################################################### +!IF "$(EFI_BUILD_TARGET_X64)" == "YES" +BUILD_TARGET_PROCESSOR = X64 +DXE_IPL = DxeIplX64 +!ELSE +BUILD_TARGET_PROCESSOR = IA32 +DXE_IPL = DxeIpl +!ENDIF +############################################################################### +# +# define EFI specification denpendant driver files +# +############################################################################### +!IF "$(UEFI_MODE)" == "YES" +UEFI_PREFIX = Uefi +ATAPI_PASS_THRU_INF = Sample\Bus\Pci\AtapiExtPassThru\Dxe\AtapiExtPassThru.inf +!IF "$(CAPSULE_INF)" == "" +CAPSULE_INF = Sample\Universal\Capsule\RuntimeDxe\Capsule.inf +!ENDIF +DEVPATH_INF = Sample\Universal\DevicePath\Dxe\DevicePath.inf +!ELSE +UEFI_PREFIX = +CAPSULE_INF = +DEVPATH_INF = +ATAPI_PASS_THRU_INF = Sample\Bus\Pci\AtapiPassThru\Dxe\AtapiPassThru.inf +!ENDIF +############################################################################### +# +# define PIWG specification denpendant driver files +# +############################################################################### +!IF "$(PI_MODE)" == "YES" +PI_PREFIX = Pi +!ELSE +PI_PREFIX = +!ENDIF +############################################################################### +# +# define customized compress makefile +# +############################################################################### +CUSTOMIZEDCOMPRESS_MAKEFILE = $(EDK_TOOLS_SOURCE)\CustomizedCompress\Makefile +COMPRESS_METHOD = Dummy +############################################################################### +# +# define EFI_BINARY default path +# +############################################################################### +!IFNDEF EFI_BINARY +EFI_BINARY=$(EDK_TOOLS_OUTPUT)\Bin +!ENDIF + +EFI_PLATFORM_BIN=$(EFI_BINARY)\$(PROJECT_NAME)$(BUILD_TARGET_DIRECTORY) diff --git a/EdkCompatibilityPkg/Sample/Include/Efi2WinNT.h b/EdkCompatibilityPkg/Sample/Include/Efi2WinNT.h new file mode 100644 index 0000000000..031a1d96fc --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Include/Efi2WinNT.h @@ -0,0 +1,59 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Efi2WinNT.h + +Abstract: + + Tiano mechanism to create WIN32 EFI code. + + Only used for NT emulation environment. This file replaces the Tiano.h + when you need to access Win32 stuff in EFI. + + Don't access Win32 APIs directly allways go WinNtThunk protocol. + + In most envirnments gWinNt is a pointer to a EFI_WIN_NT_THUNK_PROTOCOL. + +--*/ + +#ifndef _EFI_WIN_NT_H_ +#define _EFI_WIN_NT_H_ + +// +// 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 stil +// 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) + +#include "windows.h" + +// +// Set the warnings back on so the EFI code must be /W4. +// +#pragma warning(default : 4115) +#pragma warning(default : 4201) +#pragma warning(default : 4214) +// +// We replaced Tiano.h so we must include it. +// +#include "Tiano.h" + +#include EFI_PROTOCOL_DEFINITION (WinNtThunk) + +#endif diff --git a/EdkCompatibilityPkg/Sample/Include/EfiCompNameSupport.h b/EdkCompatibilityPkg/Sample/Include/EfiCompNameSupport.h new file mode 100644 index 0000000000..7159588ee1 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Include/EfiCompNameSupport.h @@ -0,0 +1,58 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + EfiCompNameSupport.h + +Abstract: + + Private data structures for the Console Splitter driver + +--*/ + +#ifndef EFI_COMPONENT_NAME_SUPPORT_H +#define EFI_COMPONENT_NAME_SUPPORT_H + +#include "Tiano.h" + +#ifndef EFI_SIZE_REDUCTION_APPLIED + +#define INSTALL_ALL_DRIVER_PROTOCOLS(ImageHandle, \ + SystemTable, \ + DriverBinding, \ + DriverBindingHandle, \ + ComponentName, \ + DriverConfiguration, \ + DriverDiagnostics) \ + EfiLibInstallAllDriverProtocols ((ImageHandle), \ + (SystemTable), \ + (DriverBinding), \ + (DriverBindingHandle), \ + (ComponentName), \ + (DriverConfiguration), \ + (DriverDiagnostics)) +#else + +#define INSTALL_ALL_DRIVER_PROTOCOLS(ImageHandle, \ + SystemTable, \ + DriverBinding, \ + DriverBindingHandle, \ + ComponentName, \ + DriverConfiguration, \ + DriverDiagnostics) \ + EfiLibInstallDriverBinding ((ImageHandle), \ + (SystemTable), \ + (DriverBinding), \ + (DriverBindingHandle)) +#endif + +#endif diff --git a/EdkCompatibilityPkg/Sample/Include/EfiWinNt.h b/EdkCompatibilityPkg/Sample/Include/EfiWinNt.h new file mode 100644 index 0000000000..7722e6a45a --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Include/EfiWinNt.h @@ -0,0 +1,46 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + EfiWinNt.h + +Abstract: + + EFI master include file for WinNt components. + +--*/ + +#ifndef _EFI_WIN_NT_H_ + +#ifdef EFI_NT_EMULATOR + +#define _EFI_WIN_NT_H_ + +#pragma warning(disable : 4115) +#pragma warning(disable : 4201) +#pragma warning(disable : 4214) + +#include "windows.h" +#include "stdio.h" + +// +// Set the warnings back on so the EFI code must be /W4. +// +#pragma warning(default : 4115) +#pragma warning(default : 4201) +#pragma warning(default : 4214) + +#endif + +#include "Tiano.h" + +#endif diff --git a/EdkCompatibilityPkg/Sample/Library/Dxe/WinNt/WinNtLib.c b/EdkCompatibilityPkg/Sample/Library/Dxe/WinNt/WinNtLib.c new file mode 100644 index 0000000000..f883a9c500 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Library/Dxe/WinNt/WinNtLib.c @@ -0,0 +1,75 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + WinNtLib.c + +Abstract: + + Setup gWinNt global + +--*/ + +#include "Efi2WinNT.h" +#include "EfiWinNtLib.h" +#include "EfiDriverLib.h" +#include "EfiHobLib.h" +#include EFI_GUID_DEFINITION (Hob) + +EFI_WIN_NT_THUNK_PROTOCOL *gWinNt; + +EFI_GUID mEfiHobListGuid = EFI_HOB_LIST_GUID; + +EFI_STATUS +EfiInitializeWinNtDriverLib ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +/*++ + +Routine Description: + + Intialize gWinNt and initialize debug console. + +Arguments: + + (Standard EFI Image entry - EFI_IMAGE_ENTRY_POINT) + +Returns: + + None + +--*/ +// TODO: ImageHandle - add argument and description to function comment +// TODO: SystemTable - add argument and description to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_NOT_FOUND - add return value to function comment +// TODO: EFI_SUCCESS - add return value to function comment +{ + EFI_STATUS Status; + VOID *HobList; + VOID *Pointer; + + Status = EfiLibGetSystemConfigurationTable (&mEfiHobListGuid, &HobList); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + ASSERT (NULL != HobList); + Status = GetNextGuidHob (&HobList, &gEfiWinNtThunkProtocolGuid, &Pointer, NULL); + if (EFI_ERROR (Status)) { + return EFI_NOT_FOUND; + } + + gWinNt = (VOID *) (*(UINTN *) (Pointer)); + return EFI_SUCCESS; +} diff --git a/EdkCompatibilityPkg/Sample/Library/Dxe/WinNt/WinNtLib.inf b/EdkCompatibilityPkg/Sample/Library/Dxe/WinNt/WinNtLib.inf new file mode 100644 index 0000000000..bbadcb9ec2 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Library/Dxe/WinNt/WinNtLib.inf @@ -0,0 +1,49 @@ +#/*++ +# +# Copyright (c) 2004, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# WinNtLib.inf +# +# Abstract: +# +# Component description file. +# +#--*/ + +[defines] +BASE_NAME = WinNtLib +COMPONENT_TYPE = LIBRARY + +[sources.common] + WinNtLib.c + +[libraries.common] + HobLib + EdkNt32ProtocolLib + +[includes.common] + $(EDK_SOURCE)\Sample\Platform\Nt32 + $(EDK_SOURCE)\Foundation\Framework + $(EDK_SOURCE)\Foundation + $(EDK_SOURCE)\Foundation\Include + $(EDK_SOURCE)\Foundation\Efi + . + $(EDK_SOURCE)\Foundation\Efi\Include + $(EDK_SOURCE)\Foundation\Framework\Include + $(EDK_SOURCE)\Foundation\Include\IndustryStandard + $(EDK_SOURCE)\Foundation\Library\Dxe\Include + $(EDK_SOURCE)\Foundation\Core\Dxe + $(EDK_SOURCE)\Sample\Include + + +[nmake.common] +C_STD_INCLUDE= diff --git a/EdkCompatibilityPkg/Sample/LocalTools.env b/EdkCompatibilityPkg/Sample/LocalTools.env new file mode 100644 index 0000000000..e5fe750388 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/LocalTools.env @@ -0,0 +1,95 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# LocalTools.env +# +# Abstract: +# +# This file is included by CommonTools.env, which is included by +# makefiles when building. +# +# It can be customized to identify the locations of the tools +# necessary to build the EFI source code for different systems. +# +#--*/ + +# +# Customize to define the base path to MASM for IA32 +# +!IFNDEF MASMPATH +MASMPATH = c:\masm611 +!ENDIF + +# +# Customize to define the base path to iASL +# +!IFNDEF ASLPATH +ASLPATH = c:\Asl +!ENDIF + +# +# Customize to define the base path to the tools for IPF +# +!IFNDEF EFI_IA64TOOLPATH +!IF "$(USE_NEWDDK)" == "YES" +EFI_IA64TOOLPATH = C:\WINDDK\3790.1830\bin\win64\x86 +!ELSE +EFI_IA64TOOLPATH = C:\DDK3790 +!ENDIF +!ENDIF + +!IFNDEF EFI_IA64ASMPATH +!IF "$(USE_NEWDDK)" == "YES" +EFI_IA64ASMPATH = C:\WINDDK\3790.1830\bin\win64\x86 +!ELSE +EFI_IA64ASMPATH = C:\DDK3790 +!ENDIF +!ENDIF + +# +# Customize to define the base path to the EBC tools +# +!IFNDEF EBC_TOOLS_PATH +EBC_TOOLS_PATH = c:\progra~1\intel\ebc +!ENDIF + +# +# Customize to define the base path to WINDDK for X64 +# +!IFNDEF WIN_DDK_PATH +WIN_DDK_X64_PATH = C:\WINDDK\3790.1830\bin\win64\x86\amd64 +!ELSE +WIN_DDK_X64_PATH = $(WIN_DDK_PATH)\bin\win64\x86\amd64 +!ENDIF + +# +# Customize to define the base path to VC8 for X64 +# +!IF "$(USE_VC8_X64)" == "YES" +!IFNDEF VCINSTALLDIR +VC8_X64_PATH = c:\Program Files\Microsoft Visual Studio 8\VC\bin\x86_amd64 +!ELSE +VC8_X64_PATH = $(VCINSTALLDIR)\bin\x86_amd64 +!ENDIF +!ENDIF + +# +# Customize to define the base path to VC8 for IPF +# +!IF "$(USE_VC8_IPF)" == "YES" +!IFNDEF VCINSTALLDIR +VC8_IPF_PATH = c:\Program Files\Microsoft Visual Studio 8\VC\bin\x86_ia64 +!ELSE +VC8_IPF_PATH = $(VCINSTALLDIR)\bin\x86_ia64 +!ENDIF +!ENDIF diff --git a/EdkCompatibilityPkg/Sample/Platform/Common.dsc b/EdkCompatibilityPkg/Sample/Platform/Common.dsc new file mode 100644 index 0000000000..c40c4e7de8 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Platform/Common.dsc @@ -0,0 +1,1522 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Common.dsc +# +# Abstract: +# +# This is the build description file containing the platform +# independent build instructions. Platform specific instructions will +# be prepended to produce the final build DSC file. +# +# +# Notes: +# +# The info in this file is broken down into sections. The start of a section +# is designated by a "[" in the first column. So the [=====] separater ends +# a section. +# +#--*/ + +[=============================================================================] +# +# These get emitted at the top of the generated master makefile. +# +[=============================================================================] +[Makefile.out] +# +# From the [makefile.out] section of the DSC file +# +TOOLCHAIN = +MAKE = nmake -nologo + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +all : libraries fvs + +[=============================================================================] +# +# These get expanded and dumped out to each component makefile after the +# component INF [defines] section gets parsed. +# +[=============================================================================] +[Makefile.Common] +# +# From the [Makefile.Common] section of the description file. +# +PROCESSOR = $(PROCESSOR) +BASE_NAME = $(BASE_NAME) +BUILD_NUMBER = $(BUILD_NUMBER) +VERSION_STRING = $(VERSION_STRING) +TOOLCHAIN = TOOLCHAIN_$(PROCESSOR) +FILE_GUID = $(FILE_GUID) +COMPONENT_TYPE = $(COMPONENT_TYPE) +FV_DIR = $(BUILD_DIR)\FV +PLATFORM = $(PROJECT_NAME) + +# +# Define the global dependency files +# +!IF EXIST ($(DEST_DIR)\$(BASE_NAME)StrDefs.h) +INC_DEPS = $(INC_DEPS) $(DEST_DIR)\$(BASE_NAME)StrDefs.h +!ENDIF +#ENV_DEPS = $(ENV_DEPS) $(EDK_SOURCE)\Sample\CommonTools.env +#ENV_DEPS = $(ENV_DEPS) $(BUILD_DIR)\PlatformTools.env +#ENV_DEPS = $(ENV_DEPS) $(BUILD_DIR)\Config.env +ALL_DEPS = $(INC_DEPS) $(ENV_DEPS) + +!IF "$(LANGUAGE)" != "" +LANGUAGE_FLAGS = -lang $(LANGUAGE) +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +!IF "$(COMPONENT_TYPE)" == "PIC_PEIM" || "$(COMPONENT_TYPE)" == "PE32_PEIM" || "$(COMPONENT_TYPE)" == "RELOCATABLE_PEIM" || "$(COMPONENT_TYPE)" == "COMBINED_PEIM_DRIVER" +DEPEX_TYPE = EFI_SECTION_PEI_DEPEX +!ELSE +DEPEX_TYPE = EFI_SECTION_DXE_DEPEX +!ENDIF + +# +# Command flags for MAKEDEPS tool +# +DEP_FLAGS = -target $** -o $(DEP_FILE) $(INC) -ignorenotfound -q + +[=============================================================================] +# +# These are the commands to compile source files. One of these blocks gets +# emitted to the component's makefile for each source file. The section +# name is encoded as [Compile.$(PROCESSOR).source_filename_extension], where +# the source filename comes from the sources section of the component INF file. +# +# If the dependency list file already exists, then include it for this +# source file. If it doesn't exist, then this is a clean build and the +# dependency file will get created below and the source file will get +# compiled. +# +# Current behavior is that the first clean build will not create dep files. +# But the following second build has to create dep files before build source files. +# CREATEDEPS flag is used to judge whether current build is the second build or not. +# +# +[=============================================================================] +[Compile.Ia32.asm,Compile.x64.asm] + +DEP_FILE = $(DEST_DIR)\$(FILE)Asm.dep + +!IF EXIST($(DEST_DIR)\$(FILE).obj) +DEP_TARGETS = $(DEP_TARGETS) $(DEST_DIR)\$(FILE)Asm.dep +!IF !EXIST($(DEP_FILE)) +CREATEDEPS = YES +!ENDIF +!ENDIF + +!IF EXIST($(DEP_FILE)) +!INCLUDE $(DEP_FILE) +!ENDIF + +# +# Update dep file for next round incremental build +# +$(DEP_FILE) : $(DEST_DIR)\$(FILE).obj + $(MAKEDEPS) -f $(SOURCE_FILE_NAME) $(DEP_FLAGS) -asm + +# +# Compile the file +# +$(DEST_DIR)\$(FILE).obj : $(SOURCE_FILE_NAME) $(INF_FILENAME) $(ALL_DEPS) + $(ASM) $(ASM_FLAGS) $(SOURCE_FILE_NAME) + +[=============================================================================] +[Compile.Ipf.s] + +DEP_FILE = $(DEST_DIR)\$(FILE)S.dep + +!IF EXIST($(DEST_DIR)\$(FILE).pro) +DEP_TARGETS = $(DEP_TARGETS) $(DEST_DIR)\$(FILE)S.dep +!IF !EXIST($(DEP_FILE)) +CREATEDEPS = YES +!ENDIF +!ENDIF + +!IF EXIST($(DEP_FILE)) +!INCLUDE $(DEP_FILE) +!ENDIF + +# +# Update dep file for next round incremental build +# +$(DEP_FILE) : $(DEST_DIR)\$(FILE).pro + $(MAKEDEPS) -f $(SOURCE_FILE_NAME) $(DEP_FLAGS) + +# +# Compile the file +# +$(DEST_DIR)\$(FILE).pro : $(SOURCE_FILE_NAME) $(INF_FILENAME) $(ALL_DEPS) + $(CC) $(C_FLAGS_PRO) $(SOURCE_FILE_NAME) > $@ + +$(DEST_DIR)\$(FILE).obj : $(DEST_DIR)\$(FILE).pro + $(ASM) $(ASM_FLAGS) $(DEST_DIR)\$(FILE).pro + +[=============================================================================] +[Compile.Ia32.c,Compile.Ipf.c,Compile.x64.c] + +DEP_FILE = $(DEST_DIR)\$(FILE).dep + +!IF EXIST($(DEST_DIR)\$(FILE).obj) +DEP_TARGETS = $(DEP_TARGETS) $(DEST_DIR)\$(FILE).dep +!IF !EXIST($(DEP_FILE)) +CREATEDEPS = YES +!ENDIF +!ENDIF + +!IF EXIST($(DEP_FILE)) +!INCLUDE $(DEP_FILE) +!ENDIF + +# +# Update dep file for next round incremental build +# +$(DEP_FILE) : $(DEST_DIR)\$(FILE).obj + $(MAKEDEPS) -f $(SOURCE_FILE_NAME) $(DEP_FLAGS) + +# +# Compile the file +# +$(DEST_DIR)\$(FILE).obj : $(SOURCE_FILE_NAME) $(INF_FILENAME) $(ALL_DEPS) + $(CC) $(C_FLAGS) $(SOURCE_FILE_NAME) + +[=============================================================================] +[Compile.Ebc.c] + +DEP_FILE = $(DEST_DIR)\$(FILE).dep + +!IF EXIST($(DEST_DIR)\$(FILE).obj) +DEP_TARGETS = $(DEP_TARGETS) $(DEST_DIR)\$(FILE).dep +!IF !EXIST($(DEP_FILE)) +CREATEDEPS = YES +!ENDIF +!ENDIF + +!IF EXIST($(DEP_FILE)) +!INCLUDE $(DEP_FILE) +!ENDIF + +# +# Update dep file for next round incremental build +# +$(DEP_FILE) : $(DEST_DIR)\$(FILE).obj + $(MAKEDEPS) -f $(SOURCE_FILE_NAME) $(DEP_FLAGS) + +# +# Compile the file +# +$(DEST_DIR)\$(FILE).obj : $(SOURCE_FILE_NAME) $(INF_FILENAME) $(ALL_DEPS) + $(EBC_CC) $(EBC_C_FLAGS) $(SOURCE_FILE_NAME) + +[=============================================================================] +# +# Commands for compiling a ".apr" Apriori source file. +# +[=============================================================================] +[Compile.Ia32.Apr,Compile.Ipf.Apr,Compile.Ebc.Apr,Compile.x64.Apr] +# +# Create the raw binary file. If you get an error on the build saying it doesn't +# know how to create the .apr file, then you're missing (or mispelled) the +# "APRIORI=" on the component lines in components section in the DSC file. +# +$(DEST_DIR)\$(BASE_NAME).bin : $(SOURCE_FILE_NAME) + $(GENAPRIORI) -v -f $(SOURCE_FILE_NAME) -o $(DEST_DIR)\$(BASE_NAME).bin + +$(DEST_DIR)\$(BASE_NAME).sec : $(DEST_DIR)\$(BASE_NAME).bin + $(GENSECTION) -I $(DEST_DIR)\$(BASE_NAME).bin -O $(DEST_DIR)\$(BASE_NAME).sec -S EFI_SECTION_RAW + +[=============================================================================] +[Build.Ia32.Apriori,Build.Ipf.Apriori,Build.Ebc.Apriori,Build.x64.Apriori] + +all : $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).FFS + +# +# Run GenFfsFile on the package file and .raw file to create the firmware file +# +$(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).FFS : $(DEST_DIR)\$(BASE_NAME).sec $(PACKAGE_FILENAME) + $(GENFFSFILE) -B $(DEST_DIR) -P1 $(PACKAGE_FILENAME) -V + +# +# Remove the generated temp and final files for this modules. +# +clean : +!IF ("$(FILE_GUID)" != "") + @if exist $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* del $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* +!ENDIF + @if exist $(BIN_DIR)\$(BASE_NAME).* del $(BIN_DIR)\$(BASE_NAME).* + @del /q $(DEST_OUTPUT_DIRS) + +[=============================================================================] +[Build.Ia32.Makefile,Build.Ipf.Makefile,Build.Ebc.Makefile,Build.x64.Makefile] + +# +# Copy the makefile directly from the source directory, then make it +# writable so we can copy over it later if we try to. +# +$(DEST_DIR)\makefile.new : $(SOURCE_DIR)\makefile.new + copy $(SOURCE_DIR)\makefile.new $(DEST_DIR)\makefile.new + attrib -r $(DEST_DIR)\makefile.new + +# +# Make the all target, set some required macros. +# +call_makefile : + $(MAKE) -f $(DEST_DIR)\makefile.new all \ + SOURCE_DIR=$(SOURCE_DIR) \ + BUILD_DIR=$(BUILD_DIR) \ + FILE_GUID=$(FILE_GUID) \ + DEST_DIR=$(DEST_DIR) \ + PROCESSOR=$(PROCESSOR) \ + TOOLCHAIN=TOOLCHAIN_$(PROCESSOR) \ + BASE_NAME=$(BASE_NAME) \ + PACKAGE_FILENAME=$(PACKAGE_FILENAME) + +all : $(DEST_DIR)\makefile.new call_makefile + +# +# Remove the generated temp and final files for this modules. +# +clean : + @- $(MAKE) -f $(DEST_DIR)\makefile.new clean > NUL 2>&1 +!IF ("$(FILE_GUID)" != "") + @if exist $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* del $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* +!ENDIF + @if exist $(BIN_DIR)\$(BASE_NAME).* del $(BIN_DIR)\$(BASE_NAME).* + @del /q $(DEST_OUTPUT_DIRS) + +[=============================================================================] +# +# Instructions for building a component that uses a custom makefile. Encoding +# is [build.$(PROCESSOR).$(BUILD_TYPE)]. +# +# To build these components, simply call the makefile from the source +# directory. +# +[=============================================================================] +[Build.Ia32.Custom_Makefile,Build.Ipf.Custom_Makefile,Build.Ebc.Custom_Makefile,Build.x64.Custom_Makefile] + +# +# Just call the makefile from the source directory, passing in some +# useful info. +# +all : + $(MAKE) -f $(SOURCE_DIR)\makefile all \ + SOURCE_DIR=$(SOURCE_DIR) \ + BUILD_DIR=$(BUILD_DIR) \ + DEST_DIR=$(DEST_DIR) \ + FILE_GUID=$(FILE_GUID) \ + PROCESSOR=$(PROCESSOR) \ + TOOLCHAIN=TOOLCHAIN_$(PROCESSOR) \ + BASE_NAME=$(BASE_NAME) \ + PLATFORM=$(PLATFORM) \ + SOURCE_FV=$(SOURCE_FV) \ + PACKAGE_FILENAME=$(PACKAGE_FILENAME) + +# +# Remove the generated temp and final files for this modules. +# +clean : + @- $(MAKE) -f $(SOURCE_DIR)\makefile clean > NUL 2>&1 +!IF ("$(FILE_GUID)" != "") + @if exist $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* del $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* +!ENDIF + @if exist $(BIN_DIR)\$(BASE_NAME).* del $(BIN_DIR)\$(BASE_NAME).* + @del /q $(DEST_OUTPUT_DIRS) + +[=============================================================================] +# +# These commands are used to build libraries +# +[=============================================================================] +[Build.Ia32.LIBRARY,Build.Ipf.LIBRARY,Build.x64.LIBRARY] +# +# LIB all the object files into to our target lib file. Put +# a dependency on the component's INF file in case it changes. +# +LIB_NAME = $(LIB_DIR)\$(BASE_NAME).lib + +$(LIB_NAME) : $(OBJECTS) $(LIBS) $(INF_FILENAME) $(ENV_DEPS) + $(LIB) $(LIB_FLAGS) $(OBJECTS) $(LIBS) /OUT:$@ + +!IF "$(CREATEDEPS)"=="YES" +all : $(DEP_TARGETS) + $(MAKE) -f $(MAKEFILE_NAME) all +!ELSE +all : $(LIB_NAME) $(DEP_TARGETS) +!ENDIF + +# +# Remove the generated temp and final files for this modules. +# +clean : +!IF ("$(FILE_GUID)" != "") + @if exist $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* del $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* +!ENDIF + @if exist $(BIN_DIR)\$(BASE_NAME).* del $(BIN_DIR)\$(BASE_NAME).* + @del /q $(DEST_OUTPUT_DIRS) + +[=============================================================================] +[Build.Ebc.LIBRARY] +# +# LIB all the object files into to our target lib file. Put +# a dependency on the component's INF file in case it changes. +# +LIB_NAME = $(LIB_DIR)\$(BASE_NAME).lib + +$(LIB_NAME) : $(OBJECTS) $(LIBS) $(INF_FILENAME) $(ENV_DEPS) + $(EBC_LIB) $(EBC_LIB_FLAGS) $(OBJECTS) $(LIBS) /OUT:$@ + +!IF "$(CREATEDEPS)"=="YES" +all : $(DEP_TARGETS) + $(MAKE) -f $(MAKEFILE_NAME) all +!ELSE +all : $(LIB_NAME) $(DEP_TARGETS) +!ENDIF + +# +# Remove the generated temp and final files for this modules. +# +clean : +!IF ("$(FILE_GUID)" != "") + @if exist $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* del $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* +!ENDIF + @if exist $(BIN_DIR)\$(BASE_NAME).* del $(BIN_DIR)\$(BASE_NAME).* + @del /q $(DEST_OUTPUT_DIRS) + +[=============================================================================] +# +# This is the Build.$(PROCESSOR).$(COMPONENT_TYPE) section that tells how to +# convert a firmware volume into an FV FFS file. Simply run it through +# GenFfsFile with the appropriate package file. SOURCE_FV must be defined +# in the component INF file Defines section. +# +[=============================================================================] +[Build.Ia32.FvImageFile,Build.x64.FvImageFile,Build.Ipf.FvImageFile] + +all : $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).Fvi + +# +# Run GenFfsFile on the package file and FV file to create the firmware +# volume FFS file. This FFS file maybe contain one pad section for alignment requirement. +# +$(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).Fvi : $(DEST_DIR)\$(SOURCE_FV)Fv.sec $(PACKAGE_FILENAME) $(PAD_SECTION) + $(GENFFSFILE) -B $(DEST_DIR) -P1 $(PACKAGE_FILENAME) -V + +# +# Remove the generated temp and final files for this modules. +# +clean : +!IF ("$(FILE_GUID)" != "") + @if exist $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* del $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* +!ENDIF + @if exist $(BIN_DIR)\$(BASE_NAME).* del $(BIN_DIR)\$(BASE_NAME).* + @del /q $(DEST_OUTPUT_DIRS) + +[=============================================================================] +# +# Since many of the steps are the same for the different component types, we +# share this section for BS_DRIVER, RT_DRIVER, .... and IFDEF the parts that +# differ. The entire section gets dumped to the output makefile. +# +[=============================================================================] +[Build.Ia32.BS_DRIVER|RT_DRIVER|SAL_RT_DRIVER|PE32_PEIM|PEI_CORE|PIC_PEIM|RELOCATABLE_PEIM|DXE_CORE|APPLICATION|COMBINED_PEIM_DRIVER, Build.Ipf.BS_DRIVER|RT_DRIVER|SAL_RT_DRIVER|PEI_CORE|PE32_PEIM|PIC_PEIM|DXE_CORE|APPLICATION|COMBINED_PEIM_DRIVER, Build.x64.BS_DRIVER|RT_DRIVER|SAL_RT_DRIVER|PE32_PEIM|PEI_CORE|PIC_PEIM|RELOCATABLE_PEIM|DXE_CORE|APPLICATION|COMBINED_PEIM_DRIVER] + +!IF "$(LOCALIZE)" == "YES" + +!IF "$(EFI_GENERATE_HII_EXPORT)" == "YES" +STRGATHER_FLAGS = $(STRGATHER_FLAGS) -hpk $(DEST_DIR)\$(BASE_NAME)Strings.hpk + +# +# There will be one HII pack containing all the strings. Add that file +# to the list of HII pack files we'll use to create our final HII export file. +# +HII_PACK_FILES = $(HII_PACK_FILES) $(DEST_DIR)\$(BASE_NAME)Strings.hpk +LOCALIZE_TARGETS = $(LOCALIZE_TARGETS) $(DEST_DIR)\$(BASE_NAME).hii +!ENDIF + +$(DEST_DIR)\$(BASE_NAME).sdb : $(SDB_FILES) $(SOURCE_FILES) + $(STRGATHER) -scan -vdbr $(STRGATHER_FLAGS) -od $(DEST_DIR)\$(BASE_NAME).sdb \ + -skipext .uni -skipext .h $(SOURCE_FILES) + +$(DEST_DIR)\$(BASE_NAME)Strings.c : $(DEST_DIR)\$(BASE_NAME).sdb + $(STRGATHER) -dump $(LANGUAGE_FLAGS) -bn $(BASE_NAME)Strings -db $(DEST_DIR)\$(BASE_NAME).sdb \ + -oc $(DEST_DIR)\$(BASE_NAME)Strings.c + +$(DEST_DIR)\$(BASE_NAME)StrDefs.h : $(DEST_DIR)\$(BASE_NAME).sdb + $(STRGATHER) -dump $(LANGUAGE_FLAGS) -bn $(BASE_NAME)Strings -db $(DEST_DIR)\$(BASE_NAME).sdb \ + -oh $(DEST_DIR)\$(BASE_NAME)StrDefs.h + +$(DEST_DIR)\$(BASE_NAME)Strings.hpk : $(DEST_DIR)\$(BASE_NAME).sdb + $(STRGATHER) -dump $(LANGUAGE_FLAGS) -bn $(BASE_NAME)Strings -db $(DEST_DIR)\$(BASE_NAME).sdb \ + -hpk $(DEST_DIR)\$(BASE_NAME)Strings.hpk + +OBJECTS = $(OBJECTS) $(DEST_DIR)\$(BASE_NAME)Strings.obj + +$(DEST_DIR)\$(BASE_NAME)Strings.obj : $(DEST_DIR)\$(BASE_NAME)Strings.c $(INF_FILENAME) $(ALL_DEPS) + $(CC) $(C_FLAGS) $(DEST_DIR)\$(BASE_NAME)Strings.c + +LOCALIZE_TARGETS = $(LOCALIZE_TARGETS) $(DEST_DIR)\$(BASE_NAME)StrDefs.h + +!ENDIF + +# +# If we have any objects associated with this component, then we're +# going to build a local library from them. +# +!IFNDEF OBJECTS +!ERROR No source files to build were defined in the INF file +!ENDIF + +TARGET_LOCAL_LIB = $(DEST_DIR)\$(BASE_NAME)Local.lib + +# +# LIB all the object files into our (local) target lib file. Put +# a dependency on the component's INF file in case it changes. +# +$(TARGET_LOCAL_LIB) : $(OBJECTS) $(INF_FILENAME) $(ENV_DEPS) + $(LIB) $(LIB_FLAGS) $(OBJECTS) /OUT:$@ + +# +# Defines for standard intermediate files and build targets +# +TARGET_DLL = $(BIN_DIR)\$(BASE_NAME).dll +TARGET_EFI = $(BIN_DIR)\$(BASE_NAME).efi +TARGET_DPX = $(DEST_DIR)\$(BASE_NAME).dpx +TARGET_UI = $(DEST_DIR)\$(BASE_NAME).ui +TARGET_VER = $(DEST_DIR)\$(BASE_NAME).ver +TARGET_MAP = $(BIN_DIR)\$(BASE_NAME).map +TARGET_PDB = $(BIN_DIR)\$(BASE_NAME).pdb +TARGET_SYM = $(BIN_DIR)\$(BASE_NAME).sym + +# +# Target executable section extension depends on the component type. +# Only define "TARGET_DXE_DPX" if it's a combined peim driver. +# +!IF "$(COMPONENT_TYPE)" == "PIC_PEIM" +TARGET_PE32 = $(DEST_DIR)\$(BASE_NAME).pic +!ELSE +TARGET_PE32 = $(DEST_DIR)\$(BASE_NAME).pe32 +!ENDIF + +# +# Target FFS file extension depends on the component type +# Also define "TARGET_DXE_DPX" if it's a combined PEIM driver. +# +SUBSYSTEM = EFI_BOOT_SERVICE_DRIVER + +!IF "$(COMPONENT_TYPE)" == "APPLICATION" +TARGET_FFS_FILE = $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).app +SUBSYSTEM = EFI_APPLICATION +!ELSE IF "$(COMPONENT_TYPE)" == "PEI_CORE" +TARGET_FFS_FILE = $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).pei +!ELSE IF "$(COMPONENT_TYPE)" == "PE32_PEIM" +TARGET_FFS_FILE = $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).pei +!ELSE IF "$(COMPONENT_TYPE)" == "RELOCATABLE_PEIM" +TARGET_FFS_FILE = $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).pei +!ELSE IF "$(COMPONENT_TYPE)" == "PIC_PEIM" +TARGET_FFS_FILE = $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).pei +!ELSE IF "$(COMPONENT_TYPE)" == "COMBINED_PEIM_DRIVER" +TARGET_FFS_FILE = $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).pei +TARGET_DXE_DPX = $(DEST_DIR)\$(BASE_NAME).dpxd +!ELSE +TARGET_FFS_FILE = $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).dxe +!ENDIF + +# +# Different methods to build section based on if PIC_PEIM +# +!IF "$(COMPONENT_TYPE)" == "PIC_PEIM" + +$(TARGET_PE32) : $(TARGET_DLL) + $(PE2BIN) $(TARGET_DLL) $(DEST_DIR)\$(BASE_NAME).TMP +# +# BUGBUG: Build PEIM header, needs to go away with new PEI. +# + $(TEMPGENSECTION) -P $(SOURCE_DIR)\$(BASE_NAME).INF -I $(DEST_DIR)\$(BASE_NAME).TMP -O $(TARGET_PIC_PEI).tmp -M $(TARGET_MAP) -S EFI_SECTION_TYPE_NO_HEADER + $(GENSECTION) -I $(TARGET_PIC_PEI).tmp -O $(TARGET_PE32) -S EFI_SECTION_PIC + del $(DEST_DIR)\$(BASE_NAME).TMP + +!ELSE + +$(TARGET_PE32) : $(TARGET_EFI) + $(GENSECTION) -I $(TARGET_EFI) -O $(TARGET_PE32) -S EFI_SECTION_PE32 + +# +# Run FWImage on the DLL to set it as an EFI image type. +# +$(TARGET_EFI) : $(TARGET_DLL) $(INF_FILENAME) + $(FWIMAGE) -t 0 $(COMPONENT_TYPE) $(TARGET_DLL) $(TARGET_EFI) + +!ENDIF + +# +# Link all objects and libs to create the executable +# +$(TARGET_DLL) : $(TARGET_LOCAL_LIB) $(LIBS) $(INF_FILENAME) $(ENV_DEPS) + $(LINK) $(LINK_FLAGS_DLL) $(LIBS) /ENTRY:$(IMAGE_ENTRY_POINT) \ + $(TARGET_LOCAL_LIB) /OUT:$(TARGET_DLL) /MAP:$(TARGET_MAP) \ + /PDB:$(TARGET_PDB) + $(SETSTAMP) $(TARGET_DLL) $(BUILD_DIR)\GenStamp.txt +!IF "$(EFI_GENERATE_SYM_FILE)" == "YES" + if exist $(TARGET_PDB) $(PE2SYM) $(TARGET_PDB) $(TARGET_SYM) +!ENDIF + +!IF "$(EFI_ZERO_DEBUG_DATA)" == "YES" + $(ZERODEBUGDATA) $(TARGET_DLL) +!ENDIF + +# +# Create the user interface section +# +$(TARGET_UI) : $(INF_FILENAME) + $(GENSECTION) -O $(TARGET_UI) -S EFI_SECTION_USER_INTERFACE -A "$(BASE_NAME)" + +# +# Create the version section +# +!IF "$(BUILD_NUMBER)" != "" +!IF "$(VERSION_STRING)" != "" +$(TARGET_VER) : $(INF_FILENAME) + $(GENSECTION) -O $(TARGET_VER) -S EFI_SECTION_VERSION -V $(BUILD_NUMBER) -A "$(VERSION_STRING)" +!ELSE +$(TARGET_VER) : $(INF_FILENAME) + $(GENSECTION) -O $(TARGET_VER) -S EFI_SECTION_VERSION -V $(BUILD_NUMBER) +!ENDIF +!ELSE +$(TARGET_VER) : + echo.>$(TARGET_VER) + type $(TARGET_VER)>$(TARGET_VER) +!ENDIF + +# +# Makefile entries to create the dependency expression section. +# Use the DPX file from the source directory unless an override file +# was specified. +# If no DPX source file was specified, then create an empty file to +# be used. +# +!IF "$(DPX_SOURCE)" != "" +DPX_SOURCE_FILE = $(SOURCE_DIR)\$(DPX_SOURCE) +!ENDIF + +!IF "$(DPX_SOURCE_OVERRIDE)" != "" +DPX_SOURCE_FILE = $(DPX_SOURCE_OVERRIDE) +!ENDIF + +!IF "$(DPX_SOURCE_FILE)" != "" +!IF EXIST ($(DPX_SOURCE_FILE)) +# +# Add dependency check for dxs file, because dxs file depends on PPI or +# PROTOCOL guid defintions. +# +DEP_FILE = $(DEST_DIR)\$(BASE_NAME)dxs.dep + +!IF EXIST($(TARGET_DPX)) +DEP_TARGETS = $(DEP_TARGETS) $(DEST_DIR)\$(BASE_NAME)dxs.dep +!IF !EXIST($(DEP_FILE)) +CREATEDEPS = YES +!ENDIF +!ENDIF + +!IF EXIST($(DEP_FILE)) +!INCLUDE $(DEP_FILE) +!ENDIF +# +# Update dep file for next round incremental build +# +$(DEP_FILE) : $(TARGET_DPX) + $(MAKEDEPS) -f $(DPX_SOURCE_FILE) $(DEP_FLAGS) + +$(TARGET_DPX) : $(DPX_SOURCE_FILE) $(INF_FILENAME) + $(CC) /nologo $(INC) $(VERSION_FLAGS) /EP $(DPX_SOURCE_FILE) > $*.tmp1 + $(GENDEPEX) -I $*.tmp1 -O $*.tmp2 + $(GENSECTION) -I $*.tmp2 -O $@ -S $(DEPEX_TYPE) + del $*.tmp1 > NUL + del $*.tmp2 > NUL +!ELSE +!ERROR Dependency expression source file "$(DPX_SOURCE_FILE)" does not exist. +!ENDIF +!ELSE +$(TARGET_DPX) : + echo. > $(TARGET_DPX) + type $(TARGET_DPX) > $(TARGET_DPX) +!ENDIF + +# +# Makefile entries for DXE DPX for combined PEIM drivers. +# If a DXE_DPX_SOURCE file was specified in the INF file, use it. Otherwise +# create an empty file and use it as a DPX file. +# +!IF "$(COMPONENT_TYPE)" == "COMBINED_PEIM_DRIVER" +!IF "$(DXE_DPX_SOURCE)" != "" +!IF EXIST ($(SOURCE_DIR)\$(DXE_DPX_SOURCE)) +$(TARGET_DXE_DPX) : $(SOURCE_DIR)\$(DXE_DPX_SOURCE) $(INF_FILENAME) + $(CC) /nologo $(INC) $(VERSION_FLAGS) /EP $(SOURCE_DIR)\$(DXE_DPX_SOURCE) > $*.tmp1 + $(GENDEPEX) -I $*.tmp1 -O $*.tmp2 + $(GENSECTION) -I $*.tmp2 -O $@ -S EFI_SECTION_DXE_DEPEX + del $*.tmp1 > NUL + del $*.tmp2 > NUL +!ELSE +!ERROR Dependency expression source file "$(SOURCE_DIR)\$(DXE_DPX_SOURCE)" does not exist. +!ENDIF +!ELSE +$(TARGET_DXE_DPX) : + echo. > $(TARGET_DXE_DPX) + type $(TARGET_DXE_DPX) > $(TARGET_DXE_DPX) +!ENDIF +!ENDIF + +# +# Describe how to build the HII export file from all the input HII pack files. +# Use the FFS file GUID for the package GUID in the export file. Only used +# when multiple VFR share strings. +# +$(DEST_DIR)\$(BASE_NAME).hii : $(HII_PACK_FILES) + $(HIIPACK) create -g $(FILE_GUID) -p $(HII_PACK_FILES) -o $(DEST_DIR)\$(BASE_NAME).hii + +# +# If the build calls for creating an FFS file with the IFR included as +# a separate binary (not compiled into the driver), then build the binary +# section now. Note that the PACKAGE must be set correctly to actually get +# this IFR section pulled into the FFS file. +# +!IF ("$(HII_IFR_PACK_FILES)" != "") + +$(DEST_DIR)\$(BASE_NAME)IfrBin.sec : $(HII_IFR_PACK_FILES) + $(HIIPACK) create -novarpacks -p $(HII_IFR_PACK_FILES) -o $(DEST_DIR)\$(BASE_NAME)IfrBin.hii + $(GENSECTION) -I $(DEST_DIR)\$(BASE_NAME)IfrBin.hii -O $(DEST_DIR)\$(BASE_NAME)IfrBin.sec -S EFI_SECTION_RAW + +BIN_TARGETS = $(BIN_TARGETS) $(DEST_DIR)\$(BASE_NAME)IfrBin.sec + +!ENDIF + +# +# Build a FFS file from the sections and package +# +$(TARGET_FFS_FILE) : $(TARGET_PE32) $(TARGET_DPX) $(TARGET_UI) $(TARGET_VER) $(TARGET_DXE_DPX) $(PACKAGE_FILENAME) +# +# Some of our components require padding to align code +# +!IF "$(PROCESSOR)" == "IPF" +!IF "$(COMPONENT_TYPE)" == "PIC_PEIM" || "$(COMPONENT_TYPE)" == "PE32_PEIM" || "$(COMPONENT_TYPE)" == "RELOCATABLE_PEIM" || "$(COMPONENT_TYPE)" == "SECURITY_CORE" || "$(COMPONENT_TYPE)" == "PEI_CORE" || "$(COMPONENT_TYPE)" == "COMBINED_PEIM_DRIVER" + copy $(BIN_DIR)\Blank.pad $(DEST_DIR) +!ENDIF +!ENDIF + $(GENFFSFILE) -B $(DEST_DIR) -P1 $(PACKAGE_FILENAME) -V + +!IF "$(CREATEDEPS)"=="YES" +all : $(DEP_TARGETS) + $(MAKE) -f $(MAKEFILE_NAME) all +!ELSE +all : $(LOCALIZE_TARGETS) $(BIN_TARGETS) $(TARGET_FFS_FILE) $(DEP_TARGETS) +!ENDIF + +# +# Remove the generated temp and final files for this modules. +# +clean : +!IF ("$(FILE_GUID)" != "") + @if exist $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* del $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* +!ENDIF + @if exist $(BIN_DIR)\$(BASE_NAME).* del $(BIN_DIR)\$(BASE_NAME).* + @del /q $(DEST_OUTPUT_DIRS) + +[=============================================================================] +[Build.Ia32.TE_PEIM,Build.Ipf.TE_PEIM,Build.x64.TE_PEIM] +# +# Define the library file we'll build if we have any objects defined. +# +!IFDEF OBJECTS +TARGET_LOCAL_LIB = $(DEST_DIR)\$(BASE_NAME)Local.lib +# +# LIB all the object files into our (local) target lib file. Put +# a dependency on the component's INF file in case it changes. +# +$(TARGET_LOCAL_LIB) : $(OBJECTS) $(INF_FILENAME) $(ENV_DEPS) + $(LIB) $(LIB_FLAGS) $(OBJECTS) /OUT:$@ + +!ELSE +!ERROR No source files to build were defined in the INF file +!ENDIF + +# +# Defines for standard intermediate files and build targets +# +TARGET_DLL = $(BIN_DIR)\$(BASE_NAME).dll +TARGET_EFI = $(BIN_DIR)\$(BASE_NAME).efi +TARGET_DPX = $(DEST_DIR)\$(BASE_NAME).dpx +TARGET_UI = $(DEST_DIR)\$(BASE_NAME).ui +TARGET_VER = $(DEST_DIR)\$(BASE_NAME).ver +TARGET_MAP = $(BIN_DIR)\$(BASE_NAME).map +TARGET_PDB = $(BIN_DIR)\$(BASE_NAME).pdb +TARGET_SYM = $(BIN_DIR)\$(BASE_NAME).sym +TARGET_TE = $(BIN_DIR)\$(BASE_NAME).te +TARGET_PE32 = $(DEST_DIR)\$(BASE_NAME).pe32 +TARGET_TES = $(DEST_DIR)\$(BASE_NAME).tes +TARGET_FFS_FILE = $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).pei + +# +# Create our TE section from our TE file +# +$(TARGET_TES) : $(TARGET_TE) + $(GENSECTION) -I $(TARGET_TE) -O $(TARGET_TES) -S EFI_SECTION_TE + +# +# Run FWImage on the DLL to set it as an EFI image type. +# +$(TARGET_EFI) : $(TARGET_DLL) $(INF_FILENAME) + $(FWIMAGE) $(COMPONENT_TYPE) $(TARGET_DLL) $(TARGET_EFI) + +# +# Run GenTEImage on the built .efi file to create our TE file. +# +$(TARGET_TE) : $(TARGET_EFI) + $(GENTEIMAGE) -o $(TARGET_TE) $(TARGET_EFI) + +# +# Link all objects and libs to create the executable +# +$(TARGET_DLL) : $(TARGET_LOCAL_LIB) $(LIBS) $(INF_FILENAME) $(ENV_DEPS) + $(LINK) $(LINK_FLAGS_DLL) $(LIBS) /ENTRY:$(IMAGE_ENTRY_POINT) \ + $(TARGET_LOCAL_LIB) /OUT:$(TARGET_DLL) /MAP:$(TARGET_MAP) \ + /PDB:$(TARGET_PDB) + $(SETSTAMP) $(TARGET_DLL) $(BUILD_DIR)\GenStamp.txt +!IF "$(EFI_GENERATE_SYM_FILE)" == "YES" + if exist $(TARGET_PDB) $(PE2SYM) $(TARGET_PDB) $(TARGET_SYM) +!ENDIF + +!IF "$(EFI_ZERO_DEBUG_DATA)" == "YES" + $(ZERODEBUGDATA) $(TARGET_DLL) +!ENDIF + +# +# Create the user interface section +# +$(TARGET_UI) : $(INF_FILENAME) + $(GENSECTION) -O $(TARGET_UI) -S EFI_SECTION_USER_INTERFACE -A "$(BASE_NAME)" + +# +# Create the version section +# +!IF "$(BUILD_NUMBER)" != "" +!IF "$(VERSION_STRING)" != "" +$(TARGET_VER) : $(INF_FILENAME) + $(GENSECTION) -O $(TARGET_VER) -S EFI_SECTION_VERSION -V $(BUILD_NUMBER) -A "$(VERSION_STRING)" +!ELSE +$(TARGET_VER) : $(INF_FILENAME) + $(GENSECTION) -O $(TARGET_VER) -S EFI_SECTION_VERSION -V $(BUILD_NUMBER) +!ENDIF +!ELSE +$(TARGET_VER) : + echo.>$(TARGET_VER) + type $(TARGET_VER)>$(TARGET_VER) +!ENDIF + +# +# Makefile entries to create the dependency expression section. +# Use the DPX file from the source directory unless an override file +# was specified. +# If no DPX source file was specified, then create an empty file to +# be used. +# +!IF "$(DPX_SOURCE)" != "" +DPX_SOURCE_FILE = $(SOURCE_DIR)\$(DPX_SOURCE) +!ENDIF + +!IF "$(DPX_SOURCE_OVERRIDE)" != "" +DPX_SOURCE_FILE = $(DPX_SOURCE_OVERRIDE) +!ENDIF + +!IF "$(DPX_SOURCE_FILE)" != "" +!IF EXIST ($(DPX_SOURCE_FILE)) +# +# Add dependency check for dxs file, because dxs file depends on PPI or +# PROTOCOL guid defintions. +# +DEP_FILE = $(DEST_DIR)\$(BASE_NAME)dxs.dep + +!IF EXIST($(TARGET_DPX)) +DEP_TARGETS = $(DEP_TARGETS) $(DEST_DIR)\$(BASE_NAME)dxs.dep +!IF !EXIST($(DEP_FILE)) +CREATEDEPS = YES +!ENDIF +!ENDIF + +!IF EXIST($(DEP_FILE)) +!INCLUDE $(DEP_FILE) +!ENDIF +# +# Update dep file for next round incremental build +# +$(DEP_FILE) : $(TARGET_DPX) + $(MAKEDEPS) -f $(DPX_SOURCE_FILE) $(DEP_FLAGS) + +$(TARGET_DPX) : $(DPX_SOURCE_FILE) $(INF_FILENAME) + $(CC) /nologo $(INC) $(VERSION_FLAGS) /EP $(DPX_SOURCE_FILE) > $*.tmp1 + $(GENDEPEX) -I $*.tmp1 -O $*.tmp2 + $(GENSECTION) -I $*.tmp2 -O $@ -S $(DEPEX_TYPE) + del $*.tmp1 > NUL + del $*.tmp2 > NUL +!ELSE +!ERROR Dependency expression source file "$(DPX_SOURCE_FILE)" does not exist. +!ENDIF +!ELSE +$(TARGET_DPX) : + echo. > $(TARGET_DPX) + type $(TARGET_DPX) > $(TARGET_DPX) +!ENDIF + +# +# Build an FFS file from the sections and package +# +$(TARGET_FFS_FILE) : $(TARGET_TES) $(TARGET_DPX) $(TARGET_UI) $(TARGET_VER) $(PACKAGE_FILENAME) + $(GENFFSFILE) -B $(DEST_DIR) -P1 $(PACKAGE_FILENAME) -V + +!IF "$(CREATEDEPS)"=="YES" +all : $(DEP_TARGETS) + $(MAKE) -f $(MAKEFILE_NAME) all +!ELSE +all : $(TARGET_FFS_FILE) $(DEP_TARGETS) +!ENDIF + +# +# Remove the generated temp and final files for this modules. +# +clean : +!IF ("$(FILE_GUID)" != "") + @if exist $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* del $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* +!ENDIF + @if exist $(BIN_DIR)\$(BASE_NAME).* del $(BIN_DIR)\$(BASE_NAME).* + @del /q $(DEST_OUTPUT_DIRS) + +[=============================================================================] +# +# These are the commands to build EBC EFI targets +# +[=============================================================================] +[Build.Ebc.BS_DRIVER|RT_DRIVER|APPLICATION] + +# +# Add the EBC library to our list of libs +# +LIBS = $(LIBS) $(EBC_TOOLS_PATH)\lib\EbcLib.lib + +!IF "$(LOCALIZE)" == "YES" + +!IF "$(EFI_GENERATE_HII_EXPORT)" == "YES" +STRGATHER_FLAGS = $(STRGATHER_FLAGS) -hpk $(DEST_DIR)\$(BASE_NAME)Strings.hpk + +# +# There will be one HII pack containing all the strings. Add that file +# to the list of HII pack files we'll use to create our final HII export file. +# +HII_PACK_FILES = $(HII_PACK_FILES) $(DEST_DIR)\$(BASE_NAME)Strings.hpk + +LOCALIZE_TARGETS = $(LOCALIZE_TARGETS) $(DEST_DIR)\$(BASE_NAME).hii +!ENDIF + +$(DEST_DIR)\$(BASE_NAME).sdb : $(SDB_FILES) $(SOURCE_FILES) + $(STRGATHER) -scan -vdbr $(STRGATHER_FLAGS) -od $(DEST_DIR)\$(BASE_NAME).sdb \ + -skipext .uni -skipext .h $(SOURCE_FILES) + +$(DEST_DIR)\$(BASE_NAME)Strings.c : $(DEST_DIR)\$(BASE_NAME).sdb + $(STRGATHER) -dump $(LANGUAGE_FLAGS) -bn $(BASE_NAME)Strings -db $(DEST_DIR)\$(BASE_NAME).sdb \ + -oc $(DEST_DIR)\$(BASE_NAME)Strings.c + +$(DEST_DIR)\$(BASE_NAME)StrDefs.h : $(DEST_DIR)\$(BASE_NAME).sdb + $(STRGATHER) -dump $(LANGUAGE_FLAGS) -bn $(BASE_NAME)Strings -db $(DEST_DIR)\$(BASE_NAME).sdb \ + -oh $(DEST_DIR)\$(BASE_NAME)StrDefs.h + +$(DEST_DIR)\$(BASE_NAME)Strings.hpk : $(DEST_DIR)\$(BASE_NAME).sdb + $(STRGATHER) -dump $(LANGUAGE_FLAGS) -bn $(BASE_NAME)Strings -db $(DEST_DIR)\$(BASE_NAME).sdb \ + -hpk $(DEST_DIR)\$(BASE_NAME)Strings.hpk + +OBJECTS = $(OBJECTS) $(DEST_DIR)\$(BASE_NAME)Strings.obj + +$(DEST_DIR)\$(BASE_NAME)Strings.obj : $(DEST_DIR)\$(BASE_NAME)Strings.c $(INF_FILENAME) $(ALL_DEPS) + $(EBC_CC) $(EBC_C_FLAGS) $(DEST_DIR)\$(BASE_NAME)Strings.c + +LOCALIZE_TARGETS = $(LOCALIZE_TARGETS) $(DEST_DIR)\$(BASE_NAME)StrDefs.h + +!ENDIF + +# +# If building an application, then the target is a .app, not .dxe +# +!IF "$(COMPONENT_TYPE)" == "APPLICATION" +TARGET_FFS_FILE = $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).app +SUBSYSTEM = EFI_APPLICATION +!ELSE +TARGET_FFS_FILE = $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).dxe +SUBSYSTEM = EFI_BOOT_SERVICE_DRIVER +!ENDIF + +# +# Defines for standard intermediate files and build targets +# +TARGET_EFI = $(BIN_DIR)\$(BASE_NAME).efi +TARGET_DPX = $(DEST_DIR)\$(BASE_NAME).dpx +TARGET_UI = $(DEST_DIR)\$(BASE_NAME).ui +TARGET_VER = $(DEST_DIR)\$(BASE_NAME).ver +TARGET_MAP = $(BIN_DIR)\$(BASE_NAME).map +TARGET_PDB = $(BIN_DIR)\$(BASE_NAME).pdb +TARGET_PE32 = $(DEST_DIR)\$(BASE_NAME).pe32 +TARGET_DLL = $(BIN_DIR)\$(BASE_NAME).dll + +# +# First link all the objects and libs together to make a .dll file +# +$(TARGET_DLL) : $(OBJECTS) $(LIBS) $(INF_FILENAME) $(ENV_DEPS) + $(EBC_LINK) $(EBC_LINK_FLAGS) /SUBSYSTEM:$(SUBSYSTEM) /ENTRY:EfiStart \ + $(OBJECTS) $(LIBS) /OUT:$(TARGET_DLL) /MAP:$(TARGET_MAP) + $(SETSTAMP) $(TARGET_DLL) $(BUILD_DIR)\GenStamp.txt +!IF "$(EFI_ZERO_DEBUG_DATA)" == "YES" + $(ZERODEBUGDATA) $(TARGET_DLL) +!ENDIF + +# +# Now take the .dll file and make a .efi file +# +$(TARGET_EFI) : $(TARGET_DLL) $(INF_FILENAME) + $(FWIMAGE) -t 0 $(COMPONENT_TYPE) $(TARGET_DLL) $(TARGET_EFI) + +# +# Now take the .efi file and make a .pe32 section +# +$(TARGET_PE32) : $(TARGET_EFI) + $(GENSECTION) -I $(TARGET_EFI) -O $(TARGET_PE32) -S EFI_SECTION_PE32 + +# +# Create the user interface section +# +$(TARGET_UI) : $(INF_FILENAME) + $(GENSECTION) -O $(TARGET_UI) -S EFI_SECTION_USER_INTERFACE -A "$(BASE_NAME)" + +# +# Create the version section +# +!IF "$(BUILD_NUMBER)" != "" +!IF "$(VERSION_STRING)" != "" +$(TARGET_VER) : $(INF_FILENAME) + $(GENSECTION) -O $(TARGET_VER) -S EFI_SECTION_VERSION -V $(BUILD_NUMBER) -A "$(VERSION_STRING)" +!ELSE +$(TARGET_VER) : $(INF_FILENAME) + $(GENSECTION) -O $(TARGET_VER) -S EFI_SECTION_VERSION -V $(BUILD_NUMBER) +!ENDIF +!ELSE +$(TARGET_VER) : + echo. > $(TARGET_VER) + type $(TARGET_VER) > $(TARGET_VER) +!ENDIF + +# +# Makefile entries to create the dependency expression section. +# Use the DPX file from the source directory unless an override file +# was specified. +# If no DPX source file was specified, then create an empty file to +# be used. +# +!IF "$(DPX_SOURCE)" != "" +DPX_SOURCE_FILE = $(SOURCE_DIR)\$(DPX_SOURCE) +!ENDIF + +!IF "$(DPX_SOURCE_OVERRIDE)" != "" +DPX_SOURCE_FILE = $(DPX_SOURCE_OVERRIDE) +!ENDIF + +!IF "$(DPX_SOURCE_FILE)" != "" +!IF EXIST ($(DPX_SOURCE_FILE)) +# +# Add dependency check for dxs file, because dxs file depends on PPI or +# PROTOCOL guid defintions. +# +DEP_FILE = $(DEST_DIR)\$(BASE_NAME)dxs.dep + +!IF EXIST($(TARGET_DPX)) +DEP_TARGETS = $(DEP_TARGETS) $(DEST_DIR)\$(BASE_NAME)dxs.dep +!IF !EXIST($(DEP_FILE)) +CREATEDEPS = YES +!ENDIF +!ENDIF + +!IF EXIST($(DEP_FILE)) +!INCLUDE $(DEP_FILE) +!ENDIF +# +# Update dep file for next round incremental build +# +$(DEP_FILE) : $(TARGET_DPX) + $(MAKEDEPS) -f $(DPX_SOURCE_FILE) $(DEP_FLAGS) + +$(TARGET_DPX) : $(DPX_SOURCE_FILE) $(INF_FILENAME) + $(CC) /nologo $(INC) $(VERSION_FLAGS) /EP $(DPX_SOURCE_FILE) > $*.tmp1 + $(GENDEPEX) -I $*.tmp1 -O $*.tmp2 + $(GENSECTION) -I $*.tmp2 -O $@ -S $(DEPEX_TYPE) + del $*.tmp1 > NUL + del $*.tmp2 > NUL +!ELSE +!ERROR Dependency expression source file "$(DPX_SOURCE_FILE)" does not exist. +!ENDIF +!ELSE +$(TARGET_DPX) : + echo. > $(TARGET_DPX) + type $(TARGET_DPX) > $(TARGET_DPX) +!ENDIF + +# +# Describe how to build the HII export file from all the input HII pack files. +# Use the FFS file GUID for the package GUID in the export file. Only used +# when multiple VFR share strings. +# +$(DEST_DIR)\$(BASE_NAME).hii : $(HII_PACK_FILES) + $(HIIPACK) create -g $(FILE_GUID) -p $(HII_PACK_FILES) -o $(DEST_DIR)\$(BASE_NAME).hii + +# +# If the build calls for creating an FFS file with the IFR included as +# a separate binary (not compiled into the driver), then build the binary +# section now. Note that the PACKAGE must be set correctly to actually get +# this IFR section pulled into the FFS file. +# +!IF ("$(HII_IFR_PACK_FILES)" != "") + +$(DEST_DIR)\$(BASE_NAME)IfrBin.sec : $(HII_IFR_PACK_FILES) + $(HIIPACK) create -novarpacks -p $(HII_IFR_PACK_FILES) -o $(DEST_DIR)\$(BASE_NAME)IfrBin.hii + $(GENSECTION) -I $(DEST_DIR)\$(BASE_NAME)IfrBin.hii -O $(DEST_DIR)\$(BASE_NAME)IfrBin.sec -S EFI_SECTION_RAW + +BIN_TARGETS = $(BIN_TARGETS) $(DEST_DIR)\$(BASE_NAME)IfrBin.sec + +!ENDIF + +# +# Build an FFS file from the sections and package +# +$(TARGET_FFS_FILE) : $(TARGET_PE32) $(TARGET_DPX) $(TARGET_UI) $(TARGET_VER) $(PACKAGE_FILENAME) + $(GENFFSFILE) -B $(DEST_DIR) -P1 $(PACKAGE_FILENAME) -V + +!IF "$(CREATEDEPS)"=="YES" +all : $(DEP_TARGETS) + $(MAKE) -f $(MAKEFILE_NAME) all +!ELSE +all : $(LOCALIZE_TARGETS) $(BIN_TARGETS) $(TARGET_FFS_FILE) $(DEP_TARGETS) +!ENDIF + +# +# Remove the generated temp and final files for this modules. +# +clean : +!IF ("$(FILE_GUID)" != "") + @if exist $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* del $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* +!ENDIF + @if exist $(BIN_DIR)\$(BASE_NAME).* del $(BIN_DIR)\$(BASE_NAME).* + @del /q $(DEST_OUTPUT_DIRS) + +[=============================================================================] +# +# These are the commands to build vendor-provided *.EFI files into an FV. +# To use them, create an INF file with BUILD_TYPE=BS_DRIVER_EFI. +# This section, as it now exists, only supports boot service drivers. +# +[=============================================================================] +[Build.Ia32.BS_DRIVER_EFI|RT_DRIVER_EFI|APPLICATION_EFI,Build.Ipf.BS_DRIVER_EFI|RT_DRIVER_EFI|APPLICATION_EFI,Build.Ebc.BS_DRIVER_EFI|RT_DRIVER_EFI|APPLICATION_EFI,Build.x64.BS_DRIVER_EFI|RT_DRIVER_EFI|APPLICATION_EFI] +# +# Defines for standard intermediate files and build targets. For the source +# .efi file, take the one in the source directory if it exists. If there's not +# one there, look for one in the processor-specfic subdirectory. +# +!IF EXIST ("$(SOURCE_DIR)\$(BASE_NAME).efi") +TARGET_EFI = $(SOURCE_DIR)\$(BASE_NAME).efi +!ELSEIF EXIST ("$(SOURCE_DIR)\$(PROCESSOR)\$(BASE_NAME).efi") +TARGET_EFI = $(SOURCE_DIR)\$(PROCESSOR)\$(BASE_NAME).efi +!ELSE +!ERROR Pre-existing $(BASE_NAME).efi file not found in $(SOURCE_DIR) nor $(SOURCE_DIR)\$(PROCESSOR) +!ENDIF + +TARGET_DPX = $(DEST_DIR)\$(BASE_NAME).dpx +TARGET_UI = $(DEST_DIR)\$(BASE_NAME).ui +TARGET_VER = $(DEST_DIR)\$(BASE_NAME).ver +TARGET_MAP = $(BIN_DIR)\$(BASE_NAME).map +TARGET_PDB = $(BIN_DIR)\$(BASE_NAME).pdb +TARGET_PE32 = $(DEST_DIR)\$(BASE_NAME).pe32 +TARGET_DLL = $(BIN_DIR)\$(BASE_NAME).dll + +# +# If building an application, then the target is a .app, not .dxe +# +!IF "$(COMPONENT_TYPE)" == "APPLICATION" +TARGET_FFS_FILE = $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).app +!ELSE +TARGET_FFS_FILE = $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).dxe +!ENDIF + +# +# Take the .efi file and make a .pe32 file +# +$(TARGET_PE32) : $(TARGET_EFI) + $(GENSECTION) -I $(TARGET_EFI) -O $(TARGET_PE32) -S EFI_SECTION_PE32 + +# +# Create the user interface section +# +$(TARGET_UI) : $(INF_FILENAME) + $(GENSECTION) -O $(TARGET_UI) -S EFI_SECTION_USER_INTERFACE -A "$(BASE_NAME)" + +# +# Create the version section +# +!IF "$(BUILD_NUMBER)" != "" +!IF "$(VERSION_STRING)" != "" +$(TARGET_VER) : $(INF_FILENAME) + $(GENSECTION) -O $(TARGET_VER) -S EFI_SECTION_VERSION -V $(BUILD_NUMBER) -A "$(VERSION_STRING)" +!ELSE +$(TARGET_VER) : $(INF_FILENAME) + $(GENSECTION) -O $(TARGET_VER) -S EFI_SECTION_VERSION -V $(BUILD_NUMBER) +!ENDIF +!ELSE +$(TARGET_VER) : + echo. > $(TARGET_VER) + type $(TARGET_VER) > $(TARGET_VER) +!ENDIF + +# +# Makefile entries to create the dependency expression section. +# Use the DPX file from the source directory unless an override file +# was specified. +# If no DPX source file was specified, then create an empty file to +# be used. +# +!IF "$(DPX_SOURCE)" != "" +DPX_SOURCE_FILE = $(SOURCE_DIR)\$(DPX_SOURCE) +!ENDIF + +!IF "$(DPX_SOURCE_OVERRIDE)" != "" +DPX_SOURCE_FILE = $(DPX_SOURCE_OVERRIDE) +!ENDIF + +!IF "$(DPX_SOURCE_FILE)" != "" +!IF EXIST ($(DPX_SOURCE_FILE)) +# +# Add dependency check for dxs file, because dxs file depends on PPI or +# PROTOCOL guid defintions. +# +DEP_FILE = $(DEST_DIR)\$(BASE_NAME)dxs.dep + +!IF EXIST($(TARGET_DPX)) +DEP_TARGETS = $(DEP_TARGETS) $(DEST_DIR)\$(BASE_NAME)dxs.dep +!IF !EXIST($(DEP_FILE)) +CREATEDEPS = YES +!ENDIF +!ENDIF + +!IF EXIST($(DEP_FILE)) +!INCLUDE $(DEP_FILE) +!ENDIF +# +# Update dep file for next round incremental build +# +$(DEP_FILE) : $(TARGET_DPX) + $(MAKEDEPS) -f $(DPX_SOURCE_FILE) $(DEP_FLAGS) + +$(TARGET_DPX) : $(DPX_SOURCE_FILE) $(INF_FILENAME) + $(CC) /nologo $(INC) $(VERSION_FLAGS) /EP $(DPX_SOURCE_FILE) > $*.tmp1 + $(GENDEPEX) -I $*.tmp1 -O $*.tmp2 + $(GENSECTION) -I $*.tmp2 -O $@ -S $(DEPEX_TYPE) + del $*.tmp1 > NUL + del $*.tmp2 > NUL +!ELSE +!ERROR Dependency expression source file "$(DPX_SOURCE_FILE)" does not exist. +!ENDIF +!ELSE +$(TARGET_DPX) : + echo. > $(TARGET_DPX) + type $(TARGET_DPX) > $(TARGET_DPX) +!ENDIF + +# +# Build a FFS file from the sections and package +# +$(TARGET_FFS_FILE) : $(TARGET_PE32) $(TARGET_DPX) $(TARGET_UI) $(TARGET_VER) $(PACKAGE_FILENAME) + $(GENFFSFILE) -B $(DEST_DIR) -P1 $(PACKAGE_FILENAME) -V + +all : $(TARGET_FFS_FILE) + +# +# Remove the generated temp and final files for this modules. +# +clean : +!IF ("$(FILE_GUID)" != "") + @if exist $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* del $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* +!ENDIF + @if exist $(BIN_DIR)\$(BASE_NAME).* del $(BIN_DIR)\$(BASE_NAME).* + @del /q $(DEST_OUTPUT_DIRS) + +[=============================================================================] +[Compile.Ia32.Bin|Bmp,Compile.x64.Bin|Bmp,Compile.Ipf.Bin|Bmp] +# +# We simply copy the binary file from the source directory to the destination directory +# +$(DEST_DIR)\$(BASE_NAME).bin : $(SOURCE_FILE_NAME) + copy $** $@ + +[=============================================================================] +[Build.Ia32.BINARY|Legacy16|Logo,Build.Ipf.BINARY|Legacy16|Logo,Build.x64.BINARY|Legacy16|Logo] +# +# Use GenFfsFile to convert it to an FFS file +# +$(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).ffs : $(DEST_DIR)\$(BASE_NAME).bin $(PACKAGE_FILENAME) + $(GENSECTION) -I $(DEST_DIR)\$(BASE_NAME).bin -O $(DEST_DIR)\$(BASE_NAME).sec -S EFI_SECTION_RAW + $(GENFFSFILE) -B $(DEST_DIR) -P1 $(PACKAGE_FILENAME) -V + +all : $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).ffs + +# +# Remove the generated temp and final files for this modules. +# +clean : +!IF ("$(FILE_GUID)" != "") + @if exist $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* del $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* +!ENDIF + @if exist $(BIN_DIR)\$(BASE_NAME).* del $(BIN_DIR)\$(BASE_NAME).* + @del /q $(DEST_OUTPUT_DIRS) + +[=============================================================================] +[Build.Ia32.RAWFILE|CONFIG,Build.Ipf.RAWFILE|CONFIG,Build.x64.RAWFILE|CONFIG] +# +# Use GenFfsFile to convert it to an raw FFS file +# +$(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).raw : $(DEST_DIR)\$(BASE_NAME).bin $(PACKAGE_FILENAME) + $(GENFFSFILE) -B $(DEST_DIR) -P1 $(PACKAGE_FILENAME) -V + +all : $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).raw + +# +# Remove the generated temp and final files for this modules. +# +clean : +!IF ("$(FILE_GUID)" != "") + @if exist $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* del $(BIN_DIR)\$(FILE_GUID)-$(BASE_NAME).* +!ENDIF + @if exist $(BIN_DIR)\$(BASE_NAME).* del $(BIN_DIR)\$(BASE_NAME).* + @del /q $(DEST_OUTPUT_DIRS) + +[=============================================================================] +# +# These are commands to compile unicode .uni files. +# +[=============================================================================] +[Compile.Ia32.Uni,Compile.Ipf.Uni,Compile.Ebc.Uni,Compile.x64.Uni] +# +# Emit an error message if the file's base name is the same as the +# component base name. This causes build issues. +# +!IF "$(FILE)" == "$(BASE_NAME)" +!ERROR Component Unicode string file name cannot be the same as the component BASE_NAME. +!ENDIF + +# +# Always create dep file for uni file as it can be created at the same time when +# strgather is parsing uni file. +# +DEP_FILE = $(DEST_DIR)\$(FILE)Uni.dep + +!IF EXIST($(DEP_FILE)) +!INCLUDE $(DEP_FILE) +!ENDIF + +$(DEST_DIR)\$(FILE).sdb : $(SOURCE_FILE_NAME) $(INF_FILENAME) + $(STRGATHER) -parse -newdb -db $(DEST_DIR)\$(FILE).sdb -dep $(DEP_FILE) $(INC) $(SOURCE_FILE_NAME) + +SDB_FILES = $(SDB_FILES) $(DEST_DIR)\$(FILE).sdb +STRGATHER_FLAGS = $(STRGATHER_FLAGS) -db $(DEST_DIR)\$(FILE).sdb +LOCALIZE = YES + +[=============================================================================] +[Compile.Ia32.Vfr,Compile.Ipf.Vfr,Compile.x64.Vfr] + +DEP_FILE = $(DEST_DIR)\$(FILE)Vfr.dep + +!IF EXIST($(DEST_DIR)\$(FILE).obj) +DEP_TARGETS = $(DEP_TARGETS) $(DEST_DIR)\$(FILE)Vfr.dep +!IF !EXIST($(DEP_FILE)) +CREATEDEPS = YES +!ENDIF +!ENDIF + +!IF EXIST($(DEP_FILE)) +!INCLUDE $(DEP_FILE) +!ENDIF + +# +# Update dep file for next round incremental build +# +$(DEP_FILE) : $(DEST_DIR)\$(FILE).obj + $(MAKEDEPS) -f $(SOURCE_FILE_NAME) $(DEP_FLAGS) + +HII_PACK_FILES = $(HII_PACK_FILES) $(DEST_DIR)\$(FILE).hpk + +# +# Add a dummy command for building the HII pack file. In reality, it's built +# below, but the C_FLAGS macro reference the target as $@, so you can't specify +# the obj and hpk files as dual targets of the same command. +# +$(DEST_DIR)\$(FILE).hpk : $(DEST_DIR)\$(FILE).obj + +$(DEST_DIR)\$(FILE).obj : $(SOURCE_FILE_NAME) $(INF_FILENAME) $(ALL_DEPS) + $(VFRCOMPILE) $(VFRCOMPILE_FLAGS) $(INC) -ibin -od $(DEST_DIR)\$(SOURCE_RELATIVE_PATH) \ + -l $(VFR_FLAGS) $(SOURCE_FILE_NAME) + $(CC) $(C_FLAGS) $(DEST_DIR)\$(FILE).c + +[=============================================================================] +[Compile.Ebc.Vfr] + +DEP_FILE = $(DEST_DIR)\$(FILE)Vfr.dep + +!IF EXIST($(DEST_DIR)\$(FILE).obj) +DEP_TARGETS = $(DEP_TARGETS) $(DEST_DIR)\$(FILE)Vfr.dep +!IF !EXIST($(DEP_FILE)) +CREATEDEPS = YES +!ENDIF +!ENDIF + +!IF EXIST($(DEP_FILE)) +!INCLUDE $(DEP_FILE) +!ENDIF + +# +# Update dep file for next round incremental build +# +$(DEP_FILE) : $(DEST_DIR)\$(FILE).obj + $(MAKEDEPS) -f $(SOURCE_FILE_NAME) $(DEP_FLAGS) + +HII_PACK_FILES = $(HII_PACK_FILES) $(DEST_DIR)\$(FILE).hpk + +# +# Add a dummy command for building the HII pack file. In reality, it's built +# below, but the C_FLAGS macro reference the target as $@, so you can't specify +# the obj and hpk files as dual targets of the same command. +# +$(DEST_DIR)\$(FILE).hpk : $(DEST_DIR)\$(FILE).obj + +$(DEST_DIR)\$(FILE).obj : $(SOURCE_FILE_NAME) $(INF_FILENAME) $(ALL_DEPS) + $(VFRCOMPILE) $(VFRCOMPILE_FLAGS) $(INC) -ibin -od $(DEST_DIR)\$(SOURCE_RELATIVE_PATH) \ + -l $(VFR_FLAGS) $(SOURCE_FILE_NAME) + $(EBC_CC) $(EBC_C_FLAGS) $(DEST_DIR)\$(FILE).c + +[=============================================================================] +# +# Commands for building IFR as uncompressed binary into the FFS file. To +# use it, set COMPILE_SELECT=.vfr=Ifr_Bin for the component in the DSC file. +# +[=============================================================================] +[Compile.Ia32.Ifr_Bin,Compile.Ipf.Ifr_Bin,Compile.x64.Ifr_Bin] + +DEP_FILE = $(DEST_DIR)\$(FILE)Vfr.dep + +!IF EXIST($(DEST_DIR)\$(FILE).obj) +DEP_TARGETS = $(DEP_TARGETS) $(DEST_DIR)\$(FILE)Vfr.dep +!IF !EXIST($(DEP_FILE)) +CREATEDEPS = YES +!ENDIF +!ENDIF + +!IF EXIST($(DEP_FILE)) +!INCLUDE $(DEP_FILE) +!ENDIF + +# +# Update dep file for next round incremental build +# +$(DEP_FILE) : $(DEST_DIR)\$(FILE).obj + $(MAKEDEPS) -f $(SOURCE_FILE_NAME) $(DEP_FLAGS) + +HII_PACK_FILES = $(HII_PACK_FILES) $(DEST_DIR)\$(FILE).hpk + +# +# Add a dummy command for building the HII pack file. In reality, it's built +# below, but the C_FLAGS macro reference the target as $@, so you can't specify +# the obj and hpk files as dual targets of the same command. +# +$(DEST_DIR)\$(FILE).hpk : $(DEST_DIR)\$(FILE).obj + +$(DEST_DIR)\$(FILE).obj : $(SOURCE_FILE_NAME) $(INF_FILENAME) $(ALL_DEPS) + $(VFRCOMPILE) $(VFRCOMPILE_FLAGS) $(INC) -ibin -od $(DEST_DIR)\$(SOURCE_RELATIVE_PATH) \ + -l $(VFR_FLAGS) $(SOURCE_FILE_NAME) + $(CC) $(C_FLAGS) $(DEST_DIR)\$(FILE).c + +# +# Add to the variable that contains the list of VFR binary files we're going +# to merge together at the end of the build. +# +HII_IFR_PACK_FILES = $(HII_IFR_PACK_FILES) $(DEST_DIR)\$(FILE).hpk + +[=============================================================================] +# +# Commands for building IFR as uncompressed binary into the FFS file. To +# use it, set COMPILE_SELECT=.vfr=Ifr_Bin for the component in the DSC file. +# +[=============================================================================] +[Compile.Ebc.Ifr_Bin] + +DEP_FILE = $(DEST_DIR)\$(FILE)Vfr.dep + +!IF EXIST($(DEST_DIR)\$(FILE).obj) +DEP_TARGETS = $(DEP_TARGETS) $(DEST_DIR)\$(FILE)Vfr.dep +!IF !EXIST($(DEP_FILE)) +CREATEDEPS = YES +!ENDIF +!ENDIF + +!IF EXIST($(DEP_FILE)) +!INCLUDE $(DEP_FILE) +!ENDIF + +# +# Update dep file for next round incremental build +# +$(DEP_FILE) : $(DEST_DIR)\$(FILE).obj + $(MAKEDEPS) -f $(SOURCE_FILE_NAME) $(DEP_FLAGS) + +HII_PACK_FILES = $(HII_PACK_FILES) $(DEST_DIR)\$(FILE).hpk + +# +# Add a dummy command for building the HII pack file. In reality, it's built +# below, but the C_FLAGS macro reference the target as $@, so you can't specify +# the obj and hpk files as dual targets of the same command. +# +$(DEST_DIR)\$(FILE).hpk : $(DEST_DIR)\$(FILE).obj + +$(DEST_DIR)\$(FILE).obj : $(SOURCE_FILE_NAME) $(INF_FILENAME) $(ALL_DEPS) + $(VFRCOMPILE) $(VFRCOMPILE_FLAGS) $(INC) -ibin -od $(DEST_DIR)\$(SOURCE_RELATIVE_PATH) \ + -l $(VFR_FLAGS) $(SOURCE_FILE_NAME) + $(EBC_CC) $(EBC_C_FLAGS) $(DEST_DIR)\$(FILE).c + +# +# Add to the variable that contains the list of VFR binary files we're going +# to merge together at the end of the build. +# +HII_IFR_PACK_FILES = $(HII_IFR_PACK_FILES) $(DEST_DIR)\$(FILE).hpk + +[=============================================================================] +[Compile.Ia32.Fv,Compile.Ipf.Fv,Compile.x64.Fv] +# +# Run GenSection on the firmware volume image. +# +$(DEST_DIR)\$(SOURCE_FV)Fv.sec : $(SOURCE_FILE_NAME) + $(GENSECTION) -I $(SOURCE_FILE_NAME) -O $(DEST_DIR)\$(SOURCE_FV)Fv.sec -S EFI_SECTION_FIRMWARE_VOLUME_IMAGE + +[=============================================================================] diff --git a/EdkCompatibilityPkg/Sample/Platform/CommonIa32.dsc b/EdkCompatibilityPkg/Sample/Platform/CommonIa32.dsc new file mode 100644 index 0000000000..f9fae29359 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Platform/CommonIa32.dsc @@ -0,0 +1,558 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CommonIa32.dsc +# +# Abstract: +# +# This is the build description file containing the processor architecture +# dependent build instructions. +# +# Notes: +# +# The info in this file is broken down into sections. The start of a section +# is designated by a "[" in the first column. So the [=====] separater ends +# a section. +# +#--*/ + + +[=============================================================================] +# +# These are the package descriptions. They are tagged as +# [Package.$(COMPONENT_TYPE).$(PACKAGE)], where COMPONENT_TYPE is typically +# defined in the component INF file, and PACKAGE is typically specified +# in the components section in the main DSC file. Main DSC file can also define +# platform specific package descriptions. +# + +[=============================================================================] +[Package.APPLICATION.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_APPLICATION +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Tool ( + $(OEMTOOLPATH)\GenCRC32Section + ARGS= -i $(DEST_DIR)\$(BASE_NAME).pe32 + $(DEST_DIR)\$(BASE_NAME).ui + $(DEST_DIR)\$(BASE_NAME).ver + -o $(DEST_DIR)\$(BASE_NAME).crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME).crc32 + ) + } +} + +[=============================================================================] +[Package.Apriori.Default|DefaultStripped,Package.FILE.Default|DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FREEFORM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).sec +} + +[=============================================================================] +[Package.RAWFILE.Default|DefaultStripped,Package.Config.Default|DefaultStripped|Config,Package.Microcode.Default|DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_RAW +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).Bin +} + +[=============================================================================] +[Package.BINARY.Default,Package.Legacy16.Default,Package.Logo.Default|Logo] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FREEFORM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Tool ( $(OEMTOOLPATH)\GenCRC32Section + ARGS = -i $(DEST_DIR)\$(BASE_NAME).sec + -o $(DEST_DIR)\$(BASE_NAME).crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME).crc32 + ) + } +} + +[=============================================================================] +# +# Package definition for TE files +# +[Package.PE32_PEIM.TE_PEIM] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).dpx + $(BASE_NAME).tes + $(BASE_NAME).ui + $(BASE_NAME).ver +} + +[=============================================================================] +# +# Package definition to put the IFR data in a separate section in the +# FFS file. +# +[Package.BS_DRIVER.Ifr_Bin] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_DRIVER +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Tool ( + $(OEMTOOLPATH)\GenCRC32Section + ARGS= -i $(DEST_DIR)\$(BASE_NAME).dpx + $(DEST_DIR)\$(BASE_NAME).pe32 + $(DEST_DIR)\$(BASE_NAME).ui + $(DEST_DIR)\$(BASE_NAME).ver + $(DEST_DIR)\$(BASE_NAME)IfrBin.sec + -o $(DEST_DIR)\$(BASE_NAME).crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME).crc32 + ) + } +} + +[=============================================================================] +[Package.PEI_CORE.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEI_CORE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ \ + $(BASE_NAME).pe32 \ + $(BASE_NAME).ui \ + $(BASE_NAME).ver \ +} + +[=============================================================================] +[Package.PEI_CORE.TE_PEIM] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEI_CORE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ \ + $(BASE_NAME).tes \ + $(BASE_NAME).ui \ + $(BASE_NAME).ver \ +} + +[=============================================================================] +[Package.PE32_PEIM.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ \ + $(BASE_NAME).dpx \ + $(BASE_NAME).pe32 \ + $(BASE_NAME).ui \ + $(BASE_NAME).ver \ +} + +[=============================================================================] +[Package.PE32_PEIM.Relocatable] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ \ + $(BASE_NAME).dpx \ + $(BASE_NAME).pe32 \ +} + +[=============================================================================] +[Package.PE32_PEIM.CompressPEIM] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).dpx + Compress ($(COMPRESS_METHOD)) { + $(BASE_NAME).pe32 + $(BASE_NAME).ui + $(BASE_NAME).ver + } +} + +[=============================================================================] +[Package.COMBINED_PEIM_DRIVER.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ \ + $(BASE_NAME).dpx \ + $(BASE_NAME).dpxd \ + $(BASE_NAME).pe32 \ + $(BASE_NAME).ui \ + $(BASE_NAME).ver \ +} + +[=============================================================================] +[Package.BS_DRIVER.DxeMain] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_DXE_CORE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + $(BASE_NAME).pe32 + $(BASE_NAME).ui + $(BASE_NAME).ver + } +} + + +[=============================================================================] +[Package.BS_DRIVER.Default,Package.RT_DRIVER.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_DRIVER +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Tool ( + $(OEMTOOLPATH)\GenCRC32Section + ARGS= -i $(DEST_DIR)\$(BASE_NAME).dpx + $(DEST_DIR)\$(BASE_NAME).pe32 + $(DEST_DIR)\$(BASE_NAME).ui + $(DEST_DIR)\$(BASE_NAME).ver + -o $(DEST_DIR)\$(BASE_NAME).crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME).crc32 + ) + } +} + +[=============================================================================] +[Package.FvImageFile.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Tool ( + $(OEMTOOLPATH)\GenCRC32Section + ARGS= -i $(DEST_DIR)\$(SOURCE_FV)Fv.sec + -o $(DEST_DIR)\$(BASE_NAME)fv.crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME)fv.crc32 + ) + } +} + +[=============================================================================] +# +# Define a package that "signs" our capsule cargo FV +# +[Package.FvImageFile.SignedFVPackage] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Tool ( + $(OEMTOOLPATH)\GenCRC32Section + ARGS= -i $(DEST_DIR)\$(SOURCE_FV)Fv.sec + -o $(DEST_DIR)\$(BASE_NAME).crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME).crc32 + ) +} + +[=============================================================================] +[Package.FvImageFile.FvMainCompact] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Blank.pad + $(SOURCE_FV)Fv.sec + } +} +[=============================================================================] +# +# Stripped package descriptions for size reduction. +# +[=============================================================================] +[Package.APPLICATION.DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_APPLICATION +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + $(DEST_DIR)\$(BASE_NAME).pe32 + } +} + +[=============================================================================] +[Package.BINARY.DefaultStripped,Package.Legacy16.DefaultStripped,Package.Logo.DefaultStripped|LogoStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FREEFORM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + $(DEST_DIR)\$(BASE_NAME).sec + } +} + +[=============================================================================] +[Package.PEI_CORE.DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEI_CORE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ \ + $(BASE_NAME).pe32 \ +} + +[=============================================================================] +[Package.PEI_CORE.TE_PEIMStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEI_CORE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).tes +} +[=============================================================================] +[Package.PE32_PEIM.DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ \ + $(BASE_NAME).dpx \ + $(BASE_NAME).pe32 \ +} + +[=============================================================================] +[Package.PE32_PEIM.CompressPEIMStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).dpx + Compress ($(COMPRESS_METHOD)) { + $(BASE_NAME).pe32 + } +} + +[=============================================================================] +# +# Package definition for TE files +# +[Package.PE32_PEIM.TE_PEIMStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).dpx + $(BASE_NAME).tes +} + +[=============================================================================] +[Package.COMBINED_PEIM_DRIVER.DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ \ + $(BASE_NAME).dpx \ + $(BASE_NAME).dpxd \ + $(BASE_NAME).pe32 \ +} + +[=============================================================================] +[Package.BS_DRIVER.DxeMainStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_DXE_CORE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + $(BASE_NAME).pe32 + } +} + + +[=============================================================================] +[Package.BS_DRIVER.DefaultStripped,Package.RT_DRIVER.DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_DRIVER +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + $(DEST_DIR)\$(BASE_NAME).dpx + $(DEST_DIR)\$(BASE_NAME).pe32 + } +} + + +[=============================================================================] +[Package.FvImageFile.DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + $(DEST_DIR)\$(SOURCE_FV)Fv.sec + } +} + +[=============================================================================] +[Package.SECURITY_CORE.Default|DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_SECURITY_CORE +FFS_ATTRIB_CHECKSUM = FALSE + +IMAGE_SCRIPT = +{ \ + Blank1.pad \ + $(BASE_NAME).tes \ + ResetVec.raw \ +} + +[=============================================================================] diff --git a/EdkCompatibilityPkg/Sample/Platform/CommonIpf.dsc b/EdkCompatibilityPkg/Sample/Platform/CommonIpf.dsc new file mode 100644 index 0000000000..13bfe9171b --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Platform/CommonIpf.dsc @@ -0,0 +1,391 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CommonIpf.dsc +# +# Abstract: +# +# This is the build description file containing the processor architecture +# dependent build instructions. +# +# Notes: +# +# The info in this file is broken down into sections. The start of a section +# is designated by a "[" in the first column. So the [=====] separater ends +# a section. +# +#--*/ + + +[=============================================================================] +# +# These are the package descriptions. They are tagged as +# [Package.$(COMPONENT_TYPE).$(PACKAGE)], where COMPONENT_TYPE is typically +# defined in the component INF file, and PACKAGE is typically specified +# in the components section in the main DSC file. Main DSC file can also define +# platform specific package descriptions. +# + +[=============================================================================] +[Package.APPLICATION.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_APPLICATION +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Tool ( + $(OEMTOOLPATH)\GenCRC32Section + ARGS= -i $(DEST_DIR)\$(BASE_NAME).pe32 + $(DEST_DIR)\$(BASE_NAME).ui + $(DEST_DIR)\$(BASE_NAME).ver + -o $(DEST_DIR)\$(BASE_NAME).crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME).crc32 + ) + } +} + +[=============================================================================] +[Package.Apriori.Default,Package.FILE.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FREEFORM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).sec +} + +[=============================================================================] +[Package.RAWFILE.Default,Package.Config.Default|Config] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_RAW +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).Bin +} + +[=============================================================================] +[Package.BINARY.Default,Package.Legacy16.Default,Package.Logo.Default|Logo] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FREEFORM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Tool ( $(OEMTOOLPATH)\GenCRC32Section + ARGS = -i $(DEST_DIR)\$(BASE_NAME).sec + -o $(DEST_DIR)\$(BASE_NAME).crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME).crc32 + ) + } +} + +[=============================================================================] +# +# Package definition for TE files +# +[Package.PE32_PEIM.TE_PEIM] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).dpx + $(BASE_NAME).tes + $(BASE_NAME).ui + $(BASE_NAME).ver +} + +[=============================================================================] +# +# Package definition to put the IFR data in a separate section in the +# FFS file. +# +[Package.BS_DRIVER.Ifr_Bin] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_DRIVER +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Tool ( + $(OEMTOOLPATH)\GenCRC32Section + ARGS= -i $(DEST_DIR)\$(BASE_NAME).dpx + $(DEST_DIR)\$(BASE_NAME).pe32 + $(DEST_DIR)\$(BASE_NAME).ui + $(DEST_DIR)\$(BASE_NAME).ver + $(DEST_DIR)\$(BASE_NAME)IfrBin.sec + -o $(DEST_DIR)\$(BASE_NAME).crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME).crc32 + ) + } +} + +[=============================================================================] +[Package.SECURITY_CORE.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_SECURITY_CORE +FFS_ATTRIB_CHECKSUM = TRUE +FFS_ALIGNMENT = 0x1 + +IMAGE_SCRIPT = +{ \ + Blank.pad \ + $(BASE_NAME).pe32 \ + $(BASE_NAME).ui \ + $(BASE_NAME).ver \ +} + +[=============================================================================] +[Package.PEI_CORE.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEI_CORE +FFS_ATTRIB_CHECKSUM = TRUE +FFS_ALIGNMENT = 0x1 + +IMAGE_SCRIPT = +{ \ + Blank.pad \ + $(BASE_NAME).pe32 \ + $(BASE_NAME).ui \ + $(BASE_NAME).ver \ +} + +[=============================================================================] +[Package.PE32_PEIM.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE +FFS_ALIGNMENT = 0x1 + +IMAGE_SCRIPT = +{ \ + Blank.pad \ + $(BASE_NAME).pe32 \ + $(BASE_NAME).dpx \ + $(BASE_NAME).ui \ + $(BASE_NAME).ver \ +} + +[=============================================================================] +[Package.PE32_PEIM.CompressPEIM] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).dpx + Compress ($(COMPRESS_METHOD)) { + $(BASE_NAME).pe32 + $(BASE_NAME).ui + $(BASE_NAME).ver + } +} + +[=============================================================================] +[Package.COMBINED_PEIM_DRIVER.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER +FFS_ATTRIB_CHECKSUM = TRUE +FFS_ALIGNMENT = 0x1 + +IMAGE_SCRIPT = +{ \ + Blank.pad \ + $(BASE_NAME).pe32 \ + $(BASE_NAME).dpx \ + $(BASE_NAME).dpxd \ + $(BASE_NAME).ui \ + $(BASE_NAME).ver \ +} + +[=============================================================================] +[Package.PIC_PEIM.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE +FFS_ALIGNMENT = 0x1 + +IMAGE_SCRIPT = +{ \ + Blank.pad \ + $(BASE_NAME).dpx \ + $(BASE_NAME).pic \ + $(BASE_NAME).ui \ + $(BASE_NAME).ver \ +} + + +[=============================================================================] +[Package.DxeIplPad.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_RAW +FFS_ATTRIB_CHECKSUM = TRUE +FFS_ALIGNMENT = 0x7 + +IMAGE_SCRIPT = +{ \ + $(BASE_NAME).pad \ +} + + +[=============================================================================] +[Package.BS_DRIVER.DxeMain] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_DXE_CORE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + $(BASE_NAME).pe32 + $(BASE_NAME).ui + $(BASE_NAME).ver + } +} + + +[=============================================================================] +[Package.BS_DRIVER.Default,Package.RT_DRIVER.Default,Package.SAL_RT_DRIVER.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_DRIVER +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Tool ( + $(OEMTOOLPATH)\GenCRC32Section + ARGS= -i $(DEST_DIR)\$(BASE_NAME).dpx + $(DEST_DIR)\$(BASE_NAME).pe32 + $(DEST_DIR)\$(BASE_NAME).ui + $(DEST_DIR)\$(BASE_NAME).ver + -o $(DEST_DIR)\$(BASE_NAME).crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME).crc32 + ) + } +} + +[=============================================================================] +[Package.FvImageFile.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Tool ( + $(OEMTOOLPATH)\GenCRC32Section + ARGS= -i $(DEST_DIR)\$(SOURCE_FV)Fv.sec + -o $(DEST_DIR)\$(BASE_NAME)fv.crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME)fv.crc32 + ) + } +} + +[=============================================================================] +# +# Define a package that "signs" our capsule cargo FV +# +[Package.FvImageFile.SignedFVPackage] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Tool ( + $(OEMTOOLPATH)\GenCRC32Section + ARGS= -i $(DEST_DIR)\$(SOURCE_FV)Fv.sec + -o $(DEST_DIR)\$(BASE_NAME).crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME).crc32 + ) +} + +[=============================================================================] +[Package.FvImageFile.FvMainCompact] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Blank.pad + $(SOURCE_FV)Fv.sec + } +} +[=============================================================================] diff --git a/EdkCompatibilityPkg/Sample/Platform/CommonX64.dsc b/EdkCompatibilityPkg/Sample/Platform/CommonX64.dsc new file mode 100644 index 0000000000..4314049361 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Platform/CommonX64.dsc @@ -0,0 +1,558 @@ +#/*++ +# +# Copyright (c) 2005 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# CommonX64.dsc +# +# Abstract: +# +# This is the build description file containing the processor architecture +# dependent build instructions. +# +# Notes: +# +# The info in this file is broken down into sections. The start of a section +# is designated by a "[" in the first column. So the [=====] separater ends +# a section. +# +#--*/ + + +[=============================================================================] +# +# These are the package descriptions. They are tagged as +# [Package.$(COMPONENT_TYPE).$(PACKAGE)], where COMPONENT_TYPE is typically +# defined in the component INF file, and PACKAGE is typically specified +# in the components section in the main DSC file. Main DSC file can also define +# platform specific package descriptions. +# + +[=============================================================================] +[Package.APPLICATION.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_APPLICATION +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Tool ( + $(OEMTOOLPATH)\GenCRC32Section + ARGS= -i $(DEST_DIR)\$(BASE_NAME).pe32 + $(DEST_DIR)\$(BASE_NAME).ui + $(DEST_DIR)\$(BASE_NAME).ver + -o $(DEST_DIR)\$(BASE_NAME).crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME).crc32 + ) + } +} + +[=============================================================================] +[Package.Apriori.Default|DefaultStripped,Package.FILE.Default|DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FREEFORM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).sec +} + +[=============================================================================] +[Package.RAWFILE.Default|DefaultStripped,Package.Config.Default|DefaultStripped|Config,Package.Microcode.Default|DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_RAW +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).Bin +} + +[=============================================================================] +[Package.BINARY.Default,Package.Legacy16.Default,Package.Logo.Default|Logo] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FREEFORM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Tool ( $(OEMTOOLPATH)\GenCRC32Section + ARGS = -i $(DEST_DIR)\$(BASE_NAME).sec + -o $(DEST_DIR)\$(BASE_NAME).crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME).crc32 + ) + } +} + +[=============================================================================] +# +# Package definition for TE files +# +[Package.PE32_PEIM.TE_PEIM] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).dpx + $(BASE_NAME).tes + $(BASE_NAME).ui + $(BASE_NAME).ver +} + +[=============================================================================] +# +# Package definition to put the IFR data in a separate section in the +# FFS file. +# +[Package.BS_DRIVER.Ifr_Bin] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_DRIVER +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Tool ( + $(OEMTOOLPATH)\GenCRC32Section + ARGS= -i $(DEST_DIR)\$(BASE_NAME).dpx + $(DEST_DIR)\$(BASE_NAME).pe32 + $(DEST_DIR)\$(BASE_NAME).ui + $(DEST_DIR)\$(BASE_NAME).ver + $(DEST_DIR)\$(BASE_NAME)IfrBin.sec + -o $(DEST_DIR)\$(BASE_NAME).crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME).crc32 + ) + } +} + +[=============================================================================] +[Package.PEI_CORE.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEI_CORE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ \ + $(BASE_NAME).pe32 \ + $(BASE_NAME).ui \ + $(BASE_NAME).ver \ +} + +[=============================================================================] +[Package.PEI_CORE.TE_PEIM] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEI_CORE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ \ + $(BASE_NAME).tes \ + $(BASE_NAME).ui \ + $(BASE_NAME).ver \ +} + +[=============================================================================] +[Package.PE32_PEIM.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ \ + $(BASE_NAME).dpx \ + $(BASE_NAME).pe32 \ + $(BASE_NAME).ui \ + $(BASE_NAME).ver \ +} + +[=============================================================================] +[Package.PE32_PEIM.Relocatable] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ \ + $(BASE_NAME).dpx \ + $(BASE_NAME).pe32 \ +} + +[=============================================================================] +[Package.PE32_PEIM.CompressPEIM] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).dpx + Compress ($(COMPRESS_METHOD)) { + $(BASE_NAME).pe32 + $(BASE_NAME).ui + $(BASE_NAME).ver + } +} + +[=============================================================================] +[Package.COMBINED_PEIM_DRIVER.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ \ + $(BASE_NAME).dpx \ + $(BASE_NAME).dpxd \ + $(BASE_NAME).pe32 \ + $(BASE_NAME).ui \ + $(BASE_NAME).ver \ +} + +[=============================================================================] +[Package.BS_DRIVER.DxeMain] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_DXE_CORE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + $(BASE_NAME).pe32 + $(BASE_NAME).ui + $(BASE_NAME).ver + } +} + + +[=============================================================================] +[Package.BS_DRIVER.Default,Package.RT_DRIVER.Default,Package.SAL_RT_DRIVER.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_DRIVER +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Tool ( + $(OEMTOOLPATH)\GenCRC32Section + ARGS= -i $(DEST_DIR)\$(BASE_NAME).dpx + $(DEST_DIR)\$(BASE_NAME).pe32 + $(DEST_DIR)\$(BASE_NAME).ui + $(DEST_DIR)\$(BASE_NAME).ver + -o $(DEST_DIR)\$(BASE_NAME).crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME).crc32 + ) + } +} + +[=============================================================================] +[Package.FvImageFile.Default] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Tool ( + $(OEMTOOLPATH)\GenCRC32Section + ARGS= -i $(DEST_DIR)\$(SOURCE_FV)Fv.sec + -o $(DEST_DIR)\$(BASE_NAME)fv.crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME)fv.crc32 + ) + } +} + +[=============================================================================] +# +# Define a package that "signs" our capsule cargo FV +# +[Package.FvImageFile.SignedFVPackage] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Tool ( + $(OEMTOOLPATH)\GenCRC32Section + ARGS= -i $(DEST_DIR)\$(SOURCE_FV)Fv.sec + -o $(DEST_DIR)\$(BASE_NAME).crc32 + OUTPUT = $(DEST_DIR)\$(BASE_NAME).crc32 + ) +} + +[=============================================================================] +# +# Stripped package descriptions for size reduction. +# +[=============================================================================] +[Package.APPLICATION.DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_APPLICATION +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + $(DEST_DIR)\$(BASE_NAME).pe32 + } +} + +[=============================================================================] +[Package.BINARY.DefaultStripped,Package.Legacy16.DefaultStripped,Package.Logo.DefaultStripped|LogoStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FREEFORM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + $(DEST_DIR)\$(BASE_NAME).sec + } +} + +[=============================================================================] +[Package.PEI_CORE.DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEI_CORE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ \ + $(BASE_NAME).pe32 \ +} + +[=============================================================================] +[Package.PEI_CORE.TE_PEIMStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEI_CORE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).tes +} +[=============================================================================] +[Package.PE32_PEIM.DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ \ + $(BASE_NAME).dpx \ + $(BASE_NAME).pe32 \ +} + +[=============================================================================] +[Package.PE32_PEIM.CompressPEIMStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).dpx + Compress ($(COMPRESS_METHOD)) { + $(BASE_NAME).pe32 + } +} + +[=============================================================================] +# +# Package definition for TE files +# +[Package.PE32_PEIM.TE_PEIMStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_PEIM +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + $(BASE_NAME).dpx + $(BASE_NAME).tes +} + +[=============================================================================] +[Package.COMBINED_PEIM_DRIVER.DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ \ + $(BASE_NAME).dpx \ + $(BASE_NAME).dpxd \ + $(BASE_NAME).pe32 \ +} + +[=============================================================================] +[Package.BS_DRIVER.DxeMainStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_DXE_CORE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + $(BASE_NAME).pe32 + } +} + + +[=============================================================================] +[Package.BS_DRIVER.DefaultStripped,Package.RT_DRIVER.DefaultStripped,Package.SAL_RT_DRIVER.DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_DRIVER +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + $(DEST_DIR)\$(BASE_NAME).dpx + $(DEST_DIR)\$(BASE_NAME).pe32 + } +} + + +[=============================================================================] +[Package.FvImageFile.DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + $(DEST_DIR)\$(SOURCE_FV)Fv.sec + } +} + +[=============================================================================] +[Package.FvImageFile.FvMainCompact] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE +FFS_ATTRIB_CHECKSUM = TRUE + +IMAGE_SCRIPT = +{ + Compress ($(COMPRESS_METHOD)) { + Blank.pad + $(SOURCE_FV)Fv.sec + } +} +[=============================================================================] +[Package.SECURITY_CORE.Default|DefaultStripped] +PACKAGE.INF +\[.] +BASE_NAME = $(BASE_NAME) +FFS_FILEGUID = $(FILE_GUID) +FFS_FILETYPE = EFI_FV_FILETYPE_SECURITY_CORE +FFS_ATTRIB_CHECKSUM = FALSE + +IMAGE_SCRIPT = +{ \ + Blank1.pad \ + $(BASE_NAME).tes \ + ResetVec.raw \ +} + +[=============================================================================] diff --git a/EdkCompatibilityPkg/Sample/Platform/EdkIIGlueLib32.dsc b/EdkCompatibilityPkg/Sample/Platform/EdkIIGlueLib32.dsc new file mode 100644 index 0000000000..5c71f41108 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Platform/EdkIIGlueLib32.dsc @@ -0,0 +1,39 @@ +#/*++ +# Copyright (c) 2006, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +#--*/ +# +# EdkII Glue Library for PEI usage (32bit) +# +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BaseLib\BaseLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BaseMemoryLib\BaseMemoryLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePrintLib\BasePrintLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BaseDebugLibNull\BaseDebugLibNull.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BaseIoLibIntrinsic\BaseIoLibIntrinsic.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePostCodeLibPort80\BasePostCodeLibPort80.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePostCodeLibDebug\BasePostCodeLibDebug.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BaseCacheMaintenanceLib\BaseCacheMaintenanceLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePciCf8Lib\BasePciCf8Lib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePciExpressLib\BasePciExpressLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePciLibCf8\BasePciLibCf8.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePciLibPciExpress\BasePciLibPciExpress.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePeCoffGetEntryPointLib\BasePeCoffGetEntryPointLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePeCoffLib\BasePeCoffLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BaseTimerLibLocalApic\BaseTimerLibLocalApic.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BaseUefiDecompressLib\BaseUefiDecompressLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiDxeDebugLibReportStatusCode\PeiDxeDebugLibReportStatusCode.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiDxePostCodeLibReportStatusCode\PeiDxePostCodeLibReportStatusCode.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiServicesTablePointerLibMm7\PeiServicesTablePointerLibMm7.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiServicesTablePointerLib\PeiServicesTablePointerLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiMemoryAllocationLib\PeiMemoryAllocationLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiServicesLib\PeiServicesLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiHobLib\PeiHobLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiReportStatusCodeLib\PeiReportStatusCodeLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiResourcePublicationLib\PeiResourcePublicationLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiSmbusLib\PeiSmbusLib.inf diff --git a/EdkCompatibilityPkg/Sample/Platform/EdkIIGlueLibAll.dsc b/EdkCompatibilityPkg/Sample/Platform/EdkIIGlueLibAll.dsc new file mode 100644 index 0000000000..8879bf3737 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Platform/EdkIIGlueLibAll.dsc @@ -0,0 +1,54 @@ +#/*++ +# Copyright (c) 2006, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +#--*/ +# +# EdkII Glue Library +# +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BaseLib\BaseLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BaseMemoryLib\BaseMemoryLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePrintLib\BasePrintLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BaseDebugLibNull\BaseDebugLibNull.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BaseIoLibIntrinsic\BaseIoLibIntrinsic.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\UefiBootServicesTableLib\UefiBootServicesTableLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\DxeIoLibCpuIo\DxeIoLibCpuIo.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePostCodeLibPort80\BasePostCodeLibPort80.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePostCodeLibDebug\BasePostCodeLibDebug.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BaseCacheMaintenanceLib\BaseCacheMaintenanceLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePciCf8Lib\BasePciCf8Lib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePciExpressLib\BasePciExpressLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePciLibCf8\BasePciLibCf8.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePciLibPciExpress\BasePciLibPciExpress.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePeCoffGetEntryPointLib\BasePeCoffGetEntryPointLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BasePeCoffLib\BasePeCoffLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BaseTimerLibLocalApic\BaseTimerLibLocalApic.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\BaseUefiDecompressLib\BaseUefiDecompressLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiDxeDebugLibReportStatusCode\PeiDxeDebugLibReportStatusCode.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiDxePostCodeLibReportStatusCode\PeiDxePostCodeLibReportStatusCode.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\DxeMemoryAllocationLib\DxeMemoryAllocationLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\UefiLib\UefiLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\DxeHobLib\DxeHobLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\UefiRuntimeServicesTableLib\UefiRuntimeServicesTableLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\DxeReportStatusCodeLib\DxeReportStatusCodeLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\HiiLib\HiiLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiServicesTablePointerLibMm7\PeiServicesTablePointerLibMm7.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiServicesTablePointerLibKr1\PeiServicesTablePointerLibKr1.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiServicesTablePointerLib\PeiServicesTablePointerLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiMemoryAllocationLib\PeiMemoryAllocationLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiServicesLib\PeiServicesLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiHobLib\PeiHobLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiReportStatusCodeLib\PeiReportStatusCodeLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiResourcePublicationLib\PeiResourcePublicationLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\UefiDevicePathLib\UefiDevicePathLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\UefiDriverModelLib\UefiDriverModelLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\DxeServicesTableLib\DxeServicesTableLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\EdkDxeSalLib\EdkDxeSalLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\EdkDxeRuntimeDriverLib\EdkDxeRuntimeDriverLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\DxeSmbusLib\DxeSmbusLib.inf +$(EDK_PREFIX)Foundation\Library\EdkIIGlueLib\Library\PeiSmbusLib\PeiSmbusLib.inf \ No newline at end of file diff --git a/EdkCompatibilityPkg/Sample/Platform/EdkLib32.dsc b/EdkCompatibilityPkg/Sample/Platform/EdkLib32.dsc new file mode 100644 index 0000000000..7be8ebbe80 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Platform/EdkLib32.dsc @@ -0,0 +1,36 @@ +#/*++ +# +# Copyright (c) 2004 - 2006, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#--*/ +# +# EDK Common Library for PEI usage (32bit) +# + +# +# Libraries common to PEI and DXE +# +$(EDK_PREFIX)Foundation\Efi\Guid\EfiGuidLib.inf +$(EDK_PREFIX)Foundation\Framework\Guid\EdkFrameworkGuidLib.inf +$(EDK_PREFIX)Foundation\Guid\EdkGuidLib.inf +$(EDK_PREFIX)Foundation\Library\EfiCommonLib\EfiCommonLib.inf +$(EDK_PREFIX)Foundation\Cpu\Pentium\CpuIA32Lib\CpuIA32Lib.inf +$(EDK_PREFIX)Foundation\Cpu\Itanium\CpuIA64Lib\CpuIA64Lib.inf +$(EDK_PREFIX)Foundation\Library\CustomizedDecompress\CustomizedDecompress.inf +$(EDK_PREFIX)Foundation\Library\CompilerStub\CompilerStubLib.inf +$(EDK_PREFIX)Foundation\Library\Dxe\Hob\HobLib.inf + +# +# PEI libraries +# +$(EDK_PREFIX)Foundation\Framework\Ppi\EdkFrameworkPpiLib.inf +$(EDK_PREFIX)Foundation\Ppi\EdkPpiLib.inf +$(EDK_PREFIX)Foundation\Library\Pei\PeiLib\PeiLib.inf +$(EDK_PREFIX)Foundation\Library\Pei\Hob\PeiHobLib.inf diff --git a/EdkCompatibilityPkg/Sample/Platform/EdkLibAll.dsc b/EdkCompatibilityPkg/Sample/Platform/EdkLibAll.dsc new file mode 100644 index 0000000000..346946f5ec --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Platform/EdkLibAll.dsc @@ -0,0 +1,63 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#--*/ +# +# EDK Common Library +# + +# +# Libraries common to PEI and DXE +# +$(EDK_PREFIX)Foundation\Efi\Guid\EfiGuidLib.inf +$(EDK_PREFIX)Foundation\Framework\Guid\EdkFrameworkGuidLib.inf +$(EDK_PREFIX)Foundation\Guid\EdkGuidLib.inf +$(EDK_PREFIX)Foundation\Library\EfiCommonLib\EfiCommonLib.inf +$(EDK_PREFIX)Foundation\Cpu\Pentium\CpuIA32Lib\CpuIA32Lib.inf +$(EDK_PREFIX)Foundation\Cpu\Itanium\CpuIA64Lib\CpuIA64Lib.inf +$(EDK_PREFIX)Foundation\Library\CustomizedDecompress\CustomizedDecompress.inf +$(EDK_PREFIX)Foundation\Library\CompilerStub\CompilerStubLib.inf +$(EDK_PREFIX)Foundation\Library\Dxe\Hob\HobLib.inf + +# +# PEI libraries +# +$(EDK_PREFIX)Foundation\Framework\Ppi\EdkFrameworkPpiLib.inf +$(EDK_PREFIX)Foundation\Ppi\EdkPpiLib.inf +$(EDK_PREFIX)Foundation\Library\Pei\PeiLib\PeiLib.inf +$(EDK_PREFIX)Foundation\Library\Pei\Hob\PeiHobLib.inf + +# +# DXE libraries +# +$(EDK_PREFIX)Foundation\Core\Dxe\ArchProtocol\ArchProtocolLib.inf +$(EDK_PREFIX)Foundation\Efi\Protocol\EfiProtocolLib.inf +$(EDK_PREFIX)Foundation\Framework\Protocol\EdkFrameworkProtocolLib.inf +$(EDK_PREFIX)Foundation\Protocol\EdkProtocolLib.inf +$(EDK_PREFIX)Foundation\Library\Dxe\EfiDriverLib\EfiDriverLib.inf +$(EDK_PREFIX)Foundation\Library\RuntimeDxe\EfiRuntimeLib\EfiRuntimeLib.inf +$(EDK_PREFIX)Foundation\Library\Dxe\Graphics\Graphics.inf +$(EDK_PREFIX)Foundation\Library\Dxe\EfiIfrSupportLib\EfiIfrSupportLib.inf +$(EDK_PREFIX)Foundation\Library\Dxe\Print\PrintLib.inf +$(EDK_PREFIX)Foundation\Library\Dxe\EfiScriptLib\EfiScriptLib.inf +$(EDK_PREFIX)Foundation\Library\Dxe\EfiUiLib\EfiUiLib.inf + +# +# Print/Graphics Library consume SetupBrowser Print Protocol +# +$(EDK_PREFIX)Foundation\Library\Dxe\PrintLite\PrintLib.inf +$(EDK_PREFIX)Foundation\Library\Dxe\GraphicsLite\Graphics.inf + +# +# Module Libraries +# +$(EDK_PREFIX)Sample\Platform\Generic\Dxe\GenericBds\GenericBds.inf +$(EDK_PREFIX)Sample\Bus\Usb\UsbLib\Dxe\UsbDxeLib.inf diff --git a/EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/EdkNt32ProtocolLib.inf b/EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/EdkNt32ProtocolLib.inf new file mode 100644 index 0000000000..1abff26c06 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/EdkNt32ProtocolLib.inf @@ -0,0 +1,46 @@ +#/*++ +# +# Copyright (c) 2004, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# EdkNt32ProtocolLib.inf +# +# Abstract: +# +# Component description file. +# +#--*/ + +[defines] +BASE_NAME= EdkNt32ProtocolLib +COMPONENT_TYPE= LIBRARY + +[includes.common] + $(EDK_SOURCE)\Sample\Platform\Nt32 + $(EDK_SOURCE)\Foundation\Efi + $(EDK_SOURCE)\Foundation\Include + $(EDK_SOURCE)\Foundation\Efi\Include + $(EDK_SOURCE)\Foundation\Framework\Include + $(EDK_SOURCE)\Foundation\Include\IndustryStandard + $(EDK_SOURCE)\Foundation\Include\Pei + $(EDK_SOURCE)\Foundation\Library\Pei\Include + $(EDK_SOURCE)\Foundation\Core\Dxe + $(EDK_SOURCE)\Foundation\Library\Dxe\Include + $(EDK_SOURCE)\Sample\Include + +[nmake.common] +C_STD_INCLUDE= + +[sources.common] + WinNtIo\WinNtIo.h + WinNtIo\WinNtIo.c + WinNtThunk\WinNtThunk.h + WinNtThunk\WinNtThunk.c diff --git a/EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtIo/WinNtIo.c b/EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtIo/WinNtIo.c new file mode 100644 index 0000000000..318ff33684 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtIo/WinNtIo.c @@ -0,0 +1,40 @@ +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + WinNtIo.c + +Abstract: + + This protocol allows an EFI driver (DLL) in the NT emulation envirnment + to make Win32 API calls. + +--*/ + +#include "EfiWinNt.h" +#include EFI_PROTOCOL_DEFINITION (WinNtIo) + +EFI_GUID gEfiWinNtIoProtocolGuid = EFI_WIN_NT_IO_PROTOCOL_GUID; + +EFI_GUID_STRING(&gEfiWinNtIoProtocolGuid, "EFI Win NT I/O Protocol", "Win32 API I/O protocol"); + +EFI_GUID gEfiWinNtVirtualDisksGuid = EFI_WIN_NT_VIRTUAL_DISKS_GUID; +EFI_GUID gEfiWinNtPhysicalDisksGuid = EFI_WIN_NT_PHYSICAL_DISKS_GUID; +EFI_GUID gEfiWinNtFileSystemGuid = EFI_WIN_NT_FILE_SYSTEM_GUID; +EFI_GUID gEfiWinNtSerialPortGuid = EFI_WIN_NT_SERIAL_PORT_GUID; +EFI_GUID gEfiWinNtUgaGuid = EFI_WIN_NT_UGA_GUID; +EFI_GUID gEfiWinNtGopGuid = EFI_WIN_NT_GOP_GUID; +EFI_GUID gEfiWinNtConsoleGuid = EFI_WIN_NT_CONSOLE_GUID; +EFI_GUID gEfiWinNtMemoryGuid = EFI_WIN_NT_MEMORY_GUID; +EFI_GUID gEfiWinNtCPUModelGuid = EFI_WIN_NT_CPU_MODEL_GUID; +EFI_GUID gEfiWinNtCPUSpeedGuid = EFI_WIN_NT_CPU_SPEED_GUID; +EFI_GUID gEfiWinNtPassThroughGuid = EFI_WIN_NT_PASS_THROUGH_GUID; diff --git a/EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtIo/WinNtIo.h b/EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtIo/WinNtIo.h new file mode 100644 index 0000000000..7da6099499 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtIo/WinNtIo.h @@ -0,0 +1,163 @@ +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + WinNtIo.h + +Abstract: + +--*/ + +#ifndef _WIN_NT_IO_H_ +#define _WIN_NT_IO_H_ + +#define EFI_WIN_NT_IO_PROTOCOL_GUID \ + { \ + 0x96eb4ad6, 0xa32a, 0x11d4, 0xbc, 0xfd, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \ + } + +// +// The following APIs require EfiWinNT.h. In some environmnets the GUID +// definitions are needed but the EfiWinNT.h is not included. +// EfiWinNT.h is needed to support WINDOWS API requirements. +// +#ifdef _EFI_WIN_NT_H_ + +#include EFI_PROTOCOL_DEFINITION (WinNtThunk) + +typedef struct { + EFI_WIN_NT_THUNK_PROTOCOL *WinNtThunk; + EFI_GUID *TypeGuid; + CHAR16 *EnvString; + UINT16 InstanceNumber; +} EFI_WIN_NT_IO_PROTOCOL; + +#endif + +extern EFI_GUID gEfiWinNtIoProtocolGuid; + +// +// The following GUIDs are used in EFI_WIN_NT_IO_PROTOCOL_GUID +// Device paths. They map 1:1 with NT envirnment variables. The variables +// define what virtual hardware the emulator/WinNtBusDriver will produce. +// +// +// EFI_WIN_NT_VIRTUAL_DISKS +// +#define EFI_WIN_NT_VIRTUAL_DISKS_GUID \ + { \ + 0xc95a928, 0xa006, 0x11d4, 0xbc, 0xfa, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \ + } + +extern EFI_GUID gEfiWinNtVirtualDisksGuid; + +// +// EFI_WIN_NT_PHYSICAL_DISKS +// +#define EFI_WIN_NT_PHYSICAL_DISKS_GUID \ + { \ + 0xc95a92f, 0xa006, 0x11d4, 0xbc, 0xfa, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \ + } + +extern EFI_GUID gEfiWinNtPhysicalDisksGuid; + +// +// EFI_WIN_NT_FILE_SYSTEM +// +#define EFI_WIN_NT_FILE_SYSTEM_GUID \ + { \ + 0xc95a935, 0xa006, 0x11d4, 0xbc, 0xfa, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \ + } + +extern EFI_GUID gEfiWinNtFileSystemGuid; + +// +// EFI_WIN_NT_SERIAL_PORT +// +#define EFI_WIN_NT_SERIAL_PORT_GUID \ + { \ + 0xc95a93d, 0xa006, 0x11d4, 0xbc, 0xfa, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \ + } + +extern EFI_GUID gEfiWinNtSerialPortGuid; + +// +// EFI_WIN_NT_UGA +// +#define EFI_WIN_NT_UGA_GUID \ + { \ + 0xab248e99, 0xabe1, 0x11d4, 0xbd, 0xd, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \ + } + +extern EFI_GUID gEfiWinNtUgaGuid; + +// +// EFI_WIN_NT_GOP +// +#define EFI_WIN_NT_GOP_GUID \ + { \ + 0x4e11e955, 0xccca, 0x11d4, 0xbd, 0xd, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \ + } + +extern EFI_GUID gEfiWinNtGopGuid; + +// +// EFI_WIN_NT_CONSOLE +// +#define EFI_WIN_NT_CONSOLE_GUID \ + { \ + 0xba73672c, 0xa5d3, 0x11d4, 0xbd, 0x0, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \ + } + +extern EFI_GUID gEfiWinNtConsoleGuid; + +// +// EFI_WIN_NT_MEMORY +// +#define EFI_WIN_NT_MEMORY_GUID \ + { \ + 0x99042912, 0x122a, 0x11d4, 0xbd, 0xd, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \ + } + +extern EFI_GUID gEfiWinNtMemoryGuid; + +// +// EFI_WIN_NT_CPU_MODEL +// +#define EFI_WIN_NT_CPU_MODEL_GUID \ + { \ + 0xbee9b6ce, 0x2f8a, 0x11d4, 0xbd, 0xd, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \ + } + +extern EFI_GUID gEfiWinNtCPUModelGuid; + +// +// EFI_WIN_NT_CPU_SPEED +// +#define EFI_WIN_NT_CPU_SPEED_GUID \ + { \ + 0xd4f29055, 0xe1fb, 0x11d4, 0xbd, 0xd, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \ + } + +extern EFI_GUID gEfiWinNtCPUSpeedGuid; + +// +// EFI_WIN_NT_PASS_THROUGH +// +#define EFI_WIN_NT_PASS_THROUGH_GUID \ + { \ + 0xcc664eb8, 0x3c24, 0x4086, 0xb6, 0xf6, 0x34, 0xe8, 0x56, 0xbc, 0xe3, 0x6e \ + } + +extern EFI_GUID gEfiWinNtPassThroughGuid; + +#endif diff --git a/EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtThunk/WinNtThunk.c b/EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtThunk/WinNtThunk.c new file mode 100644 index 0000000000..f0e827bb0e --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtThunk/WinNtThunk.c @@ -0,0 +1,28 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + WinNtThunk.c + +Abstract: + + This protocol allows an EFI driver (DLL) in the NT emulation envirnment + to make Win32 API calls. + +--*/ + +#include "Tiano.h" +#include EFI_PROTOCOL_DEFINITION (WinNtThunk) + +EFI_GUID gEfiWinNtThunkProtocolGuid = EFI_WIN_NT_THUNK_PROTOCOL_GUID; + +EFI_GUID_STRING(&gEfiWinNtThunkProtocolGuid, "EFI Win NT Thunk", "Win32 API thunk protocol"); diff --git a/EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtThunk/WinNtThunk.h b/EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtThunk/WinNtThunk.h new file mode 100644 index 0000000000..5ad6245682 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtThunk/WinNtThunk.h @@ -0,0 +1,1276 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + WinNtThunk.h + +Abstract: + + This protocol allows an EFI driver (DLL) in the NT emulation envirnment + to make Win32 API calls. + + NEVER make a Win32 call directly, always make the call via this protocol. + + There are no This pointers on the protocol member functions as they map + exactly into Win32 system calls. + + YOU MUST include EfiWinNT.h in place of Efi.h to make this file compile. + +--*/ + +#ifndef _WIN_NT_THUNK_H_ +#define _WIN_NT_THUNK_H_ + +#define EFI_WIN_NT_THUNK_PROTOCOL_GUID \ + { \ + 0x58c518b1, 0x76f3, 0x11d4, 0xbc, 0xea, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 \ + } + +// +// The following APIs require EfiWinNT.h. In some environmnets the GUID +// definitions are needed but the EfiWinNT.h is not included. +// EfiWinNT.h is needed to support WINDOWS API requirements. +// +#ifdef _EFI_WIN_NT_H_ + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtSleep) ( + DWORD Milliseconds + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtSuspendThread) ( + HANDLE hThread + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtGetCurrentThread) ( + VOID + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtGetCurrentThreadId) ( + VOID + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtGetCurrentProcess) ( + VOID + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtCreateThread) ( + LPSECURITY_ATTRIBUTES lpThreadAttributes, + DWORD dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, + LPVOID lpParameter, + DWORD dwCreationFlags, + LPDWORD lpThreadId + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtTerminateThread) ( + HANDLE hThread, + DWORD dwExitCode + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSendMessage) ( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam + ); + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtExitThread) ( + DWORD dwExitCode + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtResumeThread) ( + HANDLE hThread + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetThreadPriority) ( + HANDLE hThread, + INTN nPriority + ); + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtInitializeCriticalSection) ( + LPCRITICAL_SECTION lpCriticalSection + ); + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtDeleteCriticalSection) ( + LPCRITICAL_SECTION lpCriticalSection + ); + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtEnterCriticalSection) ( + LPCRITICAL_SECTION lpCriticalSection + ); + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtLeaveCriticalSection) ( + LPCRITICAL_SECTION lpCriticalSection + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtTlsAlloc) ( + VOID + ); + +typedef +WINBASEAPI +LPVOID +(WINAPI *WinNtTlsGetValue) ( + DWORD dwTlsIndex + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtTlsSetValue) ( + DWORD dwTlsIndex, + LPVOID lpTlsValue + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtTlsFree) ( + DWORD dwTlsIndex + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtCreateSemaphore) ( + LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, + LONG lInitialCount, + LONG lMaximumCount, + LPCWSTR lpName + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtWaitForSingleObject) ( + HANDLE hHandle, + DWORD dwMilliseconds + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtReleaseSemaphore) ( + HANDLE hSemaphore, + LONG lReleaseCount, + LPLONG lpPreviousCount + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtDuplicateHandle) ( + HANDLE hSourceProcessHandle, + HANDLE hSourceHandle, + HANDLE hTargetProcessHandle, + LPHANDLE lpTargetHandle, + DWORD dwDesiredAccess, + BOOL bInheritHandle, + DWORD dwOptions + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtCreateConsoleScreenBuffer) ( + DWORD DesiredAccess, + DWORD ShareMode, + CONST SECURITY_ATTRIBUTES *SecurityAttributes, + DWORD Flags, + LPVOID ScreenBufferData + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetConsoleScreenBufferSize) ( + HANDLE ConsoleOutput, + COORD Size + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetConsoleActiveScreenBuffer) ( + HANDLE ConsoleOutput + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtFillConsoleOutputAttribute) ( + HANDLE ConsoleOutput, + WORD Attribute, + DWORD Length, + COORD WriteCoord, + LPDWORD NumberOfAttrsWritten + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtFillConsoleOutputCharacter) ( + HANDLE ConsoleOutput, + TCHAR Character, + DWORD Length, + COORD WriteCoord, + LPDWORD NumberOfCharsWritten + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtWriteConsoleOutput) ( + HANDLE ConsoleOutput, + CONST CHAR_INFO *Buffer, + COORD BufferSize, + COORD BufferCoord, + PSMALL_RECT WriteRegion + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtScrollConsoleScreenBuffer) ( + HANDLE ConsoleOutput, + CONST SMALL_RECT *ScrollRectangle, + CONST SMALL_RECT *ClipRectangle, + COORD DestinationOrigin, + CONST CHAR_INFO *Fill + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetConsoleTitleW) ( + LPCTSTR ConsoleTitle + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtGetConsoleCursorInfo) ( + HANDLE ConsoleOutput, + PCONSOLE_CURSOR_INFO ConsoleCursorInfo + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetConsoleCursorInfo) ( + HANDLE ConsoleOutput, + CONST CONSOLE_CURSOR_INFO *ConsoleCursorInfo + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetPriorityClass) ( + HANDLE Process, + DWORD PriorityClass + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtWriteConsoleInput) ( + HANDLE ConsoleInput, + CONST INPUT_RECORD *Buffer, + DWORD Legnth, + LPDWORD NumberOfEventsWritten + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtGetNumberOfConsoleInputEvents) ( + HANDLE ConsoleInput, + LPDWORD NumberOfEvents + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtGetStdHandle) ( + DWORD StdHandle + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtReadConsoleInput) ( + HANDLE ConsoleInput, + PINPUT_RECORD Buffer, + DWORD Length, + LPDWORD NumberOfEventsRead + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtPeekConsoleInput) ( + HANDLE ConsoleInput, + PINPUT_RECORD Buffer, + DWORD Length, + LPDWORD NumberOfEventsRead + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetConsoleCursorPosition) ( + HANDLE ConsoleInput, + COORD CursorPosition + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtCreateFile) ( + LPCWSTR FileName, + DWORD DesiredAccess, + DWORD SharedMode, + LPSECURITY_ATTRIBUTES SecurityAttributes, + DWORD CreationDisposition, + DWORD FlagsAndAttributes, + HANDLE TemplateFile + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtDeviceIoControl) ( + HANDLE DeviceHandle, + DWORD IoControlCode, + LPVOID InBuffer, + DWORD InBufferSize, + LPVOID OutBuffer, + DWORD OutBufferSize, + LPDWORD BytesReturned, + LPOVERLAPPED Overlapped + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtCreateDirectory) ( + LPCWSTR PathName, + LPSECURITY_ATTRIBUTES SecurityAttributes + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtRemoveDirectory) ( + LPCWSTR PathName + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtGetFileAttributes) ( + LPCWSTR FileName + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetFileAttributes) ( + LPCWSTR FileName, + DWORD FileAttributes + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtCreateFileMapping) ( + HANDLE FileHandle, + LPSECURITY_ATTRIBUTES Attributes, + DWORD Protect, + DWORD MaximumSizeHigh, + DWORD MaximumSizeLow, + LPCTSTR Name + ); + +typedef +WINBASEAPI +LPVOID +(WINAPI *WinNtMapViewOfFileEx) ( + HANDLE FileHandle, + DWORD DesiredAccess, + DWORD FileOffsetHigh, + DWORD FileOffsetLow, + DWORD NumberOfBytesToMap, + LPVOID BaseAddress + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtGetEnvironmentVariable) ( + LPCTSTR Name, + LPTSTR Buffer, + DWORD Size + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtCloseHandle) ( + HANDLE Object + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtSetFilePointer) ( + HANDLE FileHandle, + LONG DistanceToMove, + PLONG DistanceToHoveHigh, + DWORD MoveMethod + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetEndOfFile) ( + HANDLE FileHandle + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtReadFile) ( + HANDLE FileHandle, + LPVOID Buffer, + DWORD NumberOfBytesToRead, + LPDWORD NumberOfBytesRead, + LPOVERLAPPED Overlapped + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtWriteFile) ( + HANDLE FileHandle, + LPCVOID Buffer, + DWORD NumberOfBytesToWrite, + LPDWORD NumberOfBytesWritten, + LPOVERLAPPED Overlapped + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtGetFileInformationByHandle) ( + HANDLE FileHandle, + BY_HANDLE_FILE_INFORMATION *FileInfo + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtGetDiskFreeSpace) ( + LPCTSTR RootPathName, + LPDWORD SectorsPerCluster, + LPDWORD BytesPerSector, + LPDWORD NumberOfFreeClusters, + LPDWORD TotalNumberOfClusters + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtGetDiskFreeSpaceEx) ( + LPCTSTR DirectoryName, + PULARGE_INTEGER FreeBytesAvailable, + PULARGE_INTEGER TotalNumberOfBytes, + PULARGE_INTEGER TotoalNumberOfFreeBytes + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtMoveFile) ( + LPCTSTR ExistingFileName, + LPCTSTR NewFileName + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetFileTime) ( + HANDLE FileHandle, + FILETIME *CreationTime, + FILETIME *LastAccessTime, + FILETIME *LastWriteTime + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSystemTimeToFileTime) ( + SYSTEMTIME * SystemTime, + FILETIME * FileTime + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtDeleteFile) ( + LPCTSTR FileName + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtFlushFileBuffers) ( + HANDLE + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtGetLastError) ( + VOID + ); + +typedef +WINBASEAPI +UINT +(WINAPI *WinNtSetErrorMode) ( + UINT Mode + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtGetTickCount) ( + VOID + ); + +typedef +WINBASEAPI +HMODULE +(WINAPI *WinNtLoadLibraryEx) ( + LPCTSTR LibFileName, + HANDLE FileHandle, + DWORD Flags + ); + +typedef +WINBASEAPI +FARPROC +(WINAPI *WinNtGetProcAddress) ( + HMODULE Module, + LPCSTR ProcName + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtGetTimeZoneInformation) ( + LPTIME_ZONE_INFORMATION timeZoneInformation + ); + +typedef +WINBASEAPI +MMRESULT +(WINAPI *WinNttimeSetEvent) ( + UINT uDelay, + UINT uResolution, + LPTIMECALLBACK lpTimeProc, + DWORD_PTR dwUser, + UINT fuEvent + ); + +typedef +WINBASEAPI +MMRESULT +(WINAPI *WinNttimeKillEvent) ( + UINT uTimerID + ); + +typedef +WINBASEAPI +DWORD +(WINAPI *WinNtSetTimeZoneInformation) ( + LPTIME_ZONE_INFORMATION timeZoneInformation + ); + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtGetSystemTime) ( + LPSYSTEMTIME SystemTime + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetSystemTime) ( + CONST SYSTEMTIME *SystemTime + ); + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtGetLocalTime) ( + LPSYSTEMTIME SystemTime + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetLocalTime) ( + CONST SYSTEMTIME *SystemTime + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtFileTimeToLocalFileTime) ( + CONST FILETIME *FileTime, + LPFILETIME LocalFileTime + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtFileTimeToSystemTime) ( + CONST FILETIME *FileTime, + LPSYSTEMTIME SystemTime + ); + +typedef +WINBASEAPI +HANDLE +(WINAPI *WinNtFindFirstFile) ( + LPCTSTR FileName, + LPWIN32_FIND_DATA FindFileData + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtFindNextFile) ( + HANDLE FindFile, + LPWIN32_FIND_DATA FindFileData + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtFindClose) ( + HANDLE FindFile + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtGetCommState) ( + HANDLE FileHandle, + LPDCB DCB + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetCommState) ( + HANDLE FileHandle, + LPDCB DCB + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetCommState) ( + HANDLE FileHandle, + LPDCB DCB + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtSetCommTimeouts) ( + HANDLE FileHandle, + LPCOMMTIMEOUTS CommTimeouts + ); + +typedef +WINBASEAPI +VOID +(WINAPI *WinNtExitProcess) ( + UINT uExitCode // exit code for all threads + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtPurgeComm) ( + HANDLE FileHandle, + DWORD Flags + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtEscapeCommFunction) ( + HANDLE FileHandle, + DWORD Func + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtGetCommModemStatus) ( + HANDLE FileHandle, + LPDWORD ModemStat + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtClearCommError) ( + HANDLE FileHandle, + LPDWORD Errors, + LPCOMSTAT Stat + ); + +typedef +WINUSERAPI +INT32 +(WINAPIV *WinNtSprintf) ( + LPWSTR Buffer, + LPCWSTR String, + ... + ); + +typedef +WINUSERAPI +HWND +(WINAPI *WinNtGetDesktopWindow) ( + VOID + ); + +typedef +WINUSERAPI +HWND +(WINAPI *WinNtGetForegroundWindow) ( + VOID + ); + +typedef +WINUSERAPI +HWND +(WINAPI *WinNtCreateWindowEx) ( + DWORD dwExStyle, + LPCTSTR lpClassName, + LPCTSTR lpWindowName, + DWORD dwStyle, + INT32 x, + INT32 y, + INT32 nWidth, + INT32 nHeight, + HWND hWndParent, + HMENU hMenu, + HINSTANCE hInstance, + LPVOID *lpParam + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtUpdateWindow) ( + HWND hWnd + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtShowWindow) ( + HWND hWnd, + INT32 nCmdShow + ); + +typedef +WINGDIAPI +BOOL +(WINAPI *WinNtDestroyWindow) ( + HWND hWnd + ); + +typedef +WINUSERAPI +HDC +(WINAPI *WinNtGetWindowDC) ( + HWND hWnd + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtGetClientRect) ( + HWND hWnd, + LPRECT lpRect + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtAdjustWindowRect) ( + LPRECT lpRect, + DWORD dwStyle, + BOOL bMenu + ); + +typedef +WINGDIAPI +INT32 +(WINAPI *WinNtSetDIBitsToDevice) ( + HDC, + INT32, + INT32, + DWORD, + DWORD, + INT32, + INT32, + UINT, + UINT, + CONST VOID *, + CONST BITMAPINFO *, + UINT + ); + +typedef +WINGDIAPI +BOOL +(WINAPI *WinNtBitBlt) ( + HDC, + INT32, + INT32, + INT32, + INT32, + HDC, + INT32, + INT32, + DWORD + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtInvalidateRect) ( + HWND hWnd, + CONST RECT *lpRect, + BOOL bErase + ); + +typedef +WINUSERAPI +HDC +(WINAPI *WinNtGetDC) ( + HWND hWnd + ); + +typedef +WINUSERAPI +INT32 +(WINAPI *WinNtReleaseDC) ( + HWND hWnd, + HDC hDC + ); + +typedef +WINUSERAPI +ATOM +(WINAPI *WinNtRegisterClassEx) ( + CONST WNDCLASSEX * + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtUnregisterClass) ( + LPCTSTR lpClassName, + HINSTANCE hInstance + ); + +typedef +WINUSERAPI +HDC +(WINAPI *WinNtBeginPaint) ( + HWND hWnd, + LPPAINTSTRUCT lpPaint + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtEndPaint) ( + HWND hWnd, + CONST PAINTSTRUCT *lpPaint + ); + +typedef +WINUSERAPI +VOID +(WINAPI *WinNtPostQuitMessage) ( + INT32 nExitCode + ); + +typedef +WINUSERAPI +LRESULT +(WINAPI *WinNtDefWindowProc) ( + HWND hWnd, + UINT Msg, + WPARAM wParam, + LPARAM lParam + ); + +typedef +WINUSERAPI +HICON +(WINAPI *WinNtLoadIcon) ( + HINSTANCE hInstance, + LPCTSTR lpIconName + ); + +typedef +WINUSERAPI +HCURSOR +(WINAPI *WinNtLoadCursor) ( + HINSTANCE hInstance, + LPCTSTR lpCursorName + ); + +typedef +WINGDIAPI +HGDIOBJ +(WINAPI *WinNtGetStockObject) ( + INT32 + ); + +typedef +WINGDIAPI +BOOL +(WINAPI *WinNtSetViewportOrgEx) ( + HDC, + INT32, + INT32, + LPPOINT + ); + +typedef +WINGDIAPI +BOOL +(WINAPI *WinNtSetWindowOrgEx) ( + HDC, + INT32, + INT32, + LPPOINT + ); +typedef +WINGDIAPI +BOOL +(WINAPI *WinNtMoveWindow) ( + HWND, + INT32, + INT32, + INT32, + INT32, + BOOL + ); + +typedef +WINGDIAPI +BOOL +(WINAPI *WinNtGetWindowRect) ( + HWND, + LPRECT + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtGetMessage) ( + LPMSG lpMsg, + HWND hWnd, + UINT wMsgFilterMin, + UINT wMsgFilterMax + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtTranslateMessage) ( + CONST MSG *lpMsg + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtDispatchMessage) ( + CONST MSG *lpMsg + ); + +typedef +WINUSERAPI +HANDLE +(WINAPI *WinNtGetProcessHeap) (); + +typedef +WINUSERAPI +LPVOID +(WINAPI *WinNtHeapAlloc) ( + HANDLE hHeap, + DWORD dwFlags, + SIZE_T dwBytes + ); + +typedef +WINUSERAPI +BOOL +(WINAPI *WinNtHeapFree) ( + HANDLE hHeap, + DWORD dwFlags, + LPVOID lpMem + ); + +typedef +WINBASEAPI +BOOL +(WINAPI *WinNtFreeLibrary) ( + HANDLE ModHandle + ); +// +// +// +EFI_FORWARD_DECLARATION (EFI_WIN_NT_THUNK_PROTOCOL); + +#define EFI_WIN_NT_THUNK_PROTOCOL_SIGNATURE EFI_SIGNATURE_32 ('N', 'T', 'T', 'T') + +typedef struct _EFI_WIN_NT_THUNK_PROTOCOL { + UINT64 Signature; + + // + // Win32 Process APIs + // + WinNtGetProcAddress GetProcAddress; + WinNtGetTickCount GetTickCount; + WinNtLoadLibraryEx LoadLibraryEx; + WinNtFreeLibrary FreeLibrary; + + WinNtSetPriorityClass SetPriorityClass; + WinNtSetThreadPriority SetThreadPriority; + WinNtSleep Sleep; + + WinNtSuspendThread SuspendThread; + WinNtGetCurrentThread GetCurrentThread; + WinNtGetCurrentThreadId GetCurrentThreadId; + WinNtGetCurrentProcess GetCurrentProcess; + WinNtCreateThread CreateThread; + WinNtTerminateThread TerminateThread; + WinNtSendMessage SendMessage; + WinNtExitThread ExitThread; + WinNtResumeThread ResumeThread; + WinNtDuplicateHandle DuplicateHandle; + + // + // Wint32 Mutex primitive + // + WinNtInitializeCriticalSection InitializeCriticalSection; + WinNtEnterCriticalSection EnterCriticalSection; + WinNtLeaveCriticalSection LeaveCriticalSection; + WinNtDeleteCriticalSection DeleteCriticalSection; + WinNtTlsAlloc TlsAlloc; + WinNtTlsFree TlsFree; + WinNtTlsSetValue TlsSetValue; + WinNtTlsGetValue TlsGetValue; + WinNtCreateSemaphore CreateSemaphore; + WinNtWaitForSingleObject WaitForSingleObject; + WinNtReleaseSemaphore ReleaseSemaphore; + + // + // Win32 Console APIs + // + WinNtCreateConsoleScreenBuffer CreateConsoleScreenBuffer; + WinNtFillConsoleOutputAttribute FillConsoleOutputAttribute; + WinNtFillConsoleOutputCharacter FillConsoleOutputCharacter; + WinNtGetConsoleCursorInfo GetConsoleCursorInfo; + WinNtGetNumberOfConsoleInputEvents GetNumberOfConsoleInputEvents; + WinNtPeekConsoleInput PeekConsoleInput; + WinNtScrollConsoleScreenBuffer ScrollConsoleScreenBuffer; + WinNtReadConsoleInput ReadConsoleInput; + + WinNtSetConsoleActiveScreenBuffer SetConsoleActiveScreenBuffer; + WinNtSetConsoleCursorInfo SetConsoleCursorInfo; + WinNtSetConsoleCursorPosition SetConsoleCursorPosition; + WinNtSetConsoleScreenBufferSize SetConsoleScreenBufferSize; + WinNtSetConsoleTitleW SetConsoleTitleW; + WinNtWriteConsoleInput WriteConsoleInput; + WinNtWriteConsoleOutput WriteConsoleOutput; + + // + // Win32 File APIs + // + WinNtCreateFile CreateFile; + WinNtDeviceIoControl DeviceIoControl; + WinNtCreateDirectory CreateDirectory; + WinNtRemoveDirectory RemoveDirectory; + WinNtGetFileAttributes GetFileAttributes; + WinNtSetFileAttributes SetFileAttributes; + WinNtCreateFileMapping CreateFileMapping; + WinNtCloseHandle CloseHandle; + WinNtDeleteFile DeleteFile; + WinNtFindFirstFile FindFirstFile; + WinNtFindNextFile FindNextFile; + WinNtFindClose FindClose; + WinNtFlushFileBuffers FlushFileBuffers; + WinNtGetEnvironmentVariable GetEnvironmentVariable; + WinNtGetLastError GetLastError; + WinNtSetErrorMode SetErrorMode; + WinNtGetStdHandle GetStdHandle; + WinNtMapViewOfFileEx MapViewOfFileEx; + WinNtReadFile ReadFile; + WinNtSetEndOfFile SetEndOfFile; + WinNtSetFilePointer SetFilePointer; + WinNtWriteFile WriteFile; + WinNtGetFileInformationByHandle GetFileInformationByHandle; + WinNtGetDiskFreeSpace GetDiskFreeSpace; + WinNtGetDiskFreeSpaceEx GetDiskFreeSpaceEx; + WinNtMoveFile MoveFile; + WinNtSetFileTime SetFileTime; + WinNtSystemTimeToFileTime SystemTimeToFileTime; + + // + // Win32 Time APIs + // + WinNtFileTimeToLocalFileTime FileTimeToLocalFileTime; + WinNtFileTimeToSystemTime FileTimeToSystemTime; + WinNtGetSystemTime GetSystemTime; + WinNtSetSystemTime SetSystemTime; + WinNtGetLocalTime GetLocalTime; + WinNtSetLocalTime SetLocalTime; + WinNtGetTimeZoneInformation GetTimeZoneInformation; + WinNtSetTimeZoneInformation SetTimeZoneInformation; + WinNttimeSetEvent timeSetEvent; + WinNttimeKillEvent timeKillEvent; + + // + // Win32 Serial APIs + // + WinNtClearCommError ClearCommError; + WinNtEscapeCommFunction EscapeCommFunction; + WinNtGetCommModemStatus GetCommModemStatus; + WinNtGetCommState GetCommState; + WinNtSetCommState SetCommState; + WinNtPurgeComm PurgeComm; + WinNtSetCommTimeouts SetCommTimeouts; + + WinNtExitProcess ExitProcess; + + WinNtSprintf SPrintf; + + WinNtGetDesktopWindow GetDesktopWindow; + WinNtGetForegroundWindow GetForegroundWindow; + WinNtCreateWindowEx CreateWindowEx; + WinNtShowWindow ShowWindow; + WinNtUpdateWindow UpdateWindow; + WinNtDestroyWindow DestroyWindow; + WinNtInvalidateRect InvalidateRect; + WinNtGetWindowDC GetWindowDC; + WinNtGetClientRect GetClientRect; + WinNtAdjustWindowRect AdjustWindowRect; + WinNtSetDIBitsToDevice SetDIBitsToDevice; + WinNtBitBlt BitBlt; + WinNtGetDC GetDC; + WinNtReleaseDC ReleaseDC; + WinNtRegisterClassEx RegisterClassEx; + WinNtUnregisterClass UnregisterClass; + + WinNtBeginPaint BeginPaint; + WinNtEndPaint EndPaint; + WinNtPostQuitMessage PostQuitMessage; + WinNtDefWindowProc DefWindowProc; + WinNtLoadIcon LoadIcon; + WinNtLoadCursor LoadCursor; + WinNtGetStockObject GetStockObject; + WinNtSetViewportOrgEx SetViewportOrgEx; + WinNtSetWindowOrgEx SetWindowOrgEx; + WinNtMoveWindow MoveWindow; + WinNtGetWindowRect GetWindowRect; + + WinNtGetMessage GetMessage; + WinNtTranslateMessage TranslateMessage; + WinNtDispatchMessage DispatchMessage; + + WinNtGetProcessHeap GetProcessHeap; + WinNtHeapAlloc HeapAlloc; + WinNtHeapFree HeapFree; + +} EFI_WIN_NT_THUNK_PROTOCOL; + +#endif + +extern EFI_GUID gEfiWinNtThunkProtocolGuid; + +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/Makefile new file mode 100644 index 0000000000..b067e85619 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/Makefile @@ -0,0 +1,97 @@ +#/*++ +# +# Copyright (c) 2006 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Makefile +# +# Abstract: +# +# makefile for building the BootsectImage utility. +# +#--*/ + +# +# Make sure environmental variable EDK_SOURCE is set +# +!IFNDEF EDK_SOURCE +!ERROR EDK_SOURCE environmental variable not set +!ENDIF + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Define some macros we use here. Should get rid of them someday and +# get rid of the extra level of indirection. +# +COMMON_SOURCE = $(EDK_TOOLS_COMMON) + +# +# Common information +# + +INC=$(INC) + +# +# Target specific information +# + +TARGET_NAME=BootsectImage +TARGET_SOURCE_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) + +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).exe + +TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\BootsectImage.c" +TARGET_EXE_INCLUDE = "$(TARGET_SOURCE_DIR)\fat.h" \ + "$(TARGET_SOURCE_DIR)\mbr.h" \ + + +# +# Build targets +# + +all: $(TARGET_EXE) + +# +# Build EXE +# + +$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE) + $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE): $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(EDK_TOOLS_OUTPUT)\Common.lib + $(LINK) $(MSVS_LINK_LIBPATHS) $(EDK_TOOLS_OUTPUT)\Common.lib $(L_FLAGS) /out:$(TARGET_EXE) $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL + diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/bootsectimage.c b/EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/bootsectimage.c new file mode 100644 index 0000000000..d71a03df0b --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/bootsectimage.c @@ -0,0 +1,881 @@ +/*++ + +Copyright 2006 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + bootsectimage.c + +Abstract: + Patch the BPB information in boot sector image file. + Patch the MBR code in MBR image file. + +--*/ + + +#include +#include +#include "fat.h" +#include "mbr.h" +#include "EfiUtilityMsgs.h" + +#define DEBUG_WARN 0x1 +#define DEBUG_ERROR 0x2 +int WriteToFile ( + void *BootSector, + char *FileName + ) +/*++ +Routine Description: + Write 512 bytes boot sector to file. + +Arguments: + BootSector - point to a buffer containing 512 bytes boot sector to write + FileName - file to write to + +Return: + int - number of bytes wrote, + 512 indicates write successful + 0 indicates write failure +--*/ +{ + FILE *FileHandle; + int result; + + FileHandle = fopen (FileName, "r+b"); + if (FileHandle == NULL) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "Open file: %s", FileName); + return 0; + } + fseek (FileHandle, 0, SEEK_SET); + + result = fwrite (BootSector, 1, 512, FileHandle); + if (result != 512) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "Write file: %s", FileName); + result = 0; + } + + fclose (FileHandle); + return result; +} + +int ReadFromFile ( + void *BootSector, + char *FileName + ) +/*++ +Routine Description: + Read first 512 bytes from file. + +Arguments: + BootSector - point to a buffer receiving the first 512 bytes data from file + FileName - file to read from + +Return: + int - number of bytes read, + 512 indicates read successful + 0 indicates read failure +--*/ +{ + FILE *FileHandle; + int result; + + FileHandle = fopen (FileName, "rb"); + if (FileHandle == NULL) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "Open file: %s", FileName); + return 0; + } + + result = fread (BootSector, 1, 512, FileHandle); + if (result != 512) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "Read file: %s", FileName); + result = 0; + } + + fclose (FileHandle); + return result; +} + +char * +FatTypeToString ( + IN FAT_TYPE FatType + ) +/*++ +Routine Description: + Convert enum type of FatType to string +--*/ +{ + switch (FatType) { + case FatTypeFat12: + return "FAT12"; + case FatTypeFat16: + return "FAT16"; + case FatTypeFat32: + return "FAT32"; + default: + break; + } + return "FAT Unknown"; +} + +FAT_TYPE +GetFatType ( + IN FAT_BPB_STRUCT *FatBpb + ) +/*++ +Routine Description: + Determine the FAT type according to BIOS Paramater Block (BPB) data + +Arguments: + FatBpb - BIOS Parameter Block (BPB) data, 512 Bytes + +Return: + FatTypeUnknown - Cannot determine the FAT type + FatTypeFat12 - FAT12 + FatTypeFat16 - FAT16 + FatTypeFat32 - FAT32 +--*/ +{ + FAT_TYPE FatType; + UINTN RootDirSectors; + UINTN FATSz; + UINTN TotSec; + UINTN DataSec; + UINTN CountOfClusters; + CHAR8 FilSysType[9]; + + FatType = FatTypeUnknown; + + // + // Simple check + // + if (FatBpb->Fat12_16.Signature != FAT_BS_SIGNATURE) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT: Signature Invalid - %04x, expected - %04x", + FatBpb->Fat12_16.Signature, FAT_BS_SIGNATURE); + return FatTypeUnknown; + } + + // + // Check according to FAT spec + // + if ((FatBpb->Fat12_16.BS_jmpBoot[0] != FAT_BS_JMP1) && + (FatBpb->Fat12_16.BS_jmpBoot[0] != FAT_BS_JMP2)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT: BS_jmpBoot - %02x, expected - %02x or %02x", + FatBpb->Fat12_16.BS_jmpBoot[0], FAT_BS_JMP1, FAT_BS_JMP2); + return FatTypeUnknown; + } + + if ((FatBpb->Fat12_16.BPB_BytsPerSec != 512) && + (FatBpb->Fat12_16.BPB_BytsPerSec != 1024) && + (FatBpb->Fat12_16.BPB_BytsPerSec != 2048) && + (FatBpb->Fat12_16.BPB_BytsPerSec != 4096)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT: BPB_BytsPerSec - %04x, expected - %04x, %04x, %04x, or %04x", + FatBpb->Fat12_16.BPB_BytsPerSec, 512, 1024, 2048, 4096); + return FatTypeUnknown; + } + if (FatBpb->Fat12_16.BPB_BytsPerSec != 512) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "FAT: BPB_BytsPerSec - %04x, expected - %04x", + FatBpb->Fat12_16.BPB_BytsPerSec, 512); + } + if ((FatBpb->Fat12_16.BPB_SecPerClus != 1) && + (FatBpb->Fat12_16.BPB_SecPerClus != 2) && + (FatBpb->Fat12_16.BPB_SecPerClus != 4) && + (FatBpb->Fat12_16.BPB_SecPerClus != 8) && + (FatBpb->Fat12_16.BPB_SecPerClus != 16) && + (FatBpb->Fat12_16.BPB_SecPerClus != 32) && + (FatBpb->Fat12_16.BPB_SecPerClus != 64) && + (FatBpb->Fat12_16.BPB_SecPerClus != 128)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT: BPB_SecPerClus - %02x, expected - %02x, %02x, %02x, %02x, %02x, %02x, %02x, or %02x", + FatBpb->Fat12_16.BPB_BytsPerSec, 1, 2, 4, 8, 16, 32, 64, 128); + return FatTypeUnknown; + } + if (FatBpb->Fat12_16.BPB_BytsPerSec * FatBpb->Fat12_16.BPB_SecPerClus > 32 * 1024) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT: BPB_BytsPerSec * BPB_SecPerClus - %08x, expected <= %08x", + FatBpb->Fat12_16.BPB_BytsPerSec * FatBpb->Fat12_16.BPB_SecPerClus, 32 * 1024); + return FatTypeUnknown; + } + if (FatBpb->Fat12_16.BPB_RsvdSecCnt == 0) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT: BPB_RsvdSecCnt - %04x, expected - Non-Zero", + FatBpb->Fat12_16.BPB_RsvdSecCnt); + return FatTypeUnknown; + } + if (FatBpb->Fat12_16.BPB_NumFATs != 2) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "FAT: BPB_NumFATs - %02x, expected - %02x", + FatBpb->Fat12_16.BPB_NumFATs, 2); + } + if ((FatBpb->Fat12_16.BPB_Media != 0xF0) && + (FatBpb->Fat12_16.BPB_Media != 0xF8) && + (FatBpb->Fat12_16.BPB_Media != 0xF9) && + (FatBpb->Fat12_16.BPB_Media != 0xFA) && + (FatBpb->Fat12_16.BPB_Media != 0xFB) && + (FatBpb->Fat12_16.BPB_Media != 0xFC) && + (FatBpb->Fat12_16.BPB_Media != 0xFD) && + (FatBpb->Fat12_16.BPB_Media != 0xFE) && + (FatBpb->Fat12_16.BPB_Media != 0xFF)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT: BPB_Media - %02x, expected - %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x, or %02x", + FatBpb->Fat12_16.BPB_Media, 0xF0, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF); + return FatTypeUnknown; + } + + // + // Algo in FAT spec + // + RootDirSectors = ((FatBpb->Fat12_16.BPB_RootEntCnt * sizeof(FAT_DIRECTORY_ENTRY)) + + (FatBpb->Fat12_16.BPB_BytsPerSec - 1)) / + FatBpb->Fat12_16.BPB_BytsPerSec; + + if (FatBpb->Fat12_16.BPB_FATSz16 != 0) { + FATSz = FatBpb->Fat12_16.BPB_FATSz16; + } else { + FATSz = FatBpb->Fat32.BPB_FATSz32; + } + if (FATSz == 0) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT: BPB_FATSz16, BPB_FATSz32 - 0, expected - Non-Zero"); + return FatTypeUnknown; + } + + if (FatBpb->Fat12_16.BPB_TotSec16 != 0) { + TotSec = FatBpb->Fat12_16.BPB_TotSec16; + } else { + TotSec = FatBpb->Fat12_16.BPB_TotSec32; + } + if (TotSec == 0) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT: BPB_TotSec16, BPB_TotSec32 - 0, expected - Non-Zero"); + return FatTypeUnknown; + } + + DataSec = TotSec - ( + FatBpb->Fat12_16.BPB_RsvdSecCnt + + FatBpb->Fat12_16.BPB_NumFATs * FATSz + + RootDirSectors + ); + + CountOfClusters = DataSec / FatBpb->Fat12_16.BPB_SecPerClus; + + if (CountOfClusters < FAT_MAX_FAT12_CLUSTER) { + FatType = FatTypeFat12; + } else if (CountOfClusters < FAT_MAX_FAT16_CLUSTER) { + FatType = FatTypeFat16; + } else { + FatType = FatTypeFat32; + } + // + // Check according to FAT spec + // + if (((FatType == FatTypeFat12) || (FatType == FatTypeFat16)) && + (FatBpb->Fat12_16.BPB_RsvdSecCnt != 1)) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "FAT12_16: BPB_RsvdSecCnt - %04x, expected - %04x", + FatBpb->Fat12_16.BPB_RsvdSecCnt, 1); + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat12_16.BPB_RsvdSecCnt != 32)) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "FAT32: BPB_RsvdSecCnt - %04x, expected - %04x", + FatBpb->Fat12_16.BPB_RsvdSecCnt, 32); + } + if ((FatType == FatTypeFat16) && + (FatBpb->Fat12_16.BPB_RootEntCnt != 512)) { + printf ("WARNING: FAT16: BPB_RootEntCnt - %04x, expected - %04x\n", + FatBpb->Fat12_16.BPB_RootEntCnt, 512); + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat12_16.BPB_RootEntCnt != 0)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT32: BPB_RootEntCnt - %04x, expected - %04x", + FatBpb->Fat12_16.BPB_RootEntCnt, 0); + return FatTypeUnknown; + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat12_16.BPB_TotSec16 != 0)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT32: BPB_TotSec16 - %04x, expected - %04x", + FatBpb->Fat12_16.BPB_TotSec16, 0); + return FatTypeUnknown; + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat12_16.BPB_FATSz16 != 0)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT32: BPB_FATSz16 - %04x, expected - %04x", + FatBpb->Fat12_16.BPB_FATSz16, 0); + return FatTypeUnknown; + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat12_16.BPB_TotSec32 == 0)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT32: BPB_TotSec32 - %04x, expected - Non-Zero", + FatBpb->Fat12_16.BPB_TotSec32); + return FatTypeUnknown; + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat32.BPB_FATSz32 == 0)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT32: BPB_FATSz32 - %08x, expected - Non-Zero", + FatBpb->Fat32.BPB_FATSz32); + return FatTypeUnknown; + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat32.BPB_FSVer != 0)) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "FAT32: BPB_FSVer - %08x, expected - %04x", + FatBpb->Fat32.BPB_FSVer, 0); + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat32.BPB_RootClus != 2)) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "FAT32: BPB_RootClus - %08x, expected - %04x", + FatBpb->Fat32.BPB_RootClus, 2); + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat32.BPB_FSInfo != 1)) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "FAT32: BPB_FSInfo - %08x, expected - %04x", + FatBpb->Fat32.BPB_FSInfo, 1); + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat32.BPB_BkBootSec != 6)) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "FAT32: BPB_BkBootSec - %08x, expected - %04x", + FatBpb->Fat32.BPB_BkBootSec, 6); + } + if ((FatType == FatTypeFat32) && + ((*(UINT32 *)FatBpb->Fat32.BPB_Reserved != 0) || + (*((UINT32 *)FatBpb->Fat32.BPB_Reserved + 1) != 0) || + (*((UINT32 *)FatBpb->Fat32.BPB_Reserved + 2) != 0))) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT32: BPB_Reserved - %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x, expected - 0", + FatBpb->Fat32.BPB_Reserved[0], + FatBpb->Fat32.BPB_Reserved[1], + FatBpb->Fat32.BPB_Reserved[2], + FatBpb->Fat32.BPB_Reserved[3], + FatBpb->Fat32.BPB_Reserved[4], + FatBpb->Fat32.BPB_Reserved[5], + FatBpb->Fat32.BPB_Reserved[6], + FatBpb->Fat32.BPB_Reserved[7], + FatBpb->Fat32.BPB_Reserved[8], + FatBpb->Fat32.BPB_Reserved[9], + FatBpb->Fat32.BPB_Reserved[10], + FatBpb->Fat32.BPB_Reserved[11]); + return FatTypeUnknown; + } + if (((FatType == FatTypeFat12) || (FatType == FatTypeFat16)) && + (FatBpb->Fat12_16.BS_Reserved1 != 0)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT12_16: BS_Reserved1 - %02x, expected - 0\n", + FatBpb->Fat12_16.BS_Reserved1); + return FatTypeUnknown; + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat32.BS_Reserved1 != 0)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT32: BS_Reserved1 - %02x, expected - 0\n", + FatBpb->Fat32.BS_Reserved1); + return FatTypeUnknown; + } + if (((FatType == FatTypeFat12) || (FatType == FatTypeFat16)) && + (FatBpb->Fat12_16.BS_BootSig != FAT_BS_BOOTSIG)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT12_16: BS_BootSig - %02x, expected - %02x\n", + FatBpb->Fat12_16.BS_BootSig, FAT_BS_BOOTSIG); + return FatTypeUnknown; + } + if ((FatType == FatTypeFat32) && + (FatBpb->Fat32.BS_BootSig != FAT_BS_BOOTSIG)) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT32: BS_BootSig - %02x, expected - %02x\n", + FatBpb->Fat32.BS_BootSig, FAT_BS_BOOTSIG); + return FatTypeUnknown; + } + + if ((FatType == FatTypeFat12) || (FatType == FatTypeFat16)) { + memcpy (FilSysType, FatBpb->Fat12_16.BS_FilSysType, 8); + FilSysType[8] = 0; + if ((FatType == FatTypeFat12) && + (strcmp (FilSysType, FAT12_FILSYSTYPE) != 0) && + (strcmp (FilSysType, FAT_FILSYSTYPE) != 0)) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "FAT12: BS_FilSysType - %s, expected - %s, or %s\n", + FilSysType, FAT12_FILSYSTYPE, FAT_FILSYSTYPE); + } + if ((FatType == FatTypeFat16) && + (strcmp (FilSysType, FAT16_FILSYSTYPE) != 0) && + (strcmp (FilSysType, FAT_FILSYSTYPE) != 0)) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "FAT16: BS_FilSysType - %s, expected - %s, or %s\n", + FilSysType, FAT16_FILSYSTYPE, FAT_FILSYSTYPE); + } + } + if (FatType == FatTypeFat32) { + memcpy (FilSysType, FatBpb->Fat32.BS_FilSysType, 8); + FilSysType[8] = 0; + if (strcmp (FilSysType, FAT32_FILSYSTYPE) != 0) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "FAT32: BS_FilSysType - %s, expected - %s\n", + FilSysType, FAT32_FILSYSTYPE); + } + } + + // + // pass all check, get FAT type + // + return FatType; +} + + +void +ParseBootSector ( + char *FileName + ) +{ + FAT_BPB_STRUCT FatBpb; + FAT_TYPE FatType; + + if (ReadFromFile ((void *)&FatBpb, FileName) == 0) { + return ; + } + + FatType = GetFatType (&FatBpb); + if (FatType <= FatTypeUnknown || FatType >= FatTypeMax) { + printf ("ERROR: Unknown Fat Type!\n"); + return; + } + + printf ("\nBoot Sector %s:\n", FatTypeToString (FatType)); + printf ("\n"); + printf (" Offset Title Data\n"); + printf ("==================================================================\n"); + printf (" 0 JMP instruction %02x %02x %02x\n", + FatBpb.Fat12_16.BS_jmpBoot[0], + FatBpb.Fat12_16.BS_jmpBoot[1], + FatBpb.Fat12_16.BS_jmpBoot[2]); + printf (" 3 OEM %c%c%c%c%c%c%c%c\n", + FatBpb.Fat12_16.BS_OEMName[0], + FatBpb.Fat12_16.BS_OEMName[1], + FatBpb.Fat12_16.BS_OEMName[2], + FatBpb.Fat12_16.BS_OEMName[3], + FatBpb.Fat12_16.BS_OEMName[4], + FatBpb.Fat12_16.BS_OEMName[5], + FatBpb.Fat12_16.BS_OEMName[6], + FatBpb.Fat12_16.BS_OEMName[7]); + printf ("\n"); + printf ("BIOS Parameter Block\n"); + printf (" B Bytes per sector %04x\n", FatBpb.Fat12_16.BPB_BytsPerSec); + printf (" D Sectors per cluster %02x\n", FatBpb.Fat12_16.BPB_SecPerClus); + printf (" E Reserved sectors %04x\n", FatBpb.Fat12_16.BPB_RsvdSecCnt); + printf (" 10 Number of FATs %02x\n", FatBpb.Fat12_16.BPB_NumFATs); + printf (" 11 Root entries %04x\n", FatBpb.Fat12_16.BPB_RootEntCnt); + printf (" 13 Sectors (under 32MB) %04x\n", FatBpb.Fat12_16.BPB_TotSec16); + printf (" 15 Media descriptor %02x\n", FatBpb.Fat12_16.BPB_Media); + printf (" 16 Sectors per FAT (small vol.) %04x\n", FatBpb.Fat12_16.BPB_FATSz16); + printf (" 18 Sectors per track %04x\n", FatBpb.Fat12_16.BPB_SecPerTrk); + printf (" 1A Heads %04x\n", FatBpb.Fat12_16.BPB_NumHeads); + printf (" 1C Hidden sectors %08x\n", FatBpb.Fat12_16.BPB_HiddSec); + printf (" 20 Sectors (over 32MB) %08x\n", FatBpb.Fat12_16.BPB_TotSec32); + printf ("\n"); + if (FatType != FatTypeFat32) { + printf (" 24 BIOS drive %02x\n", FatBpb.Fat12_16.BS_DrvNum); + printf (" 25 (Unused) %02x\n", FatBpb.Fat12_16.BS_Reserved1); + printf (" 26 Ext. boot signature %02x\n", FatBpb.Fat12_16.BS_BootSig); + printf (" 27 Volume serial number %08x\n", FatBpb.Fat12_16.BS_VolID); + printf (" 2B Volume lable %c%c%c%c%c%c%c%c%c%c%c\n", + FatBpb.Fat12_16.BS_VolLab[0], + FatBpb.Fat12_16.BS_VolLab[1], + FatBpb.Fat12_16.BS_VolLab[2], + FatBpb.Fat12_16.BS_VolLab[3], + FatBpb.Fat12_16.BS_VolLab[4], + FatBpb.Fat12_16.BS_VolLab[5], + FatBpb.Fat12_16.BS_VolLab[6], + FatBpb.Fat12_16.BS_VolLab[7], + FatBpb.Fat12_16.BS_VolLab[8], + FatBpb.Fat12_16.BS_VolLab[9], + FatBpb.Fat12_16.BS_VolLab[10]); + printf (" 36 File system %c%c%c%c%c%c%c%c\n", + FatBpb.Fat12_16.BS_FilSysType[0], + FatBpb.Fat12_16.BS_FilSysType[1], + FatBpb.Fat12_16.BS_FilSysType[2], + FatBpb.Fat12_16.BS_FilSysType[3], + FatBpb.Fat12_16.BS_FilSysType[4], + FatBpb.Fat12_16.BS_FilSysType[5], + FatBpb.Fat12_16.BS_FilSysType[6], + FatBpb.Fat12_16.BS_FilSysType[7]); + printf ("\n"); + } else { + printf ("FAT32 Section\n"); + printf (" 24 Sectors per FAT (large vol.) %08x\n", FatBpb.Fat32.BPB_FATSz32); + printf (" 28 Flags %04x\n", FatBpb.Fat32.BPB_ExtFlags); + printf (" 2A Version %04x\n", FatBpb.Fat32.BPB_FSVer); + printf (" 2C Root dir 1st cluster %08x\n", FatBpb.Fat32.BPB_RootClus); + printf (" 30 FSInfo sector %04x\n", FatBpb.Fat32.BPB_FSInfo); + printf (" 32 Backup boot sector %04x\n", FatBpb.Fat32.BPB_BkBootSec); + printf (" 34 (Reserved) %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", + FatBpb.Fat32.BPB_Reserved[0], + FatBpb.Fat32.BPB_Reserved[1], + FatBpb.Fat32.BPB_Reserved[2], + FatBpb.Fat32.BPB_Reserved[3], + FatBpb.Fat32.BPB_Reserved[4], + FatBpb.Fat32.BPB_Reserved[5], + FatBpb.Fat32.BPB_Reserved[6], + FatBpb.Fat32.BPB_Reserved[7], + FatBpb.Fat32.BPB_Reserved[8], + FatBpb.Fat32.BPB_Reserved[9], + FatBpb.Fat32.BPB_Reserved[10], + FatBpb.Fat32.BPB_Reserved[11]); + printf ("\n"); + printf (" 40 BIOS drive %02x\n", FatBpb.Fat32.BS_DrvNum); + printf (" 41 (Unused) %02x\n", FatBpb.Fat32.BS_Reserved1); + printf (" 42 Ext. boot signature %02x\n", FatBpb.Fat32.BS_BootSig); + printf (" 43 Volume serial number %08x\n", FatBpb.Fat32.BS_VolID); + printf (" 47 Volume lable %c%c%c%c%c%c%c%c%c%c%c\n", + FatBpb.Fat32.BS_VolLab[0], + FatBpb.Fat32.BS_VolLab[1], + FatBpb.Fat32.BS_VolLab[2], + FatBpb.Fat32.BS_VolLab[3], + FatBpb.Fat32.BS_VolLab[4], + FatBpb.Fat32.BS_VolLab[5], + FatBpb.Fat32.BS_VolLab[6], + FatBpb.Fat32.BS_VolLab[7], + FatBpb.Fat32.BS_VolLab[8], + FatBpb.Fat32.BS_VolLab[9], + FatBpb.Fat32.BS_VolLab[10]); + printf (" 52 File system %c%c%c%c%c%c%c%c\n", + FatBpb.Fat32.BS_FilSysType[0], + FatBpb.Fat32.BS_FilSysType[1], + FatBpb.Fat32.BS_FilSysType[2], + FatBpb.Fat32.BS_FilSysType[3], + FatBpb.Fat32.BS_FilSysType[4], + FatBpb.Fat32.BS_FilSysType[5], + FatBpb.Fat32.BS_FilSysType[6], + FatBpb.Fat32.BS_FilSysType[7]); + printf ("\n"); + } + printf (" 1FE Signature %04x\n", FatBpb.Fat12_16.Signature); + printf ("\n"); + + + return ; +} + +void +PatchBootSector ( + char *DestFileName, + char *SourceFileName, + BOOL ForcePatch + ) +/*++ +Routine Description: + Patch destination file according to the information from source file. + Only patch BPB data but leave boot code un-touched. + +Arguments: + DestFileName - Destination file to patch + SourceFileName - Source file where patch from +--*/ +{ + FAT_BPB_STRUCT DestFatBpb; + FAT_BPB_STRUCT SourceFatBpb; + FAT_TYPE DestFatType; + FAT_TYPE SourceFatType; + CHAR8 VolLab[11]; + CHAR8 FilSysType[8]; + + if (ReadFromFile ((void *)&DestFatBpb, DestFileName) == 0) { + return ; + } + if (ReadFromFile ((void *)&SourceFatBpb, SourceFileName) == 0) { + return ; + } + + DestFatType = GetFatType (&DestFatBpb); + SourceFatType = GetFatType (&SourceFatBpb); + + if (DestFatType != SourceFatType) { + // + // FAT type mismatch + // + if (ForcePatch) { + DebugMsg (NULL, 0, DEBUG_WARN, NULL, "FAT type mismatch: Dest - %s, Source - %s", + FatTypeToString(DestFatType), FatTypeToString(SourceFatType)); + } else { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "FAT type mismatch: Dest - %s, Source - %s", + FatTypeToString(DestFatType), FatTypeToString(SourceFatType)); + return ; + } + } + + if (SourceFatType <= FatTypeUnknown || SourceFatType >= FatTypeMax) { + DebugMsg (NULL, 0, DEBUG_ERROR, NULL, "Unknown Fat Type!\n"); + return; + } + + // + // Copy BPB/boot data (excluding BS_jmpBoot, BS_OEMName, BootCode and Signature) from SourceFatBpb to DestFatBpb + // + printf ("Patching %s BPB: ", FatTypeToString (SourceFatType)); + if (SourceFatType != FatTypeFat32) { + memcpy ( + &DestFatBpb.Fat12_16.BPB_BytsPerSec, + &SourceFatBpb.Fat12_16.BPB_BytsPerSec, + ((UINTN)&DestFatBpb.Fat12_16.Reserved - (UINTN)&DestFatBpb.Fat12_16.BPB_BytsPerSec) + ); + } else { + memcpy ( + &DestFatBpb.Fat32.BPB_BytsPerSec, + &SourceFatBpb.Fat32.BPB_BytsPerSec, + ((UINTN)&DestFatBpb.Fat32.Reserved - (UINTN)&DestFatBpb.Fat32.BPB_BytsPerSec) + ); + } + + // + // Set BS_VolLab and BS_FilSysType of DestFatBpb + // + // BS_VolLab BS_FilSysType + // FAT12: EFI FAT12 FAT12 + // FAT16: EFI FAT16 FAT16 + // FAT32: EFI FAT32 FAT32 + // + if (SourceFatType == FatTypeFat32) { + memcpy (VolLab, "EFI FAT32 ", sizeof(VolLab)); + memcpy (FilSysType, FAT32_FILSYSTYPE, sizeof(FilSysType)); + } else if (SourceFatType == FatTypeFat16) { + memcpy (VolLab, "EFI FAT16 ", sizeof(VolLab)); + memcpy (FilSysType, FAT16_FILSYSTYPE, sizeof(FilSysType)); + } else { + memcpy (VolLab, "EFI FAT12 ", sizeof(VolLab)); + memcpy (FilSysType, FAT12_FILSYSTYPE, sizeof(FilSysType)); + } + if (SourceFatType != FatTypeFat32) { + memcpy (DestFatBpb.Fat12_16.BS_VolLab, VolLab, sizeof(VolLab)); + memcpy (DestFatBpb.Fat12_16.BS_FilSysType, FilSysType, sizeof(FilSysType)); + } else { + memcpy (DestFatBpb.Fat32.BS_VolLab, VolLab, sizeof(VolLab)); + memcpy (DestFatBpb.Fat32.BS_FilSysType, FilSysType, sizeof(FilSysType)); + } + + // + // Set Signature of DestFatBpb to 55AA + // + DestFatBpb.Fat12_16.Signature = FAT_BS_SIGNATURE; + + // + // Write DestFatBpb + // + if (WriteToFile ((void *)&DestFatBpb, DestFileName)) { + printf ("successfully!\n"); + } else { + printf ("failed!\n"); + } + + return ; +} + +void +ParseMbr ( + char *FileName + ) +{ + MASTER_BOOT_RECORD Mbr; + + if (ReadFromFile ((void *)&Mbr, FileName) == 0) { + return ; + } + + printf ("\nMaster Boot Record:\n"); + printf ("\n"); + printf (" Offset Title Value\n"); + printf ("==================================================================\n"); + printf (" 0 Master bootstrap loader code (not list)\n"); + printf (" 1B8 Windows disk signature %08x\n", Mbr.UniqueMbrSignature); + printf ("\n"); + printf ("Partition Table Entry #1\n"); + printf (" 1BE 80 = active partition %02x\n", Mbr.PartitionRecord[0].BootIndicator); + printf (" 1BF Start head %02x\n", Mbr.PartitionRecord[0].StartHead); + printf (" 1C0 Start sector %02x\n", Mbr.PartitionRecord[0].StartSector); + printf (" 1C1 Start cylinder %02x\n", Mbr.PartitionRecord[0].StartTrack); + printf (" 1C2 Partition type indicator %02x\n", Mbr.PartitionRecord[0].OSType); + printf (" 1C3 End head %02x\n", Mbr.PartitionRecord[0].EndHead); + printf (" 1C4 End sector %02x\n", Mbr.PartitionRecord[0].EndSector); + printf (" 1C5 End cylinder %02x\n", Mbr.PartitionRecord[0].EndTrack); + printf (" 1C6 Sectors preceding partition %08x\n", Mbr.PartitionRecord[0].StartingLBA); + printf (" 1CA Sectors in partition %08x\n", Mbr.PartitionRecord[0].SizeInLBA); + printf ("\n"); + printf ("Partition Table Entry #2\n"); + printf (" 1CE 80 = active partition %02x\n", Mbr.PartitionRecord[1].BootIndicator); + printf (" 1CF Start head %02x\n", Mbr.PartitionRecord[1].StartHead); + printf (" 1D0 Start sector %02x\n", Mbr.PartitionRecord[1].StartSector); + printf (" 1D1 Start cylinder %02x\n", Mbr.PartitionRecord[1].StartTrack); + printf (" 1D2 Partition type indicator %02x\n", Mbr.PartitionRecord[1].OSType); + printf (" 1D3 End head %02x\n", Mbr.PartitionRecord[1].EndHead); + printf (" 1D4 End sector %02x\n", Mbr.PartitionRecord[1].EndSector); + printf (" 1D5 End cylinder %02x\n", Mbr.PartitionRecord[1].EndTrack); + printf (" 1D6 Sectors preceding partition %08x\n", Mbr.PartitionRecord[1].StartingLBA); + printf (" 1DA Sectors in partition %08x\n", Mbr.PartitionRecord[1].SizeInLBA); + printf ("\n"); + printf ("Partition Table Entry #3\n"); + printf (" 1DE 80 = active partition %02x\n", Mbr.PartitionRecord[2].BootIndicator); + printf (" 1DF Start head %02x\n", Mbr.PartitionRecord[2].StartHead); + printf (" 1E0 Start sector %02x\n", Mbr.PartitionRecord[2].StartSector); + printf (" 1E1 Start cylinder %02x\n", Mbr.PartitionRecord[2].StartTrack); + printf (" 1E2 Partition type indicator %02x\n", Mbr.PartitionRecord[2].OSType); + printf (" 1E3 End head %02x\n", Mbr.PartitionRecord[2].EndHead); + printf (" 1E4 End sector %02x\n", Mbr.PartitionRecord[2].EndSector); + printf (" 1E5 End cylinder %02x\n", Mbr.PartitionRecord[2].EndTrack); + printf (" 1E6 Sectors preceding partition %08x\n", Mbr.PartitionRecord[2].StartingLBA); + printf (" 1EA Sectors in partition %08x\n", Mbr.PartitionRecord[2].SizeInLBA); + printf ("\n"); + printf ("Partition Table Entry #4\n"); + printf (" 1EE 80 = active partition %02x\n", Mbr.PartitionRecord[3].BootIndicator); + printf (" 1EF Start head %02x\n", Mbr.PartitionRecord[3].StartHead); + printf (" 1F0 Start sector %02x\n", Mbr.PartitionRecord[3].StartSector); + printf (" 1F1 Start cylinder %02x\n", Mbr.PartitionRecord[3].StartTrack); + printf (" 1F2 Partition type indicator %02x\n", Mbr.PartitionRecord[3].OSType); + printf (" 1F3 End head %02x\n", Mbr.PartitionRecord[3].EndHead); + printf (" 1F4 End sector %02x\n", Mbr.PartitionRecord[3].EndSector); + printf (" 1F5 End cylinder %02x\n", Mbr.PartitionRecord[3].EndTrack); + printf (" 1F6 Sectors preceding partition %08x\n", Mbr.PartitionRecord[3].StartingLBA); + printf (" 1FA Sectors in partition %08x\n", Mbr.PartitionRecord[3].SizeInLBA); + printf ("\n"); + printf (" 1FE Signature %04x\n", Mbr.Signature); + printf ("\n"); + + return ; +} + +void +PatchMbr ( + char *DestFileName, + char *SourceFileName + ) +{ + MASTER_BOOT_RECORD DestMbr; + MASTER_BOOT_RECORD SourceMbr; + + if (ReadFromFile ((void *)&DestMbr, DestFileName) == 0) { + return ; + } + if (ReadFromFile ((void *)&SourceMbr, SourceFileName) == 0) { + return ; + } + + if (SourceMbr.Signature != MBR_SIGNATURE) { + printf ("ERROR: Invalid MBR!\n"); + return; + } + + printf ("Patching MBR:\n"); + memcpy ( + &DestMbr.PartitionRecord[0], + &SourceMbr.PartitionRecord[0], + sizeof(DestMbr.PartitionRecord) + ); + + DestMbr.Signature = MBR_SIGNATURE; + + + if (WriteToFile ((void *)&DestMbr, DestFileName)) { + printf ("\tsuccessfully!\n"); + } + + return ; +} + +void +PrintUsage ( + void + ) +{ + printf ( + "Usage:\n" + "bootsectimage [-m] [-v] -p SrcImage\n" + "bootsectimage [-m] [-v] [-f] -g SrcImage DstImage\n" + "where\n" + " -p: parse SrcImage\n" + " -g: get info from SrcImage, and patch to DstImage\n" + " -f: force patch even FAT type of SrcImage and DstImage mismatch\n" + " -m: process MBR instead of boot sector\n" + " -v: verbose\n" + ); +} + +int +main ( + int argc, + char *argv[] + ) +{ + char *SrcImage; + char *DstImage; + BOOL ForcePatch; // -f + BOOL ProcessMbr; // -m + BOOL DoParse; // -p SrcImage or -g SrcImage DstImage + BOOL Verbose; // -v + + SrcImage = DstImage = NULL; + ForcePatch = FALSE; + ProcessMbr = FALSE; + DoParse = TRUE; + Verbose = FALSE; + + SetUtilityName ("bootsectimage"); + + argc--; argv++; + + if (argc == 0) { + PrintUsage (); + return -1; + } + + while (argc != 0) { + if (strcmp (*argv, "-f") == 0) { + ForcePatch = TRUE; + } else if (strcmp (*argv, "-p") == 0) { + DoParse = TRUE; + argc--; argv++; + if (argc < 1) { + PrintUsage (); + return -1; + } + SrcImage = *argv; + } else if (strcmp (*argv, "-g") == 0) { + DoParse = FALSE; + argc--; argv++; + if (argc < 2) { + PrintUsage (); + return -1; + } + SrcImage = *argv; + argc--; argv++; + DstImage = *argv; + } else if (strcmp (*argv, "-m") == 0) { + ProcessMbr = TRUE; + } else if (strcmp (*argv, "-v") == 0) { + Verbose = TRUE; + } else { + PrintUsage (); + return -1; + } + + argc--; argv++; + } + + if (ForcePatch && DoParse) { + printf ("Cannot apply force(-f) to parse(-p)!\n"); + PrintUsage (); + return -1; + } + if (ForcePatch && !DoParse && ProcessMbr) { + printf ("Cannot apply force(-f) to processing MBR (-g -m)!\n"); + PrintUsage (); + return -1; + } + + if (Verbose) { + SetDebugMsgMask (DEBUG_WARN | DEBUG_ERROR); + } else { + SetDebugMsgMask (0); + } + + if (DoParse) { + if (ProcessMbr) { + ParseMbr (SrcImage); + } else { + ParseBootSector (SrcImage); + } + } else { + if (ProcessMbr) { + PatchMbr (DstImage, SrcImage); + } else { + PatchBootSector (DstImage, SrcImage, ForcePatch); + } + } + + return 0; +} + diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/fat.h b/EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/fat.h new file mode 100644 index 0000000000..330312688b --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/fat.h @@ -0,0 +1,158 @@ +/*++ + +Copyright 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + fat.h + +Abstract: + +Revision History + +--*/ + +#ifndef _FAT_BPB_H_ +#define _FAT_BPB_H_ + +#include "Tiano.h" + +#pragma pack(1) + +typedef struct { + // + // Fat common field + // + UINT8 BS_jmpBoot[3]; + CHAR8 BS_OEMName[8]; + UINT16 BPB_BytsPerSec; + UINT8 BPB_SecPerClus; + UINT16 BPB_RsvdSecCnt; + UINT8 BPB_NumFATs; + UINT16 BPB_RootEntCnt; + UINT16 BPB_TotSec16; + UINT8 BPB_Media; + UINT16 BPB_FATSz16; + UINT16 BPB_SecPerTrk; + UINT16 BPB_NumHeads; + UINT32 BPB_HiddSec; + UINT32 BPB_TotSec32; + + // + // Fat12/16 specific field + // + UINT8 BS_DrvNum; + UINT8 BS_Reserved1; + UINT8 BS_BootSig; + UINT32 BS_VolID; + CHAR8 BS_VolLab[11]; + CHAR8 BS_FilSysType[8]; + + // + // Boot Code and Data + // + UINT8 Reserved[448]; + + // + // Fat common signature - 0xAA55 + // + UINT16 Signature; +} FAT12_16_BPB_STRUCT; + +typedef struct { + // + // Fat common field + // + UINT8 BS_jmpBoot[3]; + CHAR8 BS_OEMName[8]; + UINT16 BPB_BytsPerSec; + UINT8 BPB_SecPerClus; + UINT16 BPB_RsvdSecCnt; + UINT8 BPB_NumFATs; + UINT16 BPB_RootEntCnt; + UINT16 BPB_TotSec16; + UINT8 BPB_Media; + UINT16 BPB_FATSz16; + UINT16 BPB_SecPerTrk; + UINT16 BPB_NumHeads; + UINT32 BPB_HiddSec; + UINT32 BPB_TotSec32; + + // + // Fat32 specific field + // + UINT32 BPB_FATSz32; + UINT16 BPB_ExtFlags; + UINT16 BPB_FSVer; + UINT32 BPB_RootClus; + UINT16 BPB_FSInfo; + UINT16 BPB_BkBootSec; + UINT8 BPB_Reserved[12]; + UINT8 BS_DrvNum; + UINT8 BS_Reserved1; + UINT8 BS_BootSig; + UINT32 BS_VolID; + CHAR8 BS_VolLab[11]; + CHAR8 BS_FilSysType[8]; + + // + // Boot Code and Data + // + UINT8 Reserved[420]; + + // + // Fat common signature - 0xAA55 + // + UINT16 Signature; +} FAT32_BPB_STRUCT; + +typedef union { + FAT12_16_BPB_STRUCT Fat12_16; + FAT32_BPB_STRUCT Fat32; +} FAT_BPB_STRUCT; + +typedef enum { + FatTypeUnknown, + FatTypeFat12, + FatTypeFat16, + FatTypeFat32, + FatTypeMax +} FAT_TYPE; + +typedef struct { + CHAR8 DIR_Name[11]; + UINT8 DIR_Attr; + UINT8 DIR_NTRes; + UINT8 DIR_CrtTimeTenth; + UINT16 DIR_CrtTime; + UINT16 DIR_CrtDate; + UINT16 DIR_LstAccDate; + UINT16 DIR_FstClusHI; + UINT16 DIR_WrtTime; + UINT16 DIR_WrtDate; + UINT16 DIR_FstClusLO; + UINT32 DIR_FileSize; +} FAT_DIRECTORY_ENTRY; + +#pragma pack() + +#define FAT_MAX_FAT12_CLUSTER 0xFF5 +#define FAT_MAX_FAT16_CLUSTER 0xFFF5 + +#define FAT_BS_SIGNATURE 0xAA55 +#define FAT_BS_BOOTSIG 0x29 +#define FAT_BS_JMP1 0xEB +#define FAT_BS_JMP2 0xE9 +#define FAT_FILSYSTYPE "FAT " +#define FAT12_FILSYSTYPE "FAT12 " +#define FAT16_FILSYSTYPE "FAT16 " +#define FAT32_FILSYSTYPE "FAT32 " + +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/mbr.h b/EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/mbr.h new file mode 100644 index 0000000000..5a95097dc1 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/mbr.h @@ -0,0 +1,64 @@ +/*++ + +Copyright 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + mbr.h + +Abstract: + +Revision History + +--*/ + +#ifndef _MBR_H_ +#define _MBR_H_ + +#include "Tiano.h" + +#pragma pack(1) + +#define MAX_MBR_PARTITIONS 4 + +// +// MBR Partition Entry +// +typedef struct { + UINT8 BootIndicator; + UINT8 StartHead; + UINT8 StartSector; + UINT8 StartTrack; + UINT8 OSType; + UINT8 EndHead; + UINT8 EndSector; + UINT8 EndTrack; + UINT32 StartingLBA; + UINT32 SizeInLBA; +} MBR_PARTITION_RECORD; + +// +// MBR Partition table +// +typedef struct { + UINT8 BootCode[440]; + UINT32 UniqueMbrSignature; + UINT16 Unknown; + MBR_PARTITION_RECORD PartitionRecord[MAX_MBR_PARTITIONS]; + UINT16 Signature; +} MASTER_BOOT_RECORD; + +#pragma pack() + +#define MBR_SIGNATURE 0xAA55 +#define EXTENDED_DOS_PARTITION 0x05 +#define EXTENDED_WINDOWS_PARTITION 0x0F + +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/Common/CommonLib.c b/EdkCompatibilityPkg/Sample/Tools/Source/Common/CommonLib.c new file mode 100644 index 0000000000..aa2a22edd1 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/CommonLib.c @@ -0,0 +1,497 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + CommonLib.c + +Abstract: + + Common Library Functions + +--*/ + +#include "TianoCommon.h" +#include "PeiHob.h" +#include +#include +#include +#include "CommonLib.h" + +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 (InputFileName, "rb"); + if (InputFile == NULL) { + printf ("ERROR: Could not open input file \"%s\".\n", InputFileName); + return EFI_ABORTED; + } + // + // Go to the end so that we can determine the file size + // + if (fseek (InputFile, 0, SEEK_END)) { + printf ("ERROR: System error reading input file \"%s\".\n", InputFileName); + fclose (InputFile); + return EFI_ABORTED; + } + // + // Get the file size + // + FileSize = ftell (InputFile); + if (FileSize == -1) { + printf ("ERROR: System error parsing input file \"%s\".\n", 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)) { + printf ("ERROR: System error reading input file \"%s\".\n", 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) { + printf ("ERROR: Reading file \"%s\"%i.\n", InputFileName); + fclose (InputFile); + free (*InputFileImage); + *InputFileImage = NULL; + return EFI_ABORTED; + } + // + // Close the file + // + fclose (InputFile); + + 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 UINT32 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) { + printf ("ERROR: PrintGuid called with a NULL value.\n"); + return EFI_INVALID_PARAMETER; + } + + printf ( + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x\n", + 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) { + printf ("ERROR: PrintGuidToBuffer() called with a NULL value\n"); + return EFI_INVALID_PARAMETER; + } + + if (BufferLen < PRINTED_GUID_BUFFER_SIZE) { + printf ("ERORR: PrintGuidToBuffer() called with invalid buffer size\n"); + return EFI_BUFFER_TOO_SMALL; + } + + if (Uppercase) { + sprintf ( + Buffer, + "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X", + 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 ( + Buffer, + "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + 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; +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/Common/CommonLib.h b/EdkCompatibilityPkg/Sample/Tools/Source/Common/CommonLib.h new file mode 100644 index 0000000000..f36856e5fb --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/CommonLib.h @@ -0,0 +1,120 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + CommonLib.h + +Abstract: + + Common library assistance routines. + +--*/ + +#ifndef _EFI_COMMON_LIB_H +#define _EFI_COMMON_LIB_H + +#include "TianoCommon.h" + +#define PRINTED_GUID_BUFFER_SIZE 37 // including null-termination +// +// 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 + ) +; + +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 + ) +; + +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/Common/Compress.h b/EdkCompatibilityPkg/Sample/Tools/Source/Common/Compress.h new file mode 100644 index 0000000000..43535936a6 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/Compress.h @@ -0,0 +1,90 @@ +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Compress.h + +Abstract: + + Header file for compression routine. + Providing both EFI and Tiano Compress algorithms. + +--*/ + +#ifndef _COMPRESS_H_ +#define _COMPRESS_H_ + +/*++ + +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/EdkCompatibilityPkg/Sample/Tools/Source/Common/Crc32.c b/EdkCompatibilityPkg/Sample/Tools/Source/Common/Crc32.c new file mode 100644 index 0000000000..6239ccc31e --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/Crc32.c @@ -0,0 +1,327 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + crc32.c + +Abstract: + + CalcuateCrc32 routine. + +--*/ + +#include +#include "TianoCommon.h" +#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 contaning 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/EdkCompatibilityPkg/Sample/Tools/Source/Common/Crc32.h b/EdkCompatibilityPkg/Sample/Tools/Source/Common/Crc32.h new file mode 100644 index 0000000000..51e98757a1 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/Crc32.h @@ -0,0 +1,51 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + crc32.h + +Abstract: + + Header file for CalcuateCrc32 routine + +--*/ + +#ifndef _CRC32_H +#define _CRC32_H +EFI_STATUS +CalculateCrc32 ( + IN UINT8 *Data, + IN UINTN DataSize, + IN OUT UINT32 *CrcOut + ) +; + +/*++ + +Routine Description: + + The CalculateCrc32 routine. + +Arguments: + + Data - The buffer contaning 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 \ No newline at end of file diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/Common/Decompress.c b/EdkCompatibilityPkg/Sample/Tools/Source/Common/Decompress.c new file mode 100644 index 0000000000..8afabae7d6 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/Decompress.c @@ -0,0 +1,995 @@ +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Decompress.c + +Abstract: + + Decompressor. Algorithm Ported from OPSD code (Decomp.asm) + +--*/ + +#include "TianoCommon.h" + + +// +// Decompression algorithm begins here +// +#define BITBUFSIZ 32 +#define MAXMATCH 256 +#define THRESHOLD 3 +#define CODE_BIT 16 +#define UINT8_MAX 0xff +#define BAD_TABLE - 1 + +// +// 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; + +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 + NumOfBits - The number of bits to shift and read. + +Returns: (VOID) + +--*/ +{ + Sd->mBitBuf = (UINT32) (Sd->mBitBuf << NumOfBits); + + while (NumOfBits > Sd->mBitCount) { + + Sd->mBitBuf |= (UINT32) (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; + + for (Index = 1; Index <= 16; Index++) { + Count[Index] = 0; + } + + for (Index = 0; Index < NumOfChar; Index++) { + 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 = (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)); + + for (Char = 0; Char < NumOfChar; Char++) { + + Len = BitLen[Char]; + if (Len == 0) { + continue; + } + + NextCode = (UINT16) (Start[Len] + Weight[Len]); + + if (Len <= TableBits) { + + 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; + + 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); +} + +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); + } + + 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 ; +} + +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, 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; +} + +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 + // + if (Sd->mOutBuf >= Sd->mOrigSize) { + return ; + } 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) { + Sd->mDstBase[Sd->mOutBuf++] = Sd->mDstBase[DataIdx++]; + if (Sd->mOutBuf >= Sd->mOrigSize) { + return ; + } + + BytesRemain--; + } + } + } + + return ; +} + +EFI_STATUS +GetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The internal implementation of *_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 successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + UINT8 *Src; + + *ScratchSize = sizeof (SCRATCH_DATA); + + Src = Source; + if (SrcSize < 8) { + return EFI_INVALID_PARAMETER; + } + + *DstSize = Src[4] + (Src[5] << 8) + (Src[6] << 16) + (Src[7] << 24); + 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, + IN UINT8 Version + ) +/*++ + +Routine Description: + + The internal implementation of *_DECOMPRESS_PROTOCOL.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. + 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_SUCCESS - Decompression is successfull + 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 compressed file size is 0, return + // + if (OrigSize == 0) { + return Status; + } + + if (SrcSize < CompSize + 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; + } + // + // 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: + // + // Currently, only have 2 versions + // + return EFI_INVALID_PARAMETER; + } + + 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 +EFIAPI +EfiGetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + This - The protocol instance pointer + 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 successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return GetInfo ( + Source, + SrcSize, + DstSize, + ScratchSize + ); +} + +EFI_STATUS +EFIAPI +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 is same as that of EFI_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + This - The protocol instance pointer + 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 successfull + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + // + // For EFI 1.1 de/compression algorithm, the version is 1. + // + return Decompress ( + Source, + SrcSize, + Destination, + DstSize, + Scratch, + ScratchSize, + 1 + ); +} + +EFI_STATUS +EFIAPI +TianoGetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + This - The protocol instance pointer + 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 successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + return GetInfo ( + Source, + SrcSize, + DstSize, + ScratchSize + ); +} + +EFI_STATUS +EFIAPI +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 is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + This - The protocol instance pointer + 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 successfull + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +{ + // + // For Tiano de/compression algorithm, the version is 2. + // + return Decompress ( + Source, + SrcSize, + Destination, + DstSize, + Scratch, + ScratchSize, + 2 + ); +} + diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/Common/Decompress.h b/EdkCompatibilityPkg/Sample/Tools/Source/Common/Decompress.h new file mode 100644 index 0000000000..515e7fdbed --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/Decompress.h @@ -0,0 +1,174 @@ +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Decompress.h + +Abstract: + + Header file for decompression routine. + Providing both EFI and Tiano decompress algorithms. + +--*/ + +#ifndef _DECOMPRESS_H_ +#define _DECOMPRESS_H_ + +EFI_STATUS +EFIAPI +EfiGetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The implementation is same as that of EFI_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + This - The protocol instance pointer + 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 successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +; + +EFI_STATUS +EFIAPI +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 is same as that of EFI_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + This - The protocol instance pointer + 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 successfull + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +; + +EFI_STATUS +EFIAPI +TianoGetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + + The implementation is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.GetInfo(). + +Arguments: + + This - The protocol instance pointer + 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 successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +; + +EFI_STATUS +EFIAPI +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 is same as that of EFI_TIANO_DECOMPRESS_PROTOCOL.Decompress(). + +Arguments: + + This - The protocol instance pointer + 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 successfull + 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 + ); + +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiCompress.c b/EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiCompress.c new file mode 100644 index 0000000000..6f2922ea3d --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiCompress.c @@ -0,0 +1,1600 @@ +/* + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + EfiCompress.c + +Abstract: + + 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. + +--*/ + +#include +#include +#include "TianoCommon.h" +#include "Compress.h" + + +// +// Macro Definitions +// + +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], mCTable[4096], 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 + +Argements: (VOID) + +Returns: + + EFI_SUCCESS - Memory is allocated successfully + EFI_OUT_OF_RESOURCES - Allocation fails + +--*/ +{ + UINT32 i; + + mText = malloc (WNDSIZ * 2 + MAXMATCH); + 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)); + + 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. Travese 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 + +Argments: + + 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/EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiCustomizedCompress.h b/EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiCustomizedCompress.h new file mode 100644 index 0000000000..b01f538f3d --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiCustomizedCompress.h @@ -0,0 +1,138 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + EfiCustomizedCompress.h + +Abstract: + + Header file for Customized compression routine + +--*/ + +#ifndef _EFICUSTOMIZEDCOMPRESS_H +#define _EFICUSTOMIZEDCOMPRESS_H +EFI_STATUS +SetCustomizedCompressionType ( + IN CHAR8 *Type + ) +; + +/*++ + +Routine Description: + +The implementation of Customized SetCompressionType(). + +Arguments: + Type - The type if compression. + +Returns: + + EFI_SUCCESS - The type has been set. + EFI_UNSUPPORTED - This type is unsupported. + + +--*/ +EFI_STATUS +CustomizedGetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +; + +/*++ + +Routine Description: + + The implementation of Customized 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 successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +EFI_STATUS +CustomizedDecompress ( + 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 Customized Decompress(). + +Arguments: + + This - The protocol instance pointer + 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 successfull + EFI_INVALID_PARAMETER - The source data is corrupted + +--*/ +EFI_STATUS +CustomizedCompress ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ) +; + +/*++ + +Routine Description: + + The Customized 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. + +--*/ + +#endif \ No newline at end of file diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiUtilityMsgs.c b/EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiUtilityMsgs.c new file mode 100644 index 0000000000..37705a84f1 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiUtilityMsgs.c @@ -0,0 +1,756 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + EfiUtilityMsgs.c + +Abstract: + + EFI tools utility functions to display warning, error, and informational + messages. + +--*/ + +#include +#include +#include +#include + +#include "Tiano.h" +#include "EfiUtilityMsgs.h" + +#define MAX_LINE_LEN 200 + +// +// Declare module globals for keeping track of the the utility's +// name and other settings. +// +static STATUS mStatus = STATUS_SUCCESS; +static INT8 mUtilityName[50] = { 0 }; +static UINT32 mDebugMsgMask = 0; +static INT8 *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 +PrintMessage ( + INT8 *Type, + INT8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + INT8 *Text, + INT8 *MsgFmt, + va_list List + ); + +static +void +PrintLimitExceeded ( + VOID + ); + +void +Error ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + INT8 *Text, + INT8 *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 + utilty 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); + // + // Set status accordingly + // + if (mStatus < STATUS_ERROR) { + mStatus = STATUS_ERROR; + } +} + +void +ParserError ( + UINT32 MessageCode, + INT8 *Text, + INT8 *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); + // + // Set status accordingly + // + if (mStatus < STATUS_ERROR) { + mStatus = STATUS_ERROR; + } +} + +void +ParserWarning ( + UINT32 ErrorCode, + INT8 *OffendingText, + INT8 *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); + // + // Set status accordingly + // + if (mStatus < STATUS_WARNING) { + mStatus = STATUS_WARNING; + } +} + +void +Warning ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + INT8 *Text, + INT8 *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; + // + // 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); + // + // Set status accordingly + // + if (mStatus < STATUS_WARNING) { + mStatus = STATUS_WARNING; + } +} + +void +DebugMsg ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 MsgMask, + INT8 *Text, + INT8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a warning 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) + + MsgMask - an application-specific bitmask that, in combination with mDebugMsgMask, + determines if the debug message gets printed. + + 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 mask is not applicable, then do nothing. + // + if ((MsgMask != 0) && ((mDebugMsgMask & MsgMask) == 0)) { + return ; + } + + va_start (List, MsgFmt); + PrintMessage ("debug", FileName, LineNumber, 0, Text, MsgFmt, List); + va_end (List); +} + +static +void +PrintMessage ( + INT8 *Type, + INT8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + INT8 *Text, + INT8 *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 preceed 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 + +--*/ +{ + INT8 Line[MAX_LINE_LEN]; + INT8 Line2[MAX_LINE_LEN]; + INT8 *Cptr; + // + // 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 if (mUtilityName[0] != 0) { + Cptr = mUtilityName; + } else { + Cptr = "Unknown utility"; + } + + strcpy (Line, Cptr); + if (LineNumber != 0) { + sprintf (Line2, "(%d)", LineNumber); + strcat (Line, Line2); + } + // + // Have to print an error code or Visual Studio won't find the + // message for you. It has to be decimal digits too. + // + sprintf (Line2, " : %s %c%04d", Type, toupper (Type[0]), MessageCode); + strcat (Line, Line2); + fprintf (stdout, "%s", Line); + // + // If offending text was provided, then print it + // + if (Text != NULL) { + fprintf (stdout, ": %s ", Text); + } + // + // Print formatted message if provided + // + if (MsgFmt != NULL) { + vsprintf (Line2, MsgFmt, List); + fprintf (stdout, ": %s", Line2); + } + + fprintf (stdout, "\n"); +} + +void +ParserSetPosition ( + INT8 *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 ( + INT8 *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 messags. + +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; + return ; + } else { + strcpy (mUtilityName, UtilityName); + } + } 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 +SetDebugMsgMask ( + UINT32 DebugMask + ) +/*++ + +Routine Description: + Set the debug printing mask. This is used by the DebugMsg() function + to determine when/if a debug message should be printed. + +Arguments: + DebugMask - bitmask, specific to the calling application + +Returns: + NA + +--*/ +{ + mDebugMsgMask = DebugMask; +} + +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 + ) +{ + char *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/EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiUtilityMsgs.h b/EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiUtilityMsgs.h new file mode 100644 index 0000000000..2da1fe58f6 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiUtilityMsgs.h @@ -0,0 +1,135 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + EfiUtilityMsgs.h + +Abstract: + + Defines and prototypes for common EFI utility error and debug messages. + +--*/ + +#ifndef _EFI_UTILITY_MSGS_H_ +#define _EFI_UTILITY_MSGS_H_ + +// +// 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; + +#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 ( + INT8 *ProgramName + ) +; + +void +Error ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 ErrorCode, + INT8 *OffendingText, + INT8 *MsgFmt, + ... + ) +; + +void +Warning ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 ErrorCode, + INT8 *OffendingText, + INT8 *MsgFmt, + ... + ) +; + +void +DebugMsg ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 MsgLevel, + INT8 *OffendingText, + INT8 *MsgFmt, + ... + ) +; + +void +SetDebugMsgMask ( + UINT32 MsgMask + ) +; + +void +ParserSetPosition ( + INT8 *SourceFileName, + UINT32 LineNum + ) +; + +void +ParserError ( + UINT32 ErrorCode, + INT8 *OffendingText, + INT8 *MsgFmt, + ... + ) +; + +void +ParserWarning ( + UINT32 ErrorCode, + INT8 *OffendingText, + INT8 *MsgFmt, + ... + ) +; + +void +SetPrintLimits ( + UINT32 NumErrors, + UINT32 NumWarnings, + UINT32 NumWarningsPlusErrors + ) +; + +#ifdef __cplusplus +} +#endif + +#endif // #ifndef _EFI_UTILITY_MSGS_H_ diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/Common/FvLib.c b/EdkCompatibilityPkg/Sample/Tools/Source/Common/FvLib.c new file mode 100644 index 0000000000..4b2bf81147 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/FvLib.c @@ -0,0 +1,786 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + FvLib.c + +Abstract: + + These functions assist in parsing and manipulating a Firmware Volume. + +--*/ + +// +// 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; + 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 + GetLength (CurrentFile->Size) > (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 + GetLength (CurrentFile->Size) > (UINTN) mFvHeader + mFvLength) + ) { + return EFI_INVALID_PARAMETER; + } + // + // Get next file, compensate for 8 byte alignment if necessary. + // + *NextFile = (EFI_FFS_FILE_HEADER *) (((UINTN) CurrentFile + GetLength (CurrentFile->Size) + 0x07) & (-1 << 3)); + + // + // Verify file is in this FV. + // + if (((UINTN) *NextFile + sizeof (EFI_FFS_FILE_HEADER) >= (UINTN) mFvHeader + mFvLength) || + ((UINTN) *NextFile + GetLength ((*NextFile)->Size) > (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; + + // + // 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; + } + // + // 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, 0, "error parsing the FV", NULL); + 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, 0, "error parsing the FV", NULL); + 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 Instace 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, 0, "error parsing FV", NULL); + 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, 0, "error parsing the FV", NULL); + return EFI_ABORTED; + } + } + + *File = NULL; + return EFI_SUCCESS; +} + +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. + The function will not handle encapsulating sections. + +Arguments: + + File The file to search. + SectionType Type of file to search for. + Instance Instace 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, 0, "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 + sizeof (EFI_FFS_FILE_HEADER)); + + // + // Loop as long as we have a valid file + // + while ((UINTN) CurrentSection.CommonHeader < (UINTN) File + GetLength (File->Size)) { + if (CurrentSection.CommonHeader->Type == SectionType) { + SectionCount++; + } + + if (SectionCount == Instance) { + *Section = CurrentSection; + return EFI_SUCCESS; + } + // + // Find next section (including compensating for alignment issues. + // + CurrentSection.CommonHeader = (EFI_COMMON_SECTION_HEADER *) ((((UINTN) CurrentSection.CommonHeader) + GetLength (CurrentSection.CommonHeader->Size) + 0x03) & (-1 << 2)); + } + // + // 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, 0, "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, 0, "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_HEADER BlankHeader; + UINT8 Checksum; + UINT32 FileLength; + UINT32 OccupiedFileLength; + UINT8 SavedChecksum; + UINT8 SavedState; + UINT8 FileGuidString[80]; + UINT32 TailSize; +#if (PI_SPECIFICATION_VERSION < 0x00010000) + EFI_FFS_FILE_TAIL *Tail; +#endif + + // + // 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; + } + // + // Check if we have free space + // + if (ErasePolarity) { + memset (&BlankHeader, -1, sizeof (EFI_FFS_FILE_HEADER)); + } else { + memset (&BlankHeader, 0, sizeof (EFI_FFS_FILE_HEADER)); + } + + if (memcmp (&BlankHeader, FfsHeader, sizeof (EFI_FFS_FILE_HEADER)) == 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); + if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + TailSize = sizeof (EFI_FFS_FILE_TAIL); + } else { + TailSize = 0; + } + // + // Verify file header checksum + // + SavedState = FfsHeader->State; + FfsHeader->State = 0; + SavedChecksum = FfsHeader->IntegrityCheck.Checksum.File; + FfsHeader->IntegrityCheck.Checksum.File = 0; + Checksum = CalculateSum8 ((UINT8 *) FfsHeader, sizeof (EFI_FFS_FILE_HEADER)); + FfsHeader->State = SavedState; + FfsHeader->IntegrityCheck.Checksum.File = SavedChecksum; + if (Checksum != 0) { + Error (NULL, 0, 0, FileGuidString, "invalid FFS file header checksum"); + return EFI_ABORTED; + } + // + // Verify file checksum + // + if (FfsHeader->Attributes & FFS_ATTRIB_CHECKSUM) { + // + // Verify file data checksum + // + FileLength = GetLength (FfsHeader->Size); + OccupiedFileLength = (FileLength + 0x07) & (-1 << 3); + Checksum = CalculateSum8 ((UINT8 *) FfsHeader, FileLength - TailSize); + Checksum = (UINT8) (Checksum - FfsHeader->State); + if (Checksum != 0) { + Error (NULL, 0, 0, FileGuidString, "invalid FFS file checksum"); + return EFI_ABORTED; + } + } else { + // + // File does not have a checksum + // Verify contents are 0x5A as spec'd + // + if (FfsHeader->IntegrityCheck.Checksum.File != FFS_FIXED_CHECKSUM) { + Error (NULL, 0, 0, FileGuidString, "invalid fixed FFS file header checksum"); + return EFI_ABORTED; + } + } +#if (PI_SPECIFICATION_VERSION < 0x00010000) + // + // Check if the tail is present and verify it if it is. + // + if (FfsHeader->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + // + // Verify tail is complement of integrity check field in the header. + // + Tail = (EFI_FFS_FILE_TAIL *) ((UINTN) FfsHeader + GetLength (FfsHeader->Size) - sizeof (EFI_FFS_FILE_TAIL)); + if (FfsHeader->IntegrityCheck.TailReference != (EFI_FFS_FILE_TAIL)~(*Tail)) { + Error (NULL, 0, 0, FileGuidString, "invalid FFS file tail"); + return EFI_ABORTED; + } + } +#endif + return EFI_SUCCESS; +} + +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_FVB_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/EdkCompatibilityPkg/Sample/Tools/Source/Common/FvLib.h b/EdkCompatibilityPkg/Sample/Tools/Source/Common/FvLib.h new file mode 100644 index 0000000000..4b7ef0a332 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/FvLib.h @@ -0,0 +1,177 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + FvLib.h + +Abstract: + + These functions assist in parsing and manipulating a Firmware Volume. + +--*/ + +#ifndef _EFI_FV_LIB_H +#define _EFI_FV_LIB_H + +// +// Include files +// +#include "TianoCommon.h" +#include "EfiFirmwareVolumeHeader.h" +#include "EfiFirmwareFileSystem.h" +#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 + ) +; + +/*++ + +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/EdkCompatibilityPkg/Sample/Tools/Source/Common/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/Common/Makefile new file mode 100644 index 0000000000..464d0e9930 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/Makefile @@ -0,0 +1,145 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: makefile +# +# Abstract: +# +# This file is used to build the EFI utility. +# +#--*/ + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Define some macros we use here. Should get rid of them someday and +# get rid of the extra level of indirection. +# +TARGET_NAME = Common +TARGET_SRC_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) +COMMON_SOURCE = $(EDK_TOOLS_COMMON) + +# +# Common information +# + +TARGET_LIB = $(EDK_TOOLS_OUTPUT)\Common.lib +TARGET_SOURCE_DIR = $(COMMON_SOURCE) + +OBJECTS = "$(EDK_TOOLS_OUTPUT)\ParseInf.obj" \ + "$(EDK_TOOLS_OUTPUT)\EfiCompress.obj" \ + "$(EDK_TOOLS_OUTPUT)\TianoCompress.obj" \ + "$(EDK_TOOLS_OUTPUT)\Decompress.obj" \ + "$(EDK_TOOLS_OUTPUT)\crc32.obj" \ + "$(EDK_TOOLS_OUTPUT)\CommonLib.obj" \ + "$(EDK_TOOLS_OUTPUT)\PeCoffLoader.obj" \ + "$(EDK_TOOLS_OUTPUT)\PeCoffLoaderEx.obj" \ + "$(EDK_TOOLS_OUTPUT)\FvLib.obj" \ + "$(EDK_TOOLS_OUTPUT)\EfiUtilityMsgs.obj" \ + "$(EDK_TOOLS_OUTPUT)\SimpleFileParsing.obj" \ + "$(EDK_TOOLS_OUTPUT)\MyAlloc.obj" + +# +# Build targets +# + +all: $(TARGET_LIB) + +# +# Object targets +# + +"$(EDK_TOOLS_OUTPUT)\ParseInf.obj": "$(TARGET_SOURCE_DIR)\ParseInf.c" "$(TARGET_SOURCE_DIR)\ParseInf.h" $(EDK_SOURCE)\Foundation\Include\TianoCommon.h + $(CC) $(C_FLAGS) "$(TARGET_SOURCE_DIR)\ParseInf.c" /Fo"$(EDK_TOOLS_OUTPUT)\ParseInf.obj" + +"$(EDK_TOOLS_OUTPUT)\MyAlloc.obj": "$(TARGET_SOURCE_DIR)\MyAlloc.c" "$(TARGET_SOURCE_DIR)\MyAlloc.h" $(EDK_SOURCE)\Foundation\Include\TianoCommon.h + $(CC) $(C_FLAGS) "$(TARGET_SOURCE_DIR)\MyAlloc.c" /Fo"$(EDK_TOOLS_OUTPUT)\MyAlloc.obj" + +"$(EDK_TOOLS_OUTPUT)\EfiCompress.obj": "$(TARGET_SOURCE_DIR)\EfiCompress.c" "$(TARGET_SOURCE_DIR)\Compress.h" $(EDK_SOURCE)\Foundation\Include\TianoCommon.h + $(CC) $(C_FLAGS) "$(TARGET_SOURCE_DIR)\EfiCompress.c" /Fo"$(EDK_TOOLS_OUTPUT)\EfiCompress.obj" + +"$(EDK_TOOLS_OUTPUT)\TianoCompress.obj": "$(TARGET_SOURCE_DIR)\TianoCompress.c" "$(TARGET_SOURCE_DIR)\Compress.h" $(EDK_SOURCE)\Foundation\Include\TianoCommon.h + $(CC) $(C_FLAGS) "$(TARGET_SOURCE_DIR)\TianoCompress.c" /Fo"$(EDK_TOOLS_OUTPUT)\TianoCompress.obj" + +"$(EDK_TOOLS_OUTPUT)\Decompress.obj": "$(TARGET_SOURCE_DIR)\Decompress.c" "$(TARGET_SOURCE_DIR)\Decompress.h" $(EDK_SOURCE)\Foundation\Include\TianoCommon.h + $(CC) $(C_FLAGS) "$(TARGET_SOURCE_DIR)\Decompress.c" /Fo"$(EDK_TOOLS_OUTPUT)\Decompress.obj" + +"$(EDK_TOOLS_OUTPUT)\crc32.obj": "$(TARGET_SOURCE_DIR)\crc32.c" "$(TARGET_SOURCE_DIR)\crc32.h" $(EDK_SOURCE)\Foundation\Include\TianoCommon.h + $(CC) $(C_FLAGS) "$(TARGET_SOURCE_DIR)\crc32.c" /Fo"$(EDK_TOOLS_OUTPUT)\crc32.obj" + +"$(EDK_TOOLS_OUTPUT)\CommonLib.obj": "$(TARGET_SOURCE_DIR)\CommonLib.c" "$(TARGET_SOURCE_DIR)\CommonLib.h" $(EDK_SOURCE)\Foundation\Include\TianoCommon.h + $(CC) $(C_FLAGS) "$(TARGET_SOURCE_DIR)\CommonLib.c" /Fo"$(EDK_TOOLS_OUTPUT)\CommonLib.obj" + +"$(EDK_TOOLS_OUTPUT)\PeCoffLoader.obj": "$(EDK_SOURCE)\Foundation\Include\TianoCommon.h" "$(EDK_SOURCE)\Foundation\Library\Pei\PeiLib\$(PROCESSOR)\PeCoffLoaderEx.h" "$(EDK_SOURCE)\Foundation\Library\Pei\PeiLib\PeCoffLoader.c" +# +# This tool is built differently based on the target processor architecture. +# PE32/PE32+ headers are different for IA32 and IPF, so copy the correct file +# to the tools directory and include it in the build. +# Also copy PeCoffLoaderEx.h because it contains the checks for valid image +# type. +# + @copy "$(EDK_SOURCE)\Foundation\Include\$(PROCESSOR)\EfiPeOptionalHeader.h" $(EDK_TOOLS_OUTPUT) + @copy "$(EDK_SOURCE)\Foundation\Library\Pei\PeiLib\$(PROCESSOR)\PeCoffLoaderEx.h" $(EDK_TOOLS_OUTPUT) + $(CC) -I $(EDK_TOOLS_OUTPUT) $(C_FLAGS) -I "$(EDK_SOURCE)\Foundation\Library\Pei\PeiLib\$(PROCESSOR)" "$(EDK_SOURCE)\Foundation\Library\Pei\PeiLib\PeCoffLoader.c" /Fo"$(EDK_TOOLS_OUTPUT)\PeCoffLoader.obj" + +"$(EDK_TOOLS_OUTPUT)\PeCoffLoaderEx.obj": "$(EDK_SOURCE)\Foundation\Library\Pei\PeiLib\$(PROCESSOR)\PeCoffLoaderEx.c" + $(CC) $(C_FLAGS) "$(EDK_SOURCE)\Foundation\Library\Pei\PeiLib\$(PROCESSOR)\PeCoffLoaderEx.c" /Fo"$(EDK_TOOLS_OUTPUT)\PeCoffLoaderEx.obj" + +"$(EDK_TOOLS_OUTPUT)\FvLib.obj": "$(TARGET_SOURCE_DIR)\FvLib.c" "$(TARGET_SOURCE_DIR)\FvLib.h" $(EDK_SOURCE)\Sample\Include\Efi2WinNt.h $(EDK_SOURCE)\Foundation\Framework\Include\EfiFirmwareFileSystem.h "$(EDK_SOURCE)\Foundation\Framework\Include\EfiFirmwareVolumeHeader.h" + $(CC) $(C_FLAGS) "$(TARGET_SOURCE_DIR)\FvLib.c" /Fo"$(EDK_TOOLS_OUTPUT)\FvLib.obj" + +"$(EDK_TOOLS_OUTPUT)\EfiUtilityMsgs.obj": "$(TARGET_SOURCE_DIR)\EfiUtilityMsgs.c" "$(TARGET_SOURCE_DIR)\EfiUtilityMsgs.h" + $(CC) $(C_FLAGS) "$(TARGET_SOURCE_DIR)\EfiUtilityMsgs.c" /Fo"$(EDK_TOOLS_OUTPUT)\EfiUtilityMsgs.obj" + +"$(EDK_TOOLS_OUTPUT)\SimpleFileParsing.obj" : "$(TARGET_SOURCE_DIR)\SimpleFileParsing.c" "$(TARGET_SOURCE_DIR)\SimpleFileParsing.h" + $(CC) $(C_FLAGS) "$(TARGET_SOURCE_DIR)\SimpleFileParsing.c" /Fo"$(EDK_TOOLS_OUTPUT)\SimpleFileParsing.obj" + +# +# Build LIB +# + +# +# Add Binary Build description for this lib. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).lib)) +$(TARGET_LIB): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).lib + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).lib $(TARGET_LIB) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME)Obj.pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME)Obj.pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Obj.pdb /Y +!ELSE +$(TARGET_LIB): $(OBJECTS) + $(LIB_EXE) $(LIB_FLAGS) $(OBJECTS) /OUT:$(TARGET_LIB) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_LIB) copy $(TARGET_LIB) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).lib /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Obj.pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Obj.pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME)Obj.pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\ParseInf.* del /q $(EDK_TOOLS_OUTPUT)\ParseInf.* > NUL + @if exist $(EDK_TOOLS_OUTPUT)\ParsePeim.* del /q $(EDK_TOOLS_OUTPUT)\ParsePeim.* > NUL + @if exist $(EDK_TOOLS_OUTPUT)\EfiCompress.* del /q $(EDK_TOOLS_OUTPUT)\EfiCompress.* > NUL + @if exist $(EDK_TOOLS_OUTPUT)\TianoCompress.* del /q $(EDK_TOOLS_OUTPUT)\TianoCompress.* > NUL + @if exist $(EDK_TOOLS_OUTPUT)\Decompress.* del /q $(EDK_TOOLS_OUTPUT)\Decompress.* > NUL + @if exist $(EDK_TOOLS_OUTPUT)\crc32.* del /q $(EDK_TOOLS_OUTPUT)\crc32.* > NUL + @if exist $(EDK_TOOLS_OUTPUT)\CommonLib.* del /q $(EDK_TOOLS_OUTPUT)\CommonLib.* > NUL + @if exist $(EDK_TOOLS_OUTPUT)\PeCoffLoader.* del /q $(EDK_TOOLS_OUTPUT)\PeCoffLoader.* > NUL + @if exist $(EDK_TOOLS_OUTPUT)\PeCoffLoaderEx.* del /q $(EDK_TOOLS_OUTPUT)\PeCoffLoaderEx.* > NUL + @if exist $(EDK_TOOLS_OUTPUT)\FvLib.* del /q $(EDK_TOOLS_OUTPUT)\FvLib.* > NUL + @if exist $(TARGET_LIB) del $(TARGET_LIB) diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/Common/MyAlloc.c b/EdkCompatibilityPkg/Sample/Tools/Source/Common/MyAlloc.c new file mode 100644 index 0000000000..39fddf7428 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/MyAlloc.c @@ -0,0 +1,516 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + MyAlloc.c + +Abstract: + + File for memory allocation tracking functions. + +--*/ + +#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 || Line == 0) { + printf ( + "\nMyCheck(Final=%u, File=%xh, Line=%u)" + "Invalid parameter(s).\n", + Final, + File, + Line + ); + + exit (1); + } + + if (strlen (File) == 0) { + printf ( + "\nMyCheck(Final=%u, File=%s, Line=%u)" + "Invalid parameter.\n", + Final, + File, + 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, + Line, + Tmp->File, + Tmp->Line, + Tmp->Size, + *(UINT32 *) (Tmp->Buffer), + *(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, + Line + ); + + for (Tmp = MyAllocData; Tmp != NULL; Tmp = Tmp->Next) { + printf ( + "File=%s, Line=%u, nSize=%u, Head=%xh, Tail=%xh\n", + Tmp->File, + Tmp->Line, + Tmp->Size, + *(UINT32 *) (Tmp->Buffer), + *(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 (Size == 0 || File == NULL || Line == 0) { + printf ( + "\nMyAlloc(Size=%u, File=%xh, Line=%u)" + "\nInvalid parameter(s).\n", + Size, + File, + Line + ); + + exit (1); + } + + Len = strlen (File); + if (Len == 0) { + printf ( + "\nMyAlloc(Size=%u, File=%s, Line=%u)" + "\nInvalid parameter.\n", + Size, + File, + Line + ); + + exit (1); + } + // + // Check the allocation list for corruption. + // + MyCheck (0, __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", + Size, + File, + Line + ); + + exit (1); + } + // + // Fill in the new entry. + // + Tmp->File = ((UINT8 *) Tmp) + sizeof (MY_ALLOC_STRUCT); + strcpy (Tmp->File, 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 (Size == 0 || File == NULL || Line == 0) { + printf ( + "\nMyRealloc(Ptr=%xh, Size=%u, File=%xh, Line=%u)" + "\nInvalid parameter(s).\n", + Ptr, + Size, + File, + Line + ); + + exit (1); + } + + if (strlen (File) == 0) { + printf ( + "\nMyRealloc(Ptr=%xh, Size=%u, File=%s, Line=%u)" + "\nInvalid parameter.\n", + Ptr, + Size, + File, + 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=%xh, Size=%u, File=%s, Line=%u)" + "\nCould not find buffer.\n", + Ptr, + Size, + File, + 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, __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 || Line == 0) { + printf ( + "\nMyFree(Ptr=%xh, File=%xh, Line=%u)" + "\nInvalid parameter(s).\n", + Ptr, + File, + Line + ); + + exit (1); + } + + if (strlen (File) == 0) { + printf ( + "\nMyFree(Ptr=%xh, File=%s, Line=%u)" + "\nInvalid parameter.\n", + Ptr, + File, + Line + ); + + exit (1); + } + // + // Freeing NULL is always valid. + // + if (Ptr == NULL) { + return ; + } + // + // Fail if nothing is allocated. + // + if (MyAllocData == NULL) { + printf ( + "\nMyFree(Ptr=%xh, File=%s, Line=%u)" + "\nCalled before memory allocated.\n", + Ptr, + File, + Line + ); + + exit (1); + } + // + // Check for corrupted allocation list. + // + MyCheck (0, __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=%xh, File=%s, Line=%u)\n" + "\nNot found.\n", + Ptr, + File, + 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/EdkCompatibilityPkg/Sample/Tools/Source/Common/MyAlloc.h b/EdkCompatibilityPkg/Sample/Tools/Source/Common/MyAlloc.h new file mode 100644 index 0000000000..2d195c2561 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/MyAlloc.h @@ -0,0 +1,222 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + MyAlloc.h + +Abstract: + + Header file for memory allocation tracking functions. + +--*/ + +#ifndef _MYALLOC_H_ +#define _MYALLOC_H_ + +#include +#include +#include + +#include "Tiano.h" + +// +// 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/EdkCompatibilityPkg/Sample/Tools/Source/Common/ParseInf.c b/EdkCompatibilityPkg/Sample/Tools/Source/Common/ParseInf.c new file mode 100644 index 0000000000..159d81b207 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/ParseInf.c @@ -0,0 +1,625 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ParseInf.c + +Abstract: + + This contains some useful functions for parsing INF files. + +--*/ + +#include "ParseInf.h" +#include +#include +#include + +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 _MAX_PATH 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 + // + InputBuffer[CharsToCopy - 1] = '\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_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_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_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_PATH]; + CHAR8 *CurrentToken; + BOOLEAN ParseError; + BOOLEAN ReadError; + UINTN Occurrance; + + // + // 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 + // + Occurrance = 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_PATH) == NULL) { + // + // Error reading from input file + // + ReadError = TRUE; + break; + } + // + // Get the first non-whitespace string + // + CurrentToken = strtok (InputBuffer, " \t\n"); + if (CurrentToken == 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 == Occurrance) { + // + // Copy the contents following the = + // + CurrentToken = strtok (NULL, "= \t\n"); + if (CurrentToken == NULL) { + // + // Nothing found, parsing error + // + ParseError = TRUE; + } else { + // + // Copy the current token to the output value + // + strcpy (Value, CurrentToken); + return EFI_SUCCESS; + } + } else { + // + // Increment the occurrance found + // + Occurrance++; + } + } + } while ( + !ParseError && + !ReadError && + InputFile->CurrentFilePointer < InputFile->Eof && + CurrentToken[0] != '[' && + Occurrance <= 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; + UINTN Data1; + UINTN Data2; + UINTN Data3; + UINTN Data4[8]; + + if (AsciiGuidBuffer == NULL || GuidBuffer == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Scan the guid string into the buffer + // + Index = sscanf ( + AsciiGuidBuffer, + "%08x-%04x-%04x-%02x%02x-%02hx%02hx%02hx%02hx%02hx%02hx", + &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) { + printf ("ERROR: Malformed GUID \"%s\".\n\n", 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 preceeded 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 HexNumber; + CHAR8 CurrentChar; + + // + // Initialize the result + // + HexNumber = 0; + + // + // Add each character to the result + // + if (IsHex || (AsciiString[0] == '0' && (AsciiString[1] == 'x' || AsciiString[1] == 'X'))) { + // + // Verify string is a hex number + // + for (Index = 2; Index < strlen (AsciiString); Index++) { + if (isxdigit (AsciiString[Index]) == 0) { + return EFI_ABORTED; + } + } + // + // Convert the hex string. + // + for (Index = 2; AsciiString[Index] != '\0'; Index++) { + CurrentChar = AsciiString[Index]; + HexNumber *= 16; + if (CurrentChar >= '0' && CurrentChar <= '9') { + HexNumber += CurrentChar - '0'; + } else if (CurrentChar >= 'a' && CurrentChar <= 'f') { + HexNumber += CurrentChar - 'a' + 10; + } else if (CurrentChar >= 'A' && CurrentChar <= 'F') { + HexNumber += CurrentChar - 'A' + 10; + } else { + // + // Unrecognized character + // + return EFI_ABORTED; + } + } + + *ReturnValue = HexNumber; + } else { + // + // Verify string is a number + // + for (Index = 0; Index < strlen (AsciiString); Index++) { + if (isdigit (AsciiString[Index]) == 0) { + return EFI_ABORTED; + } + } + + *ReturnValue = atol (AsciiString); + } + + 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_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_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_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/EdkCompatibilityPkg/Sample/Tools/Source/Common/ParseInf.h b/EdkCompatibilityPkg/Sample/Tools/Source/Common/ParseInf.h new file mode 100644 index 0000000000..0b4fec7a1f --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/ParseInf.h @@ -0,0 +1,233 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ParseInf.h + +Abstract: + + Header file for helper functions useful for parsing INF files. + +--*/ + +#ifndef _EFI_PARSE_INF_H +#define _EFI_PARSE_INF_H + +#include "TianoCommon.h" +#include +#include + +// +// Common data structures +// +typedef struct { + CHAR8 *FileImage; + CHAR8 *Eof; + CHAR8 *CurrentFilePointer; +} MEMORY_FILE; + +// +// Functions declarations +// +CHAR8 * +ReadLine ( + IN MEMORY_FILE *InputFile, + IN OUT CHAR8 *InputBuffer, + IN UINT32 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 _MAX_PATH 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_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 preceeded 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_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 + +--*/ +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/Common/SimpleFileParsing.c b/EdkCompatibilityPkg/Sample/Tools/Source/Common/SimpleFileParsing.c new file mode 100644 index 0000000000..2a2fbe6d90 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/SimpleFileParsing.c @@ -0,0 +1,1456 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + SimpleFileParsing.c + +Abstract: + + Generic but simple file parsing routines. + +--*/ + +#include +#include +#include +#include + +#include "Tiano.h" +#include "EfiUtilityMsgs.h" +#include "SimpleFileParsing.h" + +#define MAX_PATH 255 +// +// just in case we get in an endless loop. +// +#define MAX_NEST_DEPTH 20 +// +// number of wchars +// +#define MAX_STRING_IDENTIFIER_NAME 100 + +#define MAX_LINE_LEN 400 + +#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; + T_CHAR *FileBuffer; + T_CHAR *FileBufferPtr; + unsigned int FileSize; + char FileName[MAX_PATH]; + unsigned int LineNum; + BOOLEAN EndOfFile; + BOOLEAN SkipToHash; + struct _SOURCE_FILE *Previous; + struct _SOURCE_FILE *Next; + T_CHAR ControlCharacter; +} SOURCE_FILE; + +typedef struct { + T_CHAR *FileBufferPtr; +} FILE_POSITION; + +// +// Keep all our module globals in this structure +// +static struct { + SOURCE_FILE SourceFile; + BOOLEAN VerboseFile; + BOOLEAN VerboseToken; +} mGlobals; + +static +unsigned int +t_strcmp ( + T_CHAR *Buffer, + T_CHAR *Str + ); + +static +unsigned int +t_strncmp ( + T_CHAR *Str1, + T_CHAR *Str2, + int Len + ); + +static +unsigned int +t_strlen ( + T_CHAR *Str + ); + +static +void +RewindFile ( + SOURCE_FILE *SourceFile + ); + +static +BOOLEAN +IsWhiteSpace ( + SOURCE_FILE *SourceFile + ); + +static +unsigned int +SkipWhiteSpace ( + SOURCE_FILE *SourceFile + ); + +static +BOOLEAN +EndOfFile ( + SOURCE_FILE *SourceFile + ); + +static +void +PreprocessFile ( + SOURCE_FILE *SourceFile + ); + +static +T_CHAR * +t_strcpy ( + T_CHAR *Dest, + T_CHAR *Src + ); + +static +STATUS +ProcessIncludeFile ( + SOURCE_FILE *SourceFile, + SOURCE_FILE *ParentSourceFile + ); + +static +STATUS +ParseFile ( + SOURCE_FILE *SourceFile + ); + +static +FILE * +FindFile ( + char *FileName, + char *FoundFileName, + unsigned int FoundFileNameLen + ); + +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; +} + +unsigned +int +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; +} + +T_CHAR * +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 ( + char *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 ( + T_CHAR *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. + +--*/ +{ + unsigned int 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 ( + T_CHAR *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. + +--*/ +{ + unsigned int Len; + SkipWhiteSpace (&mGlobals.SourceFile); + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + + if ((Len = t_strcmp (mGlobals.SourceFile.FileBufferPtr, Str)) > 0) { + if (isalnum (mGlobals.SourceFile.FileBufferPtr[Len])) { + return FALSE; + } + + mGlobals.SourceFile.FileBufferPtr += Len; + if (mGlobals.VerboseToken) { + printf ("Token: '%s'\n", Str); + } + + return TRUE; + } + + return FALSE; +} + +BOOLEAN +SFPGetNextToken ( + T_CHAR *Str, + unsigned int 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: + Preceeding white space is ignored. + The parser's buffer pointer is advanced past the end of the + token. + +--*/ +{ + unsigned int Index; + T_CHAR 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 ( + T_CHAR *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 ( + T_CHAR *Str + ) +{ + unsigned int Len; + T_CHAR *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 ( + unsigned int *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 + +--*/ +{ + SkipWhiteSpace (&mGlobals.SourceFile); + if (EndOfFile (&mGlobals.SourceFile)) { + return FALSE; + } + + if (isdigit (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 (mGlobals.SourceFile.FileBufferPtr[2])) { + return FALSE; + } + + mGlobals.SourceFile.FileBufferPtr += 2; + sscanf (mGlobals.SourceFile.FileBufferPtr, "%x", Value); + while (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) { + mGlobals.SourceFile.FileBufferPtr++; + } + + return TRUE; + } else { + *Value = atoi (mGlobals.SourceFile.FileBufferPtr); + while (isdigit (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 unsigned int NestDepth = 0; + char 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", NestDepth * 2, ' ', SourceFile->FileName); + fprintf (stdout, "Parent source file = '%s'\n", ParentSourceFile); + } + + // + // Make sure we didn't exceed our maximum nesting depth + // + if (NestDepth > MAX_NEST_DEPTH) { + Error (NULL, 0, 0, SourceFile->FileName, "max nesting depth (%d) exceeded", 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 (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 = %d (0x%X)\n", SourceFile->FileSize, SourceFile->FileSize); + } + + fseek (SourceFile->Fptr, 0, SEEK_SET); + SourceFile->FileBuffer = (T_CHAR *) malloc (SourceFile->FileSize + sizeof (T_CHAR)); + if (SourceFile->FileBuffer == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + fread ((void *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr); + SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (T_CHAR))] = 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 = %d (0x%X)\n", SourceFile->FileSize, SourceFile->FileSize); + RewindFile (SourceFile); + } +} + +BOOLEAN +SFPGetQuotedString ( + T_CHAR *Str, + int 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 +T_CHAR * +GetQuotedString ( + SOURCE_FILE *SourceFile, + BOOLEAN Optional + ) +{ + T_CHAR *String; + T_CHAR *Start; + T_CHAR *Ptr; + unsigned int 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 = (T_CHAR *) malloc ((Len + 1) * sizeof (T_CHAR)); + if (String == NULL) { + Error (NULL, 0, 0, "memory allocation failed", 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 (T_CHAR)) { + SourceFile->EndOfFile = TRUE; + return TRUE; + } + + if (SourceFile->EndOfFile) { + return TRUE; + } + + return FALSE; +} + +#if 0 +static +void +ProcessTokenInclude ( + SOURCE_FILE *SourceFile + ) +{ + char IncludeFileName[MAX_PATH]; + char *To; + unsigned int 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 = (T_CHAR) SourceFile->FileBufferPtr[0]; + To++; + } + + SourceFile->FileBufferPtr++; + } + + if (!ReportedError) { + *To = 0; + memset ((char *) &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; + } +} + +unsigned int +SkipWhiteSpace ( + SOURCE_FILE *SourceFile + ) +{ + unsigned int 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 +unsigned int +t_strcmp ( + T_CHAR *Buffer, + T_CHAR *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 + +--*/ +{ + unsigned int Len; + + Len = 0; + while (*Str && (*Str == *Buffer)) { + Buffer++; + Str++; + Len++; + } + + if (*Str) { + return 0; + } + + return Len; +} + +static +unsigned int +t_strlen ( + T_CHAR *Str + ) +{ + unsigned int Len; + Len = 0; + while (*Str) { + Len++; + Str++; + } + + return Len; +} + +static +unsigned int +t_strncmp ( + T_CHAR *Str1, + T_CHAR *Str2, + int Len + ) +{ + while (Len > 0) { + if (*Str1 != *Str2) { + return Len; + } + + Len--; + Str1++; + Str2++; + } + + return 0; +} + +static +T_CHAR * +t_strcpy ( + T_CHAR *Dest, + T_CHAR *Src + ) +{ + T_CHAR *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 ( + T_CHAR *Buffer, + UINT32 BufferLen + ) +{ + UINT32 Len; + Len = 0; + while (!EndOfFile (&mGlobals.SourceFile) && (BufferLen > 0)) { + if (isxdigit (mGlobals.SourceFile.FileBufferPtr[0])) { + *Buffer = mGlobals.SourceFile.FileBufferPtr[0]; + Buffer++; + Len++; + BufferLen--; + mGlobals.SourceFile.FileBufferPtr++; + } else { + break; + } + } + // + // Null terminate if we can + // + if ((Len > 0) && (BufferLen > 0)) { + *Buffer = 0; + } + + return Len; +} + +BOOLEAN +SFPGetGuid ( + int 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 + +--*/ +{ + UINT32 Value32; + UINT32 Index; + FILE_POSITION FPos; + T_CHAR TempString[20]; + T_CHAR TempString2[3]; + T_CHAR *From; + T_CHAR *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/EdkCompatibilityPkg/Sample/Tools/Source/Common/SimpleFileParsing.h b/EdkCompatibilityPkg/Sample/Tools/Source/Common/SimpleFileParsing.h new file mode 100644 index 0000000000..ee59a6d8d4 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/SimpleFileParsing.h @@ -0,0 +1,118 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + SimpleFileParsing.h + +Abstract: + + Function prototypes and defines for the simple file parsing routines. + +--*/ + +#ifndef _SIMPLE_FILE_PARSING_H_ +#define _SIMPLE_FILE_PARSING_H_ + +#define T_CHAR char + +STATUS +SFPInit ( + VOID + ) +; + +STATUS +SFPOpenFile ( + char *FileName + ) +; + +BOOLEAN +SFPIsKeyword ( + T_CHAR *Str + ) +; + +BOOLEAN +SFPIsToken ( + T_CHAR *Str + ) +; + +BOOLEAN +SFPGetNextToken ( + T_CHAR *Str, + unsigned int Len + ) +; + +BOOLEAN +SFPGetGuidToken ( + T_CHAR *Str, + UINT32 Len + ) +; + +#define PARSE_GUID_STYLE_5_FIELDS 0 + +BOOLEAN +SFPGetGuid ( + int GuidStyle, + EFI_GUID *Value + ) +; + +BOOLEAN +SFPSkipToToken ( + T_CHAR *Str + ) +; + +BOOLEAN +SFPGetNumber ( + unsigned int *Value + ) +; + +BOOLEAN +SFPGetQuotedString ( + T_CHAR *Str, + int Length + ) +; + +BOOLEAN +SFPIsEOF ( + VOID + ) +; + +STATUS +SFPCloseFile ( + VOID + ) +; + +unsigned +int +SFPGetLineNumber ( + VOID + ) +; + +T_CHAR * +SFPGetFileName ( + VOID + ) +; + +#endif // #ifndef _SIMPLE_FILE_PARSING_H_ diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/Common/TianoCompress.c b/EdkCompatibilityPkg/Sample/Tools/Source/Common/TianoCompress.c new file mode 100644 index 0000000000..5cb13b2304 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Common/TianoCompress.c @@ -0,0 +1,1765 @@ +/*++ + +Copyright (c) 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + TianoCompress.c + +Abstract: + + 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. + +--*/ + +#include +#include +#include "TianoCommon.h" +#include "Compress.h" + +// +// Macro Definitions +// +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 +EFI_STATUS +Compress ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize, + IN UINT8 Version + ); + +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], mCTable[4096], 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 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 + +Argements: + VOID + +Returns: + + EFI_SUCCESS - Memory is allocated successfully + EFI_OUT_OF_RESOURCES - Allocation fails + +--*/ +{ + UINT32 Index; + + mText = malloc (WNDSIZ * 2 + MAXMATCH); + 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)); + + 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. Travese 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/EdkCompatibilityPkg/Sample/Tools/Source/CustomizedCompress/CustomizedCompress.c b/EdkCompatibilityPkg/Sample/Tools/Source/CustomizedCompress/CustomizedCompress.c new file mode 100644 index 0000000000..a4af74aff2 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/CustomizedCompress/CustomizedCompress.c @@ -0,0 +1,146 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + CustomizedCompress.c + +Abstract: + + Header file for Customized compression routine + +--*/ + +#include "TianoCommon.h" + +EFI_STATUS +SetCustomizedCompressionType ( + IN CHAR8 *Type + ) +/*++ + +Routine Description: + +The implementation of Customized SetCompressionType(). + +Arguments: + Type - The type if compression. + +Returns: + + EFI_SUCCESS - The type has been set. + EFI_UNSUPPORTED - This type is unsupported. + + +--*/ +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +CustomizedGetInfo ( + IN VOID *Source, + IN UINT32 SrcSize, + OUT UINT32 *DstSize, + OUT UINT32 *ScratchSize + ) +/*++ + +Routine Description: + +The implementation of Customized 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 successull retrieved. + EFI_INVALID_PARAMETER - The source data is corrupted + EFI_UNSUPPORTED - The operation is unsupported. + + +--*/ +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +CustomizedDecompress ( + 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 Customized Decompress(). + +Arguments: + + This - The protocol instance pointer + 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 successfull + EFI_INVALID_PARAMETER - The source data is corrupted + EFI_UNSUPPORTED - The operation is unsupported. + +--*/ +{ + return EFI_UNSUPPORTED; +} + +EFI_STATUS +CustomizedCompress ( + IN UINT8 *SrcBuffer, + IN UINT32 SrcSize, + IN UINT8 *DstBuffer, + IN OUT UINT32 *DstSize + ) +/*++ + +Routine Description: + + The Customized 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_UNSUPPORTED - The operation is unsupported. +--*/ +{ + return EFI_UNSUPPORTED; +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/CustomizedCompress/makefile b/EdkCompatibilityPkg/Sample/Tools/Source/CustomizedCompress/makefile new file mode 100644 index 0000000000..4e36514509 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/CustomizedCompress/makefile @@ -0,0 +1,82 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: makefile +# +# Abstract: +# +# This file is used to build the EFI utility. +# +#--*/ + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Define some macros we use here. Should get rid of them someday and +# get rid of the extra level of indirection. +# +TARGET_NAME = CustomizedCompress +TARGET_SOURCE_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) +COMMON_SOURCE = $(EDK_TOOLS_COMMON) + +# +# Common information +# + +TARGET_LIB = $(EDK_TOOLS_OUTPUT)\CustomizedCompress.lib + +OBJECTS = "$(EDK_TOOLS_OUTPUT)\CustomizedCompress.obj" + +# +# Build targets +# + +all: $(TARGET_LIB) + +# +# Object targets +# + +"$(EDK_TOOLS_OUTPUT)\CustomizedCompress.obj": "$(TARGET_SOURCE_DIR)\CustomizedCompress.c" $(EDK_SOURCE)\Foundation\Include\EfiCommon.h + $(CC) $(C_FLAGS) "$(TARGET_SOURCE_DIR)\CustomizedCompress.c" /Fo"$(EDK_TOOLS_OUTPUT)\CustomizedCompress.obj" + +# +# Build LIB +# + +# +# Add Binary Build description for this lib. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).lib)) +$(TARGET_LIB): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).lib + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).lib $(TARGET_LIB) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME)Obj.pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME)Obj.pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Obj.pdb /Y +!ELSE +$(TARGET_LIB): $(OBJECTS) + $(LIB_EXE) $(LIB_FLAGS) $(OBJECTS) /OUT:$(TARGET_LIB) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_LIB) copy $(TARGET_LIB) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).lib /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Obj.pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Obj.pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME)Obj.pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\CustomizedCompress.* del /q $(EDK_TOOLS_OUTPUT)\CustomizedCompress.* > NUL + @if exist $(TARGET_LIB) del $(TARGET_LIB) diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/EfiCompress/EfiCompressMain.c b/EdkCompatibilityPkg/Sample/Tools/Source/EfiCompress/EfiCompressMain.c new file mode 100644 index 0000000000..180422cae2 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/EfiCompress/EfiCompressMain.c @@ -0,0 +1,386 @@ +/*++ + +Copyright 2006 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + EfiCompressMain.c + +Abstract: + +--*/ + +#include +#include +#include +#include +#include +#include +#include "TianoCommon.h" +#include "Compress.h" + +typedef enum { + EFI_COMPRESS = 1, + TIANO_COMPRESS = 2 +} COMPRESS_TYPE; + +typedef struct _COMPRESS_ACTION_LIST { + struct _COMPRESS_ACTION_LIST *NextAction; + INT32 CompressType; + CHAR8 *InFileName; + CHAR8 *OutFileName; +} COMPRESS_ACTION_LIST; + + +STATIC +BOOLEAN +ParseCommandLine ( + INT32 argc, + CHAR8 *argv[], + COMPRESS_ACTION_LIST **ActionListHead + ) +/*++ + +Routine Description: + + Parse command line options + +Arguments: + + argc - number of arguments passed into the command line. + argv[] - files to compress and files to output compressed data to. + Options - Point to COMMAND_LINE_OPTIONS, receiving command line options. + +Returns: + + BOOLEAN: TRUE for a successful parse. +--*/ +; + +STATIC +VOID +Usage ( + CHAR8 *ExeName + ) +/*++ + +Routine Description: + + Print usage. + +Arguments: + + ExeName - Application's full path + +--*/ +; + + +STATIC +BOOLEAN +ProcessFile ( + CHAR8 *InFileName, + CHAR8 *OutFileName, + COMPRESS_TYPE CompressType + ) +/*++ + +Routine Description: + + Compress InFileName to OutFileName using algorithm specified by CompressType. + +Arguments: + + InFileName - Input file to compress + OutFileName - Output file compress to + CompressType - Compress algorithm, can be EFI_COMPRESS or TIANO_COMPRESS + +Returns: + + BOOLEAN: TRUE for compress file successfully + +--*/ +; + +int +main ( + INT32 argc, + CHAR8 *argv[] + ) +/*++ + +Routine Description: + + Compresses the input files + +Arguments: + + argc - number of arguments passed into the command line. + argv[] - files to compress and files to output compressed data to. + +Returns: + + int: 0 for successful execution of the function. + +--*/ +{ + COMPRESS_ACTION_LIST *ActionList; + COMPRESS_ACTION_LIST *NextAction; + UINT32 ActionCount; + UINT32 SuccessCount; + + ActionList = NULL; + ActionCount = SuccessCount = 0; + + if (!ParseCommandLine (argc, argv, &ActionList)) { + Usage (*argv); + return 1; + } + + while (ActionList != NULL) { + ++ActionCount; + if (ProcessFile ( + ActionList->InFileName, + ActionList->OutFileName, + ActionList->CompressType) + ) { + ++SuccessCount; + } + NextAction = ActionList; + ActionList = ActionList->NextAction; + free (NextAction); + } + + fprintf (stdout, "\nCompressed %d files, %d succeed!\n", ActionCount, SuccessCount); + if (SuccessCount < ActionCount) { + return 1; + } + + return 0; +} + +STATIC +BOOLEAN +ParseCommandLine ( + INT32 argc, + CHAR8 *argv[], + COMPRESS_ACTION_LIST **ActionListHead + ) +{ + COMPRESS_TYPE CurrentType; + + COMPRESS_ACTION_LIST **Action; + + Action = ActionListHead; + CurrentType = EFI_COMPRESS; // default compress algorithm + + // Skip Exe Name + --argc; + ++argv; + + while (argc > 0) { + if (strcmp (*argv, "-h") == 0 || strcmp (*argv, "-?") == 0) { + // + // 1. Directly return, help message will be printed. + // + return FALSE; + + } else if (strncmp (*argv, "-t", 2) == 0) { + // + // 2. Specifying CompressType + // + if (_stricmp ((*argv)+2, "EFI") == 0) { + CurrentType = EFI_COMPRESS; + } else if (_stricmp ((*argv)+2, "Tiano") == 0) { + CurrentType = TIANO_COMPRESS; + } else { + fprintf (stdout, " ERROR: CompressType %s not supported!\n", (*argv)+2); + return FALSE; + } + } else { + // + // 3. Current parameter is *FileName + // + if (*Action == NULL) { + // + // need to create a new action item + // + *Action = (COMPRESS_ACTION_LIST*) malloc (sizeof **Action); + if (*Action == NULL) { + fprintf (stdout, " ERROR: malloc failed!\n"); + return FALSE; + } + memset (*Action, 0, sizeof **Action); + (*Action)->CompressType = CurrentType; + } + + // + // Assignment to InFileName and OutFileName in order + // + if ((*Action)->InFileName == NULL) { + (*Action)->InFileName = *argv; + } else { + (*Action)->OutFileName = *argv; + Action = &(*Action)->NextAction; + } + } + + --argc; + ++argv; + + } + + if (*Action != NULL) { + assert ((*Action)->InFileName != NULL); + fprintf (stdout, " ERROR: Compress OutFileName not specified with InFileName: %s!\n", (*Action)->InFileName); + return FALSE; + } + + if (*ActionListHead == NULL) { + return FALSE; + } + return TRUE; +} + +STATIC +BOOLEAN +ProcessFile ( + CHAR8 *InFileName, + CHAR8 *OutFileName, + COMPRESS_TYPE CompressType + ) +{ + EFI_STATUS Status; + FILE *InFileP; + FILE *OutFileP; + UINT32 SrcSize; + UINT32 DstSize; + UINT8 *SrcBuffer; + UINT8 *DstBuffer; + COMPRESS_FUNCTION CompressFunc; + + SrcBuffer = DstBuffer = NULL; + InFileP = OutFileP = NULL; + + fprintf (stdout, "%s --> %s\n", InFileName, OutFileName); + + if ((OutFileP = fopen (OutFileName, "wb")) == NULL) { + fprintf (stdout, " ERROR: Can't open output file %s for write!\n", OutFileName); + goto ErrorHandle; + } + + if ((InFileP = fopen (InFileName, "rb")) == NULL) { + fprintf (stdout, " ERROR: Can't open input file %s for read!\n", InFileName); + goto ErrorHandle; + } + + // + // Get the size of source file + // + fseek (InFileP, 0, SEEK_END); + SrcSize = ftell (InFileP); + rewind (InFileP); + // + // Read in the source data + // + if ((SrcBuffer = malloc (SrcSize)) == NULL) { + fprintf (stdout, " ERROR: Can't allocate memory!\n"); + goto ErrorHandle; + } + + if (fread (SrcBuffer, 1, SrcSize, InFileP) != SrcSize) { + fprintf (stdout, " ERROR: Can't read from source!\n"); + goto ErrorHandle; + } + + // + // Choose the right compress algorithm + // + CompressFunc = (CompressType == EFI_COMPRESS) ? EfiCompress : TianoCompress; + + // + // Get destination data size and do the compression + // + DstSize = 0; + Status = CompressFunc (SrcBuffer, SrcSize, DstBuffer, &DstSize); + if (Status != EFI_BUFFER_TOO_SMALL) { + fprintf (stdout, " Error: Compress failed: %x!\n", Status); + goto ErrorHandle; + } + if ((DstBuffer = malloc (DstSize)) == NULL) { + fprintf (stdout, " ERROR: Can't allocate memory!\n"); + goto ErrorHandle; + } + + Status = CompressFunc (SrcBuffer, SrcSize, DstBuffer, &DstSize); + if (EFI_ERROR (Status)) { + fprintf (stdout, " ERROR: Compress Error!\n"); + goto ErrorHandle; + } + + fprintf (stdout, " Orig Size = %ld\tComp Size = %ld\n", SrcSize, DstSize); + + if (DstBuffer == NULL) { + fprintf (stdout, " ERROR: No destination to write to!\n"); + goto ErrorHandle; + } + + // + // Write out the result + // + if (fwrite (DstBuffer, 1, DstSize, OutFileP) != DstSize) { + fprintf (stdout, " ERROR: Can't write to destination file!\n"); + goto ErrorHandle; + } + + return TRUE; + +ErrorHandle: + if (SrcBuffer) { + free (SrcBuffer); + } + + if (DstBuffer) { + free (DstBuffer); + } + + if (InFileP) { + fclose (InFileP); + } + + if (OutFileP) { + fclose (OutFileP); + } + return FALSE; +} + +VOID +Usage ( + CHAR8 *ExeName + ) +{ + fprintf ( + stdout, + "\n" + "Usage: %s [-tCompressType] InFileName OutFileName\n" + " %*c [[-tCompressType] InFileName OutFileName ...]\n" + "\n" + "where:\n" + " CompressType - optional compress algorithm (EFI | Tiano), case insensitive.\n" + " If ommitted, compress type specified ahead is used, \n" + " default is EFI\n" + " e.g.: EfiCompress a.in a.out -tTiano b.in b.out \\ \n" + " c.in c.out -tEFI d.in d.out\n" + " a.in and d.in are compressed using EFI compress algorithm\n" + " b.in and c.in are compressed using Tiano compress algorithm\n" + " InFileName - input file path\n" + " OutFileName - output file path\n", + ExeName, strlen(ExeName), ' ' + ); +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/EfiCompress/makefile b/EdkCompatibilityPkg/Sample/Tools/Source/EfiCompress/makefile new file mode 100644 index 0000000000..3f034288e0 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/EfiCompress/makefile @@ -0,0 +1,89 @@ +#/*++ +# +# Copyright (c) 2006 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# makefile +# +# Abstract: +# +# This file is used to build the EFI utility. +# +#--*/ + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Define some macros we use here. Should get rid of them someday and +# get rid of the extra level of indirection. +# +COMMON_SOURCE = $(EDK_TOOLS_COMMON) + + +# +# Common information +# + +INC=$(INC) + +# +# Target specific information +# + +TARGET_NAME=EfiCompress +TARGET_SOURCE_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) + +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).exe + +TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\EfiCompressMain.c" +TARGET_EXE_INCLUDE = "$(COMMON_SOURCE)\Compress.h" +TARGET_EXE_LIBS = "$(EDK_TOOLS_OUTPUT)\Common.lib" + +# +# Build targets +# + +all: $(TARGET_EXE) + +# +# Build EXE +# + +$(EDK_TOOLS_OUTPUT)\EfiCompressMain.obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE) + $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\EfiCompressMain.obj + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE): $(EDK_TOOLS_OUTPUT)\EfiCompressMain.obj $(TARGET_EXE_LIBS) + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(EDK_TOOLS_OUTPUT)\EfiCompressMain.obj $(TARGET_EXE_LIBS) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Main.* del /q $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Main.* > NUL diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/EfiRom/EfiRom.c b/EdkCompatibilityPkg/Sample/Tools/Source/EfiRom/EfiRom.c new file mode 100644 index 0000000000..06a8581669 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/EfiRom/EfiRom.c @@ -0,0 +1,1545 @@ +/*++ + +Copyright (c) 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + EfiRom.c + +Abstract: + + Utility program to create an EFI option ROM image from binary and + EFI PE32 files. + + +--*/ + +#include +#include +#include + +// +// Includes for EFI 1.1 build +// +// #include "Tiano.h" // required defines for Compress.h +// #include "EfiImage.h" // for PE32 structure definitions +// #include "Compress.h" // for compression function +// Includes for Tiano build +// +#include "TianoCommon.h" +#include "EfiImage.h" // for PE32 structure definitions +#include "Compress.h" + +// +// END include differences +// +#include "Pci22.h" // for option ROM header structures +// +// Version of this utility +// +#define UTILITY_VERSION "v2.5" + +// +// Define some status return values +// +#define STATUS_SUCCESS 0 +#define STATUS_WARNING 1 +#define STATUS_ERROR 2 + +// +// Define the max length of a filename +// +#define MAX_PATH 200 + +#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; + INT8 *FileName; + UINT32 FileFlags; + UINT32 ClassCode; + UINT16 CodeRevision; +} FILE_LIST; + +// +// Use this to track our command-line options +// +typedef struct { + INT8 OutFileName[MAX_PATH]; + INT8 NoLast; + INT8 Verbose; + INT8 DumpOption; + UINT8 DevIdValid; + UINT8 VendIdValid; + UINT16 VendId; + UINT16 DevId; + 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; + char *Name; +} STRING_LOOKUP; + +static STRING_LOOKUP mMachineTypes[] = { + EFI_IMAGE_MACHINE_IA32, + "IA32", + EFI_IMAGE_MACHINE_IA64, + "IA64", + EFI_IMAGE_MACHINE_EBC, + "EBC", + 0, + NULL +}; + +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 +Usage ( + VOID + ); + +static +int +ParseCommandLine ( + int Argc, + char *Argv[], + OPTIONS *Options + ); + +static +int +CheckPE32File ( + FILE *Fptr, + UINT16 *MachineType, + UINT16 *SubSystem + ); + +static +int +ProcessEfiFile ( + FILE *OutFptr, + FILE_LIST *InFile, + UINT16 VendId, + UINT16 DevId, + UINT32 *Size + ); + +static +int +ProcessBinFile ( + FILE *OutFptr, + FILE_LIST *InFile, + UINT32 *Size + ); + +static +void +DumpImage ( + FILE_LIST *InFile + ); + +char * +GetMachineTypeStr ( + UINT16 MachineType + ); + +static +char * +GetSubsystemTypeStr ( + UINT16 SubsystemType + ); + +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 + +--*/ +// GC_TODO: ] - add argument and description to function comment +{ + INT8 *Ext; + FILE *FptrOut; + UINT32 Status; + FILE_LIST *FList; + UINT32 TotalSize; + UINT32 Size; + + Status = STATUS_SUCCESS; + FptrOut = NULL; + + // + // Parse the command line arguments + // + if (ParseCommandLine (Argc, Argv, &mOptions)) { + return STATUS_ERROR; + } + // + // If dumping an image, then do that and quit + // + if (mOptions.DumpOption) { + DumpImage (mOptions.FileList); + 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]) { + strcpy (mOptions.OutFileName, mOptions.FileList->FileName); + // + // Find the last . on the line and replace the filename extension with + // the default + // + for (Ext = mOptions.OutFileName + strlen (mOptions.OutFileName) - 1; + (Ext >= mOptions.OutFileName) && (*Ext != '.') && (*Ext != '\\'); + 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; + fprintf ( + stdout, + "ERROR: Input and output file names must be different - %s = %s\n", + FList->FileName, + mOptions.OutFileName + ); + goto BailOut; + } + } + // + // Now open our output file + // + if ((FptrOut = fopen (mOptions.OutFileName, "w+b")) == NULL) { + fprintf (stdout, "ERROR: Failed to open output file %s\n", 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) { + if (mOptions.Verbose) { + fprintf (stdout, "Processing EFI file %s\n", FList->FileName); + } + + Status = ProcessEfiFile (FptrOut, FList, mOptions.VendId, mOptions.DevId, &Size); + } else if (FList->FileFlags & FILE_FLAG_BINARY) { + if (mOptions.Verbose) { + fprintf (stdout, "Processing binary file %s\n", FList->FileName); + } + + Status = ProcessBinFile (FptrOut, FList, &Size); + } else { + fprintf (stdout, "ERROR: File not specified as EFI or binary: %s\n", FList->FileName); + Status = STATUS_ERROR; + } + + if (mOptions.Verbose) { + fprintf (stdout, " Output size = 0x%X\n", Size); + } + + if (Status != STATUS_SUCCESS) { + break; + } + + TotalSize += Size; + } + // + // Check total size + // + if (TotalSize > MAX_OPTION_ROM_SIZE) { + fprintf ( + stdout, + "ERROR: Option ROM image size exceeds limit 0x%X bytes\n", + MAX_OPTION_ROM_SIZE + ); + Status = STATUS_ERROR; + } + +BailOut: + if (FptrOut != NULL) { + fclose (FptrOut); + } + // + // Clean up our file list + // + while (mOptions.FileList != NULL) { + FList = mOptions.FileList->Next; + free (mOptions.FileList); + mOptions.FileList = FList; + } + + return Status; +} + +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 *PciDs; + UINT32 Index; + UINT8 ByteCheckSum; + + Status = STATUS_SUCCESS; + + // + // Try to open the input file + // + if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) { + fprintf (stdout, "ERROR: Failed to open input file %s\n", 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) { + fprintf (stdout, " File size = 0x%X\n", FileSize); + } + + fseek (InFptr, 0, SEEK_SET); + Buffer = (INT8 *) malloc (FileSize); + if (Buffer == NULL) { + fprintf (stdout, "ERROR: Memory allocation failed\n"); + Status = STATUS_ERROR; + goto BailOut; + } + + if (fread (Buffer, FileSize, 1, InFptr) != 1) { + fprintf (stdout, "ERROR: Failed to read all bytes from input file\n"); + 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) { + fprintf ( + stdout, + "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n", + 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) { + fprintf (stdout, "ERROR: ROM image file has invalid ROM signature\n"); + 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)) { + fprintf (stdout, "ERROR: Invalid PCI data structure offset\n"); + Status = STATUS_ERROR; + goto BailOut; + } + + PciDs = (PCI_DATA_STRUCTURE *) (Buffer + RomHdr->PcirOffset); + if (PciDs->Signature != PCI_DATA_STRUCTURE_SIGNATURE) { + fprintf (stdout, "ERROR: PCI data structure has invalid signature\n"); + Status = STATUS_ERROR; + goto BailOut; + } + // + // If this is the last image, then set the LAST bit unless requested not + // to via the command-line -l argument. Otherwise, make sure you clear it. + // + if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) { + PciDs->Indicator = INDICATOR_LAST; + } else { + PciDs->Indicator = 0; + } + + ByteCheckSum = 0; + for (Index = 0; Index < FileSize - 1; Index++) { + ByteCheckSum = (UINT8) (ByteCheckSum + Buffer[Index]); + } + + Buffer[FileSize - 1] = (UINT8) ((~ByteCheckSum) + 1); + fprintf (stdout, "CheckSUm = %02x\n", (UINT32) Buffer[FileSize - 1]); + + // + // Now copy the input file contents out to the output file + // + if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) { + fprintf (stdout, "ERROR: Failed to write all file bytes to output file\n"); + 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) { + fprintf (stdout, "Error processing binary file %s\n", 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 PciDs; + UINT32 FileSize; + UINT32 CompressedFileSize; + UINT8 *Buffer; + UINT8 *CompressedBuffer; + UINT8 *TempBufferPtr; + UINT32 TotalSize; + UINT32 HeaderSize; + UINT16 MachineType; + UINT16 SubSystem; + UINT32 HeaderPadBytes; + + // + // Try to open the input file + // + if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) { + fprintf (stdout, "ERROR: Failed to open input file %s\n", 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; + } + + HeaderSize = sizeof (PCI_DATA_STRUCTURE) + HeaderPadBytes + sizeof (EFI_PCI_EXPANSION_ROM_HEADER); + if (mOptions.Verbose) { + fprintf (stdout, " File size = 0x%X\n", 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 = (INT8 *) malloc (FileSize); + if (Buffer == NULL) { + fprintf (stdout, "ERROR: Memory allocation failed\n"); + Status = STATUS_ERROR; + goto BailOut; + } + + fseek (InFptr, 0, SEEK_SET); + if (fread (Buffer, FileSize, 1, InFptr) != 1) { + fprintf (stdout, "ERROR: Failed to read all bytes from input file\n"); + 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) { + // + // Allocate a buffer into which we can compress the image, compress it, + // and use that size as the new size. + // + CompressedBuffer = (INT8 *) malloc (FileSize); + if (CompressedBuffer == NULL) { + fprintf (stdout, "ERROR: Memory allocation failed\n"); + Status = STATUS_ERROR; + goto BailOut; + } + + CompressedFileSize = FileSize; + Status = EfiCompress (Buffer, FileSize, CompressedBuffer, &CompressedFileSize); + if (Status != STATUS_SUCCESS) { + fprintf (stdout, "ERROR: Compression failed\n"); + goto BailOut; + } + // + // Now compute the size, then swap buffer pointers. + // + if (mOptions.Verbose) { + fprintf (stdout, " Comp size = 0x%X\n", 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; + } + // + // Check size + // + if (TotalSize > MAX_OPTION_ROM_SIZE) { + fprintf ( + stdout, + "ERROR: Option ROM image %s size exceeds limit 0x%X bytes\n", + 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; + 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 + // + memset (&PciDs, 0, sizeof (PCI_DATA_STRUCTURE)); + + PciDs.Signature = PCI_DATA_STRUCTURE_SIGNATURE; + PciDs.VendorId = VendId; + PciDs.DeviceId = DevId; + PciDs.Length = (UINT16) sizeof (PCI_DATA_STRUCTURE); + PciDs.Revision = 0; + // + // Class code and code revision from the command line (optional) + // + PciDs.ClassCode[0] = (UINT8) InFile->ClassCode; + PciDs.ClassCode[1] = (UINT8) (InFile->ClassCode >> 8); + PciDs.ClassCode[2] = (UINT8) (InFile->ClassCode >> 16); + PciDs.ImageLength = RomHdr.InitializationSize; + PciDs.CodeRevision = InFile->CodeRevision; + PciDs.CodeType = PCI_CODE_TYPE_EFI_IMAGE; + + // + // If this is the last image, then set the LAST bit unless requested not + // to via the command-line -l argument. + // + if ((InFile->Next == NULL) && (mOptions.NoLast == 0)) { + PciDs.Indicator = INDICATOR_LAST; + } + // + // Write the ROM header to the output file + // + if (fwrite (&RomHdr, sizeof (RomHdr), 1, OutFptr) != 1) { + fprintf (stdout, "ERROR: Failed to write ROM header to output file\n"); + Status = STATUS_ERROR; + goto BailOut; + } + + // + // Write pad bytes to align the PciDs + // + while (HeaderPadBytes > 0) { + if (putc (0, OutFptr) == EOF) { + fprintf (stdout, "ERROR: Failed to write ROM header pad bytes to output file\n"); + Status = STATUS_ERROR; + goto BailOut; + } + + HeaderPadBytes--; + } + // + // Write the PCI data structure header to the output file + // + if (fwrite (&PciDs, sizeof (PciDs), 1, OutFptr) != 1) { + fprintf (stdout, "ERROR: Failed to write PCI ROM header to output file\n"); + Status = STATUS_ERROR; + goto BailOut; + } + // + // Keep track of how many bytes left to write + // + TotalSize -= HeaderSize; + + // + // Now dump the input file's contents to the output file + // + if (fwrite (Buffer, FileSize, 1, OutFptr) != 1) { + fprintf (stdout, "ERROR: Failed to write all file bytes to output file\n"); + Status = STATUS_ERROR; + goto BailOut; + } + + TotalSize -= FileSize; + // + // Pad the rest of the image to make it a multiple of 512 bytes + // + while (TotalSize > 0) { + if (putc (~0, OutFptr) == EOF) { + fprintf (stdout, "ERROR: Failed to write trailing pad bytes output file\n"); + Status = STATUS_ERROR; + goto BailOut; + } + + TotalSize--; + } + +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) { + fprintf (stdout, "Error processing EFI file %s\n", InFile->FileName); + } + + return Status; +} + +static +int +CheckPE32File ( + FILE *Fptr, + UINT16 *MachineType, + UINT16 *SubSystem + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + Fptr - GC_TODO: add argument description + MachineType - GC_TODO: add argument description + SubSystem - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + /*++ + +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_FILE_HEADER FileHdr; + EFI_IMAGE_OPTIONAL_HEADER OptionalHdr; + UINT32 PESig; + + // + // Position to the start of the file + // + fseek (Fptr, 0, SEEK_SET); + + // + // Read the DOS header + // + if (fread (&DosHeader, sizeof (DosHeader), 1, Fptr) != 1) { + fprintf (stdout, "ERROR: Failed to read the DOS stub from the input file\n"); + return STATUS_ERROR; + } + // + // Check the magic number (0x5A4D) + // + if (DosHeader.e_magic != EFI_IMAGE_DOS_SIGNATURE) { + fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (magic number)\n"); + return STATUS_ERROR; + } + // + // Position into the file and check the PE signature + // + fseek (Fptr, (long) DosHeader.e_lfanew, SEEK_SET); + if (fread (&PESig, sizeof (PESig), 1, Fptr) != 1) { + fprintf (stdout, "ERROR: Failed to read PE signature bytes from input file\n"); + return STATUS_ERROR; + } + // + // Check the PE signature in the header "PE\0\0" + // + if (PESig != EFI_IMAGE_NT_SIGNATURE) { + fprintf (stdout, "ERROR: Input file does not appear to be a PE32 image (signature)\n"); + return STATUS_ERROR; + } + // + // Read the file header and stuff their MachineType + // + if (fread (&FileHdr, sizeof (FileHdr), 1, Fptr) != 1) { + fprintf (stdout, "ERROR: Failed to read PE file header from input file\n"); + return STATUS_ERROR; + } + + memcpy ((char *) MachineType, &FileHdr.Machine, 2); + + // + // Read the optional header so we can get the subsystem + // + if (fread (&OptionalHdr, sizeof (OptionalHdr), 1, Fptr) != 1) { + fprintf (stdout, "ERROR: Failed to read COFF optional header from input file\n"); + return STATUS_ERROR; + } + + *SubSystem = OptionalHdr.Subsystem; + if (mOptions.Verbose) { + fprintf (stdout, " Got subsystem = 0x%X from image\n", (int) *SubSystem); + } + // + // Good to go + // + 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; + + FileFlags = 0; + + // + // Clear out the options + // + memset ((char *) Options, 0, sizeof (OPTIONS)); + + // + // To avoid compile warnings + // + FileList = PrevFileList = NULL; + + 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; + } + // + // Process until no more arguments + // + while (Argc > 0) { + if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) { + // + // To simplify string comparisons, replace slashes with dashes + // + Argv[0][0] = '-'; + + // + // Vendor ID specified with -v + // + if (_stricmp (Argv[0], "-v") == 0) { + // + // Make sure there's another parameter + // + if (Argc > 1) { + Options->VendId = (UINT16) strtol (Argv[1], NULL, 16); + Options->VendIdValid = 1; + } else { + fprintf ( + stdout, + "ERROR: Missing Vendor ID with %s\n\n", + Argv[0] + ); + Usage (); + return STATUS_ERROR; + } + + Argv++; + Argc--; + } else if (_stricmp (Argv[0], "-d") == 0) { + // + // Device ID specified with -d + // Make sure there's another parameter + // + if (Argc > 1) { + Options->DevId = (UINT16) strtol (Argv[1], NULL, 16); + Options->DevIdValid = 1; + } else { + fprintf ( + stdout, + "ERROR: Missing Device ID with %s\n\n", + Argv[0] + ); + Usage (); + return STATUS_ERROR; + } + + Argv++; + Argc--; + } else if (_stricmp (Argv[0], "-o") == 0) { + // + // Output filename specified with -o + // Make sure there's another parameter + // + if (Argc > 1) { + strcpy (Options->OutFileName, Argv[1]); + } else { + fprintf ( + stdout, + "ERROR: Missing output file name with %s\n\n", + Argv[0] + ); + Usage (); + return STATUS_ERROR; + } + + Argv++; + Argc--; + } else if ((_stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) { + // + // Help option + // + Usage (); + return STATUS_ERROR; + } else if (_stricmp (Argv[0], "-b") == 0) { + // + // Specify binary files with -b + // + FileFlags = (FileFlags &~FILE_FLAG_EFI) | FILE_FLAG_BINARY; + } else if ((_stricmp (Argv[0], "-e") == 0) || (_stricmp (Argv[0], "-ec") == 0)) { + // + // Specify EFI files with -e. Specify EFI-compressed with -ec. + // + FileFlags = (FileFlags &~FILE_FLAG_BINARY) | 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 -l + // + } else if (_stricmp (Argv[0], "-l") == 0) { + Options->NoLast = 1; + } else if (_stricmp (Argv[0], "-p") == 0) { + // + // -v for verbose would have been nicer, but it's already used. Let's use + // -p for prolix (wordy) output + // + Options->Verbose = 1; + } else if (_stricmp (Argv[0], "-dump") == 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->DevIdValid = 1; + FileFlags = FILE_FLAG_BINARY; + } else if (_stricmp (Argv[0], "-cc") == 0) { + // + // Class code value for the next file in the list. + // Make sure there's another parameter + // + if (Argc > 1) { + // + // No error checking on the return value. Could check for LONG_MAX, + // LONG_MIN, or 0 class code value if desired. Check range (3 bytes) + // at least. + // + ClassCode = (UINT32) strtol (Argv[1], NULL, 16); + if (ClassCode & 0xFF000000) { + fprintf (stdout, "ERROR: Class code %s out of range\n", Argv[1]); + return STATUS_ERROR; + } + } else { + fprintf ( + stdout, + "ERROR: Missing class code value with %s\n\n", + Argv[0] + ); + Usage (); + return STATUS_ERROR; + } + + Argv++; + Argc--; + } else if (_stricmp (Argv[0], "-rev") == 0) { + // + // Code revision in the PCI data structure. The value is for the next + // file in the list. + // Make sure there's another parameter + // + if (Argc > 1) { + // + // No error checking on the return value. Could check for LONG_MAX, + // LONG_MIN, or 0 value if desired. Check range (2 bytes) + // at least. + // + CodeRevision = (UINT32) strtol (Argv[1], NULL, 16); + if (CodeRevision & 0xFFFF0000) { + fprintf (stdout, "ERROR: Code revision %s out of range\n", Argv[1]); + return STATUS_ERROR; + } + } else { + fprintf ( + stdout, + "ERROR: Missing code revision value with %s\n\n", + Argv[0] + ); + Usage (); + return STATUS_ERROR; + } + + Argv++; + Argc--; + } else { + fprintf (stdout, "ERROR: Invalid option specified: %s\n\n", Argv[0]); + Usage (); + return STATUS_ERROR; + } + } 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) { + fprintf (stdout, "ERROR: Missing -e or -b with input file %s\n", Argv[0]); + return STATUS_ERROR; + } + // + // Create a new file structure + // + FileList = (FILE_LIST *) malloc (sizeof (FILE_LIST)); + if (FileList == NULL) { + fprintf (stdout, "ERROR: Memory allocation failure\n"); + return STATUS_ERROR; + } + + memset ((char *) FileList, 0, sizeof (FILE_LIST)); + FileList->FileName = Argv[0]; + FileList->FileFlags = FileFlags; + if (Options->FileList == NULL) { + Options->FileList = FileList; + } else { + if (PrevFileList == NULL) { + PrevFileList = FileList; + } else { + PrevFileList->Next = FileList; + } + } + + PrevFileList = FileList; + // + // Set the class code and code revision for this file, then reset the values. + // + FileList->ClassCode = ClassCode; + FileList->CodeRevision = (UINT16) CodeRevision; + ClassCode = 0; + CodeRevision = 0; + } + // + // Next argument + // + Argv++; + Argc--; + } + // + // Make sure they specified a device ID and vendor ID + // + if (!Options->VendIdValid) { + fprintf (stdout, "ERROR: Missing Vendor ID on command line\n\n"); + Usage (); + return STATUS_ERROR; + } + + if (!Options->DevIdValid) { + fprintf (stdout, "ERROR: Missing Device ID on command line\n\n"); + Usage (); + return STATUS_ERROR; + } + // + // Must have specified some files + // + if (Options->FileList == NULL) { + fprintf (stdout, "ERROR: Missing input file name\n"); + Usage (); + return STATUS_ERROR; + } + + return 0; +} + +static +void +Usage ( + VOID + ) +/*++ + +Routine Description: + + Print usage information for this utility. + +Arguments: + + None. + +Returns: + + Nothing. + +--*/ +{ + int Index; + static const char *Msg[] = { + "EfiRom "UTILITY_VERSION" - Intel EFI Make Option ROM utility", + " Copyright (C), 1999 - 2002 Intel Coproration\n", + " Create an option ROM image from a list of input files", + " Usage: efirom {-p} [-v VendorId] [-d DeviceId] {-o OutFileName} ", + " [-e|-b] [FileName(s)]", + " where:", + " VendorId - required hex PCI Vendor ID for the device", + " DeviceId - required hex PCI Device ID for the device", + " OutFileName - optional output file name. Default is the first input", + " file name with a "DEFAULT_OUTPUT_EXTENSION" file extension", + " FileNames - input PE32 or binary file name(s)", + " BinFileName - input binary file name(s)", + " -p - for verbose output", + " -l - to not automatically set the LAST bit on the last file", + " -b - following FileNames are binary files", + " -e - following FileNames are EFI PE32 image files", + " -ec - following FileNames are EFI PE32 image files, and should", + " be compressed by this utility", + " -cc ClassCode - to use hex ClassCode in the PCI data structure header for", + " the following FileName", + " -rev Revision - to use hex Revision in the PCI data structure header for", + " the following FileName", + " -dump - to dump the headers of an existing option ROM image", + "", + "Example usage: EfiRom -v 0xABCD -d 0x1234 -b File1.bin File2.bin -e File1.efi File2.efi ", + "", + NULL + }; + + for (Index = 0; Msg[Index] != NULL; Index++) { + fprintf (stdout, "%s\n", Msg[Index]); + } +} + +static +void +DumpImage ( + FILE_LIST *InFile + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + InFile - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + PCI_EXPANSION_ROM_HEADER PciRomHdr; + FILE *InFptr; + UINT32 ImageStart; + UINT32 ImageCount; + EFI_PCI_EXPANSION_ROM_HEADER EfiRomHdr; + PCI_DATA_STRUCTURE PciDs; + + // + // Open the input file + // + if ((InFptr = fopen (InFile->FileName, "rb")) == NULL) { + fprintf ( + stdout, + "ERROR: Could not open input file %s\n", + InFile->FileName + ); + return ; + } + // + // Go through the image and dump the header stuff for each + // + ImageCount = 0; + for (;;) { + // + // Save our postition 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) { + fprintf (stdout, "ERROR: Failed to read PCI ROM header from file\n"); + goto BailOut; + } + + // + // Dump the contents of the header + // + fprintf (stdout, "Image %d -- Offset 0x%X\n", ImageCount, ImageStart); + fprintf (stdout, " ROM header contents\n"); + fprintf (stdout, " Signature 0x%04X\n", (UINT32) PciRomHdr.Signature); + fprintf (stdout, " PCIR offset 0x%04X\n", (UINT32) PciRomHdr.PcirOffset); + // + // Find PCI data structure + // + if (fseek (InFptr, ImageStart + PciRomHdr.PcirOffset, SEEK_SET)) { + fprintf (stdout, "ERROR: Failed to seek to PCI data structure\n"); + goto BailOut; + } + // + // Read and dump the PCI data structure + // + if (fread (&PciDs, sizeof (PciDs), 1, InFptr) != 1) { + fprintf (stdout, "ERROR: Failed to read PCI data structure from file\n"); + goto BailOut; + } + + fprintf (stdout, " PCI Data Structure\n"); + fprintf ( + stdout, + " Signature %c%c%c%c\n", + (char) PciDs.Signature, + (char) (PciDs.Signature >> 8), + (char) (PciDs.Signature >> 16), + (char) (PciDs.Signature >> 24) + ); + fprintf (stdout, " Vendor ID 0x%04X\n", PciDs.VendorId); + fprintf (stdout, " Device ID 0x%04X\n", PciDs.DeviceId); + fprintf ( + stdout, + " Class Code 0x%06X\n", + (UINT32) (PciDs.ClassCode[0] | (PciDs.ClassCode[1] << 8) | (PciDs.ClassCode[2] << 16)) + ); + fprintf (stdout, " Image size 0x%X\n", PciDs.ImageLength * 512); + fprintf (stdout, " Code revision: 0x%04X\n", PciDs.CodeRevision); + fprintf (stdout, " Indicator 0x%02X", (UINT32) PciDs.Indicator); + // + // Print the indicator, used to flag the last image + // + if (PciDs.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. + // + fprintf (stdout, " Code type 0x%02X", (UINT32) PciDs.CodeType); + if (PciDs.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)) { + fprintf (stdout, "ERROR: Failed to re-seek to ROM header structure\n"); + goto BailOut; + } + + if (fread (&EfiRomHdr, sizeof (EfiRomHdr), 1, InFptr) != 1) { + fprintf (stdout, "ERROR: Failed to read EFI PCI ROM header from file\n"); + goto BailOut; + } + // + // Now dump more info + // + fprintf (stdout, " EFI Signature 0x%04X\n", EfiRomHdr.EfiSignature); + fprintf ( + stdout, + " Compression Type 0x%04X ", + (UINT32) 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", + (UINT32) EfiRomHdr.EfiImageHeaderOffset, + (UINT32) (EfiRomHdr.EfiImageHeaderOffset + 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 (PciDs.Indicator == INDICATOR_LAST) { + goto BailOut; + } + // + // Seek to the start of the next image + // + if (fseek (InFptr, ImageStart + (PciDs.ImageLength * 512), SEEK_SET)) { + fprintf (stdout, "ERROR: Failed to seek to next image\n"); + 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/EdkCompatibilityPkg/Sample/Tools/Source/EfiRom/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/EfiRom/Makefile new file mode 100644 index 0000000000..2832154763 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/EfiRom/Makefile @@ -0,0 +1,85 @@ +#/*++ +# +# Copyright (c) 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Makefile +# +# Abstract: +# +# makefile for building the EfiRom utility. +# +#--*/ + +# +# Make sure environmental variable EDK_SOURCE is set +# +!IFNDEF EDK_SOURCE +!ERROR EDK_SOURCE environmental variable not set +!ENDIF + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Target specific information +# + +TARGET_NAME = EfiRom +TARGET_SOURCE_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) + +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).exe +# +# Build targets +# + +all: $(TARGET_EXE) + +OBJECTS = $(EDK_TOOLS_OUTPUT)\EfiRom.obj \ + $(EDK_TOOLS_OUTPUT)\EfiCompress.obj + +# +# Build the EXE by compiling the source files, then linking the resultant +# object files together. +# + +$(EDK_TOOLS_OUTPUT)\EfiRom.obj : $(TARGET_SOURCE_DIR)\EfiRom.c + $(CC) $(C_FLAGS) $(TARGET_SOURCE_DIR)\EfiRom.c /Fo$@ + +$(EDK_TOOLS_OUTPUT)\EfiCompress.obj : $(EDK_TOOLS_SOURCE)\Common\EfiCompress.c + $(CC) $(C_FLAGS) $(EDK_TOOLS_SOURCE)\Common\EfiCompress.c /Fo$@ + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE): $(OBJECTS) + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/EfildrImage/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/EfildrImage/Makefile new file mode 100644 index 0000000000..155680107d --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/EfildrImage/Makefile @@ -0,0 +1,96 @@ +#/*++ +# +# Copyright (c) 2006 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Makefile +# +# Abstract: +# +# makefile for building the EfildrImage utility. +# +#--*/ + +# +# Make sure environmental variable EDK_SOURCE is set +# +!IFNDEF EDK_SOURCE +!ERROR EDK_SOURCE environmental variable not set +!ENDIF + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Define some macros we use here. Should get rid of them someday and +# get rid of the extra level of indirection. +# +COMMON_SOURCE = $(EDK_TOOLS_COMMON) + +# +# Common information +# + +INC=$(INC) + +# +# Target specific information +# + +TARGET_NAME=EfildrImage +TARGET_SOURCE_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) + +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).exe + +TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\EfildrImage.c" +TARGET_EXE_INCLUDE = + + +# +# Build targets +# + +all: $(TARGET_EXE) + +# +# Build EXE +# + +$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE) + $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE): $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) /out:$(TARGET_EXE) $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL + diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/EfildrImage/efildrimage.c b/EdkCompatibilityPkg/Sample/Tools/Source/EfildrImage/efildrimage.c new file mode 100644 index 0000000000..c072dd73ac --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/EfildrImage/efildrimage.c @@ -0,0 +1,188 @@ +/*++ + +Copyright 2006 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + efildrimage.c + +Abstract: + + Creates and EFILDR image. + This tool combines several PE Image files together using following format denoted as EBNF: + FILE := EFILDR_HEADER + EFILDR_IMAGE + + + + The order of EFILDR_IMAGE is same as the order of placing PeImageFileContent. + +Revision History + +--*/ + + +#include +#include +#include "Tiano.h" + +#define MAX_PE_IMAGES 63 +#define FILE_TYPE_FIXED_LOADER 0 +#define FILE_TYPE_RELOCATABLE_PE_IMAGE 1 + +typedef struct { + UINT32 CheckSum; + UINT32 Offset; + UINT32 Length; + UINT8 FileName[52]; +} EFILDR_IMAGE; + +typedef struct { + UINT32 Signature; + UINT32 HeaderCheckSum; + UINT32 FileLength; + UINT32 NumberOfImages; +} EFILDR_HEADER; + + + +VOID +Usage ( + VOID + ) +{ + printf ("Usage: EfiLdrImage OutImage LoaderImage PeImage1 PeImage2 ... PeImageN"); + exit (1); +} + +ULONG +FCopyFile ( + FILE *in, + FILE *out + ) +/*++ +Routine Description: + Write all the content of input file to output file. + +Arguments: + in - input file pointer + out - output file pointer + +Return: + ULONG : file size of input file +--*/ +{ + ULONG filesize, offset, length; + UCHAR Buffer[8*1024]; + + fseek (in, 0, SEEK_END); + filesize = ftell(in); + + fseek (in, 0, SEEK_SET); + + offset = 0; + while (offset < filesize) { + length = sizeof(Buffer); + if (filesize-offset < length) { + length = filesize-offset; + } + + fread (Buffer, length, 1, in); + fwrite (Buffer, length, 1, out); + offset += length; + } + + return filesize; +} + + +int +main ( + int argc, + char *argv[] + ) +/*++ + +Routine Description: + + +Arguments: + + +Returns: + + +--*/ +{ + ULONG i; + ULONG filesize; + FILE *fpIn, *fpOut; + EFILDR_HEADER EfiLdrHeader; + EFILDR_IMAGE EfiLdrImage[MAX_PE_IMAGES]; + + if (argc < 4) { + Usage(); + } + + // + // Open output file for write + // + fpOut = fopen(argv[1], "w+b"); + if (!fpOut) { + printf ("efildrimage: Could not open output file %s\n", argv[1]); + exit(1); + } + + memset (&EfiLdrHeader, 0, sizeof (EfiLdrHeader)); + memset (&EfiLdrImage, 0, sizeof (EFILDR_IMAGE) * (argc - 2)); + + memcpy (&EfiLdrHeader.Signature, "EFIL", 4); + EfiLdrHeader.FileLength = sizeof(EFILDR_HEADER) + sizeof(EFILDR_IMAGE)*(argc-2); + + // + // Skip the file header first + // + fseek (fpOut, EfiLdrHeader.FileLength, SEEK_SET); + + // + // copy all the input files to the output file + // + for(i=2;i<(ULONG)argc;i++) { + // + // Copy the content of PeImage file to output file + // + fpIn = fopen (argv[i], "rb"); + if (!fpIn) { + printf ("efildrimage: Could not open input file %s\n", argv[i-2]); + exit(1); + } + filesize = FCopyFile (fpIn, fpOut); + fclose(fpIn); + + // + // And in the same time update the EfiLdrHeader and EfiLdrImage array + // + EfiLdrImage[i-2].Offset = EfiLdrHeader.FileLength; + EfiLdrImage[i-2].Length = filesize; + strncpy (EfiLdrImage[i-2].FileName, argv[i], sizeof (EfiLdrImage[i-2].FileName) - 1); + EfiLdrHeader.FileLength += filesize; + EfiLdrHeader.NumberOfImages++; + } + + // + // Write the image header to the output file finally + // + fseek (fpOut, 0, SEEK_SET); + fwrite (&EfiLdrHeader, sizeof(EFILDR_HEADER) , 1, fpOut); + fwrite (&EfiLdrImage , sizeof(EFILDR_IMAGE)*(argc-2), 1, fpOut); + + fclose (fpOut); + printf ("Created %s\n", argv[1]); + return 0; +} + diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/FwImage/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/FwImage/Makefile new file mode 100644 index 0000000000..216ac9782b --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/FwImage/Makefile @@ -0,0 +1,86 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: makefile +# +# Abstract: +# +# This file is used to build the EFI utility. +# +#--*/ + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Define some macros we use here. Should get rid of them someday and +# get rid of the extra level of indirection. +# +COMMON_SOURCE = $(EDK_TOOLS_COMMON) + +# +# Common information +# + +INC=$(INC) + +# +# Target specific information +# + +TARGET_NAME=FwImage +TARGET_SOURCE_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) + +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).exe + +TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\FwImage.c" +TARGET_EXE_INCLUDE = "$(EDK_SOURCE)\Foundation\Include\TianoCommon.h" \ + "$(EDK_SOURCE)\Foundation\Efi\Include\EfiImage.h" +OBJECTS = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj +# +# Build targets +# + +all: $(TARGET_EXE) + +# +# Build EXE +# + +$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE) + $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE) : $(OBJECTS) + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/FwImage/fwimage.c b/EdkCompatibilityPkg/Sample/Tools/Source/FwImage/fwimage.c new file mode 100644 index 0000000000..8a9274d5c0 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/FwImage/fwimage.c @@ -0,0 +1,587 @@ +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + fwimage.c + +Abstract: + + Converts a pe32/pe32+ image to an FW image type + +--*/ + +#include +#include +#include +#include +#include + +#include "TianoCommon.h" +#include "EfiImage.h" +#include "EfiUtilityMsgs.c" + +#define UTILITY_NAME "FwImage" + +typedef union { + IMAGE_NT_HEADERS32 PeHeader32; + IMAGE_NT_HEADERS64 PeHeader64; +} PE_HEADER; + +VOID +Usage ( + VOID + ) +{ + printf ("Usage: " UTILITY_NAME " {-t time-date} {-e} {-r} [APPLICATION|BS_DRIVER|RT_DRIVER|SAL_RT_DRIVER|COMBINED_PEIM_DRIVER|SECURITY_CORE|PEI_CORE|PE32_PEIM|RELOCATABLE_PEIM] peimage [outimage]\n"); + printf (" -t: Add Time Stamp for output image\n"); + printf (" -e: Not clear ExceptionTable for output image\n"); + printf (" -r: Not strip zero pending of .reloc for output image\n"); +} + +static +STATUS +FReadFile ( + FILE *in, + VOID **Buffer, + UINTN *Length + ) +{ + fseek (in, 0, SEEK_END); + *Length = ftell (in); + *Buffer = malloc (*Length); + fseek (in, 0, SEEK_SET); + fread (*Buffer, *Length, 1, in); + return STATUS_SUCCESS; +} + +static +STATUS +FWriteFile ( + FILE *out, + VOID *Buffer, + UINTN Length + ) +{ + fseek (out, 0, SEEK_SET); + fwrite (Buffer, Length, 1, out); + if ((ULONG) ftell (out) != Length) { + Error (NULL, 0, 0, "write error", NULL); + return STATUS_ERROR; + } + free (Buffer); + return STATUS_SUCCESS; +} + +VOID +ZeroExceptionTable ( + IN UINT8 *FileBuffer, + IN EFI_IMAGE_DOS_HEADER *DosHdr, + IN PE_HEADER *PeHdr + ) +{ + UINT32 PdataSize; + UINT32 PdataOffset; + UINT32 PdataRVASize; + UINT32 PdataRVA; + UINT32 SectionOffset; + UINT16 SectionNumber; + UINT32 SectionNameSize; + EFI_IMAGE_SECTION_HEADER *Section; + + PdataSize = 0; + PdataOffset = 0; + PdataRVASize = 0; + PdataRVA = 0; + SectionOffset = 0; + + // + // Search .pdata section + // + if (PeHdr->PeHeader32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + if ((PeHdr->PeHeader32.OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_EXCEPTION) && + (PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0) && + (PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0)) { + + PdataRVA = PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress; + PdataRVASize = PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size; + + PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0; + PeHdr->PeHeader32.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0; + + SectionOffset = sizeof(PeHdr->PeHeader32); + } + } else { + if ((PeHdr->PeHeader64.OptionalHeader.NumberOfRvaAndSizes > IMAGE_DIRECTORY_ENTRY_EXCEPTION) && + (PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress != 0) && + (PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size != 0)) { + + PdataRVA = PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress; + PdataRVASize = PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size; + + PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress = 0; + PeHdr->PeHeader64.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size = 0; + + SectionOffset = sizeof(PeHdr->PeHeader64); + } + } + + if ((PdataRVASize != 0) && (PdataRVA != 0)) { + + SectionNumber = PeHdr->PeHeader32.FileHeader.NumberOfSections; + SectionNameSize = sizeof(Section->Name); + while (SectionNumber > 0) { + Section = (EFI_IMAGE_SECTION_HEADER *) &FileBuffer[DosHdr->e_lfanew + SectionOffset]; + if (strcmp (Section->Name, ".pdata") == 0) { + // + // Zero .pdata Section Header Name + // + memset ( + FileBuffer + DosHdr->e_lfanew + SectionOffset, + 0, + SectionNameSize); + + // + // Zero .pdata Secton raw data + // + PdataOffset = Section->PointerToRawData; + PdataSize = Section->SizeOfRawData; + memset (FileBuffer + PdataOffset, 0, PdataSize); + break; + } + SectionNumber--; + SectionOffset += sizeof(EFI_IMAGE_SECTION_HEADER); + } + } + + return ; +} + +VOID +StripZeroPendingReloc ( + IN UINT8 *FileBuffer, + IN OUT UINTN *FileLength, + IN EFI_IMAGE_DOS_HEADER *DosHdr, + IN PE_HEADER *PeHdr + ) +{ + EFI_IMAGE_OPTIONAL_HEADER32 *Optional32; + EFI_IMAGE_OPTIONAL_HEADER64 *Optional64; + EFI_IMAGE_SECTION_HEADER *SectionHeader; + UINTN AllignedRelocSize; + UINTN Index; + + if (PeHdr->PeHeader32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->PeHeader32.OptionalHeader; + if ((Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) && + (Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->PeHeader32.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->PeHeader32.FileHeader.NumberOfSections; Index++, SectionHeader++) { + // + // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory + // + if (strcmp (SectionHeader->Name, ".reloc") == 0) { + 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; + } + } + } + } + } + } else { + Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->PeHeader64.OptionalHeader; + if ((Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) && + (Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC].Size != 0)) { + SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(FileBuffer + DosHdr->e_lfanew + sizeof(UINT32) + sizeof (EFI_IMAGE_FILE_HEADER) + PeHdr->PeHeader64.FileHeader.SizeOfOptionalHeader); + for (Index = 0; Index < PeHdr->PeHeader64.FileHeader.NumberOfSections; Index++, SectionHeader++) { + // + // Look for the Section Header that starts as the same virtual address as the Base Relocation Data Directory + // + if (strcmp (SectionHeader->Name, ".reloc") == 0) { + 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; + } + } + } + } + } + } +} + +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. + +--*/ +{ + ULONG Type; + PUCHAR Ext; + PUCHAR p; + PUCHAR pe; + PUCHAR OutImageName; + UCHAR outname[500]; + FILE *fpIn; + FILE *fpOut; + EFI_IMAGE_DOS_HEADER *DosHdr; + PE_HEADER *PeHdr; + time_t TimeStamp; + struct tm TimeStruct; + EFI_IMAGE_DOS_HEADER BackupDosHdr; + ULONG Index; + BOOLEAN TimeStampPresent; + BOOLEAN NeedClearExceptionTable; + BOOLEAN NeedStripZeroPendingReloc; + UINT8 *FileBuffer; + UINTN FileLength; + EFI_IMAGE_OPTIONAL_HEADER32 *Optional32; + EFI_IMAGE_OPTIONAL_HEADER64 *Optional64; + + SetUtilityName (UTILITY_NAME); + // + // Assign to fix compile warning + // + OutImageName = NULL; + Type = 0; + Ext = 0; + TimeStamp = 0; + TimeStampPresent = FALSE; + + NeedClearExceptionTable = TRUE; + NeedStripZeroPendingReloc = TRUE; + + // + // Look for -t time-date option first. If the time is "0", then + // skip it. + // + if ((argc > 2) && !strcmp (argv[1], "-t")) { + TimeStampPresent = TRUE; + if (strcmp (argv[2], "0") != 0) { + // + // Convert the string to a value + // + memset ((char *) &TimeStruct, 0, sizeof (TimeStruct)); + if (sscanf( + argv[2], "%d/%d/%d,%d:%d:%d", + &TimeStruct.tm_mon, /* months since January - [0,11] */ + &TimeStruct.tm_mday, /* day of the month - [1,31] */ + &TimeStruct.tm_year, /* years since 1900 */ + &TimeStruct.tm_hour, /* hours since midnight - [0,23] */ + &TimeStruct.tm_min, /* minutes after the hour - [0,59] */ + &TimeStruct.tm_sec /* seconds after the minute - [0,59] */ + ) != 6) { + Error (NULL, 0, 0, argv[2], "failed to convert to mm/dd/yyyy,hh:mm:ss format"); + return STATUS_ERROR; + } + // + // Now fixup some of the fields + // + TimeStruct.tm_mon--; + TimeStruct.tm_year -= 1900; + // + // Sanity-check values? + // Convert + // + TimeStamp = mktime (&TimeStruct); + if (TimeStamp == (time_t) - 1) { + Error (NULL, 0, 0, argv[2], "failed to convert time"); + return STATUS_ERROR; + } + } + // + // Skip over the args + // + argc -= 2; + argv += 2; + } + + // + // Look for -e option. + // + if ((argc > 1) && !strcmp (argv[1], "-e")) { + NeedClearExceptionTable = FALSE; + // + // Skip over the args + // + argc -= 1; + argv += 1; + } + + // + // Look for -r option + // + if ((argc > 1) && !strcmp (argv[1], "-r")) { + NeedStripZeroPendingReloc = FALSE; + // + // Skip over the args + // + argc -= 1; + argv += 1; + } + + // + // Check for enough args + // + if (argc < 3) { + Usage (); + return STATUS_ERROR; + } + + if (argc == 4) { + OutImageName = argv[3]; + } + // + // Get new image type + // + p = argv[1]; + if (*p == '/' || *p == '\\') { + p += 1; + } + + if (_stricmp (p, "app") == 0 || _stricmp (p, "APPLICATION") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION; + Ext = ".efi"; + + } else if (_stricmp (p, "bsdrv") == 0 || _stricmp (p, "BS_DRIVER") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; + Ext = ".efi"; + + } else if (_stricmp (p, "rtdrv") == 0 || _stricmp (p, "RT_DRIVER") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER; + Ext = ".efi"; + + } else if (_stricmp (p, "rtdrv") == 0 || _stricmp (p, "SAL_RT_DRIVER") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER; + Ext = ".efi"; + } else if (_stricmp (p, "SECURITY_CORE") == 0) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; + Ext = ".sec"; + } else if (_stricmp (p, "peim") == 0 || + _stricmp (p, "PEI_CORE") == 0 || + _stricmp (p, "PE32_PEIM") == 0 || + _stricmp (p, "RELOCATABLE_PEIM") == 0 || + _stricmp (p, "combined_peim_driver") == 0 + ) { + Type = EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; + Ext = ".pei"; + } else { + Usage (); + return STATUS_ERROR; + } + // + // open source file + // + fpIn = fopen (argv[2], "rb"); + if (!fpIn) { + Error (NULL, 0, 0, argv[2], "failed to open input file for reading"); + return STATUS_ERROR; + } + FReadFile (fpIn, (VOID **)&FileBuffer, &FileLength); + // + // Read the dos & pe hdrs of the image + // + DosHdr = (EFI_IMAGE_DOS_HEADER *) FileBuffer; + if (DosHdr->e_magic != IMAGE_DOS_SIGNATURE) { + Error (NULL, 0, 0, argv[2], "DOS header signature not found in source image"); + fclose (fpIn); + return STATUS_ERROR; + } + + PeHdr = (PE_HEADER *)(FileBuffer + DosHdr->e_lfanew); + if (PeHdr->PeHeader32.Signature != IMAGE_NT_SIGNATURE) { + Error (NULL, 0, 0, argv[2], "PE header signature not found in source image"); + fclose (fpIn); + return STATUS_ERROR; + } + // + // open output file + // + strcpy (outname, argv[2]); + pe = NULL; + for (p = outname; *p; p++) { + if (*p == '.') { + pe = p; + } + } + + if (!pe) { + pe = p; + } + + strcpy (pe, Ext); + + if (!OutImageName) { + OutImageName = outname; + } + + fpOut = fopen (OutImageName, "w+b"); + if (!fpOut) { + Error (NULL, 0, 0, OutImageName, "could not open output file for writing"); + fclose (fpIn); + return STATUS_ERROR; + } + // + // Zero all unused fields of the DOS header + // + 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 < (ULONG) DosHdr->e_lfanew; Index++) { + FileBuffer[Index] = (UINT8) DosHdr->e_cp; + } + + // + // Modify some fields in the PE header + // + + // + // TimeDateStamp's offset is fixed for PE32/32+ + // + if (TimeStampPresent) { + PeHdr->PeHeader32.FileHeader.TimeDateStamp = (UINT32) TimeStamp; + } + + // + // PE32/32+ has different optional header layout + // Determine format is PE32 or PE32+ before modification + // + if (PeHdr->PeHeader32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + // + // PE32 image + // + Optional32 = (EFI_IMAGE_OPTIONAL_HEADER32 *)&PeHdr->PeHeader32.OptionalHeader; + + Optional32->MajorLinkerVersion = 0; + Optional32->MinorLinkerVersion = 0; + 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; + Optional32->Subsystem = (USHORT) Type; + + // + // Strip zero padding at the end of the .reloc section + // + if (NeedStripZeroPendingReloc) { + StripZeroPendingReloc (FileBuffer, &FileLength, DosHdr, PeHdr); + } + } else if (PeHdr->PeHeader32.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + // + // PE32+ image + // + Optional64 = (EFI_IMAGE_OPTIONAL_HEADER64 *)&PeHdr->PeHeader64.OptionalHeader; + + Optional64->MajorLinkerVersion = 0; + Optional64->MinorLinkerVersion = 0; + 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; + Optional64->Subsystem = (USHORT) Type; + + // + // Strip zero padding at the end of the .reloc section + // + if (NeedStripZeroPendingReloc) { + StripZeroPendingReloc (FileBuffer, &FileLength, DosHdr, PeHdr); + } + } else { + Error (NULL, 0, 0, argv[2], "Unsupported PE image"); + fclose (fpIn); + fclose (fpOut); + return STATUS_ERROR; + } + + // + // Zero PDATA section for smaller binary size after compression + // + if (NeedClearExceptionTable) { + ZeroExceptionTable (FileBuffer, DosHdr, PeHdr); + } + + FWriteFile (fpOut, FileBuffer, FileLength); + + // + // Done + // + fclose (fpIn); + fclose (fpOut); + + return STATUS_SUCCESS; +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenAprioriFile/GenAprioriFile.c b/EdkCompatibilityPkg/Sample/Tools/Source/GenAprioriFile/GenAprioriFile.c new file mode 100644 index 0000000000..98cbb072de --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenAprioriFile/GenAprioriFile.c @@ -0,0 +1,467 @@ +/*++ + + Copyright (c) 2006, Intel Corporation + All rights reserved. This program and the accompanying materials + are licensed and made available under the terms and conditions of the BSD License + which accompanies this distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license.php + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + +Module Name: + + GenAprioriFile.c + +Abstract: + + Given an input file containing a list of GUIDs (or Guided file names), + convert the file to an Apriori file consumable by the dispatcher. + +--*/ + +#include +#include +#include + +#include "EfiCommon.h" +#include "ParseInf.h" +#include "CommonLib.h" // for compare guid +#include "EfiUtilityMsgs.h" + +#define MAX_LINE_LEN 200 +#define MAX_PATH 200 + +// +// typedef unsigned int STATUS; +// #define STATUS_SUCCESS 0 +// #define STATUS_WARNING 1 +// #define STATUS_ERROR 2 +// +#define UTILITY_NAME "GenAprioriFile" +// +// Here's all our globals. +// +static struct { + FILE *BinFptr; // output dependencies to this file + INT8 *AprioriFileName; + INT8 *OutputFileName; + BOOLEAN Intelligent; + BOOLEAN Verbose; + BOOLEAN NullTerminate; +} mGlobals; + +static +STATUS +ProcessArgs ( + int Argc, + char *Argv[] + ); + +static +BOOLEAN +IsCommentLine ( + INT8 *Line + ); + +static +void +Usage ( + VOID + ); + +int +main ( + int Argc, + char *Argv[] + ) +/*++ + +Routine Description: + + Call the routine to parse the command-line options, then process the + Apriori list file and generate the GUID file. + +Arguments: + + Standard C main() argc and argv. + +Returns: + + 0 if successful + nonzero otherwise + +--*/ +// GC_TODO: Argc - add argument and description to function comment +// GC_TODO: ] - add argument and description to function comment +{ + STATUS Status; + FILE *AprioriFptr; + FILE *BinFptr; + INT8 Line[MAX_LINE_LEN]; + EFI_GUID Guid; + EFI_GUID GuidIn; + EFI_GUID ZeroGuid; + UINT32 LineCounter; + // + // Initialize the error printing routines + // + SetUtilityName (UTILITY_NAME); + // + // Clear our globals + // + memset ((char *) &mGlobals, 0, sizeof (mGlobals)); + memset ((char *) &ZeroGuid, 0, sizeof (ZeroGuid)); + AprioriFptr = NULL; + BinFptr = NULL; + + // + // Process the command-line arguments + // + Status = ProcessArgs (Argc, Argv); + if (Status != STATUS_SUCCESS) { + return Status; + } + // + // If arguments were ok, then open the Apriori file and process it. + // + if ((AprioriFptr = fopen (mGlobals.AprioriFileName, "r")) == NULL) { + Error (NULL, 0, 0, mGlobals.AprioriFileName, "failed to open file for reading"); + goto FinishUp; + } + // + // If -i intelligent option specified, then attempt to read and + // existing output file and see if we'd be creating an identical file. + // + if (mGlobals.Intelligent) { + if ((BinFptr = fopen (mGlobals.OutputFileName, "rb")) == NULL) { + if (mGlobals.Verbose) { + DebugMsg (NULL, 0, 0, "Creating new apriori file -- no existing file", NULL); + } + + goto CreateFile; + } + // + // Read lines from the input file until done. Convert each to a guid, then + // read a guid from the input file and compare them. + // + while (fgets (Line, sizeof (Line), AprioriFptr) != NULL) { + + if (IsCommentLine (Line)) { + continue; + } + // + // Convert to a guid + // + if (StringToGuid (Line, &Guid) != EFI_SUCCESS) { + if (mGlobals.Verbose) { + DebugMsg (NULL, 0, 0, "failed to read GUID from input text file -- creating new file", NULL); + } + + goto CreateFile; + } + // + // Read guid from input file, then compare + // + if (fread (&GuidIn, sizeof (GuidIn), 1, BinFptr) != 1) { + if (mGlobals.Verbose) { + DebugMsg (NULL, 0, 0, "failed to read GUID from input binary file -- creating new file", NULL); + } + + goto CreateFile; + } + + if (CompareGuid (&Guid, &GuidIn) != 0) { + if (mGlobals.Verbose) { + DebugMsg (NULL, 0, 0, "GUID comparison failed -- creating new file", NULL); + } + + goto CreateFile; + } + } + // + // May be one more NULL guid in the binary file + // + if (mGlobals.NullTerminate) { + if (fread (&GuidIn, sizeof (GuidIn), 1, BinFptr) != 1) { + if (mGlobals.Verbose) { + DebugMsg (NULL, 0, 0, "failed to read NULL GUID from input binary file -- creating new file", NULL); + } + + goto CreateFile; + } + + if (CompareGuid (&GuidIn, &ZeroGuid) != 0) { + if (mGlobals.Verbose) { + DebugMsg (NULL, 0, 0, "NULL GUID comparison failed -- creating new file", NULL); + } + + goto CreateFile; + } + } + // + // Make sure we're at the end of both files. + // + if ((fgets (Line, sizeof (Line), AprioriFptr) != NULL) || (fread (&GuidIn, 1, 1, BinFptr) != 0)) { + if (mGlobals.Verbose) { + DebugMsg (NULL, 0, 0, "file sizes different, -i test failed -- creating new file", NULL); + } + + goto CreateFile; + } + + if (mGlobals.Verbose) { + DebugMsg (NULL, 0, 0, "existing file would be unchanged -- keeping existing apriori file", NULL); + } + + goto FinishUp; + } + +CreateFile: + // + // Rewind the Apriori file in case -i was specified. Also + // try to close the output file for the case where we prescanned + // it (again, because of -i). + // + rewind (AprioriFptr); + if (BinFptr != NULL) { + fclose (BinFptr); + } + // + // Open the output file + // + if ((BinFptr = fopen (mGlobals.OutputFileName, "wb")) == NULL) { + Error (NULL, 0, 0, mGlobals.OutputFileName, "could not open input file"); + goto FinishUp; + } + // + // Read lines until we're done + // + LineCounter = 0; + while (fgets (Line, sizeof (Line), AprioriFptr) != NULL) { + LineCounter++; + if (IsCommentLine (Line)) { + continue; + } + // + // Convert to a GUID + // + if (StringToGuid (Line, &Guid) != EFI_SUCCESS) { + Error (mGlobals.AprioriFileName, LineCounter, 0, "failed to convert GUID", NULL); + goto FinishUp; + } + // + // Write the guid to the output file + // + if (fwrite (&Guid, sizeof (Guid), 1, BinFptr) != 1) { + Error (NULL, 0, 0, mGlobals.OutputFileName, "failed to write GUID to output file"); + goto FinishUp; + } + } + // + // Write a null guid out to terminate the list + // + if (mGlobals.NullTerminate) { + memset ((void *) &Guid, 0, sizeof (Guid)); + if (fwrite (&Guid, sizeof (Guid), 1, BinFptr) != 1) { + Error (NULL, 0, 0, mGlobals.OutputFileName, "failed to write NULL termination GUID to output file"); + } + } + +FinishUp: + + if (AprioriFptr != NULL) { + fclose (AprioriFptr); + } + + if (BinFptr != NULL) { + fclose (BinFptr); + } + + return GetUtilityStatus (); +} + +static +BOOLEAN +IsCommentLine ( + INT8 *Line + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + Line - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + for (; isspace (*Line) && *Line; Line++) + ; + + // + // Allow # or // comments + // + if ((*Line == '#') || ((*Line == '/') && (*(Line + 1) == '/')) || (*Line == '\n') || (*Line == 0)) { + return TRUE; + } + + return FALSE; +} +// +// Process the command-line arguments +// +static +STATUS +ProcessArgs ( + 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 + +--*/ +{ + // + // Skip program name + // + Argc--; + Argv++; + + // + // Process until no more args + // + while (Argc) { + // + // -f AprioriFile + // + if (_stricmp (Argv[0], "-f") == 0) { + // + // check for one more arg + // + if (Argc > 1) { + mGlobals.AprioriFileName = Argv[1]; + } else { + Error (NULL, 0, 0, NULL, "missing filename with %s", Argv[0]); + Usage (); + return STATUS_ERROR; + } + + Argc--; + Argv++; + } else if (_stricmp (Argv[0], "-i") == 0) { + // + // intelligent creation of output file. That is to say, if + // there's already a file there, and it's the same as what + // we'd create, then don't re-create. This is to support + // incremental builds (that is to say, running nmake a second time + // does nothing). + // + mGlobals.Intelligent = TRUE; + } else if (_stricmp (Argv[0], "-v") == 0) { + mGlobals.Verbose = TRUE; + } else if (_stricmp (Argv[0], "-null") == 0) { + mGlobals.NullTerminate = TRUE; + } else if (_stricmp (Argv[0], "-o") == 0) { + // + // -o OutputFileName + // check for one more arg + // + if (Argc > 1) { + mGlobals.OutputFileName = Argv[1]; + } else { + Error (NULL, 0, 0, NULL, "missing filename argument with %s", Argv[0]); + Usage (); + return STATUS_ERROR; + } + + Argc--; + Argv++; + } else if ((_stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) { + Usage (); + return STATUS_ERROR; + } else { + Error (NULL, 0, 0, Argv[0], "unrecognized option"); + Usage (); + return STATUS_ERROR; + } + + Argc--; + Argv++; + } + // + // Had to specify the apriori input file and output file names + // + if (mGlobals.AprioriFileName == NULL) { + Error (NULL, 0, 0, "must specify -f AprioriFile", NULL); + Usage (); + return STATUS_ERROR; + } + + if (mGlobals.OutputFileName == NULL) { + Error (NULL, 0, 0, "must specify -o OutputFile", NULL); + Usage (); + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} + +static +void +Usage ( + VOID + ) +/*++ + +Routine Description: + + Print usage information for this utility. + +Arguments: + + None. + +Returns: + + Nothing. + +--*/ +{ + int Index; + static const char *Str[] = { + UTILITY_NAME " -- create an Apriori file consumable by the DXE dispatcher", + " Usage: "UTILITY_NAME " [Options]", + " Options include:", + " -h or -? for this help information", + " -f AprioriFile parse the GUID'ed files in AprioriFile (required)", + " -o OutputFile write output to OutputFile (required)", + " -i for intelligent re-creation of OutputFile", + " -null to terminate the output file with a NULL GUID", + " -v verbose option", + "", + NULL + }; + for (Index = 0; Str[Index] != NULL; Index++) { + fprintf (stdout, "%s\n", Str[Index]); + } +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenAprioriFile/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/GenAprioriFile/Makefile new file mode 100644 index 0000000000..887da4fc8e --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenAprioriFile/Makefile @@ -0,0 +1,78 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# makefile +# +# Abstract: +# +# makefile for building the GenAproriFile utility. +# +# Revision History +# +#--*/ + + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Target specific information +# + +TARGET_NAME = GenAprioriFile +TARGET_SRC_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\GenAprioriFile.exe +LIBS = $(EDK_TOOLS_OUTPUT)\Common.lib + +# +# Build targets +# + +all: $(TARGET_EXE) + +OBJECTS = $(EDK_TOOLS_OUTPUT)\GenAprioriFile.obj + +# +# Compile each source file +# +$(EDK_TOOLS_OUTPUT)\GenAprioriFile.obj : $(TARGET_SRC_DIR)\GenAprioriFile.c $(INC_DEPS) + $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\GenAprioriFile.c /Fo$@ + +# +# Add Binary Build description for this tools. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE): $(OBJECTS) $(LIBS) + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.* del /q $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.* > NUL + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del /q $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL + diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/GetDrvNumOffset.c b/EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/GetDrvNumOffset.c new file mode 100644 index 0000000000..d16358b4e7 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/GetDrvNumOffset.c @@ -0,0 +1,58 @@ +#include "fat.h" +#include + +INTN +GetDrvNumOffset ( + IN VOID *BootSector + ) +{ + FAT_BPB_STRUCT *FatBpb; + UINTN RootDirSectors; + UINTN FATSz; + UINTN TotSec; + UINTN DataSec; + UINTN CountOfClusters; + + FatBpb = (FAT_BPB_STRUCT *) BootSector; + + // + // Check FAT type algorithm from FAT spec + // + RootDirSectors = ((FatBpb->Fat12_16.BPB_RootEntCnt * sizeof(FAT_DIRECTORY_ENTRY)) + + (FatBpb->Fat12_16.BPB_BytsPerSec - 1)) / FatBpb->Fat12_16.BPB_BytsPerSec; + + if (FatBpb->Fat12_16.BPB_FATSz16 != 0) { + FATSz = FatBpb->Fat12_16.BPB_FATSz16; + } else { + FATSz = FatBpb->Fat32.BPB_FATSz32; + } + if (FATSz == 0) { + fprintf (stderr, "ERROR: FAT: BPB_FATSz16, BPB_FATSz32 - 0, expected - Non-Zero\n"); + return -1; + } + + if (FatBpb->Fat12_16.BPB_TotSec16 != 0) { + TotSec = FatBpb->Fat12_16.BPB_TotSec16; + } else { + TotSec = FatBpb->Fat12_16.BPB_TotSec32; + } + if (TotSec == 0) { + fprintf (stderr, "ERROR: FAT: BPB_TotSec16, BPB_TotSec32 - 0, expected - Non-Zero\n"); + return -1; + } + + DataSec = TotSec - ( + FatBpb->Fat12_16.BPB_RsvdSecCnt + + FatBpb->Fat12_16.BPB_NumFATs * FATSz + + RootDirSectors + ); + + CountOfClusters = DataSec / FatBpb->Fat12_16.BPB_SecPerClus; + + if (CountOfClusters < FAT_MAX_FAT16_CLUSTER) { + return (INTN) ((UINTN) &FatBpb->Fat12_16.BS_DrvNum - (UINTN) FatBpb); + } else { + return (INTN) ((UINTN) &FatBpb->Fat32.BS_DrvNum - (UINTN) FatBpb); + } +} + diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/fat.h b/EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/fat.h new file mode 100644 index 0000000000..330312688b --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/fat.h @@ -0,0 +1,158 @@ +/*++ + +Copyright 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + fat.h + +Abstract: + +Revision History + +--*/ + +#ifndef _FAT_BPB_H_ +#define _FAT_BPB_H_ + +#include "Tiano.h" + +#pragma pack(1) + +typedef struct { + // + // Fat common field + // + UINT8 BS_jmpBoot[3]; + CHAR8 BS_OEMName[8]; + UINT16 BPB_BytsPerSec; + UINT8 BPB_SecPerClus; + UINT16 BPB_RsvdSecCnt; + UINT8 BPB_NumFATs; + UINT16 BPB_RootEntCnt; + UINT16 BPB_TotSec16; + UINT8 BPB_Media; + UINT16 BPB_FATSz16; + UINT16 BPB_SecPerTrk; + UINT16 BPB_NumHeads; + UINT32 BPB_HiddSec; + UINT32 BPB_TotSec32; + + // + // Fat12/16 specific field + // + UINT8 BS_DrvNum; + UINT8 BS_Reserved1; + UINT8 BS_BootSig; + UINT32 BS_VolID; + CHAR8 BS_VolLab[11]; + CHAR8 BS_FilSysType[8]; + + // + // Boot Code and Data + // + UINT8 Reserved[448]; + + // + // Fat common signature - 0xAA55 + // + UINT16 Signature; +} FAT12_16_BPB_STRUCT; + +typedef struct { + // + // Fat common field + // + UINT8 BS_jmpBoot[3]; + CHAR8 BS_OEMName[8]; + UINT16 BPB_BytsPerSec; + UINT8 BPB_SecPerClus; + UINT16 BPB_RsvdSecCnt; + UINT8 BPB_NumFATs; + UINT16 BPB_RootEntCnt; + UINT16 BPB_TotSec16; + UINT8 BPB_Media; + UINT16 BPB_FATSz16; + UINT16 BPB_SecPerTrk; + UINT16 BPB_NumHeads; + UINT32 BPB_HiddSec; + UINT32 BPB_TotSec32; + + // + // Fat32 specific field + // + UINT32 BPB_FATSz32; + UINT16 BPB_ExtFlags; + UINT16 BPB_FSVer; + UINT32 BPB_RootClus; + UINT16 BPB_FSInfo; + UINT16 BPB_BkBootSec; + UINT8 BPB_Reserved[12]; + UINT8 BS_DrvNum; + UINT8 BS_Reserved1; + UINT8 BS_BootSig; + UINT32 BS_VolID; + CHAR8 BS_VolLab[11]; + CHAR8 BS_FilSysType[8]; + + // + // Boot Code and Data + // + UINT8 Reserved[420]; + + // + // Fat common signature - 0xAA55 + // + UINT16 Signature; +} FAT32_BPB_STRUCT; + +typedef union { + FAT12_16_BPB_STRUCT Fat12_16; + FAT32_BPB_STRUCT Fat32; +} FAT_BPB_STRUCT; + +typedef enum { + FatTypeUnknown, + FatTypeFat12, + FatTypeFat16, + FatTypeFat32, + FatTypeMax +} FAT_TYPE; + +typedef struct { + CHAR8 DIR_Name[11]; + UINT8 DIR_Attr; + UINT8 DIR_NTRes; + UINT8 DIR_CrtTimeTenth; + UINT16 DIR_CrtTime; + UINT16 DIR_CrtDate; + UINT16 DIR_LstAccDate; + UINT16 DIR_FstClusHI; + UINT16 DIR_WrtTime; + UINT16 DIR_WrtDate; + UINT16 DIR_FstClusLO; + UINT32 DIR_FileSize; +} FAT_DIRECTORY_ENTRY; + +#pragma pack() + +#define FAT_MAX_FAT12_CLUSTER 0xFF5 +#define FAT_MAX_FAT16_CLUSTER 0xFFF5 + +#define FAT_BS_SIGNATURE 0xAA55 +#define FAT_BS_BOOTSIG 0x29 +#define FAT_BS_JMP1 0xEB +#define FAT_BS_JMP2 0xE9 +#define FAT_FILSYSTYPE "FAT " +#define FAT12_FILSYSTYPE "FAT12 " +#define FAT16_FILSYSTYPE "FAT16 " +#define FAT32_FILSYSTYPE "FAT32 " + +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/genbootsector.c b/EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/genbootsector.c new file mode 100644 index 0000000000..8438502b7c --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/genbootsector.c @@ -0,0 +1,652 @@ +/*++ + +Copyright 2006 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + genbootsector.c + +Abstract: + Reading/writing MBR/DBR. + NOTE: + If we write MBR to disk, we just update the MBR code and the partition table wouldn't be over written. + If we process DBR, we will patch MBR to set first partition active if no active partition exists. + +--*/ + +#include +#include +#include + +#define MAX_DRIVE 26 +#define PARTITION_TABLE_OFFSET 0x1BE + +#define SIZE_OF_PARTITION_ENTRY 0x10 + +#define PARTITION_ENTRY_STARTLBA_OFFSET 8 + +#define PARTITION_ENTRY_NUM 4 + +INT +GetDrvNumOffset ( + IN VOID *BootSector + ); + +typedef enum { + PatchTypeUnknown, + PatchTypeFloppy, + PatchTypeIde, + PatchTypeUsb, +} PATCH_TYPE; + +typedef enum { + ErrorSuccess, + ErrorFileCreate, + ErrorFileReadWrite, + ErrorNoMbr, + ErrorFatType +} ERROR_STATUS; + +CHAR *ErrorStatusDesc[] = { + "Success", + "Failed to create files", + "Failed to read/write files", + "No MBR exists", + "Failed to detect Fat type" +}; + +typedef struct _DRIVE_TYPE_DESC { + UINT Type; + CHAR *Description; +} DRIVE_TYPE_DESC; + +#define DRIVE_TYPE_ITEM(x) {x, #x} +DRIVE_TYPE_DESC DriveTypeDesc[] = { + DRIVE_TYPE_ITEM (DRIVE_UNKNOWN), + DRIVE_TYPE_ITEM (DRIVE_NO_ROOT_DIR), + DRIVE_TYPE_ITEM (DRIVE_REMOVABLE), + DRIVE_TYPE_ITEM (DRIVE_FIXED), + DRIVE_TYPE_ITEM (DRIVE_REMOTE), + DRIVE_TYPE_ITEM (DRIVE_CDROM), + DRIVE_TYPE_ITEM (DRIVE_RAMDISK), + (UINT) -1, NULL +}; + +typedef struct _DRIVE_INFO { + CHAR VolumeLetter; + DRIVE_TYPE_DESC *DriveType; + UINT DiskNumber; +} DRIVE_INFO; + +#define BOOT_SECTOR_LBA_OFFSET 0x1FA + +#define IsLetter(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z')) + +BOOL +GetDriveInfo ( + CHAR VolumeLetter, + DRIVE_INFO *DriveInfo + ) +/*++ +Routine Description: + Get drive information including disk number and drive type, + where disknumber is useful for reading/writing disk raw data. + NOTE: Floppy disk doesn't have disk number but it doesn't matter because + we can reading/writing floppy disk without disk number. + +Arguments: + VolumeLetter : volume letter, e.g.: C for C:, A for A: + DriveInfo : pointer to DRIVE_INFO structure receiving drive information. + +Return: + TRUE : successful + FALSE : failed +--*/ +{ + HANDLE VolumeHandle; + STORAGE_DEVICE_NUMBER StorageDeviceNumber; + DWORD BytesReturned; + BOOL Success; + UINT DriveType; + UINT Index; + + CHAR RootPath[] = "X:\\"; // "X:\" -> for GetDriveType + CHAR VolumeAccessPath[] = "\\\\.\\X:"; // "\\.\X:" -> to open the volume + + RootPath[0] = VolumeAccessPath[4] = VolumeLetter; + DriveType = GetDriveType(RootPath); + if (DriveType != DRIVE_REMOVABLE && DriveType != DRIVE_FIXED) { + return FALSE; + } + + DriveInfo->VolumeLetter = VolumeLetter; + VolumeHandle = CreateFile ( + VolumeAccessPath, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL + ); + if (VolumeHandle == INVALID_HANDLE_VALUE) { + fprintf ( + stderr, + "ERROR: CreateFile failed: Volume = %s, LastError = 0x%x\n", + VolumeAccessPath, + GetLastError () + ); + return FALSE; + } + + // + // Get Disk Number. It should fail when operating on floppy. That's ok + // because Disk Number is only needed when operating on Hard or USB disk. + // + // To direct write to disk: + // for USB and HD: use path = \\.\PHYSICALDRIVEx, where x is Disk Number + // for floppy: use path = \\.\X:, where X can be A or B + // + Success = DeviceIoControl( + VolumeHandle, + IOCTL_STORAGE_GET_DEVICE_NUMBER, + NULL, + 0, + &StorageDeviceNumber, + sizeof(StorageDeviceNumber), + &BytesReturned, + NULL + ); + // + // DeviceIoControl should fail if Volume is floppy or network drive. + // + if (!Success) { + DriveInfo->DiskNumber = (UINT) -1; + } else if (StorageDeviceNumber.DeviceType != FILE_DEVICE_DISK) { + // + // Only care about the disk. + // + return FALSE; + } else{ + DriveInfo->DiskNumber = StorageDeviceNumber.DeviceNumber; + } + CloseHandle(VolumeHandle); + + // + // Fill in the type string + // + DriveInfo->DriveType = NULL; + for (Index = 0; DriveTypeDesc[Index].Description != NULL; Index ++) { + if (DriveType == DriveTypeDesc[Index].Type) { + DriveInfo->DriveType = &DriveTypeDesc[Index]; + break; + } + } + + if (DriveInfo->DriveType == NULL) { + // + // Should have a type. + // + fprintf (stderr, "ERROR: fetal error!!!\n"); + return FALSE; + } + return TRUE; +} + +VOID +ListDrive ( + VOID + ) +/*++ +Routine Description: + List every drive in current system and their information. + +--*/ +{ + UINT Index; + DRIVE_INFO DriveInfo; + + UINT Mask = GetLogicalDrives(); + + for (Index = 0; Index < MAX_DRIVE; Index++) { + if (((Mask >> Index) & 0x1) == 1) { + if (GetDriveInfo ('A' + (CHAR) Index, &DriveInfo)) { + if (Index < 2) { + // Floppy will occupy 'A' and 'B' + fprintf ( + stdout, + "%c: - Type: %s\n", + DriveInfo.VolumeLetter, + DriveInfo.DriveType->Description + ); + } + else { + fprintf ( + stdout, + "%c: - DiskNum: %d, Type: %s\n", + DriveInfo.VolumeLetter, + DriveInfo.DiskNumber, + DriveInfo.DriveType->Description + ); + } + } + } + } + +} + +INT +GetBootSectorOffset ( + HANDLE DiskHandle, + BOOL WriteToDisk, + PATCH_TYPE PatchType + ) +/*++ +Description: + Get the offset of boot sector. + For non-MBR disk, offset is just 0 + for disk with MBR, offset needs to be caculated by parsing MBR + + NOTE: if no one is active, we will patch MBR to select first partition as active. + +Arguments: + DiskHandle : HANDLE of disk + WriteToDisk : TRUE indicates writing + PatchType : PatchTypeFloppy, PatchTypeIde, PatchTypeUsb + +Return: + -1 : failed + o.w. : Offset to boot sector +--*/ +{ + BYTE DiskPartition[0x200]; + DWORD BytesReturn; + DWORD DbrOffset; + DWORD Index; + BOOL HasMbr; + + DbrOffset = 0; + HasMbr = FALSE; + + SetFilePointer(DiskHandle, 0, NULL, FILE_BEGIN); + if (!ReadFile (DiskHandle, DiskPartition, 0x200, &BytesReturn, NULL)) { + return -1; + } + + // + // Check Signature, Jmp, and Boot Indicator. + // if all pass, we assume MBR found. + // + + // Check Signature: 55AA + if ((DiskPartition[0x1FE] == 0x55) && (DiskPartition[0x1FF] == 0xAA)) { + // Check Jmp: (EB ?? 90) or (E9 ?? ??) + if (((DiskPartition[0] != 0xEB) || (DiskPartition[2] != 0x90)) && + (DiskPartition[0] != 0xE9)) { + // Check Boot Indicator: 0x00 or 0x80 + // Boot Indicator is the first byte of Partition Entry + HasMbr = TRUE; + for (Index = 0; Index < PARTITION_ENTRY_NUM; ++Index) { + if ((DiskPartition[PARTITION_TABLE_OFFSET + Index * SIZE_OF_PARTITION_ENTRY] & 0x7F) != 0) { + HasMbr = FALSE; + break; + } + } + } + } + + if (HasMbr) { + // + // Skip MBR + // + for (Index = 0; Index < PARTITION_ENTRY_NUM; Index++) { + // + // Found Boot Indicator. + // + if (DiskPartition[PARTITION_TABLE_OFFSET + (Index * SIZE_OF_PARTITION_ENTRY)] == 0x80) { + DbrOffset = *(DWORD *)&DiskPartition[PARTITION_TABLE_OFFSET + (Index * SIZE_OF_PARTITION_ENTRY) + PARTITION_ENTRY_STARTLBA_OFFSET]; + break; + } + } + // + // If no boot indicator, we manually select 1st partition, and patch MBR. + // + if (Index == PARTITION_ENTRY_NUM) { + DbrOffset = *(DWORD *)&DiskPartition[PARTITION_TABLE_OFFSET + PARTITION_ENTRY_STARTLBA_OFFSET]; + if (WriteToDisk && (PatchType == PatchTypeUsb)) { + SetFilePointer(DiskHandle, 0, NULL, FILE_BEGIN); + DiskPartition[PARTITION_TABLE_OFFSET] = 0x80; + WriteFile (DiskHandle, DiskPartition, 0x200, &BytesReturn, NULL); + } + } + } + + return DbrOffset; +} + +ERROR_STATUS +ProcessBsOrMbr ( + CHAR *DiskName, + CHAR *FileName, + BOOL WriteToDisk, + PATCH_TYPE PatchType, + BOOL ProcessMbr + ) +/*++ +Routine Description: + Writing or reading boot sector or MBR according to the argument. + +Arguments: + DiskName : Win32 API recognized string name of disk + FileName : file name + WriteToDisk : TRUE is to write content of file to disk, otherwise, reading content of disk to file + PatchType : PatchTypeFloppy, PatchTypeIde, PatchTypeUsb + ProcessMbr : TRUE is to process MBR, otherwise, processing boot sector + +Return: + ErrorSuccess + ErrorFileCreate + ErrorFileReadWrite + ErrorNoMbr + ErrorFatType +--*/ +{ + BYTE DiskPartition[0x200]; + BYTE DiskPartitionBackup[0x200]; + HANDLE DiskHandle; + HANDLE FileHandle; + DWORD BytesReturn; + DWORD DbrOffset; + INT DrvNumOffset; + + DiskHandle = CreateFile ( + DiskName, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + if (DiskHandle == INVALID_HANDLE_VALUE) { + return ErrorFileCreate; + } + + FileHandle = CreateFile ( + FileName, + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL + ); + if (FileHandle == INVALID_HANDLE_VALUE) { + return ErrorFileCreate; + } + + DbrOffset = 0; + // + // Skip potential MBR for Ide & USB disk + // + if ((PatchType == PatchTypeIde) || (PatchType == PatchTypeUsb)) { + // + // Even user just wants to process MBR, we get offset of boot sector here to validate the disk + // if disk have MBR, DbrOffset should be greater than 0 + // + DbrOffset = GetBootSectorOffset (DiskHandle, WriteToDisk, PatchType); + + if (!ProcessMbr) { + // + // 1. Process boot sector, set file pointer to the beginning of boot sector + // + SetFilePointer (DiskHandle, DbrOffset * 0x200, NULL, FILE_BEGIN); + } else if(DbrOffset == 0) { + // + // If user want to process Mbr, but no Mbr exists, simply return FALSE + // + return ErrorNoMbr; + } else { + // + // 2. Process MBR, set file pointer to 0 + // + SetFilePointer (DiskHandle, 0, NULL, FILE_BEGIN); + } + } + + // + // [File Pointer is pointed to beginning of Mbr or Dbr] + // + if (WriteToDisk) { + // + // Write + // + if (!ReadFile (FileHandle, DiskPartition, 0x200, &BytesReturn, NULL)) { + return ErrorFileReadWrite; + } + if (ProcessMbr) { + // + // Use original partition table + // + if (!ReadFile (DiskHandle, DiskPartitionBackup, 0x200, &BytesReturn, NULL)) { + return ErrorFileReadWrite; + } + memcpy (DiskPartition + 0x1BE, DiskPartitionBackup + 0x1BE, 0x40); + SetFilePointer (DiskHandle, 0, NULL, FILE_BEGIN); + } + + if (!WriteFile (DiskHandle, DiskPartition, 0x200, &BytesReturn, NULL)) { + return ErrorFileReadWrite; + } + + } else { + // + // Read + // + if (!ReadFile (DiskHandle, DiskPartition, 0x200, &BytesReturn, NULL)) { + return ErrorFileReadWrite; + } + + if (PatchType == PatchTypeUsb) { + // Manually set BS_DrvNum to 0x80 as window's format.exe has a bug which will clear this field discarding USB disk's MBR. + // offset of BS_DrvNum is 0x24 for FAT12/16 + // 0x40 for FAT32 + // + DrvNumOffset = GetDrvNumOffset (DiskPartition); + if (DrvNumOffset == -1) { + return ErrorFatType; + } + // + // Some legacy BIOS require 0x80 discarding MBR. + // Question left here: is it needed to check Mbr before set 0x80? + // + DiskPartition[DrvNumOffset] = ((DbrOffset > 0) ? 0x80 : 0); + } + + + if (PatchType == PatchTypeIde) { + // + // Patch LBAOffsetForBootSector + // + *(DWORD *)&DiskPartition [BOOT_SECTOR_LBA_OFFSET] = DbrOffset; + } + if (!WriteFile (FileHandle, DiskPartition, 0x200, &BytesReturn, NULL)) { + return ErrorFileReadWrite; + } + } + CloseHandle (FileHandle); + CloseHandle (DiskHandle); + return ErrorSuccess; +} + +VOID +PrintUsage ( + CHAR* AppName + ) +{ + fprintf ( + stdout, + "Usage: %s [OPTIONS]...\n" + "Copy file content from/to bootsector.\n" + "\n" + " -l list disks\n" + " -if=FILE specified an input, can be files or disks\n" + " -of=FILE specified an output, can be files or disks\n" + " -mbr process MBR also\n" + " -h print this message\n" + "\n" + "FILE providing a volume plus a colon (X:), indicates a disk\n" + "FILE providing other format, indicates a file\n", + AppName + ); +} + +INT +main ( + INT argc, + CHAR *argv[] + ) +{ + CHAR *AppName; + INT Index; + BOOL ProcessMbr; + CHAR VolumeLetter; + CHAR *FilePath; + BOOL WriteToDisk; + DRIVE_INFO DriveInfo; + PATCH_TYPE PatchType; + ERROR_STATUS Status; + + CHAR FloppyPathTemplate[] = "\\\\.\\%c:"; + CHAR DiskPathTemplate[] = "\\\\.\\PHYSICALDRIVE%u"; + CHAR DiskPath[MAX_PATH]; + + AppName = *argv; + argv ++; + argc --; + + ProcessMbr = FALSE; + WriteToDisk = TRUE; + FilePath = NULL; + VolumeLetter = 0; + + // + // Parse command line + // + for (Index = 0; Index < argc; Index ++) { + if (_stricmp (argv[Index], "-l") == 0) { + ListDrive (); + return 0; + } + else if (_stricmp (argv[Index], "-mbr") == 0) { + ProcessMbr = TRUE; + } + else if ((_strnicmp (argv[Index], "-if=", 4) == 0) || + (_strnicmp (argv[Index], "-of=", 4) == 0) + ) { + if (argv[Index][6] == '\0' && argv[Index][5] == ':' && IsLetter (argv[Index][4])) { + VolumeLetter = argv[Index][4]; + if (_strnicmp (argv[Index], "-if=", 4) == 0) { + WriteToDisk = FALSE; + } + } + else { + FilePath = &argv[Index][4]; + } + } + else { + PrintUsage (AppName); + return 1; + } + } + + // + // Check parameter + // + if (VolumeLetter == 0) { + fprintf (stderr, "ERROR: Volume isn't provided!\n"); + PrintUsage (AppName); + return 1; + } + + if (FilePath == NULL) { + fprintf (stderr, "ERROR: File isn't pvovided!\n"); + PrintUsage (AppName); + return 1; + } + + PatchType = PatchTypeUnknown; + + if ((VolumeLetter == 'A') || (VolumeLetter == 'a') || + (VolumeLetter == 'B') || (VolumeLetter == 'b') + ) { + // + // Floppy + // + sprintf (DiskPath, FloppyPathTemplate, VolumeLetter); + PatchType = PatchTypeFloppy; + } + else { + // + // Hard/USB disk + // + if (!GetDriveInfo (VolumeLetter, &DriveInfo)) { + fprintf (stderr, "ERROR: GetDriveInfo - 0x%x\n", GetLastError ()); + return 1; + } + + // + // Shouldn't patch my own hard disk, but can read it. + // very safe then:) + // + if (DriveInfo.DriveType->Type == DRIVE_FIXED && WriteToDisk) { + fprintf (stderr, "ERROR: Write to local harddisk - permission denied!\n"); + return 1; + } + + sprintf (DiskPath, DiskPathTemplate, DriveInfo.DiskNumber); + if (DriveInfo.DriveType->Type == DRIVE_REMOVABLE) { + PatchType = PatchTypeUsb; + } + else if (DriveInfo.DriveType->Type == DRIVE_FIXED) { + PatchType = PatchTypeIde; + } + } + + if (PatchType == PatchTypeUnknown) { + fprintf (stderr, "ERROR: PatchType unknown!\n"); + return 1; + } + + // + // Process DBR (Patch or Read) + // + Status = ProcessBsOrMbr (DiskPath, FilePath, WriteToDisk, PatchType, ProcessMbr); + if (Status == ErrorSuccess) { + fprintf ( + stdout, + "%s %s: successfully!\n", + WriteToDisk ? "Write" : "Read", + ProcessMbr ? "MBR" : "DBR" + ); + return 0; + } else { + fprintf ( + stderr, + "%s: %s %s: failed - %s (LastError: 0x%x)!\n", + (Status == ErrorNoMbr) ? "WARNING" : "ERROR", + WriteToDisk ? "Write" : "Read", + ProcessMbr ? "MBR" : "DBR", + ErrorStatusDesc[Status], + GetLastError () + ); + return 1; + } +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/makefile b/EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/makefile new file mode 100644 index 0000000000..359f126111 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/makefile @@ -0,0 +1,99 @@ +#/*++ +# +# Copyright (c) 2006 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Makefile +# +# Abstract: +# +# makefile for building the GenBootsector utility. +# +#--*/ + +# +# Make sure environmental variable EDK_SOURCE is set +# +!IFNDEF EDK_SOURCE +!ERROR EDK_SOURCE environmental variable not set +!ENDIF + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Define some macros we use here. Should get rid of them someday and +# get rid of the extra level of indirection. +# +COMMON_SOURCE = $(EDK_TOOLS_COMMON) + +# +# Common information +# + +INC=$(INC) + +# +# Target specific information +# + +TARGET_NAME=GenBootsector +TARGET_SOURCE_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) + +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).exe + +TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\GenBootsector.c" +TARGET_EXE_INCLUDE = + + +# +# Build targets +# + +all: $(TARGET_EXE) + +# +# Build EXE +# +$(EDK_TOOLS_OUTPUT)\GetDrvNumOffset.obj: $(TARGET_SOURCE_DIR)\GenBootsector.c $(TARGET_SOURCE_DIR)\fat.h + $(CC) $(C_FLAGS) $(INC) $(TARGET_SOURCE_DIR)\GetDrvNumOffset.c /Fo$(EDK_TOOLS_OUTPUT)\GetDrvNumOffset.obj + +$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE) + $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE): $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(EDK_TOOLS_OUTPUT)\GetDrvNumOffset.obj + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) user32.lib advapi32.lib /out:$(TARGET_EXE) $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(EDK_TOOLS_OUTPUT)\GetDrvNumOffset.obj + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\GetDrvNumOffset.* del $(EDK_TOOLS_OUTPUT)\GetDrvNumOffset.* > NUL + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL + diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenCRC32Section/GenCRC32Section.c b/EdkCompatibilityPkg/Sample/Tools/Source/GenCRC32Section/GenCRC32Section.c new file mode 100644 index 0000000000..27a02a4da9 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenCRC32Section/GenCRC32Section.c @@ -0,0 +1,299 @@ +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + GenCRC32Section.c + +Abstract: + + This file contains functions required to generate a Firmware File System + file. The code is compliant with the Tiano C Coding standards. + +--*/ + +#include "TianoCommon.h" +#include "EfiFirmwareFileSystem.h" +#include "EfiFirmwareVolumeHeader.h" +#include "ParseInf.h" +#include "crc32.h" +#include "EfiUtilityMsgs.h" +#include "GenCRC32Section.h" +#include +#include +#include +#include +#include "CommonLib.h" + +#include EFI_PROTOCOL_DEFINITION (GuidedSectionExtraction) + +#define TOOLVERSION "0.2" + +#define UTILITY_NAME "GenCrc32Section" + +EFI_GUID gEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID; + +EFI_STATUS +SignSectionWithCrc32 ( + IN OUT UINT8 *FileBuffer, + IN OUT UINT32 *BufferSize, + IN UINT32 DataSize + ) +/*++ + +Routine Description: + + Signs the section with CRC32 and add GUIDed section header for the + signed data. data stays in same location (overwrites source data). + +Arguments: + + FileBuffer - Buffer containing data to sign + + BufferSize - On input, the size of FileBuffer. On output, the size of + actual section data (including added section header). + + DataSize - Length of data to Sign + + Key - Key to use when signing. Currently only CRC32 is supported. + +Returns: + + EFI_SUCCESS - Successful + EFI_OUT_OF_RESOURCES - Not enough resource to complete the operation. + +--*/ +{ + + UINT32 Crc32Checksum; + EFI_STATUS Status; + UINT32 TotalSize; + CRC32_SECTION_HEADER Crc32Header; + UINT8 *SwapBuffer; + + Crc32Checksum = 0; + SwapBuffer = NULL; + + if (DataSize == 0) { + *BufferSize = 0; + + return EFI_SUCCESS; + } + + Status = CalculateCrc32 (FileBuffer, DataSize, &Crc32Checksum); + if (EFI_ERROR (Status)) { + return Status; + } + + TotalSize = DataSize + CRC32_SECTION_HEADER_SIZE; + Crc32Header.GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED; + Crc32Header.GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalSize & 0xff); + Crc32Header.GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalSize & 0xff00) >> 8); + Crc32Header.GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalSize & 0xff0000) >> 16); + memcpy (&(Crc32Header.GuidSectionHeader.SectionDefinitionGuid), &gEfiCrc32SectionGuid, sizeof (EFI_GUID)); + Crc32Header.GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID; + Crc32Header.GuidSectionHeader.DataOffset = CRC32_SECTION_HEADER_SIZE; + Crc32Header.CRC32Checksum = Crc32Checksum; + + SwapBuffer = (UINT8 *) malloc (DataSize); + if (SwapBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + memcpy (SwapBuffer, FileBuffer, DataSize); + memcpy (FileBuffer, &Crc32Header, CRC32_SECTION_HEADER_SIZE); + memcpy (FileBuffer + CRC32_SECTION_HEADER_SIZE, SwapBuffer, DataSize); + + // + // Make sure section ends on a DWORD boundary + // + while ((TotalSize & 0x03) != 0) { + FileBuffer[TotalSize] = 0; + TotalSize++; + } + + *BufferSize = TotalSize; + + if (SwapBuffer != NULL) { + free (SwapBuffer); + } + + return EFI_SUCCESS; +} + +VOID +PrintUsage ( + VOID + ) +{ + printf ("Usage:\n"); + printf (UTILITY_NAME " -i \"inputfile1\" \"inputfile2\" -o \"outputfile\" \n"); + printf (" -i \"inputfile\":\n "); + printf (" specifies the input files that would be signed to CRC32 Guided section.\n"); + printf (" -o \"outputfile\":\n"); + printf (" specifies the output file that is a CRC32 Guided section.\n"); +} + +INT32 +ReadFilesContentsIntoBuffer ( + IN CHAR8 *argv[], + IN INT32 Start, + IN OUT UINT8 **FileBuffer, + IN OUT UINT32 *BufferSize, + OUT UINT32 *ContentSize, + IN INT32 MaximumArguments + ) +{ + INT32 Index; + CHAR8 *FileName; + FILE *InputFile; + UINT8 Temp; + UINT32 Size; + + FileName = NULL; + InputFile = NULL; + Size = 0; + Index = 0; + + // + // read all input files into one file buffer + // + while (argv[Start + Index][0] != '-') { + + FileName = argv[Start + Index]; + InputFile = fopen (FileName, "rb"); + if (InputFile == NULL) { + Error (NULL, 0, 0, FileName, "failed to open input binary file"); + return -1; + } + + fread (&Temp, sizeof (UINT8), 1, InputFile); + while (!feof (InputFile)) { + (*FileBuffer)[Size++] = Temp; + fread (&Temp, sizeof (UINT8), 1, InputFile); + } + + fclose (InputFile); + InputFile = NULL; + + // + // Make sure section ends on a DWORD boundary + // + while ((Size & 0x03) != 0) { + (*FileBuffer)[Size] = 0; + Size++; + } + + Index++; + if (Index == MaximumArguments) { + break; + } + } + + *ContentSize = Size; + return Index; +} + +INT32 +main ( + INT32 argc, + CHAR8 *argv[] + ) +{ + FILE *OutputFile; + UINT8 *FileBuffer; + UINT32 BufferSize; + EFI_STATUS Status; + UINT32 ContentSize; + CHAR8 *OutputFileName; + INT32 ReturnValue; + INT32 Index; + + OutputFile = NULL; + FileBuffer = NULL; + ContentSize = 0; + OutputFileName = NULL; + + SetUtilityName (UTILITY_NAME); + + if (argc == 1) { + PrintUsage (); + return -1; + } + + BufferSize = 1024 * 1024 * 16; + FileBuffer = (UINT8 *) malloc (BufferSize * sizeof (UINT8)); + if (FileBuffer == NULL) { + Error (NULL, 0, 0, "memory allocation failed", NULL); + return -1; + } + + ZeroMem (FileBuffer, BufferSize); + + for (Index = 0; Index < argc; Index++) { + if (_strcmpi (argv[Index], "-i") == 0) { + ReturnValue = ReadFilesContentsIntoBuffer ( + argv, + (Index + 1), + &FileBuffer, + &BufferSize, + &ContentSize, + (argc - (Index + 1)) + ); + if (ReturnValue == -1) { + Error (NULL, 0, 0, "failed to read file contents", NULL); + return -1; + } + + Index += ReturnValue; + } + + if (_strcmpi (argv[Index], "-o") == 0) { + OutputFileName = argv[Index + 1]; + } + } + + OutputFile = fopen (OutputFileName, "wb"); + if (OutputFile == NULL) { + Error (NULL, 0, 0, OutputFileName, "failed to open output binary file"); + free (FileBuffer); + return -1; + } + + /* + // + // make sure section ends on a DWORD boundary ?? + // + while ( (Size & 0x03) != 0 ) { + FileBuffer[Size] = 0; + Size ++; + } +*/ + Status = SignSectionWithCrc32 (FileBuffer, &BufferSize, ContentSize); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "failed to sign section", NULL); + free (FileBuffer); + fclose (OutputFile); + return -1; + } + + ContentSize = fwrite (FileBuffer, sizeof (UINT8), BufferSize, OutputFile); + if (ContentSize != BufferSize) { + Error (NULL, 0, 0, "failed to write output buffer", NULL); + ReturnValue = -1; + } else { + ReturnValue = 0; + } + + free (FileBuffer); + fclose (OutputFile); + return ReturnValue; +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenCRC32Section/GenCRC32Section.h b/EdkCompatibilityPkg/Sample/Tools/Source/GenCRC32Section/GenCRC32Section.h new file mode 100644 index 0000000000..7f88be2364 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenCRC32Section/GenCRC32Section.h @@ -0,0 +1,43 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + GenCRC32Section.h + +Abstract: + + Header file for GenFfsFile. Mainly defines the header of section + header for CRC32 GUID defined sections. Share with GenSection.c + +--*/ + +// +// Module Coded to Tiano Coding Conventions +// +#ifndef _EFI_GEN_CRC32_SECTION_H +#define _EFI_GEN_CRC32_SECTION_H + +// +// External Files Referenced +// +#include "TianoCommon.h" +#include "EfiImageFormat.h" + +typedef struct { + EFI_GUID_DEFINED_SECTION GuidSectionHeader; + UINT32 CRC32Checksum; +} CRC32_SECTION_HEADER; + +#define EFI_SECTION_CRC32_GUID_DEFINED 0 +#define CRC32_SECTION_HEADER_SIZE (sizeof (CRC32_SECTION_HEADER)) + +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenCRC32Section/makefile b/EdkCompatibilityPkg/Sample/Tools/Source/GenCRC32Section/makefile new file mode 100644 index 0000000000..f6c07f7340 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenCRC32Section/makefile @@ -0,0 +1,85 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: makefile +# +# Abstract: +# +# This file is used to build the EFI utility. +# +#--*/ + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Common information +# + +INC=$(INC) + +# +# Target specific information +# + +TARGET_NAME=GenCRC32Section + +TARGET_SOURCE_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) + +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).exe + +TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\GenCRC32Section.c" +TARGET_EXE_INCLUDE = "$(EDK_SOURCE)\Foundation\Include\TianoCommon.h" \ + "$(EDK_SOURCE)\Foundation\Framework\Include\EfiFirmwareFileSystem.h" \ + "$(EDK_SOURCE)\Foundation\Framework\Include\EfiFirmwareVolumeHeader.h" \ + "$(EDK_TOOLS_COMMON)\ParseInf.h" +TARGET_EXE_LIBS = "$(EDK_TOOLS_OUTPUT)\Common.lib" + + +# +# Build targets +# + +all: $(TARGET_EXE) + +# +# Build EXE +# + +$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE) + $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE): $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_EXE_LIBS) $(TARGET_DLL) + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_LIB) $(TARGET_EXE_LIBS) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/DepexParser.c b/EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/DepexParser.c new file mode 100644 index 0000000000..5cd15331db --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/DepexParser.c @@ -0,0 +1,890 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DepexParser.c + +Abstract: + + Validate Dependency Expression syntax + recursive descent Algorithm + + The original BNF grammar(taken from "Pre EFI Initialization Core Interface Specification + draft review 0.9") is thus: + ::= BEFORE END + | AFTER END + | SOR END + | END + ::= AND + | OR + | + ::= NOT + | + ::= + | TRUE + | FALSE + | GUID + + ::= '{' ',' ',' ',' + ',' ',' ',' ',' + ',' ',' ',' '}' + ::= + ::= + ::= + ::= '0' 'x' + | '0' 'X' + ::= + | + ::= [0-9] + | [a-f] + | [A-F] + + After cleaning left recursive and parentheses supported, the BNF grammar used in this module is thus: + ::= BEFORE + | AFTER + | SOR + | + ::= + ::= AND + | OR + | '' + ::= NOT + | + ::= '('')' + | NOT + | TRUE + | FALSE + | END + | + ::=AND + | OR + | '' + ::= '{' ',' ',' ',' + ',' ',' ',' ',' + ',' ',' ',' '}' + ::= + ::= + ::= + ::= '0' 'x' + | '0' 'X' + ::= + | + ::= [0-9] + | [a-f] + | [A-F] + + Note: 1. There's no precedence in operators except parentheses; + 2. For hex32, less and equal than 8 bits is valid, more than 8 bits is invalid. + Same constraint for hex16 is 4, hex8 is 2. All hex should contains at least 1 bit. + 3. " ::= '('')'" is added to support parentheses; + 4. " ::= GUID" is changed to " ::= "; + 5. "DEPENDENCY_END" is the terminal of the expression. But it has been filtered by caller. + During parsing, "DEPENDENCY_END" will be treated as illegal factor; + + This code should build in any environment that supports a standard C-library w/ string + operations and File I/O services. + + As an example of usage, consider the following: + + The input string could be something like: + + NOT ({ 0xce345171, 0xba0b, 0x11d2, 0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72, + 0x3b } AND { 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, + 0x72, 0x3b }) OR { 0x03c4e603, 0xac28, 0x11d3, 0x9a, 0x2d, 0x00, 0x90, 0x27, + 0x3f, 0xc1, 0x4d } AND + + It's invalid for an extra "AND" in the end. + + Complies with Tiano C Coding Standards Document, version 0.33, 16 Aug 2001. + +--*/ + +#include "DepexParser.h" + +BOOLEAN +ParseBool ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ); + +BOOLEAN +ParseTerm ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ); + +BOOLEAN +ParseRightBool ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ); + +BOOLEAN +ParseFactor ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ); + +VOID +LeftTrim ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Left trim the space, '\n' and '\r' character in string. + The space at the end does not need trim. + + +Arguments: + + Pbegin The pointer to the string + length length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + None + + +--*/ +{ + while + ( + ((*Pindex) < (Pbegin + length)) && + ((strncmp (*Pindex, " ", 1) == 0) || (strncmp (*Pindex, "\n", 1) == 0) || (strncmp (*Pindex, "\r", 1) == 0)) + ) { + (*Pindex)++; + } +} + +BOOLEAN +ParseHexdigit ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse Hex bit in dependency expression. + +Arguments: + + Pbegin The pointer to the string + length Length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If parses a valid hex bit, return TRUE, otherwise FALSE + + +--*/ +{ + // + // ::= [0-9] | [a-f] | [A-F] + // + if (((**Pindex) >= '0' && (**Pindex) <= '9') || + ((**Pindex) >= 'a' && (**Pindex) <= 'f') || + ((**Pindex) >= 'A' && (**Pindex) <= 'F') + ) { + (*Pindex)++; + return TRUE; + } else { + return FALSE; + } +} + +BOOLEAN +ParseHex32 ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse Hex32 in dependency expression. + +Arguments: + + Pbegin The pointer to the string + length Length of the string + Pindex The pointer of point to the next parse character in the string + +Returns: + + BOOLEAN If parses a valid hex32, return TRUE, otherwise FALSE + + +--*/ +{ + INT32 Index; + INT8 *Pin; + + Index = 0; + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + + if ((strncmp (*Pindex, "0x", 2) != 0) && (strncmp (*Pindex, "0X", 2) != 0)) { + return FALSE; + } + (*Pindex) += 2; + + while (ParseHexdigit (Pbegin, length, Pindex)) { + Index++; + } + + if (Index > 0 && Index <= 8) { + return TRUE; + } else { + *Pindex = Pin; + return FALSE; + } +} + +BOOLEAN +ParseHex16 ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse Hex16 in dependency expression. + +Arguments: + + Pbegin The pointer to the string + length Length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If parses a valid hex16, return TRUE, otherwise FALSE + + +--*/ +{ + int Index; + INT8 *Pin; + + Index = 0; + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + + if ((strncmp (*Pindex, "0x", 2) != 0) && (strncmp (*Pindex, "0X", 2) != 0)) { + return FALSE; + } + (*Pindex) += 2; + + while (ParseHexdigit (Pbegin, length, Pindex)) { + Index++; + } + + if (Index > 0 && Index <= 4) { + return TRUE; + } else { + *Pindex = Pin; + return FALSE; + } +} + +BOOLEAN +ParseHex8 ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse Hex8 in dependency expression. + +Arguments: + + Pbegin The pointer to the string + length Length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If parses a valid hex8, return TRUE, otherwise FALSE + + +--*/ +{ + int Index; + INT8 *Pin; + + Index = 0; + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + + if ((strncmp (*Pindex, "0x", 2) != 0) && (strncmp (*Pindex, "0X", 2) != 0)) { + return FALSE; + } + (*Pindex) += 2; + + while (ParseHexdigit (Pbegin, length, Pindex)) { + Index++; + } + + if (Index > 0 && Index <= 2) { + return TRUE; + } else { + *Pindex = Pin; + return FALSE; + } +} + +BOOLEAN +ParseGuid ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse guid in dependency expression. + There can be any number of spaces between '{' and hexword, ',' and hexword, + hexword and ',', hexword and '}'. The hexword include hex32, hex16 and hex8. + +Arguments: + + Pbegin The pointer to the string + length length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If parses a valid guid, return TRUE, otherwise FALSE + + +--*/ +{ + INT32 Index; + INT8 *Pin; + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + if (strncmp (*Pindex, "{", 1) != 0) { + return FALSE; + } + (*Pindex)++; + + LeftTrim (Pbegin, length, Pindex); + if (!ParseHex32 (Pbegin, length, Pindex)) { + *Pindex = Pin; + return FALSE; + } + + LeftTrim (Pbegin, length, Pindex); + if (strncmp (*Pindex, ",", 1) != 0) { + return FALSE; + } else { + (*Pindex)++; + } + + for (Index = 0; Index < 2; Index++) { + LeftTrim (Pbegin, length, Pindex); + if (!ParseHex16 (Pbegin, length, Pindex)) { + *Pindex = Pin; + return FALSE; + } + + LeftTrim (Pbegin, length, Pindex); + if (strncmp (*Pindex, ",", 1) != 0) { + return FALSE; + } else { + (*Pindex)++; + } + } + + for (Index = 0; Index < 7; Index++) { + LeftTrim (Pbegin, length, Pindex); + if (!ParseHex8 (Pbegin, length, Pindex)) { + *Pindex = Pin; + return FALSE; + } + + LeftTrim (Pbegin, length, Pindex); + if (strncmp (*Pindex, ",", 1) != 0) { + return FALSE; + } else { + (*Pindex)++; + } + } + + LeftTrim (Pbegin, length, Pindex); + if (!ParseHex8 (Pbegin, length, Pindex)) { + *Pindex = Pin; + return FALSE; + } + + LeftTrim (Pbegin, length, Pindex); + if (strncmp (*Pindex, "}", 1) != 0) { + return FALSE; + } else { + (*Pindex)++; + } + + return TRUE; +} + +BOOLEAN +ParseRightFactor ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse rightfactor in bool expression. + +Arguments: + + Pbegin The pointer to the string + length length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If string is a valid rightfactor expression, return TRUE, otherwise FALSE + + +--*/ +{ + INT8 *Pin; + + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + + // + // ::=AND + // + if (strncmp (*Pindex, OPERATOR_AND, strlen (OPERATOR_AND)) == 0) { + *Pindex += strlen (OPERATOR_AND); + LeftTrim (Pbegin, length, Pindex); + + if (ParseTerm (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightBool (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + if (ParseRightFactor (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + } + } else { + *Pindex = Pin; + } + } else { + *Pindex = Pin; + } + } + // + // ::=OR + // + if (strncmp (*Pindex, OPERATOR_OR, strlen (OPERATOR_OR)) == 0) { + *Pindex += strlen (OPERATOR_OR); + LeftTrim (Pbegin, length, Pindex); + + if (ParseTerm (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightBool (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + if (ParseRightFactor (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + } + } else { + *Pindex = Pin; + } + } else { + *Pindex = Pin; + } + } + // + // ::= '' + // + *Pindex = Pin; + return TRUE; +} + +BOOLEAN +ParseRightBool ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse rightbool in bool expression. + +Arguments: + + Pbegin The pointer to the string + length length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If string is a valid rightbool expression, return TRUE, otherwise FALSE + + +--*/ +{ + INT8 *Pin; + + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + + // + // ::= AND + // + if (strncmp (*Pindex, OPERATOR_AND, strlen (OPERATOR_AND)) == 0) { + *Pindex += strlen (OPERATOR_AND); + LeftTrim (Pbegin, length, Pindex); + + if (ParseTerm (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightBool (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + } + } else { + *Pindex = Pin; + } + } + // + // ::= OR + // + if (strncmp (*Pindex, OPERATOR_OR, strlen (OPERATOR_OR)) == 0) { + *Pindex += strlen (OPERATOR_OR); + LeftTrim (Pbegin, length, Pindex); + + if (ParseTerm (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightBool (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + } + } else { + *Pindex = Pin; + } + } + // + // ::= '' + // + *Pindex = Pin; + return TRUE; +} + +BOOLEAN +ParseFactor ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse factor in bool expression. + +Arguments: + + Pbegin The pointer to the string + length length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If string is a valid factor, return TRUE, otherwise FALSE + + +--*/ +{ + INT8 *Pin; + + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + + // + // ::= '('')' + // + if (strncmp (*Pindex, OPERATOR_LEFT_PARENTHESIS, strlen (OPERATOR_LEFT_PARENTHESIS)) == 0) { + *Pindex += strlen (OPERATOR_LEFT_PARENTHESIS); + LeftTrim (Pbegin, length, Pindex); + + if (!ParseBool (Pbegin, length, Pindex)) { + *Pindex = Pin; + } else { + LeftTrim (Pbegin, length, Pindex); + + if (strncmp (*Pindex, OPERATOR_RIGHT_PARENTHESIS, strlen (OPERATOR_RIGHT_PARENTHESIS)) == 0) { + *Pindex += strlen (OPERATOR_RIGHT_PARENTHESIS); + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightFactor (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + } + } + } + } + // + // ::= NOT + // + if (strncmp (*Pindex, OPERATOR_NOT, strlen (OPERATOR_NOT)) == 0) { + *Pindex += strlen (OPERATOR_NOT); + LeftTrim (Pbegin, length, Pindex); + + if (ParseFactor (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightBool (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightFactor (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + } + } else { + *Pindex = Pin; + } + } else { + *Pindex = Pin; + } + } + // + // ::= TRUE + // + if (strncmp (*Pindex, OPERATOR_TRUE, strlen (OPERATOR_TRUE)) == 0) { + *Pindex += strlen (OPERATOR_TRUE); + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightFactor (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + } + } + // + // ::= FALSE + // + if (strncmp (*Pindex, OPERATOR_FALSE, strlen (OPERATOR_FALSE)) == 0) { + *Pindex += strlen (OPERATOR_FALSE); + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightFactor (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + } + } + // + // ::= + // + if (ParseGuid (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + + if (ParseRightFactor (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + return FALSE; + } + } else { + *Pindex = Pin; + return FALSE; + } +} + +BOOLEAN +ParseTerm ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse term in bool expression. + +Arguments: + + Pbegin The pointer to the string + length length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If string is a valid term, return TRUE, otherwise FALSE + + +--*/ +{ + INT8 *Pin; + + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + + // + // ::= NOT + // + if (strncmp (*Pindex, OPERATOR_NOT, strlen (OPERATOR_NOT)) == 0) { + *Pindex += strlen (OPERATOR_NOT); + LeftTrim (Pbegin, length, Pindex); + + if (!ParseFactor (Pbegin, length, Pindex)) { + *Pindex = Pin; + } else { + return TRUE; + } + } + // + // ::= + // + if (ParseFactor (Pbegin, length, Pindex)) { + return TRUE; + } else { + *Pindex = Pin; + return FALSE; + } +} + +BOOLEAN +ParseBool ( + IN INT8 *Pbegin, + IN UINT32 length, + IN OUT INT8 **Pindex + ) +/*++ + +Routine Description: + + Parse bool expression. + +Arguments: + + Pbegin The pointer to the string + length length of the string + Pindex The pointer of pointer to the next parse character in the string + +Returns: + + BOOLEAN If string is a valid bool expression, return TRUE, otherwise FALSE + + +--*/ +{ + INT8 *Pin; + Pin = *Pindex; + LeftTrim (Pbegin, length, Pindex); + + if (ParseTerm (Pbegin, length, Pindex)) { + LeftTrim (Pbegin, length, Pindex); + + if (!ParseRightBool (Pbegin, length, Pindex)) { + *Pindex = Pin; + return FALSE; + } else { + return TRUE; + } + } else { + *Pindex = Pin; + return FALSE; + } +} + +BOOLEAN +ParseDepex ( + IN INT8 *Pbegin, + IN UINT32 length + ) +/*++ + +Routine Description: + + Parse whole dependency expression. + +Arguments: + + Pbegin The pointer to the string + length length of the string + +Returns: + + BOOLEAN If string is a valid dependency expression, return TRUE, otherwise FALSE + + +--*/ +{ + BOOLEAN Result; + INT8 **Pindex; + INT8 *temp; + + Result = FALSE; + temp = Pbegin; + Pindex = &temp; + + LeftTrim (Pbegin, length, Pindex); + if (strncmp (*Pindex, OPERATOR_BEFORE, strlen (OPERATOR_BEFORE)) == 0) { + (*Pindex) += strlen (OPERATOR_BEFORE); + Result = ParseGuid (Pbegin, length, Pindex); + + } else if (strncmp (*Pindex, OPERATOR_AFTER, strlen (OPERATOR_AFTER)) == 0) { + (*Pindex) += strlen (OPERATOR_AFTER); + Result = ParseGuid (Pbegin, length, Pindex); + + } else if (strncmp (*Pindex, OPERATOR_SOR, strlen (OPERATOR_SOR)) == 0) { + (*Pindex) += strlen (OPERATOR_SOR); + Result = ParseBool (Pbegin, length, Pindex); + + } else { + Result = ParseBool (Pbegin, length, Pindex); + + } + + LeftTrim (Pbegin, length, Pindex); + return (BOOLEAN) (Result && (*Pindex) >= (Pbegin + length)); +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/DepexParser.h b/EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/DepexParser.h new file mode 100644 index 0000000000..29e0884a3e --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/DepexParser.h @@ -0,0 +1,26 @@ +/*++ +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + Module Name: + GenDepex.h + + Abstract: + This file contains the relevant declarations required + to generate a binary Dependency File + + Complies with Tiano C Coding Standards Document, version 0.31, 12 Dec 2000. + +--*/ + +// TODO: fix comment to set correct module name: DepexParser.h +#ifndef _EFI_DEPEX_PARSER_H_ +#define _EFI_DEPEX_PARSER_H_ +#include "GenDepex.h" +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/GenDepex.c b/EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/GenDepex.c new file mode 100644 index 0000000000..cebcc01f9b --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/GenDepex.c @@ -0,0 +1,912 @@ +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + GenDepex.c + +Abstract: + + Generate Dependency Expression ("GenDepex") + + Infix to Postfix Algorithm + + This code has been scrubbed to be free of having any EFI core tree dependencies. + It should build in any environment that supports a standard C-library w/ string + operations and File I/O services. + + As an example of usage, consider the following: + + The input user file could be something like "Sample.DXS" whose contents are + + #include "Tiano.h" + + DEPENDENCY_START + NOT (DISK_IO_PROTOCOL AND SIMPLE_FILE_SYSTEM_PROTOCOL) + OR EFI_PXE_BASE_CODE_PROTOCOL + DEPENDENCY_END + + This file is then washed through the C-preprocessor, viz., + + cl /EP Sample.DXS > Sample.TMP1 + + This yields the following file "Sample.TMP1" whose contents are + + DEPENDENCY_START + NOT ({ 0xce345171, 0xba0b, 0x11d2, 0x8e, 0x4f, 0x0, 0xa0, 0xc9, 0x69, 0x72, + 0x3b } AND { 0x964e5b22, 0x6459, 0x11d2, 0x8e, 0x39, 0x0, 0xa0, 0xc9, 0x69, + 0x72, 0x3b }) OR { 0x03c4e603, 0xac28, 0x11d3, 0x9a, 0x2d, 0x00, 0x90, 0x27, + 0x3f, 0xc1, 0x4d } + DEPENDENCY_END + + This file, in turn, will be fed into the utility, viz., + + GenDepex Sample.TMP1 Sample.TMP2 + + With a file that is 55 bytes long: + + 55 bytes for the grammar binary + PUSH opcode - 1 byte + GUID Instance - 16 bytes + PUSH opcode - 1 byte + GUID Instance - 16 bytes + AND opcode - 1 byte + NOT opcode - 1 byte + PUSH opcode - 1 byte + GUID Instance - 16 bytes + OR opcode - 1 byte + END opcode - 1 byte + + The file "Sample.TMP2" could be fed via a Section-builder utility + (GenSection) that would be used for the creation of a dependency + section file (.DPX) which in turn would be used by a generate FFS + utility (GenFfsFile) to produce a DXE driver/core (.DXE) or + a DXE application (.APP) file. + + Complies with Tiano C Coding Standards Document, version 0.31, 12 Dec 2000. + +--*/ + +#include "GenDepex.h" + +#define TOOL_NAME "GenDepex" + +extern +BOOLEAN +ParseDepex ( + IN INT8 *Pbegin, + IN UINT32 length + ); + +VOID +PrintGenDepexUtilityInfo ( + VOID + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ( + "%s, Tiano Dependency Expression Generation Utility. Version %d.%d.\n", + UTILITY_NAME, + UTILITY_MAJOR_VERSION, + UTILITY_MINOR_VERSION + ); + printf ("Copyright (C) 1996-2002 Intel Corporation. All rights reserved.\n\n"); +} + +VOID +PrintGenDepexUsageInfo ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT. + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ( + "Usage: %s -I -O [-P ] \n", + UTILITY_NAME + ); + printf (" Where:\n"); + printf (" is the input pre-processed dependency text files name.\n"); + printf (" is the output binary dependency files name.\n"); + printf (" is the padding integer value.\n"); + printf (" This is the boundary to align the output file size to.\n"); +} + +DEPENDENCY_OPCODE +PopOpCode ( + IN OUT VOID **Stack + ) +/*++ + +Routine Description: + + Pop an element from the Opcode stack. + +Arguments: + + Stack Current top of the OpCode stack location + +Returns: + + DEPENDENCY_OPCODE OpCode at the top of the OpCode stack. + Stack New top of the OpCode stack location + + +--*/ +{ + DEPENDENCY_OPCODE *OpCodePtr; + + OpCodePtr = *Stack; + OpCodePtr--; + *Stack = OpCodePtr; + return *OpCodePtr; +} + +VOID +PushOpCode ( + IN OUT VOID **Stack, + IN DEPENDENCY_OPCODE OpCode + ) +/*++ + +Routine Description: + + Push an element onto the Opcode Stack + +Arguments: + + Stack Current top of the OpCode stack location + OpCode OpCode to push onto the stack + +Returns: + + Stack New top of the OpCode stack location + +--*/ +{ + DEPENDENCY_OPCODE *OpCodePtr; + + OpCodePtr = *Stack; + *OpCodePtr = OpCode; + OpCodePtr++; + *Stack = OpCodePtr; +} + +EFI_STATUS +GenerateDependencyExpression ( + IN FILE *InFile, + IN OUT FILE *OutFile, + IN UINT8 Padding OPTIONAL + ) +/*++ + +Routine Description: + + This takes the pre-compiled dependency text file and + converts it into a binary dependency file. + + The BNF for the dependency expression is as follows + (from the DXE 1.0 Draft specification). + + The inputted BNF grammar is thus: + ::= sor | + before GUID | + after GUID | + + + ::= | + + ::= and | + or | + + + ::= not | + + + ::= ( ) | + | + GUID | + + + ::= true | + false + + The outputed binary grammer is thus: + ::= sor | + before | + after | + + + ::= | + + ::= and | + or | + + ::= not | + + + ::= ( ) | + | + | + | + + + ::= true | + false + + ::= push GUID + + ::= end + + BugBug: A correct grammer is parsed correctly. A file that violates the + grammer may parse when it should generate an error. There is some + error checking and it covers most of the case when it's an include + of definition issue. An ill formed expresion may not be detected. + +Arguments: + + InFile - Input pre-compiled text file of the dependency expression. + This needs to be in ASCII. + The file pointer can not be NULL. + + OutFile - Binary dependency file. + The file pointer can not be NULL. + + Padding - OPTIONAL integer value to pad the output file to. + + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the parameters in the text file was invalid. + EFI_OUT_OF_RESOURCES Unable to allocate memory. + EFI_ABORTED An misc error occurred. + +--*/ +{ + INT8 *Ptrx; + INT8 *Pend; + INT8 *EvaluationStack; + INT8 *StackPtr; + INT8 *Buffer; + INT8 Line[LINESIZE]; + UINTN Index; + UINTN OutFileSize; + UINTN FileSize; + UINTN Results; + BOOLEAN NotDone; + BOOLEAN Before_Flag; + BOOLEAN After_Flag; + BOOLEAN Dep_Flag; + BOOLEAN SOR_Flag; + EFI_GUID Guid; + UINTN ArgCountParsed; + DEPENDENCY_OPCODE Opcode; + + Before_Flag = FALSE; + After_Flag = FALSE; + Dep_Flag = FALSE; + SOR_Flag = FALSE; + + memset (Line, 0, LINESIZE); + + OutFileSize = 0; + + EvaluationStack = (INT8 *) malloc (EVAL_STACK_SIZE); + + if (EvaluationStack != NULL) { + StackPtr = EvaluationStack; + } else { + printf ("Unable to allocate memory to EvaluationStack - Out of resources\n"); + return EFI_OUT_OF_RESOURCES; + } + + Results = (UINTN) fseek (InFile, 0, SEEK_END); + + if (Results != 0) { + printf ("FSEEK failed - Aborted\n"); + return EFI_ABORTED; + } + + FileSize = ftell (InFile); + + if (FileSize == -1L) { + printf ("FTELL failed - Aborted\n"); + return EFI_ABORTED; + } + + Buffer = (INT8 *) malloc (FileSize + BUFFER_SIZE); + + if (Buffer == NULL) { + printf ("Unable to allocate memory to Buffer - Out of resources\n"); + free (EvaluationStack); + + Results = (UINTN) fclose (InFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + Results = (UINTN) fclose (OutFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + return EFI_OUT_OF_RESOURCES; + } + + Results = (UINTN) fseek (InFile, 0, SEEK_SET); + + if (Results != 0) { + printf ("FSEEK failed - Aborted\n"); + return EFI_ABORTED; + } + + fread (Buffer, FileSize, 1, InFile); + + Ptrx = Buffer; + Pend = Ptrx + FileSize - strlen (DEPENDENCY_END); + Index = FileSize; + + NotDone = TRUE; + while ((Index--) && NotDone) { + + if (strncmp (Pend, DEPENDENCY_END, strlen (DEPENDENCY_END)) == 0) { + NotDone = FALSE; + } else { + Pend--; + } + } + + if (NotDone) { + printf ("Couldn't find end string %s\n", DEPENDENCY_END); + + Results = (UINTN) fclose (InFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + Results = (UINTN) fclose (OutFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + free (Buffer); + free (EvaluationStack); + + return EFI_INVALID_PARAMETER; + } + + Index = FileSize; + + NotDone = TRUE; + while ((Index--) && NotDone) { + + if (strncmp (Ptrx, DEPENDENCY_START, strlen (DEPENDENCY_START)) == 0) { + Ptrx += strlen (DEPENDENCY_START); + NotDone = FALSE; + // + // BUGBUG -- should Index be decremented by sizeof(DEPENDENCY_START)? + // + } else { + Ptrx++; + } + } + + if (NotDone) { + printf ("Couldn't find start string %s\n", DEPENDENCY_START); + + Results = (UINTN) fclose (InFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + Results = (UINTN) fclose (OutFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + free (Buffer); + free (EvaluationStack); + + return EFI_INVALID_PARAMETER; + } + // + // validate the syntax of expression + // + if (!ParseDepex (Ptrx, Pend - Ptrx - 1)) { + printf ("The syntax of expression is wrong\n"); + + Results = (UINTN) fclose (InFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + Results = (UINTN) fclose (OutFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + free (Buffer); + free (EvaluationStack); + + return EFI_INVALID_PARAMETER; + } + + NotDone = TRUE; + + while ((Index--) && NotDone) { + + if (*Ptrx == ' ') { + Ptrx++; + } else if (*Ptrx == '\n' || *Ptrx == '\r') { + Ptrx++; + } else if (strncmp (Ptrx, OPERATOR_SOR, strlen (OPERATOR_SOR)) == 0) { + // + // Checks for some invalid dependencies + // + if (Before_Flag) { + + printf ("A BEFORE operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (After_Flag) { + + printf ("An AFTER operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (SOR_Flag) { + + printf ("Another SOR operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (Dep_Flag) { + + printf ("The Schedule On Request - SOR operator must be the first operator following DEPENDENCY_START\n"); + return EFI_INVALID_PARAMETER; + + } else { + // + // BUGBUG - This was not in the spec but is in the CORE code + // An OPERATOR_SOR has to be first - following the DEPENDENCY_START + // + fputc (EFI_DEP_SOR, OutFile); + OutFileSize++; + Ptrx += strlen (OPERATOR_SOR); + SOR_Flag = TRUE; + + } + } else if (strncmp (Ptrx, OPERATOR_BEFORE, strlen (OPERATOR_BEFORE)) == 0) { + // + // Checks for some invalid dependencies + // + if (Before_Flag) { + + printf ("Another BEFORE operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (After_Flag) { + + printf ("An AFTER operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (SOR_Flag) { + + printf ("A SOR operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (Dep_Flag) { + + printf ("The BEFORE operator must be the first operator following DEPENDENCY_START\n"); + return EFI_INVALID_PARAMETER; + + } else { + fputc (EFI_DEP_BEFORE, OutFile); + OutFileSize++; + Ptrx += strlen (OPERATOR_BEFORE); + Before_Flag = TRUE; + } + } else if (strncmp (Ptrx, OPERATOR_AFTER, strlen (OPERATOR_AFTER)) == 0) { + // + // Checks for some invalid dependencies + // + if (Before_Flag) { + + printf ("A BEFORE operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (After_Flag) { + + printf ("Another AFTER operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (SOR_Flag) { + + printf ("A SOR operator was detected.\n"); + printf ("There can only be one SOR or one AFTER or one BEFORE operator\n"); + return EFI_INVALID_PARAMETER; + + } else if (Dep_Flag) { + + printf ("The AFTER operator must be the first operator following DEPENDENCY_START\n"); + return EFI_INVALID_PARAMETER; + + } else { + fputc (EFI_DEP_AFTER, OutFile); + OutFileSize++; + Ptrx += strlen (OPERATOR_AFTER); + Dep_Flag = TRUE; + After_Flag = TRUE; + } + } else if (strncmp (Ptrx, OPERATOR_AND, strlen (OPERATOR_AND)) == 0) { + while (StackPtr != EvaluationStack) { + Opcode = PopOpCode ((VOID **) &StackPtr); + if (Opcode != DXE_DEP_LEFT_PARENTHESIS) { + fputc (Opcode, OutFile); + OutFileSize++; + } else { + PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS); + break; + } + } + + PushOpCode ((VOID **) &StackPtr, EFI_DEP_AND); + Ptrx += strlen (OPERATOR_AND); + Dep_Flag = TRUE; + + } else if (strncmp (Ptrx, OPERATOR_OR, strlen (OPERATOR_OR)) == 0) { + while (StackPtr != EvaluationStack) { + Opcode = PopOpCode ((VOID **) &StackPtr); + if (Opcode != DXE_DEP_LEFT_PARENTHESIS) { + fputc (Opcode, OutFile); + OutFileSize++; + } else { + PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS); + break; + } + } + + PushOpCode ((VOID **) &StackPtr, EFI_DEP_OR); + Ptrx += strlen (OPERATOR_OR); + Dep_Flag = TRUE; + + } else if (strncmp (Ptrx, OPERATOR_NOT, strlen (OPERATOR_NOT)) == 0) { + while (StackPtr != EvaluationStack) { + Opcode = PopOpCode ((VOID **) &StackPtr); + if (Opcode != DXE_DEP_LEFT_PARENTHESIS) { + fputc (Opcode, OutFile); + OutFileSize++; + } else { + PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS); + break; + } + } + + PushOpCode ((VOID **) &StackPtr, EFI_DEP_NOT); + Ptrx += strlen (OPERATOR_NOT); + Dep_Flag = TRUE; + + } else if (*Ptrx == '\t') { + + printf ("File contains tabs. This violates the coding standard\n"); + return EFI_INVALID_PARAMETER; + + } else if (*Ptrx == '\n') { + // + // Skip the newline character in the file + // + Ptrx++; + + } else if (strncmp (Ptrx, OPERATOR_LEFT_PARENTHESIS, strlen (OPERATOR_LEFT_PARENTHESIS)) == 0) { + PushOpCode ((VOID **) &StackPtr, DXE_DEP_LEFT_PARENTHESIS); + + Ptrx += strlen (OPERATOR_LEFT_PARENTHESIS); + Dep_Flag = TRUE; + + } else if (strncmp (Ptrx, OPERATOR_RIGHT_PARENTHESIS, strlen (OPERATOR_RIGHT_PARENTHESIS)) == 0) { + while (StackPtr != EvaluationStack) { + Opcode = PopOpCode ((VOID **) &StackPtr); + if (Opcode != DXE_DEP_LEFT_PARENTHESIS) { + fputc (Opcode, OutFile); + OutFileSize++; + } else { + break; + } + } + + Ptrx += strlen (OPERATOR_RIGHT_PARENTHESIS); + Dep_Flag = TRUE; + + } else if (strncmp (Ptrx, OPERATOR_TRUE, strlen (OPERATOR_TRUE)) == 0) { + + fputc (EFI_DEP_TRUE, OutFile); + + OutFileSize++; + + // + // OutFileSize += sizeof (EFI_DEP_TRUE); + // + Dep_Flag = TRUE; + + Ptrx += strlen (OPERATOR_TRUE); + + } else if (strncmp (Ptrx, OPERATOR_FALSE, strlen (OPERATOR_FALSE)) == 0) { + + fputc (EFI_DEP_FALSE, OutFile); + + OutFileSize++; + + // + // OutFileSize += sizeof (EFI_DEP_FALSE); + // + Dep_Flag = TRUE; + + Ptrx += strlen (OPERATOR_FALSE); + + } else if (*Ptrx == '{') { + Ptrx++; + + if (*Ptrx == ' ') { + Ptrx++; + } + + ArgCountParsed = sscanf ( + Ptrx, + "%x, %x, %x, %x, %x, %x, %x, %x, %x, %x, %x", + &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] + ); + + if (ArgCountParsed != 11) { + printf ("We have found an illegal GUID\n"); + printf ("Fix your depex\n"); + exit (-1); + } + + while (*Ptrx != '}') { + Ptrx++; + } + // + // Absorb the closing } + // + Ptrx++; + + // + // Don't provide a PUSH Opcode for the Before and After case + // + if ((!Before_Flag) && (!After_Flag)) { + fputc (EFI_DEP_PUSH, OutFile); + OutFileSize++; + } + + fwrite (&Guid, sizeof (EFI_GUID), 1, OutFile); + + OutFileSize += sizeof (EFI_GUID); + Dep_Flag = TRUE; + + } else if (strncmp (Ptrx, DEPENDENCY_END, strlen (DEPENDENCY_END)) == 0) { + NotDone = FALSE; + } else { + // + // Not a valid construct. Null terminate somewhere out there and + // print an error message. + // + *(Ptrx + 20) = 0; + printf (TOOL_NAME " ERROR: Unrecognized input at: \"%s\"...\n", Ptrx); + return EFI_INVALID_PARAMETER; + } + } + // + // DRAIN(); + // + while (StackPtr != EvaluationStack) { + fputc (PopOpCode ((VOID **) &StackPtr), OutFile); + OutFileSize++; + } + + if (OutFileSize == 0) { + printf ("Grammer contains no operators or constants\n"); + return EFI_INVALID_PARAMETER; + } + + fputc (EFI_DEP_END, OutFile); + + OutFileSize++; + + // + // Checks for invalid padding values + // + if (Padding < 0) { + + printf ("The inputted padding value was %d\n", Padding); + printf ("The optional padding value can not be less than ZERO\n"); + return EFI_INVALID_PARAMETER; + + } else if (Padding > 0) { + + while ((OutFileSize % Padding) != 0) { + + fputc (' ', OutFile); + OutFileSize++; + } + } + + Results = (UINTN) fclose (InFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + Results = (UINTN) fclose (OutFile); + if (Results != 0) { + printf ("FCLOSE failed\n"); + } + + free (Buffer); + free (EvaluationStack); + + return EFI_SUCCESS; +} // End GenerateDependencyExpression function + +EFI_STATUS +main ( + IN UINTN argc, + IN CHAR8 *argv[] + ) +/*++ + +Routine Description: + + Parse user entries. Print some rudimentary help + +Arguments: + + argc The count of input arguments + argv The input arguments string array + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid or one of the parameters in the text file was invalid. + EFI_OUT_OF_RESOURCES Unable to allocate memory. + EFI_ABORTED Unable to open/create a file or a misc error. + +--*/ +// TODO: ] - add argument and description to function comment +{ + FILE *OutFile; + FILE *InFile; + UINT8 Padding; + UINTN Index; + BOOLEAN Input_Flag; + BOOLEAN Output_Flag; + BOOLEAN Pad_Flag; + + InFile = NULL; + OutFile = NULL; + Padding = 0; + Input_Flag = FALSE; + Output_Flag = FALSE; + Pad_Flag = FALSE; + + // + // Output the calling arguments + // + printf ("\n\n"); + for (Index = 0; Index < argc; Index++) { + printf ("%s ", argv[Index]); + } + + printf ("\n\n"); + + if (argc < 5) { + printf ("Not enough arguments\n"); + PrintGenDepexUsageInfo (); + return EFI_INVALID_PARAMETER; + } + + for (Index = 1; Index < argc - 1; Index++) { + + if ((strcmp (argv[Index], "-I") == 0) || (strcmp (argv[Index], "-i") == 0)) { + + if (!Input_Flag) { + + InFile = fopen (argv[Index + 1], "rb"); + Input_Flag = TRUE; + + } else { + printf ("GenDepex only allows one INPUT (-I) argument\n"); + return EFI_INVALID_PARAMETER; + } + + } else if ((strcmp (argv[Index], "-O") == 0) || (strcmp (argv[Index], "-o") == 0)) { + + if (!Output_Flag) { + + OutFile = fopen (argv[Index + 1], "wb"); + Output_Flag = TRUE; + + } else { + printf ("GenDepex only allows one OUTPUT (-O) argument\n"); + return EFI_INVALID_PARAMETER; + } + + } else if ((strcmp (argv[Index], "-P") == 0) || (strcmp (argv[Index], "-p") == 0)) { + + if (!Pad_Flag) { + + Padding = (UINT8) atoi (argv[Index + 1]); + Pad_Flag = TRUE; + + } else { + printf ("GenDepex only allows one PADDING (-P) argument\n"); + return EFI_INVALID_PARAMETER; + } + } + } + + PrintGenDepexUtilityInfo (); + + if (InFile == NULL) { + printf ("Can not open for reading.\n"); + PrintGenDepexUsageInfo (); + return EFI_ABORTED; + } + + if (OutFile == NULL) { + printf ("Can not open for writting.\n"); + PrintGenDepexUsageInfo (); + return EFI_ABORTED; + } + + return GenerateDependencyExpression (InFile, OutFile, Padding); +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/GenDepex.h b/EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/GenDepex.h new file mode 100644 index 0000000000..d9df5faa69 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/GenDepex.h @@ -0,0 +1,67 @@ +/*++ +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + Module Name: + GenDepex.h + + Abstract: + This file contains the relevant declarations required + to generate a binary Dependency File + + Complies with Tiano C Coding Standards Document, version 0.31, 12 Dec 2000. + +--*/ + +#ifndef _EFI_GEN_DEPEX_H +#define _EFI_GEN_DEPEX_H + +#include "TianoCommon.h" +#include "EfiDependency.h" +#include +#include +#include +#include +#include + +#define DEPENDENCY_START "DEPENDENCY_START" +#define OPERATOR_BEFORE "BEFORE" +#define OPERATOR_AFTER "AFTER" +#define OPERATOR_AND "AND" +#define OPERATOR_OR "OR" +#define OPERATOR_NOT "NOT" +#define OPERATOR_TRUE "TRUE" +#define OPERATOR_FALSE "FALSE" +#define OPERATOR_SOR "SOR" +#define OPERATOR_END "END" +#define OPERATOR_LEFT_PARENTHESIS "(" +#define OPERATOR_RIGHT_PARENTHESIS ")" +#define DEPENDENCY_END "DEPENDENCY_END" + +#define DXE_DEP_LEFT_PARENTHESIS 0x0a +#define DXE_DEP_RIGHT_PARENTHESIS 0x0b + +#define LINESIZE 320 +#define SIZE_A_SYMBOL 60 +#define DEPENDENCY_OPCODE UINT8 +#define EVAL_STACK_SIZE 0x1024 +#define BUFFER_SIZE 0x100 + +// +// Utility Name +// +#define UTILITY_NAME "GenDepex" + +// +// Utility version information +// +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 4 + +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/makefile b/EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/makefile new file mode 100644 index 0000000000..4faceb1802 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/makefile @@ -0,0 +1,100 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: makefile +# +# Abstract: +# +# This file is used to build the EFI utility. +# +#--*/ + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Define some macros we use here. Should get rid of them someday and +# get rid of the extra level of indirection. +# +COMMON_SOURCE = $(EDK_TOOLS_COMMON) + +# +# Common information +# + +INC=$(INC) + +# +# Target specific information +# + +TARGET_NAME=GenDepex +TARGET_LIB_NAME=DepexParser +TARGET_SOURCE_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) + +TARGET_LIB = $(EDK_TOOLS_OUTPUT)\$(TARGET_LIB_NAME).lib +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).exe + +TARGET_LIB_SOURCE = "$(TARGET_SOURCE_DIR)\DepexParser.c" +TARGET_LIB_INCLUDE = "$(TARGET_SOURCE_DIR)\DepexParser.h" + +TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\GenDepex.c" +TARGET_EXE_INCLUDE = "$(EDK_SOURCE)\Foundation\Include\TianoCommon.h" + +# +# Build targets +# + +all: $(TARGET_EXE) + +# +# Build EXE +# + +$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE) + $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE): $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_LIB) + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_LIB) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +# +# Build LIB +# + +$(TARGET_LIB): $(EDK_TOOLS_OUTPUT)\$(TARGET_LIB_NAME).obj + $(LIB_EXE) $(LIB_FLAGS) $(EDK_TOOLS_OUTPUT)\$(TARGET_LIB_NAME).obj /OUT:$(TARGET_LIB) + +$(EDK_TOOLS_OUTPUT)\$(TARGET_LIB_NAME).obj: $(TARGET_LIB_SOURCE) $(TARGET_LIB_INCLUDE) + $(CC) $(C_FLAGS) $(INC) $(TARGET_LIB_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\$(TARGET_LIB_NAME).obj + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/GenFfsFile.c b/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/GenFfsFile.c new file mode 100644 index 0000000000..188ca77945 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/GenFfsFile.c @@ -0,0 +1,2681 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + GenFfsFile.c + +Abstract: + + This file contains functions required to generate a Firmware File System + file. + +--*/ + +#include "TianoCommon.h" +#include "EfiFirmwareFileSystem.h" +#include "EfiFirmwareVolumeHeader.h" +#include "EfiImageFormat.h" +#include "ParseInf.h" +#include "Compress.h" +#include "EfiCustomizedCompress.h" +#include "crc32.h" +#include "GenFfsFile.h" +#include +#include // for isalpha() +// +// include file for _spawnv +// +#include +#include +#include +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" +#include "SimpleFileParsing.h" + +#define UTILITY_NAME "GenFfsFile" +#define TOOLVERSION "0.32" +#define MAX_ARRAY_SIZE 100 + +static +INT32 +GetNextLine ( + OUT CHAR8 *Destination, + IN FILE *Package, + IN OUT UINT32 *LineNumber + ); + +static +void +CheckSlash ( + IN OUT CHAR8 *String, + IN FILE *In, + IN OUT UINT32 *LineNumber + ); + +static +INT32 +FindSectionInPackage ( + IN CHAR8 *BuildDirectory, + IN FILE *OverridePackage, + IN OUT UINT32 *LineNumber + ); + +static +STATUS +ProcessCommandLineArgs ( + int Argc, + char *Argv[] + ); + +static +void +PrintUsage ( + void + ); + +// +// Keep globals in this structure +// +static struct { + UINT8 BuildDirectory[_MAX_PATH]; + UINT8 PrimaryPackagePath[_MAX_PATH]; + UINT8 OverridePackagePath[_MAX_PATH]; + BOOLEAN Verbose; +} mGlobals; + +static EFI_GUID mZeroGuid = { 0 }; + +static +void +StripQuotes ( + IN OUT CHAR8 *String + ) +/*++ + +Routine Description: + + Removes quotes and/or whitespace from around a string + +Arguments: + + String - String to remove quotes from + +Returns: + + None + +--*/ +{ + UINTN Index; + UINTN Index2; + UINTN StrLen; + + Index2 = strspn (String, "\" \t\n"); + StrLen = strlen (String); + + for (Index = Index2; String[Index] != '\"', Index < StrLen; Index++) { + String[Index - Index2] = String[Index]; + } + + String[Index - Index2] = 0; +} + +static +void +PrintUsage ( + void + ) +/*++ + +Routine Description: + + Print Error / Help message. + +Arguments: + + void + +Returns: + + None + +--*/ +{ + printf ("Usage:\n"); + printf (UTILITY_NAME " -b \"build directory\" -p1 \"package1.inf\" -p2 \"package2.inf\" -v\n"); + printf (" -b \"build directory\":\n "); + printf (" specifies the full path to the component build directory.\n"); + printf (" -p1 \"P1_path\":\n"); + printf (" specifies fully qualified file name to the primary package file.\n"); + printf (" This file will normally exist in the same directory as the makefile\n"); + printf (" for the component. Required.\n"); + printf (" -p2 \"P2_path\":\n"); + printf (" specifies fully qualified file name to the override package file.\n"); + printf (" This file will normally exist in the build tip. Optional.\n"); +} + +static +INT32 +TestComment ( + IN CHAR8 *String, + IN FILE *In + ) +/*++ + +Routine Description: + + Tests input string to see if it is a comment, and if so goes to the next line in the file that is not a comment + +Arguments: + + String - String to test + + In - Open file to move pointer within + +Returns: + + -1 - End of file reached + 0 - Not a comment + 1 - Comment bypassed + +--*/ +{ + CHAR8 CharBuffer; + + CharBuffer = 0; + if ((String[0] == '/') && (String[1] == '/')) { + while (CharBuffer != '\n') { + fscanf (In, "%c", &CharBuffer); + if (feof (In)) { + return -1; + } + } + } else { + return 0; + } + + return 1; +} + +static +void +BreakString ( + IN CONST CHAR8 *Source, + OUT CHAR8 *Destination, + IN INTN Direction + ) +/*++ + +Routine Description: + + Takes an input string and returns either the part before the =, or the part after the =, depending on direction + +Arguments: + + Source - String to break + + Destination - Buffer to place new string in + + Direction - 0 to return all of source string before = + 1 to return all of source string after = + +Returns: + + None + +--*/ +{ + UINTN Index; + UINTN Index2; + + Index = 0; + Index2 = 0; + + if (strchr (Source, '=') == NULL) { + strcpy (Destination, Source); + + return ; + } + + if (Direction == 0) { + // + // return part of string before = + // + while (Source[Index] != '=') { + Destination[Index] = Source[Index++]; + } + + Destination[Index] = 0; + } else { + // + // return part of string after = + // + strcpy (Destination, strchr (Source, '=') + 1); + } +} + +static +INT32 +GetNextLine ( + OUT CHAR8 *Destination, + IN FILE *Package, + IN OUT UINT32 *LineNumber + ) +/*++ + +Routine Description: + + Gets the next non-commented line from the file + +Arguments: + + Destination - Where to put string + + Package - Package to get string from + + LineNumber - The actual line number. + +Returns: + + -1 - End of file reached + 0 - Success + +--*/ +{ + CHAR8 String[_MAX_PATH]; + fscanf (Package, "%s", &String); + if (feof (Package)) { + return -1; + } + + while (TestComment (String, Package) == 1) { + fscanf (Package, "%s", &String); + if (feof (Package)) { + return -1; + } + } + + strcpy (Destination, String); + return 0; +} + +static +VOID +CheckSlash ( + IN OUT CHAR8 *String, + IN FILE *In, + IN OUT UINT32 *LineNumber + ) +/*++ + +Routine Description: + + Checks to see if string is line continuation character, if so goes to next valid line + +Arguments: + + String - String to test + + In - Open file to move pointer within + + LineNumber - The line number. + +Returns: + + None + +--*/ +{ + CHAR8 ByteBuffer; + ByteBuffer = 0; + + switch (String[0]) { + + case '\\': + while (String[0] == '\\') { + while (ByteBuffer != '\n') { + fscanf (In, "%c", &ByteBuffer); + } + (*LineNumber)++; + if (GetNextLine (String, In, LineNumber) == -1) { + return ; + } + } + break; + + case '\n': + (*LineNumber)++; + while (String[0] == '\n') { + if (GetNextLine (String, In, LineNumber) == -1) { + return ; + } + } + break; + + default: + break; + + } + +} + +static +INT32 +FindSectionInPackage ( + IN CHAR8 *BuildDirectory, + IN FILE *OverridePackage, + IN OUT UINT32 *LineNumber + ) +/*++ + +Routine Description: + + Finds the matching section within the package + +Arguments: + + BuildDirectory - name of section to find + + OverridePackage - Package file to search within + + LineNumber - The line number. + +Returns: + + -1 - End of file reached + 0 - Success + +--*/ +{ + CHAR8 String[_MAX_PATH]; + CHAR8 NewString[_MAX_PATH]; + String[0] = 0; + + while (strcmp (BuildDirectory, String) != 0) { + if (GetNextLine (NewString, OverridePackage, LineNumber) != 0) { + return -1; + } + + if (NewString[0] == '[') { + if (NewString[strlen (NewString) - 1] != ']') { + // + // have to construct string. + // + strcpy (String, NewString + 1); + + while (1) { + fscanf (OverridePackage, "%s", &NewString); + if (feof (OverridePackage)) { + return -1; + } + + if (NewString[0] != ']') { + if (strlen (String) != 0) { + strcat (String, " "); + } + + strcat (String, NewString); + if (String[strlen (String) - 1] == ']') { + String[strlen (String) - 1] = 0; + break; + } + } else { + break; + } + } + } else { + NewString[strlen (NewString) - 1] = 0; + strcpy (String, NewString + 1); + } + } + } + + return 0; +} + +static +EFI_STATUS +GenSimpleGuidSection ( + IN OUT UINT8 *FileBuffer, + IN OUT UINT32 *BufferSize, + IN UINT32 DataSize, + IN EFI_GUID SignGuid, + IN UINT16 GuidedSectionAttributes + ) +/*++ + +Routine Description: + + add GUIDed section header for the data buffer. + data stays in same location (overwrites source data). + +Arguments: + + FileBuffer - Buffer containing data to sign + + BufferSize - On input, the size of FileBuffer. On output, the size of + actual section data (including added section header). + + DataSize - Length of data to Sign + + SignGuid - Guid to be add. + + GuidedSectionAttributes - The section attribute. + +Returns: + + EFI_SUCCESS - Successful + EFI_OUT_OF_RESOURCES - Not enough resource. + +--*/ +{ + UINT32 TotalSize; + + EFI_GUID_DEFINED_SECTION GuidSectionHeader; + UINT8 *SwapBuffer; + + SwapBuffer = NULL; + + if (DataSize == 0) { + *BufferSize = 0; + + return EFI_SUCCESS; + } + + TotalSize = DataSize + sizeof (EFI_GUID_DEFINED_SECTION); + GuidSectionHeader.CommonHeader.Type = EFI_SECTION_GUID_DEFINED; + GuidSectionHeader.CommonHeader.Size[0] = (UINT8) (TotalSize & 0xff); + GuidSectionHeader.CommonHeader.Size[1] = (UINT8) ((TotalSize & 0xff00) >> 8); + GuidSectionHeader.CommonHeader.Size[2] = (UINT8) ((TotalSize & 0xff0000) >> 16); + memcpy (&(GuidSectionHeader.SectionDefinitionGuid), &SignGuid, sizeof (EFI_GUID)); + GuidSectionHeader.Attributes = GuidedSectionAttributes; + GuidSectionHeader.DataOffset = sizeof (EFI_GUID_DEFINED_SECTION); + + SwapBuffer = (UINT8 *) malloc (DataSize); + if (SwapBuffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + memcpy (SwapBuffer, FileBuffer, DataSize); + memcpy (FileBuffer, &GuidSectionHeader, sizeof (EFI_GUID_DEFINED_SECTION)); + memcpy (FileBuffer + sizeof (EFI_GUID_DEFINED_SECTION), SwapBuffer, DataSize); + + // + // Make sure section ends on a DWORD boundary + // + while ((TotalSize & 0x03) != 0) { + FileBuffer[TotalSize] = 0; + TotalSize++; + } + + *BufferSize = TotalSize; + + if (SwapBuffer != NULL) { + free (SwapBuffer); + } + + return EFI_SUCCESS; +} + +static +EFI_STATUS +CompressSection ( + UINT8 *FileBuffer, + UINT32 *BufferSize, + UINT32 DataSize, + CHAR8 *Type + ) +/*++ + +Routine Description: + + Compress the data and add section header for the compressed data. + Compressed data (with section header) stays in same location as the source + (overwrites source data). + +Arguments: + + FileBuffer - Buffer containing data to Compress + + BufferSize - On input, the size of FileBuffer. On output, the size of + actual compressed data (including added section header). + When buffer is too small, this value indicates the size needed. + + DataSize - The size of data to compress + + Type - The compression type (not used currently). + Assume EFI_HEAVY_COMPRESSION. + +Returns: + + EFI_BUFFER_TOO_SMALL - Buffer size is too small. + EFI_UNSUPPORTED - Compress type can not be supported. + EFI_SUCCESS - Successful + EFI_OUT_OF_RESOURCES - Not enough resource. + +--*/ +{ + EFI_STATUS Status; + UINT8 *CompData; + UINT32 CompSize; + UINT32 TotalSize; + EFI_COMPRESSION_SECTION CompressionSet; + UINT8 CompressionType; + COMPRESS_FUNCTION CompressFunction; + + Status = EFI_SUCCESS; + CompData = NULL; + CompSize = 0; + TotalSize = 0; + CompressFunction = NULL; + + // + // Get the compress type + // + if (_strcmpi (Type, "Dummy") == 0) { + // + // Added "Dummy" to keep backward compatibility. + // + CompressionType = EFI_STANDARD_COMPRESSION; + CompressFunction = (COMPRESS_FUNCTION) TianoCompress; + + } else if (_strcmpi (Type, "LZH") == 0) { + // + // EFI stardard compression (LZH) + // + CompressionType = EFI_STANDARD_COMPRESSION; + CompressFunction = (COMPRESS_FUNCTION) TianoCompress; + + } else { + // + // Customized compression + // + Status = SetCustomizedCompressionType (Type); + if (EFI_ERROR (Status)) { + return Status; + } + + CompressionType = EFI_CUSTOMIZED_COMPRESSION; + CompressFunction = (COMPRESS_FUNCTION) CustomizedCompress; + } + // + // Compress the raw data + // + Status = CompressFunction (FileBuffer, DataSize, CompData, &CompSize); + if (Status == EFI_BUFFER_TOO_SMALL) { + CompData = malloc (CompSize); + if (!CompData) { + return EFI_OUT_OF_RESOURCES; + } + + Status = CompressFunction (FileBuffer, DataSize, CompData, &CompSize); + } + + if (EFI_ERROR (Status)) { + if (CompData != NULL) { + free (CompData); + } + + return Status; + } + + TotalSize = CompSize + sizeof (EFI_COMPRESSION_SECTION); + + // + // Buffer too small? + // + if (TotalSize > *BufferSize) { + *BufferSize = TotalSize; + if (CompData != NULL) { + free (CompData); + } + + return EFI_BUFFER_TOO_SMALL; + } + // + // Add the section header for the compressed data + // + CompressionSet.CommonHeader.Type = EFI_SECTION_COMPRESSION; + CompressionSet.CommonHeader.Size[0] = (UINT8) (TotalSize & 0xff); + CompressionSet.CommonHeader.Size[1] = (UINT8) ((TotalSize & 0xff00) >> 8); + CompressionSet.CommonHeader.Size[2] = (UINT8) ((TotalSize & 0xff0000) >> 16); + CompressionSet.CompressionType = CompressionType; + CompressionSet.UncompressedLength = DataSize; + + // + // Copy header and data to the buffer + // + memcpy (FileBuffer, &CompressionSet, sizeof (EFI_COMPRESSION_SECTION)); + memcpy (FileBuffer + sizeof (CompressionSet), CompData, CompSize); + + // + // Make sure section ends on a DWORD boundary + // + while ((TotalSize & 0x03) != 0) { + FileBuffer[TotalSize] = 0; + TotalSize++; + } + + *BufferSize = TotalSize; + + if (CompData != NULL) { + free (CompData); + } + + return EFI_SUCCESS; +} + +static +void +StripParens ( + IN OUT CHAR8 *String + ) +/*++ + +Routine Description: + + Removes Parenthesis from around a string + +Arguments: + + String - String to remove parens from + +Returns: + + None + +--*/ +{ + INT32 Index; + + if (String[0] != '(') { + return ; + } + + for (Index = 1; String[Index] != ')'; Index++) { + String[Index - 1] = String[Index]; + if (String[Index] == 0) { + return ; + } + } + + String[Index - 1] = 0; + + return ; +} + +static +void +StripEqualMark ( + IN OUT CHAR8 *String + ) +/*++ + +Routine Description: + + Removes Equal Mark from around a string + +Arguments: + + String - String to remove equal mark from + +Returns: + + None + +--*/ +{ + INT32 Index; + + if (String[0] != '=' && String[strlen (String) - 1] != '=') { + return ; + } + + if (String[0] == '=') { + + for (Index = 1; String[Index] != 0; Index++) { + String[Index - 1] = String[Index]; + } + + String[Index - 1] = 0; + } + + if (String[strlen (String) - 1] == '=') { + String[strlen (String) - 1] = 0; + } + + return ; +} + +static +INT32 +ProcessEnvironmentVariable ( + IN CHAR8 *Buffer, + OUT CHAR8 *NewBuffer + ) +/*++ + +Routine Description: + + Converts environment variables to values + +Arguments: + + Buffer - Buffer containing Environment Variable String + + NewBuffer - Buffer containing value of environment variable + + +Returns: + + Number of characters from Buffer used + +--*/ +{ + INT32 Index; + INT32 Index2; + CHAR8 VariableBuffer[_MAX_PATH]; + + Index = 2; + Index2 = 0; + + while (Buffer[Index] != ')') { + VariableBuffer[Index - 2] = Buffer[Index++]; + } + + VariableBuffer[Index - 2] = 0; + Index++; + + if (getenv (VariableBuffer) != NULL) { + strcpy (NewBuffer, getenv (VariableBuffer)); + } else { + printf ("Environment variable %s not found!\n", VariableBuffer); + } + + return Index; +} + +static +void +SplitAttributesField ( + IN CHAR8 *Buffer, + IN CHAR8 *AttributesArray[], + IN OUT UINT32 *NumberOfAttributes + ) +/* + NumberOfAttributes: on input, it specifies the current number of attributes + stored in AttributeArray. + on output, it is updated to the latest number of attributes + stored in AttributesArray. +*/ +{ + UINT32 Index; + UINT32 Index2; + UINT32 z; + CHAR8 *CharBuffer; + + CharBuffer = NULL; + CharBuffer = (CHAR8 *) malloc (_MAX_PATH); + ZeroMem (CharBuffer, _MAX_PATH); + + for (Index = 0, z = 0, Index2 = 0; Index < strlen (Buffer); Index++) { + + if (Buffer[Index] != '|') { + CharBuffer[z] = Buffer[Index]; + z++; + } else { + + CharBuffer[z] = 0; + AttributesArray[*NumberOfAttributes + Index2] = CharBuffer; + Index2++; + + // + // allocate new char buffer for the next attributes string + // + CharBuffer = (CHAR8 *) malloc (_MAX_PATH); + ZeroMem (CharBuffer, _MAX_PATH); + z = 0; + } + } + + CharBuffer[z] = 0; + // + // record the last attributes string in the Buffer + // + AttributesArray[*NumberOfAttributes + Index2] = CharBuffer; + Index2++; + + *NumberOfAttributes += Index2; + + return ; +} + +static +INT32 +GetToolArguments ( + CHAR8 *ToolArgumentsArray[], + FILE *Package, + CHAR8 **PtrInputFileName, + CHAR8 **PtrOutputFileName, + EFI_GUID *Guid, + UINT16 *GuidedSectionAttributes + ) +{ + CHAR8 Buffer[_MAX_PATH]; + BOOLEAN ArgumentsFlag; + BOOLEAN InputFlag; + BOOLEAN OutputFlag; + BOOLEAN GuidFlag; + BOOLEAN AttributesFlag; + UINT32 argc; + UINT32 Index2; + UINT32 z; + CHAR8 *CharBuffer; + INT32 Index; + INT32 ReturnValue; + EFI_STATUS Status; + + CHAR8 *AttributesArray[MAX_ARRAY_SIZE]; + UINT32 NumberOfAttributes; + CHAR8 *InputFileName; + CHAR8 *OutputFileName; + UINT32 LineNumber; + Buffer[_MAX_PATH]; + + ArgumentsFlag = FALSE; + InputFlag = FALSE; + OutputFlag = FALSE; + GuidFlag = FALSE; + AttributesFlag = FALSE; + // + // Start at 1, since ToolArgumentsArray[0] + // is the program name. + // + argc = 1; + Index2 = 0; + + z = 0; + ReturnValue = 0; + NumberOfAttributes = 0; + InputFileName = NULL; + OutputFileName = NULL; + + ZeroMem (Buffer, _MAX_PATH); + ZeroMem (AttributesArray, sizeof (CHAR8 *) * MAX_ARRAY_SIZE); + LineNumber = 0; + while (Buffer[0] != ')') { + + if (GetNextLine (Buffer, Package, &LineNumber) != -1) { + CheckSlash (Buffer, Package, &LineNumber); + StripEqualMark (Buffer); + } else { + Error (NULL, 0, 0, "failed to get next line from package file", NULL); + return -1; + } + + if (Buffer[0] == ')') { + break; + } else if (_strcmpi (Buffer, "ARGS") == 0) { + + ArgumentsFlag = TRUE; + AttributesFlag = FALSE; + continue; + + } else if (_strcmpi (Buffer, "INPUT") == 0) { + + InputFlag = TRUE; + ArgumentsFlag = FALSE; + AttributesFlag = FALSE; + continue; + + } else if (_strcmpi (Buffer, "OUTPUT") == 0) { + + OutputFlag = TRUE; + ArgumentsFlag = FALSE; + AttributesFlag = FALSE; + continue; + + } else if (_strcmpi (Buffer, "GUID") == 0) { + + GuidFlag = TRUE; + ArgumentsFlag = FALSE; + AttributesFlag = FALSE; + // + // fetch the GUID for the section + // + continue; + + } else if (_strcmpi (Buffer, "ATTRIBUTES") == 0) { + + AttributesFlag = TRUE; + ArgumentsFlag = FALSE; + // + // fetch the GUIDed Section's Attributes + // + continue; + + } else if (_strcmpi (Buffer, "") == 0) { + continue; + } + // + // get all command arguments into ToolArgumentsArray + // + if (ArgumentsFlag) { + + StripEqualMark (Buffer); + + CharBuffer = (CHAR8 *) malloc (_MAX_PATH); + if (CharBuffer == NULL) { + goto ErrorExit; + } + + ZeroMem (CharBuffer, sizeof (_MAX_PATH)); + + ToolArgumentsArray[argc] = CharBuffer; + + if (Buffer[0] == '$') { + Index = ProcessEnvironmentVariable (&Buffer[0], ToolArgumentsArray[argc]); + // + // if there is string after the environment variable, cat it. + // + if ((UINT32) Index < strlen (Buffer)) { + strcat (ToolArgumentsArray[argc], &Buffer[Index]); + } + } else { + strcpy (ToolArgumentsArray[argc], Buffer); + } + + argc += 1; + ToolArgumentsArray[argc] = NULL; + continue; + } + + if (InputFlag) { + + StripEqualMark (Buffer); + + InputFileName = (CHAR8 *) malloc (_MAX_PATH); + if (InputFileName == NULL) { + goto ErrorExit; + } + + ZeroMem (InputFileName, sizeof (_MAX_PATH)); + + if (Buffer[0] == '$') { + Index = ProcessEnvironmentVariable (&Buffer[0], InputFileName); + // + // if there is string after the environment variable, cat it. + // + if ((UINT32) Index < strlen (Buffer)) { + strcat (InputFileName, &Buffer[Index]); + } + } else { + strcpy (InputFileName, Buffer); + } + + InputFlag = FALSE; + continue; + } + + if (OutputFlag) { + + StripEqualMark (Buffer); + + OutputFileName = (CHAR8 *) malloc (_MAX_PATH); + if (OutputFileName == NULL) { + goto ErrorExit; + } + + ZeroMem (OutputFileName, sizeof (_MAX_PATH)); + + if (Buffer[0] == '$') { + Index = ProcessEnvironmentVariable (&Buffer[0], OutputFileName); + // + // if there is string after the environment variable, cat it. + // + if ((UINT32) Index < strlen (Buffer)) { + strcat (OutputFileName, &Buffer[Index]); + } + } else { + strcpy (OutputFileName, Buffer); + } + + OutputFlag = FALSE; + continue; + } + + if (GuidFlag) { + + StripEqualMark (Buffer); + + Status = StringToGuid (Buffer, Guid); + if (EFI_ERROR (Status)) { + ReturnValue = -1; + goto ErrorExit; + } + + GuidFlag = FALSE; + } + + if (AttributesFlag) { + + StripEqualMark (Buffer); + + // + // there might be no space between each attribute in the statement, + // split them aside and return each attribute string + // in the AttributesArray + // + SplitAttributesField (Buffer, AttributesArray, &NumberOfAttributes); + } + } + // + // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"INPUT",InputVariable,j); + // ReplaceVariableInBuffer (ToolArgumentsArray,&i,"OUTPUT",&TargetFileName,1); + // + for (z = 0; z < NumberOfAttributes; z++) { + if (_strcmpi (AttributesArray[z], "PROCESSING_REQUIRED") == 0) { + *GuidedSectionAttributes |= EFI_GUIDED_SECTION_PROCESSING_REQUIRED; + } else if (_strcmpi (AttributesArray[z], "AUTH_STATUS_VALID") == 0) { + *GuidedSectionAttributes |= EFI_GUIDED_SECTION_AUTH_STATUS_VALID; + } + } + +ErrorExit: + + for (Index2 = 0; Index2 < MAX_ARRAY_SIZE; Index2++) { + if (AttributesArray[Index2] == NULL) { + break; + } + + free (AttributesArray[Index2]); + } + + *PtrInputFileName = InputFileName; + *PtrOutputFileName = OutputFileName; + + return ReturnValue; +} + +static +INT32 +ProcessScript ( + IN OUT UINT8 *FileBuffer, + IN FILE *Package, + IN CHAR8 *BuildDirectory, + IN BOOLEAN ForceUncompress + ) +/*++ + +Routine Description: + + Signs the section, data stays in same location + +Arguments: + + FileBuffer - Data Buffer + + Package - Points to curly brace in Image Script + + BuildDirectory - Name of the source directory parameter + + ForceUncompress - Whether to force uncompress. + +Returns: + + Number of bytes added to file buffer + -1 on error + +--*/ +{ + EFI_STATUS Status; + UINT32 Size; + CHAR8 Buffer[_MAX_PATH]; + CHAR8 Type[_MAX_PATH]; + CHAR8 FileName[_MAX_PATH]; + CHAR8 NewBuffer[_MAX_PATH]; + INT32 Index3; + INT32 Index2; + UINT32 ReturnValue; + UINT8 ByteBuffer; + FILE *InFile; + UINT32 SourceDataSize; + CHAR8 *ToolArgumentsArray[MAX_ARRAY_SIZE]; + CHAR8 *OutputFileName; + CHAR8 *InputFileName; + CHAR8 ToolName[_MAX_PATH]; + FILE *OutputFile; + FILE *InputFile; + UINT8 Temp; + int returnint; + INT32 Index; + UINT32 LineNumber; + BOOLEAN IsError; + EFI_GUID SignGuid; + UINT16 GuidedSectionAttributes; + UINT8 *TargetFileBuffer; + + OutputFileName = NULL; + InputFileName = NULL; + OutputFile = NULL; + InputFile = NULL; + IsError = FALSE; + GuidedSectionAttributes = 0; + TargetFileBuffer = NULL; + + Size = 0; + LineNumber = 0; + Buffer[0] = 0; + for (Index3 = 0; Index3 < MAX_ARRAY_SIZE; ++Index3) { + ToolArgumentsArray[Index3] = NULL; + } + + while (Buffer[0] != '}') { + if (GetNextLine (Buffer, Package, &LineNumber) != -1) { + CheckSlash (Buffer, Package, &LineNumber); + } else { + printf ("ERROR in IMAGE SCRIPT!\n"); + IsError = TRUE; + goto Done; + } + + if (_strcmpi (Buffer, "Compress") == 0) { + // + // Handle compress + // + // + // read compression type + // + if (GetNextLine (Buffer, Package, &LineNumber) != -1) { + CheckSlash (Buffer, Package, &LineNumber); + } + + StripParens (Buffer); + if (Buffer[0] == '$') { + ProcessEnvironmentVariable (&Buffer[0], Type); + } else { + strcpy (Type, Buffer); + } + // + // build buffer + // + while (Buffer[0] != '{') { + if (GetNextLine (Buffer, Package, &LineNumber) != -1) { + CheckSlash (Buffer, Package, &LineNumber); + } + } + + ReturnValue = ProcessScript (&FileBuffer[Size], Package, BuildDirectory, ForceUncompress); + if (ReturnValue == -1) { + IsError = TRUE; + goto Done; + } + // + // Call compress routine on buffer. + // Occasionally, compressed data + section header would + // be largere than the source and EFI_BUFFER_TOO_SMALL is + // returned from CompressSection() + // + SourceDataSize = ReturnValue; + + if (!ForceUncompress) { + + Status = CompressSection ( + &FileBuffer[Size], + &ReturnValue, + SourceDataSize, + Type + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + Status = CompressSection ( + &FileBuffer[Size], + &ReturnValue, + SourceDataSize, + Type + ); + } + + if (EFI_ERROR (Status)) { + IsError = TRUE; + goto Done; + } + } + + Size += ReturnValue; + + } else if (_strcmpi (Buffer, "Tool") == 0) { + + ZeroMem (ToolName, _MAX_PATH); + ZeroMem (ToolArgumentsArray, sizeof (CHAR8 *) * MAX_ARRAY_SIZE); + ZeroMem (&SignGuid, sizeof (EFI_GUID)); + + // + // handle signing Tool + // + while (Buffer[0] != '(') { + if (GetNextLine (Buffer, Package, &LineNumber) != -1) { + CheckSlash (Buffer, Package, &LineNumber); + } + } + + if (_strcmpi (Buffer, "(") == 0) { + if (GetNextLine (Buffer, Package, &LineNumber) != -1) { + CheckSlash (Buffer, Package, &LineNumber); + } + } + + StripParens (Buffer); + + if (Buffer[0] == '$') { + Index = ProcessEnvironmentVariable (&Buffer[0], ToolName); + // + // if there is string after the environment variable, cat it. + // + if ((UINT32) Index < strlen (Buffer)) { + strcat (ToolName, &Buffer[Index]); + } + } else { + strcpy (ToolName, Buffer); + } + + ToolArgumentsArray[0] = ToolName; + + // + // read ARGS + // + if (GetToolArguments ( + ToolArgumentsArray, + Package, + &InputFileName, + &OutputFileName, + &SignGuid, + &GuidedSectionAttributes + ) == -1) { + IsError = TRUE; + goto Done; + } + // + // if the tool need input file, + // dump the file buffer to the specified input file. + // + if (InputFileName != NULL) { + InputFile = fopen (InputFileName, "wb"); + if (InputFile == NULL) { + Error (NULL, 0, 0, InputFileName, "failed to open output file for writing"); + IsError = TRUE; + goto Done; + } + + fwrite (FileBuffer, sizeof (UINT8), Size, InputFile); + fclose (InputFile); + InputFile = NULL; + free (InputFileName); + InputFileName = NULL; + } + // + // dispatch signing tool + // + returnint = _spawnv (_P_WAIT, ToolName, ToolArgumentsArray); + if (returnint != 0) { + Error (NULL, 0, 0, ToolName, "external tool failed"); + IsError = TRUE; + goto Done; + } + // + // if the tool has output file, + // dump the output file to the file buffer + // + if (OutputFileName != NULL) { + + OutputFile = fopen (OutputFileName, "rb"); + if (OutputFile == NULL) { + Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing"); + IsError = TRUE; + goto Done; + } + + TargetFileBuffer = &FileBuffer[Size]; + SourceDataSize = Size; + + fread (&Temp, sizeof (UINT8), 1, OutputFile); + while (!feof (OutputFile)) { + FileBuffer[Size++] = Temp; + fread (&Temp, sizeof (UINT8), 1, OutputFile); + } + + while ((Size & 0x03) != 0) { + FileBuffer[Size] = 0; + Size++; + } + + SourceDataSize = Size - SourceDataSize; + + fclose (OutputFile); + OutputFile = NULL; + free (OutputFileName); + OutputFileName = NULL; + + if (CompareGuid (&SignGuid, &mZeroGuid) != 0) { + ReturnValue = SourceDataSize; + Status = GenSimpleGuidSection ( + TargetFileBuffer, + &ReturnValue, + SourceDataSize, + SignGuid, + GuidedSectionAttributes + ); + if (EFI_ERROR (Status)) { + IsError = TRUE; + goto Done; + } + + Size = ReturnValue; + } + } + + } else if (Buffer[0] != '}') { + // + // if we are here, we should see either a file name, + // or a }. + // + Index3 = 0; + FileName[0] = 0; + // + // Prepend the build directory to the file name if the + // file name does not already contain a full path. + // + if (!isalpha (Buffer[0]) || (Buffer[1] != ':')) { + sprintf (FileName, "%s\\", BuildDirectory); + } + + while (Buffer[Index3] != '\n') { + if (Buffer[Index3] == '$') { + Index3 += ProcessEnvironmentVariable (&Buffer[Index3], NewBuffer); + strcat (FileName, NewBuffer); + } + + if (Buffer[Index3] == 0) { + break; + } else { + Index2 = strlen (FileName); + FileName[Index2++] = Buffer[Index3++]; + FileName[Index2] = 0; + } + } + + InFile = fopen (FileName, "rb"); + if (InFile == NULL) { + Error (NULL, 0, 0, FileName, "failed to open file for reading"); + IsError = TRUE; + goto Done; + } + + fread (&ByteBuffer, sizeof (UINT8), 1, InFile); + while (!feof (InFile)) { + FileBuffer[Size++] = ByteBuffer; + fread (&ByteBuffer, sizeof (UINT8), 1, InFile); + } + + fclose (InFile); + InFile = NULL; + + // + // Make sure section ends on a DWORD boundary + // + while ((Size & 0x03) != 0) { + FileBuffer[Size] = 0; + Size++; + } + + } + } + +Done: + for (Index3 = 1; Index3 < MAX_ARRAY_SIZE; Index3++) { + if (ToolArgumentsArray[Index3] == NULL) { + break; + } + + free (ToolArgumentsArray[Index3]); + } + + if (IsError) { + return -1; + } + + return Size; + +} + +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 + +--*/ +{ + if (_strcmpi (String, "EFI_FV_FILETYPE_RAW") == 0) { + return EFI_FV_FILETYPE_RAW; + } + + if (_strcmpi (String, "EFI_FV_FILETYPE_FREEFORM") == 0) { + return EFI_FV_FILETYPE_FREEFORM; + } + + if (_strcmpi (String, "EFI_FV_FILETYPE_SECURITY_CORE") == 0) { + return EFI_FV_FILETYPE_SECURITY_CORE; + } + + if (_strcmpi (String, "EFI_FV_FILETYPE_PEI_CORE") == 0) { + return EFI_FV_FILETYPE_PEI_CORE; + } + + if (_strcmpi (String, "EFI_FV_FILETYPE_DXE_CORE") == 0) { + return EFI_FV_FILETYPE_DXE_CORE; + } + + if (_strcmpi (String, "EFI_FV_FILETYPE_PEIM") == 0) { + return EFI_FV_FILETYPE_PEIM; + } + + if (_strcmpi (String, "EFI_FV_FILETYPE_DRIVER") == 0) { + return EFI_FV_FILETYPE_DRIVER; + } + + if (_strcmpi (String, "EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER") == 0) { + return EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER; + } + + if (_strcmpi (String, "EFI_FV_FILETYPE_APPLICATION") == 0) { + return EFI_FV_FILETYPE_APPLICATION; + } + + if (_strcmpi (String, "EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE") == 0) { + return EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE; + } + + return EFI_FV_FILETYPE_ALL; +} + +static +UINT32 +AdjustFileSize ( + IN UINT8 *FileBuffer, + IN UINT32 FileSize + ) +/*++ + +Routine Description: + Adjusts file size to insure sectioned file is exactly the right length such + that it ends on exactly the last byte of the last section. ProcessScript() + may have padded beyond the end of the last section out to a 4 byte boundary. + This padding is stripped. + +Arguments: + FileBuffer - Data Buffer - contains a section stream + FileSize - Size of FileBuffer as returned from ProcessScript() + +Returns: + Corrected size of file. + +--*/ +{ + UINT32 TotalLength; + UINT32 CurrentLength; + UINT32 SectionLength; + UINT32 SectionStreamLength; + EFI_COMMON_SECTION_HEADER *SectionHeader; + EFI_COMMON_SECTION_HEADER *NextSectionHeader; + + TotalLength = 0; + CurrentLength = 0; + SectionStreamLength = FileSize; + + SectionHeader = (EFI_COMMON_SECTION_HEADER *) FileBuffer; + + while (TotalLength < SectionStreamLength) { + SectionLength = *((UINT32 *) SectionHeader->Size) & 0x00ffffff; + TotalLength += SectionLength; + + if (TotalLength == SectionStreamLength) { + return TotalLength; + } + // + // Move to the next byte following the section... + // + SectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + SectionLength); + CurrentLength = (UINTN) SectionHeader - (UINTN) FileBuffer; + + // + // Figure out where the next section begins + // + NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINT8 *) SectionHeader + 3); + NextSectionHeader = (EFI_COMMON_SECTION_HEADER *) ((UINTN) NextSectionHeader &~ (UINTN) 3); + TotalLength += (UINTN) NextSectionHeader - (UINTN) SectionHeader; + SectionHeader = NextSectionHeader; + } + + return CurrentLength; +} + +static +INT32 +MainEntry ( + INT32 argc, + CHAR8 *argv[], + BOOLEAN ForceUncompress + ) +/*++ + +Routine Description: + + MainEntry function. + +Arguments: + + argc - Number of command line parameters. + argv - Array of pointers to command line parameter strings. + ForceUncompress - If TRUE, force to do not compress the sections even if compression + is specified in the script. Otherwise, FALSE. + +Returns: + STATUS_SUCCESS - Function exits successfully. + STATUS_ERROR - Some error occurred during execution. + +--*/ +{ + FILE *PrimaryPackage; + FILE *OverridePackage; + FILE *Out; + CHAR8 BaseName[_MAX_PATH]; + EFI_GUID FfsGuid; + CHAR8 GuidString[_MAX_PATH]; + EFI_FFS_FILE_HEADER FileHeader; + CHAR8 FileType[_MAX_PATH]; + EFI_FFS_FILE_ATTRIBUTES FfsAttrib; + EFI_FFS_FILE_ATTRIBUTES FfsAttribDefined; + UINT64 FfsAlignment; + UINT32 FfsAlignment32; + CHAR8 InputString[_MAX_PATH]; + BOOLEAN ImageScriptInOveride; + UINT32 FileSize; + UINT8 *FileBuffer; + EFI_STATUS Status; + UINT32 LineNumber; +#if (PI_SPECIFICATION_VERSION < 0x00010000) + EFI_FFS_FILE_TAIL TailValue; +#endif + BaseName[0] = 0; + FileType[0] = 0; + FfsAttrib = 0; + FfsAttribDefined = 0; + FfsAlignment = 0; + FfsAlignment32 = 0; + PrimaryPackage = NULL; + Out = NULL; + OverridePackage = NULL; + FileBuffer = NULL; + + strcpy (GuidString, "00000000-0000-0000-0000-000000000000"); + Status = StringToGuid (GuidString, &FfsGuid); + if (Status != 0) { + Error (NULL, 0, 0, GuidString, "error parsing GUID string"); + return STATUS_ERROR; + } + + GuidString[0] = 0; + ImageScriptInOveride = FALSE; + // + // Initialize the simple file parsing routines. Then open + // the primary package file for parsing. + // + SFPInit (); + if (SFPOpenFile (mGlobals.PrimaryPackagePath) != STATUS_SUCCESS) { + Error (NULL, 0, 0, mGlobals.PrimaryPackagePath, "unable to open primary package file"); + goto Done; + } + // + // First token in the file must be "PACKAGE.INF" + // + if (!SFPIsToken ("PACKAGE.INF")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'PACKAGE.INF'", NULL); + goto Done; + } + // + // Find the [.] section + // + if (!SFPSkipToToken ("[.]")) { + Error (mGlobals.PrimaryPackagePath, 1, 0, "could not locate [.] section in package file", NULL); + goto Done; + } + // + // Start parsing the data. The algorithm is essentially the same for each keyword: + // 1. Identify the keyword + // 2. Verify that the keyword/value pair has not already been defined + // 3. Set some flag indicating that the keyword/value pair has been defined + // 4. Skip over the "=" + // 5. Get the value, which may be a number, TRUE, FALSE, or a string. + // + while (1) { + if (SFPIsToken ("BASE_NAME")) { + // + // Found BASE_NAME, format: + // BASE_NAME = MyBaseName + // + if (BaseName[0] != 0) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "BASE_NAME already defined", NULL); + goto Done; + } + + if (!SFPIsToken ("=")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL); + goto Done; + } + + if (!SFPGetNextToken (BaseName, sizeof (BaseName))) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid base name", NULL); + goto Done; + } + } else if (SFPIsToken ("IMAGE_SCRIPT")) { + // + // Found IMAGE_SCRIPT. Break out and process below. + // + break; + } else if (SFPIsToken ("FFS_FILEGUID")) { + // + // found FILEGUID, format: + // FFS_FILEGUID = F7845C4F-EDF5-42C5-BD8F-A02AF63DD93A + // + if (GuidString[0] != 0) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_FILEGUID already defined", NULL); + goto Done; + } + + if (!SFPIsToken ("=")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL); + goto Done; + } + + if (SFPGetGuidToken (GuidString, sizeof (GuidString)) != TRUE) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected file GUID", NULL); + goto Done; + } + + Status = StringToGuid (GuidString, &FfsGuid); + if (Status != 0) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid file GUID", NULL); + goto Done; + } + } else if (SFPIsToken ("FFS_FILETYPE")) { + // + // *********************************************************************** + // + // Found FFS_FILETYPE, format: + // FFS_FILETYPE = EFI_FV_FILETYPE_APPLICATION + // + if (FileType[0] != 0) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_FILETYPE previously defined", NULL); + goto Done; + } + + if (!SFPIsToken ("=")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL); + goto Done; + } + + if (!SFPGetNextToken (FileType, sizeof (FileType))) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected valid FFS_FILETYPE", NULL); + goto Done; + } + } +#if (PI_SPECIFICATION_VERSION < 0x00010000) + else if (SFPIsToken ("FFS_ATTRIB_HEADER_EXTENSION")) { + // + // *********************************************************************** + // + // Found: FFS_ATTRIB_HEADER_EXTENSION = FALSE + // Spec says the bit is for future expansion, and must be false. + // + if (FfsAttribDefined & FFS_ATTRIB_HEADER_EXTENSION) { + Error ( + mGlobals.PrimaryPackagePath, + SFPGetLineNumber (), + 0, + "FFS_ATTRIB_HEADER_EXTENSION previously defined", + NULL + ); + goto Done; + } + + FfsAttribDefined |= FFS_ATTRIB_HEADER_EXTENSION; + if (!SFPIsToken ("=")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL); + goto Done; + } + + if (SFPIsToken ("TRUE")) { + Error ( + mGlobals.PrimaryPackagePath, + SFPGetLineNumber (), + 0, + "only FFS_ATTRIB_HEADER_EXTENSION = FALSE is supported", + NULL + ); + goto Done; + } else if (SFPIsToken ("FALSE")) { + // + // Default is FALSE + // + } else { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'FALSE'", NULL); + goto Done; + } + } +#else + else if (SFPIsToken ("FFS_ATTRIB_FIXED")) { + // + // *********************************************************************** + // + // Found: FFS_ATTRIB_FIXED = TRUE | FALSE + // + if (FfsAttribDefined & FFS_ATTRIB_FIXED) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_FIXED previously defined", NULL); + goto Done; + } + + FfsAttribDefined |= FFS_ATTRIB_FIXED; + if (!SFPIsToken ("=")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL); + goto Done; + } + + if (SFPIsToken ("TRUE")) { + FfsAttrib |= FFS_ATTRIB_FIXED; + } else if (SFPIsToken ("FALSE")) { + // + // Default is FALSE + // + } else { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL); + goto Done; + } + } +#endif + else if (SFPIsToken ("FFS_ATTRIB_TAIL_PRESENT")) { + // + // *********************************************************************** + // + // Found: FFS_ATTRIB_TAIL_PRESENT = TRUE | FALSE + // + if (FfsAttribDefined & FFS_ATTRIB_TAIL_PRESENT) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_TAIL_PRESENT previously defined", NULL); + goto Done; + } + + FfsAttribDefined |= FFS_ATTRIB_TAIL_PRESENT; + if (!SFPIsToken ("=")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL); + goto Done; + } + + if (SFPIsToken ("TRUE")) { + FfsAttrib |= FFS_ATTRIB_TAIL_PRESENT; + } else if (SFPIsToken ("FALSE")) { + // + // Default is FALSE + // + } else { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL); + goto Done; + } + } else if (SFPIsToken ("FFS_ATTRIB_RECOVERY")) { + // + // *********************************************************************** + // + // Found: FFS_ATTRIB_RECOVERY = TRUE | FALSE + // + if (FfsAttribDefined & FFS_ATTRIB_RECOVERY) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_RECOVERY previously defined", NULL); + goto Done; + } + + FfsAttribDefined |= FFS_ATTRIB_RECOVERY; + if (!SFPIsToken ("=")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL); + goto Done; + } + + if (SFPIsToken ("TRUE")) { + FfsAttrib |= FFS_ATTRIB_RECOVERY; + } else if (SFPIsToken ("FALSE")) { + // + // Default is FALSE + // + } else { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL); + goto Done; + } + } else if (SFPIsToken ("FFS_ATTRIB_CHECKSUM")) { + // + // *********************************************************************** + // + // Found: FFS_ATTRIB_CHECKSUM = TRUE | FALSE + // + if (FfsAttribDefined & FFS_ATTRIB_CHECKSUM) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "FFS_ATTRIB_CHECKSUM previously defined", NULL); + goto Done; + } + + FfsAttribDefined |= FFS_ATTRIB_CHECKSUM; + if (!SFPIsToken ("=")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL); + goto Done; + } + + if (SFPIsToken ("TRUE")) { + FfsAttrib |= FFS_ATTRIB_CHECKSUM; + } else if (SFPIsToken ("FALSE")) { + // + // Default is FALSE + // + } else { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 'TRUE' or 'FALSE'", NULL); + goto Done; + } + } else if (SFPIsToken ("FFS_ALIGNMENT") || SFPIsToken ("FFS_ATTRIB_DATA_ALIGNMENT")) { + // + // *********************************************************************** + // + // Found FFS_ALIGNMENT, formats: + // FFS_ALIGNMENT = 0-7 + // FFS_ATTRIB_DATA_ALIGNMENT = 0-7 + // + if (FfsAttribDefined & FFS_ATTRIB_DATA_ALIGNMENT) { + Error ( + mGlobals.PrimaryPackagePath, + SFPGetLineNumber (), + 0, + "FFS_ALIGNMENT/FFS_ATTRIB_DATA_ALIGNMENT previously defined", + NULL + ); + goto Done; + } + + FfsAttribDefined |= FFS_ATTRIB_DATA_ALIGNMENT; + if (!SFPIsToken ("=")) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected '='", NULL); + goto Done; + } + + if (!SFPGetNumber (&FfsAlignment32)) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected numeric value for alignment", NULL); + goto Done; + } + + if (FfsAlignment32 > 7) { + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, "expected 0 <= alignment <= 7", NULL); + goto Done; + } + + FfsAttrib |= (((EFI_FFS_FILE_ATTRIBUTES) FfsAlignment32) << 3); + } else { + SFPGetNextToken (InputString, sizeof (InputString)); + Error (mGlobals.PrimaryPackagePath, SFPGetLineNumber (), 0, InputString, "unrecognized/unexpected token"); + goto Done; + } + } + // + // Close the primary package file + // + SFPCloseFile (); + // + // TODO: replace code below with basically a copy of the code above. Don't + // forget to reset the FfsAttribDefined variable first. Also, you'll need + // to somehow keep track of whether or not the basename is defined multiple + // times in the override package. Ditto on the file GUID. + // + if (mGlobals.OverridePackagePath[0] != 0) { + OverridePackage = fopen (mGlobals.OverridePackagePath, "r"); + // + // NOTE: For package override to work correctly, the code below must be modified to + // SET or CLEAR bits properly. For example, if the primary package set + // FFS_ATTRIB_CHECKSUM = TRUE, and the override set FFS_ATTRIB_CHECKSUM = FALSE, then + // we'd need to clear the bit below. Since this is not happening, I'm guessing that + // the override functionality is not being used, so should be made obsolete. If I'm + // wrong, and it is being used, then it needs to be fixed. Thus emit an error if it is + // used, and we'll address it then. 4/10/2003 + // + Error (__FILE__, __LINE__, 0, "package override functionality is not implemented correctly", NULL); + goto Done; + } else { + OverridePackage = NULL; + } + +#ifdef OVERRIDE_SUPPORTED + if (OverridePackage != NULL) { + // + // Parse override package file + // + fscanf (OverridePackage, "%s", &InputString); + if (_strcmpi (InputString, "PACKAGE.INF") != 0) { + Error (mGlobals.OverridePackagePath, 1, 0, "invalid package file", "expected 'PACKAGE.INF'"); + goto Done; + } + // + // Match [dir] to Build Directory + // + if (FindSectionInPackage (mGlobals.BuildDirectory, OverridePackage, &LineNumber) != 0) { + Error (mGlobals.OverridePackagePath, 1, 0, mGlobals.BuildDirectory, "section not found in package file"); + goto Done; + } + + InputString[0] = 0; + while ((InputString[0] != '[') && (!feof (OverridePackage))) { + if (GetNextLine (InputString, OverridePackage, &LineNumber) != -1) { + if (InputString[0] != '[') { +here: + if (_strcmpi (InputString, "BASE_NAME") == 0) { + // + // found BASE_NAME, next is = and string. + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (strlen (InputString) == 1) { + // + // string is just = + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + strcpy (BaseName, InputString); + } else { + BreakString (InputString, InputString, 1); + strcpy (BaseName, InputString); + } + } else if (_strcmpi (InputString, "IMAGE_SCRIPT") == 0) { + // + // found IMAGE_SCRIPT, come back later to process it + // + ImageScriptInOveride = TRUE; + fscanf (OverridePackage, "%s", &InputString); + } else if (_strcmpi (InputString, "FFS_FILEGUID") == 0) { + // + // found FILEGUID, next is = and string. + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (strlen (InputString) == 1) { + // + // string is just = + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + Status = StringToGuid (InputString, &FfsGuid); + if (Status != 0) { + Error (mGlobals.OverridePackagePath, 1, 0, InputString, "bad FFS_FILEGUID format"); + goto Done; + } + } else { + BreakString (InputString, InputString, 1); + Status = StringToGuid (InputString, &FfsGuid); + if (Status != 0) { + Error (mGlobals.OverridePackagePath, 1, 0, InputString, "bad FFS_FILEGUID format"); + goto Done; + } + } + } else if (_strcmpi (InputString, "FFS_FILETYPE") == 0) { + // + // found FILETYPE, next is = and string. + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (strlen (InputString) == 1) { + // + // string is just = + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + strcpy (FileType, InputString); + } else { + BreakString (InputString, InputString, 1); + strcpy (FileType, InputString); + } + + } else if (_strcmpi (InputString, "FFS_ATTRIB_RECOVERY") == 0) { + // + // found FFS_ATTRIB_RECOVERY, next is = and string. + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (strlen (InputString) == 1) { + // + // string is just = + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (_strcmpi (InputString, "TRUE") == 0) { + FfsAttrib |= FFS_ATTRIB_RECOVERY; + } + } else { + BreakString (InputString, InputString, 1); + if (_strcmpi (InputString, "TRUE") == 0) { + FfsAttrib |= FFS_ATTRIB_RECOVERY; + } + } + } else if (_strcmpi (InputString, "FFS_ATTRIB_CHECKSUM") == 0) { + // + // found FFS_ATTRIB_CHECKSUM, next is = and string. + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (strlen (InputString) == 1) { + // + // string is just = + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (_strcmpi (InputString, "TRUE") == 0) { + FfsAttrib |= FFS_ATTRIB_CHECKSUM; + } + } else { + BreakString (InputString, InputString, 1); + if (_strcmpi (InputString, "TRUE") == 0) { + FfsAttrib |= FFS_ATTRIB_CHECKSUM; + } + } + } else if (_strcmpi (InputString, "FFS_ALIGNMENT") == 0) { + // + // found FFS_ALIGNMENT, next is = and string. + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (strlen (InputString) == 1) { + // + // string is just = + // + fscanf (OverridePackage, "%s", &InputString); + CheckSlash (InputString, OverridePackage, &LineNumber); + } else { + BreakString (InputString, InputString, 1); + } + + AsciiStringToUint64 (InputString, FALSE, &FfsAlignment); + if (FfsAlignment > 7) { + Error (mGlobals.OverridePackagePath, 1, 0, InputString, "invalid FFS_ALIGNMENT value"); + goto Done; + } + + FfsAttrib |= (((EFI_FFS_FILE_ATTRIBUTES) FfsAlignment) << 3); + } else if (strchr (InputString, '=') != NULL) { + BreakString (InputString, String, 1); + fseek (OverridePackage, (-1 * (strlen (String) + 1)), SEEK_CUR); + BreakString (InputString, InputString, 0); + goto here; + } + } + } + } + } +#endif // #ifdef OVERRIDE_SUPPORTED + // + // Require that they specified a file GUID at least, since that's how we're + // naming the file. + // + if (GuidString[0] == 0) { + Error (mGlobals.PrimaryPackagePath, 1, 0, "FFS_FILEGUID must be specified", NULL); + return STATUS_ERROR; + } + // + // Build Header and process image script + // + FileBuffer = (UINT8 *) malloc ((1024 * 1024 * 16) * sizeof (UINT8)); + if (FileBuffer == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL); + goto Done; + } + + FileSize = 0; + if (ImageScriptInOveride) { +#ifdef OVERRIDE_SUPPORTED + rewind (OverridePackage); + LineNumber = 0; + FindSectionInPackage (mGlobals.BuildDirectory, OverridePackage, &LineNumber); + while (_strcmpi (InputString, "IMAGE_SCRIPT") != 0) { + GetNextLine (InputString, OverridePackage, &LineNumber); + CheckSlash (InputString, OverridePackage, &LineNumber); + if (strchr (InputString, '=') != NULL) { + BreakString (InputString, InputString, 0); + } + } + + while (InputString[0] != '{') { + GetNextLine (InputString, OverridePackage, &LineNumber); + CheckSlash (InputString, OverridePackage, &LineNumber); + } + // + // Found start of image script, process it + // + FileSize += ProcessScript (FileBuffer, OverridePackage, mGlobals.BuildDirectory, ForceUncompress); + if (FileSize == -1) { + Error (NULL, 0, 0, "failed to process script", NULL); + goto Done; + } + + if (StringToType (FileType) != EFI_FV_FILETYPE_RAW) { + FileSize = AdjustFileSize (FileBuffer, FileSize); + } + + if (BaseName[0] == '\"') { + StripQuotes (BaseName); + } + + if (BaseName[0] != 0) { + sprintf (InputString, "%s-%s", GuidString, BaseName); + } else { + strcpy (InputString, GuidString); + } + + switch (StringToType (FileType)) { + + case EFI_FV_FILETYPE_SECURITY_CORE: + strcat (InputString, ".SEC"); + break; + + case EFI_FV_FILETYPE_PEIM: + case EFI_FV_FILETYPE_PEI_CORE: + case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: + strcat (InputString, ".PEI"); + break; + + case EFI_FV_FILETYPE_DRIVER: + case EFI_FV_FILETYPE_DXE_CORE: + strcat (InputString, ".DXE"); + break; + + case EFI_FV_FILETYPE_APPLICATION: + strcat (InputString, ".APP"); + break; + + case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: + strcat (InputString, ".FVI"); + break; + + case EFI_FV_FILETYPE_RAW: + strcat (InputString, ".RAW"); + break; + + case EFI_FV_FILETYPE_ALL: + Error (mGlobals.OverridePackagePath, 1, 0, "invalid FFS file type for this utility", NULL); + goto Done; + + default: + strcat (InputString, ".FFS"); + break; + } + + if (ForceUncompress) { + strcat (InputString, ".ORG"); + } + + Out = fopen (InputString, "wb"); + if (Out == NULL) { + Error (NULL, 0, 0, InputString, "could not open output file for writing"); + goto Done; + } + // + // create ffs header + // + memset (&FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER)); + memcpy (&FileHeader.Name, &FfsGuid, sizeof (EFI_GUID)); + FileHeader.Type = StringToType (FileType); + FileHeader.Attributes = FfsAttrib; + // + // Now FileSize includes the EFI_FFS_FILE_HEADER + // + FileSize += sizeof (EFI_FFS_FILE_HEADER); + FileHeader.Size[0] = (UINT8) (FileSize & 0xFF); + FileHeader.Size[1] = (UINT8) ((FileSize & 0xFF00) >> 8); + FileHeader.Size[2] = (UINT8) ((FileSize & 0xFF0000) >> 16); + // + // Fill in checksums and state, these must be zero for checksumming + // + // FileHeader.IntegrityCheck.Checksum.Header = 0; + // FileHeader.IntegrityCheck.Checksum.File = 0; + // FileHeader.State = 0; + // + FileHeader.IntegrityCheck.Checksum.Header = CalculateChecksum8 ( + (UINT8 *) &FileHeader, + sizeof (EFI_FFS_FILE_HEADER) + ); + if (FileHeader.Attributes & FFS_ATTRIB_CHECKSUM) { + FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) &FileHeader, FileSize); + } else { + FileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + + FileHeader.State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID; + // + // write header + // + if (fwrite (&FileHeader, sizeof (FileHeader), 1, Out) != 1) { + Error (NULL, 0, 0, "failed to write file header to output file", NULL); + goto Done; + } + // + // write data + // + if (fwrite (FileBuffer, FileSize - sizeof (EFI_FFS_FILE_HEADER), 1, Out) != 1) { + Error (NULL, 0, 0, "failed to write all bytes to output file", NULL); + goto Done; + } + + fclose (Out); + Out = NULL; +#endif // #ifdef OVERRIDE_SUPPORTED + } else { + // + // Open primary package file and process the IMAGE_SCRIPT section + // + PrimaryPackage = fopen (mGlobals.PrimaryPackagePath, "r"); + if (PrimaryPackage == NULL) { + Error (NULL, 0, 0, mGlobals.PrimaryPackagePath, "unable to open primary package file"); + goto Done; + } + + LineNumber = 1; + FindSectionInPackage (".", PrimaryPackage, &LineNumber); + while (_strcmpi (InputString, "IMAGE_SCRIPT") != 0) { + GetNextLine (InputString, PrimaryPackage, &LineNumber); + CheckSlash (InputString, PrimaryPackage, &LineNumber); + if (strchr (InputString, '=') != NULL) { + BreakString (InputString, InputString, 0); + } + } + + while (InputString[0] != '{') { + GetNextLine (InputString, PrimaryPackage, &LineNumber); + CheckSlash (InputString, PrimaryPackage, &LineNumber); + } + // + // Found start of image script, process it + // + FileSize += ProcessScript (FileBuffer, PrimaryPackage, mGlobals.BuildDirectory, ForceUncompress); + if (FileSize == -1) { + Error (NULL, 0, 0, "failed to process script", NULL); + goto Done; + } + + if (StringToType (FileType) != EFI_FV_FILETYPE_RAW) { + FileSize = AdjustFileSize (FileBuffer, FileSize); + } + + if (BaseName[0] == '\"') { + StripQuotes (BaseName); + } + + if (BaseName[0] != 0) { + sprintf (InputString, "%s-%s", GuidString, BaseName); + } else { + strcpy (InputString, GuidString); + } + + switch (StringToType (FileType)) { + + case EFI_FV_FILETYPE_SECURITY_CORE: + strcat (InputString, ".SEC"); + break; + + case EFI_FV_FILETYPE_PEIM: + case EFI_FV_FILETYPE_PEI_CORE: + case EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER: + strcat (InputString, ".PEI"); + break; + + case EFI_FV_FILETYPE_DRIVER: + case EFI_FV_FILETYPE_DXE_CORE: + strcat (InputString, ".DXE"); + break; + + case EFI_FV_FILETYPE_APPLICATION: + strcat (InputString, ".APP"); + break; + + case EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE: + strcat (InputString, ".FVI"); + break; + + case EFI_FV_FILETYPE_RAW: + strcat (InputString, ".RAW"); + break; + + case EFI_FV_FILETYPE_ALL: + Error (mGlobals.PrimaryPackagePath, 1, 0, "invalid FFS file type for this utility", NULL); + goto Done; + + default: + strcat (InputString, ".FFS"); + break; + } + + if (ForceUncompress) { + strcat (InputString, ".ORG"); + } + + Out = fopen (InputString, "wb"); + if (Out == NULL) { + Error (NULL, 0, 0, InputString, "failed to open output file for writing"); + goto Done; + } + // + // Initialize the FFS file header + // + memset (&FileHeader, 0, sizeof (EFI_FFS_FILE_HEADER)); + memcpy (&FileHeader.Name, &FfsGuid, sizeof (EFI_GUID)); + FileHeader.Type = StringToType (FileType); + FileHeader.Attributes = FfsAttrib; + // + // From this point on FileSize includes the size of the EFI_FFS_FILE_HEADER + // + FileSize += sizeof (EFI_FFS_FILE_HEADER); + // + // If using a tail, then it adds two bytes + // + if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) { + // + // Tail is not allowed for pad and 0-length files + // + if ((FileHeader.Type == EFI_FV_FILETYPE_FFS_PAD) || (FileSize == sizeof (EFI_FFS_FILE_HEADER))) { + Error ( + mGlobals.PrimaryPackagePath, + 1, + 0, + "FFS_ATTRIB_TAIL_PRESENT=TRUE is invalid for PAD or 0-length files", + NULL + ); + goto Done; + } + + FileSize += sizeof (EFI_FFS_FILE_TAIL); + } + + FileHeader.Size[0] = (UINT8) (FileSize & 0xFF); + FileHeader.Size[1] = (UINT8) ((FileSize & 0xFF00) >> 8); + FileHeader.Size[2] = (UINT8) ((FileSize & 0xFF0000) >> 16); + // + // Fill in checksums and state, they must be 0 for checksumming. + // + // FileHeader.IntegrityCheck.Checksum.Header = 0; + // FileHeader.IntegrityCheck.Checksum.File = 0; + // FileHeader.State = 0; + // + FileHeader.IntegrityCheck.Checksum.Header = CalculateChecksum8 ( + (UINT8 *) &FileHeader, + sizeof (EFI_FFS_FILE_HEADER) + ); + if (FileHeader.Attributes & FFS_ATTRIB_CHECKSUM) { + // + // Cheating here. Since the header checksums, just calculate the checksum of the body. + // Checksum does not include the tail + // + if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) { + FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 ( + FileBuffer, + FileSize - sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_FFS_FILE_TAIL) + ); + } else { + FileHeader.IntegrityCheck.Checksum.File = CalculateChecksum8 ( + FileBuffer, + FileSize - sizeof (EFI_FFS_FILE_HEADER) + ); + } + } else { + FileHeader.IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + // + // Set the state now. Spec says the checksum assumes the state is 0 + // + FileHeader.State = EFI_FILE_HEADER_CONSTRUCTION | EFI_FILE_HEADER_VALID | EFI_FILE_DATA_VALID; + +#if (PI_SPECIFICATION_VERSION < 0x00010000) + + // + // If there is a tail, then set it + // + if (FileHeader.Attributes & FFS_ATTRIB_TAIL_PRESENT) { + TailValue = FileHeader.IntegrityCheck.TailReference; + TailValue = (UINT16) (~TailValue); + memcpy ( + (UINT8 *) FileBuffer + FileSize - sizeof (EFI_FFS_FILE_HEADER) - sizeof (EFI_FFS_FILE_TAIL), + &TailValue, + sizeof (TailValue) + ); + } +#endif + // + // Write the FFS file header + // + if (fwrite (&FileHeader, sizeof (FileHeader), 1, Out) != 1) { + Error (NULL, 0, 0, "failed to write file header contents", NULL); + goto Done; + } + // + // Write data + // + if (fwrite (FileBuffer, FileSize - sizeof (EFI_FFS_FILE_HEADER), 1, Out) != 1) { + Error (NULL, 0, 0, "failed to write file contents", NULL); + goto Done; + } + } + +Done: + SFPCloseFile (); + if (Out != NULL) { + fclose (Out); + } + + if (PrimaryPackage != NULL) { + fclose (PrimaryPackage); + } + + if (FileBuffer != NULL) { + free (FileBuffer); + } + + if (OverridePackage != NULL) { + fclose (OverridePackage); + } + + return GetUtilityStatus (); +} + +int +main ( + INT32 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. + +--*/ +{ + STATUS Status; + // + // Set the name of our utility for error reporting purposes. + // + SetUtilityName (UTILITY_NAME); + Status = ProcessCommandLineArgs (argc, argv); + if (Status != STATUS_SUCCESS) { + return Status; + } + + Status = MainEntry (argc, argv, TRUE); + if (Status == STATUS_SUCCESS) { + MainEntry (argc, argv, FALSE); + } + // + // 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. + // + return GetUtilityStatus (); +} + +static +STATUS +ProcessCommandLineArgs ( + int Argc, + char *Argv[] + ) +/*++ + +Routine Description: + Process the command line arguments. + +Arguments: + Argc - as passed in to main() + Argv - as passed in to main() + +Returns: + STATUS_SUCCESS - arguments all ok + STATUS_ERROR - problem with args, so caller should exit + +--*/ +{ + // + // If no args, then print usage instructions and return an error + // + if (Argc == 1) { + PrintUsage (); + return STATUS_ERROR; + } + + memset (&mGlobals, 0, sizeof (mGlobals)); + Argc--; + Argv++; + while (Argc > 0) { + if (_strcmpi (Argv[0], "-b") == 0) { + // + // OPTION: -b BuildDirectory + // Make sure there is another argument, then save it to our globals. + // + if (Argc < 2) { + Error (NULL, 0, 0, "-b option requires the build directory name", NULL); + return STATUS_ERROR; + } + + if (mGlobals.BuildDirectory[0]) { + Error (NULL, 0, 0, Argv[0], "option can only be specified once"); + return STATUS_ERROR; + } + + strcpy (mGlobals.BuildDirectory, Argv[1]); + Argc--; + Argv++; + } else if (_strcmpi (Argv[0], "-p1") == 0) { + // + // OPTION: -p1 PrimaryPackageFile + // Make sure there is another argument, then save it to our globals. + // + if (Argc < 2) { + Error (NULL, 0, 0, Argv[0], "option requires the primary package file name"); + return STATUS_ERROR; + } + + if (mGlobals.PrimaryPackagePath[0]) { + Error (NULL, 0, 0, Argv[0], "option can only be specified once"); + return STATUS_ERROR; + } + + strcpy (mGlobals.PrimaryPackagePath, Argv[1]); + Argc--; + Argv++; + } else if (_strcmpi (Argv[0], "-p2") == 0) { + // + // OPTION: -p2 OverridePackageFile + // Make sure there is another argument, then save it to our globals. + // + if (Argc < 2) { + Error (NULL, 0, 0, Argv[0], "option requires the override package file name"); + return STATUS_ERROR; + } + + if (mGlobals.OverridePackagePath[0]) { + Error (NULL, 0, 0, Argv[0], "option can only be specified once"); + return STATUS_ERROR; + } + + strcpy (mGlobals.OverridePackagePath, Argv[1]); + Argc--; + Argv++; + } else if (_strcmpi (Argv[0], "-v") == 0) { + // + // OPTION: -v verbose + // + mGlobals.Verbose = TRUE; + } else if (_strcmpi (Argv[0], "-h") == 0) { + // + // OPTION: -h help + // + PrintUsage (); + return STATUS_ERROR; + } else if (_strcmpi (Argv[0], "-?") == 0) { + // + // OPTION: -? help + // + PrintUsage (); + return STATUS_ERROR; + } else { + Error (NULL, 0, 0, Argv[0], "unrecognized option"); + PrintUsage (); + return STATUS_ERROR; + } + + Argv++; + Argc--; + } + // + // Must have at least specified the package file name + // + if (mGlobals.PrimaryPackagePath[0] == 0) { + Error (NULL, 0, 0, "must specify primary package file", NULL); + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/GenFfsFile.h b/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/GenFfsFile.h new file mode 100644 index 0000000000..d3bcdbb90c --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/GenFfsFile.h @@ -0,0 +1,35 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + GenFfsFile.h + +Abstract: + + Header file for GenFfsFile. + +--*/ + +// +// Module Coded to Tiano Coding Conventions +// +#ifndef _EFI_GEN_FFSFILE_H +#define _EFI_GEN_FFSFILE_H + +// +// External Files Referenced +// +#include "TianoCommon.h" +#include "EfiImageFormat.h" +#include "MyAlloc.h" + +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/makefile b/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/makefile new file mode 100644 index 0000000000..85f9cfde9a --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/makefile @@ -0,0 +1,88 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# makefile +# +# Abstract: +# +# This file is used to build the EFI GenFfsFile utility. +# +#--*/ + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Common information +# + +INC=$(INC) + +LIBS = $(LIBS) $(EDK_TOOLS_OUTPUT)\CustomizedCompress.lib + +# +# Target specific information +# + +TARGET_NAME = GenFfsFile +TARGET_SOURCE_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).exe +TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\GenFfsFile.c" +TARGET_EXE_INCLUDE = "$(EDK_SOURCE)\Foundation\Include\TianoCommon.h" \ + "$(EDK_SOURCE)\Foundation\Framework\Include\EfiFirmwareFileSystem.h" \ + "$(EDK_SOURCE)\Foundation\Framework\Include\EfiFirmwareVolumeHeader.h" \ + "$(EDK_TOOLS_COMMON)\ParseInf.h" \ + "$(EDK_TOOLS_COMMON)\MyAlloc.h" + +TARGET_EXE_LIBS = "$(EDK_TOOLS_OUTPUT)\Common.lib" +C_FLAGS = $(C_FLAGS) -W4 +# +# Build targets +# + +all: $(TARGET_EXE) + +# +# Build EXE +# + +$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE) + $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE): $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(LIBS) $(TARGET_EXE_LIBS) + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj \ + $(TARGET_LIB) $(TARGET_EXE_LIBS) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageExe.c b/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageExe.c new file mode 100644 index 0000000000..ccd1199435 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageExe.c @@ -0,0 +1,299 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + GenFvImageExe.c + +Abstract: + + 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. + +--*/ + +// +// File included in build +// +#include "GenFvImageExe.h" +#include "CommonLib.h" +#include "EfiUtilityMsgs.h" + +VOID +PrintUtilityInfo ( + VOID + ) +/*++ + +Routine Description: + + Displays the standard utility information to SDTOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ( + "%s - Tiano Firmware Volume Generation Utility."" Version %i.%i\n\n", + UTILITY_NAME, + UTILITY_MAJOR_VERSION, + UTILITY_MINOR_VERSION + ); +} + +VOID +PrintUsage ( + VOID + ) +/*++ + +Routine Description: + + Displays the utility usage syntax to STDOUT + +Arguments: + + None + +Returns: + + None + +--*/ +{ + printf ("Usage: %s -I FvInfFileName\n", UTILITY_NAME); + printf (" Where:\n"); + printf ("\tFvInfFileName is the name of the image description file.\n\n"); +} + +EFI_STATUS +main ( + IN INTN argc, + IN CHAR8 **argv + ) +/*++ + +Routine Description: + + This utility uses GenFvImage.Lib to build a firmware volume image. + +Arguments: + + FvInfFileName The name of an FV image description file. + + 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[_MAX_PATH]; + CHAR8 *InfFileImage; + UINTN InfFileSize; + UINT8 *FvImage; + UINTN FvImageSize; + UINT8 Index; + CHAR8 FvFileNameBuffer[_MAX_PATH]; + CHAR8 *FvFileName; + FILE *FvFile; + FILE *SymFile; + CHAR8 SymFileNameBuffer[_MAX_PATH]; + CHAR8 *SymFileName; + UINT8 *SymImage; + UINTN SymImageSize; + CHAR8 *CurrentSymString; + + FvFileName = FvFileNameBuffer; + SymFileName = SymFileNameBuffer; + + SetUtilityName (UTILITY_NAME); + // + // Display utility information + // + PrintUtilityInfo (); + + // + // Verify the correct number of arguments + // + if (argc != MAX_ARGS) { + Error (NULL, 0, 0, "invalid number of input parameters specified", NULL); + PrintUsage (); + return GetUtilityStatus (); + } + // + // Initialize variables + // + strcpy (InfFileName, ""); + + // + // Parse the command line arguments + // + for (Index = 1; Index < MAX_ARGS; Index += 2) { + // + // Make sure argument pair begin with - or / + // + if (argv[Index][0] != '-' && argv[Index][0] != '/') { + Error (NULL, 0, 0, argv[Index], "argument pair must begin with \"-\" or \"/\""); + PrintUsage (); + return GetUtilityStatus (); + } + // + // Make sure argument specifier is only one letter + // + if (argv[Index][2] != 0) { + Error (NULL, 0, 0, argv[Index], "unrecognized argument"); + PrintUsage (); + return GetUtilityStatus (); + } + // + // Determine argument to read + // + switch (argv[Index][1]) { + + case 'I': + case 'i': + if (strlen (InfFileName) == 0) { + strcpy (InfFileName, argv[Index + 1]); + } else { + Error (NULL, 0, 0, argv[Index + 1], "FvInfFileName may only be specified once"); + PrintUsage (); + return GetUtilityStatus (); + } + break; + + default: + Error (NULL, 0, 0, argv[Index], "unrecognized argument"); + PrintUsage (); + return GetUtilityStatus (); + break; + } + } + // + // Read the INF file image + // + Status = GetFileImage (InfFileName, &InfFileImage, &InfFileSize); + if (EFI_ERROR (Status)) { + return STATUS_ERROR; + } + // + // Call the GenFvImage lib + // + Status = GenerateFvImage ( + InfFileImage, + InfFileSize, + &FvImage, + &FvImageSize, + &FvFileName, + &SymImage, + &SymImageSize, + &SymFileName + ); + + if (EFI_ERROR (Status)) { + switch (Status) { + + case EFI_INVALID_PARAMETER: + Error (NULL, 0, 0, "invalid parameter passed to GenFvImage Lib", NULL); + return GetUtilityStatus (); + break; + + case EFI_ABORTED: + Error (NULL, 0, 0, "error detected while creating the file image", NULL); + return GetUtilityStatus (); + break; + + case EFI_OUT_OF_RESOURCES: + Error (NULL, 0, 0, "GenFvImage Lib could not allocate required resources", NULL); + return GetUtilityStatus (); + break; + + case EFI_VOLUME_CORRUPTED: + Error (NULL, 0, 0, "no base address was specified, but the FV.INF included a PEI or BSF file", NULL); + return GetUtilityStatus (); + break; + + case EFI_LOAD_ERROR: + Error (NULL, 0, 0, "could not load FV image generation library", NULL); + return GetUtilityStatus (); + break; + + default: + Error (NULL, 0, 0, "GenFvImage Lib returned unknown status", "status returned = 0x%X", Status); + return GetUtilityStatus (); + break; + } + } + // + // Write file + // + FvFile = fopen (FvFileName, "wb"); + if (FvFile == NULL) { + Error (NULL, 0, 0, FvFileName, "could not open output file"); + free (FvImage); + free (SymImage); + return GetUtilityStatus (); + } + + if (fwrite (FvImage, 1, FvImageSize, FvFile) != FvImageSize) { + Error (NULL, 0, 0, FvFileName, "failed to write to output file"); + free (FvImage); + free (SymImage); + fclose (FvFile); + return GetUtilityStatus (); + } + + fclose (FvFile); + free (FvImage); + + // + // Write symbol file + // + if (strcmp (SymFileName, "")) { + SymFile = fopen (SymFileName, "wt"); + if (SymFile == NULL) { + Error (NULL, 0, 0, SymFileName, "could not open output symbol file"); + free (SymImage); + return GetUtilityStatus (); + } + + fprintf (SymFile, "TEXTSYM format | V1.0\n"); + + CurrentSymString = SymImage; + while (((UINTN) CurrentSymString - (UINTN) SymImage) < SymImageSize) { + fprintf (SymFile, "%s", CurrentSymString); + CurrentSymString = (CHAR8 *) (((UINTN) CurrentSymString) + strlen (CurrentSymString) + 1); + } + + fclose (SymFile); + } + + free (SymImage); + + return GetUtilityStatus (); +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageExe.h b/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageExe.h new file mode 100644 index 0000000000..9b97935656 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageExe.h @@ -0,0 +1,98 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + GenFvImageExe.h + +Abstract: + + Definitions for the PeimFixup exe utility. + +--*/ + +// +// Coded to Tiano Coding Standards +// +#ifndef _EFI_GEN_FV_IMAGE_EXE_H +#define _EFI_GEN_FV_IMAGE_EXE_H + +#include +#include +#include +#include "GenFvImageLib.h" + +// +// Utility Name +// +#define UTILITY_NAME "GenFvImage" + +// +// Utility version information +// +#define UTILITY_MAJOR_VERSION 0 +#define UTILITY_MINOR_VERSION 1 +#define UTILITY_DATE __DATE__ + +// +// The maximum number of arguments accepted from the command line. +// +#define MAX_ARGS 3 + +// +// The function that displays general utility information +// +VOID +PrintUtilityInfo ( + VOID + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + None + +Returns: + + TODO: add return values + +--*/ +; + +// +// The function that displays the utility usage message. +// +VOID +PrintUsage ( + VOID + ) +/*++ + +Routine Description: + + TODO: Add function description + +Arguments: + + None + +Returns: + + TODO: add return values + +--*/ +; + +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.c b/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.c new file mode 100644 index 0000000000..3c591841ed --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.c @@ -0,0 +1,3054 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + GenFvImageLib.c + +Abstract: + + This file contains functions required to generate a Firmware Volume. + +--*/ + +// +// Include files +// +#include "GenFvImageLib.h" +#include "GenFvImageLibInternal.h" +#include +#include EFI_GUID_DEFINITION (PeiPeCoffLoader) +#include "EfiFirmwareFileSystem.h" +#include "EfiWorkingBlockHeader.h" +#include "EfiVariable.h" +#include +#include +#include "CommonLib.h" +#include "FvLib.h" +#include "EfiImage.h" +#include "crc32.h" +#include "EfiUtilityMsgs.h" +#include EFI_GUID_DEFINITION (FirmwareFileSystem) +#include EFI_GUID_DEFINITION (FirmwareFileSystem2) + +// +// Define the PE/COFF loader +// +extern EFI_PEI_PE_COFF_LOADER_PROTOCOL mPeCoffLoader; + +// +// Local function prototypes +// +EFI_STATUS +GetPe32Info ( + IN UINT8 *Pe32, + OUT UINT32 *EntryPoint, + OUT UINT32 *BaseOfCode, + OUT UINT16 *MachineType + ); + +// +// Local function implementations. +// +#if (PI_SPECIFICATION_VERSION < 0x00010000) +EFI_GUID FfsGuid = EFI_FIRMWARE_FILE_SYSTEM_GUID; +#else +EFI_GUID FfsGuid = EFI_FIRMWARE_FILE_SYSTEM2_GUID; +#endif + +EFI_GUID DefaultFvPadFileNameGuid = { 0x78f54d4, 0xcc22, 0x4048, 0x9e, 0x94, 0x87, 0x9c, 0x21, 0x4d, 0x56, 0x2f }; + +// +// 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 starutp 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 +}; + +EFI_STATUS +ParseFvInf ( + IN MEMORY_FILE *InfFile, + IN 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_PATH]; + UINT64 Value64; + UINTN Index; + EFI_STATUS Status; + + // + // Initialize FV info + // + memset (FvInfo, 0, sizeof (FV_INFO)); + + // + // Read the FV base address + // + 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, 0, EFI_FV_BASE_ADDRESS_STRING, "invalid value"); + return EFI_ABORTED; + } + + FvInfo->BaseAddress = Value64; + } else { + Error (NULL, 0, 0, EFI_FV_BASE_ADDRESS_STRING, "could not find value"); + return EFI_ABORTED; + } + // + // Read the FV Guid + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_FV_GUID_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Get the guid value + // + Status = StringToGuid (Value, &FvInfo->FvGuid); + if (EFI_ERROR (Status)) { + memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID)); + } + } else { + memcpy (&FvInfo->FvGuid, &FfsGuid, sizeof (EFI_GUID)); + } + // + // 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); + } else { + Error (NULL, 0, 0, EFI_FV_FILE_NAME_STRING, "value not specified"); + return EFI_ABORTED; + } + // + // Read the Sym file name + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_SYM_FILE_NAME_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // copy the file name + // + strcpy (FvInfo->SymName, Value); + } else { + // + // Symbols not required, so init to NULL. + // + strcpy (FvInfo->SymName, ""); + } + // + // Read the read disabled capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_DISABLED_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the read disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_READ_DISABLED_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_READ_DISABLED_CAP_STRING, "value not specified"); + return Status; + } + // + // Read the read enabled capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_ENABLED_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the read disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_READ_ENABLED_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_READ_ENABLED_CAP_STRING, "value not specified"); + return Status; + } + // + // Read the read status attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_STATUS_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the read disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_READ_STATUS; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_READ_STATUS_STRING, "value not specified"); + return Status; + } + // + // Read the write disabled capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_DISABLED_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the write disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_WRITE_DISABLED_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_WRITE_DISABLED_CAP_STRING, "value not specified"); + return Status; + } + // + // Read the write enabled capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_ENABLED_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the write disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_WRITE_ENABLED_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_WRITE_ENABLED_CAP_STRING, "value not specified"); + return Status; + } + // + // Read the write status attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_STATUS_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the write disabled flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_WRITE_STATUS; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_WRITE_STATUS_STRING, "value not specified"); + return Status; + } + // + // Read the lock capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the attribute flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_LOCK_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_LOCK_CAP_STRING, "value not specified"); + return Status; + } + // + // Read the lock status attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_LOCK_STATUS_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the attribute flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_LOCK_STATUS; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_LOCK_STATUS_STRING, "value not specified"); + return Status; + } + // + // Read the sticky write attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_STICKY_WRITE_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the attribute flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_STICKY_WRITE; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_STICKY_WRITE_STRING, "value not specified"); + return Status; + } + // + // Read the memory mapped attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_MEMORY_MAPPED_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the attribute flag + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_MEMORY_MAPPED; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_MEMORY_MAPPED_STRING, "value not specified"); + return Status; + } + // + // Read the erase polarity attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ERASE_POLARITY_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the attribute flag + // + if (strcmp (Value, ONE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ERASE_POLARITY; + } else if (strcmp (Value, ZERO_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ERASE_POLARITY_STRING, "value not specified"); + return Status; + } + +#if (PI_SPECIFICATION_VERSION >= 0x00010000) + // + // Read the read lock capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_LOCK_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_READ_LOCK_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_READ_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_READ_LOCK_CAP_STRING, "value not specified"); + return Status; + } + + // + // Read the read lock status attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_READ_LOCK_STATUS_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_READ_LOCK_STATUS; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_READ_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_READ_LOCK_STATUS_STRING, "value not specified"); + return Status; + } + + // + // Read the write lock capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_LOCK_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_WRITE_LOCK_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_CAP_STRING, "value not specified"); + return Status; + } + + // + // Read the write lock status attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_WRITE_LOCK_STATUS_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_WRITE_LOCK_STATUS; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_STATUS_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_WRITE_LOCK_STATUS_STRING, "value not specified"); + return Status; + } +#endif + +#if (PI_SPECIFICATION_VERSION < 0x00010000) + // + // Read the alignment capabilities attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_CAP_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_CAP; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_CAP_STRING, "value not specified"); + return Status; + } + + // + // Read the word alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2_STRING, "value not specified"); + return Status; + } + + + // + // Read the dword alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4_STRING, "value not specified"); + return Status; + } + // + // Read the word alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8_STRING, "value not specified"); + return Status; + } + // + // Read the qword alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16_STRING, "value not specified"); + return Status; + } + // + // Read the 32 byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32_STRING, "value not specified"); + return Status; + } + // + // Read the 64 byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64_STRING, "value not specified"); + return Status; + } + // + // Read the 128 byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_128_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_128; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_128_STRING, "value not specified"); + return Status; + } + // + // Read the 256 byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_256_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_256; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_256_STRING, "value not specified"); + return Status; + } + // + // Read the 512 byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_512_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_512; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_512_STRING, "value not specified"); + return Status; + } + // + // Read the 1K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_1K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_1K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_1K_STRING, "value not specified"); + return Status; + } + // + // Read the 2K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_2K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_2K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_2K_STRING, "value not specified"); + return Status; + } + // + // Read the 4K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_4K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_4K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_4K_STRING, "value not specified"); + return Status; + } + // + // Read the 8K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_8K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_8K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_8K_STRING, "value not specified"); + return Status; + } + // + // Read the 16K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_16K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_16K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_16K_STRING, "value not specified"); + return Status; + } + // + // Read the 32K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_32K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_32K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_32K_STRING, "value not specified"); + return Status; + } + // + // Read the 64K byte alignment capability attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB_ALIGNMENT_64K_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, TRUE_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB_ALIGNMENT_64K; + } else if (strcmp (Value, FALSE_STRING) != 0) { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "expected %s | %s", TRUE_STRING, FALSE_STRING); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB_ALIGNMENT_64K_STRING, "value not specified"); + return Status; + } + + if (!(FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_CAP) && + ( + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_128) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_256) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_512) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_1K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_2K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_4K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_8K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_16K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_32K) || + (FvInfo->FvAttributes & EFI_FVB_ALIGNMENT_64K) + ) + ){ + Error ( + NULL, + 0, + 0, + "illegal combination of alignment attributes", + "if %s is not %s, no individual alignments can be %s", + EFI_FVB_ALIGNMENT_CAP_STRING, + TRUE_STRING, + TRUE_STRING + ); + return EFI_ABORTED; + } +#else + // + // Read the PI1.0 FVB2 Alignment Capabilities Attribute + // + Status = FindToken (InfFile, ATTRIBUTES_SECTION_STRING, EFI_FVB2_ALIGNMENT_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Update attribute + // + if (strcmp (Value, EFI_FVB2_ALIGNMENT_1_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_512; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1K_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1K; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2K_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2K; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4K_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4K; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8K_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8K; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16K_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16K; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32K_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32K; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64K_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64K; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128K_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128K; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256K_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256K; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512K_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMNET_512K; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1M_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1M; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2M_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2M; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_4M_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_4M; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_8M_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_8M; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_16M_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_16M; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_32M_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_32M; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_64M_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_64M; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_128M_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_128M; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_256M_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_256M; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_512M_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_512M; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_1G_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_1G; + } else if (strcmp (Value, EFI_FVB2_ALIGNMENT_2G_STRING) == 0) { + FvInfo->FvAttributes |= EFI_FVB2_ALIGNMENT_2G; + } else { + Error (NULL, 0, 0, EFI_FVB2_ALIGNMENT_STRING, "value not correct!"); + return EFI_ABORTED; + } + } else { + Error (NULL, 0, 0, EFI_FVB2_ALIGNMENT_STRING, "value not specified"); + return Status; + } + +#endif + // + // Read block maps + // + for (Index = 0; Index < MAX_NUMBER_OF_FV_BLOCKS; Index++) { + // + // Read the number of blocks + // + 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, 0, Value, "invalid value for %s", EFI_NUM_BLOCKS_STRING); + return EFI_ABORTED; + } + + FvInfo->FvBlocks[Index].NumBlocks = (UINT32) Value64; + } else { + // + // If there is no number of blocks, but there is a size, then we have a mismatched pair + // and should return an error. + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value); + if (!EFI_ERROR (Status)) { + Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING); + return EFI_ABORTED; + } else { + // + // We are done + // + break; + } + } + // + // Read the size of blocks + // + Status = FindToken (InfFile, OPTIONS_SECTION_STRING, EFI_BLOCK_SIZE_STRING, Index, Value); + + if (Status == EFI_SUCCESS) { + // + // Update the number of blocks + // + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, Value, "invalid value specified for %s", EFI_BLOCK_SIZE_STRING); + return EFI_ABORTED; + } + + FvInfo->FvBlocks[Index].BlockLength = (UINT32) Value64; + } else { + // + // There is a number of blocks, but there is no size, so we have a mismatched pair + // and should return an error. + // + Error (NULL, 0, 0, "must specify both", "%s and %s", EFI_NUM_BLOCKS_STRING, EFI_BLOCK_SIZE_STRING); + return EFI_ABORTED; + } + } + // + // Read files + // + for (Index = 0; Index < MAX_NUMBER_OF_FILES_IN_FV; Index++) { + // + // Read the number of blocks + // + Status = FindToken (InfFile, FILES_SECTION_STRING, EFI_FILE_NAME_STRING, Index, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the file + // + strcpy (FvInfo->FvFiles[Index], Value); + } else { + break; + } + } + + if (FindSection (InfFile, COMPONENT_SECTION_STRING)) { + Index = 0; + // + // Read component FV_VARIABLE + // + Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_VARIABLE_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the component + // + strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING); + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + printf ("ERROR: %s is not a valid integer.\n", EFI_NV_VARIABLE_STRING); + return EFI_ABORTED; + } + + FvInfo->FvComponents[Index].Size = (UINTN) Value64; + } else { + printf ("WARNING: Could not read %s.\n", EFI_NV_VARIABLE_STRING); + } + + Index++; + // + // Read component FV_EVENT_LOG + // + Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_EVENT_LOG_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the component + // + strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING); + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + printf ("ERROR: %s is not a valid integer.\n", EFI_NV_EVENT_LOG_STRING); + return EFI_ABORTED; + } + + FvInfo->FvComponents[Index].Size = (UINTN) Value64; + } else { + printf ("WARNING: Could not read %s.\n", EFI_NV_EVENT_LOG_STRING); + } + + Index++; + // + // Read component FV_FTW_WORKING + // + Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_WORKING_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the component + // + strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING); + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_WORKING_STRING); + return EFI_ABORTED; + } + + FvInfo->FvComponents[Index].Size = (UINTN) Value64; + } else { + printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_WORKING_STRING); + } + + Index++; + // + // Read component FV_FTW_SPARE + // + Status = FindToken (InfFile, COMPONENT_SECTION_STRING, EFI_NV_FTW_SPARE_STRING, 0, Value); + + if (Status == EFI_SUCCESS) { + // + // Add the component + // + strcpy (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING); + Status = AsciiStringToUint64 (Value, FALSE, &Value64); + if (EFI_ERROR (Status)) { + printf ("ERROR: %s is not a valid integer.\n", EFI_NV_FTW_SPARE_STRING); + return EFI_ABORTED; + } + + FvInfo->FvComponents[Index].Size = (UINTN) Value64; + } else { + printf ("WARNING: Could not read %s.\n", EFI_NV_FTW_SPARE_STRING); + } + } + // + // Compute size for easy access later + // + FvInfo->Size = 0; + for (Index = 0; FvInfo->FvBlocks[Index].NumBlocks; Index++) { + FvInfo->Size += FvInfo->FvBlocks[Index].NumBlocks * FvInfo->FvBlocks[Index].BlockLength; + } + + 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. + +Arguments: + + FfsFile File header. + FvHeader FV header. + +Returns: + + None + +--*/ +{ + if (FvHeader->Attributes & EFI_FVB_ERASE_POLARITY) { + FfsFile->State = (UINT8)~(FfsFile->State); + } +} + +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 of the FFS file, in bytes + +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 + // + *Alignment = (1 << 0); + break; + + case 1: + // + // 16 byte alignment + // + *Alignment = (1 << 4); + break; + + case 2: + // + // 128 byte alignment + // + *Alignment = (1 << 7); + break; + + case 3: + // + // 512 byte alignment + // + *Alignment = (1 << 9); + break; + + case 4: + // + // 1K byte alignment + // + *Alignment = (1 << 10); + break; + + case 5: + // + // 4K byte alignment + // + *Alignment = (1 << 12); + break; + + case 6: + // + // 32K byte alignment + // + *Alignment = (1 << 15); + break; + + case 7: + // + // 64K byte alignment + // + *Alignment = (1 << 16); + break; + + default: + Error (NULL, 0, 0, "nvalid file attribute calculated, this is most likely a utility error", NULL); + return EFI_ABORTED; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AddPadFile ( + IN OUT MEMORY_FILE *FvImage, + IN UINT32 DataAlignment + ) +/*++ + +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. + +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; + UUID PadFileGuid; + UINTN PadFileSize; + + // + // Verify input parameters. + // + if (FvImage == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Basic assumption is we start from an 8 byte aligned address + // and our file header is a multiple of 8 bytes + // + assert ((UINTN) FvImage->CurrentFilePointer % 8 == 0); + assert (sizeof (EFI_FFS_FILE_HEADER) % 8 == 0); + + // + // Check if a pad file is necessary + // + if (((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + sizeof (EFI_FFS_FILE_HEADER)) % DataAlignment == 0) { + return EFI_SUCCESS; + } + // + // Write pad file header + // + PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer; + + // + // Verify that we have enough space for the file header + // + if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) { + return EFI_OUT_OF_RESOURCES; + } + + UuidCreate (&PadFileGuid); + memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER)); + memcpy (&PadFile->Name, &PadFileGuid, sizeof (EFI_GUID)); + PadFile->Type = EFI_FV_FILETYPE_FFS_PAD; + PadFile->Attributes = 0; + + // + // Calculate the pad file size + // + // + // This is the earliest possible valid offset (current plus pad file header + // plus the next file header) + // + PadFileSize = (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage + (sizeof (EFI_FFS_FILE_HEADER) * 2); + + // + // Add whatever it takes to get to the next aligned address + // + while ((PadFileSize % DataAlignment) != 0) { + PadFileSize++; + } + // + // Subtract the next file header size + // + PadFileSize -= sizeof (EFI_FFS_FILE_HEADER); + + // + // Subtract the starting offset to get size + // + PadFileSize -= (UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage; + + // + // Write pad file size (calculated size minus next file header size) + // + 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, sizeof (EFI_FFS_FILE_HEADER)); + if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) { + PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, PadFileSize); + } else { + 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 + ); + + // + // Verify that we have enough space (including the padding + // + if ((UINTN) (PadFile + sizeof (EFI_FFS_FILE_HEADER)) >= (UINTN) FvImage->Eof) { + return EFI_OUT_OF_RESOURCES; + } + // + // Update the current FV pointer + // + FvImage->CurrentFilePointer += PadFileSize; + + 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 + +--*/ +{ + EFI_GUID VtfGuid = EFI_FFS_VOLUME_TOP_FILE_GUID; + if (!memcmp (&FileBuffer->Name, &VtfGuid, sizeof (EFI_GUID))) { + return TRUE; + } else { + return FALSE; + } +} + +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 +RebaseFfsFile ( + IN OUT EFI_FFS_FILE_HEADER *FfsFile, + IN EFI_PHYSICAL_ADDRESS BaseAddress + ) +/*++ + +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: + + FfsFile A pointer to Ffs file image. + BaseAddress The base address to use for rebasing the file image. + +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_STATUS Status; + EFI_PEI_PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + UINTN MemoryImagePointer; + UINTN MemoryImagePointerAligned; + + EFI_PHYSICAL_ADDRESS ImageAddress; + UINT64 ImageSize; + EFI_PHYSICAL_ADDRESS EntryPoint; + + UINT32 Pe32FileSize; + UINT32 NewPe32BaseAddress; + + UINTN Index; + EFI_FILE_SECTION_POINTER CurrentPe32Section; + UINT8 FileGuidString[80]; + + // + // Verify input parameters + // + if (FfsFile == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Convert the GUID to a string so we can at least report which file + // if we find an error. + // + PrintGuidToBuffer (&FfsFile->Name, FileGuidString, sizeof (FileGuidString), TRUE); + + // + // Do some nominal checks on the file, then check for XIP. + // + Status = VerifyFfsFile (FfsFile); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "invalid FFS file", FileGuidString); + return EFI_INVALID_PARAMETER; + } + + if (FfsFile->Type != EFI_FV_FILETYPE_SECURITY_CORE && + FfsFile->Type != EFI_FV_FILETYPE_PEI_CORE && + FfsFile->Type != EFI_FV_FILETYPE_PEIM + ) { + // + // File is not XIP, so don't rebase + // + return EFI_SUCCESS; + } + // + // Rebase each PE32 section + // + for (Index = 1;; Index++) { + Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, Index, &CurrentPe32Section); + if (EFI_ERROR (Status)) { + break; + } + // + // Calculate the PE32 base address, the FFS file base plus the offset of the PE32 section + // + NewPe32BaseAddress = ((UINT32) BaseAddress) + ((UINTN) CurrentPe32Section.Pe32Section - (UINTN) FfsFile); + + // + // Initialize context + // + memset (&ImageContext, 0, sizeof (ImageContext)); + ImageContext.Handle = (VOID *) ((UINTN) CurrentPe32Section.Pe32Section + sizeof (EFI_PE32_SECTION)); + ImageContext.ImageRead = (EFI_PEI_PE_COFF_LOADER_READ_FILE) FfsRebaseImageRead; + + Status = mPeCoffLoader.GetImageInfo (&mPeCoffLoader, &ImageContext); + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "GetImageInfo() failed", FileGuidString); + return Status; + } + // + // Allocate a buffer for the image to be loaded into. + // + Pe32FileSize = GetLength (CurrentPe32Section.Pe32Section->CommonHeader.Size); + MemoryImagePointer = (UINTN) (malloc (Pe32FileSize + 0x1000)); + MemoryImagePointerAligned = (MemoryImagePointer + 0x0FFF) & (-1 << 12); + if (MemoryImagePointerAligned == 0) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return EFI_OUT_OF_RESOURCES; + } + + // + // bugbug + // + ImageContext.ImageAddress = MemoryImagePointerAligned; + Status = mPeCoffLoader.LoadImage (&mPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "LoadImage() failure", FileGuidString); + free ((VOID *) MemoryImagePointer); + return Status; + } + + Status = mPeCoffLoader.RelocateImage (&mPeCoffLoader, &ImageContext); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "RelocateImage() failure", FileGuidString); + free ((VOID *) MemoryImagePointer); + return Status; + } + + ImageAddress = ImageContext.ImageAddress; + ImageSize = ImageContext.ImageSize; + EntryPoint = ImageContext.EntryPoint; + + if (ImageSize > Pe32FileSize) { + Error ( + NULL, + 0, + 0, + "rebased PE32 is larger than original PE32 image", + "0x%X > 0x%X on file %s", + ImageSize, + Pe32FileSize, + FileGuidString + ); + free ((VOID *) MemoryImagePointer); + return EFI_ABORTED; + } + + memcpy (CurrentPe32Section.Pe32Section, (VOID *) MemoryImagePointerAligned, Pe32FileSize); + + free ((VOID *) MemoryImagePointer); + } + // + // the above for loop will always exit with EFI_NOT_FOUND if it completes + // normally. If Index == 1 at exit, then no PE32 sections were found. If it + // exits with any other error code, then something broke... + // + if (Status != EFI_NOT_FOUND) { + Error (NULL, 0, 0, "failed to parse PE32 section", FileGuidString); + return Status; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AddSymFile ( + IN UINT64 BaseAddress, + IN EFI_FFS_FILE_HEADER *FfsFile, + IN OUT MEMORY_FILE *SymImage, + IN CHAR8 *SourceFileName + ) +/*++ + +Routine Description: + + This function adds the SYM tokens in the source file to the destination file. + The SYM tokens are updated to reflect the base address. + +Arguments: + + BaseAddress The base address for the new SYM tokens. + FfsFile Pointer to the beginning of the FFS file in question. + SymImage The memory file to update with symbol information. + SourceFileName The source file. + +Returns: + + EFI_SUCCESS The function completed successfully. + EFI_INVALID_PARAMETER One of the input parameters was invalid. + EFI_ABORTED An error occurred. + +--*/ +{ + FILE *SourceFile; + + CHAR8 Buffer[_MAX_PATH]; + CHAR8 Type[_MAX_PATH]; + CHAR8 Address[_MAX_PATH]; + CHAR8 Section[_MAX_PATH]; + CHAR8 Token[_MAX_PATH]; + CHAR8 SymFileName[_MAX_PATH]; + CHAR8 CodeModuleName[_MAX_PATH]; + CHAR8 *Ptr; + + UINT64 TokenAddress; + + EFI_STATUS Status; + EFI_FILE_SECTION_POINTER Pe32Section; + UINT32 EntryPoint; + UINT32 BaseOfCode; + UINT16 MachineType; + + // + // Verify input parameters. + // + if (BaseAddress == 0 || FfsFile == NULL || SymImage == NULL || SourceFileName == NULL) { + Error (NULL, 0, 0, "invalid parameter passed to AddSymFile()", NULL); + return EFI_INVALID_PARAMETER; + } + // + // Check if we want to add this file + // + // + // Get the file name + // + strcpy (Buffer, SourceFileName); + + // + // Copy the file name for the path of the sym file and truncate the name portion. + // + strcpy (SymFileName, Buffer); + Ptr = strrchr (SymFileName, '\\'); + assert (Ptr); + Ptr[0] = 0; + + // + // Find the file extension and make it lower case + // + Ptr = strrchr (SymFileName, '.'); + if (Ptr != NULL) { + _strlwr (Ptr); + } + // + // Check if it is PEI file + // + if (strstr (Buffer, ".pei") != NULL) { + // + // Find the human readable portion + // + if (!strtok (Buffer, "-") || + !strtok (NULL, "-") || + !strtok (NULL, "-") || + !strtok (NULL, "-") || + !strtok (NULL, "-") || + !strcpy (Buffer, strtok (NULL, ".")) + ) { + Error (NULL, 0, 0, "failed to find human readable portion of the file name in AddSymFile()", NULL); + return EFI_ABORTED; + } + // + // Save code module name + // + strcpy (CodeModuleName, Buffer); + + // + // Add the symbol file name and extension to the file path. + // + strcat (Buffer, ".sym"); + strcat (SymFileName, "\\"); + strcat (SymFileName, Buffer); + } else { + // + // Only handle PEIM files. + // + return EFI_SUCCESS; + } + // + // Find PE32 section + // + Status = GetSectionByType (FfsFile, EFI_SECTION_PE32, 1, &Pe32Section); + + // + // BUGBUG: Assume if no PE32 section it is PIC and hardcode base address + // + if (Status == EFI_NOT_FOUND) { + Status = GetSectionByType (FfsFile, EFI_SECTION_TE, 1, &Pe32Section); + } + + if (Status == EFI_SUCCESS) { + Status = GetPe32Info ( + (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)), + &EntryPoint, + &BaseOfCode, + &MachineType + ); + } else { + if (Status == EFI_NOT_FOUND) { + BaseOfCode = 0x60; + Status = EFI_SUCCESS; + } else { + Error (NULL, 0, 0, "could not parse a PE32 section from the PEI file", NULL); + return Status; + } + } + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "GetPe32Info() could not get PE32 entry point for PEI file", NULL); + return Status; + } + + // + // Open the source file + // + SourceFile = fopen (SymFileName, "r"); + if (SourceFile == NULL) { + // + // SYM files are not required. + // + return EFI_SUCCESS; + } + // + // Read the first line + // + if (fgets (Buffer, _MAX_PATH, SourceFile) == NULL) { + Buffer[0] = 0; + } + // + // Make sure it matches the expected sym format + // + if (strcmp (Buffer, "TEXTSYM format | V1.0\n")) { + fclose (SourceFile); + Error (NULL, 0, 0, "AddSymFile() found unexpected sym format in input file", NULL); + return EFI_ABORTED; + } + // + // Read in the file + // + while (feof (SourceFile) == 0) { + // + // Read a line + // + if (fscanf ( + SourceFile, + "%s | %s | %s | %s\n", + Type, + Address, + Section, + Token + ) == 4) { + // + // If the token starts with "??" ignore it + // + if (Token[0] == '?' && Token[1] == '?') { + continue; + } + // + // Get the token address + // + AsciiStringToUint64 (Address, TRUE, &TokenAddress); + + // + // Add the base address + // + TokenAddress += BaseAddress; + + // + // If PE32 or TE section then find the start of code. For PIC it is hardcoded. + // + if (Pe32Section.Pe32Section) { + // + // Add the offset of the PE32 section + // + TokenAddress += (UINTN) Pe32Section.Pe32Section - (UINTN) FfsFile; + + // + // Add the size of the PE32 section header + // + TokenAddress += sizeof (EFI_PE32_SECTION); + } else { + // + // BUGBUG: Don't know why this is 0x28 bytes. + // + TokenAddress += 0x28; + } + // + // Add the beginning of the code + // + TokenAddress += BaseOfCode; + + sprintf ( + Buffer, + "%s | %016I64X | %s | _%s%s\n", + Type, + TokenAddress, + Section, + CodeModuleName, + Token + ); + memcpy (SymImage->CurrentFilePointer, Buffer, strlen (Buffer) + 1); + SymImage->CurrentFilePointer = (UINT8 *) (((UINTN) SymImage->CurrentFilePointer) + strlen (Buffer) + 1); + } + } + + fclose (SourceFile); + return EFI_SUCCESS; +} + +EFI_STATUS +AddFile ( + IN OUT MEMORY_FILE *FvImage, + IN FV_INFO *FvInfo, + IN UINTN Index, + IN OUT EFI_FFS_FILE_HEADER **VtfFileImage, + IN OUT MEMORY_FILE *SymImage + ) +/*++ + +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. + SymImage The memory image of the Sym file to update if symbols are present. + The current offset must be valid. + +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; + EFI_PHYSICAL_ADDRESS CurrentFileBaseAddress; + UINT8 VtfHeaderChecksum; + UINT8 VtfFileChecksum; + UINT8 FileState; + UINT32 TailSize; +#if (PI_SPECIFICATION_VERSION < 0x00010000) + EFI_FFS_FILE_TAIL TailValue; +#endif + // + // Verify input parameters. + // + if (FvImage == NULL || FvInfo == NULL || FvInfo->FvFiles[Index][0] == 0 || VtfFileImage == NULL || SymImage == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Read the file to add + // + NewFile = fopen (FvInfo->FvFiles[Index], "rb"); + + if (NewFile == NULL) { + Error (NULL, 0, 0, FvInfo->FvFiles[Index], "failed to open file for reading"); + return EFI_ABORTED; + } + // + // Get the file size + // + FileSize = _filelength (_fileno (NewFile)); + + // + // Read the file into a buffer + // + FileBuffer = malloc (FileSize); + if (FileBuffer == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + 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, 0, FvInfo->FvFiles[Index], "failed to read input file contents"); + return EFI_ABORTED; + } + // + // Verify space exists to add the file + // + if (FileSize > (UINTN) ((UINTN) *VtfFileImage - (UINTN) FvImage->CurrentFilePointer)) { + Error (NULL, 0, 0, FvInfo->FvFiles[Index], "insufficient space remains to add the file"); + return EFI_OUT_OF_RESOURCES; + } + // + // Update the file state based on polarity of the FV. + // + UpdateFfsFileState ( + (EFI_FFS_FILE_HEADER *) FileBuffer, + (EFI_FIRMWARE_VOLUME_HEADER *) FvImage->FileImage + ); + + // + // 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) & 0x07) != 0) { + Error (NULL, 0, 0, "VTF file does not align on 8-byte boundary", NULL); + } + // + // copy VTF File Header + // + memcpy (*VtfFileImage, FileBuffer, sizeof (EFI_FFS_FILE_HEADER)); + + // + // Copy VTF body + // + memcpy ( + (UINT8 *) *VtfFileImage + sizeof (EFI_FFS_FILE_HEADER), + FileBuffer + sizeof (EFI_FFS_FILE_HEADER), + FileSize - sizeof (EFI_FFS_FILE_HEADER) + ); + + // + // re-calculate the VTF File Header + // + FileState = (*VtfFileImage)->State; + (*VtfFileImage)->State = 0; + *(UINT32 *) ((*VtfFileImage)->Size) = FileSize; + (*VtfFileImage)->IntegrityCheck.Checksum.Header = 0; + (*VtfFileImage)->IntegrityCheck.Checksum.File = 0; + + VtfHeaderChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, sizeof (EFI_FFS_FILE_HEADER)); + (*VtfFileImage)->IntegrityCheck.Checksum.Header = VtfHeaderChecksum; + // + // Determine if it has a tail + // + if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + TailSize = sizeof (EFI_FFS_FILE_TAIL); + } else { + TailSize = 0; + } + + if ((*VtfFileImage)->Attributes & FFS_ATTRIB_CHECKSUM) { + VtfFileChecksum = CalculateChecksum8 ((UINT8 *) *VtfFileImage, FileSize - TailSize); + (*VtfFileImage)->IntegrityCheck.Checksum.File = VtfFileChecksum; + } else { + (*VtfFileImage)->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + #if (PI_SPECIFICATION_VERSION < 0x00010000) + // + // If it has a file tail, update it + // + if ((*VtfFileImage)->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + TailValue = (EFI_FFS_FILE_TAIL) (~((*VtfFileImage)->IntegrityCheck.TailReference)); + *(EFI_FFS_FILE_TAIL *) (((UINTN) (*VtfFileImage) + GetLength ((*VtfFileImage)->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue; + } + #endif + (*VtfFileImage)->State = FileState; + free (FileBuffer); + return EFI_SUCCESS; + } else { + // + // Already found a VTF file. + // + Error (NULL, 0, 0, "multiple VTF files are illegal in a single FV", NULL); + free (FileBuffer); + return EFI_ABORTED; + } + } + // + // Check if alignment is required + // + Status = ReadFfsAlignment ((EFI_FFS_FILE_HEADER *) FileBuffer, &CurrentFileAlignment); + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not determine alignment of file %s.\n", FvInfo->FvFiles[Index]); + free (FileBuffer); + return EFI_ABORTED; + } + // + // Add pad file if necessary + // + Status = AddPadFile (FvImage, CurrentFileAlignment); + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not align the file data properly.\n"); + free (FileBuffer); + return EFI_ABORTED; + } + // + // Add file + // + if ((FvImage->CurrentFilePointer + FileSize) < FvImage->Eof) { + // + // Copy the file + // + memcpy (FvImage->CurrentFilePointer, FileBuffer, FileSize); + + // + // If the file is XIP, rebase + // + CurrentFileBaseAddress = FvInfo->BaseAddress + ((UINTN) FvImage->CurrentFilePointer - (UINTN) FvImage->FileImage); + // + // Status = RebaseFfsFile ((EFI_FFS_FILE_HEADER*) FvImage->CurrentFilePointer, CurrentFileBaseAddress); + // if (EFI_ERROR(Status)) { + // printf ("ERROR: Could not rebase the file %s.\n", FvInfo->FvFiles[Index]); + // return EFI_ABORTED; + // } + // + // Update Symbol file + // + Status = AddSymFile ( + CurrentFileBaseAddress, + (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer, + SymImage, + FvInfo->FvFiles[Index] + ); + assert (!EFI_ERROR (Status)); + + // + // Update the current pointer in the FV image + // + FvImage->CurrentFilePointer += FileSize; + } else { + printf ("ERROR: The firmware volume is out of space, could not add file %s.\n", FvInfo->FvFiles[Index]); + return EFI_ABORTED; + } + // + // Make next file start at QWord Boundry + // + while (((UINTN) FvImage->CurrentFilePointer & 0x07) != 0) { + FvImage->CurrentFilePointer++; + } + // + // Free allocated memory. + // + free (FileBuffer); + + return EFI_SUCCESS; +} + +EFI_STATUS +AddVariableBlock ( + IN UINT8 *FvImage, + IN UINTN Size, + IN FV_INFO *FvInfo + ) +{ + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + VARIABLE_STORE_HEADER *VarStoreHeader; + // + // Variable block should exclude FvHeader. Since the length of + // FvHeader depends on the block map, which is variable length, + // we could only decide the actual variable block length here. + // + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage; + FvImage = FvImage + FvHeader->HeaderLength; + + VarStoreHeader = (VARIABLE_STORE_HEADER *) FvImage; + + VarStoreHeader->Signature = VARIABLE_STORE_SIGNATURE; + VarStoreHeader->Size = Size - FvHeader->HeaderLength; + VarStoreHeader->Format = VARIABLE_STORE_FORMATTED; + VarStoreHeader->State = VARIABLE_STORE_HEALTHY; + VarStoreHeader->Reserved = 0; + VarStoreHeader->Reserved1 = 0; + + return EFI_SUCCESS; +} + +EFI_STATUS +AddEventLogBlock ( + IN UINT8 *FvImage, + IN UINTN Size, + IN FV_INFO *FvInfo + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +AddFTWWorkingBlock ( + IN UINT8 *FvImage, + IN UINTN Size, + IN FV_INFO *FvInfo + ) +{ + EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *FTWHeader; + UINT32 Crc32; + + Crc32 = 0; + FTWHeader = (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER *) FvImage; + memcpy (&FTWHeader->Signature, &(FvInfo->FvGuid), sizeof (EFI_GUID)); + FTWHeader->WriteQueueSize = Size - sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER); + CalculateCrc32 (FvImage, sizeof (EFI_FAULT_TOLERANT_WORKING_BLOCK_HEADER), &Crc32); + FTWHeader->Crc = Crc32; + if (FvInfo->FvAttributes & EFI_FVB_ERASE_POLARITY) { + FTWHeader->WorkingBlockValid = 0; + FTWHeader->WorkingBlockInvalid = 1; + } else { + FTWHeader->WorkingBlockValid = 1; + FTWHeader->WorkingBlockInvalid = 0; + } + + return EFI_SUCCESS; +} + +EFI_STATUS +AddFTWSpareBlock ( + IN UINT8 *FvImage, + IN UINTN Size, + IN FV_INFO *FvInfo + ) +{ + return EFI_SUCCESS; +} + +EFI_STATUS +GenNonFFSFv ( + IN UINT8 *FvImage, + IN FV_INFO *FvInfo + ) +/*++ + +Routine Description: + + This function generate the non FFS FV image, such as the working block + and spare block. How each component of the FV is built is component + specific. + +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. + +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. + +--*/ +{ + UINTN Index; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + UINT64 TotalSize; + + FvHeader = (EFI_FIRMWARE_VOLUME_HEADER *) FvImage; + TotalSize = 0; + + for (Index = 0; FvInfo->FvComponents[Index].Size != 0; Index++) { + if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_VARIABLE_STRING) == 0) { + AddVariableBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo); + } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_EVENT_LOG_STRING) == 0) { + AddEventLogBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo); + } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_WORKING_STRING) == 0) { + AddFTWWorkingBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo); + } else if (_stricmp (FvInfo->FvComponents[Index].ComponentName, EFI_NV_FTW_SPARE_STRING) == 0) { + AddFTWSpareBlock (FvImage, FvInfo->FvComponents[Index].Size, FvInfo); + } else { + printf ("Error. Unknown Non-FFS block %s \n", FvInfo->FvComponents[Index].ComponentName); + return EFI_ABORTED; + } + + FvImage = FvImage + FvInfo->FvComponents[Index].Size; + TotalSize = TotalSize + FvInfo->FvComponents[Index].Size; + } + // + // Index and TotalSize is zero mean there's no component, so this is an empty fv + // + if ((Index != 0 || TotalSize != 0) && TotalSize != FvInfo->Size) { + printf ("Error. Component size does not sum up to FV size.\n"); + return EFI_ABORTED; + } + + 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; + + // + // 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 || (void *) FvImage->CurrentFilePointer == (void *) VtfFileImage) { + return EFI_SUCCESS; + } + // + // Pad file starts at beginning of free space + // + PadFile = (EFI_FFS_FILE_HEADER *) FvImage->CurrentFilePointer; + + // + // write header + // + memset (PadFile, 0, sizeof (EFI_FFS_FILE_HEADER)); + memcpy (&PadFile->Name, &DefaultFvPadFileNameGuid, sizeof (EFI_GUID)); + PadFile->Type = EFI_FV_FILETYPE_FFS_PAD; + PadFile->Attributes = 0; + + // + // FileSize includes the EFI_FFS_FILE_HEADER + // + FileSize = (UINTN) VtfFileImage - (UINTN) FvImage->CurrentFilePointer; + PadFile->Size[0] = (UINT8) (FileSize & 0x000000FF); + PadFile->Size[1] = (UINT8) ((FileSize & 0x0000FF00) >> 8); + PadFile->Size[2] = (UINT8) ((FileSize & 0x00FF0000) >> 16); + + // + // 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, sizeof (EFI_FFS_FILE_HEADER)); + if (PadFile->Attributes & FFS_ATTRIB_CHECKSUM) { + PadFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ((UINT8 *) PadFile, FileSize); + } else { + 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; + EFI_PHYSICAL_ADDRESS *SecCoreEntryAddressPtr; + UINT32 *Ia32ResetAddressPtr; + UINT8 *BytePointer; + UINT8 *BytePointer2; + UINT16 *WordPointer; + UINT16 CheckSum; + UINTN Index; + EFI_FFS_FILE_STATE SavedState; + UINT32 TailSize; + UINT64 FitAddress; + FIT_TABLE *FitTablePtr; +#if (PI_SPECIFICATION_VERSION < 0x00010000) + EFI_FFS_FILE_TAIL TailValue; +#endif + // + // Verify input parameters + // + if (FvImage == NULL || FvInfo == NULL || VtfFile == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Initialize FV library + // + InitializeFvLib (FvImage->FileImage, (UINTN) FvImage->Eof - (UINTN) FvImage->FileImage); + + // + // Verify VTF file + // + Status = VerifyFfsFile (VtfFile); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + // + // Find the PEI Core + // + Status = GetFileByType (EFI_FV_FILETYPE_PEI_CORE, 1, &PeiCoreFile); + if (EFI_ERROR (Status) || PeiCoreFile == NULL) { + Error (NULL, 0, 0, "could not find the PEI core in the FV", NULL); + return EFI_ABORTED; + } + // + // 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, 0, "could not find PE32 or TE section in PEI core file", NULL); + return EFI_ABORTED; + } + + Status = GetPe32Info ( + (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)), + &EntryPoint, + &BaseOfCode, + &MachineType + ); + + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "could not get PE32 entry point for PEI core", NULL); + return EFI_ABORTED; + } + // + // Physical address is FV base + offset of PE32 + offset of the entry point + // + PeiCorePhysicalAddress = FvInfo->BaseAddress; + PeiCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage; + PeiCorePhysicalAddress += EntryPoint; + + if (MachineType == EFI_IMAGE_MACHINE_IA64) { + // + // Update PEI_CORE address + // + // + // Set the uncached attribute bit in the physical address + // + PeiCorePhysicalAddress |= 0x8000000000000000; + + // + // Check if address is aligned on a 16 byte boundary + // + if (PeiCorePhysicalAddress & 0xF) { + printf ( + "ERROR: PEI_CORE entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n", + PeiCorePhysicalAddress + ); + return EFI_ABORTED; + } + // + // First Get the FIT table address + // + FitAddress = (*(UINT64 *) (FvImage->Eof - IPF_FIT_ADDRESS_OFFSET)) & 0xFFFFFFFF; + + FitTablePtr = (FIT_TABLE *) (FvImage->FileImage + (FitAddress - FvInfo->BaseAddress)); + + Status = UpdatePeiCoreEntryInFit (FitTablePtr, PeiCorePhysicalAddress); + + if (!EFI_ERROR (Status)) { + UpdateFitCheckSum (FitTablePtr); + } + // + // Find the Sec Core + // + Status = GetFileByType (EFI_FV_FILETYPE_SECURITY_CORE, 1, &SecCoreFile); + if (EFI_ERROR (Status) || SecCoreFile == NULL) { + Error (NULL, 0, 0, "could not find the Sec core in the FV", NULL); + return EFI_ABORTED; + } + // + // Sec Core found, now find PE32 section + // + Status = GetSectionByType (SecCoreFile, EFI_SECTION_PE32, 1, &Pe32Section); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "could not find PE32 section in SEC core file", NULL); + return EFI_ABORTED; + } + + Status = GetPe32Info ( + (VOID *) ((UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32)), + &EntryPoint, + &BaseOfCode, + &MachineType + ); + if (EFI_ERROR (Status)) { + Error (NULL, 0, 0, "could not get PE32 entry point for SEC core", NULL); + return EFI_ABORTED; + } + // + // Physical address is FV base + offset of PE32 + offset of the entry point + // + SecCorePhysicalAddress = FvInfo->BaseAddress; + SecCorePhysicalAddress += (UINTN) Pe32Section.Pe32Section + sizeof (EFI_SECTION_PE32) - (UINTN) FvImage->FileImage; + SecCorePhysicalAddress += EntryPoint; + + // + // Update SEC_CORE address + // + // + // Set the uncached attribute bit in the physical address + // + SecCorePhysicalAddress |= 0x8000000000000000; + + // + // Update the address + // + SecCoreEntryAddressPtr = (EFI_PHYSICAL_ADDRESS *) ((UINTN) FvImage->Eof - IPF_SALE_ENTRY_ADDRESS_OFFSET); + *SecCoreEntryAddressPtr = SecCorePhysicalAddress; + + // + // Check if address is aligned on a 16 byte boundary + // + if (SecCorePhysicalAddress & 0xF) { + printf ( + "ERROR: SALE_ENTRY entry point is not aligned on a 16 byte boundary, address specified is %Xh.\n", + SecCorePhysicalAddress + ); + return EFI_ABORTED; + } + } else if ((MachineType == EFI_IMAGE_MACHINE_IA32) || + (MachineType == EFI_IMAGE_MACHINE_X64)) { + // + // Get the location to update + // + Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - IA32_PEI_CORE_ENTRY_OFFSET); + + // + // Write lower 32 bits of physical address + // + *Ia32ResetAddressPtr = (UINT32) PeiCorePhysicalAddress; + + // + // Update the BFV base address + // + Ia32ResetAddressPtr = (UINT32 *) ((UINTN) FvImage->Eof - 4); + *Ia32ResetAddressPtr = (UINT32) (FvInfo->BaseAddress); + + CheckSum = 0x0000; + + // + // Update the Startup AP in the FVH header block ZeroVector region. + // + BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage); + BytePointer2 = (FvInfo->Size == 0x10000) ? m64kRecoveryStartupApDataArray : m128kRecoveryStartupApDataArray; + for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY; Index++) { + *BytePointer++ = *BytePointer2++; + } + // + // Calculate the checksum + // + WordPointer = (UINT16 *) ((UINTN) FvImage->FileImage); + for (Index = 0; Index < SIZEOF_STARTUP_DATA_ARRAY / 2; Index++) { + CheckSum = (UINT16) (CheckSum + ((UINT16) *WordPointer)); + WordPointer++; + } + // + // Update the checksum field + // + BytePointer = (UINT8 *) ((UINTN) FvImage->FileImage); + BytePointer += (SIZEOF_STARTUP_DATA_ARRAY - 2); + WordPointer = (UINT16 *) BytePointer; + *WordPointer = (UINT16) (0x10000 - (UINT32) CheckSum); + } else { + Error (NULL, 0, 0, "invalid machine type in PEI core", "machine type=0x%X", (UINT32) MachineType); + return EFI_ABORTED; + } + // + // Determine if it has an FFS file tail. + // + if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + TailSize = sizeof (EFI_FFS_FILE_TAIL); + } else { + TailSize = 0; + } + // + // Now update file checksum + // + SavedState = VtfFile->State; + VtfFile->IntegrityCheck.Checksum.File = 0; + VtfFile->State = 0; + if (VtfFile->Attributes & FFS_ATTRIB_CHECKSUM) { + VtfFile->IntegrityCheck.Checksum.File = CalculateChecksum8 ( + (UINT8 *) VtfFile, + GetLength (VtfFile->Size) - TailSize + ); + } else { + VtfFile->IntegrityCheck.Checksum.File = FFS_FIXED_CHECKSUM; + } + + VtfFile->State = SavedState; + +#if (PI_SPECIFICATION_VERSION < 0x00010000) + // + // Update tail if present + // + if (VtfFile->Attributes & FFS_ATTRIB_TAIL_PRESENT) { + TailValue = (EFI_FFS_FILE_TAIL) (~(VtfFile->IntegrityCheck.TailReference)); + *(EFI_FFS_FILE_TAIL *) (((UINTN) (VtfFile) + GetLength (VtfFile->Size) - sizeof (EFI_FFS_FILE_TAIL))) = TailValue; + } +#endif + 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 TE image. + 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_NT_HEADERS *NtHeader; + 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 + // is the DOS header + // + DosHeader = (EFI_IMAGE_DOS_HEADER *) Pe32; + + // + // Verify DOS header is expected + // + if (DosHeader->e_magic != EFI_IMAGE_DOS_SIGNATURE) { + printf ("ERROR: Unknown magic number in the DOS header, 0x%04X.\n", DosHeader->e_magic); + return EFI_UNSUPPORTED; + } + // + // Immediately following is the NT header. + // + NtHeader = (EFI_IMAGE_NT_HEADERS *) ((UINTN) Pe32 + DosHeader->e_lfanew); + + // + // Verify NT header is expected + // + if (NtHeader->Signature != EFI_IMAGE_NT_SIGNATURE) { + printf ("ERROR: Unrecognized image signature 0x%08X.\n", NtHeader->Signature); + return EFI_UNSUPPORTED; + } + // + // Get output + // + *EntryPoint = NtHeader->OptionalHeader.AddressOfEntryPoint; + *BaseOfCode = NtHeader->OptionalHeader.BaseOfCode; + *MachineType = NtHeader->FileHeader.Machine; + } + + // + // Verify machine type is supported + // + if (*MachineType != EFI_IMAGE_MACHINE_IA32 && + *MachineType != EFI_IMAGE_MACHINE_IA64 && + *MachineType != EFI_IMAGE_MACHINE_X64) { + printf ("ERROR: Unrecognized machine type in the PE32 file.\n"); + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} +// +// Exposed function implementations (prototypes are defined in GenFvImageLib.h) +// +EFI_STATUS +GenerateFvImage ( + IN CHAR8 *InfFileImage, + IN UINTN InfFileSize, + OUT UINT8 **FvImage, + OUT UINTN *FvImageSize, + OUT CHAR8 **FvFileName, + OUT UINT8 **SymImage, + OUT UINTN *SymImageSize, + OUT CHAR8 **SymFileName + ) +/*++ + +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. + FvImage Pointer to the FV image created. + FvImageSize Size of the FV image created and pointed to by FvImage. + FvFileName Requested name for the FV file. + SymImage Pointer to the Sym image created. + SymImageSize Size of the Sym image created and pointed to by SymImage. + SymFileName Requested name for the Sym 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 Status; + MEMORY_FILE InfMemoryFile; + MEMORY_FILE FvImageMemoryFile; + MEMORY_FILE SymImageMemoryFile; + FV_INFO FvInfo; + UINTN Index; + EFI_FIRMWARE_VOLUME_HEADER *FvHeader; + EFI_FFS_FILE_HEADER *VtfFileImage; + + // + // Check for invalid parameter + // + if (InfFileImage == NULL || FvImage == NULL || FvImageSize == NULL || FvFileName == NULL) { + return EFI_INVALID_PARAMETER; + } + // + // Initialize file structures + // + InfMemoryFile.FileImage = InfFileImage; + InfMemoryFile.CurrentFilePointer = InfFileImage; + InfMemoryFile.Eof = InfFileImage + InfFileSize; + + // + // Parse the FV inf file for header information + // + Status = ParseFvInf (&InfMemoryFile, &FvInfo); + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not parse the input INF file.\n"); + return EFI_ABORTED; + } + // + // Update the file name return values + // + strcpy (*FvFileName, FvInfo.FvName); + strcpy (*SymFileName, FvInfo.SymName); + + // + // Calculate the FV size + // + *FvImageSize = FvInfo.Size; + + // + // Allocate the FV + // + *FvImage = malloc (*FvImageSize); + if (*FvImage == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Allocate space for symbol file storage + // + *SymImage = malloc (SYMBOL_FILE_SIZE); + if (*SymImage == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // + // Initialize the FV to the erase polarity + // + if (FvInfo.FvAttributes & EFI_FVB_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 FFS GUID + // + memcpy (&FvHeader->FileSystemGuid, &FvInfo.FvGuid, sizeof (EFI_GUID)); + + FvHeader->FvLength = *FvImageSize; + FvHeader->Signature = EFI_FVH_SIGNATURE; + FvHeader->Attributes = FvInfo.FvAttributes; +#if (PI_SPECIFICATION_VERSION < 0x00010000) + FvHeader->Revision = EFI_FVH_REVISION; + FvHeader->Reserved[0] = 0; + FvHeader->Reserved[1] = 0; + FvHeader->Reserved[2] = 0; +#else + FvHeader->Revision = EFI_FVH_PI_REVISION; + FvHeader->ExtHeaderOffset = 0; + FvHeader->Reserved[0] = 0; +#endif + // + // Copy firmware block map + // + for (Index = 0; FvInfo.FvBlocks[Index].NumBlocks != 0; Index++) { + FvHeader->FvBlockMap[Index].NumBlocks = FvInfo.FvBlocks[Index].NumBlocks; + FvHeader->FvBlockMap[Index].BlockLength = FvInfo.FvBlocks[Index].BlockLength; + } + // + // Add block map terminator + // + FvHeader->FvBlockMap[Index].NumBlocks = 0; + FvHeader->FvBlockMap[Index].BlockLength = 0; + + // + // Complete the header + // + FvHeader->HeaderLength = (UINT16) (((UINTN) &(FvHeader->FvBlockMap[Index + 1])) - (UINTN) *FvImage); + FvHeader->Checksum = 0; + FvHeader->Checksum = CalculateChecksum16 ((UINT16 *) FvHeader, FvHeader->HeaderLength / sizeof (UINT16)); + + // + // If there is no FFS file, find and generate each components of the FV + // + if (FvInfo.FvFiles[0][0] == 0) { + Status = GenNonFFSFv (*FvImage, &FvInfo); + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not generate NonFFS FV.\n"); + free (*FvImage); + return EFI_ABORTED; + } + + return EFI_SUCCESS; + } + // + // Initialize our "file" view of the buffer + // + FvImageMemoryFile.FileImage = *FvImage; + FvImageMemoryFile.CurrentFilePointer = *FvImage + FvHeader->HeaderLength; + FvImageMemoryFile.Eof = *FvImage +*FvImageSize; + + // + // Initialize our "file" view of the symbol file. + // + SymImageMemoryFile.FileImage = *SymImage; + SymImageMemoryFile.CurrentFilePointer = *SymImage; + SymImageMemoryFile.Eof = *FvImage + SYMBOL_FILE_SIZE; + + // + // Initialize the FV library. + // + InitializeFvLib (FvImageMemoryFile.FileImage, FvInfo.Size); + + // + // Files start on 8 byte alignments, so move to the next 8 byte aligned + // address. For now, just assert if it isn't. Currently FV header is + // always a multiple of 8 bytes. + // BUGBUG: Handle this better + // + assert ((((UINTN) FvImageMemoryFile.CurrentFilePointer) % 8) == 0); + + // + // Initialize the VTF file address. + // + VtfFileImage = (EFI_FFS_FILE_HEADER *) FvImageMemoryFile.Eof; + + // + // Add files to FV + // + for (Index = 0; FvInfo.FvFiles[Index][0] != 0; Index++) { + // + // Add the file + // + Status = AddFile (&FvImageMemoryFile, &FvInfo, Index, &VtfFileImage, &SymImageMemoryFile); + + // + // Exit if error detected while adding the file + // + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not add file %s.\n", FvInfo.FvFiles[Index]); + free (*FvImage); + return EFI_ABORTED; + } + } + // + // 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. + // + Status = PadFvImage (&FvImageMemoryFile, VtfFileImage); + if (EFI_ERROR (Status)) { + printf ("ERROR: Could not create the pad file between the last file and the VTF file.\n"); + free (*FvImage); + return EFI_ABORTED; + } + // + // 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. 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 ((FvInfo.BaseAddress + FvInfo.Size) == FV_IMAGES_TOP_ADDRESS) { + Status = UpdateResetVector (&FvImageMemoryFile, &FvInfo, VtfFileImage); + if (EFI_ERROR(Status)) { + printf ("ERROR: Could not update the reset vector.\n"); + free (*FvImage); + return EFI_ABORTED; + } + } + } + // + // Determine final Sym file size + // + *SymImageSize = SymImageMemoryFile.CurrentFilePointer - SymImageMemoryFile.FileImage; + + return EFI_SUCCESS; +} + +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); + } +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.h b/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.h new file mode 100644 index 0000000000..e1db1b1468 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.h @@ -0,0 +1,140 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + GenFvImageLib.h + +Abstract: + + This file contains describes the public interfaces to the GenFvImage Library. + The basic purpose of the library is to create Firmware Volume images. + +--*/ + +#ifndef _EFI_GEN_FV_IMAGE_LIB_H +#define _EFI_GEN_FV_IMAGE_LIB_H + +// +// Include files +// +#include "Efi2WinNT.h" +#include "ParseInf.h" + +// +// 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 + +#pragma pack(1) + +typedef struct { + UINT64 CompAddress; + UINT32 CompSize; + UINT16 CompVersion; + UINT8 CvAndType; + UINT8 CheckSum; +} FIT_TABLE; + +#pragma pack() +// +// Exported function prototypes +// +EFI_STATUS +GenerateFvImage ( + IN CHAR8 *InfFileImage, + IN UINTN InfFileSize, + OUT UINT8 **FvImage, + OUT UINTN *FvImageSize, + OUT CHAR8 **FvFileName, + OUT UINT8 **SymImage, + OUT UINTN *SymImageSize, + OUT CHAR8 **SymFileName + ) +; + +/*++ + +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. + FvImage Pointer to the FV image created. + FvImageSize Size of the FV image created and pointed to by FvImage. + FvFileName Requested name for the FV file. + SymImage Pointer to the Sym image created. + SymImageSize Size of the Sym image created and pointed to by SymImage. + SymFileName Requested name for the Sym 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 +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. + +--*/ +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLibInternal.h b/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLibInternal.h new file mode 100644 index 0000000000..505188b495 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLibInternal.h @@ -0,0 +1,212 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + GenFvImageLibInternal.h + +Abstract: + + This file contains describes the private declarations for the GenFvImage Library. + The basic purpose of the library is to create Firmware Volume images. + +--*/ + +#ifndef _EFI_GEN_FV_IMAGE_LIB_INTERNAL_H +#define _EFI_GEN_FV_IMAGE_LIB_INTERNAL_H + +// +// Include files +// +#include "GenFvImageLib.h" +#include +#include "EfiFirmwareVolumeHeader.h" + +// +// Private data declarations +// +// +// 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_COMPONENTS_IN_FV 10 + +// +// INF file strings +// +#define OPTIONS_SECTION_STRING "[options]" +#define ATTRIBUTES_SECTION_STRING "[attributes]" +#define FILES_SECTION_STRING "[files]" +#define COMPONENT_SECTION_STRING "[components]" + +#define EFI_FV_BASE_ADDRESS_STRING "EFI_BASE_ADDRESS" +#define EFI_FV_FILE_NAME_STRING "EFI_FILE_NAME" +#define EFI_SYM_FILE_NAME_STRING "EFI_SYM_FILE_NAME" +#define EFI_NUM_BLOCKS_STRING "EFI_NUM_BLOCKS" +#define EFI_BLOCK_SIZE_STRING "EFI_BLOCK_SIZE" +#define EFI_FV_GUID_STRING "EFI_FV_GUID" + +#define EFI_FVB_READ_DISABLED_CAP_STRING "EFI_READ_DISABLED_CAP" +#define EFI_FVB_READ_ENABLED_CAP_STRING "EFI_READ_ENABLED_CAP" +#define EFI_FVB_READ_STATUS_STRING "EFI_READ_STATUS" + +#define EFI_FVB_WRITE_DISABLED_CAP_STRING "EFI_WRITE_DISABLED_CAP" +#define EFI_FVB_WRITE_ENABLED_CAP_STRING "EFI_WRITE_ENABLED_CAP" +#define EFI_FVB_WRITE_STATUS_STRING "EFI_WRITE_STATUS" + +#define EFI_FVB_LOCK_CAP_STRING "EFI_LOCK_CAP" +#define EFI_FVB_LOCK_STATUS_STRING "EFI_LOCK_STATUS" + +#define EFI_FVB_STICKY_WRITE_STRING "EFI_STICKY_WRITE" +#define EFI_FVB_MEMORY_MAPPED_STRING "EFI_MEMORY_MAPPED" +#define EFI_FVB_ERASE_POLARITY_STRING "EFI_ERASE_POLARITY" + +#define EFI_FVB_ALIGNMENT_CAP_STRING "EFI_ALIGNMENT_CAP" +#define EFI_FVB_ALIGNMENT_2_STRING "EFI_ALIGNMENT_2" +#define EFI_FVB_ALIGNMENT_4_STRING "EFI_ALIGNMENT_4" +#define EFI_FVB_ALIGNMENT_8_STRING "EFI_ALIGNMENT_8" +#define EFI_FVB_ALIGNMENT_16_STRING "EFI_ALIGNMENT_16" +#define EFI_FVB_ALIGNMENT_32_STRING "EFI_ALIGNMENT_32" +#define EFI_FVB_ALIGNMENT_64_STRING "EFI_ALIGNMENT_64" +#define EFI_FVB_ALIGNMENT_128_STRING "EFI_ALIGNMENT_128" +#define EFI_FVB_ALIGNMENT_256_STRING "EFI_ALIGNMENT_256" +#define EFI_FVB_ALIGNMENT_512_STRING "EFI_ALIGNMENT_512" +#define EFI_FVB_ALIGNMENT_1K_STRING "EFI_ALIGNMENT_1K" +#define EFI_FVB_ALIGNMENT_2K_STRING "EFI_ALIGNMENT_2K" +#define EFI_FVB_ALIGNMENT_4K_STRING "EFI_ALIGNMENT_4K" +#define EFI_FVB_ALIGNMENT_8K_STRING "EFI_ALIGNMENT_8K" +#define EFI_FVB_ALIGNMENT_16K_STRING "EFI_ALIGNMENT_16K" +#define EFI_FVB_ALIGNMENT_32K_STRING "EFI_ALIGNMENT_32K" +#define EFI_FVB_ALIGNMENT_64K_STRING "EFI_ALIGNMENT_64K" + +// +// Add these for PI1.0 new Attributes. +// +#define EFI_FVB_READ_LOCK_CAP_STRING "EFI_READ_LOCK_CAP" +#define EFI_FVB_READ_LOCK_STATUS_STRING "EFI_READ_LOCK_STATUS" +#define EFI_FVB_WRITE_LOCK_CAP_STRING "EFI_WRITE_LOCK_CAP" +#define EFI_FVB_WRITE_LOCK_STATUS_STRING "EFI_WRITE_LOCK_STATUS" +#define EFI_FVB2_ALIGNMENT_STRING "EFI_FVB2_ALIGNMENT" + +#define EFI_FVB2_ALIGNMENT_1_STRING "1" +#define EFI_FVB2_ALIGNMENT_2_STRING "2" +#define EFI_FVB2_ALIGNMENT_4_STRING "4" +#define EFI_FVB2_ALIGNMENT_8_STRING "8" +#define EFI_FVB2_ALIGNMENT_16_STRING "16" +#define EFI_FVB2_ALIGNMENT_32_STRING "32" +#define EFI_FVB2_ALIGNMENT_64_STRING "64" +#define EFI_FVB2_ALIGNMENT_128_STRING "128" +#define EFI_FVB2_ALIGNMENT_256_STRING "256" +#define EFI_FVB2_ALIGNMENT_512_STRING "512" +#define EFI_FVB2_ALIGNMENT_1K_STRING "1K" +#define EFI_FVB2_ALIGNMENT_2K_STRING "2K" +#define EFI_FVB2_ALIGNMENT_4K_STRING "4K" +#define EFI_FVB2_ALIGNMENT_8K_STRING "8K" +#define EFI_FVB2_ALIGNMENT_16K_STRING "16K" +#define EFI_FVB2_ALIGNMENT_32K_STRING "32K" +#define EFI_FVB2_ALIGNMENT_64K_STRING "64K" +#define EFI_FVB2_ALIGNMENT_128K_STRING "128K" +#define EFI_FVB2_ALIGNMENT_256K_STRING "256K" +#define EFI_FVB2_ALIGNMENT_512K_STRING "512K" +#define EFI_FVB2_ALIGNMENT_1M_STRING "1M" +#define EFI_FVB2_ALIGNMENT_2M_STRING "2M" +#define EFI_FVB2_ALIGNMENT_4M_STRING "4M" +#define EFI_FVB2_ALIGNMENT_8M_STRING "8M" +#define EFI_FVB2_ALIGNMENT_16M_STRING "16M" +#define EFI_FVB2_ALIGNMENT_32M_STRING "32M" +#define EFI_FVB2_ALIGNMENT_64M_STRING "64M" +#define EFI_FVB2_ALIGNMENT_128M_STRING "128M" +#define EFI_FVB2_ALIGNMENT_256M_STRING "256M" +#define EFI_FVB2_ALIGNMENT_512M_STRING "512M" +#define EFI_FVB2_ALIGNMENT_1G_STRING "1G" +#define EFI_FVB2_ALIGNMENT_2G_STRING "2G" + + +// +// Component sections +// +#define EFI_NV_VARIABLE_STRING "EFI_NV_VARIABLE" +#define EFI_NV_EVENT_LOG_STRING "EFI_NV_EVENT_LOG" +#define EFI_NV_FTW_WORKING_STRING "EFI_NV_FTW_WORKING" +#define EFI_NV_FTW_SPARE_STRING "EFI_NV_FTW_SPARE" + +#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" + +// +// Defines to calculate the offset for PEI CORE entry points +// +#define IA32_PEI_CORE_ENTRY_OFFSET 0x20 + +// +// Defines to calculate the FIT table +// +#define IPF_FIT_ADDRESS_OFFSET 0x20 + +// +// Defines to calculate the offset for SALE_ENTRY +// +#define IPF_SALE_ENTRY_ADDRESS_OFFSET 0x18 + +// +// Symbol file definitions, current max size if 512K +// +#define SYMBOL_FILE_SIZE 0x80000 + +#define FV_IMAGES_TOP_ADDRESS 0x100000000 + +// +// Private data types +// +// +// Component information +// +typedef struct { + UINTN Size; + CHAR8 ComponentName[_MAX_PATH]; +} COMPONENT_INFO; + +// +// FV information holder +// +typedef struct { + EFI_PHYSICAL_ADDRESS BaseAddress; + EFI_GUID FvGuid; + UINTN Size; + CHAR8 FvName[_MAX_PATH]; + CHAR8 SymName[_MAX_PATH]; + EFI_FV_BLOCK_MAP_ENTRY FvBlocks[MAX_NUMBER_OF_FV_BLOCKS]; + EFI_FVB_ATTRIBUTES FvAttributes; + CHAR8 FvFiles[MAX_NUMBER_OF_FILES_IN_FV][_MAX_PATH]; + COMPONENT_INFO FvComponents[MAX_NUMBER_OF_COMPONENTS_IN_FV]; +} FV_INFO; + +// +// Private function prototypes +// +EFI_STATUS +ParseFvInf ( + IN MEMORY_FILE *InfFile, + IN FV_INFO *FvInfo + ) +; + +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/Makefile new file mode 100644 index 0000000000..d3b43c0ab7 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/Makefile @@ -0,0 +1,109 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: makefile +# +# Abstract: +# +# This file is used to build the EFI utility. +# +#--*/ + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Common information +# + +INC=$(INC) \ + -I "$(EDK_TOOLS_COMMON)" + + + +# +# Target specific information +# + +TARGET_NAME=GenFvImage + +TARGET_SOURCE_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) +TARGET_LIB = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).lib +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).exe +TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\GenFvImageExe.c" + +TARGET_EXE_INCLUDE = "$(TARGET_SOURCE_DIR)\GenFvImageExe.h" \ + "$(TARGET_SOURCE_DIR)\GenFvImageLib.h" \ + "$(EDK_TOOLS_COMMON)\ParseInf.h" \ + "$(EDK_SOURCE)\Foundation\Include\TianoCommon.h" + +TARGET_EXE_LIBS = "$(EDK_TOOLS_OUTPUT)\Common.lib" +TARGET_LIB_SOURCE = "$(TARGET_SOURCE_DIR)\GenFvImageLib.c" + +TARGET_LIB_INCLUDE = "$(TARGET_SOURCE_DIR)\GenFvImageLib.h" \ + "$(TARGET_SOURCE_DIR)\GenFvImageLibInternal.h" \ + "$(EDK_TOOLS_COMMON)\ParseInf.h" \ + "$(EDK_SOURCE)\Foundation\Include\TianoCommon.h" \ + "$(EDK_SOURCE)\Foundation\Framework\Include\EfiFirmwareVolumeHeader.h" \ + "$(EDK_SOURCE)\Foundation\Framework\Include\EfiFirmwareFileSystem.h" \ + "$(EDK_SOURCE)\Foundation\Framework\Guid\FirmwareFileSystem\FirmwareFileSystem.h" + +TARGET_LIB_LIBS = "$(EDK_TOOLS_OUTPUT)\Common.lib" +# +# Build targets +# + +all: $(TARGET_EXE) + +# +# Build EXE +# + +$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE) + $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE): $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_EXE_LIBS) $(TARGET_LIB) + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_LIB) $(TARGET_EXE_LIBS) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +# +# Build LIB +# + +$(TARGET_LIB): $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.obj $(TARGET_LIB_LIBS) + $(LIB_EXE) $(LIB_FLAGS) $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.obj $(MSVS_LINK_LIBPATHS) $(TARGET_LIB_LIBS) RPCRT4.lib /OUT:$(TARGET_LIB) + +$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.obj: $(TARGET_LIB_SOURCE) $(TARGET_LIB_INCLUDE) + $(CC) $(C_FLAGS) $(INC) $(TARGET_LIB_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.obj + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Lib.* > NUL + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenPage/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/GenPage/Makefile new file mode 100644 index 0000000000..8c4addb43d --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenPage/Makefile @@ -0,0 +1,95 @@ +#/*++ +# +# Copyright (c) 2006 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Makefile +# +# Abstract: +# +# makefile for building the GenPage utility. +# +#--*/ + +# +# Make sure environmental variable EDK_SOURCE is set +# +!IFNDEF EDK_SOURCE +!ERROR EDK_SOURCE environmental variable not set +!ENDIF + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Define some macros we use here. Should get rid of them someday and +# get rid of the extra level of indirection. +# +COMMON_SOURCE = $(EDK_TOOLS_COMMON) + +# +# Common information +# + +INC=$(INC) + +# +# Target specific information +# + +TARGET_NAME=GenPage +TARGET_SOURCE_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) + +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).exe + +TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\GenPage.c" +TARGET_EXE_INCLUDE = "$(TARGET_SOURCE_DIR)\VirtualMemory.h" + +# +# Build targets +# + +all: $(TARGET_EXE) + +# +# Build EXE +# + +$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE) + $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE): $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) /out:$(TARGET_EXE) $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL + diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenPage/VirtualMemory.h b/EdkCompatibilityPkg/Sample/Tools/Source/GenPage/VirtualMemory.h new file mode 100644 index 0000000000..d9d928f4e4 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenPage/VirtualMemory.h @@ -0,0 +1,127 @@ +/*++ + +Copyright 2006 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + VirtualMemory.h + +Abstract: + + x64 Long Mode Virtual Memory Management Definitions + + References: + 1) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 1:Basic Architecture, Intel + 2) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 2:Instruction Set Reference, Intel + 3) IA-32 Intel(R) Atchitecture Software Developer's Manual Volume 3:System Programmer's Guide, Intel + 4) AMD64 Architecture Programmer's Manual Volume 2: System Programming +--*/ + +#ifndef _VIRTUAL_MEMORY_H_ +#define _VIRTUAL_MEMORY_H_ + +#include "Tiano.h" + +#pragma pack(1) + +// +// Page-Map Level-4 Offset (PML4) and +// Page-Directory-Pointer Offset (PDPE) entries 4K & 2MB +// + +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Reserved:1; // Reserved + UINT64 MustBeZero:2; // Must Be Zero + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K; + +// +// Page-Directory Offset 4K +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Reserved:1; // Reserved + UINT64 MustBeZero:1; // Must Be Zero + UINT64 Reserved2:1; // Reserved + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // No Execute bit + } Bits; + UINT64 Uint64; +} X64_PAGE_DIRECTORY_ENTRY_4K; + +// +// Page Table Entry 4K +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 PAT:1; // 0 = Ignore Page Attribute Table + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} X64_PAGE_TABLE_ENTRY_4K; + + +// +// Page Table Entry 2MB +// +typedef union { + struct { + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page + UINT64 MustBe1:1; // Must be 1 + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system software + UINT64 PAT:1; // + UINT64 MustBeZero:8; // Must be zero; + UINT64 PageTableBaseAddress:31; // Page Table Base Address + UINT64 AvabilableHigh:11; // Available for use by system software + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution + } Bits; + UINT64 Uint64; +} X64_PAGE_TABLE_ENTRY_2M; + +#pragma pack() + +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenPage/genpage.c b/EdkCompatibilityPkg/Sample/Tools/Source/GenPage/genpage.c new file mode 100644 index 0000000000..7085f198aa --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenPage/genpage.c @@ -0,0 +1,344 @@ +/*++ + +Copyright 2006 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + GenPage.c + +Abstract: + Pre-Create a 4G page table (2M pages). + It's used in DUET x64 build needed to enter LongMode. + + Create 4G page table (2M pages) + + Linear Address + 63 48 47 39 38 30 29 21 20 0 + +--------+-------+---------------+-----------+-----------------------------+ + PML4 Directory-Ptr Directory Offset + + Paging-Structures := + PML4 + ( + Directory-Ptr Directory {512} + ) {4} +--*/ + +#include +#include +#include "VirtualMemory.h" + +void +memset (void *, char, long); + +unsigned int +xtoi (char *); + +#define EFI_PAGE_BASE_OFFSET_IN_LDR 0x70000 +#define EFI_PAGE_BASE_ADDRESS (EFI_PAGE_BASE_OFFSET_IN_LDR + 0x20000) + +unsigned int gPageTableBaseAddress = EFI_PAGE_BASE_ADDRESS; +unsigned int gPageTableOffsetInFile = EFI_PAGE_BASE_OFFSET_IN_LDR; + +#define EFI_MAX_ENTRY_NUM 512 + +#define EFI_PML4_ENTRY_NUM 1 +#define EFI_PDPTE_ENTRY_NUM 4 +#define EFI_PDE_ENTRY_NUM EFI_MAX_ENTRY_NUM + +#define EFI_PML4_PAGE_NUM 1 +#define EFI_PDPTE_PAGE_NUM EFI_PML4_ENTRY_NUM +#define EFI_PDE_PAGE_NUM (EFI_PML4_ENTRY_NUM * EFI_PDPTE_ENTRY_NUM) + +#define EFI_PAGE_NUMBER (EFI_PML4_PAGE_NUM + EFI_PDPTE_PAGE_NUM + EFI_PDE_PAGE_NUM) + +#define EFI_SIZE_OF_PAGE 0x1000 +#define EFI_PAGE_SIZE_2M 0x200000 + +#define CONVERT_BIN_PAGE_ADDRESS(a) ((UINT8 *) a - PageTable + gPageTableBaseAddress) + + +void * +CreateIdentityMappingPageTables ( + void + ) +/*++ + +Routine Description: + To create 4G PAE 2M pagetable + +Return: + void * - buffer containing created pagetable + +--*/ +{ + UINT64 PageAddress; + UINT8 *PageTable; + UINT8 *PageTablePtr; + int PML4Index; + int PDPTEIndex; + int PDEIndex; + X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageMapLevel4Entry; + X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *PageDirectoryPointerEntry; + X64_PAGE_TABLE_ENTRY_2M *PageDirectoryEntry2MB; + + PageTable = (void *)malloc (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE); + memset (PageTable, 0, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE)); + PageTablePtr = PageTable; + + PageAddress = 0; + + // + // Page Table structure 3 level 2MB. + // + // Page-Map-Level-4-Table : bits 47-39 + // Page-Directory-Pointer-Table : bits 38-30 + // + // Page Table 2MB : Page-Directory(2M) : bits 29-21 + // + // + + PageMapLevel4Entry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr; + + for (PML4Index = 0; PML4Index < EFI_PML4_ENTRY_NUM; PML4Index++, PageMapLevel4Entry++) { + // + // Each Page-Map-Level-4-Table Entry points to the base address of a Page-Directory-Pointer-Table Entry + // + PageTablePtr += EFI_SIZE_OF_PAGE; + PageDirectoryPointerEntry = (X64_PAGE_MAP_AND_DIRECTORY_POINTER_2MB_4K *)PageTablePtr; + + // + // Make a Page-Map-Level-4-Table Entry + // + PageMapLevel4Entry->Uint64 = (UINT64)(UINT32)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryPointerEntry)); + PageMapLevel4Entry->Bits.ReadWrite = 1; + PageMapLevel4Entry->Bits.Present = 1; + + for (PDPTEIndex = 0; PDPTEIndex < EFI_PDPTE_ENTRY_NUM; PDPTEIndex++, PageDirectoryPointerEntry++) { + // + // Each Page-Directory-Pointer-Table Entry points to the base address of a Page-Directory Entry + // + PageTablePtr += EFI_SIZE_OF_PAGE; + PageDirectoryEntry2MB = (X64_PAGE_TABLE_ENTRY_2M *)PageTablePtr; + + // + // Make a Page-Directory-Pointer-Table Entry + // + PageDirectoryPointerEntry->Uint64 = (UINT64)(UINT32)(CONVERT_BIN_PAGE_ADDRESS (PageDirectoryEntry2MB)); + PageDirectoryPointerEntry->Bits.ReadWrite = 1; + PageDirectoryPointerEntry->Bits.Present = 1; + + for (PDEIndex = 0; PDEIndex < EFI_PDE_ENTRY_NUM; PDEIndex++, PageDirectoryEntry2MB++) { + // + // Make a Page-Directory Entry + // + PageDirectoryEntry2MB->Uint64 = (UINT64)PageAddress; + PageDirectoryEntry2MB->Bits.ReadWrite = 1; + PageDirectoryEntry2MB->Bits.Present = 1; + PageDirectoryEntry2MB->Bits.MustBe1 = 1; + + PageAddress += EFI_PAGE_SIZE_2M; + } + } + } + + return PageTable; +} + +int +GenBinPage ( + void *BaseMemory, + char *NoPageFileName, + char *PageFileName + ) +/*++ + +Routine Description: + Write the buffer containing page table to file at a specified offset. + Here the offset is defined as EFI_PAGE_BASE_OFFSET_IN_LDR. + +Arguments: + BaseMemory - buffer containing page table + NoPageFileName - file to write page table + PageFileName - file save to after writing + +return: + 0 : successful + -1 : failed + +--*/ +{ + FILE *PageFile; + FILE *NoPageFile; + UINT8 Data; + unsigned long FileSize; + + // + // Open files + // + PageFile = fopen (PageFileName, "w+b"); + if (PageFile == NULL) { + fprintf (stderr, "GenBinPage: Could not open file %s\n", PageFileName); + return -1; + } + + NoPageFile = fopen (NoPageFileName, "r+b"); + if (NoPageFile == NULL) { + fprintf (stderr, "GenBinPage: Could not open file %s\n", NoPageFileName); + fclose (PageFile); + return -1; + } + + // + // Check size - should not be great than EFI_PAGE_BASE_OFFSET_IN_LDR + // + fseek (NoPageFile, 0, SEEK_END); + FileSize = ftell (NoPageFile); + fseek (NoPageFile, 0, SEEK_SET); + if (FileSize > gPageTableOffsetInFile) { + fprintf (stderr, "GenBinPage: file size too large - 0x%x\n", FileSize); + fclose (PageFile); + fclose (NoPageFile); + return -1; + } + + // + // Write data + // + while (fread (&Data, sizeof(UINT8), 1, NoPageFile)) { + fwrite (&Data, sizeof(UINT8), 1, PageFile); + } + + // + // Write PageTable + // + fseek (PageFile, gPageTableOffsetInFile, SEEK_SET); + fwrite (BaseMemory, (EFI_PAGE_NUMBER * EFI_SIZE_OF_PAGE), 1, PageFile); + + // + // Close files + // + fclose (PageFile); + fclose (NoPageFile); + + return 0; +} + +int +main ( + int argc, + char **argv + ) +{ + void *BaseMemory; + int result; + + // + // Check parameter + // + if ((argc != 3) && (argc != 5)) { + printf ("Usage: GenPage.exe NoPageFile PageFile [ ]\n"); + return 1; + } + + // + // Get PageTable parameter, if have + // + if (argc == 5) { + gPageTableBaseAddress = xtoi (argv[3]); + gPageTableOffsetInFile = xtoi (argv[4]); + } + + // + // Create X64 page table + // + BaseMemory = CreateIdentityMappingPageTables (); + + // + // Add page table to binary file + // + result = GenBinPage (BaseMemory, argv[1], argv[2]); + if (result < 0) { + return 1; + } + + return 0; +} + +unsigned int +xtoi ( + char *str + ) +/*++ + +Routine Description: + + Convert hex string to uint + +Arguments: + + Str - The string + +Returns: + +--*/ +{ + unsigned int u; + char c; + unsigned int m; + + if (str == NULL) { + return 0; + } + + m = (unsigned int) -1 >> 4; + // + // skip preceeding white space + // + while (*str && *str == ' ') { + str += 1; + } + // + // skip preceeding zeros + // + while (*str && *str == '0') { + str += 1; + } + // + // skip preceeding white space + // + if (*str && (*str == 'x' || *str == 'X')) { + str += 1; + } + // + // convert hex digits + // + u = 0; + c = *(str++); + while (c) { + if (c >= 'a' && c <= 'f') { + c -= 'a' - 'A'; + } + + if ((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F')) { + if (u > m) { + return (unsigned int) -1; + } + + u = u << 4 | c - (c >= 'A' ? 'A' - 10 : '0'); + } else { + break; + } + + c = *(str++); + } + + return u; +} + diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenSection/GenSection.c b/EdkCompatibilityPkg/Sample/Tools/Source/GenSection/GenSection.c new file mode 100644 index 0000000000..61ce9caafa --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenSection/GenSection.c @@ -0,0 +1,1000 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + GenSection.c + +Abstract: + + Creates output file that is a properly formed section per the FV spec. + +--*/ + +#include "TianoCommon.h" +#include "EfiImageFormat.h" +#include "Compress.h" +#include "EfiCustomizedCompress.h" +#include "Crc32.h" +#include "EfiUtilityMsgs.h" + +#include +#include +#include + +#include "GenSection.h" + +#include EFI_PROTOCOL_DEFINITION (GuidedSectionExtraction) + +#define UTILITY_NAME "GenSection" + +#define PARAMETER_NOT_SPECIFIED "Parameter not specified" +#define MAXIMUM_INPUT_FILE_NUM 10 +#define MAX_SECTION_SIZE 0x1000000 + +char *SectionTypeName[] = { + 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 +}; + +char *CompressionTypeName[] = { "NONE", "STANDARD" }; +char *GUIDedSectionTypeName[] = { "CRC32" }; +EFI_GUID gEfiCrc32SectionGuid = EFI_CRC32_GUIDED_SECTION_EXTRACTION_PROTOCOL_GUID; + +static +VOID +PrintUsageMessage ( + VOID + ) +{ + UINTN SectionType; + UINTN DisplayCount; + + printf ("Usage: "UTILITY_NAME " -i InputFile -o OutputFile -s SectionType [SectionType params]\n\n"); + printf (" Where SectionType is one of the following section types:\n\n"); + + DisplayCount = 0; + for (SectionType = 0; SectionType <= EFI_SECTION_LAST_SECTION_TYPE; SectionType++) { + if (SectionTypeName[SectionType] != NULL) { + printf (" %s\n", SectionTypeName[SectionType]); + } + } + + printf ("\n and SectionType dependent parameters are as follows:\n\n"); + printf ( + " %s: -t < %s | %s >\n", + SectionTypeName[EFI_SECTION_COMPRESSION], + CompressionTypeName[EFI_NOT_COMPRESSED], + CompressionTypeName[EFI_STANDARD_COMPRESSION] + ); + printf ( + " %s: -t < %s >\n"" // Currently only CRC32 is supported\n\n", + SectionTypeName[EFI_SECTION_GUID_DEFINED], + GUIDedSectionTypeName[EFI_SECTION_CRC32_GUID_DEFINED] + ); + printf ( + " %s: -v VersionNumber\n"" [-a \"Version string\"]\n\n", + SectionTypeName[EFI_SECTION_VERSION] + ); + printf ( + " %s: -a \"Human readable name\"\n\n", + SectionTypeName[EFI_SECTION_USER_INTERFACE] + ); +} + +VOID +Ascii2UnicodeWriteString ( + char *String, + FILE *OutFile, + BOOLEAN WriteLangCode + ) +{ + UINTN Index; + UINT8 AsciiNull; + // + // BUGBUG need to get correct language code... + // + char *EnglishLangCode = "eng"; + AsciiNull = 0; + // + // first write the language code (english only) + // + if (WriteLangCode) { + fwrite (EnglishLangCode, 1, 4, OutFile); + } + // + // Next, write out the string... Convert ASCII to Unicode in the process. + // + Index = 0; + do { + fwrite (&String[Index], 1, 1, OutFile); + fwrite (&AsciiNull, 1, 1, OutFile); + } while (String[Index++] != 0); +} + +STATUS +GenSectionCommonLeafSection ( + char **InputFileName, + int InputFileNum, + UINTN SectionType, + FILE *OutFile + ) +/*++ + +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 + + OutFile - Output file handle + +Returns: + + STATUS_ERROR - can't continue + STATUS_SUCCESS - successful return + +--*/ +{ + UINT64 InputFileLength; + FILE *InFile; + UINT8 *Buffer; + INTN TotalLength; + EFI_COMMON_SECTION_HEADER CommonSect; + STATUS Status; + + if (InputFileNum > 1) { + Error (NULL, 0, 0, "invalid parameter", "more than one input file specified"); + return STATUS_ERROR; + } else if (InputFileNum < 1) { + Error (NULL, 0, 0, "no input file specified", NULL); + return STATUS_ERROR; + } + // + // Open the input file + // + InFile = fopen (InputFileName[0], "rb"); + if (InFile == NULL) { + Error (NULL, 0, 0, InputFileName[0], "failed to open input file"); + 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); + fgetpos (InFile, &InputFileLength); + fseek (InFile, 0, SEEK_SET); + // + // Fill in the fields in the local section header structure + // + CommonSect.Type = (EFI_SECTION_TYPE) SectionType; + TotalLength = sizeof (CommonSect) + (INTN) InputFileLength; + // + // Size must fit in 3 bytes + // + if (TotalLength >= MAX_SECTION_SIZE) { + Error (NULL, 0, 0, InputFileName[0], "file size (0x%X) exceeds section size limit(%dM).", TotalLength, MAX_SECTION_SIZE>>20); + goto Done; + } + // + // Now copy the size into the section header and write out the section header + // + memcpy (&CommonSect.Size, &TotalLength, 3); + fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile); + // + // Allocate a buffer to read in the contents of the input file. Then + // read it in as one block and write it to the output file. + // + if (InputFileLength != 0) { + Buffer = (UINT8 *) malloc ((size_t) InputFileLength); + if (Buffer == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + goto Done; + } + + if (fread (Buffer, (size_t) InputFileLength, 1, InFile) != 1) { + Error (NULL, 0, 0, InputFileName[0], "failed to read contents of file"); + goto Done; + } + + if (fwrite (Buffer, (size_t) InputFileLength, 1, OutFile) != 1) { + Error (NULL, 0, 0, "failed to write to output file", NULL); + goto Done; + } + } + + Status = STATUS_SUCCESS; +Done: + fclose (InFile); + if (Buffer != NULL) { + free (Buffer); + } + + return Status; +} + +EFI_STATUS +GetSectionContents ( + char **InputFileName, + int InputFileNum, + UINT8 *FileBuffer, + UINTN *BufferLength + ) +/*++ + +Routine Description: + + Get the contents of all section files specified in InputFileName + into FileBuffer. + +Arguments: + + InputFileName - Name of the input file. + + 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. +--*/ +{ + UINTN Size; + fpos_t FileSize; + INTN Index; + FILE *InFile; + + if (InputFileNum < 1) { + Error (NULL, 0, 0, "must specify at least one input file", NULL); + return EFI_INVALID_PARAMETER; + } + + if (BufferLength == NULL) { + Error (NULL, 0, 0, "BufferLength can't be NULL", NULL); + return EFI_INVALID_PARAMETER; + } + + Size = 0; + // + // Go through our array of file names and copy their contents + // to the output buffer. + // + for (Index = 0; Index < InputFileNum; Index++) { + InFile = fopen (InputFileName[Index], "rb"); + if (InFile == NULL) { + Error (NULL, 0, 0, InputFileName[Index], "failed to open input file"); + return EFI_ABORTED; + } + + fseek (InFile, 0, SEEK_END); + fgetpos (InFile, &FileSize); + fseek (InFile, 0, SEEK_SET); + // + // 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 + (UINTN) FileSize) <= *BufferLength) { + if (fread (FileBuffer + Size, (size_t) FileSize, 1, InFile) != 1) { + Error (NULL, 0, 0, InputFileName[Index], "failed to read contents of input file"); + fclose (InFile); + return EFI_ABORTED; + } + } + + fclose (InFile); + Size += (UINTN) FileSize; + // + // make sure section ends on a DWORD boundary + // + while ((Size & 0x03) != 0) { + if (FileBuffer != NULL && Size < *BufferLength) { + FileBuffer[Size] = 0; + } + Size++; + } + } + + if (Size > *BufferLength) { + *BufferLength = Size; + return EFI_BUFFER_TOO_SMALL; + } else { + *BufferLength = Size; + return EFI_SUCCESS; + } +} + +EFI_STATUS +GenSectionCompressionSection ( + char **InputFileName, + int InputFileNum, + UINTN SectionType, + UINTN SectionSubType, + FILE *OutFile + ) +/*++ + +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. + + InputFileNum - Number of input files. Should be at least 1. + + SectionType - Section type to generate. Should be + EFI_SECTION_COMPRESSION + + SectionSubType - Specify the compression algorithm requested. + + OutFile - Output file handle + +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. +--*/ +{ + UINTN TotalLength; + UINTN InputLength; + UINTN CompressedLength; + UINT8 *FileBuffer; + UINT8 *OutputBuffer; + EFI_STATUS Status; + EFI_COMPRESSION_SECTION CompressionSect; + COMPRESS_FUNCTION CompressFunction; + + if (SectionType != EFI_SECTION_COMPRESSION) { + Error (NULL, 0, 0, "parameter must be EFI_SECTION_COMPRESSION", NULL); + return EFI_INVALID_PARAMETER; + } + + InputLength = 0; + FileBuffer = NULL; + OutputBuffer = NULL; + CompressedLength = 0; + // + // read all input file contents into a buffer + // first get the size of all file contents + // + Status = GetSectionContents ( + InputFileName, + InputFileNum, + FileBuffer, + &InputLength + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + FileBuffer = (UINT8 *) malloc (InputLength); + if (FileBuffer == NULL) { + Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory"); + return EFI_OUT_OF_RESOURCES; + } + // + // read all input file contents into a buffer + // + Status = GetSectionContents ( + InputFileName, + InputFileNum, + FileBuffer, + &InputLength + ); + } + + if (EFI_ERROR (Status)) { + if (FileBuffer != NULL) { + free (FileBuffer); + } + return Status; + } + + CompressFunction = NULL; + + // + // Now data is in FileBuffer, compress the data + // + switch (SectionSubType) { + case EFI_NOT_COMPRESSED: + CompressedLength = InputLength; + break; + + case EFI_STANDARD_COMPRESSION: + CompressFunction = (COMPRESS_FUNCTION) TianoCompress; + break; + + case EFI_CUSTOMIZED_COMPRESSION: + CompressFunction = (COMPRESS_FUNCTION) CustomizedCompress; + break; + + default: + Error (NULL, 0, 0, "unknown compression type", NULL); + free (FileBuffer); + return EFI_ABORTED; + } + + if (CompressFunction != NULL) { + + Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength); + if (Status == EFI_BUFFER_TOO_SMALL) { + OutputBuffer = malloc (CompressedLength); + if (!OutputBuffer) { + free (FileBuffer); + return EFI_OUT_OF_RESOURCES; + } + + Status = CompressFunction (FileBuffer, InputLength, OutputBuffer, &CompressedLength); + } + + free (FileBuffer); + FileBuffer = OutputBuffer; + + if (EFI_ERROR (Status)) { + if (FileBuffer != NULL) { + free (FileBuffer); + } + + return Status; + } + } + + TotalLength = CompressedLength + sizeof (EFI_COMPRESSION_SECTION); + if (TotalLength >= MAX_SECTION_SIZE) { + Error (__FILE__, __LINE__, 0, "input error", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20); + if (FileBuffer != NULL) { + free (FileBuffer); + } + if (OutputBuffer != NULL) { + free (OutputBuffer); + } + return STATUS_ERROR; + } + // + // Add the section header for the compressed data + // + CompressionSect.CommonHeader.Type = (EFI_SECTION_TYPE) SectionType; + 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 = (UINT8) SectionSubType; + CompressionSect.UncompressedLength = InputLength; + + fwrite (&CompressionSect, sizeof (CompressionSect), 1, OutFile); + fwrite (FileBuffer, CompressedLength, 1, OutFile); + free (FileBuffer); + return EFI_SUCCESS; +} + +EFI_STATUS +GenSectionGuidDefinedSection ( + char **InputFileName, + int InputFileNum, + UINTN SectionType, + UINTN SectionSubType, + FILE *OutFile + ) +/*++ + +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. + + InputFileNum - Number of input files. Should be at least 1. + + SectionType - Section type to generate. Should be + EFI_SECTION_GUID_DEFINED + + SectionSubType - Specify the authentication algorithm requested. + + OutFile - Output file handle + +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. + +--*/ +{ + INTN TotalLength; + INTN InputLength; + UINT8 *FileBuffer; + UINT32 Crc32Checksum; + EFI_STATUS Status; + CRC32_SECTION_HEADER Crc32GuidSect; + + if (SectionType != EFI_SECTION_GUID_DEFINED) { + Error (NULL, 0, 0, "parameter must be EFI_SECTION_GUID_DEFINED", NULL); + return EFI_INVALID_PARAMETER; + } + + InputLength = 0; + FileBuffer = NULL; + // + // read all input file contents into a buffer + // first get the size of all file contents + // + Status = GetSectionContents ( + InputFileName, + InputFileNum, + FileBuffer, + &InputLength + ); + + if (Status == EFI_BUFFER_TOO_SMALL) { + FileBuffer = (UINT8 *) malloc (InputLength); + if (FileBuffer == NULL) { + Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory"); + return EFI_OUT_OF_RESOURCES; + } + // + // read all input file contents into a buffer + // + Status = GetSectionContents ( + InputFileName, + InputFileNum, + FileBuffer, + &InputLength + ); + } + + if (EFI_ERROR (Status)) { + if (FileBuffer != NULL) { + free (FileBuffer); + } + return Status; + } + // + // Now data is in FileBuffer + // + switch (SectionSubType) { + case EFI_SECTION_CRC32_GUID_DEFINED: + Crc32Checksum = 0; + CalculateCrc32 (FileBuffer, InputLength, &Crc32Checksum); + if (EFI_ERROR (Status)) { + free (FileBuffer); + return Status; + } + + TotalLength = InputLength + CRC32_SECTION_HEADER_SIZE; + if (TotalLength >= MAX_SECTION_SIZE) { + Error (__FILE__, __LINE__, 0, "input error", "The size of all files exceeds section size limit(%dM).", MAX_SECTION_SIZE>>20); + free (FileBuffer); + return STATUS_ERROR; + } + + Crc32GuidSect.GuidSectionHeader.CommonHeader.Type = (EFI_SECTION_TYPE) SectionType; + 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), &gEfiCrc32SectionGuid, sizeof (EFI_GUID)); + Crc32GuidSect.GuidSectionHeader.Attributes = EFI_GUIDED_SECTION_AUTH_STATUS_VALID; + Crc32GuidSect.GuidSectionHeader.DataOffset = CRC32_SECTION_HEADER_SIZE; + Crc32GuidSect.CRC32Checksum = Crc32Checksum; + + break; + + default: + Error (NULL, 0, 0, "invalid parameter", "unknown GUID defined type"); + free (FileBuffer); + return EFI_ABORTED; + } + + fwrite (&Crc32GuidSect, sizeof (Crc32GuidSect), 1, OutFile); + fwrite (FileBuffer, InputLength, 1, OutFile); + + free (FileBuffer); + + 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. + +--*/ +{ + INTN Index; + INTN VersionNumber; + UINTN SectionType; + UINTN SectionSubType; + BOOLEAN InputFileRequired; + BOOLEAN SubTypeRequired; + FILE *InFile; + FILE *OutFile; + INTN InputFileNum; + + char **InputFileName; + char *OutputFileName; + char AuxString[500] = { 0 }; + + char *ParamSectionType; + char *ParamSectionSubType; + char *ParamLength; + char *ParamVersion; + char *ParamDigitalSignature; + + EFI_STATUS Status; + EFI_COMMON_SECTION_HEADER CommonSect; + + InputFileName = NULL; + OutputFileName = PARAMETER_NOT_SPECIFIED; + ParamSectionType = PARAMETER_NOT_SPECIFIED; + ParamSectionSubType = PARAMETER_NOT_SPECIFIED; + ParamLength = PARAMETER_NOT_SPECIFIED; + ParamVersion = PARAMETER_NOT_SPECIFIED; + ParamDigitalSignature = PARAMETER_NOT_SPECIFIED; + Status = EFI_SUCCESS; + + VersionNumber = 0; + SectionType = 0; + SectionSubType = 0; + InputFileRequired = TRUE; + SubTypeRequired = FALSE; + InFile = NULL; + OutFile = NULL; + InputFileNum = 0; + Status = EFI_SUCCESS; + + SetUtilityName (UTILITY_NAME); + if (argc == 1) { + PrintUsageMessage (); + return STATUS_ERROR; + } + // + // Parse command line + // + Index = 1; + while (Index < argc) { + if (_strcmpi (argv[Index], "-i") == 0) { + // + // Input File found + // + Index++; + InputFileName = (char **) malloc (MAXIMUM_INPUT_FILE_NUM * sizeof (char *)); + if (InputFileName == NULL) { + Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory"); + return EFI_OUT_OF_RESOURCES; + } + + memset (InputFileName, 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *))); + InputFileName[InputFileNum] = argv[Index]; + InputFileNum++; + Index++; + // + // Parse subsequent parameters until another switch is encountered + // + while ((Index < argc) && (argv[Index][0] != '-')) { + if ((InputFileNum % MAXIMUM_INPUT_FILE_NUM) == 0) { + // + // InputFileName buffer too small, need to realloc + // + InputFileName = (char **) realloc ( + InputFileName, + (InputFileNum + MAXIMUM_INPUT_FILE_NUM) * sizeof (char *) + ); + if (InputFileName == NULL) { + Error (__FILE__, __LINE__, 0, "application error", "failed to allocate memory"); + return EFI_OUT_OF_RESOURCES; + } + + memset (&(InputFileName[InputFileNum]), 0, (MAXIMUM_INPUT_FILE_NUM * sizeof (char *))); + } + + InputFileName[InputFileNum] = argv[Index]; + InputFileNum++; + Index++; + } + + } + + if (_strcmpi (argv[Index], "-o") == 0) { + // + // Output file found + // + Index++; + OutputFileName = argv[Index]; + } else if (_strcmpi (argv[Index], "-s") == 0) { + // + // Section Type found + // + Index++; + ParamSectionType = argv[Index]; + } else if (_strcmpi (argv[Index], "-t") == 0) { + // + // Compression or Authentication type + // + Index++; + ParamSectionSubType = argv[Index]; + } else if (_strcmpi (argv[Index], "-l") == 0) { + // + // Length + // + Index++; + ParamLength = argv[Index]; + } else if (_strcmpi (argv[Index], "-v") == 0) { + // + // VersionNumber + // + Index++; + ParamVersion = argv[Index]; + } else if (_strcmpi (argv[Index], "-a") == 0) { + // + // Aux string + // + Index++; + // + // Note, the MSVC C-Start parses out and consolidates quoted strings from the command + // line. Quote characters are stripped. If this tool is ported to other environments + // this will need to be taken into account + // + strncpy (AuxString, argv[Index], 499); + } else if (_strcmpi (argv[Index], "-d") == 0) { + // + // Digital signature for EFI_TEST_AUTHENTICAION (must be 0 or 1) + // + Index++; + ParamDigitalSignature = argv[Index]; + } else if (_strcmpi (argv[Index], "-?") == 0) { + PrintUsageMessage (); + return STATUS_ERROR; + } else { + Error (NULL, 0, 0, argv[Index], "unknown option"); + return GetUtilityStatus (); + } + + Index++; + } + // + // At this point, all command line parameters are verified as not being totally + // bogus. Next verify the command line parameters are complete and make + // sense... + // + if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPRESSION]) == 0) { + SectionType = EFI_SECTION_COMPRESSION; + SubTypeRequired = TRUE; + if (_stricmp (ParamSectionSubType, CompressionTypeName[EFI_NOT_COMPRESSED]) == 0) { + SectionSubType = EFI_NOT_COMPRESSED; + } else if (_stricmp (ParamSectionSubType, CompressionTypeName[EFI_STANDARD_COMPRESSION]) == 0) { + SectionSubType = EFI_STANDARD_COMPRESSION; + } else { + Error (NULL, 0, 0, ParamSectionSubType, "unknown compression type"); + PrintUsageMessage (); + return GetUtilityStatus (); + } + } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_GUID_DEFINED]) == 0) { + SectionType = EFI_SECTION_GUID_DEFINED; + SubTypeRequired = TRUE; + if (_stricmp (ParamSectionSubType, GUIDedSectionTypeName[EFI_SECTION_CRC32_GUID_DEFINED]) == 0) { + SectionSubType = EFI_SECTION_CRC32_GUID_DEFINED; + } else { + Error (NULL, 0, 0, ParamSectionSubType, "unknown GUID defined section type", ParamSectionSubType); + PrintUsageMessage (); + return GetUtilityStatus (); + } + } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PE32]) == 0) { + SectionType = EFI_SECTION_PE32; + } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PIC]) == 0) { + SectionType = EFI_SECTION_PIC; + } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_TE]) == 0) { + SectionType = EFI_SECTION_TE; + } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_DXE_DEPEX]) == 0) { + SectionType = EFI_SECTION_DXE_DEPEX; + } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_VERSION]) == 0) { + SectionType = EFI_SECTION_VERSION; + InputFileRequired = FALSE; + Index = sscanf (ParamVersion, "%d", &VersionNumber); + if (Index != 1 || VersionNumber < 0 || VersionNumber > 65565) { + Error (NULL, 0, 0, ParamVersion, "illegal version number"); + PrintUsageMessage (); + return GetUtilityStatus (); + } + + if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) { + AuxString[0] = 0; + } + } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_USER_INTERFACE]) == 0) { + SectionType = EFI_SECTION_USER_INTERFACE; + InputFileRequired = FALSE; + if (strcmp (AuxString, PARAMETER_NOT_SPECIFIED) == 0) { + Error (NULL, 0, 0, "user interface string not specified", NULL); + PrintUsageMessage (); + return GetUtilityStatus (); + } + } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_COMPATIBILITY16]) == 0) { + SectionType = EFI_SECTION_COMPATIBILITY16; + } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FIRMWARE_VOLUME_IMAGE]) == 0) { + SectionType = EFI_SECTION_FIRMWARE_VOLUME_IMAGE; + } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_FREEFORM_SUBTYPE_GUID]) == 0) { + SectionType = EFI_SECTION_FREEFORM_SUBTYPE_GUID; + } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_RAW]) == 0) { + SectionType = EFI_SECTION_RAW; + } else if (_stricmp (ParamSectionType, SectionTypeName[EFI_SECTION_PEI_DEPEX]) == 0) { + SectionType = EFI_SECTION_PEI_DEPEX; + } else { + Error (NULL, 0, 0, ParamSectionType, "unknown section type"); + PrintUsageMessage (); + return GetUtilityStatus (); + } + // + // Open output file + // + OutFile = fopen (OutputFileName, "wb"); + if (OutFile == NULL) { + Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing"); + if (InFile != NULL) { + fclose (InFile); + } + + return GetUtilityStatus (); + } + // + // 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 (SectionType) { + case EFI_SECTION_COMPRESSION: + Status = GenSectionCompressionSection ( + InputFileName, + InputFileNum, + SectionType, + SectionSubType, + OutFile + ); + break; + + case EFI_SECTION_GUID_DEFINED: + Status = GenSectionGuidDefinedSection ( + InputFileName, + InputFileNum, + SectionType, + SectionSubType, + OutFile + ); + break; + + case EFI_SECTION_VERSION: + CommonSect.Type = (EFI_SECTION_TYPE) SectionType; + + Index = sizeof (CommonSect); + // + // 2 characters for the build number + // + Index += 2; + // + // Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null. + // + Index += (strlen (AuxString) * 2) + 2; + memcpy (&CommonSect.Size, &Index, 3); + fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile); + fwrite (&VersionNumber, 2, 1, OutFile); + Ascii2UnicodeWriteString (AuxString, OutFile, FALSE); + break; + + case EFI_SECTION_USER_INTERFACE: + CommonSect.Type = (EFI_SECTION_TYPE) SectionType; + Index = sizeof (CommonSect); + // + // Aux string is ascii.. unicode is 2X + 2 bytes for terminating unicode null. + // + Index += (strlen (AuxString) * 2) + 2; + memcpy (&CommonSect.Size, &Index, 3); + fwrite (&CommonSect, sizeof (CommonSect), 1, OutFile); + Ascii2UnicodeWriteString (AuxString, OutFile, FALSE); + break; + + default: + // + // All other section types are caught by default (they're all the same) + // + Status = GenSectionCommonLeafSection ( + InputFileName, + InputFileNum, + SectionType, + OutFile + ); + break; + } + + if (InputFileName != NULL) { + free (InputFileName); + } + + fclose (OutFile); + // + // If we had errors, then delete the output file + // + if (GetUtilityStatus () == STATUS_ERROR) { + remove (OutputFileName); + } + + return GetUtilityStatus (); +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenSection/GenSection.h b/EdkCompatibilityPkg/Sample/Tools/Source/GenSection/GenSection.h new file mode 100644 index 0000000000..24c1c4e34d --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenSection/GenSection.h @@ -0,0 +1,42 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + GenSection.h + +Abstract: + + Header file for GenSection. + +--*/ + +// +// Module Coded to Tiano Coding Conventions +// +#ifndef _EFI_GEN_SECTION_H +#define _EFI_GEN_SECTION_H + +// +// External Files Referenced +// +#include "TianoCommon.h" +#include "EfiImageFormat.h" + +typedef struct { + EFI_GUID_DEFINED_SECTION GuidSectionHeader; + UINT32 CRC32Checksum; +} CRC32_SECTION_HEADER; + +#define EFI_SECTION_CRC32_GUID_DEFINED 0 +#define CRC32_SECTION_HEADER_SIZE (sizeof (CRC32_SECTION_HEADER)) + +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GenSection/makefile b/EdkCompatibilityPkg/Sample/Tools/Source/GenSection/makefile new file mode 100644 index 0000000000..053d2376a0 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GenSection/makefile @@ -0,0 +1,82 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: makefile +# +# Abstract: +# +# This file is used to build the EFI utility. +# +#--*/ + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Common information +# +INC = $(INC) -I $(EDK_TOOLS_SOURCE)\Common + +LIBS = $(LIBS) $(EDK_TOOLS_OUTPUT)\CustomizedCompress.lib + +# +# Target specific information +# + +TARGET_NAME = GenSection +TARGET_SOURCE_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).exe +TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\GenSection.c" +TARGET_EXE_LIBS = "$(EDK_TOOLS_OUTPUT)\Common.lib" +TARGET_EXE_INCLUDE = "$(EDK_SOURCE)\Foundation\Include\TianoCommon.h" \ + "$(EDK_SOURCE)\Foundation\Framework\Include\EfiFirmwareFileSystem.h" \ + "$(EDK_SOURCE)\Foundation\Framework\Include\EfiFirmwareVolumeHeader.h" \ + "$(EDK_TOOLS_COMMON)\ParseInf.h" + +# +# Build targets +# + +all: $(TARGET_EXE) + +# +# Build EXE +# + +$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE) + $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE): $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(LIBS) $(TARGET_EXE_LIBS) + $(LINK) /DEBUG $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj $(TARGET_EXE_LIBS) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/CommonUtils.h b/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/CommonUtils.h new file mode 100644 index 0000000000..f7a331e5d7 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/CommonUtils.h @@ -0,0 +1,57 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + CommonUtils.h + +Abstract: + + Common utility defines and structure definitions. + +--*/ + +#ifndef _COMMON_UTILS_H_ +#define _COMMON_UTILS_H_ + +// +// Basic types +// +typedef unsigned char UINT8; +typedef char INT8; +typedef unsigned short UINT16; +typedef unsigned int UINT32; + +typedef UINT8 BOOLEAN; +typedef UINT32 STATUS; + +#define TRUE 1 +#define FALSE 0 + +#define STATUS_SUCCESS 0 +#define STATUS_WARNING 1 +#define STATUS_ERROR 2 + +// +// Linked list of strings +// +typedef struct _STRING_LIST { + struct _STRING_LIST *Next; + char *Str; +} STRING_LIST; + +int +CreateGuidList ( + INT8 *OutFileName + ) +; + +#endif // #ifndef _COMMON_UTILS_H_ diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/FileSearch.c b/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/FileSearch.c new file mode 100644 index 0000000000..dc7c7c58a9 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/FileSearch.c @@ -0,0 +1,285 @@ +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + FileSearch.c + +Abstract: + + Module used to support file searches on the system. + +--*/ + +#include + +#include "CommonUtils.h" +#include "FileSearch.h" +#include "UtilsMsgs.h" + +// +// Internal file search flag for sanity checks +// +#define FILE_SEARCH_STARTED 0x8000 +#define FILE_SEARCH_INITED 0x4000 + +static +BOOLEAN +FileSearchMeetsCriteria ( + FILE_SEARCH_DATA *FSData + ); + +/*****************************************************************************/ +STATUS +FileSearchInit ( + FILE_SEARCH_DATA *FSData + ) +{ + memset ((char *) FSData, 0, sizeof (FILE_SEARCH_DATA)); + FSData->Handle = INVALID_HANDLE_VALUE; + FSData->FileSearchFlags = FILE_SEARCH_INITED; + FSData->FileName[0] = 0; + return STATUS_SUCCESS; +} + +STATUS +FileSearchStart ( + FILE_SEARCH_DATA *FSData, + char *FileMask, + UINT32 SearchFlags + ) +{ + BOOLEAN Done; + + // + // Save their flags, and set a flag to indicate that they called this + // start function so we can perform extended checking in the other + // routines we have in this module. + // + FSData->FileSearchFlags |= (SearchFlags | FILE_SEARCH_STARTED); + FSData->FileName[0] = 0; + + // + // Begin the search + // + FSData->Handle = FindFirstFile (FileMask, &(FSData->FindData)); + if (FSData->Handle == INVALID_HANDLE_VALUE) { + return STATUS_ERROR; + } + // + // Keep looping through until we find a file meeting the caller's + // criteria per the search flags + // + Done = FALSE; + while (!Done) { + // + // If we're done (we found a match) copy the file name found and return + // + Done = FileSearchMeetsCriteria (FSData); + if (Done) { + return STATUS_SUCCESS; + } + // + // Go on to next file + // + if (!FindNextFile (FSData->Handle, &(FSData->FindData))) { + return STATUS_NOT_FOUND; + } + } + // + // Not reached + // + return STATUS_NOT_FOUND; +} + +// +// Find the next file meeting their criteria and return it. +// +STATUS +FileSearchFindNext ( + FILE_SEARCH_DATA *FSData + ) +{ + BOOLEAN Done; + + Done = FALSE; + while (!Done) { + if (!FindNextFile (FSData->Handle, &(FSData->FindData))) { + return STATUS_NOT_FOUND; + } + // + // See if it matches their criteria + // + Done = FileSearchMeetsCriteria (FSData); + if (Done) { + return STATUS_SUCCESS; + } + } + // + // Not reached + // + return STATUS_NOT_FOUND; +} +// +// Perform any cleanup necessary to close down a search +// +STATUS +FileSearchDestroy ( + FILE_SEARCH_DATA *FSData + ) +{ + if (FSData->Handle != INVALID_HANDLE_VALUE) { + FindClose (FSData->Handle); + FSData->Handle = INVALID_HANDLE_VALUE; + } + + FSData->FileName[0] = 0; + FSData->FileSearchFlags = 0; + return STATUS_SUCCESS; +} + +static +BOOLEAN +FileSearchMeetsCriteria ( + FILE_SEARCH_DATA *FSData + ) +{ + BOOLEAN Status; + STRING_LIST *StrList; + UINT32 ExtLen; + UINT32 FileNameLen; + + Status = FALSE; + + // + // First clear the flag indicating this is neither a file or a + // directory. + // + FSData->FileFlags &= ~(FILE_SEARCH_DIR | FILE_SEARCH_FILE); + + // + // We found a file. See if it matches the user's search criteria. First + // check for this being a directory, and they want directories, and + // it's not "." and it's not ".." + // + if ((FSData->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && + (FSData->FileSearchFlags & FILE_SEARCH_DIR) && + (strcmp (FSData->FindData.cFileName, ".")) && + (strcmp (FSData->FindData.cFileName, "..")) + ) { + // + // Assume we'll make it past this check + // + Status = TRUE; + // + // If they have a list of exclude directories, then check for those + // + StrList = FSData->ExcludeDirs; + while (StrList != NULL) { + if (_stricmp (FSData->FindData.cFileName, StrList->Str) == 0) { + Status = FALSE; + break; + } + + StrList = StrList->Next; + } + // + // If we didn't fail due to excluded directories, then set the dir flag + // + if (Status) { + FSData->FileFlags |= FILE_SEARCH_DIR; + } + // + // Else check for a file, and they want files.... + // + } else if (((FSData->FindData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) && + (FSData->FileSearchFlags & FILE_SEARCH_FILE) + ) { + // + // See if it's in our list of excluded files + // + Status = TRUE; + StrList = FSData->ExcludeFiles; + while (StrList != NULL) { + if (_stricmp (FSData->FindData.cFileName, StrList->Str) == 0) { + Status = FALSE; + break; + } + + StrList = StrList->Next; + } + + if (Status) { + // + // See if it's in our list of excluded file extensions + // + FileNameLen = strlen (FSData->FindData.cFileName); + StrList = FSData->ExcludeExtensions; + while (StrList != NULL) { + ExtLen = strlen (StrList->Str); + if (_stricmp ( + FSData->FindData.cFileName + FileNameLen - ExtLen, + StrList->Str + ) == 0) { + Status = FALSE; + break; + } + + StrList = StrList->Next; + } + } + + if (Status) { + FSData->FileFlags |= FILE_SEARCH_FILE; + } + } + // + // If it's a match, copy the filename into another field of the structure + // for portability. + // + if (Status) { + strcpy (FSData->FileName, FSData->FindData.cFileName); + } + + return Status; +} +// +// Exclude a list of subdirectories. +// +STATUS +FileSearchExcludeDirs ( + FILE_SEARCH_DATA *FSData, + STRING_LIST *StrList + ) +{ + FSData->ExcludeDirs = StrList; + return STATUS_SUCCESS; +} + +STATUS +FileSearchExcludeFiles ( + FILE_SEARCH_DATA *FSData, + STRING_LIST *StrList + ) +{ + FSData->ExcludeFiles = StrList; + return STATUS_SUCCESS; +} + +STATUS +FileSearchExcludeExtensions ( + FILE_SEARCH_DATA *FSData, + STRING_LIST *StrList + ) +{ + FSData->ExcludeExtensions = StrList; + return STATUS_SUCCESS; +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/FileSearch.h b/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/FileSearch.h new file mode 100644 index 0000000000..bc40265366 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/FileSearch.h @@ -0,0 +1,108 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + FileSearch.h + +Abstract: + + Header file to support file searching. + +--*/ + +#ifndef _FILE_SEARCH_H_ +#define _FILE_SEARCH_H_ + +// +// Since the file searching routines are OS dependent, put the +// necessary include paths in this header file so that the non-OS-dependent +// files don't need to include these windows-specific header files. +// +#include +#include +#include +#include +#include + +// +// Return codes of some of the file search routines +// +#define STATUS_NOT_FOUND 0x1000 + +// +// Flags for what to search for. Also used in the FileFlags return field. +// +#define FILE_SEARCH_DIR 0x0001 +#define FILE_SEARCH_FILE 0x0002 + +// +// Here's our class definition +// +typedef struct { + HANDLE Handle; + WIN32_FIND_DATA FindData; + UINT32 FileSearchFlags; // DIRS, FILES, etc + UINT32 FileFlags; + INT8 FileName[MAX_PATH]; // for portability + STRING_LIST *ExcludeDirs; + STRING_LIST *ExcludeFiles; + STRING_LIST *ExcludeExtensions; +} FILE_SEARCH_DATA; + +// +// Here's our member functions +// +STATUS +FileSearchInit ( + FILE_SEARCH_DATA *FSData + ) +; + +STATUS +FileSearchDestroy ( + FILE_SEARCH_DATA *FSData + ) +; + +STATUS +FileSearchStart ( + FILE_SEARCH_DATA *FSData, + char *FileMask, + UINT32 SearchFlags + ) +; + +STATUS +FileSearchFindNext ( + FILE_SEARCH_DATA *FSData + ) +; + +STATUS +FileSearchExcludeDirs ( + FILE_SEARCH_DATA *FSData, + STRING_LIST *StrList + ) +; +STATUS +FileSearchExcludeExtensions ( + FILE_SEARCH_DATA *FSData, + STRING_LIST *StrList + ) +; +STATUS +FileSearchExcludeFiles ( + FILE_SEARCH_DATA *FSData, + STRING_LIST *StrList + ) +; +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/GuidChk.c b/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/GuidChk.c new file mode 100644 index 0000000000..97d58925b4 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/GuidChk.c @@ -0,0 +1,2417 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + GuidChk.c + +Abstract: + + Parse files in a directory and subdirectories to find all guid definitions. + Then check them against each other to make sure there are no duplicates. + +--*/ + +#include +#include +#include +#include + +#include "CommonUtils.h" +#include "FileSearch.h" +#include "UtilsMsgs.h" + +#define MAX_LINE_LEN 1024 // we concatenate lines sometimes +// Define a structure that correlates filename extensions to an enumerated +// type. +// +#ifdef MAX_PATH +#undef MAX_PATH +#define MAX_PATH 1024 +#endif + +typedef struct { + INT8 *Extension; + INT8 ExtensionCode; +} FILE_TYPE_TABLE_ENTRY; + +#define FILE_EXTENSION_UNKNOWN 0 +#define FILE_EXTENSION_C 1 +#define FILE_EXTENSION_H 2 +#define FILE_EXTENSION_IA32_ASM 3 +#define FILE_EXTENSION_IA32_INC 4 +#define FILE_EXTENSION_IA64_ASM 5 +#define FILE_EXTENSION_IA64_INC 6 +#define FILE_EXTENSION_PKG 7 +#define FILE_EXTENSION_INF 8 + +FILE_TYPE_TABLE_ENTRY FileTypeTable[] = { + ".c", + FILE_EXTENSION_C, + ".h", + FILE_EXTENSION_H, + ".inc", + FILE_EXTENSION_IA32_INC, + ".asm", + FILE_EXTENSION_IA32_ASM, + ".s", + FILE_EXTENSION_IA64_ASM, + ".pkg", + FILE_EXTENSION_PKG, + ".inf", + FILE_EXTENSION_INF, + ".i", + FILE_EXTENSION_IA64_INC, + NULL, + 0 +}; + +typedef struct EFI_GUID { + UINT32 Data1; + UINT16 Data2; + UINT16 Data3; + UINT8 Data4[8]; +} EFI_GUID; + +typedef struct { + INT8 Data[8]; + INT8 DataLen; +} EFI_SIGNATURE; + +typedef struct _GUID_RECORD { + struct _GUID_RECORD *Next; + BOOLEAN Reported; + INT8 *FileName; + INT8 *SymName; + EFI_GUID Guid; +} GUID_RECORD; + +typedef struct _SIGNATURE_RECORD { + struct _SIGNATURE_RECORD *Next; + BOOLEAN Reported; + INT8 *FileName; + EFI_SIGNATURE Signature; +} SIGNATURE_RECORD; + +// +// Utility options +// +typedef struct { + INT8 DatabaseOutputFileName[MAX_PATH]; // with -b option + STRING_LIST *ExcludeDirs; // list of directory names not to process + STRING_LIST *ExcludeSubDirs; // list of directory names to not process subdirectories (build) + STRING_LIST *ExcludeFiles; // list of files to exclude (make.inf) + STRING_LIST *ExcludeExtensions; // list of filename extensions to exclude (.inf, .pkg) + BOOLEAN Verbose; + BOOLEAN PrintFound; + BOOLEAN CheckGuids; + BOOLEAN CheckSignatures; + BOOLEAN GuidXReference; +} OPTIONS; + +static +STATUS +ProcessArgs ( + int Argc, + char *Argv[] + ); + +static +VOID +Usage ( + VOID + ); + +static +STATUS +ProcessDirectory ( + INT8 *Path, + INT8 *DirectoryName + ); + +static +STATUS +ProcessFile ( + INT8 *DirectoryName, + INT8 *FileName + ); + +static +UINT32 +GetFileExtension ( + INT8 *FileName + ); + +static +UINT32 +SkipWhiteSpace ( + INT8 *Str + ); + +static +UINT32 +ValidSymbolName ( + INT8 *Name + ); + +static +STATUS +ProcessCFileGuids ( + INT8 *FileName + ); + +static +STATUS +AddSignature ( + INT8 *FileName, + INT8 *StrDef, + UINT32 SigSize + ); + +static +STATUS +ProcessCFileSigs ( + INT8 *FileName + ); + +static +STATUS +ProcessINFFileGuids ( + INT8 *FileName + ); + +static +STATUS +ProcessPkgFileGuids ( + INT8 *FileName + ); + +static +STATUS +ProcessIA32FileGuids ( + INT8 *FileName + ); + +static +STATUS +ProcessIA64FileGuids ( + INT8 *FileName + ); + +static +BOOLEAN +IsIA64GuidLine ( + INT8 *Line, + UINT32 *GuidHigh, + UINT32 *GuidLow, + BOOLEAN *Low, + INT8 *SymName + ); + +static +STATUS +AddGuid11 ( + INT8 *FileName, + UINT32 *Data, + INT8 *SymName + ); + +static +STATUS +AddPkgGuid ( + INT8 *FileName, + UINT32 *Data, + UINT64 *Data64 + ); + +static +STATUS +AddGuid16 ( + INT8 *FileName, + UINT32 *Data + ); + +static +STATUS +AddGuid64x2 ( + INT8 *FileName, + UINT32 DataHH, // Upper 32-bits of upper 64 bits of guid + UINT32 DataHL, // Lower 32-bits of upper 64 bits + UINT32 DataLH, + UINT32 DataLL, + INT8 *SymName + ); + +static +VOID +FreeGuids ( + VOID + ); + +static +VOID +FreeSigs ( + VOID + ); + +static +STATUS +CheckDuplicates ( + VOID + ); + +// +// static +// VOID +// ReportGuid ( +// INT8 *FileName, +// GUID_RECORD *FileRecord +// ); +// +static +VOID +FreeOptions ( + VOID + ); + +static +BOOLEAN +CheckGuidData ( + UINT32 *GuidData, + UINT32 DataCount + ); + +static +VOID +ConcatenateLines ( + FILE *Fptr, + INT8 *Line, + UINT32 Len + ); + +/**************************** GLOBALS ****************************************/ +static GUID_RECORD *gGuidList = NULL; +static SIGNATURE_RECORD *gSignatureList = NULL; +static OPTIONS gOptions; + +/*****************************************************************************/ +int +main ( + int Argc, + char *Argv[] + ) +{ + INT8 *Cwd; + STATUS Status; + + SetUtilityName ("GuidChk"); + // + // Get the current working directory and then process the command line + // arguments. + // + Cwd = _getcwd (NULL, 0); + Status = ProcessArgs (Argc, Argv); + if (Status != STATUS_SUCCESS) { + return Status; + } + + if (gOptions.CheckGuids || gOptions.CheckSignatures) { + Status = ProcessDirectory (Cwd, NULL); + if (Status == STATUS_SUCCESS) { + // + // Check for duplicates + // + Status = CheckDuplicates (); + } + } + + if (gOptions.DatabaseOutputFileName[0] != 0) { + CreateGuidList (gOptions.DatabaseOutputFileName); + } + // + // Free up the memory + // + free (Cwd); + FreeGuids (); + FreeSigs (); + FreeOptions (); + return GetUtilityStatus (); +} + +static +STATUS +ProcessArgs ( + int Argc, + char *Argv[] + ) +{ + STRING_LIST *StrList; + + memset ((char *) &gOptions, 0, sizeof (gOptions)); + // + // skip over program name + // + Argc--; + Argv++; + + if (Argc == 0) { + Usage (); + return STATUS_ERROR; + } + + while (Argc > 0) { + // + // Look for options + // + if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) { + switch (Argv[0][1]) { + // + // Help option + // + case 'h': + case 'H': + case '?': + Usage (); + return STATUS_ERROR; + break; + + // + // Check guids option + // + case 'g': + case 'G': + gOptions.CheckGuids = TRUE; + break; + + // + // Check signatures option + // + case 's': + case 'S': + gOptions.CheckSignatures = TRUE; + break; + + // + // Print guids found option + // + case 'p': + case 'P': + gOptions.PrintFound = TRUE; + break; + + // + // Exclude files option + // + case 'f': + case 'F': + // + // Check for another arg + // + if (Argc < 2) { + Error (NULL, 0, 0, Argv[0], "missing argument with option"); + Usage (); + return STATUS_ERROR; + } + + StrList = malloc (sizeof (STRING_LIST)); + if (StrList == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset ((char *) StrList, 0, sizeof (STRING_LIST)); + StrList->Str = Argv[1]; + StrList->Next = gOptions.ExcludeFiles; + gOptions.ExcludeFiles = StrList; + Argc--; + Argv++; + break; + + // + // Exclude directories option + // + case 'd': + case 'D': + // + // Check for another arg + // + if (Argc < 2) { + Error (NULL, 0, 0, Argv[0], "missing argument with option"); + Usage (); + return STATUS_ERROR; + } + + StrList = malloc (sizeof (STRING_LIST)); + if (StrList == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset ((char *) StrList, 0, sizeof (STRING_LIST)); + StrList->Str = Argv[1]; + StrList->Next = gOptions.ExcludeDirs; + gOptions.ExcludeDirs = StrList; + Argc--; + Argv++; + break; + + // + // -u exclude all subdirectories of a given directory option + // + case 'u': + case 'U': + // + // Check for another arg + // + if (Argc < 2) { + Error (NULL, 0, 0, Argv[0], "missing argument with option"); + Usage (); + return STATUS_ERROR; + } + + StrList = malloc (sizeof (STRING_LIST)); + if (StrList == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset ((char *) StrList, 0, sizeof (STRING_LIST)); + StrList->Str = Argv[1]; + StrList->Next = gOptions.ExcludeSubDirs; + gOptions.ExcludeSubDirs = StrList; + Argc--; + Argv++; + break; + + // + // -e exclude by filename extension option + // + case 'e': + case 'E': + // + // Check for another arg + // + if (Argc < 2) { + Error (NULL, 0, 0, Argv[0], "missing argument with option"); + Usage (); + return STATUS_ERROR; + } + + StrList = malloc (sizeof (STRING_LIST)); + if (StrList == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset ((char *) StrList, 0, sizeof (STRING_LIST)); + // + // Let them put a * in front of the filename extension + // + StrList->Str = Argv[1]; + if (StrList->Str[0] == '*') { + StrList->Str++; + } + + StrList->Next = gOptions.ExcludeExtensions; + gOptions.ExcludeExtensions = StrList; + Argc--; + Argv++; + break; + + // + // Print guid with matching symbol name for guid definitions found + // + case 'x': + case 'X': + gOptions.GuidXReference = TRUE; + break; + + // + // -b Print the internal database list to a file + // + case 'b': + case 'B': + // + // Check for one more arg + // + if (Argc < 2) { + Error (NULL, 0, 0, Argv[0], "must specify file name with option"); + Usage (); + return STATUS_ERROR; + } + + strcpy (gOptions.DatabaseOutputFileName, Argv[1]); + Argc--; + Argv++; + break; + + default: + Error (NULL, 0, 0, Argv[0], "invalid option"); + Usage (); + return STATUS_ERROR; + } + } else { + break; + } + // + // Next arg + // + Argc--; + Argv++; + } + + if (Argc > 0) { + Error (NULL, 0, 0, Argv[0], "invalid argument"); + Usage (); + return STATUS_ERROR; + } + // + // Have to check signatures, GUIDs, or dump the GUID database. + // + if ((!gOptions.CheckGuids) && (!gOptions.CheckSignatures) && (gOptions.DatabaseOutputFileName[0] == 0)) { + Error (NULL, 0, 0, "nothing to do", "must specify -g, -s, and/or -b"); + Usage (); + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} +// +// Print usage instructions +// +static +VOID +Usage ( + VOID + ) +{ + int Index; + char *Str[] = { + "GuidChk - scan files for duplicate GUID or signature definitions", + "", + "Usage: GuidChk {options}\n", + " Options: ", + " -d dirname exclude searching of a directory", + " -f filename exclude searching of a file", + " -e extension exclude searching of files by extension", + " -p print all GUIDS found", + " -g check for duplicate guids", + " -s check for duplicate signatures", + " -x print guid+defined symbol name", + " -b outfile write internal GUID+basename list to outfile", + " -u dirname exclude searching all subdirectories of a directory", + " -h -? print this help text", + " ", + " Example: GuidChk -g -u build -d fv -f make.inf -e .pkg", + "", + NULL + }; + for (Index = 0; Str[Index] != NULL; Index++) { + fprintf (stdout, "%s\n", Str[Index]); + } +} +// +// Process an entire directory by name +// +static +STATUS +ProcessDirectory ( + INT8 *Path, + INT8 *DirectoryName + ) +{ + FILE_SEARCH_DATA FSData; + char *FileMask; + BOOLEAN Done; + UINT32 Len; + BOOLEAN NoSubdirs; + STRING_LIST *SLPtr; + + // + // Root directory may be null + // + if (DirectoryName != NULL) { + // + // printf ("Processing directory: %s\n", DirectoryName); + // + } + // + // Initialize our file searching + // + FileSearchInit (&FSData); + + // + // Exclude some directories, files, and extensions + // + FileSearchExcludeDirs (&FSData, gOptions.ExcludeDirs); + FileSearchExcludeExtensions (&FSData, gOptions.ExcludeExtensions); + FileSearchExcludeFiles (&FSData, gOptions.ExcludeFiles); + // + // See if this directory is in the list of directories that they + // don't want to process subdirectories of + // + NoSubdirs = FALSE; + if (DirectoryName != NULL) { + for (SLPtr = gOptions.ExcludeSubDirs; SLPtr != NULL; SLPtr = SLPtr->Next) { + if (_stricmp (SLPtr->Str, DirectoryName) == 0) { + // + // printf ("not processing subdirectories of %s\n", DirectoryName); + // + NoSubdirs = TRUE; + break; + } + } + } + // + // Create a filemask of files to search for. We'll append "\*.*" on the + // end, so allocate some extra bytes. + // + Len = strlen (Path) + 10; + if (DirectoryName != NULL) { + Len += strlen (DirectoryName); + } + + FileMask = malloc (Len); + if (FileMask == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + // + // Now put it all together + // + strcpy (FileMask, Path); + if ((DirectoryName != NULL) && (strlen (DirectoryName) > 0)) { + strcat (FileMask, "\\"); + strcat (FileMask, DirectoryName); + } + + strcat (FileMask, "\\*.*"); + + // + // Start file searching for files and directories + // + if (FileSearchStart (&FSData, FileMask, FILE_SEARCH_FILE | FILE_SEARCH_DIR) == STATUS_SUCCESS) { + Done = FALSE; + } else { + Done = TRUE; + } + + // + // Now hack the "\*.*" off the end of the filemask so we can use it to pass + // the full directory path on recursive calls to process directories. + // + FileMask[strlen (FileMask) - 4] = 0; + + // + // Loop until no more files + // + while (!Done) { + // + // printf ("Found %s...", FSData.FileName); + // + if (FSData.FileFlags & FILE_SEARCH_DIR) { + // + // printf ("directory\n"); + // + if (!NoSubdirs) { + ProcessDirectory (FileMask, FSData.FileName); + } + } else if (FSData.FileFlags & FILE_SEARCH_FILE) { + // + // printf ("file\n"); + // + ProcessFile (FileMask, FSData.FileName); + } else { + // + // printf ("unknown\n"); + // + } + + if (FileSearchFindNext (&FSData) != STATUS_SUCCESS) { + Done = TRUE; + } + } + // + // Free up allocated memory + // + free (FileMask); + + // + // Free up our file searching + // + FileSearchDestroy (&FSData); + + return STATUS_SUCCESS; +} +// +// Process a single file. +// +static +STATUS +ProcessFile ( + INT8 *DirectoryName, + INT8 *FileName + ) +{ + STATUS Status; + UINT32 FileExtension; + INT8 FullFileName[MAX_PATH]; + + Status = STATUS_SUCCESS; + + sprintf (FullFileName, "%s\\%s", DirectoryName, FileName); + // + // printf ("Found file: %s\n", FullFileName); + // + FileExtension = GetFileExtension (FileName); + + // + // Process these for GUID checks + // + if (gOptions.CheckGuids) { + switch (FileExtension) { + case FILE_EXTENSION_C: + case FILE_EXTENSION_H: + Status = ProcessCFileGuids (FullFileName); + break; + + case FILE_EXTENSION_PKG: + Status = ProcessPkgFileGuids (FullFileName); + break; + + case FILE_EXTENSION_IA32_INC: + case FILE_EXTENSION_IA32_ASM: + Status = ProcessIA32FileGuids (FullFileName); + break; + + case FILE_EXTENSION_INF: + Status = ProcessINFFileGuids (FullFileName); + break; + + case FILE_EXTENSION_IA64_INC: + case FILE_EXTENSION_IA64_ASM: + Status = ProcessIA64FileGuids (FullFileName); + break; + + default: + // + // No errors anyway + // + Status = STATUS_SUCCESS; + break; + } + } + + if (gOptions.CheckSignatures) { + switch (FileExtension) { + case FILE_EXTENSION_C: + case FILE_EXTENSION_H: + Status = ProcessCFileSigs (FullFileName); + break; + + default: + // + // No errors anyway + // + Status = STATUS_SUCCESS; + break; + } + } + + return Status; +} +// +// Return a code indicating the file name extension. +// +static +UINT32 +GetFileExtension ( + INT8 *FileName + ) +{ + INT8 *Extension; + int Index; + + // + // Look back for a filename extension + // + for (Extension = FileName + strlen (FileName) - 1; Extension >= FileName; Extension--) { + if (*Extension == '.') { + for (Index = 0; FileTypeTable[Index].Extension != NULL; Index++) { + if (_stricmp (FileTypeTable[Index].Extension, Extension) == 0) { + return FileTypeTable[Index].ExtensionCode; + } + } + } + } + + return FILE_TYPE_UNKNOWN; +} +// +// Process a .pkg file. +// +// Look for FFS_FILEGUID=35b898ca-b6a9-49ce-8c72-904735cc49b7 +// +static +STATUS +ProcessPkgFileGuids ( + INT8 *FileName + ) +{ + FILE *Fptr; + INT8 Line[MAX_LINE_LEN * 2]; + INT8 *Cptr; + INT8 *Cptr2; + UINT32 GuidScan[11]; + UINT64 Guid64; + + if ((Fptr = fopen (FileName, "r")) == NULL) { + Error (NULL, 0, 0, FileName, "could not open input file for reading"); + return STATUS_ERROR; + } + // + // Read lines from the file until done + // + while (fgets (Line, sizeof (Line), Fptr) != NULL) { + Cptr = Line; + Cptr += SkipWhiteSpace (Line); + if (strncmp (Cptr, "FFS_FILEGUID", 12) == 0) { + Cptr += 12; + Cptr += SkipWhiteSpace (Cptr); + if (*Cptr == '=') { + Cptr++; + Cptr += SkipWhiteSpace (Cptr + 1); + // + // Blank out dashes on the line. + // + for (Cptr2 = Cptr; *Cptr2; Cptr2++) { + if (*Cptr2 == '-') { + *Cptr2 = ' '; + } + } + + if (sscanf ( + Cptr, + "%X %X %X %X %I64X", + &GuidScan[0], + &GuidScan[1], + &GuidScan[2], + &GuidScan[3], + &Guid64 + ) == 5) { + AddPkgGuid (FileName, GuidScan, &Guid64); + } else { + DebugMsg (NULL, 0, 0, FileName, "GUID scan failed"); + } + } + } + } + + fclose (Fptr); + return STATUS_SUCCESS; +} +// +// Process an IA32 assembly file. +// +// Look for: +// FIND_FD_GUID_VAL equ 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h, 01h +// PEI_GUID_FileNameGuid_Gmch815 equ 081818181h, 08181h, 08181h, 081h, 081h, 081h, 081h, 081h, 081h, 081h, 081h +// +static +STATUS +ProcessIA32FileGuids ( + INT8 *FileName + ) +{ + FILE *Fptr; + INT8 Line[MAX_LINE_LEN]; + INT8 *Cptr; + INT8 CSave; + INT8 *CSavePtr; + UINT32 Len; + UINT32 GuidData[16]; + UINT32 Index; + + if ((Fptr = fopen (FileName, "r")) == NULL) { + Error (NULL, 0, 0, FileName, "could not open input file for reading"); + return STATUS_ERROR; + } + // + // Read lines from the file until done + // + while (fgets (Line, sizeof (Line), Fptr) != NULL) { + Cptr = Line; + Cptr += SkipWhiteSpace (Line); + // + // Look for xxxGUIDyyy equ 01h, 02h, 03h, ... + // + Len = ValidSymbolName (Cptr); + if (Len) { + // + // Terminate the line after the symbol name, then look for "guid" in + // the name. + // + CSavePtr = Cptr + Len; + CSave = *CSavePtr; + *CSavePtr = 0; + while (*Cptr) { + if (_strnicmp (Cptr, "guid", 4) == 0) { + break; + } + + Cptr++; + } + // + // If we found the string "guid", continue + // + if (*Cptr) { + // + // Restore the character on the line where we null-terminated the symbol + // + *CSavePtr = CSave; + Cptr = CSavePtr; + Len = SkipWhiteSpace (Cptr); + // + // Had to be some white space + // + if (Len) { + Cptr += Len; + // + // now look for "equ" + // + if (_strnicmp (Cptr, "equ", 3) == 0) { + Cptr += 3; + Cptr += SkipWhiteSpace (Cptr); + // + // Now scan all the data + // + for (Index = 0; Index < 16; Index++) { + if (sscanf (Cptr, "%X", &GuidData[Index]) != 1) { + break; + } + // + // Skip to next + // + while (isxdigit (*Cptr)) { + Cptr++; + } + + if ((*Cptr != 'h') && (*Cptr != 'H')) { + break; + } else { + Cptr++; + while (*Cptr && (isspace (*Cptr) || (*Cptr == ','))) { + Cptr++; + } + } + } + // + // Now see which form we had + // + if (Index == 16) { + AddGuid16 (FileName, GuidData); + } else if (Index == 11) { + AddGuid11 (FileName, GuidData, NULL); + } + } + } + } + } + } + + fclose (Fptr); + return STATUS_SUCCESS; +} +// +// Found and parsed an IA32 assembly code guid. Save the 16 bytes off in the list +// of guids. +// +static +STATUS +AddGuid16 ( + INT8 *FileName, + UINT32 *Data + ) +{ + GUID_RECORD *NewRec; + int Index; + + // + // Sanity check the data + // + if (!CheckGuidData (Data, 16)) { + return STATUS_ERROR; + } + // + // Allocate memory for a new guid structure + // + NewRec = malloc (sizeof (GUID_RECORD)); + if (NewRec == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset ((char *) NewRec, 0, sizeof (GUID_RECORD)); + NewRec->FileName = malloc (strlen (FileName) + 1); + if (NewRec->FileName == NULL) { + free (NewRec); + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + strcpy (NewRec->FileName, FileName); + NewRec->Guid.Data1 = (UINT32) (Data[0] | (Data[1] << 8) | (Data[2] << 16) | (Data[3] << 24)); + NewRec->Guid.Data2 = (UINT16) (Data[4] | (Data[5] << 8)); + NewRec->Guid.Data3 = (UINT16) (Data[6] | (Data[7] << 8)); + for (Index = 0; Index < 8; Index++) { + NewRec->Guid.Data4[Index] = (UINT8) Data[Index + 8]; + } + // + // Add it to the list + // + NewRec->Next = gGuidList; + gGuidList = NewRec; + + // + // Report it + // ReportGuid (FileName, NewRec); + // + return STATUS_SUCCESS; +} +// +// Add a GUID defined as GuidLow: 0x1122334455667788 +// GuidHi: 0x99AABBCCDDEEFF00 +// +// These are equivalent: +// { 0x11223344, 0x5566, 0x7788, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00 } +// and: +// Low: 00FFEEDDCCBBAA99 +// Hi: 7788556611223344 +// +static +STATUS +AddGuid64x2 ( + INT8 *FileName, + UINT32 DataHH, // Upper 32-bits of upper 64 bits of guid + UINT32 DataHL, // Lower 32-bits of upper 64 bits + UINT32 DataLH, + UINT32 DataLL, + INT8 *SymName + ) +{ + GUID_RECORD *NewRec; + int Index; + + // + // Allocate memory for a new guid structure + // + NewRec = malloc (sizeof (GUID_RECORD)); + if (NewRec == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset ((char *) NewRec, 0, sizeof (GUID_RECORD)); + NewRec->FileName = malloc (strlen (FileName) + 1); + if (NewRec->FileName == NULL) { + free (NewRec); + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + strcpy (NewRec->FileName, FileName); + NewRec->Guid.Data1 = DataHL; + NewRec->Guid.Data2 = (UINT16) DataHH; + NewRec->Guid.Data3 = (UINT16) (DataHH >> 16); + for (Index = 0; Index < 4; Index++) { + NewRec->Guid.Data4[Index] = (UINT8) DataLL; + DataLL >>= 8; + } + + for (Index = 0; Index < 4; Index++) { + NewRec->Guid.Data4[Index + 4] = (UINT8) DataLH; + DataLH >>= 8; + } + + if (SymName != NULL) { + NewRec->SymName = malloc (strlen (SymName) + 1); + if (NewRec->SymName == NULL) { + free (NewRec); + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + strcpy (NewRec->SymName, SymName); + } + + // + // Add it to the list + // + NewRec->Next = gGuidList; + gGuidList = NewRec; + + // + // Report it + // ReportGuid (FileName, NewRec); + // + return STATUS_SUCCESS; +} +// +// Process INF files. Look for: +// FILE_GUID = 240612B6-A063-11d4-9A3A-0090273FC14D +// +static +STATUS +ProcessINFFileGuids ( + INT8 *FileName + ) +{ + FILE *Fptr; + INT8 Line[MAX_LINE_LEN * 2]; + INT8 *Cptr; + INT8 *Cptr2; + UINT32 GuidScan[11]; + UINT64 Guid64; + + if ((Fptr = fopen (FileName, "r")) == NULL) { + Error (NULL, 0, 0, FileName, "could not open input file for reading"); + return STATUS_ERROR; + } + // + // Read lines from the file until done + // + while (fgets (Line, sizeof (Line), Fptr) != NULL) { + Cptr = Line; + Cptr += SkipWhiteSpace (Line); + if (strncmp (Cptr, "FILE_GUID", 9) == 0) { + Cptr += 9; + Cptr += SkipWhiteSpace (Cptr); + if (*Cptr == '=') { + Cptr++; + Cptr += SkipWhiteSpace (Cptr + 1); + // + // Blank out dashes on the line. + // + for (Cptr2 = Cptr; *Cptr2; Cptr2++) { + if (*Cptr2 == '-') { + *Cptr2 = ' '; + } + } + + if (sscanf ( + Cptr, + "%X %X %X %X %I64X", + &GuidScan[0], + &GuidScan[1], + &GuidScan[2], + &GuidScan[3], + &Guid64 + ) == 5) { + AddPkgGuid (FileName, GuidScan, &Guid64); + } else { + DebugMsg (NULL, 0, 0, FileName, "GUID scan failed"); + } + } + } + } + + fclose (Fptr); + return STATUS_SUCCESS; +} +// +// Parse ('g','m','a','p','a','b','c','d') +// +static +STATUS +AddSignature ( + INT8 *FileName, + INT8 *StrDef, + UINT32 SigSize + ) +{ + SIGNATURE_RECORD *NewRec; + INT8 *Cptr; + UINT32 Index; + BOOLEAN Fail; + + // + // Allocate memory for the new record + // + Fail = FALSE; + NewRec = malloc (sizeof (SIGNATURE_RECORD)); + + if (NewRec == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + memset ((char *) NewRec, 0, sizeof (SIGNATURE_RECORD)); + + // + // Allocate memory to save the file name + // + NewRec->FileName = malloc (strlen (FileName) + 1); + if (NewRec->FileName == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + free (NewRec); + return STATUS_ERROR; + } + // + // Fill in the fields + // + strcpy (NewRec->FileName, FileName); + NewRec->Signature.DataLen = (UINT8) SigSize; + // + // Skip to open parenthesis + // + Cptr = StrDef; + Cptr += SkipWhiteSpace (Cptr); + if (*Cptr != '(') { + Fail = TRUE; + goto Done; + } + + Cptr++; + // + // Skip to first ' and start processing + // + while (*Cptr && (*Cptr != '\'')) { + Cptr++; + } + + for (Index = 0; Index < SigSize; Index++) { + if (*Cptr == '\'') { + Cptr++; + NewRec->Signature.Data[Index] = (INT8) *Cptr; + // + // Skip to closing quote + // + Cptr++; + if (*Cptr != '\'') { + Fail = TRUE; + break; + } + // + // Skip over closing quote, go to next one + // + Cptr++; + while (*Cptr && (*Cptr != '\'')) { + Cptr++; + } + } else { + Fail = TRUE; + DebugMsg (NULL, 0, 0, FileName, "failed to parse signature"); + break; + } + } + +Done: + if (Fail) { + free (NewRec->FileName); + free (NewRec); + return STATUS_ERROR; + } + + NewRec->Next = gSignatureList; + gSignatureList = NewRec; + return STATUS_SUCCESS; +} +// +// Look for: +// #define POOL_HEAD_SIGNATURE EFI_SIGNATURE_16('p','h') +// #define GCD_MEMORY_MAP_SIGNATURE EFI_SIGNATURE_32('g','m','a','p') +// #define GCD_MEMORY_MAP_SIGNATURE EFI_SIGNATURE_64('g','m','a','p','a','b','c','d') +// +static +STATUS +ProcessCFileSigs ( + INT8 *FileName + ) +{ + FILE *Fptr; + INT8 Line[MAX_LINE_LEN * 2]; + INT8 *Cptr; + UINT32 Len; + + if ((Fptr = fopen (FileName, "r")) == NULL) { + Error (NULL, 0, 0, FileName, "could not open input file for reading"); + return STATUS_ERROR; + } + // + // Read lines from the file until done + // + while (fgets (Line, sizeof (Line), Fptr) != NULL) { + Cptr = Line; + Cptr += SkipWhiteSpace (Line); + // + // look for #define EFI_SIGNATURE_xx value + // + if (*Cptr == '#') { + Cptr++; + Cptr += SkipWhiteSpace (Cptr); + // + // Look for "define" + // + if (!strncmp (Cptr, "define", 6)) { + Cptr += 6; + // + // Better be whitespace + // + Len = SkipWhiteSpace (Cptr); + if (Len) { + Cptr += Len; + // + // See if it's a valid symbol name + // + Len = ValidSymbolName (Cptr); + if (Len) { + // + // It is a valid symbol name. See if there's line continuation, + // and if so, read more lines. + // Skip over the symbol name and look for the string "EFI_SIGNATURE_xx" + // + ConcatenateLines (Fptr, Line, sizeof(Line)); + + Cptr += Len; + Cptr += SkipWhiteSpace (Cptr); + if (strncmp (Cptr, "EFI_SIGNATURE_16", 16) == 0) { + AddSignature (FileName, Cptr + 16, 2); + } else if (strncmp (Cptr, "EFI_SIGNATURE_32", 16) == 0) { + AddSignature (FileName, Cptr + 16, 4); + } else if (strncmp (Cptr, "EFI_SIGNATURE_64", 16) == 0) { + AddSignature (FileName, Cptr + 16, 8); + } + } + } + } + } + } + + fclose (Fptr); + return STATUS_SUCCESS; +} +// +// look for #define xxxGUIDyyy { 0x...} +// xxx EFI_GUID GuidName = { 0x... }; +// +static +STATUS +ProcessCFileGuids ( + INT8 *FileName + ) +{ + FILE *Fptr; + INT8 Line[MAX_LINE_LEN * 2]; + INT8 *Cptr; + INT8 *CSavePtr; + INT8 *TempCptr; + INT8 *SymName; + UINT32 Len; + UINT32 LineLen; + UINT32 GuidScan[11]; + + if ((Fptr = fopen (FileName, "r")) == NULL) { + Error (NULL, 0, 0, FileName, "could not open input file for reading"); + return STATUS_ERROR; + } + // + // Read lines from the file until done + // + while (fgets (Line, sizeof (Line), Fptr) != NULL) { + Cptr = Line; + Cptr += SkipWhiteSpace (Line); + // + // look for #define xxxGUIDxxx value + // + if (*Cptr == '#') { + Cptr++; + Cptr += SkipWhiteSpace (Cptr); + // + // Look for "define" + // + if (!strncmp (Cptr, "define", 6)) { +DefineLine: + Cptr += 6; + // + // Better be whitespace + // + Len = SkipWhiteSpace (Cptr); + if (Len) { + Cptr += Len; + // + // See if it's a valid symbol name + // + Len = ValidSymbolName (Cptr); + if (Len) { + // + // It is a valid symbol name. See if there's line continuation, + // and if so, read more lines. + // Then truncate after the symbol name, look for the string "GUID", + // and continue. + // + SymName = Cptr; + ConcatenateLines (Fptr, Line, sizeof(Line)); + + // + // Now look for { 0x....... } + // + CSavePtr = Cptr + Len; + Cptr += Len; + Cptr += SkipWhiteSpace (Cptr); + if (*Cptr == '{') { + Cptr++; + // + // Blank out 'L', 'l', '{', '}', ',' on the line. + // + for (TempCptr = Cptr; *TempCptr; TempCptr++) { + if ((*TempCptr == 'L') || (*TempCptr == 'l') || (*TempCptr == '{') || + (*TempCptr == '}') || (*TempCptr == ',')) { + *TempCptr = ' '; + } + } + + if (sscanf ( + Cptr, + "%X %X %X %X %X %X %X %X %X %X %X", + &GuidScan[0], + &GuidScan[1], + &GuidScan[2], + &GuidScan[3], + &GuidScan[4], + &GuidScan[5], + &GuidScan[6], + &GuidScan[7], + &GuidScan[8], + &GuidScan[9], + &GuidScan[10] + ) == 11) { + *CSavePtr = '\0'; + AddGuid11 (FileName, GuidScan, SymName); + } + } + } + } + } + // + // Else look for "static EFI_GUID xxxGUIDxxx = { 0x.... }; + // + } else if ((CSavePtr = strstr (Line, "EFI_GUID")) != NULL) { + // + // Read more lines until met ';' + // + ConcatenateLines (Fptr, Line, sizeof(Line)); + while (strstr (Line, ";") == NULL) { + LineLen = strlen (Line); + Len = sizeof(Line) - LineLen; + if (Len <= 1) { + break; + } + if (Line[LineLen - 1] == '\n') { + Cptr = Line + LineLen - 1; + *Cptr = '\0'; + if (fgets (Cptr, Len, Fptr) == NULL){ + break; + } + ConcatenateLines (Fptr, Line, sizeof(Line)); + } else { + Cptr = Line + LineLen; + *Cptr = '\0'; + if (fgets (Cptr, Len, Fptr) == NULL) { + break; + } + ConcatenateLines (Fptr, Line, sizeof(Line)); + } + + // + // EFI_GUID may appear in comments wihout end of ';' which may cause + // ignoring of new #define, so handle it here. + // + Cptr += SkipWhiteSpace (Cptr); + if (*Cptr == '#') { + Cptr++; + Cptr += SkipWhiteSpace (Cptr); + if (!strncmp (Cptr, "define", 6)) { + goto DefineLine; + } + } + } + + Cptr = CSavePtr + 8; + Cptr += SkipWhiteSpace (Cptr); + // + // Should be variable name next + // + Len = ValidSymbolName (Cptr); + SymName = Cptr; + Cptr += Len; + CSavePtr = Cptr; + Cptr += SkipWhiteSpace (Cptr); + if (*Cptr == '=') { + *CSavePtr = '\0'; + Cptr++; + Cptr += SkipWhiteSpace (Cptr); + // + // Should be open-brace next to define guid + // + if (*Cptr == '{') { + Cptr++; + // + // Blank out 'L', 'l', '{', '}', ',' on the line. + // + for (TempCptr = Cptr; *TempCptr; TempCptr++) { + if ((*TempCptr == 'L') || (*TempCptr == 'l') || (*TempCptr == '{') || + (*TempCptr == '}') || (*TempCptr == ',')) { + *TempCptr = ' '; + } + } + + if (sscanf ( + Cptr, + "%X %X %X %X %X %X %X %X %X %X %X", + &GuidScan[0], + &GuidScan[1], + &GuidScan[2], + &GuidScan[3], + &GuidScan[4], + &GuidScan[5], + &GuidScan[6], + &GuidScan[7], + &GuidScan[8], + &GuidScan[9], + &GuidScan[10] + ) == 11) { + AddGuid11 (FileName, GuidScan, SymName); + } + } + } + } + } + + fclose (Fptr); + return STATUS_SUCCESS; +} +// +// Process Intel Itanium(TM) GUID definitions. Look for: +// #define Cs870MemoryTestPEIMGuidL 0x9C2403386E1C8FAA +// #define Cs870MemoryTestPEIMGuidH 0xE89E95C6180342f0 +// in either order. +// This function assumes no blank lines between definitions. +// +static +STATUS +ProcessIA64FileGuids ( + INT8 *FileName + ) +{ + FILE *Fptr; + INT8 Line[MAX_LINE_LEN]; + UINT32 Guid1H; + UINT32 Guid1L; + UINT32 Guid2H; + UINT32 Guid2L; + INT8 SymName1[MAX_LINE_LEN]; + INT8 SymName2[MAX_LINE_LEN]; + BOOLEAN Done; + BOOLEAN LowFirst; + BOOLEAN FoundLow; + + if ((Fptr = fopen (FileName, "r")) == NULL) { + Error (NULL, 0, 0, FileName, "could not open input file for reading"); + return STATUS_ERROR; + } + + Done = FALSE; + if (fgets (Line, sizeof (Line), Fptr) == NULL) { + Done = 1; + } + // + // Read lines from the file until done. Since the guid definition takes + // two lines, we read lines in different places to recover gracefully + // from mismatches. For example, if you thought you found the first half, + // but the next line had a symbol mismatch, then you have to process the + // line again in case it's the start of a new definition. + // + while (!Done) { + // + // Check current line for GUID definition. Assume low define first. + // + if (IsIA64GuidLine (Line, &Guid1H, &Guid1L, &FoundLow, SymName1)) { + // + // Might have to swap guids later. Save off if we found the LOW first + // + if (FoundLow) { + LowFirst = TRUE; + } else { + LowFirst = FALSE; + } + // + // Read the next line and try for the rest of the guid definition + // + if (fgets (Line, sizeof (Line), Fptr) == NULL) { + Done = 1; + } else { + if (IsIA64GuidLine (Line, &Guid2H, &Guid2L, &FoundLow, SymName2)) { + // + // Found another. If the symbol names match, then save it off. + // + if (strcmp (SymName1, SymName2) == 0) { + // + // Yea, found one. Save it off. + // + if (LowFirst) { + AddGuid64x2 (FileName, Guid2H, Guid2L, Guid1H, Guid1L, SymName1); + } else { + AddGuid64x2 (FileName, Guid1H, Guid1L, Guid2H, Guid2L, SymName1); + } + // + // Read the next line for processing + // + if (fgets (Line, sizeof (Line), Fptr) == NULL) { + Done = 1; + } + } else { + // + // Don't get another line so that we reprocess this line in case it + // contains the start of a new definition. + // fprintf (stdout, "Symbol name mismatch: %s: %s != %s\n", + // FileName, SymName1, SymName2); + // + } + } else { + // + // Second line was not a guid definition. Get the next line from the + // file. + // + if (fgets (Line, sizeof (Line), Fptr) == NULL) { + Done = 1; + } + } + } + } else { + // + // Not a guid define line. Next. + // + if (fgets (Line, sizeof (Line), Fptr) == NULL) { + Done = 1; + } + } + } + + fclose (Fptr); + return STATUS_SUCCESS; +} +// +// Given a line from an Itanium-based assembly file, check the line for a guid +// defininition. One of either: +// #define Cs870MemoryTestPEIMGuidL 0x9C2403386E1C8FAA +// #define Cs870MemoryTestPEIMGuidH 0xE89E95C6180342f0 +// Return the defined value as two 32-bit values, and whether it's a high +// or low guid. +// +static +BOOLEAN +IsIA64GuidLine ( + INT8 *Line, + UINT32 *GuidHigh, + UINT32 *GuidLow, + BOOLEAN *FoundLow, + INT8 *SymName + ) +{ + INT8 *Cptr; + INT8 CSave; + INT8 *CSavePtr; + INT8 *SymStart; + UINT32 Len; + + Cptr = Line; + Cptr += SkipWhiteSpace (Cptr); + // + // look for #define xxxGUID[L|H] 0xHexValue + // + if (*Cptr == '#') { + Cptr++; + Cptr += SkipWhiteSpace (Cptr); + // + // Look for "define" + // + if (!strncmp (Cptr, "define", 6)) { + Cptr += 6; + // + // Better be whitespace + // + Len = SkipWhiteSpace (Cptr); + if (Len) { + Cptr += Len; + // + // See if it's a valid symbol name + // + Len = ValidSymbolName (Cptr); + if (Len) { + // + // Save the start so we can copy it to their string if later checks are ok + // + SymStart = Cptr; + // + // It is a valid symbol name, look for the string GuidL or GuidH + // + CSavePtr = Cptr + Len; + CSave = *CSavePtr; + *CSavePtr = 0; + while (*Cptr) { + if (strncmp (Cptr, "GuidL", 5) == 0) { + *FoundLow = 1; + break; + } else if (strncmp (Cptr, "GuidH", 5) == 0) { + *FoundLow = 0; + break; + } + + Cptr++; + } + // + // If we didn't run out of string, then we found the GUID string. + // Restore the null character we inserted above and continue. + // Now look for 0x....... + // + if (*Cptr) { + // + // Return symbol name less the "L" or "H" + // + strcpy (SymName, SymStart); + SymName[strlen (SymName) - 1] = 0; + Cptr = CSavePtr; + *CSavePtr = CSave; + Cptr += SkipWhiteSpace (Cptr); + if ((*Cptr == '0') && (*(Cptr + 1) == 'x')) { + // + // skip over "0x" + // + Cptr += 2; + // + // 0x0123456789ABCDEF -- null terminate after 8 characters, + // scan, replace the character and scan at that point. + // + CSave = *(Cptr + 8); + *(Cptr + 8) = 0; + if (sscanf (Cptr, "%X", GuidHigh) == 1) { + *(Cptr + 8) = CSave; + if (sscanf (Cptr + 8, "%X", GuidLow) == 1) { + return TRUE; + } + } + } + } + } + } + } + } + + return FALSE; +} +// +// Look at the characters in the string and determine if it's a valid +// symbol name. Basically [a-zA-Z_][a-zA-Z_0-9]* +// +static +UINT32 +ValidSymbolName ( + INT8 *Name + ) +{ + int Len; + + Len = 0; + + // + // Test first character + // + if (((*Name >= 'a') && (*Name <= 'z')) || ((*Name >= 'A') && (*Name <= 'Z')) || (*Name == '_')) { + Name++; + Len = 1; + while (*Name) { + if (((*Name >= 'a') && (*Name <= 'z')) || + ((*Name >= 'A') && (*Name <= 'Z')) || + ((*Name >= '0') && (*Name <= '9')) || + (*Name == '_') + ) { + Name++; + Len++; + } else { + break; + } + } + } + + return Len; +} + +static +UINT32 +SkipWhiteSpace ( + INT8 *Str + ) +{ + UINT32 Len; + Len = 0; + while (isspace (*Str) && *Str) { + Len++; + Str++; + } + + return Len; +} +// +// found FFS_FILEGUID=35b898ca-b6a9-49ce-8c72-904735cc49b7 +// +static +STATUS +AddPkgGuid ( + INT8 *FileName, + UINT32 *Data, + UINT64 *Data64 + ) +{ + GUID_RECORD *NewRec; + int Index; + + // + // Sanity check the data + // + if ((Data[1] | Data[2] | Data[3]) & 0xFFFF0000) { + Error (NULL, 0, 0, "out of range value for GUID data word(s) [1] - [3]", NULL); + return STATUS_ERROR; + } + // + // More checks for Data64? + // Allocate memory for a new one guid structure + // + NewRec = malloc (sizeof (GUID_RECORD)); + if (NewRec == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset ((char *) NewRec, 0, sizeof (GUID_RECORD)); + NewRec->FileName = malloc (strlen (FileName) + 1); + if (NewRec->FileName == NULL) { + free (NewRec); + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + strcpy (NewRec->FileName, FileName); + NewRec->Guid.Data1 = Data[0]; + NewRec->Guid.Data2 = (UINT16) Data[1]; + NewRec->Guid.Data3 = (UINT16) Data[2]; + NewRec->Guid.Data4[0] = (UINT8) (Data[3] >> 8); + NewRec->Guid.Data4[1] = (UINT8) Data[3]; + for (Index = 2; Index < 8; Index++) { + NewRec->Guid.Data4[Index] = ((UINT8*)Data64)[7-Index]; + } + // + // Add it to the list + // + NewRec->Next = gGuidList; + gGuidList = NewRec; + + // + // Report it + // ReportGuid (FileName, NewRec); + // + return STATUS_SUCCESS; +} +// +// Add a guid consisting of 11 fields to our list of guids +// +static +STATUS +AddGuid11 ( + INT8 *FileName, + UINT32 *Data, + INT8 *SymName + ) +{ + GUID_RECORD *NewRec; + int Index; + + // + // Sanity check the data + // + if (!CheckGuidData (Data, 11)) { + return STATUS_ERROR; + } + // + // Allocate memory for a new one guid structure + // + NewRec = malloc (sizeof (GUID_RECORD)); + if (NewRec == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset ((char *) NewRec, 0, sizeof (GUID_RECORD)); + NewRec->FileName = malloc (strlen (FileName) + 1); + if (NewRec->FileName == NULL) { + free (NewRec); + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + strcpy (NewRec->FileName, FileName); + if (SymName != NULL) { + NewRec->SymName = malloc (strlen (SymName) + 1); + if (NewRec->SymName == NULL) { + free (NewRec); + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + strcpy (NewRec->SymName, SymName); + } + + NewRec->Guid.Data1 = Data[0]; + NewRec->Guid.Data2 = (UINT16) Data[1]; + NewRec->Guid.Data3 = (UINT16) Data[2]; + for (Index = 0; Index < 8; Index++) { + NewRec->Guid.Data4[Index] = (UINT8) Data[3 + Index]; + } + // + // Add it to the list + // + NewRec->Next = gGuidList; + gGuidList = NewRec; + + // + // Report it + // ReportGuid (FileName, NewRec); + // + return STATUS_SUCCESS; +} +// +// For debug purposes, print each guid found +// +// static +// VOID +// ReportGuid ( +// INT8 *FileName, +// GUID_RECORD *NewGuid +// ) +// { +// //fprintf (stdout, "%s: 0x%08X\n", FileName, NewGuid->Guid.Data1); +// } +// +// Free up memory we allocated to keep track of guids defined. +// +static +VOID +FreeGuids ( + VOID + ) +{ + GUID_RECORD *NextRec; + while (gGuidList != NULL) { + NextRec = gGuidList->Next; + if (gGuidList->FileName != NULL) { + free (gGuidList->FileName); + } + + if (gGuidList->SymName != NULL) { + free (gGuidList->SymName); + } + + free (gGuidList); + gGuidList = NextRec; + } +} + +static +VOID +FreeSigs ( + VOID + ) +{ + SIGNATURE_RECORD *NextRec; + while (gSignatureList != NULL) { + NextRec = gSignatureList->Next; + if (gSignatureList->FileName != NULL) { + free (gSignatureList->FileName); + } + + free (gSignatureList); + gSignatureList = NextRec; + } +} +// +// Scan through all guids defined and compare each for duplicates. +// +static +STATUS +CheckDuplicates ( + VOID + ) +{ + GUID_RECORD *CurrentFile; + + GUID_RECORD *TempFile; + SIGNATURE_RECORD *CurrentSig; + SIGNATURE_RECORD *TempSig; + STATUS Status; + int Index; + int DupCount; + int Len; + BOOLEAN Same; + UINT32 GuidSum; + INT8 *SymName; + + Status = STATUS_SUCCESS; + + // + // If we're checking guids..... + // + if (gOptions.CheckGuids) { + // + // If -p option, print all guids found + // + if (gOptions.PrintFound) { + CurrentFile = gGuidList; + while (CurrentFile != NULL) { + fprintf ( + stdout, + "GUID: 0x%08X 0x%04X 0x%04X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X %s\n", + (UINT32) CurrentFile->Guid.Data1, + (UINT32) CurrentFile->Guid.Data2, + (UINT32) CurrentFile->Guid.Data3, + (UINT32) CurrentFile->Guid.Data4[0], + (UINT32) CurrentFile->Guid.Data4[1], + (UINT32) CurrentFile->Guid.Data4[2], + (UINT32) CurrentFile->Guid.Data4[3], + (UINT32) CurrentFile->Guid.Data4[4], + (UINT32) CurrentFile->Guid.Data4[5], + (UINT32) CurrentFile->Guid.Data4[6], + (UINT32) CurrentFile->Guid.Data4[7], + CurrentFile->FileName + ); + CurrentFile = CurrentFile->Next; + } + } + + if (gOptions.GuidXReference) { + CurrentFile = gGuidList; + while (CurrentFile != NULL) { + // + // If no symbol name, print FileName + // + SymName = CurrentFile->SymName; + if (SymName == NULL) { + // + // Assume file name will not be NULL and strlen > 0 + // + SymName = CurrentFile->FileName + strlen (CurrentFile->FileName) - 1; + while ((*SymName != '\\') && (SymName > CurrentFile->FileName)) SymName --; + if (*SymName == '\\') SymName ++; + } + + fprintf ( + stdout, + "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X %s\n", + (UINT32) CurrentFile->Guid.Data1, + (UINT32) CurrentFile->Guid.Data2, + (UINT32) CurrentFile->Guid.Data3, + (UINT32) CurrentFile->Guid.Data4[0], + (UINT32) CurrentFile->Guid.Data4[1], + (UINT32) CurrentFile->Guid.Data4[2], + (UINT32) CurrentFile->Guid.Data4[3], + (UINT32) CurrentFile->Guid.Data4[4], + (UINT32) CurrentFile->Guid.Data4[5], + (UINT32) CurrentFile->Guid.Data4[6], + (UINT32) CurrentFile->Guid.Data4[7], + SymName + ); + CurrentFile = CurrentFile->Next; + } + } + // + // Now go through all guids and report duplicates. + // + CurrentFile = gGuidList; + while (CurrentFile != NULL) { + DupCount = 0; + TempFile = CurrentFile->Next; + while (TempFile) { + // + // Compare the guids + // + if ((CurrentFile->Guid.Data1 == TempFile->Guid.Data1) && + (CurrentFile->Guid.Data2 == TempFile->Guid.Data2) && + (CurrentFile->Guid.Data3 == TempFile->Guid.Data3) + ) { + // + // OR in all the guid bytes so we can ignore NULL-guid definitions. + // + GuidSum = CurrentFile->Guid.Data1 | CurrentFile->Guid.Data2 | CurrentFile->Guid.Data3; + Same = TRUE; + for (Index = 0; Index < 8; Index++) { + GuidSum |= CurrentFile->Guid.Data4[Index]; + if (CurrentFile->Guid.Data4[Index] != TempFile->Guid.Data4[Index]) { + Same = FALSE; + break; + } + } + // + // If they're the same, and the guid was non-zero, print a message. + // + if (Same && GuidSum) { + if (DupCount == 0) { + Error (NULL, 0, 0, "duplicate GUIDS found", NULL); + fprintf (stdout, " FILE1: %s\n", CurrentFile->FileName); + } + + DupCount++; + fprintf (stdout, " FILE%d: %s\n", DupCount + 1, TempFile->FileName); + // + // Flag it as reported so we don't report it again if there's three or more + // + TempFile->Reported = TRUE; + } + } + // + // Next one + // + TempFile = TempFile->Next; + } + // + // Print the guid if we found duplicates + // + if (DupCount) { + fprintf ( + stdout, + " GUID: 0x%08X 0x%04X 0x%04X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X\n", + (UINT32) CurrentFile->Guid.Data1, + (UINT32) CurrentFile->Guid.Data2, + (UINT32) CurrentFile->Guid.Data3, + (UINT32) CurrentFile->Guid.Data4[0], + (UINT32) CurrentFile->Guid.Data4[1], + (UINT32) CurrentFile->Guid.Data4[2], + (UINT32) CurrentFile->Guid.Data4[3], + (UINT32) CurrentFile->Guid.Data4[4], + (UINT32) CurrentFile->Guid.Data4[5], + (UINT32) CurrentFile->Guid.Data4[6], + (UINT32) CurrentFile->Guid.Data4[7] + ); + // + // return STATUS_ERROR; + // + } + // + // Find the next one that hasn't been reported + // + do { + CurrentFile = CurrentFile->Next; + } while ((CurrentFile != NULL) && (CurrentFile->Reported)); + } + } + + if (gOptions.CheckSignatures) { + // + // Print ones found if specified + // + if (gOptions.PrintFound) { + CurrentSig = gSignatureList; + while (CurrentSig != NULL) { + Len = CurrentSig->Signature.DataLen; + for (Index = 0; Index < Len; Index++) { + fprintf (stdout, "%c", CurrentSig->Signature.Data[Index]); + } + + fprintf (stdout, " %s\n", CurrentSig->FileName); + CurrentSig = CurrentSig->Next; + } + } + + CurrentSig = gSignatureList; + while (CurrentSig != NULL) { + DupCount = 0; + TempSig = CurrentSig->Next; + Len = CurrentSig->Signature.DataLen; + while (TempSig) { + // + // Check for same length, then do string compare + // + if (Len == TempSig->Signature.DataLen) { + if (strncmp (CurrentSig->Signature.Data, TempSig->Signature.Data, Len) == 0) { + // + // Print header message if first failure for this sig + // + if (DupCount == 0) { + Error (NULL, 0, 0, "duplicate signatures found", NULL); + fprintf (stdout, " FILE1: %s\n", CurrentSig->FileName); + } + + DupCount++; + fprintf (stdout, " FILE%d: %s\n", DupCount + 1, TempSig->FileName); + TempSig->Reported = TRUE; + } + } + + TempSig = TempSig->Next; + } + + if (DupCount) { + fprintf (stdout, " SIG: "); + for (Index = 0; Index < Len; Index++) { + fprintf (stdout, "%c", CurrentSig->Signature.Data[Index]); + } + + fprintf (stdout, "\n"); + } + // + // On to the next one that hasn't been reported + // + do { + CurrentSig = CurrentSig->Next; + } while ((CurrentSig != NULL) && (CurrentSig->Reported)); + } + } + + return Status; +} + +static +VOID +FreeOptions ( + VOID + ) +/*++ + +Routine Description: + Free up any memory we allocated when processing command-line options. + +Arguments: + None. + +Returns: + NA + +Notes: + We don't free up the ->Str fields because we did not allocate them. + Instead, we just set the pointer to point to the actual parameter + from the command line. + +--*/ +{ + STRING_LIST *Ptr; + while (gOptions.ExcludeDirs != NULL) { + Ptr = gOptions.ExcludeDirs->Next; + // + // free (gOptions.ExcludeDirs->Str); + // + free (gOptions.ExcludeDirs); + gOptions.ExcludeDirs = Ptr; + } + + while (gOptions.ExcludeSubDirs != NULL) { + Ptr = gOptions.ExcludeSubDirs->Next; + // + // free (gOptions.ExcludeSubDirs->Str); + // + free (gOptions.ExcludeSubDirs); + gOptions.ExcludeSubDirs = Ptr; + } + + while (gOptions.ExcludeExtensions != NULL) { + Ptr = gOptions.ExcludeExtensions->Next; + // + // free (gOptions.ExcludeExtensions->Str); + // + free (gOptions.ExcludeExtensions); + gOptions.ExcludeExtensions = Ptr; + } + + while (gOptions.ExcludeFiles != NULL) { + Ptr = gOptions.ExcludeFiles->Next; + // + // free (gOptions.ExcludeFiles->Str); + // + free (gOptions.ExcludeFiles); + gOptions.ExcludeFiles = Ptr; + } +} +// +// Given an array of 32-bit data, validate the data for the given number of +// guid data. For example, it might have been scanned as 16 bytes of data, or +// 11 fields of data. +// +static +BOOLEAN +CheckGuidData ( + UINT32 *Data, + UINT32 DataCount + ) +{ + UINT32 Index; + + if (DataCount == 16) { + for (Index = 0; Index < 16; Index++) { + if (Data[Index] &~0xFF) { + return FALSE; + } + } + + return TRUE; + } else if (DataCount == 11) { + // + // Data[0] never out of range (32-bit) + // + if ((Data[1] | Data[2]) &~0xFFFF) { + // + // Error ("Out of range value for GUID data word(s) [1] and/or [2]"); + // + return FALSE; + } + + for (Index = 0; Index < 8; Index++) { + if (Data[Index + 3] &~0xFF) { + // + // Error ("Out of range value for GUID data byte(s) [4] - [11]"); + // + return FALSE; + } + } + + return TRUE; + } + + return FALSE; +} + +static +VOID +ConcatenateLines ( + FILE *Fptr, + INT8 *Line, + UINT32 Len + ) +{ + UINT32 LineLen; + BOOLEAN NeedCheck; + + NeedCheck = TRUE; + while (NeedCheck) { + LineLen = strlen (Line); + if ((Line[LineLen - 1] == '\n') && (Line[LineLen - 2] == '\\')) { + Line[LineLen - 2] = '\0'; + fgets (Line + LineLen - 2, Len - LineLen, Fptr); + } else if (Line[LineLen - 1] == '\\') { + Line[LineLen - 1] = '\0'; + fgets (Line + LineLen - 1, Len - LineLen, Fptr); + } else { + NeedCheck = FALSE; + } + } +} \ No newline at end of file diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/GuidList.c b/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/GuidList.c new file mode 100644 index 0000000000..83ca51d353 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/GuidList.c @@ -0,0 +1,188 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + GuidList.c + +Abstract: + + Utility to create a GUID-to-name listing file that can + be used by other utilities. Basic operation is to take the + table of name+GUIDs that we have compiled into this utility, + and create a text file that can be parsed by other utilities + to do replacement of "name" with "GUID". + +Notes: + To add a new GUID to this database: + 1. Add a "#include EFI_GUID_DEFINITION(name)" statement below + 2. Modify the mGuidList[] array below to add the new GUID name + + The only issue that may come up is that, if the source GUID file + is not in the standard GUID directory, then this utility won't + compile because the #include fails. In this case you'd need + to define a new macro (if it's in a standard place) or modify + this utility's makefile to add the path to your new .h file. + +--*/ + +#include +#include +#include +#include + +#include "Tiano.h" +#include "EfiUtilityMsgs.h" + +#include EFI_GUID_DEFINITION (Apriori) +#include EFI_GUID_DEFINITION (AcpiTableStorage) +#include EFI_GUID_DEFINITION (Bmp) +#include EFI_GUID_DEFINITION (AcpiTableStorage) +#include EFI_GUID_DEFINITION (PeiApriori) + + +#define GUID_XREF(varname, guid) { \ + #varname, #guid, guid \ + } + +#define NULL_GUID \ + { \ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 \ + } + +typedef struct { + INT8 *VariableName; + INT8 *DefineName; + EFI_GUID Guid; +} GUID_LIST; + +// +// This is our table of all GUIDs we want to print out to create +// a GUID-to-name cross reference. +// Use the #defined name from the GUID definition's source .h file. +// +static GUID_LIST mGuidList[] = { + GUID_XREF(gEfiPeiAprioriGuid, EFI_PEI_APRIORI_FILE_NAME_GUID), + GUID_XREF(gAprioriGuid, EFI_APRIORI_GUID), + GUID_XREF(gEfiDefaultBmpLogoGuid, EFI_DEFAULT_BMP_LOGO_GUID), + GUID_XREF(gEfiAcpiTableStorageGuid, EFI_ACPI_TABLE_STORAGE_GUID), + // + // Terminator + // + { + NULL, + NULL, + NULL_GUID + } +}; + +void +PrintGuidText ( + FILE *OutFptr, + INT8 *VariableName, + INT8 *DefineName, + EFI_GUID *Guid + ); + +int +CreateGuidList ( + INT8 *OutFileName + ) +/*++ + +Routine Description: + Print our GUID/name list to the specified output file. + +Arguments: + OutFileName - name of the output file to write our results to. + +Returns: + 0 if successful + nonzero otherwise + +--*/ +{ + FILE *OutFptr; + int Index; + + // + // Open output file for writing. If the name is NULL, then write to stdout + // + if (OutFileName != NULL) { + OutFptr = fopen (OutFileName, "w"); + if (OutFptr == NULL) { + Error (NULL, 0, 0, OutFileName, "failed to open output file for writing"); + return STATUS_ERROR; + } + } else { + OutFptr = stdout; + } + + for (Index = 0; mGuidList[Index].VariableName != NULL; Index++) { + PrintGuidText (OutFptr, mGuidList[Index].VariableName, mGuidList[Index].DefineName, &mGuidList[Index].Guid); + } + // + // Close the output file if they specified one. + // + if (OutFileName != NULL) { + fclose (OutFptr); + } + + return STATUS_SUCCESS; +} + +void +PrintGuidText ( + FILE *OutFptr, + INT8 *VariableName, + INT8 *DefineName, + EFI_GUID *Guid + ) +/*++ + +Routine Description: + Print a GUID/name combo in INF-style format + + guid-guid-guid-guid DEFINE_NAME gName + +Arguments: + OutFptr - file pointer to which to write the output + VariableName - the GUID variable's name + DefineName - the name used in the #define + Guid - pointer to the GUID value + +Returns: + NA + +--*/ +{ + if (OutFptr == NULL) { + OutFptr = stdout; + } + + fprintf ( + OutFptr, + "%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X %s %s\n", + 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], + DefineName, + VariableName + ); +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/Makefile new file mode 100644 index 0000000000..5aeddd8cad --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/Makefile @@ -0,0 +1,96 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Makefile +# +# Abstract: +# +# makefile for building the GUID check utility. +# +#--*/ + +# +# Make sure environmental variable EDK_SOURCE is set +# +!IFNDEF EDK_SOURCE +!ERROR EDK_SOURCE environmental variable not set +!ENDIF + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Target specific information +# + +TARGET_NAME = GuidChk +TARGET_SRC_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\GuidChk.exe + +#LIBS = $(LIBS) "$(EDK_TOOLS_OUTPUT)\Common.lib" + +# +# Build targets +# +all: $(TARGET_EXE) + +INC_DEPS = $(TARGET_SRC_DIR)\FileSearch.h $(INC_DEPS) +#INC_DEPS = $(TARGET_SRC_DIR)\CommonUtils.h $(INC_DEPS) +#INC_DEPS = $(TARGET_SRC_DIR)\UtilsMsgs.h $(INC_DEPS) + +OBJECTS = $(EDK_TOOLS_OUTPUT)\GuidChk.obj \ + $(EDK_TOOLS_OUTPUT)\FileSearch.obj \ + $(EDK_TOOLS_OUTPUT)\GuidList.obj \ + $(EDK_TOOLS_OUTPUT)\UtilsMsgs.obj +# +# Compile each source file +# +$(EDK_TOOLS_OUTPUT)\GuidChk.obj : $(TARGET_SRC_DIR)\GuidChk.c $(INC_DEPS) + $(CC) $(C_FLAGS) $(INC) $(TARGET_SRC_DIR)\GuidChk.c /Fo$@ + +$(EDK_TOOLS_OUTPUT)\FileSearch.obj : $(TARGET_SRC_DIR)\FileSearch.c $(INC_DEPS) + $(CC) $(C_FLAGS) $(INC) $(TARGET_SRC_DIR)\FileSearch.c /Fo$@ + +$(EDK_TOOLS_OUTPUT)\GuidList.obj : $(TARGET_SRC_DIR)\GuidList.c $(INC_DEPS) + $(CC) $(C_FLAGS) $(INC) $(TARGET_SRC_DIR)\GuidList.c /Fo$@ + +$(EDK_TOOLS_OUTPUT)\UtilsMsgs.obj : $(TARGET_SRC_DIR)\UtilsMsgs.c $(INC_DEPS) + $(CC) $(C_FLAGS) $(INC) $(TARGET_SRC_DIR)\UtilsMsgs.c /Fo$@ + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE) : $(OBJECTS) + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL + @if exist $(EDK_TOOLS_OUTPUT)\FileSearch.* del $(EDK_TOOLS_OUTPUT)\FileSearch.* > NUL diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/UtilsMsgs.c b/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/UtilsMsgs.c new file mode 100644 index 0000000000..2abe621536 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/UtilsMsgs.c @@ -0,0 +1,489 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + UtilsMsgs.c + +Abstract: + + EFI tools utility functions to display warning, error, and informational + messages. + +--*/ + +#include +#include +#include +#include + +#include "Tiano.h" +#include "EfiUtilityMsgs.h" + +#define MAX_LINE_LEN 200 + +// +// Declare module globals for keeping track of the the utility's +// name and other settings. +// +static STATUS mStatus = STATUS_SUCCESS; +static INT8 mUtilityName[50] = { 0 }; +static INT8 *mSourceFileName = NULL; +static UINT32 mSourceFileLineNum = 0; +static UINT32 mErrorCount = 0; +static UINT32 mWarningCount = 0; +static UINT32 mDebugMsgMask = 0; + +static +void +PrintMessage ( + INT8 *Type, + INT8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + INT8 *Text, + INT8 *MsgFmt, + va_list List + ); + +void +Error ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + INT8 *Text, + INT8 *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 + utilty 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; + mErrorCount++; + va_start (List, MsgFmt); + PrintMessage ("error", FileName, LineNumber, MessageCode, Text, MsgFmt, List); + va_end (List); + // + // Set status accordingly + // + if (mStatus < STATUS_ERROR) { + mStatus = STATUS_ERROR; + } +} + +void +ParserError ( + UINT32 MessageCode, + INT8 *Text, + INT8 *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; + mErrorCount++; + va_start (List, MsgFmt); + PrintMessage ("error", mSourceFileName, mSourceFileLineNum, MessageCode, Text, MsgFmt, List); + va_end (List); + // + // Set status accordingly + // + if (mStatus < STATUS_ERROR) { + mStatus = STATUS_ERROR; + } +} + +void +ParserWarning ( + UINT32 ErrorCode, + INT8 *OffendingText, + INT8 *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; + mWarningCount++; + va_start (List, MsgFmt); + PrintMessage ("warning", mSourceFileName, mSourceFileLineNum, ErrorCode, OffendingText, MsgFmt, List); + va_end (List); + // + // Set status accordingly + // + if (mStatus < STATUS_WARNING) { + mStatus = STATUS_WARNING; + } +} + +void +Warning ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + INT8 *Text, + INT8 *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; + mWarningCount++; + va_start (List, MsgFmt); + PrintMessage ("warning", FileName, LineNumber, MessageCode, Text, MsgFmt, List); + va_end (List); + // + // Set status accordingly + // + if (mStatus < STATUS_WARNING) { + mStatus = STATUS_WARNING; + } +} + +void +DebugMsg ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 MsgMask, + INT8 *Text, + INT8 *MsgFmt, + ... + ) +/*++ + +Routine Description: + Print a warning 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) + + MsgMask - an application-specific bitmask that, in combination with mDebugMsgMask, + determines if the debug message gets printed. + + 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 mask is not applicable, then do nothing. + // + if ((MsgMask != 0) && ((mDebugMsgMask & MsgMask) == 0)) { + return ; + } + + va_start (List, MsgFmt); + PrintMessage ("debug", FileName, LineNumber, 0, Text, MsgFmt, List); + va_end (List); +} + +static +void +PrintMessage ( + INT8 *Type, + INT8 *FileName, + UINT32 LineNumber, + UINT32 MessageCode, + INT8 *Text, + INT8 *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 preceed 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 - Variable function parameter 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 + +--*/ +{ + INT8 Line[MAX_LINE_LEN]; + INT8 Line2[MAX_LINE_LEN]; + INT8 *Cptr; + // + // 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 if (mUtilityName[0] != 0) { + Cptr = mUtilityName; + } else { + Cptr = "Unknown utility"; + } + + strcpy (Line, Cptr); + if (LineNumber != 0) { + sprintf (Line2, "(%d)", LineNumber); + strcat (Line, Line2); + } + // + // Have to print an error code or Visual Studio won't find the + // message for you. It has to be decimal digits too. + // + sprintf (Line2, " : %s %c%04d", Type, toupper (Type[0]), MessageCode); + strcat (Line, Line2); + fprintf (stdout, "%s", Line); + // + // If offending text was provided, then print it + // + if (Text != NULL) { + fprintf (stdout, ": %s ", Text); + } + // + // Print formatted message if provided + // + if (MsgFmt != NULL) { + vsprintf (Line2, MsgFmt, List); + fprintf (stdout, ": %s", Line2); + } + + fprintf (stdout, "\n"); +} + +void +ParserSetPosition ( + INT8 *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 ( + INT8 *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 messags. + +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; + return ; + } else { + strcpy (mUtilityName, UtilityName); + } + } 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; +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/UtilsMsgs.h b/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/UtilsMsgs.h new file mode 100644 index 0000000000..5f6c7010b4 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/UtilsMsgs.h @@ -0,0 +1,106 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + UtilsMsgs.h + +Abstract: + + Prototypes for the EFI tools utility functions. + +--*/ + +#ifndef _UTILS_MESSAGES_H_ +#define _UTILS_MESSAGES_H_ + +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 ( + INT8 *ProgramName + ) +; + +void +Error ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 ErrorCode, + INT8 *OffendingText, + INT8 *MsgFmt, + ... + ) +; + +void +Warning ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 ErrorCode, + INT8 *OffendingText, + INT8 *MsgFmt, + ... + ) +; + +void +DebugMsg ( + INT8 *FileName, + UINT32 LineNumber, + UINT32 MsgLevel, + INT8 *OffendingText, + INT8 *MsgFmt, + ... + ) +; + +void +SetDebugMsgMask ( + UINT32 MsgMask + ) +; + +void +ParserSetPosition ( + INT8 *SourceFileName, + UINT32 LineNum + ) +; + +void +ParserError ( + UINT32 ErrorCode, + INT8 *OffendingText, + INT8 *MsgFmt, + ... + ) +; + +void +ParserWarning ( + UINT32 ErrorCode, + INT8 *OffendingText, + INT8 *MsgFmt, + ... + ) +; + +#endif diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/MakeDeps/MakeDeps.c b/EdkCompatibilityPkg/Sample/Tools/Source/MakeDeps/MakeDeps.c new file mode 100644 index 0000000000..bf086e64a4 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/MakeDeps/MakeDeps.c @@ -0,0 +1,1316 @@ +/*++ + +Copyright (c) 2004 - 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + MakeDeps.c + +Abstract: + + Recursively scan source files to find include files and emit them to + create dependency lists. + +--*/ + +#include +#include +#include +#include + +#include "Tiano.h" +#include "EfiUtilityMsgs.h" + +// +// Structure to maintain a linked list of strings +// +typedef struct _STRING_LIST { + struct _STRING_LIST *Next; + char *Str; +} STRING_LIST; + +#define UTILITY_NAME "MakeDeps" + +#define MAX_LINE_LEN 2048 +#define MAX_PATH 2048 +#define START_NEST_DEPTH 1 +#define MAX_NEST_DEPTH 1000 // just in case we get in an endless loop. +// +// Define the relative paths used by the special #include macros +// +#define PROTOCOL_DIR_PATH "Protocol\\" +#define GUID_DIR_PATH "Guid\\" +#define ARCH_PROTOCOL_DIR_PATH "ArchProtocol\\" +#define PPI_PROTOCOL_DIR_PATH "Ppi\\" + +// +// Use this structure to keep track of all the special #include forms +// +typedef struct { + INT8 *IncludeMacroName; + INT8 *PathName; +} INCLUDE_MACRO_CONVERSION; + +// +// This data is used to convert #include macros like: +// #include EFI_PROTOCOL_DEFINITION(xxx) +// into +// #include Protocol/xxx/xxx.h +// +static const INCLUDE_MACRO_CONVERSION mMacroConversion[] = { + "EFI_PROTOCOL_DEFINITION", + PROTOCOL_DIR_PATH, + "EFI_GUID_DEFINITION", + GUID_DIR_PATH, + "EFI_ARCH_PROTOCOL_DEFINITION", + ARCH_PROTOCOL_DIR_PATH, + "EFI_PROTOCOL_PRODUCER", + PROTOCOL_DIR_PATH, + "EFI_PROTOCOL_CONSUMER", + PROTOCOL_DIR_PATH, + "EFI_PROTOCOL_DEPENDENCY", + PROTOCOL_DIR_PATH, + "EFI_ARCH_PROTOCOL_PRODUCER", + ARCH_PROTOCOL_DIR_PATH, + "EFI_ARCH_PROTOCOL_CONSUMER", + ARCH_PROTOCOL_DIR_PATH, + "EFI_ARCH_PROTOCOL_DEPENDENCY", + ARCH_PROTOCOL_DIR_PATH, + "EFI_PPI_DEFINITION", + PPI_PROTOCOL_DIR_PATH, + "EFI_PPI_PRODUCER", + PPI_PROTOCOL_DIR_PATH, + "EFI_PPI_CONSUMER", + PPI_PROTOCOL_DIR_PATH, + "EFI_PPI_DEPENDENCY", + PPI_PROTOCOL_DIR_PATH, + NULL, + NULL +}; + +typedef struct _SYMBOL { + struct _SYMBOL *Next; + INT8 *Name; + INT8 *Value; +} SYMBOL; + +// +// Here's all our globals. We need a linked list of include paths, a linked +// list of source files, a linked list of subdirectories (appended to each +// include path when searching), and flags to keep track of command-line options. +// +static struct { + STRING_LIST *IncludePaths; // all include paths to search + STRING_LIST *SourceFiles; // all source files to parse + STRING_LIST *SubDirs; // appended to each include path when searching + SYMBOL *SymbolTable; // for replacement strings + FILE *OutFptr; // output dependencies to this file + BOOLEAN Verbose; // for more detailed output + BOOLEAN IgnoreNotFound; // no warnings if files not found + BOOLEAN QuietMode; // -q - don't print missing file warnings + BOOLEAN NoSystem; // don't process #include files + BOOLEAN NeverFail; // always return success + BOOLEAN NoDupes; // to not list duplicate dependency files (for timing purposes) + BOOLEAN UseSumDeps; // use summary dependency files if found + BOOLEAN IsAsm; // The SourceFiles are assembler files + INT8 TargetFileName[MAX_PATH]; // target object filename + INT8 SumDepsPath[MAX_PATH]; // path to summary files + INT8 *OutFileName; // -o option +} mGlobals; + +static +STATUS +ProcessFile ( + INT8 *TargetFileName, + INT8 *FileName, + UINT32 NestDepth, + STRING_LIST *ProcessedFiles + ); + +static +FILE * +FindFile ( + INT8 *FileName, + UINT32 FileNameLen + ); + +static +void +PrintDependency ( + INT8 *Target, + INT8 *DependentFile + ); + +static +void +ReplaceSymbols ( + INT8 *Str, + UINT32 StrSize + ); + +static +STATUS +ProcessArgs ( + int Argc, + char *Argv[] + ); + +static +void +Usage ( + VOID + ); + +static +void +FreeLists ( + VOID + ); + +int +main ( + int Argc, + char *Argv[] + ) +/*++ + +Routine Description: + + Call the routine to parse the command-line options, then process each file + to build dependencies. + +Arguments: + + Argc - Standard C main() argc. + Argv - Standard C main() argv. + +Returns: + + 0 if successful + nonzero otherwise + +--*/ +{ + STRING_LIST *File; + STRING_LIST ProcessedFiles; + STRING_LIST *TempList; + STATUS Status; + INT8 *Cptr; + INT8 TargetFileName[MAX_PATH]; + + SetUtilityName (UTILITY_NAME); + // + // Process the command-line arguments + // + Status = ProcessArgs (Argc, Argv); + if (Status != STATUS_SUCCESS) { + return STATUS_ERROR; + } + // + // Go through the list of source files and process each. + // + memset (&ProcessedFiles, 0, sizeof (STRING_LIST)); + File = mGlobals.SourceFiles; + while (File != NULL) { + // + // Clear out our list of processed files + // + TempList = ProcessedFiles.Next; + while (ProcessedFiles.Next != NULL) { + TempList = ProcessedFiles.Next->Next; + free (ProcessedFiles.Next->Str); + free (ProcessedFiles.Next); + ProcessedFiles.Next = TempList; + } + // + // Replace filename extension with ".obj" if they did not + // specifically specify the target file + // + if (mGlobals.TargetFileName[0] == 0) { + strcpy (TargetFileName, File->Str); + // + // Find the .extension + // + for (Cptr = TargetFileName + strlen (TargetFileName) - 1; + (*Cptr != '\\') && (Cptr > TargetFileName) && (*Cptr != '.'); + Cptr-- + ) + ; + if (Cptr == TargetFileName) { + Error (NULL, 0, 0, File->Str, "could not locate extension in filename"); + goto Finish; + } + // + // Tack on the ".obj" + // + strcpy (Cptr, ".obj"); + } else { + // + // Copy the target filename they specified + // + strcpy (TargetFileName, mGlobals.TargetFileName); + } + + Status = ProcessFile (TargetFileName, File->Str, START_NEST_DEPTH, &ProcessedFiles); + if (Status != STATUS_SUCCESS) { + goto Finish; + } + + File = File->Next; + } + +Finish: + // + // Free up memory + // + FreeLists (); + // + // Free up our processed files list + // + TempList = ProcessedFiles.Next; + while (ProcessedFiles.Next != NULL) { + TempList = ProcessedFiles.Next->Next; + free (ProcessedFiles.Next->Str); + free (ProcessedFiles.Next); + ProcessedFiles.Next = TempList; + } + // + // Close our output file + // + if ((mGlobals.OutFptr != stdout) && (mGlobals.OutFptr != NULL)) { + fclose (mGlobals.OutFptr); + } + + if (mGlobals.NeverFail) { + return STATUS_SUCCESS; + } + // + // If any errors, then delete our output so that it will get created + // again on a rebuild. + // + if ((GetUtilityStatus () == STATUS_ERROR) && (mGlobals.OutFileName != NULL)) { + remove (mGlobals.OutFileName); + } + + return GetUtilityStatus (); +} + +static +STATUS +ProcessFile ( + INT8 *TargetFileName, + INT8 *FileName, + UINT32 NestDepth, + STRING_LIST *ProcessedFiles + ) +/*++ + +Routine Description: + + Given a source file name, open the file and parse all #include lines. + +Arguments: + + TargetFileName - name of the usually .obj target + FileName - name of the file to process + NestDepth - how deep we're nested in includes + ProcessedFiles - list of processed files. + +Returns: + + standard status. + +--*/ +{ + FILE *Fptr; + INT8 Line[MAX_LINE_LEN]; + INT8 *Cptr; + INT8 *EndPtr; + INT8 *SaveCptr; + INT8 EndChar; + INT8 FileNameCopy[MAX_PATH]; + INT8 MacroIncludeFileName[MAX_LINE_LEN]; + INT8 SumDepsFile[MAX_PATH]; + STATUS Status; + UINT32 Index; + UINT32 LineNum; + STRING_LIST *ListPtr; + + Status = STATUS_SUCCESS; + Fptr = NULL; + // + // Print the file being processed. Indent so you can tell the include nesting + // depth. + // + if (mGlobals.Verbose) { + fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', FileName); + } + // + // If we're using summary dependency files, and a matching .dep file is + // found for this file, then just emit the summary dependency file as + // a dependency and return. + // + if (mGlobals.UseSumDeps) { + strcpy (SumDepsFile, mGlobals.SumDepsPath); + strcat (SumDepsFile, FileName); + for (Cptr = SumDepsFile + strlen (SumDepsFile) - 1; + (*Cptr != '\\') && (Cptr > SumDepsFile) && (*Cptr != '.'); + Cptr-- + ) + ; + if (*Cptr == '.') { + strcpy (Cptr, ".dep"); + } else { + strcat (SumDepsFile, ".dep"); + } + // + // See if the summary dep file exists. Could use _stat() function, but + // it's less portable. + // + if ((Fptr = fopen (SumDepsFile, "r")) != NULL) { + PrintDependency (TargetFileName, SumDepsFile); + fclose (Fptr); + return STATUS_SUCCESS; + } + } + // + // If we're not doing duplicates, and we've already seen this filename, + // then return + // + if (mGlobals.NoDupes) { + for (ListPtr = ProcessedFiles->Next; ListPtr != NULL; ListPtr = ListPtr->Next) { + if (_stricmp (FileName, ListPtr->Str) == 0) { + break; + } + } + // + // If we found a match, we're done. If we didn't, create a new element + // and add it to the list. + // + if (ListPtr != NULL) { + // + // Print a message if verbose mode + // + if (mGlobals.Verbose) { + DebugMsg (NULL, 0, 0, FileName, "duplicate include -- not processed again"); + } + + return STATUS_SUCCESS; + } + + ListPtr = malloc (sizeof (STRING_LIST)); + ListPtr->Str = malloc (strlen (FileName) + 1); + strcpy (ListPtr->Str, FileName); + ListPtr->Next = ProcessedFiles->Next; + ProcessedFiles->Next = ListPtr; + } + + // + // Make sure we didn't exceed our maximum nesting depth + // + if (NestDepth > MAX_NEST_DEPTH) { + Error (NULL, 0, 0, FileName, "max nesting depth exceeded on file"); + goto Finish; + } + // + // Make a local copy of the filename. Then we can manipulate it + // if we have to. + // + strcpy (FileNameCopy, FileName); + // + // Try to open the file locally + // + if ((Fptr = fopen (FileNameCopy, "r")) == NULL) { + // + // Try to find it among the paths. + // + Fptr = FindFile (FileNameCopy, sizeof (FileNameCopy)); + if (Fptr == NULL) { + // + // If this is not the top-level file, and the command-line argument + // said to ignore missing files, then return ok + // + if (NestDepth != START_NEST_DEPTH) { + if (mGlobals.IgnoreNotFound) { + if (!mGlobals.QuietMode) { + DebugMsg (NULL, 0, 0, FileNameCopy, "could not find file"); + } + + return STATUS_SUCCESS; + } else { + Error (NULL, 0, 0, FileNameCopy, "could not find file"); + return STATUS_ERROR; + } + } else { + // + // Top-level (first) file. Emit an error. + // + Error (NULL, 0, 0, FileNameCopy, "could not find file"); + return STATUS_ERROR; + } + } + } + // + // Print the dependency, with string substitution + // + PrintDependency (TargetFileName, FileNameCopy); + + // + // Now read in lines and find all #include lines. Allow them to indent, and + // to put spaces between the # and include. + // + LineNum = 0; + while ((fgets (Line, sizeof (Line), Fptr) != NULL) && (Status == STATUS_SUCCESS)) { + LineNum++; + Cptr = Line; + // + // Skip preceeding spaces on the line + // + while (*Cptr && (isspace (*Cptr))) { + Cptr++; + } + // + // Check for # character, there is no # for asm + // + if ((*Cptr == '#') || (mGlobals.IsAsm)) { + if (*Cptr == '#') { + Cptr++; + } + + // + // Check for "include", case insensitive for asm + // + while (*Cptr && (isspace (*Cptr))) { + Cptr++; + } + if (((!mGlobals.IsAsm) && (strncmp (Cptr, "include", 7) == 0)) || + (mGlobals.IsAsm && (_strnicmp (Cptr, "include", 7) == 0))) { + // + // Skip over "include" and move on to filename as "file" or or file for asm + // + Cptr += 7; + while (*Cptr && (isspace (*Cptr))) { + Cptr++; + } + + if (*Cptr == '<') { + EndChar = '>'; + } else if (*Cptr == '"') { + EndChar = '"'; + } else if (mGlobals.IsAsm) { + // + // Handle include file for asm + // Set EndChar to null so we fall through on processing below. + // + EndChar = 0; + + // + // Look for the end of include file name + // + EndPtr = Cptr; + while (*EndPtr && (!isspace (*EndPtr))) { + EndPtr++; + } + + // + // Null terminate the filename and try to process it. + // + *EndPtr = 0; + Status = ProcessFile (TargetFileName, Cptr, NestDepth + 1, ProcessedFiles); + } else { + // + // Handle special #include MACRO_NAME(file) + // Set EndChar to null so we fall through on processing below. + // + EndChar = 0; + // + // Look for all the special include macros and convert accordingly. + // + for (Index = 0; mMacroConversion[Index].IncludeMacroName != NULL; Index++) { + // + // Save the start of the string in case some macros are substrings + // of others. + // + SaveCptr = Cptr; + if (strncmp ( + Cptr, + mMacroConversion[Index].IncludeMacroName, + strlen (mMacroConversion[Index].IncludeMacroName) + ) == 0) { + // + // Skip over the macro name + // + Cptr += strlen (mMacroConversion[Index].IncludeMacroName); + // + // Skip over open parenthesis, blank spaces, then find closing + // parenthesis or blank space + // + while (*Cptr && (isspace (*Cptr))) { + Cptr++; + } + + if (*Cptr == '(') { + Cptr++; + while (*Cptr && (isspace (*Cptr))) { + Cptr++; + } + + EndPtr = Cptr; + while (*EndPtr && !isspace (*EndPtr) && (*EndPtr != ')')) { + EndPtr++; + } + + *EndPtr = 0; + // + // Create the path + // + strcpy (MacroIncludeFileName, mMacroConversion[Index].PathName); + strcat (MacroIncludeFileName, Cptr); + strcat (MacroIncludeFileName, "\\"); + strcat (MacroIncludeFileName, Cptr); + strcat (MacroIncludeFileName, ".h"); + // + // Process immediately, then break out of the outside FOR loop. + // + Status = ProcessFile (TargetFileName, MacroIncludeFileName, NestDepth + 1, ProcessedFiles); + break; + } + } + // + // Restore the start + // + Cptr = SaveCptr; + } + // + // Don't recognize the include line? Ignore it. We assume that the + // file compiles anyway. + // + if (mMacroConversion[Index].IncludeMacroName == NULL) { + // + // Warning (FileNameCopy, LineNum, 0, "could not parse line", NULL); + // Status = STATUS_WARNING; + // + } + } + // + // Process "normal" includes. If the endchar is 0, then the + // file has already been processed. Otherwise look for the + // endchar > or ", and process the include file. + // + if (EndChar != 0) { + Cptr++; + EndPtr = Cptr; + while (*EndPtr && (*EndPtr != EndChar)) { + EndPtr++; + } + + if (*EndPtr == EndChar) { + // + // If we're processing it, do it + // + if ((EndChar != '>') || (!mGlobals.NoSystem)) { + // + // Null terminate the filename and try to process it. + // + *EndPtr = 0; + Status = ProcessFile (TargetFileName, Cptr, NestDepth + 1, ProcessedFiles); + } + } else { + Warning (FileNameCopy, LineNum, 0, "malformed include", "missing closing %c", EndChar); + Status = STATUS_WARNING; + goto Finish; + } + } + } + } + } + +Finish: + // + // Close open files and return status + // + if (Fptr != NULL) { + fclose (Fptr); + } + + return Status; +} + +static +void +PrintDependency ( + INT8 *TargetFileName, + INT8 *DependentFile + ) +/*++ + +Routine Description: + + Given a target (.obj) file name, and a dependent file name, do any string + substitutions (per the command line options) on the file names, then + print the dependency line of form: + + TargetFileName : DependentFile + +Arguments: + + TargetFileName - build target file name + DependentFile - file on which TargetFileName depends + +Returns: + + None + +--*/ +{ + INT8 Str[MAX_PATH]; + + // + // Go through the symbols and do replacements + // + strcpy (Str, TargetFileName); + ReplaceSymbols (Str, sizeof (Str)); + fprintf (mGlobals.OutFptr, "%s : ", Str); + strcpy (Str, DependentFile); + ReplaceSymbols (Str, sizeof (Str)); + fprintf (mGlobals.OutFptr, "%s\n", Str); + // + // Add pseudo target to avoid incremental build failure when the file is deleted + // + fprintf (mGlobals.OutFptr, "%s : \n", Str); +} + +static +void +ReplaceSymbols ( + INT8 *Str, + UINT32 StrSize + ) +{ + SYMBOL *Sym; + INT8 StrCopy[MAX_LINE_LEN]; + INT8 *From; + INT8 *To; + BOOLEAN Replaced; + + // + // Go through the entire string to look for replacement strings at + // every position. + // + From = Str; + To = StrCopy; + while (*From) { + // + // Copy the character + // + *To = *From; + Replaced = FALSE; + // + // Go through each symbol and try to find a string substitution + // + Sym = mGlobals.SymbolTable; + while (Sym != NULL) { + if (_strnicmp (From, Sym->Value, strlen (Sym->Value)) == 0) { + // + // Replace the string, then advance the pointers past the + // replaced strings + // + strcpy (To, Sym->Name); + To += strlen (Sym->Name); + From += strlen (Sym->Value); + Replaced = TRUE; + // + // Break from the while() + // + break; + } else { + Sym = Sym->Next; + } + } + + if (!Replaced) { + From++; + To++; + } + } + // + // Null terminate, and return it + // + *To = 0; + if (strlen (StrCopy) < StrSize) { + strcpy (Str, StrCopy); + } +} +// +// Given a filename, try to find it along the include paths. +// +static +FILE * +FindFile ( + INT8 *FileName, + UINT32 FileNameLen + ) +{ + FILE *Fptr; + STRING_LIST *List; + STRING_LIST *SubDir; + INT8 FullFileName[MAX_PATH * 2]; + + // + // Traverse the list of paths and try to find the file + // + List = mGlobals.IncludePaths; + while (List != NULL) { + // + // Put the path and filename together + // + if (strlen (List->Str) + strlen (FileName) + 1 > sizeof (FullFileName)) { + Error ( + __FILE__, + __LINE__, + 0, + "application error", + "cannot concatenate '%s' + '%s'", + List->Str, + FileName + ); + return NULL; + } + // + // Append the filename to this include path and try to open the file. + // + strcpy (FullFileName, List->Str); + strcat (FullFileName, FileName); + if ((Fptr = fopen (FullFileName, "r")) != NULL) { + // + // Return the file name + // + if (FileNameLen <= strlen (FullFileName)) { + Error (__FILE__, __LINE__, 0, "application error", "internal path name of insufficient length"); + // + // fprintf (stdout, "File length > %d: %s\n", FileNameLen, FullFileName); + // + return NULL; + } + + strcpy (FileName, FullFileName); + return Fptr; + } + // + // Didn't find it there. Now try this directory with every subdirectory + // the user specified on the command line + // + for (SubDir = mGlobals.SubDirs; SubDir != NULL; SubDir = SubDir->Next) { + strcpy (FullFileName, List->Str); + strcat (FullFileName, SubDir->Str); + strcat (FullFileName, FileName); + if ((Fptr = fopen (FullFileName, "r")) != NULL) { + // + // Return the file name + // + if (FileNameLen <= strlen (FullFileName)) { + Error (__FILE__, __LINE__, 0, "application error", "internal path name of insufficient length"); + return NULL; + } + + strcpy (FileName, FullFileName); + return Fptr; + } + } + + List = List->Next; + } + // + // Not found + // + return NULL; +} +// +// Process the command-line arguments +// +static +STATUS +ProcessArgs ( + int Argc, + char *Argv[] + ) +{ + STRING_LIST *NewList; + STRING_LIST *LastIncludePath; + STRING_LIST *LastSourceFile; + SYMBOL *Symbol; + int Index; + // + // Clear our globals + // + memset ((char *) &mGlobals, 0, sizeof (mGlobals)); + mGlobals.NoDupes = TRUE; + // + // Skip program name + // + Argc--; + Argv++; + // + // Initialize locals + // + LastIncludePath = NULL; + LastSourceFile = NULL; + // + // Process until no more args + // + while (Argc) { + // + // -i path add include search path + // + if (_stricmp (Argv[0], "-i") == 0) { + // + // check for one more arg + // + if (Argc > 1) { + // + // Allocate memory for a new list element, fill it in, and + // add it to our list of include paths. Always make sure it + // has a "\" on the end of it. + // + NewList = malloc (sizeof (STRING_LIST)); + if (NewList == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + NewList->Next = NULL; + NewList->Str = malloc (strlen (Argv[1]) + 2); + if (NewList->Str == NULL) { + free (NewList); + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + strcpy (NewList->Str, Argv[1]); + if (NewList->Str[strlen (NewList->Str) - 1] != '\\') { + strcat (NewList->Str, "\\"); + } + // + // Add it to the end of the our list of include paths + // + if (mGlobals.IncludePaths == NULL) { + mGlobals.IncludePaths = NewList; + } else { + LastIncludePath->Next = NewList; + } + + LastIncludePath = NewList; + // + // fprintf (stdout, "Added path: %s\n", NewList->Str); + // + } else { + Error (NULL, 0, 0, Argv[0], "option requires an include path"); + Usage (); + return STATUS_ERROR; + } + + Argc--; + Argv++; + } else if (_stricmp (Argv[0], "-f") == 0) { + // + // Check for one more arg + // + if (Argc > 1) { + // + // Allocate memory for a new list element, fill it in, and + // add it to our list of source files. + // + NewList = malloc (sizeof (STRING_LIST)); + if (NewList == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + NewList->Next = NULL; + // + // Allocate space to replace ".c" with ".obj", plus null termination + // + NewList->Str = malloc (strlen (Argv[1]) + 5); + if (NewList->Str == NULL) { + free (NewList); + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + strcpy (NewList->Str, Argv[1]); + if (mGlobals.SourceFiles == NULL) { + mGlobals.SourceFiles = NewList; + } else { + LastSourceFile->Next = NewList; + } + + LastSourceFile = NewList; + } else { + Error (NULL, 0, 0, Argv[0], "option requires a file name"); + Usage (); + return STATUS_ERROR; + } + // + // The C compiler first looks for #include files in the directory where + // the source file came from. Add the file's source directory to the + // list of include paths. + // + NewList = malloc (sizeof (STRING_LIST)); + if (NewList == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + NewList->Next = NULL; + NewList->Str = malloc (strlen (Argv[1]) + 3); + if (NewList->Str == NULL) { + free (NewList); + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + strcpy (NewList->Str, Argv[1]); + // + // Back up in the source file name to the last backslash and terminate after it. + // + for (Index = strlen (NewList->Str) - 1; (Index > 0) && (NewList->Str[Index] != '\\'); Index--) + ; + if (Index < 0) { + strcpy (NewList->Str, ".\\"); + } else { + NewList->Str[Index + 1] = 0; + } + // + // Add it to the end of the our list of include paths + // + if (mGlobals.IncludePaths == NULL) { + mGlobals.IncludePaths = NewList; + } else { + LastIncludePath->Next = NewList; + } + + if (mGlobals.Verbose) { + fprintf (stdout, "Adding include path: %s\n", NewList->Str); + } + + LastIncludePath = NewList; + Argc--; + Argv++; + } else if (_stricmp (Argv[0], "-s") == 0) { + // + // -s subdir add subdirectory subdir to list of subdirecties to scan. + // Check for one more arg first. + // + if (Argc > 1) { + // + // Allocate memory for a new list element, fill it in, and + // add it to our list of subdirectory include paths. Always + // make sure it has a "\" on the end of it. + // + NewList = malloc (sizeof (STRING_LIST)); + if (NewList == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + NewList->Str = malloc (strlen (Argv[1]) + 2); + if (NewList->Str == NULL) { + free (NewList); + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + strcpy (NewList->Str, Argv[1]); + if (NewList->Str[strlen (NewList->Str) - 1] != '\\') { + strcat (NewList->Str, "\\"); + } + + NewList->Next = mGlobals.SubDirs; + mGlobals.SubDirs = NewList; + } else { + Error (NULL, 0, 0, Argv[0], "option requires a subdirectory name"); + Usage (); + return STATUS_ERROR; + } + + Argc--; + Argv++; + } else if (_stricmp (Argv[0], "-sub") == 0) { + // + // -sub symname symvalue to do string substitution in the output + // + if (Argc > 2) { + // + // Allocate memory for the symbol object + // + Symbol = malloc (sizeof (SYMBOL)); + if (Symbol == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + // + // Allocate memory for the symbol name and value, then save copies + // + Symbol->Name = malloc (strlen (Argv[1]) + 1); + if (Symbol->Name == NULL) { + free (Symbol); + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + strcpy (Symbol->Name, Argv[1]); + Symbol->Value = malloc (strlen (Argv[2]) + 1); + if (Symbol->Value == NULL) { + free (Symbol->Name); + free (Symbol); + Error (__FILE__, __LINE__, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + strcpy (Symbol->Value, Argv[2]); + // + // Add it to the list + // + Symbol->Next = mGlobals.SymbolTable; + mGlobals.SymbolTable = Symbol; + } else { + Error (NULL, 0, 0, Argv[0], "option requires a symbol name and value"); + Usage (); + return STATUS_ERROR; + } + // + // Skip over args + // + Argc -= 2; + Argv += 2; + } else if (_stricmp (Argv[0], "-nosystem") == 0) { + mGlobals.NoSystem = TRUE; + } else if (_stricmp (Argv[0], "-nodupes") == 0) { + mGlobals.NoDupes = TRUE; + } else if (_stricmp (Argv[0], "-nodups") == 0) { + mGlobals.NoDupes = TRUE; + } else if (_stricmp (Argv[0], "-target") == 0) { + // + // -target TargetFileName - Target object file (only one allowed right + // now) is TargetFileName rather than SourceFile.obj + // + if (Argc > 1) { + strcpy (mGlobals.TargetFileName, Argv[1]); + } else { + Error (NULL, 0, 0, Argv[0], "option requires a target file name"); + Usage (); + return STATUS_ERROR; + } + + Argc--; + Argv++; + } else if (_stricmp (Argv[0], "-usesumdeps") == 0) { + // + // -usesumdeps Path - if we find an included file xxx.h, and file + // Path/xxx.dep exists, list Path/xxx.dep as a dependency rather than + // xxx.h and don't parse xxx.h. This allows you to create a dependency + // file for a commonly included file, and have its dependency file updated + // only if its included files are updated. Then anyone else including this + // common include file can simply have a dependency on that file's .dep file + // rather than on all the files included by it. Confusing enough? + // + mGlobals.UseSumDeps = 1; + if (Argc > 1) { + strcpy (mGlobals.SumDepsPath, Argv[1]); + // + // Add slash on end if not there + // + if (mGlobals.SumDepsPath[strlen (mGlobals.SumDepsPath) - 1] != '\\') { + strcat (mGlobals.SumDepsPath, "\\"); + } + } else { + Error (NULL, 0, 0, Argv[0], "option requires path to summary dependency files"); + Usage (); + return STATUS_ERROR; + } + + Argc--; + Argv++; + + } else if (_stricmp (Argv[0], "-o") == 0) { + // + // -o OutputFileName - specify an output filename for dependency list + // check for one more arg + // + if (Argc > 1) { + // + // Try to open the file + // + if ((mGlobals.OutFptr = fopen (Argv[1], "w")) == NULL) { + Error (NULL, 0, 0, Argv[1], "could not open file for writing"); + return STATUS_ERROR; + } + + mGlobals.OutFileName = Argv[1]; + } else { + Error (NULL, 0, 0, Argv[0], "option requires output file name"); + Usage (); + return STATUS_ERROR; + } + + Argc--; + Argv++; + } else if (_stricmp (Argv[0], "-v") == 0) { + mGlobals.Verbose = TRUE; + } else if (_stricmp (Argv[0], "-neverfail") == 0) { + mGlobals.NeverFail = TRUE; + } else if (_stricmp (Argv[0], "-q") == 0) { + mGlobals.QuietMode = TRUE; + } else if (_stricmp (Argv[0], "-ignorenotfound") == 0) { + mGlobals.IgnoreNotFound = TRUE; + } else if (_stricmp (Argv[0], "-asm") == 0) { + mGlobals.IsAsm = TRUE; + } else if ((_stricmp (Argv[0], "-h") == 0) || (strcmp (Argv[0], "-?") == 0)) { + Usage (); + return STATUS_ERROR; + } else { + Error (NULL, 0, 0, Argv[0], "unrecognized option"); + Usage (); + return STATUS_ERROR; + } + + Argc--; + Argv++; + } + // + // Had to specify at least one source file + // + if (mGlobals.SourceFiles == NULL) { + Error (NULL, 0, 0, "must specify one source file name", NULL); + Usage (); + return STATUS_ERROR; + } + // + // Assume output to stdout if not specified + // + if (mGlobals.OutFptr == NULL) { + mGlobals.OutFptr = stdout; + } + + return STATUS_SUCCESS; +} +// +// Free the global string lists we allocated memory for +// +static +void +FreeLists ( + VOID + ) +{ + STRING_LIST *Temp; + SYMBOL *NextSym; + + // + // printf ("Free lists....."); + // + // Traverse the include paths, freeing each + // printf ("freeing include paths\n"); + // + while (mGlobals.IncludePaths != NULL) { + Temp = mGlobals.IncludePaths->Next; + // + // printf ("Freeing include path string '%s' at 0x%X\n", + // mGlobals.IncludePaths->Str, (int)(mGlobals.IncludePaths->Str)); + // + free (mGlobals.IncludePaths->Str); + // + // printf ("Freeing include path object at 0x%X\n", (int)(mGlobals.IncludePaths)); + // + free (mGlobals.IncludePaths); + mGlobals.IncludePaths = Temp; + } + // + // Traverse the source files, freeing each + // + while (mGlobals.SourceFiles != NULL) { + Temp = mGlobals.SourceFiles->Next; + free (mGlobals.SourceFiles->Str); + free (mGlobals.SourceFiles); + mGlobals.SourceFiles = Temp; + } + // + // Traverse the subdirectory list, freeing each + // + while (mGlobals.SubDirs != NULL) { + Temp = mGlobals.SubDirs->Next; + free (mGlobals.SubDirs->Str); + free (mGlobals.SubDirs); + mGlobals.SubDirs = Temp; + } + // + // Free the symbol table + // + while (mGlobals.SymbolTable != NULL) { + NextSym = mGlobals.SymbolTable->Next; + free (mGlobals.SymbolTable->Name); + free (mGlobals.SymbolTable->Value); + mGlobals.SymbolTable = NextSym; + } + // + // printf ("done\n"); + // +} + +static +void +Usage ( + VOID + ) +/*++ + +Routine Description: + + Print usage information for this utility. + +Arguments: + + None. + +Returns: + + Nothing. + +--*/ +{ + int Index; + static const char *Str[] = { + UTILITY_NAME " -- make dependencies", + " Usage: MakeDeps [options]", + " Options include:", + " -h or -? for this help information", + " -f SourceFile add SourceFile to list of files to scan", + " -i IncludePath add IncludePath to list of search paths", + " -o OutputFile write output dependencies to OutputFile", + " -s SubDir for each IncludePath, also search IncludePath\\SubDir", + " -v for verbose output", + " -ignorenotfound don't warn for files not found", + " -target Target for single SourceFile, target is Target, not SourceFile.obj", + " -q quiet mode to not report files not found if ignored", + " -sub sym str replace all occurrances of 'str' with 'sym' in the output", + " -nosystem not process system files", + " -neverfail always return a success return code", + // + // " -nodupes keep track of include files, don't rescan duplicates", + // + " -usesumdeps path use summary dependency files in 'path' directory.", + " -asm The SourceFile is assembler file", + "", + NULL + }; + for (Index = 0; Str[Index] != NULL; Index++) { + fprintf (stdout, "%s\n", Str[Index]); + } +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/MakeDeps/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/MakeDeps/Makefile new file mode 100644 index 0000000000..4cd9084f8e --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/MakeDeps/Makefile @@ -0,0 +1,69 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Makefile +# +# Abstract: +# +# makefile for building the MakeDeps utility. +# +#--*/ + +# +# Make sure environmental variable EDK_SOURCE is set +# +!IFNDEF EDK_SOURCE +!ERROR EDK_SOURCE environmental variable not set +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Target specific information +# +TARGET_NAME = MakeDeps +TARGET_SRC_DIR = $(EDK_TOOLS_SOURCE)\MakeDeps +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\MakeDeps.exe + +OBJECTS = $(EDK_TOOLS_OUTPUT)\MakeDeps.obj +LIBS = $(LIBS) $(EDK_TOOLS_OUTPUT)\Common.lib + +# +# Build targets +# + +all: $(TARGET_EXE) + +# +# Compile each tool source file +# +$(OBJECTS) : $(TARGET_SRC_DIR)\MakeDeps.c $(INC_DEPS) + $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\MakeDeps.c /Fo$@ + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE) : $(OBJECTS) $(LIBS) + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/Makefile new file mode 100644 index 0000000000..974c9b4aa9 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/Makefile @@ -0,0 +1,79 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: makefile +# +# Abstract: +# +# This file is used to build the EFI build tools. +# +#--*/ + +# +# Everything depends on EDK_SOURCE. Make sure it's defined +# +!IFNDEF EDK_SOURCE +!ERROR EDK_SOURCE environmental variable not set +!ENDIF + +# +# Define our toolchain before we include the master settings file +# +TOOLCHAIN = TOOLCHAIN_MSVC + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Define all the makefiles we want to call +# + +MAKEFILES = $(EDK_TOOLS_SOURCE)\Common\Makefile \ + $(CUSTOMIZEDCOMPRESS_MAKEFILE) \ + $(EDK_TOOLS_SOURCE)\GenCRC32Section\Makefile \ + $(EDK_TOOLS_SOURCE)\GenSection\Makefile \ + $(EDK_TOOLS_SOURCE)\GenDepex\Makefile \ + $(EDK_TOOLS_SOURCE)\GenFfsFile\Makefile \ + $(EDK_TOOLS_SOURCE)\GenFvImage\Makefile \ + $(EDK_TOOLS_SOURCE)\FwImage\Makefile \ + $(EDK_TOOLS_SOURCE)\ProcessDsc\makefile \ + $(EDK_TOOLS_SOURCE)\GuidChk\makefile \ + $(EDK_TOOLS_SOURCE)\MakeDeps\makefile \ + $(EDK_TOOLS_SOURCE)\SetStamp\makefile \ + $(EDK_TOOLS_SOURCE)\VfrCompile\makefile \ + $(EDK_TOOLS_SOURCE)\StrGather\makefile \ + $(EDK_TOOLS_SOURCE)\BootsectImage\Makefile \ + $(EDK_TOOLS_SOURCE)\GenBootsector\Makefile \ + $(EDK_TOOLS_SOURCE)\GenPage\Makefile \ + $(EDK_TOOLS_SOURCE)\SplitFile\Makefile \ + $(EDK_TOOLS_SOURCE)\EfiCompress\Makefile \ + $(EDK_TOOLS_SOURCE)\EfildrImage\Makefile \ + $(EDK_TOOLS_SOURCE)\EfiRom\Makefile \ + $(EDK_TOOLS_SOURCE)\GenAprioriFile\Makefile \ + $(EDK_TOOLS_SOURCE)\ModifyInf\Makefile + + + +# +# Define default all target which calls all our makefiles. The special +# bang (!) tells nmake to do the command for each out-of-date dependent. +# +# Create the BIN directory, which will only exist if you pull the source tree +# from version control. +# +all : $(MAKEFILES) + -if not exist $(EDK_TOOLS_OUTPUT) mkdir $(EDK_TOOLS_OUTPUT) + !$(MAKE) -f $? TOOLCHAIN=$(TOOLCHAIN) BUILD_DIR=$(BUILD_DIR) all + +# +# Call all the tools makefiles with a clean target. +# +clean : $(MAKEFILES) + !$(MAKE) -f $? TOOLCHAIN=$(TOOLCHAIN) clean diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/ModifyInf/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/ModifyInf/Makefile new file mode 100644 index 0000000000..f303a54d10 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/ModifyInf/Makefile @@ -0,0 +1,82 @@ +#/*++ +# +# Copyright (c) 2001 - 2006 Intel Corporation. +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Makefile +# +# Abstract: +# +# This file is used to build the EFI utility. +# +#--*/ + +# +# Make sure environmental variable EDK_SOURCE is set +# +!IFNDEF EDK_SOURCE +!ERROR EDK_SOURCE environmental variable not set +!ENDIF + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Target specific information +# + +TARGET_NAME = ModifyInf +TARGET_SRC_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).exe + +TARGET_EXE_SOURCE = "$(TARGET_SRC_DIR)\ModifyInf.c" +TARGET_EXE_INCLUDE = +OBJECTS = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + +# +# Build targets +# + +all: $(TARGET_EXE) + +# +# Build EXE +# + +$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE) + $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE) : $(OBJECTS) + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/ModifyInf/ModifyInf.c b/EdkCompatibilityPkg/Sample/Tools/Source/ModifyInf/ModifyInf.c new file mode 100644 index 0000000000..edfcba00a9 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/ModifyInf/ModifyInf.c @@ -0,0 +1,322 @@ +/*++ + +Copyright (c) 1999 - 2002 Intel Corporation. +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ModifyInf.c + +Abstract: + + It is a simple tool to modify some fields in a FV inf file + and output a new FV inf file. + +--*/ + +#include "stdio.h" +#include "string.h" + +// +// Read a line into buffer including '\r\n' +// +int +ReadLine ( + char *LineBuffer, + FILE *fp + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + LineBuffer - GC_TODO: add argument description + fp - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + int CharC; + char *Line; + + Line = LineBuffer; + + while ((CharC = fgetc (fp)) != EOF) { + *Line++ = (char) CharC; + if (CharC == 0x0a) { + break; + } + } + + *Line = 0; + + if (CharC == EOF) { + return 0; + } else { + return 1; + } + +} +// +// Write a line into output file +// +int +WriteLine ( + char *Line, + FILE *fp + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + Line - GC_TODO: add argument description + fp - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + fwrite (Line, strlen (Line), 1, fp); + return 0; +} +// +// Apply patterns to a line +// Currently there are 2 patterns to support +// '==' replace a field value with a new value +// '+=' append a string at the end of original line +// '-' prevent the line from applying any patterns +// it has the highest priority +// +int +ApplyPattern ( + char *Line, + char *argv[], + int argc + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + Line - GC_TODO: add argument description + ] - GC_TODO: add argument description + argc - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + static char Section[256]; + int SectionLength; + char PatternBuffer[256]; + char *Pattern; + char *Pattern1; + char *Pattern2; + int PatternNum; + char *Ptr; + + Pattern = PatternBuffer; + + PatternNum = argc; + + // + // For section field + // record current scope section into static buffer + // + Ptr = Line; + if (*Ptr == '[') { + while (*Ptr != ']') { + if (!(*Ptr++)) { + return -1; + } + } + SectionLength = Ptr - Line + 1; + SectionLength = SectionLength > 255 ? 255 : SectionLength; + strncpy (Section, Line, SectionLength); + Section[SectionLength] = 0; + } + // + // Apply each pattern on the line + // + while (PatternNum-- > 3) { + + strcpy (Pattern, argv[PatternNum]); + + // + // For pattern '-' + // keep it unmodified by other patterns + // + if (*Pattern == '-') { + if (strstr (Line, Pattern + 1)) { + return 0; + } else { + continue; + } + } + // + // For other patterns + // get its section at first if it has + // + if (*Pattern == '[') { + if (strncmp (Section, Pattern, strlen (Section))) { + // + // This pattern can't be appied for current section + // + continue; + } + // + // Strip the section field + // + while (*Pattern != ']') { + if (!(*Pattern++)) { + return -1; + } + } + + Pattern++; + } + // + // Apply patterns + // + Pattern1 = strstr (Pattern, "=="); + Pattern2 = strstr (Pattern, "+="); + if (Pattern1) { + // + // For pattern '==' + // replace the field value with a new string + // + if (!strncmp (Line, Pattern, Pattern1 - Pattern)) { + Pattern1 += 2; + Ptr = strstr (Line, "="); + if (!Ptr) { + return -1; + } + + while (*(++Ptr) == ' ') + ; + *Ptr = 0; + strcat (Line, Pattern1); + strcat (Line, "\r\n"); + } + } else if (Pattern2) { + // + // For pattern '+=' + // append a string at end of the original string + // + if (!strncmp (Line, Pattern, Pattern2 - Pattern)) { + Pattern2 += 2; + Ptr = Line; + while (*Ptr != 0x0D && *Ptr != 0x0A) { + Ptr++; + } + + *Ptr = 0; + strcat (Line, Pattern2); + strcat (Line, "\r\n"); + } + } + } + + return 0; +} + +void +Usage ( + void + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + None + +Returns: + + GC_TODO: add return values + +--*/ +{ + printf ("ModifyInf InputFVInfFileName OutputFVInfFileName [Pattern strings]\r\n"); +} + +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 + +--*/ +{ + char LineBuffer[256]; + FILE *fpin; + FILE *fpout; + + if (argc < 3) { + Usage (); + return -1; + } + + fpin = fopen (argv[1], "rb"); + if (!fpin) { + printf ("Can't open input file!\r\n"); + return -1; + } + + fpout = fopen (argv[2], "wb"); + if (!fpout) { + fclose (fpin); + printf ("Can't create output file!\r\n"); + return -1; + } + + while (ReadLine (LineBuffer, fpin)) { + ApplyPattern (LineBuffer, argv, argc); + WriteLine (LineBuffer, fpout); + } + + fclose (fpin); + fclose (fpout); + + return 0; +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Common.h b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Common.h new file mode 100644 index 0000000000..b642d092cb --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Common.h @@ -0,0 +1,123 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Common.h + +Abstract: + + Common include file for the ProcessDsc utility. + +--*/ + +#ifndef _COMMON_H_ +#define _COMMON_H_ + +typedef char INT8; +typedef unsigned int UINT32; + +#include "EfiUtilityMsgs.h" + +#define MAX_LINE_LEN 1024 + +#ifdef MAX_PATH +#undef MAX_PATH +#define MAX_PATH 1024 +#endif + +// +// Defines for how to expand symbols +// +#define EXPANDMODE_NO_UNDEFS 0x01 +#define EXPANDMODE_NO_DESTDIR 0x02 +#define EXPANDMODE_NO_SOURCEDIR 0x04 +#define EXPANDMODE_RECURSIVE 0x08 + +// +// Defines for adding symbols +// +#define SYM_OVERWRITE 0x01 // overwrite existing assignments +#define SYM_GLOBAL 0x02 // global symbol (persistent) +#define SYM_LOCAL 0x04 // symbols at component level +#define SYM_FILE 0x08 // symbols at file level +#define SYM_FILEPATH 0x10 // symbol is a file path +#define SYM_FILENAME 0x20 // symbol is a file name +#define FV_DIR "FV_DIR" // symbol for base dir where FV files are +#define DSC_FILENAME "DSC_FILENAME" + +// +// Smart file for better incremental build support. +// Only re-create .pkg .inf or .apr files when it's content is changed. +// +// +typedef struct _SMART_FILE { + char *FileName; + char *FileContent; // Previous file content + int FileLength; // Previous file string length + int FilePosition; // The offset from FileContent for next comparison + FILE *FilePtr; // New file pointer if the file need to be re-created +} SMART_FILE; + +SMART_FILE * +SmartOpen ( + char *FileName + ); + +int +SmartWrite ( + SMART_FILE *SmartFile, + char *String + ); + +void +SmartClose ( + SMART_FILE *SmartFile + ); + +INT8 * +GetSymbolValue ( + INT8 *SymbolName + ); + +int +AddSymbol ( + INT8 *Name, + INT8 *Value, + int Mode + ); + +int +ExpandSymbols ( + INT8 *SourceLine, + INT8 *DestLine, + int LineLen, + int ExpandMode + ); + +void +Message ( + UINT32 PrintMask, + INT8 *Fmt, + ... + ); + +int +MakeFilePath ( + INT8 *FileName + ); + +int +IsAbsolutePath ( + INT8 *FileName + ); + +#endif // ifndef _COMMON_H_ diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/DscFile.c b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/DscFile.c new file mode 100644 index 0000000000..345e1a9e4a --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/DscFile.c @@ -0,0 +1,534 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + + Module Name: + + DscFile.c + + Abstract: + + This module is used to process description files at a high level. For the + most part, it pre-parses the file to find and save off positions of all + the sections ([section.subsection.subsection]) in a linked list, then + provides services to find the sections by name, and read the lines from + the section until you run into the next section. + + NOTE: DSC file is synonomous with section file. A DSC file is simply a file + containing bracketed section names [section.subsection.subsection...] + +--*/ + +#include // for file ops +#include +#include +#include // for malloc +#include "Common.h" +#include "DSCFile.h" + +#define MAX_INCLUDE_NEST_LEVEL 20 + +static +void +DSCFileFree ( + DSC_FILE *DSC + ); + +static +STATUS +DSCParseInclude ( + DSC_FILE *DSC, + char *FileName, + int NestLevel + ); + +// +// Constructor for a DSC file +// +int +DSCFileInit ( + DSC_FILE *DSC + ) +{ + memset ((char *) DSC, 0, sizeof (DSC_FILE)); + DSC->SavedPositionIndex = -1; + return STATUS_SUCCESS; +} +// +// Destructor for a DSC file +// +int +DSCFileDestroy ( + DSC_FILE *DSC + ) +{ + DSC->SavedPositionIndex = -1; + DSCFileFree (DSC); + return STATUS_SUCCESS; +} +// +// Get the next line from a DSC file. +// +char * +DSCFileGetLine ( + DSC_FILE *DSC, + char *Line, + int LineLen + ) +{ + char *Cptr; + + if (DSC->CurrentLine == NULL) { + return NULL; + } + // + // Check for running into next section + // + if (DSC->CurrentLine->Line[0] == '[') { + return NULL; + } + // + // Allow special case where the line starts with backslash-bracket. If we + // see this, then shift everything left one character. + // + if ((DSC->CurrentLine->Line[0] == '\\') && (DSC->CurrentLine->Line[1] == '[')) { + Cptr = DSC->CurrentLine->Line + 1; + } else { + Cptr = DSC->CurrentLine->Line; + } + + strncpy (Line, Cptr, LineLen); + ParserSetPosition (DSC->CurrentLine->FileName, DSC->CurrentLine->LineNum); + DSC->CurrentLine = DSC->CurrentLine->Next; + return Line; +} + +int +DSCFileSetFile ( + DSC_FILE *DSC, + char *FileName + ) +/*++ + +Routine Description: + + Pre-scan a section file to find all the sections. Then we can speed up + searching for the different sections. + +Arguments: + + DSC - pointer to a DSC structure (this pointer) + FileName - name of the file to process + +Returns: + + STATUS_SUCCESS if everything went well. + +--*/ +{ + STATUS Status; + + // + // Called to open a new sectioned file. + // + Status = DSCParseInclude (DSC, FileName, 1); + return Status; +} + +static +STATUS +DSCParseInclude ( + DSC_FILE *DSC, + char *FileName, + int NestLevel + ) +{ + SECTION *NewSect; + SECTION_LINE *NewLine; + DSC_FILE_NAME *NewDscFileName; + char Line[MAX_LINE_LEN]; + char *Start; + char *End; + char SaveChar; + char *TempCptr; + char ShortHandSectionName[MAX_LINE_LEN]; + char ThisSectionName[MAX_LINE_LEN]; + SECTION *CurrSect; + SECTION *TempSect; + FILE *FilePtr; + STATUS Status; + UINT32 LineNum; + + // + // Make sure we haven't exceeded our maximum nesting level + // + if (NestLevel > MAX_INCLUDE_NEST_LEVEL) { + Error (NULL, 0, 0, "application error", "maximum !include nesting level exceeded"); + return STATUS_ERROR; + } + // + // Try to open the file + // + if ((FilePtr = fopen (FileName, "r")) == NULL) { + // + // This function is called to handle the DSC file from the command line too, + // so differentiate whether this file is an include file or the main file + // by examining the nest level. + // + if (NestLevel == 1) { + Error (NULL, 0, 0, FileName, "could not open DSC file for reading"); + } else { + Error (NULL, 0, 0, FileName, "could not open !include DSC file for reading"); + } + + return STATUS_ERROR; + } + // + // We keep a linked list of files we parse for error reporting purposes. + // + NewDscFileName = malloc (sizeof (DSC_FILE_NAME)); + if (NewDscFileName == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL); + return STATUS_ERROR; + } + + memset (NewDscFileName, 0, sizeof (DSC_FILE_NAME)); + NewDscFileName->FileName = (INT8 *) malloc (strlen (FileName) + 1); + if (NewDscFileName->FileName == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failed", NULL); + return STATUS_ERROR; + } + + strcpy (NewDscFileName->FileName, FileName); + if (DSC->FileName == NULL) { + DSC->FileName = NewDscFileName; + } else { + DSC->LastFileName->Next = NewDscFileName; + } + + DSC->LastFileName = NewDscFileName; + // + // Read lines and process until done + // + Status = STATUS_SUCCESS; + LineNum = 0; + for (;;) { + if (fgets (Line, sizeof (Line), FilePtr) == NULL) { + break; + } + + LineNum++; + ParserSetPosition (FileName, LineNum); + // + // Add the line to our list if it's not a !include line + // + if ((strncmp (Line, "!include", 8) == 0) && (isspace (Line[8]))) { + Start = Line + 9; + while (*Start && (*Start != '"')) { + Start++; + } + + if (*Start != '"') { + Error (FileName, LineNum, 0, NULL, "invalid format for !include"); + Status = STATUS_ERROR; + goto Done; + } + + Start++; + for (End = Start; *End && (*End != '"'); End++) + ; + if (*End != '"') { + Error (FileName, LineNum, 0, NULL, "invalid format for !include"); + Status = STATUS_ERROR; + goto Done; + } + + *End = 0; + // + // Expand symbols. Use 'ThisSectionName' as scratchpad + // + ExpandSymbols (Start, ThisSectionName, sizeof (ThisSectionName), EXPANDMODE_NO_UNDEFS); + Status = DSCParseInclude (DSC, ThisSectionName, NestLevel + 1); + if (Status != STATUS_SUCCESS) { + Error (FileName, LineNum, 0, NULL, "failed to parse !include file"); + goto Done; + } + } else { + NewLine = (SECTION_LINE *) malloc (sizeof (SECTION_LINE)); + if (NewLine == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + Status = STATUS_ERROR; + goto Done; + } + + memset ((char *) NewLine, 0, sizeof (SECTION_LINE)); + NewLine->LineNum = LineNum; + NewLine->FileName = NewDscFileName->FileName; + NewLine->Line = (char *) malloc (strlen (Line) + 1); + if (NewLine->Line == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + Status = STATUS_ERROR; + goto Done; + } + + strcpy (NewLine->Line, Line); + if (DSC->Lines == NULL) { + DSC->Lines = NewLine; + } else { + DSC->LastLine->Next = NewLine; + } + + DSC->LastLine = NewLine; + // + // Parse the line for []. Ignore [] and [----] delimiters. The + // line may have multiple definitions separated by commas, so + // take each separately + // + Start = Line; + if ((Line[0] == '[') && ((Line[1] != ']') && (Line[1] != '-'))) { + // + // Skip over open bracket and preceeding spaces + // + Start++; + ShortHandSectionName[0] = 0; + + while (*Start && (*Start != ']')) { + while (isspace (*Start)) { + Start++; + } + // + // Hack off closing bracket or trailing spaces or comma separator. + // Also allow things like [section.subsection1|subsection2], which + // is shorthand for [section.subsection1,section.subsection2] + // + End = Start; + while (*End && (*End != ']') && !isspace (*End) && (*End != ',') && (*End != '|')) { + End++; + } + // + // Save the character and null-terminate the string + // + SaveChar = *End; + *End = 0; + // + // Now allocate space for a new section and add it to the linked list. + // If the previous section ended with the shorthand indicator, then + // the section name was saved off. Append this section name to it. + // + strcpy (ThisSectionName, ShortHandSectionName); + if (*Start == '.') { + strcat (ThisSectionName, Start + 1); + } else { + strcat (ThisSectionName, Start); + } + // + // Allocate memory for the section. Then clear it out. + // + NewSect = (SECTION *) malloc (sizeof (SECTION)); + if (NewSect == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocation memory for sections"); + Status = STATUS_ERROR; + goto Done; + } + + memset ((char *) NewSect, 0, sizeof (SECTION)); + NewSect->FirstLine = NewLine; + NewSect->Name = (char *) malloc (strlen (ThisSectionName) + 1); + if (NewSect->Name == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocation memory for sections"); + Status = STATUS_ERROR; + goto Done; + } + + strcpy (NewSect->Name, ThisSectionName); + if (DSC->Sections == NULL) { + DSC->Sections = NewSect; + } else { + DSC->LastSection->Next = NewSect; + } + + DSC->LastSection = NewSect; + *End = SaveChar; + // + // If the name ended in a shorthand indicator, then save the + // section name and truncate it at the last dot. + // + if (SaveChar == '|') { + strcpy (ShortHandSectionName, ThisSectionName); + for (TempCptr = ShortHandSectionName + strlen (ShortHandSectionName) - 1; + (TempCptr != ShortHandSectionName) && (*TempCptr != '.'); + TempCptr-- + ) + ; + // + // If we didn't find a dot, then hopefully they have [name1|name2] + // instead of [name1,name2]. + // + if (TempCptr == ShortHandSectionName) { + ShortHandSectionName[0] = 0; + } else { + // + // Truncate after the dot + // + *(TempCptr + 1) = 0; + } + } else { + // + // Kill the shorthand string + // + ShortHandSectionName[0] = 0; + } + // + // Skip to next section name or closing bracket + // + while (*End && ((*End == ',') || isspace (*End) || (*End == '|'))) { + End++; + } + + Start = End; + } + } + } + } + // + // Look through all the sections to make sure we don't have any duplicates. + // Allow [----] and [====] section separators + // + CurrSect = DSC->Sections; + while (CurrSect != NULL) { + TempSect = CurrSect->Next; + while (TempSect != NULL) { + if (isalpha (CurrSect->Name[0]) && (_stricmp (CurrSect->Name, TempSect->Name) == 0)) { + Error ( + TempSect->FirstLine->FileName, + TempSect->FirstLine->LineNum, + 0, + TempSect->Name, + "duplicate section found" + ); + Error ( + CurrSect->FirstLine->FileName, + CurrSect->FirstLine->LineNum, + 0, + TempSect->Name, + "first definition of duplicate section" + ); + Status = STATUS_ERROR; + goto Done; + } + + TempSect = TempSect->Next; + } + + CurrSect = CurrSect->Next; + } + +Done: + fclose (FilePtr); + return Status; +} +// +// Free up memory allocated for DSC file handling. +// +static +void +DSCFileFree ( + DSC_FILE *DSC + ) +{ + SECTION *NextSection; + SECTION_LINE *NextLine; + DSC_FILE_NAME *NextName; + + while (DSC->Sections != NULL) { + NextSection = DSC->Sections->Next; + if (DSC->Sections->Name != NULL) { + free (DSC->Sections->Name); + } + + free (DSC->Sections); + DSC->Sections = NextSection; + } + + while (DSC->Lines != NULL) { + NextLine = DSC->Lines->Next; + free (DSC->Lines->Line); + free (DSC->Lines); + DSC->Lines = NextLine; + } + + while (DSC->FileName != NULL) { + NextName = DSC->FileName->Next; + free (DSC->FileName->FileName); + free (DSC->FileName); + DSC->FileName = NextName; + } +} + +SECTION * +DSCFileFindSection ( + DSC_FILE *DSC, + char *Name + ) +{ + SECTION *Sect; + + // + // Look through all the sections to find one with this name (case insensitive) + // + Sect = DSC->Sections; + while (Sect != NULL) { + if (_stricmp (Name, Sect->Name) == 0) { + // + // Position within file + // + DSC->CurrentLine = Sect->FirstLine->Next; + return Sect; + } + + Sect = Sect->Next; + } + + return NULL; +} + +int +DSCFileSavePosition ( + DSC_FILE *DSC + ) +{ + // + // Advance to next slot + // + DSC->SavedPositionIndex++; + if (DSC->SavedPositionIndex >= MAX_SAVES) { + DSC->SavedPositionIndex--; + Error (NULL, 0, 0, "APP ERROR", "max nesting of saved section file positions exceeded"); + return STATUS_ERROR; + } + + DSC->SavedPosition[DSC->SavedPositionIndex] = DSC->CurrentLine; + return STATUS_SUCCESS; +} + +int +DSCFileRestorePosition ( + DSC_FILE *DSC + ) +{ + if (DSC->SavedPositionIndex < 0) { + Error (NULL, 0, 0, "APP ERROR", "underflow of saved positions in section file"); + return STATUS_ERROR; + } + + DSC->CurrentLine = DSC->SavedPosition[DSC->SavedPositionIndex]; + DSC->SavedPositionIndex--; + return STATUS_SUCCESS; +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/DscFile.h b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/DscFile.h new file mode 100644 index 0000000000..4dcad547ec --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/DscFile.h @@ -0,0 +1,109 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + DscFile.h + +Abstract: + + Defines and function prototypes for the ProcessDsc utility. + +--*/ + +#ifndef _DSC_FILE_H_ +#define _DSC_FILE_H_ + +typedef struct _SECTION_LINE { + struct _SECTION_LINE *Next; + char *Line; + char *FileName; + UINT32 LineNum; +} SECTION_LINE; + +// +// Use this structure to keep track of parsed file names. Then +// if we get a parse error we can figure out the file/line of +// the error and print a useful message. +// +typedef struct _DSC_FILE_NAME { + struct _DSC_FILE_NAME *Next; + char *FileName; +} DSC_FILE_NAME; + +// +// We create a list of section names when we pre-parse a description file. +// Use this structure. +// +typedef struct _SECTION { + struct _SECTION *Next; + char *Name; + SECTION_LINE *FirstLine; +} SECTION; + +#define MAX_SAVES 4 + +typedef struct { + SECTION_LINE *SavedPosition[MAX_SAVES]; + int SavedPositionIndex; + SECTION *Sections; + SECTION_LINE *Lines; + SECTION *LastSection; + SECTION_LINE *LastLine; + SECTION_LINE *CurrentLine; + DSC_FILE_NAME *FileName; + DSC_FILE_NAME *LastFileName; +} DSC_FILE; + +// +// Function prototypes +// +int +DSCFileSetFile ( + DSC_FILE *DSC, + char *FileName + ) +; +SECTION * +DSCFileFindSection ( + DSC_FILE *DSC, + char *Name + ) +; +int +DSCFileSavePosition ( + DSC_FILE *DSC + ) +; +int +DSCFileRestorePosition ( + DSC_FILE *DSC + ) +; +char * +DSCFileGetLine ( + DSC_FILE *DSC, + char *Line, + int LineLen + ) +; +int +DSCFileInit ( + DSC_FILE *DSC + ) +; +int +DSCFileDestroy ( + DSC_FILE *DSC + ) +; + +#endif // ifndef _DSC_FILE_H_ diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Exceptions.c b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Exceptions.c new file mode 100644 index 0000000000..bc50183ac3 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Exceptions.c @@ -0,0 +1,141 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Exceptions.c + +Abstract: + + Exception logging routines. + +--*/ + +#include +#include +#include // for memset() +#include "Exceptions.h" + +// +// Max length of a saved exception message +// +#define MAX_EXCEPTION_MSG 200 + +// +// We use this structure to track exceptions thrown. We nest deeper on +// TryException() calls, and come back out on CatchException() calls. +// We save off the first exception message for a given exception level, +// but we save the count of how many were thrown. +// +typedef struct { + int ExceptionCount; + char ExceptionMsg[MAX_EXCEPTION_MSG]; +} EXCEPTION_LOG; + +static EXCEPTION_LOG ExceptionLog[MAX_EXCEPTION_NESTING + 1]; +static int ExceptionLevel; + +// +// Initialize our data and structures for tracking exceptions. +// +int +InitExceptions ( + VOID + ) +{ + ExceptionLevel = -1; + memset ((char *) &ExceptionLog, 0, sizeof (ExceptionLog)); + return 0; +} +// +// This function replaces the _try() exception macro. It sets the +// nesting level. +// +int +TryException ( + VOID + ) +{ + // + // Boost our exception level if we would not go out of range + // + ExceptionLevel++; + if (ExceptionLevel >= MAX_EXCEPTION_NESTING) { + fprintf (stderr, "ERROR: Max exception nesting level exceeded\n"); + ExceptionLevel--; + return 1; + } + + return 0; +} +// +// This function replaces the _catch() exception macro. It's used to decrement +// the nesting level and return any exeption error messages that were +// thrown at the current nesting level. +// +char * +CatchException ( + VOID + ) +{ + // + // Return a pointer to exception message. NULL if no exceptions at this level + // + if (ExceptionLevel >= 0) { + ExceptionLevel--; + if (ExceptionLog[ExceptionLevel + 1].ExceptionMsg[0]) { + return ExceptionLog[ExceptionLevel + 1].ExceptionMsg; + } else { + return NULL; + } + } else { + fprintf (stderr, "ERROR: Invalid nesting level call to CatchException()\n"); + return NULL; + } +} +// +// This function can be used to test for exceptions between the TryException() +// and CatchException() calls in a given function. +// +int +ExceptionThrown ( + VOID + ) +{ + return ExceptionLog[ExceptionLevel].ExceptionCount; +} +// +// This function replaces the _throw() exception macro. It saves off the +// given error message at the current exeption level nesting. +// +int +ThrowException ( + char *Msg + ) +{ + if (ExceptionLevel < 0) { + // + // fprintf (stderr, "ERROR: Exception thrown out of scope"); + // Haven't yet enabled handling of exceptions, so just emit the message. + // + fprintf (stderr, Msg); + return 1; + } + // + // Only log the first + // + if (ExceptionLog[ExceptionLevel].ExceptionMsg[0] == 0) { + strncpy (ExceptionLog[ExceptionLevel].ExceptionMsg, Msg, MAX_EXCEPTION_MSG); + } + + ExceptionLog[ExceptionLevel].ExceptionCount++; + return 0; +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Exceptions.h b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Exceptions.h new file mode 100644 index 0000000000..1425d4387a --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Exceptions.h @@ -0,0 +1,57 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + Exceptions.h + +Abstract: + + Defines and function prototypes for the ProcessDsc utility. + +--*/ + +#ifndef _EXCEPTIONS_H_ +#define _EXCEPTIONS_H_ + +#define VOID void +#define MAX_EXCEPTION_NESTING 4 + +// +// Function prototypes +// +int +InitExceptions ( + VOID + ) +; +int +TryException ( + VOID + ) +; +char * +CatchException ( + VOID + ) +; +int +ExceptionThrown ( + VOID + ) +; +int +ThrowException ( + char *EMsg + ) +; + +#endif // ifndef _EXCEPTIONS_H_ diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/FWVolume.c b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/FWVolume.c new file mode 100644 index 0000000000..28baf5551b --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/FWVolume.c @@ -0,0 +1,1566 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + FWVolume.c + +Abstract: + + This module contains functionality to keep track of files destined for + multiple firmware volues. It saves them up, and when told to, dumps the + file names out to some files used as input to other utilities that + actually generate the FVs. + +--*/ + +#include // for max_path definition +#include +#include +#include // for malloc() +#include "Common.h" +#include "DSCFile.h" +#include "FWVolume.h" + +#define FV_INF_DIR "FV_INF_DIR" // symbol for where we create the FV INF file +#define FV_FILENAME "FV_FILENAME" // symbol for the current FV.INF filename +#define EFI_BASE_ADDRESS "EFI_BASE_ADDRESS" +#define DEFAULT_FV_INF_DIR "FV" // default dir for where we create the FV INF file +#define DEFAULT_FV_DIR "$(BUILD_DIR)" // where the FV file comes from +#define MALLOC(size) malloc (size) +#define FREE(ptr) free (ptr) + +// +// Disable warning for unused function arguments +// +#pragma warning(disable : 4100) +// +// Disable warning for while(1) code +// +// #pragma warning (disable : 4127) +// +typedef struct { + char *ComponentType; + char *Extension; +} COMP_TYPE_EXTENSION; + +// +// Use a linked list of these to keep track of all the FV names used +// +typedef struct _FV_LIST { + struct _FV_LIST *Next; + char FVFileName[MAX_PATH]; + char BaseAddress[MAX_LINE_LEN]; + SMART_FILE *FVFilePtr; + SMART_FILE *AprioriFilePtr; + char *Processor; + int ComponentsInstance; // highest [components.n] section with a file for this FV +} FV_LIST; + +// +// Use a linked list of these to keep track of all FFS files built. When +// we're done, we turn the info into the FV INF files used to build the +// firmware volumes. +// +typedef struct _FILE_LIST { + struct _FILE_LIST *Next; + char *FileName; + char *BaseFileName; + char *FVs; // from FV=x,y,z + char *BaseName; // only needed for duplicate basename check + char *Processor; // only needed for duplicate basename check + char Apriori[100]; // of format "FVRecovery:1,FVMain:2" from APRIORI define + char *Guid; // guid string + int ComponentsInstance; // which [components.n] section it's in +} FILE_LIST; + +typedef struct _LINKED_LIST { + struct _LINKED_LIST *Next; + void *Data; +} LINKED_LIST; + +static FILE_LIST *mFileList; +static FILE_LIST *mLastFile; +static char *mXRefFileName = NULL; +static FV_LIST *mNonFfsFVList = NULL; + +// +// Whenever an FV name is referenced, then add it to our list of known +// FV's using these. +// +static FV_LIST *mFVList = NULL; +static FV_LIST *mFVListLast = NULL; + +// +// We use this list so that from a given component type, we can determine +// the name of the file on disk. For example, if we're given a file's +// guid and base name, and we know it's a "bs_driver", then we can look +// up "bs_driver" in this array and know that the file (after it's built) +// name is GUID-BASENAME.DXE +// +static const COMP_TYPE_EXTENSION mCompTypeExtension[] = { + { + "bs_driver", + ".dxe" + }, + { + "rt_driver", + ".dxe" + }, + { + "sal_rt_driver", + ".dxe" + }, + { + "security_core", + ".sec" + }, + { + "pei_core", + ".pei" + }, + { + "pic_peim", + ".pei" + }, + { + "pe32_peim", + ".pei" + }, + { + "relocatable_peim", + ".pei" + }, + { + "binary", + ".ffs" + }, + { + "application", + ".app" + }, + { + "file", + ".ffs" + }, + { + "fvimagefile", + ".fvi" + }, + { + "rawfile", + ".raw" + }, + { + "apriori", + ".ffs" + }, + { + "combined_peim_driver", + ".pei" + }, + { + NULL, + NULL + } +}; + +static +void +CFVFreeFileList ( + VOID + ); + +static +char * +UpperCaseString ( + char *Str + ); + +static +BOOLEAN +InSameFv ( + char *FVs1, + char *FVs2 +); + +static +void +AddFirmwareVolumes ( + char *FVs, + int ComponentsInstance, + FILE_LIST *FileListPtr + ); + +static +BOOLEAN +OrderInFvList ( + char *FvList, + char *FvName, + int *Order + ); + +int +GetBaseAddress ( + char *Name, + char *BaseAddress + ) +{ + char *Start; + char *Cptr; + char CSave; + char *Value; + + Start = Name; + while (*Name && isspace (*Name)) { + Name++; + } + + if (!*Name) { + return STATUS_ERROR; + } + // + // Find the end of the name. Either space or a '='. + // + for (Value = Name; *Value && !isspace (*Value) && (*Value != '='); Value++) + ; + if (!*Value) { + return STATUS_ERROR; + } + // + // Look for the '=' + // + Cptr = Value; + while (*Value && (*Value != '=')) { + Value++; + } + + if (!*Value) { + return STATUS_ERROR; + } + // + // Now truncate the name + // + CSave = *Cptr; + *Cptr = 0; + if (_stricmp (Name, EFI_BASE_ADDRESS) != 0) { + return STATUS_ERROR; + } + + *Cptr = CSave; + // + // Skip over the = and then any spaces + // + Value++; + while (*Value && isspace (*Value)) { + Value++; + } + // + // Find end of string, checking for quoted string + // + if (*Value == '\"') { + Value++; + for (Cptr = Value; *Cptr && *Cptr != '\"'; Cptr++) + ; + } else { + for (Cptr = Value; *Cptr && !isspace (*Cptr); Cptr++) + ; + } + // + // Null terminate the value string + // + CSave = *Cptr; + *Cptr = 0; + strcpy (BaseAddress, Value); + *Cptr = CSave; + + return STATUS_SUCCESS; +} + +int +CFVAddFVFile ( + char *Name, + char *ComponentType, + char *FVs, + int ComponentsInstance, + char *FFSExt, + char *Processor, + char *Apriori, + char *BaseName, + char *Guid + ) +/*++ + +Routine Description: + + Add a file to the list of files in one or more firmware volumes. + +Arguments: + + Name - $(FILE_GUID)-$(BASE_NAME), or filename + ComponentType - type of component being added. Required so we know the + resultant file name after it has been built + FVs - string of commma-separated FVs that the given file is + to be added to. For example, FVs="FV0001,FV0002" + FFSExt - FFS filename extension of the file after it has been built. + This is passed in to us in case we don't know the default + filename extension based on the component type. + Processor - the target processor which the FV is being built for + Apriori - pointer to the definition of APRIORI. For example APRIORI="FvRecovery:1,FvMain:4" + +Returns: + + STATUS_SUCCESS if successful + +--*/ +{ + FILE_LIST *Ptr; + char FileName[MAX_PATH]; + char Str[MAX_PATH]; + int i; + char *Sym; + + // If they provided a filename extension for this type of file, then use it. + // If they did not provide a filename extension, search our list for a + // matching component type and use the extension appropriate for this + // component type. + // + if (FFSExt == NULL) { + // + // They didn't give us a filename extension. Figure it out from the + // component type. + // + for (i = 0; mCompTypeExtension[i].ComponentType != NULL; i++) { + if (_stricmp (ComponentType, mCompTypeExtension[i].ComponentType) == 0) { + FFSExt = mCompTypeExtension[i].Extension; + break; + } + } + // + // If we don't know the file extension, then error out. Just means + // the need to define "FFS_EXT = raw" in the component INF file. + // + if (mCompTypeExtension[i].ComponentType == NULL) { + Error ( + NULL, + 0, + 0, + ComponentType, + "unknown component type - must define FFS_EXT for built filename extension in component INF file" + ); + return STATUS_ERROR; + } + } + // + // We now have all the parts to the FFS filename. Prepend the path to it if + // it's not a full pathname. + // See if they overrode the default base directory for the FV files. + // + if (!IsAbsolutePath (Name)) { + Sym = GetSymbolValue (FV_DIR); + if (Sym == NULL) { + Sym = DEFAULT_FV_DIR; + } + // + // Create the file path. Something like $(BUILD_DIR)\$(PROCESSOR)\$(GUID)-$(BASE_NAME).ext + // If the extension is non-zero length, then make sure there's a dot in it. + // + if ((strlen (FFSExt) > 0) && (FFSExt[0] != '.')) { + sprintf (Str, "%s\\%s\\%s.%s", Sym, Processor, Name, FFSExt); + } else { + sprintf (Str, "%s\\%s\\%s%s", Sym, Processor, Name, FFSExt); + } + + ExpandSymbols (Str, FileName, sizeof (FileName), EXPANDMODE_NO_UNDEFS); + } else { + strcpy (FileName, Name); + } + // + // Traverse the list of files we have so far and make sure we don't have + // any duplicate basenames. If the base name and processor match, then we'll + // have build issues, so don't allow it. We also don't allow the same file GUID + // in the same FV which will cause boot time error if we allow this. + // + Ptr = mFileList; + while (Ptr != NULL) { + if ((Ptr->BaseName != NULL) && (BaseName != NULL) && (_stricmp (BaseName, Ptr->BaseName) == 0)) { + if ((Ptr->Processor != NULL) && (Processor != NULL) && (_stricmp (Processor, Ptr->Processor) == 0)) { + Error (NULL, 0, 0, BaseName, "duplicate base name specified"); + return STATUS_ERROR; + } + } + + if ((Ptr->Guid != NULL) && (Guid != NULL) && (_stricmp (Guid, Ptr->Guid) == 0)) { + if ((Ptr->FVs != NULL) && (FVs != NULL) && (InSameFv (FVs, Ptr->FVs))) { + Error (NULL, 0, 0, Guid, "duplicate Guid specified in the same FV for %s and %s", + (Ptr->BaseName==NULL)?"Unknown":Ptr->BaseName, + (BaseName==NULL)?"Unknown":BaseName); + return STATUS_ERROR; + } + } + + Ptr = Ptr->Next; + } + // + // Allocate a new structure so we can add this file to the list of + // files. + // + Ptr = (FILE_LIST *) malloc (sizeof (FILE_LIST)); + if (Ptr == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + return STATUS_ERROR; + } + + memset ((char *) Ptr, 0, sizeof (FILE_LIST)); + Ptr->FileName = (char *) malloc (strlen (FileName) + 1); + if (Ptr->FileName == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + return STATUS_ERROR; + } + + strcpy (Ptr->FileName, FileName); + Ptr->ComponentsInstance = ComponentsInstance; + // + // Allocate memory to save the FV list if it's going into an FV. + // + if ((FVs != NULL) && (FVs[0] != 0)) { + Ptr->FVs = (char *) malloc (strlen (FVs) + 1); + if (Ptr->FVs == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + return STATUS_ERROR; + } + + strcpy (Ptr->FVs, FVs); + } + + Ptr->BaseFileName = (char *) malloc (strlen (Name) + 1); + if (Ptr->BaseFileName == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + return STATUS_ERROR; + } + + strcpy (Ptr->BaseFileName, Name); + // + // Allocate memory for the basename if they gave us one. May not have one + // if the user is simply adding pre-existing binary files to the image. + // + if (BaseName != NULL) { + Ptr->BaseName = (char *) malloc (strlen (BaseName) + 1); + if (Ptr->BaseName == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + return STATUS_ERROR; + } + + strcpy (Ptr->BaseName, BaseName); + } + // + // Allocate memory for the processor name + // + if (Processor != NULL) { + Ptr->Processor = (char *) malloc (strlen (Processor) + 1); + if (Ptr->Processor == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + return STATUS_ERROR; + } + + strcpy (Ptr->Processor, Processor); + } + // + // Allocate memory for the guid name + // + if (Guid != NULL) { + Ptr->Guid = (char *) malloc (strlen (Guid) + 1); + if (Ptr->Guid == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + return STATUS_ERROR; + } + + strcpy (Ptr->Guid, Guid); + } + // + // If non-null apriori symbol, then save the apriori list for this file + // + if (Apriori != NULL) { + strcpy (Ptr->Apriori, Apriori); + } + + if (mFileList == NULL) { + mFileList = Ptr; + } else { + mLastFile->Next = Ptr; + } + + mLastFile = Ptr; + // + // Add these firmware volumes to the list of known firmware + // volume names. + // + AddFirmwareVolumes (FVs, ComponentsInstance, Ptr); + + return STATUS_SUCCESS; +} + +void +CFVConstructor ( + VOID + ) +{ + mFileList = NULL; + mLastFile = NULL; +} + +void +CFVDestructor ( + VOID + ) +{ + CFVFreeFileList (); + // + // Free up our firmware volume list + // + while (mFVList != NULL) { + mFVListLast = mFVList->Next; + FREE (mFVList); + mFVList = mFVListLast; + } +} + +static +void +CFVFreeFileList ( + VOID + ) +{ + FILE_LIST *Next; + while (mFileList != NULL) { + if (mFileList->FileName != NULL) { + free (mFileList->FileName); + } + + if (mFileList->FVs != NULL) { + free (mFileList->FVs); + } + + free (mFileList->BaseFileName); + if (mFileList->BaseName != NULL) { + free (mFileList->BaseName); + } + + if (mFileList->Processor != NULL) { + free (mFileList->Processor); + } + + if (mFileList->Guid != NULL) { + free (mFileList->Guid); + } + + Next = mFileList->Next; + free (mFileList); + mFileList = Next; + } + + mFileList = NULL; +} + +int +CFVWriteInfFiles ( + DSC_FILE *DSC, + FILE *MakeFptr + ) +/*++ + +Routine Description: + + After processing all components in a DSC file, create the firmware + volume INF files. We actually do a lot more here. + + * Create the FVxxx.inf file that is used by GenFvImage + * Create the Apriori files for each firmware volume that requires one + * Create makefile.out macros for FVxxx_FILES = FVxxx_FILES AnotherFile + so you can do incremental builds of firmware volumes. + * For each FV, emit its build commands to makefile.out + +Arguments: + + DSC - pointer to a DSC_FILE object to extract info from + MakeFptr - pointer to the output makefile + +Returns: + + 0 if successful + non-zero otherwise + +--*/ +{ + FILE_LIST *FileListPtr; + FV_LIST *FVList; + FV_LIST *LastFVList; + FV_LIST *FVPtr; + SECTION *Section; + char *StartCptr; + char *EndCptr; + char CSave; + char Str[MAX_PATH]; + char Line[MAX_LINE_LEN]; + char ExpandedLine[MAX_LINE_LEN]; + char FVDir[MAX_PATH]; + FILE *XRefFptr; + int AprioriCounter; + int AprioriCount; + int AprioriPosition; + BOOLEAN AprioriFound; + int ComponentsInstance; + int ComponentCount; + + // + // Use this to keep track of all the firmware volume names + // + FVList = NULL; + LastFVList = NULL; + // + // See if they specified a FV directory to dump the FV files out to. If not, + // then use the default. Then create the output directory. + // + StartCptr = GetSymbolValue (FV_INF_DIR); + if (StartCptr == NULL) { + ExpandSymbols (DEFAULT_FV_INF_DIR, FVDir, sizeof (FVDir), EXPANDMODE_NO_UNDEFS); + } else { + strcpy (FVDir, StartCptr); + } + // + // Make sure the fv directory path ends in / + // + CSave = FVDir[strlen (FVDir) - 1]; + if ((CSave != '\\') && (CSave != '/')) { + strcat (FVDir, "\\"); + } + // + // Traverse the list of all files, determine which FV each is in, then + // write out the file's name to the output FVxxx.inf file. + // + for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) { + // + // Parse all the "FV1,FV2..." in the FVs + // + if (FileListPtr->FVs != NULL) { + // + // Process each fv this file is in + // + StartCptr = FileListPtr->FVs; + while (*StartCptr) { + EndCptr = StartCptr; + while (*EndCptr && (*EndCptr != ',')) { + EndCptr++; + } + + CSave = *EndCptr; + *EndCptr = 0; + // + // Ok, we have a fv name, now see if we've already opened + // an fv output file of this name. + // + for (FVPtr = FVList; FVPtr != NULL; FVPtr = FVPtr->Next) { + if (_stricmp (FVPtr->FVFileName, StartCptr) == 0) { + break; + } + } + // + // If we didn't find one, then create a new one + // + if (FVPtr == NULL) { + // + // Create a new one, add it to the list + // + FVPtr = (FV_LIST *) malloc (sizeof (FV_LIST)); + if (FVPtr == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory for FV"); + return STATUS_ERROR; + } + + memset ((char *) FVPtr, 0, sizeof (FV_LIST)); + // + // Add it to the end of our list + // + if (FVList == NULL) { + FVList = FVPtr; + } else { + LastFVList->Next = FVPtr; + } + + LastFVList = FVPtr; + // + // Save the FV name in the FileName pointer so we can compare + // for any future FV names specified. + // + strcpy (FVPtr->FVFileName, StartCptr); + + // + // Add a symbol for the FV filename + // + UpperCaseString (FVPtr->FVFileName); + AddSymbol (FV_FILENAME, FVPtr->FVFileName, SYM_LOCAL | SYM_OVERWRITE); + // + // Now create the FVx.inf filename from the fv name and + // default filename extension. Dump it in the FV directory + // as well. + // + strcpy (Str, FVDir); + strcat (Str, FVPtr->FVFileName); + strcat (Str, ".inf"); + // + // Create the directory path for our new fv.inf output file. + // + MakeFilePath (Str); + if ((FVPtr->FVFilePtr = SmartOpen (Str)) == NULL) { + Error (NULL, 0, 0, Str, "could not open FV output file"); + return STATUS_ERROR; + } + // + // Now copy the [fv.$(FV).options] to the fv INF file + // + sprintf (Str, "fv.%s.options", StartCptr); + Section = DSCFileFindSection (DSC, Str); + if (Section != NULL) { + SmartWrite (FVPtr->FVFilePtr, "[options]\n"); + while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) { + ExpandSymbols (Line, ExpandedLine, sizeof (ExpandedLine), 0); + SmartWrite (FVPtr->FVFilePtr, ExpandedLine); + GetBaseAddress (ExpandedLine, FVPtr->BaseAddress); + } + } else { + Error (NULL, 0, 0, Str, "could not find FV section in description file"); + } + // + // Copy the [fv.$(FV).attributes] to the fv INF file + // + sprintf (Str, "fv.%s.attributes", StartCptr); + Section = DSCFileFindSection (DSC, Str); + if (Section != NULL) { + SmartWrite (FVPtr->FVFilePtr, "[attributes]\n"); + while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) { + ExpandSymbols (Line, ExpandedLine, sizeof (ExpandedLine), 0); + SmartWrite (FVPtr->FVFilePtr, ExpandedLine); + } + } else { + Error (NULL, 0, 0, Str, "Could not find FV section in description file"); + } + // + // Start the files section + // + SmartWrite (FVPtr->FVFilePtr, "\n[files]\n"); + } + // + // Now write the FV filename to the FV.inf file. Prepend $(PROCESSOR) on + // it. + // + sprintf (ExpandedLine, "EFI_FILE_NAME = %s\n", FileListPtr->FileName); + SmartWrite (FVPtr->FVFilePtr, ExpandedLine); + + // + // Next FV on the FV list + // + *EndCptr = CSave; + StartCptr = EndCptr; + if (*StartCptr) { + StartCptr++; + } + } + } + } + // + // Now we walk the list of firmware volumes and create the APRIORI list + // file for it . + // + for (FVPtr = FVList; FVPtr != NULL; FVPtr = FVPtr->Next) { + // + // Run through all the files and count up how many are to be + // added to the apriori list for this FV. Then when we're done + // we'll make sure we processed them all. We do this in case they + // skipped an apriori index for a given FV. + // + AprioriCount = 0; + for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) { + if (OrderInFvList (FileListPtr->Apriori, FVPtr->FVFileName, &AprioriPosition)) { + // + // Emit an error if the index was 0, or they didn't give one. + // + if (AprioriPosition == 0) { + Error ( + GetSymbolValue (DSC_FILENAME), + 1, + 0, + "apriori indexes are 1-based", + "component %s:APRIORI=%s", + FileListPtr->BaseName, + FileListPtr->Apriori + ); + } else { + AprioriCount++; + } + + } + } + // + // Now scan the files as we increment our apriori index + // + AprioriCounter = 0; + do { + AprioriFound = 0; + AprioriCounter++; + for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) { + // + // If in the apriori list for this fv, print the name. Open the + // file first if we have to. + // + if ((FileListPtr->Apriori[0] != 0) && + (OrderInFvList (FileListPtr->Apriori, FVPtr->FVFileName, &AprioriPosition)) + ) { + if (AprioriPosition == AprioriCounter) { + // + // If we've already found one for this index, emit an error. Decrement the + // count of how files we are to process so we don't emit another error for + // a miscount below. + // + if (AprioriFound) { + Error ( + GetSymbolValue (DSC_FILENAME), + 1, + 0, + "duplicate apriori index found", + "%s:%d", + FVPtr->FVFileName, + AprioriCounter + ); + AprioriCount--; + } + + AprioriFound = 1; + // + // Open the apriori output file if we haven't already + // + if (FVPtr->AprioriFilePtr == NULL) { + strcpy (Str, FVDir); + strcat (Str, FVPtr->FVFileName); + strcat (Str, ".apr"); + if ((FVPtr->AprioriFilePtr = SmartOpen (Str)) == NULL) { + Error (NULL, 0, 0, Str, "could not open output Apriori file for writing"); + return STATUS_ERROR; + } + } + + sprintf (ExpandedLine, "%s\n", FileListPtr->BaseFileName); + SmartWrite (FVPtr->AprioriFilePtr, ExpandedLine); + } + } + } + } while (AprioriFound); + // + // See if they skipped an apriori position for this FV + // + if (AprioriCount != (AprioriCounter - 1)) { + Error ( + GetSymbolValue (DSC_FILENAME), + 1, + 0, + "apriori index skipped", + "%s:%d", + FVPtr->FVFileName, + AprioriCounter + ); + } + } + // + // Traverse the list of all files again, and create a macro in the output makefile + // that defines all the files in each fv. For example, for each FV file, create a line: + // FV0001_FILES = $(FV_0001_FILES) xxxx-yyy.dxe. + // This can then be used as a dependency in their makefile. + // Also if they wanted us to dump a cross-reference, do that now. + // + if (mXRefFileName != NULL) { + if ((XRefFptr = fopen (mXRefFileName, "w")) == NULL) { + Message ( + 0, + "Failed to open cross-reference file '%s' for writing\n", + mXRefFileName + ); + } + } else { + XRefFptr = NULL; + } + + for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) { + // + // Parse all the "FV1,FV2..." in the FV field that came from FV=FVa,FVb,... on the + // component line in the DSC file. + // + if (FileListPtr->FVs != NULL) { + // + // If generating a cross-reference file, dump the data + // + if (XRefFptr != NULL) { + if ((FileListPtr->Guid != NULL) && (FileListPtr->BaseName != NULL) && (FileListPtr->Processor)) { + fprintf ( + XRefFptr, + "%s %s %s\n", + FileListPtr->Guid, + FileListPtr->BaseName, + FileListPtr->Processor + ); + } + } + // + // Convert to uppercase since we're going to use the name as a macro variable name + // in the makefile. + // + UpperCaseString (FileListPtr->FVs); + // + // Process each FV this file is in to write fvxxx_FILES = $(fvxxx_FILES) Guid-BaseName.ffs + // + StartCptr = FileListPtr->FVs; + while (*StartCptr) { + EndCptr = StartCptr; + while (*EndCptr && (*EndCptr != ',')) { + EndCptr++; + } + + CSave = *EndCptr; + *EndCptr = 0; + fprintf ( + MakeFptr, + "%s_FILES = $(%s_FILES) %s\n", + StartCptr, + StartCptr, + FileListPtr->FileName + ); + // + // Next FV on the FV list + // + *EndCptr = CSave; + StartCptr = EndCptr; + if (*StartCptr) { + StartCptr++; + } + } + } + } + + fprintf (MakeFptr, "\n"); + + // + // Now go through the list of all NonFFS FVs they specified and search for + // a [build.fv.$(FV)] or [build.fv] command and emit the commands to the + // output makefile. Add them to the "fvs" target as well. + // + if (mNonFfsFVList != NULL) { + fprintf (MakeFptr, "fvs ::"); + FVPtr = mNonFfsFVList; + while (FVPtr != NULL) { + fprintf (MakeFptr, " %s%s.fv", FVDir, FVPtr->FVFileName); + FVPtr = FVPtr->Next; + } + + fprintf (MakeFptr, "\n\n"); + FVPtr = mNonFfsFVList; + while (FVPtr != NULL) { + // + // Save the position in the file + // + DSCFileSavePosition (DSC); + // + // first try to find a build section specific for this fv. + // + sprintf (Str, "build.fv.%s", FVPtr->FVFileName); + Section = DSCFileFindSection (DSC, Str); + if (Section == NULL) { + sprintf (Str, "build.fv"); + Section = DSCFileFindSection (DSC, Str); + } + + if (Section == NULL) { + Warning ( + NULL, + 0, + 0, + NULL, + "No [build.fv.%s] nor [%s] section found in description file for building %s", + FVPtr->FVFileName, + Str, + FVPtr->FVFileName + ); + } else { + // + // Add a symbol for the FV filename + // + UpperCaseString (FVPtr->FVFileName); + AddSymbol (FV_FILENAME, FVPtr->FVFileName, SYM_LOCAL | SYM_OVERWRITE); + AddSymbol (EFI_BASE_ADDRESS, FVPtr->BaseAddress, SYM_LOCAL | SYM_OVERWRITE); + + // + // Now copy the build commands from the section to the makefile + // + while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) { + ExpandSymbols ( + Line, + ExpandedLine, + sizeof (ExpandedLine), + EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR + ); + + fprintf (MakeFptr, ExpandedLine); + } + } + + FVPtr = FVPtr->Next; + DSCFileRestorePosition (DSC); + } + } + // + // Go through our list of firmware volumes and create an "fvs" target that + // builds everything. It has to be a mix of components and FV's in order. + // For example: fvs : components_0 fv\fv001.fv fv\fv002.fv components_1 fv\fv003.fv + // + ComponentsInstance = 0; + ComponentCount = 0; + fprintf (MakeFptr, "fvs ::"); + for (;;) { + // + // First see if we have any components for this section. If we don't, + // then we're done + // + for (FileListPtr = mFileList; FileListPtr != NULL; FileListPtr = FileListPtr->Next) { + if (FileListPtr->ComponentsInstance == ComponentsInstance) { + break; + } + } + + if (FileListPtr == NULL) { + break; + } + + fprintf (MakeFptr, " components_%d", ComponentsInstance); + ComponentCount++; + // + // Now print any firmware volumes that match this components instance + // + for (FVPtr = mFVList; FVPtr != NULL; FVPtr = FVPtr->Next) { + if (FVPtr->ComponentsInstance == ComponentsInstance) { + fprintf (MakeFptr, " %s%s.fv", FVDir, FVPtr->FVFileName); + } + } + + ComponentsInstance++; + } + + fprintf (MakeFptr, "\n\n"); + + // + // Create a "components" target for build convenience. It should + // look something like: + // components : components_0 components_1... + // + if (ComponentCount > 0) { + fprintf (MakeFptr, "components :"); + for (ComponentsInstance = 0; ComponentsInstance < ComponentCount; ComponentsInstance++) { + fprintf (MakeFptr, " components_%d", ComponentsInstance); + } + + fprintf (MakeFptr, "\n\n"); + } + // + // Now go through the list of all FV's defined and search for + // a [build.fv.$(FV)] or [build.fv] command and emit the commands to the + // output makefile. + // + FVPtr = mFVList; + while (FVPtr != NULL) { + if (FVPtr->FVFileName[0]) { + // + // Save the position in the file + // + DSCFileSavePosition (DSC); + // + // First try to find a build section specific for this FV. + // + sprintf (Str, "build.fv.%s", FVPtr->FVFileName); + Section = DSCFileFindSection (DSC, Str); + if (Section == NULL) { + sprintf (Str, "build.fv"); + Section = DSCFileFindSection (DSC, Str); + } + + if (Section == NULL) { + Error ( + NULL, + 0, + 0, + NULL, + "no [build.fv.%s] nor [%s] section found in description file for building %s", + FVPtr->FVFileName, + Str, + FVPtr->FVFileName + ); + } else { + // + // Add a symbol for the FV filename + // + UpperCaseString (FVPtr->FVFileName); + AddSymbol (FV_FILENAME, FVPtr->FVFileName, SYM_LOCAL | SYM_OVERWRITE); + AddSymbol (EFI_BASE_ADDRESS, FVPtr->BaseAddress, SYM_LOCAL | SYM_OVERWRITE); + + // + // Now copy the build commands from the section to the makefile + // + while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) { + ExpandSymbols ( + Line, + ExpandedLine, + sizeof (ExpandedLine), + EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR + ); + fprintf (MakeFptr, ExpandedLine); + } + } + + DSCFileRestorePosition (DSC); + } + + FVPtr = FVPtr->Next; + } + // + // Close all the files and free up the memory + // + while (FVList != NULL) { + FVPtr = FVList->Next; + if (FVList->FVFilePtr != NULL) { + SmartClose (FVList->FVFilePtr); + } + + if (FVList->AprioriFilePtr != NULL) { + SmartClose (FVList->AprioriFilePtr); + } + + free (FVList); + FVList = FVPtr; + } + + while (mNonFfsFVList != NULL) { + FVPtr = mNonFfsFVList->Next; + free (mNonFfsFVList); + mNonFfsFVList = FVPtr; + } + + if (XRefFptr != NULL) { + fclose (XRefFptr); + } + + return STATUS_SUCCESS; +} + +int +NonFFSFVWriteInfFiles ( + DSC_FILE *DSC, + char *FileName + ) +/*++ + +Routine Description: + + Generate a Non FFS fv file. It can only some variables, + or simply contains nothing except header. + +Arguments: + + DSC - pointer to a DSC_FILE object to extract info from + FileName - pointer to the fv file + +Returns: + + STATUS_SUCCESS if successful + non-STATUS_SUCCESS otherwise + +--*/ +{ + FV_LIST *FVPtr; + SECTION *Section; + char *StartCptr; + char *EndCptr; + char CSave; + char Str[MAX_PATH]; + char Line[MAX_LINE_LEN]; + char ExpandedLine[MAX_LINE_LEN]; + char FVDir[MAX_PATH]; + + // + // See if they specified a FV directory to dump the FV files out to. If not, + // then use the default. Then create the output directory. + // + DSCFileSavePosition (DSC); + StartCptr = GetSymbolValue (FV_INF_DIR); + if (StartCptr == NULL) { + ExpandSymbols (DEFAULT_FV_INF_DIR, FVDir, sizeof (FVDir), EXPANDMODE_NO_UNDEFS); + } else { + strcpy (FVDir, StartCptr); + } + + // + // Make sure the fv directory path ends in / + // + CSave = FVDir[strlen (FVDir) - 1]; + if ((CSave != '\\') && (CSave != '/')) { + strcat (FVDir, "\\"); + } + + StartCptr = FileName; + while (*StartCptr) { + EndCptr = StartCptr; + while (*EndCptr && (*EndCptr != ',')) { + EndCptr++; + } + + CSave = *EndCptr; + *EndCptr = 0; + // + // Ok, we have a fv name, now see if we've already opened + // an fv output file of this name. + // + for (FVPtr = mNonFfsFVList; FVPtr != NULL; FVPtr = FVPtr->Next) { + if (_stricmp (FVPtr->FVFileName, StartCptr) == 0) { + break; + } + } + // + // If there is already one with the same name, wrong + // + if (FVPtr != NULL) { + DSCFileRestorePosition (DSC); + return STATUS_ERROR; + } + // + // Create a new one, add it to the list + // + FVPtr = (FV_LIST *) malloc (sizeof (FV_LIST)); + if (FVPtr == NULL) { + Error (__FILE__, __LINE__, 0, "failed to allocate memory", NULL); + DSCFileRestorePosition (DSC); + return STATUS_ERROR; + } + + memset ((char *) FVPtr, 0, sizeof (FV_LIST)); + FVPtr->Next = mNonFfsFVList; + mNonFfsFVList = FVPtr; + // + // Save the FV name in the FileName pointer so we can compare + // for any future FV names specified. + // + strcpy (FVPtr->FVFileName, StartCptr); + // + // Add a symbol for the FV filename + // + UpperCaseString (FVPtr->FVFileName); + AddSymbol (FV_FILENAME, FVPtr->FVFileName, SYM_LOCAL | SYM_OVERWRITE); + + // + // Now create the FVx.inf filename from the fv name and + // default filename extension. Dump it in the FV directory + // as well. + // + strcpy (Str, FVDir); + strcat (Str, FVPtr->FVFileName); + strcat (Str, ".inf"); + // + // Create the directory path for our new fv.inf output file. + // + MakeFilePath (Str); + if ((FVPtr->FVFilePtr = SmartOpen (Str)) == NULL) { + Error (NULL, 0, 0, Str, "could not open FV output file"); + DSCFileRestorePosition (DSC); + return STATUS_ERROR; + } + // + // Now copy the [fv.fvfile.options] to the fv file + // + sprintf (Str, "fv.%s.options", StartCptr); + Section = DSCFileFindSection (DSC, Str); + if (Section != NULL) { + SmartWrite (FVPtr->FVFilePtr, "[options]\n"); + while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) { + ExpandSymbols (Line, ExpandedLine, sizeof (ExpandedLine), 0); + SmartWrite (FVPtr->FVFilePtr, ExpandedLine); + GetBaseAddress (ExpandedLine, FVPtr->BaseAddress); + } + } else { + Warning (NULL, 0, 0, NULL, "Could not find FV section '%s' in description file", Str); + } + // + // Copy the [fv.fvfile.attributes] to the fv file + // + sprintf (Str, "fv.%s.attributes", StartCptr); + Section = DSCFileFindSection (DSC, Str); + if (Section != NULL) { + SmartWrite (FVPtr->FVFilePtr, "[attributes]\n"); + while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) { + ExpandSymbols (Line, ExpandedLine, sizeof (ExpandedLine), 0); + SmartWrite (FVPtr->FVFilePtr, ExpandedLine); + } + } else { + Warning (NULL, 0, 0, NULL, "Could not find FV section '%s' in description file", Str); + } + // + // Copy the [fv.fvfile.components] to the fv file + // + sprintf (Str, "fv.%s.components", StartCptr); + Section = DSCFileFindSection (DSC, Str); + if (Section != NULL) { + SmartWrite (FVPtr->FVFilePtr, "[components]\n"); + while (DSCFileGetLine (DSC, Line, sizeof (Line)) != NULL) { + ExpandSymbols (Line, ExpandedLine, sizeof (ExpandedLine), 0); + SmartWrite (FVPtr->FVFilePtr, ExpandedLine); + } + } else { + // + // An empty FV is allowed to contain nothing + // + } + // + // Close the file + // + SmartClose (FVPtr->FVFilePtr); + // + // Next FV in FileName + // + *EndCptr = CSave; + StartCptr = EndCptr; + if (*StartCptr) { + StartCptr++; + } + } + + DSCFileRestorePosition (DSC); + return STATUS_SUCCESS; +} + +static +void +AddFirmwareVolumes ( + char *FVs, + int ComponentsInstance, + FILE_LIST *FileListPtr + ) +{ + FV_LIST *FvPtr; + char *StartPtr; + char *EndPtr; + char SaveChar; + + if ((FVs != NULL) && (FVs[0] != 0)) { + // + // Extract each FV name from the string. It's from the DSC file "FV=FvRecover,FvMain" + // + StartPtr = FVs; + while (*StartPtr != 0) { + EndPtr = StartPtr; + while (*EndPtr && (*EndPtr != ',')) { + EndPtr++; + } + + SaveChar = *EndPtr; + *EndPtr = 0; + // + // Look through our list of known firmware volumes and see if we've + // already added it. + // + for (FvPtr = mFVList; FvPtr != NULL; FvPtr = FvPtr->Next) { + if (_stricmp (FvPtr->FVFileName, StartPtr) == 0) { + break; + } + } + // + // If we didn't find a match, then create a new one + // + if (FvPtr == NULL) { + FvPtr = MALLOC (sizeof (FV_LIST)); + if (FvPtr == NULL) { + Error (__FILE__, __LINE__, 0, "application error", "memory allocation failed"); + return ; + } + + memset (FvPtr, 0, sizeof (FV_LIST)); + strcpy (FvPtr->FVFileName, StartPtr); + if (mFVList == NULL) { + mFVList = FvPtr; + } else { + mFVListLast->Next = FvPtr; + } + + mFVListLast = FvPtr; + } + // + // If this component's section number is higher than that of this + // FV, then set the FV's to it. + // + if (FvPtr->ComponentsInstance < ComponentsInstance) { + FvPtr->ComponentsInstance = ComponentsInstance; + } + // + // If we found then end of the FVs in the string, then we're done. + // Always restore the original string's contents. + // + if (SaveChar != 0) { + *EndPtr = SaveChar; + StartPtr = EndPtr + 1; + } else { + StartPtr = EndPtr; + } + } + } +} + +static +BOOLEAN +OrderInFvList ( + char *FvList, + char *FvName, + int *Order + ) +{ + // + // Given FvList of format "FV_a,FV_b,FV_c" or "FV_a:1,FV_b:2" and + // FvName of format "FV_c", determine if FvName is in FvList. If + // FV_a:1 format, then return the value after the colon. + // + while (*FvList) { + // + // If it matches for the length of FvName... + // + if (_strnicmp (FvList, FvName, strlen (FvName)) == 0) { + // + // Then see if the match string in FvList is terminated at the + // same length. + // + if ((FvList[strlen (FvName)] == ',') || (FvList[strlen (FvName)] == 0)) { + *Order = 0; + return TRUE; + } else if (FvList[strlen (FvName)] == ':') { + *Order = atoi (FvList + strlen (FvName) + 1); + return TRUE; + } + } + // + // Skip to next FV in the comma-separated list + // + while ((*FvList != ',') && (*FvList != 0)) { + FvList++; + } + // + // Skip over comma + // + if (*FvList == ',') { + FvList++; + } + } + + return FALSE; +} + +static +char * +UpperCaseString ( + char *Str + ) +{ + char *Cptr; + + for (Cptr = Str; *Cptr; Cptr++) { + *Cptr = (char) toupper (*Cptr); + } + + return Str; +} + +static +BOOLEAN +InSameFv ( + char *FVs1, + char *FVs2 +) +{ + char *StartCptr1; + char *StartCptr2; + char *EndCptr1; + char *EndCptr2; + char CSave1; + char CSave2; + + // + // Process each FV in first FV list + // + StartCptr1 = FVs1; + while (*StartCptr1) { + EndCptr1 = StartCptr1; + while (*EndCptr1 && (*EndCptr1 != ',')) { + EndCptr1++; + } + + CSave1 = *EndCptr1; + *EndCptr1 = 0; + + if (*StartCptr1) { + // + // Process each FV in second FV list + // + StartCptr2 = FVs2; + while (*StartCptr2) { + EndCptr2 = StartCptr2; + while (*EndCptr2 && (*EndCptr2 != ',')) { + EndCptr2++; + } + + CSave2 = *EndCptr2; + *EndCptr2 = 0; + + if (_stricmp (StartCptr1, StartCptr2) == 0) { + *EndCptr1 = CSave1; + *EndCptr2 = CSave2; + return TRUE; + } + + // + // Next FV on the second FV list + // + *EndCptr2 = CSave2; + StartCptr2 = EndCptr2; + if (*StartCptr2) { + StartCptr2++; + } + } + } + + // + // Next FV on the first FV list + // + *EndCptr1 = CSave1; + StartCptr1 = EndCptr1; + if (*StartCptr1) { + StartCptr1++; + } + } + + return FALSE; +} + +int +CFVSetXRefFileName ( + char *FileName + ) +{ + mXRefFileName = FileName; + return 0; +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/FWVolume.h b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/FWVolume.h new file mode 100644 index 0000000000..4a7af36e73 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/FWVolume.h @@ -0,0 +1,76 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + FWVolume.h + +Abstract: + + Include file for the module that keeps track of files for the firmware + volumes. + +--*/ + +#ifndef _FW_VOLUME_H_ +#define _FW_VOLUME_H_ + +// +// class CFirmwareVolume +// { +// public: +// +void +CFVConstructor ( + VOID + ) +; +void +CFVDestructor ( + VOID + ) +; + +int +CFVAddFVFile ( + char *Name, + char *ComponentType, + char *FVs, + int ComponentsInstance, + char *FFSExt, + char *Processor, + char *Apriori, + char *BaseName, + char *Guid + ) +; + +int +CFVSetXRefFileName ( + char *FileName + ) +; + +int +CFVWriteInfFiles ( + DSC_FILE *DSC, + FILE *MakeFptr + ) +; + +int +NonFFSFVWriteInfFiles ( + DSC_FILE *DSC, + char *FileName + ) +; + +#endif // ifndef _FW_VOLUME_H_ diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Makefile new file mode 100644 index 0000000000..c835a80025 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Makefile @@ -0,0 +1,102 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Makefile +# +# Abstract: +# +# makefile for building the ProcessDsc utility. +# +#--*/ + +# +# Make sure environmental variable EDK_SOURCE is set +# +!IFNDEF EDK_SOURCE +!ERROR EDK_SOURCE environmental variable not set +!ENDIF + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Target specific information +# + +TARGET_NAME = ProcessDsc +TARGET_SRC_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\ProcessDsc.exe + +# +# Build targets +# + +all: $(TARGET_EXE) + +INC_DEPS = $(TARGET_SRC_DIR)\DSCFile.h $(INC_DEPS) +INC_DEPS = $(TARGET_SRC_DIR)\FWVolume.h $(INC_DEPS) +INC_DEPS = $(TARGET_SRC_DIR)\Exceptions.h $(INC_DEPS) +INC_DEPS = $(TARGET_SRC_DIR)\Common.h $(INC_DEPS) + +LIBS = $(LIBS) "$(EDK_TOOLS_OUTPUT)\Common.lib" + +OBJECTS = $(EDK_TOOLS_OUTPUT)\DSCFile.obj \ + $(EDK_TOOLS_OUTPUT)\FWVolume.obj \ + $(EDK_TOOLS_OUTPUT)\ProcessDsc.obj \ + $(EDK_TOOLS_OUTPUT)\Exceptions.obj + +# +# Compile each source file +# + +$(EDK_TOOLS_OUTPUT)\DSCFile.obj : $(TARGET_SRC_DIR)\DSCFile.c $(INC_DEPS) + $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\DSCFile.c /Fo$@ + +$(EDK_TOOLS_OUTPUT)\FWVolume.obj : $(TARGET_SRC_DIR)\FWVolume.c $(INC_DEPS) + $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\FWVolume.c /Fo$@ + +$(EDK_TOOLS_OUTPUT)\ProcessDsc.obj : $(TARGET_SRC_DIR)\ProcessDsc.c $(INC_DEPS) + $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\ProcessDsc.c /Fo$@ + +$(EDK_TOOLS_OUTPUT)\Exceptions.obj : $(TARGET_SRC_DIR)\Exceptions.c $(INC_DEPS) + $(CC) $(C_FLAGS) $(TARGET_SRC_DIR)\Exceptions.c /Fo$@ + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE) : $(OBJECTS) $(LIBS) + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL + @if exist $(EDK_TOOLS_OUTPUT)\DscFile.* del $(EDK_TOOLS_OUTPUT)\DscFile.* > NUL + @if exist $(EDK_TOOLS_OUTPUT)\Exceptions* del $(EDK_TOOLS_OUTPUT)\Exceptions.* > NUL + @if exist $(EDK_TOOLS_OUTPUT)\FwVolume.* del $(EDK_TOOLS_OUTPUT)\FwVolume.* > NUL diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/ProcessDsc.c b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/ProcessDsc.c new file mode 100644 index 0000000000..4833b78e0d --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/ProcessDsc.c @@ -0,0 +1,4726 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + ProcessDsc.c + +Abstract: + + Main module for the ProcessDsc utility. + +--*/ + +#include // for GetShortPathName() +#include +#include +#include +#include +#include // for _mkdir() +#include +#include // for getenv() +#include "DSCFile.h" +#include "FWVolume.h" +#include "Exceptions.h" +#include "Common.h" + +#include "EfiUtilityMsgs.h" +#include "TianoBind.h" +// +// Disable warning for while(1) code +// +#pragma warning(disable : 4127) +// +// Disable warning for unreferenced function parameters +// +#pragma warning(disable : 4100) + +extern int errno; + +#define PROGRAM_NAME "ProcessDsc" + +// +// Common symbol name definitions. For example, the user can reference +// $(BUILD_DIR) in their DSC file and we will expand it for them (usually). +// I've defined the equivalents here in case we want to change the name the +// user references, in which case we just change the string value here and +// our code still works. +// +#define BUILD_DIR "BUILD_DIR" +#define EFI_SOURCE "EFI_SOURCE" +#define DEST_DIR "DEST_DIR" +#define SOURCE_DIR "SOURCE_DIR" +#define LIB_DIR "LIB_DIR" +#define BIN_DIR "BIN_DIR" +#define OUT_DIR "OUT_DIR" +#define INF_FILENAME "INF_FILENAME" +#define SOURCE_RELATIVE_PATH "SOURCE_RELATIVE_PATH" +#define SOURCE_BASE_NAME "SOURCE_BASE_NAME" +#define SOURCE_FILE_NAME "SOURCE_FILE_NAME" // c:\FullPath\File.c +#define PROCESSOR "PROCESSOR" +#define FV "FV" +#define BASE_NAME "BASE_NAME" +#define GUID "GUID" +#define FILE_GUID "FILE_GUID" +#define COMPONENT_TYPE_FILE "FILE" +#define BUILD_TYPE "BUILD_TYPE" +#define FFS_EXT "FFS_EXT" // FV_EXT is deprecated -- extension of FFS file +#define MAKEFILE_NAME "MAKEFILE_NAME" // name of component's output makefile +#define PLATFORM "PLATFORM" // for more granularity +#define PACKAGE_FILENAME "PACKAGE_FILENAME" +#define PACKAGE "PACKAGE" +#define PACKAGE_TAG "PACKAGE_TAG" // alternate name to PACKAGE +#define SHORT_NAMES "SHORT_NAMES" // for 8.3 names of symbols +#define APRIORI "APRIORI" // to add to apriori list +#define OPTIONAL_COMPONENT "OPTIONAL" // define as non-zero for optional INF files +#define SOURCE_SELECT "SOURCE_SELECT" // say SOURCE_SELECT=smm,common to select INF sources +#define NONFFS_FV "NONFFS_FV" // for non-FFS FV such as working & spare block FV +#define SKIP_FV_NULL "SKIP_FV_NULL" // define as nonzero to not build components with FV=NULL +#define SOURCE_COMPILE_TYPE "SOURCE_COMPILE_TYPE" // to build a source using a custom build section in the DSC file +#define SOURCE_FILE_EXTENSION "SOURCE_FILE_EXTENSION" +#define COMPILE_SELECT "COMPILE_SELECT" +#define SOURCE_OVERRIDE_PATH "SOURCE_OVERRIDE_PATH" // get source files from here first +#define MAKEFILE_OUT_SECTION_NAME "makefile.out" +#define COMMON_SECTION_NAME "common" // shared files or functionality +#define NMAKE_SECTION_NAME "nmake" +#define SOURCES_SECTION_NAME "sources" +#define COMPONENTS_SECTION_NAME "components" +#define INCLUDE_SECTION_NAME "includes" +#define DEFINES_SECTION_NAME "defines" +#define LIBRARIES_SECTION_NAME "libraries" +#define LIBRARIES_PLATFORM_SECTION_NAME "libraries.platform" +#define MAKEFILE_SECTION_NAME "makefile" +#define COMPONENT_TYPE "component_type" +#define PLATFORM_STR "\\platform\\" // to determine EFI_SOURCE +#define MAKEFILE_OUT_NAME "makefile.out" // if not specified on command line +#define MODULE_MAKEFILE_NAME "module.mak" // record all module makefile targets +#define MODULE_NAME_FILE "module.list" // record all module names defined in the dsc file +#define GLOBAL_LINK_LIB_NAME "CompilerStub" // Lib added in link option, maybe removed in the future +#define MODULE_BASE_NAME_WIDTH 25 // Width for module name output + +// +// When a symbol is defined as "NULL", it gets saved in the symbol table as a 0-length +// string. Use this macro to detect if a symbol has been defined this way. +// +#define IS_NULL_SYMBOL_VALUE(var) ((var != NULL) && (strlen (var) == 0)) + +// +// Defines for file types +// +#define FILETYPE_UNKNOWN 0 +#define FILETYPE_C 1 +#define FILETYPE_ASM 2 +#define FILETYPE_S 3 +#define FILETYPE_VFR 4 +#define FILETYPE_INC 5 +#define FILETYPE_H 6 +#define FILETYPE_I 7 + + +typedef struct { + INT8 *Extension; // file extension + INT8 *BuiltExtension; + INT8 FileFlags; + int FileType; +} FILETYPE; + +// +// Define masks for the FileFlags field +// +#define FILE_FLAG_INCLUDE 0x01 +#define FILE_FLAG_SOURCE 0x02 + +// +// This table describes a from-to list of files. For +// example, when a ".c" is built, it results in a ".obj" file. +// +static const FILETYPE mFileTypes[] = { + { + ".c", + ".obj", + FILE_FLAG_SOURCE, + FILETYPE_C + }, + { + ".asm", + ".obj", + FILE_FLAG_SOURCE, + FILETYPE_ASM + }, + { + ".s", + ".obj", + FILE_FLAG_SOURCE, + FILETYPE_S + }, + { + ".vfr", + ".obj", + FILE_FLAG_SOURCE, + FILETYPE_VFR + }, // actually *.vfr -> *.c -> *.obj + { + ".h", + NULL, + FILE_FLAG_INCLUDE, + FILETYPE_H + }, + { + ".inc", + NULL, + FILE_FLAG_INCLUDE, + FILETYPE_INC + }, + { + ".i", + NULL, + FILE_FLAG_INCLUDE, + FILETYPE_I + }, + { + NULL, + NULL, + 0, + 0 + } +}; + +// +// Structure to split up a file into its different parts. +// +typedef struct { + INT8 Drive[3]; + INT8 *Path; + INT8 *BaseName; + INT8 *Extension; + int ExtensionCode; +} FILE_NAME_PARTS; + +// +// Maximum length for any line in any file after symbol expansion +// +#define MAX_EXP_LINE_LEN (MAX_LINE_LEN * 2) + +// +// Linked list to keep track of all symbols +// +typedef struct _SYMBOL { + struct _SYMBOL *Next; + int Type; // local or global symbol + INT8 *Name; + INT8 *Value; +} SYMBOL; + +// +// Define new SYMBOL list to record all module name used in the platform.dsc file. +// +SYMBOL *gModuleList = NULL; + +// +// This structure is used to save globals +// +struct { + INT8 *DscFilename; + SYMBOL *Symbol; + INT8 MakefileName[MAX_PATH]; // output makefile name + INT8 XRefFileName[MAX_PATH]; + INT8 GuidDatabaseFileName[MAX_PATH]; + INT8 ModuleMakefileName[MAX_PATH]; + FILE *MakefileFptr; + FILE *ModuleMakefileFptr; + SYMBOL *ModuleList; + SYMBOL *OutdirList; + UINT32 Verbose; +} gGlobals; + +// +// This gets dumped to the head of makefile.out +// +static const INT8 *MakefileHeader[] = { + "#/*++", + "#", + "# DO NOT EDIT", + "# File auto-generated by build utility", + "#", + "# Module Name:", + "#", + "# makefile", + "#", + "# Abstract:", + "#", + "# Auto-generated makefile for building of EFI components/libraries", + "#", + "#--*/", + "", + NULL +}; + +// +// Function prototypes +// +static +int +ProcessOptions ( + int Argc, + INT8 *Argv[] + ); + +static +void +Usage ( + VOID + ); + +static +INT8 * +StripLine ( + INT8 *Line + ); + +static +STATUS +ParseGuidDatabaseFile ( + INT8 *FileName + ); + +#define DSC_SECTION_TYPE_COMPONENTS 0 +#define DSC_SECTION_TYPE_LIBRARIES 1 +#define DSC_SECTION_TYPE_PLATFORM_LIBRARIES 2 + +static +int +ProcessSectionComponents ( + DSC_FILE *DscFile, + int DscSectionType, + int Instance + ); +static +int +ProcessComponentFile ( + DSC_FILE *DscFile, + INT8 *Line, + int DscSectionType, + int Instance + ); +static +int +ProcessIncludeFiles ( + DSC_FILE *ComponentFile, + FILE *MakeFptr + ); +static + +int +ProcessIncludeFilesSingle ( + DSC_FILE *ComponentFile, + FILE *MakeFptr, + INT8 *SectionName + ); + +// +// Mode flags for processing source files +// +#define SOURCE_MODE_BUILD_COMMANDS 0x01 +#define SOURCE_MODE_SOURCE_FILES 0x02 + +static +int +ProcessSourceFiles ( + DSC_FILE *DSCFile, + DSC_FILE *ComponentFile, + FILE *MakeFptr, + UINT32 Mode + ); + +static +int +ProcessSourceFilesSection ( + DSC_FILE *DSCFile, + DSC_FILE *ComponentFile, + FILE *MakeFptr, + INT8 *SectionName, + UINT32 Mode + ); + +static +int +ProcessObjects ( + DSC_FILE *ComponentFile, + FILE *MakeFptr + ); + +static +int +ProcessObjectsSingle ( + DSC_FILE *ComponentFile, + FILE *MakeFptr, + INT8 *SectionName + ); + +static +int +ProcessLibs ( + DSC_FILE *ComponentFile, + FILE *MakeFptr + ); + +static +int +ProcessLibsSingle ( + DSC_FILE *ComponentFile, + FILE *MakeFptr, + INT8 *SectionName + ); + +static +int +ProcessIncludesSection ( + DSC_FILE *ComponentFile, + FILE *MakeFptr + ); + +static +int +ProcessIncludesSectionSingle ( + DSC_FILE *ComponentFile, + FILE *MakeFptr, + INT8 *SectionName + ); + +static +int +ProcessINFNMakeSection ( + DSC_FILE *ComponentFile, + FILE *MakeFptr + ); + +static +int +ProcessINFDefinesSection ( + DSC_FILE *ComponentFile + ); + +static +int +ProcessINFDefinesSectionSingle ( + DSC_FILE *ComponentFile, + INT8 *SectionName + ); + +static +int +ProcessSectionLibraries ( + DSC_FILE *DscFile, + long Offset + ); + +static +int +ProcessDSCDefinesSection ( + DSC_FILE *DscFile + ); + +static +int +SetSymbolType ( + INT8 *SymbolName, + INT8 Type + ); + +static +int +RemoveLocalSymbols ( + VOID + ); + +static +int +RemoveFileSymbols ( + VOID + ); + +static +int +RemoveSymbol ( + INT8 *Name, + INT8 SymbolType + ); + +static +int +SetFileExtension ( + INT8 *FileName, + INT8 *Extension + ); + +static +int +GetSourceFileType ( + INT8 *FileName + ); + +static +int +IsIncludeFile ( + INT8 *FileName + ); + +static +int +WriteCompileCommands ( + DSC_FILE *DscFile, + FILE *MakeFptr, + INT8 *FileName, + INT8 *Processor + ); + +static +int +WriteCommonMakefile ( + DSC_FILE *DscFile, + FILE *MakeFptr, + INT8 *Processor + ); + +static +int +WriteComponentTypeBuildCommands ( + DSC_FILE *DscFile, + FILE *MakeFptr, + INT8 *SectionName + ); + +static +void +StripTrailingSpaces ( + INT8 *Str + ); + +static +void +FreeFileParts ( + FILE_NAME_PARTS *FP + ); + +static +FILE_NAME_PARTS * +GetFileParts ( + INT8 *FileName + ); + +static +SYMBOL * +FreeSymbols ( + SYMBOL *Syms + ); + +static +int +GetEfiSource ( + VOID + ); + +static +int +CreatePackageFile ( + DSC_FILE *DSCFile + ); + +static +INT8 * +BuiltFileExtension ( + INT8 *SourceFileName + ); + +static +void +SmartFree ( + SMART_FILE *SmartFile + ); + +static +int +AddModuleName ( + SYMBOL **SymbolList, + INT8 *ModuleName, + INT8 *InfName + ); + +/*****************************************************************************/ +int +main ( + int Argc, + INT8 *Argv[] + ) +/*++ + +Routine Description: + + Main utility entry point. + +Arguments: + + Argc - Standard app entry point args. + Argv - Standard app entry point args. + +Returns: + + 0 if successful + non-zero otherwise + +--*/ +{ + int i; + DSC_FILE DSCFile; + SECTION *Sect; + INT8 Line[MAX_LINE_LEN]; + INT8 ExpLine[MAX_LINE_LEN]; + INT8 *EMsg; + FILE *FpModule; + SYMBOL *TempSymbol; + + SetUtilityName (PROGRAM_NAME); + + InitExceptions (); + + DSCFileInit (&DSCFile); + // + // Initialize the firmware volume data + // + CFVConstructor (); + // + // Exception handling for this block of code. + // + TryException (); + // + // Process command-line options. + // + if (ProcessOptions (Argc, Argv)) { + EMsg = CatchException (); + if (EMsg != NULL) { + fprintf (stderr, "%s\n", EMsg); + } + + return STATUS_ERROR; + } + // + // Parse the GUID database file if specified + // + if (gGlobals.GuidDatabaseFileName[0] != 0) { + ParseGuidDatabaseFile (gGlobals.GuidDatabaseFileName); + } + // + // Set the output cross-reference file if applicable + // + if (gGlobals.XRefFileName[0]) { + CFVSetXRefFileName (gGlobals.XRefFileName); + } + + // + // Now get the EFI_SOURCE directory which we use everywhere. + // + if (GetEfiSource ()) { + return STATUS_ERROR; + } + + // + // Pre-process the DSC file to get section info. + // + if (DSCFileSetFile (&DSCFile, gGlobals.DscFilename) != 0) { + goto ProcessingError; + } + + // + // Set output makefile name for single module build + // + strcpy (gGlobals.ModuleMakefileName, MODULE_MAKEFILE_NAME); + + // + // Try to open all final output makefiles + // + if ((gGlobals.MakefileFptr = fopen (gGlobals.MakefileName, "w")) == NULL) { + Error (NULL, 0, 0, gGlobals.MakefileName, "failed to open output makefile for writing"); + goto ProcessingError; + } + if ((gGlobals.ModuleMakefileFptr = fopen (gGlobals.ModuleMakefileName, "w")) == NULL) { + Error (NULL, 0, 0, gGlobals.ModuleMakefileName, "failed to open output makefile for writing"); + goto ProcessingError; + } + + // + // Write the header out to the makefiles + // + for (i = 0; MakefileHeader[i] != NULL; i++) { + fprintf (gGlobals.MakefileFptr, "%s\n", MakefileHeader[i]); + fprintf (gGlobals.ModuleMakefileFptr, "%s\n", MakefileHeader[i]); + } + + // + // Init global potint = NULL + // + gGlobals.ModuleList = NULL; + gGlobals.OutdirList = NULL; + + // + // Process the [defines] section in the DSC file to get any defines we need + // elsewhere + // + ProcessDSCDefinesSection (&DSCFile); + if (ExceptionThrown ()) { + goto ProcessingError; + } + // + // Write out the [makefile.out] section data to the output makefiles + // + Sect = DSCFileFindSection (&DSCFile, MAKEFILE_OUT_SECTION_NAME); + if (Sect != NULL) { + while (DSCFileGetLine (&DSCFile, Line, sizeof (Line)) != NULL) { + ExpandSymbols (Line, ExpLine, sizeof (ExpLine), 0); + // + // Write the line to the output makefiles + // + fprintf (gGlobals.MakefileFptr, ExpLine); + fprintf (gGlobals.ModuleMakefileFptr, ExpLine); + } + } + + // + // Add a pseudo target for GLOBAL_LINK_LIB_NAME to avoid single module build + // failure when this lib is not used. + // + fprintf (gGlobals.ModuleMakefileFptr, "%sbuild ::\n\n", GLOBAL_LINK_LIB_NAME); + + fprintf (gGlobals.MakefileFptr, "libraries : \n"); + // + // Process [libraries] section in the DSC file + // + Sect = DSCFileFindSection (&DSCFile, LIBRARIES_SECTION_NAME); + if (Sect != NULL) { + ProcessSectionComponents (&DSCFile, DSC_SECTION_TYPE_LIBRARIES, 0); + } + + if (ExceptionThrown ()) { + goto ProcessingError; + } + // + // Process [libraries.platform] section in the DSC file + // + Sect = DSCFileFindSection (&DSCFile, LIBRARIES_PLATFORM_SECTION_NAME); + if (Sect != NULL) { + ProcessSectionComponents (&DSCFile, DSC_SECTION_TYPE_PLATFORM_LIBRARIES, 0); + } + + fprintf (gGlobals.MakefileFptr, "\n"); + if (ExceptionThrown ()) { + goto ProcessingError; + } + + // + // Process [components] section in the DSC file + // + Sect = DSCFileFindSection (&DSCFile, COMPONENTS_SECTION_NAME); + if (Sect != NULL) { + fprintf (gGlobals.MakefileFptr, "components_0 : \n"); + ProcessSectionComponents (&DSCFile, DSC_SECTION_TYPE_COMPONENTS, 0); + fprintf (gGlobals.MakefileFptr, "\n"); + } + + if (ExceptionThrown ()) { + goto ProcessingError; + } + // + // Now cycle through all [components.1], [components.2], ....[components.n]. + // This is necessary to support building of firmware volumes that may contain + // other encapsulated firmware volumes (ala capsules). + // + i = 1; + while (1) { + RemoveSymbol (FV, SYM_GLOBAL); + sprintf (Line, "%s.%d", COMPONENTS_SECTION_NAME, i); + Sect = DSCFileFindSection (&DSCFile, Line); + if (Sect != NULL) { + fprintf (gGlobals.MakefileFptr, "components_%d : \n", i); + ProcessSectionComponents (&DSCFile, DSC_SECTION_TYPE_COMPONENTS, i); + fprintf (gGlobals.MakefileFptr, "\n"); + } else { + break; + } + + if (ExceptionThrown ()) { + goto ProcessingError; + } + + i++; + } + +ProcessingError: + EMsg = CatchException (); + if (EMsg != NULL) { + fprintf (stderr, "%s\n", EMsg); + fprintf (stderr, "Processing aborted\n"); + } + + TryException (); + // + // Create the FV files if no fatal errors or errors + // + if (GetUtilityStatus () < STATUS_ERROR) { + CFVWriteInfFiles (&DSCFile, gGlobals.MakefileFptr); + } + + // + // Write all module name into MODULE_NAME_FILE file. + // + if ((FpModule = fopen (MODULE_NAME_FILE, "w")) != NULL) { + TempSymbol = gGlobals.ModuleList; + while (TempSymbol != NULL) { + fprintf (FpModule, " %-*s %s \n", MODULE_BASE_NAME_WIDTH, TempSymbol->Name, TempSymbol->Value); + TempSymbol = TempSymbol->Next; + } + fclose (FpModule); + FpModule = NULL; + } + + // + // Close the all the output makefiles + // + if (gGlobals.MakefileFptr != NULL) { + fclose (gGlobals.MakefileFptr); + gGlobals.MakefileFptr = NULL; + } + + if (gGlobals.ModuleMakefileFptr != NULL) { + fclose (gGlobals.ModuleMakefileFptr); + gGlobals.ModuleMakefileFptr = NULL; + } + + // + // Clean up + // + FreeSymbols (gGlobals.ModuleList); + FreeSymbols (gGlobals.OutdirList); + FreeSymbols (gGlobals.Symbol); + gGlobals.Symbol = NULL; + CFVDestructor (); + DSCFileDestroy (&DSCFile); + + EMsg = CatchException (); + if (EMsg != NULL) { + fprintf (stderr, "%s\n", EMsg); + fprintf (stderr, "Processing aborted\n"); + } + + return GetUtilityStatus (); +} + +static +int +ProcessSectionComponents ( + DSC_FILE *DSCFile, + int DscSectionType, + int Instance + ) +/*++ + +Routine Description: + + Process the [components] or [libraries] section in the description file. We + use this function for both since they're very similar. Here we just + read each line from the section, and if it's valid, call a function to + do the actual processing of the component description file. + +Arguments: + + DSCFile - structure containing section info on the description file + DscSectionType - type of description section + +Returns: + + 0 if successful + +--*/ +{ + INT8 Line[MAX_LINE_LEN]; + INT8 Line2[MAX_EXP_LINE_LEN]; + INT8 *Cptr; + + // + // Read lines while they're valid + // + while (DSCFileGetLine (DSCFile, Line, sizeof (Line)) != NULL) { + // + // Expand symbols on the line + // + if (ExpandSymbols (Line, Line2, sizeof (Line2), 0)) { + return STATUS_ERROR; + } + // + // Strip the line + // + Cptr = StripLine (Line2); + if (*Cptr) { + Message (2, "Processing component line: %s", Line2); + if (ProcessComponentFile (DSCFile, Line2, DscSectionType, Instance) != 0) { + return STATUS_ERROR; + } + } + } + + return 0; +} + +static +int +ProcessComponentFile ( + DSC_FILE *DSCFile, + INT8 *ArgLine, + int DscSectionType, + int Instance + ) +/*++ + +Routine Description: + + Given a line from the [components] or [libraries] section of the description + file, process the line to extract the component's INF filename and + parameters. Then open the INF file and process it to create a corresponding + makefile. + +Arguments: + + DSCFile The project DSC file info structure. + Libs Indicates whether we're processing the [components] + section or the [libraries] section. + ArgLine The actual line from the DSC file. Looks something like + one of the following: + + dxe\drivers\vm\vm.dsc PROCESSOR=IA32 DEST_DIR=$(DEST_DIR)\xxx FV=FV1,FV2 + $(BUILD_DIR).\FvVariable.ffs COMPONENT_TYPE=FILE + .\FvVariable.ffs COMPONENT_TYPE=FILE + define VAR1=value1 VAR2=value2 + +Returns: + + 0 if successful + +--*/ +{ + FILE *MakeFptr; + FILE *TempFptr; + INT8 *Cptr; + INT8 *name; + INT8 *End; + INT8 *TempCptr; + INT8 FileName[MAX_PATH]; + INT8 ComponentFilePath[MAX_PATH]; + INT8 InLine[MAX_LINE_LEN]; + INT8 Line[MAX_LINE_LEN]; + INT8 *Processor; + INT8 SymType; + int Len; + int ComponentCreated; + int ComponentFilePathAbsolute; + int DefineLine; + DSC_FILE ComponentFile; + INT8 ComponentMakefileName[MAX_PATH]; + BOOLEAN IsForFv; + + // + // Now remove all local symbols + // + RemoveLocalSymbols (); + // + // Null out the file pointer in case we take an exception somewhere + // and we need to close it only if we opened it. + // + MakeFptr = NULL; + ComponentFilePathAbsolute = 0; + ComponentCreated = 0; + // + // Skip preceeding spaces on the line + // + while (isspace (*ArgLine) && (*ArgLine)) { + ArgLine++; + } + // + // Find the end of the component's filename and truncate the line at that + // point. From here on out ArgLine is the name of the component filename. + // + Cptr = ArgLine; + while (!isspace (*Cptr) && *Cptr) { + Cptr++; + } + + End = Cptr; + if (*Cptr) { + End++; + *Cptr = 0; + } + // + // Exception-handle processing of this component description file + // + TryException (); + + // + // We also allow a component line format for defines of global symbols + // instead of a component filename. In this case, the line looks like: + // defines x=abc y=yyy. Be nice and accept "define" and "defines" in a + // case-insensitive manner. If it's defines, then make the symbols global. + // + if ((_stricmp (ArgLine, "define") == 0) || (_stricmp (ArgLine, "defines") == 0)) { + SymType = SYM_OVERWRITE | SYM_GLOBAL; + DefineLine = 1; + } else { + SymType = SYM_OVERWRITE | SYM_LOCAL; + DefineLine = 0; + } + // + // The rest of the component line from the DSC file should be defines + // + while (*End) { + End = StripLine (End); + if (*End) { + // + // If we're processing a "define abc=1 xyz=2" line, then set symbols + // as globals per the SymType set above. + // + Len = AddSymbol (End, NULL, SymType); + if (Len > 0) { + End += Len; + } else { + Warning (NULL, 0, 0, ArgLine, "unrecognized option in description file"); + break; + } + } + } + + // + // If DEBUG_BREAK or EFI_BREAKPOINT is defined, then do a debug breakpoint. + // + if ((GetSymbolValue ("DEBUG_BREAK") != NULL) || (GetSymbolValue ("EFI_BREAKPOINT") != NULL)) { + EFI_BREAKPOINT (); + } + + // + // If it's a define line, then we're done + // + if (DefineLine) { + // + // If there is NonFFS_FV, create the FVxxx.inf file + // and include it in makefile.out. Remove the symbol + // in order not to process it again next time + // + Cptr = GetSymbolValue (NONFFS_FV); + if (Cptr != NULL) { + NonFFSFVWriteInfFiles (DSCFile, Cptr); + RemoveSymbol (NONFFS_FV, SYM_GLOBAL); + } + + goto ComponentDone; + } + + // + // Expand symbols in the component description filename to expand the newly + // added local symbols + // + ExpandSymbols (ArgLine, Line, sizeof (Line), EXPANDMODE_NO_UNDEFS); + + // + // If we have "c:\path\filename" + // + if (IsAbsolutePath (Line)) { + ComponentFilePathAbsolute = 1; + } else if (Line[0] == '.') { + // + // or if the path starts with ".", then it's build-dir relative. + // Prepend $(BUILD_DIR) on the file name + // + sprintf (InLine, "%s\\%s", GetSymbolValue (BUILD_DIR), Line); + strcpy (Line, InLine); + ComponentFilePathAbsolute = 1; + } + + // + // Save the path from the component name for later. It may be relative or + // absolute. + // + strcpy (ComponentFilePath, Line); + Cptr = ComponentFilePath + strlen (ComponentFilePath) - 1; + while ((*Cptr != '\\') && (*Cptr != '/') && (Cptr != ComponentFilePath)) { + Cptr--; + } + // + // Terminate the path. + // + *Cptr = 0; + + // + // Typically the given line is a component description filename. However we + // also allow a FV filename (fvvariable.ffs COMPONENT_TYPE=FILE). If the + // component type is "FILE", then add it to the FV list, create a package + // file, and we're done. + // + Cptr = GetSymbolValue (COMPONENT_TYPE); + if ((Cptr != NULL) && (strncmp ( + Cptr, + COMPONENT_TYPE_FILE, + strlen (COMPONENT_TYPE_FILE) + ) == 0)) { + if (ComponentFilePathAbsolute) { + strcpy (InLine, Line); + } else { + sprintf (InLine, "%s\\%s", GetSymbolValue (EFI_SOURCE), Line); + } + CFVAddFVFile ( + InLine, + Cptr, + GetSymbolValue (FV), + Instance, + NULL, + NULL, + GetSymbolValue (APRIORI), + NULL, + NULL + ); + goto ComponentDone; + } + + // + // Better have defined processor by this point. + // + Processor = GetSymbolValue (PROCESSOR); + if (Processor == NULL) { + Error (NULL, 0, 0, NULL, "PROCESSOR not defined for component %s", Line); + return STATUS_ERROR; + } + + // + // The bin, out, and lib dirs are now = $(BUILD_DIR)/$(PROCESSOR). Set them. + // Don't flag them as file paths (required for short 8.3 filenames) since + // they're defined using the BUILD_DIR macro. + // + sprintf (InLine, "$(BUILD_DIR)\\%s", Processor); + AddSymbol (BIN_DIR, InLine, SYM_LOCAL); + AddSymbol (OUT_DIR, InLine, SYM_LOCAL); + AddSymbol (LIB_DIR, InLine, SYM_LOCAL); + // + // See if it's been destined for an FV. It's possible to not be in an + // FV if they just want to build it. + // + Cptr = GetSymbolValue (FV); + if ((Cptr != NULL) && !IS_NULL_SYMBOL_VALUE (Cptr)) { + IsForFv = TRUE; + } else { + IsForFv = FALSE; + } + // + // As an optimization, if they've defined SKIP_FV_NULL as non-zero, and + // the component is not destined for an FV, then skip it. + // Since libraries are never intended for firmware volumes, we have to + // build all of them. + // + if ((DscSectionType == DSC_SECTION_TYPE_COMPONENTS) && (IsForFv == FALSE)) { + if ((GetSymbolValue (SKIP_FV_NULL) != NULL) && (atoi (GetSymbolValue (SKIP_FV_NULL)) != 0)) { + Message (0, "%s not being built (FV=NULL)", FileName); + goto ComponentDone; + } + } + // + // Prepend EFI_SOURCE to the component description file to get the + // full path. Only do this if the path is not a full path already. + // + if (ComponentFilePathAbsolute == 0) { + name = GetSymbolValue (EFI_SOURCE); + sprintf (FileName, "%s\\%s", name, Line); + } else { + strcpy (FileName, Line); + } + // + // Print a message, depending on verbose level. + // + if (DscSectionType == DSC_SECTION_TYPE_COMPONENTS) { + Message (1, "Processing component %s", FileName); + } else { + Message (1, "Processing library %s", FileName); + } + // + // Open the component's description file and get the sections. If we fail + // to open it, see if they defined "OPTIONAL=1, in which case we'll just + // ignore the component. + // + TempFptr = fopen (FileName, "r"); + if (TempFptr == NULL) { + // + // Better have defined OPTIONAL + // + if (GetSymbolValue (OPTIONAL_COMPONENT) != NULL) { + if (atoi (GetSymbolValue (OPTIONAL_COMPONENT)) != 0) { + Message (0, "Optional component '%s' not found", FileName); + goto ComponentDone; + } + } + + ParserError (0, FileName, "failed to open component file"); + return STATUS_ERROR; + } else { + fclose (TempFptr); + } + + DSCFileInit (&ComponentFile); + ComponentCreated = 1; + if (DSCFileSetFile (&ComponentFile, FileName)) { + Error (NULL, 0, 0, NULL, "failed to preprocess component file '%s'", FileName); + return STATUS_ERROR; + } + // + // Add a symbol for the INF filename so users can create dependencies + // in makefiles. + // + AddSymbol (INF_FILENAME, FileName, SYM_OVERWRITE | SYM_LOCAL | SYM_FILENAME); + // + // Process the [defines], [defines.$(PROCESSOR)], and [defines.$(PROCESSOR).$(PLATFORM)] + // sections in the INF file + // + ProcessINFDefinesSection (&ComponentFile); + // + // Better have defined FILE_GUID if not a library + // + if ((GetSymbolValue (GUID) == NULL) && + (GetSymbolValue (FILE_GUID) == NULL) && + (DscSectionType == DSC_SECTION_TYPE_COMPONENTS) + ) { + Error (GetSymbolValue (INF_FILENAME), 1, 0, NULL, "missing FILE_GUID definition in component file"); + DSCFileDestroy (&ComponentFile); + return STATUS_ERROR; + } + // + // Better have defined base name + // + if (GetSymbolValue (BASE_NAME) == NULL) { + Error (GetSymbolValue (INF_FILENAME), 1, 0, NULL, "missing BASE_NAME definition in INF file"); + DSCFileDestroy (&ComponentFile); + return STATUS_ERROR; + } + // + // Better have defined COMPONENT_TYPE, since it's used to find named sections. + // + if (GetSymbolValue (COMPONENT_TYPE) == NULL) { + Error (GetSymbolValue (INF_FILENAME), 1, 0, NULL, "missing COMPONENT_TYPE definition in INF file"); + DSCFileDestroy (&ComponentFile); + return STATUS_ERROR; + } + + // + // Create the source directory path from the component file's path. If the component + // file's path is absolute, we may have problems here. Try to account for it though. + // + if (ComponentFilePathAbsolute == 0) { + sprintf ( + FileName, + "%s\\%s", + GetSymbolValue (EFI_SOURCE), + ComponentFilePath + ); + } else { + strcpy (FileName, ComponentFilePath); + } + AddSymbol (SOURCE_DIR, FileName, SYM_OVERWRITE | SYM_LOCAL | SYM_FILEPATH); + + // + // Create the destination path. + // They may have defined DEST_DIR on the component INF line, so it's already + // been defined, If that's the case, then don't set it to the path of this file. + // + if (GetSymbolValue (DEST_DIR) == NULL) { + if (ComponentFilePathAbsolute == 0) { + // + // The destination path is $(BUILD_DIR)\$(PROCESSOR)\component_path + // + sprintf ( + FileName, + "%s\\%s\\%s", + GetSymbolValue (BUILD_DIR), + Processor, + ComponentFilePath + ); + } else { + // + // The destination path is $(BUILD_DIR)\$(PROCESSOR)\$(BASE_NAME) + // + sprintf ( + FileName, + "%s\\%s\\%s", + GetSymbolValue (BUILD_DIR), + Processor, + GetSymbolValue (BASE_NAME) + ); + } + AddSymbol (DEST_DIR, FileName, SYM_OVERWRITE | SYM_LOCAL | SYM_FILEPATH); + } + + // + // Create the output directory, then open the output component's makefile + // we're going to create. Allow them to override the makefile name. + // + TempCptr = GetSymbolValue (MAKEFILE_NAME); + if (TempCptr != NULL) { + ExpandSymbols (TempCptr, ComponentMakefileName, sizeof (ComponentMakefileName), EXPANDMODE_NO_UNDEFS); + TempCptr = ComponentMakefileName; + } else { + TempCptr = "makefile"; + } + + sprintf (FileName, "%s\\%s", GetSymbolValue (DEST_DIR), TempCptr); + // + // Save it now with path info + // + AddSymbol (MAKEFILE_NAME, FileName, SYM_OVERWRITE | SYM_LOCAL | SYM_FILENAME); + + if (MakeFilePath (FileName)) { + return STATUS_ERROR; + } + + if ((MakeFptr = fopen (FileName, "w")) == NULL) { + Error (NULL, 0, 0, FileName, "could not create makefile"); + return STATUS_ERROR; + } + // + // At this point we should have all the info we need to create a package + // file if setup to do so. Libraries don't use package files, so + // don't do this for libs. + // + if (DscSectionType == DSC_SECTION_TYPE_COMPONENTS) { + CreatePackageFile (DSCFile); + } + + // + // Add Module name to the global module list + // + AddModuleName (&gGlobals.ModuleList, GetSymbolValue (BASE_NAME), GetSymbolValue (INF_FILENAME)); + // + // Write an nmake line to makefile.out + // + fprintf (gGlobals.MakefileFptr, " @cd %s\n", Processor); + fprintf (gGlobals.MakefileFptr, " $(MAKE) -f %s all\n", FileName); + fprintf (gGlobals.MakefileFptr, " @cd ..\n"); + + // + // Copy the common makefile section from the description file to + // the component's makefile + // + WriteCommonMakefile (DSCFile, MakeFptr, Processor); + // + // Process the component's [nmake.common] and [nmake.$(PROCESSOR)] sections + // + ProcessINFNMakeSection (&ComponentFile, MakeFptr); + // + // Create the SOURCE_FILES macro that includes the names of all source + // files in this component. This macro can then be used elsewhere to + // process all the files making up the component. Required for scanning + // files for string localization. + // + ProcessSourceFiles (DSCFile, &ComponentFile, MakeFptr, SOURCE_MODE_SOURCE_FILES); + // + // Create the include paths. Process [includes.common] and + // [includes.$(PROCESSOR)] and [includes.$(PROCESSOR).$(PLATFORM)] sections. + // + ProcessIncludesSection (&ComponentFile, MakeFptr); + // + // Process all include source files to create a dependency list that can + // be used in the makefile. + // + ProcessIncludeFiles (&ComponentFile, MakeFptr); + // + // Process the [sources.common], [sources.$(PROCESSOR)], and + // [sources.$(PROCESSOR).$(PLATFORM)] files and emit their build commands + // + ProcessSourceFiles (DSCFile, &ComponentFile, MakeFptr, SOURCE_MODE_BUILD_COMMANDS); + // + // Process sources again to create an OBJECTS macro + // + ProcessObjects (&ComponentFile, MakeFptr); + + // + // Add Single Module target : build and clean in top level makefile + // + fprintf (gGlobals.ModuleMakefileFptr, "%sbuild ::", GetSymbolValue (BASE_NAME)); + if (DscSectionType == DSC_SECTION_TYPE_COMPONENTS) { + fprintf (gGlobals.ModuleMakefileFptr, " %sbuild", GLOBAL_LINK_LIB_NAME); + } + + // + // Process all the libraries to define "LIBS = x.lib y.lib..." + // Be generous and append ".lib" if they forgot. + // Make a macro definition: LIBS = $(LIBS) xlib.lib ylib.lib... + // Also add libs dependency for single module build: basenamebuild :: xlibbuild ylibbuild ... + // + ProcessLibs (&ComponentFile, MakeFptr); + + fprintf (gGlobals.ModuleMakefileFptr, "\n"); + + fprintf (gGlobals.ModuleMakefileFptr, " @cd %s\n", Processor); + fprintf (gGlobals.ModuleMakefileFptr, " $(MAKE) -f %s all\n", FileName); + fprintf (gGlobals.ModuleMakefileFptr, " @cd ..\n\n"); + + fprintf (gGlobals.ModuleMakefileFptr, "%sclean ::\n", GetSymbolValue (BASE_NAME)); + fprintf (gGlobals.ModuleMakefileFptr, " $(MAKE) -f %s clean\n\n", FileName); + + // + // Emit commands to create the component. These are simply copied from + // the description file to the component's makefile. First look for + // [build.$(PROCESSOR).$(BUILD_TYPE)]. If not found, then look for if + // find a [build.$(PROCESSOR).$(COMPONENT_TYPE)] line. + // + Cptr = GetSymbolValue (BUILD_TYPE); + if (Cptr != NULL) { + sprintf (InLine, "build.%s.%s", Processor, Cptr); + WriteComponentTypeBuildCommands (DSCFile, MakeFptr, InLine); + } else { + sprintf (InLine, "build.%s.%s", Processor, GetSymbolValue (COMPONENT_TYPE)); + WriteComponentTypeBuildCommands (DSCFile, MakeFptr, InLine); + } + // + // Add it to the FV if not a library + // + if (DscSectionType == DSC_SECTION_TYPE_COMPONENTS) { + // + // Create the FV filename and add it to the FV. + // By this point we know it's in FV. + // + Cptr = GetSymbolValue (FILE_GUID); + if (Cptr == NULL) { + Cptr = GetSymbolValue (GUID); + } + + sprintf (InLine, "%s-%s", Cptr, GetSymbolValue (BASE_NAME)); + // + // We've deprecated FV_EXT, which should be FFS_EXT, the extension + // of the FFS file generated by GenFFSFile. + // + TempCptr = GetSymbolValue (FFS_EXT); + if (TempCptr == NULL) { + TempCptr = GetSymbolValue ("FV_EXT"); + } + + CFVAddFVFile ( + InLine, + GetSymbolValue (COMPONENT_TYPE), + GetSymbolValue (FV), + Instance, + TempCptr, + Processor, + GetSymbolValue (APRIORI), + GetSymbolValue (BASE_NAME), + Cptr + ); + } + // + // Catch any failures and print the name of the component file + // being processed to assist debugging. + // +ComponentDone: + + Cptr = CatchException (); + if (Cptr != NULL) { + fprintf (stderr, "%s\n", Cptr); + sprintf (InLine, "Processing of component %s failed", ArgLine); + ThrowException (InLine); + } + + if (MakeFptr != NULL) { + fclose (MakeFptr); + } + + if (ComponentCreated) { + DSCFileDestroy (&ComponentFile); + } + + return STATUS_SUCCESS; +} + +static +int +CreatePackageFile ( + DSC_FILE *DSCFile + ) +{ + INT8 *Package; + SECTION *TempSect; + INT8 Str[MAX_LINE_LEN]; + INT8 StrExpanded[MAX_LINE_LEN]; + SMART_FILE *PkgFptr; + int Status; + + PkgFptr = NULL; + + // + // First find out if PACKAGE_FILENAME or PACKAGE is defined. PACKAGE_FILENAME + // is used to specify the exact package file to use. PACKAGE is used to + // specify the package section name. + // + Package = GetSymbolValue (PACKAGE_FILENAME); + if (Package != NULL) { + // + // Use existing file. We're done. + // + return STATUS_SUCCESS; + } + // + // See if PACKAGE or PACKAGE_TAG is defined + // + Package = GetSymbolValue (PACKAGE); + if (Package == NULL) { + Package = GetSymbolValue (PACKAGE_TAG); + } + + if (Package == NULL) { + // + // Not defined either. Assume they are not using the package functionality + // of this utility. However define the PACKAGE_FILENAME macro to the + // best-guess value. + // + sprintf ( + Str, + "%s\\%s.pkg", + GetSymbolValue (SOURCE_DIR), + GetSymbolValue (BASE_NAME) + ); + + // + // Expand symbols in the package filename + // + ExpandSymbols (Str, StrExpanded, sizeof (StrExpanded), EXPANDMODE_NO_UNDEFS); + + AddSymbol (PACKAGE_FILENAME, StrExpanded, SYM_LOCAL | SYM_FILENAME); + return STATUS_SUCCESS; + } + // + // Save the position in the DSC file. + // Find the [package.$(COMPONENT_TYPE).$(PACKAGE)] section in the DSC file + // + Status = STATUS_SUCCESS; + DSCFileSavePosition (DSCFile); + sprintf (Str, "%s.%s.%s", PACKAGE, GetSymbolValue (COMPONENT_TYPE), Package); + TempSect = DSCFileFindSection (DSCFile, Str); + if (TempSect != NULL) { + // + // So far so good. Create the name of the package file, then open it up + // for writing. File name is c:\...\oem\platform\nt32\ia32\...\BaseName.pkg. + // + sprintf ( + Str, + "%s\\%s.pkg", + GetSymbolValue (DEST_DIR), + GetSymbolValue (BASE_NAME) + ); + + // + // Expand symbols in the package filename + // + ExpandSymbols (Str, StrExpanded, sizeof (StrExpanded), EXPANDMODE_NO_UNDEFS); + + // + // Try to open the file, then save the file name as the PACKAGE_FILENAME + // symbol for use elsewhere. + // + if ((PkgFptr = SmartOpen (StrExpanded)) == NULL) { + Error (NULL, 0, 0, Str, "could not open package file for writing"); + Status = STATUS_ERROR; + goto Finish; + } + + AddSymbol (PACKAGE_FILENAME, StrExpanded, SYM_LOCAL | SYM_FILENAME); + // + // Now read lines in from the DSC file and write them back out to the + // package file (with string substitution). + // + while (DSCFileGetLine (DSCFile, Str, sizeof (Str)) != NULL) { + // + // Expand symbols, then write the line out to the package file + // + ExpandSymbols (Str, StrExpanded, sizeof (StrExpanded), EXPANDMODE_RECURSIVE); + SmartWrite (PkgFptr, StrExpanded); + } + } else { + Warning ( + NULL, + 0, + 0, + NULL, + "cannot locate package section [%s] in DSC file for %s", + Str, + GetSymbolValue (INF_FILENAME) + ); + Status = STATUS_WARNING; + goto Finish; + } + + if (PkgFptr != NULL) { + SmartClose (PkgFptr); + } + +Finish: + // + // Restore the position in the DSC file + // + DSCFileRestorePosition (DSCFile); + + return STATUS_SUCCESS; +} + +static +int +ProcessINFDefinesSection ( + DSC_FILE *ComponentFile + ) +/*++ + +Routine Description: + + Process the [defines.xxx] sections of the component description file. Process + platform first, then processor. In this way, if a platform wants and override, + that one gets parsed first, and later assignments do not overwrite the value. + +Arguments: + + ComponentFile - section info on the component file being processed + +Returns: + + +--*/ +{ + INT8 *Cptr; + INT8 Str[MAX_LINE_LEN]; + + // + // Find a [defines.$(PROCESSOR).$(PLATFORM)] section and process it + // + Cptr = GetSymbolValue (PLATFORM); + if (Cptr != NULL) { + sprintf ( + Str, + "%s.%s.%s", + DEFINES_SECTION_NAME, + GetSymbolValue (PROCESSOR), + Cptr + ); + ProcessINFDefinesSectionSingle (ComponentFile, Str); + } + // + // Find a [defines.$(PROCESSOR)] section and process it + // + sprintf (Str, "%s.%s", DEFINES_SECTION_NAME, GetSymbolValue (PROCESSOR)); + ProcessINFDefinesSectionSingle (ComponentFile, Str); + + // + // Find a [defines] section and process it + // + if (ProcessINFDefinesSectionSingle (ComponentFile, DEFINES_SECTION_NAME) != STATUS_SUCCESS) { + Error (NULL, 0, 0, NULL, "missing [defines] section in component file %s", GetSymbolValue (INF_FILENAME)); + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} + +static +int +ProcessINFDefinesSectionSingle ( + DSC_FILE *ComponentFile, + INT8 *SectionName + ) +{ + INT8 *Cptr; + INT8 Str[MAX_LINE_LEN]; + INT8 ExpandedLine[MAX_LINE_LEN]; + SECTION *TempSect; + + TempSect = DSCFileFindSection (ComponentFile, SectionName); + if (TempSect != NULL) { + while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { + ExpandSymbols (Str, ExpandedLine, sizeof (ExpandedLine), 0); + Cptr = StripLine (ExpandedLine); + // + // Don't process blank lines. + // + if (*Cptr) { + // + // Add without overwriting macros specified on the component line + // in the description file + // + AddSymbol (Cptr, NULL, SYM_LOCAL); + } + } + } else { + return STATUS_WARNING; + } + + return STATUS_SUCCESS; +} + +static +int +ProcessINFNMakeSection ( + DSC_FILE *ComponentFile, + FILE *MakeFptr + ) +/*++ + +Routine Description: + + Process the [nmake.common] and [nmake.$(PROCESSOR)] sections of the component + description file and write and copy them to the component's makefile. + +Arguments: + + ComponentFile - section info on the component file being processed + MakeFptr - file pointer to the component' makefile we're creating + +Returns: + + Always STATUS_SUCCESS right now, since the sections are optional. + +--*/ +{ + INT8 *Cptr; + INT8 Str[MAX_LINE_LEN]; + INT8 ExpandedLine[MAX_LINE_LEN]; + SECTION *TempSect; + + // + // Copy the [nmake.common] and [nmake.$(PROCESSOR)] sections from the + // component file directly to the output file. + // The line will be stripped and don't print blank lines + // + sprintf (Str, "%s.%s", NMAKE_SECTION_NAME, COMMON_SECTION_NAME); + TempSect = DSCFileFindSection (ComponentFile, Str); + if (TempSect != NULL) { + while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { + ExpandSymbols ( + Str, + ExpandedLine, + sizeof (ExpandedLine), + EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR + ); + Cptr = StripLine (ExpandedLine); + if (*Cptr) { + fprintf (MakeFptr, "%s\n", Cptr); + } + } + + fprintf (MakeFptr, "\n"); + } else { + Error (GetSymbolValue (INF_FILENAME), 1, 0, Str, "section not found in component INF file"); + } + + sprintf (Str, "%s.%s", NMAKE_SECTION_NAME, GetSymbolValue (PROCESSOR)); + TempSect = DSCFileFindSection (ComponentFile, Str); + if (TempSect != NULL) { + while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { + ExpandSymbols ( + Str, + ExpandedLine, + sizeof (ExpandedLine), + EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR + ); + Cptr = StripLine (ExpandedLine); + if (*Cptr) { + fprintf (MakeFptr, "%s\n", Cptr); + } + } + + fprintf (MakeFptr, "\n"); + } + // + // Do the same for [nmake.$(PROCESSOR).$(PLATFORM)] + // + Cptr = GetSymbolValue (PLATFORM); + if (Cptr != NULL) { + sprintf (Str, "%s.%s.%s", NMAKE_SECTION_NAME, GetSymbolValue (PROCESSOR), Cptr); + TempSect = DSCFileFindSection (ComponentFile, Str); + if (TempSect != NULL) { + while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { + ExpandSymbols ( + Str, + ExpandedLine, + sizeof (ExpandedLine), + EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR + ); + Cptr = StripLine (ExpandedLine); + if (*Cptr) { + fprintf (MakeFptr, "%s\n", Cptr); + } + } + + fprintf (MakeFptr, "\n"); + } + } + + return STATUS_SUCCESS; +} + +static +int +ProcessIncludesSection ( + DSC_FILE *ComponentFile, + FILE *MakeFptr + ) +/*++ + +Routine Description: + + Process the [includes.common], [includes.processor], and + [includes.processor.platform] section of the component description file + and write the appropriate macros to the component's makefile. + + Process in reverse order to allow overrides on platform basis. + +Arguments: + + ComponentFile - section info on the component file being processed + MakeFptr - file pointer to the component' makefile we're creating + +Returns: + + Always STATUS_SUCCESS right now, since the sections are optional. + +--*/ +{ + INT8 *Cptr; + INT8 Str[MAX_LINE_LEN]; + INT8 *Processor; + INT8 *OverridePath; + + // + // Write a useful comment to the output makefile so the user knows where + // the data came from. + // + fprintf (MakeFptr, "#\n# Tool-generated list of include paths that are created\n"); + fprintf (MakeFptr, "# from the list of include paths in the [includes.*] sections\n"); + fprintf (MakeFptr, "# of the component INF file.\n#\n"); + + // + // We use this a lot here, so get the value only once. + // + Processor = GetSymbolValue (PROCESSOR); + // + // If they're using an override source path, then add OverridePath and + // OverridePath\$(PROCESSOR) to the list of include paths. + // + OverridePath = GetSymbolValue (SOURCE_OVERRIDE_PATH); + if (OverridePath != NULL) { + fprintf (MakeFptr, "INC = $(INC) -I %s\n", OverridePath); + fprintf (MakeFptr, "INC = $(INC) -I %s\\%s \n", OverridePath, Processor); + } + // + // Try for an [includes.$(PROCESSOR).$(PLATFORM)] + // + Cptr = GetSymbolValue (PLATFORM); + if (Cptr != NULL) { + sprintf (Str, "%s.%s.%s", INCLUDE_SECTION_NAME, Processor, Cptr); + ProcessIncludesSectionSingle (ComponentFile, MakeFptr, Str); + } + // + // Now the [includes.$(PROCESSOR)] section + // + sprintf (Str, "%s.%s", INCLUDE_SECTION_NAME, Processor); + ProcessIncludesSectionSingle (ComponentFile, MakeFptr, Str); + + // + // Now the [includes.common] section + // + sprintf (Str, "%s.%s", INCLUDE_SECTION_NAME, COMMON_SECTION_NAME); + ProcessIncludesSectionSingle (ComponentFile, MakeFptr, Str); + + // + // Done + // + fprintf (MakeFptr, "\n"); + return STATUS_SUCCESS; +} +// +// Process one of the [includes.xxx] sections to create a list of all +// the include paths. +// +static +int +ProcessIncludesSectionSingle ( + DSC_FILE *ComponentFile, + FILE *MakeFptr, + INT8 *SectionName + ) +{ + INT8 *Cptr; + SECTION *TempSect; + INT8 Str[MAX_LINE_LEN]; + INT8 ExpandedLine[MAX_LINE_LEN]; + INT8 *Processor; + + TempSect = DSCFileFindSection (ComponentFile, SectionName); + if (TempSect != NULL) { + // + // Add processor subdirectory on every include path + // + Processor = GetSymbolValue (PROCESSOR); + // + // Copy lines directly + // + while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { + ExpandSymbols (Str, ExpandedLine, sizeof (ExpandedLine), 0); + Cptr = StripLine (ExpandedLine); + // + // Don't process blank lines + // + if (*Cptr) { + // + // Strip off trailing slash + // + if (Cptr[strlen (Cptr) - 1] == '\\') { + Cptr[strlen (Cptr) - 1] = 0; + } + // + // Special case of ".". Replace it with source path + // and the rest of the line (for .\$(PROCESSOR)) + // + if (*Cptr == '.') { + // + // Handle case of just a "." + // + if (Cptr[1] == 0) { + fprintf (MakeFptr, "INC = $(INC) -I $(SOURCE_DIR)\n"); + fprintf ( + MakeFptr, + "INC = $(INC) -I $(SOURCE_DIR)\\%s \n", + Processor + ); + } else { + // + // Handle case of ".\path\path\path" or "..\path\path\path" + // + fprintf ( + MakeFptr, + "INC = $(INC) -I $(SOURCE_DIR)\\%s \n", + Cptr + ); + fprintf ( + MakeFptr, + "INC = $(INC) -I $(SOURCE_DIR)\\%s\\%s \n", + Cptr, + Processor + ); + } + } else if ((Cptr[1] != ':') && isalpha (*Cptr)) { + fprintf (MakeFptr, "INC = $(INC) -I $(EFI_SOURCE)\\%s \n", Cptr); + fprintf ( + MakeFptr, + "INC = $(INC) -I $(EFI_SOURCE)\\%s\\%s \n", + Cptr, + Processor + ); + } else { + // + // The line is something like: $(EFI_SOURCE)\dxe\include. Add it to + // the existing $(INC) definition. Add user includes before any + // other existing paths. + // + fprintf (MakeFptr, "INC = $(INC) -I %s \n", Cptr); + fprintf (MakeFptr, "INC = $(INC) -I %s\\%s \n", Cptr, Processor); + } + } + } + } + + return STATUS_SUCCESS; +} + +static +int +ProcessSourceFiles ( + DSC_FILE *DSCFile, + DSC_FILE *ComponentFile, + FILE *MakeFptr, + UINT32 Mode + ) +/*++ + +Routine Description: + + Process the [sources.common], [sources.$(PROCESSOR)], and + [sources.$(PROCESSOR).$(PLATFORM] sections of the component + description file and write the appropriate build commands out to the + component's makefile. If $(SOURCE_SELECT) is defined, then it overrides + the source selections. We use this functionality for SMM. + +Arguments: + + ComponentFile - section info on the component file being processed + MakeFptr - file pointer to the component' makefile we're creating + DSCFile - section info on the description file we're processing + Mode - to write build commands, or just create a list + of sources. + +Returns: + + Always STATUS_SUCCESS right now, since the sections are optional. + +--*/ +{ + INT8 Str[MAX_LINE_LEN]; + INT8 *Processor; + INT8 *Platform; + INT8 *SourceSelect; + INT8 *CStart; + INT8 *CEnd; + INT8 CSave; + INT8 *CopySourceSelect; + + if (Mode & SOURCE_MODE_SOURCE_FILES) { + // + // Write a useful comment to the output makefile so the user knows where + // the data came from. + // + fprintf (MakeFptr, "#\n# Tool-generated list of source files that are created\n"); + fprintf (MakeFptr, "# from the list of source files in the [sources.*] sections\n"); + fprintf (MakeFptr, "# of the component INF file.\n#\n"); + } + + // + // We use this a lot here, so get the value only once. + // + Processor = GetSymbolValue (PROCESSOR); + // + // See if they defined SOURCE_SELECT=xxx,yyy in which case we'll + // select each [sources.xxx] and [sources.yyy] files and process + // them. + // + SourceSelect = GetSymbolValue (SOURCE_SELECT); + + if (SourceSelect != NULL) { + // + // Make a copy of the string and break it up (comma-separated) and + // select each [sources.*] file from the INF. + // + CopySourceSelect = (INT8 *) malloc (strlen (SourceSelect) + 1); + if (CopySourceSelect == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + return STATUS_ERROR; + } + + strcpy (CopySourceSelect, SourceSelect); + CStart = CopySourceSelect; + CEnd = CStart; + while (*CStart) { + CEnd = CStart + 1; + while (*CEnd && *CEnd != ',') { + CEnd++; + } + + CSave = *CEnd; + *CEnd = 0; + sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, CStart); + ProcessSourceFilesSection (DSCFile, ComponentFile, MakeFptr, Str, Mode); + // + // Restore the terminator and advance + // + *CEnd = CSave; + CStart = CEnd; + if (*CStart) { + CStart++; + } + } + + free (CopySourceSelect); + + } else { + // + // Process all the [sources.common] source files to make them build + // + sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, COMMON_SECTION_NAME); + ProcessSourceFilesSection (DSCFile, ComponentFile, MakeFptr, Str, Mode); + // + // Now process the [sources.$(PROCESSOR)] files. + // + sprintf (Str, "sources.%s", Processor); + ProcessSourceFilesSection (DSCFile, ComponentFile, MakeFptr, Str, Mode); + // + // Now process the [sources.$(PROCESSOR).$(PLATFORM)] files. + // + Platform = GetSymbolValue (PLATFORM); + if (Platform != NULL) { + sprintf (Str, "sources.%s.%s", Processor, Platform); + ProcessSourceFilesSection (DSCFile, ComponentFile, MakeFptr, Str, Mode); + } + } + + fprintf (MakeFptr, "\n"); + return STATUS_SUCCESS; +} + +/*++ + +Routine Description: + Given a source file line from an INF file, parse it to see if there are + any defines on it. If so, then add them to the symbol table. + Also, terminate the line after the file name. + +Arguments: + SourceFileLine - a line from a [sources.?] section of the INF file. Likely + something like: + + MySourceFile.c BUILT_NAME=$(BUILD_DIR)\MySourceFile.obj + +Returns: + Nothing. + +--*/ +static +void +AddFileSymbols ( + INT8 *SourceFileLine + ) +{ + int Len; + // + // Skip spaces + // + for (; *SourceFileLine && isspace (*SourceFileLine); SourceFileLine++) + ; + for (; *SourceFileLine && !isspace (*SourceFileLine); SourceFileLine++) + ; + if (*SourceFileLine) { + *SourceFileLine = 0; + SourceFileLine++; + // + // AddSymbol() will parse it for us, and return the length. Keep calling + // it until it reports an error or is done. + // + do { + Len = AddSymbol (SourceFileLine, NULL, SYM_FILE); + SourceFileLine += Len; + } while (Len > 0); + } +} +// +// Process a single section of source files in the component INF file +// +static +int +ProcessSourceFilesSection ( + DSC_FILE *DSCFile, + DSC_FILE *ComponentFile, + FILE *MakeFptr, + INT8 *SectionName, + UINT32 Mode + ) +{ + INT8 *Cptr; + INT8 FileName[MAX_EXP_LINE_LEN]; + INT8 FilePath[MAX_PATH]; + INT8 TempFileName[MAX_PATH]; + SECTION *TempSect; + INT8 Str[MAX_LINE_LEN]; + INT8 *Processor; + INT8 *OverridePath; + FILE *FPtr; + + TempSect = DSCFileFindSection (ComponentFile, SectionName); + if (TempSect != NULL) { + Processor = GetSymbolValue (PROCESSOR); + while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { + Cptr = StripLine (Str); + // + // Don't process blank lines + // + if (*Cptr) { + // + // Expand symbols in the filename, then parse the line for symbol + // definitions. AddFileSymbols() will null-terminate the line + // after the file name. Save a copy for override purposes, in which + // case we'll need to know the file name and path (in case it's in + // a subdirectory). + // + ExpandSymbols (Cptr, FileName, sizeof (FileName), 0); + AddFileSymbols (FileName); + // + // Set the SOURCE_FILE_NAME symbol. What we have now is the name of + // the file, relative to the location of the INF file. So prepend + // $(SOURCE_DIR) to it first. + // + if (IsAbsolutePath (FileName)) { + strcpy (TempFileName, FileName); + } else { + strcpy (TempFileName, "$(SOURCE_DIR)\\"); + strcat (TempFileName, FileName); + } + AddSymbol (SOURCE_FILE_NAME, TempFileName, SYM_FILE | SYM_OVERWRITE); + // + // Extract path information from the source file and set internal + // variable SOURCE_RELATIVE_PATH. Only do this if the path + // contains a backslash. + // + strcpy (FilePath, FileName); + for (Cptr = FilePath + strlen (FilePath) - 1; (Cptr > FilePath) && (*Cptr != '\\'); Cptr--) + ; + if (*Cptr == '\\') { + *(Cptr + 1) = 0; + AddSymbol (SOURCE_RELATIVE_PATH, FilePath, SYM_FILE); + } + // + // Define another internal symbol for the name of the file without + // the path and extension. + // + for (Cptr = FileName + strlen (FileName) - 1; (Cptr > FileName) && (*Cptr != '\\'); Cptr--) + ; + if (*Cptr == '\\') { + Cptr++; + } + + strcpy (FilePath, Cptr); + // + // We now have a file name with no path information. Before we do anything else, + // see if OVERRIDE_PATH is set, and if so, see if file $(OVERRIDE_PATH)FileName + // exists. If it does, then recursive call this function to use the override file + // instead of the one from the INF file. + // + if (IsAbsolutePath (FileName)) { + OverridePath = NULL; + } else { + OverridePath = GetSymbolValue (SOURCE_OVERRIDE_PATH); + } + if (OverridePath != NULL) { + // + // See if the file exists. If it does, reset the SOURCE_FILE_NAME symbol. + // + strcpy (TempFileName, OverridePath); + strcat (TempFileName, "\\"); + strcat (TempFileName, FileName); + if ((FPtr = fopen (TempFileName, "rb")) != NULL) { + fclose (FPtr); + AddSymbol (SOURCE_FILE_NAME, TempFileName, SYM_FILE | SYM_OVERWRITE); + // + // Print a message. This function is called to create build commands + // for source files, and to create a macro of all source files. Therefore + // do this check so we don't print the override message multiple times. + // + if (Mode & SOURCE_MODE_BUILD_COMMANDS) { + fprintf (stdout, "Override: %s\n", TempFileName); + } + } else { + // + // Set override path to null to use as a flag below + // + OverridePath = NULL; + } + } + + // + // Start at the end and work back + // + for (Cptr = FilePath + strlen (FilePath) - 1; (Cptr > FilePath) && (*Cptr != '\\') && (*Cptr != '.'); Cptr--) + ; + if (*Cptr == '.') { + *Cptr = 0; + AddSymbol (SOURCE_FILE_EXTENSION, Cptr + 1, SYM_FILE); + } + + AddSymbol (SOURCE_BASE_NAME, FilePath, SYM_FILE); + // + // If we're just creating the SOURCE_FILES macro, then write the + // file name out to the makefile. + // + if (Mode & SOURCE_MODE_SOURCE_FILES) { + // + // If we're processing an override file, then use the file name as-is + // + if (OverridePath != NULL) { + // + // SOURCE_FILES = $(SOURCE_FILES) c:\Path\ThisFile.c + // + fprintf (MakeFptr, "SOURCE_FILES = $(SOURCE_FILES) %s\n", TempFileName); + } else if (IsAbsolutePath (FileName)) { + // + // For Absolute path, don't print $(SOURCE_FILE) directory. + // + fprintf (MakeFptr, "SOURCE_FILES = $(SOURCE_FILES) %s\n", FileName); + } else { + // + // SOURCE_FILES = $(SOURCE_FILES) $(SOURCE_DIR)\ThisFile.c + // + fprintf (MakeFptr, "SOURCE_FILES = $(SOURCE_FILES) $(SOURCE_DIR)\\%s\n", FileName); + } + } else if (Mode & SOURCE_MODE_BUILD_COMMANDS) { + // + // Write the build commands for this file per the build commands + // for this file type as defined in the description file. + // Also create the directory for it in the build path. + // + WriteCompileCommands (DSCFile, MakeFptr, FileName, Processor); + if (!IsAbsolutePath (FileName)) { + sprintf (Str, "%s\\%s", GetSymbolValue (DEST_DIR), FileName); + MakeFilePath (Str); + // + // Get all output directory for build output files. + // + Cptr = FileName + strlen (FileName) - 1; + for (; (Cptr > FileName) && (*Cptr != '\\'); Cptr--); + if (*Cptr == '\\') { + *Cptr = '\0'; + AddModuleName (&gGlobals.OutdirList, FileName, NULL); + } + } + } + // + // Remove file-level symbols + // + RemoveFileSymbols (); + } + } + } + + return STATUS_SUCCESS; +} +// +// Process the INF [sources.*] sections and emit the OBJECTS = ..... +// lines to the component's makefile. +// +static +int +ProcessObjects ( + DSC_FILE *ComponentFile, + FILE *MakeFptr + ) +{ + INT8 Str[MAX_LINE_LEN]; + INT8 *Processor; + INT8 *Platform; + INT8 *SourceSelect; + INT8 *CStart; + INT8 *CEnd; + INT8 CSave; + INT8 *CopySourceSelect; + SYMBOL *TempSymbol; + + // + // Write a useful comment to the output makefile so the user knows where + // the data came from. + // + fprintf (MakeFptr, "#\n# Tool-generated list of object files that are created\n"); + fprintf (MakeFptr, "# from the list of source files in the [sources.*] sections\n"); + fprintf (MakeFptr, "# of the component INF file.\n#\n"); + // + // We use this a lot here, so get the value only once. + // + Processor = GetSymbolValue (PROCESSOR); + // + // Now define the OBJECTS variable and assign it to be all the object files we're going + // to create. Afterwards create a pseudo-target objects to let the user quickly just compile + // the source files. This means we need to process all the common objects and + // processor-specific objects again. + // + fprintf (MakeFptr, "OBJECTS = $(OBJECTS) "); + // + // See if they defined SOURCE_SELECT=xxx,yyy in which case well + // select each [sources.xxx] and [sources.yyy] files and process + // them. + // + SourceSelect = GetSymbolValue (SOURCE_SELECT); + + if (SourceSelect != NULL) { + // + // Make a copy of the string and break it up (comma-separated) and + // select each [sources.*] file from the INF. + // + CopySourceSelect = (INT8 *) malloc (strlen (SourceSelect) + 1); + if (CopySourceSelect == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + return STATUS_ERROR; + } + + strcpy (CopySourceSelect, SourceSelect); + CStart = CopySourceSelect; + CEnd = CStart; + while (*CStart) { + CEnd = CStart + 1; + while (*CEnd && *CEnd != ',') { + CEnd++; + } + + CSave = *CEnd; + *CEnd = 0; + sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, CStart); + ProcessObjectsSingle (ComponentFile, MakeFptr, Str); + // + // Restore the terminator and advance + // + *CEnd = CSave; + CStart = CEnd; + if (*CStart) { + CStart++; + } + } + + free (CopySourceSelect); + + } else { + // + // Now process all the [sources.common] files and emit build commands for them + // + sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, COMMON_SECTION_NAME); + if (ProcessObjectsSingle (ComponentFile, MakeFptr, Str) != STATUS_SUCCESS) { + Warning (GetSymbolValue (INF_FILENAME), 1, 0, NULL, "no [%s] section found in component description", Str); + } + // + // Now process any processor-specific source files in [sources.$(PROCESSOR)] + // + sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, Processor); + ProcessObjectsSingle (ComponentFile, MakeFptr, Str); + + // + // Now process any [sources.$(PROCESSOR).$(PLATFORM)] files + // + Platform = GetSymbolValue (PLATFORM); + if (Platform != NULL) { + sprintf (Str, "sources.%s.%s", Processor, Platform); + ProcessObjectsSingle (ComponentFile, MakeFptr, Str); + } + } + + fprintf (MakeFptr, "\n\n"); + + // + // Write a useful comment to the output makefile so the user knows where + // the data came from. + // + fprintf (MakeFptr, "#\n# Tool-generated list of dest output dirs that are created\n"); + fprintf (MakeFptr, "# from the list of source files in the [sources.*] sections\n"); + fprintf (MakeFptr, "# of the component INF file.\n#\n"); + // + // Create output directory list + // for clean target to delete all build output files. + // + fprintf (MakeFptr, "DEST_OUTPUT_DIRS = $(%s) ", DEST_DIR); + + TempSymbol = gGlobals.OutdirList; + while (TempSymbol != NULL) { + fprintf (MakeFptr, "\\\n $(%s)\\%s ", + DEST_DIR, TempSymbol->Name); + TempSymbol = TempSymbol->Next; + } + fprintf (MakeFptr, "\n\n"); + + // + // clean up for the next module + // + FreeSymbols (gGlobals.OutdirList); + gGlobals.OutdirList = NULL; + + return STATUS_SUCCESS; +} + +static +INT8 * +BuiltFileExtension ( + INT8 *SourceFileName + ) +{ + int i; + INT8 *Cptr; + // + // Find the dot in the filename extension + // + for (Cptr = SourceFileName + strlen (SourceFileName) - 1; + (Cptr > SourceFileName) && (*Cptr != '\\') && (*Cptr != '.'); + Cptr-- + ) { + // + // Do nothing + // + } + + if (*Cptr != '.') { + return NULL; + } + // + // Look through our list of known file types and return a pointer to + // its built file extension. + // + for (i = 0; mFileTypes[i].Extension != NULL; i++) { + if (_stricmp (Cptr, mFileTypes[i].Extension) == 0) { + return mFileTypes[i].BuiltExtension; + } + } + + return NULL; +} + +int +ProcessObjectsSingle ( + DSC_FILE *ComponentFile, + FILE *MakeFptr, + INT8 *SectionName + ) +{ + INT8 *Cptr; + INT8 *Cptr2; + INT8 Str[MAX_LINE_LEN]; + INT8 FileName[MAX_EXP_LINE_LEN]; + SECTION *TempSect; + + TempSect = DSCFileFindSection (ComponentFile, SectionName); + if (TempSect != NULL) { + while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { + Cptr = StripLine (Str); + // + // Don't process blank lines + // + if (*Cptr) { + // + // Expand symbols then create the output filename. We'll do a lookup + // on the source file's extension to determine what the extension of + // the built version of the file is. For example, .c -> .obj. + // + if (!IsIncludeFile (Cptr)) { + ExpandSymbols (Cptr, FileName, sizeof (FileName), 0); + Cptr2 = BuiltFileExtension (FileName); + if (Cptr2 != NULL) { + SetFileExtension (FileName, Cptr2); + if (!IsAbsolutePath (FileName)) { + fprintf (MakeFptr, "\\\n $(%s)\\%s ", DEST_DIR, FileName); + } else { + fprintf (MakeFptr, "\\\n %s ", FileName); + } + } + } + } + } + } else { + return STATUS_WARNING; + } + + return STATUS_SUCCESS; +} +// +// Process all [libraries.*] sections in the component INF file to create a +// macro to the component's output makefile: LIBS = Lib1 Lib2, ... +// +static +int +ProcessLibs ( + DSC_FILE *ComponentFile, + FILE *MakeFptr + ) +{ + INT8 Str[MAX_LINE_LEN]; + INT8 *Processor; + INT8 *Platform; + + // + // Print a useful comment to the component's makefile so the user knows + // where the data came from. + // + fprintf (MakeFptr, "#\n# Tool-generated list of libraries that are generated\n"); + fprintf (MakeFptr, "# from the list of libraries listed in the [libraries.*] sections\n"); + fprintf (MakeFptr, "# of the component INF file.\n#\n"); + + fprintf (MakeFptr, "LIBS = $(LIBS) "); + + Processor = GetSymbolValue (PROCESSOR); + // + // Process [libraries.common] files + // + sprintf (Str, "%s.%s", LIBRARIES_SECTION_NAME, COMMON_SECTION_NAME); + ProcessLibsSingle (ComponentFile, MakeFptr, Str); + // + // Process the [libraries.$(PROCESSOR)] libraries to define "LIBS = x.lib y.lib..." + // + sprintf (Str, "%s.%s", LIBRARIES_SECTION_NAME, Processor); + ProcessLibsSingle (ComponentFile, MakeFptr, Str); + // + // Now process any [libraries.$(PROCESSOR).$(PLATFORM)] files + // + Platform = GetSymbolValue (PLATFORM); + if (Platform != NULL) { + sprintf (Str, "%s.%s.%s", LIBRARIES_SECTION_NAME, Processor, Platform); + ProcessLibsSingle (ComponentFile, MakeFptr, Str); + } + // + // Process any [libraries.platform] files + // + ProcessLibsSingle (ComponentFile, MakeFptr, LIBRARIES_PLATFORM_SECTION_NAME); + + fprintf (MakeFptr, "\n\n"); + return STATUS_SUCCESS; +} + +static +int +ProcessLibsSingle ( + DSC_FILE *ComponentFile, + FILE *MakeFptr, + INT8 *SectionName + ) +{ + INT8 *Cptr; + INT8 Str[MAX_LINE_LEN]; + INT8 ExpandedLine[MAX_LINE_LEN]; + SECTION *TempSect; + + TempSect = DSCFileFindSection (ComponentFile, SectionName); + if (TempSect != NULL) { + while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { + ExpandSymbols (Str, ExpandedLine, sizeof (ExpandedLine), 0); + Cptr = StripLine (ExpandedLine); + // + // Don't process blank lines + // + if (*Cptr) { + if (Cptr[strlen (Cptr) - 4] != '.') { + fprintf (MakeFptr, " \\\n $(LIB_DIR)\\%s.lib", Cptr); + // + // Add lib dependency for single module build + // + fprintf (gGlobals.ModuleMakefileFptr, " %sbuild", Cptr); + } else { + fprintf (MakeFptr, " \\\n $(LIB_DIR)\\%s", Cptr); + // + // Add lib dependency for single module build + // + Cptr[strlen (Cptr) - 4] = 0; + fprintf (gGlobals.ModuleMakefileFptr, " %sbuild", Cptr); + } + } + } + } + + return STATUS_SUCCESS; +} + +static +int +ProcessIncludeFiles ( + DSC_FILE *ComponentFile, + FILE *MakeFptr + ) +{ + INT8 Str[MAX_LINE_LEN]; + INT8 *Processor; + INT8 *Platform; + INT8 *SourceSelect; + INT8 *CStart; + INT8 *CEnd; + INT8 CSave; + INT8 *CopySourceSelect; + + // + // Print a useful comment to the output makefile so the user knows where + // the info came from + // + //fprintf (MakeFptr, "#\n# Tool-generated include dependencies from any include files in the\n"); + //fprintf (MakeFptr, "# [sources.*] sections of the component INF file\n#\n"); + + Processor = GetSymbolValue (PROCESSOR); + + // + // See if they defined SOURCE_SELECT=xxx,yyy in which case we'll + // select each [sources.xxx] and [sources.yyy] files and process + // them. + // + SourceSelect = GetSymbolValue (SOURCE_SELECT); + + if (SourceSelect != NULL) { + // + // Make a copy of the string and break it up (comma-separated) and + // select each [sources.*] file from the INF. + // + CopySourceSelect = (INT8 *) malloc (strlen (SourceSelect) + 1); + if (CopySourceSelect == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + return STATUS_ERROR; + } + + strcpy (CopySourceSelect, SourceSelect); + CStart = CopySourceSelect; + CEnd = CStart; + while (*CStart) { + CEnd = CStart + 1; + while (*CEnd && *CEnd != ',') { + CEnd++; + } + + CSave = *CEnd; + *CEnd = 0; + sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, CStart); + ProcessIncludeFilesSingle (ComponentFile, MakeFptr, Str); + // + // Restore the terminator and advance + // + *CEnd = CSave; + CStart = CEnd; + if (*CStart) { + CStart++; + } + } + + free (CopySourceSelect); + + } else { + // + // Find all the include files in the [sources.common] sections. + // + sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, COMMON_SECTION_NAME); + ProcessIncludeFilesSingle (ComponentFile, MakeFptr, Str); + // + // Now process the [sources.$(PROCESSOR)] files. + // + sprintf (Str, "%s.%s", SOURCES_SECTION_NAME, Processor); + ProcessIncludeFilesSingle (ComponentFile, MakeFptr, Str); + // + // Now process the [sources.$(PROCESSOR).$(PLATFORM)] files. + // + Platform = GetSymbolValue (PLATFORM); + if (Platform != NULL) { + sprintf (Str, "sources.%s.%s", Processor, Platform); + ProcessIncludeFilesSingle (ComponentFile, MakeFptr, Str); + } + } + + fprintf (MakeFptr, "\n"); + return STATUS_SUCCESS; +} + +int +ProcessIncludeFilesSingle ( + DSC_FILE *ComponentFile, + FILE *MakeFptr, + INT8 *SectionName + ) +{ + INT8 *Cptr; + INT8 FileName[MAX_EXP_LINE_LEN]; + INT8 TempFileName[MAX_PATH]; + SECTION *TempSect; + INT8 Str[MAX_LINE_LEN]; + INT8 *OverridePath; + FILE *FPtr; + + TempSect = DSCFileFindSection (ComponentFile, SectionName); + if (TempSect != NULL) { + // + // See if the SOURCE_OVERRIDE_PATH has been set. If it has, and + // they have an include file that is overridden, then add the path + // to it to the list of include paths (prepend). + // + OverridePath = GetSymbolValue (SOURCE_OVERRIDE_PATH); + while (DSCFileGetLine (ComponentFile, Str, sizeof (Str)) != NULL) { + Cptr = StripLine (Str); + // + // Don't process blank lines + // + if (*Cptr) { + // + // Expand symbols in the filename, then get its parts + // + ExpandSymbols (Cptr, FileName, sizeof (FileName), 0); + AddFileSymbols (FileName); + if (IsIncludeFile (FileName)) { + if ((OverridePath != NULL) && (!IsAbsolutePath (FileName))) { + strcpy (TempFileName, OverridePath); + strcat (TempFileName, "\\"); + strcat (TempFileName, FileName); + if ((FPtr = fopen (TempFileName, "rb")) != NULL) { + fclose (FPtr); + // + // Null-terminate the file name at the last backslash and add that + // to the beginning of the list of include paths. + // + for (Cptr = TempFileName + strlen (TempFileName) - 1; + (Cptr >= TempFileName) && (*Cptr != '\\') && (*Cptr != '/'); + Cptr-- + ) + ; + if (Cptr >= TempFileName) { + *Cptr = 0; + } + + fprintf (MakeFptr, "INC = -I %s $(INC)\n", TempFileName); + } + } + // + // If absolute path already, don't prepend source directory + // + // if (IsAbsolutePath (FileName)) { + // fprintf (MakeFptr, "INC_DEPS = $(INC_DEPS) %s\n", FileName); + // } else { + // fprintf (MakeFptr, "INC_DEPS = $(INC_DEPS) $(SOURCE_DIR)\\%s\n", FileName); + // } + } + + RemoveFileSymbols (); + } + } + } + + return STATUS_SUCCESS; +} + +static +void +FreeFileParts ( + FILE_NAME_PARTS *FP + ) +{ + if (FP != NULL) { + if (FP->Path != NULL) { + free (FP->Path); + } + + if (FP->BaseName != NULL) { + free (FP->BaseName); + } + + if (FP->Extension != NULL) { + free (FP->Extension); + } + } +} + +static +FILE_NAME_PARTS * +GetFileParts ( + INT8 *FileName + ) +{ + FILE_NAME_PARTS *FP; + INT8 *Cptr; + INT8 CopyFileName[MAX_PATH]; + INT8 *FileNamePtr; + + strcpy (CopyFileName, FileName); + FP = (FILE_NAME_PARTS *) malloc (sizeof (FILE_NAME_PARTS)); + if (FP == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + return NULL; + } + + memset ((INT8 *) FP, 0, sizeof (FILE_NAME_PARTS)); + // + // Get extension code + // + FP->ExtensionCode = GetSourceFileType (CopyFileName); + // + // Get drive if there + // + FileNamePtr = CopyFileName; + if (FileNamePtr[1] == ':') { + FP->Drive[0] = FileNamePtr[0]; + FP->Drive[1] = ':'; + FileNamePtr += 2; + } + // + // Start at the end and work back + // + for (Cptr = FileNamePtr + strlen (FileNamePtr) - 1; (Cptr > FileNamePtr) && (*Cptr != '.'); Cptr--) + ; + + if (*Cptr == '.') { + // + // Don't copy the dot + // + FP->Extension = (char *) malloc (strlen (Cptr)); + strcpy (FP->Extension, Cptr + 1); + *Cptr = 0; + Cptr--; + StripTrailingSpaces (FP->Extension); + } else { + // + // Create empty string for extension + // + FP->Extension = (char *) malloc (1); + FP->Extension[0] = 0; + } + // + // Now back up and get the base name (include the preceding '\' or '/') + // + for (; (Cptr > FileNamePtr) && (*Cptr != '\\') && (*Cptr != '/'); Cptr--) + ; + FP->BaseName = (char *) malloc (strlen (Cptr) + 1); + strcpy (FP->BaseName, Cptr); + *Cptr = 0; + Cptr--; + // + // Rest is path + // + if (Cptr >= FileNamePtr) { + Cptr = FileNamePtr; + FP->Path = (char *) malloc (strlen (Cptr) + 1); + strcpy (FP->Path, Cptr); + } else { + FP->Path = (char *) malloc (1); + FP->Path[0] = 0; + } + + return FP; +} + +/***************************************************************************** +******************************************************************************/ +static +int +WriteCommonMakefile ( + DSC_FILE *DSCFile, + FILE *MakeFptr, + INT8 *Processor + ) +{ + INT8 InLine[MAX_LINE_LEN]; + INT8 OutLine[MAX_EXP_LINE_LEN]; + SECTION *Sect; + INT8 *Sym; + int i; + // + // Don't mess up the original file pointer, since we're processing it at a higher + // level. + // + DSCFileSavePosition (DSCFile); + // + // Write the header to the file + // + for (i = 0; MakefileHeader[i] != NULL; i++) { + fprintf (MakeFptr, "%s\n", MakefileHeader[i]); + } + + fprintf (MakeFptr, "#\n# Hard-coded defines output by the tool\n#\n"); + // + // First write the basics to the component's makefile. These includes + // EFI_SOURCE, BIN_DIR, OUT_DIR, LIB_DIR, SOURCE_DIR, DEST_DIR. + // + Sym = GetSymbolValue (EFI_SOURCE); + fprintf (MakeFptr, "%s = %s\n", EFI_SOURCE, Sym); + Sym = GetSymbolValue (BUILD_DIR); + fprintf (MakeFptr, "%s = %s\n", BUILD_DIR, Sym); + Sym = GetSymbolValue (BIN_DIR); + fprintf (MakeFptr, "%s = %s\n", BIN_DIR, Sym); + Sym = GetSymbolValue (OUT_DIR); + fprintf (MakeFptr, "%s = %s\n", OUT_DIR, Sym); + Sym = GetSymbolValue (LIB_DIR); + fprintf (MakeFptr, "%s = %s\n", LIB_DIR, Sym); + Sym = GetSymbolValue (SOURCE_DIR); + fprintf (MakeFptr, "%s = %s\n", SOURCE_DIR, Sym); + Sym = GetSymbolValue (DEST_DIR); + fprintf (MakeFptr, "%s = %s\n", DEST_DIR, Sym); + fprintf (MakeFptr, "\n"); + // + // If there was a [makefile.common] section in the description file, + // copy it (after symbol expansion) to the output file. + // + sprintf (InLine, "%s.%s", MAKEFILE_SECTION_NAME, COMMON_SECTION_NAME); + Sect = DSCFileFindSection (DSCFile, InLine); + if (Sect != NULL) { + // + // fprintf (MakeFptr, "# From the [makefile.common] section of the DSC file\n"); + // Read lines, expand, then dump out + // + while (DSCFileGetLine (DSCFile, InLine, sizeof (InLine)) != NULL) { + // + // Replace symbols + // + ExpandSymbols (InLine, OutLine, sizeof (OutLine), EXPANDMODE_RECURSIVE); + fprintf (MakeFptr, OutLine); + } + } + // + // If there was a [makefile.platform] section in the description file, + // copy it (after symbol expansion) to the output file. + // + sprintf (InLine, "%s.%s", MAKEFILE_SECTION_NAME, "Platform"); + Sect = DSCFileFindSection (DSCFile, InLine); + if (Sect != NULL) { + // + // Read lines, expand, then dump out + // + while (DSCFileGetLine (DSCFile, InLine, sizeof (InLine)) != NULL) { + // + // Replace symbols + // + ExpandSymbols (InLine, OutLine, sizeof (OutLine), EXPANDMODE_RECURSIVE); + fprintf (MakeFptr, OutLine); + } + } + // + // Do the same for any [makefile.$(PROCESSOR)] + // + sprintf (InLine, "%s.%s", MAKEFILE_SECTION_NAME, Processor); + Sect = DSCFileFindSection (DSCFile, InLine); + if (Sect != NULL) { + // + // Read lines, expand, then dump out + // + while (DSCFileGetLine (DSCFile, InLine, sizeof (InLine)) != NULL) { + ExpandSymbols (InLine, OutLine, sizeof (OutLine), EXPANDMODE_RECURSIVE); + fprintf (MakeFptr, OutLine); + } + } + // + // Same thing for [makefile.$(PROCESSOR).$(PLATFORM)] + // + Sym = GetSymbolValue (PLATFORM); + if (Sym != NULL) { + sprintf (InLine, "%s.%s.%s", MAKEFILE_SECTION_NAME, Processor, Sym); + Sect = DSCFileFindSection (DSCFile, InLine); + if (Sect != NULL) { + // + // Read lines, expand, then dump out + // + while (DSCFileGetLine (DSCFile, InLine, sizeof (InLine)) != NULL) { + ExpandSymbols (InLine, OutLine, sizeof (OutLine), EXPANDMODE_RECURSIVE); + fprintf (MakeFptr, OutLine); + } + } + } + + fprintf (MakeFptr, "\n"); + DSCFileRestorePosition (DSCFile); + return 0; +} + +static +int +WriteComponentTypeBuildCommands ( + DSC_FILE *DSCFile, + FILE *MakeFptr, + INT8 *SectionName + ) +/*++ + +Routine Description: + + Given a section name such as [build.ia32.library], find the section in + the description file and copy the build commands. + +Arguments: + + DSCFile - section information on the main description file + MakeFptr - file pointer to the makefile we're writing to + SectionName - name of the section we're to copy out to the makefile. + +Returns: + + Always successful, since the section may be optional. + +--*/ +{ + SECTION *Sect; + INT8 InLine[MAX_LINE_LEN]; + INT8 OutLine[MAX_EXP_LINE_LEN]; + + // + // Don't mess up the original file pointer, since we're processing it at a higher + // level. + // + DSCFileSavePosition (DSCFile); + Sect = DSCFileFindSection (DSCFile, SectionName); + if (Sect != NULL) { + // + // Read lines, expand, then dump out + // + while (DSCFileGetLine (DSCFile, InLine, sizeof (InLine)) != NULL) { + ExpandSymbols ( + InLine, + OutLine, + sizeof(OutLine), + EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR + ); + fprintf (MakeFptr, OutLine); + } + } else { + Warning ( + NULL, + 0, + 0, + GetSymbolValue (INF_FILENAME), + "no [%s] build commands found in DSC file for component", + SectionName + ); + } + + DSCFileRestorePosition (DSCFile); + return STATUS_SUCCESS; +} + +/***************************************************************************** + +******************************************************************************/ +static +int +WriteCompileCommands ( + DSC_FILE *DscFile, + FILE *MakeFptr, + INT8 *FileName, + INT8 *Processor + ) +{ + FILE_NAME_PARTS *File; + SECTION *Sect; + INT8 BuildSectionName[40]; + INT8 InLine[MAX_LINE_LEN]; + INT8 OutLine[MAX_EXP_LINE_LEN]; + INT8 *SourceCompileType; + char *CPtr; + char *CPtr2; + // + // Determine the filename, then chop it up into its parts + // + File = GetFileParts (FileName); + if (File != NULL) { + // + // Don't mess up the original file pointer, since we're processing it at a higher + // level. + // + DSCFileSavePosition (DscFile); + // + // Option 1: SOURCE_COMPILE_TYPE=MyCompileSection + // Find a section of that name from which to get the compile + // commands for this source file. + // Look for [compile.$(PROCESSOR).$(SOURCE_COMPILE_TYPE] + // Option 2: COMPILE_SELECT=.c=MyCCompile,.asm=MyAsm + // Find a [compile.$(PROCESSOR).MyCompile] section from which to + // get the compile commands for this source file. + // Look for [compile.$(PROCESSOR).MyCompile] + // Option 3: Look for standard section types to compile the file by extension. + // Look for [compile.$(PROCESSOR).] + // + Sect = NULL; + // + // Option 1 - use SOURCE_COMPILE_TYPE variable + // + SourceCompileType = GetSymbolValue (SOURCE_COMPILE_TYPE); + if (SourceCompileType != NULL) { + sprintf (BuildSectionName, "compile.%s.%s", Processor, SourceCompileType); + Sect = DSCFileFindSection (DscFile, BuildSectionName); + } + // + // Option 2 - use COMPILE_SELECT variable + // + if (Sect == NULL) { + SourceCompileType = GetSymbolValue (COMPILE_SELECT); + if (SourceCompileType != NULL) { + // + // Parse the variable, which looks like COMPILE_SELECT=.c=MyCCompiler;.asm=MyAsm; + // to find an entry with a matching file name extension. If you find one, + // then use that name to find the section name. + // + CPtr = SourceCompileType; + while (*CPtr && (Sect == NULL)) { + // + // See if we found a match with this source file name extension. File->Extension + // does not include the dot, so skip the dot in the COMPILE_SELECT variable if there + // is one. + // + if (*CPtr == '.') { + CPtr++; + } + + if (_strnicmp (CPtr, File->Extension, strlen (File->Extension)) == 0) { + // + // Found a file name extension match -- extract the name from the variable, for + // example "MyCCompiler" + // + while (*CPtr && (*CPtr != '=')) { + CPtr++; + } + + if ((*CPtr != '=') || (CPtr[1] == 0)) { + Error (NULL, 0, 0, SourceCompileType, "malformed COMPILE_SELECT variable"); + break; + } + + CPtr++; + sprintf (BuildSectionName, "compile.%s.", Processor); + for (CPtr2 = BuildSectionName + strlen (BuildSectionName); + *CPtr && (*CPtr != ',') && (*CPtr != ';'); + CPtr++ + ) { + *CPtr2 = *CPtr; + CPtr2++; + } + + *CPtr2 = 0; + Sect = DSCFileFindSection (DscFile, BuildSectionName); + if (Sect == NULL) { + ParserError ( + 0, + BuildSectionName, + "could not find section in DSC file - selected by COMPILE_SELECT variable" + ); + } + } + + // + // Skip to next file name extension in the COMPILE_SELECT variable + // + while (*CPtr && (*CPtr != ';') && (*CPtr != ',')) { + CPtr++; + } + + if (*CPtr) { + CPtr++; + } + } + } + } + // + // Option 3 - use "Compile.$(PROCESSOR)." section + // + if (Sect == NULL) { + sprintf (BuildSectionName, "compile.%s.%s", Processor, File->Extension); + Sect = DSCFileFindSection (DscFile, BuildSectionName); + } + // + // Should have found something by now unless it's an include (.h) file + // + if (Sect != NULL) { + // + // Temporarily add a FILE variable to the global symbol table. Omit the + // extension. + // + sprintf (InLine, "%s%s%s", File->Drive, File->Path, File->BaseName); + AddSymbol ("FILE", InLine, SYM_OVERWRITE | SYM_LOCAL | SYM_FILENAME); + // + // Read lines, expand (except SOURCE_DIR and DEST_DIR), then dump out + // + while (DSCFileGetLine (DscFile, InLine, sizeof (InLine)) != NULL) { + ExpandSymbols ( + InLine, + OutLine, + sizeof (OutLine), + EXPANDMODE_NO_DESTDIR | EXPANDMODE_NO_SOURCEDIR + ); + fprintf (MakeFptr, OutLine); + } + fprintf (MakeFptr, "\n"); + } else { + // + // Be nice and ignore include files + // + if (!IsIncludeFile (FileName)) { + Error ( + NULL, + 0, + 0, + NULL, + "no compile commands section [%s] found in DSC file for %s", + BuildSectionName, + FileName + ); + } + } + + DSCFileRestorePosition (DscFile); + FreeFileParts (File); + } + + return STATUS_SUCCESS; +} + +/***************************************************************************** +******************************************************************************/ +static +int +SetFileExtension ( + INT8 *FileName, + INT8 *Extension + ) +{ + INT8 *Cptr; + + Cptr = FileName + strlen (FileName) - 1; + while ((Cptr > FileName) && (*Cptr != '.')) { + Cptr--; + + } + // + // Better be a dot + // + if (*Cptr != '.') { + Message (2, "Missing filename extension: %s", FileName); + return STATUS_WARNING; + } + + Cptr++; + if (*Extension == '.') { + Extension++; + } + + strcpy (Cptr, Extension); + return STATUS_SUCCESS; +} + +/***************************************************************************** +******************************************************************************/ +int +MakeFilePath ( + INT8 *FileName + ) +{ + INT8 *Cptr; + INT8 SavedChar; + INT8 BuildDir[MAX_PATH]; + INT8 CopyFileName[MAX_PATH]; + + // + // Expand symbols in the filename + // + if (ExpandSymbols (FileName, CopyFileName, sizeof (CopyFileName), EXPANDMODE_NO_UNDEFS)) { + Error (NULL, 0, 0, NULL, "undefined symbols in file path: %s", FileName); + return STATUS_ERROR; + } + // + // Copy it back + // + strcpy (FileName, CopyFileName); + // + // To avoid creating $(BUILD_DIR) path, see if this path is the same as + // $(BUILD_DIR), and if it is, see if build dir exists and skip over that + // portion if it does + // + Cptr = GetSymbolValue (BUILD_DIR); + if (Cptr != NULL) { + if (_strnicmp (Cptr, FileName, strlen (Cptr)) == 0) { + // + // BUILD_DIR path. See if it exists + // + strcpy (BuildDir, FileName); + BuildDir[strlen (Cptr)] = 0; + if ((_mkdir (BuildDir) != 0) && (errno != EEXIST)) { + Cptr = FileName; + } else { + // + // Already done. Shortcut. Skip to next path so that we don't create + // the BUILD_DIR as well. + // + Cptr = FileName + strlen (Cptr); + if (*Cptr == '\\') { + Cptr++; + } + } + } else { + // + // Not build dir + // + Cptr = FileName; + } + } else { + Cptr = FileName; + } + // + // Create directories until done. Skip over "c:\" in the path if it exists + // + if (*Cptr && (*(Cptr + 1) == ':') && (*(Cptr + 2) == '\\')) { + Cptr += 3; + } + + for (;;) { + for (; *Cptr && (*Cptr != '/') && (*Cptr != '\\'); Cptr++) + ; + if (*Cptr) { + SavedChar = *Cptr; + *Cptr = 0; + if ((_mkdir (FileName) != 0)) { + // + // Error (NULL, 0, 0, FileName, "failed to create directory"); + // return 1; + // + } + + *Cptr = SavedChar; + Cptr++; + } else { + break; + } + } + + return STATUS_SUCCESS; +} + +/***************************************************************************** +******************************************************************************/ +int +ExpandSymbols ( + INT8 *SourceLine, + INT8 *DestLine, + int LineLen, + int ExpandMode + ) +{ + static int NestDepth = 0; + INT8 *FromPtr; + INT8 *ToPtr; + INT8 *SaveStart; + INT8 *Cptr; + INT8 *value; + int Expanded; + int ExpandedCount; + INT8 *LocalDestLine; + STATUS Status; + int LocalLineLen; + + NestDepth++; + Status = STATUS_SUCCESS; + LocalDestLine = (INT8 *) malloc (LineLen); + if (LocalDestLine == NULL) { + Error (__FILE__, __LINE__, 0, "application error", "memory allocation failed"); + NestDepth = 0; + return STATUS_ERROR; + } + + FromPtr = SourceLine; + ToPtr = LocalDestLine; + // + // Walk the entire line, replacing $(SYMBOL_NAME). + // + LocalLineLen = LineLen; + ExpandedCount = 0; + while (*FromPtr && (LocalLineLen > 0)) { + if ((*FromPtr == '$') && (*(FromPtr + 1) == '(')) { + // + // Save the start in case it's undefined, in which case we copy it as-is. + // + SaveStart = FromPtr; + Expanded = 0; + // + // Symbol expansion time. Find the end (no spaces allowed) + // + FromPtr += 2; + for (Cptr = FromPtr; *Cptr && (*Cptr != ')'); Cptr++) + ; + if (*Cptr) { + // + // Truncate the string at the closing parenthesis for ease-of-use. + // Then copy the string directly to the destination line in case we don't find + // a definition for it. + // + *Cptr = 0; + strcpy (ToPtr, SaveStart); + if ((_stricmp (SOURCE_DIR, FromPtr) == 0) && (ExpandMode & EXPANDMODE_NO_SOURCEDIR)) { + // + // excluded this expansion + // + } else if ((_stricmp (DEST_DIR, FromPtr) == 0) && (ExpandMode & EXPANDMODE_NO_DESTDIR)) { + // + // excluded this expansion + // + } else if ((value = GetSymbolValue (FromPtr)) != NULL) { + strcpy (ToPtr, value); + LocalLineLen -= strlen (value); + ToPtr += strlen (value); + Expanded = 1; + ExpandedCount++; + } else if (ExpandMode & EXPANDMODE_NO_UNDEFS) { + Error (NULL, 0, 0, "undefined symbol", "$(%s)", FromPtr); + Status = STATUS_ERROR; + goto Done; + } + + // + // Restore closing parenthesis, and advance to next character + // + *Cptr = ')'; + if (!Expanded) { + FromPtr = SaveStart + 1; + ToPtr++; + } else { + FromPtr = Cptr + 1; + } + } else { + Error (NULL, 0, 0, SourceLine, "missing closing parenthesis on symbol"); + strcpy (ToPtr, FromPtr); + Status = STATUS_WARNING; + goto Done; + } + } else { + *ToPtr = *FromPtr; + FromPtr++; + ToPtr++; + LocalLineLen--; + } + } + + if (*FromPtr == 0) { + *ToPtr = 0; + } + + // + // If we're in recursive mode, and we expanded at least one string successfully, + // then make a recursive call to try again. + // + if ((ExpandedCount != 0) && (Status == STATUS_SUCCESS) && (ExpandMode & EXPANDMODE_RECURSIVE) && (NestDepth < 2)) { + Status = ExpandSymbols (LocalDestLine, DestLine, LineLen, ExpandMode); + free (LocalDestLine); + NestDepth = 0; + return Status; + } + +Done: + if (Status != STATUS_ERROR) { + strcpy (DestLine, LocalDestLine); + } + + NestDepth = 0; + free (LocalDestLine); + return Status; +} + +INT8 * +GetSymbolValue ( + INT8 *SymbolName + ) +/*++ + +Routine Description: + + Look up a symbol in our symbol table. + +Arguments: + + SymbolName - The name of symbol. + +Returns: + + Pointer to the value of the symbol if found + NULL if the symbol is not found + +--*/ +{ + SYMBOL *Symbol; + + // + // Scan once for file-level symbols + // + Symbol = gGlobals.Symbol; + while (Symbol) { + if ((_stricmp (SymbolName, Symbol->Name) == 0) && (Symbol->Type & SYM_FILE)) { + return Symbol->Value; + } + + Symbol = Symbol->Next; + } + // + // Scan once for local symbols + // + Symbol = gGlobals.Symbol; + while (Symbol) { + if ((_stricmp (SymbolName, Symbol->Name) == 0) && (Symbol->Type & SYM_LOCAL)) { + return Symbol->Value; + } + + Symbol = Symbol->Next; + } + // + // No local value found. Scan for globals. + // + Symbol = gGlobals.Symbol; + while (Symbol) { + if ((_stricmp (SymbolName, Symbol->Name) == 0) && (Symbol->Type & SYM_GLOBAL)) { + return Symbol->Value; + } + + Symbol = Symbol->Next; + } + // + // For backwards-compatibility, if it's "GUID", return FILE_GUID value + // + if (_stricmp (SymbolName, GUID) == 0) { + return GetSymbolValue (FILE_GUID); + } + + return NULL; +} + +static +int +RemoveLocalSymbols ( + VOID + ) +/*++ + +Routine Description: + + Remove all local symbols from the symbol table. Local symbols are those + that are defined typically by the component's INF file. + +Arguments: + + None. + +Returns: + + Right now, never fails. + +--*/ +{ + SYMBOL *Sym; + int FoundOne; + + do { + FoundOne = 0; + Sym = gGlobals.Symbol; + while (Sym) { + if (Sym->Type & SYM_LOCAL) { + // + // Going to delete it out from under ourselves, so break and restart + // + FoundOne = 1; + RemoveSymbol (Sym->Name, SYM_LOCAL); + break; + } + + Sym = Sym->Next; + } + } while (FoundOne); + return STATUS_SUCCESS; +} + +static +int +RemoveFileSymbols ( + VOID + ) +/*++ + +Routine Description: + + Remove all file-level symbols from the symbol table. File-level symbols are + those that are defined on a source file line in an INF file. + +Arguments: + + None. + +Returns: + + Right now, never fails. + +--*/ +{ + SYMBOL *Sym; + int FoundOne; + + do { + FoundOne = 0; + Sym = gGlobals.Symbol; + while (Sym) { + if (Sym->Type & SYM_FILE) { + // + // Going to delete it out from under ourselves, so break and restart + // + FoundOne = 1; + RemoveSymbol (Sym->Name, SYM_FILE); + break; + } + + Sym = Sym->Next; + } + } while (FoundOne); + return STATUS_SUCCESS; +} + +static +STATUS +ParseGuidDatabaseFile ( + INT8 *FileName + ) +/*++ + +Routine Description: + This function parses a GUID-to-basename text file (perhaps output by + the GuidChk utility) to define additional symbols. The format of the + file should be: + + 7BB28B99-61BB-11D5-9A5D-0090273FC14D EFI_DEFAULT_BMP_LOGO_GUID gEfiDefaultBmpLogoGuid + + This function parses the line and defines global symbol: + + EFI_DEFAULT_BMP_LOGO_GUID=7BB28B99-61BB-11D5-9A5D-0090273FC14D + + This symbol (rather than the actual GUID) can then be used in INF files to + fix duplicate GUIDs + +Arguments: + FileName - the name of the file to parse. + +Returns: + STATUS_ERROR - could not open FileName + STATUS_SUCCESS - we opened the file + +--*/ +{ + FILE *Fptr; + INT8 Line[100]; + INT8 Guid[100]; + INT8 DefineName[80]; + + Fptr = fopen (FileName, "r"); + if (Fptr == NULL) { + Error (NULL, 0, 0, FileName, "failed to open input GUID database input file"); + return STATUS_ERROR; + } + + while (fgets (Line, sizeof (Line), Fptr) != NULL) { + // + // Get the GUID string, skip the defined name (EFI_XXX_GUID), and get the + // variable name (gWhateverProtocolGuid) + // + if (sscanf (Line, "%s %s %*s", Guid, DefineName) == 2) { + AddSymbol (DefineName, Guid, SYM_GLOBAL); + } + } + + fclose (Fptr); + return STATUS_SUCCESS; +} + +/***************************************************************************** + + Returns: + 0 if successful standard add + length of the parsed string if passed in " name = value " + < 0 on error + +******************************************************************************/ +int +AddSymbol ( + INT8 *Name, + INT8 *Value, + int Mode + ) +{ + SYMBOL *Symbol; + SYMBOL *NewSymbol; + int Len; + INT8 *Start; + INT8 *Cptr; + INT8 CSave1; + INT8 *SaveCptr1; + INT8 CSave2; + INT8 *SaveCptr2; + INT8 ShortName[MAX_PATH]; + + Len = 0; + SaveCptr1 = NULL; + CSave1 = 0; + SaveCptr2 = NULL; + CSave2 = 0; + + ShortName[0] = 0; + // + // Mode better be local or global symbol + // + if ((Mode & (SYM_LOCAL | SYM_GLOBAL | SYM_FILE)) == 0) { + Error (NULL, 0, 0, "APP ERROR", "adding symbol '%s' that is not local, global, nor file level", Name); + return -1; + } + // + // If value pointer is null, then they passed us a line something like: + // varname = value, or simply var = + // + if (Value == NULL) { + Start = Name; + while (*Name && isspace (*Name)) { + Name++; + + } + + if (!*Name) { + return -1; + } + // + // Find the end of the name. Either space or a '='. + // + for (Value = Name; *Value && !isspace (*Value) && (*Value != '='); Value++) + ; + if (!*Value) { + return -1; + } + // + // Look for the '=' + // + Cptr = Value; + while (*Value && (*Value != '=')) { + Value++; + } + + if (!*Value) { + return -1; + } + + // + // Now truncate the name + // + CSave1 = *Cptr; + SaveCptr1 = Cptr; + *Cptr = 0; + + // + // Skip over the = and then any spaces + // + Value++; + while (*Value && isspace (*Value)) { + Value++; + + } + // + // Find end of string, checking for quoted string + // + if (*Value == '\"') { + Value++; + for (Cptr = Value; *Cptr && *Cptr != '\"'; Cptr++) + ; + } else { + for (Cptr = Value; *Cptr && !isspace (*Cptr); Cptr++) + ; + } + // + // Null terminate the value string + // + if (*Cptr) { + Len = (int) (Cptr - Start) + 1; + CSave2 = *Cptr; + SaveCptr2 = Cptr; + *Cptr = 0; + } else { + Len = (int) (Cptr - Start); + } + } + + // + // If file name or file path, and we're shortening, then print it + // + if ((Mode & (SYM_FILEPATH | SYM_FILENAME)) && (GetSymbolValue (SHORT_NAMES) != NULL)) { + if (GetShortPathName (Value, ShortName, sizeof (ShortName)) > 0) { + // + // fprintf (stdout, "String value '%s' shortened to '%s'\n", + // Value, ShortName); + // + Value = ShortName; + } else { + // + // fprintf (stdout, "WARNING: Failed to get short name for %s\n", Value); + // + } + } + // + // We now have a symbol name and a value. Look for an existing variable of + // the same type (global or local) and overwrite it. + // + Symbol = gGlobals.Symbol; + while (Symbol) { + // + // Check for symbol name match + // + if (_stricmp (Name, Symbol->Name) == 0) { + // + // See if this symbol is of the same type (global or local) as what + // they're requesting + // + if ((Symbol->Type & (SYM_LOCAL | SYM_GLOBAL)) == (Mode & (SYM_LOCAL | SYM_GLOBAL))) { + // + // Did they say we could overwrite it? + // + if (Mode & SYM_OVERWRITE) { + free (Symbol->Value); + Symbol->Value = (INT8 *) malloc (strlen (Value) + 1); + if (Symbol->Value == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + return -1; + } + + strcpy (Symbol->Value, Value); + // + // If value == "NULL", then make it a 0-length string + // + if (_stricmp (Symbol->Value, "NULL") == 0) { + Symbol->Value[0] = 0; + } + + return Len; + } else { + return STATUS_ERROR; + } + } + } + + Symbol = Symbol->Next; + } + // + // Does not exist, create a new one + // + NewSymbol = (SYMBOL *) malloc (sizeof (SYMBOL)); + if (NewSymbol == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + return -1; + } + + memset ((INT8 *) NewSymbol, 0, sizeof (SYMBOL)); + NewSymbol->Name = (INT8 *) malloc (strlen (Name) + 1); + NewSymbol->Value = (INT8 *) malloc (strlen (Value) + 1); + // + // Simply use the mode bits as the type. + // + NewSymbol->Type = Mode; + if ((NewSymbol->Name == NULL) || (NewSymbol->Value == NULL)) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + return -1; + } + + strcpy (NewSymbol->Name, Name); + strcpy (NewSymbol->Value, Value); + // + // Remove trailing spaces + // + Cptr = NewSymbol->Value + strlen (NewSymbol->Value) - 1; + while (Cptr > NewSymbol->Value) { + if (isspace (*Cptr)) { + *Cptr = 0; + Cptr--; + } else { + break; + } + } + // + // Add it to the head of the list. + // + NewSymbol->Next = gGlobals.Symbol; + gGlobals.Symbol = NewSymbol; + // + // If value == "NULL", then make it a 0-length string + // + if (_stricmp (NewSymbol->Value, "NULL") == 0) { + NewSymbol->Value[0] = 0; + } + // + // Restore the terminator we inserted if they passed in var=value + // + if (SaveCptr1 != NULL) { + *SaveCptr1 = CSave1; + } + if (SaveCptr2 != NULL) { + *SaveCptr2 = CSave2; + } + + return Len; +} + +/***************************************************************************** +******************************************************************************/ +static +int +RemoveSymbol ( + INT8 *Name, + INT8 SymbolType + ) +{ + SYMBOL *Symbol; + SYMBOL *PrevSymbol; + + PrevSymbol = NULL; + Symbol = gGlobals.Symbol; + while (Symbol) { + if ((_stricmp (Name, Symbol->Name) == 0) && (Symbol->Type & SymbolType)) { + if (Symbol->Value) { + free (Symbol->Value); + } + + free (Symbol->Name); + if (PrevSymbol) { + PrevSymbol->Next = Symbol->Next; + } else { + gGlobals.Symbol = Symbol->Next; + } + + free (Symbol); + return STATUS_SUCCESS; + } + + PrevSymbol = Symbol; + Symbol = Symbol->Next; + } + + return STATUS_WARNING; +} + +#if 0 + +/***************************************************************************** +******************************************************************************/ +static +void +FreeSections ( + SECTION *Sect + ) +{ + SECTION *Next; + + while (Sect != NULL) { + Next = Sect->Next; + if (Sect->Name != NULL) { + delete[] Sect->Name; + } + + delete Sect; + Sect = Next; + } +} +#endif + +/***************************************************************************** +******************************************************************************/ +static +INT8 * +StripLine ( + INT8 *Line + ) +{ + INT8 *Cptr; + int Len; + + Cptr = Line; + // + // Look for '#' comments in first character of line + // + if (*Cptr == '#') { + *Cptr = 0; + return Cptr; + } + + while (isspace (*Cptr)) { + Cptr++; + } + // + // Hack off newlines + // + Len = strlen (Cptr); + if ((Len > 0) && (Cptr[Len - 1] == '\n')) { + Cptr[Len - 1] = 0; + } + // + // Hack off trailing spaces + // + StripTrailingSpaces (Cptr); + return Cptr; +} + +/***************************************************************************** + FUNCTION: ProcessOptions() + + DESCRIPTION: Process the command-line options. +******************************************************************************/ +static +int +ProcessOptions ( + int Argc, + INT8 *Argv[] + ) +/*++ + +Routine Description: + + Process the command line options to this utility. + +Arguments: + + Argc - Standard Argc. + Argv[] - Standard Argv. + +Returns: + +--*/ +{ + INT8 *Cptr; + int FreeCwd; + + // + // Clear out the options + // + memset ((INT8 *) &gGlobals, 0, sizeof (gGlobals)); + + Argc--; + Argv++; + + if (Argc == 0) { + Usage (); + return STATUS_ERROR; + } + // + // Now process the arguments + // + while (Argc > 0) { + + if ((Argv[0][0] == '-') || (Argv[0][0] == '/')) { + switch (Argv[0][1]) { + // + // -? or -h help option + // + case '?': + case 'h': + case 'H': + Usage (); + return STATUS_ERROR; + + // + // /d symbol=name + // + case 'd': + case 'D': + // + // Skip to next arg + // + Argc--; + Argv++; + if (Argc == 0) { + Argv--; + Error (NULL, 0, 0, NULL, "missing symbol definition with %c%c", Argv[0][0], Argv[0][1]); + return STATUS_ERROR; + } else { + if (AddSymbol (Argv[0], NULL, SYM_OVERWRITE | SYM_GLOBAL) <= 0) { + Warning (NULL, 0, 0, Argv[0], "failed to add symbol: %s"); + } + } + break; + + // + // output makefile name + // + case 'm': + case 'M': + // + // Skip to next arg + // + Argc--; + Argv++; + if (Argc == 0) { + Argv--; + Error (NULL, 0, 0, Argv[0], "missing output makefile name with option"); + Usage (); + return STATUS_ERROR; + } else { + strcpy (gGlobals.MakefileName, Argv[0]); + } + break; + + // + // Print a cross-reference file containing guid/basename/processor + // + case 'x': + case 'X': + // + // Skip to next arg + // + Argc--; + Argv++; + if (Argc == 0) { + Argv--; + Error (NULL, 0, 0, Argv[0], "missing cross-reference output filename with option"); + Usage (); + return STATUS_ERROR; + } else { + strcpy (gGlobals.XRefFileName, Argv[0]); + } + break; + + // + // GUID database file to preparse + // + case 'g': + case 'G': + // + // Skip to next arg + // + Argc--; + Argv++; + if (Argc == 0) { + Argv--; + Error (NULL, 0, 0, Argv[0], "missing input GUID database filename with option"); + Usage (); + return STATUS_ERROR; + } else { + strcpy (gGlobals.GuidDatabaseFileName, Argv[0]); + } + break; + + case 'v': + case 'V': + gGlobals.Verbose = 1; + break; + + default: + Error (NULL, 0, 0, Argv[0], "unrecognized option"); + return STATUS_ERROR; + } + } else { + break; + } + + Argc--; + Argv++; + } + // + // Must be at least one arg left + // + if (Argc > 0) { + gGlobals.DscFilename = Argv[0]; + } + + if (gGlobals.DscFilename == NULL) { + Error (NULL, 0, 0, NULL, "must specify DSC filename on command line"); + return STATUS_ERROR; + } + // + // Make a global symbol for the DSC filename + // + AddSymbol (DSC_FILENAME, gGlobals.DscFilename, SYM_GLOBAL | SYM_FILENAME); + // + // If no output makefile specified, take the default + // + if (gGlobals.MakefileName[0] == 0) { + strcpy (gGlobals.MakefileName, MAKEFILE_OUT_NAME); + } + // + // Get the current working directory and use it for the build directory. + // Only do this if they have not defined it on the command line. Do the + // same for the bin dir, output dir, and library directory. + // + Cptr = GetSymbolValue (BUILD_DIR); + if (Cptr == NULL) { + Cptr = _getcwd (NULL, 0); + FreeCwd = 1; + AddSymbol (BUILD_DIR, Cptr, SYM_OVERWRITE | SYM_GLOBAL | SYM_FILEPATH); + } else { + FreeCwd = 0; + } + + if (FreeCwd) { + free (Cptr); + } + + return 0; +} + +/***************************************************************************** +******************************************************************************/ +static +SYMBOL * +FreeSymbols ( + SYMBOL *Syms + ) +{ + SYMBOL *Next; + while (Syms) { + + if (Syms->Name != NULL) { + free (Syms->Name); + } + + if (Syms->Value != NULL) { + free (Syms->Value); + } + + Next = Syms->Next; + free (Syms); + Syms = Next; + } + + return Syms; +} + +/***************************************************************************** +******************************************************************************/ +static +int +GetSourceFileType ( + INT8 *FileName + ) +{ + INT8 *Cptr; + int len; + int i; + + len = strlen (FileName); + if (len == 0) { + return FILETYPE_UNKNOWN; + + } + + Cptr = FileName + len - 1; + while ((*Cptr != '.') && (Cptr >= FileName)) { + Cptr--; + + } + + if (*Cptr == '.') { + + for (i = 0; mFileTypes[i].Extension != NULL; i++) { + len = strlen (mFileTypes[i].Extension); + if (_strnicmp (mFileTypes[i].Extension, Cptr, len) == 0) { + if ((*(Cptr + len) == 0) || isspace (*(Cptr + len))) { + return mFileTypes[i].FileType; + } + } + } + } + + return FILETYPE_UNKNOWN; +} +// +// Determine if a given file is a standard include file. If we don't know, +// then assume it's not. +// +static +int +IsIncludeFile ( + INT8 *FileName + ) +{ + INT8 *Cptr; + int len; + int i; + + len = strlen (FileName); + if (len == 0) { + return 0; + } + + Cptr = FileName + len - 1; + while ((*Cptr != '.') && (Cptr >= FileName)) { + Cptr--; + } + + if (*Cptr == '.') { + // + // Now go through the list of filename extensions and try to find + // a match for this file extension. + // + for (i = 0; mFileTypes[i].Extension != NULL; i++) { + len = strlen (mFileTypes[i].Extension); + if (_strnicmp (mFileTypes[i].Extension, Cptr, len) == 0) { + // + // Make sure that's all there is to the filename extension. + // + if ((*(Cptr + len) == 0) || isspace (*(Cptr + len))) { + return mFileTypes[i].FileFlags & FILE_FLAG_INCLUDE; + } + } + } + } + + return 0; +} + +/***************************************************************************** +******************************************************************************/ +static +void +StripTrailingSpaces ( + INT8 *Str + ) +{ + INT8 *Cptr; + Cptr = Str + strlen (Str) - 1; + while (Cptr > Str) { + if (isspace (*Cptr)) { + *Cptr = 0; + Cptr--; + } else { + break; + } + } +} + +/***************************************************************************** +******************************************************************************/ +static +int +GetEfiSource ( + VOID + ) +{ + INT8 *EfiSource; + + // + // Don't set it if the user specified it on the command line. + // + EfiSource = GetSymbolValue (EFI_SOURCE); + if ( EfiSource != NULL) { + if (EfiSource[strlen (EfiSource) - 1] == '\\') { + EfiSource[strlen (EfiSource) - 1] = 0; + } + return STATUS_SUCCESS; + } + + // + // Get the environmental variable setting of EFI_SOURCE. + // + EfiSource = getenv (EFI_SOURCE); + if (EfiSource != NULL) { + if (EfiSource[strlen (EfiSource) - 1] == '\\') { + EfiSource[strlen (EfiSource) - 1] = 0; + } + AddSymbol (EFI_SOURCE, EfiSource, SYM_GLOBAL | SYM_FILEPATH); + return STATUS_SUCCESS; + } + + Error (NULL, 0, 0, NULL, "could not determine EFI_SOURCE"); + return STATUS_ERROR; +} + +void +Message ( + UINT32 PrintMask, + INT8 *Fmt, + ... + ) +{ + INT8 Line[MAX_LINE_LEN]; + va_list List; + + va_start (List, Fmt); + vsprintf (Line, Fmt, List); + if (PrintMask & gGlobals.Verbose) { + fprintf (stdout, "%s\n", Line); + } + + va_end (List); +} + +static +void +Usage ( + VOID + ) +{ + int i; + static const INT8 *Help[] = { + "Usage: ProcessDsc {options} [Dsc Filename]", + " Options:", + " -d var=value to define symbol 'var' to 'value'", + " -v for verbose mode", + " -g filename to preparse GUID listing file", + " -x filename to create a cross-reference file", + NULL + }; + for (i = 0; Help[i] != NULL; i++) { + fprintf (stdout, "%s\n", Help[i]); + } +} + +/*++ + +Routine Description: + + Process the [defines] section in the DSC file. + +Arguments: + + DscFile - pointer to the DSCFile class that contains the relevant info. + +Returns: + + 0 if not necessarily an absolute path + 1 otherwise + +--*/ +static +int +ProcessDSCDefinesSection ( + DSC_FILE *DscFile + ) +{ + INT8 Line[MAX_LINE_LEN]; + INT8 Line2[MAX_EXP_LINE_LEN]; + INT8 *Cptr; + SECTION *Sect; + + // + // Look for a [defines] section and process it + // + Sect = DSCFileFindSection (DscFile, DEFINES_SECTION_NAME); + if (Sect == NULL) { + return STATUS_ERROR; + } + // + // Read lines while they're valid + // + while (DSCFileGetLine (DscFile, Line, sizeof (Line)) != NULL) { + // + // Expand symbols on the line + // + if (ExpandSymbols (Line, Line2, sizeof (Line2), 0)) { + return STATUS_ERROR; + } + // + // Strip the line + // + Cptr = StripLine (Line2); + if (*Cptr) { + // + // Make the assignment + // + AddSymbol (Line2, NULL, SYM_OVERWRITE | SYM_GLOBAL); + } + } + + return STATUS_SUCCESS; +} + +int +IsAbsolutePath ( + char *FileName + ) +/*++ + +Routine Description: + + Determine if a given filename contains the full path information. + +Arguments: + + FileName - the name of the file, with symbol expanded. + +Returns: + + 0 if not necessarily an absolute path + 1 otherwise + +--*/ +{ + // + // If the first character is a-z, and the second character is a colon, then + // it is an absolute path. + // + if (isalpha (FileName[0]) && (FileName[1] == ':')) { + return 1; + } + + return 0; +} + +SMART_FILE * +SmartOpen ( + char *FileName + ) +{ + SMART_FILE *SmartFile; + FILE *Fptr; + int FileSize; + + SmartFile = malloc (sizeof (SMART_FILE)); + if (SmartFile == NULL) { + return NULL; + } + memset (SmartFile, 0, sizeof (SMART_FILE)); + + SmartFile->FileName = malloc (strlen (FileName) + 1); + if (SmartFile->FileName == NULL){ + SmartFree (SmartFile); + return NULL; + } + strcpy (SmartFile->FileName, FileName); + + if ((Fptr = fopen (FileName, "r")) != NULL) { + fseek (Fptr, 0, SEEK_END); + FileSize = ftell (Fptr); + fseek (Fptr, 0, SEEK_SET); + SmartFile->FileContent = malloc (FileSize + 1); + if (SmartFile->FileContent != NULL) { + memset (SmartFile->FileContent, 0, FileSize + 1); + // + // Usually FileLength < FileSize, because in text mode, carriage return¨Clinefeed + // combinations are translated into single linefeeds on input + // + SmartFile->FileLength = fread (SmartFile->FileContent, sizeof(char), FileSize, Fptr); + } + fclose (Fptr); + } + + // + // No previous output file content, re-create the file + // + if (SmartFile->FileContent == NULL) { + if ((SmartFile->FilePtr = fopen (FileName, "w")) == NULL) { + SmartFree (SmartFile); + return NULL; + } + } + + return SmartFile; +} + +int +SmartWrite ( + SMART_FILE *SmartFile, + char *String + ) +{ + int StrLen; + + if (SmartFile->FilePtr != NULL) { + return fprintf (SmartFile->FilePtr, "%s", String); + } else { + StrLen = strlen (String); + if ((StrLen > SmartFile->FileLength - SmartFile->FilePosition) || + (_strnicmp (&SmartFile->FileContent[SmartFile->FilePosition], String, StrLen) != 0)) { + // + // file changed, need to re-create. + // + if ((SmartFile->FilePtr = fopen (SmartFile->FileName, "w")) == NULL) { + Error (NULL, 0, 0, SmartFile->FileName, "could not open file for writing when SmartWrite"); + return -1; + } else { + SmartFile->FileContent[SmartFile->FilePosition] = 0; + fprintf (SmartFile->FilePtr, "%s%s", SmartFile->FileContent, String); + return StrLen; + } + } else { + SmartFile->FilePosition += StrLen; + return StrLen; + } + } +} + +void +SmartClose ( + SMART_FILE *SmartFile + ) +{ + if ((SmartFile->FilePtr == NULL) && (SmartFile->FilePosition < SmartFile->FileLength)) { + // + // The new file is smaller than before, re-create it. + // + if ((SmartFile->FilePtr = fopen (SmartFile->FileName, "w")) == NULL) { + Error (NULL, 0, 0, SmartFile->FileName, "could not open file for writing when SmartClose"); + } else { + SmartFile->FileContent[SmartFile->FilePosition] = 0; + fprintf (SmartFile->FilePtr, "%s", SmartFile->FileContent); + } + } + + SmartFree(SmartFile); +} + +static +void +SmartFree ( + SMART_FILE *SmartFile + ) +{ + if (SmartFile == NULL) { + return; + } + + if (SmartFile->FileName != NULL ) { + free (SmartFile->FileName); + } + + if (SmartFile->FileContent != NULL ) { + free (SmartFile->FileContent); + } + + if (SmartFile->FilePtr != NULL ) { + fclose (SmartFile->FilePtr); + } + + free (SmartFile); + + return; +} + +static +int +AddModuleName ( + SYMBOL **SymbolList, + INT8 *ModuleName, + INT8 *InfName + ) +/*++ + +Routine Description: + + Add module name in the global module list. + For the same module names, it is only added once. + +Arguments: + SymbolList : add name into this list + ModuleName : point to one module name char string. + InfName : point to this module inf file name with path. + +Returns: + + 0 : Successfully add input name into the global list. + other value : allocate memory failed. + +--*/ +{ + SYMBOL *CurrentSymbol; + SYMBOL *LastSymbol; + + // + // Get the global module list. + // + CurrentSymbol = *SymbolList; + LastSymbol = *SymbolList; + + // + // Search whether this module name has been added into the global list. + // + while (CurrentSymbol != NULL) { + if (_stricmp (CurrentSymbol->Name, ModuleName) == 0) { + if ((CurrentSymbol->Value == NULL) && (InfName == NULL)) { + break; + } else if ((CurrentSymbol->Value != NULL) && (InfName != NULL) && \ + (_stricmp (CurrentSymbol->Value, InfName) == 0)) { + break; + } + } + LastSymbol = CurrentSymbol; + CurrentSymbol = CurrentSymbol->Next; + } + + // + // Add new module name in list. + // + if (CurrentSymbol == NULL) { + CurrentSymbol = (SYMBOL *) malloc (sizeof (SYMBOL)); + if (CurrentSymbol == NULL) { + Error (NULL, 0, 0, NULL, "failed to allocate memory"); + return -1; + } + memset ((INT8 *) CurrentSymbol, 0, sizeof (SYMBOL)); + + if (ModuleName != NULL) { + CurrentSymbol->Name = (INT8 *) malloc (strlen (ModuleName) + 1); + strcpy (CurrentSymbol->Name, ModuleName); + } + + if (InfName != NULL) { + CurrentSymbol->Value = (INT8 *) malloc (strlen (InfName) + 1); + strcpy (CurrentSymbol->Value, InfName); + } + + if (LastSymbol == NULL) { + *SymbolList = CurrentSymbol; + } else { + LastSymbol->Next = CurrentSymbol; + } + } + + return 0; +} + diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/SetStamp/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/SetStamp/Makefile new file mode 100644 index 0000000000..39750fb441 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/SetStamp/Makefile @@ -0,0 +1,88 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# makefile +# +# Abstract: +# +# This file is used to build the EFI utility. +# +#--*/ + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Define some macros we use here. Should get rid of them someday and +# get rid of the extra level of indirection. +# +COMMON_SOURCE = $(EDK_TOOLS_COMMON) + +# +# Common information +# + +INC=$(INC) + +# +# Target specific information +# + +TARGET_NAME=SetStamp +TARGET_SOURCE_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) + +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).exe + +TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\SetStamp.c" +TARGET_EXE_INCLUDE = +OBJECTS = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + +# +# Build targets +# + +all: $(TARGET_EXE) + +# +# Build EXE +# + +$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) + $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE) : $(OBJECTS) + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/SetStamp/SetStamp.c b/EdkCompatibilityPkg/Sample/Tools/Source/SetStamp/SetStamp.c new file mode 100644 index 0000000000..539aced1d9 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/SetStamp/SetStamp.c @@ -0,0 +1,475 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + SetStamp.c + +Abstract: + Set Date/Time Stamp of Portable Executable (PE) format file + +--*/ + +#include +#include +#include + +#define LINE_MAXLEN 80 + +void +PrintUsage ( + void + ) +/*++ +Routine Description: + print usage of setstamp command + +Arguments: + void + +Returns: + None +--*/ +{ + // + // print usage of command + // + printf ("Usage: SetStamp \n"); +} + +int +GetDateTime ( + FILE *fp, + time_t *ltime + ) +/*++ +Routine Description: + Read the date and time from TIME file. If the date/time string is +"NOW NOW", write the current date and time to TIME file and set it to +ltime. Else, set the date and time of TIME file to ltime. + +Arguments: + fp - The pointer of TIME file + ltime - Date and time + +Returns: + = 0 - Success + = -1 - Failed +--*/ +{ + char buffer[LINE_MAXLEN]; + struct tm stime; + struct tm *now; + + if (fgets (buffer, LINE_MAXLEN, fp) == NULL) { + printf ("Error: Cannot read TIME file.\n"); + return -1; + } + // + // compare the value with "NOW NOW", write TIME file if equal + // + if (strncmp (buffer, "NOW NOW", 7) == 0) { + // + // get system current time and date + // + time (ltime); + + now = localtime (ltime); + if (now == NULL) { + printf ("Error: Cannot get local time.\n"); + return -1; + } + + if (strftime (buffer, LINE_MAXLEN, "%Y-%m-%d %H:%M:%S", now) == 0) { + printf ("Error: Cannot format time string.\n"); + return -1; + } + // + // write TIME file + // + if (fseek (fp, 0, SEEK_SET) != 0) { + printf ("Error: Cannot move location of TIME file.\n"); + return -1; + } + + if (fputs (buffer, fp) == EOF) { + printf ("Error: Cannot write time string to TIME file.\n"); + return -1; + } + // + // ltime has been set as current time and date, return + // + return 0; + } + // + // get the date and time from buffer + // + if (6 != sscanf ( + buffer, + "%d-%d-%d %d:%d:%d", + &stime.tm_year, + &stime.tm_mon, + &stime.tm_mday, + &stime.tm_hour, + &stime.tm_min, + &stime.tm_sec + )) { + printf ("Error: Invaild date or time!\n"); + return -1; + } + // + // in struct, Month (0 - 11; Jan = 0). So decrease 1 from it + // + 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 <= 38) { + stime.tm_year += 100; + } + // + // convert 1970 -> 70, 2000 -> 100, ... + // + else if (stime.tm_year >= 1970) { + stime.tm_year -= 1900; + } + // + // convert the date and time to time_t format + // + *ltime = mktime (&stime); + if (*ltime == (time_t) - 1) { + printf ("Error: Invalid date or time!\n"); + return -1; + } + + return 0; +} + +int +ReadFromFile ( + FILE *fp, + long offset, + void *buffer, + int size + ) +/*++ +Routine Description: + read data from a specified location of file + +Arguments: + fp - file pointer + offset - number of bytes from beginning of file + buffer - buffer used to store data + size - size of buffer + +Returns: + = 0 - Success + = -1 - Failed +--*/ +{ + // + // set file pointer to the specified location of file + // + if (fseek (fp, offset, SEEK_SET) != 0) { + printf ("Error: Cannot move the current location of the file.\n"); + return -1; + } + // + // read data from the file + // + if (fread (buffer, size, 1, fp) != 1) { + printf ("Error: Cannot read data from the file.\n"); + return -1; + } + + return 0; +} + +int +WriteToFile ( + FILE *fp, + long offset, + void *buffer, + int size + ) +/*++ +Routine Description: + write data to a specified location of file + +Arguments: + fp - file pointer + offset - number of bytes from beginning of file + buffer - buffer used to store data + size - size of buffer + +Returns: + = 0 - Success + = -1 - Failed +--*/ +{ + // + // set file pointer to the specified location of file + // + if (fseek (fp, offset, SEEK_SET) != 0) { + printf ("Error: Cannot move the current location of the file.\n"); + return -1; + } + // + // write data to the file + // + if (fwrite (buffer, size, 1, fp) != 1) { + perror ("Error: Cannot write data to the file.\n"); + return -1; + } + + return 0; +} + +int +SetStamp ( + FILE *fp, + time_t ltime + ) +/*++ +Routine Description: + set Date/Time Stamp of the file + +Arguments: + fp - file pointer + ltime - time and date + +Returns: + = 0 - Success + = -1 - Failed +--*/ +{ + unsigned char header[4]; + unsigned long offset; + unsigned long NumberOfRvaAndSizes; + unsigned int nvalue; + unsigned long lvalue; + + // + // read the header of file + // + if (ReadFromFile (fp, 0, header, 2) != 0) { + return -1; + } + // + // "MZ" -- the header of image file (PE) + // + if (strncmp ((char *) header, "MZ", 2) != 0) { + printf ("Error: Invalid Image file.\n"); + return -1; + } + // + // At location 0x3C, the stub has the file offset to the + // PE signature. + // + if (ReadFromFile (fp, 0x3C, &offset, 4) != 0) { + return -1; + } + // + // read the header of optional + // + if (ReadFromFile (fp, offset, header, 4) != 0) { + return -1; + } + // + // "PE\0\0" -- the signature of optional header + // + if (strncmp ((char *) header, "PE\0\0", 4) != 0) { + printf ("Error: Invalid PE format file.\n"); + return -1; + } + // + // Add 8 to skip PE signature (4-byte), Machine (2-byte) and + // NumberOfSection (2-byte) + // + offset += 8; + + if (WriteToFile (fp, offset, <ime, 4) != 0) { + return -1; + } + // + // Add 16 to skip COFF file header, and get to optional header. + // + offset += 16; + + // + // Check the magic field, 0x10B for PE32 and 0x20B for PE32+ + // + if (ReadFromFile (fp, offset, &nvalue, 2) != 0) { + return -1; + } + // + // If this is PE32 image file, offset of NumberOfRvaAndSizes is 92. + // Else it is 108. + // + switch (nvalue & 0xFFFF) { + case 0x10B: + offset += 92; + break; + + case 0x20B: + offset += 108; + break; + + default: + printf ("Error: Sorry! The Magic value is unknown.\n"); + return -1; + } + // + // get the value of NumberOfRvaAndSizes + // + if (ReadFromFile (fp, offset, &NumberOfRvaAndSizes, 4) != 0) { + return -1; + } + // + // Date/time stamp exists in Export Table, Import Table, Resource Table, + // Debug Table and Delay Import Table. And in Import Table and Delay Import + // Table, it will be set when bound. So here only set the date/time stamp + // of Export Table, Resource Table and Debug Table. + // + // + // change date/time stamp of Export Table, the offset of Export Table + // is 4 + 0 * 8 = 4. And the offset of stamp is 4. + // + if (NumberOfRvaAndSizes >= 1) { + if (ReadFromFile (fp, offset + 4, &lvalue, 4) != 0) { + return -1; + } + + if (lvalue != 0) { + if (WriteToFile (fp, lvalue + 4, <ime, 4) != 0) { + return -1; + } + } + } + // + // change date/time stamp of Resource Table, the offset of Resource Table + // is 4 + 2 * 8 = 20. And the offset of stamp is 4. + // + if (NumberOfRvaAndSizes >= 3) { + if (ReadFromFile (fp, offset + 20, &lvalue, 4) != 0) { + return -1; + } + + if (lvalue != 0) { + if (WriteToFile (fp, lvalue + 4, <ime, 4) != 0) { + return -1; + } + } + } + // + // change date/time stamp of Debug Table, offset of Debug Table + // is 4 + 6 * 8 = 52. And the offset of stamp is 4. + // + if (NumberOfRvaAndSizes >= 7) { + if (ReadFromFile (fp, offset + 52, &lvalue, 4) != 0) { + return -1; + } + + if (lvalue != 0) { + if (WriteToFile (fp, lvalue + 4, <ime, 4) != 0) { + return -1; + } + } + // + // change the date/time stamp of Debug Data + // + if (ReadFromFile (fp, lvalue + 24, &lvalue, 4) != 0) { + return -1; + } + // + // get the signature of debug data + // + if (ReadFromFile (fp, lvalue, header, 2) != 0) { + return -1; + } + // + // "NB" - the signature of Debug Data + // Need Review: (From Spec. is "NB05", From .dll is "NB10") + // + if (strncmp ((char *) header, "NB", 2) == 0) { + if (WriteToFile (fp, lvalue + 8, <ime, 4) != 0) { + return -1; + } + } + } + + return 0; +} + +int +main ( + int argc, + char *argv[] + ) +{ + FILE *fp; + time_t ltime; + + // + // check the number of parameters + // + if (argc != 3) { + PrintUsage (); + return -1; + } + // + // open the TIME file, if not exists, return + // + fp = fopen (argv[2], "r+"); + if (fp == NULL) { + return 0; + } + // + // get time and date from file + // + if (GetDateTime (fp, <ime) != 0) { + fclose (fp); + return -1; + } + // + // close the TIME file + // + fclose (fp); + + // + // open the PE file + // + fp = fopen (argv[1], "r+b"); + if (fp == NULL) { + printf ("Error: Cannot open the PE file!\n"); + return -1; + } + // + // set time and date stamp to the PE file + // + if (SetStamp (fp, ltime) != 0) { + fclose (fp); + return -1; + } + + printf ("Set Date/Time Stamp to %s", ctime (<ime)); + + // + // close the PE file + // + fclose (fp); + + return 0; +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/SplitFile/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/SplitFile/Makefile new file mode 100644 index 0000000000..a90e133cec --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/SplitFile/Makefile @@ -0,0 +1,94 @@ +#/*++ +# +# Copyright (c) 2006 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Makefile +# +# Abstract: +# +# makefile for building the SplitFile utility. +# +#--*/ + +# +# Make sure environmental variable EDK_SOURCE is set +# +!IFNDEF EDK_SOURCE +!ERROR EDK_SOURCE environmental variable not set +!ENDIF + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Define some macros we use here. Should get rid of them someday and +# get rid of the extra level of indirection. +# +COMMON_SOURCE = $(EDK_TOOLS_COMMON) + +# +# Common information +# + +INC=$(INC) + +# +# Target specific information +# + +TARGET_NAME=SplitFile +TARGET_SOURCE_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) + +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).exe + +TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\SplitFile.c" +TARGET_EXE_INCLUDE = + +# +# Build targets +# + +all: $(TARGET_EXE) + +# +# Build EXE +# + +$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE) + $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + +# +# Add Binary Build description for this tool. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE): $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) /out:$(TARGET_EXE) $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/SplitFile/splitfile.c b/EdkCompatibilityPkg/Sample/Tools/Source/SplitFile/splitfile.c new file mode 100644 index 0000000000..860093ca4f --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/SplitFile/splitfile.c @@ -0,0 +1,136 @@ +/*++ + +Copyright 2006, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + splitfile.c + +Abstract: + +--*/ + +#include "stdio.h" +#include "string.h" +#include "stdlib.h" + +void +helpmsg ( + void + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + +Returns: + + GC_TODO: add return values + +--*/ +{ + printf ( + "SplitFile Filename Offset\n"" Filename = Input file to split\n"" Offset = offset at which to split file\n" + "\n\n""SplitFile will break a file in two pieces at the requested offset\n" + " outputting Filename1 and Filename2\n" + ); +} + +int +main ( + int argc, + char*argv[] + ) +/*++ + +Routine Description: + + GC_TODO: Add function description + +Arguments: + + argc - GC_TODO: add argument description + argv - GC_TODO: add argument description + +Returns: + + GC_TODO: add return values + +--*/ +{ + FILE *In; + + FILE *Out1; + + FILE *Out2; + char OutName1[512]; + char OutName2[512]; + unsigned long Index; + unsigned long splitpoint; + char CharC; + + if (argc != 3) { + helpmsg (); + return -1; + } + + In = fopen (argv[1], "rb"); + if (In == NULL) { + printf ("Unable to open file \"%s\"\n", argv[1]); + return -1; + } + + strncpy (OutName1, argv[1], 510); + strncpy (OutName2, argv[1], 510); + strcat (OutName1, "1"); + strcat (OutName2, "2"); + + Out1 = fopen (OutName1, "wb"); + if (Out1 == NULL) { + printf ("Unable to open file \"%s\"\n", OutName1); + return -1; + } + + Out2 = fopen (OutName2, "wb"); + if (Out2 == NULL) { + printf ("Unable to open file \"%s\"\n", OutName2); + return -1; + } + + splitpoint = atoi (argv[2]); + + for (Index = 0; Index < splitpoint; Index++) { + CharC = (char) fgetc (In); + if (feof (In)) { + break; + } + + fputc (CharC, Out1); + } + + for (;;) { + CharC = (char) fgetc (In); + if (feof (In)) { + break; + } + + fputc (CharC, Out2); + } + + fclose (In); + fclose (Out1); + fclose (Out2); + + return 0; +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/StrGather/Makefile b/EdkCompatibilityPkg/Sample/Tools/Source/StrGather/Makefile new file mode 100644 index 0000000000..dce81b0e04 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/StrGather/Makefile @@ -0,0 +1,89 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Makefile +# +# Abstract: +# +# makefile for building the StrGather utility. +# +#--*/ + +# +# Make sure environmental variable EDK_SOURCE is set +# +!IFNDEF EDK_SOURCE +!ERROR EDK_SOURCE environmental variable not set +!ENDIF + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Target specific information +# +TARGET_NAME = StrGather +TARGET_SRC_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\StrGather.exe + +# +# Build targets +# + +all: $(TARGET_EXE) + + +LIBS = "$(EDK_TOOLS_OUTPUT)\Common.lib" + +OBJECTS = $(EDK_TOOLS_OUTPUT)\StrGather.obj \ + $(EDK_TOOLS_OUTPUT)\StringDB.obj + +INC_DEPS = $(TARGET_SRC_DIR)\StrGather.h $(TARGET_SRC_DIR)\StringDB.h + +C_FLAGS = $(C_FLAGS) /W4 + +# +# Compile each source file +# +$(EDK_TOOLS_OUTPUT)\StrGather.obj : $(TARGET_SRC_DIR)\StrGather.c $(INC_DEPS) + $(CC) $(C_FLAGS) $(INC_PATHS) $(TARGET_SRC_DIR)\StrGather.c /Fo$@ + +$(EDK_TOOLS_OUTPUT)\StringDB.obj : $(TARGET_SRC_DIR)\StringDB.c $(INC_DEPS) + $(CC) $(C_FLAGS) $(INC_PATHS) $(TARGET_SRC_DIR)\StringDB.c /Fo$@ + +# +# Add Binary Build description for this tools. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE) : $(OBJECTS) $(LIBS) + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StrGather.c b/EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StrGather.c new file mode 100644 index 0000000000..107a46306b --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StrGather.c @@ -0,0 +1,2574 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + StrGather.c + +Abstract: + + Parse a strings file and create or add to a string database file. + +--*/ + +#include +#include +#include +#include + +#include "Tiano.h" +#include "EfiUtilityMsgs.h" +#include "StrGather.h" +#include "StringDB.h" + +#define TOOL_VERSION "0.31" + +typedef UINT16 WCHAR; + +#define MAX_PATH 1024 +#define MAX_NEST_DEPTH 20 // just in case we get in an endless loop. +#define MAX_STRING_IDENTIFIER_NAME 100 // number of wchars +#define MAX_LINE_LEN 400 +#define STRING_TOKEN "STRING_TOKEN" +#define DEFAULT_BASE_NAME "BaseName" +// +// Operational modes for this utility +// +#define MODE_UNKNOWN 0 +#define MODE_PARSE 1 +#define MODE_SCAN 2 +#define MODE_DUMP 3 + +// +// We keep a linked list of these for the source files we process +// +typedef struct _SOURCE_FILE { + FILE *Fptr; + WCHAR *FileBuffer; + WCHAR *FileBufferPtr; + UINT32 FileSize; + INT8 FileName[MAX_PATH]; + UINT32 LineNum; + BOOLEAN EndOfFile; + BOOLEAN SkipToHash; + struct _SOURCE_FILE *Previous; + struct _SOURCE_FILE *Next; + WCHAR ControlCharacter; +} SOURCE_FILE; + +#define DEFAULT_CONTROL_CHARACTER UNICODE_SLASH + +// +// Here's all our globals. We need a linked list of include paths, a linked +// list of source files, a linked list of subdirectories (appended to each +// include path when searching), and a couple other fields. +// +static struct { + SOURCE_FILE SourceFiles; + TEXT_STRING_LIST *IncludePaths; // all include paths to search + TEXT_STRING_LIST *LastIncludePath; + TEXT_STRING_LIST *ScanFileName; + TEXT_STRING_LIST *LastScanFileName; + TEXT_STRING_LIST *SkipExt; // if -skipext .uni + TEXT_STRING_LIST *LastSkipExt; + TEXT_STRING_LIST *IndirectionFileName; + TEXT_STRING_LIST *LastIndirectionFileName; + TEXT_STRING_LIST *DatabaseFileName; + TEXT_STRING_LIST *LastDatabaseFileName; + WCHAR_STRING_LIST *Language; + WCHAR_STRING_LIST *LastLanguage; + WCHAR_MATCHING_STRING_LIST *IndirectionList; // from indirection file(s) + WCHAR_MATCHING_STRING_LIST *LastIndirectionList; + BOOLEAN Verbose; // for more detailed output + BOOLEAN VerboseDatabaseWrite; // for more detailed output when writing database + BOOLEAN VerboseDatabaseRead; // for more detailed output when reading database + BOOLEAN NewDatabase; // to start from scratch + BOOLEAN IgnoreNotFound; // when scanning + BOOLEAN VerboseScan; + BOOLEAN UnquotedStrings; // -uqs option + INT8 OutputDatabaseFileName[MAX_PATH]; + INT8 StringHFileName[MAX_PATH]; + INT8 StringCFileName[MAX_PATH]; // output .C filename + INT8 DumpUFileName[MAX_PATH]; // output unicode dump file name + INT8 HiiExportPackFileName[MAX_PATH]; // HII export pack file name + INT8 BaseName[MAX_PATH]; // base filename of the strings file + INT8 OutputDependencyFileName[MAX_PATH]; + FILE *OutputDependencyFptr; + UINT32 Mode; +} mGlobals; + +static +BOOLEAN +IsValidIdentifierChar ( + INT8 Char, + BOOLEAN FirstChar + ); + +static +void +RewindFile ( + SOURCE_FILE *SourceFile + ); + +static +BOOLEAN +SkipTo ( + SOURCE_FILE *SourceFile, + WCHAR WChar, + BOOLEAN StopAfterNewline + ); + +static +UINT32 +SkipWhiteSpace ( + SOURCE_FILE *SourceFile + ); + +static +BOOLEAN +IsWhiteSpace ( + SOURCE_FILE *SourceFile + ); + +static +BOOLEAN +EndOfFile ( + SOURCE_FILE *SourceFile + ); + +static +void +PreprocessFile ( + SOURCE_FILE *SourceFile + ); + +static +UINT32 +GetStringIdentifierName ( + IN SOURCE_FILE *SourceFile, + IN OUT WCHAR *StringIdentifierName, + IN UINT32 StringIdentifierNameLen + ); + +static +UINT32 +GetLanguageIdentifierName ( + IN SOURCE_FILE *SourceFile, + IN OUT WCHAR *LanguageIdentifierName, + IN UINT32 LanguageIdentifierNameLen, + IN BOOLEAN Optional + ); + +static +WCHAR * +GetPrintableLanguageName ( + IN SOURCE_FILE *SourceFile + ); + +static +STATUS +AddCommandLineLanguage ( + IN INT8 *Language + ); + +static +WCHAR * +GetQuotedString ( + SOURCE_FILE *SourceFile, + BOOLEAN Optional + ); + +static +STATUS +ProcessIncludeFile ( + SOURCE_FILE *SourceFile, + SOURCE_FILE *ParentSourceFile + ); + +static +STATUS +ParseFile ( + SOURCE_FILE *SourceFile + ); + +static +FILE * +FindFile ( + IN INT8 *FileName, + OUT INT8 *FoundFileName, + IN UINT32 FoundFileNameLen + ); + +static +STATUS +ProcessArgs ( + int Argc, + char *Argv[] + ); + +static +STATUS +ProcessFile ( + SOURCE_FILE *SourceFile + ); + +static +UINT32 +wstrcmp ( + WCHAR *Buffer, + WCHAR *Str + ); + +static +void +Usage ( + VOID + ); + +static +void +FreeLists ( + VOID + ); + +static +void +ProcessTokenString ( + SOURCE_FILE *SourceFile + ); + +static +void +ProcessTokenInclude ( + SOURCE_FILE *SourceFile + ); + +static +void +ProcessTokenScope ( + SOURCE_FILE *SourceFile + ); + +static +void +ProcessTokenLanguage ( + SOURCE_FILE *SourceFile + ); + +static +void +ProcessTokenLangDef ( + SOURCE_FILE *SourceFile + ); + +static +STATUS +ScanFiles ( + TEXT_STRING_LIST *ScanFiles + ); + +static +STATUS +ParseIndirectionFiles ( + TEXT_STRING_LIST *Files + ); + +STATUS +StringDBCreateHiiExportPack ( + INT8 *OutputFileName + ); + +int +main ( + int Argc, + char *Argv[] + ) +/*++ + +Routine Description: + + Call the routine to parse the command-line options, then process the file. + +Arguments: + + Argc - Standard C main() argc and argv. + Argv - Standard C main() argc and argv. + +Returns: + + 0 if successful + nonzero otherwise + +--*/ +{ + STATUS Status; + + SetUtilityName (PROGRAM_NAME); + // + // Process the command-line arguments + // + Status = ProcessArgs (Argc, Argv); + if (Status != STATUS_SUCCESS) { + return Status; + } + // + // Initialize the database manager + // + StringDBConstructor (); + // + // We always try to read in an existing database file. It may not + // exist, which is ok usually. + // + if (mGlobals.NewDatabase == 0) { + // + // Read all databases specified. + // + for (mGlobals.LastDatabaseFileName = mGlobals.DatabaseFileName; + mGlobals.LastDatabaseFileName != NULL; + mGlobals.LastDatabaseFileName = mGlobals.LastDatabaseFileName->Next + ) { + Status = StringDBReadDatabase (mGlobals.LastDatabaseFileName->Str, TRUE, mGlobals.VerboseDatabaseRead); + if (Status != STATUS_SUCCESS) { + return Status; + } + } + } + // + // Read indirection file(s) if specified + // + if (ParseIndirectionFiles (mGlobals.IndirectionFileName) != STATUS_SUCCESS) { + goto Finish; + } + // + // If scanning source files, do that now + // + if (mGlobals.Mode == MODE_SCAN) { + ScanFiles (mGlobals.ScanFileName); + } else if (mGlobals.Mode == MODE_PARSE) { + // + // Parsing a unicode strings file + // + mGlobals.SourceFiles.ControlCharacter = DEFAULT_CONTROL_CHARACTER; + if (mGlobals.OutputDependencyFileName[0] != 0) { + if ((mGlobals.OutputDependencyFptr = fopen (mGlobals.OutputDependencyFileName, "w")) == NULL) { + Error (NULL, 0, 0, mGlobals.OutputDependencyFileName, "failed to open output dependency file"); + goto Finish; + } + } + Status = ProcessIncludeFile (&mGlobals.SourceFiles, NULL); + if (mGlobals.OutputDependencyFptr != NULL) { + fclose (mGlobals.OutputDependencyFptr); + } + if (Status != STATUS_SUCCESS) { + goto Finish; + } + } + // + // Create the string defines header file if there have been no errors. + // + ParserSetPosition (NULL, 0); + if ((mGlobals.StringHFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) { + Status = StringDBDumpStringDefines (mGlobals.StringHFileName, mGlobals.BaseName); + if (Status != EFI_SUCCESS) { + goto Finish; + } + } + // + // Dump the strings to a .c file if there have still been no errors. + // + if ((mGlobals.StringCFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) { + Status = StringDBDumpCStrings ( + mGlobals.StringCFileName, + mGlobals.BaseName, + mGlobals.Language, + mGlobals.IndirectionList + ); + if (Status != EFI_SUCCESS) { + goto Finish; + } + } + // + // Dump the database if requested + // + if ((mGlobals.DumpUFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) { + StringDBDumpDatabase (NULL, mGlobals.DumpUFileName, FALSE); + } + // + // Dump the string data as HII binary string pack if requested + // + if ((mGlobals.HiiExportPackFileName[0] != 0) && (GetUtilityStatus () < STATUS_ERROR)) { + StringDBCreateHiiExportPack (mGlobals.HiiExportPackFileName); + } + // + // Always update the database if no errors and not in dump mode. If they specified -od + // for an output database file name, then use that name. Otherwise use the name of + // the first database file specified with -db + // + if ((mGlobals.Mode != MODE_DUMP) && (GetUtilityStatus () < STATUS_ERROR)) { + if (mGlobals.OutputDatabaseFileName[0]) { + Status = StringDBWriteDatabase (mGlobals.OutputDatabaseFileName, mGlobals.VerboseDatabaseWrite); + } else { + Status = StringDBWriteDatabase (mGlobals.DatabaseFileName->Str, mGlobals.VerboseDatabaseWrite); + } + + if (Status != EFI_SUCCESS) { + goto Finish; + } + } + +Finish: + // + // Free up memory + // + FreeLists (); + StringDBDestructor (); + return GetUtilityStatus (); +} + +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 UINT32 NestDepth = 0; + INT8 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.Verbose) { + fprintf (stdout, "%*cProcessing file '%s'\n", NestDepth * 2, ' ', SourceFile->FileName); + } + + // + // Make sure we didn't exceed our maximum nesting depth + // + if (NestDepth > MAX_NEST_DEPTH) { + Error (NULL, 0, 0, SourceFile->FileName, "max nesting depth (%d) exceeded", 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 (FoundFileName, "rb")) == NULL) { + // + // Try to find it among the paths if it has a parent (that is, it is included + // by someone else). + // + if (ParentSourceFile == NULL) { + Error (NULL, 0, 0, SourceFile->FileName, "file not found"); + Status = STATUS_ERROR; + goto Finish; + } + + SourceFile->Fptr = FindFile (SourceFile->FileName, FoundFileName, sizeof (FoundFileName)); + if (SourceFile->Fptr == NULL) { + Error (ParentSourceFile->FileName, ParentSourceFile->LineNum, 0, SourceFile->FileName, "include file not found"); + Status = STATUS_ERROR; + goto Finish; + } + } + + // + // Output the dependency + // + if (mGlobals.OutputDependencyFptr != NULL) { + fprintf (mGlobals.OutputDependencyFptr, "%s : %s\n", mGlobals.DatabaseFileName->Str, FoundFileName); + // + // Add pseudo target to avoid incremental build failure when the file is deleted + // + fprintf (mGlobals.OutputDependencyFptr, "%s : \n", FoundFileName); + } + + // + // Process the file found + // + ProcessFile (SourceFile); + +Finish: + NestDepth--; + // + // Close open files and return status + // + if (SourceFile->Fptr != NULL) { + fclose (SourceFile->Fptr); + } + + return Status; +} + +static +STATUS +ProcessFile ( + SOURCE_FILE *SourceFile + ) +{ + // + // Get the file size, and then read the entire thing into memory. + // Allocate space for a terminator character. + // + fseek (SourceFile->Fptr, 0, SEEK_END); + SourceFile->FileSize = ftell (SourceFile->Fptr); + fseek (SourceFile->Fptr, 0, SEEK_SET); + SourceFile->FileBuffer = (WCHAR *) malloc (SourceFile->FileSize + sizeof (WCHAR)); + if (SourceFile->FileBuffer == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + fread ((VOID *) SourceFile->FileBuffer, SourceFile->FileSize, 1, SourceFile->Fptr); + SourceFile->FileBuffer[(SourceFile->FileSize / sizeof (WCHAR))] = UNICODE_NULL; + // + // Pre-process the file to replace comments with spaces + // + PreprocessFile (SourceFile); + // + // Parse the file + // + ParseFile (SourceFile); + free (SourceFile->FileBuffer); + return STATUS_SUCCESS; +} + +static +STATUS +ParseFile ( + SOURCE_FILE *SourceFile + ) +{ + BOOLEAN InComment; + UINT32 Len; + + // + // First character of a unicode file is special. Make sure + // + if (SourceFile->FileBufferPtr[0] != UNICODE_FILE_START) { + Error (SourceFile->FileName, 1, 0, SourceFile->FileName, "file does not appear to be a unicode file"); + return STATUS_ERROR; + } + + SourceFile->FileBufferPtr++; + InComment = FALSE; + // + // Print the first line if in verbose mode + // + if (mGlobals.Verbose) { + printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr); + } + // + // Since the syntax is relatively straightforward, just switch on the next char + // + while (!EndOfFile (SourceFile)) { + // + // Check for whitespace + // + if (SourceFile->FileBufferPtr[0] == UNICODE_SPACE) { + SourceFile->FileBufferPtr++; + } else if (SourceFile->FileBufferPtr[0] == UNICODE_TAB) { + SourceFile->FileBufferPtr++; + } else if (SourceFile->FileBufferPtr[0] == UNICODE_CR) { + SourceFile->FileBufferPtr++; + } else if (SourceFile->FileBufferPtr[0] == UNICODE_LF) { + SourceFile->FileBufferPtr++; + SourceFile->LineNum++; + if (mGlobals.Verbose) { + printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr); + } + + InComment = FALSE; + } else if (SourceFile->FileBufferPtr[0] == 0) { + SourceFile->FileBufferPtr++; + } else if (InComment) { + SourceFile->FileBufferPtr++; + } else if ((SourceFile->FileBufferPtr[0] == UNICODE_SLASH) && (SourceFile->FileBufferPtr[1] == UNICODE_SLASH)) { + SourceFile->FileBufferPtr += 2; + InComment = TRUE; + } else if (SourceFile->SkipToHash && (SourceFile->FileBufferPtr[0] != SourceFile->ControlCharacter)) { + SourceFile->FileBufferPtr++; + } else { + SourceFile->SkipToHash = FALSE; + if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) && + ((Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"include")) > 0) + ) { + SourceFile->FileBufferPtr += Len + 1; + ProcessTokenInclude (SourceFile); + } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) && + (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"scope")) > 0 + ) { + SourceFile->FileBufferPtr += Len + 1; + ProcessTokenScope (SourceFile); + } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) && + (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"language")) > 0 + ) { + SourceFile->FileBufferPtr += Len + 1; + ProcessTokenLanguage (SourceFile); + } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) && + (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"langdef")) > 0 + ) { + SourceFile->FileBufferPtr += Len + 1; + ProcessTokenLangDef (SourceFile); + } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) && + (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"string")) > 0 + ) { + SourceFile->FileBufferPtr += Len + 1; + ProcessTokenString (SourceFile); + } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) && + (Len = wstrcmp (SourceFile->FileBufferPtr + 1, L"EFI_BREAKPOINT()")) > 0 + ) { + SourceFile->FileBufferPtr += Len; + EFI_BREAKPOINT (); + } else if ((SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter) && + (SourceFile->FileBufferPtr[1] == UNICODE_EQUAL_SIGN) + ) { + SourceFile->ControlCharacter = SourceFile->FileBufferPtr[2]; + SourceFile->FileBufferPtr += 3; + } else { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "unrecognized token", "%S", SourceFile->FileBufferPtr); + // + // Treat rest of line as a comment. + // + InComment = TRUE; + } + } + } + + 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 from the file to the screen. + +Arguments: + SourceFile - structure that we use to keep track of an input file. + +Returns: + Nothing. + +--*/ +{ + BOOLEAN InComment; + + RewindFile (SourceFile); + InComment = FALSE; + while (!EndOfFile (SourceFile)) { + // + // If a line-feed, then no longer in a comment + // + if (SourceFile->FileBufferPtr[0] == UNICODE_LF) { + SourceFile->FileBufferPtr++; + SourceFile->LineNum++; + InComment = 0; + } else if (SourceFile->FileBufferPtr[0] == UNICODE_CR) { + // + // Replace all carriage returns with a NULL so we can print stuff + // + SourceFile->FileBufferPtr[0] = 0; + SourceFile->FileBufferPtr++; + } else if (InComment) { + SourceFile->FileBufferPtr[0] = UNICODE_SPACE; + SourceFile->FileBufferPtr++; + } else if ((SourceFile->FileBufferPtr[0] == UNICODE_SLASH) && (SourceFile->FileBufferPtr[1] == UNICODE_SLASH)) { + SourceFile->FileBufferPtr += 2; + 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); +} + +static +WCHAR * +GetPrintableLanguageName ( + IN SOURCE_FILE *SourceFile + ) +{ + WCHAR *String; + WCHAR *Start; + WCHAR *Ptr; + UINT32 Len; + + SkipWhiteSpace (SourceFile); + if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + "expected quoted printable language name", + "%S", + SourceFile->FileBufferPtr + ); + SourceFile->SkipToHash = TRUE; + return NULL; + } + + Len = 0; + SourceFile->FileBufferPtr++; + Start = Ptr = SourceFile->FileBufferPtr; + while (!EndOfFile (SourceFile)) { + if (SourceFile->FileBufferPtr[0] == UNICODE_CR) { + Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start); + break; + } else if (SourceFile->FileBufferPtr[0] == UNICODE_DOUBLE_QUOTE) { + break; + } + + SourceFile->FileBufferPtr++; + Len++; + } + + if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) { + Warning ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + "missing closing quote on printable language name string", + "%S", + Start + ); + } else { + SourceFile->FileBufferPtr++; + } + // + // Now allocate memory for the string and save it off + // + String = (WCHAR *) malloc ((Len + 1) * sizeof (WCHAR)); + if (String == NULL) { + Error (NULL, 0, 0, "memory allocation failed", 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; + // + // Now format the string to convert \wide and \narrow controls + // + StringDBFormatString (String); + return String; +} + +static +WCHAR * +GetQuotedString ( + SOURCE_FILE *SourceFile, + BOOLEAN Optional + ) +{ + WCHAR *String; + WCHAR *Start; + WCHAR *Ptr; + UINT32 Len; + BOOLEAN PreviousBackslash; + + if (SourceFile->FileBufferPtr[0] != UNICODE_DOUBLE_QUOTE) { + if (!Optional) { + 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] == UNICODE_DOUBLE_QUOTE) && (!PreviousBackslash)) { + break; + } else if (SourceFile->FileBufferPtr[0] == UNICODE_CR) { + Warning (SourceFile->FileName, SourceFile->LineNum, 0, "carriage return found in quoted string", "%S", Start); + PreviousBackslash = FALSE; + } else if (SourceFile->FileBufferPtr[0] == UNICODE_BACKSLASH) { + PreviousBackslash = TRUE; + } else { + PreviousBackslash = FALSE; + } + + SourceFile->FileBufferPtr++; + Len++; + } + + if (SourceFile->FileBufferPtr[0] != UNICODE_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 = (WCHAR *) malloc ((Len + 1) * sizeof (WCHAR)); + if (String == NULL) { + Error (NULL, 0, 0, "memory allocation failed", 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; +} +// +// Parse: +// #string STR_ID_NAME +// +// All we can do is call the string database to add the string identifier. Unfortunately +// he'll have to keep track of the last identifier we added. +// +static +void +ProcessTokenString ( + SOURCE_FILE *SourceFile + ) +{ + WCHAR StringIdentifier[MAX_STRING_IDENTIFIER_NAME]; + UINT16 StringId; + // + // Extract the string identifier name and add it to the database. + // + if (GetStringIdentifierName (SourceFile, StringIdentifier, sizeof (StringIdentifier)) > 0) { + StringId = STRING_ID_INVALID; + StringDBAddStringIdentifier (StringIdentifier, &StringId, 0); + } else { + // + // Error recovery -- skip to the next # + // + SourceFile->SkipToHash = TRUE; + } +} + +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 (WCHAR)) { + SourceFile->EndOfFile = TRUE; + return TRUE; + } + + if (SourceFile->EndOfFile) { + return TRUE; + } + + return FALSE; +} + +static +UINT32 +GetStringIdentifierName ( + IN SOURCE_FILE *SourceFile, + IN OUT WCHAR *StringIdentifierName, + IN UINT32 StringIdentifierNameLen + ) +{ + UINT32 Len; + WCHAR *From; + WCHAR *Start; + + // + // Skip whitespace + // + SkipWhiteSpace (SourceFile); + if (SourceFile->EndOfFile) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-file encountered", "expected string identifier"); + return 0; + } + // + // Verify first character of name is [A-Za-z] + // + Len = 0; + StringIdentifierNameLen /= 2; + From = SourceFile->FileBufferPtr; + Start = SourceFile->FileBufferPtr; + if (((SourceFile->FileBufferPtr[0] >= UNICODE_A) && (SourceFile->FileBufferPtr[0] <= UNICODE_Z)) || + ((SourceFile->FileBufferPtr[0] >= UNICODE_z) && (SourceFile->FileBufferPtr[0] <= UNICODE_z)) + ) { + // + // Do nothing + // + } else { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid character in string identifier name", "%S", Start); + return 0; + } + + while (!EndOfFile (SourceFile)) { + if (((SourceFile->FileBufferPtr[0] >= UNICODE_A) && (SourceFile->FileBufferPtr[0] <= UNICODE_Z)) || + ((SourceFile->FileBufferPtr[0] >= UNICODE_z) && (SourceFile->FileBufferPtr[0] <= UNICODE_z)) || + ((SourceFile->FileBufferPtr[0] >= UNICODE_0) && (SourceFile->FileBufferPtr[0] <= UNICODE_9)) || + (SourceFile->FileBufferPtr[0] == UNICODE_UNDERSCORE) + ) { + Len++; + if (Len >= StringIdentifierNameLen) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "string identifier name too long", "%S", Start); + return 0; + } + + *StringIdentifierName = SourceFile->FileBufferPtr[0]; + StringIdentifierName++; + SourceFile->FileBufferPtr++; + } else if (SkipWhiteSpace (SourceFile) == 0) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid string identifier name", "%S", Start); + return 0; + } else { + break; + } + } + // + // Terminate the copy of the string. + // + *StringIdentifierName = 0; + return Len; +} + +static +UINT32 +GetLanguageIdentifierName ( + IN SOURCE_FILE *SourceFile, + IN OUT WCHAR *LanguageIdentifierName, + IN UINT32 LanguageIdentifierNameLen, + IN BOOLEAN Optional + ) +{ + UINT32 Len; + WCHAR *From; + WCHAR *Start; + // + // Skip whitespace + // + SkipWhiteSpace (SourceFile); + if (SourceFile->EndOfFile) { + if (!Optional) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + "end-of-file encountered", + "expected language identifier" + ); + } + + return 0; + } + // + // This function is called to optionally get a language identifier name in: + // #string STR_ID eng "the string" + // If it's optional, and we find a double-quote, then return now. + // + if (Optional) { + if (*SourceFile->FileBufferPtr == UNICODE_DOUBLE_QUOTE) { + return 0; + } + } + + Len = 0; + LanguageIdentifierNameLen /= 2; + // + // Internal error if we weren't given at least 4 WCHAR's to work with. + // + if (LanguageIdentifierNameLen < LANGUAGE_IDENTIFIER_NAME_LEN + 1) { + Error ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + "app error -- language identifier name length is invalid", + NULL + ); + } + + From = SourceFile->FileBufferPtr; + Start = SourceFile->FileBufferPtr; + while (!EndOfFile (SourceFile)) { + if (((SourceFile->FileBufferPtr[0] >= UNICODE_a) && (SourceFile->FileBufferPtr[0] <= UNICODE_z))) { + Len++; + if (Len > LANGUAGE_IDENTIFIER_NAME_LEN) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "language identifier name too long", "%S", Start); + return 0; + } + + *LanguageIdentifierName = SourceFile->FileBufferPtr[0]; + SourceFile->FileBufferPtr++; + LanguageIdentifierName++; + } else if (!IsWhiteSpace (SourceFile)) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid language identifier name", "%S", Start); + return 0; + } else { + break; + } + } + // + // Terminate the copy of the string. + // + *LanguageIdentifierName = 0; + return Len; +} + +static +void +ProcessTokenInclude ( + SOURCE_FILE *SourceFile + ) +{ + INT8 IncludeFileName[MAX_PATH]; + INT8 *To; + UINT32 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] != UNICODE_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] == UNICODE_CR) || (SourceFile->FileBufferPtr[0] == UNICODE_LF)) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "end-of-line found in quoted include file name", NULL); + goto FailDone; + } + + if (SourceFile->FileBufferPtr[0] == UNICODE_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 = UNICODE_TO_ASCII (SourceFile->FileBufferPtr[0]); + To++; + } + + SourceFile->FileBufferPtr++; + } + + if (!ReportedError) { + *To = 0; + memset ((char *) &IncludedSourceFile, 0, sizeof (SOURCE_FILE)); + strcpy (IncludedSourceFile.FileName, IncludeFileName); + IncludedSourceFile.ControlCharacter = DEFAULT_CONTROL_CHARACTER; + ProcessIncludeFile (&IncludedSourceFile, SourceFile); + // + // printf ("including file '%s'\n", IncludeFileName); + // + } + + return ; +FailDone: + // + // Error recovery -- skip to next # + // + SourceFile->SkipToHash = TRUE; +} + +static +void +ProcessTokenScope ( + SOURCE_FILE *SourceFile + ) +{ + WCHAR StringIdentifier[MAX_STRING_IDENTIFIER_NAME]; + // + // Extract the scope name + // + if (GetStringIdentifierName (SourceFile, StringIdentifier, sizeof (StringIdentifier)) > 0) { + StringDBSetScope (StringIdentifier); + } +} +// +// Parse: #langdef eng "English" +// #langdef chn "\wideChinese" +// +static +void +ProcessTokenLangDef ( + SOURCE_FILE *SourceFile + ) +{ + WCHAR LanguageIdentifier[MAX_STRING_IDENTIFIER_NAME]; + UINT32 Len; + WCHAR *PrintableName; + // + // Extract the 3-character language identifier + // + Len = GetLanguageIdentifierName (SourceFile, LanguageIdentifier, sizeof (LanguageIdentifier), FALSE); + if (Len != LANGUAGE_IDENTIFIER_NAME_LEN) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid or missing language identifier", NULL); + } else { + // + // Extract the printable name + // + PrintableName = GetPrintableLanguageName (SourceFile); + if (PrintableName != NULL) { + ParserSetPosition (SourceFile->FileName, SourceFile->LineNum); + StringDBAddLanguage (LanguageIdentifier, PrintableName); + free (PrintableName); + return ; + } + } + // + // Error recovery -- skip to next # + // + SourceFile->SkipToHash = TRUE; +} + +static +BOOLEAN +ApparentQuotedString ( + SOURCE_FILE *SourceFile + ) +{ + WCHAR *Ptr; + // + // See if the first and last nonblank characters on the line are double quotes + // + for (Ptr = SourceFile->FileBufferPtr; *Ptr && (*Ptr == UNICODE_SPACE); Ptr++) + ; + if (*Ptr != UNICODE_DOUBLE_QUOTE) { + return FALSE; + } + + while (*Ptr) { + Ptr++; + } + + Ptr--; + for (; *Ptr && (*Ptr == UNICODE_SPACE); Ptr--) + ; + if (*Ptr != UNICODE_DOUBLE_QUOTE) { + return FALSE; + } + + return TRUE; +} +// +// Parse: +// #language eng "some string " "more string" +// +static +void +ProcessTokenLanguage ( + SOURCE_FILE *SourceFile + ) +{ + WCHAR *String; + WCHAR *SecondString; + WCHAR *TempString; + WCHAR *From; + WCHAR *To; + WCHAR Language[LANGUAGE_IDENTIFIER_NAME_LEN + 1]; + UINT32 Len; + BOOLEAN PreviousNewline; + // + // Get the language identifier + // + Language[0] = 0; + Len = GetLanguageIdentifierName (SourceFile, Language, sizeof (Language), TRUE); + if (Len != LANGUAGE_IDENTIFIER_NAME_LEN) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "invalid or missing language identifier", "%S", Language); + SourceFile->SkipToHash = TRUE; + return ; + } + // + // Extract the string value. It's either a quoted string that starts on the current line, or + // an unquoted string that starts on the following line and continues until the next control + // character in column 1. + // Look ahead to find a quote or a newline + // + if (SkipTo (SourceFile, UNICODE_DOUBLE_QUOTE, TRUE)) { + String = GetQuotedString (SourceFile, FALSE); + if (String != NULL) { + // + // Set the position in the file of where we are parsing for error + // reporting purposes. Then start looking ahead for additional + // quoted strings, and concatenate them until we get a failure + // back from the string parser. + // + Len = wcslen (String) + 1; + ParserSetPosition (SourceFile->FileName, SourceFile->LineNum); + do { + SkipWhiteSpace (SourceFile); + SecondString = GetQuotedString (SourceFile, TRUE); + if (SecondString != NULL) { + Len += wcslen (SecondString); + TempString = (WCHAR *) malloc (Len * sizeof (WCHAR)); + if (TempString == NULL) { + Error (NULL, 0, 0, "application error", "failed to allocate memory"); + return ; + } + + wcscpy (TempString, String); + wcscat (TempString, SecondString); + free (String); + free (SecondString); + String = TempString; + } + } while (SecondString != NULL); + StringDBAddString (Language, NULL, NULL, String, TRUE, 0); + free (String); + } else { + // + // Error was reported at lower level. Error recovery mode. + // + SourceFile->SkipToHash = TRUE; + } + } else { + if (!mGlobals.UnquotedStrings) { + // + // They're using unquoted strings. If the next non-blank character is a double quote, and the + // last non-blank character on the line is a double quote, then more than likely they're using + // quotes, so they need to put the quoted string on the end of the previous line + // + if (ApparentQuotedString (SourceFile)) { + Warning ( + SourceFile->FileName, + SourceFile->LineNum, + 0, + "unexpected quoted string on line", + "specify -uqs option if necessary" + ); + } + } + // + // Found end-of-line (hopefully). Skip over it and start taking in characters + // until we find a control character at the start of a line. + // + Len = 0; + From = SourceFile->FileBufferPtr; + PreviousNewline = FALSE; + while (!EndOfFile (SourceFile)) { + if (SourceFile->FileBufferPtr[0] == UNICODE_LF) { + PreviousNewline = TRUE; + SourceFile->LineNum++; + } else { + Len++; + if (PreviousNewline && (SourceFile->FileBufferPtr[0] == SourceFile->ControlCharacter)) { + break; + } + + PreviousNewline = FALSE; + } + + SourceFile->FileBufferPtr++; + } + + if ((Len == 0) && EndOfFile (SourceFile)) { + Error (SourceFile->FileName, SourceFile->LineNum, 0, "unexpected end of file", NULL); + SourceFile->SkipToHash = TRUE; + return ; + } + // + // Now allocate a buffer, copy the characters, and add the string. + // + String = (WCHAR *) malloc ((Len + 1) * sizeof (WCHAR)); + if (String == NULL) { + Error (NULL, 0, 0, "application error", "failed to allocate memory"); + return ; + } + + To = String; + while (From < SourceFile->FileBufferPtr) { + switch (*From) { + case UNICODE_LF: + case 0: + break; + + default: + *To = *From; + To++; + break; + } + + From++; + } + + // + // String[Len] = 0; + // + *To = 0; + StringDBAddString (Language, NULL, NULL, String, TRUE, 0); + } +} + +static +BOOLEAN +IsWhiteSpace ( + SOURCE_FILE *SourceFile + ) +{ + switch (SourceFile->FileBufferPtr[0]) { + case UNICODE_NULL: + case UNICODE_CR: + case UNICODE_SPACE: + case UNICODE_TAB: + case UNICODE_LF: + return TRUE; + + default: + return FALSE; + } +} + +static +UINT32 +SkipWhiteSpace ( + SOURCE_FILE *SourceFile + ) +{ + UINT32 Count; + + Count = 0; + while (!EndOfFile (SourceFile)) { + Count++; + switch (*SourceFile->FileBufferPtr) { + case UNICODE_NULL: + case UNICODE_CR: + case UNICODE_SPACE: + case UNICODE_TAB: + SourceFile->FileBufferPtr++; + break; + + case UNICODE_LF: + SourceFile->FileBufferPtr++; + SourceFile->LineNum++; + if (mGlobals.Verbose) { + printf ("%d: %S\n", SourceFile->LineNum, SourceFile->FileBufferPtr); + } + 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 +UINT32 +wstrcmp ( + WCHAR *Buffer, + WCHAR *Str + ) +{ + UINT32 Len; + + Len = 0; + while (*Str == *Buffer) { + Buffer++; + Str++; + Len++; + } + + if (*Str) { + return 0; + } + + return Len; +} +// +// Given a filename, try to find it along the include paths. +// +static +FILE * +FindFile ( + IN INT8 *FileName, + OUT INT8 *FoundFileName, + IN UINT32 FoundFileNameLen + ) +{ + FILE *Fptr; + TEXT_STRING_LIST *List; + + // + // Traverse the list of paths and try to find the file + // + List = mGlobals.IncludePaths; + while (List != NULL) { + // + // Put the path and filename together + // + if (strlen (List->Str) + strlen (FileName) + 1 > FoundFileNameLen) { + Error (PROGRAM_NAME, 0, 0, NULL, "internal error - cannot concatenate path+filename"); + return NULL; + } + // + // Append the filename to this include path and try to open the file. + // + strcpy (FoundFileName, List->Str); + strcat (FoundFileName, FileName); + if ((Fptr = fopen (FoundFileName, "rb")) != NULL) { + // + // Return the file pointer + // + return Fptr; + } + + List = List->Next; + } + // + // Not found + // + FoundFileName[0] = 0; + return NULL; +} +// +// Process the command-line arguments +// +static +STATUS +ProcessArgs ( + int Argc, + char *Argv[] + ) +{ + TEXT_STRING_LIST *NewList; + // + // Clear our globals + // + memset ((char *) &mGlobals, 0, sizeof (mGlobals)); + strcpy (mGlobals.BaseName, DEFAULT_BASE_NAME); + // + // Skip program name + // + Argc--; + Argv++; + + if (Argc == 0) { + Usage (); + return STATUS_ERROR; + } + + mGlobals.Mode = MODE_UNKNOWN; + // + // Process until no more -args. + // + while ((Argc > 0) && (Argv[0][0] == '-')) { + // + // -parse option + // + if (_stricmp (Argv[0], "-parse") == 0) { + if (mGlobals.Mode != MODE_UNKNOWN) { + Error (NULL, 0, 0, "only one of -parse/-scan/-dump allowed", NULL); + return STATUS_ERROR; + } + + mGlobals.Mode = MODE_PARSE; + // + // -scan option + // + } else if (_stricmp (Argv[0], "-scan") == 0) { + if (mGlobals.Mode != MODE_UNKNOWN) { + Error (NULL, 0, 0, "only one of -parse/-scan/-dump allowed", NULL); + return STATUS_ERROR; + } + + mGlobals.Mode = MODE_SCAN; + // + // -vscan verbose scanning option + // + } else if (_stricmp (Argv[0], "-vscan") == 0) { + mGlobals.VerboseScan = TRUE; + // + // -dump option + // + } else if (_stricmp (Argv[0], "-dump") == 0) { + if (mGlobals.Mode != MODE_UNKNOWN) { + Error (NULL, 0, 0, "only one of -parse/-scan/-dump allowed", NULL); + return STATUS_ERROR; + } + + mGlobals.Mode = MODE_DUMP; + } else if (_stricmp (Argv[0], "-uqs") == 0) { + mGlobals.UnquotedStrings = TRUE; + // + // -i path add include search path when parsing + // + } else if (_stricmp (Argv[0], "-i") == 0) { + // + // check for one more arg + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing include path"); + return STATUS_ERROR; + } + // + // Allocate memory for a new list element, fill it in, and + // add it to our list of include paths. Always make sure it + // has a "\" on the end of it. + // + NewList = malloc (sizeof (TEXT_STRING_LIST)); + if (NewList == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + memset ((char *) NewList, 0, sizeof (TEXT_STRING_LIST)); + NewList->Str = malloc (strlen (Argv[1]) + 2); + if (NewList->Str == NULL) { + free (NewList); + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + strcpy (NewList->Str, Argv[1]); + if (NewList->Str[strlen (NewList->Str) - 1] != '\\') { + strcat (NewList->Str, "\\"); + } + // + // Add it to our linked list + // + if (mGlobals.IncludePaths == NULL) { + mGlobals.IncludePaths = NewList; + } else { + mGlobals.LastIncludePath->Next = NewList; + } + + mGlobals.LastIncludePath = NewList; + Argc--; + Argv++; + } else if (_stricmp (Argv[0], "-if") == 0) { + // + // Indirection file -- check for one more arg + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing indirection file name"); + return STATUS_ERROR; + } + // + // Allocate memory for a new list element, fill it in, and + // add it to our list of include paths. Always make sure it + // has a "\" on the end of it. + // + NewList = malloc (sizeof (TEXT_STRING_LIST)); + if (NewList == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + memset ((char *) NewList, 0, sizeof (TEXT_STRING_LIST)); + NewList->Str = malloc (strlen (Argv[1]) + 1); + if (NewList->Str == NULL) { + free (NewList); + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + strcpy (NewList->Str, Argv[1]); + // + // Add it to our linked list + // + if (mGlobals.IndirectionFileName == NULL) { + mGlobals.IndirectionFileName = NewList; + } else { + mGlobals.LastIndirectionFileName->Next = NewList; + } + + mGlobals.LastIndirectionFileName = NewList; + Argc--; + Argv++; + } else if (_stricmp (Argv[0], "-db") == 0) { + // + // -db option to specify a database file. + // Check for one more arg (the database file name) + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing database file name"); + return STATUS_ERROR; + } + + NewList = malloc (sizeof (TEXT_STRING_LIST)); + if (NewList == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + memset ((char *) NewList, 0, sizeof (TEXT_STRING_LIST)); + NewList->Str = malloc (strlen (Argv[1]) + 1); + if (NewList->Str == NULL) { + free (NewList); + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + strcpy (NewList->Str, Argv[1]); + // + // Add it to our linked list + // + if (mGlobals.DatabaseFileName == NULL) { + mGlobals.DatabaseFileName = NewList; + } else { + mGlobals.LastDatabaseFileName->Next = NewList; + } + + mGlobals.LastDatabaseFileName = NewList; + Argc--; + Argv++; + } else if (_stricmp (Argv[0], "-ou") == 0) { + // + // -ou option to specify an output unicode file to + // which we can dump our database. + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing database dump output file name"); + return STATUS_ERROR; + } + + if (mGlobals.DumpUFileName[0] == 0) { + strcpy (mGlobals.DumpUFileName, Argv[1]); + } else { + Error (PROGRAM_NAME, 0, 0, Argv[1], "-ou option already specified with '%s'", mGlobals.DumpUFileName); + return STATUS_ERROR; + } + + Argc--; + Argv++; + } else if (_stricmp (Argv[0], "-hpk") == 0) { + // + // -hpk option to create an HII export pack of the input database file + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing raw string data dump output file name"); + return STATUS_ERROR; + } + + if (mGlobals.HiiExportPackFileName[0] == 0) { + strcpy (mGlobals.HiiExportPackFileName, Argv[1]); + } else { + Error (PROGRAM_NAME, 0, 0, Argv[1], "-or option already specified with '%s'", mGlobals.HiiExportPackFileName); + return STATUS_ERROR; + } + + Argc--; + Argv++; + } else if ((_stricmp (Argv[0], "-?") == 0) || (_stricmp (Argv[0], "-h") == 0)) { + Usage (); + return STATUS_ERROR; + } else if (_stricmp (Argv[0], "-v") == 0) { + mGlobals.Verbose = 1; + } else if (_stricmp (Argv[0], "-vdbw") == 0) { + mGlobals.VerboseDatabaseWrite = 1; + } else if (_stricmp (Argv[0], "-vdbr") == 0) { + mGlobals.VerboseDatabaseRead = 1; + } else if (_stricmp (Argv[0], "-newdb") == 0) { + mGlobals.NewDatabase = 1; + } else if (_stricmp (Argv[0], "-ignorenotfound") == 0) { + mGlobals.IgnoreNotFound = 1; + } else if (_stricmp (Argv[0], "-oc") == 0) { + // + // check for one more arg + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output C filename"); + return STATUS_ERROR; + } + + strcpy (mGlobals.StringCFileName, Argv[1]); + Argc--; + Argv++; + } else if (_stricmp (Argv[0], "-bn") == 0) { + // + // check for one more arg + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing base name"); + Usage (); + return STATUS_ERROR; + } + + strcpy (mGlobals.BaseName, Argv[1]); + Argc--; + Argv++; + } else if (_stricmp (Argv[0], "-oh") == 0) { + // + // -oh to specify output .h defines file name + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output .h filename"); + return STATUS_ERROR; + } + + strcpy (mGlobals.StringHFileName, Argv[1]); + Argc--; + Argv++; + } else if (_stricmp (Argv[0], "-dep") == 0) { + // + // -dep to specify output dependency file name + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output dependency filename"); + return STATUS_ERROR; + } + + strcpy (mGlobals.OutputDependencyFileName, Argv[1]); + Argc--; + Argv++; + } else if (_stricmp (Argv[0], "-skipext") == 0) { + // + // -skipext to skip scanning of files with certain filename extensions + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing filename extension"); + return STATUS_ERROR; + } + // + // Allocate memory for a new list element, fill it in, and + // add it to our list of excluded extensions. Always make sure it + // has a "." as the first character. + // + NewList = malloc (sizeof (TEXT_STRING_LIST)); + if (NewList == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + memset ((char *) NewList, 0, sizeof (TEXT_STRING_LIST)); + NewList->Str = malloc (strlen (Argv[1]) + 2); + if (NewList->Str == NULL) { + free (NewList); + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + if (Argv[1][0] == '.') { + strcpy (NewList->Str, Argv[1]); + } else { + NewList->Str[0] = '.'; + strcpy (NewList->Str + 1, Argv[1]); + } + // + // Add it to our linked list + // + if (mGlobals.SkipExt == NULL) { + mGlobals.SkipExt = NewList; + } else { + mGlobals.LastSkipExt->Next = NewList; + } + + mGlobals.LastSkipExt = NewList; + Argc--; + Argv++; + } else if (_stricmp (Argv[0], "-lang") == 0) { + // + // "-lang eng" or "-lang spa+cat" to only output certain languages + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing language name"); + Usage (); + return STATUS_ERROR; + } + + if (AddCommandLineLanguage (Argv[1]) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + Argc--; + Argv++; + } else if (_stricmp (Argv[0], "-od") == 0) { + // + // Output database file name -- check for another arg + // + if ((Argc <= 1) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output database file name"); + return STATUS_ERROR; + } + + strcpy (mGlobals.OutputDatabaseFileName, Argv[1]); + Argv++; + Argc--; + } else { + // + // Unrecognized arg + // + Error (PROGRAM_NAME, 0, 0, Argv[0], "unrecognized option"); + Usage (); + return STATUS_ERROR; + } + + Argv++; + Argc--; + } + // + // Make sure they specified the mode parse/scan/dump + // + if (mGlobals.Mode == MODE_UNKNOWN) { + Error (NULL, 0, 0, "must specify one of -parse/-scan/-dump", NULL); + return STATUS_ERROR; + } + // + // All modes require a database filename + // + if (mGlobals.DatabaseFileName == 0) { + Error (NULL, 0, 0, "must specify a database filename using -db DbFileName", NULL); + Usage (); + return STATUS_ERROR; + } + // + // If dumping the database file, then return immediately if all + // parameters check out. + // + if (mGlobals.Mode == MODE_DUMP) { + // + // Not much use if they didn't specify -oh or -oc or -ou or -hpk + // + if ((mGlobals.DumpUFileName[0] == 0) && + (mGlobals.StringHFileName[0] == 0) && + (mGlobals.StringCFileName[0] == 0) && + (mGlobals.HiiExportPackFileName[0] == 0) + ) { + Error (NULL, 0, 0, "-dump without -oc/-oh/-ou/-hpk is a NOP", NULL); + return STATUS_ERROR; + } + + return STATUS_SUCCESS; + } + // + // Had to specify source string file and output string defines header filename. + // + if (mGlobals.Mode == MODE_SCAN) { + if (Argc < 1) { + Error (PROGRAM_NAME, 0, 0, NULL, "must specify at least one source file to scan with -scan"); + Usage (); + return STATUS_ERROR; + } + // + // Get the list of filenames + // + while (Argc > 0) { + NewList = malloc (sizeof (TEXT_STRING_LIST)); + if (NewList == NULL) { + Error (PROGRAM_NAME, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + memset (NewList, 0, sizeof (TEXT_STRING_LIST)); + NewList->Str = (UINT8 *) malloc (strlen (Argv[0]) + 1); + if (NewList->Str == NULL) { + Error (PROGRAM_NAME, 0, 0, "memory allocation failure", NULL); + return STATUS_ERROR; + } + + strcpy (NewList->Str, Argv[0]); + if (mGlobals.ScanFileName == NULL) { + mGlobals.ScanFileName = NewList; + } else { + mGlobals.LastScanFileName->Next = NewList; + } + + mGlobals.LastScanFileName = NewList; + Argc--; + Argv++; + } + } else { + // + // Parse mode -- must specify an input unicode file name + // + if (Argc < 1) { + Error (PROGRAM_NAME, 0, 0, NULL, "must specify input unicode string file name with -parse"); + Usage (); + return STATUS_ERROR; + } + + strcpy (mGlobals.SourceFiles.FileName, Argv[0]); + } + + return STATUS_SUCCESS; +} +// +// Found "-lang eng,spa+cat" on the command line. Parse the +// language list and save the setting for later processing. +// +static +STATUS +AddCommandLineLanguage ( + IN INT8 *Language + ) +{ + WCHAR_STRING_LIST *WNewList; + WCHAR *From; + WCHAR *To; + // + // Keep processing the input string until we find the end. + // + while (*Language) { + // + // Allocate memory for a new list element, fill it in, and + // add it to our list. + // + WNewList = MALLOC (sizeof (WCHAR_STRING_LIST)); + if (WNewList == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + + memset ((char *) WNewList, 0, sizeof (WCHAR_STRING_LIST)); + WNewList->Str = malloc ((strlen (Language) + 1) * sizeof (WCHAR)); + if (WNewList->Str == NULL) { + free (WNewList); + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + // + // Copy it as unicode to our new structure. Then remove the + // plus signs in it, and verify each language name is 3 characters + // long. If we find a comma, then we're done with this group, so + // break out. + // +#ifdef USE_VC8 + swprintf (WNewList->Str, (strlen (Language) + 1) * sizeof (WCHAR), L"%S", Language); +#else + swprintf (WNewList->Str, L"%S", Language); +#endif + From = To = WNewList->Str; + while (*From) { + if (*From == L',') { + break; + } + + if ((wcslen (From) < LANGUAGE_IDENTIFIER_NAME_LEN) || + ( + (From[LANGUAGE_IDENTIFIER_NAME_LEN] != 0) && + (From[LANGUAGE_IDENTIFIER_NAME_LEN] != UNICODE_PLUS_SIGN) && + (From[LANGUAGE_IDENTIFIER_NAME_LEN] != L',') + ) + ) { + Error (PROGRAM_NAME, 0, 0, Language, "invalid format for language name on command line"); + FREE (WNewList->Str); + FREE (WNewList); + return STATUS_ERROR; + } + + wcsncpy (To, From, LANGUAGE_IDENTIFIER_NAME_LEN); + To += LANGUAGE_IDENTIFIER_NAME_LEN; + From += LANGUAGE_IDENTIFIER_NAME_LEN; + if (*From == L'+') { + From++; + } + } + + *To = 0; + // + // Add it to our linked list + // + if (mGlobals.Language == NULL) { + mGlobals.Language = WNewList; + } else { + mGlobals.LastLanguage->Next = WNewList; + } + + mGlobals.LastLanguage = WNewList; + // + // Skip to next entry (comma-separated list) + // + while (*Language) { + if (*Language == L',') { + Language++; + break; + } + + Language++; + } + } + + return STATUS_SUCCESS; +} +// +// The contents of the text file are expected to be (one per line) +// STRING_IDENTIFIER_NAME ScopeName +// For example: +// STR_ID_MY_FAVORITE_STRING IBM +// +static +STATUS +ParseIndirectionFiles ( + TEXT_STRING_LIST *Files + ) +{ + FILE *Fptr; + INT8 Line[200]; + INT8 *StringName; + INT8 *ScopeName; + INT8 *End; + UINT32 LineCount; + WCHAR_MATCHING_STRING_LIST *NewList; + + Line[sizeof (Line) - 1] = 0; + Fptr = NULL; + while (Files != NULL) { + Fptr = fopen (Files->Str, "r"); + LineCount = 0; + if (Fptr == NULL) { + Error (NULL, 0, 0, Files->Str, "failed to open input indirection file for reading"); + return STATUS_ERROR; + } + + while (fgets (Line, sizeof (Line), Fptr) != NULL) { + // + // remove terminating newline for error printing purposes. + // + if (Line[strlen (Line) - 1] == '\n') { + Line[strlen (Line) - 1] = 0; + } + + LineCount++; + if (Line[sizeof (Line) - 1] != 0) { + Error (Files->Str, LineCount, 0, "line length exceeds maximum supported", NULL); + goto Done; + } + + StringName = Line; + while (*StringName && (isspace (*StringName))) { + StringName++; + } + + if (*StringName) { + if ((*StringName == '_') || isalpha (*StringName)) { + End = StringName; + while ((*End) && (*End == '_') || (isalnum (*End))) { + End++; + } + + if (isspace (*End)) { + *End = 0; + End++; + while (isspace (*End)) { + End++; + } + + if (*End) { + ScopeName = End; + while (*End && !isspace (*End)) { + End++; + } + + *End = 0; + // + // Add the string name/scope pair + // + NewList = malloc (sizeof (WCHAR_MATCHING_STRING_LIST)); + if (NewList == NULL) { + Error (NULL, 0, 0, "memory allocation error", NULL); + goto Done; + } + + memset (NewList, 0, sizeof (WCHAR_MATCHING_STRING_LIST)); + NewList->Str1 = (WCHAR *) malloc ((strlen (StringName) + 1) * sizeof (WCHAR)); + NewList->Str2 = (WCHAR *) malloc ((strlen (ScopeName) + 1) * sizeof (WCHAR)); + if ((NewList->Str1 == NULL) || (NewList->Str2 == NULL)) { + Error (NULL, 0, 0, "memory allocation error", NULL); + goto Done; + } + +#ifdef USE_VC8 + swprintf (NewList->Str1, (strlen (StringName) + 1) * sizeof (WCHAR), L"%S", StringName); + swprintf (NewList->Str2, (strlen (ScopeName) + 1) * sizeof (WCHAR), L"%S", ScopeName); +#else + swprintf (NewList->Str1, L"%S", StringName); + swprintf (NewList->Str2, L"%S", ScopeName); +#endif + if (mGlobals.IndirectionList == NULL) { + mGlobals.IndirectionList = NewList; + } else { + mGlobals.LastIndirectionList->Next = NewList; + } + + mGlobals.LastIndirectionList = NewList; + } else { + Error (Files->Str, LineCount, 0, StringName, "invalid line : expected 'StringIdentifier Scope'"); + goto Done; + } + } else { + Error (Files->Str, LineCount, 0, StringName, "invalid line : expected 'StringIdentifier Scope'"); + goto Done; + } + } else { + Error (Files->Str, LineCount, 0, StringName, "invalid string identifier"); + goto Done; + } + } + } + + fclose (Fptr); + Fptr = NULL; + Files = Files->Next; + } + +Done: + if (Fptr != NULL) { + fclose (Fptr); + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} + +static +STATUS +ScanFiles ( + TEXT_STRING_LIST *ScanFiles + ) +{ + char Line[MAX_LINE_LEN]; + FILE *Fptr; + UINT32 LineNum; + char *Cptr; + char *SavePtr; + char *TermPtr; + char *StringTokenPos; + TEXT_STRING_LIST *SList; + BOOLEAN SkipIt; + + // + // Put a null-terminator at the end of the line. If we read in + // a line longer than we support, then we can catch it. + // + Line[MAX_LINE_LEN - 1] = 0; + // + // Process each file. If they gave us a skip extension list, then + // skip it if the extension matches. + // + while (ScanFiles != NULL) { + SkipIt = FALSE; + for (SList = mGlobals.SkipExt; SList != NULL; SList = SList->Next) { + if ((strlen (ScanFiles->Str) > strlen (SList->Str)) && + (strcmp (ScanFiles->Str + strlen (ScanFiles->Str) - strlen (SList->Str), SList->Str) == 0) + ) { + SkipIt = TRUE; + // + // printf ("Match: %s : %s\n", ScanFiles->Str, SList->Str); + // + break; + } + } + + if (!SkipIt) { + if (mGlobals.VerboseScan) { + printf ("Scanning %s\n", ScanFiles->Str); + } + + Fptr = fopen (ScanFiles->Str, "r"); + if (Fptr == NULL) { + Error (NULL, 0, 0, ScanFiles->Str, "failed to open input file for scanning"); + return STATUS_ERROR; + } + + LineNum = 0; + while (fgets (Line, sizeof (Line), Fptr) != NULL) { + LineNum++; + if (Line[MAX_LINE_LEN - 1] != 0) { + Error (ScanFiles->Str, LineNum, 0, "line length exceeds maximum supported by tool", NULL); + fclose (Fptr); + return STATUS_ERROR; + } + // + // Remove the newline from the input line so we can print a warning message + // + if (Line[strlen (Line) - 1] == '\n') { + Line[strlen (Line) - 1] = 0; + } + // + // Terminate the line at // comments + // + Cptr = strstr (Line, "//"); + if (Cptr != NULL) { + *Cptr = 0; + } + + Cptr = Line; + while ((Cptr = strstr (Cptr, STRING_TOKEN)) != NULL) { + // + // Found "STRING_TOKEN". Make sure we don't have NUM_STRING_TOKENS or + // something like that. Then make sure it's followed by + // an open parenthesis, a string identifier, and then a closing + // parenthesis. + // + if (mGlobals.VerboseScan) { + printf (" %d: %s", LineNum, Cptr); + } + + if (((Cptr == Line) || (!IsValidIdentifierChar (*(Cptr - 1), FALSE))) && + (!IsValidIdentifierChar (*(Cptr + sizeof (STRING_TOKEN) - 1), FALSE)) + ) { + StringTokenPos = Cptr; + SavePtr = Cptr; + Cptr += strlen (STRING_TOKEN); + while (*Cptr && isspace (*Cptr) && (*Cptr != '(')) { + Cptr++; + } + + if (*Cptr != '(') { + Warning (ScanFiles->Str, LineNum, 0, StringTokenPos, "expected "STRING_TOKEN "(identifier)"); + } else { + // + // Skip over the open-parenthesis and find the next non-blank character + // + Cptr++; + while (isspace (*Cptr)) { + Cptr++; + } + + SavePtr = Cptr; + if ((*Cptr == '_') || isalpha (*Cptr)) { + while ((*Cptr == '_') || (isalnum (*Cptr))) { + Cptr++; + } + + TermPtr = Cptr; + while (*Cptr && isspace (*Cptr)) { + Cptr++; + } + + if (*Cptr != ')') { + Warning (ScanFiles->Str, LineNum, 0, StringTokenPos, "expected "STRING_TOKEN "(identifier)"); + } + + if (*TermPtr) { + *TermPtr = 0; + Cptr = TermPtr + 1; + } else { + Cptr = TermPtr; + } + // + // Add the string identifier to the list of used strings + // + ParserSetPosition (ScanFiles->Str, LineNum); + StringDBSetStringReferenced (SavePtr, mGlobals.IgnoreNotFound); + if (mGlobals.VerboseScan) { + printf ("...referenced %s", SavePtr); + } + } else { + Warning (ScanFiles->Str, LineNum, 0, StringTokenPos, "expected valid string identifier name"); + } + } + } else { + // + // Found it, but it's a substring of something else. Advance our pointer. + // + Cptr++; + } + + if (mGlobals.VerboseScan) { + printf ("\n"); + } + } + } + + fclose (Fptr); + } else { + // + // Skipping this file type + // + if (mGlobals.VerboseScan) { + printf ("Skip scanning of %s\n", ScanFiles->Str); + } + } + + ScanFiles = ScanFiles->Next; + } + + return STATUS_SUCCESS; +} +// +// Free the global string lists we allocated memory for +// +static +void +FreeLists ( + VOID + ) +{ + TEXT_STRING_LIST *Temp; + WCHAR_STRING_LIST *WTemp; + + // + // Traverse the include paths, freeing each + // + while (mGlobals.IncludePaths != NULL) { + Temp = mGlobals.IncludePaths->Next; + free (mGlobals.IncludePaths->Str); + free (mGlobals.IncludePaths); + mGlobals.IncludePaths = Temp; + } + // + // If we did a scan, then free up our + // list of files to scan. + // + while (mGlobals.ScanFileName != NULL) { + Temp = mGlobals.ScanFileName->Next; + free (mGlobals.ScanFileName->Str); + free (mGlobals.ScanFileName); + mGlobals.ScanFileName = Temp; + } + // + // If they gave us a list of filename extensions to + // skip on scan, then free them up. + // + while (mGlobals.SkipExt != NULL) { + Temp = mGlobals.SkipExt->Next; + free (mGlobals.SkipExt->Str); + free (mGlobals.SkipExt); + mGlobals.SkipExt = Temp; + } + // + // Free up any languages specified + // + while (mGlobals.Language != NULL) { + WTemp = mGlobals.Language->Next; + free (mGlobals.Language->Str); + free (mGlobals.Language); + mGlobals.Language = WTemp; + } + // + // Free up our indirection list + // + while (mGlobals.IndirectionList != NULL) { + mGlobals.LastIndirectionList = mGlobals.IndirectionList->Next; + free (mGlobals.IndirectionList->Str1); + free (mGlobals.IndirectionList->Str2); + free (mGlobals.IndirectionList); + mGlobals.IndirectionList = mGlobals.LastIndirectionList; + } + + while (mGlobals.IndirectionFileName != NULL) { + mGlobals.LastIndirectionFileName = mGlobals.IndirectionFileName->Next; + free (mGlobals.IndirectionFileName->Str); + free (mGlobals.IndirectionFileName); + mGlobals.IndirectionFileName = mGlobals.LastIndirectionFileName; + } +} + +static +BOOLEAN +IsValidIdentifierChar ( + INT8 Char, + BOOLEAN FirstChar + ) +{ + // + // If it's the first character of an identifier, then + // it must be one of [A-Za-z_]. + // + if (FirstChar) { + if (isalpha (Char) || (Char == '_')) { + return TRUE; + } + } else { + // + // If it's not the first character, then it can + // be one of [A-Za-z_0-9] + // + if (isalnum (Char) || (Char == '_')) { + return TRUE; + } + } + + return FALSE; +} + +static +void +RewindFile ( + SOURCE_FILE *SourceFile + ) +{ + SourceFile->LineNum = 1; + SourceFile->FileBufferPtr = SourceFile->FileBuffer; + SourceFile->EndOfFile = 0; +} + +static +BOOLEAN +SkipTo ( + SOURCE_FILE *SourceFile, + WCHAR WChar, + BOOLEAN StopAfterNewline + ) +{ + while (!EndOfFile (SourceFile)) { + // + // Check for the character of interest + // + if (SourceFile->FileBufferPtr[0] == WChar) { + return TRUE; + } else { + if (SourceFile->FileBufferPtr[0] == UNICODE_LF) { + SourceFile->LineNum++; + if (StopAfterNewline) { + SourceFile->FileBufferPtr++; + if (SourceFile->FileBufferPtr[0] == 0) { + SourceFile->FileBufferPtr++; + } + + return FALSE; + } + } + + SourceFile->FileBufferPtr++; + } + } + + return FALSE; +} + +static +void +Usage ( + VOID + ) +/*++ + +Routine Description: + + Print usage information for this utility. + +Arguments: + + None. + +Returns: + + Nothing. + +--*/ +{ + int Index; + static const char *Str[] = { + "", + PROGRAM_NAME " version "TOOL_VERSION " -- process unicode strings file", + " Usage: "PROGRAM_NAME " -parse {parse options} [FileNames]", + " "PROGRAM_NAME " -scan {scan options} [FileName]", + " "PROGRAM_NAME " -dump {dump options}", + " Common options include:", + " -h or -? for this help information", + " -db Database required name of output/input database file", + " -bn BaseName for use in the .h and .c output files", + " Default = "DEFAULT_BASE_NAME, + " -v for verbose output", + " -vdbw for verbose output when writing database", + " -vdbr for verbose output when reading database", + " -od FileName to specify an output database file name", + " Parse options include:", + " -i IncludePath add IncludePath to list of search paths", + " -dep FileName to specify an output dependency file name", + " -newdb to not read in existing database file", + " -uqs to indicate that unquoted strings are used", + " FileNames name of one or more unicode files to parse", + " Scan options include:", + " -scan scan text file(s) for STRING_TOKEN() usage", + " -skipext .ext to skip scan of files with .ext filename extension", + " -ignorenotfound ignore if a given STRING_TOKEN(STR) is not ", + " found in the database", + " FileNames one or more files to scan", + " Dump options include:", + " -oc FileName write string data to FileName", + " -oh FileName write string defines to FileName", + " -ou FileName dump database to unicode file FileName", + " -lang Lang only dump for the language 'Lang'", + " -if FileName to specify an indirection file", + " -hpk FileName to create an HII export pack of the strings", + "", + " The expected process is to parse a unicode string file to create an initial", + " database of string identifier names and string definitions. Then text files", + " should be scanned for STRING_TOKEN() usages, and the referenced", + " strings will be tagged as used in the database. After all files have been", + " scanned, then the database should be dumped to create the necessary output", + " files.", + "", + NULL + }; + for (Index = 0; Str[Index] != NULL; Index++) { + fprintf (stdout, "%s\n", Str[Index]); + } +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StrGather.h b/EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StrGather.h new file mode 100644 index 0000000000..df175c2db6 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StrGather.h @@ -0,0 +1,84 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + StrGather.h + +Abstract: + + Common defines and prototypes for StrGather. + +--*/ + +#ifndef _STR_GATHER_H_ +#define _STR_GATHER_H_ + +#define MALLOC(size) malloc (size) +#define FREE(ptr) free (ptr) + +#define PROGRAM_NAME "StrGather" + +typedef CHAR16 WCHAR; + +#define UNICODE_TO_ASCII(w) (INT8) ((w) & 0xFF) +#define ASCII_TO_UNICODE(a) (WCHAR) ((UINT8) (a)) + +#define UNICODE_HASH L'#' +#define UNICODE_BACKSLASH L'\\' +#define UNICODE_SLASH L'/' +#define UNICODE_EQUAL_SIGN L'=' +#define UNICODE_PLUS_SIGN L'+' + +#define UNICODE_FILE_START 0xFEFF +#define UNICODE_CR 0x000D +#define UNICODE_LF 0x000A +#define UNICODE_NULL 0x0000 +#define UNICODE_SPACE L' ' +#define UNICODE_SLASH L'/' +#define UNICODE_DOUBLE_QUOTE L'"' +#define UNICODE_Z L'Z' +#define UNICODE_z L'z' +#define UNICODE_A L'A' +#define UNICODE_a L'a' +#define UNICODE_F L'F' +#define UNICODE_f L'f' +#define UNICODE_UNDERSCORE L'_' +#define UNICODE_0 L'0' +#define UNICODE_9 L'9' +#define UNICODE_TAB L'\t' +#define UNICODE_NBR_STRING L"\\nbr" +#define UNICODE_BR_STRING L"\\br" +#define UNICODE_WIDE_STRING L"\\wide" +#define UNICODE_NARROW_STRING L"\\narrow" + +// +// This is the length of a valid string identifier +// +#define LANGUAGE_IDENTIFIER_NAME_LEN 3 + +typedef struct _TEXT_STRING_LIST { + struct _TEXT_STRING_LIST *Next; + UINT8 *Str; +} TEXT_STRING_LIST; + +typedef struct _WCHAR_STRING_LIST { + struct _WCHAR_STRING_LIST *Next; + WCHAR *Str; +} WCHAR_STRING_LIST; + +typedef struct _WCHAR_MATCHING_STRING_LIST { + struct _WCHAR_MATCHING_STRING_LIST *Next; + WCHAR *Str1; + WCHAR *Str2; +} WCHAR_MATCHING_STRING_LIST; + +#endif // #ifndef _STR_GATHER_H_ diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StringDB.c b/EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StringDB.c new file mode 100644 index 0000000000..8fa01e80ab --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StringDB.c @@ -0,0 +1,2808 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + StringDB.c + +Abstract: + + String database implementation + +--*/ + +#include +#include +#include +#include // for tolower() +#include "Tiano.h" +#include "EfiUtilityMsgs.h" +#include "StrGather.h" +#include "StringDb.h" +#include "EfiInternalFormRepresentation.h" + +#include EFI_PROTOCOL_DEFINITION (Hii) + +typedef CHAR16 WCHAR; +#define STRING_OFFSET RELOFST + +#define STRING_DB_KEY (('S' << 24) | ('D' << 16) | ('B' << 8) | 'K') +// +// Version supported by this tool +// +#define STRING_DB_VERSION 0x00010000 + +#define STRING_DB_MAJOR_VERSION_MASK 0xFFFF0000 +#define STRING_DB_MINOR_VERSION_MASK 0x0000FFFF + +#define DEFINE_STR L"// #define" + +#define LANGUAGE_CODE_WIDTH 4 +// +// This is the header that gets written to the top of the +// output binary database file. +// +typedef struct { + UINT32 Key; + UINT32 HeaderSize; + UINT32 Version; + UINT32 NumStringIdenfiers; + UINT32 StringIdentifiersSize; + UINT32 NumLanguages; +} STRING_DB_HEADER; + +// +// When we write out data to the database, we have a UINT16 identifier, which +// indicates what follows, followed by the data. Here's the structure. +// +typedef struct { + UINT16 DataType; + UINT16 Reserved; +} DB_DATA_ITEM_HEADER; + +#define DB_DATA_TYPE_INVALID 0x0000 +#define DB_DATA_TYPE_STRING_IDENTIFIER 0x0001 +#define DB_DATA_TYPE_LANGUAGE_DEFINITION 0x0002 +#define DB_DATA_TYPE_STRING_DEFINITION 0x0003 +#define DB_DATA_TYPE_LAST DB_DATA_TYPE_STRING_DEFINITION + +// +// We have to keep track of a list of languages, each of which has its own +// list of strings. Define a structure to keep track of all languages and +// their list of strings. +// +typedef struct _STRING_LIST { + struct _STRING_LIST *Next; + UINT32 Size; // number of bytes in string, including null terminator + WCHAR *LanguageName; + WCHAR *StringName; // for example STR_ID_TEXT1 + WCHAR *Scope; // + WCHAR *Str; // the actual string + UINT16 Flags; // properties of this string (used, undefined) +} STRING_LIST; + +typedef struct _LANGUAGE_LIST { + struct _LANGUAGE_LIST *Next; + WCHAR LanguageName[4]; + WCHAR *PrintableLanguageName; + STRING_LIST *String; + STRING_LIST *LastString; +} LANGUAGE_LIST; + +// +// We also keep track of all the string identifier names, which we assign unique +// values to. Create a structure to keep track of them all. +// +typedef struct _STRING_IDENTIFIER { + struct _STRING_IDENTIFIER *Next; + UINT32 Index; // only need 16 bits, but makes it easier with UINT32 + WCHAR *StringName; + UINT16 Flags; // if someone referenced it via STRING_TOKEN() +} STRING_IDENTIFIER; +// +// Keep our globals in this structure to be as modular as possible. +// +typedef struct { + FILE *StringDBFptr; + LANGUAGE_LIST *LanguageList; + LANGUAGE_LIST *LastLanguageList; + LANGUAGE_LIST *CurrentLanguage; // keep track of the last language they used + STRING_IDENTIFIER *StringIdentifier; + STRING_IDENTIFIER *LastStringIdentifier; + UINT8 *StringDBFileName; + UINT32 NumStringIdentifiers; + UINT32 NumStringIdentifiersReferenced; + STRING_IDENTIFIER *CurrentStringIdentifier; // keep track of the last string identifier they added + WCHAR *CurrentScope; +} STRING_DB_DATA; + +static STRING_DB_DATA mDBData; + +static const char *mSourceFileHeader[] = { + "//", + "// DO NOT EDIT -- auto-generated file", + "//", + "// This file is generated by the string gather utility", + "//", + NULL +}; + +static +STRING_LIST * +StringDBFindString ( + WCHAR *LanguageName, + WCHAR *StringName, + WCHAR *Scope, + WCHAR_STRING_LIST *LanguagesOfInterest, + WCHAR_MATCHING_STRING_LIST *IndirectionList + ); + +static +STRING_IDENTIFIER * +StringDBFindStringIdentifierByName ( + WCHAR *Name + ); + +static +STRING_IDENTIFIER * +StringDBFindStringIdentifierByIndex ( + UINT32 Index + ); + +static +LANGUAGE_LIST * +StringDBFindLanguageList ( + WCHAR *LanguageName + ); + +static +void +StringDBWriteStandardFileHeader ( + FILE *OutFptr + ); + +static +WCHAR * +AsciiToWchar ( + INT8 *Str + ); + +static +WCHAR * +DuplicateString ( + WCHAR *Str + ); + +static +STATUS +StringDBWriteStringIdentifier ( + FILE *DBFptr, + UINT16 StringId, + UINT16 Flags, + WCHAR *IdentifierName + ); + +static +STATUS +StringDBReadStringIdentifier ( + FILE *DBFptr + ); + +static +STATUS +StringDBWriteLanguageDefinition ( + FILE *DBFptr, + WCHAR *LanguageName, + WCHAR *PrintableLanguageName + ); + +static +STATUS +StringDBReadLanguageDefinition ( + FILE *DBFptr + ); + +static +STATUS +StringDBWriteString ( + FILE *DBFptr, + UINT16 Flags, + WCHAR *Language, + WCHAR *StringName, + WCHAR *Scope, + WCHAR *Str + ); + +static +STATUS +StringDBReadString ( + FILE *DBFptr + ); + +static +STATUS +StringDBReadGenericString ( + FILE *DBFptr, + UINT16 *Size, + WCHAR **Str + ); + +static +STATUS +StringDBWriteGenericString ( + FILE *DBFptr, + WCHAR *Str + ); + +static +void +StringDBAssignStringIndexes ( + VOID + ); + +/*****************************************************************************/ + +/*++ + +Routine Description: + Constructor function for the string database handler. + +Arguments: + None. + +Returns: + None. + +--*/ +void +StringDBConstructor ( + VOID + ) +{ + memset ((char *) &mDBData, 0, sizeof (STRING_DB_DATA)); + mDBData.CurrentScope = DuplicateString (L"NULL"); +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + Destructor function for the string database handler. + +Arguments: + None. + +Returns: + None. + +--*/ +void +StringDBDestructor ( + VOID + ) +{ + LANGUAGE_LIST *NextLang; + STRING_LIST *NextStr; + STRING_IDENTIFIER *NextIdentifier; + // + // Close the database file if it's open + // + if (mDBData.StringDBFptr != NULL) { + fclose (mDBData.StringDBFptr); + mDBData.StringDBFptr = NULL; + } + // + // If we've allocated any strings/languages, free them up + // + while (mDBData.LanguageList != NULL) { + NextLang = mDBData.LanguageList->Next; + // + // Free up all strings for this language + // + while (mDBData.LanguageList->String != NULL) { + NextStr = mDBData.LanguageList->String->Next; + FREE (mDBData.LanguageList->String->Str); + FREE (mDBData.LanguageList->String); + mDBData.LanguageList->String = NextStr; + } + + FREE (mDBData.LanguageList->PrintableLanguageName); + FREE (mDBData.LanguageList); + mDBData.LanguageList = NextLang; + } + // + // Free up string identifiers + // + while (mDBData.StringIdentifier != NULL) { + NextIdentifier = mDBData.StringIdentifier->Next; + FREE (mDBData.StringIdentifier->StringName); + FREE (mDBData.StringIdentifier); + mDBData.StringIdentifier = NextIdentifier; + } + // + // Free the filename + // + if (mDBData.StringDBFileName != NULL) { + FREE (mDBData.StringDBFileName); + mDBData.StringDBFileName = NULL; + } + // + // We save a copy of the scope, so free it up if we + // have one. + // + if (mDBData.CurrentScope != NULL) { + FREE (mDBData.CurrentScope); + mDBData.CurrentScope = NULL; + } +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Dump the contents of a database to an output C file. + +Arguments: + + FileName - name of the output file to write + BaseName - used for the name of the C array defined + Languages - list of languages of interest + +Returns: + + STATUS + +Notes: + + Languages is a pointer to a linked list of languages specified on + the command line. Format is "eng" and "spa+cat". For this, print + the strings for eng. Print the strings for spa too, but if one is + missing look for a cat string and print if it it exists. + +--*/ +STATUS +StringDBDumpCStrings ( + INT8 *FileName, + INT8 *BaseName, + WCHAR_STRING_LIST *LanguagesOfInterest, + WCHAR_MATCHING_STRING_LIST *IndirectionList + ) +{ + FILE *Fptr; + LANGUAGE_LIST *Lang; + STRING_LIST *CurrString; + STRING_LIST EmptyString; + UINT32 Offset; + UINT32 StringIndex; + UINT32 TempIndex; + UINT32 BytesThisLine; + EFI_HII_STRING_PACK_HEADER StringPack; + UINT8 *Ptr; + UINT32 Len; + WCHAR ZeroString[1]; + WCHAR_STRING_LIST *LOIPtr; + BOOLEAN LanguageOk; + WCHAR *TempStringPtr; + WCHAR *LangName; + STRING_IDENTIFIER *StringIdentifier; + + if ((Fptr = fopen (FileName, "w")) == NULL) { + Error (NULL, 0, 0, FileName, "failed to open output C string file"); + return STATUS_ERROR; + } + // + // Assign index values to the string identifiers + // + StringDBAssignStringIndexes (); + // + // Write the standard header to the output file, then the structure + // definition header. + // + StringDBWriteStandardFileHeader (Fptr); + fprintf (Fptr, "\nunsigned char %s[] = {\n", BaseName); + // + // If a given string is not defined, then we'll use this one. + // + memset (&EmptyString, 0, sizeof (EmptyString)); + EmptyString.Size = sizeof (ZeroString); + EmptyString.Str = ZeroString; + // + // Process each language, then each string for each langage + // + ZeroString[0] = 0; + for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { + // + // If we have a language list, then make sure this language is in that + // list. + // + LanguageOk = TRUE; + LangName = Lang->LanguageName; + if (LanguagesOfInterest != NULL) { + LanguageOk = FALSE; + for (LOIPtr = LanguagesOfInterest; LOIPtr != NULL; LOIPtr = LOIPtr->Next) { + if (wcsncmp (LOIPtr->Str, Lang->LanguageName, LANGUAGE_IDENTIFIER_NAME_LEN) == 0) { + LangName = LOIPtr->Str; + LanguageOk = TRUE; + break; + } + } + } + + if (!LanguageOk) { + continue; + } + // + // Process each string for this language. We have to make 3 passes on the strings: + // Pass1: computes sizes and fill in the string pack header + // Pass2: write the array of offsets + // Pass3: write the strings + // + // + // PASS 1: Fill in and print the HII string pack header + // + // Compute the size for this language package and write + // the header out. Each string package contains: + // Header + // Offset[] -- an array of offsets to strings, of type RELOFST each + // String[] -- the actual strings themselves + // + fprintf ( + Fptr, + "\n//******************************************************************************" + "\n// Start of string definitions for %S/%S", + Lang->LanguageName, + Lang->PrintableLanguageName + ); + memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK_HEADER)); + StringPack.Header.Type = EFI_HII_STRING; + StringPack.NumStringPointers = (UINT16) mDBData.NumStringIdentifiersReferenced; + // + // First string is the language name. If we're printing all languages, then + // it's just the "spa". If we were given a list of languages to print, then it's + // the "spacat" string. Compute its offset and fill in + // the info in the header. Since we know the language name string's length, + // and the printable language name follows it, use that info to fill in the + // entry for the printable language name as well. + // + StringPack.LanguageNameString = (STRING_OFFSET) (sizeof (EFI_HII_STRING_PACK_HEADER) + (mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET))); + StringPack.PrintableLanguageName = (STRING_OFFSET) (StringPack.LanguageNameString + (wcslen (LangName) + 1) * sizeof (WCHAR)); + // + // Add up the size of all strings so we can fill in our header. + // + Len = 0; + for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { + // + // For the first string (language name), we print out the "spacat" if they + // requested it. We set LangName to point to the proper language name string above. + // + if (StringIndex == STRING_ID_LANGUAGE_NAME) { + Len += (wcslen (LangName) + 1) * sizeof (WCHAR); + } else { + // + // Find a string with this language.stringname + // + StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); + if (StringIdentifier == NULL) { + Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); + return STATUS_ERROR; + } + // + // Find a matching string if this string identifier was referenced + // + EmptyString.Flags = STRING_FLAGS_UNDEFINED; + CurrString = NULL; + if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) { + CurrString = StringDBFindString ( + Lang->LanguageName, + StringIdentifier->StringName, + NULL, + LanguagesOfInterest, + IndirectionList + ); + if (NULL == CurrString) { + // + // If string for Lang->LanguageName is not found, try to get an English version + // + CurrString = StringDBFindString ( + L"eng", + StringIdentifier->StringName, + NULL, + LanguagesOfInterest, + IndirectionList + ); + } + } + + if (CurrString == NULL) { + CurrString = &EmptyString; + EmptyString.Flags |= StringIdentifier->Flags; + } + + Len += CurrString->Size; + } + } + StringPack.Header.Length = sizeof (EFI_HII_STRING_PACK_HEADER) + + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET) + + Len; + // + // Write out the header one byte at a time + // + Ptr = (UINT8 *) &StringPack; + for (TempIndex = 0; TempIndex < sizeof (EFI_HII_STRING_PACK_HEADER); TempIndex++, Ptr++) { + if ((TempIndex & 0x07) == 0) { + fprintf (Fptr, "\n "); + } + + fprintf (Fptr, "0x%02X, ", (UINT32) *Ptr); + } + + fprintf (Fptr, "\n // offset 0x%X\n", sizeof (StringPack)); + // + // PASS2 : write the offsets + // + // Traverse the list of strings again and write the array of offsets. The + // offset to the first string is the size of the string pack header + // plus the size of the offsets array. The other strings follow it. + // + StringIndex = 0; + Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET); + for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { + // + // Write the offset, followed by a useful comment + // + fprintf (Fptr, " "); + Ptr = (UINT8 *) &Offset; + for (TempIndex = 0; TempIndex < sizeof (STRING_OFFSET); TempIndex++) { + fprintf (Fptr, "0x%02X, ", (UINT32) Ptr[TempIndex]); + } + // + // Find the string name + // + StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); + if (StringIdentifier == NULL) { + Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); + return STATUS_ERROR; + } + + fprintf (Fptr, " // offset to string %S (0x%04X)", StringIdentifier->StringName, StringIndex); + // + // For the first string (language name), we print out the "spacat" if they + // requested it. We set LangName to point to the proper language name string above. + // + if (StringIndex == STRING_ID_LANGUAGE_NAME) { + Offset += (wcslen (LangName) + 1) * sizeof (WCHAR); + CurrString = StringDBFindString ( + Lang->LanguageName, + StringIdentifier->StringName, + NULL, // scope + NULL, + NULL + ); + } else { + // + // Find a matching string + // + CurrString = StringDBFindString ( + Lang->LanguageName, + StringIdentifier->StringName, + NULL, // scope + LanguagesOfInterest, + IndirectionList + ); + + if (NULL == CurrString) { + CurrString = StringDBFindString ( + L"eng", + StringIdentifier->StringName, + NULL, // scope + LanguagesOfInterest, + IndirectionList + ); + } + + EmptyString.LanguageName = Lang->LanguageName; + if (CurrString == NULL) { + CurrString = &EmptyString; + EmptyString.Flags = STRING_FLAGS_UNDEFINED; + } else if ((StringIdentifier->Flags & STRING_FLAGS_REFERENCED) == 0) { + CurrString = &EmptyString; + EmptyString.Flags = 0; + } + + Offset += CurrString->Size; + } + // + // Print useful info about this string + // + if ((StringIdentifier->Flags & STRING_FLAGS_REFERENCED) == 0) { + fprintf (Fptr, " - not referenced"); + } + + if (CurrString->Flags & STRING_FLAGS_UNDEFINED) { + fprintf (Fptr, " - not defined for this language"); + } else if (wcscmp (CurrString->LanguageName, Lang->LanguageName) != 0) { + fprintf ( + Fptr, + " - not defined for this language -- using secondary language %S definition", + CurrString->LanguageName + ); + } + + fprintf (Fptr, "\n"); + } + // + // For unreferenced string identifiers, print a message that they are not referenced anywhere + // + while (StringIndex < mDBData.NumStringIdentifiers) { + StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); + if (StringIdentifier != NULL) { + fprintf (Fptr, " // %S not referenced\n", StringIdentifier->StringName); + } + + StringIndex++; + } + + // + // PASS 3: write the strings themselves. + // Keep track of how many bytes we write per line because some editors + // (Visual Studio for instance) can't handle too long of lines. + // + Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET); + for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { + StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); + if (StringIdentifier == NULL) { + Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); + return STATUS_ERROR; + } + + fprintf (Fptr, " // string %S offset 0x%08X\n ", StringIdentifier->StringName, Offset); + // + // For the first string (language name), we print out the "spacat" if they + // requested it. We set LangName to point to the proper language name string above. + // + if (StringIndex == STRING_ID_LANGUAGE_NAME) { + TempStringPtr = LangName; + } else { + // + // Find a matching string if this string identifier was referenced + // + CurrString = NULL; + if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) { + CurrString = StringDBFindString ( + Lang->LanguageName, + StringIdentifier->StringName, + NULL, // scope + LanguagesOfInterest, + IndirectionList + ); + if (NULL == CurrString) { + CurrString = StringDBFindString ( + L"eng", + StringIdentifier->StringName, + NULL, // scope + LanguagesOfInterest, + IndirectionList + ); + } + } + + if (CurrString == NULL) { + CurrString = &EmptyString; + } + + TempStringPtr = CurrString->Str; + } + + BytesThisLine = 0; + for (TempIndex = 0; TempStringPtr[TempIndex] != 0; TempIndex++) { + fprintf ( + Fptr, + "0x%02X, 0x%02X, ", + (UINT32) TempStringPtr[TempIndex] & 0xFF, + (UINT32) ((TempStringPtr[TempIndex] >> 8) & 0xFF) + ); + BytesThisLine += 2; + Offset += 2; + // + // Let's say we only allow 14 per line + // + if (BytesThisLine > 14) { + fprintf (Fptr, "\n "); + BytesThisLine = 0; + } + } + // + // Print NULL WCHAR at the end of this string. + // + fprintf (Fptr, "0x00, 0x00,\n"); + Offset += 2; + } + // + // Sanity check the offset. Make sure our running offset is what we put in the + // string pack header. + // + if (StringPack.Header.Length != Offset) { + Error ( + __FILE__, + __LINE__, + 0, + "application error", + "stringpack size 0x%X does not match final size 0x%X", + StringPack.Header.Length, + Offset + ); + } + } + // + // Print terminator string pack, closing brace and close the file. + // The size of 0 triggers to the consumer that this is the end. + // + memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK_HEADER)); + StringPack.Header.Type = EFI_HII_STRING; + Ptr = (UINT8 *) &StringPack; + fprintf (Fptr, "\n // strings terminator pack"); + for (TempIndex = 0; TempIndex < sizeof (StringPack); TempIndex++, Ptr++) { + if ((TempIndex & 0x0F) == 0) { + fprintf (Fptr, "\n "); + } + + fprintf (Fptr, "0x%02X, ", (UINT32) *Ptr); + } + + fprintf (Fptr, "\n};\n"); + fclose (Fptr); + return STATUS_SUCCESS; +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Dump the #define string names + +Arguments: + + FileName - name of the output file to write + BaseName - used for the protection #ifndef/#endif + +Returns: + + STATUS + +--*/ +STATUS +StringDBDumpStringDefines ( + INT8 *FileName, + INT8 *BaseName + ) +{ + FILE *Fptr; + STRING_IDENTIFIER *Identifier; + INT8 CopyBaseName[100]; + UINT32 Index; + const INT8 *StrDefHeader[] = { + "#ifndef _%s_STRINGS_DEFINE_H_\n", + "#define _%s_STRINGS_DEFINE_H_\n\n", + NULL + }; + + if ((Fptr = fopen (FileName, "w")) == NULL) { + Error (NULL, 0, 0, FileName, "failed to open output string defines file"); + return STATUS_ERROR; + } + // + // Get the base source filename and convert to uppercase. + // + if (sizeof (CopyBaseName) <= strlen (BaseName) + 1) { + Error (NULL, 0, 0, "application error", "StringDBDumpStringDefines() string length insufficient"); + return STATUS_ERROR; + } + + strcpy (CopyBaseName, BaseName); + for (Index = 0; CopyBaseName[Index] != 0; Index++) { + if (islower (CopyBaseName[Index])) { + CopyBaseName[Index] = (INT8) toupper (CopyBaseName[Index]); + } + } + // + // Assign index values to the string identifiers + // + StringDBAssignStringIndexes (); + // + // Write the standard header to the output file, and then the + // protective #ifndef. + // + StringDBWriteStandardFileHeader (Fptr); + for (Index = 0; StrDefHeader[Index] != NULL; Index++) { + fprintf (Fptr, StrDefHeader[Index], CopyBaseName); + } + // + // Print all the #defines for the string identifiers. Print identifiers + // whose names start with '$' as comments. Add comments for string + // identifiers not used as well. + // + Identifier = mDBData.StringIdentifier; + while (Identifier != NULL) { + if (Identifier->StringName[0] == L'$') { + fprintf (Fptr, "// "); + } + + if (Identifier->Flags & STRING_FLAGS_REFERENCED) { + fprintf (Fptr, "#define %-40S 0x%04X\n", Identifier->StringName, Identifier->Index); + } else { + fprintf (Fptr, "//#define %-40S 0x%04X // not referenced\n", Identifier->StringName, Identifier->Index); + } + + Identifier = Identifier->Next; + } + + fprintf (Fptr, "\n#endif\n"); + fclose (Fptr); + return STATUS_SUCCESS; +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Add a string identifier to the database. + +Arguments: + + StringName - name of the string identifier. For example "STR_MY_STRING" + NewId - if an ID has been assigned + Flags - characteristics for the identifier + +Returns: + + STATUS + +--*/ +STATUS +StringDBAddStringIdentifier ( + WCHAR *StringName, + UINT16 *NewId, + UINT16 Flags + ) +{ + STRING_IDENTIFIER *StringIdentifier; + STATUS Status; + // + // If it was already used for some other language, then we don't + // need to add it. But set it to the current string identifier. + // The referenced bit is sticky. + // + Status = STATUS_SUCCESS; + StringIdentifier = StringDBFindStringIdentifierByName (StringName); + if (StringIdentifier != NULL) { + if (Flags & STRING_FLAGS_REFERENCED) { + StringIdentifier->Flags |= STRING_FLAGS_REFERENCED; + } + + mDBData.CurrentStringIdentifier = StringIdentifier; + *NewId = (UINT16) StringIdentifier->Index; + return Status; + } + + StringIdentifier = (STRING_IDENTIFIER *) MALLOC (sizeof (STRING_IDENTIFIER)); + if (StringIdentifier == NULL) { + Error (NULL, 0, 0, NULL, "memory allocation error"); + return STATUS_ERROR; + } + + memset ((char *) StringIdentifier, 0, sizeof (STRING_IDENTIFIER)); + StringIdentifier->StringName = (WCHAR *) malloc ((wcslen (StringName) + 1) * sizeof (WCHAR)); + if (StringIdentifier->StringName == NULL) { + Error (NULL, 0, 0, NULL, "memory allocation error"); + return STATUS_ERROR; + } + + wcscpy (StringIdentifier->StringName, StringName); + if (*NewId != STRING_ID_INVALID) { + StringIdentifier->Index = *NewId; + StringIdentifier->Flags |= STRING_FLAGS_INDEX_ASSIGNED; + if (mDBData.NumStringIdentifiers <= StringIdentifier->Index) { + mDBData.NumStringIdentifiers = StringIdentifier->Index + 1; + } + } else { + StringIdentifier->Index = mDBData.NumStringIdentifiers++; + } + + StringIdentifier->Flags |= Flags; + // + // Add it to our list of string identifiers + // + if (mDBData.StringIdentifier == NULL) { + mDBData.StringIdentifier = StringIdentifier; + } else { + mDBData.LastStringIdentifier->Next = StringIdentifier; + } + + mDBData.LastStringIdentifier = StringIdentifier; + mDBData.CurrentStringIdentifier = StringIdentifier; + *NewId = (UINT16) StringIdentifier->Index; + return Status; +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Add a new string to the database. + +Arguments: + + LanguageName - "eng" or "spa" language name + StringName - "STR_MY_TEXT" string name + Scope - from the #scope statements in the string file + Format - if we should format the string + Flags - characteristic flags for the string + +Returns: + + STATUS + +Notes: + + Several of the fields can be "inherited" from the previous calls to + our database functions. For example, if scope is NULL here, then + we'll use the previous setting. + +--*/ +STATUS +StringDBAddString ( + WCHAR *LanguageName, + WCHAR *StringName, + WCHAR *Scope, + WCHAR *String, + BOOLEAN Format, + UINT16 Flags + ) +{ + LANGUAGE_LIST *Lang; + UINT32 Size; + STRING_LIST *Str; + UINT16 StringIndex; + WCHAR TempLangName[4]; + STRING_IDENTIFIER *StringIdentifier; + + // + // Check that language name is exactly 3 characters, or emit an error. + // Truncate at 3 if it's longer, or make it 3 if it's shorter. + // + if (LanguageName != NULL) { + Size = wcslen (LanguageName); + if (Size != 3) { + ParserError (0, "invalid length for language name", "%S", LanguageName); + if (Size > 3) { + LanguageName[3] = 0; + } else { + // + // Make a local copy of the language name string, and extend to + // 3 characters since we make assumptions elsewhere in this program + // on the length. + // + wcscpy (TempLangName, LanguageName); + for (; Size < 3; Size++) { + TempLangName[Size] = L'?'; + } + + TempLangName[3] = 0; + LanguageName = TempLangName; + } + } + } + // + // If they specified a language, make sure they've defined it already + // via a #langdef statement. Otherwise use the current default language. + // + if (LanguageName != NULL) { + Lang = StringDBFindLanguageList (LanguageName); + if (Lang == NULL) { + ParserError (0, "language not defined", "%S", LanguageName); + return STATUS_ERROR; + } else { + StringDBSetCurrentLanguage (LanguageName); + } + } else { + Lang = mDBData.CurrentLanguage; + if (Lang == NULL) { + // + // Have to call SetLanguage() first + // + ParserError (0, "no language defined", "%S", StringName); + return STATUS_ERROR; + } + } + // + // If they didn't define a string identifier, use the last string identifier + // added. + // + if (StringName == NULL) { + StringName = mDBData.CurrentStringIdentifier->StringName; + if (StringName == NULL) { + ParserError (0, "no string identifier previously specified", NULL); + return STATUS_ERROR; + } + } + // + // If scope was not specified, use the default setting + // + if (Scope != NULL) { + Scope = DuplicateString (Scope); + } else { + Scope = DuplicateString (mDBData.CurrentScope); + } + // + // printf ("Adding string: %S.%S.%S\n", Lang->LanguageName, StringName, Scope); + // + // Check for duplicates for this Language.StringName.Scope. Allow multiple + // definitions of the language name and printable language name, since the + // user does not specifically define them. + // + if (StringDBFindString (Lang->LanguageName, StringName, Scope, NULL, NULL) != NULL) { + if ((wcscmp (StringName, LANGUAGE_NAME_STRING_NAME) == 0) && + (wcscmp (StringName, PRINTABLE_LANGUAGE_NAME_STRING_NAME) == 0) + ) { + ParserError ( + 0, + "string multiply defined", + "Language.Name.Scope = %S.%S.%S", + Lang->LanguageName, + StringName, + Scope + ); + return STATUS_ERROR; + } + } + + StringIndex = STRING_ID_INVALID; + if (StringDBAddStringIdentifier (StringName, &StringIndex, Flags) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + StringIdentifier = StringDBFindStringIdentifierByName (StringName); + // + // Add this string to the end of the strings for this language. + // + Str = (STRING_LIST *) malloc (sizeof (STRING_LIST)); + if (Str == NULL) { + Error (NULL, 0, 0, NULL, "memory allocation error"); + return STATUS_ERROR; + } + + memset ((char *) Str, 0, sizeof (STRING_LIST)); + Size = (wcslen (String) + 1) * sizeof (WCHAR); + Str->Flags = Flags; + Str->Scope = Scope; + Str->StringName = StringIdentifier->StringName; + Str->LanguageName = DuplicateString (LanguageName); + Str->Str = (WCHAR *) MALLOC (Size); + if (Str->Str == NULL) { + Error (NULL, 0, 0, NULL, "memory allocation error"); + return STATUS_ERROR; + } + // + // If not formatting, just copy the string. + // + wcscpy (Str->Str, String); + if (Format) { + StringDBFormatString (Str->Str); + } + // + // Size may change after formatting. We set the size to + // the actual size of the string, including the null for + // easier processing later. + // + Str->Size = (wcslen (Str->Str) + 1) * sizeof (WCHAR); + if (Lang->String == NULL) { + Lang->String = Str; + } else { + Lang->LastString->Next = Str; + } + + Lang->LastString = Str; + return STATUS_SUCCESS; +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Given a language name, see if a language list for it has been defined + +Arguments: + + LanguageName - like "eng" + +Returns: + + A pointer to the language list + +--*/ +static +LANGUAGE_LIST * +StringDBFindLanguageList ( + WCHAR *LanguageName + ) +{ + LANGUAGE_LIST *Lang; + + Lang = mDBData.LanguageList; + while (Lang != NULL) { + if (wcscmp (LanguageName, Lang->LanguageName) == 0) { + break; + } + + Lang = Lang->Next; + } + + return Lang; +} + +/*****************************************************************************/ +STATUS +StringDBSetCurrentLanguage ( + WCHAR *LanguageName + ) +{ + LANGUAGE_LIST *Lang; + + Lang = StringDBFindLanguageList (LanguageName); + if (Lang == NULL) { + ParserError (0, "language not previously defined", "%S", LanguageName); + return STATUS_ERROR; + } + + mDBData.CurrentLanguage = Lang; + return STATUS_SUCCESS; +} + +/*****************************************************************************/ +STATUS +StringDBAddLanguage ( + WCHAR *LanguageName, + WCHAR *PrintableLanguageName + ) +{ + LANGUAGE_LIST *Lang; + // + // Check for redefinitions + // + Lang = StringDBFindLanguageList (LanguageName); + if (Lang != NULL) { + // + // Better be the same printable name + // + if (wcscmp (PrintableLanguageName, Lang->PrintableLanguageName) != 0) { + ParserError ( + 0, + "language redefinition", + "%S:%S != %S:%S", + Lang->LanguageName, + Lang->PrintableLanguageName, + LanguageName, + PrintableLanguageName + ); + return STATUS_ERROR; + // + // } else { + // ParserWarning (0, "benign language redefinition", "%S", PrintableLanguageName); + // return STATUS_WARNING; + // + } + } else { + // + // Allocate memory to keep track of this new language + // + Lang = (LANGUAGE_LIST *) malloc (sizeof (LANGUAGE_LIST)); + if (Lang == NULL) { + Error (NULL, 0, 0, NULL, "memory allocation error"); + return STATUS_ERROR; + } + + memset ((char *) Lang, 0, sizeof (LANGUAGE_LIST)); + // + // Save the language name, then allocate memory to save the + // printable language name + // + Lang->LanguageName[3] = 0; + wcsncpy (Lang->LanguageName, LanguageName, 3); + Lang->PrintableLanguageName = (WCHAR *) malloc ((wcslen (PrintableLanguageName) + 1) * sizeof (WCHAR)); + if (Lang->PrintableLanguageName == NULL) { + Error (NULL, 0, 0, NULL, "memory allocation error"); + return STATUS_ERROR; + } + + wcscpy (Lang->PrintableLanguageName, PrintableLanguageName); + + if (mDBData.LanguageList == NULL) { + mDBData.LanguageList = Lang; + } else { + mDBData.LastLanguageList->Next = Lang; + } + + mDBData.LastLanguageList = Lang; + } + // + // Default is to make our active language this new one + // + StringDBSetCurrentLanguage (LanguageName); + // + // The first two strings for any language are the language name, + // followed by the printable language name. Add them and set them + // to referenced so they never get stripped out. + // + StringDBAddString ( + LanguageName, + LANGUAGE_NAME_STRING_NAME, + NULL, + LanguageName, + FALSE, + STRING_FLAGS_REFERENCED + ); + StringDBAddString ( + LanguageName, + PRINTABLE_LANGUAGE_NAME_STRING_NAME, + NULL, + PrintableLanguageName, + FALSE, + STRING_FLAGS_REFERENCED + ); + return STATUS_SUCCESS; +} + +/*****************************************************************************/ +static +STRING_IDENTIFIER * +StringDBFindStringIdentifierByName ( + WCHAR *StringName + ) +{ + STRING_IDENTIFIER *Identifier; + + Identifier = mDBData.StringIdentifier; + while (Identifier != NULL) { + if (wcscmp (StringName, Identifier->StringName) == 0) { + return Identifier; + } + + Identifier = Identifier->Next; + } + + return NULL; +} + +static +STRING_IDENTIFIER * +StringDBFindStringIdentifierByIndex ( + UINT32 StringIndex + ) +{ + STRING_IDENTIFIER *Identifier; + + Identifier = mDBData.StringIdentifier; + while (Identifier != NULL) { + if (Identifier->Index == StringIndex) { + return Identifier; + } + + Identifier = Identifier->Next; + } + + return NULL; +} + +/*****************************************************************************/ +static +void +StringDBWriteStandardFileHeader ( + FILE *OutFptr + ) +{ + UINT32 TempIndex; + for (TempIndex = 0; mSourceFileHeader[TempIndex] != NULL; TempIndex++) { + fprintf (OutFptr, "%s\n", mSourceFileHeader[TempIndex]); + } +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Given a Unicode string from an input file, reformat the string to replace + backslash control sequences with the appropriate encoding. + +Arguments: + + String - pointer to string to reformat + +Returns: + + Nothing + +--*/ +void +StringDBFormatString ( + WCHAR *String + ) +{ + WCHAR *From; + WCHAR *To; + int HexNibbles; + WCHAR HexValue; + // + // Go through the string and process any formatting characters + // + From = String; + To = String; + while (*From) { + if (*From == UNICODE_BACKSLASH) { + // + // First look for \wide and replace with the appropriate control character. Note that + // when you have "define STR L"ABC"", then sizeof(ABC) is 8 because the null char is + // counted. Make adjustments for this. We advance From below, so subtract 2 each time. + // + if (wcsncmp (From, UNICODE_WIDE_STRING, sizeof (UNICODE_WIDE_STRING) / sizeof (WCHAR) - 1) == 0) { + *To = WIDE_CHAR; + From += sizeof (UNICODE_WIDE_STRING) / sizeof (WCHAR) - 2; + } else if (wcsncmp (From, UNICODE_NARROW_STRING, sizeof (UNICODE_NARROW_STRING) / sizeof (WCHAR) - 1) == 0) { + // + // Found: \narrow + // + *To = NARROW_CHAR; + From += sizeof (UNICODE_NARROW_STRING) / sizeof (WCHAR) - 2; + } else if (wcsncmp (From, UNICODE_NBR_STRING, sizeof (UNICODE_NBR_STRING) / sizeof (WCHAR) - 1) == 0) { + // + // Found: \nbr + // + *To = NON_BREAKING_CHAR; + From += sizeof (UNICODE_NBR_STRING) / sizeof (WCHAR) - 2; + } else if (wcsncmp (From, UNICODE_BR_STRING, sizeof (UNICODE_BR_STRING) / sizeof (WCHAR) - 1) == 0) { + // + // Found: \br -- pass through untouched + // + *To = *From; + } else { + // + // Standard one-character control sequences such as \n, \r, \\, or \x + // + From++; + switch (*From) { + case ASCII_TO_UNICODE ('n'): + *To = UNICODE_CR; + To++; + *To = UNICODE_LF; + break; + + // + // carriage return + // + case ASCII_TO_UNICODE ('r'): + *To = UNICODE_CR; + break; + + // + // backslash + // + case UNICODE_BACKSLASH: + *To = UNICODE_BACKSLASH; + break; + + // + // Tab + // + case ASCII_TO_UNICODE ('t'): + *To = UNICODE_TAB; + break; + + // + // embedded double-quote + // + case UNICODE_DOUBLE_QUOTE: + *To = UNICODE_DOUBLE_QUOTE; + break; + + // + // Hex Unicode character \x1234. We'll process up to 4 hex characters + // + case ASCII_TO_UNICODE ('x'): + HexValue = 0; + for (HexNibbles = 0; HexNibbles < 4; HexNibbles++) { + if ((From[1] >= UNICODE_0) && (From[1] <= UNICODE_9)) { + HexValue = (HexValue << 4) | (From[1] - UNICODE_0); + } else if ((From[1] >= UNICODE_a) && (From[1] <= UNICODE_f)) { + HexValue = (HexValue << 4) | (10 + From[1] - UNICODE_a); + } else if ((From[1] >= UNICODE_A) && (From[1] <= UNICODE_F)) { + HexValue = (HexValue << 4) | (10 + From[1] - UNICODE_A); + } else { + break; + } + + From++; + } + + if (HexNibbles == 0) { + ParserWarning ( + 0, + "expected at least one valid hex digit with \\x escaped character in string", + "\\%C", + *From + ); + } else { + *To = HexValue; + } + break; + + default: + *To = UNICODE_SPACE; + ParserWarning (0, "invalid escaped character in string", "\\%C", *From); + break; + } + } + } else { + *To = *From; + } + + From++; + To++; + } + + *To = 0; +} + +/*****************************************************************************/ +STATUS +StringDBReadDatabase ( + INT8 *DBFileName, + BOOLEAN IgnoreIfNotExist, + BOOLEAN Verbose + ) +{ + STRING_DB_HEADER DbHeader; + STATUS Status; + FILE *DBFptr; + DB_DATA_ITEM_HEADER DataItemHeader; + + Status = STATUS_SUCCESS; + DBFptr = NULL; + // + // if (Verbose) { + // fprintf (stdout, "Reading database file %s\n", DBFileName); + // } + // + // Try to open the input file + // + if ((DBFptr = fopen (DBFileName, "rb")) == NULL) { + if (IgnoreIfNotExist) { + return STATUS_SUCCESS; + } + + Error (NULL, 0, 0, DBFileName, "failed to open input database file for reading"); + return STATUS_ERROR; + } + // + // Read and verify the database header + // + if (fread ((void *) &DbHeader, sizeof (STRING_DB_HEADER), 1, DBFptr) != 1) { + Error (NULL, 0, 0, DBFileName, "failed to read header from database file"); + Status = STATUS_ERROR; + goto Finish; + } + + if (DbHeader.Key != STRING_DB_KEY) { + Error (NULL, 0, 0, DBFileName, "invalid header in database file"); + Status = STATUS_ERROR; + goto Finish; + } + + if ((DbHeader.Version & STRING_DB_MAJOR_VERSION_MASK) != (STRING_DB_VERSION & STRING_DB_MAJOR_VERSION_MASK)) { + Error (NULL, 0, 0, DBFileName, "incompatible database file version -- rebuild clean"); + Status = STATUS_ERROR; + goto Finish; + } + // + // Read remaining items + // + while (fread (&DataItemHeader, sizeof (DataItemHeader), 1, DBFptr) == 1) { + switch (DataItemHeader.DataType) { + case DB_DATA_TYPE_STRING_IDENTIFIER: + StringDBReadStringIdentifier (DBFptr); + break; + + case DB_DATA_TYPE_LANGUAGE_DEFINITION: + StringDBReadLanguageDefinition (DBFptr); + break; + + case DB_DATA_TYPE_STRING_DEFINITION: + StringDBReadString (DBFptr); + break; + + default: + Error ( + NULL, + 0, + 0, + "database corrupted", + "invalid data item type 0x%X at offset 0x%X", + (UINT32) DataItemHeader.DataType, + ftell (DBFptr) - sizeof (DataItemHeader) + ); + Status = STATUS_ERROR; + goto Finish; + } + } + +Finish: + if (DBFptr != NULL) { + fclose (DBFptr); + } + + return Status; +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Write everything we know to the output database file. Write: + + Database header + String identifiers[] + StringPacks[] + +Arguments: + + DBFileName - name of the file to write to + Verbose - for debug purposes, print info messages along the way. + +Returns: + + STATUS + +--*/ +STATUS +StringDBWriteDatabase ( + INT8 *DBFileName, + BOOLEAN Verbose + ) +{ + STRING_DB_HEADER DbHeader; + UINT32 Counter; + UINT32 StrLen; + LANGUAGE_LIST *Lang; + STRING_IDENTIFIER *StringIdentifier; + STRING_LIST *StrList; + FILE *DBFptr; + + if (Verbose) { + fprintf (stdout, "Writing database %s\n", DBFileName); + } + + if ((DBFptr = fopen (DBFileName, "wb")) == NULL) { + Error (NULL, 0, 0, DBFileName, "failed to open output database file for writing"); + return STATUS_ERROR; + } + // + // Fill in and write the database header + // + memset (&DbHeader, 0, sizeof (STRING_DB_HEADER)); + DbHeader.HeaderSize = sizeof (STRING_DB_HEADER); + DbHeader.Key = STRING_DB_KEY; + DbHeader.Version = STRING_DB_VERSION; + // + // Count the number of languages we have + // + for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { + DbHeader.NumLanguages++; + } + // + // Count up how many string identifiers we have, and total up the + // size of the names plus the size of the flags field we will + // write out too. + // + DbHeader.NumStringIdenfiers = mDBData.NumStringIdentifiers; + StringIdentifier = mDBData.StringIdentifier; + for (Counter = 0; Counter < mDBData.NumStringIdentifiers; Counter++) { + StrLen = wcslen (StringIdentifier->StringName) + 1; + DbHeader.StringIdentifiersSize += StrLen * sizeof (WCHAR) + sizeof (StringIdentifier->Flags); + StringIdentifier = StringIdentifier->Next; + } + + // + // Write the header + // + fwrite (&DbHeader, sizeof (STRING_DB_HEADER), 1, DBFptr); + if (Verbose) { + fprintf (stdout, " Number of string identifiers 0x%04X\n", DbHeader.NumStringIdenfiers); + fprintf (stdout, " Number of languages %d\n", DbHeader.NumLanguages); + } + // + // Write the string identifiers + // + for (StringIdentifier = mDBData.StringIdentifier; StringIdentifier != NULL; StringIdentifier = StringIdentifier->Next) { + StringDBWriteStringIdentifier ( + DBFptr, + (UINT16) StringIdentifier->Index, + StringIdentifier->Flags, + StringIdentifier->StringName + ); + } + // + // Now write all the strings for each language + // + for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { + StringDBWriteLanguageDefinition (DBFptr, Lang->LanguageName, Lang->PrintableLanguageName); + for (StrList = Lang->String; StrList != NULL; StrList = StrList->Next) { + StringDBWriteString ( + DBFptr, + StrList->Flags, + Lang->LanguageName, + StrList->StringName, + StrList->Scope, + StrList->Str + ); + } + } + + fclose (DBFptr); + return STATUS_SUCCESS; +} + +STATUS +StringDBSetStringReferenced ( + INT8 *StringIdentifierName, + BOOLEAN IgnoreNotFound + ) +{ + STRING_IDENTIFIER *Id; + WCHAR *WName; + STATUS Status; + // + // See if it's already been defined. + // + Status = STATUS_SUCCESS; + WName = (WCHAR *) malloc ((strlen (StringIdentifierName) + 1) * sizeof (WCHAR)); +#ifdef USE_VC8 + swprintf (WName, (strlen (StringIdentifierName) + 1) * sizeof (WCHAR), L"%S", StringIdentifierName); +#else + swprintf (WName, L"%S", StringIdentifierName); +#endif + Id = StringDBFindStringIdentifierByName (WName); + if (Id != NULL) { + Id->Flags |= STRING_FLAGS_REFERENCED; + } else { + if (IgnoreNotFound == 0) { + ParserWarning (0, StringIdentifierName, "string identifier not found in database"); + Status = STATUS_WARNING; + } + } + + free (WName); + return Status; +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Dump the contents of a database to an output unicode file. + +Arguments: + + DBFileName - name of the pre-existing database file to read + OutputFileName - name of the file to dump the database contents to + Verbose - for printing of additional info useful for debugging + +Returns: + + STATUS + +Notes: + + There's some issue with the unicode printing routines. Therefore to + write to the output file properly, open it as binary and use fwrite. + Ideally we could open it with just L"w" and use fwprintf(). + +--*/ +STATUS +StringDBDumpDatabase ( + INT8 *DBFileName, + INT8 *OutputFileName, + BOOLEAN Verbose + ) +{ + LANGUAGE_LIST *Lang; + STRING_IDENTIFIER *StringIdentifier; + STRING_LIST *StrList; + FILE *OutFptr; + WCHAR WChar; + WCHAR *WOutputFileName; + WCHAR CrLf[2]; + WCHAR Line[200]; + WCHAR *Scope; + // + // This function assumes the database has already been read, and + // we're just dumping our internal data structures to a unicode file. + // + if (Verbose) { + fprintf (stdout, "Dumping database file %s\n", DBFileName); + } + + WOutputFileName = AsciiToWchar (OutputFileName); + OutFptr = _wfopen (WOutputFileName, L"wb"); + free (WOutputFileName); + if (OutFptr == NULL) { + Error (NULL, 0, 0, OutputFileName, "failed to open output file for writing"); + return STATUS_ERROR; + } + + WChar = UNICODE_FILE_START; + fwrite (&WChar, sizeof (WCHAR), 1, OutFptr); + CrLf[1] = UNICODE_LF; + CrLf[0] = UNICODE_CR; + // + // The default control character is '/'. Make it '#' by writing + // "/=#" to the output file. + // +#ifdef USE_VC8 + swprintf (Line, wcslen(Line) * sizeof (WCHAR), L"/=#"); +#else + swprintf (Line, L"/=#"); +#endif + fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr); + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + // + // Dump all the string identifiers and their values + // + StringDBAssignStringIndexes (); + for (StringIdentifier = mDBData.StringIdentifier; StringIdentifier != NULL; StringIdentifier = StringIdentifier->Next) { + // + // Write the "#define " string + // + if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) { +#ifdef USE_VC8 + swprintf ( + Line, + wcslen(Line) * sizeof (WCHAR), + L"%s %-60.60s 0x%04X", + DEFINE_STR, + StringIdentifier->StringName, + StringIdentifier->Index + ); +#else + swprintf ( + Line, + L"%s %-60.60s 0x%04X", + DEFINE_STR, + StringIdentifier->StringName, + StringIdentifier->Index + ); +#endif + } else { +#ifdef USE_VC8 + swprintf ( + Line, + wcslen(Line) * sizeof (WCHAR), + L"%s %-60.60s 0x%04X // NOT REFERENCED", + DEFINE_STR, + StringIdentifier->StringName, + StringIdentifier->Index + ); +#else + swprintf ( + Line, + L"%s %-60.60s 0x%04X // NOT REFERENCED", + DEFINE_STR, + StringIdentifier->StringName, + StringIdentifier->Index + ); +#endif + } + + fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr); + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + } + + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + // + // Now write all the strings for each language. + // + WChar = UNICODE_DOUBLE_QUOTE; + Scope = NULL; + for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); +#ifdef USE_VC8 + swprintf (Line, wcslen(Line) * sizeof (WCHAR), L"#langdef %s \"%s\"", Lang->LanguageName, Lang->PrintableLanguageName); +#else + swprintf (Line, L"#langdef %s \"%s\"", Lang->LanguageName, Lang->PrintableLanguageName); +#endif + fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr); + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + // + // Now the strings (in double-quotes) for this language. Write + // #string STR_NAME #language eng "string" + // + for (StrList = Lang->String; StrList != NULL; StrList = StrList->Next) { + // + // Print the internal flags for debug + // +#ifdef USE_VC8 + swprintf (Line, wcslen(Line) * sizeof (WCHAR), L"// flags=0x%02X", (UINT32) StrList->Flags); +#else + swprintf (Line, L"// flags=0x%02X", (UINT32) StrList->Flags); +#endif + fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr); + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + // + // Print the scope if changed + // + if ((Scope == NULL) || (wcscmp (Scope, StrList->Scope) != 0)) { +#ifdef USE_VC8 + swprintf (Line, wcslen(Line) * sizeof (WCHAR), L"#scope %s", StrList->Scope); +#else + swprintf (Line, L"#scope %s", StrList->Scope); +#endif + fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr); + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + Scope = StrList->Scope; + } + +#ifdef USE_VC8 + swprintf ( + Line, + wcslen(Line) * sizeof (WCHAR), + L"#string %-50.50s #language %s \"", + StrList->StringName, + Lang->LanguageName + ); +#else + swprintf ( + Line, + L"#string %-50.50s #language %s \"", + StrList->StringName, + Lang->LanguageName + ); +#endif + fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr); + fwrite (StrList->Str, StrList->Size - sizeof (WCHAR), 1, OutFptr); +#ifdef USE_VC8 + swprintf (Line, wcslen(Line) * sizeof (WCHAR), L"\""); +#else + swprintf (Line, L"\""); +#endif + fwrite (Line, wcslen (Line) * sizeof (WCHAR), 1, OutFptr); + fwrite (&CrLf, sizeof (CrLf), 1, OutFptr); + } + } + + fclose (OutFptr); + return STATUS_SUCCESS; +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Given a primary language, a string identifier number, and a list of + languages, find a secondary string. + +Arguments: + + LanguageName - primary language, like "spa" + StringId - string index value + LanguageList - linked list of "eng", "spa+cat",... + +Returns: + + Pointer to a secondary string if found. NULL otherwise. + +Notes: + + Given: LanguageName "spa" and LanguageList "spa+cat", match the + "spa" and extract the "cat" and see if there is a string defined + for "cat".StringId. + +--*/ +static +STATUS +StringDBWriteStringIdentifier ( + FILE *DBFptr, + UINT16 StringId, + UINT16 Flags, + WCHAR *IdentifierName + ) +{ + DB_DATA_ITEM_HEADER Hdr; + memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER)); + Hdr.DataType = DB_DATA_TYPE_STRING_IDENTIFIER; + if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to write string to output database file", NULL); + return STATUS_ERROR; + } + + if (fwrite (&StringId, sizeof (StringId), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to write StringId to output database", NULL); + return STATUS_ERROR; + } + + if (fwrite (&Flags, sizeof (Flags), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to write StringId flags to output database", NULL); + return STATUS_ERROR; + } + + if (StringDBWriteGenericString (DBFptr, IdentifierName) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} + +static +STATUS +StringDBReadStringIdentifier ( + FILE *DBFptr + ) +{ + WCHAR *IdentifierName; + UINT16 Flags; + UINT16 StringId; + UINT16 Size; + + if (fread (&StringId, sizeof (StringId), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to read StringId from database", NULL); + return STATUS_ERROR; + } + + if (fread (&Flags, sizeof (Flags), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to read StringId flags from database", NULL); + return STATUS_ERROR; + } + + if (StringDBReadGenericString (DBFptr, &Size, &IdentifierName) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + StringDBAddStringIdentifier (IdentifierName, &StringId, Flags); + // + // printf ("STRID: 0x%04X %S\n", (UINT32)StringId, IdentifierName); + // + FREE (IdentifierName); + return STATUS_SUCCESS; +} + +static +STATUS +StringDBWriteString ( + FILE *DBFptr, + UINT16 Flags, + WCHAR *Language, + WCHAR *StringName, + WCHAR *Scope, + WCHAR *Str + ) +{ + DB_DATA_ITEM_HEADER Hdr; + memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER)); + Hdr.DataType = DB_DATA_TYPE_STRING_DEFINITION; + if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to write string header to output database file", NULL); + return STATUS_ERROR; + } + + if (fwrite (&Flags, sizeof (Flags), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to write string flags to output database", NULL); + return STATUS_ERROR; + } + + if (StringDBWriteGenericString (DBFptr, Language) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + if (StringDBWriteGenericString (DBFptr, StringName) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + if (StringDBWriteGenericString (DBFptr, Scope) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + if (StringDBWriteGenericString (DBFptr, Str) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + // + // printf ("DBWriteString: %S.%S.%S\n", Language, StringName, Scope); + // + return STATUS_SUCCESS; +} + +static +STATUS +StringDBReadString ( + FILE *DBFptr + ) +{ + UINT16 Flags; + UINT16 Size; + WCHAR *Language; + WCHAR *StringName; + WCHAR *Scope; + WCHAR *Str; + + if (fread (&Flags, sizeof (Flags), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to read string flags from database", NULL); + return STATUS_ERROR; + } + + if (StringDBReadGenericString (DBFptr, &Size, &Language) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + if (StringDBReadGenericString (DBFptr, &Size, &StringName) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + if (StringDBReadGenericString (DBFptr, &Size, &Scope) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + if (StringDBReadGenericString (DBFptr, &Size, &Str) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + // + // If the first or second string (language name and printable language name), + // then skip them. They're added via language definitions data items in + // the database. + // + if (StringName[0] != L'$') { + StringDBAddString (Language, StringName, Scope, Str, FALSE, Flags); + } + // + // printf ("DBReadString: %S.%S.%S\n", Language, StringName, Scope); + // + FREE (Language); + FREE (StringName); + if (Str != NULL) { + FREE (Str); + } + + if (Scope != NULL) { + FREE (Scope); + } + + return STATUS_SUCCESS; +} + +static +STATUS +StringDBWriteLanguageDefinition ( + FILE *DBFptr, + WCHAR *LanguageName, + WCHAR *PrintableLanguageName + ) +{ + DB_DATA_ITEM_HEADER Hdr; + memset (&Hdr, 0, sizeof (DB_DATA_ITEM_HEADER)); + Hdr.DataType = DB_DATA_TYPE_LANGUAGE_DEFINITION; + if (fwrite (&Hdr, sizeof (DB_DATA_ITEM_HEADER), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to write string to output database file", NULL); + return STATUS_ERROR; + } + + if (StringDBWriteGenericString (DBFptr, LanguageName) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + if (StringDBWriteGenericString (DBFptr, PrintableLanguageName) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} + +static +STATUS +StringDBReadLanguageDefinition ( + FILE *DBFptr + ) +{ + WCHAR *LanguageName; + WCHAR *PrintableLanguageName; + UINT16 Size; + STATUS Status; + + if (StringDBReadGenericString (DBFptr, &Size, &LanguageName) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + + if (StringDBReadGenericString (DBFptr, &Size, &PrintableLanguageName) != STATUS_SUCCESS) { + return STATUS_ERROR; + } + // + // printf("LANG: %S %S\n", LanguageName, PrintableLanguageName); + // + Status = StringDBAddLanguage (LanguageName, PrintableLanguageName); + FREE (LanguageName); + FREE (PrintableLanguageName); + return Status; +} +// +// All unicode strings in the database consist of a UINT16 length +// field, followed by the string itself. This routine reads one +// of those and returns the info. +// +static +STATUS +StringDBReadGenericString ( + FILE *DBFptr, + UINT16 *Size, + WCHAR **Str + ) +{ + UINT16 LSize; + UINT16 Flags; + WCHAR *LStr; + + if (fread (&LSize, sizeof (UINT16), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to read a string length field from the database", NULL); + return STATUS_ERROR; + } + + if (fread (&Flags, sizeof (UINT16), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to read a string flags field from the database", NULL); + return STATUS_ERROR; + } + + LStr = MALLOC (LSize); + if (LStr == NULL) { + Error (__FILE__, __LINE__, 0, "memory allocation failed reading the database", NULL); + return STATUS_ERROR; + } + + if (fread (LStr, sizeof (WCHAR), (UINT32) LSize / sizeof (WCHAR), DBFptr) != (UINT32) LSize / sizeof (WCHAR)) { + Error (NULL, 0, 0, "failed to read string from database", NULL); + Error (NULL, 0, 0, "database read failure", "offset 0x%X", ftell (DBFptr)); + free (LStr); + return STATUS_ERROR; + } + // + // printf ("DBR: %S\n", LStr); + // + // If the flags field indicated we were asked to write a NULL string, then + // return them a NULL pointer. + // + if (Flags & STRING_FLAGS_UNDEFINED) { + *Size = 0; + *Str = NULL; + } else { + *Size = LSize; + *Str = LStr; + } + + return STATUS_SUCCESS; +} + +static +STATUS +StringDBWriteGenericString ( + FILE *DBFptr, + WCHAR *Str + ) +{ + UINT16 Size; + UINT16 Flags; + WCHAR ZeroString[1]; + // + // Strings in the database consist of a size UINT16 followed + // by the string itself. + // + if (Str == NULL) { + ZeroString[0] = 0; + Str = ZeroString; + Size = sizeof (ZeroString); + Flags = STRING_FLAGS_UNDEFINED; + } else { + Flags = 0; + Size = (UINT16) ((wcslen (Str) + 1) * sizeof (WCHAR)); + } + + if (fwrite (&Size, sizeof (UINT16), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to write string size to database", NULL); + return STATUS_ERROR; + } + + if (fwrite (&Flags, sizeof (UINT16), 1, DBFptr) != 1) { + Error (NULL, 0, 0, "failed to write string flags to database", NULL); + return STATUS_ERROR; + } + + if (fwrite (Str, sizeof (WCHAR), Size / sizeof (WCHAR), DBFptr) != Size / sizeof (WCHAR)) { + Error (NULL, 0, 0, "failed to write string to database", NULL); + return STATUS_ERROR; + } + + return STATUS_SUCCESS; +} + +static +STRING_LIST * +StringDBFindString ( + WCHAR *LanguageName, + WCHAR *StringName, + WCHAR *Scope, + WCHAR_STRING_LIST *LanguagesOfInterest, + WCHAR_MATCHING_STRING_LIST *IndirectionList + ) +{ + LANGUAGE_LIST *Lang; + STRING_LIST *CurrString; + WCHAR_MATCHING_STRING_LIST *IndListPtr; + WCHAR TempLangName[LANGUAGE_IDENTIFIER_NAME_LEN + 1]; + WCHAR *WCharPtr; + + // + // If we were given an indirection list, then see if one was specified for this + // string identifier. That is to say, if the indirection says "STR_ID_MY_FAVORITE MyScope", + // then if this string name matches one in the list, then do a lookup with the + // specified scope and return that value. + // + if (IndirectionList != NULL) { + for (IndListPtr = IndirectionList; IndListPtr != NULL; IndListPtr = IndListPtr->Next) { + if (wcscmp (StringName, IndListPtr->Str1) == 0) { + CurrString = StringDBFindString (LanguageName, StringName, IndListPtr->Str2, LanguagesOfInterest, NULL); + if (CurrString != NULL) { + return CurrString; + } + } + } + } + // + // First look for exact match language.stringname + // + for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { + if (wcscmp (LanguageName, Lang->LanguageName) == 0) { + // + // Found language match. Try to find string name match + // + for (CurrString = Lang->String; CurrString != NULL; CurrString = CurrString->Next) { + if (wcscmp (StringName, CurrString->StringName) == 0) { + // + // Found a string name match. See if we're supposed to find + // a scope match. + // + if (Scope != NULL) { + if (wcscmp (CurrString->Scope, Scope) == 0) { + return CurrString; + } + } else { + return CurrString; + } + } + } + } + } + // + // If we got here, then we didn't find a match. Look for secondary string + // matches. That is to say, if we're processing "spa", and they requested + // "spa+cat", then recursively call with "cat" + // + while (LanguagesOfInterest != NULL) { + // + // If this is the language we're looking for, then process the + // languages of interest list for it. + // + if (wcsncmp (LanguageName, LanguagesOfInterest->Str, LANGUAGE_IDENTIFIER_NAME_LEN) == 0) { + WCharPtr = LanguagesOfInterest->Str + LANGUAGE_IDENTIFIER_NAME_LEN; + while (*WCharPtr) { + // + // Double-check the length, though it should have been checked on the + // command line. + // + if (wcslen (WCharPtr) < LANGUAGE_IDENTIFIER_NAME_LEN) { + Error (NULL, 0, 0, "malformed alternate language list", "%S", LanguagesOfInterest->Str); + return NULL; + } + + wcsncpy (TempLangName, WCharPtr, LANGUAGE_IDENTIFIER_NAME_LEN); + TempLangName[LANGUAGE_IDENTIFIER_NAME_LEN] = 0; + CurrString = StringDBFindString (TempLangName, StringName, NULL, NULL, IndirectionList); + if (CurrString != NULL) { + return CurrString; + } + + WCharPtr += LANGUAGE_IDENTIFIER_NAME_LEN; + } + } + + LanguagesOfInterest = LanguagesOfInterest->Next; + } + + return NULL; +} + +STATUS +StringDBSetScope ( + WCHAR *Scope + ) +{ + // + // Free up existing scope memory. + // + if (mDBData.CurrentScope != NULL) { + FREE (mDBData.CurrentScope); + } + + mDBData.CurrentScope = DuplicateString (Scope); + return STATUS_SUCCESS; +} +// +// We typically don't assign index values to string identifiers +// until we're ready to write out files. To reduce the size of +// the output file, re-order the string identifiers to move any +// unreferenced ones to the end. Then we'll walk the list +// again to assign string indexes, keeping track of the last +// one referenced. +// +static +void +StringDBAssignStringIndexes ( + VOID + ) +{ + STRING_IDENTIFIER *StrId; + STRING_IDENTIFIER *FirstUsed; + STRING_IDENTIFIER *LastUsed; + STRING_IDENTIFIER *FirstUnused; + STRING_IDENTIFIER *LastUnused; + UINT32 Index; + UINT32 MaxReferenced; + + // + // Create two lists -- used and unused. Then put them together with + // the unused ones on the end. + // + FirstUsed = NULL; + LastUsed = NULL; + FirstUnused = NULL; + LastUnused = NULL; + StrId = mDBData.StringIdentifier; + while (StrId != NULL) { + if ((StrId->Flags & STRING_FLAGS_REFERENCED) == 0) { + // + // Put it on the unused list + // + if (FirstUnused == NULL) { + FirstUnused = StrId; + } else { + LastUnused->Next = StrId; + } + + LastUnused = StrId; + StrId = StrId->Next; + LastUnused->Next = NULL; + } else { + // + // Put it on the used list + // + if (FirstUsed == NULL) { + FirstUsed = StrId; + } else { + LastUsed->Next = StrId; + } + + LastUsed = StrId; + StrId = StrId->Next; + LastUsed->Next = NULL; + } + } + // + // Join the lists + // + if (FirstUsed != NULL) { + mDBData.StringIdentifier = FirstUsed; + LastUsed->Next = FirstUnused; + } else { + mDBData.StringIdentifier = FirstUnused; + } + + MaxReferenced = 0; + Index = 0; + for (StrId = mDBData.StringIdentifier; StrId != NULL; StrId = StrId->Next) { + StrId->Index = Index; + Index++; + if (StrId->Flags & STRING_FLAGS_REFERENCED) { + mDBData.NumStringIdentifiersReferenced = Index; + } + } + + mDBData.NumStringIdentifiers = Index; +} + +static +WCHAR * +DuplicateString ( + WCHAR *Str + ) +{ + WCHAR *NewStr; + if (Str == NULL) { + return NULL; + } + + NewStr = MALLOC ((wcslen (Str) + 1) * sizeof (WCHAR)); + if (NewStr == NULL) { + Error (NULL, 0, 0, "memory allocation failure", NULL); + return NULL; + } + + wcscpy (NewStr, Str); + return NewStr; +} + +static +WCHAR * +AsciiToWchar ( + INT8 *Str + ) +{ + UINT32 Len; + WCHAR *NewStr; + WCHAR *Ptr; + + Len = strlen (Str) + 1; + NewStr = (WCHAR *) malloc (Len * sizeof (WCHAR)); + for (Ptr = NewStr; *Str != 0; Str++, Ptr++) { + *Ptr = (UINT16) (UINT8) *Str; + } + + *Ptr = 0; + return NewStr; +} + +/*****************************************************************************/ + +/*++ + +Routine Description: + + Create an HII export string pack for the strings in our database. + +Arguments: + + FileName - name of the output file to write + +Returns: + + STATUS + + +--*/ +STATUS +StringDBCreateHiiExportPack ( + INT8 *FileName + ) +{ + FILE *Fptr; + LANGUAGE_LIST *Lang; + STRING_LIST *CurrString; + STRING_LIST EmptyString; + UINT32 Offset; + UINT32 StringIndex; + UINT32 TempIndex; + EFI_HII_STRING_PACK_HEADER StringPack; + UINT32 Len; + WCHAR ZeroString[1]; + WCHAR *TempStringPtr; + WCHAR *LangName; + STRING_IDENTIFIER *StringIdentifier; + + if ((Fptr = fopen (FileName, "wb")) == NULL) { + Error (NULL, 0, 0, FileName, "failed to open output HII export file"); + return STATUS_ERROR; + } + // + // Assign index values to the string identifiers + // + StringDBAssignStringIndexes (); + // + // If a given string is not defined, then we'll use this one. + // + memset (&EmptyString, 0, sizeof (EmptyString)); + EmptyString.Size = sizeof (ZeroString); + EmptyString.Str = ZeroString; + // + // Process each language, then each string for each langage + // + ZeroString[0] = 0; + for (Lang = mDBData.LanguageList; Lang != NULL; Lang = Lang->Next) { + // + // Process each string for this language. We have to make 3 passes on the strings: + // Pass1: computes sizes and fill in the string pack header + // Pass2: write the array of offsets + // Pass3: write the strings + // + // + // PASS 1: Fill in and print the HII string pack header + // + // Compute the size for this language package and write + // the header out. Each string package contains: + // Header + // Offset[] -- an array of offsets to strings, of type RELOFST each + // String[] -- the actual strings themselves + // + memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK_HEADER)); + StringPack.Header.Type = EFI_HII_STRING; + StringPack.NumStringPointers = (UINT16) mDBData.NumStringIdentifiersReferenced; + LangName = Lang->LanguageName; + // + // First string is the language name. If we're printing all languages, then + // it's just the "spa". If we were given a list of languages to print, then it's + // the "spacat" string. Compute its offset and fill in + // the info in the header. Since we know the language name string's length, + // and the printable language name follows it, use that info to fill in the + // entry for the printable language name as well. + // + StringPack.LanguageNameString = (STRING_OFFSET) (sizeof (EFI_HII_STRING_PACK_HEADER) + (mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET))); + StringPack.PrintableLanguageName = (STRING_OFFSET) (StringPack.LanguageNameString + (wcslen (LangName) + 1) * sizeof (WCHAR)); + // + // Add up the size of all strings so we can fill in our header. + // + Len = 0; + for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { + // + // For the first string (language name), we print out the "spacat" if they + // requested it. We set LangName to point to the proper language name string above. + // + if (StringIndex == STRING_ID_LANGUAGE_NAME) { + Len += (wcslen (LangName) + 1) * sizeof (WCHAR); + } else { + // + // Find a string with this language.stringname + // + StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); + if (StringIdentifier == NULL) { + Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); + return STATUS_ERROR; + } + // + // Find a matching string if this string identifier was referenced + // + EmptyString.Flags = STRING_FLAGS_UNDEFINED; + CurrString = NULL; + if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) { + CurrString = StringDBFindString ( + Lang->LanguageName, + StringIdentifier->StringName, + NULL, + NULL, // LanguagesOfInterest, + NULL + ); + // + // IndirectionList); + // + if (NULL == CurrString) { + // + // If string for Lang->LanguageName is not found, try to get an English version + // + CurrString = StringDBFindString ( + L"eng", + StringIdentifier->StringName, + NULL, + NULL, // LanguagesOfInterest, + NULL + ); + // + // IndirectionList); + // + } + } + + if (CurrString == NULL) { + CurrString = &EmptyString; + EmptyString.Flags |= StringIdentifier->Flags; + } + + Len += CurrString->Size; + } + } + StringPack.Header.Length = sizeof (EFI_HII_STRING_PACK_HEADER) + + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET) + + Len; + // + // Write out the string pack header + // + fwrite ((void *) &StringPack, sizeof (StringPack), 1, Fptr); + // + // PASS2 : write the offsets + // + // Traverse the list of strings again and write the array of offsets. The + // offset to the first string is the size of the string pack header + // plus the size of the offsets array. The other strings follow it. + // + StringIndex = 0; + Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET); + for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { + // + // Write the offset + // + fwrite (&Offset, sizeof (STRING_OFFSET), 1, Fptr); + // + // Find the string name + // + StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); + if (StringIdentifier == NULL) { + Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); + return STATUS_ERROR; + } + // + // For the first string (language name), we print out the "spacat" if they + // requested it. We set LangName to point to the proper language name string above. + // + if (StringIndex == STRING_ID_LANGUAGE_NAME) { + Offset += (wcslen (LangName) + 1) * sizeof (WCHAR); + CurrString = StringDBFindString ( + Lang->LanguageName, + StringIdentifier->StringName, + NULL, // scope + NULL, + NULL + ); + } else { + // + // Find a matching string + // + CurrString = StringDBFindString ( + Lang->LanguageName, + StringIdentifier->StringName, + NULL, // scope + NULL, // LanguagesOfInterest, + NULL + ); + // + // IndirectionList); + // + if (NULL == CurrString) { + CurrString = StringDBFindString ( + L"eng", + StringIdentifier->StringName, + NULL, // scope + NULL, // LanguagesOfInterest, + NULL + ); + // + // IndirectionList); + // + } + + EmptyString.LanguageName = Lang->LanguageName; + if (CurrString == NULL) { + CurrString = &EmptyString; + EmptyString.Flags = STRING_FLAGS_UNDEFINED; + } else if ((StringIdentifier->Flags & STRING_FLAGS_REFERENCED) == 0) { + CurrString = &EmptyString; + EmptyString.Flags = 0; + } + + Offset += CurrString->Size; + } + } + + // + // PASS 3: write the strings themselves. + // + Offset = sizeof (StringPack) + mDBData.NumStringIdentifiersReferenced * sizeof (STRING_OFFSET); + for (StringIndex = 0; StringIndex < mDBData.NumStringIdentifiersReferenced; StringIndex++) { + StringIdentifier = StringDBFindStringIdentifierByIndex (StringIndex); + if (StringIdentifier == NULL) { + Error (NULL, 0, 0, "internal error", "invalid string index 0x%X", StringIndex); + return STATUS_ERROR; + } + // + // For the first string (language name), we print out the "spacat" if they + // requested it. We set LangName to point to the proper language name string above. + // + if (StringIndex == STRING_ID_LANGUAGE_NAME) { + TempStringPtr = LangName; + } else { + // + // Find a matching string if this string identifier was referenced + // + CurrString = NULL; + if (StringIdentifier->Flags & STRING_FLAGS_REFERENCED) { + CurrString = StringDBFindString ( + Lang->LanguageName, + StringIdentifier->StringName, + NULL, // scope + NULL, // LanguagesOfInterest, + NULL + ); + // + // IndirectionList); + // + if (NULL == CurrString) { + CurrString = StringDBFindString ( + L"eng", + StringIdentifier->StringName, + NULL, // scope + NULL, // LanguagesOfInterest, + NULL + ); + // + // IndirectionList); + // + } + } + + if (CurrString == NULL) { + CurrString = &EmptyString; + } + + TempStringPtr = CurrString->Str; + } + + for (TempIndex = 0; TempStringPtr[TempIndex] != 0; TempIndex++) { + fwrite (&TempStringPtr[TempIndex], sizeof (CHAR16), 1, Fptr); + Offset += 2; + } + // + // Print NULL WCHAR at the end of this string. + // + TempIndex = 0; + fwrite (&TempIndex, sizeof (CHAR16), 1, Fptr); + Offset += 2; + } + // + // Sanity check the offset. Make sure our running offset is what we put in the + // string pack header. + // + if (StringPack.Header.Length != Offset) { + Error ( + __FILE__, + __LINE__, + 0, + "application error", + "stringpack size 0x%X does not match final size 0x%X", + StringPack.Header.Length, + Offset + ); + } + } + // + // Print terminator string pack, closing brace and close the file. + // The size of 0 triggers to the consumer that this is the end. + // + memset ((char *) &StringPack, 0, sizeof (EFI_HII_STRING_PACK_HEADER)); + StringPack.Header.Type = EFI_HII_STRING; + fwrite ((void *) &StringPack, sizeof (StringPack), 1, Fptr); + fclose (Fptr); + return STATUS_SUCCESS; +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StringDB.h b/EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StringDB.h new file mode 100644 index 0000000000..4dc05a3642 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StringDB.h @@ -0,0 +1,136 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + StringDB.h + +Abstract: + + Common defines and prototypes for string database management + +--*/ + +#ifndef _STRING_DB_H_ +#define _STRING_DB_H_ + +#define LANGUAGE_NAME_STRING_NAME L"$LANGUAGE_NAME" +#define PRINTABLE_LANGUAGE_NAME_STRING_NAME L"$PRINTABLE_LANGUAGE_NAME" + +void +StringDBConstructor ( + void + ) +; +void +StringDBDestructor ( + void + ) +; + +STATUS +StringDBAddString ( + WCHAR *LanguageName, + WCHAR *StringIdentifier, + WCHAR *Scope, + WCHAR *String, + BOOLEAN Format, + UINT16 Flags + ) +; + +STATUS +StringDBSetScope ( + WCHAR *Scope + ) +; + +#define STRING_FLAGS_REFERENCED 0x0001 // if referenced somewhere +#define STRING_FLAGS_UNDEFINED 0x0002 // if we added it for padding purposes +#define STRING_FLAGS_INDEX_ASSIGNED 0x0004 // so don't change the index value +#define STRING_ID_INVALID 0xFFFF +#define STRING_ID_LANGUAGE_NAME 0x0000 +#define STRING_ID_PRINTABLE_LANGUAGE_NAME 0x0001 + +STATUS +StringDBAddStringIdentifier ( + WCHAR *StringIdentifier, + UINT16 *NewId, + UINT16 Flags + ) +; + +STATUS +StringDBReadDatabase ( + INT8 *DBFileName, + BOOLEAN IgnoreIfNotExist, + BOOLEAN Verbose + ) +; + +STATUS +StringDBWriteDatabase ( + INT8 *DBFileName, + BOOLEAN Verbose + ) +; + +STATUS +StringDBDumpDatabase ( + INT8 *DBFileName, + INT8 *OutputFileName, + BOOLEAN Verbose + ) +; + +STATUS +StringDBAddLanguage ( + WCHAR *LanguageName, + WCHAR *PrintableLanguageName + ) +; + +STATUS +StringDBDumpCStrings ( + INT8 *FileName, + INT8 *BaseName, + WCHAR_STRING_LIST *LanguagesOfInterest, + WCHAR_MATCHING_STRING_LIST *IndirectionList + ) +; + +STATUS +StringDBDumpStringDefines ( + INT8 *FileName, + INT8 *BaseName + ) +; + +STATUS +StringDBSetCurrentLanguage ( + WCHAR *LanguageName + ) +; + +STATUS +StringDBSetStringReferenced ( + INT8 *StringIdentifierName, + BOOLEAN IgnoreNotFound + ) +; + +void +StringDBFormatString ( + WCHAR *String + ) +; + +#endif // #ifndef _STRING_DB_H_ diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/VcCheck/VcCheck.c b/EdkCompatibilityPkg/Sample/Tools/Source/VcCheck/VcCheck.c new file mode 100644 index 0000000000..32f1c33b8c --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/VcCheck/VcCheck.c @@ -0,0 +1,121 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + VcCheck.c + +Abstract: + + We have found problems with the Visual C++ SP4 and the /O1 flag. + If this tests ask a question you have the wrong version of Visual C++ + on your system + + This test assumes the tools are being compiled with the same complier + as the Tiano code. + + Please see $(EFI_SOURCE)\EFI2.0 Developer's Manual.doc to get the + correct version of Visual C++ + +--*/ + +#include + +_int16 gGloba16; + +int +CheckLostCode ( + int Value + ) +/*++ + +Routine Description: + This routine is used to test for compiler isseus with /O1. + If the /O1 compiler option, and C2.dll is got from Visual C++ SP5 + (version: 6.00.8168.0), the assember codes after default branch will be + losted. (Execute "cl Visual Ccheck.c /O1 /FAsc" to get detail information) + +Arguments: + Value - Test case + +Returns: + Test to see if comiler error is present. + +--*/ +{ + switch (Value) { + case 0: + break; + + default: + _asm + { + mov bx, 1 + mov gGloba16, bx + } + + return 1; + } + + _asm + { + mov bx, 0 + mov gGloba16, bx + } + + return 0; +} + +int +main ( + void + ) +/*++ + +Routine Description: + This utility is checking for a known Visual C++ compiler issues. To remove this + question from the build follow the steps in the developers manual. + +Arguments: + NONE + +Returns: + 0 - Compiler version is O.K. + 1 - Compiler version is Bad + +--*/ +{ + int result; + char select; + + gGloba16 = 0xFF; + result = 0; + + CheckLostCode (0); + result += (gGloba16 == 0) ? 0 : 1; + + CheckLostCode (1); + result += (gGloba16 == 1) ? 0 : 1; + + if (result != 0) { + printf ("Warning: C2.dll is incorrect.\n Please see $(EFI_SOURCE)\\EFI2.0 Developer's Manual.doc for corrective action.\n"); + printf ("Would you want to continue?(Y/N)"); + + scanf ("%c", &select); + if ((select == 'Y') || (select == 'y')) { + return 0; + } else { + return 1; + } + } + + return 0; +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/VcCheck/makefile b/EdkCompatibilityPkg/Sample/Tools/Source/VcCheck/makefile new file mode 100644 index 0000000000..d0a680c978 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/VcCheck/makefile @@ -0,0 +1,92 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: makefile +# +# Abstract: +# +# This file is used to build the EFI utility. +# +#--*/ + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +# +# Define some macros we use here. Should get rid of them someday and +# get rid of the extra level of indirection. +# +COMMON_SOURCE = $(EDK_TOOLS_COMMON) + +# +# Common information +# + +INC=$(INC) + +# +# Target specific information +# + +TARGET_NAME=VcCheck + +TARGET_SOURCE_DIR = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) + +TARGET_EXE = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).exe + +TARGET_EXE_SOURCE = "$(TARGET_SOURCE_DIR)\VcCheck.c" +TARGET_EXE_INCLUDE = +OBJECTS = $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + +# +# Replace /Od with "" to fix the Command line warning D4025 +# +C_FLAGS = $(C_FLAGS:/Od=) /O1 + +# +# Build targets +# + +all: $(TARGET_EXE) + +# +# Build EXE +# + +$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj: $(TARGET_EXE_SOURCE) $(TARGET_EXE_INCLUDE) + $(CC) $(C_FLAGS) $(INC) $(TARGET_EXE_SOURCE) /Fo$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).obj + +# +# Add Binary Build description for this tools. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE) : $(OBJECTS) + $(LINK) $(MSVS_LINK_LIBPATHS) $(L_FLAGS) $(LIBS) /out:$(TARGET_EXE) $(OBJECTS) + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + @if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* del $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).* > NUL diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/EfiVfr.h b/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/EfiVfr.h new file mode 100644 index 0000000000..d6862119db --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/EfiVfr.h @@ -0,0 +1,178 @@ +/*++ + +Copyright (c) 2004 - 2005, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + EfiVfr.h + +Abstract: + + Defines and prototypes for the EFI internal forms representation + setup protocol and drivers + +--*/ + +#ifndef _EFI_VFR_H_ +#define _EFI_VFR_H_ + +#include "Tiano.h" +#include "EfiInternalFormRepresentation.h" +#include + +// +// This number should be incremented with each change to the VFR compiler. +// We write the version to the output list file for debug purposes. +// +#define VFR_COMPILER_VERSION "1.88" + +// +// Maximum file path for filenames +// +#define MAX_PATH 255 +#define MAX_QUEUE_COUNT 255 +#define MAX_LINE_LEN 1024 +#define PROGRAM_NAME "VfrCompile" + +// +// We parse C-style structure definitions which can then be referenced +// in VFR statements. +// We need to define an internal structure that can be used to +// track the fields in a structure definition, and another structure +// to keep track of the structure name and subfields. +// +typedef struct _STRUCT_FIELD_DEFINITION { + struct _STRUCT_FIELD_DEFINITION *Next; + int DataSize; + int Offset; // from the start of the structure + int ArrayLength; + char IsArray; + char *Name; +} STRUCT_FIELD_DEFINITION; + +typedef struct _STRUCT_DEFINITION { + struct _STRUCT_DEFINITION *Next; + int Size; + int LineNum; // line number where the structure was defined + int IsNonNV; // if this is the non-NV data structure definition + int Referenced; // if it's referenced anywhere in the VFR + int VarStoreIdValid; // found a 'varstore' statement for it in the VFR + unsigned short VarStoreId; // key from a varstore IFR statement + int VarStoreLineNum; // line number where VARSTORE was defined + char *Name; + STRUCT_FIELD_DEFINITION *Field; + STRUCT_FIELD_DEFINITION *LastField; +} STRUCT_DEFINITION; + +// +// For the IdEqValList variable list of UINT16's, keep track of them using +// a linked list until we know how many there are. +// We also use a linked list of these to keep track of labels used in +// the VFR script so we can catch duplicates. +// We'll also use it to keep track of defined varstore id's so we can +// detect duplicate definitions. +// +typedef struct _UINT16_LIST { + struct _UINT16_LIST *Next; + UINT16 Value; + UINT32 LineNum; +} UINT16_LIST; + +typedef struct _GOTO_REFERENCE { + struct _GOTO_REFERENCE *Next; + UINT32 RefLineNum; // line number of source file where referenced + UINT16 Value; +} GOTO_REFERENCE; + +typedef struct _FORM_ID_VALUE { + struct _FORM_ID_VALUE *Next; + UINT32 LineNum; + UINT16 Value; +} FORM_ID_VALUE; + +// +// We keep track in the parser of all "#line 4 "x.y"" strings so we +// can cross-reference the line numbers in the preprocessor output .i file +// to the original input files. +// +typedef struct _PARSER_LINE_DEFINITION { + struct _PARSER_LINE_DEFINITION *Next; + UINT32 HashLineNum; // from the #line stmt + UINT32 TokenLineNum; // line number in the .i file + INT8 *FileName; // from the #line stmt +} PARSER_LINE_DEFINITION; + +extern PARSER_LINE_DEFINITION *gLineDefinition; +extern PARSER_LINE_DEFINITION *gLastLineDefinition; + +extern +char * +ConvertLineNumber ( + UINT32 *LineNum + ) +/*++ + +Routine Description: + Given the line number in the preprocessor-output file, use the line number + information we've saved to determine the source file name and line number + where the code originally came from. This is required for error reporting. + +Arguments: + LineNum - the line number in the preprocessor-output file. + +Returns: + Returns a pointer to the source file name. Also returns the line number + in the provided LineNum argument + +--*/ +; + +typedef struct _IFR_BYTE { + struct _IFR_BYTE *Next; + UINT32 LineNum; + UINT8 OpcodeByte; + UINT8 KeyByte; +} IFR_BYTE; + +typedef struct { + INT8 VfrFileName[MAX_PATH]; + INT8 VfrListFileName[MAX_PATH]; + INT8 CreateListFile; + INT8 CreateIfrBinFile; + INT8 IfrOutputFileName[MAX_PATH]; + INT8 OutputDirectory[MAX_PATH]; + INT8 PreprocessorOutputFileName[MAX_PATH]; + INT8 VfrBaseFileName[MAX_PATH]; // name of input VFR file with no path or extension + INT8 *IncludePaths; + INT8 *CPreprocessorOptions; +} OPTIONS; + +extern OPTIONS gOptions; + +VOID +WriteStandardFileHeader ( + FILE *OutFptr + ) +/*++ + +Routine Description: + This function is invoked to emit a standard header to an + output text file. + +Arguments: + OutFptr - file to write the header to + +Returns: + None + +--*/ +; + +#endif // #ifndef _EFI_VFR_H_ diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrCompile.g b/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrCompile.g new file mode 100644 index 0000000000..cba6fa6a6a --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrCompile.g @@ -0,0 +1,3463 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + VfrCompile.g + +Abstract: + + PCCTS parser and lexer definitions for the EFI VFR forms compiler + +--*/ + +#header<< + +#include "Tiano.h" +#include "EfiUtilityMsgs.h" +#include "EfiVfr.h" +#include "VfrServices.h" +#include EFI_PROTOCOL_DEFINITION (Hii) + +#include +#include +#include // for spawn functions + +>> + +<< + +// +// Base info for DLG-generated scanner +// +#include "DLexerBase.h" + +// +// Include the scanner file generated by DLG +// +#include "DLGLexer.h" + +class DLGLexerVfr : public DLGLexer +{ +public: + DLGLexerVfr (DLGFileInput *F) : DLGLexer (F) {}; + INT32 errstd (char *Text) + { + printf ("unrecognized input '%s'\n", Text); + } +}; + +// +// Base token definitions for ANTLR +// +#include "AToken.h" + +// +// 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.exe " +#define PREPROCESSOR_OPTIONS "/nologo /E /TC /DVFRCOMPILE " + +typedef ANTLRCommonToken ANTLRToken; + +// +// Specify the filename extensions for the files we generate. +// +#define VFR_BINARY_FILENAME_EXTENSION ".c" +#define VFR_LIST_FILENAME_EXTENSION ".lst" +#define VFR_PREPROCESS_FILENAME_EXTENSION ".i" + +static +VOID +Usage (); + +static +STATUS +ProcessArgs ( + int Argc, + char *Argv[] + ); + +static +VOID +Cleanup (); + +// +// Globals +// +OPTIONS gOptions; + +int +main ( + int argc, + char **argv + ) +/*++ + +Routine Description: + Application entry point function. Parse command-line arguments, + invoke the parser, clean up, and return. + +Arguments: + argc - standard argc passed to main() per C conventions + argv - standard argv passed to main() per C conventions + +Returns: + STATUS_SUCCESS - program executed with no errors or warnings + STATUS_WARNING - program executed with warnings + STATUS_ERROR - non-recoverable errors encountered while processing + +--*/ +{ + FILE *VfrFptr; + char *Cmd; + char *Cptr; + int Len; + STATUS Status; + + // + // Set our program name for the error printing routines. + // Then set printing limits. + // + SetUtilityName (PROGRAM_NAME); + SetPrintLimits (20, 20, 30); + // + // Process the command-line arguments + // + if (ProcessArgs (argc, argv) != STATUS_SUCCESS) { + Usage (); + Cleanup(); + return STATUS_ERROR; + } + VfrFptr = NULL; + // + // Verify the VFR script file exists + // + if ((VfrFptr = fopen (gOptions.VfrFileName, "r")) == NULL) { + Error (PROGRAM_NAME, 0, 0, gOptions.VfrFileName, "could not open input VFR file"); + Cleanup(); + return STATUS_ERROR; + } + // + // Now close the file and make a system call to run the preprocessor + // on it. + // + fclose (VfrFptr); + Len = strlen (PREPROCESSOR_OPTIONS) + strlen (gOptions.VfrFileName) + 10 + + strlen (PREPROCESSOR_COMMAND) + strlen (gOptions.PreprocessorOutputFileName); + if (gOptions.CPreprocessorOptions != NULL) { + Len += strlen (gOptions.CPreprocessorOptions) + 1; + } + if (gOptions.IncludePaths != NULL) { + Len += strlen (gOptions.IncludePaths) + 1; + } + Cmd = (char *)malloc (Len); + if (Cmd == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "could not allocate memory"); + Cleanup(); + return STATUS_ERROR; + } + strcpy (Cmd, PREPROCESSOR_COMMAND PREPROCESSOR_OPTIONS); + if (gOptions.IncludePaths != NULL) { + strcat (Cmd, gOptions.IncludePaths); + strcat (Cmd, " "); + } + if (gOptions.CPreprocessorOptions != NULL) { + strcat (Cmd, gOptions.CPreprocessorOptions); + strcat (Cmd, " "); + } + strcat (Cmd, gOptions.VfrFileName); + strcat (Cmd, " > "); + strcat (Cmd, gOptions.PreprocessorOutputFileName); + Status = system (Cmd); + if (Status != 0) { + Error (PROGRAM_NAME, 0, 0, gOptions.VfrFileName, "failed to spawn C preprocessor on VFR file"); + printf ("Command: '%s %s'\n", PREPROCESSOR_COMMAND, Cmd); + Cleanup(); + return STATUS_ERROR; + } + free (Cmd); + // + // Open the preprocessor output file + // + if ((VfrFptr = fopen (gOptions.PreprocessorOutputFileName, "r")) == NULL) { + Error (PROGRAM_NAME, 0, 0, "failed to open input VFR preprocessor output file", + gOptions.PreprocessorOutputFileName); + Cleanup(); + return STATUS_ERROR; + } + // + // Define input VFR file + // + DLGFileInput InputFile (VfrFptr); + // + // Define an instance of the scanner + // + DLGLexerVfr Scanner (&InputFile); + // + // Define token buffer between scanner and parser + // + ANTLRTokenBuffer Pipe (&Scanner); + // + // Create a token to use as a model + // + ANTLRToken Tok; + // + // Tell the scanner what type the token is + // + Scanner.setToken (&Tok); + // + // Create an instance of our parser + // + EfiVfrParser Parser (&Pipe); + // + // Initialize the parser + // + Parser.init (); + Status = GetUtilityStatus (); + if (Status != STATUS_SUCCESS) { + Cleanup(); + return Status; + } + // + // Start the first rule + // + Parser.program (); + // + // Close the input script file + // + fclose (VfrFptr); + Parser.WriteIfrBytes (); + // + // Call cleanup, which does some extra checking of the script + // + Parser.Cleanup (); + Cleanup(); + // + // If we had an error somewhere, delete our output files so that + // a subsequent build will rebuild them. + // + Status = GetUtilityStatus (); + if (Status == STATUS_ERROR) { + remove (gOptions.IfrOutputFileName); + } + return Status; +} +static +VOID +Cleanup () +/*++ + +Routine Description: + Free up memory allocated during parsing. + +Arguments: + None + +Returns: + None + +--*/ +{ + // + // Free up our string we allocated to track the include paths + // + if (gOptions.IncludePaths != NULL) { + free (gOptions.IncludePaths); + gOptions.IncludePaths = NULL; + } + // + // Free up our string we allocated to track preprocessor options + // + if (gOptions.CPreprocessorOptions != NULL) { + free (gOptions.CPreprocessorOptions); + gOptions.CPreprocessorOptions = NULL; + } +} + +static +STATUS +ProcessArgs ( + int Argc, + char *Argv[] + ) +/*++ + +Routine Description: + Process the command-line arguments. + +Arguments: + Argc - standard argc passed to main() + Argv - standard argv passed to main() + +Returns: + STATUS_SUCCESS - program should continue (all args ok) + +--*/ +{ + char *IncludePaths; + char *CPreprocessorOptions; + int Len; + char CopyStr[MAX_PATH]; + char *Cptr; + + // + // Put options in known state. + // + memset ((char *)&gOptions, 0, sizeof (OPTIONS)); + // + // Go through all the arguments that start with '-' + // + Argc--; + Argv++; + while ((Argc > 0) && (Argv[0][0] == '-')) { + // + // -? or -h help option -- return an error for printing usage + // + if ((_stricmp (Argv[0], "-?") == 0) || (_stricmp (Argv[0], "-h") == 0)) { + return STATUS_ERROR; + break; + // + // -l to create a listing output file + // + } else if (_stricmp (Argv[0], "-l") == 0) { + gOptions.CreateListFile = 1; + // + // -I include_path option for finding include files. We'll pass this + // to the preprocessor. Turn them all into a single include string. + // + } else if (_stricmp (Argv[0], "-i") == 0) { + if ((Argc < 2) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing path argument"); + return STATUS_ERROR; + } + Argc--; + Argv++; + Len = strlen (" -I "); + Len += strlen (Argv[0]) + 2; + if (gOptions.IncludePaths != NULL) { + Len += strlen (gOptions.IncludePaths); + } + IncludePaths = (INT8 *)malloc (Len); + if (IncludePaths == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + IncludePaths[0] = 0; + if (gOptions.IncludePaths != NULL) { + strcpy (IncludePaths, gOptions.IncludePaths); + free (gOptions.IncludePaths); + } + strcat (IncludePaths, " -I "); + strcat (IncludePaths, Argv[0]); + gOptions.IncludePaths = IncludePaths; + // + // -od OutputDirectory to define a common directory for output files + // + } else if (_stricmp (Argv[0], "-od") == 0) { + if ((Argc < 2) || (Argv[1][0] == '-')) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing output directory name"); + return STATUS_ERROR; + } + Argc--; + Argv++; + strcpy (gOptions.OutputDirectory, Argv[0]); + } else if (_stricmp (Argv[0], "-ibin") == 0) { + gOptions.CreateIfrBinFile = 1; + } else if (_stricmp (Argv[0], "-nostrings") == 0) { + // deprecated option + // + // -ppflag C-preprocessor-flag option for passing options to the C preprocessor. + // Turn them all into a single string. + // + } else if (_stricmp (Argv[0], "-ppflag") == 0) { + if (Argc < 2) { + Error (PROGRAM_NAME, 0, 0, Argv[0], "missing C-preprocessor argument"); + return STATUS_ERROR; + } + Argc--; + Argv++; + Len = strlen (Argv[0]) + 2; + if (gOptions.CPreprocessorOptions != NULL) { + Len += strlen (gOptions.CPreprocessorOptions); + } + CPreprocessorOptions = (INT8 *)malloc (Len); + if (CPreprocessorOptions == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return STATUS_ERROR; + } + CPreprocessorOptions[0] = 0; + if (gOptions.CPreprocessorOptions != NULL) { + strcpy (CPreprocessorOptions, gOptions.CPreprocessorOptions); + free (gOptions.CPreprocessorOptions); + } + strcat (CPreprocessorOptions, " "); + strcat (CPreprocessorOptions, Argv[0]); + gOptions.CPreprocessorOptions = CPreprocessorOptions; + } else { + Error (PROGRAM_NAME, 0, 0, Argv[0], "unrecognized option"); + return STATUS_ERROR; + } + Argc--; + Argv++; + } + // + // Must specify at least the vfr file name + // + if (Argc > 1) { + Error (PROGRAM_NAME, 0, 0, Argv[1], "unrecognized argument after VFR file name"); + return STATUS_ERROR; + } else if (Argc < 1) { + Error (PROGRAM_NAME, 0, 0, NULL, "must specify VFR file name"); + return STATUS_ERROR; + } + strcpy (gOptions.VfrFileName, Argv[0]); + + strcpy (CopyStr, gOptions.VfrFileName); + Cptr = CopyStr + strlen (CopyStr) - 1; + for (;(Cptr > CopyStr) && (*Cptr != '\\') && (*Cptr != ':'); Cptr--); + if (Cptr == CopyStr) { + strcpy (gOptions.VfrBaseFileName, Cptr); + } else { + strcpy (gOptions.VfrBaseFileName, Cptr+1); + } + // + // Terminate the vfr file basename at the extension + // + for (Cptr = gOptions.VfrBaseFileName; *Cptr && (*Cptr != '.'); Cptr++) { + } + *Cptr = 0; + // + // If they defined an output directory, prepend all output files + // with the working directory. Output files of interest: + // VfrListFileName -- list file + // IfrOutputFileName -- IFR bytes + // StringOutputFileName -- string bytes + // StringListFileName -- not used + // StringDefineFileName -- #defines of string identifiers + // + // We have two cases: + // 1. Output directory (-od) not specified, in which case output files + // go to the current working directory. + // 2. Output directory specified, in which case the output files + // go directly to the specified directory. + // + if (gOptions.OutputDirectory[0] == 0) { + CopyStr[0] = 0; + _getcwd (CopyStr, sizeof (CopyStr)); + strcpy (gOptions.OutputDirectory, CopyStr); + } + // + // Make sure output directory has a trailing backslash + // + if (gOptions.OutputDirectory[strlen (gOptions.OutputDirectory) - 1] != '\\') { + strcat (gOptions.OutputDirectory, "\\"); + } + // + // Create the base output file name as: path\base, copy it to all the output + // filenames, and then add the appropriate extension to each. + // + strcpy (gOptions.VfrListFileName, gOptions.OutputDirectory); + strcat (gOptions.VfrListFileName, gOptions.VfrBaseFileName); + strcpy (gOptions.IfrOutputFileName, gOptions.VfrListFileName); + strcpy (gOptions.PreprocessorOutputFileName, gOptions.VfrListFileName); + strcat (gOptions.VfrListFileName, VFR_LIST_FILENAME_EXTENSION); + strcat (gOptions.IfrOutputFileName, VFR_BINARY_FILENAME_EXTENSION); + strcat (gOptions.PreprocessorOutputFileName, VFR_PREPROCESS_FILENAME_EXTENSION); + + // + // We set a default list file name, so if they do not + // want a list file, null out the name now. + // + if (gOptions.CreateListFile == 0) { + gOptions.VfrListFileName[0] = 0; + } + return STATUS_SUCCESS; +} +static +VOID +Usage () +/*++ + +Routine Description: + Print utility usage instructions + +Arguments: + None + +Returns: + None + +--*/ +{ + int Index; + const char *Help[] = { + " ", + "VfrCompile version " VFR_COMPILER_VERSION, + " ", + " Usage: VfrCompile {options} [VfrFile]", + " ", + " where options include:", + " -? or -h prints this help", + " -l create an output IFR listing file", + " -i IncPath add IncPath to the search path for VFR included files", + " -od OutputDir deposit all output files to directory OutputDir (default=cwd)", + " -ibin create an IFR HII pack file", + " where parameters include:", + " VfrFile name of the input VFR script file", + " ", + NULL + }; + for (Index = 0; Help[Index] != NULL; Index++) { + fprintf (stdout, "%s\n", Help[Index]); + } +} + +>> + + +#lexaction +<< + +#include "EfiVfr.h" + +PARSER_LINE_DEFINITION *gLineDefinition = NULL; +PARSER_LINE_DEFINITION *gLastLineDefinition = NULL; + +VOID +AddFileLine ( + char *TokenString, + UINT32 TokenLine + ) +/*++ + +Routine Description: + During the lexer phase, if we encounter a #line statement output by + the preprocessor, this function gets called. We'll save off the info + for error reporting purposes. The preprocessor line information has the + form: + + #line 3 "FileName.c" + +Arguments: + TokenString - the parsed string as shown above + TokenLine - the line number in the preprocessed output file + +Returns: + NA + +--*/ +{ + PARSER_LINE_DEFINITION *LineDef; + INT8 *Cptr; + + // + // Allocate a structure in which we can keep track of this line information. + // + LineDef = (PARSER_LINE_DEFINITION *)malloc (sizeof (PARSER_LINE_DEFINITION)); + memset ((char *)LineDef, 0, sizeof (PARSER_LINE_DEFINITION)); + LineDef->TokenLineNum = TokenLine; + LineDef->HashLineNum = atoi (TokenString + 6); + // + // Find the quotes in the filename, then allocate space in the line + // def structure for a copy of the filename. Finally, copy it without + // quotes to the line def. + // + for (Cptr = TokenString + 7; *Cptr && (*Cptr != '"'); Cptr++); + if (*Cptr == '"') { + LineDef->FileName = (INT8 *)malloc (strlen (Cptr)); + Cptr++; + strcpy (LineDef->FileName, Cptr); + for (Cptr = LineDef->FileName; *Cptr && (*Cptr != '"'); Cptr++); + *Cptr = 0; + // + // Now add this new one to the list + // + if (gLineDefinition == NULL) { + gLineDefinition = LineDef; + } else { + gLastLineDefinition->Next = LineDef; + } + gLastLineDefinition = LineDef; + } else { + Error (PROGRAM_NAME, 0, 0, "invalid line definition in preprocessor output file", TokenString); + free (LineDef); + return; + } +} +char * +ConvertLineNumber ( + UINT32 *LineNum + ) +/*++ + +Routine Description: + Given the line number in the preprocessor-output file, use the line number + information we've saved to determine the source file name and line number + where the code originally came from. This is required for error reporting. + +Arguments: + LineNum - the line number in the preprocessor-output file. + +Returns: + Returns a pointer to the source file name. Also returns the line number + in the provided LineNum argument + +--*/ +{ + PARSER_LINE_DEFINITION *LineDef; + // + // Step through our linked list of #line information we saved off. + // For each one, look at its line number, and the line number of the + // next record, and see if the passed-in line number is in the range. + // If it is, then convert the line number to the appropriate line number + // of the original source file. + // + for (LineDef = gLineDefinition; LineDef != NULL; LineDef = LineDef->Next) { + // + // The given LineNum is the line number from the .i file. + // Find a line definition whose range includes this line number, + // convert the line number, and return the filename. + // + if (LineDef->TokenLineNum <= *LineNum) { + if (LineDef->Next != NULL) { + if (LineDef->Next->TokenLineNum > *LineNum) { + *LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum; + return LineDef->FileName; + } + } else { + // + // Last one in the list of line definitions, so has to be right + // + *LineNum = *LineNum - LineDef->TokenLineNum + LineDef->HashLineNum; + return LineDef->FileName; + } + } + } + return NULL; +} + +>> + +// +// Define a lexical class for parsing quoted strings. Basically +// starts with a double quote, and ends with a double quote that +// is not preceeded with a backslash. +// +#lexclass QUOTED_STRING +#token TheString "~[\"]*\"" << mode (START); >> + +// +// Define a lexical class for parsing "#pragma pack" statements. +// We do this just for convenience (since we skip them here) so +// that users can include some minimal .h files. +// +#lexclass PRAGMA_PACK +#token "pack" << skip (); >> +#token "[\ \t]" << skip (); >> +#token "\(" << skip (); >> +#token "[0-9]*" << skip (); >> +#token "\)" << skip (); 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 pragma pack statements +// +#token "\#pragma" << skip (); mode(PRAGMA_PACK); >> + +// +// Skip over 'extern' in any included .H file +// +#token "extern" << skip (); >> + +// +// 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 LineDefinition "#line\ [0-9]+\ \"~[\"]+\"[\ \t]*\n" << AddFileLine (begexpr (), line ()); skip (); >> +#token FormSet("formset") "formset" +#token EndFormSet("endformset") "endformset" +#token Title("title") "title" +#token FormId("formid") "formid" +#token OneOf("oneof") "oneof" +#token Prompt("prompt") "prompt" +#token OrderedList("orderedlist") "orderedlist" +#token EndList("endlist") "endlist" +#token EndForm("endform") "endform" +#token EndOneOf("endoneof") "endoneof" +#token Form("form") "form" +#token Subtitle("subtitle") "subtitle" +#token Help("help") "help" +#token VarId("varid") "varid" +#token Text("text") "text" +#token Option("option") "option" +#token Value("value") "value" +#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 AND("AND") "AND" +#token OR("OR") "OR" +#token GrayOutIf("grayoutif") "grayoutif" +#token NOT("NOT") "NOT" +#token Label("label") "label" +#token Timeout("timeout") "timeout" +#token Inventory("inventory") "inventory" +#token StringToken("STRING_TOKEN") "STRING_TOKEN" +#token NonNvDataMap("_NON_NV_DATA_MAP") "_NON_NV_DATA_MAP" +#token Struct("struct") "struct" +#token Uint64("UINT64") "UINT64" +#token Uint32("UINT32") "UINT32" +#token Uint16("UINT16") "UINT16" +#token Char16("CHAR16") "CHAR16" +#token Uint8("UINT8") "UINT8" +#token Guid("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 Hidden("hidden") "hidden" +#token Goto("goto") "goto" +#token InconsistentIf "inconsistentif" +#token EndIf("endif") "endif" +#token IdEqId("ideqid") "ideqid" +#token IdEqVal("ideqval") "ideqval" +#token VarEqVal("vareqval") "vareqval" +#token Var("var") "var" +#token IdEqValList("ideqvallist") "ideqvallist" +#token Length("length") "length" +#token Values("values") "values" +#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 LateCheckFlag("LATE_CHECK") "LATE_CHECK" +#token Class("class") "class" +#token Subclass("subclass") "subclass" +#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 VarStore("varstore") "varstore" +#token Name("name") "name" +#token Oem("oem") "oem" +#token True("TRUE") "TRUE" +#token False("FALSE") "FALSE" +#token GreaterThan(">") ">" +#token GreaterEqual(">=") ">=" +#token LessThan("<") "<" +#token LessEqual("<=") "<=" + +// +// 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" + +#token LanguageIdentifier("language identifier") "[a-z][a-z][a-z]" // 3 lowercase characters +#token StringIdentifier("string identifier") "[A-Za-z_][A-Za-z_0-9]*" +#token Number("numeric value") "(0x[0-9A-Fa-f]+) | [0-9]+" +#token OpenBrace("{") "\{" +#token CloseBrace("}") "\}" +#token OpenParen("(") "\(" +#token CloseParen(")") "\)" +#token OpenBracket("[") "\[" +#token CloseBracket("]") "\]" + +// +// Define all other invalid characters so that they get through the lexical phase +// and we can catch them during the parse phase. We get much better error +// messages then. +// +#token InvalidCharacters("invalid characters") "~[;:=,\.\|]" + +// +// This is the overall definition of a VFR form definition script. +// +program : + ( dataStructDefinition )* + formSetStatement + ( vfrStatementVarStore )* + ( formDefinition )* + EFS:EndFormSet ";" << WriteOpByte (EFS->getLine(), EFI_IFR_END_FORM_SET_OP); >> + "@" // end of file + ; + +formSetStatement : + FS:FormSet << WriteOpByte (FS->getLine(), EFI_IFR_FORM_SET_OP); >> + Guid "=" + OpenBrace + G1:Number "," + G2:Number "," + G3:Number "," + G4:Number "," + G5:Number "," + G6:Number "," + G7:Number "," + G8:Number "," + G9:Number "," + G10:Number "," + G11:Number + CloseBrace << WriteGuidValue (G1->getLine (), G1->getText (), G2->getText (), G3->getText (), + G4->getText (), G5->getText (), G6->getText (), G7->getText (), + G8->getText (), G9->getText (), G10->getText (), G11->getText () + ); + >> + "," + Title "=" getStringId "," + Help "=" getStringId "," + // + // insert padding for an EFI_PHYSICAL_ADDRESS (UINT64) + // + << WriteDWord (0, 0); WriteDWord (0, 0); >> + Class "=" CVAL:classDefinition "," << WriteClass (); >> + Subclass "=" SVAL:subclassDefinition "," << WriteSubclass (); >> + << WriteWord (mNvDataStructSize); >> + ; + +// +// A form can be of multiple classes, thus allow CLASS_A | CLASS_B | CLASS_C +// +classDefinition : + validClassNames ( "\|" validClassNames )* + ; + +validClassNames : + CND:ClassNonDevice << SetClass (CND->getLine(), EFI_NON_DEVICE_CLASS); >> + | CDD:ClassDiskDevice << SetClass (CDD->getLine(), EFI_DISK_DEVICE_CLASS); >> + | CVD:ClassVideoDevice << SetClass (CVD->getLine(), EFI_VIDEO_DEVICE_CLASS); >> + | CNW:ClassNetworkDevice << SetClass (CNW->getLine(), EFI_NETWORK_DEVICE_CLASS); >> + | CID:ClassInputDevice << SetClass (CID->getLine(), EFI_INPUT_DEVICE_CLASS); >> + | COB:ClassOnBoardDevice << SetClass (COB->getLine(), EFI_ON_BOARD_DEVICE_CLASS); >> + | COD:ClassOtherDevice << SetClass (COD->getLine(), EFI_OTHER_DEVICE_CLASS); >> + | CNUM:Number << SetClass (CNUM->getLine(), GetNumber (CNUM->getText(), CNUM->getLine(), 4)); >> + ; << PrintErrorMessage (LT(1)->getLine(), LT(1)->getText(), "invalid class"); >> + +// +// A form can only be of one subclass type. +// +subclassDefinition : + SSA:SubclassSetupApplication << SetSubclass (SSA->getLine(), EFI_SETUP_APPLICATION_SUBCLASS); >> + | SGA:SubclassGeneralApplication << SetSubclass (SGA->getLine(), EFI_GENERAL_APPLICATION_SUBCLASS); >> + | SFP:SubclassFrontPage << SetSubclass (SFP->getLine(), EFI_FRONT_PAGE_SUBCLASS); >> + | SSU:SubclassSingleUse << SetSubclass (SSU->getLine(), EFI_SINGLE_USE_SUBCLASS); >> + | SNUM:Number << SetSubclass (SNUM->getLine(), GetNumber (SNUM->getText(), SNUM->getLine(), 4)); >> + ; << PrintErrorMessage (LT(1)->getLine(), LT(1)->getText(), "invalid subclass"); >> + +// +// Parse a C type data structure for storing VFR setup data. Allow: +// typedef struct _XXX_ { +// (fields) +// } MY_NV_DATA; +// +dataStructDefinition : + << int IsNonNV = 0; >> + { TypeDef } + S:Struct + ( + NonNvDataMap << IsNonNV = 1; >> + | + { StringIdentifier } + ) << StartStructDefinition (IsNonNV, S->getLine()); >> + OpenBrace + dataStructFields + CloseBrace NAME:StringIdentifier << EndStructDefinition (NAME->getText(), NAME->getLine()); >> + ";" + ; + +dataStructFields : + ( dataStructField64 | dataStructField32 | dataStructField16 | dataStructField8 ) * + ; + +//***************************************************************************** +// +// PARSE: +// UINT64 Name[4]; +// UINT64 Name; +// +// Used while parsing the NV data map structures. +// +dataStructField64 : + << int ArrayLength = 1; char IsArray = 0; >> + "UINT64" + NAME:StringIdentifier + ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> ) + << AddStructField (NAME->getText(), NAME->getLine(), 8, ArrayLength, IsArray); >> + ; + +//***************************************************************************** +// +// PARSE: +// UINT32 Name[4]; +// UINT32 Name; +// +// Used while parsing the NV data map structures. +// +dataStructField32 : + << int ArrayLength = 1; char IsArray = 0; >> + "UINT32" + NAME:StringIdentifier + ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> ) + << AddStructField (NAME->getText(), NAME->getLine(), 4, ArrayLength, IsArray); >> + ; + +//***************************************************************************** +// +// PARSE: +// UINT16 Name[4]; +// UINT16 Name; +// +// Used while parsing the NV data map structures. +// +dataStructField16 : + << int ArrayLength = 1; char IsArray = 0; >> + ( "UINT16" | "CHAR16" ) + NAME:StringIdentifier + ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> ) + << AddStructField (NAME->getText(), NAME->getLine(), 2, ArrayLength, IsArray); >> + ; + +//***************************************************************************** +// +// PARSE: +// UINT8 Name[4]; +// UINT8 Name; +// +// Used while parsing the NV data map structures. +// +dataStructField8 : + << int ArrayLength = 1; char IsArray = 0; >> + "UINT8" + NAME:StringIdentifier + ( ";" | OpenBracket IVal:Number CloseBracket ";" << ArrayLength = GetNumber (IVal->getText(), IVal->getLine(), 4); IsArray = 1; >> ) + << AddStructField (NAME->getText(), NAME->getLine(), 1, ArrayLength, IsArray); >> + ; + +//***************************************************************************** +// +// PARSE: +// form formid = 1, +// title = STRING_TOKEN(STR_FORM_TITLE); +// -- form statements -- +// endform; +// +// The Form ID cannot be 0 +// +formDefinition : + FRM:Form FormId << WriteOpByte (FRM->getLine(), EFI_IFR_FORM_OP); >> + "=" + VAL:Number << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); AddFormId (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine()); >> + "," + Title "=" getStringId ";" // writes string identifier + ( vfrStatements )* + ENDF:EndForm ";" << WriteOpByte (ENDF->getLine(), EFI_IFR_END_FORM_OP); >> + ; + +// +// VFR statements in a formset +// +vfrStatements : + vfrStatementSubTitle | + vfrStatementOneOf | + vfrStatementTextText | + vfrStatementCheckBox | + vfrStatementNumeric | + vfrStatementDate | + vfrStatementTime | + vfrStatementPassword | + vfrStatementString | + vfrStatementSuppressIf | + vfrStatementHidden | + vfrStatementGoto | + vfrStatementGrayOutIf | + vfrStatementInconsistentIf | + vfrStatementLabel | + vfrStatementBanner | + vfrStatementInventory | + vfrStatementOrderedList | + vfrStatementOem | + vfrStatementSaveRestoreDefaults + ; + +//***************************************************************************** +// +// PARSE: +// label 100; +// +vfrStatementLabel : + OPID:Label << WriteOpByte (OPID->getLine(), EFI_IFR_LABEL_OP); >> + VAL:Number << + WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); + AddLabel (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine()); + >> + ";" + ; + +//***************************************************************************** +// +// PARSE: +// oem 0x12, 0x34, 0x56; +// +vfrStatementOem : + OPID:Oem << WriteOpByte (OPID->getLine(), EFI_IFR_OEM_DEFINED_OP); >> + ( VAL1:Number << WriteByte (GetNumber (VAL1->getText(), VAL1->getLine(), 1), 0); >> ) + ( "," VAL2:Number << WriteByte (GetNumber (VAL2->getText(), VAL2->getLine(), 1), 0); >> )* + ";" + ; + +//***************************************************************************** +// +// PARSE: +// inconsistentif NOT .... AND NOT .... OR ... endif; +// +vfrStatementInconsistentIf : + << ResetFlags (); >> + IIFOP:InconsistentIf << WriteOpByte (IIFOP->getLine(), EFI_IFR_INCONSISTENT_IF_OP); >> + Prompt "=" getStringId "," + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," + } + << WriteFlags (); >> // write the flags field + vfrBooleanExpression + EOP:EndIf ";" << WriteOpByte (EOP->getLine(), EFI_IFR_END_IF_OP); >> + ; + +//***************************************************************************** +// +// PARSE: +// TRUE AND (ideqval SomeStruct.SomeMember >= 0x10 OR +// ideqid SomeStruct.SomeMember < SomeStruct.SomeOtherMember) AND +// (ideqlist SomeStruct.SomeOtherMember == 0x10, 0x20, 0x30 OR +// vareqval var(VAR_EQ_TEST_NAME) == 0x1) +// +// For supporting complex express, divide the vfrBooleanExpression to two parts +// so that pred-LL(k) parser can parse incrementally. +// +vfrBooleanExpression : + leftPartVfrBooleanExp { rightPartVfrBooleanExp } + ; + +leftPartVfrBooleanExp : + OpenParen vfrBooleanExpression CloseParen | + (ideqval | ideqid | ideqvallist | vareqval | truefalse) | + NOPID:NOT leftPartVfrBooleanExp << WriteOpByte (NOPID->getLine(), EFI_IFR_NOT_OP); >> + ; + +rightPartVfrBooleanExp : + AOPID:AND vfrBooleanExpression << WriteOpByte (AOPID->getLine(), EFI_IFR_AND_OP); >> | + OOPID:OR vfrBooleanExpression << WriteOpByte (OOPID->getLine(), EFI_IFR_OR_OP); >> + ; + +//***************************************************************************** +// +// PARSE: +// TRUE +// +truefalse : + TOPID:True << WriteOpByte (TOPID->getLine(), EFI_IFR_TRUE_OP); >> | + FOPID:False << WriteOpByte (FOPID->getLine(), EFI_IFR_FALSE_OP); >> + ; + +//***************************************************************************** +// +// PARSE: +// varstore MY_STRUCT_NAME, key = 0x1234, name = "MyVariableName", guid = {...}; +// +vfrStatementVarStore : + OP:VarStore << WriteOpByte (OP->getLine(), EFI_IFR_VARSTORE_OP); >> + STRUCT_NAME:StringIdentifier "," + Key "=" KNUM:Number "," + Name "=" VAR_NAME:StringIdentifier "," + Guid "=" + OpenBrace + G1:Number "," + G2:Number "," + G3:Number "," + G4:Number "," + G5:Number "," + G6:Number "," + G7:Number "," + G8:Number "," + G9:Number "," + G10:Number "," + G11:Number + CloseBrace << WriteGuidValue (G1->getLine (), G1->getText (), G2->getText (), G3->getText (), + G4->getText (), G5->getText (), G6->getText (), G7->getText (), + G8->getText (), G9->getText (), G10->getText (), G11->getText () + ); + WriteWord (GetNumber (KNUM->getText(), KNUM->getLine(), 2)); + AddVarStore (STRUCT_NAME->getText(), VAR_NAME->getText(), GetNumber (KNUM->getText(), KNUM->getLine(), 2), STRUCT_NAME->getLine()); + >> + + ";" + ; + +//***************************************************************************** +// +// PARSE: +// vareqval var(0x100) == 0x20 +// +vareqval : + OPID:VarEqVal << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_VAR_VAL_OP); >> + Var OpenParen + VAR:Number << WriteWord (GetNumber (VAR->getText(), VAR->getLine(), 2)); >> + CloseParen + compareNumber + ; + +ideqval : + OPID:IdEqVal << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_VAL_OP); >> + vfrStructFieldName[0] + compareNumber + ; + +//***************************************************************************** +// +// PARSE: +// ideqid MyNVData3.Field16A == MyNVData3.Field16B +// +// NOTE: Before processing the second variable store in the ideqid statement, set a global flag +// so that when we parse the second variable we set the secondary variable store id. +// +ideqid : + OPID:IdEqId << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_ID_OP); >> + vfrStructFieldName[0] + compareVfrStructFieldNameNL0 + ; + +//***************************************************************************** +// +// compareNumber is the combination of compare operation and Number +// +compareNumber : + ( + "==" + VAL1:Number << WriteWord (GetNumber (VAL1->getText(), VAL1->getLine(), 2)); >> + ) | + ( + GTOPID:GreaterThan + VAL2:Number << WriteWord (GetNumber (VAL2->getText(), VAL2->getLine(), 2)); + WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >> + ) | + ( + GEOPID:GreaterEqual + VAL3:Number << WriteWord (GetNumber (VAL3->getText(), VAL3->getLine(), 2)); + WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >> + ) | + ( + LTOPID:LessThan + VAL4:Number << WriteWord (GetNumber (VAL4->getText(), VAL4->getLine(), 2)); + WriteOpByte (LTOPID->getLine(), EFI_IFR_GE_OP); + WriteOpByte (LTOPID->getLine(), EFI_IFR_NOT_OP); >> + ) | + ( + LEOPID:LessEqual + VAL5:Number << WriteWord (GetNumber (VAL5->getText(), VAL5->getLine(), 2)); + WriteOpByte (LEOPID->getLine(), EFI_IFR_GT_OP); + WriteOpByte (LEOPID->getLine(), EFI_IFR_NOT_OP); >> + ) + ; + +//***************************************************************************** +// +// compareVfrStructFieldNameNL0 is the combination of compare operation and vfrStructFieldNameNL[0] +// +compareVfrStructFieldNameNL0 : + ( + "==" << mIdEqIdStmt = 1; >> + vfrStructFieldNameNL[0] << mIdEqIdStmt = 0; >> + ) | + ( + GTOPID:GreaterThan << mIdEqIdStmt = 1; >> + vfrStructFieldNameNL[0] << mIdEqIdStmt = 0; + WriteOpByte (GTOPID->getLine(), EFI_IFR_GT_OP); >> + ) | + ( + GEOPID:GreaterEqual << mIdEqIdStmt = 1; >> + vfrStructFieldNameNL[0] << mIdEqIdStmt = 0; + WriteOpByte (GEOPID->getLine(), EFI_IFR_GE_OP); >> + ) | + ( + LTOPID:LessThan << mIdEqIdStmt = 1; >> + vfrStructFieldNameNL[0] << mIdEqIdStmt = 0; + WriteOpByte (LTOPID->getLine(), EFI_IFR_GE_OP); + WriteOpByte (LTOPID->getLine(), EFI_IFR_NOT_OP); >> + ) | + ( + LEOPID:LessEqual << mIdEqIdStmt = 1; >> + vfrStructFieldNameNL[0] << mIdEqIdStmt = 0; + WriteOpByte (LEOPID->getLine(), EFI_IFR_GT_OP); + WriteOpByte (LEOPID->getLine(), EFI_IFR_NOT_OP); >> + ) + ; + + +ideqvallist : + OPID:IdEqValList << WriteOpByte (OPID->getLine(), EFI_IFR_EQ_ID_LIST_OP); >> + vfrStructFieldName[0] + "==" + ( VAL:Number << QueueIdEqValList (GetNumber (VAL->getText(), VAL->getLine(), 2)); >> ) + + << FlushQueueIdEqValList(); >> + ; + +vfrStatementGoto : + << UINT32 LineNum, KeyValue = 0; ResetFlags (); >> + IDG:Goto << WriteOpByte (IDG->getLine(), EFI_IFR_REF_OP); >> + VAL:Number "," << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); + AddGotoReference (GetNumber (VAL->getText(), VAL->getLine(), 2), VAL->getLine()); + >> + KP:Prompt "=" getStringId "," << LineNum = KP->getLine(); >> + Help "=" getStringId + { + "," + FF:Flags "=" flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >> + } + { + "," Key "=" KNUM:Number << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >> + } + << WriteFlagsKey (KeyValue, LineNum); >> + ";" + ; + +vfrStatementHidden : + IDH:Hidden << WriteOpByte (IDH->getLine(), EFI_IFR_HIDDEN_OP); >> + Value "=" + VAL:Number "," << WriteWord (GetNumber (VAL->getText(), VAL->getLine(), 2)); >> + Key "=" + KVAL:Number << WriteWord (GetNumber (KVAL->getText(), KVAL->getLine(), 2)); >> + ";" + ; + +//***************************************************************************** +// +// PARSE: +// suppressif { grayoutif } + endif; +// Note: +// You can have: suppressif:grayoutif:statements:endif +// suppressif:grayoutif:endif -- serves no purpose +// suppressif:statements:endif +// suppressif:endif -- serves no purpose +// +vfrStatementSuppressIf : + << ResetFlags (); >> + OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >> + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," + } + << WriteFlags (); >> // write the flags field + vfrBooleanExpression + ";" + { suppressIfGrayOutIf } ( suppressIfAndGrayoutIfSubstatements )+ + ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >> + ; + +// +// This is the form for a grayoutif nested in a suppressif statement +// +suppressIfGrayOutIf : + << ResetFlags (); >> + OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); >> + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," + } + << WriteFlags (); >> // write the flags field + vfrBooleanExpression + ";" + ; + +//***************************************************************************** +// +// PARSE: +// grayoutif { flags = n, } endif; +// Note: +// You can have: grayoutif:suppressif:statements:endif +// grayoutif:statements:endif +// +// +vfrStatementGrayOutIf : + << ResetFlags (); >> + OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >> + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," + } + << WriteFlags (); >> // write the flags field + vfrBooleanExpression + ";" + { grayoutIfSuppressIf } ( suppressIfAndGrayoutIfSubstatements )+ + ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >> + ; + +// +// This is the format for a suppressif nested in a grayoutif +// +grayoutIfSuppressIf : + << ResetFlags (); >> + OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); >> + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," + } + << WriteFlags (); >> // write the flags field + vfrBooleanExpression + ";" + ; + +// +// These are the VFR statements that are valid inside a suppressif or grayoutif statement. +// +suppressIfAndGrayoutIfSubstatements : + vfrStatementOneOf | + vfrStatementTextText | + vfrStatementCheckBox | + vfrStatementNumeric | + vfrStatementDate | + vfrStatementTime | + vfrStatementPassword | + vfrStatementString | + vfrStatementHidden | + vfrStatementGoto | + vfrStatementLabel | + vfrStatementInventory | + vfrStatementOrderedList | + vfrStatementSaveRestoreDefaults + ; + +//***************************************************************************** +// +// PARSE: +// +// password varid = MyNvData.Password, +// prompt = STRING_TOKEN(STR_PASSWORD_PROMPT), +// help = STRING_TOKEN(STR_PASSWORD_HELP), +// minsize = 6, +// maxsize = 20, +// encoding = 1, +// endpassword; + +vfrStatementPassword : + << UINT32 KeyValue = 0; UINT32 LineNum; ResetFlags (); >> + IDPW:Password << WriteOpByte (IDPW->getLine(), EFI_IFR_PASSWORD_OP); >> + VarId "=" vfrStructFieldNameArray[0] "," + Prompt "=" getStringId "," + KH:Help "=" getStringId "," << LineNum = KH->getLine(); >> + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine(); >> + } + { + Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >> + } + << WriteFlagsKey (KeyValue, LineNum); >> + MinSize "=" MIN:Number "," << WriteByte (GetNumber (MIN->getText(), MIN->getLine(), 1), 0); >> + MaxSize "=" MAX:Number "," << WriteByte (GetNumber (MAX->getText(), MAX->getLine(), 1), 0); >> + Encoding "=" ENC:Number "," << WriteWord (GetNumber (ENC->getText(), ENC->getLine(), 2)); >> + EndPassword ";" + ; + +//***************************************************************************** +// +// PARSE: +// +// string varid = MyNv.String, +// prompt = STRING_TOKEN(STR_STRING_PROMPT), +// help = STRING_TOKEN(STR_STRING_HELP), +// flags = INTERACTIVE, +// key = 0x1234, +// minsize = 6, +// maxsize = 0x14, +// endstring; +// +// Since flags and key are optional, we can't use Flags->getLine(). Therefore for error +// reporting we save the line number of the "help" keyword. +// +vfrStatementString : + << unsigned int KeyValue = 0; UINT32 LineNum; ResetFlags (); >> + IDS:String << WriteOpByte (IDS->getLine(), EFI_IFR_STRING_OP); >> + VarId "=" vfrStructFieldNameArray[0] "," + Prompt "=" getStringId "," + KH:Help "=" getStringId "," << LineNum = KH->getLine(); >> + { + FF:Flags "=" + flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >> + "," + } + { + Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >> + } + << WriteFlagsKey (KeyValue, LineNum); >> + MinSize "=" MIN:Number "," << WriteByte (GetNumber (MIN->getText(), MIN->getLine(), 1), 0); >> + MaxSize "=" MAX:Number "," << WriteByte (GetNumber (MAX->getText(), MAX->getLine(), 1), 0); >> + EndString ";" + ; + +//***************************************************************************** +// +// PARSE: +// numeric varid = MyIfrNVData.HowOldAreYouInYears, +// prompt = STRING_TOKEN(STR_NUMERIC_PROMPT), +// help = STRING_TOKEN(STR_NUMERIC_HELP), +// flags = INTERACTIVE, // flags is optional +// key = 0x1234, // key is optional if (flags & INTERACTIVE = 0) +// minimum = 0x0, +// maximum = 0xf0, +// step = 1, // step is option, and step=1 if not specified +// default = 0; // default is optional, and default=minimum if not specified +// endnumeric; +// +// Make flags and key optional. However if flags includes INTERACTIVE, then a key is required. +// That check is done in WriteFlagsKey() function. +// +vfrStatementNumeric : + << UINT32 LineNum, KeyValue = 0; ResetFlags (); >> + IDN:Numeric << WriteOpByte (IDN->getLine(), EFI_IFR_NUMERIC_OP); >> + VarId "=" vfrStructFieldName[2] "," + Prompt "=" getStringId "," + KH:Help "=" getStringId "," << LineNum = KH->getLine(); >> + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine (); >> + } + { + Key "=" KNUM:Number "," << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >> + } + << WriteFlagsKey (KeyValue, LineNum); >> + minMaxStepDefault + EndNumeric ";" << WriteMinMaxStepDefault (); >> + ; + +// +// Parse minimum/maximum/step/default statements. Special cases: +// - if step not specified, then the value is 1 +// - if default not specified, then the value is the min value specified +// - if max < min, print a warning and swap the values (changes default too) +// +minMaxStepDefault : + << InitMinMaxStepDefault (); >> + Minimum "=" MIN:Number "," << SetMinMaxStepDefault (GetNumber (MIN->getText(), MIN->getLine(), 2), 0, MIN->getLine()); >> + Maximum "=" MAX:Number "," << SetMinMaxStepDefault (GetNumber (MAX->getText(), MAX->getLine(), 2), 1, MAX->getLine()); >> + { Step "=" STEP:Number "," << SetMinMaxStepDefault (GetNumber (STEP->getText(), STEP->getLine(), 2), 2, STEP->getLine()); >> } + { Default "=" DEF:Number "," << SetMinMaxStepDefault (GetNumber (DEF->getText(), DEF->getLine(), 2), 3, DEF->getLine()); >> } + ; + + +//***************************************************************************** +// +// PARSE: +// +// date year varid = Date.Year, // "Date.Year" is a special case we recognize +// prompt = STRING_TOKEN(STR_DATE_PROMPT), +// help = STRING_TOKEN(STR_DATE_YEAR_HELP), +// minimum = 1939, +// maximum = 2101, +// step = 1, +// default = 1964, +// +// month varid = Date.Month, +// prompt = STRING_TOKEN(STR_DATE_PROMPT), +// help = STRING_TOKEN(STR_DATE_MONTH_HELP), +// minimum = 1, +// maximum = 12, +// step = 1, +// default = 1, +// +// day varid = Date.Day, +// prompt = STRING_TOKEN(STR_DATE_PROMPT), +// help = STRING_TOKEN(STR_DATE_DAY_HELP), +// minimum = 1, +// maximum = 31, +// step = 0x1, +// default = 1, +// +// enddate; +// +vfrStatementDate : + Date + IDY:Year VarId "=" << WriteOpByte (IDY->getLine(), EFI_IFR_DATE_OP); >> + vfrStructFieldName[2] "," + dateTimeSubStatement + IDM:Month VarId "=" << WriteOpByte (IDM->getLine(), EFI_IFR_DATE_OP); >> + vfrStructFieldName[2] "," + dateTimeSubStatement + IDD:Day VarId "=" << WriteOpByte (IDD->getLine(), EFI_IFR_DATE_OP); >> + vfrStructFieldName[2] "," + dateTimeSubStatement + EndDate ";" + ; + +vfrStatementTime : + Time + IDH:Hour VarId "=" << WriteOpByte (IDH->getLine(), EFI_IFR_TIME_OP); >> + vfrStructFieldName[2] "," + dateTimeSubStatement + IDM:Minute VarId "=" << WriteOpByte (IDM->getLine(), EFI_IFR_TIME_OP); >> + vfrStructFieldName[2] "," + dateTimeSubStatement + IDS:Second VarId "=" << WriteOpByte (IDS->getLine(), EFI_IFR_TIME_OP); >> + vfrStructFieldName[2] "," + dateTimeSubStatement + EndTime ";" + ; + +//***************************************************************************** +// +// PARSE: +// +// text text = STRING_ID; +// text text = STRING_ID, text = STRING_ID; +// text text = STRING_ID, text = STRING_ID, flags = x, key = y; +// +vfrStatementTextText : + << ResetFlags (); >> + IDT:Text << WriteOpByte (IDT->getLine(), EFI_IFR_TEXT_OP); >> + Help "=" getStringId "," + Text "=" + getStringId // writes string identifier + { "," Text "=" getStringId + "," Flags "=" flagsField ( "\|" flagsField )* << WriteFlags (); >> + "," + Key "=" KNUM:Number << WriteWord (GetNumber(KNUM->getText(), KNUM->getLine(), 2)); >> + } + ";" + ; + +//***************************************************************************** +// +// PARSE: +// +// inventory help = ID, text = ID; +// inventory help = ID, text = id, text = ID; +// +vfrStatementInventory : + IDI:Inventory << WriteOpByte (IDI->getLine(), EFI_IFR_INVENTORY_OP); >> + Help "=" getStringId "," + Text "=" getStringId // writes string identifier + { "," Text "=" getStringId + } + ";" + ; + +//***************************************************************************** +// +// PARSE: +// +// restore defaults, +// formid = 4, +// prompt = STRING_TOKEN(STR_RESTORE_DEFAULTS_PROMPT), +// help = STRING_TOKEN(STR_RESTORE_DEFAULTS_HELP), +// flags = 0, +// key = 0; +// +// save defaults, +// formid = 4, +// prompt = STRING_TOKEN(STR_SAVE_DEFAULTS_PROMPT), +// help = STRING_TOKEN(STR_SAVE_DEFAULTS_HELP), +// flags = 0, +// key = 0; +// +vfrStatementSaveRestoreDefaults : + << unsigned int KeyValue = 0; UINT32 LineNum; ResetFlags (); >> + ( IDS:Save << WriteOpByte (IDS->getLine(), EFI_IFR_SAVE_DEFAULTS_OP); >> + | IDR:Restore << WriteOpByte (IDR->getLine(), EFI_IFR_RESTORE_DEFAULTS_OP); >> + ) + Defaults "," + FormId "=" FRMID:Number "," << WriteWord (GetNumber (FRMID->getText(), FRMID->getLine(), 2)); + AddGotoReference (GetNumber (FRMID->getText(), FRMID->getLine(), 2), FRMID->getLine()); + >> + Prompt "=" getStringId "," + KH:Help "=" getStringId << LineNum = KH->getLine(); >> + { + "," FF:Flags "=" flagsField ( "\|" flagsField )* << LineNum = FF->getLine(); >> + } + { + "," Key "=" KNUM:Number << LineNum = KNUM->getLine(); KeyValue = GetNumber(KNUM->getText(), LineNum, 2); >> + } + << WriteFlagsKey (KeyValue, LineNum); >> + ";" + ; + +//***************************************************************************** +// +// PARSE: +// +// flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK +// +// +flagsField : + VAL:Number << SetFlags (GetNumber(VAL->getText(), VAL->getLine(), 4), VAL->getLine()); >> + | IF:InteractiveFlag << SetFlags (EFI_IFR_FLAG_INTERACTIVE, IF->getLine()); >> + | MF:ManufacturingFlag << SetFlags (EFI_IFR_FLAG_MANUFACTURING, MF->getLine()); >> + | DF:DefaultFlag << SetFlags (EFI_IFR_FLAG_DEFAULT, DF->getLine()); >> + | NV:NVAccessFlag << SetFlags (EFI_IFR_FLAG_NV_ACCESS, NV->getLine()); >> + | RR:ResetRequiredFlag << SetFlags (EFI_IFR_FLAG_RESET_REQUIRED, RR->getLine()); >> + | LC:LateCheckFlag << SetFlags (EFI_IFR_FLAG_LATE_CHECK, LC->getLine()); >> + ; + +dateTimeSubStatement : + Prompt "=" getStringId "," + Help "=" getStringId "," + << WriteByte (0, 0); WriteWord (0); >> // bogus flags and key + minMaxStepDefault << WriteMinMaxStepDefault (); >> + ; + +vfrStatementCheckBox : + << UINT32 LineNum, KeyValue = 0; ResetFlags (); >> + IDCB:CheckBox << WriteOpByte (IDCB->getLine(), EFI_IFR_CHECKBOX_OP); >> + VarId "=" vfrStructFieldName[1] "," + Prompt "=" getStringId "," + Help "=" getStringId "," + FF:Flags "=" flagsField ( "\|" flagsField )* "," << LineNum = FF->getLine(); >> + { + Key "=" KV:Number "," << LineNum = KV->getLine(); KeyValue = GetNumber(KV->getText(), LineNum, 2); >> + } + << WriteFlagsKey (KeyValue, LineNum); >> + EndCheckBox ";" + ; + +vfrStatementSubTitle : + IDS:Subtitle Text "=" << WriteOpByte (IDS->getLine(), EFI_IFR_SUBTITLE_OP); >> + getStringId // writes string indentifier + ";" + ; + +//***************************************************************************** +// +// PARSE: +// banner +// title = STRING_TOKEN(STR_BANNER_TITLE), +// line 1, +// align center; // or left or right +// +// banner, +// title = STRING_TOKEN(STR_BANNER_TITLE), timeout = 100; +// +vfrStatementBanner : + IDB:Banner { "," } << WriteOpByte (IDB->getLine(), EFI_IFR_BANNER_OP); >> + Title "=" getStringId "," + ( + Line VAL:Number "," << WriteWord (GetNumber(VAL->getText(), VAL->getLine(), 2)); >> + Align + ( Left << WriteByte (EFI_IFR_BANNER_ALIGN_LEFT, 0); >> + | Center << WriteByte (EFI_IFR_BANNER_ALIGN_CENTER, 0); >> + | Right << WriteByte (EFI_IFR_BANNER_ALIGN_RIGHT, 0); >> + ) ";" + | + Timeout "=" TO:Number ";" << WriteWord (GetNumber(TO->getText(), TO->getLine(), 2)); >> + << WriteByte (EFI_IFR_BANNER_TIMEOUT, 0); >> + ) + ; + +//***************************************************************************** +// +// PARSE: +// oneof varid = MyNv.OneOfData, +// prompt = STRING_TOKEN(STR_ONE_OF_PROMPT), +// help = STRING_TOKEN(STR_ONE_OF_HELP), +// option text = STRING_TOKEN(STR_ONE_OF_TEXT), +// value = 0, +// flags = DEFAULT | INTERACTIVE; +// +// supressif/grayoutif are supported inside oneof stmt. +// We do not restrict the number of oneOfOptionText to >=2, but >=1. +// The situation that all oneOfOptionText are suppressed is also possiable. +// +vfrStatementOneOf : + << ResetFlags (); >> + IDOO:OneOf << WriteOpByte (IDOO->getLine(), EFI_IFR_ONE_OF_OP); >> + VarId "=" vfrStructFieldName[2] "," + Prompt "=" getStringId "," // writes string identifier + Help "=" getStringId "," // writes string identifier + ( oneOfOptionText )+ // there must be at least 1 option to be choosed, not 2. + IDEOO:EndOneOf ";" << TestOneOfFlags (IDEOO->getLine()); WriteOpByte (IDEOO->getLine(), EFI_IFR_END_ONE_OF_OP); >> + ; + +//***************************************************************************** +// +// PARSE: +// +// orderedlist varid = MyNv.OrderedListData, +// prompt = STRING_TOKEN(STR_ORDERED_LIST_PROMPT), +// help = STRING_TOKEN(STR_ORDERED_LIST_HELP), +// option text = STRING_TOKEN(STR_ORDERED_LIST_TEXT), value = 0, flags = INTERACTIVE; +// -- additional option text -- +// endlist; +// +vfrStatementOrderedList : + << ResetFlags (); InitOrderedList(); >> + IDOL:OrderedList << WriteOpByte (IDOL->getLine(), EFI_IFR_ORDERED_LIST_OP); >> + VarId "=" vfrStructFieldNameArray[1] "," + Prompt "=" getStringId "," // writes string identifier + Help "=" getStringId "," // writes string identifier + orderedListOptionText ( orderedListOptionText )+ + IDEOL:EndList ";" << WriteOpByte (IDEOL->getLine(), EFI_IFR_END_OP); EndOrderedList(IDEOL->getLine()); >> + ; + +//***************************************************************************** +// +// PARSE: +// +// option text = STRING_TOKEN(STRING_ID), value = 0 flags = 99; +// +// Differs from the oneOfOptionText in that we don't allow the DEFAULT flag to +// be set, and value cannot be 0. +// +orderedListOptionText : + << UINT32 KeyValue = 0; >> + IDO:Option << WriteOpByte (IDO->getLine(), EFI_IFR_ONE_OF_OPTION_OP); >> + Text "=" getStringId "," // writes string identifier + Value "=" WVAL:Number "," << + if (GetNumber(WVAL->getText(), WVAL->getLine(), 2) == 0) { + PrintErrorMessage (WVAL->getLine(), "value=0 is invalid for ordered lists", NULL); + } else { + WriteWord (GetNumber(WVAL->getText(), WVAL->getLine(), 2)); + } + >> + FF:Flags "=" orderedListFlagsField + ("\|" orderedListFlagsField )* + { + "," Key "=" KV:Number << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >> + } + << WriteFlagsKey (KeyValue, FF->getLine()); >> + ";" << mOptionCount++; >> + ; + +//***************************************************************************** +// +// PARSE: +// +// flags = 0x10 | DEFAULT | MANUFACTURING | INTERACTIVE | NV_ACCESS | RESET_REQUIRED | LATE_CHECK +// +// The ordered list flags field cannot have a default. +// +orderedListFlagsField : + VAL:Number << SetFlags (GetNumber(VAL->getText(), VAL->getLine(), 4), VAL->getLine()); >> + | IF:InteractiveFlag << SetFlags (EFI_IFR_FLAG_INTERACTIVE, IF->getLine()); >> + | MF:ManufacturingFlag << SetFlags (EFI_IFR_FLAG_MANUFACTURING, MF->getLine()); >> + | NV:NVAccessFlag << SetFlags (EFI_IFR_FLAG_NV_ACCESS, NV->getLine()); >> + | RR:ResetRequiredFlag << SetFlags (EFI_IFR_FLAG_RESET_REQUIRED, RR->getLine()); >> + | LC:LateCheckFlag << SetFlags (EFI_IFR_FLAG_LATE_CHECK, LC->getLine()); >> + | DF:DefaultFlag << PrintWarningMessage (DF->getLine(), "DEFAULT flag not valid for ordered lists", NULL); >> + ; + +// +// Parse references to VFR structure field names of form "MyNvStructure.Field". +// This implementation is specific to strings, passwords, and references in an +// ordered list statement because we want to specify the size of the entire +// field, rather than just one element. Then call a function to write out its +// offset and length. +// +vfrStructFieldNameArray[int FieldWidth] : + << int ArrayIndex = 1; char IsArrayIndex = 0; >> + SName:StringIdentifier + "." + SFieldName:StringIdentifier + { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> } + << + WriteFieldOffset (1, + SName->getText(), + SName->getLine(), + SFieldName->getText(), + SFieldName->getLine(), + ArrayIndex, + IsArrayIndex, + FieldWidth, + 1 + ); + >> + ; + +// +// Parse references to VFR structure field names of form "MyNvStructure.Field", +// then call a function to write out its offset and length. +// +vfrStructFieldName[int FieldWidth] : + << int ArrayIndex = 1; char IsArrayIndex = 0; >> + SName:StringIdentifier + "." + SFieldName:StringIdentifier + { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> } + << + WriteFieldOffset (1, + SName->getText(), + SName->getLine(), + SFieldName->getText(), + SFieldName->getLine(), + ArrayIndex, + IsArrayIndex, + FieldWidth, + 0 + ); + >> + ; + +//***************************************************************************** +// +// PARSE: +// +// MyNvStructure.FieldName[4] +// +// Parse references to VFR structure field names of form "MyNvStructure.Field", +// then call a function to write out the offset with no length. +// +vfrStructFieldNameNL[int FieldWidth] : + << int ArrayIndex = 1; char IsArrayIndex = 0; >> + SName:StringIdentifier + "." + SFieldName:StringIdentifier + { OpenBracket AIndex:Number CloseBracket << ArrayIndex = GetNumber(AIndex->getText(), AIndex->getLine(), 4); IsArrayIndex = 1; >> } + << + WriteFieldOffset (0, + SName->getText(), + SName->getLine(), + SFieldName->getText(), + SFieldName->getLine(), + ArrayIndex, + IsArrayIndex, + FieldWidth, + 0 + ); + >> + ; + +//***************************************************************************** +// +// PARSE: +// suppressif TRUE OR FALSE; +// grayoutif FALSE OR TRUE; +// option text = STRING_TOKEN(STRING_ID), value = 0 flags = 99; +// option text = STRING_TOKEN(STRING_ID2), value = 1 flags = 98; +// endif; +// +oneOfOptionText : + suppressIfOptionText | + grayOutIfOptionText | + commonOptionText + ; + +suppressIfOptionText : + << ResetFlags (); >> + OPID:SuppressIf << WriteOpByte (OPID->getLine(), EFI_IFR_SUPPRESS_IF_OP); SetIfStart (OPID->getLine()); >> + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," + } + << WriteFlags (); >> // write the flags field + vfrBooleanExpression + ";" + { suppressIfGrayOutIf } ( commonOptionText )+ + ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >> + ; + +grayOutIfOptionText : + << ResetFlags (); >> + OPID:GrayOutIf << WriteOpByte (OPID->getLine(), EFI_IFR_GRAYOUT_IF_OP); SetIfStart (OPID->getLine()); >> + { + FF:Flags "=" flagsField ( "\|" flagsField )* "," + } + << WriteFlags (); >> // write the flags field + vfrBooleanExpression + ";" + { grayoutIfSuppressIf } ( commonOptionText )+ + ENDOP:EndIf ";" << WriteOpByte (ENDOP->getLine(), EFI_IFR_END_IF_OP); SetIfStart (0); >> + ; + +commonOptionText : + << UINT32 KeyValue = 0; >> + IDO:Option << WriteOpByte (IDO->getLine(), EFI_IFR_ONE_OF_OPTION_OP); >> + Text "=" getStringId "," // writes string identifier + Value "=" WVal:Number "," << WriteWord (GetNumber(WVal->getText(), WVal->getLine(), 2)); >> + FF:Flags "=" flagsField ("\|" flagsField )* + { + "," Key "=" KV:Number << KeyValue = GetNumber (KV->getText(), KV->getLine(), 2); >> + } + << WriteFlagsKey (KeyValue, FF->getLine()); >> + ";" << mOptionCount++; >> + ; + +// +// Gets a string identifier. It must be a numeric value of form: +// +// STRING_TOKEN(100) +// +getStringId : + << unsigned short StrId; >> + StringToken OpenParen + IdVal:Number << StrId = GetNumber (IdVal->getText(), IdVal->getLine(), 2); WriteStringIdWord (StrId); >> + CloseParen + ; + +//****************************************************************************** +// +// Parser class definition. +// +class EfiVfrParser { +<< +// +// Parser definitions go here +// +private: + STRUCT_DEFINITION *mFirstStructDefinition; + STRUCT_DEFINITION *mLastStructDefinition; + INT32 mNvDataStructSize; + INT32 mNonNvDataStructSize; + // + // Flag to indicate that we're processing a ideqid VFR statement so that + // we can do late checks on the statement. + // + INT32 mIdEqIdStmt; + INT32 mLastNVVariableDataSize; + GOTO_REFERENCE *mGotoReferences; + FORM_ID_VALUE *mFormIdValues; + VfrOpcodeHandler mOpcodeHandler; + UINT16_LIST *mUint16List; + UINT16_LIST *mLastUint16; + UINT16_LIST *mDefinedLabels; + UINT16_LIST *mDefinedVarStoreId; + UINT16_LIST *mLastDefinedVarStoreId; + UINT32 mMinimumValue, mMaximumValue, mStepValue, mDefaultValue; + UINT32 mStmtFlags; + UINT32 mSubStmtFlags; + UINT32 mSubStmtFlagsLineNum; + EFI_GUID mFormSetGuid; + UINT8 mNvDataStructDefined; + UINT16 mClass, mSubclass; + UINT32 mIfStart; + UINT32 mOptionCount; // how many "option" fields in a given statement + UINT32 mLastVarIdSize; + UINT8 mOutput; +public: + +VOID +EfiVfrParser::SetIfStart ( + UINT32 LineNum + ) +/*++ + +Routine Description: + Invoked during VFR parsing when an "if" is encountered. Save the + source line number so we can point to it if we don't find a + corresponding endif later. + +Arguments: + LineNum - source line number where the "if" was parsed. + +Returns: + None + +--*/ +{ + mIfStart = LineNum; +} +VOID +EfiVfrParser::SetClass ( + UINT32 LineNum, + UINT32 Value + ) +/*++ + +Routine Description: + Invoked during VFR parsing when a "class" statement is found. Check the + range on the class value and save it for later. + +Arguments: + LineNum - source line number where the class statement was parsed. + Value - the class value + +Returns: + None + +--*/ +{ + if (Value & 0xFFFF0000) { + PrintWarningMessage (LineNum, NULL, "class value exceeds maximum allowed"); + } + mClass |= (UINT16)Value; +} +VOID +EfiVfrParser::SetSubclass ( + UINT32 LineNum, + UINT32 Value + ) +/*++ + +Routine Description: + Invoked during VFR parsing when a subclass statement is found. Check the + range on the value and save it for later. + +Arguments: + LineNum - source line number where the class statement was parsed. + Value - the subclass value from the VFR statement + +Returns: + None + +--*/ +{ + if (Value & 0xFFFF0000) { + PrintWarningMessage (LineNum, NULL, "subclass value exceeds maximum allowed"); + } + mSubclass |= (UINT16)Value; +} +VOID EfiVfrParser::WriteClass () +{ + WriteWord (mClass); + mClass = 0; +} +VOID EfiVfrParser::WriteSubclass () +{ + WriteWord (mSubclass); + mSubclass = 0; +} +VOID EfiVfrParser::WriteIfrBytes () +{ + mOpcodeHandler.WriteIfrBytes (); +} +VOID +EfiVfrParser::WriteFlagsKey ( + UINT32 KeyValue, + UINT32 LineNum + ) +/*++ + +Routine Description: + Write out the flags and key values from the previous VFR statement. + Many statements take a flags/key pair. If not specified, then 0 + values are written out. However do not allow an interactive flags field + to be specified if no key value is specified. Also, if NV_ACCESS flag + is set but INTERACTIVE is not, then set interactive and issue a warning. + +Arguments: + KeyValue - the key value from the VFR statement + LineNum - source line number where the statement was parsed + +Returns: + None + +--*/ +{ + if ((mSubStmtFlags & EFI_IFR_FLAG_INTERACTIVE) && (KeyValue == 0)) { + PrintErrorMessage (LineNum, NULL, "invalid or missing key value - required with INTERACTIVE"); + } + if ((mSubStmtFlags & EFI_IFR_FLAG_NV_ACCESS) && !(mSubStmtFlags & EFI_IFR_FLAG_INTERACTIVE)) { + PrintWarningMessage (LineNum, NULL, "NV_ACCESS without INTERACTIVE has no effect -- setting INTERACTIVE"); + mSubStmtFlags |= EFI_IFR_FLAG_INTERACTIVE; + } + WriteFlags (); + WriteWord (KeyValue); +} +VOID +EfiVfrParser::InitOrderedList () +{ + mOptionCount = 0; +} +VOID +EfiVfrParser::EndOrderedList ( + UINT32 LineNum + ) +{ + if (mLastVarIdSize < mOptionCount) { + PrintErrorMessage (LineNum, NULL, "number of options exceeds the variable store size"); + } +} +VOID +EfiVfrParser::ResetFlags () +/*++ + +Routine Description: + + Flags are set for each substatement in a given one-of statement. + To make sure there are no conflicts, for example setting DEFAULT on + more than one substatement, we keep track of the flags at a statement + level and a substatement level. This function resets the flags so + we get a fresh start. + +Arguments: + None + +Returns: + None + +--*/ +{ + mStmtFlags = 0; + mSubStmtFlagsLineNum = 0; + mSubStmtFlags = 0; +} +// +// Test validity of flags value for a one-of statement. +// +VOID +EfiVfrParser::TestOneOfFlags ( + UINT32 LineNum + ) +{ + // + // One of the fields must have had the default bit set + // + if ((mStmtFlags & EFI_IFR_FLAG_DEFAULT) == 0) { + PrintWarningMessage (LineNum, "default value must be specified", NULL); + } +} +VOID +EfiVfrParser::SetFlags ( + UINT32 Flags, + UINT32 LineNum + ) +{ + // + // Check for redefinitions and invalid combinations + // + if (mStmtFlags & Flags & EFI_IFR_FLAG_MANUFACTURING) { + PrintErrorMessage (LineNum, "MANUFACTURING", "a field with this flag already defined"); + } + if (mStmtFlags & Flags & EFI_IFR_FLAG_DEFAULT) { + PrintErrorMessage (LineNum, "DEFAULT", "a field with this flag already defined"); + } + mSubStmtFlags |= Flags; + mSubStmtFlagsLineNum = LineNum; +} +VOID +EfiVfrParser::WriteFlags () +{ + // + // Check value for validity + // + if (mSubStmtFlags & ~(EFI_IFR_FLAG_DEFAULT | + EFI_IFR_FLAG_MANUFACTURING | + EFI_IFR_FLAG_INTERACTIVE | + EFI_IFR_FLAG_NV_ACCESS | + EFI_IFR_FLAG_RESET_REQUIRED | + EFI_IFR_FLAG_LATE_CHECK )) { + PrintWarningMessage (mSubStmtFlagsLineNum, "invalid bits defined in flag", NULL); + } + WriteByte ((UINT8)mSubStmtFlags, 'F'); + // + // We can now clear the substatement flags + // + mStmtFlags |= mSubStmtFlags; + mSubStmtFlags = 0; +} +// +// When we parse a min/max/step/default sequence, save off the values for +// later use. Call this first to init the values. +// +VOID +EfiVfrParser::InitMinMaxStepDefault () +{ + mMinimumValue = 0; + mMaximumValue = 0; + mStepValue = 1; + mDefaultValue = 0; +} +VOID +EfiVfrParser::WriteMinMaxStepDefault () +{ + WriteWord (mMinimumValue); + WriteWord (mMaximumValue); + WriteWord (mStepValue); + WriteWord (mDefaultValue); +} +VOID +EfiVfrParser::SetMinMaxStepDefault ( + UINT16 Value, + INT32 MMSD, + INT32 LineNum + ) +{ + UINT16 TempValue; + // + // Min specified + // + if (MMSD == 0) { + mMinimumValue = Value; + mDefaultValue = Value; + // + // Max specified + // + } else if (MMSD == 1) { + mMaximumValue = Value; + // + // If min > max, then swap the values. That includes resetting the default + // value as well. + // + if (mMinimumValue > mMaximumValue) { + PrintWarningMessage (LineNum, NULL, "maximum < minimum"); + TempValue = Value; + mMaximumValue = mMinimumValue; + mMinimumValue = TempValue; + mDefaultValue = mMinimumValue; + } + // + // Step specified + // + } else if (MMSD == 2) { + mStepValue = Value; + // + // Default specified. Make sure min <= default <= max. + // + } else if (MMSD == 3) { + mDefaultValue = Value; + if (mMinimumValue > Value) { + PrintErrorMessage (LineNum, NULL, "default value < minimum value"); + } else if (Value > mMaximumValue) { + PrintErrorMessage (LineNum, NULL, "default value > maximum value"); + } + } else { + PrintErrorMessage (LineNum, "application error", "internal MMSD error"); + } +} +VOID +EfiVfrParser::AddLabel ( + UINT32 LabelNumber, + UINT32 LineNum + ) +{ + UINT16_LIST *Label; + + // + // Added a label from the user VFR script. Make sure they haven't already + // defined the same label elsewhere + // + for (Label = mDefinedLabels; Label != NULL; Label = Label->Next) { + if (Label->Value == LabelNumber) { + PrintErrorMessage (LineNum, NULL, "label already defined"); + PrintErrorMessage (Label->LineNum, NULL, "previous definition of redefined label"); + break; + } + } + Label = (UINT16_LIST *)malloc (sizeof (UINT16_LIST)); + if (Label == NULL) { + PrintErrorMessage (0, NULL, "memory allocation error"); + return; + } + memset ((char *)Label, 0, sizeof (UINT16_LIST)); + Label->Value = LabelNumber; + Label->LineNum = LineNum; + Label->Next = mDefinedLabels; + mDefinedLabels = Label; +} +VOID +EfiVfrParser::QueueIdEqValList ( + UINT16 Value + ) +{ + UINT16_LIST *U16; + + U16 = (UINT16_LIST *)malloc (sizeof (UINT16_LIST)); + if (U16 == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failed"); + } else { + memset ((char *)U16, 0, sizeof (UINT16_LIST)); + U16->Value = Value; + if (mUint16List == NULL) { + mUint16List = U16; + } else { + mLastUint16->Next = U16; + } + mLastUint16 = U16; + } +} +VOID +EfiVfrParser::FlushQueueIdEqValList () +{ + UINT32 Count; + + // + // We queued up a list of IdEqValList items. The IFR requires a count + // followed by the actual values. Do it. + // + Count = 0; + mLastUint16 = mUint16List; + while (mLastUint16 != NULL) { + Count++; + mLastUint16 = mLastUint16->Next; + } + // BUGBUG -- check for more than 16K items? + WriteWord (Count); + // + // Now write the values. + // + mLastUint16 = mUint16List; + while (mLastUint16 != NULL) { + WriteWord ((UINT32)mLastUint16->Value); + mLastUint16 = mLastUint16->Next; + } + // + // Free up the list + // + mLastUint16 = mUint16List; + while (mUint16List != NULL) { + mLastUint16 = mUint16List->Next; + free (mUint16List); + mUint16List = mLastUint16; + } +} +VOID +EfiVfrParser::PrintErrorMessage ( + UINT32 LineNum, + INT8 *Msg1, + INT8 *Msg2 + ) +{ + char *FileName; + + if (LineNum != 0) { + FileName = ConvertLineNumber ((UINT32 *)&LineNum); + Error (FileName, LineNum, 0, Msg1, Msg2); + } else { + Error (PROGRAM_NAME, 0, 0, Msg1, Msg2); + } +} +VOID +EfiVfrParser::PrintWarningMessage ( + UINT32 LineNum, + INT8 *Msg1, + INT8 *Msg2 + ) +{ + char *FileName; + + if (LineNum != 0) { + FileName = ConvertLineNumber ((UINT32 *)&LineNum); + Warning (FileName, LineNum, 0, Msg1, Msg2); + } else { + Warning (PROGRAM_NAME, 0, 0, Msg1, Msg2); + } +} +VOID +EfiVfrParser::syn ( + ANTLRAbstractToken *Tok, + ANTLRChar *Egroup, + SetWordType *Eset, + ANTLRTokenType ETok, + INT32 Huh + ) +/*++ + +Routine Description: + Called by the parser base class as a result of parse syntax errors. + +Arguments: + Tok - token that caused the error + Egroup - not sure + Eset - index in token table of the expected token + Huh - not sure + +Returns: + NA + +--*/ +{ + char *FileName; + UINT32 LineNum; + + LineNum = Tok->getLine (); + FileName = ConvertLineNumber ((UINT32 *)&LineNum); + // + // Sometimes the token number is 0, in which case I don't know what to + // print. + // + if (ETok == 0) { + Error (FileName, LineNum, 0, Tok->getText (), "unexpected token"); + } else { + // + // If we were expecting an endif, then report the line where the corresponding + // IF began. + // + if ((strcmp (_token_tbl[ETok], "endif") == 0) && (mIfStart != 0)) { + LineNum = mIfStart; + FileName = ConvertLineNumber (&LineNum); + Error (FileName, LineNum, 0, "statement missing corresponding endif", NULL); + } else { + Error (FileName, LineNum, 0, Tok->getText (), "expected %s", _token_tbl[ETok]); + } + } +} + +VOID +EfiVfrParser::init() +/*++ + +Routine Description: + Initializations function for our parser. + +Arguments: + None. + +Returns: + None. + +--*/ +{ + ANTLRParser::init(); + + // + // Used for queuing a variable list of UINT16's + // + mUint16List = NULL; + mLastUint16 = NULL; + mFirstStructDefinition = NULL; + mLastStructDefinition = NULL; + mNvDataStructSize = 0; + mNonNvDataStructSize = 0; + mNvDataStructDefined = 0; + mGotoReferences = NULL; + mFormIdValues = NULL; + mDefinedLabels = NULL; + mClass = 0; + mSubclass = 0; + mIfStart = 0; + mDefinedVarStoreId = NULL; + mLastDefinedVarStoreId = NULL; + mIdEqIdStmt = 0; + mLastNVVariableDataSize = 0; + + memset ((char *)&mFormSetGuid, 0, sizeof (EFI_GUID)); +} +// +// Destructor for the parser. +// +EfiVfrParser::~EfiVfrParser(VOID) +{ + Cleanup(); +} +VOID +EfiVfrParser::Cleanup (VOID) +/*++ + +Routine Description: + Free memory allocated during parsing + +Arguments: + None. + +Returns: + None. + +--*/ +{ + STRUCT_DEFINITION *NextStruct; + STRUCT_FIELD_DEFINITION *NextField; + UINT8 Buff[6]; + UINT16_LIST *NextU16List; + + // + // Free up the structure definitions if any + // + while (mFirstStructDefinition != NULL) { + // + // Free up all the fields for this struct + // + while (mFirstStructDefinition->Field != NULL) { + NextField = mFirstStructDefinition->Field->Next; + free (mFirstStructDefinition->Field->Name); + free (mFirstStructDefinition->Field); + mFirstStructDefinition->Field = NextField; + } + NextStruct = mFirstStructDefinition->Next; + free (mFirstStructDefinition->Name); + free (mFirstStructDefinition); + mFirstStructDefinition = NextStruct; + } + // + // Free up the goto references and form id defines + // + FreeGotoReferences (); + // + // Free up label list + // + while (mDefinedLabels != NULL) { + NextU16List = mDefinedLabels->Next; + delete (mDefinedLabels); + mDefinedLabels = NextU16List; + } + // + // Free up the list of defined variable storage IDs + // + while (mDefinedVarStoreId != NULL) { + NextU16List = mDefinedVarStoreId->Next; + delete (mDefinedVarStoreId); + mDefinedVarStoreId = NextU16List; + } +} + +INT32 +EfiVfrParser::AtoX ( + INT8 *HexString, + INT32 NumBytes, + UINT32 *HexValue + ) +/*++ + +Routine Description: + Given a pointer to a ascii hex string, convert to a number with the given + number of bytes. + +Arguments: + HexString - pointer to a string of format 30BCA + Size - number of bytes to convert + HexValue - return result + +Returns: + The number of bytes converted. + +--*/ +{ + INT32 Count; + INT32 Value; + + *HexValue = 0; + Count = 0; + while (Count < NumBytes) { + if ((*HexString >= '0') && (*HexString <= '9')) { + Value = *HexString - '0'; + } else if ((*HexString >= 'a') && (*HexString <= 'f')) { + Value = *HexString - 'a' + 10; + } else if ((*HexString >= 'A') && (*HexString <= 'F')) { + Value = *HexString - 'A' + 10; + } else { + return Count; + } + HexString++; + *HexValue = (*HexValue << 4) | Value; + if ((*HexString >= '0') && (*HexString <= '9')) { + Value = *HexString - '0'; + } else if ((*HexString >= 'a') && (*HexString <= 'f')) { + Value = *HexString - 'a' + 10; + } else if ((*HexString >= 'A') && (*HexString <= 'F')) { + Value = *HexString - 'A' + 10; + } else { + return Count; + } + *HexValue = (*HexValue << 4) | Value; + HexString++; + Count++; + } + return Count; +} +VOID +EfiVfrParser::WriteGuidValue ( + UINT32 TokenLineNum, + INT8 *G1, + INT8 *G2, + INT8 *G3, + INT8 *G4, + INT8 *G5, + INT8 *G6, + INT8 *G7, + INT8 *G8, + INT8 *G9, + INT8 *G10, + INT8 *G11 + ) +/*++ + +Routine Description: + A Guid was parsed, likely of format: + #define MY_GUID { 0x12345678, 0xAABB, 0xCCDD, 0xEE, 0xFF, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66 } + + Write out the value. + +Arguments: + TokenLineNum - line number where the guid was used + G1-G11 - the 11 fields of the guid value + +Returns: + None. + +--*/ +{ + UINT32 Value; + INT32 Loop; + INT8 *Cptr; + + mFormSetGuid.Data1 = GetNumber (G1, TokenLineNum, 4); + mFormSetGuid.Data2 = (UINT16)GetNumber (G2, TokenLineNum, 2); + mFormSetGuid.Data3 = (UINT16)GetNumber (G3, TokenLineNum, 2); + mFormSetGuid.Data4[0] = (UINT8)GetNumber (G4, TokenLineNum, 1); + mFormSetGuid.Data4[1] = (UINT8)GetNumber (G5, TokenLineNum, 1); + mFormSetGuid.Data4[2] = (UINT8)GetNumber (G6, TokenLineNum, 1); + mFormSetGuid.Data4[3] = (UINT8)GetNumber (G7, TokenLineNum, 1); + mFormSetGuid.Data4[4] = (UINT8)GetNumber (G8, TokenLineNum, 1); + mFormSetGuid.Data4[5] = (UINT8)GetNumber (G9, TokenLineNum, 1); + mFormSetGuid.Data4[6] = (UINT8)GetNumber (G10, TokenLineNum, 1); + mFormSetGuid.Data4[7] = (UINT8)GetNumber (G11, TokenLineNum, 1); + + WriteDWord (mFormSetGuid.Data1, 'G'); + WriteWord (mFormSetGuid.Data2); + WriteWord (mFormSetGuid.Data3); + WriteByte (mFormSetGuid.Data4[0], 0); + WriteByte (mFormSetGuid.Data4[1], 0); + WriteByte (mFormSetGuid.Data4[2], 0); + WriteByte (mFormSetGuid.Data4[3], 0); + WriteByte (mFormSetGuid.Data4[4], 0); + WriteByte (mFormSetGuid.Data4[5], 0); + WriteByte (mFormSetGuid.Data4[6], 0); + WriteByte (mFormSetGuid.Data4[7], 0); +} +VOID +EfiVfrParser::WriteFieldOffset ( + INT8 WriteLength, + INT8 *StructName, + INT32 LineNum1, + INT8 *FieldName, + INT32 LineNum2, + INT32 ArrayIndex, + INT8 IsArrayIndex, + INT32 FieldWidth, + INT8 WriteArraySize + ) +/*++ + +Routine Description: + A VFR script referenced the NV store structure. Given the structure's name + and the field's name, write the offset of the field to the output file. + +Arguments: + WriteLength - write the field length byte out + StructName - name of the NV store structure + LineNum1 - line number in the VFR where we are (for error printing) + FieldName - the name of the field within the NV store structure + LineNum2 - line number in the VFR where FieldName is referenced + ArrayIndex - the index specified, for example NV_DATA.Field[ArrayIndex] + IsArrayIndex - non-zero if an array index was specified + FieldWidth - expected size for the Field (1 byte? 2 bytes?) + WriteArraySize - write the size of the entire field, not the size of a single element + +Returns: + None. + +--*/ +{ + STRUCT_DEFINITION *StructDef; + STRUCT_FIELD_DEFINITION *FieldDef; + UINT32 Offset; + UINT32 VarSize; + INT8 Msg[100]; + // + // If we're writing an array size, then they better have referenced the field without an + // index. + // + if (WriteArraySize && IsArrayIndex) { + sprintf (Msg, "array index specified where an array is required"); + PrintErrorMessage (LineNum2, FieldName, Msg); + return; + } + + // + // The reference index starts at 1 not 0 + // + if (IsArrayIndex && (ArrayIndex < 1)) { + printf ("WARNING: array index shouldn't be less than 1"); + } + // + // Look through our list of known structures for a match + // + for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) { + // + // Check for matching structure name + // + if (strcmp (StructDef->Name, StructName) == 0) { + // + // Mark it as referenced (for debug purposes only). Check the + // flag that indicates that we have already found a varstore VFR + // statement for it. + // + StructDef->Referenced++; + if (StructDef->VarStoreIdValid == 0) { + // + // Set it valid so we don't flag it multiple times, then emit the error + // + StructDef->VarStoreIdValid = 1; + PrintErrorMessage (LineNum1, StructName, "varstore statement missing for this variable store"); + } + // + // Let the opcode-handler know which variable storage we're now using + // + if (mIdEqIdStmt) { + mOpcodeHandler.SetSecondaryVarStoreId (StructDef->VarStoreId); + } else { + mOpcodeHandler.SetVarStoreId (StructDef->VarStoreId); + } + // + // Found matching structure name. Now find the matching field name + // + for (FieldDef = StructDef->Field; FieldDef != NULL; FieldDef = FieldDef->Next) { + if (strcmp (FieldDef->Name, FieldName) == 0) { + // + // Make sure the variable size is valid + // + if ((FieldWidth != 0) && (FieldDef->DataSize > FieldWidth)) { + sprintf (Msg, "field width exceeds %d byte%c", FieldWidth, FieldWidth == 1 ? ' ' : 's'); + PrintErrorMessage (LineNum2, FieldName, Msg); + } + // + // If they specified an index (MyVfrData.FieldX[10]), then make sure that the + // data structure was declared as an array, and that the index is in bounds. + // If they did not specify an index, then we'll assume 0. This is required for + // strings. + // + if (IsArrayIndex) { + VarSize = FieldDef->DataSize; + if (FieldDef->IsArray == 0) { + PrintErrorMessage (LineNum2, FieldName, "field is not declared as an array"); + return; + } + if (FieldDef->ArrayLength < ArrayIndex) { + PrintErrorMessage (LineNum2, FieldName, "array index exceeds declared size of field"); + return; + } + } else { + if (FieldDef->IsArray) { + VarSize = FieldDef->DataSize * FieldDef->ArrayLength; + } else { + VarSize = FieldDef->DataSize; + } + } + // + // If we're in the middle of a ideqid VFR statement, then this is the second + // variable ID that we're now processing. Make sure that its size is the same + // as the first variable. + // + if (mIdEqIdStmt) { + if (mLastVarIdSize != VarSize) { + PrintErrorMessage (LineNum2, FieldName, "variables must have the same size"); + return; + } + } + mLastVarIdSize = VarSize; + // + // If we're supposed to write an array size, then require it to be an array + // + if (WriteArraySize && !FieldDef->IsArray) { + PrintErrorMessage (LineNum2, FieldName, "array required"); + return; + } + // + // Write the variable offset and size. If we're in the non-NV structure, then + // set the offset beyond the NV data structure size. + // + Offset = FieldDef->Offset + FieldDef->DataSize * (ArrayIndex - 1); + if (StructDef->IsNonNV) Offset += mNvDataStructSize; + WriteWord (Offset); + if (WriteLength) { + if (WriteArraySize) { + if (FieldDef->DataSize * FieldDef->ArrayLength > 255) { + PrintErrorMessage (LineNum2, FieldName, "array size exceeds 255 maximum encoding limit"); + return; + } + WriteByte (FieldDef->DataSize * FieldDef->ArrayLength, 0); + } else { + WriteByte (FieldDef->DataSize, 0); + } + } + return; + } + } + sprintf (Msg, "structure %s does not have a field named '%s'", StructName, FieldName); + PrintErrorMessage (LineNum2, Msg, NULL); + PrintErrorMessage (StructDef->LineNum, "see structure definition", NULL); + return; + } + } + // + // The structure was not found in the defined list. See if it's the "Date" structure + // + if (strcmp (StructName, "Date") == 0) { + // + // BUGBUG -- remove support for Date and Time as valid structure + // names. They should use the NON_NV_DATA_MAP structure for this. + // + // Someone specified Date.Years|Months|Days + // BUGBUG -- define some constants for the IDs used here + // Length == 0 implies that this is not user NV data storage. + // + if (strcmp (FieldName, "Year") == 0) { + // + // Write ID (offset), ID, and size + // + WriteWord (mNvDataStructSize + mNonNvDataStructSize + 0); + if (WriteLength) { + WriteByte (0, 0); + } + } else if (strcmp (FieldName, "Month") == 0) { + // + // Write ID (offset), ID, and size + // + WriteWord (mNvDataStructSize + mNonNvDataStructSize + 2); + if (WriteLength) { + WriteByte (0, 0); + } + } else if (strcmp (FieldName, "Day") == 0) { + // + // Write ID (offset), ID, and size + // + WriteWord (mNvDataStructSize + mNonNvDataStructSize + 4); + if (WriteLength) { + WriteByte (0, 0); + } + } else { + PrintErrorMessage (LineNum1, FieldName, "expected valid field name TheYear/TheMonth/TheDay"); + } + return; + } else if (strcmp (StructName, "Time") == 0) { + // + // Someone specified Time.Hours|Minutes|Seconds + // BUGBUG -- define some constants for the IDs used here + // + if (strcmp (FieldName, "Hours") == 0) { + // + // Write ID (offset), ID, and size + // + WriteWord (mNvDataStructSize + mNonNvDataStructSize + 6); + if (WriteLength) { + WriteByte (0, 0); + } + } else if (strcmp (FieldName, "Minutes") == 0) { + // + // Write ID (offset), ID, and size + // + WriteWord (mNvDataStructSize + mNonNvDataStructSize + 8); + if (WriteLength) { + WriteByte (0, 0); + } + } else if (strcmp (FieldName, "Seconds") == 0) { + // + // Write ID (offset), ID, and size + // + WriteWord (mNvDataStructSize + mNonNvDataStructSize + 10); + if (WriteLength) { + WriteByte (0, 0); + } + } else { + PrintErrorMessage (LineNum1, FieldName, "expected valid field name Hours/Minutes/Seconds"); + } + return; + } else { + PrintErrorMessage (LineNum1, StructName, "undefined structure"); + return; + } +} +VOID +EfiVfrParser::StartStructDefinition ( + INT32 IsNonNV, + INT32 LineNum + ) +/*++ + +Routine Description: + Called when we encounter a new "struct _MY_STRUCT..." statement while parsing. + Initialize internal data and structures for parsing the fields of the structure. + +Arguments: + LineNum - line number in the source file (for error reporting purposes) + IsNonNv - flag indicating (if nonzero) that the variable referred to is not in + the standard NV store. +Returns: + None + +--*/ +{ + STRUCT_DEFINITION *StructDef; + // + // Allocate memory for the structure record + // + StructDef = (STRUCT_DEFINITION *)malloc (sizeof (STRUCT_DEFINITION)); + memset (StructDef, 0, sizeof (STRUCT_DEFINITION)); + StructDef->LineNum = LineNum; + // + // Set flag indicating non-NV data structure or not + // + StructDef->IsNonNV = IsNonNV; + // + // Add it to the end of our linked list. If it's the first one + // defined, then it's the default varstore ID, so set it valid. + // + if (mFirstStructDefinition == NULL) { + mFirstStructDefinition = StructDef; + StructDef->VarStoreIdValid = 1; + } else { + mLastStructDefinition->Next = StructDef; + } + mLastStructDefinition = StructDef; +} +VOID +EfiVfrParser::EndStructDefinition ( + INT8 *StructName, + INT32 LineNum + ) +{ + STRUCT_DEFINITION *StructDef; + STRUCT_FIELD_DEFINITION *FieldDef; + UINT32 Offset; + // + // Make sure they have not already defined a structure with this name + // + for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) { + if ((StructDef->Name != NULL) && (strcmp (StructDef->Name, StructName) == 0)) { + PrintErrorMessage (LineNum, StructName, "structure with this name already defined"); + // + // Fall through and fill in the rest of the structure information. We do + // this because the structure has already been added to our global list, + // so will be used elsewhere, so we want it to contain valid fields. + // + } + } + // + // Allocate memory for the structure name + // + mLastStructDefinition->Name = (char *)malloc (strlen (StructName) + 1); + strcpy (mLastStructDefinition->Name, StructName); + // + // Compute the structure size, and the offsets to each field + // + Offset = 0; + for (FieldDef = mLastStructDefinition->Field; FieldDef != NULL; FieldDef = FieldDef->Next) { + FieldDef->Offset = Offset; + Offset += FieldDef->ArrayLength * FieldDef->DataSize; + } + mLastStructDefinition->Size = Offset; + // + // Go through all the structure we have so far and figure out (if we can) + // the size of the non-NV storage. We also assume that the first structure + // definition is the primary/default storage for the VFR form. + // + if (mNonNvDataStructSize == 0) { + for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) { + if (StructDef->IsNonNV) { + mNonNvDataStructSize = StructDef->Size; + break; + } + } + } + if (mNvDataStructSize == 0) { + for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) { + if (StructDef->IsNonNV == 0) { + mNvDataStructSize = StructDef->Size; + break; + } + } + } +} +VOID +EfiVfrParser::AddStructField ( + INT8 *FieldName, + INT32 LineNum, + INT32 DataSize, + INT32 ArrayLength, + INT8 IsArray + ) +/*++ + +Routine Description: + We're parsing the VFR structure definition. Add another defined field to + our definition. + +Arguments: + FieldName - name of the field in the structure. + LineNum - the line number from the input (preprocessor output) file + DataSize - the size of the field (1, 2, or 4 bytes) + ArrayLength - the number of elements (for array) + IsArray - non-zero if the field is an array + +Returns: + None. + +--*/ +{ + STRUCT_FIELD_DEFINITION *FieldDef; + STRUCT_FIELD_DEFINITION *Temp; + // + // Make sure we don't already have a field of this name in our structure + // + for (FieldDef = mLastStructDefinition->Field; FieldDef != NULL; FieldDef = FieldDef->Next) { + if (strcmp (FieldDef->Name, FieldName) == 0) { + PrintErrorMessage (LineNum, FieldName, "field with this name already defined"); + return; + } + } + // + // If it's an array, then they better not have a size of 0. For example: + // UINT8 MyBytes[0]; + // + if (IsArray && (ArrayLength <= 0)) { + PrintErrorMessage (LineNum, FieldName, "invalid array size"); + return; + } + // + // Allocate memory for a new structure field definition + // + FieldDef = (STRUCT_FIELD_DEFINITION *)malloc (sizeof (STRUCT_FIELD_DEFINITION)); + memset ((char *)FieldDef, 0, sizeof (STRUCT_FIELD_DEFINITION)); + FieldDef->ArrayLength = ArrayLength; + FieldDef->DataSize = DataSize; + FieldDef->IsArray = IsArray; + FieldDef->Name = (char *)malloc (strlen (FieldName) + 1); + strcpy (FieldDef->Name, FieldName); + // + // Add it to the end of the field list for the currently active structure + // + if (mLastStructDefinition->Field == NULL) { + mLastStructDefinition->Field = FieldDef; + } else { + mLastStructDefinition->LastField->Next = FieldDef; + } + mLastStructDefinition->LastField = FieldDef; +} +VOID +EfiVfrParser::AddVarStore ( + INT8 *StructName, // actual name of the structure + INT8 *VarName, // actual NV variable name + UINT16 VarStoreId, // key value + INT32 LineNum // parse line number (for error reporting) + ) +/*++ + +Routine Description: + Called while parsing a varstore statement. Add the variable store + to our linked list. + +Arguments: + StructName - the name of the typedef'ed structure to use + VarName - the NV variable name as specified in the varstore statement + VarStoreId - the variable store ID as specified in the varstore statememt + LineNum - the line number from the input (preprocessor output) file + +Returns: + None. + +--*/ +{ + STRUCT_DEFINITION *StructDef; + UINT16_LIST *L16Ptr; + // + // Go through our list of previously-defined variable store IDs and + // make sure this one is not a duplicate in name or key value. + // + for (L16Ptr = mDefinedVarStoreId; L16Ptr != NULL; L16Ptr = L16Ptr->Next) { + if (L16Ptr->Value == VarStoreId) { + PrintErrorMessage (LineNum, "variable storage key already used", NULL); + PrintErrorMessage (L16Ptr->LineNum, "previous usage of storage key", NULL); + } + } + // + // Key value of 0 is invalid since that's assigned by default to the default + // variable store (the first structure parsed). + // + if (VarStoreId == 0) { + PrintErrorMessage (LineNum, "variable storage key of 0 is invalid", NULL); + } + // + // Create a new element to add to the list + // + L16Ptr = (UINT16_LIST *)malloc(sizeof (UINT16_LIST)); + memset (L16Ptr, 0, sizeof (UINT16_LIST)); + L16Ptr->LineNum = LineNum; + L16Ptr->Value = VarStoreId; + if (mDefinedVarStoreId == NULL) { + mDefinedVarStoreId = L16Ptr; + } else { + mLastDefinedVarStoreId->Next = L16Ptr; + } + mLastDefinedVarStoreId = L16Ptr; + // + // Find the structure definition with this name + // + for (StructDef = mFirstStructDefinition; StructDef != NULL; StructDef = StructDef->Next) { + if (strcmp (StructDef->Name, StructName) == 0) { + // + // Make sure they did not already define a variable storage ID + // for this structure. + // + if (StructDef->VarStoreId != 0) { + PrintErrorMessage (LineNum, StructName, "variable storage already defined for this structure"); + PrintErrorMessage (StructDef->VarStoreLineNum, StructName, "previous definition for variable storage"); + } + StructDef->VarStoreId = VarStoreId; + StructDef->VarStoreIdValid = 1; + StructDef->VarStoreLineNum = LineNum; + WriteWord (StructDef->Size); + while (*VarName) { + WriteByte(*VarName, 0); + VarName++; + } + WriteByte(0,0); + return; + } + } + PrintErrorMessage (LineNum, StructName, "structure with this name not defined"); +} +VOID +EfiVfrParser::WriteDWord ( + UINT32 Value, + UINT8 KeyByte + ) +/*++ + +Routine Description: + During parsing, we came upon some code that requires a 32-bit value be + written to the VFR binary file. Queue up the 4 bytes. + +Arguments: + Value - the 32-bit value to write + KeyByte - a single character which gets written out beside the first byte. + This is used to tag the data in the output file so that during + debug you have an idea what the value is. + +Returns: + None. + +--*/ +{ + // + // Write 4 bytes, little endian. Specify a key byte only on the first one + // + mOpcodeHandler.AddByte ((UINT8)Value, KeyByte); + Value \>>= 8; + mOpcodeHandler.AddByte ((UINT8)Value, 0); + Value \>>= 8; + mOpcodeHandler.AddByte ((UINT8)Value, 0); + Value \>>= 8; + mOpcodeHandler.AddByte ((UINT8)Value, 0); +} +VOID +EfiVfrParser::WriteOpByte ( + UINT32 LineNum, + UINT8 ByteValue + ) +/*++ + +Routine Description: + + During parsing, we came upon a new VFR opcode. At this point we flush + the output queue and then queue up this byte (with 'O' for opcode tag). + +Arguments: + + ByteValue - opcode value + +Returns: + + None. + +--*/ +{ + mOpcodeHandler.AddOpcodeByte (ByteValue, LineNum); +} +VOID +EfiVfrParser::WriteByte ( + UINT8 ByteValue, + UINT8 Key + ) +/*++ + +Routine Description: + + During parsing of the VFR we spoonfeed this function with bytes to write to + the output VFR binary file. This function simply queues up the bytes, and + the queue gets flushed each time a new VFR opcode is encountered. + +Arguments: + + ByteValue - raw byte to write + Key - character to tag the byte with when we write ByteValue to the + output file. + +Returns: + + None. + +--*/ +{ + mOpcodeHandler.AddByte (ByteValue, Key); +} +VOID +EfiVfrParser::WriteWord ( + UINT32 Value + ) +/*++ + +Routine Description: + During VFR parsing we came upon a case where we need to write out a + 16-bit value. Queue it up. + +Arguments: + Value - value to write. + +Returns: + None. + +--*/ +{ + mOpcodeHandler.AddByte ((UINT8)Value, 0); + mOpcodeHandler.AddByte ((UINT8)((Value \>> 8) & 0xFF), 0); +} +VOID +EfiVfrParser::WriteStringIdWord ( + UINT16 WordValue + ) +{ + mOpcodeHandler.AddByte ((UINT8)WordValue, 'S'); + mOpcodeHandler.AddByte ((UINT8)((WordValue \>> 8) & 0xFF), 0); +} +VOID +EfiVfrParser::FreeGotoReferences () +/*++ + +Routine Description: + Called during cleanup to free up the memory we allocated when + keeping track of VFR goto statements. + +Arguments: + None + +Returns: + None + +--*/ +{ + GOTO_REFERENCE *CurrRef; + GOTO_REFERENCE *NextRef; + FORM_ID_VALUE *CurrFormId; + FORM_ID_VALUE *NextFormId; + UINT8 Found; + INT8 Name[20]; + + // + // Go through all the "goto" references and make sure there was a + // form ID of that value defined. + // + for (CurrRef = mGotoReferences; CurrRef != NULL; CurrRef = CurrRef->Next) { + Found = 0; + for (CurrFormId = mFormIdValues; CurrFormId != NULL; CurrFormId = CurrFormId->Next) { + if (CurrRef->Value == CurrFormId->Value) { + Found = 1; + break; + } + } + if (!Found) { + sprintf (Name, "%d", (UINT32)CurrRef->Value); + PrintErrorMessage (CurrRef->RefLineNum, Name, "undefined form ID"); + } + } + // + // Now free up the form id and goto references + // + CurrFormId = mFormIdValues; + while (CurrFormId != NULL) { + NextFormId = CurrFormId->Next; + free (CurrFormId); + CurrFormId = NextFormId; + } + mFormIdValues = NULL; + CurrRef = mGotoReferences; + while (CurrRef != NULL) { + NextRef = CurrRef->Next; + free (CurrRef); + CurrRef = NextRef; + } + mGotoReferences = NULL; +} +VOID +EfiVfrParser::AddGotoReference ( + UINT32 GotoNumber, + UINT32 LineNum + ) +/*++ + +Routine Description: + During VFR parsing we came upon a goto statement. Since we support + forward references, save the referenced label and at the end of parsing + we'll check that the label was actually defined somewhere. + +Arguments: + GotoNumber - the label number referenced + LineNum - the line number where the reference was made (used for + error reporting) + +Returns: + None + +--*/ +{ + GOTO_REFERENCE *NewRef; + + NewRef = (GOTO_REFERENCE *)malloc (sizeof (GOTO_REFERENCE)); + if (NewRef == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return; + } + memset ((char *)NewRef, 0, sizeof (GOTO_REFERENCE)); + NewRef->Value = (UINT16)GotoNumber; + NewRef->RefLineNum = LineNum; + NewRef->Next = mGotoReferences; + mGotoReferences = NewRef; +} +VOID +EfiVfrParser::AddFormId ( + INT32 FormIdValue, + UINT32 LineNum + ) +/*++ + +Routine Description: + This function is called when we parse "form formid = 3" statements. + We save the form ID valud so we can verify that duplicates are not + defined. Also, these are the targets of goto statements, so when we're + done parsing the script we also go through all the goto statements to + check that there was a target FormId defined as referenced by each + goto statement. + + Note that formid = 0 is invalid. + +Arguments: + FormIdValue - the parsed value for the Form ID + LineNum - line number of the source file we're parsing + +Returns: + NA + +--*/ +{ + FORM_ID_VALUE *NewFormId; + char *FileName; + char *FileName2; + UINT32 LineNum2; + // + // Verify that FormId != 0 + // + if (FormIdValue == 0) { + FileName = ConvertLineNumber (&LineNum); + Error (FileName, LineNum, 0, "form ID cannot be 0", NULL); + return; + } + // + // First go through all previously defined form IDs and make sure they have not defined + // duplicates. + // + for (NewFormId = mFormIdValues; NewFormId != NULL; NewFormId = NewFormId->Next) { + if ((UINT16)FormIdValue == NewFormId->Value) { + FileName = ConvertLineNumber (&LineNum); + LineNum2 = NewFormId->LineNum; + FileName2 = ConvertLineNumber (&LineNum2); + Error (FileName, LineNum, 0, NULL, "form ID %d already defined", FormIdValue); + Error (FileName2, LineNum2, 0, NULL, "form ID %d previous definition", FormIdValue); + return; + } + } + // + // Allocate memory for a new one + // + NewFormId = (FORM_ID_VALUE *)malloc (sizeof (FORM_ID_VALUE)); + if (NewFormId == NULL) { + Error (PROGRAM_NAME, 0, 0, NULL, "memory allocation failure"); + return; + } + memset ((char *)NewFormId, 0, sizeof (FORM_ID_VALUE)); + NewFormId->LineNum = LineNum; + NewFormId->Next = mFormIdValues; + NewFormId->Value = (UINT16)FormIdValue; + mFormIdValues = NewFormId; +} +UINT32 +EfiVfrParser::GetNumber ( + INT8 *NumStr, + UINT32 LineNum, + UINT32 NumBytes + ) +{ + UINT32 Value; + + if ((NumStr[0] == '0') && (NumStr[1] == 'x')) { + AtoX (NumStr + 2, 4, &Value); + } else { + Value = (UINT32)atoi (NumStr); + } + // + // Check range + // + if ((NumBytes < 4) && (Value & ((UINT32)0xFFFFFFFF << (NumBytes * 8)))) { + PrintErrorMessage (LineNum, NumStr, "value out of range"); + return 0; + } + return Value; +} + +>> + +} // end grammar class + + diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrServices.cpp b/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrServices.cpp new file mode 100644 index 0000000000..e9c54d3387 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrServices.cpp @@ -0,0 +1,754 @@ +/*++ + +Copyright (c) 2004 - 2007, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + VfrServices.cpp + +Abstract: + + Support routines for the VFR compiler + +--*/ + +#include // for FILE routines +#include // for malloc() and free() + +#include "Tiano.h" +#include "EfiUtilityMsgs.h" +#include "EfiVfr.h" +#include "VfrServices.h" + +#include EFI_PROTOCOL_DEFINITION (Hii) + +static const char *mSourceFileHeader[] = { + "//", + "// DO NOT EDIT -- auto-generated file", + "//", + "// This file is generated by the VFR compiler.", + "//", + NULL +}; + +typedef struct { + INT8 *Name; + INT32 Size; +} IFR_OPCODE_SIZES; + +// +// Create a table that can be used to do internal checking on the IFR +// bytes we emit. +// +static const IFR_OPCODE_SIZES mOpcodeSizes[] = { + { 0, 0 }, // invalid + { "EFI_IFR_FORM", sizeof (EFI_IFR_FORM) }, + { "EFI_IFR_SUBTITLE", sizeof (EFI_IFR_SUBTITLE) }, + { "EFI_IFR_TEXT", -6 }, //sizeof (EFI_IFR_TEXT) }, + { "unused 0x04 opcode", 0 }, // EFI_IFR_GRAPHIC_OP + { "EFI_IFR_ONE_OF", sizeof (EFI_IFR_ONE_OF) }, + { "EFI_IFR_CHECK_BOX", sizeof (EFI_IFR_CHECK_BOX) }, + { "EFI_IFR_NUMERIC", sizeof (EFI_IFR_NUMERIC) }, + { "EFI_IFR_PASSWORD", sizeof (EFI_IFR_PASSWORD) }, + { "EFI_IFR_ONE_OF_OPTION", sizeof (EFI_IFR_ONE_OF_OPTION) }, + { "EFI_IFR_SUPPRESS", sizeof (EFI_IFR_SUPPRESS) }, + { "EFI_IFR_END_FORM", sizeof (EFI_IFR_END_FORM) }, + { "EFI_IFR_HIDDEN", sizeof (EFI_IFR_HIDDEN) }, + { "EFI_IFR_END_FORM_SET", sizeof (EFI_IFR_END_FORM_SET) }, + { "EFI_IFR_FORM_SET", sizeof (EFI_IFR_FORM_SET) }, + { "EFI_IFR_REF", sizeof (EFI_IFR_REF) }, + { "EFI_IFR_END_ONE_OF", sizeof (EFI_IFR_END_ONE_OF) }, + { "EFI_IFR_INCONSISTENT", sizeof (EFI_IFR_INCONSISTENT) }, + { "EFI_IFR_EQ_ID_VAL", sizeof (EFI_IFR_EQ_ID_VAL) }, + { "EFI_IFR_EQ_ID_ID", sizeof (EFI_IFR_EQ_ID_ID) }, + { "EFI_IFR_EQ_ID_LIST", -sizeof (EFI_IFR_EQ_ID_LIST) }, + { "EFI_IFR_AND", sizeof (EFI_IFR_AND) }, + { "EFI_IFR_OR", sizeof (EFI_IFR_OR) }, + { "EFI_IFR_NOT", sizeof (EFI_IFR_NOT) }, + { "EFI_IFR_END_IF", sizeof (EFI_IFR_END_IF) }, + { "EFI_IFR_GRAYOUT", sizeof (EFI_IFR_GRAYOUT) }, + { "EFI_IFR_DATE", sizeof (EFI_IFR_DATE) / 3 }, + { "EFI_IFR_TIME", sizeof (EFI_IFR_TIME) / 3 }, + { "EFI_IFR_STRING", sizeof (EFI_IFR_STRING) }, + { "EFI_IFR_LABEL", sizeof (EFI_IFR_LABEL) }, + { "EFI_IFR_SAVE_DEFAULTS", sizeof (EFI_IFR_SAVE_DEFAULTS) }, + { "EFI_IFR_RESTORE_DEFAULTS", sizeof (EFI_IFR_RESTORE_DEFAULTS) }, + { "EFI_IFR_BANNER", sizeof (EFI_IFR_BANNER) }, + { "EFI_IFR_INVENTORY", sizeof (EFI_IFR_INVENTORY) }, + { "EFI_IFR_EQ_VAR_VAL_OP", sizeof (EFI_IFR_EQ_VAR_VAL) }, + { "EFI_IFR_ORDERED_LIST_OP", sizeof (EFI_IFR_ORDERED_LIST) }, + { "EFI_IFR_VARSTORE_OP", -sizeof (EFI_IFR_VARSTORE) }, + { "EFI_IFR_VARSTORE_SELECT_OP", sizeof (EFI_IFR_VARSTORE_SELECT) }, + { "EFI_IFR_VARSTORE_SELECT_PAIR_OP", sizeof (EFI_IFR_VARSTORE_SELECT_PAIR) }, + { "EFI_IFR_TRUE", sizeof (EFI_IFR_TRUE)}, + { "EFI_IFR_FALSE", sizeof (EFI_IFR_FALSE)}, + { "EFI_IFR_GT", sizeof (EFI_IFR_GT)}, + { "EFI_IFR_GE", sizeof (EFI_IFR_GE)}, + { "EFI_IFR_OEM_DEFINED_OP", -2 }, +}; + + +VfrOpcodeHandler::VfrOpcodeHandler ( + ) +/*++ + +Routine Description: + Constructor for the VFR opcode handling class. + +Arguments: + None + +Returns: + None + +--*/ +{ + mIfrBytes = NULL; + mLastIfrByte = NULL; + mBytesWritten = 0; + mQueuedByteCount = 0; + mQueuedOpcodeByteValid = 0; + mPrimaryVarStoreId = 0; + mSecondaryVarStoreId = 0; + mSecondaryVarStoreIdSet = 0; + mPrimaryVarStoreIdSet = 0; + mDefaultVarStoreId = 0; +} + +VOID +VfrOpcodeHandler::SetVarStoreId ( + UINT16 VarStoreId + ) +/*++ + +Routine Description: + This function is invoked by the parser when a variable is referenced in the + VFR. Save the variable store (and set a flag) so that we can later determine + if we need to emit a varstore-select or varstore-select-pair opcode. + +Arguments: + VarStoreId - ID of the variable store referenced in the VFR + +Returns: + None + +--*/ +{ + mPrimaryVarStoreId = VarStoreId; + mPrimaryVarStoreIdSet = 1; +} + +VOID +VfrOpcodeHandler::SetSecondaryVarStoreId ( + UINT16 VarStoreId + ) +/*++ + +Routine Description: + This function is invoked by the parser when a secondary variable is + referenced in the VFR. Save the variable store (and set a flag) so + that we can later determine if we need to emit a varstore-select or + varstore-pair opcode. + +Arguments: + VarStoreId - ID of the variable store referenced in the VFR + +Returns: + None + +--*/ +{ + mSecondaryVarStoreId = VarStoreId; + mSecondaryVarStoreIdSet = 1; +} + +VOID +VfrOpcodeHandler::WriteIfrBytes ( + ) +/*++ + +Routine Description: + This function is invoked at the end of parsing. Its purpose + is to write out all the IFR bytes that were queued up while + parsing. + +Arguments: + None + +Returns: + None + +--*/ +{ + IFR_BYTE *Curr; + IFR_BYTE *Next; + UINT32 Count; + UINT32 LineCount; + UINT32 PoundLines; + UINT32 ByteCount; + INT8 Line[MAX_LINE_LEN]; + INT8 *Cptr; + FILE *InFptr; + FILE *OutFptr; + UINT32 ListFile; + EFI_HII_IFR_PACK_HEADER IfrHeader; + UINT8 *Ptr; + FILE *IfrBinFptr; + UINT32 BytesLeftThisOpcode; + // + // If someone added a new opcode and didn't update our opcode sizes structure, error out. + // + if (sizeof(mOpcodeSizes) / sizeof (mOpcodeSizes[0]) != EFI_IFR_LAST_OPCODE + 1) { + Error (__FILE__, __LINE__, 0, "application error", "internal IFR binary table size is incorrect"); + return; + } + // + // Flush the queue + // + FlushQueue (); + // + // If there have been any errors to this point, then skip dumping the IFR + // binary data. This way doing an nmake again will try to build it again, and + // the build will fail if they did not fix the problem. + // + if (GetUtilityStatus () != STATUS_ERROR) { + if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "w")) == NULL) { + Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing"); + return; + } + // + // Write the standard file header to the output file + // + WriteStandardFileHeader (IfrBinFptr); + // + // Write the structure header + // + fprintf (IfrBinFptr, "\nunsigned char %sBin[] = {", gOptions.VfrBaseFileName); + // + // Write the header + // + memset ((char *)&IfrHeader, 0, sizeof (IfrHeader)); + IfrHeader.Header.Type = EFI_HII_IFR; + IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader); + Ptr = (UINT8 *)&IfrHeader; + for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) { + if ((Count & 0x03) == 0) { + fprintf (IfrBinFptr, "\n "); + } + fprintf (IfrBinFptr, "0x%02X, ", *Ptr); + } + // + // + // Write all the IFR bytes + // + fprintf (IfrBinFptr, "\n // start of IFR data"); + Curr = mIfrBytes; + Count = 0; + while (Curr != NULL) { + if ((Count & 0x0F) == 0) { + fprintf (IfrBinFptr, "\n "); + } + if (Curr->KeyByte != 0) { + fprintf (IfrBinFptr, "/*%c*/ ", Curr->KeyByte); + } + fprintf (IfrBinFptr, "0x%02X, ", Curr->OpcodeByte); + Count++; + Curr = Curr->Next; + } + fprintf (IfrBinFptr, "\n};\n\n"); + // + // + // Close the file + // + fclose (IfrBinFptr); + IfrBinFptr = NULL; + } + // + // Write the bytes as binary data if the user specified to do so + // + if ((GetUtilityStatus () != STATUS_ERROR) && (gOptions.CreateIfrBinFile != 0)) { + // + // Use the Ifr output file name with a ".hpk" extension. + // + for (Cptr = gOptions.IfrOutputFileName + strlen (gOptions.IfrOutputFileName) - 1; + (*Cptr != '.') && (Cptr > gOptions.IfrOutputFileName) && (*Cptr != '\\'); + Cptr--) { + // + // do nothing + // + } + if (*Cptr == '.') { + strcpy (Cptr, ".hpk"); + } else { + strcat (gOptions.IfrOutputFileName, ".hpk"); + } + if ((IfrBinFptr = fopen (gOptions.IfrOutputFileName, "wb")) == NULL) { + Error (PROGRAM_NAME, 0, 0, gOptions.IfrOutputFileName, "could not open file for writing"); + return; + } + // + // Write the structure header + // + memset ((char *)&IfrHeader, 0, sizeof (IfrHeader)); + IfrHeader.Header.Type = EFI_HII_IFR; + IfrHeader.Header.Length = mBytesWritten + sizeof (IfrHeader); + Ptr = (UINT8 *)&IfrHeader; + for (Count = 0; Count < sizeof (IfrHeader); Count++, Ptr++) { + fwrite (Ptr, 1, 1, IfrBinFptr); + } + // + // + // Write all the IFR bytes + // + Curr = mIfrBytes; + Count = 0; + while (Curr != NULL) { + fwrite (&Curr->OpcodeByte, 1, 1, IfrBinFptr); + Curr = Curr->Next; + } + // + // + // Close the file + // + fclose (IfrBinFptr); + IfrBinFptr = NULL; + } + // + // If creating a listing file, then open the input and output files + // + ListFile = 0; + if (gOptions.CreateListFile) { + // + // Open the input VFR file and the output list file + // + if ((InFptr = fopen (gOptions.PreprocessorOutputFileName, "r")) == NULL) { + Warning (PROGRAM_NAME, 0, 0, gOptions.PreprocessorOutputFileName, "could not open file for creating a list file"); + } else { + if ((OutFptr = fopen (gOptions.VfrListFileName, "w")) == NULL) { + Warning (PROGRAM_NAME, 0, 0, gOptions.VfrListFileName, "could not open output list file for writing"); + fclose (InFptr); + InFptr = NULL; + } else { + LineCount = 0; + ListFile = 1; + PoundLines = 0; + ByteCount = 0; + } + } + } + // + // Write the list file + // + if (ListFile) { + // + // Write out the VFR compiler version + // + fprintf (OutFptr, "//\n// VFR compiler version " VFR_COMPILER_VERSION "\n//\n"); + Curr = mIfrBytes; + while (Curr != NULL) { + // + // Print lines until we reach the line of the current opcode + // + while (LineCount < PoundLines + Curr->LineNum) { + if (fgets (Line, sizeof (Line), InFptr) != NULL) { + // + // We should check for line length exceeded on the fgets(). Otherwise it + // throws the listing file output off. Future enhancement perhaps. + // + fprintf (OutFptr, "%s", Line); + if (strncmp (Line, "#line", 5) == 0) { + PoundLines++; + } + } + LineCount++; + } + // + // Print all opcodes with line numbers less than where we are now + // + BytesLeftThisOpcode = 0; + while ((Curr != NULL) && ((Curr->LineNum == 0) || (LineCount >= PoundLines + Curr->LineNum))) { + if (BytesLeftThisOpcode == 0) { + fprintf (OutFptr, ">%08X: ", ByteCount); + if (Curr->Next != NULL) { + BytesLeftThisOpcode = (UINT32)Curr->Next->OpcodeByte; + } + } + fprintf (OutFptr, "%02X ", (UINT32)Curr->OpcodeByte); + ByteCount++; + BytesLeftThisOpcode--; + if (BytesLeftThisOpcode == 0) { + fprintf (OutFptr, "\n"); + } + Curr = Curr->Next; + } + } + // + // Dump any remaining lines from the input file + // + while (fgets (Line, sizeof (Line), InFptr) != NULL) { + fprintf (OutFptr, "%s", Line); + } + fclose (InFptr); + fclose (OutFptr); + } + // + // Debug code to make sure that each opcode we write out has as many + // bytes as the IFR structure requires. If there were errors, then + // don't do this step. + // + if (GetUtilityStatus () != STATUS_ERROR) { + Curr = mIfrBytes; + ByteCount = 0; + while (Curr != NULL) { + // + // First byte is the opcode, second byte is the length + // + if (Curr->Next == NULL) { + Error (__FILE__, __LINE__, 0, "application error", "last opcode written does not contain a length byte"); + break; + } + Count = (UINT32)Curr->Next->OpcodeByte; + if (Count == 0) { + Error ( + __FILE__, + __LINE__, + 0, + "application error", + "opcode with 0 length specified in output at offset 0x%X", + ByteCount + ); + break; + } + // + // Check the length + // + if ((Curr->OpcodeByte > EFI_IFR_LAST_OPCODE) || (Curr->OpcodeByte == 0)) { + Error ( + __FILE__, + __LINE__, + 0, + "application error", + "invalid opcode 0x%X in output at offset 0x%X", + (UINT32) Curr->OpcodeByte, ByteCount + ); + } else if (mOpcodeSizes[Curr->OpcodeByte].Size < 0) { + // + // For those cases where the length is variable, the size is negative, and indicates + // the miniumum size. + // + if ((mOpcodeSizes[Curr->OpcodeByte].Size * -1) > Count) { + Error ( + __FILE__, + __LINE__, + 0, + "application error", + "insufficient number of bytes written for %s at offset 0x%X", + mOpcodeSizes[Curr->OpcodeByte].Name, + ByteCount + ); + } + } else { + // + // Check for gaps + // + if (mOpcodeSizes[Curr->OpcodeByte].Size == 0) { + Error ( + __FILE__, + __LINE__, + 0, + "application error", + "invalid opcode 0x%X in output at offset 0x%X", + (UINT32)Curr->OpcodeByte, + ByteCount + ); + } else { + // + // Check size + // + if (mOpcodeSizes[Curr->OpcodeByte].Size != Count) { + Error ( + __FILE__, + __LINE__, + 0, + "application error", + "invalid number of bytes (%d written s/b %d) written for %s at offset 0x%X", + Count, + mOpcodeSizes[Curr->OpcodeByte].Size, + mOpcodeSizes[Curr->OpcodeByte].Name, + ByteCount + ); + } + } + } + // + // Skip to next opcode + // + while (Count > 0) { + ByteCount++; + if (Curr == NULL) { + Error (__FILE__, __LINE__, 0, "application error", "last opcode written has invalid length"); + break; + } + Curr = Curr->Next; + Count--; + } + } + } +} + +VfrOpcodeHandler::~VfrOpcodeHandler( + ) +/*++ + +Routine Description: + Destructor for the VFR opcode handler. Free up memory allocated + while parsing the VFR script. + +Arguments: + None + +Returns: + None + +--*/ +{ + IFR_BYTE *Curr; + IFR_BYTE *Next; + // + // Free up the IFR bytes + // + Curr = mIfrBytes; + while (Curr != NULL) { + Next = Curr->Next; + free (Curr); + Curr = Next; + } +} + +int +VfrOpcodeHandler::AddOpcodeByte ( + UINT8 OpcodeByte, + UINT32 LineNum + ) +/*++ + +Routine Description: + This function is invoked by the parser when a new IFR + opcode should be emitted. + +Arguments: + OpcodeByte - the IFR opcode + LineNum - the line number from the source file that resulted + in the opcode being emitted. + +Returns: + 0 always + +--*/ +{ + UINT32 Count; + + FlushQueue(); + // + // Now add this new byte + // + mQueuedOpcodeByte = OpcodeByte; + mQueuedLineNum = LineNum; + mQueuedOpcodeByteValid = 1; + return 0; +} + +VOID +VfrOpcodeHandler::AddByte ( + UINT8 ByteVal, + UINT8 KeyByte + ) +/*++ + +Routine Description: + This function is invoked by the parser when it determines + that more raw IFR bytes should be emitted to the output stream. + Here we just queue them up into an output buffer. + +Arguments: + ByteVal - the raw byte to emit to the output IFR stream + KeyByte - a value that can be used for debug. + +Returns: + None + +--*/ +{ + // + // Check for buffer overflow + // + if (mQueuedByteCount >= MAX_QUEUE_COUNT) { + Error (PROGRAM_NAME, 0, 0, NULL, "opcode queue overflow"); + } else { + mQueuedBytes[mQueuedByteCount] = ByteVal; + mQueuedKeyBytes[mQueuedByteCount] = KeyByte; + mQueuedByteCount++; + } +} + +int +VfrOpcodeHandler::FlushQueue ( + ) +/*++ + +Routine Description: + This function is invoked to flush the internal IFR buffer. + +Arguments: + None + +Returns: + 0 always + +--*/ +{ + UINT32 Count; + UINT32 EmitNoneOnePair; + + EmitNoneOnePair = 0; + // + // If the secondary varstore was specified, then we have to emit + // a varstore-select-pair opcode, which only applies to the following + // statement. + // + if (mSecondaryVarStoreIdSet) { + mSecondaryVarStoreIdSet = 0; + // + // If primary and secondary are the same as the current default + // varstore, then we don't have to do anything. + // Note that the varstore-select-pair only applies to the following + // opcode. + // + if ((mPrimaryVarStoreId != mSecondaryVarStoreId) || (mPrimaryVarStoreId != mDefaultVarStoreId)) { + IAddByte (EFI_IFR_VARSTORE_SELECT_PAIR_OP, 'O', mQueuedLineNum); + IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT_PAIR), 'L', 0); + IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0); + IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0); + IAddByte ((UINT8)mSecondaryVarStoreId, 0, 0); + IAddByte ((UINT8)(mSecondaryVarStoreId >> 8), 0, 0); + } + } else if (mPrimaryVarStoreIdSet != 0) { + mPrimaryVarStoreIdSet = 0; + if (mDefaultVarStoreId != mPrimaryVarStoreId) { + // + // The VFR statement referenced a different variable store + // than the last one we reported. Insert a new varstore select + // statement. + // + IAddByte (EFI_IFR_VARSTORE_SELECT_OP, 'O', mQueuedLineNum); + IAddByte ((UINT8)sizeof (EFI_IFR_VARSTORE_SELECT), 'L', 0); + IAddByte ((UINT8)mPrimaryVarStoreId, 0, 0); + IAddByte ((UINT8)(mPrimaryVarStoreId >> 8), 0, 0); + mDefaultVarStoreId = mPrimaryVarStoreId; + } + } + // + // Likely a new opcode is being added. Since each opcode item in the IFR has + // a header that specifies the size of the opcode item (which we don't + // know until we find the next opcode in the VFR), we queue up bytes + // until we know the size. Then we write them out. So flush the queue + // now. + // + if (mQueuedOpcodeByteValid != 0) { + // + // Add the previous opcode byte, the length byte, and the binary + // data. + // + IAddByte (mQueuedOpcodeByte, 'O', mQueuedLineNum); + IAddByte ((UINT8)(mQueuedByteCount + 2), 'L', 0); + for (Count = 0; Count < mQueuedByteCount; Count++) { + IAddByte (mQueuedBytes[Count], mQueuedKeyBytes[Count], 0); + } + mQueuedByteCount = 0; + mQueuedOpcodeByteValid = 0; + } + return 0; +} + +int +VfrOpcodeHandler::IAddByte ( + UINT8 ByteVal, + UINT8 KeyByte, + UINT32 LineNum + ) +/*++ + +Routine Description: + This internal function is used to add actual IFR bytes to + the output stream. Most other functions queue up the bytes + in an internal buffer. Once they come here, there's no + going back. + + +Arguments: + ByteVal - value to write to output + KeyByte - key value tied to the byte -- useful for debug + LineNum - line number from source file the byte resulted from + +Returns: + 0 - if successful + 1 - failed due to memory allocation failure + +--*/ +{ + IFR_BYTE *NewByte; + NewByte = (IFR_BYTE *)malloc (sizeof (IFR_BYTE)); + if (NewByte == NULL) { + return 1; + } + memset ((char *)NewByte, 0, sizeof (IFR_BYTE)); + NewByte->OpcodeByte = ByteVal; + NewByte->KeyByte = KeyByte; + NewByte->LineNum = LineNum; + // + // Add to the list + // + if (mIfrBytes == NULL) { + mIfrBytes = NewByte; + } else { + mLastIfrByte->Next = NewByte; + } + mLastIfrByte = NewByte; + mBytesWritten++; + return 0; +} + +VOID +WriteStandardFileHeader ( + FILE *OutFptr + ) +/*++ + +Routine Description: + This function is invoked to emit a standard header to an + output text file. + +Arguments: + OutFptr - file to write the header to + +Returns: + None + +--*/ +{ + UINT32 TempIndex; + for (TempIndex = 0; mSourceFileHeader[TempIndex] != NULL; TempIndex++) { + fprintf (OutFptr, "%s\n", mSourceFileHeader[TempIndex]); + } + // + // Write out the VFR compiler version + // + fprintf (OutFptr, "// VFR compiler version " VFR_COMPILER_VERSION "\n//\n"); +} diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrServices.h b/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrServices.h new file mode 100644 index 0000000000..6b8c560d63 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrServices.h @@ -0,0 +1,227 @@ +/*++ + +Copyright (c) 2004, Intel Corporation +All rights reserved. This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at +http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + +Module Name: + + VfrServices.h + +Abstract: + + Prototypes and defines for routines and classes used by the + EFI VFR compiler. + +--*/ + +#ifndef _VFR_SERVICES_H_ +#define _VFR_SERVICES_H_ + +class VfrOpcodeHandler +{ +public: + VfrOpcodeHandler ( + VOID + ) + /*++ + +Routine Description: + Constructor for the VFR opcode handling class. + +Arguments: + None + +Returns: + None + +--*/ + ; + ~VfrOpcodeHandler ( + VOID + ) + /*++ + +Routine Description: + Destructor for the VFR opcode handler. Free up memory allocated + while parsing the VFR script. + +Arguments: + None + +Returns: + None + +--*/ + ; + void + WriteIfrBytes ( + VOID + ) + /*++ + +Routine Description: + This function is invoked at the end of parsing. Its purpose + is to write out all the IFR bytes that were queued up while + parsing. + +Arguments: + None + +Returns: + None + +--*/ + ; + int + AddOpcodeByte ( + UINT8 OpcodeByte, + UINT32 LineNum + ) + /*++ + +Routine Description: + This function is invoked by the parser when a new IFR + opcode should be emitted. + +Arguments: + OpcodeByte - the IFR opcode + LineNum - the line number from the source file that resulted + in the opcode being emitted. + +Returns: + 0 always + +--*/ + ; + void + AddByte ( + UINT8 ByteVal, + UINT8 KeyByte + ) + /*++ + +Routine Description: + This function is invoked by the parser when it determines + that more raw IFR bytes should be emitted to the output stream. + Here we just queue them up into an output buffer. + +Arguments: + ByteVal - the raw byte to emit to the output IFR stream + KeyByte - a value that can be used for debug. + +Returns: + None + +--*/ + ; + void + SetVarStoreId ( + UINT16 VarStoreId + ) + /*++ + +Routine Description: + This function is invoked by the parser when a variable is referenced in the + VFR. Save the variable store (and set a flag) so that we can later determine + if we need to emit a varstore-select or varstore-select-pair opcode. + +Arguments: + VarStoreId - ID of the variable store referenced in the VFR + +Returns: + None + +--*/ + ; + void + SetSecondaryVarStoreId ( + UINT16 VarStoreId + ) + /*++ + +Routine Description: + This function is invoked by the parser when a secondary variable is + referenced in the VFR. Save the variable store (and set a flag) so + that we can later determine if we need to emit a varstore-select or + varstore-pair opcode. + +Arguments: + VarStoreId - ID of the variable store referenced in the VFR + +Returns: + None + +--*/ + ; + +/* */ +private: + int + FlushQueue ( + VOID + ) + /*++ + +Routine Description: + This function is invoked to flush the internal IFR buffer. + +Arguments: + None + +Returns: + 0 always + +--*/ + ; + int + IAddByte ( + UINT8 ByteVal, + UINT8 KeyByte, + UINT32 LineNum + ) + /*++ + +Routine Description: + This internal function is used to add actual IFR bytes to + the output stream. Most other functions queue up the bytes + in an internal buffer. Once they come here, there's no + going back. + + +Arguments: + ByteVal - value to write to output + KeyByte - key value tied to the byte -- useful for debug + LineNum - line number from source file the byte resulted from + +Returns: + 0 - if successful + 1 - failed due to memory allocation failure + +--*/ + ; + +/* */ +private: + IFR_BYTE *mIfrBytes; + IFR_BYTE *mLastIfrByte; + UINT32 mQueuedByteCount; + UINT32 mBytesWritten; + UINT32 mQueuedLineNum; + UINT8 mQueuedBytes[MAX_QUEUE_COUNT]; + UINT8 mQueuedKeyBytes[MAX_QUEUE_COUNT]; + UINT8 mQueuedOpcodeByte; + UINT32 mQueuedOpcodeByteValid; + UINT16 mPrimaryVarStoreId; + UINT8 mPrimaryVarStoreIdSet; + UINT16 mSecondaryVarStoreId; + UINT8 mSecondaryVarStoreIdSet; + UINT16 mDefaultVarStoreId; +}; + +#endif // #ifndef _VFR_SERVICES_H_ diff --git a/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/makefile b/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/makefile new file mode 100644 index 0000000000..d703b02f31 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/makefile @@ -0,0 +1,172 @@ +#/*++ +# +# Copyright (c) 2004 - 2007, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# makefile +# +# Abstract: +# +# Makefile for building the EFI VFR compiler +# +#--*/ + + +!IFNDEF EDK_SOURCE +!ERROR EDK_SOURCE environmental variable not set +!ENDIF + +# +# Do this if you want to compile from this directory +# +!IFNDEF TOOLCHAIN +TOOLCHAIN = TOOLCHAIN_MSVC +!ENDIF + +!INCLUDE $(BUILD_DIR)\PlatformTools.env + +.SUFFIXES : + +TARGET_NAME = VfrCompile +ANTLR_H = $(PCCTS_DIR)\h +C_FLAGS_PCCTS = -I. -I$(ANTLR_H) /Zi /Fd$(EDK_TOOLS_OUTPUT)\$(TARGET_NAME)Obj /WX /Od /D _CRT_SECURE_NO_DEPRECATE $(VERSION_FLAGS) +C_FLAGS_PCCTS = $(C_FLAGS_PCCTS) + +LINK_FLAGS_PCCTS = +LIBS = "$(EDK_TOOLS_OUTPUT)\Common.lib" + +# +# Define the EFI output and source directories. +# +ETO = $(EDK_TOOLS_OUTPUT) +SRC = $(EDK_TOOLS_SOURCE)\$(TARGET_NAME) +TARGET_EXE = $(ETO)\$(TARGET_NAME).exe + +# +# Add deeper lookahead with -ck 3 +# +ANTLR_FLAGS = -CC -e3 -ck 3 +DLG_FLAGS = -C2 -i -CC + +# +# Define paths for include files +# +INC = -I $(SRC) +INC = $(INC) -I $(EDK_SOURCE)\Foundation\Include\Ia32 +INC = $(INC) -I $(EDK_SOURCE)\Foundation\Efi\Include +INC = $(INC) -I $(EDK_SOURCE)\Foundation\Framework\Include +INC = $(INC) -I $(EDK_SOURCE)\Foundation\Include\IndustryStandard +INC = $(INC) -I $(EDK_SOURCE)\Foundation\ \ + -I $(EDK_SOURCE)\Foundation\Core\Dxe \ + -I $(EDK_SOURCE)\Foundation\Efi \ + -I $(EDK_SOURCE)\Foundation\Framework +INC = $(INC) -I $(EDK_TOOLS_SOURCE)\Common +INC = $(INC) -I $(EDK_SOURCE)\Foundation\Include + +DLG_FILE = Parser.dlg +SCAN_FILE = DLGLexer +PARSER_FILE = EfiVfrParser + +# +# Create a list of include dependencies +# +INC_DEPS = $(INC_DEPS) $(SRC)\EfiVfr.h +INC_DEPS = $(INC_DEPS) $(EDK_SOURCE)\Foundation\Framework\Include\EfiInternalFormRepresentation.h + +# +# This is the grammer file for our project +# +GRAMMER_FILE = $(SRC)\$(TARGET_NAME).g + +# +# If we utilize a separate token file, define it here. +# +#TOKEN_FILE = + + +OBJECTS = $(ETO)\$(TARGET_NAME).obj \ + $(ETO)\$(PARSER_FILE).obj \ + $(ETO)\AParser.obj \ + $(ETO)\DLexerBase.obj \ + $(ETO)\ATokenBuffer.obj \ + $(ETO)\$(SCAN_FILE).obj \ + $(ETO)\VfrServices.obj + +# +# Per the Language Translation Using PCCTS and C++ Reference Guide, page 109, +# these are the outputs of ANTLR and DLG +# +ANTLR_SPAWN = $(ETO)\$(TARGET_NAME).cpp \ + $(ETO)\$(PARSER_FILE).cpp \ + $(ETO)\$(PARSER_FILE).h \ + $(ETO)\$(DLG_FILE) \ + $(ETO)\tokens.h + +DLG_SPAWN = $(ETO)\$(SCAN_FILE).cpp \ + $(ETO)\$(SCAN_FILE).h + + +# +# Default target +# +all : $(TARGET_EXE) + +# +# All antlr-generated files depend on the .g grammer file. Use the -o +# option to emit them to the appropriate output directory. +# +$(ANTLR_SPAWN) : $(GRAMMER_FILE) $(INC_DEPS) + $(ANTLR) $(ANTLR_FLAGS) -o $(ETO) $(GRAMMER_FILE) + +$(ETO)\$(TARGET_NAME).obj : $(ETO)\$(TARGET_NAME).cpp $(DLG_SPAWN) $(INC_DEPS) + $(CC) -c $(C_FLAGS_PCCTS) /Fo$@ $(INC) $(ETO)\$(TARGET_NAME).cpp + +$(ETO)\$(SCAN_FILE).obj : $(ETO)\$(SCAN_FILE).cpp $(DLG_SPAWN) $(INC_DEPS) + $(CC) -c $(C_FLAGS_PCCTS) /Fo$@ $(INC) $(ETO)\$(SCAN_FILE).cpp + +$(ETO)\$(PARSER_FILE).obj : $(ETO)\$(PARSER_FILE).cpp $(ETO)\$(PARSER_FILE).h $(DLG_SPAWN) $(INC_DEPS) + $(CC) -c $(C_FLAGS_PCCTS) /Fo$@ $(INC) $(ETO)\$(PARSER_FILE).cpp + +$(DLG_SPAWN) : $(ETO)\$(DLG_FILE) $(INC_DEPS) + $(DLG) $(DLG_FLAGS) -o $(ETO) $(ETO)\$(DLG_FILE) + +$(ETO)\AParser.obj : $(ANTLR_H)/AParser.cpp + $(CC) -c $(C_FLAGS_PCCTS) /Fo$@ $(ANTLR_H)/AParser.cpp + +$(ETO)\ATokenBuffer.obj : $(ANTLR_H)/ATokenBuffer.cpp + $(CC) -c $(C_FLAGS_PCCTS) /Fo$@ $(ANTLR_H)/ATokenBuffer.cpp + +$(ETO)\DLexerBase.obj : $(ANTLR_H)/DLexerBase.cpp + $(CC) -c $(C_FLAGS_PCCTS) /Fo$@ $(ANTLR_H)/DLexerBase.cpp + +$(ETO)\VfrServices.obj : $(SRC)\VfrServices.cpp $(SRC)\VfrServices.h $(INC_DEPS) + $(CC) -c $(C_FLAGS_PCCTS) $(INC) /Fo$@ $(SRC)\VfrServices.cpp + +# +# Add Binary Build description for this tools. +# + +!IF (("$(EFI_BINARY_TOOLS)" == "YES") && EXIST($(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe)) +$(TARGET_EXE): $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).exe $(TARGET_EXE) /Y + if exist $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb \ + copy $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb /Y +!ELSE +$(TARGET_EXE) : $(OBJECTS) $(LIBS) + $(LINK) $(MSVS_LINK_LIBPATHS) $(LIBS) /DEBUG /OUT:$(TARGET_EXE) $(LINK_FLAGS_PCCTS) $(OBJECTS) /PDB:$*.pdb + if not exist $(EFI_PLATFORM_BIN)\Tools mkdir $(EFI_PLATFORM_BIN)\Tools + if exist $(TARGET_EXE) copy $(TARGET_EXE) $(EFI_PLATFORM_BIN)\tools\$(TARGET_NAME).exe /Y + if exist $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb \ + copy $(EDK_TOOLS_OUTPUT)\$(TARGET_NAME).pdb $(EFI_PLATFORM_BIN)\Tools\$(TARGET_NAME).pdb /Y +!ENDIF + +clean: + diff --git a/EdkCompatibilityPkg/Sample/Version.env b/EdkCompatibilityPkg/Sample/Version.env new file mode 100644 index 0000000000..dde7a7d067 --- /dev/null +++ b/EdkCompatibilityPkg/Sample/Version.env @@ -0,0 +1,34 @@ +#/*++ +# +# Copyright (c) 2006, Intel Corporation +# All rights reserved. This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# Module Name: +# +# Version.env +# +# Abstract: +# +# This file is used to define EDK related version info. +# +#--*/ + +!IF "$(UEFI_MODE)" == "YES" +EFI_SPECIFICATION_VERSION = 0x00020000 +!ELSE +EFI_SPECIFICATION_VERSION = 0x0001000A +!ENDIF + +!IF "$(PI_MODE)" == "YES" +PI_SPECIFICATION_VERSION = 0x00010000 +!ELSE +PI_SPECIFICATION_VERSION = 0x00000009 +!ENDIF + +TIANO_RELEASE_VERSION = 0x00080006 -- cgit v1.2.3