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

@@ -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.