From 3195af72bd2129d05e81b013cb30c93342f76c03 Mon Sep 17 00:00:00 2001 From: Kun Qin Date: Fri, 12 Jan 2024 00:08:28 -0800 Subject: [PATCH] BaseTools: Add GenStm Adds GenStm as a C tool. Co-authored-by: Michael Kubacki Signed-off-by: Michael Kubacki --- BaseTools/Edk2ToolsBuild.py | 4 + BaseTools/Source/C/GNUmakefile | 5 +- BaseTools/Source/C/GenStm/GNUmakefile | 18 + BaseTools/Source/C/GenStm/GenStm.c | 728 +++++++++++++++++++++++++ BaseTools/Source/C/GenStm/GenStm.h | 72 +++ BaseTools/Source/C/GenStm/Makefile | 17 + BaseTools/Source/C/Makefile | 7 + BaseTools/Source/C/Makefiles/ms.common | 4 +- 8 files changed, 852 insertions(+), 3 deletions(-) create mode 100644 BaseTools/Source/C/GenStm/GNUmakefile create mode 100644 BaseTools/Source/C/GenStm/GenStm.c create mode 100644 BaseTools/Source/C/GenStm/GenStm.h create mode 100644 BaseTools/Source/C/GenStm/Makefile 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