aboutsummaryrefslogtreecommitdiff
path: root/MdePkg/Library
diff options
context:
space:
mode:
Diffstat (limited to 'MdePkg/Library')
-rw-r--r--MdePkg/Library/BaseFdtLib/LibFdtSupport.h22
-rw-r--r--MdePkg/Library/BasePeCoffLib/BasePeCoff.c44
-rw-r--r--MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf1
-rw-r--r--MdePkg/Library/BasePeCoffLib/LoongArch/PeCoffLoaderEx.c10
-rw-r--r--MdePkg/Library/BaseRngLib/AArch64/ArmRng.S2
-rw-r--r--MdePkg/Library/BaseRngLib/AArch64/ArmRng.asm2
-rw-r--r--MdePkg/Library/BaseRngLib/AArch64/ArmRng.h2
-rw-r--r--MdePkg/Library/BaseRngLib/BaseRngLibInternals.h7
-rw-r--r--MdePkg/Library/BaseRngLib/Rand/RdRand.c37
-rw-r--r--MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf1
-rw-r--r--MdePkg/Library/DxeRngLib/DxeRngLib.c7
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/AArch64/DynamicCookieGcc.S56
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCore/DxeCoreEntryPoint.c70
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCore/DxeCoreEntryPoint.uni16
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCoreEntryPoint.inf45
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/IA32/DynamicCookieGcc.nasm63
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/IA32/DynamicCookieMsvc.nasm63
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCore/X64/StandaloneMmCoreEntryPoint.c65
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCoreEntryPoint.inf38
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriver/StandaloneMmDriverEntryPoint.c135
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriver/StandaloneMmDriverEntryPoint.uni17
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriverEntryPoint.inf53
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/ApplicationEntryPoint.c112
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/UefiApplicationEntryPoint.uni16
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplicationEntryPoint.inf45
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriver/DriverEntryPoint.c162
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriver/UefiDriverEntryPoint.uni16
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriverEntryPoint.inf68
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/X64/DynamicCookieGcc.nasm63
-rw-r--r--MdePkg/Library/DynamicStackCookieEntryPointLib/X64/DynamicCookieMsvc.nasm63
-rw-r--r--MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf2
-rw-r--r--MdePkg/Library/PeiRngLib/PeiRngLib.c229
-rw-r--r--MdePkg/Library/PeiRngLib/PeiRngLib.inf41
-rw-r--r--MdePkg/Library/PeiRngLib/PeiRngLib.uni12
-rw-r--r--MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf2
-rw-r--r--MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf1
-rw-r--r--MdePkg/Library/StackCheckLib/Readme.md197
-rw-r--r--MdePkg/Library/StackCheckLib/StackCheckLib.inf56
-rw-r--r--MdePkg/Library/StackCheckLib/StackCheckLibCommonGcc.c2
-rw-r--r--MdePkg/Library/StackCheckLib/StackCheckLibCommonMsvc.c1
-rw-r--r--MdePkg/Library/StackCheckLibNull/StackCheckLibNullGcc.c1
-rw-r--r--MdePkg/Library/StackCheckLibNull/StackCheckLibNullMsvc.c1
-rw-r--r--MdePkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf33
-rw-r--r--MdePkg/Library/StandaloneMmCoreEntryPoint/X64/StandaloneMmCoreEntryPoint.c69
-rw-r--r--MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf1
-rw-r--r--MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf1
-rw-r--r--MdePkg/Library/UefiDevicePathLib/DevicePathToText.c12
-rw-r--r--MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf1
-rw-r--r--MdePkg/Library/UefiUsbLib/UefiUsbLib.inf3
-rw-r--r--MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h2
-rw-r--r--MdePkg/Library/UefiUsbLib/UsbDxeLib.c533
51 files changed, 2363 insertions, 138 deletions
diff --git a/MdePkg/Library/BaseFdtLib/LibFdtSupport.h b/MdePkg/Library/BaseFdtLib/LibFdtSupport.h
index ebe1eb6b26c8..03532c8c4d96 100644
--- a/MdePkg/Library/BaseFdtLib/LibFdtSupport.h
+++ b/MdePkg/Library/BaseFdtLib/LibFdtSupport.h
@@ -14,17 +14,21 @@
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
-typedef UINT8 uint8_t;
-typedef UINT16 uint16_t;
-typedef INT32 int32_t;
-typedef UINT32 uint32_t;
-typedef UINT64 uint64_t;
-typedef UINTN uintptr_t;
-typedef UINTN size_t;
-typedef BOOLEAN bool;
-
+typedef UINT8 uint8_t;
+typedef UINT16 uint16_t;
+typedef INT32 int32_t;
+typedef UINT32 uint32_t;
+typedef UINT64 uint64_t;
+typedef UINTN uintptr_t;
+typedef UINTN size_t;
+
+#if defined __STDC_VERSION__ && __STDC_VERSION__ > 201710L
+/* bool, true and false are keywords. */
+#else
+typedef BOOLEAN bool;
#define true (1 == 1)
#define false (1 == 0)
+#endif
//
// Definitions for global constants used by libfdt library routines
diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
index 9e74622fe48a..8c9f0c9450e4 100644
--- a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
+++ b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
@@ -24,6 +24,7 @@
**/
#include "BasePeCoffLibInternals.h"
+#include <Library/SafeIntLib.h>
/**
Adjust some fields in section header for TE image.
@@ -975,6 +976,7 @@ PeCoffLoaderRelocateImage (
PHYSICAL_ADDRESS BaseAddress;
UINT32 NumberOfRvaAndSizes;
UINT32 TeStrippedOffset;
+ UINT32 EndAddress;
ASSERT (ImageContext != NULL);
@@ -1054,22 +1056,24 @@ PeCoffLoaderRelocateImage (
RelocDir = &Hdr.Te->DataDirectory[0];
}
- if ((RelocDir != NULL) && (RelocDir->Size > 0) && ((RelocDir->Size - 1) < (MAX_UINT32 - RelocDir->VirtualAddress))) {
- RelocBase = (EFI_IMAGE_BASE_RELOCATION *)PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress, TeStrippedOffset);
- RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *)PeCoffLoaderImageAddress (
- ImageContext,
- RelocDir->VirtualAddress + RelocDir->Size - 1,
- TeStrippedOffset
- );
+ RelocBase = NULL;
+ RelocBaseEnd = NULL;
+ if ((RelocDir != NULL) && (RelocDir->Size > 0)) {
+ Status = SafeUint32Add (RelocDir->VirtualAddress, (RelocDir->Size - 1), &EndAddress);
+ if (!RETURN_ERROR (Status)) {
+ RelocBase = (EFI_IMAGE_BASE_RELOCATION *)PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress, TeStrippedOffset);
+ RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *)PeCoffLoaderImageAddress (
+ ImageContext,
+ EndAddress,
+ TeStrippedOffset
+ );
+ }
+
if ((RelocBase == NULL) || (RelocBaseEnd == NULL) || ((UINTN)RelocBaseEnd < (UINTN)RelocBase)) {
ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
+ DEBUG ((DEBUG_ERROR, "Relocation block is not valid\n"));
return RETURN_LOAD_ERROR;
}
- } else {
- //
- // Set base and end to bypass processing below.
- //
- RelocBase = RelocBaseEnd = NULL;
}
RelocBaseOrg = RelocBase;
@@ -1767,6 +1771,7 @@ PeCoffLoaderRelocateImageForRuntime (
UINTN Adjust;
RETURN_STATUS Status;
PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
+ UINT32 EndAddress;
if ((RelocationData == NULL) || (ImageBase == 0x0) || (VirtImageBase == 0x0)) {
return;
@@ -1828,12 +1833,15 @@ PeCoffLoaderRelocateImageForRuntime (
if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
RelocDir = DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC;
if ((RelocDir != NULL) && (RelocDir->Size > 0)) {
- RelocBase = (EFI_IMAGE_BASE_RELOCATION *)PeCoffLoaderImageAddress (&ImageContext, RelocDir->VirtualAddress, 0);
- RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *)PeCoffLoaderImageAddress (
- &ImageContext,
- RelocDir->VirtualAddress + RelocDir->Size - 1,
- 0
- );
+ Status = SafeUint32Add (RelocDir->VirtualAddress, (RelocDir->Size - 1), &EndAddress);
+ if (!RETURN_ERROR (Status)) {
+ RelocBase = (EFI_IMAGE_BASE_RELOCATION *)PeCoffLoaderImageAddress (&ImageContext, RelocDir->VirtualAddress, 0);
+ RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *)PeCoffLoaderImageAddress (
+ &ImageContext,
+ EndAddress,
+ 0
+ );
+ }
}
if ((RelocBase == NULL) || (RelocBaseEnd == NULL) || ((UINTN)RelocBaseEnd < (UINTN)RelocBase)) {
diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf b/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
index 0172d2691c68..80fd5344539d 100644
--- a/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+++ b/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
@@ -58,4 +58,5 @@
DebugLib
PeCoffExtraActionLib
BaseMemoryLib
+ SafeIntLib
diff --git a/MdePkg/Library/BasePeCoffLib/LoongArch/PeCoffLoaderEx.c b/MdePkg/Library/BasePeCoffLib/LoongArch/PeCoffLoaderEx.c
index 738b056dd1f5..f3ec94c07c5d 100644
--- a/MdePkg/Library/BasePeCoffLib/LoongArch/PeCoffLoaderEx.c
+++ b/MdePkg/Library/BasePeCoffLib/LoongArch/PeCoffLoaderEx.c
@@ -104,7 +104,15 @@ PeCoffLoaderImageFormatSupported (
IN UINT16 Machine
)
{
- if (Machine == IMAGE_FILE_MACHINE_LOONGARCH64) {
+ /*
+ * ARM64 and X64 may allow such foreign images to be used when
+ * a driver implementing EDKII_PECOFF_IMAGE_EMULATOR_PROTOCOL is
+ * present.
+ */
+ if ((Machine == IMAGE_FILE_MACHINE_LOONGARCH64) ||
+ (Machine == IMAGE_FILE_MACHINE_ARM64) ||
+ (Machine == IMAGE_FILE_MACHINE_X64))
+ {
return TRUE;
}
diff --git a/MdePkg/Library/BaseRngLib/AArch64/ArmRng.S b/MdePkg/Library/BaseRngLib/AArch64/ArmRng.S
index 688abba68b9e..10de2ecca456 100644
--- a/MdePkg/Library/BaseRngLib/AArch64/ArmRng.S
+++ b/MdePkg/Library/BaseRngLib/AArch64/ArmRng.S
@@ -8,7 +8,7 @@
#
#------------------------------------------------------------------------------
-#include "BaseRngLibInternals.h"
+#include "ArmRng.h"
.text
.p2align 2
diff --git a/MdePkg/Library/BaseRngLib/AArch64/ArmRng.asm b/MdePkg/Library/BaseRngLib/AArch64/ArmRng.asm
index 76f6e960ac11..c8666926c4db 100644
--- a/MdePkg/Library/BaseRngLib/AArch64/ArmRng.asm
+++ b/MdePkg/Library/BaseRngLib/AArch64/ArmRng.asm
@@ -8,7 +8,7 @@
;
;------------------------------------------------------------------------------
-#include "BaseRngLibInternals.h"
+#include "ArmRng.h"
EXPORT ArmRndr
AREA BaseLib_LowLevel, CODE, READONLY
diff --git a/MdePkg/Library/BaseRngLib/AArch64/ArmRng.h b/MdePkg/Library/BaseRngLib/AArch64/ArmRng.h
index 5937dd7deac2..12521a1a6f83 100644
--- a/MdePkg/Library/BaseRngLib/AArch64/ArmRng.h
+++ b/MdePkg/Library/BaseRngLib/AArch64/ArmRng.h
@@ -11,6 +11,8 @@
#ifndef ARM_RNG_H_
#define ARM_RNG_H_
+#include <AArch64/AArch64.h>
+
/**
Generates a random number using RNDR.
Returns TRUE on success; FALSE on failure.
diff --git a/MdePkg/Library/BaseRngLib/BaseRngLibInternals.h b/MdePkg/Library/BaseRngLib/BaseRngLibInternals.h
index 221f158066a7..3b5bdcf8a2e3 100644
--- a/MdePkg/Library/BaseRngLib/BaseRngLibInternals.h
+++ b/MdePkg/Library/BaseRngLib/BaseRngLibInternals.h
@@ -69,11 +69,4 @@ ArchIsRngSupported (
VOID
);
-#if defined (MDE_CPU_AARCH64)
-
-// RNDR, Random Number
-#define RNDR S3_3_C2_C4_0
-
-#endif
-
#endif // BASE_RNGLIB_INTERNALS_H_
diff --git a/MdePkg/Library/BaseRngLib/Rand/RdRand.c b/MdePkg/Library/BaseRngLib/Rand/RdRand.c
index 63ad43283d8d..d37808913875 100644
--- a/MdePkg/Library/BaseRngLib/Rand/RdRand.c
+++ b/MdePkg/Library/BaseRngLib/Rand/RdRand.c
@@ -2,6 +2,7 @@
Random number generator services that uses RdRand instruction access
to provide high-quality random numbers.
+Copyright (C) 2024 Advanced Micro Devices, Inc. All rights reserved.<BR>
Copyright (c) 2023, Arm Limited. All rights reserved.<BR>
Copyright (c) 2022, Pedro Falcato. All rights reserved.<BR>
Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
@@ -23,8 +24,6 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
//
#define RDRAND_MASK BIT30
-STATIC BOOLEAN mRdRandSupported;
-
//
// Intel SDM says 10 tries is good enough for reliable RDRAND usage.
//
@@ -124,20 +123,6 @@ BaseRngLibConstructor (
VOID
)
{
- UINT32 RegEcx;
-
- //
- // Determine RDRAND support by examining bit 30 of the ECX register returned by
- // CPUID. A value of 1 indicates that processor support RDRAND instruction.
- //
- AsmCpuid (1, 0, 0, &RegEcx, 0);
-
- mRdRandSupported = ((RegEcx & RDRAND_MASK) == RDRAND_MASK);
-
- if (mRdRandSupported) {
- mRdRandSupported = TestRdRand ();
- }
-
return EFI_SUCCESS;
}
@@ -156,7 +141,6 @@ ArchGetRandomNumber16 (
OUT UINT16 *Rand
)
{
- ASSERT (mRdRandSupported);
return AsmRdRand16 (Rand);
}
@@ -175,7 +159,6 @@ ArchGetRandomNumber32 (
OUT UINT32 *Rand
)
{
- ASSERT (mRdRandSupported);
return AsmRdRand32 (Rand);
}
@@ -194,7 +177,6 @@ ArchGetRandomNumber64 (
OUT UINT64 *Rand
)
{
- ASSERT (mRdRandSupported);
return AsmRdRand64 (Rand);
}
@@ -211,7 +193,22 @@ ArchIsRngSupported (
VOID
)
{
- return mRdRandSupported;
+ BOOLEAN RdRandSupported;
+ UINT32 RegEcx;
+
+ //
+ // Determine RDRAND support by examining bit 30 of the ECX register returned by
+ // CPUID. A value of 1 indicates that processor support RDRAND instruction.
+ //
+ AsmCpuid (1, 0, 0, &RegEcx, 0);
+
+ RdRandSupported = ((RegEcx & RDRAND_MASK) == RDRAND_MASK);
+
+ if (RdRandSupported) {
+ RdRandSupported = TestRdRand ();
+ }
+
+ return RdRandSupported;
}
/**
diff --git a/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf b/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
index 279263b04119..10b57e236d85 100644
--- a/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
+++ b/MdePkg/Library/DxeCoreEntryPoint/DxeCoreEntryPoint.inf
@@ -33,4 +33,5 @@
[LibraryClasses]
BaseLib
DebugLib
+ StackCheckLib
diff --git a/MdePkg/Library/DxeRngLib/DxeRngLib.c b/MdePkg/Library/DxeRngLib/DxeRngLib.c
index 2afce29d589f..c7c146e10c94 100644
--- a/MdePkg/Library/DxeRngLib/DxeRngLib.c
+++ b/MdePkg/Library/DxeRngLib/DxeRngLib.c
@@ -32,7 +32,7 @@ typedef struct {
// These represent UEFI SPEC defined algorithms that should be supported by
// the RNG protocol and are generally considered secure.
//
-static GLOBAL_REMOVE_IF_UNREFERENCED SECURE_RNG_ALGO_ARRAY mSecureHashAlgorithms[] = {
+static SECURE_RNG_ALGO_ARRAY mSecureHashAlgorithms[] = {
#ifdef MDE_CPU_AARCH64
{
&gEfiRngAlgorithmArmRndr, // unspecified SP800-90A DRBG (through RNDR instr.)
@@ -204,7 +204,10 @@ GenerateRandomNumberViaNist800Algorithm (
}
}
- if (!PcdGetBool (PcdEnforceSecureRngAlgorithms)) {
+ if (PcdGetBool (PcdEnforceSecureRngAlgorithms)) {
+ // Platform does not permit the use of the default (insecure) algorithm.
+ Status = EFI_SECURITY_VIOLATION;
+ } else {
// If all the other methods have failed, use the default method from the RngProtocol
Status = mRngProtocol->GetRNG (mRngProtocol, NULL, BufferSize, Buffer);
DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm default - Status = %r\n", __func__, Status));
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/AArch64/DynamicCookieGcc.S b/MdePkg/Library/DynamicStackCookieEntryPointLib/AArch64/DynamicCookieGcc.S
new file mode 100644
index 000000000000..f508f692d3f9
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/AArch64/DynamicCookieGcc.S
@@ -0,0 +1,56 @@
+#------------------------------------------------------------------------------
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+# Module Name:
+#
+# DynamicCookie.S
+#
+# Abstract:
+#
+# Generates random number through the RNDR instruction on a 64-bit AARCH64 platform
+# to store a random value in the GCC __stack_check_guard stack cookie.
+# The first byte is 0'd to prevent string copy functions from clobbering
+# the stack cookie.
+#
+# Notes:
+#
+# If RNDR fails, the build time static stack cookie value will be used instead.
+#
+#------------------------------------------------------------------------------
+
+#include <AArch64/AArch64.h>
+
+.text
+.p2align 2
+
+GCC_ASM_IMPORT(__stack_chk_guard)
+GCC_ASM_IMPORT(_CModuleEntryPoint)
+GCC_ASM_EXPORT(_ModuleEntryPoint)
+
+#------------------------------------------------------------------------------
+# VOID
+# EFIAPI
+# _ModuleEntryPoint (
+# Parameters are passed through.
+# )
+#------------------------------------------------------------------------------
+ASM_PFX(_ModuleEntryPoint):
+ AARCH64_BTI(c)
+
+ mrs x9, ID_AA64ISAR0_EL1 // Read the AArch64 Instruction Set Attribute Register 0
+ ubfx x9, x9, #60, #4 // Extract the RNDR bit field (bits 60-63)
+ cbz x9, c_entry // If RNDR is not supported, jump to c_entry
+
+ mrs x9, RNDR // Generate a random number
+ b.eq c_entry // RNDR sets NZCV to 0b0100 on failure
+ // So if the zero flag is set, use the static stack guard
+
+ and x9, x9, #0xFFFFFFFFFFFFFF00 // Zero the first byte of the random value
+
+ adrp x8, ASM_PFX(__stack_chk_guard) // Load the page address of __stack_chk_guard
+ str x9, [x8, :lo12:ASM_PFX(__stack_chk_guard)] // Store the random value in __stack_chk_guard
+
+c_entry:
+ b ASM_PFX(_CModuleEntryPoint) // Jump to the C module entry point
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCore/DxeCoreEntryPoint.c b/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCore/DxeCoreEntryPoint.c
new file mode 100644
index 000000000000..5118132bd2c3
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCore/DxeCoreEntryPoint.c
@@ -0,0 +1,70 @@
+/** @file
+ Entry point to the DXE Core.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiDxe.h>
+
+#include <Library/DxeCoreEntryPoint.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+
+//
+// Cache copy of HobList pointer.
+//
+VOID *gHobList = NULL;
+
+/**
+ The entry point of PE/COFF Image for the DXE Core.
+
+ This function is the entry point for the DXE Core. This function is required to call
+ ProcessModuleEntryPointList() and ProcessModuleEntryPointList() is never expected to return.
+ The DXE Core is responsible for calling ProcessLibraryConstructorList() as soon as the EFI
+ System Table and the image handle for the DXE Core itself have been established.
+ If ProcessModuleEntryPointList() returns, then ASSERT() and halt the system.
+
+ @param HobStart The pointer to the beginning of the HOB List passed in from the PEI Phase.
+
+**/
+VOID
+EFIAPI
+_CModuleEntryPoint (
+ IN VOID *HobStart
+ )
+{
+ //
+ // Cache a pointer to the HobList
+ //
+ gHobList = HobStart;
+
+ //
+ // Call the DXE Core entry point
+ //
+ ProcessModuleEntryPointList (HobStart);
+
+ //
+ // Should never return
+ //
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+}
+
+/**
+ Required by the EBC compiler and identical in functionality to _ModuleEntryPoint().
+
+ This function is required to call _ModuleEntryPoint() passing in HobStart.
+
+ @param HobStart The pointer to the beginning of the HOB List passed in from the PEI Phase.
+
+**/
+VOID
+EFIAPI
+EfiMain (
+ IN VOID *HobStart
+ )
+{
+ _ModuleEntryPoint (HobStart);
+}
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCore/DxeCoreEntryPoint.uni b/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCore/DxeCoreEntryPoint.uni
new file mode 100644
index 000000000000..e6515659a9e0
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCore/DxeCoreEntryPoint.uni
@@ -0,0 +1,16 @@
+// /** @file
+// Module entry point library for DXE core.
+//
+// Module entry point library for DXE core.
+//
+// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Module entry point library for DXE core"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Module entry point library for DXE core."
+
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCoreEntryPoint.inf b/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCoreEntryPoint.inf
new file mode 100644
index 000000000000..1da877ae1d97
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/DxeCoreEntryPoint.inf
@@ -0,0 +1,45 @@
+## @file
+# Module entry point library for DXE core that dynamically updates the stack cookie.
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = DxeCoreEntryPointDynamicInit
+ MODULE_UNI_FILE = DxeCore/DxeCoreEntryPoint.uni
+ FILE_GUID = FD044D85-1407-4043-B527-471F16ABD8C6
+ MODULE_TYPE = DXE_CORE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = DxeCoreEntryPoint|DXE_CORE
+
+
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ DxeCore/DxeCoreEntryPoint.c
+
+[Sources.IA32]
+ IA32/DynamicCookieGcc.nasm | GCC
+ IA32/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.X64]
+ X64/DynamicCookieGcc.nasm | GCC
+ X64/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.AARCH64]
+ AArch64/DynamicCookieGcc.S | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ StackCheckLib
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/IA32/DynamicCookieGcc.nasm b/MdePkg/Library/DynamicStackCookieEntryPointLib/IA32/DynamicCookieGcc.nasm
new file mode 100644
index 000000000000..c3c3e0e9931c
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/IA32/DynamicCookieGcc.nasm
@@ -0,0 +1,63 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) Microsoft Corporation.
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; DynamicCookie.nasm
+;
+; Abstract:
+;
+; Generates random number through CPU RdRand instruction on a 32-bit platform
+; to store a random value in the GCC __stack_check_guard stack cookie.
+; The first byte is 0'd to prevent string copy functions from clobbering
+; the stack cookie.
+;
+; Notes:
+;
+; If RdRand fails, the build time static stack cookie value will be used instead.
+;
+;------------------------------------------------------------------------------
+
+SECTION .text
+
+extern ASM_PFX(__stack_chk_guard)
+extern ASM_PFX(_CModuleEntryPoint)
+global ASM_PFX(_ModuleEntryPoint)
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; _ModuleEntryPoint (
+; Parameters are passed through
+; );
+;------------------------------------------------------------------------------
+global _ModuleEntryPoint
+_ModuleEntryPoint:
+ push ebx
+ push ecx
+ push edx
+
+ mov eax, 1 ; CPUID function 1
+ cpuid
+ test ecx, 0x40000000 ; Check if the RdRand bit (bit 30) is set in ECX
+ jz c_entry ; If not set, jump to c_entry
+
+ rdrand eax ; Use rdrand, getting a 32 bit value as on
+ ; IA32, __stack_chk_guard is a 32 bit value.
+ ; CF=1 if RN generated ok, otherwise CF=0
+ jnc c_entry ; If the cmd fails, don't update __stack_chk_guard, we'll have to move forward
+ ; with the static value provided at build time.
+
+ lea ebx, [ASM_PFX(__stack_chk_guard)] ; load the address of __stack_chk_guard into ebx
+
+ xor ah, ah ; Zero a byte of the __stack_chk_guard value to protect against string functions
+ ; (such as strcpy like functions) clobbering past the canary
+ mov [ebx], eax ; Store our random value, with 0'd first byte to __stack_chk_guard
+
+c_entry:
+ pop edx
+ pop ecx
+ pop ebx
+ jmp ASM_PFX(_CModuleEntryPoint)
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/IA32/DynamicCookieMsvc.nasm b/MdePkg/Library/DynamicStackCookieEntryPointLib/IA32/DynamicCookieMsvc.nasm
new file mode 100644
index 000000000000..2b8ec94fdbe9
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/IA32/DynamicCookieMsvc.nasm
@@ -0,0 +1,63 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) Microsoft Corporation.
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; DynamicCookie.nasm
+;
+; Abstract:
+;
+; Generates random number through CPU RdRand instruction on a 32-bit platform
+; to store a random value in the GCC __stack_check_guard stack cookie.
+; The first byte is 0'd to prevent string copy functions from clobbering
+; the stack cookie.
+;
+; Notes:
+;
+; If RdRand fails, the build time static stack cookie value will be used instead.
+;
+;------------------------------------------------------------------------------
+
+SECTION .text
+
+extern ASM_PFX(__security_cookie)
+extern ASM_PFX(_CModuleEntryPoint)
+global ASM_PFX(_ModuleEntryPoint)
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; _ModuleEntryPoint (
+; Parameters are passed through
+; );
+;------------------------------------------------------------------------------
+global _ModuleEntryPoint
+_ModuleEntryPoint:
+ push ebx
+ push ecx
+ push edx
+
+ mov eax, 1 ; CPUID function 1
+ cpuid
+ test ecx, 0x40000000 ; Check if the RdRand bit (bit 30) is set in ECX
+ jz c_entry ; If not set, jump to c_entry
+
+ rdrand eax ; Use rdrand, getting a 32 bit value as on
+ ; IA32, __security_cookie is a 32 bit value.
+ ; CF=1 if RN generated ok, otherwise CF=0
+ jnc c_entry ; If the cmd fails, don't update __security_cookie, we'll have to move forward
+ ; with the static value provided at build time.
+
+ lea ebx, [ASM_PFX(__security_cookie)] ; load the address of __stack_chk_guard into ebx
+
+ xor ah, ah ; Zero a byte of the __security_cookie value to protect against string functions
+ ; (such as strcpy like functions) clobbering past the canary
+ mov [ebx], eax ; Store our random value, with 0'd first byte to __security_cookie
+
+c_entry:
+ pop edx
+ pop ecx
+ pop ebx
+ jmp ASM_PFX(_CModuleEntryPoint)
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCore/X64/StandaloneMmCoreEntryPoint.c b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCore/X64/StandaloneMmCoreEntryPoint.c
new file mode 100644
index 000000000000..204702727319
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCore/X64/StandaloneMmCoreEntryPoint.c
@@ -0,0 +1,65 @@
+/** @file
+ Entry point to the Standalone Mm Core.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+
+#include <Library/StandaloneMmCoreEntryPoint.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+
+//
+// Cache copy of HobList pointer.
+//
+VOID *gHobList = NULL;
+
+/**
+ The entry point of PE/COFF Image for the STANDALONE MM Core.
+
+ This function is the entry point for the STANDALONE MM Core. This function is required to call
+ ProcessModuleEntryPointList() and ProcessModuleEntryPointList() is never expected to return.
+ The STANDALONE MM Core is responsible for calling ProcessLibraryConstructorList() as soon as the EFI
+ System Table and the image handle for the STANDALONE MM Core itself have been established.
+ If ProcessModuleEntryPointList() returns, then ASSERT() and halt the system.
+
+ @param HobStart Pointer to the beginning of the HOB List passed in from the PEI Phase.
+
+**/
+VOID
+EFIAPI
+_CModuleEntryPoint (
+ IN VOID *HobStart
+ )
+{
+ //
+ // Cache a pointer to the HobList
+ //
+ gHobList = HobStart;
+
+ //
+ // Call the Standalone MM Core entry point
+ //
+ ProcessModuleEntryPointList (HobStart);
+}
+
+/**
+ Required by the EBC compiler and identical in functionality to _ModuleEntryPoint().
+
+ This function is required to call _ModuleEntryPoint() passing in HobStart.
+
+ @param HobStart Pointer to the beginning of the HOB List passed in from the PEI Phase.
+
+**/
+VOID
+EFIAPI
+EfiMain (
+ IN VOID *HobStart
+ )
+{
+ _ModuleEntryPoint (HobStart);
+}
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCoreEntryPoint.inf b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCoreEntryPoint.inf
new file mode 100644
index 000000000000..b82415e6b8fc
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCoreEntryPoint.inf
@@ -0,0 +1,38 @@
+## @file
+# Module entry point library for StandaloneMm core that dynamically updates the stack cookie.
+# The AARCH64 version of this library lives in ArmPkg.
+#
+# Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = StandaloneMmCoreEntryPointDynamicInit
+ FILE_GUID = 490073A1-4DBC-4E9E-B30D-A4204139FC5F
+ MODULE_TYPE = MM_CORE_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ LIBRARY_CLASS = StandaloneMmCoreEntryPoint|MM_CORE_STANDALONE
+
+#
+# VALID_ARCHITECTURES = X64
+#
+
+[Sources.X64]
+ StandaloneMmCore/X64/StandaloneMmCoreEntryPoint.c
+
+[Sources.X64]
+ X64/DynamicCookieGcc.nasm | GCC
+ X64/DynamicCookieMsvc.nasm | MSFT
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ StackCheckLib
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriver/StandaloneMmDriverEntryPoint.c b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriver/StandaloneMmDriverEntryPoint.c
new file mode 100644
index 000000000000..51df419953d5
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriver/StandaloneMmDriverEntryPoint.c
@@ -0,0 +1,135 @@
+/** @file
+ Entry point to a Standalone MM driver.
+
+Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2016 - 2018, ARM Ltd. All rights reserved.<BR>
+Copyright (c) 2018, Linaro, Limited. All rights reserved.<BR>
+
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+
+#include <Protocol/LoadedImage.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MmServicesTableLib.h>
+#include <Library/StandaloneMmDriverEntryPoint.h>
+
+/**
+ Unloads an image from memory.
+
+ This function is a callback that a driver registers to do cleanup
+ when the UnloadImage boot service function is called.
+
+ @param ImageHandle The handle to the image to unload.
+
+ @return Status returned by all unload().
+
+**/
+EFI_STATUS
+EFIAPI
+_DriverUnloadHandler (
+ EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // If an UnloadImage() handler is specified, then call it
+ //
+ Status = ProcessModuleUnloadList (ImageHandle);
+
+ //
+ // If the driver specific unload handler does not return an error, then call all of the
+ // library destructors. If the unload handler returned an error, then the driver can not be
+ // unloaded, and the library destructors should not be called
+ //
+ if (!EFI_ERROR (Status)) {
+ ProcessLibraryDestructorList (ImageHandle, gMmst);
+ }
+
+ //
+ // Return the status from the driver specific unload handler
+ //
+ return Status;
+}
+
+/**
+ The entry point of PE/COFF Image for a Standalone MM Driver.
+
+ This function is the entry point for a Standalone MM Driver.
+ This function must call ProcessLibraryConstructorList() and
+ ProcessModuleEntryPointList().
+ If the return status from ProcessModuleEntryPointList()
+ is an error status, then ProcessLibraryDestructorList() must be called.
+ The return value from ProcessModuleEntryPointList() is returned.
+ If _gMmRevision is not zero and SystemTable->Hdr.Revision is
+ less than _gMmRevision, then return EFI_INCOMPATIBLE_VERSION.
+
+ @param ImageHandle The image handle of the Standalone MM Driver.
+ @param MmSystemTable A pointer to the MM System Table.
+
+ @retval EFI_SUCCESS The Standalone MM Driver exited normally.
+ @retval EFI_INCOMPATIBLE_VERSION _gMmRevision is greater than
+ MmSystemTable->Hdr.Revision.
+ @retval Other Return value from
+ ProcessModuleEntryPointList().
+
+**/
+EFI_STATUS
+EFIAPI
+_CModuleEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN IN EFI_MM_SYSTEM_TABLE *MmSystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+
+ if (_gMmRevision != 0) {
+ //
+ // Make sure that the MM spec revision of the platform
+ // is >= MM spec revision of the driver
+ //
+ if (MmSystemTable->Hdr.Revision < _gMmRevision) {
+ return EFI_INCOMPATIBLE_VERSION;
+ }
+ }
+
+ //
+ // Call constructor for all libraries
+ //
+ ProcessLibraryConstructorList (ImageHandle, MmSystemTable);
+
+ //
+ // Install unload handler...
+ //
+ if (_gDriverUnloadImageCount != 0) {
+ Status = gMmst->MmHandleProtocol (
+ ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&LoadedImage
+ );
+ ASSERT_EFI_ERROR (Status);
+ LoadedImage->Unload = _DriverUnloadHandler;
+ }
+
+ //
+ // Call the driver entry point
+ //
+ Status = ProcessModuleEntryPointList (ImageHandle, MmSystemTable);
+
+ //
+ // If all of the drivers returned errors, then invoke all of the library destructors
+ //
+ if (EFI_ERROR (Status)) {
+ ProcessLibraryDestructorList (ImageHandle, MmSystemTable);
+ }
+
+ //
+ // Return the cumulative return status code from all of the driver entry points
+ //
+ return Status;
+}
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriver/StandaloneMmDriverEntryPoint.uni b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriver/StandaloneMmDriverEntryPoint.uni
new file mode 100644
index 000000000000..de36debd74ec
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriver/StandaloneMmDriverEntryPoint.uni
@@ -0,0 +1,17 @@
+// /** @file
+//
+// Module entry point library for standalone MM driver
+//
+// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+// Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.<BR>
+// Copyright (c) 2018, Linaro, Limited. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Module entry point library for standalone MM driver"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Module entry point library for standalone MM driver."
+
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriverEntryPoint.inf b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriverEntryPoint.inf
new file mode 100644
index 000000000000..a5cb42518c1b
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmDriverEntryPoint.inf
@@ -0,0 +1,53 @@
+## @file
+# Module entry point library for Standalone MM drivers that dynamically updates the stack cookie.
+#
+# Copyright (c) 2015 - 2021, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2016-2018, ARM Ltd. All rights reserved.<BR>
+# Copyright (c) 2018, Linaro, Limited. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = StandaloneMmDriverEntryPointDynamicInit
+ MODULE_UNI_FILE = StandaloneMmDriver/StandaloneMmDriverEntryPoint.uni
+ FILE_GUID = 28CBCD87-2FEE-4D46-BB5C-B37732BBEEB1
+ MODULE_TYPE = MM_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ LIBRARY_CLASS = StandaloneMmDriverEntryPoint|MM_STANDALONE
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = X64 AARCH64
+#
+
+[Sources]
+ StandaloneMmDriver/StandaloneMmDriverEntryPoint.c
+
+[Sources.IA32]
+ IA32/DynamicCookieGcc.nasm | GCC
+ IA32/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.X64]
+ X64/DynamicCookieGcc.nasm | GCC
+ X64/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.AARCH64]
+ AArch64/DynamicCookieGcc.S | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ MmServicesTableLib
+ StackCheckLib
+
+[Protocols]
+ gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMES
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/ApplicationEntryPoint.c b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/ApplicationEntryPoint.c
new file mode 100644
index 000000000000..81b9b55130e3
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/ApplicationEntryPoint.c
@@ -0,0 +1,112 @@
+/** @file
+ Entry point library instance to a UEFI application.
+
+Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+#include <Library/UefiApplicationEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+/**
+ Entry point to UEFI Application.
+
+ This function is the entry point for a UEFI Application. This function must call
+ ProcessLibraryConstructorList(), ProcessModuleEntryPointList(), and ProcessLibraryDestructorList().
+ The return value from ProcessModuleEntryPointList() is returned.
+ If _gUefiDriverRevision is not zero and SystemTable->Hdr.Revision is less than _gUefiDriverRevison,
+ then return EFI_INCOMPATIBLE_VERSION.
+
+ @param ImageHandle The image handle of the UEFI Application.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The UEFI Application exited normally.
+ @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than SystemTable->Hdr.Revision.
+ @retval Other Return value from ProcessModuleEntryPointList().
+
+**/
+EFI_STATUS
+EFIAPI
+_CModuleEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ if (_gUefiDriverRevision != 0) {
+ //
+ // Make sure that the EFI/UEFI spec revision of the platform is >= EFI/UEFI spec revision of the application.
+ //
+ if (SystemTable->Hdr.Revision < _gUefiDriverRevision) {
+ return EFI_INCOMPATIBLE_VERSION;
+ }
+ }
+
+ //
+ // Call constructor for all libraries.
+ //
+ ProcessLibraryConstructorList (ImageHandle, SystemTable);
+
+ //
+ // Call the module's entry point
+ //
+ Status = ProcessModuleEntryPointList (ImageHandle, SystemTable);
+
+ //
+ // Process destructor for all libraries.
+ //
+ ProcessLibraryDestructorList (ImageHandle, SystemTable);
+
+ //
+ // Return the return status code from the driver entry point
+ //
+ return Status;
+}
+
+/**
+ Invokes the library destructors for all dependent libraries and terminates
+ the UEFI Application.
+
+ This function calls ProcessLibraryDestructorList() and the EFI Boot Service Exit()
+ with a status specified by Status.
+
+ @param Status Status returned by the application that is exiting.
+
+**/
+VOID
+EFIAPI
+Exit (
+ IN EFI_STATUS Status
+ )
+
+{
+ ProcessLibraryDestructorList (gImageHandle, gST);
+
+ gBS->Exit (gImageHandle, Status, 0, NULL);
+}
+
+/**
+ Required by the EBC compiler and identical in functionality to _ModuleEntryPoint().
+
+ @param ImageHandle The image handle of the UEFI Application.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The UEFI Application exited normally.
+ @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than SystemTable->Hdr.Revision.
+ @retval Other Return value from ProcessModuleEntryPointList().
+
+**/
+EFI_STATUS
+EFIAPI
+EfiMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return _ModuleEntryPoint (ImageHandle, SystemTable);
+}
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/UefiApplicationEntryPoint.uni b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/UefiApplicationEntryPoint.uni
new file mode 100644
index 000000000000..168ce7469bb7
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplication/UefiApplicationEntryPoint.uni
@@ -0,0 +1,16 @@
+// /** @file
+// Module entry point library for UEFI Application.
+//
+// Module entry point library for UEFI Application.
+//
+// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Module entry point library for UEFI Application"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Module entry point library for UEFI Application."
+
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplicationEntryPoint.inf b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplicationEntryPoint.inf
new file mode 100644
index 000000000000..1a82fc498de1
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiApplicationEntryPoint.inf
@@ -0,0 +1,45 @@
+## @file
+# Module entry point library for UEFI Application that dynamically updates the stack cookie.
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UefiApplicationEntryPointDynamicInit
+ MODULE_UNI_FILE = UefiApplication/UefiApplicationEntryPoint.uni
+ FILE_GUID = 755B9094-E5AF-4E5B-BE33-D430CDE2C5D2
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = UefiApplicationEntryPoint|UEFI_APPLICATION
+
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ UefiApplication/ApplicationEntryPoint.c
+
+[Sources.IA32]
+ IA32/DynamicCookieGcc.nasm | GCC
+ IA32/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.X64]
+ X64/DynamicCookieGcc.nasm | GCC
+ X64/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.AARCH64]
+ AArch64/DynamicCookieGcc.S | GCC
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ DebugLib
+ BaseLib
+ StackCheckLib
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriver/DriverEntryPoint.c b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriver/DriverEntryPoint.c
new file mode 100644
index 000000000000..ad17e0d1c616
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriver/DriverEntryPoint.c
@@ -0,0 +1,162 @@
+/** @file
+ Entry point to a EFI/DXE driver.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Uefi.h>
+
+#include <Protocol/LoadedImage.h>
+
+#include <Library/UefiDriverEntryPoint.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+
+/**
+ Unloads an image from memory.
+
+ This function is a callback that a driver registers to do cleanup
+ when the UnloadImage boot service function is called.
+
+ @param ImageHandle The handle to the image to unload.
+
+ @return Status returned by all unload().
+
+**/
+EFI_STATUS
+EFIAPI
+_DriverUnloadHandler (
+ EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // If an UnloadImage() handler is specified, then call it
+ //
+ Status = ProcessModuleUnloadList (ImageHandle);
+
+ //
+ // If the driver specific unload handler does not return an error, then call all of the
+ // library destructors. If the unload handler returned an error, then the driver can not be
+ // unloaded, and the library destructors should not be called
+ //
+ if (!EFI_ERROR (Status)) {
+ ProcessLibraryDestructorList (ImageHandle, gST);
+ }
+
+ //
+ // Return the status from the driver specific unload handler
+ //
+ return Status;
+}
+
+/**
+ The entry point of PE/COFF Image for a DXE Driver, DXE Runtime Driver, DXE SMM
+ Driver, or UEFI Driver.
+
+ This function is the entry point for a DXE Driver, DXE Runtime Driver, DXE SMM Driver,
+ or UEFI Driver. This function must call ProcessLibraryConstructorList() and
+ ProcessModuleEntryPointList(). If the return status from ProcessModuleEntryPointList()
+ is an error status, then ProcessLibraryDestructorList() must be called. The return
+ value from ProcessModuleEntryPointList() is returned. If _gDriverUnloadImageCount
+ is greater than zero, then an unload handler must be registered for this image
+ and the unload handler must invoke ProcessModuleUnloadList().
+ If _gUefiDriverRevision is not zero and SystemTable->Hdr.Revision is less than
+ _gUefiDriverRevison, then return EFI_INCOMPATIBLE_VERSION.
+
+
+ @param ImageHandle The image handle of the DXE Driver, DXE Runtime Driver,
+ DXE SMM Driver, or UEFI Driver.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The DXE Driver, DXE Runtime Driver, DXE SMM
+ Driver, or UEFI Driver exited normally.
+ @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than
+ SystemTable->Hdr.Revision.
+ @retval Other Return value from ProcessModuleEntryPointList().
+
+**/
+EFI_STATUS
+EFIAPI
+_CModuleEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+
+ if (_gUefiDriverRevision != 0) {
+ //
+ // Make sure that the EFI/UEFI spec revision of the platform is >= EFI/UEFI spec revision of the driver
+ //
+ if (SystemTable->Hdr.Revision < _gUefiDriverRevision) {
+ return EFI_INCOMPATIBLE_VERSION;
+ }
+ }
+
+ //
+ // Call constructor for all libraries
+ //
+ ProcessLibraryConstructorList (ImageHandle, SystemTable);
+
+ //
+ // Install unload handler...
+ //
+ if (_gDriverUnloadImageCount != 0) {
+ Status = gBS->HandleProtocol (
+ ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **)&LoadedImage
+ );
+ ASSERT_EFI_ERROR (Status);
+ LoadedImage->Unload = _DriverUnloadHandler;
+ }
+
+ //
+ // Call the driver entry point
+ //
+ Status = ProcessModuleEntryPointList (ImageHandle, SystemTable);
+
+ //
+ // If all of the drivers returned errors, then invoke all of the library destructors
+ //
+ if (EFI_ERROR (Status)) {
+ ProcessLibraryDestructorList (ImageHandle, SystemTable);
+ }
+
+ //
+ // Return the cummalative return status code from all of the driver entry points
+ //
+ return Status;
+}
+
+/**
+ Required by the EBC compiler and identical in functionality to _ModuleEntryPoint().
+
+ This function is required to call _ModuleEntryPoint() passing in ImageHandle,
+ and SystemTable.
+
+ @param ImageHandle The image handle of the DXE Driver, DXE Runtime Driver, DXE
+ SMM Driver, or UEFI Driver.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The DXE Driver, DXE Runtime Driver, DXE SMM
+ Driver, or UEFI Driver exited normally.
+ @retval EFI_INCOMPATIBLE_VERSION _gUefiDriverRevision is greater than
+ SystemTable->Hdr.Revision.
+ @retval Other Return value from ProcessModuleEntryPointList().
+**/
+EFI_STATUS
+EFIAPI
+EfiMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return _ModuleEntryPoint (ImageHandle, SystemTable);
+}
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriver/UefiDriverEntryPoint.uni b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriver/UefiDriverEntryPoint.uni
new file mode 100644
index 000000000000..9d820b25f063
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriver/UefiDriverEntryPoint.uni
@@ -0,0 +1,16 @@
+// /** @file
+// Module entry point library for UEFI driver, DXE driver and SMM driver.
+//
+// Module entry point library for UEFI driver, DXE driver and SMM driver.
+//
+// Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT #language en-US "Module entry point library for UEFI driver, DXE driver and SMM driver"
+
+#string STR_MODULE_DESCRIPTION #language en-US "Module entry point library for UEFI driver, DXE driver and SMM driver."
+
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriverEntryPoint.inf b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriverEntryPoint.inf
new file mode 100644
index 000000000000..522bcd930c23
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriverEntryPoint.inf
@@ -0,0 +1,68 @@
+## @file
+# Module entry point library for UEFI driver, DXE driver and SMM driver that dynamically sets the stack cookie.
+#
+# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = UefiDriverEntryPointDynamicInit
+ MODULE_UNI_FILE = UefiDriver/UefiDriverEntryPoint.uni
+ FILE_GUID = 900238F9-1421-4596-9548-A1BF58C97693
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = UefiDriverEntryPoint|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_DRIVER SMM_CORE DXE_SMM_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 AARCH64
+#
+
+[Sources]
+ UefiDriver/DriverEntryPoint.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[Sources.IA32]
+ IA32/DynamicCookieGcc.nasm | GCC
+ IA32/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.X64]
+ X64/DynamicCookieGcc.nasm | GCC
+ X64/DynamicCookieMsvc.nasm | MSFT
+
+[Sources.AARCH64]
+ AArch64/DynamicCookieGcc.S | GCC
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ DebugLib
+ BaseLib
+ StackCheckLib
+
+[Protocols]
+ gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMES
+
+#
+# For UEFI drivers, these architectural protocols defined in PI 1.0 spec need
+# to be appended and merged to the final dependency section.
+#
+[Depex.common.UEFI_DRIVER]
+ gEfiBdsArchProtocolGuid AND
+ gEfiCpuArchProtocolGuid AND
+ gEfiMetronomeArchProtocolGuid AND
+ gEfiMonotonicCounterArchProtocolGuid AND
+ gEfiRealTimeClockArchProtocolGuid AND
+ gEfiResetArchProtocolGuid AND
+ gEfiRuntimeArchProtocolGuid AND
+ gEfiSecurityArchProtocolGuid AND
+ gEfiTimerArchProtocolGuid AND
+ gEfiVariableWriteArchProtocolGuid AND
+ gEfiVariableArchProtocolGuid AND
+ gEfiWatchdogTimerArchProtocolGuid
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/X64/DynamicCookieGcc.nasm b/MdePkg/Library/DynamicStackCookieEntryPointLib/X64/DynamicCookieGcc.nasm
new file mode 100644
index 000000000000..782e8bbb791a
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/X64/DynamicCookieGcc.nasm
@@ -0,0 +1,63 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) Microsoft Corporation.
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; DynamicCookie.nasm
+;
+; Abstract:
+;
+; Generates random number through CPU RdRand instruction on 64-bit platform
+; to store a random value in the GCC __stack_check_guard stack cookie.
+; The first byte is 0'd to prevent string copy functions from clobbering
+; the stack cookie.
+;
+; Notes:
+;
+; If RdRand fails, the build time static stack cookie value will be used instead.
+;
+;------------------------------------------------------------------------------
+
+DEFAULT REL
+SECTION .text
+
+extern ASM_PFX(__stack_chk_guard)
+extern ASM_PFX(_CModuleEntryPoint)
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; _ModuleEntryPoint (
+; Parameters are passed through. TODO: Make sure there are only two args on X64
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+ push rbx
+ push rcx
+ push rdx
+
+ mov eax, 1 ; Set eax to 1 to get feature information
+ cpuid ; Call cpuid
+ test ecx, 0x40000000 ; Test the rdrand bit (bit 30) in ecx
+ jz c_entry ; If rdrand is not supported, jump to c_entry
+
+ rdrand rax ; Call rdrand functionality here, getting a 64 bit value as on
+ ; X64, __stack_chk_guard is a 64 bit value.
+ ; CF=1 if RN generated ok, otherwise CF=0
+ jnc c_entry ; If the cmd fails, don't, update __stack_chk_guard, we'll have to move forward
+ ; with the static value provided at build time.
+
+ lea rbx, [rel ASM_PFX(__stack_chk_guard)] ; load the address of __stack_check_guard into rbx
+
+ xor ah, ah ; Zero a byte of the __stack_chk_guard value to protect against string functions
+ ; (such as strcpy like functions) clobbering past the canary
+ mov [rbx], rax ; Store our random value, with 0'd first byte to __stack_chk_guard
+
+c_entry:
+ pop rdx
+ pop rcx
+ pop rbx
+ jmp ASM_PFX(_CModuleEntryPoint)
diff --git a/MdePkg/Library/DynamicStackCookieEntryPointLib/X64/DynamicCookieMsvc.nasm b/MdePkg/Library/DynamicStackCookieEntryPointLib/X64/DynamicCookieMsvc.nasm
new file mode 100644
index 000000000000..bd290f712634
--- /dev/null
+++ b/MdePkg/Library/DynamicStackCookieEntryPointLib/X64/DynamicCookieMsvc.nasm
@@ -0,0 +1,63 @@
+;------------------------------------------------------------------------------
+;
+; Copyright (c) Microsoft Corporation.
+; SPDX-License-Identifier: BSD-2-Clause-Patent
+;
+; Module Name:
+;
+; DynamicCookie.nasm
+;
+; Abstract:
+;
+; Generates random number through CPU RdRand instruction on 64-bit platform
+; to store a random value in the GCC __stack_check_guard stack cookie.
+; The first byte is 0'd to prevent string copy functions from clobbering
+; the stack cookie.
+;
+; Notes:
+;
+; If RdRand fails, the build time static stack cookie value will be used instead.
+;
+;------------------------------------------------------------------------------
+
+DEFAULT REL
+SECTION .text
+
+extern ASM_PFX(__security_cookie)
+extern ASM_PFX(_CModuleEntryPoint)
+
+;------------------------------------------------------------------------------
+; VOID
+; EFIAPI
+; _ModuleEntryPoint (
+; Parameters are passed through. TODO: Make sure there are only two args on X64
+; );
+;------------------------------------------------------------------------------
+global ASM_PFX(_ModuleEntryPoint)
+ASM_PFX(_ModuleEntryPoint):
+ push rbx
+ push rcx
+ push rdx
+
+ mov eax, 1 ; Set eax to 1 to get feature information
+ cpuid ; Call cpuid
+ test ecx, 0x40000000 ; Test the rdrand bit (bit 30) in ecx
+ jz c_entry ; If rdrand is not supported, jump to c_entry
+
+ rdrand rax ; Call rdrand functionality here, getting a 64 bit value as on
+ ; X64, __stack_chk_guard is a 64 bit value.
+ ; CF=1 if RN generated ok, otherwise CF=0
+ jnc c_entry ; If the cmd fails, don't, update __stack_chk_guard, we'll have to move forward
+ ; with the static value provided at build time.
+
+ lea rbx, [rel ASM_PFX(__security_cookie)] ; load the address of __stack_check_guard into rbx
+
+ xor ah, ah ; Zero a byte of the __stack_chk_guard value to protect against string functions
+ ; (such as strcpy like functions) clobbering past the canary
+ mov [rbx], rax ; Store our random value, with 0'd first byte to __stack_chk_guard
+
+c_entry:
+ pop rdx
+ pop rcx
+ pop rbx
+ jmp ASM_PFX(_CModuleEntryPoint)
diff --git a/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf b/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
index 163daa67afd3..02d1c582a114 100644
--- a/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
+++ b/MdePkg/Library/PeiCoreEntryPoint/PeiCoreEntryPoint.inf
@@ -31,4 +31,4 @@
[LibraryClasses]
BaseLib
DebugLib
-
+ StackCheckLib
diff --git a/MdePkg/Library/PeiRngLib/PeiRngLib.c b/MdePkg/Library/PeiRngLib/PeiRngLib.c
new file mode 100644
index 000000000000..d6c957327c6b
--- /dev/null
+++ b/MdePkg/Library/PeiRngLib/PeiRngLib.c
@@ -0,0 +1,229 @@
+/** @file
+ RNG library instance that uses the Random Number Generator (RNG) PPI to provide
+ random numbers.
+
+ Copyright (c) Microsoft Corporation.
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Ppi/Rng.h>
+
+/**
+ Generates a random number via the NIST 800-9A algorithm. Refer to
+ http://csrc.nist.gov/groups/STM/cavp/documents/drbg/DRBGVS.pdf for more information.
+
+ @param[out] Buffer Buffer to receive the random number.
+ @param[in] BufferSize Number of bytes in Buffer.
+
+ @retval EFI_SUCCESS or underlying failure code.
+
+**/
+STATIC
+EFI_STATUS
+GenerateRandomNumberViaNist800Algorithm (
+ OUT UINT8 *Buffer,
+ IN UINTN BufferSize
+ )
+{
+ EFI_STATUS Status;
+ RNG_PPI *RngPpi;
+
+ RngPpi = NULL;
+
+ if (Buffer == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Buffer == NULL.\n", __func__));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = PeiServicesLocatePpi (&gEfiRngPpiGuid, 0, NULL, (VOID **)&RngPpi);
+ if (EFI_ERROR (Status) || (RngPpi == NULL)) {
+ DEBUG ((DEBUG_ERROR, "%a: Could not locate RNG PPI, Status = %r\n", __func__, Status));
+ return Status;
+ }
+
+ Status = RngPpi->GetRNG (RngPpi, &gEfiRngAlgorithmSp80090Ctr256Guid, BufferSize, Buffer);
+ DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm CTR-256 - Status = %r\n", __func__, Status));
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = RngPpi->GetRNG (RngPpi, &gEfiRngAlgorithmSp80090Hmac256Guid, BufferSize, Buffer);
+ DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm HMAC-256 - Status = %r\n", __func__, Status));
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = RngPpi->GetRNG (RngPpi, &gEfiRngAlgorithmSp80090Hash256Guid, BufferSize, Buffer);
+ DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm Hash-256 - Status = %r\n", __func__, Status));
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = RngPpi->GetRNG (RngPpi, &gEfiRngAlgorithmRaw, BufferSize, Buffer);
+ DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm Raw - Status = %r\n", __func__, Status));
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // If all the other methods have failed, use the default method from the RngPpi
+ Status = RngPpi->GetRNG (RngPpi, NULL, BufferSize, Buffer);
+ DEBUG ((DEBUG_INFO, "%a: GetRNG algorithm default - Status = %r\n", __func__, Status));
+ if (!EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ // If we get to this point, we have failed
+ DEBUG ((DEBUG_ERROR, "%a: GetRNG() failed, staus = %r\n", __func__, Status));
+
+ return Status;
+}
+
+/**
+ Generates a 16-bit random number.
+
+ if Rand is NULL, return FALSE.
+
+ @param[out] Rand Buffer pointer to store the 16-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+GetRandomNumber16 (
+ OUT UINT16 *Rand
+ )
+{
+ EFI_STATUS Status;
+
+ if (Rand == NULL) {
+ return FALSE;
+ }
+
+ Status = GenerateRandomNumberViaNist800Algorithm ((UINT8 *)Rand, sizeof (UINT16));
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ Generates a 32-bit random number.
+
+ if Rand is NULL, return FALSE.
+
+ @param[out] Rand Buffer pointer to store the 32-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+GetRandomNumber32 (
+ OUT UINT32 *Rand
+ )
+{
+ EFI_STATUS Status;
+
+ if (Rand == NULL) {
+ return FALSE;
+ }
+
+ Status = GenerateRandomNumberViaNist800Algorithm ((UINT8 *)Rand, sizeof (UINT32));
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ Generates a 64-bit random number.
+
+ if Rand is NULL, return FALSE.
+
+ @param[out] Rand Buffer pointer to store the 64-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+GetRandomNumber64 (
+ OUT UINT64 *Rand
+ )
+{
+ EFI_STATUS Status;
+
+ if (Rand == NULL) {
+ return FALSE;
+ }
+
+ Status = GenerateRandomNumberViaNist800Algorithm ((UINT8 *)Rand, sizeof (UINT64));
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ Generates a 128-bit random number.
+
+ if Rand is NULL, return FALSE.
+
+ @param[out] Rand Buffer pointer to store the 128-bit random value.
+
+ @retval TRUE Random number generated successfully.
+ @retval FALSE Failed to generate the random number.
+
+**/
+BOOLEAN
+EFIAPI
+GetRandomNumber128 (
+ OUT UINT64 *Rand
+ )
+{
+ EFI_STATUS Status;
+
+ if (Rand == NULL) {
+ return FALSE;
+ }
+
+ Status = GenerateRandomNumberViaNist800Algorithm ((UINT8 *)Rand, 2 * sizeof (UINT64));
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ Get a GUID identifying the RNG algorithm implementation.
+
+ @param [out] RngGuid If success, contains the GUID identifying
+ the RNG algorithm implementation.
+
+ @retval EFI_SUCCESS Success.
+ @retval EFI_UNSUPPORTED Not supported.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+**/
+EFI_STATUS
+EFIAPI
+GetRngGuid (
+ GUID *RngGuid
+ )
+{
+ // Similar to DxeRngLib, EFI_UNSUPPORTED is returned for this library instance since it is unknown
+ // which exact algorithm may be used for a given request.
+
+ return EFI_UNSUPPORTED;
+}
diff --git a/MdePkg/Library/PeiRngLib/PeiRngLib.inf b/MdePkg/Library/PeiRngLib/PeiRngLib.inf
new file mode 100644
index 000000000000..1588366eebff
--- /dev/null
+++ b/MdePkg/Library/PeiRngLib/PeiRngLib.inf
@@ -0,0 +1,41 @@
+## @file
+# PPI-based Instance of RNG (Random Number Generator) Library.
+#
+# This library instance requires a RNG PPI to be produced so that the module may use
+# it for RNG operations. A RNG PPI DEPEX will be placed on the module.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 0x0001001B
+ BASE_NAME = PeiRngLib
+ MODULE_UNI_FILE = PeiRngLib.uni
+ FILE_GUID = FF240232-C25D-4277-AB81-D6B0C51F2D25
+ VERSION_STRING = 1.0
+ MODULE_TYPE = PEIM
+ LIBRARY_CLASS = RngLib | PEIM
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ PeiServicesLib
+
+[Guids]
+ gEfiRngAlgorithmSp80090Ctr256Guid
+ gEfiRngAlgorithmSp80090Hash256Guid
+ gEfiRngAlgorithmSp80090Hmac256Guid
+ gEfiRngAlgorithmRaw
+
+[Sources]
+ PeiRngLib.c
+
+[Ppis]
+ gEfiRngPpiGuid ## CONSUMES
+
+[Depex]
+ gEfiRngPpiGuid
diff --git a/MdePkg/Library/PeiRngLib/PeiRngLib.uni b/MdePkg/Library/PeiRngLib/PeiRngLib.uni
new file mode 100644
index 000000000000..8aea8ab7415f
--- /dev/null
+++ b/MdePkg/Library/PeiRngLib/PeiRngLib.uni
@@ -0,0 +1,12 @@
+// @file
+// PEI Instance of the RNG (Random Number Generator) Library.
+//
+// A RngLib instance that uses the RNG PPI to provide random numbers.
+//
+// Copyright (c) Microsoft Corporation.
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+
+#string STR_MODULE_ABSTRACT #language en-US "Instance of the RNG Library for PEI"
+
+#string STR_MODULE_DESCRIPTION #language en-US "A library that uses the RNG PPI to provide random numbers"
diff --git a/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf b/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
index 8d11a2b35f6c..dee997aa3ca4 100644
--- a/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+++ b/MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
@@ -31,4 +31,4 @@
[LibraryClasses]
DebugLib
-
+ StackCheckLib
diff --git a/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf b/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf
index 523a3e1d9f19..b8ebf3303d61 100644
--- a/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf
+++ b/MdePkg/Library/SmmPciExpressLib/SmmPciExpressLib.inf
@@ -32,6 +32,7 @@
PcdLib
DebugLib
IoLib
+ UefiBootServicesTableLib
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress ## CONSUMES
diff --git a/MdePkg/Library/StackCheckLib/Readme.md b/MdePkg/Library/StackCheckLib/Readme.md
index 6558c222cd24..2d3d34a8ef06 100644
--- a/MdePkg/Library/StackCheckLib/Readme.md
+++ b/MdePkg/Library/StackCheckLib/Readme.md
@@ -1,12 +1,12 @@
-# StackCheckLib
+# StackCheckLib Overview
## Table of Contents
- [StackCheckLib](#stackchecklib)
- [Table of Contents](#table-of-contents)
- [Introduction and Library Instances](#introduction-and-library-instances)
- - [StackCheckLibStaticInit](#stackchecklibstaticinit)
- - [StackCheckLibDynamicInit](#stackchecklibdynamicinit)
+ - [StackCheckLib](#stackchecklib)
+ - [DynamicStackCookieEntryPointLib](#dynamicstackcookieentrypointlib)
- [StackCheckLibNull](#stackchecklibnull)
- [How Failures are Handled](#how-failures-are-handled)
- [Debugging Stack Cookie Check Failures](#debugging-stack-cookie-check-failures)
@@ -15,44 +15,79 @@
## Introduction and Library Instances
`StackCheckLib` contains the required functionality for initializing the stack cookie
-value, checking the value, and triggering an interrupt when a mismatch occurs.
-The stack cookie is a random value placed on the stack between the stack variables
-and the return address so that continuously writing past the stack variables will
-cause the stack cookie to be overwritten. Before the function returns, the stack
-cookie value will be checked and if there is a mismatch then `StackCheckLib` handles
-the failure.
+value (based on a randomly generated value during build time), checking the value,
+and triggering an interrupt when a mismatch occurs. The stack cookie is a random value
+placed on the stack between the stack variables and the return address so that
+continuously writing past the stack variables will cause the stack cookie to be
+overwritten. Before the function returns, the stack cookie value will be checked and
+if there is a mismatch then `StackCheckLib` handles the failure.
Because UEFI doesn't use the C runtime libraries provided by MSVC, the stack
check code is written in assembly within this library. GCC and Clang compilers
have built-in support for stack cookie checking, so this library only handles failures.
-### StackCheckLibStaticInit
-
-`StackCheckLibStaticInit` is an instance of `StackCheckLib` which does not update the
-stack cookie value for the module at runtime. It's always preferable to use
-`StackCheckLibDynamicInit` for improved security but there are cases where the stack
-cookie global cannot be written to such as in execute-in-place (XIP) modules and during
-the Cache-as-RAM (CAR) phase of the boot process. The stack cookie value is initialized
-at compile time via updates to the AutoGen process. Each module will define
-`STACK_COOKIE_VALUE` which is used for the module stack cookie value.
-
-### StackCheckLibDynamicInit
-
-This section is future work. The below is the proposed instance.
-
-`StackCheckLibDynamicInit` is an instance of `StackCheckLib` which updates the stack
-cookie value for the module at runtime. This is the preferred method for stack cookie
-initialization as it provides improved security. The stack cookie value is initialized
-at runtime by calling `GetRandomNumber32()` or `GetRandomNumber64()` to generate a random
-value via the platform's random number generator protocol. If the random number generator
-returns an error, then the value will still have the build-time randomized value to fall
-back on.
+The stack cookie value is initialized at compile time via updates to the AutoGen process.
+Each module will define `STACK_COOKIE_VALUE` which is used for the module stack cookie
+value.
+
+The entry point libraries under `MdePkg/DynamicStackCookieEntryPointLib/` update the stack
+cookie value at runtime for improved security, but there are cases where the stack cookie
+global cannot be written to such as in execute-in-place (XIP) modules and during the
+temporary RAM phase of the boot process. It is always preferable to use
+one of the dynamic stack cookie entry points when possible.
+
+### StackCheckLib
+
+`StackCheckLib` provides the stack cookie checking functionality per architecture and
+toolchain. The currently supported pairs are IA32{GCC,MSVC}, X64{GCC, MSVC},
+ARM{GCC, MSVC}, and AARCH64{GCC, MSVC}. `StackCheckLib` is agnostic as to
+whether the stack cookie was updated during build time or run time; it simply
+checks the cookie in the MSVC case and in both GCC and MSVC responds to stack
+cookie checking failures.
+
+To add support for other architectures/toolchains, additional assembly files
+should be added to `StackCheckLib.inf` and scoped to that architecture/toolchain.
+
+Note: Stack cookie failures generate exceptions and SEC and PEI_CORE may not have
+exception handlers registered. In order to safely use stack cookie checking in
+these phases, a platform should implement exception handlers because unhandled
+exceptions may lead to a hung system state. If a platform does not implement
+exception handlers in SEC and PEI_CORE, it is recommended to use `StackCheckLibNull`
+for these phases, except for development purposes.
+
+### DynamicStackCookieEntryPointLib
+
+Each EntryPoint lib under `MdePkg/DynamicStackCookieEntryPointLib/` is an instance of
+that module type entry point lib which updates the stack cookie value for the module at
+runtime. This is the preferred method for stack cookie initialization as it provides
+improved security. The stack cookie value is initialized at runtime in `_ModuleEntryPoint`
+by calling `rdrand` on x86 and `RNDR` on AARCH64. If the random number generator is not
+supported on that platform or otherwise returns an error, then the value will still have
+the build-time randomized value to fall back on.
+
+Typically, dynamic cookies cannot be used for SEC, PEI_CORE, and PEIM modules, due to
+the lack of the ability to write to globals for many architectures. If a given platform
+can write to globals during these phases, it is recommended to use the provided dynamic
+stack cookie entry point lib for those types. Note that SEC does not have a universal
+entry point, so there is no dynamic stack cookie entry point lib there.
+
+The dynamic stack cookie entry point lib is used in place of the standard entry point lib,
+e.g. for UefiDriverEntryPoint to have dynamic stack cookies, a platform would remove
+MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf from its DSC and instead
+include MdePkg/Library/DynamicStackCookieEntryPointLib/UefiDriverEntryPoint.inf.
+
+See the Usage section for other ways of including these libraries.
+
+Note: Standalone MM Core support for dynamic cookies for AARCH64 is currently not
+supported, due to the unique entry point mechanism there. This support will be
+added at a future date.
### StackCheckLibNull
`StackCheckLibNull` is an instance of `StackCheckLib` which does not perform any stack
cookie checks. This is useful for modules which will fail if stack cookie checks are
-inserted. Of course, this is not recommended for production code.
+inserted. Of course, this is not recommended for production code outside of
+SEC and PEI_CORE.
## How Failures are Handled
@@ -104,8 +139,9 @@ edk2 updated the tools_def to add `/GS` to VS2022 and VS2019 IA32/X64 builds and
`-fstack-protector` to GCC builds. This will cause stack cookie references to be inserted
throughout the code. Every module should have a `StackCheckLib` instance linked to satisfy
these references. So every module doesn't need to add `StackCheckLib` to the LibraryClasses
-section of the INF file, `StackCheckLib` instances should be linked as NULL in the platform
-DSC files. The only exception to this is MSVC built host-based unit tests as they will be
+section of the INF file, `StackCheckLib` is added as a dependency for each entry point lib.
+This means that custom entry point libs need to have StackCheckLib added as a dependency.
+The only exception to this is MSVC built host-based unit tests as they will be
compiled with the runtime libraries which already contain the stack cookie definitions
and will collide with `StackCheckLib`. A `StackCheckLibHostApplication.inf` is linked
by `UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc` that provides the stack
@@ -113,70 +149,75 @@ cookie functions for GCC HOST_APPLICATIONS but not for MSVC HOST_APPLICATIONS.
### Default Stack Check Library Configuration
-`MdePkg/MdeLibs.dsc.inc` links `StackCheckLibNull` for all types except SEC, HOST_APPLICATION,
-and USER_DEFINED in order to not break existing DSCs. SEC cannot be generically linked to
-because there are some SEC modules which do not link against the standard entry point
-libraries and thus do not get stack cookies inserted by the compiler. USER_DEFINED modules
-are by nature different from other modules, so we do not make any assumptions about their
-state.
+`MdePkg/MdeLibs.dsc.inc` links `StackCheckLibNull` and `StackCheckFailureLibNull` for all
+types.
As stated above, all HOST_APPLICATIONS will link against a HOST_APPLICATION specific
implementation provided in `UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc`.
-To link the rest of a platform's modules to `StackCheckLibNull`, a platform would needs
-to link it for all SEC and USER_DEFINED modules. If all of the DSC's SEC and USER_DEFINED
-modules link against the entry point libs, it would look like the following:
+### Custom Stack Check Library Configuration
+
+In order to use a different instance of StackCheckLib than `MdeLibs.dsc.inc` provides, a DSC
+should add one of the following:
+
+#### Static Stack Check Cookie Configuration
```inf
-[LibraryClasses.common.SEC, LibraryClasses.common.USER_DEFINED]
- NULL|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf
+[Defines]
+ DEFINE CUSTOM_STACK_CHECK_LIB = STATIC
```
-If some do not, then the individual SEC/USER_DEFINED modules that do link against
-the entry point libs will need to be linked to `StackCheckLibNull`, such as below.
-This case is identifiable if a DSC is built and the linker complains the stack
-check functions are not found for a module.
+This will cause `MdeLibs.dsc.inc` to not link `StackCheckLibNull` and instead link
+`StackCheckLib` to perform stack cookie checking on the static stack cookies, but not update
+any of the stack cookies at runtime.
+
+Because edk2 does not implement exception handling for `SEC` and `PEI_CORE`, `MdeLibs.dsc.inc`
+uses `StackCheckLibNull` for these phases always. If a platform wishes to use `StackCheckLib`
+for these phases, it should override this in its DSC, e.g.:
```inf
-UefiCpuPkg/SecCore/SecCore.inf {
- <LibraryClasses>
- NULL|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf
- }
+[LibraryClasses.common.SEC, LibraryClasses.common.PEI_CORE]
+ StackCheckLib|MdePkg/Library/StackCheckLib/StackCheckLib.inf
```
-### Custom Stack Check Library Configuration
+It is recommended that a platform only do this for debugging or if they have implemented
+exception handlers for these phases.
-In order to use a different instance of StackCheckLib than `MdeLibs.dsc.inc` provides, a DSC
-should add the following:
+#### Dynamic Stack Cookie Configuration
```inf
[Defines]
- DEFINE CUSTOM_STACK_CHECK_LIB = TRUE
+ DEFINE CUSTOM_STACK_CHECK_LIB = DYNAMIC
```
-This will cause `MdeLibs.dsc.inc` to not link `StackCheckLibNull` and rely on a DSC to
-link whichever version(s) of `StackCheckLib` it desires.
-
-It is recommended that SEC and PEI_CORE modules use `StackCheckLibNull` and pre-memory modules
-should use `StackCheckLibStaticInit`. All other modules should use `StackCheckLibDynamicInit`.
+This will cause `MdeLibs.dsc.inc` to not link `StackCheckLibNull` and instead link
+`StackCheckLib` to perform stack cookie checking. It will also link the dynamic
+stack cookie updating versions of `DxeCoreEntryPoint`, `StandaloneMmDriverEntryPoint`,
+`UefiApplicationEntryPoint`, and `UefiDriverEntryPoint`.
-Below is an **example** of how to link the `StackCheckLib` instances in the platform DSC file
-but it may need customization based on the platform's requirements:
+Because edk2 does not implement exception handling for `SEC` and `PEI_CORE`,
+`MdeLibs.dsc.inc` uses `StackCheckLibNull` for these phases always. If a
+platform wishes to use `StackCheckLib` for these phases, it can enable static
+stack cookie checking, as documented in the previous section. Due to the fact
+that writable global variables are not supported in the `SEC` or `PEI` phases
+of execution, dynamic stack cookie checking is not supported here.
-```inf
-[LibraryClasses.common.SEC, LibraryClasses.common.PEI_CORE]
- NULL|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf
+It is recommended that a platform only do this for debugging or if they have implemented
+exception handlers for these phases.
-[LibraryClasses.common.PEIM]
- NULL|MdePkg/Library/StackCheckLib/StackCheckLibStaticInit.inf
+Note: `StandaloneMmCoreEntryPoint` is recommended to use the dynamic stack cookie if
+possible, but as it is not supported on AARCH64 today, it is not included in MdeLibs.dsc.inc.
+Platforms should include this separately, e.g.:
-[LibraryClasses.common.MM_CORE_STANDALONE, LibraryClasses.common.MM_STANDALONE, LibraryClasses.common.DXE_CORE,
-LibraryClasses.common.SMM_CORE, LibraryClasses.common.DXE_SMM_DRIVER, LibraryClasses.common.DXE_DRIVER,
-LibraryClasses.common.DXE_RUNTIME_DRIVER, LibraryClasses.common.DXE_SAL_DRIVER, LibraryClasses.common.UEFI_DRIVER,
-LibraryClasses.common.UEFI_APPLICATION]
- NULL|MdePkg/Library/StackCheckLib/StackCheckLibDynamicInit.inf
+```inf
+[LibraryClasses.X64]
+ StandaloneMmCoreEntryPoint|MdePkg/Library/DynamicStackCookieEntryPointLib/StandaloneMmCoreEntryPoint.inf
```
+Platforms then must remove any references to these entry point libs in their DSC, so that
+the `MdeLibs.dsc.inc` versions are chosen. Alternatively, for better DSC readability,
+a platform can directly reference the dynamic stack cookie entry points.
+
### Disable Stack Check Library
If a platform would like to disable stack cookies (say for debugging purposes),
@@ -191,4 +232,14 @@ they can add the following to their DSC:
The same build options can be put in a module's INF to only disable stack cookies
for that module.
+Alternatively, a module can have the stack cookies inserted but checking disabled
+by including the following in a DSC:
+
+```inf
+SomePkg/SomeDirectory/SomeModule.inf {
+ <LibraryClasses>
+ StackCheckLib|MdePkg/Library/StackCheckLibNull/StackCheckLibNull.inf
+}
+```
+
It is not recommended to disable stack cookie checking in production scenarios.
diff --git a/MdePkg/Library/StackCheckLib/StackCheckLib.inf b/MdePkg/Library/StackCheckLib/StackCheckLib.inf
new file mode 100644
index 000000000000..417d340a851f
--- /dev/null
+++ b/MdePkg/Library/StackCheckLib/StackCheckLib.inf
@@ -0,0 +1,56 @@
+## @file
+# Provides the required functionality for checking the stack cookie.
+#
+# Copyright (c) Microsoft Corporation.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+ INF_VERSION = 1.29
+ BASE_NAME = StackCheckLib
+ FILE_GUID = 1C4CA056-8FEA-413C-89D2-59A7E22847B3
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = StackCheckLib
+
+[Sources]
+ StackCheckLibCommonMsvc.c | MSFT
+ StackCheckLibCommonGcc.c | GCC
+
+[Sources.IA32]
+ IA32/CheckCookieMsvc.nasm | MSFT
+
+[Sources.X64]
+ X64/CheckCookieMsvc.nasm | MSFT
+
+[Sources.IA32, Sources.X64]
+ IA32/StackCookieInterrupt.nasm
+
+[Sources.ARM]
+ Arm/StackCookieInterrupt.S |GCC
+ Arm/StackCookieInterrupt.asm |MSFT
+
+[Sources.AARCH64]
+ AArch64/StackCookieInterrupt.S |GCC
+ AArch64/StackCookieInterrupt.asm |MSFT
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ StackCheckFailureHookLib
+
+[FixedPcd]
+ gEfiMdePkgTokenSpaceGuid.PcdStackCookieExceptionVector
+
+[BuildOptions]
+ # We cannot build the MSVC version with /GL (whole program optimization) because we run into linker error
+ # LNK1237, which is a failure to link against a symbol from a library compiled with /GL. The whole program
+ # optimization tries to do away with references to this symbol. The solution is to not compile the stack
+ # check libs with /GL
+ MSFT:*_*_*_CC_FLAGS = /GL-
+
+ # We cannot build the GCC version with LTO (link time optimization) because we run into linker errors where
+ # the stack cookie variable has been optimized away, as it looks to GCC like the variable is not used, because
+ # the compiler inserts the usage.
+ GCC:*_*_*_CC_FLAGS = -fno-lto
diff --git a/MdePkg/Library/StackCheckLib/StackCheckLibCommonGcc.c b/MdePkg/Library/StackCheckLib/StackCheckLibCommonGcc.c
index 996d1e6d732f..cccab4212bbf 100644
--- a/MdePkg/Library/StackCheckLib/StackCheckLibCommonGcc.c
+++ b/MdePkg/Library/StackCheckLib/StackCheckLibCommonGcc.c
@@ -10,6 +10,7 @@
#include <Library/DebugLib.h>
#include <Library/BaseLib.h>
+#include <Library/StackCheckLib.h>
#include <Library/StackCheckFailureHookLib.h>
/**
@@ -28,6 +29,7 @@ VOID *__stack_chk_guard = (VOID *)(UINTN)STACK_COOKIE_VALUE;
**/
VOID
+EFIAPI
__stack_chk_fail (
VOID
)
diff --git a/MdePkg/Library/StackCheckLib/StackCheckLibCommonMsvc.c b/MdePkg/Library/StackCheckLib/StackCheckLibCommonMsvc.c
index 6018e3790990..449ffe6da171 100644
--- a/MdePkg/Library/StackCheckLib/StackCheckLibCommonMsvc.c
+++ b/MdePkg/Library/StackCheckLib/StackCheckLibCommonMsvc.c
@@ -10,6 +10,7 @@
#include <Library/DebugLib.h>
#include <Library/BaseLib.h>
+#include <Library/StackCheckLib.h>
#include <Library/StackCheckFailureHookLib.h>
/**
diff --git a/MdePkg/Library/StackCheckLibNull/StackCheckLibNullGcc.c b/MdePkg/Library/StackCheckLibNull/StackCheckLibNullGcc.c
index 5c4278d60bf4..91568dee88c5 100644
--- a/MdePkg/Library/StackCheckLibNull/StackCheckLibNullGcc.c
+++ b/MdePkg/Library/StackCheckLibNull/StackCheckLibNullGcc.c
@@ -6,6 +6,7 @@
**/
#include <Uefi.h>
+#include <Library/StackCheckLib.h>
VOID *__stack_chk_guard = (VOID *)(UINTN)0x0;
diff --git a/MdePkg/Library/StackCheckLibNull/StackCheckLibNullMsvc.c b/MdePkg/Library/StackCheckLibNull/StackCheckLibNullMsvc.c
index a9c26dc36b21..ff99120ad2fd 100644
--- a/MdePkg/Library/StackCheckLibNull/StackCheckLibNullMsvc.c
+++ b/MdePkg/Library/StackCheckLibNull/StackCheckLibNullMsvc.c
@@ -6,5 +6,6 @@
**/
#include <Uefi.h>
+#include <Library/StackCheckLib.h>
VOID *__security_cookie = (VOID *)(UINTN)0x0;
diff --git a/MdePkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf b/MdePkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf
new file mode 100644
index 000000000000..3052788d8216
--- /dev/null
+++ b/MdePkg/Library/StandaloneMmCoreEntryPoint/StandaloneMmCoreEntryPoint.inf
@@ -0,0 +1,33 @@
+## @file
+# Module entry point library for Standalone MM core.
+#
+# Copyright (c) 2017 - 2021, Arm Ltd. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = StandaloneMmCoreEntryPoint
+ FILE_GUID = 6D1B60B2-5DD1-4523-8F0A-607DB4D6B0CE
+ MODULE_TYPE = MM_CORE_STANDALONE
+ VERSION_STRING = 1.0
+ PI_SPECIFICATION_VERSION = 0x00010032
+ LIBRARY_CLASS = StandaloneMmCoreEntryPoint|MM_CORE_STANDALONE
+
+#
+# VALID_ARCHITECTURES = X64
+#
+
+[Sources.X64]
+ X64/StandaloneMmCoreEntryPoint.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ DebugLib
+ StackCheckLib
diff --git a/MdePkg/Library/StandaloneMmCoreEntryPoint/X64/StandaloneMmCoreEntryPoint.c b/MdePkg/Library/StandaloneMmCoreEntryPoint/X64/StandaloneMmCoreEntryPoint.c
new file mode 100644
index 000000000000..7c67c4d3c73a
--- /dev/null
+++ b/MdePkg/Library/StandaloneMmCoreEntryPoint/X64/StandaloneMmCoreEntryPoint.c
@@ -0,0 +1,69 @@
+/** @file
+ Entry point to the Standalone Mm Core.
+
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+Copyright (c) Microsoft Corporation.
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <PiMm.h>
+
+#include <Library/StandaloneMmCoreEntryPoint.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseLib.h>
+
+//
+// Cache copy of HobList pointer.
+//
+VOID *gHobList = NULL;
+
+/**
+ The entry point of PE/COFF Image for the STANDALONE MM Core.
+
+ This function is the entry point for the STANDALONE MM Core. This function is required to call
+ ProcessModuleEntryPointList() and ProcessModuleEntryPointList() is never expected to return.
+ The STANDALONE MM Core is responsible for calling ProcessLibraryConstructorList() as soon as the EFI
+ System Table and the image handle for the STANDALONE MM Core itself have been established.
+ If ProcessModuleEntryPointList() returns, then ASSERT() and halt the system.
+
+ @param HobStart Pointer to the beginning of the HOB List passed in from the PEI Phase.
+
+**/
+VOID
+EFIAPI
+_ModuleEntryPoint (
+ IN VOID *HobStart
+ )
+{
+ //
+ // Cache a pointer to the HobList
+ //
+ gHobList = HobStart;
+
+ //
+ // Call the Standalone MM Core entry point
+ //
+ ProcessModuleEntryPointList (HobStart);
+
+ //
+ // TODO: Set page table here?? AARCH64 has this step for some reason
+ //
+}
+
+/**
+ Required by the EBC compiler and identical in functionality to _ModuleEntryPoint().
+
+ This function is required to call _ModuleEntryPoint() passing in HobStart.
+
+ @param HobStart Pointer to the beginning of the HOB List passed in from the PEI Phase.
+
+**/
+VOID
+EFIAPI
+EfiMain (
+ IN VOID *HobStart
+ )
+{
+ _ModuleEntryPoint (HobStart);
+}
diff --git a/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf b/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf
index a83545aac051..9fafd44d3a04 100644
--- a/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf
+++ b/MdePkg/Library/StandaloneMmDriverEntryPoint/StandaloneMmDriverEntryPoint.inf
@@ -36,6 +36,7 @@
BaseLib
DebugLib
MmServicesTableLib
+ StackCheckLib
[Protocols]
gEfiLoadedImageProtocolGuid ## SOMETIMES_CONSUMES
diff --git a/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf b/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
index ced65892ad11..ecd033f7f741 100644
--- a/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+++ b/MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
@@ -32,4 +32,5 @@
UefiBootServicesTableLib
DebugLib
BaseLib
+ StackCheckLib
diff --git a/MdePkg/Library/UefiDevicePathLib/DevicePathToText.c b/MdePkg/Library/UefiDevicePathLib/DevicePathToText.c
index 23f3010286e6..f1d1f4bc97eb 100644
--- a/MdePkg/Library/UefiDevicePathLib/DevicePathToText.c
+++ b/MdePkg/Library/UefiDevicePathLib/DevicePathToText.c
@@ -1882,7 +1882,7 @@ DevPathToTextHardDrive (
case SIGNATURE_TYPE_MBR:
UefiDevicePathLibCatPrint (
Str,
- L"HD(%d,%s,0x%08x,",
+ L"HD(%d,%s,0x%08x",
Hd->PartitionNumber,
L"MBR",
*((UINT32 *)(&(Hd->Signature[0])))
@@ -1892,7 +1892,7 @@ DevPathToTextHardDrive (
case SIGNATURE_TYPE_GUID:
UefiDevicePathLibCatPrint (
Str,
- L"HD(%d,%s,%g,",
+ L"HD(%d,%s,%g",
Hd->PartitionNumber,
L"GPT",
(EFI_GUID *)&(Hd->Signature[0])
@@ -1902,14 +1902,18 @@ DevPathToTextHardDrive (
default:
UefiDevicePathLibCatPrint (
Str,
- L"HD(%d,%d,0,",
+ L"HD(%d,%d,0",
Hd->PartitionNumber,
Hd->SignatureType
);
break;
}
- UefiDevicePathLibCatPrint (Str, L"0x%lx,0x%lx)", Hd->PartitionStart, Hd->PartitionSize);
+ if (DisplayOnly) {
+ UefiDevicePathLibCatPrint (Str, L")");
+ } else {
+ UefiDevicePathLibCatPrint (Str, L",0x%lx,0x%lx)", Hd->PartitionStart, Hd->PartitionSize);
+ }
}
/**
diff --git a/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf b/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
index bef65fb22631..8432fd56b921 100644
--- a/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
+++ b/MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
@@ -36,6 +36,7 @@
UefiBootServicesTableLib
DebugLib
BaseLib
+ StackCheckLib
[Protocols]
diff --git a/MdePkg/Library/UefiUsbLib/UefiUsbLib.inf b/MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
index 2f1224081165..8f7b26138132 100644
--- a/MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
+++ b/MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
@@ -5,6 +5,7 @@
# Usb Hid 1.1 spec and the standard requests defined in Usb 1.1 spec.
#
# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2024, American Megatrends International LLC. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -19,6 +20,7 @@
MODULE_TYPE = UEFI_DRIVER
VERSION_STRING = 1.0
LIBRARY_CLASS = UefiUsbLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER
+ DESTRUCTOR = UefiUsbLibDestructor
#
@@ -37,6 +39,7 @@
DebugLib
BaseMemoryLib
PcdLib
+ UefiBootServicesTableLib
[Pcd]
gEfiMdePkgTokenSpaceGuid.PcdUsbTransferTimeoutValue ## CONSUMES
diff --git a/MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h b/MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h
index 30cb4a2cb864..1c43b348b19f 100644
--- a/MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h
+++ b/MdePkg/Library/UefiUsbLib/UefiUsbLibInternal.h
@@ -5,6 +5,7 @@
This file includes package header files, library classes and protocol, PPI & GUID definitions.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2024, American Megatrends International LLC. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -17,6 +18,7 @@
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#include <Library/PcdLib.h>
+#include <Library/UefiBootServicesTableLib.h>
#include <IndustryStandard/Usb.h>
diff --git a/MdePkg/Library/UefiUsbLib/UsbDxeLib.c b/MdePkg/Library/UefiUsbLib/UsbDxeLib.c
index 6d46529ae2f4..f25e8097fc41 100644
--- a/MdePkg/Library/UefiUsbLib/UsbDxeLib.c
+++ b/MdePkg/Library/UefiUsbLib/UsbDxeLib.c
@@ -4,12 +4,16 @@
in Usb specification 9.4 section.
Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2024, American Megatrends International LLC. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "UefiUsbLibInternal.h"
+static UINT8 *mConfigData = NULL;
+static EFI_USB_DEVICE_DESCRIPTOR mDeviceDescriptor;
+
/**
Get the descriptor of the specified USB device.
@@ -650,3 +654,532 @@ UsbClearEndpointHalt (
return Result;
}
+
+/**
+ Global library data initialization.
+
+ Library public functions' input is the instance of UsbIo protocol. Check if the global
+ data relevant to the UsbIo. If not, read the device and update the global data.
+
+ @param UsbIo The instance of EFI_USB_IO_PROTOCOL.
+
+ @retval EFI_SUCCESS The global data is updated.
+ @retval EFI_NOT_FOUND The UsbIo configuration was not found.
+
+**/
+static
+EFI_STATUS
+InitUsbConfigDescriptorData (
+ EFI_USB_IO_PROTOCOL *UsbIo
+ )
+{
+ EFI_STATUS Status;
+ EFI_USB_DEVICE_DESCRIPTOR DevDesc;
+ EFI_USB_CONFIG_DESCRIPTOR CnfDesc;
+ UINT8 ConfigNum;
+ UINT8 ConfigValue;
+ UINT32 UsbStatus;
+
+ //
+ // Get UsbIo device and configuration descriptors.
+ //
+ Status = UsbIo->UsbGetDeviceDescriptor (UsbIo, &DevDesc);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = UsbIo->UsbGetConfigDescriptor (UsbIo, &CnfDesc);
+ ASSERT_EFI_ERROR (Status);
+
+ if (mConfigData != NULL) {
+ if ( (CompareMem (&DevDesc, &mDeviceDescriptor, sizeof (EFI_USB_DEVICE_DESCRIPTOR)) == 0)
+ && (CompareMem (&CnfDesc, mConfigData, sizeof (EFI_USB_CONFIG_DESCRIPTOR)) == 0))
+ {
+ return EFI_SUCCESS;
+ }
+
+ gBS->FreePool (mConfigData);
+ mConfigData = NULL;
+ }
+
+ CopyMem (&mDeviceDescriptor, &DevDesc, sizeof (EFI_USB_DEVICE_DESCRIPTOR));
+
+ //
+ // Examine device with multiple configurations: find configuration index of UsbIo config descriptor.
+ //
+ // Use EFI_USB_DEVICE_DESCRIPTOR.NumConfigurations to loop through configuration descriptors, match
+ // EFI_USB_CONFIG_DESCRIPTOR.ConfigurationValue to the configuration value reported by UsbIo->UsbGetConfigDescriptor.
+ // The index of the matched configuration is used in wValue of the following GET_DESCRIPTOR request.
+ //
+ ConfigValue = CnfDesc.ConfigurationValue;
+ for (ConfigNum = 0; ConfigNum < DevDesc.NumConfigurations; ConfigNum++) {
+ Status = UsbGetDescriptor (
+ UsbIo,
+ (USB_DESC_TYPE_CONFIG << 8) | ConfigNum,
+ 0,
+ sizeof (EFI_USB_CONFIG_DESCRIPTOR),
+ &CnfDesc,
+ &UsbStatus
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ if (CnfDesc.ConfigurationValue == ConfigValue) {
+ break;
+ }
+ }
+
+ ASSERT (ConfigNum < DevDesc.NumConfigurations);
+ if (ConfigNum == DevDesc.NumConfigurations) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // ConfigNum has zero based index of the configuration that UsbIo belongs to. Use this index to retrieve
+ // full configuration descriptor data.
+ //
+ Status = gBS->AllocatePool (EfiBootServicesData, CnfDesc.TotalLength, (VOID **)&mConfigData);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = UsbGetDescriptor (
+ UsbIo,
+ (USB_DESC_TYPE_CONFIG << 8) | ConfigNum,
+ 0,
+ CnfDesc.TotalLength,
+ mConfigData,
+ &UsbStatus
+ );
+ ASSERT_EFI_ERROR (Status);
+
+ return Status;
+}
+
+/**
+ Find descriptor of a given type within data area pointed by mConfigData.
+
+ The following are the assumptions of the configuration descriptor layout:
+ - mConfigData is populated with the configuration data that contains USB interface referenced by UsbIo.
+ - Endpoint may have only one class specific descriptor that immediately follows the endpoint descriptor.
+
+ @param[in] UsbIo A pointer to the EFI_USB_IO_PROTOCOL instance.
+ @param[in] DescType Type of descriptor to look for.
+ @param[in] Setting Interface alternate setting.
+ @param[in] Index Index of the descriptor. This descriptor index is used to find a specific
+ descriptor (only for endpoint descriptors and class specific interface descriptors)
+ when several descriptors of the same type are implemented in a device. For other
+ descriptor types, a descriptor index of zero must be used.
+ @param[out] Data A pointer to the caller allocated Descriptor.
+
+ @retval EFI_SUCCESS Output parameters were updated successfully.
+ @retval EFI_UNSUPPORTED Setting is greater than the number of alternate settings in this interface.
+ @retval EFI_NOT_FOUND Index is greater than the number of descriptors of the requested type in this
+ interface.
+**/
+static
+EFI_STATUS
+FindUsbDescriptor (
+ EFI_USB_IO_PROTOCOL *UsbIo,
+ UINT8 DescType,
+ UINT16 Setting,
+ UINTN Index,
+ VOID **Data
+ )
+{
+ EFI_USB_INTERFACE_DESCRIPTOR IntfDesc;
+ EFI_STATUS Status;
+ UINT8 *BufferPtr;
+ UINT8 *BufferEnd;
+ UINT8 *ConfigEnd;
+ UINTN Idx;
+
+ //
+ // Find the interface descriptor referenced by UsbIo in the current configuration
+ //
+ Status = UsbIo->UsbGetInterfaceDescriptor (UsbIo, &IntfDesc);
+ ASSERT_EFI_ERROR (Status);
+
+ ConfigEnd = mConfigData + ((EFI_USB_CONFIG_DESCRIPTOR *)mConfigData)->TotalLength;
+
+ for (BufferPtr = mConfigData; BufferPtr < ConfigEnd; BufferPtr += BufferPtr[0]) {
+ if (BufferPtr[1] == USB_DESC_TYPE_INTERFACE) {
+ if ((BufferPtr[2] == IntfDesc.InterfaceNumber) && (BufferPtr[3] == (UINT8)Setting)) {
+ break;
+ }
+ }
+ }
+
+ if (BufferPtr >= ConfigEnd) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Found the beginning of the interface, find the ending
+ //
+ for (BufferEnd = BufferPtr + BufferPtr[0]; BufferEnd < ConfigEnd; BufferEnd += BufferEnd[0]) {
+ if (BufferEnd[1] == USB_DESC_TYPE_INTERFACE) {
+ break;
+ }
+ }
+
+ Idx = 0;
+
+ if (DescType == USB_DESC_TYPE_INTERFACE) {
+ *Data = BufferPtr;
+ return EFI_SUCCESS;
+ }
+
+ if ((DescType == USB_DESC_TYPE_ENDPOINT) || (DescType == USB_DESC_TYPE_CS_ENDPOINT)) {
+ while (BufferPtr < BufferEnd) {
+ BufferPtr += BufferPtr[0];
+ if (BufferPtr[1] == USB_DESC_TYPE_ENDPOINT) {
+ if (Idx == Index) {
+ if (DescType == USB_DESC_TYPE_CS_ENDPOINT) {
+ BufferPtr += BufferPtr[0];
+ if (BufferPtr[1] != USB_DESC_TYPE_CS_ENDPOINT) {
+ break;
+ }
+ }
+
+ *Data = BufferPtr;
+ return EFI_SUCCESS;
+ }
+
+ Idx++;
+ }
+ }
+ }
+
+ if (DescType == USB_DESC_TYPE_CS_INTERFACE) {
+ while (BufferPtr < BufferEnd) {
+ BufferPtr += BufferPtr[0];
+ if (BufferPtr[1] == USB_DESC_TYPE_CS_INTERFACE) {
+ if (Idx == Index) {
+ *Data = BufferPtr;
+ return EFI_SUCCESS;
+ }
+
+ Idx++;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Retrieve the number of class specific interface descriptors.
+
+ @param[in] Data A pointer to the USB interface descriptor that may contain class code descriptors.
+
+ @retval UINT8 Number of the class code interface descriptors.
+
+**/
+static
+UINT8
+FindNumberOfCsInterfaces (
+ VOID *Data
+ )
+{
+ UINT8 *Buffer;
+ UINT8 *ConfigEnd;
+ UINT8 Index;
+
+ Buffer = Data;
+ ConfigEnd = mConfigData + ((EFI_USB_CONFIG_DESCRIPTOR *)mConfigData)->TotalLength;
+
+ Index = 0;
+
+ for (Buffer += Buffer[0]; Buffer < ConfigEnd; Buffer += Buffer[0]) {
+ if (Buffer[1] == USB_DESC_TYPE_INTERFACE) {
+ break;
+ }
+
+ if (Buffer[1] == USB_DESC_TYPE_CS_INTERFACE) {
+ Index++;
+ }
+ }
+
+ return Index;
+}
+
+/**
+ Retrieve the interface descriptor details from the interface setting.
+
+ This is an extended version of UsbIo->GetInterfaceDescriptor. It returns the interface
+ descriptor for an alternate setting of the interface without executing SET_INTERFACE
+ transfer. It also returns the number of class specific interfaces.
+ AlternateSetting parameter is the zero-based interface descriptor index that is used in USB
+ interface descriptor as USB_INTERFACE_DESCRIPTOR.AlternateSetting.
+
+
+ @param[in] This A pointer to the EFI_USB_IO_PROTOCOL instance.
+ @param[in] AlternateSetting Interface alternate setting.
+ @param[out] Descriptor The caller allocated buffer to return the contents of the Interface descriptor.
+ @param[out] CsInterfaceNumber Number of class specific interfaces for this interface setting.
+
+ @retval EFI_SUCCESS Output parameters were updated successfully.
+ @retval EFI_INVALID_PARAMETER Descriptor or CsInterfaceNumber is NULL.
+ @retval EFI_UNSUPPORTED AlternateSetting is greater than the number of alternate settings in this interface.
+ @retval EFI_DEVICE_ERROR Error reading device data.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbGetInterfaceDescriptorSetting (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT16 AlternateSetting,
+ OUT EFI_USB_INTERFACE_DESCRIPTOR *Descriptor,
+ OUT UINTN *CsInterfacesNumber
+ )
+{
+ EFI_STATUS Status;
+ VOID *Data;
+ EFI_TPL OldTpl;
+
+ if ((Descriptor == NULL) || (CsInterfacesNumber == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ Status = InitUsbConfigDescriptorData (This);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto ON_EXIT;
+ }
+
+ Status = FindUsbDescriptor (This, USB_DESC_TYPE_INTERFACE, AlternateSetting, 0, &Data);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ *CsInterfacesNumber = FindNumberOfCsInterfaces (Data);
+ CopyMem (Descriptor, Data, sizeof (EFI_USB_INTERFACE_DESCRIPTOR));
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ Retrieve the endpoint descriptor from the interface setting.
+
+ This is an extended version of UsbIo->GetEndpointDescriptor. It returns the endpoint
+ descriptor for an alternate setting of a given interface.
+ AlternateSetting parameter is the zero-based interface descriptor index that is used in USB
+ interface descriptor as USB_INTERFACE_DESCRIPTOR.AlternateSetting.
+
+ Note: The total number of endpoints can be retrieved from the interface descriptor
+ returned by EDKII_USBIO_EXT_GET_INTERFACE_DESCRIPTOR function.
+
+ @param[in] This A pointer to the EFI_USB_IO_PROTOCOL instance.
+ @param[in] AlternateSetting Interface alternate setting.
+ @param[in] Index Index of the endpoint to retrieve. The valid range is 0..15.
+ @param[out] Descriptor A pointer to the caller allocated USB Interface Descriptor.
+
+ @retval EFI_SUCCESS Output parameters were updated successfully.
+ @retval EFI_INVALID_PARAMETER Descriptor is NULL.
+ @retval EFI_UNSUPPORTED AlternateSetting is greater than the number of alternate settings in this interface.
+ @retval EFI_NOT_FOUND Index is greater than the number of endpoints in this interface.
+ @retval EFI_DEVICE_ERROR Error reading device data.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbGetEndpointDescriptorSetting (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT16 AlternateSetting,
+ IN UINTN Index,
+ OUT EFI_USB_ENDPOINT_DESCRIPTOR *Descriptor
+ )
+{
+ EFI_STATUS Status;
+ VOID *Data;
+ EFI_TPL OldTpl;
+
+ if (Descriptor == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ Status = InitUsbConfigDescriptorData (This);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto ON_EXIT;
+ }
+
+ Status = FindUsbDescriptor (This, USB_DESC_TYPE_ENDPOINT, AlternateSetting, Index, &Data);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ CopyMem (Descriptor, Data, sizeof (EFI_USB_ENDPOINT_DESCRIPTOR));
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ Retrieve class specific interface descriptor.
+
+ AlternateSetting parameter is the zero-based interface descriptor index that is used in USB
+ interface descriptor as USB_INTERFACE_DESCRIPTOR.AlternateSetting.
+
+ @param[in] This A pointer to the EFI_USB_IO_PROTOCOL instance.
+ @param[in] AlternateSetting Interface alternate setting.
+ @param[in] Index Zero-based index of the class specific interface.
+ @param[in][out] BufferSize On input, the size in bytes of the return Descriptor buffer.
+ On output the size of data returned in Descriptor.
+ @param[out] Descriptor The buffer to return the contents of the class specific interface descriptor. May
+ be NULL with a zero BufferSize in order to determine the size buffer needed.
+
+ @retval EFI_SUCCESS Output parameters were updated successfully.
+ @retval EFI_INVALID_PARAMETER BufferSize is NULL.
+ Buffer is NULL and *BufferSize is not zero.
+ @retval EFI_UNSUPPORTED AlternateSetting is greater than the number of alternate settings in this interface.
+ @retval EFI_NOT_FOUND Index is greater than the number of class specific interfaces.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small for the result. BufferSize has been updated with the size
+ needed to complete the request.
+ @retval EFI_DEVICE_ERROR Error reading device data.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbGetCsInterfaceDescriptor (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT16 AlternateSetting,
+ IN UINTN Index,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ VOID *Data;
+ UINT8 DescLength;
+ EFI_TPL OldTpl;
+
+ if ((BufferSize == NULL) || ((Buffer == NULL) && (*BufferSize != 0))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ Status = InitUsbConfigDescriptorData (This);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto ON_EXIT;
+ }
+
+ Status = FindUsbDescriptor (This, USB_DESC_TYPE_CS_INTERFACE, AlternateSetting, Index, &Data);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ DescLength = ((UINT8 *)Data)[0];
+
+ if ((Buffer == NULL) || (DescLength > *BufferSize)) {
+ *BufferSize = DescLength;
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto ON_EXIT;
+ }
+
+ CopyMem (Buffer, Data, DescLength);
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ Retrieve class specific endpoint descriptor.
+
+ AlternateSetting parameter is the zero-based interface descriptor index that is used in USB
+ interface descriptor as USB_INTERFACE_DESCRIPTOR.AlternateSetting.
+
+ @param[in] This A pointer to the EFI_USB_IO_PROTOCOL instance.
+ @param[in] AlternateSetting Interface alternate setting.
+ @param[in] Index Zero-based index of the non-zero endpoint.
+ @param[in][out] BufferSize On input, the size in bytes of the return Descriptor buffer.
+ On output the size of data returned in Descriptor.
+ @param[out] Descriptor The buffer to return the contents of the class specific endpoint descriptor. May
+ be NULL with a zero BufferSize in order to determine the size buffer needed.
+
+ @retval EFI_SUCCESS Output parameters were updated successfully.
+ @retval EFI_INVALID_PARAMETER BufferSize is NULL.
+ Buffer is NULL and *BufferSize is not zero.
+ @retval EFI_UNSUPPORTED AlternateSetting is greater than the number of alternate settings in this interface.
+ @retval EFI_NOT_FOUND Index is greater than the number of endpoints in this interface.
+ Endpoint does not have class specific endpoint descriptor.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small for the result. BufferSize has been updated with the size
+ needed to complete the request.
+ @retval EFI_DEVICE_ERROR Error reading device data.
+
+**/
+EFI_STATUS
+EFIAPI
+UsbGetCsEndpointDescriptor (
+ IN EFI_USB_IO_PROTOCOL *This,
+ IN UINT16 AlternateSetting,
+ IN UINTN Index,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ VOID *Data;
+ UINT8 DescLength;
+ EFI_TPL OldTpl;
+
+ if ((BufferSize == NULL) || ((Buffer == NULL) && (*BufferSize != 0))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+
+ Status = InitUsbConfigDescriptorData (This);
+ if (EFI_ERROR (Status)) {
+ Status = EFI_DEVICE_ERROR;
+ goto ON_EXIT;
+ }
+
+ Status = FindUsbDescriptor (This, USB_DESC_TYPE_CS_ENDPOINT, AlternateSetting, Index, &Data);
+ if (EFI_ERROR (Status)) {
+ goto ON_EXIT;
+ }
+
+ DescLength = ((UINT8 *)Data)[0];
+
+ if ((Buffer == NULL) || (DescLength > *BufferSize)) {
+ *BufferSize = DescLength;
+ Status = EFI_BUFFER_TOO_SMALL;
+ goto ON_EXIT;
+ }
+
+ CopyMem (Buffer, Data, DescLength);
+
+ON_EXIT:
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+}
+
+/**
+ Destructor frees memory which was allocated by the library functions.
+
+ @param ImageHandle Handle that identifies the image to be unloaded.
+ @param SystemTable The system table.
+
+ @retval EFI_SUCCESS The image has been unloaded.
+
+**/
+EFI_STATUS
+EFIAPI
+UefiUsbLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (mConfigData != NULL) {
+ gBS->FreePool (mConfigData);
+ }
+
+ return EFI_SUCCESS;
+}