OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
PavpProvision.c
Go to the documentation of this file.
1
15#include <PiDxe.h>
17#include <Protocol/PciRootBridgeIo.h>
18#include <Library/UefiBootServicesTableLib.h>
19#include <Library/UefiRuntimeServicesTableLib.h>
20#include <Library/BaseLib.h>
21#include <Library/BaseMemoryLib.h>
22#include <Library/MemoryAllocationLib.h>
23#include <Library/PciLib.h>
24#include <Library/HobLib.h>
25#include <Library/IoLib.h>
26#include <Guid/GlobalVariable.h>
27
29#include <Library/OcHeciLib.h>
30#include <Library/OcMiscLib.h>
31
32#include <Protocol/Heci.h>
33#include <Protocol/Heci2.h>
37
38#define FORCE_PROVISIONING 1
39#define SA_MC_BUS 0x00
40#define R_SA_PAVPC (0x58)
41
42#define MmPciAddress(Segment, Bus, Device, Function, Register) \
43 ((UINTN) (PciRead32 (PCI_LIB_ADDRESS (0,0,0,0x60)) & 0xFC000000) + \
44 (UINTN) (Bus << 20) + (UINTN) (Device << 15) + (UINTN) \
45 (Function << 12) + (UINTN) (Register))
46
47#define MmPci32(Segment, Bus, Device, Function, Register) \
48 *((volatile UINT32 *) MmPciAddress (Segment, Bus, Device, Function, Register))
49
52
53extern UINT8 gDefaultAppleEpidCertificate[];
55
56extern UINT8 gDefaultAppleGroupPublicKeys[];
58
59STATIC
60EFI_STATUS
62 IN EFI_GUID *FvNameGuid,
63 OUT VOID **Buffer,
64 OUT UINTN *BufferSize
65 )
66{
67 UINTN Index;
68 EFI_STATUS Status;
69 UINT32 AuthenticationStatus;
70 EFI_FIRMWARE_VOLUME_PROTOCOL *FirmwareVolumeInterface;
71 UINTN NumOfHandles;
72 EFI_HANDLE *HandleBuffer;
73
74 Status = gBS->LocateHandleBuffer (
75 ByProtocol,
77 NULL,
78 &NumOfHandles,
79 &HandleBuffer
80 );
81
82 if (!EFI_ERROR (Status)) {
83 for (Index = 0; Index < NumOfHandles; ++Index) {
84 Status = gBS->HandleProtocol (
85 HandleBuffer[Index],
87 (VOID **)&FirmwareVolumeInterface
88 );
89
90 if (EFI_ERROR (Status)) {
91 gBS->FreePool (HandleBuffer);
92 return Status;
93 }
94
95 *Buffer = NULL;
96 *BufferSize = 0;
97
98 Status = FirmwareVolumeInterface->ReadSection (
99 FirmwareVolumeInterface,
100 FvNameGuid,
102 0,
103 Buffer,
104 BufferSize,
105 &AuthenticationStatus
106 );
107
108 if (!EFI_ERROR (Status)) {
109 gBS->FreePool (HandleBuffer);
110 return Status;
111 }
112 }
113
114 gBS->FreePool (HandleBuffer);
115 Status = EFI_NOT_FOUND;
116 }
117
118 //
119 // Implement fallback for our firmware.
120 //
121 if (EFI_ERROR (Status)) {
122 DEBUG ((DEBUG_INFO, "OCPAVP: No %g in firmware, using default - %r\n", FvNameGuid, Status));
123
124 if (CompareGuid (&gAppleEpidCertificateFileGuid, FvNameGuid)) {
127 } else if (CompareGuid (&gAppleEpidGroupPublicKeysFileGuid, FvNameGuid)) {
130 } else {
131 *Buffer = NULL;
132 }
133
134 if (*Buffer != NULL) {
135 Status = EFI_SUCCESS;
136 } else {
137 Status = EFI_NOT_FOUND;
138 }
139 }
140
141 return Status;
142}
143
144STATIC
145EFI_STATUS
147 OUT EPID_CERTIFICATE **EpidCertificate,
148 OUT EPID_GROUP_PUBLIC_KEY **EpidGroupPublicKeys,
149 OUT UINT32 *EpidGroupPublicKeysCount
150 )
151{
152 EFI_STATUS Status;
153 UINTN EpidCertificateSize;
154 UINTN EpidGroupPublicKeysSize;
155
156 Status = ReadProvisioningDataFile (
158 (VOID **)EpidCertificate,
159 &EpidCertificateSize
160 );
161
162 if (EFI_ERROR (Status)) {
163 return Status;
164 }
165
166 Status = ReadProvisioningDataFile (
168 (VOID **)EpidGroupPublicKeys,
169 &EpidGroupPublicKeysSize
170 );
171
172 if (EFI_ERROR (Status)) {
173 gBS->FreePool (*EpidGroupPublicKeys);
174 return Status;
175 }
176
177 if ( (EpidCertificateSize == EPID_CERTIFICATE_SIZE)
178 && (EpidGroupPublicKeysSize % EPID_GROUP_PUBLIC_KEY_SIZE == 0))
179 {
180 *EpidGroupPublicKeysCount = (UINT32)(EpidGroupPublicKeysSize / EPID_GROUP_PUBLIC_KEY_SIZE);
181 return EFI_SUCCESS;
182 }
183
184 gBS->FreePool (*EpidCertificate);
185 gBS->FreePool (*EpidGroupPublicKeys);
186 return EFI_VOLUME_CORRUPTED;
187}
188
189STATIC
190VOID
192 IN CHAR16 *Variable,
193 IN UINT32 Value
194 )
195{
196 #ifdef FORCE_PROVISIONING
197 (VOID)Variable;
198 (VOID)Value;
199 #else
200 gRT->SetVariable (
201 Variable,
203 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
204 sizeof (Value),
205 &Value
206 );
207 #endif
208}
209
210STATIC
211EFI_STATUS
213 IN EPID_GROUP_PUBLIC_KEY *PublicKeys,
214 IN UINTN PublicKeyCount,
215 IN UINT32 Key,
216 OUT EPID_GROUP_PUBLIC_KEY **ChosenPublicKey
217 )
218{
219 EFI_STATUS Status;
220 UINT32 Index;
221
222 Status = EFI_NOT_FOUND;
223
224 for (Index = 0; Index < PublicKeyCount; ++Index) {
225 if (SwapBytes32 (PublicKeys[Index].GroupId) == Key) {
226 *ChosenPublicKey = &PublicKeys[Index];
227 return EFI_SUCCESS;
228 }
229 }
230
231 return Status;
232}
233
234STATIC
235BOOLEAN
237 VOID
238 )
239{
240 EFI_STATUS Status;
241 UINT32 Value;
242 EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Interface;
243
244 Status = gBS->LocateProtocol (
246 NULL,
247 (VOID **)&Interface
248 );
249
250 if (EFI_ERROR (Status)) {
251 DEBUG ((DEBUG_INFO, "OCPAVP: Failed to find PCI root protocol - %r\n", Status));
252 return FALSE;
253 }
254
255 //
256 // IGPU_DEVICE_ID = 0x2
257 // PCI_VENDOR_ID_OFFSET = 0x0
258 // (IGPU_DEVICE_ID << 16U | PCI_VENDOR_ID_OFFSET)
259 // See EFI_PCI_ADDRESS
260 //
261 Status = Interface->Pci.Read (
262 Interface,
263 EfiPciWidthUint32,
264 0x20000,
265 1,
266 &Value
267 );
268
269 if (EFI_ERROR (Status)) {
270 DEBUG ((DEBUG_INFO, "OCPAVP: Failed to read from IGPU device - %r\n", Status));
271 return FALSE;
272 }
273
274 DEBUG ((DEBUG_INFO, "OCPAVP: IGPU is %X\n", Value));
275
276 return Value != 0xFFFFFFFFU;
277}
278
279STATIC
280EFI_STATUS
282 VOID
283 )
284{
285 EFI_STATUS Status;
286 UINT32 Data;
287 UINTN DataSize;
288
289 if (IsBuiltinGpuAvailable ()) {
290 DataSize = sizeof (Data);
291
292 Status = gRT->GetVariable (
295 NULL,
296 &DataSize,
297 &Data
298 );
299
300 #ifdef FORCE_PROVISIONING
301 Data = 0;
302 #endif
303
304 if (EFI_ERROR (Status) || (Data != 1)) {
305 return EFI_SUCCESS;
306 }
307 }
308
309 return EFI_NOT_FOUND;
310}
311
312STATIC
313EFI_STATUS
315 VOID
316 )
317{
318 EFI_STATUS Status;
319 UINT32 Data;
320 UINTN DataSize;
322
323 #if 0
325 #else
326 Hob = NULL;
327 #endif
328
329 DEBUG ((DEBUG_INFO, "OCPAVP: HOB for FPF is %p\n", Hob));
330
331 if ((Hob == NULL) || Hob->ShouldProvision) {
332 DataSize = sizeof (Data);
333 Status = gRT->GetVariable (
336 NULL,
337 &DataSize,
338 &Data
339 );
340
341 if (EFI_ERROR (Status) || (Data != 1)) {
342 return EFI_SUCCESS;
343 }
344
345 return EFI_NOT_FOUND;
346 }
347
348 return EFI_UNSUPPORTED;
349}
350
351EFI_STATUS
353 VOID
354 )
355{
356 EFI_STATUS Status;
357 UINTN Index;
358 HECI_CLIENT_PROPERTIES Properties;
359 EPID_GROUP_PUBLIC_KEY *EpidGroupPublicKeys;
360 EPID_CERTIFICATE *EpidCertificate;
361 UINT32 EpidGroupPublicKeysCount;
362 UINT32 EpidStatus;
363 UINT32 EpidGroupId;
364 EPID_GROUP_PUBLIC_KEY *EpidCurrentGroupPublicKey;
365 BOOLEAN SetVar;
366
367 Status = NeedsEpidProvisioning ();
368 DEBUG ((DEBUG_INFO, "OCPAVP: Needs provisioning EPID - %r\n", Status));
369 if (EFI_ERROR (Status)) {
370 return EFI_ALREADY_STARTED;
371 }
372
373 Status = HeciLocateProtocol ();
374 DEBUG ((DEBUG_INFO, "OCPAVP: HECI protocol lookup - %r\n", Status));
375 if (EFI_ERROR (Status)) {
376 return Status;
377 }
378
379 Status = ReadProvisioningData (
380 &EpidCertificate,
381 &EpidGroupPublicKeys,
382 &EpidGroupPublicKeysCount
383 );
384 DEBUG ((DEBUG_INFO, "OCPAVP: Provisioning data - %r\n", Status));
385 if (EFI_ERROR (Status)) {
386 return Status;
387 }
388
389 //
390 // Get Management Engine proccesses namespace.
391 // Each App like PAVP or FPF have unique identifier represented as GUID.
392 //
394 DEBUG ((DEBUG_INFO, "OCPAVP: Got %d clients - %r\n", mMeClientActiveCount, Status));
395 if (EFI_ERROR (Status)) {
396 return Status;
397 }
398
399 Status = EFI_NOT_FOUND;
400
401 for (Index = 0; Index < mMeClientActiveCount; ++Index) {
402 Status = HeciGetClientProperties (
403 mMeClientMap[Index],
404 &Properties
405 );
406
407 DEBUG ((
408 DEBUG_INFO,
409 "OCPAVP: Client %u has %g protocol - %r\n",
410 (UINT32)Index,
411 Properties.ProtocolName,
412 Status
413 ));
414
415 if (EFI_ERROR (Status)) {
416 break;
417 }
418
419 if (CompareGuid (&Properties.ProtocolName, &gMePavpProtocolGuid)) {
420 break;
421 }
422 }
423
424 if (!EFI_ERROR (Status) && (Index != mMeClientActiveCount)) {
425 DEBUG ((DEBUG_INFO, "OCPAVP: Found application at %u\n", (UINT32)Index));
426
427 Status = HeciConnectToClient (mMeClientMap[Index]);
428 if (!EFI_ERROR (Status)) {
429 EpidStatus = EpidGroupId = 0;
430 Status = HeciPavpRequestProvisioning (&EpidStatus, &EpidGroupId);
431
432 DEBUG ((DEBUG_INFO, "OCPAVP: Got EPID status %X and group id %x - %r\n", EpidStatus, EpidGroupId, Status));
433 }
434
435 if (!EFI_ERROR (Status)) {
436 if (EpidStatus == EPID_STATUS_PROVISIONED) {
438 } else if (EpidStatus == EPID_STATUS_CAN_PROVISION) {
439 Status = GetGroupPublicKey (
440 EpidGroupPublicKeys,
441 EpidGroupPublicKeysCount,
442 EpidGroupId,
443 &EpidCurrentGroupPublicKey
444 );
445
446 DEBUG ((DEBUG_INFO, "OCPAVP: Got EPID group public key - %r\n", Status));
447
448 if (!EFI_ERROR (Status)) {
449 Status = HeciPavpPerformProvisioning (EpidCertificate, EpidCurrentGroupPublicKey, &SetVar);
450 DEBUG ((DEBUG_INFO, "OCPAVP: Sent EPID certificate - %r / %d\n", Status, SetVar));
451 if (!EFI_ERROR (Status) || SetVar) {
453 }
454 }
455 }
456 }
457
459 } else {
460 DEBUG ((DEBUG_INFO, "OCPAVP: No EPID application found\n"));
461
462 if (Index == mMeClientActiveCount) {
463 //
464 // Do not retry provisioning on incompatible firmware.
465 // TODO: Do we really need this?
466 //
468 Status = EFI_NOT_FOUND;
469 }
470 }
471
472 gBS->FreePool (EpidCertificate);
473 gBS->FreePool (EpidGroupPublicKeys);
474
475 return Status;
476}
477
478EFI_STATUS
480 VOID
481 )
482{
483 EFI_STATUS Status;
484 UINTN Index;
485 HECI_CLIENT_PROPERTIES Properties;
486 UINT32 FpfStatus;
487
488 Status = NeedsFpfProvisioning ();
489 DEBUG ((DEBUG_INFO, "OCPAVP: Needs provisioning FPF - %r\n", Status));
490 if (EFI_ERROR (Status)) {
491 return EFI_ALREADY_STARTED;
492 }
493
494 Status = HeciLocateProtocol ();
495 DEBUG ((DEBUG_INFO, "OCPAVP: HECI protocol lookup - %r\n", Status));
496 if (EFI_ERROR (Status)) {
497 return Status;
498 }
499
500 //
501 // Get Management Engine proccesses namespace.
502 // Each App like PAVP or FPF have unique identifier represented as GUID.
503 //
505 DEBUG ((DEBUG_INFO, "OCPAVP: Got %d clients - %r\n", mMeClientActiveCount, Status));
506 if (EFI_ERROR (Status)) {
507 return Status;
508 }
509
510 Status = EFI_NOT_FOUND;
511
512 for (Index = 0; Index < mMeClientActiveCount; ++Index) {
513 Status = HeciGetClientProperties (
514 mMeClientMap[Index],
515 &Properties
516 );
517
518 DEBUG ((
519 DEBUG_INFO,
520 "OCPAVP: Client %u has %g protocol - %r\n",
521 (UINT32)Index,
522 Properties.ProtocolName,
523 Status
524 ));
525
526 if (EFI_ERROR (Status)) {
527 break;
528 }
529
530 if (CompareGuid (&Properties.ProtocolName, &gMeFpfProtocolGuid)) {
531 break;
532 }
533 }
534
535 if (!EFI_ERROR (Status) && (Index != mMeClientActiveCount)) {
536 DEBUG ((DEBUG_INFO, "OCPAVP: Found application at %u\n", (UINT32)Index));
537
538 Status = HeciConnectToClient (mMeClientMap[Index]);
539
540 //
541 // I *think* FPF provisioning locks fuses from further update.
542 // For this reason we do not want it.
543 //
544 if (!EFI_ERROR (Status)) {
545 Status = HeciFpfGetStatus (&FpfStatus);
546 DEBUG ((DEBUG_INFO, "OCPAVP: Got FPF status %u - %r\n", FpfStatus, Status));
547 if (!EFI_ERROR (Status)) {
548 if (FpfStatus == 250) {
549 Status = HeciFpfProvision (&FpfStatus);
550 DEBUG ((DEBUG_INFO, "OCPAVP: Got FPF provisioning %u - %r\n", FpfStatus, Status));
551 if (!EFI_ERROR (Status) && (FpfStatus == 0)) {
553 } else {
554 Status = EFI_DEVICE_ERROR;
555 }
556 } else {
557 Status = EFI_DEVICE_ERROR;
558 }
559 }
560
562 }
563 } else {
564 DEBUG ((DEBUG_INFO, "OCPAVP: No FPF application found\n"));
565
566 if (Index == mMeClientActiveCount) {
567 //
568 // Do not retry provisioning on incompatible firmware.
569 // TODO: Do we really need this?
570 //
572 Status = EFI_NOT_FOUND;
573 }
574 }
575
576 return Status;
577}
578
579STATIC
580VOID
582 VOID
583 )
584{
585 EFI_STATUS Status;
586
587 DEBUG ((DEBUG_INFO, "OCPAVP: Checking PAVPC register...\n"));
588
589 UINT32 PAVPC = MmPci32 (0, SA_MC_BUS, 0, 0, R_SA_PAVPC);
590
591 DEBUG ((DEBUG_INFO, "OCPAVP: Current PAVPC is %X\n", PAVPC));
592
593 if ((PAVPC & BIT2) == 0) {
594 MmPci32 (0, SA_MC_BUS, 0, 0, R_SA_PAVPC) = (PAVPC & (~BIT2)) | BIT4;
595 PAVPC = MmPci32 (0, SA_MC_BUS, 0, 0, R_SA_PAVPC);
596 DEBUG ((DEBUG_INFO, "OCPAVP: New PAVPC is %X\n", PAVPC));
597 }
598
599 DEBUG ((DEBUG_INFO, "OCPAVP: Starting EPID provisioning\n"));
600
601 Status = OcPerformEpidProvisioning ();
602
603 DEBUG ((DEBUG_INFO, "OCPAVP: Done EPID provisioning - %r\n", Status));
604
605 #if 0
606 DEBUG ((DEBUG_INFO, "OCPAVP: Starting FPF provisioning\n"));
607
608 Status = OcPerformFpfProvisioning ();
609
610 DEBUG ((DEBUG_INFO, "OCPAVP: Done FPF provisioning - %r\n", Status));
611 #endif
612}
613
614EFI_STATUS
615EFIAPI
617 IN EFI_HANDLE ImageHandle,
618 IN EFI_SYSTEM_TABLE *SystemTable
619 )
620{
622
623 gBS->Stall (SECONDS_TO_MICROSECONDS (3));
624
625 return EFI_SUCCESS;
626}
#define APPLE_EPID_PROVISIONED_VARIABLE_NAME
#define APPLE_FPF_PROVISIONED_VARIABLE_NAME
EFI_GUID gAppleFpfConfigurationHobGuid
EFI_GUID gAppleEpidCertificateFileGuid
EFI_GUID gAppleEpidGroupPublicKeysFileGuid
#define EFI_SECTION_RAW
EFI_GUID gEfiFirmwareVolumeProtocolGuid
STATIC EFI_STATUS SetVar(UINTN Line, CHAR8 *Token, BOOLEAN IsIndented, BOOLEAN ContainsVars)
Definition GrubCfg.c:345
EFI_GUID gMeFpfProtocolGuid
#define EPID_STATUS_PROVISIONED
#define EPID_CERTIFICATE_SIZE
EFI_GUID gMePavpProtocolGuid
#define EPID_GROUP_PUBLIC_KEY_SIZE
#define EPID_STATUS_CAN_PROVISION
#define HBM_ME_CLIENT_MAX
Definition HeciMsg.h:135
EFI_BOOT_SERVICES * gBS
EFI_STATUS HeciDisconnectFromClients(VOID)
Definition OcHeciLib.c:414
EFI_STATUS HeciPavpPerformProvisioning(IN EPID_CERTIFICATE *EpidCertificate, IN EPID_GROUP_PUBLIC_KEY *EpidGroupPublicKey, OUT BOOLEAN *SetVar OPTIONAL)
Definition OcHeciLib.c:494
EFI_STATUS HeciPavpRequestProvisioning(OUT UINT32 *EpidStatus, OUT UINT32 *EpidGroupId)
Definition OcHeciLib.c:466
EFI_STATUS HeciLocateProtocol(VOID)
Definition OcHeciLib.c:92
EFI_STATUS HeciConnectToClient(IN UINT8 Address)
Definition OcHeciLib.c:334
EFI_STATUS HeciFpfGetStatus(OUT UINT32 *FpfStatus)
Definition OcHeciLib.c:557
EFI_STATUS HeciFpfProvision(OUT UINT32 *FpfStatus)
Definition OcHeciLib.c:580
EFI_STATUS HeciGetClientMap(OUT UINT8 *ClientMap, OUT UINT8 *ClientActiveCount)
Definition OcHeciLib.c:245
EFI_STATUS HeciGetClientProperties(IN UINT8 Address, OUT HECI_CLIENT_PROPERTIES *Properties)
Definition OcHeciLib.c:298
#define SECONDS_TO_MICROSECONDS(x)
Definition OcMiscLib.h:30
OC_TYPING_BUFFER_ENTRY Buffer[OC_TYPING_BUFFER_SIZE]
Definition OcTypingLib.h:42
STATIC BOOLEAN IsBuiltinGpuAvailable(VOID)
STATIC EFI_STATUS NeedsEpidProvisioning(VOID)
STATIC UINT8 mMeClientActiveCount
UINTN gDefaultAppleEpidCertificateSize
EFI_STATUS EFIAPI UefiMain(IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable)
STATIC VOID SetProvisioningVariable(IN CHAR16 *Variable, IN UINT32 Value)
STATIC UINT8 mMeClientMap[HBM_ME_CLIENT_MAX]
STATIC EFI_STATUS ReadProvisioningDataFile(IN EFI_GUID *FvNameGuid, OUT VOID **Buffer, OUT UINTN *BufferSize)
STATIC EFI_STATUS GetGroupPublicKey(IN EPID_GROUP_PUBLIC_KEY *PublicKeys, IN UINTN PublicKeyCount, IN UINT32 Key, OUT EPID_GROUP_PUBLIC_KEY **ChosenPublicKey)
EFI_STATUS OcPerformEpidProvisioning(VOID)
UINT8 gDefaultAppleEpidCertificate[]
#define R_SA_PAVPC
STATIC VOID OcPerformProvisioning(VOID)
STATIC EFI_STATUS ReadProvisioningData(OUT EPID_CERTIFICATE **EpidCertificate, OUT EPID_GROUP_PUBLIC_KEY **EpidGroupPublicKeys, OUT UINT32 *EpidGroupPublicKeysCount)
EFI_STATUS OcPerformFpfProvisioning(VOID)
STATIC EFI_STATUS NeedsFpfProvisioning(VOID)
UINTN gDefaultAppleGroupPublicKeysSize
#define MmPci32(Segment, Bus, Device, Function, Register)
#define SA_MC_BUS
UINT8 gDefaultAppleGroupPublicKeys[]
BOOLEAN EFIAPI CompareGuid(IN CONST GUID *Guid1, IN CONST GUID *Guid2)
EFI_RUNTIME_SERVICES * gRT
EFI_GUID gEfiPciRootBridgeIoProtocolGuid
EFI_GUID gEfiGlobalVariableGuid
VOID *EFIAPI GetFirstGuidHob(IN CONST EFI_GUID *Guid)
Definition UserMisc.c:671