diff --git a/BaseTools/Edk2ToolsBuild.py b/BaseTools/Edk2ToolsBuild.py
index e810d63421..df22ebbf2c 100644
--- a/BaseTools/Edk2ToolsBuild.py
+++ b/BaseTools/Edk2ToolsBuild.py
@@ -190,6 +190,10 @@ def Go(self):
shell_env.insert_path(shell_env.get_shell_var("EDK_TOOLS_BIN"))
# Actually build the tools.
+ # MU_CHANGE [BEGIN] - Run nmake clean for GenStm
+ ret = RunCmd('nmake.exe', 'clean',
+ workingdir=shell_env.get_shell_var("EDK_TOOLS_PATH"))
+ # MU_CHANGE [END] - Run nmake clean for GenStm
output_stream = edk2_logging.create_output_stream()
ret = RunCmd('nmake.exe', None,
workingdir=shell_env.get_shell_var("EDK_TOOLS_PATH"))
diff --git a/BaseTools/Source/C/GNUmakefile b/BaseTools/Source/C/GNUmakefile
index 5275f657ef..1013e7f3e0 100644
--- a/BaseTools/Source/C/GNUmakefile
+++ b/BaseTools/Source/C/GNUmakefile
@@ -48,6 +48,7 @@ include Makefiles/header.makefile
all: makerootdir subdirs
@echo Finished building BaseTools C Tools with HOST_ARCH=$(HOST_ARCH)
+# MU_CHANGE [BEGIN] - Add the GenStm application
LIBRARIES = Common
VFRAUTOGEN = VfrCompile/VfrLexer.h
APPLICATIONS = \
@@ -62,7 +63,9 @@ APPLICATIONS = \
LzmaCompress \
TianoCompress \
VolInfo \
- DevicePath
+ DevicePath \
+ GenStm
+# MU_CHANGE [END] - Add the GenStm application
SUBDIRS := $(LIBRARIES) $(APPLICATIONS)
diff --git a/BaseTools/Source/C/GenStm/GNUmakefile b/BaseTools/Source/C/GenStm/GNUmakefile
new file mode 100644
index 0000000000..2c94b7a126
--- /dev/null
+++ b/BaseTools/Source/C/GenStm/GNUmakefile
@@ -0,0 +1,18 @@
+## @file
+# GNU/Linux makefile for 'GenStm' module build.
+#
+# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+# MU_CHANGE [WHOLE FILE] - Add the GenStm application
+#
+#
+MAKEROOT ?= ..
+
+APPNAME = GenStm
+
+LIBS = -lCommon
+
+OBJECTS = GenStm.o
+
+include $(MAKEROOT)/Makefiles/app.makefile
diff --git a/BaseTools/Source/C/GenStm/GenStm.c b/BaseTools/Source/C/GenStm/GenStm.c
new file mode 100644
index 0000000000..bd80cb30fb
--- /dev/null
+++ b/BaseTools/Source/C/GenStm/GenStm.c
@@ -0,0 +1,728 @@
+/** @file
+ STM tool generate STM binary
+
+ Copyright (c) 2015, 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.
+
+ # MU_CHANGE [WHOLE FILE] - Add the GenStm application
+
+**/
+
+#include "GenStm.h"
+
+#pragma pack (push, 1)
+
+typedef struct {
+ UINT16 LimitLow;
+ UINT16 BaseLow;
+ UINT8 BaseMid;
+ UINT8 Attribute;
+ UINT8 LimitHi;
+ UINT8 BaseHi;
+} GDT_ENTRY;
+
+#pragma pack (pop)
+
+GDT_ENTRY mGdtEntries[] = {
+// LimitLow BaseLow BaseMid Attribute LimitHi BaseHi
+ {0, 0, 0, 0, 0, 0, }, /* 0x0: reserve */
+ {0, 0, 0, 0, 0, 0, }, /* 0x0: reserve */
+ {0xFFFF, 0, 0, 0x9B, 0xCF, 0, }, /* 0x10: code 32 seg */
+ {0xFFFF, 0, 0, 0x93, 0xCF, 0, }, /* 0x18: data seg */
+ {0, 0, 0, 0, 0, 0, }, /* 0x20: reserve */
+ {104, 0, 0, 0x89, 0x80, 0, }, /* 0x28: TSS */
+ {0, 0, 0, 0, 0, 0, }, /* 0x30: reserve */
+ {0xFFFF, 0, 0, 0x9B, 0xAF, 0, }, /* 0x38: code 64 seg */
+ {0xFFFF, 0, 0, 0x93, 0xCF, 0, }, /* 0x40: data seg */
+};
+
+UINT64 DebugLevel = 0;
+BOOLEAN DebugMode = FALSE;
+BOOLEAN VerboseMode = FALSE;
+BOOLEAN QuietMode = FALSE;
+
+/**
+
+ Displays the standard utility information to SDTOUT.
+
+**/
+VOID
+Version (
+ VOID
+ )
+{
+ fprintf (stdout, "%s Version %d.%d\n", UTILITY_NAME, UTILITY_MAJOR_VERSION, UTILITY_MINOR_VERSION);
+}
+
+/**
+
+ Displays the utility usage syntax to STDOUT.
+
+**/
+VOID
+Usage (
+ VOID
+ )
+{
+ //
+ // Summary usage
+ //
+ fprintf (stdout, "Usage: %s -e [options] \n\n", UTILITY_NAME);
+
+ //
+ // Copyright declaration
+ //
+ fprintf (stdout, "Copyright (c) 2015, Intel Corporation. All rights reserved.\n\n");
+
+ //
+ // Details Option
+ //
+ fprintf (stdout, "Options:\n");
+ fprintf (stdout, " -o FileName, --output FileName\n\
+ File will be created to store the ouput content.\n");
+ fprintf (stdout, " -v, --verbose\n\
+ Turn on verbose output with informational messages.\n");
+ fprintf (stdout, " -q, --quiet\n\
+ Disable all messages except key message and fatal error\n");
+ fprintf (stdout, " --debug [0-9]\n\
+ Enable debug messages, at input debug level.\n");
+ fprintf (stdout, " --version\n\
+ Show program's version number and exit.\n");
+ fprintf (stdout, " -h, --help\n\
+ Show this help message and exit.\n");
+}
+
+/**
+
+ This function dump raw data.
+
+ @param Data raw data
+ @param Size raw data size
+
+**/
+VOID
+DumpData (
+ IN UINT8 *Data,
+ IN UINT32 Size
+ )
+{
+ UINT32 Index;
+ for (Index = 0; Index < Size; Index++) {
+ printf ("%02x", Data[Index]);
+ }
+}
+
+/**
+
+ This function dump raw data with colume format.
+
+ @param Data raw data
+ @param Size raw data size
+
+**/
+VOID
+DumpHex (
+ IN UINT8 *Data,
+ IN UINT32 Size
+ )
+{
+ UINT32 Index;
+ UINT32 Count;
+ UINT32 Left;
+
+#define COLUME_SIZE (16 * 2)
+
+ Count = Size / COLUME_SIZE;
+ Left = Size % COLUME_SIZE;
+ for (Index = 0; Index < Count; Index++) {
+ printf ("%04x: ", Index * COLUME_SIZE);
+ DumpData (Data + Index * COLUME_SIZE, COLUME_SIZE);
+ printf ("\n");
+ }
+
+ if (Left != 0) {
+ printf ("%04x: ", Index * COLUME_SIZE);
+ DumpData (Data + Index * COLUME_SIZE, Left);
+ printf ("\n");
+ }
+}
+
+/**
+
+ This function dump STM image.
+
+ @param StmHeader STM image header
+
+**/
+VOID
+DumpStmImage (
+ IN STM_HEADER *StmHeader
+ )
+{
+ UINT32 Index;
+
+ printf (
+ "*****************************************************************************\n"
+ "* STM Header *\n"
+ "*****************************************************************************\n"
+ );
+
+ printf ("STM Header (%08x)\n", (UINT32)(UINTN)StmHeader);
+ printf ("Hardware field:\n");
+ printf (" StmHeaderRevision - %08x\n", StmHeader->HwStmHdr.MsegHeaderRevision);
+ printf (" MonitorFeatures - %08x\n", StmHeader->HwStmHdr.MonitorFeatures);
+ printf (" GdtrLimit - %08x\n", StmHeader->HwStmHdr.GdtrLimit);
+ printf (" GdtrBaseOffset - %08x\n", StmHeader->HwStmHdr.GdtrBaseOffset);
+ printf (" CsSelector - %08x\n", StmHeader->HwStmHdr.CsSelector);
+ printf (" EipOffset - %08x\n", StmHeader->HwStmHdr.EipOffset);
+ printf (" EspOffset - %08x\n", StmHeader->HwStmHdr.EspOffset);
+ printf (" Cr3Offset - %08x\n", StmHeader->HwStmHdr.Cr3Offset);
+ printf ("Software field:\n");
+ printf (" StmSpecVerMajor - %02x\n", StmHeader->SwStmHdr.StmSpecVerMajor);
+ printf (" StmSpecVerMinor - %02x\n", StmHeader->SwStmHdr.StmSpecVerMinor);
+ printf (" StaticImageSize - %08x\n", StmHeader->SwStmHdr.StaticImageSize);
+ printf (" PerProcDynamicMemorySize - %08x\n", StmHeader->SwStmHdr.PerProcDynamicMemorySize);
+ printf (" AdditionalDynamicMemorySize - %08x\n", StmHeader->SwStmHdr.AdditionalDynamicMemorySize);
+ printf (" Intel64ModeSupported - %08x\n", StmHeader->SwStmHdr.StmFeatures.Intel64ModeSupported);
+ printf (" EptSupported - %08x\n", StmHeader->SwStmHdr.StmFeatures.EptSupported);
+ printf (" NumberOfRevIDs - %08x\n", StmHeader->SwStmHdr.NumberOfRevIDs);
+ for (Index = 0; Index < StmHeader->SwStmHdr.NumberOfRevIDs; Index++) {
+ printf (" StmSmmRevID(%02d) - %08x\n", Index, StmHeader->SwStmHdr.StmSmmRevID[Index]);
+ }
+
+ printf (
+ "*****************************************************************************\n\n"
+ );
+
+ return ;
+}
+
+/**
+
+ Read input file.
+
+ @param FileName - The input file name
+ @param FileData - The input file data, the memory is alligned.
+ @param FileSize - The input file size
+
+ @retval STATUS_SUCCESS - The file found and data read
+ @retval STATUS_ERROR - The file data is not read
+ @retval STATUS_WARNING - The file is not found
+
+**/
+STATUS
+ReadInputFile (
+ IN CHAR8 *FileName,
+ OUT UINT8 **FileData,
+ OUT UINT32 *FileSize
+ )
+{
+ FILE *FpIn;
+ UINT32 TempResult;
+
+ //
+ // Open the Input file
+ //
+ if ((FpIn = fopen (FileName, "rb")) == NULL) {
+ //
+ // Return WARNING, let caller make decision
+ //
+ Error (NULL, 0, 0, "Unable to open file", FileName);
+ return STATUS_WARNING;
+ }
+ //
+ // Get the Input file size
+ //
+ fseek (FpIn, 0, SEEK_END);
+ *FileSize = ftell (FpIn);
+ //
+ // Read the contents of input file to memory buffer
+ //
+ *FileData = (UINT8 *) malloc (*FileSize);
+ fseek (FpIn, 0, SEEK_SET);
+ TempResult = fread (*FileData, 1, *FileSize, FpIn);
+ if (TempResult != *FileSize) {
+ Error (NULL, 0, 0, "Read input file error!", NULL);
+ free ((VOID *)*FileData);
+ fclose (FpIn);
+ return STATUS_ERROR;
+ }
+
+ //
+ // Close the input file
+ //
+ fclose (FpIn);
+
+ return STATUS_SUCCESS;
+}
+
+/**
+
+ Write output file.
+
+ @param FileName - The input file name
+ @param FileData - The input file data
+ @param FileSize - The input file size
+
+ @retval STATUS_SUCCESS - Write file data successfully
+ @retval STATUS_ERROR - The file data is not written
+
+**/
+STATUS
+WriteOutputFile (
+ IN CHAR8 *FileName,
+ IN UINT8 *FileData,
+ IN UINT32 FileSize
+ )
+{
+ FILE *FpOut;
+
+ //
+ // Open the output file
+ //
+ if ((FpOut = fopen (FileName, "w+b")) == NULL) {
+ Error (NULL, 0, 0, "Unable to open file", FileName);
+ return STATUS_ERROR;
+ }
+ //
+ // Write the output file
+ //
+ if ((fwrite (FileData, 1, FileSize, FpOut)) != FileSize) {
+ Error (NULL, 0, 0, "Write output file error!", NULL);
+ return STATUS_ERROR;
+ }
+
+ //
+ // Close the output file
+ //
+ fclose (FpOut);
+
+ return STATUS_SUCCESS;
+}
+
+/**
+
+ Construct STM image.
+
+ +--------------------+ --
+ | SMM VMCS | |
+ +--------------------+ |-> Per-Processor VMCS
+ | SMI VMCS | |
+ +--------------------+ --
+ | SMM VMCS | |
+ +--------------------+ |-> Per-Processor VMCS
+ | SMI VMCS | |
+ +--------------------+ --
+ | Stack | |-> Per-Processor Dynamic
+ +--------------------+ --
+ | Stack | |-> Per-Processor Dynamic
+ RSP-> +--------------------+ --
+ | Heap | |
+ +--------------------+ |-> Additional Dynamic
+ | Page Table (24K) | |
+ CR3-> +--------------------+ --
+ RIP-> | STM Code | |
+ +--------------------+ |
+ | GDT (4K) | |-> Static Image
+ GDT-> +--------------------+ |
+ | STM Header (4K) | |
+ MSEG-> +--------------------+ --
+
+ @param InStmImage STM input PE/COFF image
+ @param InStmImageSize STM input PE/COFF image size
+ @param OutStmImage STM output image (See static image above)
+ @param OutStmImageSize STM output image size
+
+ @retval STATUS_SUCCESS - STM image is constructed correctly
+ @retval STATUS_ERROR - Input file format incorrect
+
+**/
+STATUS
+ConstructStmImage (
+ IN UINT8 *InStmImage,
+ IN UINT32 InStmImageSize,
+ OUT UINT8 **OutStmImage,
+ OUT UINT32 *OutStmImageSize
+ )
+{
+ EFI_IMAGE_DOS_HEADER *DosHdr;
+ UINT32 PeCoffHeaderOffset;
+ EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
+ UINT16 Magic;
+ STM_HEADER *StmHeader;
+
+ UINT32 AddressOfEntryPoint;
+ UINT32 SizeOfImage;
+ UINT32 SizeOfStack;
+ UINT32 SizeOfHeap;
+ UINT32 SizeOfImageRaw;
+ EFI_IMAGE_SECTION_HEADER *SectionHeader;
+ UINTN Index;
+
+ UINTN OutPadSectionSize;
+ EFI_COMMON_SECTION_HEADER2 *OutPadSection;
+ BOOLEAN NeedAddSectionHeader;
+
+ //
+ // Step 0, collect info
+ //
+ DosHdr = (EFI_IMAGE_DOS_HEADER *)InStmImage;
+ PeCoffHeaderOffset = 0;
+ OutPadSectionSize = 0;
+ OutPadSection = NULL;
+ NeedAddSectionHeader = FALSE;
+
+ if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+ PeCoffHeaderOffset = DosHdr->e_lfanew;
+ } else {
+ //
+ // EDK2 build environment may add section header, so we need skip it
+ //
+ OutPadSection = (EFI_COMMON_SECTION_HEADER2 *)InStmImage;
+ if (OutPadSection->Type != EFI_SECTION_RAW) {
+ Error (NULL, 0, 1001, "Input file incorrect", "Input file should be DLL with RAW section header.");
+ return STATUS_ERROR;
+ }
+ NeedAddSectionHeader = TRUE;
+ //
+ // Skip Section Header
+ //
+ if ((*(UINT32 *)OutPadSection->Size & 0xFFFFFF) != 0xFFFFFF) {
+ OutPadSectionSize = sizeof (EFI_COMMON_SECTION_HEADER);
+ } else {
+ OutPadSectionSize = sizeof (EFI_COMMON_SECTION_HEADER2);
+ }
+ InStmImage += OutPadSectionSize;
+ InStmImageSize -= OutPadSectionSize;
+ //
+ // Check again
+ //
+ DosHdr = (EFI_IMAGE_DOS_HEADER *)InStmImage;
+ if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+ PeCoffHeaderOffset = DosHdr->e_lfanew;
+ } else {
+ Error (NULL, 0, 1001, "Input file incorrect", "Input file should be DLL or DLL with RAW section header.");
+ return STATUS_ERROR;
+ }
+ }
+ Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(UINTN)(InStmImage + PeCoffHeaderOffset);
+ Magic = Hdr.Pe32->OptionalHeader.Magic;
+
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ AddressOfEntryPoint = (UINT32)Hdr.Pe32->OptionalHeader.AddressOfEntryPoint;
+ SizeOfImage = (UINT32)Hdr.Pe32->OptionalHeader.SizeOfImage;
+ SizeOfHeap = (UINT32)Hdr.Pe32->OptionalHeader.SizeOfHeapCommit;
+ SizeOfStack = (UINT32)Hdr.Pe32->OptionalHeader.SizeOfStackCommit;
+ } else {
+ AddressOfEntryPoint = (UINT32)Hdr.Pe32Plus->OptionalHeader.AddressOfEntryPoint;
+ SizeOfImage = (UINT32)Hdr.Pe32Plus->OptionalHeader.SizeOfImage;
+ SizeOfHeap = (UINT32)Hdr.Pe32Plus->OptionalHeader.SizeOfHeapCommit;
+ SizeOfStack = (UINT32)Hdr.Pe32Plus->OptionalHeader.SizeOfStackCommit;
+ }
+ SizeOfImageRaw = SizeOfImage;
+ SizeOfImage = STM_PAGES_TO_SIZE (STM_SIZE_TO_PAGES (SizeOfImage));
+
+ if (NeedAddSectionHeader) {
+ //
+ // Adjust size when necessary
+ //
+ if (OutPadSectionSize == sizeof (EFI_COMMON_SECTION_HEADER)) {
+ if (SizeOfImageRaw + STM_CODE_OFFSET + sizeof (EFI_COMMON_SECTION_HEADER2) > 0xFFFFFF) {
+ //
+ // If it exceeds 0xFFFFFF, we need use EFI_COMMON_SECTION_HEADER2
+ //
+ OutPadSectionSize = sizeof (EFI_COMMON_SECTION_HEADER2);
+ }
+ }
+ }
+
+ *OutStmImageSize = SizeOfImageRaw + STM_CODE_OFFSET;
+ if (NeedAddSectionHeader) {
+ *OutStmImageSize += OutPadSectionSize;
+ }
+ *OutStmImage = (UINT8 *) malloc (*OutStmImageSize);
+ ZeroMem (*OutStmImage, *OutStmImageSize);
+
+ //
+ // Fill Section header
+ //
+ if (NeedAddSectionHeader) {
+ if (OutPadSectionSize != 0) {
+ OutPadSection = (EFI_COMMON_SECTION_HEADER2 *)*OutStmImage;
+ *OutStmImage += OutPadSectionSize;
+ if (OutPadSectionSize == sizeof (EFI_COMMON_SECTION_HEADER)) {
+ *(UINT32 *)OutPadSection->Size = *OutStmImageSize;
+ } else {
+ *(UINT32 *)OutPadSection->Size = 0xFFFFFF;
+ OutPadSection->ExtendedSize = *OutStmImageSize;
+ }
+ OutPadSection->Type = EFI_SECTION_RAW;
+ } else {
+ OutPadSection = NULL;
+ }
+ }
+
+ //
+ // Step 1: STM header
+ //
+
+ //
+ // 1.1 hardware field
+ //
+
+ StmHeader = (STM_HEADER *)(*OutStmImage);
+ StmHeader->HwStmHdr.MsegHeaderRevision = 0;
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ StmHeader->HwStmHdr.MonitorFeatures = 0;
+ StmHeader->HwStmHdr.CsSelector = 0x10;
+ } else {
+ StmHeader->HwStmHdr.MonitorFeatures = STM_FEATURES_IA32E;
+ StmHeader->HwStmHdr.CsSelector = 0x38;
+ }
+ StmHeader->HwStmHdr.GdtrLimit = sizeof(mGdtEntries) - 1;
+ StmHeader->HwStmHdr.GdtrBaseOffset = STM_GDT_OFFSET;
+ StmHeader->HwStmHdr.EipOffset = STM_CODE_OFFSET + AddressOfEntryPoint;
+ StmHeader->HwStmHdr.Cr3Offset = STM_CODE_OFFSET + SizeOfImage;
+ StmHeader->HwStmHdr.EspOffset = STM_CODE_OFFSET + SizeOfImage + SizeOfHeap + STM_PAGES_TO_SIZE (6); // let it point to first stack bottom
+
+ //
+ // 1.2 software field
+ //
+ StmHeader->SwStmHdr.StmSpecVerMajor = STM_SPEC_VERSION_MAJOR;
+ StmHeader->SwStmHdr.StmSpecVerMinor = STM_SPEC_VERSION_MINOR;
+ StmHeader->SwStmHdr.StaticImageSize = STM_CODE_OFFSET + SizeOfImageRaw;
+ StmHeader->SwStmHdr.AdditionalDynamicMemorySize = SizeOfHeap + STM_PAGES_TO_SIZE (6);
+ StmHeader->SwStmHdr.PerProcDynamicMemorySize = SizeOfStack;
+ if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+ StmHeader->SwStmHdr.StmFeatures.Intel64ModeSupported = 0;
+ } else {
+ StmHeader->SwStmHdr.StmFeatures.Intel64ModeSupported = 1;
+ }
+ StmHeader->SwStmHdr.StmFeatures.EptSupported = 1;
+ StmHeader->SwStmHdr.NumberOfRevIDs = 1;
+ StmHeader->SwStmHdr.StmSmmRevID[0] = STM_SMM_REV_ID;
+
+ //
+ // Step 2: GDT
+ //
+ CopyMem ((VOID *)((UINTN)StmHeader + StmHeader->HwStmHdr.GdtrBaseOffset), (VOID *)mGdtEntries, sizeof(mGdtEntries));
+
+ //
+ // Step 3: code
+ //
+
+ //
+ // 3.1 PE header
+ //
+ CopyMem ((VOID *)((UINTN)StmHeader + STM_CODE_OFFSET), InStmImage, Hdr.Pe32->OptionalHeader.SizeOfHeaders);
+
+ //
+ // 3.2 section
+ //
+ SectionHeader = (EFI_IMAGE_SECTION_HEADER *)(UINTN)(InStmImage +
+ PeCoffHeaderOffset +
+ sizeof (UINT32) +
+ sizeof (EFI_IMAGE_FILE_HEADER) +
+ Hdr.Pe32->FileHeader.SizeOfOptionalHeader
+ );
+ for (Index = 0; Index < Hdr.Pe32->FileHeader.NumberOfSections; Index++) {
+ if (SectionHeader[Index].SizeOfRawData != 0) {
+ CopyMem (
+ (VOID *)((UINTN)StmHeader + STM_CODE_OFFSET + SectionHeader[Index].VirtualAddress),
+ InStmImage + SectionHeader[Index].PointerToRawData,
+ SectionHeader[Index].Misc.VirtualSize
+ );
+ }
+ }
+
+ if (NeedAddSectionHeader) {
+ if ((OutPadSectionSize != 0) && (OutPadSection != NULL)) {
+ *OutStmImage = (UINT8 *)OutPadSection;
+ }
+ }
+
+ return STATUS_SUCCESS;
+}
+
+/**
+
+ Main function.
+
+ @param argc Number of command line parameters.
+ @param argv Array of pointers to parameter strings.
+
+ @retval STATUS_SUCCESS Utility exits successfully.
+ @retval STATUS_ERROR Some error occurred during execution.
+
+**/
+STATUS
+main (
+ IN INT32 argc,
+ IN CHAR8 **argv
+ )
+{
+ STATUS Status;
+ CHAR8 *InFileName;
+ CHAR8 *OutFileName;
+ UINT8 *InStmImage;
+ UINT32 InStmImageSize;
+ UINT8 *OutStmImage;
+ UINT32 OutStmImageSize;
+
+ SetUtilityName (UTILITY_NAME);
+
+ //
+ // Verify the correct number of arguments
+ //
+ if (argc == 1) {
+ Error (NULL, 0, 1001, "Missing options", "No input options specified.");
+ Usage();
+ return 0;
+ }
+
+ if ((strcmp(argv[1], "-h") == 0) || (strcmp(argv[1], "--help") == 0)) {
+ Usage();
+ return 0;
+ }
+
+ if ((strcmp(argv[1], "--version") == 0)) {
+ Version();
+ return 0;
+ }
+
+ argc--;
+ argv++;
+ if (strcmp(argv[0],"-e") == 0) {
+ argc--;
+ argv++;
+ } else {
+ //
+ // Error command line
+ //
+ Error (NULL, 0, 1003, "Invalid option value", "the options specified are not recognized.");
+ Usage();
+ return 1;
+ }
+
+ InFileName = NULL;
+ OutFileName = NULL;
+ while (argc > 0) {
+ if ((strcmp(argv[0], "-v") == 0) || (stricmp(argv[0], "--verbose") == 0)) {
+ VerboseMode = TRUE;
+ argc--;
+ argv++;
+ continue;
+ }
+
+ if (stricmp (argv[0], "--debug") == 0) {
+ argc-=2;
+ argv++;
+ Status = AsciiStringToUint64(argv[0], FALSE, &DebugLevel);
+ if (DebugLevel > 9) {
+ Error (NULL, 0 ,2000, "Invalid parameter", "Unrecognized argument %s", argv[0]);
+ goto ERROR;
+ }
+ if (DebugLevel>=5 && DebugLevel <=9){
+ DebugMode = TRUE;
+ } else {
+ DebugMode = FALSE;
+ }
+ argv++;
+ continue;
+ }
+
+ if ((strcmp(argv[0], "-q") == 0) || (stricmp (argv[0], "--quiet") == 0)) {
+ QuietMode = TRUE;
+ argc--;
+ argv++;
+ continue;
+ }
+
+ if ((strcmp(argv[0], "-o") == 0) || (stricmp (argv[0], "--output") == 0)) {
+ if (argv[1] == NULL || argv[1][0] == '-') {
+ Error (NULL, 0, 1003, "Invalid option value", "Output File name is missing for -o option");
+ goto ERROR;
+ }
+ OutFileName = argv[1];
+ argc -=2;
+ argv +=2;
+ continue;
+ }
+
+ if (argv[0][0] != '-') {
+ InFileName = argv[0];
+ argc--;
+ argv++;
+ continue;
+ }
+
+ Error (NULL, 0, 1000, "Unknown option", argv[0]);
+ goto ERROR;
+ }
+
+ if (InFileName == NULL) {
+ Error (NULL, 0, 1001, "Missing options", "No input files specified.");
+ goto ERROR;
+ }
+
+ if (OutFileName == NULL) {
+ Error (NULL, 0, 1001, "Missing options", "No output files specified.");
+ goto ERROR;
+ }
+
+ //
+ // All Parameters has been parsed, now set the message print level
+ //
+ if (QuietMode) {
+ SetPrintLevel(40);
+ } else if (VerboseMode) {
+ SetPrintLevel(15);
+ } else if (DebugMode) {
+ SetPrintLevel(DebugLevel);
+ }
+
+ if (VerboseMode) {
+ VerboseMsg("%s tool start.\n", UTILITY_NAME);
+ }
+ //
+ // Read STM efi image
+ //
+ Status = ReadInputFile (InFileName, &InStmImage, &InStmImageSize);
+ if (Status != STATUS_SUCCESS) {
+ goto ERROR;
+ }
+
+ Status = ConstructStmImage (InStmImage, InStmImageSize, &OutStmImage, &OutStmImageSize);
+ if (Status != STATUS_SUCCESS) {
+ goto ERROR;
+ }
+
+ //
+ // Dump DLME descriptor
+ //
+ if (DebugMode) {
+ DumpStmImage ((STM_HEADER *)OutStmImage);
+ }
+
+ //
+ // Write STM binary image
+ //
+ Status = WriteOutputFile (OutFileName, OutStmImage, OutStmImageSize);
+ if (Status != STATUS_SUCCESS) {
+ goto ERROR;
+ }
+ if (VerboseMode) {
+ VerboseMsg("%s successfully\n", UTILITY_NAME);
+ }
+
+ return 0;
+ERROR:
+ return GetUtilityStatus ();
+}
+
diff --git a/BaseTools/Source/C/GenStm/GenStm.h b/BaseTools/Source/C/GenStm/GenStm.h
new file mode 100644
index 0000000000..1b3f8690bd
--- /dev/null
+++ b/BaseTools/Source/C/GenStm/GenStm.h
@@ -0,0 +1,72 @@
+/** @file
+ STM tool generate STM binary
+
+ Copyright (c) 2015, 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.
+
+ # MU_CHANGE [WHOLE FILE] - Add the GenStm application
+
+**/
+
+#ifndef _GEN_STM_H_
+#define _GEN_STM_H_
+
+#include
+#include
+#include
+#include
+
+#include "EfiUtilityMsgs.h"
+#include "CommonLib.h"
+#include "ParseInf.h"
+
+#include
+
+//
+// Data structure needed to pass build
+//
+#include
+
+#define SIZE_2KB 0x00000800
+
+#include
+
+//
+// The EFI memory allocation functions work in units of EFI_PAGEs that are
+// 4K. This should in no way be confused with the page size of the processor.
+// An EFI_PAGE is just the quanta of memory in EFI.
+//
+#define STM_PAGE_SIZE 0x1000
+#define STM_PAGE_MASK 0xFFF
+#define STM_PAGE_SHIFT 12
+
+#define STM_SIZE_TO_PAGES(a) (((a) >> STM_PAGE_SHIFT) + (((a) & STM_PAGE_MASK) ? 1 : 0))
+
+#define STM_PAGES_TO_SIZE(a) ( (a) << STM_PAGE_SHIFT)
+
+//
+// Utility Name
+//
+#define UTILITY_NAME "GenStm"
+
+//
+// Utility version information
+//
+#define UTILITY_MAJOR_VERSION 0
+#define UTILITY_MINOR_VERSION 1
+#define UTILITY_DATE __DATE__
+
+//
+// STM data structure
+//
+#define STM_DATA_OFFSET 0x1000
+#define STM_GDT_OFFSET STM_DATA_OFFSET
+#define STM_CODE_OFFSET STM_DATA_OFFSET + 0x1000
+
+#endif
diff --git a/BaseTools/Source/C/GenStm/Makefile b/BaseTools/Source/C/GenStm/Makefile
new file mode 100644
index 0000000000..4a4122ef54
--- /dev/null
+++ b/BaseTools/Source/C/GenStm/Makefile
@@ -0,0 +1,17 @@
+## @file
+# Windows makefile for the GenStm C tool build.
+#
+# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+# MU_CHANGE [WHOLE FILE] - Add the GenStm application
+
+!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.common
+
+APPNAME = GenStm
+
+LIBS = $(LIB_PATH)\Common.lib
+
+OBJECTS = GenStm.obj
+
+!INCLUDE $(BASE_TOOLS_PATH)\Source\C\Makefiles\ms.app
diff --git a/BaseTools/Source/C/Makefile b/BaseTools/Source/C/Makefile
index dd709e0cf8..c10341c586 100644
--- a/BaseTools/Source/C/Makefile
+++ b/BaseTools/Source/C/Makefile
@@ -11,6 +11,7 @@ HOST_ARCH = IA32
!INCLUDE Makefiles\ms.common
+# MU_CHANGE [BEGIN] - Add the GenStm application
LIBRARIES = Common
APPLICATIONS = \
VfrCompile \
@@ -26,6 +27,12 @@ APPLICATIONS = \
VolInfo \
DevicePath
+!IF "$(HOST_ARCH)" == "IA32" || "$(HOST_ARCH)" == "X64"
+APPLICATIONS = $(APPLICATIONS) \
+ GenStm
+!ENDIF
+# MU_CHANGE [END] - Add the GenStm application
+
all: libs apps install
libs: $(LIBRARIES)
diff --git a/BaseTools/Source/C/Makefiles/ms.common b/BaseTools/Source/C/Makefiles/ms.common
index cb854f5bf7..81ddc4334a 100644
--- a/BaseTools/Source/C/Makefiles/ms.common
+++ b/BaseTools/Source/C/Makefiles/ms.common
@@ -44,14 +44,14 @@ BIN_PATH = $(BASE_TOOLS_PATH)\Bin\Win32
LIB_PATH = $(BASE_TOOLS_PATH)\Lib\Win32
SYS_BIN_PATH = $(EDK_TOOLS_PATH)\Bin\Win32
SYS_LIB_PATH = $(EDK_TOOLS_PATH)\Lib\Win32
-
+CFLAGS = $(CFLAGS) /wd4200 # MU_CHANGE - Add the GenStm application
!ELSEIF "$(HOST_ARCH)"=="X64"
ARCH_INCLUDE = $(EDK2_PATH)\MdePkg\Include\X64
BIN_PATH = $(BASE_TOOLS_PATH)\Bin\Win64
LIB_PATH = $(BASE_TOOLS_PATH)\Lib\Win64
SYS_BIN_PATH = $(EDK_TOOLS_PATH)\Bin\Win64
SYS_LIB_PATH = $(EDK_TOOLS_PATH)\Lib\Win64
-
+CFLAGS = $(CFLAGS) /wd4200 # MU_CHANGE - Add the GenStm application
# MU_CHANGE Starts: Adding support to build base tools for ARM and AARCH64
!ELSEIF "$(HOST_ARCH)"=="ARM"
ARCH_INCLUDE = $(EDK2_PATH)\MdePkg\Include\Arm