diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalAhciMode.c b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalAhciMode.c index 0dc3490a36..33f77bd8a2 100644 --- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalAhciMode.c +++ b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalAhciMode.c @@ -1022,6 +1022,34 @@ GetAhciBarSize ( return Size; } +/** + This function check if the memory region is in GCD MMIO region. + + @param Addr The memory region start address to be checked. + @param Size The memory region length to be checked. + + @retval TRUE This memory region is in GCD MMIO region. + @retval FALSE This memory region is not in GCD MMIO region. +**/ +BOOLEAN +EFIAPI +OpalIsValidMmioSpace ( + IN EFI_PHYSICAL_ADDRESS Addr, + IN UINTN Size + ) +{ + UINTN Index; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Desc; + + for (Index = 0; Index < mNumberOfDescriptors; Index ++) { + Desc = &mGcdMemSpace[Index]; + if ((Desc->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) && (Addr >= Desc->BaseAddress) && ((Addr + Size) <= (Desc->BaseAddress + Desc->Length))) { + return TRUE; + } + } + + return FALSE; +} /** Get AHCI mode base address registers' Value. @@ -1055,7 +1083,7 @@ GetAhciBaseAddress ( // // Check if the AHCI Bar region is in SMRAM to avoid malicious attack by modifying MMIO Bar to point to SMRAM. // - if (!SmmIsBufferOutsideSmmValid ((EFI_PHYSICAL_ADDRESS)mAhciBar, Size)) { + if (!OpalIsValidMmioSpace ((EFI_PHYSICAL_ADDRESS)mAhciBar, Size)) { return EFI_UNSUPPORTED; } diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.c b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.c index 57d10a17b7..b7e2d552d5 100644 --- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.c +++ b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.c @@ -61,6 +61,9 @@ VOID *mBuffer = NULL; // DMA can not read/write Data to smram, s // NVME NVME_CONTEXT mNvmeContext; +EFI_GCD_MEMORY_SPACE_DESCRIPTOR *mGcdMemSpace = NULL; +UINTN mNumberOfDescriptors = 0; + /** Add new bridge node or nvme device info to the device list. @@ -592,6 +595,44 @@ S3SleepEntryCallBack ( return Status; } +/** + OpalPassword Notification for SMM EndOfDxe protocol. + + @param[in] Protocol Points to the protocol's unique identifier. + @param[in] Interface Points to the interface instance. + @param[in] Handle The handle on which the interface was installed. + + @retval EFI_SUCCESS Notification runs successfully. +**/ +EFI_STATUS +EFIAPI +OpalPasswordEndOfDxeNotification ( + IN CONST EFI_GUID *Protocol, + IN VOID *Interface, + IN EFI_HANDLE Handle + ) +{ + UINTN NumberOfDescriptors; + EFI_GCD_MEMORY_SPACE_DESCRIPTOR *MemSpaceMap; + EFI_STATUS Status; + + Status = gDS->GetMemorySpaceMap (&NumberOfDescriptors, &MemSpaceMap); + if (EFI_ERROR (Status)) { + return Status; + } + + mGcdMemSpace = AllocateCopyPool (NumberOfDescriptors * sizeof (EFI_GCD_MEMORY_SPACE_DESCRIPTOR), MemSpaceMap); + if (EFI_ERROR (Status)) { + gBS->FreePool (MemSpaceMap); + return Status; + } + + mNumberOfDescriptors = NumberOfDescriptors; + gBS->FreePool (MemSpaceMap); + + return EFI_SUCCESS; +} + /** Main entry for this driver. @@ -618,6 +659,7 @@ OpalPasswordSmmInit ( EFI_SMM_VARIABLE_PROTOCOL *SmmVariable; OPAL_EXTRA_INFO_VAR OpalExtraInfo; UINTN DataSize; + EFI_EVENT EndOfDxeEvent; EFI_PHYSICAL_ADDRESS Address; mBuffer = NULL; @@ -726,6 +768,15 @@ OpalPasswordSmmInit ( // mSwSmiValue = (UINT8) Context.SwSmiInputValue; + // + // Create event to record GCD descriptors at end of dxe for judging AHCI/NVMe PCI Bar + // is in MMIO space to avoid attack. + // + Status = gSmst->SmmRegisterProtocolNotify (&gEfiSmmEndOfDxeProtocolGuid, OpalPasswordEndOfDxeNotification, &EndOfDxeEvent); + if (EFI_ERROR (Status)) { + DEBUG((DEBUG_ERROR, "OpalPasswordSmm: Register SmmEndOfDxe fail, Status: %r\n", Status)); + goto EXIT; + } Status = gSmst->SmmLocateProtocol (&gEfiSmmVariableProtocolGuid, NULL, (VOID**)&SmmVariable); if (!EFI_ERROR (Status)) { DataSize = sizeof (OPAL_EXTRA_INFO_VAR); diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.h b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.h index f365136918..ab31a6bfe7 100644 --- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.h +++ b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.h @@ -25,6 +25,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include #include #include @@ -43,8 +44,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include -#include - #include #include @@ -71,6 +70,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. extern VOID *mBuffer; +extern EFI_GCD_MEMORY_SPACE_DESCRIPTOR *mGcdMemSpace; +extern UINTN mNumberOfDescriptors; #pragma pack(1) typedef struct { diff --git a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf index dae51ece02..cab0fd5656 100644 --- a/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf +++ b/SecurityPkg/Tcg/Opal/OpalPasswordSmm/OpalPasswordSmm.inf @@ -58,7 +58,6 @@ DxeServicesTableLib DevicePathLib OpalPasswordSupportLib - SmmMemLib [Guids] gOpalExtraInfoVariableGuid ## CONSUMES ## GUID @@ -70,6 +69,7 @@ gEfiSmmSxDispatch2ProtocolGuid ## CONSUMES gEfiSmmVariableProtocolGuid ## CONSUMES gEfiStorageSecurityCommandProtocolGuid ## CONSUMES + gEfiSmmEndOfDxeProtocolGuid ## CONSUMES [Depex] gEfiSmmSwDispatch2ProtocolGuid AND