summaryrefslogtreecommitdiff
path: root/EdkCompatibilityPkg/Sample
diff options
context:
space:
mode:
authorqwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524>2007-06-28 07:00:39 +0000
committerqwang12 <qwang12@6f19259b-4bc3-4df7-8a09-765794883524>2007-06-28 07:00:39 +0000
commit3eb9473ea9a949badfe06ae61d2d3fcfa53651c7 (patch)
treee9d8c368dbb1e58794b2c00acefe4bbad270f8c4 /EdkCompatibilityPkg/Sample
parent30d4a0c7ec19938196b1308006b990e0945150da (diff)
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
Diffstat (limited to 'EdkCompatibilityPkg/Sample')
-rw-r--r--EdkCompatibilityPkg/Sample/CommonTools.env672
-rw-r--r--EdkCompatibilityPkg/Sample/Include/Efi2WinNT.h59
-rw-r--r--EdkCompatibilityPkg/Sample/Include/EfiCompNameSupport.h58
-rw-r--r--EdkCompatibilityPkg/Sample/Include/EfiWinNt.h46
-rw-r--r--EdkCompatibilityPkg/Sample/Library/Dxe/WinNt/WinNtLib.c75
-rw-r--r--EdkCompatibilityPkg/Sample/Library/Dxe/WinNt/WinNtLib.inf49
-rw-r--r--EdkCompatibilityPkg/Sample/LocalTools.env95
-rw-r--r--EdkCompatibilityPkg/Sample/Platform/Common.dsc1522
-rw-r--r--EdkCompatibilityPkg/Sample/Platform/CommonIa32.dsc558
-rw-r--r--EdkCompatibilityPkg/Sample/Platform/CommonIpf.dsc391
-rw-r--r--EdkCompatibilityPkg/Sample/Platform/CommonX64.dsc558
-rw-r--r--EdkCompatibilityPkg/Sample/Platform/EdkIIGlueLib32.dsc39
-rw-r--r--EdkCompatibilityPkg/Sample/Platform/EdkIIGlueLibAll.dsc54
-rw-r--r--EdkCompatibilityPkg/Sample/Platform/EdkLib32.dsc36
-rw-r--r--EdkCompatibilityPkg/Sample/Platform/EdkLibAll.dsc63
-rw-r--r--EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/EdkNt32ProtocolLib.inf46
-rw-r--r--EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtIo/WinNtIo.c40
-rw-r--r--EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtIo/WinNtIo.h163
-rw-r--r--EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtThunk/WinNtThunk.c28
-rw-r--r--EdkCompatibilityPkg/Sample/Platform/Nt32/Protocol/WinNtThunk/WinNtThunk.h1276
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/Makefile97
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/bootsectimage.c881
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/fat.h158
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/BootsectImage/mbr.h64
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/CommonLib.c497
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/CommonLib.h120
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/Compress.h90
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/Crc32.c327
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/Crc32.h51
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/Decompress.c995
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/Decompress.h174
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiCompress.c1600
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiCustomizedCompress.h138
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiUtilityMsgs.c756
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/EfiUtilityMsgs.h135
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/FvLib.c786
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/FvLib.h177
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/Makefile145
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/MyAlloc.c516
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/MyAlloc.h222
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/ParseInf.c625
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/ParseInf.h233
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/SimpleFileParsing.c1456
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/SimpleFileParsing.h118
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Common/TianoCompress.c1765
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/CustomizedCompress/CustomizedCompress.c146
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/CustomizedCompress/makefile82
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/EfiCompress/EfiCompressMain.c386
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/EfiCompress/makefile89
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/EfiRom/EfiRom.c1545
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/EfiRom/Makefile85
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/EfildrImage/Makefile96
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/EfildrImage/efildrimage.c188
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/FwImage/Makefile86
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/FwImage/fwimage.c587
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenAprioriFile/GenAprioriFile.c467
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenAprioriFile/Makefile78
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/GetDrvNumOffset.c58
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/fat.h158
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/genbootsector.c652
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenBootsector/makefile99
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenCRC32Section/GenCRC32Section.c299
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenCRC32Section/GenCRC32Section.h43
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenCRC32Section/makefile85
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/DepexParser.c890
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/DepexParser.h26
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/GenDepex.c912
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/GenDepex.h67
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenDepex/makefile100
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/GenFfsFile.c2681
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/GenFfsFile.h35
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenFfsFile/makefile88
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageExe.c299
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageExe.h98
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.c3054
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLib.h140
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/GenFvImageLibInternal.h212
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenFvImage/Makefile109
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenPage/Makefile95
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenPage/VirtualMemory.h127
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenPage/genpage.c344
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenSection/GenSection.c1000
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenSection/GenSection.h42
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GenSection/makefile82
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/CommonUtils.h57
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/FileSearch.c285
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/FileSearch.h108
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/GuidChk.c2417
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/GuidList.c188
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/Makefile96
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/UtilsMsgs.c489
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/GuidChk/UtilsMsgs.h106
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/MakeDeps/MakeDeps.c1316
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/MakeDeps/Makefile69
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/Makefile79
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/ModifyInf/Makefile82
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/ModifyInf/ModifyInf.c322
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Common.h123
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/DscFile.c534
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/DscFile.h109
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Exceptions.c141
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Exceptions.h57
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/FWVolume.c1566
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/FWVolume.h76
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/Makefile102
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/ProcessDsc/ProcessDsc.c4726
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/SetStamp/Makefile88
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/SetStamp/SetStamp.c475
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/SplitFile/Makefile94
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/SplitFile/splitfile.c136
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/StrGather/Makefile89
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StrGather.c2574
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StrGather.h84
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StringDB.c2808
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/StrGather/StringDB.h136
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/VcCheck/VcCheck.c121
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/VcCheck/makefile92
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/EfiVfr.h178
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrCompile.g3463
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrServices.cpp754
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/VfrServices.h227
-rw-r--r--EdkCompatibilityPkg/Sample/Tools/Source/VfrCompile/makefile172
-rw-r--r--EdkCompatibilityPkg/Sample/Version.env34
123 files changed, 58157 insertions, 0 deletions
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 <windows.h>
+#include <stdio.h>
+#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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#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 <stdlib.h>
+#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 <stdlib.h>
+#include <string.h>
+#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 <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#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:
+ <FileName>(<LineNumber>) : <Type> <Type[0]><MessageCode>: <Text> : <MsgFmt>
+
+ 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 <string.h>
+
+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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <assert.h>
+#include <string.h>
+#include <ctype.h>
+
+CHAR8 *
+ReadLine (
+ IN MEMORY_FILE *InputFile,
+ IN OUT CHAR8 *InputBuffer,
+ IN UINTN MaxLength
+ )
+/*++
+
+Routine Description:
+
+ This function reads a line, stripping any comments.
+ The function reads a string from the input stream argument and stores it in
+ the input string. ReadLine reads characters from the current file position
+ to and including the first newline character, to the end of the stream, or
+ until the number of characters read is equal to MaxLength - 1, whichever
+ comes first. The newline character, if read, is replaced with a \0.
+
+Arguments:
+
+ InputFile Memory file image.
+ InputBuffer Buffer to read into, must be _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 <stdio.h>
+#include <stdlib.h>
+
+//
+// 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#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 <string.h>
+#include <stdlib.h>
+#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 <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+//
+// 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 +
+ <PeImageFileContent> +
+ The order of EFILDR_IMAGE is same as the order of placing PeImageFileContent.
+
+Revision History
+
+--*/
+
+
+#include <windows.h>
+#include <stdio.h>
+#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 <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#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 <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#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 <stdio.h>
+
+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 <windows.h>
+#include <stdio.h>
+#include <string.h>
+
+#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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#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:
+ <depex> ::= BEFORE <guid> END
+ | AFTER <guid> END
+ | SOR <bool> END
+ | <bool> END
+ <bool> ::= <bool> AND <term>
+ | <bool> OR <term>
+ | <term>
+ <term> ::= NOT <factor>
+ | <factor>
+ <factor> ::= <bool>
+ | TRUE
+ | FALSE
+ | GUID
+
+ <guid> ::= '{' <hex32> ',' <hex16> ',' <hex16> ','
+ <hex8> ',' <hex8> ',' <hex8> ',' <hex8> ','
+ <hex8> ',' <hex8> ',' <hex8> ',' <hex8> '}'
+ <hex32> ::= <hexprefix> <hexvalue>
+ <hex16> ::= <hexprefix> <hexvalue>
+ <hex8> ::= <hexprefix> <hexvalue>
+ <hexprefix>::= '0' 'x'
+ | '0' 'X'
+ <hexvalue> ::= <hexdigit> <hexvalue>
+ | <hexdigit>
+ <hexdigit> ::= [0-9]
+ | [a-f]
+ | [A-F]
+
+ After cleaning left recursive and parentheses supported, the BNF grammar used in this module is thus:
+ <depex> ::= BEFORE <guid>
+ | AFTER <guid>
+ | SOR <bool>
+ | <bool>
+ <bool> ::= <term><rightbool>
+ <rightbool>::= AND <term><rightbool>
+ | OR <term><rightbool>
+ | ''
+ <term> ::= NOT <factor>
+ | <factor>
+ <factor> ::= '('<bool>')'<rightfactor>
+ | NOT <factor> <rightbool> <rightfactor>
+ | TRUE <rightfactor>
+ | FALSE <rightfactor>
+ | END <rightfactor>
+ | <guid> <rightfactor>
+ <rightfactor> ::=AND <term><rightbool> <rightfactor>
+ | OR <term><rightbool> <rightfactor>
+ | ''
+ <guid> ::= '{' <hex32> ',' <hex16> ',' <hex16> ','
+ <hex8> ',' <hex8> ',' <hex8> ',' <hex8> ','
+ <hex8> ',' <hex8> ',' <hex8> ',' <hex8> '}'
+ <hex32> ::= <hexprefix> <hexvalue>
+ <hex16> ::= <hexprefix> <hexvalue>
+ <hex8> ::= <hexprefix> <hexvalue>
+ <hexprefix>::= '0' 'x'
+ | '0' 'X'
+ <hexvalue> ::= <hexdigit> <hexvalue>
+ | <hexdigit>
+ <hexdigit> ::= [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. "<factor> ::= '('<bool>')'<rightfactor>" is added to support parentheses;
+ 4. "<factor> ::= GUID" is changed to "<factor> ::= <guid>";
+ 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
+
+
+--*/
+{
+ //
+ // <hexdigit> ::= [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);
+
+ //
+ // <rightfactor> ::=AND <term> <rightbool> <rightfactor>
+ //
+ 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;
+ }
+ }
+ //
+ // <rightfactor> ::=OR <term> <rightbool> <rightfactor>
+ //
+ 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;
+ }
+ }
+ //
+ // <rightfactor> ::= ''
+ //
+ *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);
+
+ //
+ // <rightbool>::= AND <term><rightbool>
+ //
+ 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;
+ }
+ }
+ //
+ // <rightbool>::= OR <term><rightbool>
+ //
+ 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;
+ }
+ }
+ //
+ // <rightbool>::= ''
+ //
+ *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);
+
+ //
+ // <factor> ::= '('<bool>')'<rightfactor>
+ //
+ 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;
+ }
+ }
+ }
+ }
+ //
+ // <factor> ::= NOT <factor> <rightbool> <rightfactor>
+ //
+ 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;
+ }
+ }
+ //
+ // <factor> ::= TRUE <rightfactor>
+ //
+ 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;
+ }
+ }
+ //
+ // <factor> ::= FALSE <rightfactor>
+ //
+ 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;
+ }
+ }
+ //
+ // <factor> ::= <guid> <rightfactor>
+ //
+ 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);
+
+ //
+ // <term> ::= NOT <factor>
+ //
+ 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;
+ }
+ }
+ //
+ // <term> ::=<factor>
+ //
+ 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 <INFILE> -O <OUTFILE> [-P <Optional Boundary for padding up>] \n",
+ UTILITY_NAME
+ );
+ printf (" Where:\n");
+ printf (" <INFILE> is the input pre-processed dependency text files name.\n");
+ printf (" <OUTFILE> is the output binary dependency files name.\n");
+ printf (" <Optional Boundary for padding up> 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:
+ <depex> ::= sor <dep> |
+ before GUID <dep> |
+ after GUID <dep> |
+ <bool>
+
+ <dep> ::= <bool> |
+
+ <bool> ::= <bool> and <term> |
+ <bool> or <term> |
+ <term>
+
+ <term> ::= not <factor> |
+ <factor>
+
+ <factor> ::= ( <bool> ) |
+ <term> <term> |
+ GUID |
+ <boolval>
+
+ <boolval> ::= true |
+ false
+
+ The outputed binary grammer is thus:
+ <depex> ::= sor <dep> |
+ before <depinst> <dep> |
+ after <depinst> <dep> |
+ <bool>
+
+ <dep> ::= <bool> |
+
+ <bool> ::= <bool> and <term> |
+ <bool> or <term> | <term>
+
+ <term> ::= not <factor> |
+ <factor>
+
+ <factor> ::= ( <bool> ) |
+ <term> <term> |
+ <boolval> |
+ <depinst> |
+ <termval>
+
+ <boolval> ::= true |
+ false
+
+ <depinst> ::= push GUID
+
+ <termval> ::= 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 <INFILE> for reading.\n");
+ PrintGenDepexUsageInfo ();
+ return EFI_ABORTED;
+ }
+
+ if (OutFile == NULL) {
+ printf ("Can not open <OUTFILE> 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 <stdio.h>
+#include <stdlib.h>
+#include <memory.h>
+#include <string.h>
+#include <malloc.h>
+
+#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 <stdio.h>
+#include <ctype.h> // for isalpha()
+//
+// include file for _spawnv
+//
+#include <process.h>
+#include <stdlib.h>
+#include <string.h>
+#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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#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 <string.h>
+#include EFI_GUID_DEFINITION (PeiPeCoffLoader)
+#include "EfiFirmwareFileSystem.h"
+#include "EfiWorkingBlockHeader.h"
+#include "EfiVariable.h"
+#include <io.h>
+#include <assert.h>
+#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 <stdlib.h>
+#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 <stdio.h>
+#include <stdlib.h>
+#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 [<PageTableBaseAddrss> <PageTableOffsetInFile>]\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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#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 <stdio.h>
+
+#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 <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <direct.h>
+#include <windows.h>
+
+//
+// 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#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 <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#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:
+ <FileName>(<LineNumber>) : <Type> <Type[0]><MessageCode>: <Text> : <MsgFmt>
+
+ 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#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 <system> 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 <file> 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 <include> 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 <stdio.h> // for file ops
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h> // 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h> // 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 <windows.h> // for max_path definition
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h> // 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 <windows.h> // for GetShortPathName()
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <direct.h> // for _mkdir()
+#include <errno.h>
+#include <stdlib.h> // 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).<extension>]
+ //
+ 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).<Extension>" 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 <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#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 <PE-File> <TIME-File>\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, &ltime, 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, &ltime, 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, &ltime, 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, &ltime, 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, &ltime, 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, &ltime) != 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 (&ltime));
+
+ //
+ // 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 <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+
+#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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h> // 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 <stdio.h>
+
+_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 <string.h>
+
+//
+// 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 <ctype.h>
+#include <direct.h>
+#include <process.h> // 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 <boolean_expression> { grayoutif } <statements>+ 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, } <boolean_expression> 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 <stdio.h> // for FILE routines
+#include <stdlib.h> // 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