]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/LockBox/SmmLockBox/SmmLockBox.c
MdeModulePkg: Add SMM LockBox
[mirror_edk2.git] / MdeModulePkg / Universal / LockBox / SmmLockBox / SmmLockBox.c
CommitLineData
1c837cd5 1/** @file\r
2\r
3Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>\r
4\r
5This program and the accompanying materials\r
6are licensed and made available under the terms and conditions\r
7of the BSD License which accompanies this distribution. The\r
8full text of the license may be found at\r
9http://opensource.org/licenses/bsd-license.php\r
10\r
11THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include <PiSmm.h>\r
17#include <Library/UefiDriverEntryPoint.h>\r
18#include <Library/UefiBootServicesTableLib.h>\r
19#include <Library/UefiRuntimeServicesTableLib.h>\r
20#include <Library/SmmServicesTableLib.h>\r
21#include <Library/BaseLib.h>\r
22#include <Library/BaseMemoryLib.h>\r
23#include <Library/DebugLib.h>\r
24#include <Library/LockBoxLib.h>\r
25#include <Protocol/SmmReadyToLock.h>\r
26#include <Protocol/SmmCommunication.h>\r
27#include <Protocol/SmmAccess2.h>\r
28#include <Protocol/LockBox.h>\r
29#include <Guid/SmmLockBox.h>\r
30\r
31BOOLEAN mLocked = FALSE;\r
32\r
33EFI_SMRAM_DESCRIPTOR *mSmramRanges;\r
34UINTN mSmramRangeCount;\r
35\r
36/**\r
37 This function check if the address is in SMRAM.\r
38\r
39 @param Buffer the buffer address to be checked.\r
40 @param Length the buffer length to be checked.\r
41\r
42 @retval TRUE this address is in SMRAM.\r
43 @retval FALSE this address is NOT in SMRAM.\r
44**/\r
45BOOLEAN\r
46IsAddressInSmram (\r
47 IN EFI_PHYSICAL_ADDRESS Buffer,\r
48 IN UINT64 Length\r
49 )\r
50{\r
51 UINTN Index;\r
52\r
53 for (Index = 0; Index < mSmramRangeCount; Index ++) {\r
54 if (((Buffer >= mSmramRanges[Index].CpuStart) && (Buffer < mSmramRanges[Index].CpuStart + mSmramRanges[Index].PhysicalSize)) ||\r
55 ((mSmramRanges[Index].CpuStart >= Buffer) && (mSmramRanges[Index].CpuStart < Buffer + Length))) {\r
56 return TRUE;\r
57 }\r
58 }\r
59\r
60 return FALSE;\r
61}\r
62\r
63/**\r
64 Dispatch function for SMM lock box save.\r
65\r
66 @param LockBoxParameterSave parameter of lock box save \r
67**/\r
68VOID\r
69SmmLockBoxSave (\r
70 IN EFI_SMM_LOCK_BOX_PARAMETER_SAVE *LockBoxParameterSave\r
71 )\r
72{\r
73 EFI_STATUS Status;\r
74\r
75 //\r
76 // Sanity check\r
77 //\r
78 if (mLocked) {\r
79 DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n"));\r
80 LockBoxParameterSave->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;\r
81 return ;\r
82 }\r
83\r
84 //\r
85 // Save data\r
86 //\r
87 Status = SaveLockBox (\r
88 &LockBoxParameterSave->Guid,\r
89 (VOID *)(UINTN)LockBoxParameterSave->Buffer,\r
90 (UINTN)LockBoxParameterSave->Length\r
91 );\r
92 LockBoxParameterSave->Header.ReturnStatus = (UINT64)Status;\r
93 return ;\r
94}\r
95\r
96/**\r
97 Dispatch function for SMM lock box set attributes.\r
98\r
99 @param LockBoxParameterSetAttributes parameter of lock box set attributes\r
100**/\r
101VOID\r
102SmmLockBoxSetAttributes (\r
103 IN EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *LockBoxParameterSetAttributes\r
104 )\r
105{\r
106 EFI_STATUS Status;\r
107\r
108 //\r
109 // Sanity check\r
110 //\r
111 if (mLocked) {\r
112 DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n"));\r
113 LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;\r
114 return ;\r
115 }\r
116\r
117 //\r
118 // Update data\r
119 //\r
120 Status = SetLockBoxAttributes (\r
121 &LockBoxParameterSetAttributes->Guid,\r
122 LockBoxParameterSetAttributes->Attributes\r
123 );\r
124 LockBoxParameterSetAttributes->Header.ReturnStatus = (UINT64)Status;\r
125 return ;\r
126}\r
127\r
128/**\r
129 Dispatch function for SMM lock box update.\r
130\r
131 @param LockBoxParameterUpdate parameter of lock box update \r
132**/\r
133VOID\r
134SmmLockBoxUpdate (\r
135 IN EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *LockBoxParameterUpdate\r
136 )\r
137{\r
138 EFI_STATUS Status;\r
139\r
140 //\r
141 // Sanity check\r
142 //\r
143 if (mLocked) {\r
144 DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n"));\r
145 LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;\r
146 return ;\r
147 }\r
148\r
149 //\r
150 // Update data\r
151 //\r
152 Status = UpdateLockBox (\r
153 &LockBoxParameterUpdate->Guid,\r
154 (UINTN)LockBoxParameterUpdate->Offset,\r
155 (VOID *)(UINTN)LockBoxParameterUpdate->Buffer,\r
156 (UINTN)LockBoxParameterUpdate->Length\r
157 );\r
158 LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)Status;\r
159 return ;\r
160}\r
161\r
162/**\r
163 Dispatch function for SMM lock box restore.\r
164\r
165 @param LockBoxParameterRestore parameter of lock box restore \r
166**/\r
167VOID\r
168SmmLockBoxRestore (\r
169 IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *LockBoxParameterRestore\r
170 )\r
171{\r
172 EFI_STATUS Status;\r
173\r
174 //\r
175 // Sanity check\r
176 //\r
177 if (IsAddressInSmram (LockBoxParameterRestore->Buffer, LockBoxParameterRestore->Length)) {\r
178 DEBUG ((EFI_D_ERROR, "SmmLockBox Restore address in SMRAM!\n"));\r
179 LockBoxParameterRestore->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED;\r
180 return ;\r
181 }\r
182\r
183 //\r
184 // Restore data\r
185 //\r
186 Status = RestoreLockBox (\r
187 &LockBoxParameterRestore->Guid,\r
188 (VOID *)(UINTN)LockBoxParameterRestore->Buffer,\r
189 (UINTN *)&LockBoxParameterRestore->Length\r
190 );\r
191 LockBoxParameterRestore->Header.ReturnStatus = (UINT64)Status;\r
192 return ;\r
193}\r
194\r
195/**\r
196 Dispatch function for SMM lock box restore all in place.\r
197\r
198 @param LockBoxParameterRestoreAllInPlace parameter of lock box restore all in place\r
199**/\r
200VOID\r
201SmmLockBoxRestoreAllInPlace (\r
202 IN EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *LockBoxParameterRestoreAllInPlace\r
203 )\r
204{\r
205 EFI_STATUS Status;\r
206\r
207 Status = RestoreAllLockBoxInPlace ();\r
208 LockBoxParameterRestoreAllInPlace->Header.ReturnStatus = (UINT64)Status;\r
209 return ;\r
210}\r
211\r
212/**\r
213 Dispatch function for a Software SMI handler.\r
214\r
215 @param DispatchHandle The unique handle assigned to this handler by SmiHandlerRegister().\r
216 @param Context Points to an optional handler context which was specified when the\r
217 handler was registered.\r
218 @param CommBuffer A pointer to a collection of data in memory that will\r
219 be conveyed from a non-SMM environment into an SMM environment.\r
220 @param CommBufferSize The size of the CommBuffer.\r
221\r
222 @retval EFI_SUCCESS Command is handled successfully.\r
223\r
224**/\r
225EFI_STATUS\r
226EFIAPI\r
227SmmLockBoxHandler (\r
228 IN EFI_HANDLE DispatchHandle,\r
229 IN CONST VOID *Context OPTIONAL,\r
230 IN OUT VOID *CommBuffer OPTIONAL,\r
231 IN OUT UINTN *CommBufferSize OPTIONAL\r
232 )\r
233{\r
234 EFI_SMM_LOCK_BOX_PARAMETER_HEADER *LockBoxParameterHeader;\r
235\r
236 DEBUG ((EFI_D_ERROR, "SmmLockBox SmmLockBoxHandler Enter\n"));\r
237\r
238 LockBoxParameterHeader = (EFI_SMM_LOCK_BOX_PARAMETER_HEADER *)((UINTN)CommBuffer);\r
239\r
240 LockBoxParameterHeader->ReturnStatus = (UINT64)-1;\r
241\r
242 DEBUG ((EFI_D_ERROR, "SmmLockBox LockBoxParameterHeader - %x\n", (UINTN)LockBoxParameterHeader));\r
243\r
244 DEBUG ((EFI_D_ERROR, "SmmLockBox Command - %x\n", (UINTN)LockBoxParameterHeader->Command));\r
245\r
246 switch (LockBoxParameterHeader->Command) {\r
247 case EFI_SMM_LOCK_BOX_COMMAND_SAVE:\r
248 SmmLockBoxSave ((EFI_SMM_LOCK_BOX_PARAMETER_SAVE *)(UINTN)LockBoxParameterHeader);\r
249 break;\r
250 case EFI_SMM_LOCK_BOX_COMMAND_UPDATE:\r
251 SmmLockBoxUpdate ((EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *)(UINTN)LockBoxParameterHeader);\r
252 break;\r
253 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE:\r
254 SmmLockBoxRestore ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)(UINTN)LockBoxParameterHeader);\r
255 break;\r
256 case EFI_SMM_LOCK_BOX_COMMAND_SET_ATTRIBUTES:\r
257 SmmLockBoxSetAttributes ((EFI_SMM_LOCK_BOX_PARAMETER_SET_ATTRIBUTES *)(UINTN)LockBoxParameterHeader);\r
258 break;\r
259 case EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE:\r
260 SmmLockBoxRestoreAllInPlace ((EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *)(UINTN)LockBoxParameterHeader);\r
261 break;\r
262 default:\r
263 break;\r
264 }\r
265\r
266 LockBoxParameterHeader->Command = (UINT32)-1;\r
267\r
268 DEBUG ((EFI_D_ERROR, "SmmLockBox SmmLockBoxHandler Exit\n"));\r
269\r
270 return EFI_SUCCESS;\r
271}\r
272\r
273/**\r
274 Smm Ready To Lock event notification handler.\r
275\r
276 It sets a flag indicating that SMRAM has been locked.\r
277 \r
278 @param[in] Protocol Points to the protocol's unique identifier.\r
279 @param[in] Interface Points to the interface instance.\r
280 @param[in] Handle The handle on which the interface was installed.\r
281\r
282 @retval EFI_SUCCESS Notification handler runs successfully.\r
283 **/\r
284EFI_STATUS\r
285EFIAPI\r
286SmmReadyToLockEventNotify (\r
287 IN CONST EFI_GUID *Protocol,\r
288 IN VOID *Interface,\r
289 IN EFI_HANDLE Handle\r
290 )\r
291{\r
292 mLocked = TRUE;\r
293 return EFI_SUCCESS;\r
294}\r
295\r
296/**\r
297 Entry Point for LockBox SMM driver.\r
298\r
299 @param[in] ImageHandle Image handle of this driver.\r
300 @param[in] SystemTable A Pointer to the EFI System Table.\r
301\r
302 @retval EFI_SUCEESS \r
303 @return Others Some error occurs.\r
304**/\r
305EFI_STATUS\r
306EFIAPI\r
307SmmLockBoxEntryPoint (\r
308 IN EFI_HANDLE ImageHandle,\r
309 IN EFI_SYSTEM_TABLE *SystemTable\r
310 )\r
311{\r
312 EFI_STATUS Status;\r
313 EFI_HANDLE DispatchHandle;\r
314 VOID *Registration;\r
315 EFI_SMM_ACCESS2_PROTOCOL *SmmAccess;\r
316 UINTN Size;\r
317\r
318 //\r
319 // Get SMRAM information\r
320 //\r
321 Status = gBS->LocateProtocol (&gEfiSmmAccess2ProtocolGuid, NULL, (VOID **)&SmmAccess);\r
322 ASSERT_EFI_ERROR (Status);\r
323\r
324 Size = 0;\r
325 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, NULL);\r
326 ASSERT (Status == EFI_BUFFER_TOO_SMALL);\r
327\r
328 Status = gSmst->SmmAllocatePool (\r
329 EfiRuntimeServicesData,\r
330 Size,\r
331 (VOID **)&mSmramRanges\r
332 );\r
333 ASSERT_EFI_ERROR (Status);\r
334\r
335 Status = SmmAccess->GetCapabilities (SmmAccess, &Size, mSmramRanges);\r
336 ASSERT_EFI_ERROR (Status);\r
337\r
338 mSmramRangeCount = Size / sizeof (EFI_SMRAM_DESCRIPTOR);\r
339\r
340 //\r
341 // Register LockBox communication handler\r
342 //\r
343 Status = gSmst->SmiHandlerRegister (\r
344 SmmLockBoxHandler,\r
345 &gEfiSmmLockBoxCommunicationGuid,\r
346 &DispatchHandle\r
347 );\r
348 ASSERT_EFI_ERROR (Status);\r
349\r
350 //\r
351 // Register SMM Ready To Lock Protocol notification\r
352 //\r
353 Status = gSmst->SmmRegisterProtocolNotify (\r
354 &gEfiSmmReadyToLockProtocolGuid,\r
355 SmmReadyToLockEventNotify,\r
356 &Registration\r
357 );\r
358 ASSERT_EFI_ERROR (Status);\r
359\r
360 //\r
361 // Install NULL to DXE data base as notify\r
362 //\r
363 ImageHandle = NULL;\r
364 Status = gBS->InstallProtocolInterface (\r
365 &ImageHandle,\r
366 &gEfiLockBoxProtocolGuid,\r
367 EFI_NATIVE_INTERFACE,\r
368 NULL\r
369 );\r
370 ASSERT_EFI_ERROR (Status);\r
371\r
372 return Status;\r
373}\r