microsoft/mu_feature_ffa

Public

mirrored fromhttps://github.com/microsoft/mu_feature_ffaAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
fix_upload

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

FfaFeaturePkg/Library/TpmServiceLib/TpmServiceLib.c

706lines · modecode

1/** @file
2 Implementation for the TPM Service. This library is based
3 off of the ARM spec: TPM Service Command Response Buffer
4 Interface Over FF-A. The spec can be found here:
5
6 https://developer.arm.com/documentation/den0138/0100/?lang=en
7
8 The state flow is based off the TCG PC Client Specific Platform
9 TPM Profile for TPM 2.0. The spec can be found here:
10
11 https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/
12
13 Figure 4 - TPM State Diagram for CRB Interface
14
15 Copyright (c), Microsoft Corporation.
16 SPDX-License-Identifier: BSD-2-Clause-Patent
17
18**/
19
20#include <Uefi.h>
21#include <Library/BaseLib.h>
22#include <Library/BaseMemoryLib.h>
23#include <Library/DebugLib.h>
24#include <Library/BaseMemoryLib.h>
25#include <Library/TpmServiceLib.h>
26#include <Library/TpmServiceStateTranslationLib.h>
27#include <Guid/Tpm2ServiceFfa.h>
28#include <IndustryStandard/TpmPtp.h>
29#include <IndustryStandard/Tpm20.h>
30
31/* TPM Service Defines */
32#define TPM_MAJOR_VER (0x1)
33#define TPM_MINOR_VER (0x0)
34
35/* TODO: Temporary Solution - May move to Tpm2ServiceFfa.h */
36#define TPM_START_PROCESS_OPEN_LOC (0x100)
37#define TPM_START_PROCESS_CLOSE_LOC (0x101)
38
39#define TPM_LOCALITY_OFFSET (0x1000)
40
41/* TPM Service States */
42typedef enum {
43 TPM_STATE_IDLE = 0,
44 TPM_STATE_READY,
45 TPM_STATE_COMPLETE,
46 NUM_TPM_STATES
47} TpmState;
48
49/* TPM Locality States */
50typedef enum {
51 TPM_LOCALITY_CLOSED = 0,
52 TPM_LOCALITY_OPEN,
53 NUM_LOCALITY_STATES
54} TpmLocalityState;
55
56typedef UINTN TpmStatus;
57
58/* TPM Service Variables */
59STATIC TpmState mCurrentState;
60STATIC UINT8 mActiveLocality;
61STATIC PTP_CRB_INTERFACE_IDENTIFIER mInterfaceIdDefault;
62STATIC TpmLocalityState mLocalityStates[NUM_LOCALITIES];
63
64/**
65 Converts the passed in EFI_STATUS to a TPM_STATUS
66
67 @param Status The EFI_STATUS to convert
68
69 @retval TPM_STATUS_OK Success
70 @retval TPM_STATUS_INVARG Invalid parameter
71 @retval TPM_STATUS_DENIED Access denied
72 @retval TPM_STATUS_NOMEM Insufficient memory
73
74**/
75STATIC
76TpmStatus
77ConvertEfiToTpmStatus (
78 EFI_STATUS Status
79 )
80{
81 TpmStatus ReturnVal;
82
83 switch (Status) {
84 case EFI_SUCCESS:
85 ReturnVal = TPM2_FFA_SUCCESS_OK;
86 break;
87
88 case EFI_DEVICE_ERROR:
89 ReturnVal = TPM2_FFA_ERROR_DENIED;
90 break;
91
92 case EFI_BUFFER_TOO_SMALL:
93 ReturnVal = TPM2_FFA_ERROR_NOMEM;
94 break;
95
96 default:
97 ReturnVal = TPM2_FFA_ERROR_DENIED;
98 break;
99 }
100
101 return ReturnVal;
102}
103
104/**
105 Initializes the internal CRB
106
107 @param Locality The locality of the CRB
108
109**/
110STATIC
111VOID
112InitInternalCrb (
113 UINT8 Locality
114 )
115{
116 PTP_CRB_REGISTERS_PTR InternalTpmCrb;
117
118 InternalTpmCrb = (PTP_CRB_REGISTERS_PTR)(UINTN)(PcdGet64 (PcdTpmInternalBaseAddress) + (Locality * TPM_LOCALITY_OFFSET));
119 DEBUG ((DEBUG_INFO, "Locality: %x - InternalTpmCrb Address: %lx\n", Locality, (UINTN)InternalTpmCrb));
120 SetMem ((void *)InternalTpmCrb, sizeof (PTP_CRB_REGISTERS), 0x00);
121 InternalTpmCrb->InterfaceId = mInterfaceIdDefault.Uint32;
122 InternalTpmCrb->CrbControlStatus = PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE;
123
124 /* Set the CRB Command/Response buffer address + size. */
125 InternalTpmCrb->CrbControlCommandAddressHigh = (UINT32)RShiftU64 ((UINTN)InternalTpmCrb->CrbDataBuffer, 32);
126 InternalTpmCrb->CrbControlCommandAddressLow = (UINT32)(UINTN)InternalTpmCrb->CrbDataBuffer;
127 InternalTpmCrb->CrbControlCommandSize = sizeof (InternalTpmCrb->CrbDataBuffer);
128 InternalTpmCrb->CrbControlResponseAddrss = (UINTN)InternalTpmCrb->CrbDataBuffer;
129 InternalTpmCrb->CrbControlResponseSize = sizeof (InternalTpmCrb->CrbDataBuffer);
130}
131
132/**
133 Cleans the internal CRB putting registers into a known good state
134
135**/
136STATIC
137VOID
138CleanInternalCrb (
139 VOID
140 )
141{
142 PTP_CRB_REGISTERS_PTR InternalTpmCrb;
143
144 /* If the user has never requested a locality, don't clean, no need.
145 * We should only ever clean the active locality as when localities change
146 * we clear the entire CRB region. */
147 if (mActiveLocality == NUM_LOCALITIES) {
148 return;
149 }
150
151 InternalTpmCrb = (PTP_CRB_REGISTERS_PTR)(UINTN)(PcdGet64 (PcdTpmInternalBaseAddress) + (mActiveLocality * TPM_LOCALITY_OFFSET));
152
153 /* Set the locality state based on the active locality. */
154 switch (mActiveLocality) {
155 case 0:
156 InternalTpmCrb->LocalityState |= PTP_CRB_LOCALITY_STATE_ACTIVE_LOCALITY_0;
157 break;
158
159 case 1:
160 InternalTpmCrb->LocalityState |= PTP_CRB_LOCALITY_STATE_ACTIVE_LOCALITY_1;
161 break;
162
163 case 2:
164 InternalTpmCrb->LocalityState |= PTP_CRB_LOCALITY_STATE_ACTIVE_LOCALITY_2;
165 break;
166
167 case 3:
168 InternalTpmCrb->LocalityState |= PTP_CRB_LOCALITY_STATE_ACTIVE_LOCALITY_3;
169 break;
170
171 case 4:
172 InternalTpmCrb->LocalityState |= PTP_CRB_LOCALITY_STATE_ACTIVE_LOCALITY_4;
173 break;
174
175 default:
176 break;
177 }
178
179 InternalTpmCrb->LocalityState |= PTP_CRB_LOCALITY_STATE_TPM_REG_VALID_STATUS;
180 InternalTpmCrb->LocalityState |= PTP_CRB_LOCALITY_STATE_LOCALITY_ASSIGNED;
181 InternalTpmCrb->LocalityStatus |= PTP_CRB_LOCALITY_STATUS_GRANTED;
182 InternalTpmCrb->LocalityControl = 0;
183 InternalTpmCrb->InterfaceId = mInterfaceIdDefault.Uint32;
184 InternalTpmCrb->CrbControlExtension = 0;
185 InternalTpmCrb->CrbControlRequest = 0;
186 InternalTpmCrb->CrbControlCancel = 0;
187 InternalTpmCrb->CrbControlStart = 0;
188 InternalTpmCrb->CrbInterruptEnable = 0;
189 InternalTpmCrb->CrbInterruptStatus = 0;
190
191 /* Set the current TPM Status based on the current state. */
192 if (mCurrentState == TPM_STATE_IDLE) {
193 InternalTpmCrb->CrbControlStatus = PTP_CRB_CONTROL_AREA_STATUS_TPM_IDLE;
194 } else {
195 InternalTpmCrb->CrbControlStatus = 0;
196 }
197
198 /* Set the CRB Command/Response buffer address + size. */
199 InternalTpmCrb->CrbControlCommandAddressHigh = (UINT32)RShiftU64 ((UINTN)InternalTpmCrb->CrbDataBuffer, 32);
200 InternalTpmCrb->CrbControlCommandAddressLow = (UINT32)(UINTN)InternalTpmCrb->CrbDataBuffer;
201 InternalTpmCrb->CrbControlCommandSize = sizeof (InternalTpmCrb->CrbDataBuffer);
202 InternalTpmCrb->CrbControlResponseAddrss = (UINTN)InternalTpmCrb->CrbDataBuffer;
203 InternalTpmCrb->CrbControlResponseSize = sizeof (InternalTpmCrb->CrbDataBuffer);
204
205 /* Remaining registers can be ignored. */
206}
207
208/**
209 Handles commands for the TPM service
210
211 @retval TPM_STATUS_OK Success
212 @retval TPM_STATUS_INVARG Invalid parameter
213 @retval TPM_STATUS_DENIED Access denied
214 @retval TPM_STATUS_NOMEM Insufficient memory
215
216**/
217STATIC
218TpmStatus
219HandleCommand (
220 VOID
221 )
222{
223 EFI_STATUS Status;
224 PTP_CRB_REGISTERS_PTR InternalTpmCrb;
225
226 InternalTpmCrb = (PTP_CRB_REGISTERS_PTR)(UINTN)(PcdGet64 (PcdTpmInternalBaseAddress) + (mActiveLocality * TPM_LOCALITY_OFFSET));
227
228 /* Depending on our current state, we will investigate specific registers and
229 * make state transitions or deny commands. */
230 Status = EFI_ACCESS_DENIED;
231 switch (mCurrentState) {
232 /* The TPM can transition to IDLE from any state outside of command execution when the
233 * SW sets the goIdle bit in the CrbControlRequest register. When the TPM transitions to
234 * IDLE from COMPLETE it should clear the buffer. */
235 case TPM_STATE_IDLE:
236 /* Check the cmdReady bit in the CrbControlRequest register to see if we need to
237 * transition to the READY state, otherwise, deny the request. */
238 if (InternalTpmCrb->CrbControlRequest & PTP_CRB_CONTROL_AREA_REQUEST_COMMAND_READY) {
239 DEBUG ((DEBUG_INFO, "IDLE State - Handle TPM Command cmdReady Request\n"));
240 Status = TpmSstCmdReady (mActiveLocality);
241 if (Status == EFI_SUCCESS) {
242 mCurrentState = TPM_STATE_READY;
243 }
244 }
245
246 break;
247
248 /* The TPM can transition to READY from IDLE or COMPLETE when the SW sets the cmdReady bit
249 * in the CrbControlRequest register. When the TPM transitions to READY from COMPLETE it
250 * should clear the buffer. */
251 case TPM_STATE_READY:
252 /* Check the goIdle bit in the CrbControlRequest register to see if we need to
253 * transition back to the IDLE state. */
254 if (InternalTpmCrb->CrbControlRequest & PTP_CRB_CONTROL_AREA_REQUEST_GO_IDLE) {
255 DEBUG ((DEBUG_INFO, "READY State - Handle TPM Command goIdle Request\n"));
256 Status = TpmSstGoIdle (mActiveLocality);
257 if (Status == EFI_SUCCESS) {
258 mCurrentState = TPM_STATE_IDLE;
259 }
260
261 /* Check the cmdReady bit in the CrbControlRequest register, clear it if it has been
262 * set again. */
263 } else if (InternalTpmCrb->CrbControlRequest & PTP_CRB_CONTROL_AREA_REQUEST_COMMAND_READY) {
264 DEBUG ((DEBUG_INFO, "READY State - Handle TPM Command cmdReady Request\n"));
265 Status = TpmSstCmdReady (mActiveLocality);
266
267 /* Check the CrbControlStart register to see if we need to start executing a command.
268 * Once the command completes, transition to the COMPLETE state. */
269 } else if (InternalTpmCrb->CrbControlStart & PTP_CRB_CONTROL_START) {
270 DEBUG ((DEBUG_INFO, "READY State - Handle TPM Command Start Request\n"));
271 Status = TpmSstStart (mActiveLocality, InternalTpmCrb);
272 if (Status == EFI_SUCCESS) {
273 mCurrentState = TPM_STATE_COMPLETE;
274 }
275 }
276
277 break;
278
279 /* The TPM can transition to COMPLETE only from READY when the SW writes a 1 to the
280 * CrbControlStart register and the command execution finishes. The SW can write more
281 * data to the buffer and set the register again to trigger another command execution;
282 * this is only if TPM_CapCRBIdleBypass is 1. */
283 case TPM_STATE_COMPLETE:
284 /* Check the goIdle bit in the CrbControlRequest register to see if we need to
285 * transition to the IDLE state. */
286 if (InternalTpmCrb->CrbControlRequest & PTP_CRB_CONTROL_AREA_REQUEST_GO_IDLE) {
287 DEBUG ((DEBUG_INFO, "COMPLETE State - Handle TPM Command goIdle Request\n"));
288 Status = TpmSstGoIdle (mActiveLocality);
289 if (Status == EFI_SUCCESS) {
290 mCurrentState = TPM_STATE_IDLE;
291 SetMem ((void *)InternalTpmCrb->CrbDataBuffer, sizeof (InternalTpmCrb->CrbDataBuffer), 0x00);
292 }
293
294 /* Check the cmdReady bit in the CrbControlRequest register to see if we need to
295 * transition back to the READY state. */
296 } else if (InternalTpmCrb->CrbControlRequest & PTP_CRB_CONTROL_AREA_REQUEST_COMMAND_READY) {
297 /* Transition to READY from COMPLETE is only supported if TPM_CapCRBIdleBypass is 1.*/
298 if (TpmSstIsIdleBypassSupported ()) {
299 DEBUG ((DEBUG_INFO, "COMPLETE State - Handle TPM Command cmdReady Request\n"));
300 Status = TpmSstCmdReady (mActiveLocality);
301 if (Status == EFI_SUCCESS) {
302 mCurrentState = TPM_STATE_READY;
303 SetMem ((void *)InternalTpmCrb->CrbDataBuffer, sizeof (InternalTpmCrb->CrbDataBuffer), 0x00);
304 }
305 }
306
307 /* Check the CrbControlStart register to see if we need to execute another command. */
308 } else if (InternalTpmCrb->CrbControlStart & PTP_CRB_CONTROL_START) {
309 /* Execution of another command from COMPLETE is only supported if TPM_CapCRBIdleBypass
310 * is 1. */
311 if (TpmSstIsIdleBypassSupported ()) {
312 DEBUG ((DEBUG_INFO, "COMPLETE State - Handle TPM Command Start Request\n"));
313 Status = TpmSstStart (mActiveLocality, InternalTpmCrb);
314 }
315 }
316
317 break;
318
319 /* The normal state flow should be: IDLE -> READY -> COMPLETE -> IDLE. */
320 default:
321 DEBUG ((DEBUG_ERROR, "INVALID State - Attempting to transition to IDLE State\n"));
322 Status = TpmSstGoIdle (mActiveLocality);
323 if (Status == EFI_SUCCESS) {
324 mCurrentState = TPM_STATE_IDLE;
325 SetMem ((void *)InternalTpmCrb->CrbDataBuffer, sizeof (InternalTpmCrb->CrbDataBuffer), 0x00);
326 }
327
328 break;
329 }
330
331 /* Clear the internal CRB start register to indicate successful completion and response ready */
332 if (Status != EFI_SUCCESS) {
333 DEBUG ((DEBUG_ERROR, "Command Failed w/ Status: %x\n", Status));
334 }
335
336 return ConvertEfiToTpmStatus (Status);
337}
338
339/**
340 Handles locality requests for the TPM service
341
342 @param Locality The locality of the CRB
343
344 @retval TPM_STATUS_OK Success
345 @retval TPM_STATUS_INVARG Invalid parameter
346 @retval TPM_STATUS_DENIED Access denied
347 @retval TPM_STATUS_NOMEM Insufficient memory
348
349**/
350STATIC
351TpmStatus
352HandleLocalityRequest (
353 UINT8 Locality
354 )
355{
356 EFI_STATUS Status;
357 PTP_CRB_REGISTERS_PTR InternalTpmCrb;
358 UINT8 ActiveLocality;
359
360 InternalTpmCrb = (PTP_CRB_REGISTERS_PTR)(UINTN)(PcdGet64 (PcdTpmInternalBaseAddress) + (Locality * TPM_LOCALITY_OFFSET));
361
362 /* Check if we are doing a locality relinquish */
363 if (InternalTpmCrb->LocalityControl & PTP_CRB_LOCALITY_CONTROL_RELINQUISH) {
364 /* Make sure the locality being relinquished is the active locality */
365 if (Locality != mActiveLocality) {
366 DEBUG ((DEBUG_ERROR, "Locality Relinquish Failed - Invalid Locality\n"));
367 return TPM2_FFA_ERROR_DENIED;
368 }
369
370 DEBUG ((DEBUG_INFO, "Handle TPM Locality%x Relinquish\n", Locality));
371 Status = TpmSstLocalityRelinquish (Locality);
372 ActiveLocality = NUM_LOCALITIES; // Invalid
373 /* Check if we are doing a locality request */
374 } else if (InternalTpmCrb->LocalityControl & PTP_CRB_LOCALITY_CONTROL_REQUEST_ACCESS) {
375 DEBUG ((DEBUG_INFO, "Handle TPM Locality%x Request\n", Locality));
376 Status = TpmSstLocalityRequest (Locality);
377 ActiveLocality = Locality;
378 /* Otherwise, the host didn't set the correct bits, invalid */
379 } else {
380 DEBUG ((DEBUG_ERROR, "Request/Relinquish Bit Not Set\n"));
381 return TPM2_FFA_ERROR_DENIED;
382 }
383
384 /* Update the internal TPM CRB */
385 if (Status == EFI_SUCCESS) {
386 InitInternalCrb (Locality);
387 mActiveLocality = ActiveLocality;
388 } else {
389 DEBUG ((DEBUG_ERROR, "Locality Request Failed w/ Status: %x\n", Status));
390 }
391
392 return ConvertEfiToTpmStatus (Status);
393}
394
395/**
396 Handler for TPM service GetInterfaceVersion command
397
398 @param Request The incoming message
399 @param Response The outgoing message
400
401 @retval TPM_STATUS_OK Success
402
403**/
404STATIC
405TpmStatus
406GetInterfaceVersionHandler (
407 DIRECT_MSG_ARGS_EX *Request,
408 DIRECT_MSG_ARGS_EX *Response
409 )
410{
411 TpmStatus ReturnVal;
412
413 ReturnVal = TPM2_FFA_SUCCESS_OK;
414 Response->Arg0 = TPM2_FFA_SUCCESS_OK_RESULTS_RETURNED;
415 Response->Arg1 = (TPM_MAJOR_VER << 16) | TPM_MINOR_VER;
416 return ReturnVal;
417}
418
419/**
420 Handler for TPM service GetFeatureInfo command
421
422 @param Request The incoming message
423 @param Response The outgoing message
424
425 @retval TPM_STATUS_OK Success
426
427**/
428STATIC
429TpmStatus
430GetFeatureInfoHandler (
431 DIRECT_MSG_ARGS_EX *Request,
432 DIRECT_MSG_ARGS_EX *Response
433 )
434{
435 TpmStatus ReturnVal;
436
437 ReturnVal = TPM2_FFA_SUCCESS_OK;
438 Response->Arg0 = TPM2_FFA_ERROR_NOTSUP;
439 DEBUG ((DEBUG_ERROR, "Unsupported Function\n"));
440 return ReturnVal;
441}
442
443/**
444 Handler for TPM service Start command
445
446 @param Request The incoming message
447 @param Response The outgoing message
448
449 @retval TPM_STATUS_OK Success
450 @retval TPM_STATUS_INVARG Invalid parameter
451 @retval TPM_STATUS_DENIED Access denied
452 @retval TPM_STATUS_NOMEM Insufficient memory
453
454**/
455STATIC
456TpmStatus
457StartHandler (
458 DIRECT_MSG_ARGS_EX *Request,
459 DIRECT_MSG_ARGS_EX *Response
460 )
461{
462 TpmStatus ReturnVal;
463 UINT16 Function;
464 UINT8 Locality;
465
466 ReturnVal = TPM2_FFA_SUCCESS_OK;
467 Function = Request->Arg1;
468 Locality = Request->Arg2;
469
470 /* Check to make sure we received a valid locality */
471 if (Locality >= NUM_LOCALITIES) {
472 Response->Arg0 = TPM2_FFA_ERROR_INVARG;
473 DEBUG ((DEBUG_ERROR, "Invalid Locality\n"));
474 ReturnVal = TPM2_FFA_ERROR_INVARG;
475 goto exit;
476 }
477
478 /* TODO: Temporary solution*/
479
480 /* NOTE: The following commands should only be coming
481 * from TF-A. */
482 /* Check if there was a request to open a locality */
483 if (Function == TPM_START_PROCESS_OPEN_LOC) {
484 /* Set the locality state to OPEN */
485 mLocalityStates[Locality] = TPM_LOCALITY_OPEN;
486 goto exit;
487 /* Check if there was a request to close a locality */
488 } else if (Function == TPM_START_PROCESS_CLOSE_LOC) {
489 /* Set the locality state to CLOSED */
490 mLocalityStates[Locality] = TPM_LOCALITY_CLOSED;
491 goto exit;
492 }
493
494 /* Check if the locality is open */
495 if (mLocalityStates[Locality] == TPM_LOCALITY_CLOSED) {
496 DEBUG ((DEBUG_ERROR, "Locality Closed\n"));
497 ReturnVal = TPM2_FFA_ERROR_DENIED;
498 goto exit;
499 }
500
501 /* Check if we are processing a command */
502 if (Function == TPM2_FFA_START_FUNC_QUALIFIER_COMMAND) {
503 /* We should only proceed if the locality being requested matches that of the
504 * current locality that is active. */
505 if (Locality == mActiveLocality) {
506 ReturnVal = HandleCommand ();
507 } else {
508 ReturnVal = TPM2_FFA_ERROR_INVARG;
509 DEBUG ((DEBUG_ERROR, "Locality Mismatch\n"));
510 }
511
512 /* Check if we are processing a locality request */
513 } else if (Function == TPM2_FFA_START_FUNC_QUALIFIER_LOCALITY) {
514 ReturnVal = HandleLocalityRequest (Locality);
515 /* Otherwise, invalid function ID */
516 } else {
517 ReturnVal = TPM2_FFA_ERROR_INVARG;
518 DEBUG ((DEBUG_ERROR, "Invalid Start Function\n"));
519 }
520
521exit:
522 /* Clean up the internal CRB at the given locality */
523 CleanInternalCrb ();
524
525 Response->Arg0 = ReturnVal;
526 return ReturnVal;
527}
528
529/**
530 Handler for TPM service Register command
531
532 @param Request The incoming message
533 @param Response The outgoing message
534
535 @retval TPM_STATUS_OK Success
536
537**/
538STATIC
539TpmStatus
540RegisterHandler (
541 DIRECT_MSG_ARGS_EX *Request,
542 DIRECT_MSG_ARGS_EX *Response
543 )
544{
545 TpmStatus ReturnVal;
546
547 ReturnVal = TPM2_FFA_SUCCESS_OK;
548 Response->Arg0 = TPM2_FFA_ERROR_NOTSUP;
549 DEBUG ((DEBUG_ERROR, "Unsupported Function\n"));
550 return ReturnVal;
551}
552
553/**
554 Handler for TPM service Unregister command
555
556 @param Request The incoming message
557 @param Response The outgoing message
558
559 @retval TPM_STATUS_OK Success
560
561**/
562STATIC
563TpmStatus
564UnregisterHandler (
565 DIRECT_MSG_ARGS_EX *Request,
566 DIRECT_MSG_ARGS_EX *Response
567 )
568{
569 TpmStatus ReturnVal;
570
571 ReturnVal = TPM2_FFA_SUCCESS_OK;
572 Response->Arg0 = TPM2_FFA_ERROR_NOTSUP;
573 DEBUG ((DEBUG_ERROR, "Unsupported Function\n"));
574 return ReturnVal;
575}
576
577/**
578 Handler for TPM service Finish command
579
580 @param Request The incoming message
581 @param Response The outgoing message
582
583 @retval TPM_STATUS_OK Success
584
585**/
586STATIC
587TpmStatus
588FinishHandler (
589 DIRECT_MSG_ARGS_EX *Request,
590 DIRECT_MSG_ARGS_EX *Response
591 )
592{
593 TpmStatus ReturnVal;
594
595 ReturnVal = TPM2_FFA_SUCCESS_OK;
596 Response->Arg0 = TPM2_FFA_ERROR_NOTSUP;
597 DEBUG ((DEBUG_ERROR, "Unsupported Function\n"));
598 return ReturnVal;
599}
600
601/**
602 Initializes the TPM service
603
604**/
605VOID
606TpmServiceInit (
607 VOID
608 )
609{
610 UINT8 Locality;
611
612 /* Initialize the default interface ID. */
613 mInterfaceIdDefault.Uint32 = 0;
614 mInterfaceIdDefault.Bits.InterfaceType = 1; // CRB active
615 mInterfaceIdDefault.Bits.InterfaceVersion = 1; // CRB interface version
616 mInterfaceIdDefault.Bits.CapLocality = 1; // 5 localities supported
617 mInterfaceIdDefault.Bits.CapCRB = 1; // CRB supported
618
619 /* Initializes all of the localities. */
620 for (Locality = 0; Locality < NUM_LOCALITIES; Locality++) {
621 InitInternalCrb (Locality);
622 }
623
624 /* Default the locality states */
625 for (Locality = 0; Locality < NUM_LOCALITIES; Locality++) {
626 /* Locality 0 and 1 are open by default */
627 if ((Locality == 0) || (Locality == 1)) {
628 mLocalityStates[Locality] = TPM_LOCALITY_OPEN;
629 } else {
630 mLocalityStates[Locality] = TPM_LOCALITY_CLOSED;
631 }
632 }
633
634 /* Initialize the TPM Service State Translation Library. */
635 TpmSstInit ();
636
637 /* Initialize our default state information. */
638 mCurrentState = TPM_STATE_IDLE;
639 mActiveLocality = NUM_LOCALITIES; // Invalid - No active locality
640}
641
642/**
643 De-initializes the TPM service
644
645**/
646VOID
647TpmServiceDeInit (
648 VOID
649 )
650{
651 /* Nothing to DeInit */
652}
653
654/**
655 Handler for TPM service commands
656
657 @param Request The incoming message
658 @param Response The outgoing message
659
660**/
661VOID
662TpmServiceHandle (
663 DIRECT_MSG_ARGS_EX *Request,
664 DIRECT_MSG_ARGS_EX *Response
665 )
666{
667 UINT64 Opcode;
668
669 /* Validate the input parameters before attempting to dereference or pass them along */
670 if ((Request == NULL) || (Response == NULL)) {
671 return;
672 }
673
674 Opcode = Request->Arg0;
675
676 switch (Opcode) {
677 case TPM2_FFA_GET_INTERFACE_VERSION:
678 GetInterfaceVersionHandler (Request, Response);
679 break;
680
681 case TPM2_FFA_GET_FEATURE_INFO:
682 GetFeatureInfoHandler (Request, Response);
683 break;
684
685 case TPM2_FFA_START:
686 StartHandler (Request, Response);
687 break;
688
689 case TPM2_FFA_REGISTER_FOR_NOTIFICATION:
690 RegisterHandler (Request, Response);
691 break;
692
693 case TPM2_FFA_UNREGISTER_FROM_NOTIFICATION:
694 UnregisterHandler (Request, Response);
695 break;
696
697 case TPM2_FFA_FINISH_NOTIFIED:
698 FinishHandler (Request, Response);
699 break;
700
701 default:
702 Response->Arg0 = TPM2_FFA_ERROR_NOFUNC;
703 DEBUG ((DEBUG_ERROR, "Invalid TPM Service Opcode\n"));
704 break;
705 }
706}
707