OpenCore  1.0.4
OpenCore Bootloader
Loading...
Searching...
No Matches
OcHeciLib.c
Go to the documentation of this file.
1
9#include <PiDxe.h>
10
11#include <Library/BaseMemoryLib.h>
12#include <Library/OcHeciLib.h>
14#include <Library/OcMiscLib.h>
15#include <Library/UefiBootServicesTableLib.h>
16
17#include <Protocol/Heci.h>
18#include <Protocol/Heci2.h>
22
26
29STATIC BOOLEAN mSendingHeciCommand;
31
32EFI_STATUS
34 IN UINT32 Blocking,
35 IN UINT32 *MessageBody,
36 IN OUT UINT32 *Length
37 )
38{
39 if (mHeci != NULL) {
40 return mHeci->ReadMsg (
41 Blocking,
42 MessageBody,
43 Length
44 );
45 }
46
47 if (mHeci2 != NULL) {
48 return mHeci2->ReadMsg (
50 Blocking,
51 MessageBody,
52 Length
53 );
54 }
55
56 DEBUG ((DEBUG_INFO, "OCME: No ME protocol loaded, cannot read message\n"));
57 return EFI_NOT_FOUND;
58}
59
60EFI_STATUS
62 IN UINT32 *Message,
63 IN UINT32 Length,
64 IN UINT8 HostAddress,
65 IN UINT8 MEAddress
66 )
67{
68 if (mHeci != NULL) {
69 return mHeci->SendMsg (
70 Message,
71 Length,
72 HostAddress,
73 MEAddress
74 );
75 }
76
77 if (mHeci2 != NULL) {
78 return mHeci2->SendMsg (
80 Message,
81 Length,
82 HostAddress,
83 MEAddress
84 );
85 }
86
87 DEBUG ((DEBUG_INFO, "OCME: No ME protocol loaded, cannot send message\n"));
88 return EFI_NOT_FOUND;
89}
90
91EFI_STATUS
93 VOID
94 )
95{
96 EFI_STATUS Status;
97
98 if ((mHeci != NULL) || (mHeci2 != NULL)) {
99 return EFI_SUCCESS;
100 }
101
102 Status = gBS->LocateProtocol (
104 NULL,
105 (VOID **)&mHeci
106 );
107
108 if (EFI_ERROR (Status)) {
109 DEBUG ((DEBUG_INFO, "OCME: Falling back to HECI 2 protocol - %r\n", Status));
110
111 //
112 // Ensure we don't have both set
113 //
114 mHeci = NULL;
115
116 Status = gBS->LocateProtocol (
118 NULL,
119 (VOID **)&mHeci2
120 );
121 }
122
123 if (EFI_ERROR (Status)) {
124 DEBUG ((DEBUG_INFO, "OCME: Failed to find any HECI protocol - %r\n", Status));
125 }
126
127 return Status;
128}
129
130VOID
132 VOID
133 )
134{
135 EFI_STATUS Status;
136 UINT32 Size;
138
140 ZeroMem (&Command, sizeof (Command));
141 Size = sizeof (Command);
142 Status = HeciReadMessage (
143 BLOCKING,
144 (UINT32 *)&Command,
145 &Size
146 );
147
148 if (!EFI_ERROR (Status) && (Command.Command.Fields.Command == FLOW_CONTROL)) {
150 }
151 }
152}
153
154EFI_STATUS
156 OUT VOID *MessageData,
157 IN UINT32 ResponseSize
158 )
159{
160 EFI_STATUS Status;
162
163 Status = EFI_NOT_READY;
164
165 STATIC_ASSERT (sizeof (HBM_FLOW_CONTROL) == 8, "Invalid ME command size");
166
168 ZeroMem (MessageData, ResponseSize);
169
170 //
171 // Note, this was reworked to make more sense.
172 // https://github.com/osy86/OpenCorePkg/commit/8f7188d41876109aec2fe3a721f69daf979dd268.diff
173 //
175 ZeroMem (&Command, sizeof (Command));
176 Command.Command.Fields.Command = FLOW_CONTROL;
178 Command.HostAddress = HBM_CLIENT_ADDRESS;
179
180 Status = HeciSendMessage (
181 (UINT32 *)&Command,
182 sizeof (Command),
185 );
186
187 if (!EFI_ERROR (Status)) {
189 }
190 }
191
192 Status = HeciReadMessage (
193 BLOCKING,
194 MessageData,
195 &ResponseSize
196 );
197
198 if (!EFI_ERROR (Status)) {
200 }
201 }
202
203 return Status;
204}
205
206EFI_STATUS
208 IN OUT VOID *MessageData,
209 IN UINT32 RequestSize,
210 IN UINT32 ResponseSize
211 )
212{
213 HECI_BUS_MESSAGE *Message;
215 EFI_STATUS Status;
216
217 mSendingHeciCommand = TRUE;
218
219 Message = (HECI_BUS_MESSAGE *)MessageData;
220 Command = Message->Command;
221
222 Status = HeciSendMessage (
223 MessageData,
224 RequestSize,
227 );
228
229 if (!EFI_ERROR (Status)) {
230 Status = HeciGetResponse (MessageData, ResponseSize);
231
232 if ( !EFI_ERROR (Status)
233 && (Command.Fields.Command != Message->Command.Fields.Command))
234 {
235 Status = EFI_PROTOCOL_ERROR;
236 }
237 }
238
239 mSendingHeciCommand = FALSE;
240
241 return Status;
242}
243
244EFI_STATUS
246 OUT UINT8 *ClientMap,
247 OUT UINT8 *ClientActiveCount
248 )
249{
250 EFI_STATUS Status;
252 UINTN Index;
253 UINTN Index2;
254 UINT8 *ValidAddressesPtr;
255 UINT32 ValidAddresses;
256
257 *ClientActiveCount = 0;
258
259 Status = HeciLocateProtocol ();
260 if (EFI_ERROR (Status)) {
261 return Status;
262 }
263
264 STATIC_ASSERT (sizeof (Command.Request) == 4, "Invalid ME command size");
265 STATIC_ASSERT (sizeof (Command.Response) == 36, "Invalid ME command size");
266
267 ZeroMem (&Command, sizeof (Command));
268 Command.Request.Command.Fields.Command = HOST_ENUMERATION_REQUEST;
269
271 &Command,
272 sizeof (Command.Request),
273 sizeof (Command.Response)
274 );
275
276 if (EFI_ERROR (Status)) {
277 return Status;
278 }
279
280 ValidAddressesPtr = &Command.Response.ValidAddresses[0];
281 for (Index = 0; Index < HBM_ME_CLIENT_MAX; Index += OC_CHAR_BIT) {
282 ValidAddresses = *ValidAddressesPtr;
283
284 for (Index2 = 0; Index2 < OC_CHAR_BIT; Index2++) {
285 if ((ValidAddresses & (1U << Index2)) != 0) {
286 ClientMap[*ClientActiveCount] = (UINT8)(Index + Index2);
287 ++(*ClientActiveCount);
288 }
289 }
290
291 ++ValidAddressesPtr;
292 }
293
294 return Status;
295}
296
297EFI_STATUS
299 IN UINT8 Address,
300 OUT HECI_CLIENT_PROPERTIES *Properties
301 )
302{
303 EFI_STATUS Status;
305
306 Status = HeciLocateProtocol ();
307 if (EFI_ERROR (Status)) {
308 return Status;
309 }
310
311 STATIC_ASSERT (sizeof (Command.Request) == 4, "Invalid ME command size");
312 STATIC_ASSERT (sizeof (Command.Response) == 28, "Invalid ME command size");
313
314 ZeroMem (&Command, sizeof (Command));
315 Command.Request.Command.Fields.Command = HOST_CLIENT_PROPERTIES_REQUEST;
316 Command.Request.Address = Address;
317
319 &Command,
320 sizeof (Command.Request),
321 sizeof (Command.Response)
322 );
323
324 CopyMem (
325 Properties,
326 &Command.Response.ClientProperties,
327 sizeof (*Properties)
328 );
329
330 return Status;
331}
332
333EFI_STATUS
335 IN UINT8 Address
336 )
337{
338 EFI_STATUS Status;
340
341 Status = HeciLocateProtocol ();
342 if (EFI_ERROR (Status)) {
343 return Status;
344 }
345
346 ZeroMem (&Command, sizeof (Command));
347 STATIC_ASSERT (sizeof (Command.Request) == 4, "Invalid ME command size");
348
349 Command.Request.Command.Fields.Command = CLIENT_CONNECT_REQUEST;
350 Command.Request.MeAddress = Address;
351 Command.Request.HostAddress = HBM_CLIENT_ADDRESS;
352
354 &Command,
355 sizeof (Command.Request),
356 sizeof (Command.Response)
357 );
358
359 DEBUG ((DEBUG_INFO, "OCME: Connect to client %X code %d - %r\n", Address, Command.Response.Status, Status));
360
361 if (EFI_ERROR (Status)) {
362 return Status;
363 }
364
365 switch (Command.Response.Status) {
367 return EFI_NOT_FOUND;
369 return EFI_ALREADY_STARTED;
371 return EFI_OUT_OF_RESOURCES;
373 return EFI_INVALID_PARAMETER;
374 default:
378 mCurrentMeClientAddress = Address;
379 return EFI_SUCCESS;
380 }
381}
382
383EFI_STATUS
385 IN VOID *Message,
386 IN UINT32 Size
387 )
388{
389 EFI_STATUS Status;
390
391 Status = EFI_SUCCESS;
392
396 }
397
398 Status = HeciSendMessage (
399 Message,
400 Size,
403 );
404
405 if (!EFI_ERROR (Status)) {
407 }
408 }
409
410 return Status;
411}
412
413EFI_STATUS
415 VOID
416 )
417{
418 EFI_STATUS Status;
420
421 Status = EFI_SUCCESS;
422
424 //
425 // Note, this is different between HECI 1 and HECI 2.
426 // HECI 1 has 4 byte response, and it does not require HeciUpdateReceiveMsgStatus.
427 //
428 STATIC_ASSERT (sizeof (Command.Request) == 4, "Invalid ME command req size");
429 STATIC_ASSERT (sizeof (Command.Response) == 8, "Invalid ME command rsp size");
430
433 }
434
435 ZeroMem (&Command, sizeof (Command));
436
437 Command.Request.Command.Fields.Command = CLIENT_DISCONNECT_REQUEST;
438 Command.Request.MeAddress = mCurrentMeClientAddress;
439 Command.Request.HostAddress = HBM_CLIENT_ADDRESS;
440
442
444 &Command,
445 sizeof (Command.Request),
446 sizeof (Command.Response)
447 );
448
449 DEBUG ((
450 DEBUG_INFO,
451 "OCME: Disconnect from client %X code %d - %r\n",
453 Command.Response.Status,
454 Status
455 ));
456
457 if (!EFI_ERROR (Status)) {
459 }
460 }
461
462 return Status;
463}
464
465EFI_STATUS
467 OUT UINT32 *EpidStatus,
468 OUT UINT32 *EpidGroupId
469 )
470{
471 EFI_STATUS Status;
473
474 STATIC_ASSERT (sizeof (Command.Request) == 16, "Invalid ME command size");
475 STATIC_ASSERT (sizeof (Command.Response) == 24, "Invalid ME command size");
476
477 ZeroMem (&Command, sizeof (Command));
478 Command.Request.Header.Version = ME_PAVP_PROTOCOL_VERSION;
479 Command.Request.Header.Command = ME_PAVP_PROVISION_REQUEST_COMMAND;
480 HeciSendMessagePerClient (&Command, sizeof (Command.Request));
481
482 ZeroMem (&Command, sizeof (Command));
483 Status = HeciGetResponse (&Command, sizeof (Command.Response));
484
485 if (!EFI_ERROR (Status)) {
486 *EpidStatus = Command.Response.Status;
487 *EpidGroupId = Command.Response.GroupId;
488 }
489
490 return Status;
491}
492
493EFI_STATUS
495 IN EPID_CERTIFICATE *EpidCertificate,
496 IN EPID_GROUP_PUBLIC_KEY *EpidGroupPublicKey,
497 OUT BOOLEAN *SetVar OPTIONAL
498 )
499{
500 EFI_STATUS Status;
502 UINTN Index;
503
504 STATIC_ASSERT (sizeof (Command.Request) == 1284, "Invalid ME command size");
505 STATIC_ASSERT (sizeof (Command.Response) == 16, "Invalid ME command size");
506
507 if (SetVar != NULL) {
508 *SetVar = FALSE;
509 }
510
511 ZeroMem (&Command, sizeof (Command));
512 Command.Request.Header.Version = ME_PAVP_PROTOCOL_VERSION;
513 Command.Request.Header.Command = ME_PAVP_PROVISION_PERFORM_COMMAND;
514 Command.Request.Header.PayloadSize = ME_PAVP_PROVISION_PERFORM_PAYLOAD_SIZE;
515 CopyMem (&Command.Request.Certificate, EpidCertificate, sizeof (Command.Request.Certificate));
516 CopyMem (&Command.Request.PublicKey, EpidGroupPublicKey, sizeof (Command.Request.PublicKey));
517
518 Status = HeciSendMessagePerClient (&Command, sizeof (Command.Request));
519 ZeroMem (&Command, sizeof (Command));
520 if (EFI_ERROR (Status)) {
521 DEBUG ((DEBUG_INFO, "OCME: Failed to send provisioning command - %r\n", Status));
522 return EFI_DEVICE_ERROR;
523 }
524
525 for (Index = 0; Index < 3; ++Index) {
526 Status = HeciGetResponse (&Command, sizeof (Command.Response));
527 if (Status != EFI_TIMEOUT) {
528 break;
529 }
530 }
531
532 DEBUG ((
533 DEBUG_INFO,
534 "OCME: Finished provisioning command with status %x - %r\n",
535 Command.Response.Header.Status,
536 Status
537 ));
538
539 if (EFI_ERROR (Status)) {
540 return EFI_DEVICE_ERROR;
541 }
542
543 if (Command.Response.Header.Status != EPID_STATUS_PROVISIONED) {
544 Status = EFI_DEVICE_ERROR;
545 }
546
547 if (Command.Response.Header.Status == EPID_STATUS_FAIL_PROVISION) {
548 if (SetVar != NULL) {
549 *SetVar = TRUE;
550 }
551 }
552
553 return Status;
554}
555
556EFI_STATUS
558 OUT UINT32 *FpfStatus
559 )
560{
561 EFI_STATUS Status;
562 UINT32 Response[11];
563 UINT32 Request[4];
564
565 ZeroMem (Request, sizeof (Request));
566 Request[0] = 3;
567 HeciSendMessagePerClient (Request, sizeof (Request));
568
569 ZeroMem (Response, sizeof (Response));
570 Status = HeciGetResponse (Response, sizeof (Response));
571
572 if (!EFI_ERROR (Status)) {
573 *FpfStatus = Response[1];
574 }
575
576 return Status;
577}
578
579EFI_STATUS
581 OUT UINT32 *FpfStatus
582 )
583{
584 EFI_STATUS Status;
585 UINT32 Response[2];
586 UINT32 Request[3];
587
588 ZeroMem (Request, sizeof (Request));
589 Request[0] = 5;
590 Request[1] = 1;
591 Request[2] = 255;
592 HeciSendMessagePerClient (Request, sizeof (Request));
593
594 ZeroMem (Response, sizeof (Response));
595 Status = HeciGetResponse (Response, sizeof (Response));
596
597 if (!EFI_ERROR (Status)) {
598 *FpfStatus = Response[1];
599 }
600
601 return Status;
602}
UINT8 Command[7]
Actual command for the Command Page.
Definition AppleNec.h:74
UINT64 Length
STATIC EFI_STATUS SetVar(UINTN Line, CHAR8 *Token, BOOLEAN IsIndented, BOOLEAN ContainsVars)
Definition GrubCfg.c:345
#define HECI_DEFAULT_DEVICE
Definition Heci2.h:17
EFI_GUID gEfiHeci2ProtocolGuid
EFI_GUID gEfiHeciProtocolGuid
#define ME_PAVP_PROVISION_PERFORM_COMMAND
#define ME_PAVP_PROVISION_REQUEST_COMMAND
#define ME_PAVP_PROVISION_PERFORM_PAYLOAD_SIZE
#define EPID_STATUS_PROVISIONED
#define ME_PAVP_PROTOCOL_VERSION
#define EPID_STATUS_FAIL_PROVISION
#define CLIENT_CONNECT_REQUEST
Definition HeciMsg.h:31
#define HBM_CLIENT_CONNECT_ALREADY_CONNECTED
Definition HeciMsg.h:203
#define HBM_CLIENT_CONNECT_OUT_OF_RESOURCES
Definition HeciMsg.h:204
#define HBM_ME_ADDRESS
Definition HeciMsg.h:19
#define HBM_HOST_ADDRESS
Definition HeciMsg.h:18
#define HBM_CLIENT_CONNECT_INVALID_PARAMETER
Definition HeciMsg.h:205
#define CLIENT_DISCONNECT_REQUEST
Definition HeciMsg.h:32
#define HBM_CLIENT_CONNECT_NOT_FOUND
Definition HeciMsg.h:202
#define HBM_CLIENT_ADDRESS
Definition HeciMsg.h:20
#define HOST_ENUMERATION_REQUEST
Definition HeciMsg.h:29
#define HOST_CLIENT_PROPERTIES_REQUEST
Definition HeciMsg.h:30
#define HBM_ME_CLIENT_MAX
Definition HeciMsg.h:135
#define FLOW_CONTROL
Definition HeciMsg.h:33
#define BLOCKING
Definition MkhiMsgs.h:37
DMG_SIZE_DEVICE_PATH Size
STATIC_ASSERT(BYTES_PER_PIXEL==sizeof(UINT32), "Non 4-byte pixels are unsupported!")
EFI_BOOT_SERVICES * gBS
EFI_STATUS HeciDisconnectFromClients(VOID)
Definition OcHeciLib.c:414
STATIC BOOLEAN mSendingHeciCommand
Definition OcHeciLib.c:29
STATIC EFI_HECI_PROTOCOL * mHeci
Definition OcHeciLib.c:27
STATIC BOOLEAN mSendingHeciCommandPerClient
Definition OcHeciLib.c:30
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 HeciReadMessage(IN UINT32 Blocking, IN UINT32 *MessageBody, IN OUT UINT32 *Length)
Definition OcHeciLib.c:33
EFI_STATUS HeciGetResponse(OUT VOID *MessageData, IN UINT32 ResponseSize)
Definition OcHeciLib.c:155
EFI_STATUS HeciLocateProtocol(VOID)
Definition OcHeciLib.c:92
EFI_STATUS HeciConnectToClient(IN UINT8 Address)
Definition OcHeciLib.c:334
STATIC UINT8 mCurrentMeClientAddress
Definition OcHeciLib.c:25
EFI_STATUS HeciFpfGetStatus(OUT UINT32 *FpfStatus)
Definition OcHeciLib.c:557
EFI_STATUS HeciFpfProvision(OUT UINT32 *FpfStatus)
Definition OcHeciLib.c:580
STATIC UINT8 mCurrentMeClientCanReceiveMsg
Definition OcHeciLib.c:24
VOID HeciUpdateReceiveMsgStatus(VOID)
Definition OcHeciLib.c:131
EFI_STATUS HeciSendMessagePerClient(IN VOID *Message, IN UINT32 Size)
Definition OcHeciLib.c:384
EFI_STATUS HeciGetClientMap(OUT UINT8 *ClientMap, OUT UINT8 *ClientActiveCount)
Definition OcHeciLib.c:245
STATIC EFI_HECI2_PROTOCOL * mHeci2
Definition OcHeciLib.c:28
EFI_STATUS HeciSendMessageWithResponse(IN OUT VOID *MessageData, IN UINT32 RequestSize, IN UINT32 ResponseSize)
Definition OcHeciLib.c:207
STATIC UINT8 mCurrentMeClientRequestedReceiveMsg
Definition OcHeciLib.c:23
EFI_STATUS HeciSendMessage(IN UINT32 *Message, IN UINT32 Length, IN UINT8 HostAddress, IN UINT8 MEAddress)
Definition OcHeciLib.c:61
EFI_STATUS HeciGetClientProperties(IN UINT8 Address, OUT HECI_CLIENT_PROPERTIES *Properties)
Definition OcHeciLib.c:298
#define OC_CHAR_BIT
Definition OcMiscLib.h:25
VOID *EFIAPI CopyMem(OUT VOID *DestinationBuffer, IN CONST VOID *SourceBuffer, IN UINTN Length)
VOID *EFIAPI ZeroMem(OUT VOID *Buffer, IN UINTN Length)
EFI_HECI2_READ_MESSAGE ReadMsg
Definition Heci2.h:88
EFI_HECI2_SEND_MESSAGE SendMsg
Definition Heci2.h:89
EFI_HECI_SEND_MESSAGE SendMsg
Definition Heci.h:85
EFI_HECI_READ_MESSAGE ReadMsg
Definition Heci.h:84
HBM_COMMAND Command
Definition HeciMsg.h:52
struct HBM_COMMAND::@63 Fields
UINT8 Command
Definition HeciMsg.h:46