Слияние кода завершено, страница обновится автоматически
/** @file
Provision EPID key.
Copyright (c) 2019, vit9696. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#include <PiDxe.h>
#include <Protocol/FirmwareVolume.h>
#include <Protocol/PciRootBridgeIo.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiRuntimeServicesTableLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/PciLib.h>
#include <Library/HobLib.h>
#include <Library/IoLib.h>
#include <Guid/GlobalVariable.h>
#include <Library/OcDebugLogLib.h>
#include <Library/OcHeciLib.h>
#include <Library/OcMiscLib.h>
#include <Protocol/Heci.h>
#include <Protocol/Heci2.h>
#include <IndustryStandard/AppleProvisioning.h>
#include <IndustryStandard/HeciMsg.h>
#include <IndustryStandard/HeciClientMsg.h>
#define FORCE_PROVISIONING 1
#define SA_MC_BUS 0x00
#define R_SA_PAVPC (0x58)
#define MmPciAddress(Segment, Bus, Device, Function, Register) \
((UINTN) (PciRead32 (PCI_LIB_ADDRESS (0,0,0,0x60)) & 0xFC000000) + \
(UINTN) (Bus << 20) + (UINTN) (Device << 15) + (UINTN) \
(Function << 12) + (UINTN) (Register))
#define MmPci32(Segment, Bus, Device, Function, Register) \
*((volatile UINT32 *) MmPciAddress (Segment, Bus, Device, Function, Register))
STATIC UINT8 mMeClientMap[HBM_ME_CLIENT_MAX];
STATIC UINT8 mMeClientActiveCount;
extern UINT8 gDefaultAppleEpidCertificate[];
extern UINTN gDefaultAppleEpidCertificateSize;
extern UINT8 gDefaultAppleGroupPublicKeys[];
extern UINTN gDefaultAppleGroupPublicKeysSize;
STATIC
EFI_STATUS
ReadProvisioningDataFile (
IN EFI_GUID *FvNameGuid,
OUT VOID **Buffer,
OUT UINTN *BufferSize
)
{
UINTN Index;
EFI_STATUS Status;
UINT32 AuthenticationStatus;
EFI_FIRMWARE_VOLUME_PROTOCOL *FirmwareVolumeInterface;
UINTN NumOfHandles;
EFI_HANDLE *HandleBuffer;
Status = gBS->LocateHandleBuffer (
ByProtocol,
&gEfiFirmwareVolumeProtocolGuid,
NULL,
&NumOfHandles,
&HandleBuffer
);
if (!EFI_ERROR (Status)) {
for (Index = 0; Index < NumOfHandles; ++Index) {
Status = gBS->HandleProtocol (
HandleBuffer[Index],
&gEfiFirmwareVolumeProtocolGuid,
(VOID **) &FirmwareVolumeInterface
);
if (EFI_ERROR (Status)) {
gBS->FreePool (HandleBuffer);
return Status;
}
*Buffer = NULL;
*BufferSize = 0;
Status = FirmwareVolumeInterface->ReadSection (
FirmwareVolumeInterface,
FvNameGuid,
EFI_SECTION_RAW,
0,
Buffer,
BufferSize,
&AuthenticationStatus
);
if (!EFI_ERROR (Status)) {
gBS->FreePool (HandleBuffer);
return Status;
}
}
gBS->FreePool (HandleBuffer);
Status = EFI_NOT_FOUND;
}
//
// Implement fallback for our firmware.
//
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCPAVP: No %g in firmware, using default - %r\n", FvNameGuid, Status));
if (CompareGuid (&gAppleEpidCertificateFileGuid, FvNameGuid)) {
*Buffer = AllocateCopyPool (gDefaultAppleEpidCertificateSize, gDefaultAppleEpidCertificate);
*BufferSize = gDefaultAppleEpidCertificateSize;
} else if (CompareGuid (&gAppleEpidGroupPublicKeysFileGuid, FvNameGuid)) {
*Buffer = AllocateCopyPool (gDefaultAppleGroupPublicKeysSize, gDefaultAppleGroupPublicKeys);
*BufferSize = gDefaultAppleGroupPublicKeysSize;
} else {
*Buffer = NULL;
}
if (*Buffer != NULL) {
Status = EFI_SUCCESS;
} else {
Status = EFI_NOT_FOUND;
}
}
return Status;
}
STATIC
EFI_STATUS
ReadProvisioningData (
OUT EPID_CERTIFICATE **EpidCertificate,
OUT EPID_GROUP_PUBLIC_KEY **EpidGroupPublicKeys,
OUT UINT32 *EpidGroupPublicKeysCount
)
{
EFI_STATUS Status;
UINTN EpidCertificateSize;
UINTN EpidGroupPublicKeysSize;
Status = ReadProvisioningDataFile (
&gAppleEpidCertificateFileGuid,
(VOID **) EpidCertificate,
&EpidCertificateSize
);
if (EFI_ERROR (Status)) {
return Status;
}
Status = ReadProvisioningDataFile (
&gAppleEpidGroupPublicKeysFileGuid,
(VOID **) EpidGroupPublicKeys,
&EpidGroupPublicKeysSize
);
if (EFI_ERROR (Status)) {
gBS->FreePool (*EpidGroupPublicKeys);
return Status;
}
if (EpidCertificateSize == EPID_CERTIFICATE_SIZE
&& EpidGroupPublicKeysSize % EPID_GROUP_PUBLIC_KEY_SIZE == 0) {
*EpidGroupPublicKeysCount = (UINT32) (EpidGroupPublicKeysSize / EPID_GROUP_PUBLIC_KEY_SIZE);
return EFI_SUCCESS;
}
gBS->FreePool (*EpidCertificate);
gBS->FreePool (*EpidGroupPublicKeys);
return EFI_VOLUME_CORRUPTED;
}
STATIC
VOID
SetProvisioningVariable (
IN CHAR16 *Variable,
IN UINT32 Value
)
{
#ifdef FORCE_PROVISIONING
(VOID) Variable;
(VOID) Value;
#else
gRT->SetVariable (
Variable,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
sizeof (Value),
&Value
);
#endif
}
STATIC
EFI_STATUS
GetGroupPublicKey (
IN EPID_GROUP_PUBLIC_KEY *PublicKeys,
IN UINTN PublicKeyCount,
IN UINT32 Key,
OUT EPID_GROUP_PUBLIC_KEY **ChosenPublicKey
)
{
EFI_STATUS Status;
UINT32 Index;
Status = EFI_NOT_FOUND;
for (Index = 0; Index < PublicKeyCount; ++Index) {
if (SwapBytes32 (PublicKeys[Index].GroupId) == Key) {
*ChosenPublicKey = &PublicKeys[Index];
return EFI_SUCCESS;
}
}
return Status;
}
STATIC
BOOLEAN
IsBuiltinGpuAvailable (
VOID
)
{
EFI_STATUS Status;
UINT32 Value;
EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Interface;
Status = gBS->LocateProtocol (
&gEfiPciRootBridgeIoProtocolGuid,
NULL,
(VOID **) &Interface
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCPAVP: Failed to find PCI root protocol - %r\n", Status));
return FALSE;
}
//
// IGPU_DEVICE_ID = 0x2
// PCI_VENDOR_ID_OFFSET = 0x0
// (IGPU_DEVICE_ID << 16U | PCI_VENDOR_ID_OFFSET)
// See EFI_PCI_ADDRESS
//
Status = Interface->Pci.Read (
Interface,
EfiPciWidthUint32,
0x20000,
1,
&Value
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "OCPAVP: Failed to read from IGPU device - %r\n", Status));
return FALSE;
}
DEBUG ((DEBUG_INFO, "OCPAVP: IGPU is %X\n", Value));
return Value != 0xFFFFFFFFU;
}
STATIC
EFI_STATUS
NeedsEpidProvisioning (
VOID
)
{
EFI_STATUS Status;
UINT32 Data;
UINTN DataSize;
if (IsBuiltinGpuAvailable()) {
DataSize = sizeof (Data);
Status = gRT->GetVariable (
APPLE_EPID_PROVISIONED_VARIABLE_NAME,
&gEfiGlobalVariableGuid,
NULL,
&DataSize,
&Data
);
#ifdef FORCE_PROVISIONING
Data = 0;
#endif
if (EFI_ERROR (Status) || Data != 1) {
return EFI_SUCCESS;
}
}
return EFI_NOT_FOUND;
}
STATIC
EFI_STATUS
NeedsFpfProvisioning (
VOID
)
{
EFI_STATUS Status;
UINT32 Data;
UINTN DataSize;
APPLE_FPF_CONFIGURATION_HOB *Hob;
#if 0
Hob = GetFirstGuidHob (&gAppleFpfConfigurationHobGuid);
#else
Hob = NULL;
#endif
DEBUG ((DEBUG_INFO, "OCPAVP: HOB for FPF is %p\n", Hob));
if (Hob == NULL || Hob->ShouldProvision) {
DataSize = sizeof (Data);
Status = gRT->GetVariable (
APPLE_FPF_PROVISIONED_VARIABLE_NAME,
&gEfiGlobalVariableGuid,
NULL,
&DataSize,
&Data
);
if (EFI_ERROR (Status) || Data != 1) {
return EFI_SUCCESS;
}
return EFI_NOT_FOUND;
}
return EFI_UNSUPPORTED;
}
EFI_STATUS
OcPerformEpidProvisioning (
VOID
)
{
EFI_STATUS Status;
UINTN Index;
HECI_CLIENT_PROPERTIES Properties;
EPID_GROUP_PUBLIC_KEY *EpidGroupPublicKeys;
EPID_CERTIFICATE *EpidCertificate;
UINT32 EpidGroupPublicKeysCount;
UINT32 EpidStatus;
UINT32 EpidGroupId;
EPID_GROUP_PUBLIC_KEY *EpidCurrentGroupPublicKey;
BOOLEAN SetVar;
Status = NeedsEpidProvisioning ();
DEBUG ((DEBUG_INFO, "OCPAVP: Needs provisioning EPID - %r\n", Status));
if (EFI_ERROR (Status)) {
return EFI_ALREADY_STARTED;
}
Status = HeciLocateProtocol ();
DEBUG ((DEBUG_INFO, "OCPAVP: HECI protocol lookup - %r\n", Status));
if (EFI_ERROR (Status)) {
return Status;
}
Status = ReadProvisioningData (
&EpidCertificate,
&EpidGroupPublicKeys,
&EpidGroupPublicKeysCount
);
DEBUG ((DEBUG_INFO, "OCPAVP: Provisioning data - %r\n", Status));
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get Management Engine proccesses namespace.
// Each App like PAVP or FPF have unique identifier represented as GUID.
//
Status = HeciGetClientMap (mMeClientMap, &mMeClientActiveCount);
DEBUG ((DEBUG_INFO, "OCPAVP: Got %d clients - %r\n", mMeClientActiveCount, Status));
if (EFI_ERROR (Status)) {
return Status;
}
Status = EFI_NOT_FOUND;
for (Index = 0; Index < mMeClientActiveCount; ++Index) {
Status = HeciGetClientProperties (
mMeClientMap[Index],
&Properties
);
DEBUG ((
DEBUG_INFO,
"OCPAVP: Client %u has %g protocol - %r\n",
(UINT32) Index,
Properties.ProtocolName,
Status
));
if (EFI_ERROR (Status)) {
break;
}
if (CompareGuid (&Properties.ProtocolName, &gMePavpProtocolGuid)) {
break;
}
}
if (!EFI_ERROR (Status) && Index != mMeClientActiveCount) {
DEBUG ((DEBUG_INFO, "OCPAVP: Found application at %u\n", (UINT32) Index));
Status = HeciConnectToClient (mMeClientMap[Index]);
if (!EFI_ERROR (Status)) {
EpidStatus = EpidGroupId = 0;
Status = HeciPavpRequestProvisioning (&EpidStatus, &EpidGroupId);
DEBUG ((DEBUG_INFO, "OCPAVP: Got EPID status %X and group id %x - %r\n", EpidStatus, EpidGroupId, Status));
}
if (!EFI_ERROR (Status)) {
if (EpidStatus == EPID_STATUS_PROVISIONED) {
SetProvisioningVariable (APPLE_EPID_PROVISIONED_VARIABLE_NAME, 1);
} else if (EpidStatus == EPID_STATUS_CAN_PROVISION) {
Status = GetGroupPublicKey (
EpidGroupPublicKeys,
EpidGroupPublicKeysCount,
EpidGroupId,
&EpidCurrentGroupPublicKey
);
DEBUG ((DEBUG_INFO, "OCPAVP: Got EPID group public key - %r\n", Status));
if (!EFI_ERROR (Status)) {
Status = HeciPavpPerformProvisioning (EpidCertificate, EpidCurrentGroupPublicKey, &SetVar);
DEBUG ((DEBUG_INFO, "OCPAVP: Sent EPID certificate - %r / %d\n", Status, SetVar));
if (!EFI_ERROR (Status) || SetVar) {
SetProvisioningVariable (APPLE_EPID_PROVISIONED_VARIABLE_NAME, 1);
}
}
}
}
HeciDisconnectFromClients ();
} else {
DEBUG ((DEBUG_INFO, "OCPAVP: No EPID application found\n"));
if (Index == mMeClientActiveCount) {
//
// Do not retry provisioning on incompatible firmware.
// TODO: Do we really need this?
//
SetProvisioningVariable (APPLE_EPID_PROVISIONED_VARIABLE_NAME, 1);
Status = EFI_NOT_FOUND;
}
}
gBS->FreePool (EpidCertificate);
gBS->FreePool (EpidGroupPublicKeys);
return Status;
}
EFI_STATUS
OcPerformFpfProvisioning (
VOID
)
{
EFI_STATUS Status;
UINTN Index;
HECI_CLIENT_PROPERTIES Properties;
UINT32 FpfStatus;
Status = NeedsFpfProvisioning ();
DEBUG ((DEBUG_INFO, "OCPAVP: Needs provisioning FPF - %r\n", Status));
if (EFI_ERROR (Status)) {
return EFI_ALREADY_STARTED;
}
Status = HeciLocateProtocol ();
DEBUG ((DEBUG_INFO, "OCPAVP: HECI protocol lookup - %r\n", Status));
if (EFI_ERROR (Status)) {
return Status;
}
//
// Get Management Engine proccesses namespace.
// Each App like PAVP or FPF have unique identifier represented as GUID.
//
Status = HeciGetClientMap (mMeClientMap, &mMeClientActiveCount);
DEBUG ((DEBUG_INFO, "OCPAVP: Got %d clients - %r\n", mMeClientActiveCount, Status));
if (EFI_ERROR (Status)) {
return Status;
}
Status = EFI_NOT_FOUND;
for (Index = 0; Index < mMeClientActiveCount; ++Index) {
Status = HeciGetClientProperties (
mMeClientMap[Index],
&Properties
);
DEBUG ((
DEBUG_INFO,
"OCPAVP: Client %u has %g protocol - %r\n",
(UINT32) Index,
Properties.ProtocolName,
Status
));
if (EFI_ERROR (Status)) {
break;
}
if (CompareGuid (&Properties.ProtocolName, &gMeFpfProtocolGuid)) {
break;
}
}
if (!EFI_ERROR (Status) && Index != mMeClientActiveCount) {
DEBUG ((DEBUG_INFO, "OCPAVP: Found application at %u\n", (UINT32) Index));
Status = HeciConnectToClient (mMeClientMap[Index]);
//
// I *think* FPF provisioning locks fuses from further update.
// For this reason we do not want it.
//
if (!EFI_ERROR (Status)) {
Status = HeciFpfGetStatus (&FpfStatus);
DEBUG ((DEBUG_INFO, "OCPAVP: Got FPF status %u - %r\n", FpfStatus, Status));
if (!EFI_ERROR (Status)) {
if (FpfStatus == 250) {
Status = HeciFpfProvision (&FpfStatus);
DEBUG ((DEBUG_INFO, "OCPAVP: Got FPF provisioning %u - %r\n", FpfStatus, Status));
if (!EFI_ERROR (Status) && FpfStatus == 0) {
SetProvisioningVariable (APPLE_FPF_PROVISIONED_VARIABLE_NAME, 1);
} else {
Status = EFI_DEVICE_ERROR;
}
} else {
Status = EFI_DEVICE_ERROR;
}
}
HeciDisconnectFromClients ();
}
} else {
DEBUG ((DEBUG_INFO, "OCPAVP: No FPF application found\n"));
if (Index == mMeClientActiveCount) {
//
// Do not retry provisioning on incompatible firmware.
// TODO: Do we really need this?
//
SetProvisioningVariable (APPLE_FPF_PROVISIONED_VARIABLE_NAME, 1);
Status = EFI_NOT_FOUND;
}
}
return Status;
}
STATIC
VOID
OcPerformProvisioning (
VOID
)
{
EFI_STATUS Status;
DEBUG ((DEBUG_INFO, "OCPAVP: Checking PAVPC register...\n"));
UINT32 PAVPC = MmPci32 (0, SA_MC_BUS, 0, 0, R_SA_PAVPC);
DEBUG ((DEBUG_INFO, "OCPAVP: Current PAVPC is %X\n", PAVPC));
if ((PAVPC & BIT2) == 0) {
MmPci32 (0, SA_MC_BUS, 0, 0, R_SA_PAVPC) = (PAVPC & (~BIT2)) | BIT4;
PAVPC = MmPci32 (0, SA_MC_BUS, 0, 0, R_SA_PAVPC);
DEBUG ((DEBUG_INFO, "OCPAVP: New PAVPC is %X\n", PAVPC));
}
DEBUG ((DEBUG_INFO, "OCPAVP: Starting EPID provisioning\n"));
Status = OcPerformEpidProvisioning ();
DEBUG ((DEBUG_INFO, "OCPAVP: Done EPID provisioning - %r\n", Status));
#if 0
DEBUG ((DEBUG_INFO, "OCPAVP: Starting FPF provisioning\n"));
Status = OcPerformFpfProvisioning ();
DEBUG ((DEBUG_INFO, "OCPAVP: Done FPF provisioning - %r\n", Status));
#endif
}
EFI_STATUS
EFIAPI
UefiMain (
IN EFI_HANDLE ImageHandle,
IN EFI_SYSTEM_TABLE *SystemTable
)
{
OcPerformProvisioning ();
gBS->Stall (SECONDS_TO_MICROSECONDS (3));
return EFI_SUCCESS;
}
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )