EmbeddedPkg: drop unused Pcds from package .dsc
[mirror_edk2.git] / EmbeddedPkg / Library / HalRuntimeServicesExampleLib / Mtc.c
CommitLineData
2ef2b01e
A
1/** @file\r
2 Generic Monotonic Counter services\r
3\r
60274cca
HT
4 Copyright (c) 2007, Intel Corporation. All rights reserved.<BR>\r
5 Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
2ef2b01e 6\r
60274cca 7 This program and the accompanying materials\r
2ef2b01e
A
8 are licensed and made available under the terms and conditions of the BSD License\r
9 which accompanies this distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15\r
16**/\r
17\r
18\r
19//\r
20// The current Monotonic count value\r
21//\r
22UINT64 mEfiMtc = 0;\r
23\r
24\r
25//\r
26// Event to use to update the Mtc's high part when wrapping\r
27//\r
28EFI_EVENT mEfiMtcEvent;\r
29\r
30//\r
31// EfiMtcName - Variable name of the MTC value\r
32//\r
33CHAR16 *mEfiMtcName = L"MTC";\r
34\r
35//\r
36// EfiMtcGuid - Guid of the MTC value\r
37//\r
38EFI_GUID mEfiMtcGuid = { 0xeb704011, 0x1402, 0x11d3, { 0x8e, 0x77, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b } };\r
39\r
40\r
41\r
42//\r
43// Worker functions\r
44//\r
45\r
46\r
47VOID\r
48EFIAPI\r
49EfiMtcEventHandler (\r
50 IN EFI_EVENT Event,\r
51 IN VOID *Context\r
52 )\r
53/*++\r
54\r
55Routine Description:\r
56\r
57 Monotonic count event handler. This handler updates the high monotonic count.\r
58\r
59Arguments:\r
60\r
61 Event The event to handle\r
62 Context The event context\r
63\r
64Returns:\r
65\r
3402aac7 66 EFI_SUCCESS The event has been handled properly\r
2ef2b01e
A
67 EFI_NOT_FOUND An error occurred updating the variable.\r
68\r
69--*/\r
70{\r
71 UINT32 HighCount;\r
72\r
73 EfiGetNextHighMonotonicCount (&HighCount);\r
74 return;\r
75}\r
76\r
77\r
78\r
79VOID\r
80LibMtcVirtualAddressChangeEvent (VOID)\r
81{\r
82}\r
83\r
84\r
85EFI_STATUS\r
86EFIAPI\r
87LibMtcGetNextHighMonotonicCount (\r
88 OUT UINT32 *HighCount\r
89 )\r
90{\r
91 EFI_STATUS Status;\r
92 EFI_TPL OldTpl;\r
93\r
94 //\r
95 // Check input parameters\r
96 //\r
97 if (HighCount == NULL) {\r
98 return EFI_INVALID_PARAMETER;\r
99 }\r
100\r
101\r
102 if (!EfiAtRuntime ()) {\r
103 // Use a lock if called before ExitBootServices()\r
104 OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);\r
105 }\r
106\r
107 *HighCount = (UINT32) RShiftU64 (mEfiMtc, 32) + 1;\r
108 mEfiMtc = LShiftU64 (*HighCount, 32);\r
3402aac7 109\r
2ef2b01e
A
110 if (!EfiAtRuntime ()) {\r
111 gBS->RestoreTPL (OldTpl);\r
112 }\r
113\r
114 //\r
115 // Update the NvRam store to match the new high part\r
116 //\r
117 Status = EfiSetVariable (\r
118 mEfiMtcName,\r
119 &mEfiMtcGuid,\r
120 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
121 sizeof (UINT32),\r
122 HighCount\r
123 );\r
124\r
125 return Status;\r
126}\r
127\r
128\r
129EFI_STATUS\r
130LibMtcGetNextMonotonicCount (\r
131 OUT UINT64 *Count\r
132 )\r
133{\r
134 EFI_STATUS Status;\r
135 EFI_TPL OldTpl;\r
136 UINT32 HighCount;\r
137 UINTN BufferSize;\r
138\r
139 //\r
140 // Can not be called after ExitBootServices()\r
141 //\r
142 if (EfiAtRuntime ()) {\r
143 return EFI_UNSUPPORTED;\r
144 }\r
145\r
146 //\r
147 // Check input parameters\r
148 //\r
149 if (Count == NULL) {\r
150 return EFI_INVALID_PARAMETER;\r
151 }\r
152\r
153 if (mEfiMtc == 0) {\r
154 //\r
155 // If the MTC has not been initialized read the variable\r
156 //\r
157\r
158 //\r
159 // Read the last high part\r
160 //\r
161 BufferSize = sizeof (UINT32);\r
162 Status = EfiGetVariable (\r
163 mEfiMtcName,\r
164 &mEfiMtcGuid,\r
165 NULL,\r
166 &BufferSize,\r
167 &HighCount\r
168 );\r
169 if (EFI_ERROR (Status)) {\r
170 HighCount = 0;\r
171 }\r
172\r
173 //\r
174 // Set the current value\r
175 //\r
176 mEfiMtc = LShiftU64 (HighCount, 32);\r
177 //\r
178 // Increment the upper 32 bits for this boot\r
179 // Continue even if it fails. It will only fail if the variable services are\r
180 // not functional.\r
181 //\r
182 Status = EfiGetNextHighMonotonicCount (&HighCount);\r
183 }\r
184\r
185\r
186 //\r
187 // Update the monotonic counter with a lock\r
188 //\r
189 OldTpl = gBS->RaiseTPL (EFI_TPL_HIGH_LEVEL);\r
190 *Count = mEfiMtc;\r
191 mEfiMtc++;\r
192 gBS->RestoreTPL (OldTpl);\r
193\r
194 //\r
195 // If the MSB bit of the low part toggled, then signal that the high\r
196 // part needs updated now\r
197 //\r
198 if ((((UINT32) mEfiMtc) ^ ((UINT32) *Count)) & 0x80000000) {\r
199 gBS->SignalEvent (mEfiMtcEvent);\r
200 }\r
201\r
202 return EFI_SUCCESS;\r
203}\r
204\r
205\r
206\r
207VOID\r
208LibMtcInitialize (\r
209 VOID\r
210 )\r
211{\r
212 EFI_STATUS Status;\r
213\r
214 //\r
215 // Initialize event to handle overflows\r
216 //\r
217 Status = gBS->CreateEvent (\r
218 EVT_NOTIFY_SIGNAL,\r
219 EFI_TPL_CALLBACK,\r
220 EfiMtcEventHandler,\r
221 NULL,\r
222 &mEfiMtcEvent\r
223 );\r
224 ASSERT_EFI_ERROR (Status);\r
225}\r
226\r