]> git.proxmox.com Git - mirror_edk2.git/blob - SecurityPkg/Tcg/TcgPei/TisPei.c
Add security package to repository.
[mirror_edk2.git] / SecurityPkg / Tcg / TcgPei / TisPei.c
1 /** @file
2 TIS (TPM Interface Specification) functions used by TPM PEI driver.
3
4 Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13 **/
14
15 #include <IndustryStandard/Tpm12.h>
16 #include <IndustryStandard/UefiTcgPlatform.h>
17 #include <Library/TpmCommLib.h>
18 #include <Library/DebugLib.h>
19 #include <Library/BaseLib.h>
20 #include <Library/IoLib.h>
21 #include <Library/BaseMemoryLib.h>
22
23 /**
24 Send a command to TPM for execution and return response data.
25
26 @param[in] PeiServices Describes the list of possible PEI Services.
27 @param[in] TisReg TPM register space base address.
28 @param[in] BufferIn Buffer for command data.
29 @param[in] SizeIn Size of command data.
30 @param[in, out] BufferOut Buffer for response data.
31 @param[in, out] SizeOut Size of response data.
32
33 @retval EFI_SUCCESS Operation completed successfully.
34 @retval EFI_TIMEOUT The register can't run into the expected status in time.
35 @retval EFI_BUFFER_TOO_SMALL Response data buffer is too small.
36 @retval EFI_DEVICE_ERROR Unexpected device behavior.
37
38 **/
39 EFI_STATUS
40 TisTpmCommand (
41 IN EFI_PEI_SERVICES **PeiServices,
42 IN TIS_PC_REGISTERS_PTR TisReg,
43 IN UINT8 *BufferIn,
44 IN UINT32 SizeIn,
45 IN OUT UINT8 *BufferOut,
46 IN OUT UINT32 *SizeOut
47 )
48 {
49 EFI_STATUS Status;
50 UINT16 BurstCount;
51 UINT32 Index;
52 UINT32 TpmOutSize;
53 UINT16 Data16;
54 UINT32 Data32;
55
56 Status = TisPcPrepareCommand (TisReg);
57 if (EFI_ERROR (Status)){
58 DEBUG ((DEBUG_ERROR, "Tpm is not ready for command!\n"));
59 return Status;
60 }
61 //
62 // Send the command data to Tpm
63 //
64 Index = 0;
65 while (Index < SizeIn) {
66 Status = TisPcReadBurstCount (TisReg, &BurstCount);
67 if (EFI_ERROR (Status)) {
68 Status = EFI_TIMEOUT;
69 goto Exit;
70 }
71 for (; BurstCount > 0 && Index < SizeIn; BurstCount--) {
72 MmioWrite8((UINTN)&TisReg->DataFifo, *(BufferIn + Index));
73 Index++;
74 }
75 }
76 //
77 // Check the Tpm status STS_EXPECT change from 1 to 0
78 //
79 Status = TisPcWaitRegisterBits (
80 &TisReg->Status,
81 (UINT8) TIS_PC_VALID,
82 TIS_PC_STS_EXPECT,
83 TIS_TIMEOUT_C
84 );
85 if (EFI_ERROR (Status)) {
86 DEBUG ((DEBUG_ERROR, "The send buffer too small!\n"));
87 Status = EFI_BUFFER_TOO_SMALL;
88 goto Exit;
89 }
90 //
91 // Executed the TPM command and waiting for the response data ready
92 //
93 MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_GO);
94 Status = TisPcWaitRegisterBits (
95 &TisReg->Status,
96 (UINT8) (TIS_PC_VALID | TIS_PC_STS_DATA),
97 0,
98 TIS_TIMEOUT_B
99 );
100 if (EFI_ERROR (Status)) {
101 DEBUG ((DEBUG_ERROR, "Wait for Tpm response data time out!!\n"));
102 Status = EFI_TIMEOUT;
103 goto Exit;
104 }
105 //
106 // Get response data header
107 //
108 Index = 0;
109 BurstCount = 0;
110 while (Index < sizeof (TPM_RSP_COMMAND_HDR)) {
111 Status = TisPcReadBurstCount (TisReg, &BurstCount);
112 if (EFI_ERROR (Status)) {
113 Status = EFI_TIMEOUT;
114 goto Exit;
115 }
116 for (; BurstCount > 0; BurstCount--) {
117 *(BufferOut + Index) = MmioRead8 ((UINTN)&TisReg->DataFifo);
118 Index++;
119 if (Index == sizeof (TPM_RSP_COMMAND_HDR)) break;
120 }
121 }
122 //
123 // Check the reponse data header (tag,parasize and returncode )
124 //
125 CopyMem (&Data16, BufferOut, sizeof (UINT16));
126 if (SwapBytes16 (Data16) != TPM_TAG_RSP_COMMAND ) {
127 Status = EFI_DEVICE_ERROR;
128 goto Exit;
129 }
130
131 CopyMem (&Data32, (BufferOut + 2), sizeof (UINT32));
132 TpmOutSize = SwapBytes32 (Data32);
133 if (*SizeOut < TpmOutSize) {
134 Status = EFI_BUFFER_TOO_SMALL;
135 goto Exit;
136 }
137 *SizeOut = TpmOutSize;
138 //
139 // Continue reading the remaining data
140 //
141 while ( Index < TpmOutSize ) {
142 for (; BurstCount > 0; BurstCount--) {
143 *(BufferOut + Index) = MmioRead8 ((UINTN)&TisReg->DataFifo);
144 Index++;
145 if (Index == TpmOutSize) {
146 Status = EFI_SUCCESS;
147 goto Exit;
148 }
149 }
150 Status = TisPcReadBurstCount (TisReg, &BurstCount);
151 if (EFI_ERROR (Status)) {
152 Status = EFI_TIMEOUT;
153 goto Exit;
154 }
155 }
156 Exit:
157 MmioWrite8((UINTN)&TisReg->Status, TIS_PC_STS_READY);
158 return Status;
159 }
160