diff --git a/MmSupervisorPkg/Core/Handler/Mmi.c b/MmSupervisorPkg/Core/Handler/Mmi.c index 03726031..f291e46e 100644 --- a/MmSupervisorPkg/Core/Handler/Mmi.c +++ b/MmSupervisorPkg/Core/Handler/Mmi.c @@ -212,6 +212,11 @@ MmiManage ( CommBuffer, CommBufferSize ); + if (Status == EFI_NOT_READY) { + // This is from the wrap itself due to ring 3 broker not ready, so we bail the loop and bubble it back to the caller + ReturnStatus = Status; + break; + } } else if (SupervisorPath && MmiHandler->IsSupervisor) { Status = MmiHandler->Handler ( (EFI_HANDLE)MmiHandler, diff --git a/MmSupervisorPkg/Core/MmSupervisorCore.c b/MmSupervisorPkg/Core/MmSupervisorCore.c index 546d7816..e4699fcd 100644 --- a/MmSupervisorPkg/Core/MmSupervisorCore.c +++ b/MmSupervisorPkg/Core/MmSupervisorCore.c @@ -108,10 +108,17 @@ EFI_MEMORY_DESCRIPTOR mMmSupervisorAccessBuffer[MM_OPEN_BUFFER_CNT]; // Table of MMI Handlers that are registered by the MM Core when it is initialized // MM_CORE_MMI_HANDLERS mMmCoreMmiHandlers[] = { - { MmDriverDispatchHandler, &gMmSupervisorDriverDispatchGuid, NULL, TRUE }, - { MmReadyToLockHandler, &gEfiDxeMmReadyToLockProtocolGuid, NULL, TRUE }, - { MmSupvRequestHandler, &gMmSupervisorRequestHandlerGuid, NULL, FALSE }, - { NULL, NULL, NULL, FALSE }, + // Note: The driver dispatch handler is registered in user handler pool, to suffice the needs + // if a driver dispatch call is invoked from user space. The handler is intentionally left + // to duplicate the real dispatcher. Because if the ring 3 broker is ready, supervisor will + // dispatch to this handler after demotion, which will trip on #GP due to SMAP. Otherwise, + // if this is invoked before ring 3 broker being dispatched, the demotion routine will + // directly bail with EFI_NOT_READY. + { MmDriverDispatchHandler, &gEventMmDispatchGuid, NULL, FALSE, FALSE }, + { MmDriverDispatchHandler, &gMmSupervisorDriverDispatchGuid, NULL, TRUE, TRUE }, + { MmReadyToLockHandler, &gEfiDxeMmReadyToLockProtocolGuid, NULL, TRUE, TRUE }, + { MmSupvRequestHandler, &gMmSupervisorRequestHandlerGuid, NULL, FALSE, TRUE }, + { NULL, NULL, NULL, FALSE, TRUE }, }; EFI_SYSTEM_TABLE *mEfiSystemTable; @@ -385,13 +392,18 @@ MmReadyToLockHandler ( // for (Index = 0; mMmCoreMmiHandlers[Index].HandlerType != NULL; Index++) { if (mMmCoreMmiHandlers[Index].UnRegister) { - Status = MmiHandlerSupvUnRegister (mMmCoreMmiHandlers[Index].DispatchHandle); + if (mMmCoreMmiHandlers[Index].SupervisorHandler) { + Status = MmiHandlerSupvUnRegister (mMmCoreMmiHandlers[Index].DispatchHandle); + } else { + Status = MmiHandlerUserUnRegister (mMmCoreMmiHandlers[Index].DispatchHandle); + } if (EFI_ERROR (Status)) { DEBUG (( DEBUG_ERROR, - "Failed to unregister supervisor handler No. %d %g - %r\n", + "Failed to unregister supervisor handler No. %d %g (%a) - %r\n", Index, mMmCoreMmiHandlers[Index].HandlerType, + mMmCoreMmiHandlers[Index].SupervisorHandler ? "S" : "U", Status )); } @@ -547,7 +559,8 @@ MmEntryPoint ( mMmCommunicationBufferStatus.IsCommBufferValid = FALSE; mMmCommunicationBufferStatus.ReturnBufferSize = BufferSize; - mMmCommunicationBufferStatus.ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : EFI_NOT_FOUND; + // Rather than typical not_found on errors, this will bubble up the not_ready error. + mMmCommunicationBufferStatus.ReturnStatus = (Status == EFI_SUCCESS) ? EFI_SUCCESS : ((Status == EFI_NOT_READY) ? EFI_NOT_READY : EFI_NOT_FOUND); } else { // // This should be supervisor communicate channel, everything can be ring 0 buffer fine @@ -1156,12 +1169,21 @@ MmSupervisorMain ( // Register all handlers in the core table // for (Index = 0; mMmCoreMmiHandlers[Index].HandlerType != NULL; Index++) { - Status = MmiSupvHandlerRegister ( - mMmCoreMmiHandlers[Index].Handler, - mMmCoreMmiHandlers[Index].HandlerType, - &mMmCoreMmiHandlers[Index].DispatchHandle - ); - DEBUG ((DEBUG_INFO, "MmiHandlerRegister - GUID %g - Status %d\n", mMmCoreMmiHandlers[Index].HandlerType, Status)); + if (mMmCoreMmiHandlers[Index].SupervisorHandler) { + Status = MmiSupvHandlerRegister ( + mMmCoreMmiHandlers[Index].Handler, + mMmCoreMmiHandlers[Index].HandlerType, + &mMmCoreMmiHandlers[Index].DispatchHandle + ); + DEBUG ((DEBUG_INFO, "MmiSupvHandlerRegister - GUID %g - Status %d\n", mMmCoreMmiHandlers[Index].HandlerType, Status)); + } else { + Status = MmiUserHandlerRegister ( + mMmCoreMmiHandlers[Index].Handler, + mMmCoreMmiHandlers[Index].HandlerType, + &mMmCoreMmiHandlers[Index].DispatchHandle + ); + DEBUG ((DEBUG_INFO, "MmiUserHandlerRegister - GUID %g - Status %d\n", mMmCoreMmiHandlers[Index].HandlerType, Status)); + } } Status = InitializeMmSupervisorTestAgents (); diff --git a/MmSupervisorPkg/Core/MmSupervisorCore.h b/MmSupervisorPkg/Core/MmSupervisorCore.h index d18911c8..5d923cc4 100644 --- a/MmSupervisorPkg/Core/MmSupervisorCore.h +++ b/MmSupervisorPkg/Core/MmSupervisorCore.h @@ -61,6 +61,7 @@ typedef struct { EFI_GUID *HandlerType; EFI_HANDLE DispatchHandle; BOOLEAN UnRegister; + BOOLEAN SupervisorHandler; } MM_CORE_MMI_HANDLERS; // diff --git a/MmSupervisorPkg/Core/MmSupervisorCore.inf b/MmSupervisorPkg/Core/MmSupervisorCore.inf index a7923428..02acd267 100644 --- a/MmSupervisorPkg/Core/MmSupervisorCore.inf +++ b/MmSupervisorPkg/Core/MmSupervisorCore.inf @@ -236,6 +236,7 @@ gMmSupervisorRequestHandlerGuid ## SOMETIMES_CONSUMES ## GUID # SmiHandlerRegister gMmSupervisorPolicyFileGuid ## CONSUMES gMmPagingAuditMmiHandlerGuid ## SOMETIMES_CONSUMES + gEventMmDispatchGuid ## CONSUMES gEfiHobMemoryAllocModuleGuid gEfiMmPeiMmramMemoryReserveGuid diff --git a/MmSupervisorPkg/Drivers/MmPeiLaunchers/MmIplPei.c b/MmSupervisorPkg/Drivers/MmPeiLaunchers/MmIplPei.c index 58cfe993..2c369383 100644 --- a/MmSupervisorPkg/Drivers/MmPeiLaunchers/MmIplPei.c +++ b/MmSupervisorPkg/Drivers/MmPeiLaunchers/MmIplPei.c @@ -15,7 +15,6 @@ #include #include #include -#include #include // MU_CHANGE: Added MM configuration PPI #include @@ -76,29 +75,6 @@ SmmCommunicationCommunicate ( IN OUT UINTN *CommSize ); -// MU_CHANGE: MM_SUPV: Supervisor communication function prototype - -/** - Communicates with a registered handler. - - This function provides a service to send and receive messages from a registered UEFI service. - - @param[in] This The MM_SUPERVISOR_COMMUNICATION_PPI instance. - @param[in] CommBuffer A pointer to the buffer to convey into SMRAM. - @param[in] CommSize The size of the data buffer being passed in.On exit, the size of data - being returned. Zero if the handler does not wish to reply with any data. - - @retval EFI_SUCCESS The message was successfully posted. - @retval EFI_INVALID_PARAMETER The CommBuffer was NULL. -**/ -EFI_STATUS -EFIAPI -SupvCommunicationCommunicate ( - IN CONST MM_SUPERVISOR_COMMUNICATION_PPI *This, - IN OUT VOID *CommBuffer, - IN OUT UINTN *CommSize OPTIONAL - ); - /** This is the callback function on end of PEI. @@ -127,30 +103,15 @@ EFI_PEI_SMM_COMMUNICATION_PPI mSmmCommunication = { .Communicate = SmmCommunicationCommunicate }; -// MU_CHANGE: MM_SUPV: Supervisor communication PPI instance -// -// Supervisor MM Communication PPI instance -// -MM_SUPERVISOR_COMMUNICATION_PPI mMmSupvCommunication = { - .Signature = MM_SUPERVISOR_COMM_PPI_SIG, - .Version = MM_SUPERVISOR_COMM_PPI_VER, - .Communicate = SupvCommunicationCommunicate -}; - // // List of PPIs to be installed at the success of MM foundation setup // STATIC EFI_PEI_PPI_DESCRIPTOR mPeiMmIplPpiList[] = { { - EFI_PEI_PPI_DESCRIPTOR_PPI, + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), &gEfiPeiSmmCommunicationPpiGuid, &mSmmCommunication - }, - { - (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), - &gPeiMmSupervisorCommunicationPpiGuid, - &mMmSupvCommunication } }; @@ -242,54 +203,6 @@ GetMmramCacheRange ( } while (FoundAdjacentRange); } -// MU_CHANGE: MM_SUPV: MM Supervisor communication protocol, used to query MM policy, -// region unblock, driver dispatching - -/** - Communicates with a registered handler. - - This function provides a service to send and receive messages from a registered UEFI service. - - @param[in] This The MM_SUPERVISOR_COMMUNICATION_PPI instance. - @param[in, out] CommBuffer A pointer to the buffer to convey into MMRAM. - @param[in, out] CommSize The size of the data buffer being passed in. On exit, the size of data - being returned. Zero if the handler does not wish to reply with any data. - This parameter is optional and may be NULL. - - @retval EFI_SUCCESS The message was successfully posted. - @retval EFI_INVALID_PARAMETER The CommBuffer was NULL. - @retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation. - If this error is returned, the MessageLength field - in the CommBuffer header or the integer pointed by - CommSize, are updated to reflect the maximum payload - size the implementation can accommodate. - @retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter, - if not omitted, are in address range that cannot be - accessed by the MM environment. - -**/ -EFI_STATUS -EFIAPI -SupvCommunicationCommunicate ( - IN CONST MM_SUPERVISOR_COMMUNICATION_PPI *This, - IN OUT VOID *CommBuffer, - IN OUT UINTN *CommSize OPTIONAL - ) -{ - if ((This == NULL) || - (This->Signature != MM_SUPERVISOR_COMM_PPI_SIG) || - (This->Version != MM_SUPERVISOR_COMM_PPI_VER)) - { - return EFI_INVALID_PARAMETER; - } - - return SmmCommunicationCommunicateWorker ( - TRUE, - CommBuffer, - CommSize - ); -} - /** Communicates with a registered handler. @@ -358,172 +271,14 @@ EndOfPeiCallback ( return SmmIplGuidedEventNotifyWorker (&gEfiMmEndOfPeiProtocol); } -// MU_CHANGE Starts: MM_SUPV: Will immediately signal MM core to dispatch MM drivers - -/** - Invokes the MM core to dispatch drivers from inside MM environment. This - function will only be called after MM foundation is successfully set. - - @return Status of the notification. - The status code returned from this function is ignored. -**/ -EFI_STATUS -EFIAPI -MmDriverDispatchNotify ( - VOID - ) -{ - UINTN Size; - EFI_STATUS Status; - - // MU_CHANGE: MM_SUPV: Driver dispatcher command only deals with supervisor - mCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)mMmSupvCommonBuffer; - - // - // Use Guid to initialize EFI_MM_COMMUNICATE_HEADER structure - // Clear the buffer passed into the Software SMI. This buffer will return - // the status of the SMM Core Dispatcher. - // - CopyGuid (&(mCommunicateHeader->HeaderGuid), &gMmSupervisorDriverDispatchGuid); - - // - // This is actually an empty payload command, but the EFI_MM_COMMUNICATE_HEADER structure - // comes with a payload of at least one byte. So we set the MessageLength to 1 and - // the first byte to 0. - // - mCommunicateHeader->MessageLength = 1; - mCommunicateHeader->Data[0] = 0; - - // - // Generate the Software SMI and return the result - // - Size = sizeof (EFI_MM_COMMUNICATE_HEADER); - Status = SupvCommunicationCommunicate (&mMmSupvCommunication, mCommunicateHeader, &Size); - - // - // Return if there is no request to restart the MM Core Dispatcher - // - if (Status != EFI_SUCCESS) { - DEBUG ((DEBUG_ERROR, "MM Driver Dispatch failed (%r)\n", Status)); - return Status; - } - - // - // Get the status returned from the MM Core Dispatcher - // - if (Size >= sizeof (EFI_STATUS)) { - Status = *(EFI_STATUS *)mCommunicateHeader->Data; - } else { - Status = EFI_DEVICE_ERROR; - } - - return Status; -} - -// MU_CHANGE Ends: MM_SUPV - -// MU_CHANGE: Loaded Fixed Address information is unsupported -// /** -// Get the fixed loading address from image header assigned by build tool. This function only be called -// when Loading module at Fixed address feature enabled. - -// @param ImageContext Pointer to the image context structure that describes the PE/COFF -// image that needs to be examined by this function. -// @retval EFI_SUCCESS An fixed loading address is assigned to this image by build tools . -// @retval EFI_NOT_FOUND The image has no assigned fixed loading address. -// **/ -// EFI_STATUS -// GetPeCoffImageFixLoadingAssignedAddress( -// IN OUT PE_COFF_LOADER_IMAGE_CONTEXT *ImageContext -// ) -// { -// UINTN SectionHeaderOffset; -// EFI_STATUS Status; -// EFI_IMAGE_SECTION_HEADER SectionHeader; -// EFI_IMAGE_OPTIONAL_HEADER_UNION *ImgHdr; -// EFI_PHYSICAL_ADDRESS FixLoadingAddress; -// UINT16 Index; -// UINTN Size; -// UINT16 NumberOfSections; -// EFI_PHYSICAL_ADDRESS MmramBase; -// UINT64 MmCodeSize; -// UINT64 ValueInSectionHeader; -// // -// // Build tool will calculate the smm code size and then patch the PcdLoadFixAddressSmmCodePageNumber -// // -// MmCodeSize = EFI_PAGES_TO_SIZE (PcdGet32(PcdLoadFixAddressSmmCodePageNumber)); - -// FixLoadingAddress = 0; -// Status = EFI_NOT_FOUND; -// MmramBase = mLMFAConfigurationTable->SmramBase; -// // -// // Get PeHeader pointer -// // -// ImgHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((CHAR8* )ImageContext->Handle + ImageContext->PeCoffHeaderOffset); -// SectionHeaderOffset = ImageContext->PeCoffHeaderOffset + -// sizeof (UINT32) + -// sizeof (EFI_IMAGE_FILE_HEADER) + -// ImgHdr->Pe32.FileHeader.SizeOfOptionalHeader; -// NumberOfSections = ImgHdr->Pe32.FileHeader.NumberOfSections; - -// // -// // Get base address from the first section header that doesn't point to code section. -// // -// for (Index = 0; Index < NumberOfSections; Index++) { -// // -// // Read section header from file -// // -// Size = sizeof (EFI_IMAGE_SECTION_HEADER); -// Status = ImageContext->ImageRead ( -// ImageContext->Handle, -// SectionHeaderOffset, -// &Size, -// &SectionHeader -// ); -// if (EFI_ERROR (Status)) { -// return Status; -// } - -// Status = EFI_NOT_FOUND; - -// if ((SectionHeader.Characteristics & EFI_IMAGE_SCN_CNT_CODE) == 0) { -// // -// // Build tool saves the offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields in the -// // first section header that doesn't point to code section in image header. And there is an assumption that when the -// // feature is enabled, if a module is assigned a loading address by tools, PointerToRelocations & PointerToLineNumbers -// // fields should NOT be Zero, or else, these 2 fields should be set to Zero -// // -// ValueInSectionHeader = ReadUnaligned64((UINT64*)&SectionHeader.PointerToRelocations); -// if (ValueInSectionHeader != 0) { -// // -// // Found first section header that doesn't point to code section in which build tool saves the -// // offset to SMRAM base as image base in PointerToRelocations & PointerToLineNumbers fields -// // -// FixLoadingAddress = (EFI_PHYSICAL_ADDRESS)(MmramBase + (INT64)ValueInSectionHeader); - -// if (MmramBase + MmCodeSize > FixLoadingAddress && MmramBase <= FixLoadingAddress) { -// // -// // The assigned address is valid. Return the specified loading address -// // -// ImageContext->ImageAddress = FixLoadingAddress; -// Status = EFI_SUCCESS; -// } -// } -// break; -// } -// SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER); -// } -// DEBUG ((DEBUG_INFO|DEBUG_LOAD, "LOADING MODULE FIXED INFO: Loading module at fixed address %x, Status = %r \n", FixLoadingAddress, Status)); -// return Status; -// } - // MU_CHANGE Starts: The MM core address found routine is updated with PEI services /** Searches MmCore in all published firmware Volumes and loads the first instance that contains MmCore. - @param[in] Buffer Placeholder for address of MM core located by this routine. + @param[out] Buffer Placeholder for address of MM core located by this routine. + @param[out] MmCoreFileName Placeholder for the GUID of the MM core file located by this routine. @retval EFI_SUCCESS This function located MM core successfully. @retval Others Errors returned by PeiServices routines. @@ -531,7 +286,8 @@ MmDriverDispatchNotify ( **/ EFI_STATUS MmIplPeiFindMmCore ( - OUT VOID **Buffer + OUT VOID **Buffer, + OUT EFI_GUID *MmCoreFileName ) { EFI_STATUS Status; @@ -539,6 +295,10 @@ MmIplPeiFindMmCore ( EFI_PEI_FV_HANDLE VolumeHandle; EFI_PEI_FILE_HANDLE FileHandle; + if ((Buffer == NULL) || (MmCoreFileName == NULL)) { + return EFI_INVALID_PARAMETER; + } + Instance = 0; while (TRUE) { // @@ -561,17 +321,21 @@ MmIplPeiFindMmCore ( FileHandle = NULL; Status = PeiServicesFfsFindNextFile (EFI_FV_FILETYPE_MM_CORE_STANDALONE, VolumeHandle, &FileHandle); if (!EFI_ERROR (Status)) { - // - // Find MmCore FileHandle in this volume, then we skip other firmware volume and - // return the FileHandle. Search Section now. - // - Status = PeiServicesFfsFindSectionData (EFI_SECTION_PE32, FileHandle, Buffer); - if (EFI_ERROR (Status)) { - break; - } + ASSERT (FileHandle != NULL); + if (FileHandle != NULL) { + CopyGuid (MmCoreFileName, &((EFI_FFS_FILE_HEADER *)FileHandle)->Name); + DEBUG ((DEBUG_INFO, "Mm core has file name as %g\n", MmCoreFileName)); + // + // Find MmCore FileHandle in this volume, then we skip other firmware volume and + // return the FileHandle. Search Section now. + // + Status = PeiServicesFfsFindSectionData (EFI_SECTION_PE32, FileHandle, Buffer); + if (EFI_ERROR (Status)) { + break; + } - return EFI_SUCCESS; - break; + return EFI_SUCCESS; + } } // @@ -737,6 +501,7 @@ ExecuteMmCoreFromMmram ( UINTN PageCount; STANDALONE_MM_FOUNDATION_ENTRY_POINT EntryPoint; VOID *HobStart; + EFI_GUID MmCoreFileName; DEBUG ((DEBUG_INFO, "%a Enters...\n", __func__)); // @@ -744,7 +509,7 @@ ExecuteMmCoreFromMmram ( // SourceBuffer = NULL; // MU_CHANGE: The MM core address found routine is updated with PEI services - Status = MmIplPeiFindMmCore (&SourceBuffer); + Status = MmIplPeiFindMmCore (&SourceBuffer, &MmCoreFileName); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "%a Failed to find MM core file - %r...\n", __func__, Status)); goto Exit; @@ -818,7 +583,7 @@ ExecuteMmCoreFromMmram ( EntryPoint = (STANDALONE_MM_FOUNDATION_ENTRY_POINT)(UINTN)ImageContext.EntryPoint; BuildModuleHob ( - &gMmSupervisorCoreGuid, + &MmCoreFileName, ImageContext.ImageAddress, (UINT64)EFI_PAGES_TO_SIZE (PageCount), (EFI_PHYSICAL_ADDRESS)(UINTN)ImageContext.EntryPoint @@ -1105,20 +870,14 @@ MmIplPeiEntry ( IN CONST EFI_PEI_SERVICES **PeiServices ) { - EFI_STATUS Status; - UINTN Index; - UINT64 MaxSize; - UINTN Size; - UINTN MmramRangeCount; - // UINT64 MmCodeSize; - // EFI_CPU_ARCH_PROTOCOL *CpuArch; - // EFI_STATUS SetAttrStatus; - // EFI_MMRAM_DESCRIPTOR *MmramRangeSmmDriver; - // EFI_GCD_MEMORY_SPACE_DESCRIPTOR MemDesc; - EFI_MMRAM_DESCRIPTOR *MmramRanges; - // MU_CHANGE: MM_SUPV: Test supervisor communication before publishing protocol - MM_SUPERVISOR_VERSION_INFO_BUFFER VersionInfo; - MTRR_MEMORY_CACHE_TYPE CacheAttribute; + EFI_STATUS Status; + UINTN Index; + UINT64 MaxSize; + UINTN Size; + UINTN MmramRangeCount; + EFI_MMRAM_DESCRIPTOR *MmramRanges; + MTRR_MEMORY_CACHE_TYPE CacheAttribute; + EFI_MEMORY_DESCRIPTOR CommunicationRegion; Status = PeiServicesRegisterForShadow (FileHandle); @@ -1128,7 +887,7 @@ MmIplPeiEntry ( // MU_CHANGE: MM_SUPV: Initialize Comm buffer from HOBs first Status = InitializeCommunicationBufferFromHob ( - &mMmSupvCommunication.CommunicationRegion + &CommunicationRegion ); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_INFO, "%a Failed to initialize communication buffer from HOBs - %r\n", __func__, Status)); @@ -1282,67 +1041,6 @@ MmIplPeiEntry ( DEBUG ((DEBUG_ERROR, "SMM IPL could not find a large enough SMRAM region to load SMM Core\n")); } - // - // Close all SMRAM ranges - // - // MU_CHANGE: Iterate through each MMRAM for PPI instance - for (Index = 0; Index < MmramRangeCount; Index++) { - Status = mSmmAccess->Close ((EFI_PEI_SERVICES **)PeiServices, mSmmAccess, Index); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "SMM IPL failed to close SMRAM windows index %d - %r\n", Index, Status)); - ASSERT (FALSE); - return Status; - } - - // - // Print debug message that the SMRAM window is now closed. - // - DEBUG ((DEBUG_INFO, "MM IPL closed SMRAM window index %d\n", Index)); - } - - // MU_CHANGE: MM_SUPV: Locked immediately after closing instead of waiting for ready to lock event - // - // Lock the SMRAM (Note: Locking SMRAM may not be supported on all platforms) - // - for (Index = 0; Index < MmramRangeCount; Index++) { - Status = mSmmAccess->Lock ((EFI_PEI_SERVICES **)PeiServices, mSmmAccess, Index); - if (EFI_ERROR (Status)) { - // - // Print error message that the SMRAM failed to lock... - // - DEBUG ((DEBUG_ERROR, "MM IPL could not lock MMRAM (Index %d) after executing MM Core %r\n", Index, Status)); - ASSERT (FALSE); - return Status; - } - - // - // Print debug message that the SMRAM window is now closed. - // - DEBUG ((DEBUG_INFO, "MM IPL locked SMRAM window index %d\n", Index)); - } - - SECURITY_LOCK_REPORT_EVENT ("Lock MMRAM", HARDWARE_LOCK); // MSCHANGE - - // - // Print debug message that the SMRAM window is now locked. - // - DEBUG ((DEBUG_INFO, "SMM IPL locked SMRAM window\n")); - - // MU_CHANGE: MM_SUPV: We are just making sure this communication to supervisor does not fail after setup. - Status = QuerySupervisorVersion (&VersionInfo); - if (EFI_ERROR (Status)) { - return Status; - } - - // MU_CHANGE: MM_SUPV: Added a forced trigger to load all drivers in MM - // - // Trigger to dispatch MM drivers from inside MM - // - if (!EFI_ERROR (Status)) { - Status = MmDriverDispatchNotify (); - DEBUG ((DEBUG_INFO, "MM driver dispatching returned - %r\n", Status)); - } - // // If the SMM Core could not be loaded then close SMRAM window, free allocated // resources, and return an error so SMM IPL will be unloaded. diff --git a/MmSupervisorPkg/Drivers/MmPeiLaunchers/MmIplPei.inf b/MmSupervisorPkg/Drivers/MmPeiLaunchers/MmIplPei.inf index aa2b6299..11b70c17 100644 --- a/MmSupervisorPkg/Drivers/MmPeiLaunchers/MmIplPei.inf +++ b/MmSupervisorPkg/Drivers/MmPeiLaunchers/MmIplPei.inf @@ -68,7 +68,6 @@ gEfiPeiSmmCommunicationPpiGuid ## PRODUCES gEfiPeiMmAccessPpiGuid ## CONSUMES gEfiPeiMmControlPpiGuid ## CONSUMES - gPeiMmSupervisorCommunicationPpiGuid ## PRODUCES gEfiPeiLoadFilePpiGuid ## CONSUMES gEfiEndOfPeiSignalPpiGuid ## CONSUMES gEfiPeiMmConfigurationPpi ## CONSUMES # MU_CHANGE: Added MM Configuration PPI @@ -79,13 +78,11 @@ [Guids] # gLoadFixedAddressConfigurationTableGuid ## SOMETIMES_CONSUMES ## MU_CHANGE: Feature unsupported gMmCoreMmProfileGuid ## SOMETIMES_CONSUMES - gMmCommonRegionHobGuid ## PRODUCES - gMmSupervisorDriverDispatchGuid ## PRODUCES ## Invoke driver dispatcher + gMmCommonRegionHobGuid ## CONSUMES gMmSupervisorRequestHandlerGuid ## CONSUMES gEfiMmPeiMmramMemoryReserveGuid ## CONSUMES gEfiSmmSmramMemoryGuid ## CONSUMES gMmCommBufferHobGuid ## CONSUMES - gMmSupervisorCoreGuid ## CONSUMES [Pcd] # gEfiMdeModulePkgTokenSpaceGuid.PcdLoadFixAddressSmmCodePageNumber ## SOMETIMES_CONSUMES ## MU_CHANGE: Feature unsupported diff --git a/MmSupervisorPkg/Drivers/MmPeiLaunchers/MmPeiSupport.c b/MmSupervisorPkg/Drivers/MmPeiLaunchers/MmPeiSupport.c new file mode 100644 index 00000000..13507624 --- /dev/null +++ b/MmSupervisorPkg/Drivers/MmPeiLaunchers/MmPeiSupport.c @@ -0,0 +1,321 @@ +/** @file + MM IPL in PEI that produces MM related PPIs and load the MM Core into MMRAM + + Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+ Copyright (c) Microsoft Corporation. + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include // MU_CHANGE: MM_SUPV: Added MM Supervisor request data structure +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include // MU_CHANGE: BZ3398 +#include // MSCHANGE + +#include "Common/CommonHeader.h" +#include "Common/MmIplCommon.h" +#ifdef MDE_CPU_IA32 + #include "IA32/X64Loader.h" +#endif + +#define SMRAM_CAPABILITIES (EFI_MEMORY_WB | EFI_MEMORY_UC) + +// +// Function prototypes from produced PPIs +// + +/** + Communicates with a registered handler. + + This function provides a service to send and receive messages from a registered UEFI service. + + @param[in] This The EFI_PEI_SMM_COMMUNICATION_PPI instance. + @param[in] CommBuffer A pointer to the buffer to convey into SMRAM. + @param[in] CommSize The size of the data buffer being passed in.On exit, the size of data + being returned. Zero if the handler does not wish to reply with any data. + + @retval EFI_SUCCESS The message was successfully posted. + @retval EFI_INVALID_PARAMETER The CommBuffer was NULL. +**/ +EFI_STATUS +EFIAPI +SmmCommunicationCommunicate ( + IN CONST EFI_PEI_SMM_COMMUNICATION_PPI *This, + IN OUT VOID *CommBuffer, + IN OUT UINTN *CommSize + ); + +// MU_CHANGE: MM_SUPV: Supervisor communication function prototype + +/** + Communicates with a registered handler. + + This function provides a service to send and receive messages from a registered UEFI service. + + @param[in] This The MM_SUPERVISOR_COMMUNICATION_PPI instance. + @param[in] CommBuffer A pointer to the buffer to convey into SMRAM. + @param[in] CommSize The size of the data buffer being passed in.On exit, the size of data + being returned. Zero if the handler does not wish to reply with any data. + + @retval EFI_SUCCESS The message was successfully posted. + @retval EFI_INVALID_PARAMETER The CommBuffer was NULL. +**/ +EFI_STATUS +EFIAPI +SupvCommunicationCommunicate ( + IN CONST MM_SUPERVISOR_COMMUNICATION_PPI *This, + IN OUT VOID *CommBuffer, + IN OUT UINTN *CommSize OPTIONAL + ); + +// MU_CHANGE: MM_SUPV: Supervisor communication PPI instance +// +// Supervisor MM Communication PPI instance +// +MM_SUPERVISOR_COMMUNICATION_PPI mMmSupvCommunication = { + .Signature = MM_SUPERVISOR_COMM_PPI_SIG, + .Version = MM_SUPERVISOR_COMM_PPI_VER, + .Communicate = SupvCommunicationCommunicate +}; + +// +// List of PPIs to be installed at the success of MM foundation setup +// +STATIC EFI_PEI_PPI_DESCRIPTOR mPeiMmIplPpiList[] = +{ + { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gPeiMmSupervisorCommunicationPpiGuid, + &mMmSupvCommunication + } +}; + +// +// SMM IPL global variables +// +EFI_PEI_MM_CONTROL_PPI *mSmmControl; +EFI_PHYSICAL_ADDRESS mMmramCacheBase; +UINT64 mMmramCacheSize; + +// MU_CHANGE: Abstracted function implementation of MmControl->Trigger for PEI + +/** + Abstraction layer for MM Control Trigger under various environments (PEI & DXE). + The IPL driver will implement this functionality to be used by MM Communication + routine. + + @retval Others See definition of EFI_MM_ACTIVATE. + + **/ +EFI_STATUS +InternalMmControlTrigger ( + VOID + ) +{ + return mSmmControl->Trigger ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), mSmmControl, NULL, NULL, FALSE, 0); +} + +// MU_CHANGE: MM_SUPV: MM Supervisor communication protocol, used to query MM policy, +// region unblock, driver dispatching + +/** + Communicates with a registered handler. + + This function provides a service to send and receive messages from a registered UEFI service. + + @param[in] This The MM_SUPERVISOR_COMMUNICATION_PPI instance. + @param[in, out] CommBuffer A pointer to the buffer to convey into MMRAM. + @param[in, out] CommSize The size of the data buffer being passed in. On exit, the size of data + being returned. Zero if the handler does not wish to reply with any data. + This parameter is optional and may be NULL. + + @retval EFI_SUCCESS The message was successfully posted. + @retval EFI_INVALID_PARAMETER The CommBuffer was NULL. + @retval EFI_BAD_BUFFER_SIZE The buffer is too large for the MM implementation. + If this error is returned, the MessageLength field + in the CommBuffer header or the integer pointed by + CommSize, are updated to reflect the maximum payload + size the implementation can accommodate. + @retval EFI_ACCESS_DENIED The CommunicateBuffer parameter or CommSize parameter, + if not omitted, are in address range that cannot be + accessed by the MM environment. + +**/ +EFI_STATUS +EFIAPI +SupvCommunicationCommunicate ( + IN CONST MM_SUPERVISOR_COMMUNICATION_PPI *This, + IN OUT VOID *CommBuffer, + IN OUT UINTN *CommSize OPTIONAL + ) +{ + if ((This == NULL) || + (This->Signature != MM_SUPERVISOR_COMM_PPI_SIG) || + (This->Version != MM_SUPERVISOR_COMM_PPI_VER)) + { + return EFI_INVALID_PARAMETER; + } + + return SmmCommunicationCommunicateWorker ( + TRUE, + CommBuffer, + CommSize + ); +} + +// MU_CHANGE Starts: MM_SUPV: Will immediately signal MM core to dispatch MM drivers + +/** + Invokes the MM core to dispatch drivers from inside MM environment. This + function will only be called after MM foundation is successfully set. + + @return Status of the notification. + The status code returned from this function is ignored. +**/ +EFI_STATUS +EFIAPI +MmDriverDispatchNotify ( + VOID + ) +{ + UINTN Size; + EFI_STATUS Status; + + // MU_CHANGE: MM_SUPV: Driver dispatcher command only deals with supervisor + mCommunicateHeader = (EFI_MM_COMMUNICATE_HEADER *)mMmSupvCommonBuffer; + + // + // This is actually an empty payload command, but the EFI_MM_COMMUNICATE_HEADER structure + // comes with a payload of at least one byte. So we set the MessageLength to 1 and + // the first byte to 0. + // + CopyGuid (&(mCommunicateHeader->HeaderGuid), &gMmSupervisorDriverDispatchGuid); + mCommunicateHeader->MessageLength = 1; + mCommunicateHeader->Data[0] = 0; + + // + // Generate the Software SMI and return the result + // + Size = sizeof (EFI_MM_COMMUNICATE_HEADER); + Status = SupvCommunicationCommunicate (&mMmSupvCommunication, mCommunicateHeader, &Size); + + // + // Return if there is no request to restart the MM Core Dispatcher + // + if (Status != EFI_SUCCESS) { + DEBUG ((DEBUG_ERROR, "MM Driver Dispatch failed (%r)\n", Status)); + return Status; + } + + // + // Get the status returned from the MM Core Dispatcher + // + if (Size >= sizeof (EFI_STATUS)) { + Status = *(EFI_STATUS *)mCommunicateHeader->Data; + } else { + Status = EFI_DEVICE_ERROR; + } + + return Status; +} + +// MU_CHANGE Ends: MM_SUPV + +/** + The Entry Point for PEI MM IPL + + Load MM Core into MMRAM, register MM Core entry point for SMIs, install + MM Communication PPI (both for user and supervisor), and register for the + critical events required to coordinate between PEI and MM environments. + + @param[in] FileHandle Not used. + @param[in] PeiServices General purpose services available to every PEIM. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval Other Some error occurred when executing this entry point. + +**/ +EFI_STATUS +EFIAPI +MmPeiSupportEntry ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + MM_SUPERVISOR_VERSION_INFO_BUFFER VersionInfo; + + Status = PeiServicesRegisterForShadow (FileHandle); + + if (!EFI_ERROR (Status)) { + return EFI_SUCCESS; + } + + // MU_CHANGE: MM_SUPV: Initialize Comm buffer from HOBs first + Status = InitializeCommunicationBufferFromHob ( + &mMmSupvCommunication.CommunicationRegion + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a Failed to initialize communication buffer from HOBs - %r\n", __func__, Status)); + return Status; + } + + // + // Get SMM Control PPI + // + Status = (*PeiServices)->LocatePpi ( + PeiServices, + &gEfiPeiMmControlPpiGuid, + 0, + NULL, + (VOID **)&mSmmControl + ); + ASSERT_EFI_ERROR (Status); + + // MU_CHANGE: MM_SUPV: We are just making sure this communication to supervisor does not fail after setup. + Status = QuerySupervisorVersion (&VersionInfo); + if (EFI_ERROR (Status)) { + return Status; + } + + // MU_CHANGE: MM_SUPV: Added a forced trigger to load all drivers in MM + // + // Trigger to dispatch MM drivers from inside MM + // + if (!EFI_ERROR (Status)) { + Status = MmDriverDispatchNotify (); + DEBUG ((DEBUG_INFO, "MM driver dispatching returned - %r\n", Status)); + } + + // + // Install MM Communication and Supervisor MM Communication PPI + // + Status = (*PeiServices)->InstallPpi (PeiServices, mPeiMmIplPpiList); + ASSERT_EFI_ERROR (Status); + + return EFI_SUCCESS; +} diff --git a/MmSupervisorPkg/Drivers/MmPeiLaunchers/MmPeiSupport.inf b/MmSupervisorPkg/Drivers/MmPeiLaunchers/MmPeiSupport.inf new file mode 100644 index 00000000..a2297c2b --- /dev/null +++ b/MmSupervisorPkg/Drivers/MmPeiLaunchers/MmPeiSupport.inf @@ -0,0 +1,63 @@ +## @file +# This module provides the MM supervisor communication PPI service. +# +# Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.
+# Copyright (c) Microsoft Corporation. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = MmPeiSupport + FILE_GUID = B525E664-18E1-4EB3-806E-078F75058454 + MODULE_TYPE = PEIM + VERSION_STRING = 1.0 + PI_SPECIFICATION_VERSION = 0x0001000A + ENTRY_POINT = MmPeiSupportEntry + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + MmPeiSupport.c + Common/MmIplCommon.c + Common/MmIplCommon.h + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + StandaloneMmPkg/StandaloneMmPkg.dec + UefiCpuPkg/UefiCpuPkg.dec + MmSupervisorPkg/MmSupervisorPkg.dec + +[LibraryClasses] + PeimEntryPoint + BaseLib + BaseMemoryLib + PeCoffLib + MemoryAllocationLib + DebugLib + PcdLib + ReportStatusCodeLib + PeiServicesLib #MU_CHANGE: Add PeiServicesLib to INF + HobLib #MU_CHANGE: Add HobLib to INF + PanicLib #MU_CHANGE: Add PanicLib to INF + +[Ppis] + gEfiPeiMmControlPpiGuid ## CONSUMES + gPeiMmSupervisorCommunicationPpiGuid ## PRODUCES + +[Guids] + gMmCommonRegionHobGuid ## CONSUMES + gMmSupervisorDriverDispatchGuid ## PRODUCES ## Invoke driver dispatcher + gMmSupervisorRequestHandlerGuid ## CONSUMES + gMmCommBufferHobGuid ## CONSUMES + gMmSupervisorCoreGuid ## CONSUMES + +[Depex] + gEfiPeiSmmCommunicationPpiGuid diff --git a/MmSupervisorPkg/MmSupervisorPkg.dsc b/MmSupervisorPkg/MmSupervisorPkg.dsc index 89c729c6..caaf7568 100644 --- a/MmSupervisorPkg/MmSupervisorPkg.dsc +++ b/MmSupervisorPkg/MmSupervisorPkg.dsc @@ -55,7 +55,7 @@ TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf MmSupervisorCoreInitLib|MmSupervisorPkg/Library/BaseMmSupervisorCoreInitLibNull/BaseMmSupervisorCoreInitLibNull.inf -[LibraryClasses.IA32] +[LibraryClasses.IA32.PEIM, LibraryClasses.X64.PEIM] HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf @@ -128,9 +128,9 @@ [Components] MmSupervisorPkg/Library/BaseMmSupervisorCoreInitLibNull/BaseMmSupervisorCoreInitLibNull.inf MmSupervisorPkg/Library/DxeMmSupervisorVersionPublicationLib/DxeMmSupervisorVersionPublicationLib.inf - -[Components.IA32] MmSupervisorPkg/Library/MmSupervisorUnblockMemoryLib/MmSupervisorUnblockMemoryLibPei.inf + + MmSupervisorPkg/Drivers/MmPeiLaunchers/MmPeiSupport.inf MmSupervisorPkg/Drivers/MmCommunicationBuffer/MmCommunicationBufferPei.inf MmSupervisorPkg/Drivers/MmPeiLaunchers/MmIplPei.inf