MdeModulePkg/Pci: Add DeviceSecurity support.

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2303

Whenever a PCI device is discovered, PCI bus calls the
EDKII_DEVICE_SECURITY_PROTOCOL to authenticate it.
If the function returns success, the PCI bus allocates
the resource and installs the PCI_IO for the device.
If the function returns fail, the PCI bus skips the device.

It is similar to EFI_SECURITY_ARCH_PROTOCOL, which
is used to verify an EFI image.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Yun Lou <yun.lou@intel.com>
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Ray Ni <ray.ni@intel.com>
This commit is contained in:
Jiewen Yao 2019-09-29 16:37:14 +08:00
parent 985e0a6de7
commit 995d8b8568
5 changed files with 94 additions and 4 deletions

View File

@ -8,7 +8,7 @@
PCI Root Bridges. So it means platform needs install PCI Root Bridge IO protocol for each
PCI Root Bus and install PCI Host Bridge Resource Allocation Protocol.
Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@ -37,7 +37,7 @@ UINT64 gAllZero = 0;
EFI_PCI_PLATFORM_PROTOCOL *gPciPlatformProtocol;
EFI_PCI_OVERRIDE_PROTOCOL *gPciOverrideProtocol;
EDKII_IOMMU_PROTOCOL *mIoMmuProtocol;
EDKII_DEVICE_SECURITY_PROTOCOL *mDeviceSecurityProtocol;
GLOBAL_REMOVE_IF_UNREFERENCED EFI_PCI_HOTPLUG_REQUEST_PROTOCOL mPciHotPlugRequest = {
PciHotPlugRequestNotify
@ -293,6 +293,14 @@ PciBusDriverBindingStart (
);
}
if (mDeviceSecurityProtocol == NULL) {
gBS->LocateProtocol (
&gEdkiiDeviceSecurityProtocolGuid,
NULL,
(VOID **) &mDeviceSecurityProtocol
);
}
if (PcdGetBool (PcdPciDisableBusEnumeration)) {
gFullEnumeration = FALSE;
} else {

View File

@ -27,6 +27,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include <Protocol/PciOverride.h>
#include <Protocol/PciEnumerationComplete.h>
#include <Protocol/IoMmu.h>
#include <Protocol/DeviceSecurity.h>
#include <Library/DebugLib.h>
#include <Library/UefiDriverEntryPoint.h>

View File

@ -2,7 +2,7 @@
# The PCI bus driver will probe all PCI devices and allocate MMIO and IO space for these devices.
# Please use PCD feature flag PcdPciBusHotplugDeviceSupport to enable hot plug supporting.
#
# Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
# Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@ -90,6 +90,8 @@
gEfiIncompatiblePciDeviceSupportProtocolGuid ## SOMETIMES_CONSUMES
gEfiLoadFile2ProtocolGuid ## SOMETIMES_PRODUCES
gEdkiiIoMmuProtocolGuid ## SOMETIMES_CONSUMES
gEdkiiDeviceSecurityProtocolGuid ## SOMETIMES_CONSUMES
gEdkiiDeviceIdentifierTypePciGuid ## SOMETIMES_CONSUMES
gEfiLoadedImageDevicePathProtocolGuid ## CONSUMES
[FeaturePcd]

View File

@ -10,6 +10,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
#include "PciBus.h"
extern CHAR16 *mBarTypeStr[];
extern EDKII_DEVICE_SECURITY_PROTOCOL *mDeviceSecurityProtocol;
#define OLD_ALIGN 0xFFFFFFFFFFFFFFFFULL
#define EVEN_ALIGN 0xFFFFFFFFFFFFFFFEULL
@ -2070,6 +2071,67 @@ InitializeP2C (
PciIo->Pci.Write (PciIo, EfiPciIoWidthUint8, 0x3C, 1, &gAllZero);
}
/*
Authenticate the PCI device by using DeviceSecurityProtocol.
@param PciIoDevice PCI device.
@retval EFI_SUCCESS The device passes the authentication.
@return not EFI_SUCCESS The device failes the authentication or
unexpected error happen during authentication.
*/
EFI_STATUS
AuthenticatePciDevice (
IN PCI_IO_DEVICE *PciIoDevice
)
{
EDKII_DEVICE_IDENTIFIER DeviceIdentifier;
EFI_STATUS Status;
if (mDeviceSecurityProtocol != NULL) {
//
// Prepare the parameter
//
DeviceIdentifier.Version = EDKII_DEVICE_IDENTIFIER_REVISION;
CopyGuid (&DeviceIdentifier.DeviceType, &gEdkiiDeviceIdentifierTypePciGuid);
DeviceIdentifier.DeviceHandle = NULL;
Status = gBS->InstallMultipleProtocolInterfaces (
&DeviceIdentifier.DeviceHandle,
&gEfiDevicePathProtocolGuid,
PciIoDevice->DevicePath,
&gEdkiiDeviceIdentifierTypePciGuid,
&PciIoDevice->PciIo,
NULL
);
if (EFI_ERROR(Status)) {
return Status;
}
//
// Do DeviceAuthentication
//
Status = mDeviceSecurityProtocol->DeviceAuthenticate (mDeviceSecurityProtocol, &DeviceIdentifier);
//
// Always uninstall, because they are only for Authentication.
// No need to check return Status.
//
gBS->UninstallMultipleProtocolInterfaces (
DeviceIdentifier.DeviceHandle,
&gEfiDevicePathProtocolGuid,
PciIoDevice->DevicePath,
&gEdkiiDeviceIdentifierTypePciGuid,
&PciIoDevice->PciIo,
NULL
);
return Status;
}
//
// Device Security Protocol is not found, just return success
//
return EFI_SUCCESS;
}
/**
Create and initialize general PCI I/O device instance for
PCI device/bridge device/hotplug bridge device.
@ -2156,6 +2218,21 @@ CreatePciIoDevice (
PciIoDevice->IsPciExp = TRUE;
}
//
// Now we can do the authentication check for the device.
//
Status = AuthenticatePciDevice (PciIoDevice);
//
// If authentication fails, skip this device.
//
if (EFI_ERROR(Status)) {
if (PciIoDevice->DevicePath != NULL) {
FreePool (PciIoDevice->DevicePath);
}
FreePool (PciIoDevice);
return NULL;
}
if (PcdGetBool (PcdAriSupport)) {
//
// Check if the device is an ARI device.

View File

@ -1054,7 +1054,9 @@ PciScanBus (
&PciDevice
);
ASSERT (!EFI_ERROR (Status));
if (EFI_ERROR (Status)) {
continue;
}
PciAddress = EFI_PCI_ADDRESS (StartBusNumber, Device, Func, 0);