microsoft/mu_feature_ffa

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
v0.1.3

Branches

Tags

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

Clone

HTTPS

Download ZIP

FfaFeaturePkg/Library/TpmServiceLib/TpmServiceLib.c

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