Vishal Bhoj | 82c8071 | 2015-12-15 21:13:33 +0530 | [diff] [blame^] | 1 | /** @file
|
| 2 |
|
| 3 | Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
|
| 4 |
|
| 5 | This program and the accompanying materials
|
| 6 | are licensed and made available under the terms and conditions
|
| 7 | of the BSD License which accompanies this distribution. The
|
| 8 | full text of the license may be found at
|
| 9 | http://opensource.org/licenses/bsd-license.php
|
| 10 |
|
| 11 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
| 12 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
| 13 |
|
| 14 | **/
|
| 15 |
|
| 16 | #include <PiPei.h>
|
| 17 | #include <PiDxe.h>
|
| 18 | #include <PiSmm.h>
|
| 19 | #include <Library/PeiServicesTablePointerLib.h>
|
| 20 | #include <Library/PeiServicesLib.h>
|
| 21 | #include <Library/BaseLib.h>
|
| 22 | #include <Library/BaseMemoryLib.h>
|
| 23 | #include <Library/LockBoxLib.h>
|
| 24 | #include <Library/HobLib.h>
|
| 25 | #include <Library/DebugLib.h>
|
| 26 | #include <Library/PcdLib.h>
|
| 27 | #include <Protocol/SmmCommunication.h>
|
| 28 | #include <Ppi/SmmCommunication.h>
|
| 29 | #include <Ppi/SmmAccess.h>
|
| 30 | #include <Guid/AcpiS3Context.h>
|
| 31 | #include <Guid/SmmLockBox.h>
|
| 32 |
|
| 33 | #include "SmmLockBoxLibPrivate.h"
|
| 34 |
|
| 35 | #if defined (MDE_CPU_IA32)
|
| 36 | typedef struct _LIST_ENTRY64 LIST_ENTRY64;
|
| 37 | struct _LIST_ENTRY64 {
|
| 38 | LIST_ENTRY64 *ForwardLink;
|
| 39 | UINT32 Reserved1;
|
| 40 | LIST_ENTRY64 *BackLink;
|
| 41 | UINT32 Reserved2;
|
| 42 | };
|
| 43 |
|
| 44 | typedef struct {
|
| 45 | EFI_TABLE_HEADER Hdr;
|
| 46 | UINT64 SmmFirmwareVendor;
|
| 47 | UINT64 SmmFirmwareRevision;
|
| 48 | UINT64 SmmInstallConfigurationTable;
|
| 49 | UINT64 SmmIoMemRead;
|
| 50 | UINT64 SmmIoMemWrite;
|
| 51 | UINT64 SmmIoIoRead;
|
| 52 | UINT64 SmmIoIoWrite;
|
| 53 | UINT64 SmmAllocatePool;
|
| 54 | UINT64 SmmFreePool;
|
| 55 | UINT64 SmmAllocatePages;
|
| 56 | UINT64 SmmFreePages;
|
| 57 | UINT64 SmmStartupThisAp;
|
| 58 | UINT64 CurrentlyExecutingCpu;
|
| 59 | UINT64 NumberOfCpus;
|
| 60 | UINT64 CpuSaveStateSize;
|
| 61 | UINT64 CpuSaveState;
|
| 62 | UINT64 NumberOfTableEntries;
|
| 63 | UINT64 SmmConfigurationTable;
|
| 64 | } EFI_SMM_SYSTEM_TABLE2_64;
|
| 65 |
|
| 66 | typedef struct {
|
| 67 | EFI_GUID VendorGuid;
|
| 68 | UINT64 VendorTable;
|
| 69 | } EFI_CONFIGURATION_TABLE64;
|
| 70 | #endif
|
| 71 |
|
| 72 | #if defined (MDE_CPU_X64)
|
| 73 | typedef LIST_ENTRY LIST_ENTRY64;
|
| 74 | typedef EFI_SMM_SYSTEM_TABLE2 EFI_SMM_SYSTEM_TABLE2_64;
|
| 75 | typedef EFI_CONFIGURATION_TABLE EFI_CONFIGURATION_TABLE64;
|
| 76 | #endif
|
| 77 |
|
| 78 | /**
|
| 79 | This function return first node of LinkList queue.
|
| 80 |
|
| 81 | @param LockBoxQueue LinkList queue
|
| 82 |
|
| 83 | @return first node of LinkList queue
|
| 84 | **/
|
| 85 | LIST_ENTRY *
|
| 86 | InternalInitLinkDxe (
|
| 87 | IN LIST_ENTRY *LinkList
|
| 88 | )
|
| 89 | {
|
| 90 | if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) {
|
| 91 | //
|
| 92 | // 32 PEI + 64 DXE
|
| 93 | //
|
| 94 | return (LIST_ENTRY *)(((LIST_ENTRY64 *)LinkList)->ForwardLink);
|
| 95 | } else {
|
| 96 | return LinkList->ForwardLink;
|
| 97 | }
|
| 98 | }
|
| 99 |
|
| 100 | /**
|
| 101 | This function return next node of LinkList.
|
| 102 |
|
| 103 | @param Link LinkList node
|
| 104 |
|
| 105 | @return next node of LinkList
|
| 106 | **/
|
| 107 | LIST_ENTRY *
|
| 108 | InternalNextLinkDxe (
|
| 109 | IN LIST_ENTRY *Link
|
| 110 | )
|
| 111 | {
|
| 112 | if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) {
|
| 113 | //
|
| 114 | // 32 PEI + 64 DXE
|
| 115 | //
|
| 116 | return (LIST_ENTRY *)(((LIST_ENTRY64 *)Link)->ForwardLink);
|
| 117 | } else {
|
| 118 | return Link->ForwardLink;
|
| 119 | }
|
| 120 | }
|
| 121 |
|
| 122 | /**
|
| 123 | This function find LockBox by GUID from SMRAM.
|
| 124 |
|
| 125 | @param LockBoxQueue The LockBox queue in SMRAM
|
| 126 | @param Guid The guid to indentify the LockBox
|
| 127 |
|
| 128 | @return LockBoxData
|
| 129 | **/
|
| 130 | SMM_LOCK_BOX_DATA *
|
| 131 | InternalFindLockBoxByGuidFromSmram (
|
| 132 | IN LIST_ENTRY *LockBoxQueue,
|
| 133 | IN EFI_GUID *Guid
|
| 134 | )
|
| 135 | {
|
| 136 | LIST_ENTRY *Link;
|
| 137 | SMM_LOCK_BOX_DATA *LockBox;
|
| 138 |
|
| 139 | for (Link = InternalInitLinkDxe (LockBoxQueue);
|
| 140 | Link != LockBoxQueue;
|
| 141 | Link = InternalNextLinkDxe (Link)) {
|
| 142 | LockBox = BASE_CR (
|
| 143 | Link,
|
| 144 | SMM_LOCK_BOX_DATA,
|
| 145 | Link
|
| 146 | );
|
| 147 | if (CompareGuid (&LockBox->Guid, Guid)) {
|
| 148 | return LockBox;
|
| 149 | }
|
| 150 | }
|
| 151 | return NULL;
|
| 152 | }
|
| 153 |
|
| 154 | /**
|
| 155 | Get VendorTable by VendorGuid in Smst.
|
| 156 |
|
| 157 | @param Signature Signature of SMM_S3_RESUME_STATE
|
| 158 | @param Smst SMM system table
|
| 159 | @param VendorGuid vendor guid
|
| 160 |
|
| 161 | @return vendor table.
|
| 162 | **/
|
| 163 | VOID *
|
| 164 | InternalSmstGetVendorTableByGuid (
|
| 165 | IN UINT64 Signature,
|
| 166 | IN EFI_SMM_SYSTEM_TABLE2 *Smst,
|
| 167 | IN EFI_GUID *VendorGuid
|
| 168 | )
|
| 169 | {
|
| 170 | EFI_CONFIGURATION_TABLE *SmmConfigurationTable;
|
| 171 | UINTN NumberOfTableEntries;
|
| 172 | UINTN Index;
|
| 173 | EFI_SMM_SYSTEM_TABLE2_64 *Smst64;
|
| 174 | EFI_CONFIGURATION_TABLE64 *SmmConfigurationTable64;
|
| 175 |
|
| 176 | if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode))) {
|
| 177 | //
|
| 178 | // 32 PEI + 64 DXE
|
| 179 | //
|
| 180 | Smst64 = (EFI_SMM_SYSTEM_TABLE2_64 *)Smst;
|
| 181 | SmmConfigurationTable64 = (EFI_CONFIGURATION_TABLE64 *)(UINTN)Smst64->SmmConfigurationTable;
|
| 182 | NumberOfTableEntries = (UINTN)Smst64->NumberOfTableEntries;
|
| 183 | for (Index = 0; Index < NumberOfTableEntries; Index++) {
|
| 184 | if (CompareGuid (&SmmConfigurationTable64[Index].VendorGuid, VendorGuid)) {
|
| 185 | return (VOID *)(UINTN)SmmConfigurationTable64[Index].VendorTable;
|
| 186 | }
|
| 187 | }
|
| 188 | return NULL;
|
| 189 | } else {
|
| 190 | SmmConfigurationTable = Smst->SmmConfigurationTable;
|
| 191 | NumberOfTableEntries = Smst->NumberOfTableEntries;
|
| 192 | for (Index = 0; Index < NumberOfTableEntries; Index++) {
|
| 193 | if (CompareGuid (&SmmConfigurationTable[Index].VendorGuid, VendorGuid)) {
|
| 194 | return (VOID *)SmmConfigurationTable[Index].VendorTable;
|
| 195 | }
|
| 196 | }
|
| 197 | return NULL;
|
| 198 | }
|
| 199 | }
|
| 200 |
|
| 201 | /**
|
| 202 | Get SMM LockBox context.
|
| 203 |
|
| 204 | @return SMM LockBox context.
|
| 205 | **/
|
| 206 | SMM_LOCK_BOX_CONTEXT *
|
| 207 | InternalGetSmmLockBoxContext (
|
| 208 | VOID
|
| 209 | )
|
| 210 | {
|
| 211 | EFI_SMRAM_DESCRIPTOR *SmramDescriptor;
|
| 212 | SMM_S3_RESUME_STATE *SmmS3ResumeState;
|
| 213 | VOID *GuidHob;
|
| 214 | SMM_LOCK_BOX_CONTEXT *SmmLockBoxContext;
|
| 215 |
|
| 216 | GuidHob = GetFirstGuidHob (&gEfiAcpiVariableGuid);
|
| 217 | ASSERT (GuidHob != NULL);
|
| 218 | SmramDescriptor = (EFI_SMRAM_DESCRIPTOR *) GET_GUID_HOB_DATA (GuidHob);
|
| 219 | SmmS3ResumeState = (SMM_S3_RESUME_STATE *)(UINTN)SmramDescriptor->CpuStart;
|
| 220 |
|
| 221 | SmmLockBoxContext = (SMM_LOCK_BOX_CONTEXT *)InternalSmstGetVendorTableByGuid (
|
| 222 | SmmS3ResumeState->Signature,
|
| 223 | (EFI_SMM_SYSTEM_TABLE2 *)(UINTN)SmmS3ResumeState->Smst,
|
| 224 | &gEfiSmmLockBoxCommunicationGuid
|
| 225 | );
|
| 226 | ASSERT (SmmLockBoxContext != NULL);
|
| 227 |
|
| 228 | return SmmLockBoxContext;
|
| 229 | }
|
| 230 |
|
| 231 | /**
|
| 232 | This function will restore confidential information from lockbox in SMRAM directly.
|
| 233 |
|
| 234 | @param Guid the guid to identify the confidential information
|
| 235 | @param Buffer the address of the restored confidential information
|
| 236 | NULL means restored to original address, Length MUST be NULL at same time.
|
| 237 | @param Length the length of the restored confidential information
|
| 238 |
|
| 239 | @retval RETURN_SUCCESS the information is restored successfully.
|
| 240 | @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox has no
|
| 241 | LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE attribute.
|
| 242 | @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the confidential information.
|
| 243 | @retval RETURN_NOT_FOUND the requested GUID not found.
|
| 244 | **/
|
| 245 | EFI_STATUS
|
| 246 | InternalRestoreLockBoxFromSmram (
|
| 247 | IN GUID *Guid,
|
| 248 | IN VOID *Buffer, OPTIONAL
|
| 249 | IN OUT UINTN *Length OPTIONAL
|
| 250 | )
|
| 251 | {
|
| 252 | PEI_SMM_ACCESS_PPI *SmmAccess;
|
| 253 | UINTN Index;
|
| 254 | EFI_STATUS Status;
|
| 255 | SMM_LOCK_BOX_CONTEXT *SmmLockBoxContext;
|
| 256 | LIST_ENTRY *LockBoxQueue;
|
| 257 | SMM_LOCK_BOX_DATA *LockBox;
|
| 258 | VOID *RestoreBuffer;
|
| 259 |
|
| 260 | //
|
| 261 | // Get needed resource
|
| 262 | //
|
| 263 | Status = PeiServicesLocatePpi (
|
| 264 | &gPeiSmmAccessPpiGuid,
|
| 265 | 0,
|
| 266 | NULL,
|
| 267 | (VOID **)&SmmAccess
|
| 268 | );
|
| 269 | if (!EFI_ERROR (Status)) {
|
| 270 | for (Index = 0; !EFI_ERROR (Status); Index++) {
|
| 271 | Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
|
| 272 | }
|
| 273 | }
|
| 274 |
|
| 275 | //
|
| 276 | // Get LockBox context
|
| 277 | //
|
| 278 | SmmLockBoxContext = InternalGetSmmLockBoxContext ();
|
| 279 | LockBoxQueue = (LIST_ENTRY *)(UINTN)SmmLockBoxContext->LockBoxDataAddress;
|
| 280 |
|
| 281 | //
|
| 282 | // We do NOT check Buffer address in SMRAM, because if SMRAM not locked, we trust the caller.
|
| 283 | //
|
| 284 |
|
| 285 | //
|
| 286 | // Restore this, Buffer and Length MUST be both NULL or both non-NULL
|
| 287 | //
|
| 288 |
|
| 289 | //
|
| 290 | // Find LockBox
|
| 291 | //
|
| 292 | LockBox = InternalFindLockBoxByGuidFromSmram (LockBoxQueue, Guid);
|
| 293 | if (LockBox == NULL) {
|
| 294 | //
|
| 295 | // Not found
|
| 296 | //
|
| 297 | return EFI_NOT_FOUND;
|
| 298 | }
|
| 299 |
|
| 300 | //
|
| 301 | // Set RestoreBuffer
|
| 302 | //
|
| 303 | if (Buffer != NULL) {
|
| 304 | //
|
| 305 | // restore to new buffer
|
| 306 | //
|
| 307 | RestoreBuffer = Buffer;
|
| 308 | } else {
|
| 309 | //
|
| 310 | // restore to original buffer
|
| 311 | //
|
| 312 | if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) == 0) {
|
| 313 | return EFI_WRITE_PROTECTED;
|
| 314 | }
|
| 315 | RestoreBuffer = (VOID *)(UINTN)LockBox->Buffer;
|
| 316 | }
|
| 317 |
|
| 318 | //
|
| 319 | // Set RestoreLength
|
| 320 | //
|
| 321 | if (Length != NULL) {
|
| 322 | if (*Length < (UINTN)LockBox->Length) {
|
| 323 | //
|
| 324 | // Input buffer is too small to hold all data.
|
| 325 | //
|
| 326 | *Length = (UINTN)LockBox->Length;
|
| 327 | return EFI_BUFFER_TOO_SMALL;
|
| 328 | }
|
| 329 | *Length = (UINTN)LockBox->Length;
|
| 330 | }
|
| 331 |
|
| 332 | //
|
| 333 | // Restore data
|
| 334 | //
|
| 335 | CopyMem (RestoreBuffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);
|
| 336 |
|
| 337 | //
|
| 338 | // Done
|
| 339 | //
|
| 340 | return EFI_SUCCESS;
|
| 341 | }
|
| 342 |
|
| 343 | /**
|
| 344 | This function will restore confidential information from all lockbox which have RestoreInPlace attribute.
|
| 345 |
|
| 346 | @retval RETURN_SUCCESS the information is restored successfully.
|
| 347 | **/
|
| 348 | EFI_STATUS
|
| 349 | InternalRestoreAllLockBoxInPlaceFromSmram (
|
| 350 | VOID
|
| 351 | )
|
| 352 | {
|
| 353 | PEI_SMM_ACCESS_PPI *SmmAccess;
|
| 354 | UINTN Index;
|
| 355 | EFI_STATUS Status;
|
| 356 | SMM_LOCK_BOX_CONTEXT *SmmLockBoxContext;
|
| 357 | LIST_ENTRY *LockBoxQueue;
|
| 358 | SMM_LOCK_BOX_DATA *LockBox;
|
| 359 | LIST_ENTRY *Link;
|
| 360 |
|
| 361 | //
|
| 362 | // Get needed resource
|
| 363 | //
|
| 364 | Status = PeiServicesLocatePpi (
|
| 365 | &gPeiSmmAccessPpiGuid,
|
| 366 | 0,
|
| 367 | NULL,
|
| 368 | (VOID **)&SmmAccess
|
| 369 | );
|
| 370 | if (!EFI_ERROR (Status)) {
|
| 371 | for (Index = 0; !EFI_ERROR (Status); Index++) {
|
| 372 | Status = SmmAccess->Open ((EFI_PEI_SERVICES **)GetPeiServicesTablePointer (), SmmAccess, Index);
|
| 373 | }
|
| 374 | }
|
| 375 |
|
| 376 | //
|
| 377 | // Get LockBox context
|
| 378 | //
|
| 379 | SmmLockBoxContext = InternalGetSmmLockBoxContext ();
|
| 380 | LockBoxQueue = (LIST_ENTRY *)(UINTN)SmmLockBoxContext->LockBoxDataAddress;
|
| 381 |
|
| 382 | //
|
| 383 | // We do NOT check Buffer address in SMRAM, because if SMRAM not locked, we trust the caller.
|
| 384 | //
|
| 385 |
|
| 386 | //
|
| 387 | // Restore all, Buffer and Length MUST be NULL
|
| 388 | //
|
| 389 | for (Link = InternalInitLinkDxe (LockBoxQueue);
|
| 390 | Link != LockBoxQueue;
|
| 391 | Link = InternalNextLinkDxe (Link)) {
|
| 392 | LockBox = BASE_CR (
|
| 393 | Link,
|
| 394 | SMM_LOCK_BOX_DATA,
|
| 395 | Link
|
| 396 | );
|
| 397 | if ((LockBox->Attributes & LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE) != 0) {
|
| 398 | //
|
| 399 | // Restore data
|
| 400 | //
|
| 401 | CopyMem ((VOID *)(UINTN)LockBox->Buffer, (VOID *)(UINTN)LockBox->SmramBuffer, (UINTN)LockBox->Length);
|
| 402 | }
|
| 403 | }
|
| 404 | //
|
| 405 | // Done
|
| 406 | //
|
| 407 | return EFI_SUCCESS;
|
| 408 | }
|
| 409 |
|
| 410 | /**
|
| 411 | This function will save confidential information to lockbox.
|
| 412 |
|
| 413 | @param Guid the guid to identify the confidential information
|
| 414 | @param Buffer the address of the confidential information
|
| 415 | @param Length the length of the confidential information
|
| 416 |
|
| 417 | @retval RETURN_SUCCESS the information is saved successfully.
|
| 418 | @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0
|
| 419 | @retval RETURN_ALREADY_STARTED the requested GUID already exist.
|
| 420 | @retval RETURN_OUT_OF_RESOURCES no enough resource to save the information.
|
| 421 | @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
|
| 422 | @retval RETURN_NOT_STARTED it is too early to invoke this interface
|
| 423 | @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
|
| 424 | **/
|
| 425 | RETURN_STATUS
|
| 426 | EFIAPI
|
| 427 | SaveLockBox (
|
| 428 | IN GUID *Guid,
|
| 429 | IN VOID *Buffer,
|
| 430 | IN UINTN Length
|
| 431 | )
|
| 432 | {
|
| 433 | ASSERT (FALSE);
|
| 434 |
|
| 435 | //
|
| 436 | // No support to save at PEI phase
|
| 437 | //
|
| 438 | return RETURN_UNSUPPORTED;
|
| 439 | }
|
| 440 |
|
| 441 | /**
|
| 442 | This function will set lockbox attributes.
|
| 443 |
|
| 444 | @param Guid the guid to identify the confidential information
|
| 445 | @param Attributes the attributes of the lockbox
|
| 446 |
|
| 447 | @retval RETURN_SUCCESS the information is saved successfully.
|
| 448 | @retval RETURN_INVALID_PARAMETER attributes is invalid.
|
| 449 | @retval RETURN_NOT_FOUND the requested GUID not found.
|
| 450 | @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
|
| 451 | @retval RETURN_NOT_STARTED it is too early to invoke this interface
|
| 452 | @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
|
| 453 | **/
|
| 454 | RETURN_STATUS
|
| 455 | EFIAPI
|
| 456 | SetLockBoxAttributes (
|
| 457 | IN GUID *Guid,
|
| 458 | IN UINT64 Attributes
|
| 459 | )
|
| 460 | {
|
| 461 | ASSERT (FALSE);
|
| 462 |
|
| 463 | //
|
| 464 | // No support to save at PEI phase
|
| 465 | //
|
| 466 | return RETURN_UNSUPPORTED;
|
| 467 | }
|
| 468 |
|
| 469 | /**
|
| 470 | This function will update confidential information to lockbox.
|
| 471 |
|
| 472 | @param Guid the guid to identify the original confidential information
|
| 473 | @param Offset the offset of the original confidential information
|
| 474 | @param Buffer the address of the updated confidential information
|
| 475 | @param Length the length of the updated confidential information
|
| 476 |
|
| 477 | @retval RETURN_SUCCESS the information is saved successfully.
|
| 478 | @retval RETURN_INVALID_PARAMETER the Guid is NULL, or Buffer is NULL, or Length is 0.
|
| 479 | @retval RETURN_NOT_FOUND the requested GUID not found.
|
| 480 | @retval RETURN_BUFFER_TOO_SMALL the original buffer to too small to hold new information.
|
| 481 | @retval RETURN_ACCESS_DENIED it is too late to invoke this interface
|
| 482 | @retval RETURN_NOT_STARTED it is too early to invoke this interface
|
| 483 | @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
|
| 484 | **/
|
| 485 | RETURN_STATUS
|
| 486 | EFIAPI
|
| 487 | UpdateLockBox (
|
| 488 | IN GUID *Guid,
|
| 489 | IN UINTN Offset,
|
| 490 | IN VOID *Buffer,
|
| 491 | IN UINTN Length
|
| 492 | )
|
| 493 | {
|
| 494 | ASSERT (FALSE);
|
| 495 |
|
| 496 | //
|
| 497 | // No support to update at PEI phase
|
| 498 | //
|
| 499 | return RETURN_UNSUPPORTED;
|
| 500 | }
|
| 501 |
|
| 502 | /**
|
| 503 | This function will restore confidential information from lockbox.
|
| 504 |
|
| 505 | @param Guid the guid to identify the confidential information
|
| 506 | @param Buffer the address of the restored confidential information
|
| 507 | NULL means restored to original address, Length MUST be NULL at same time.
|
| 508 | @param Length the length of the restored confidential information
|
| 509 |
|
| 510 | @retval RETURN_SUCCESS the information is restored successfully.
|
| 511 | @retval RETURN_INVALID_PARAMETER the Guid is NULL, or one of Buffer and Length is NULL.
|
| 512 | @retval RETURN_WRITE_PROTECTED Buffer and Length are NULL, but the LockBox has no
|
| 513 | LOCK_BOX_ATTRIBUTE_RESTORE_IN_PLACE attribute.
|
| 514 | @retval RETURN_BUFFER_TOO_SMALL the Length is too small to hold the confidential information.
|
| 515 | @retval RETURN_NOT_FOUND the requested GUID not found.
|
| 516 | @retval RETURN_NOT_STARTED it is too early to invoke this interface
|
| 517 | @retval RETURN_ACCESS_DENIED not allow to restore to the address
|
| 518 | @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
|
| 519 | **/
|
| 520 | RETURN_STATUS
|
| 521 | EFIAPI
|
| 522 | RestoreLockBox (
|
| 523 | IN GUID *Guid,
|
| 524 | IN VOID *Buffer, OPTIONAL
|
| 525 | IN OUT UINTN *Length OPTIONAL
|
| 526 | )
|
| 527 | {
|
| 528 | EFI_STATUS Status;
|
| 529 | EFI_PEI_SMM_COMMUNICATION_PPI *SmmCommunicationPpi;
|
| 530 | EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *LockBoxParameterRestore;
|
| 531 | EFI_SMM_COMMUNICATE_HEADER *CommHeader;
|
| 532 | UINT8 CommBuffer[sizeof(EFI_GUID) + sizeof(UINT64) + sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE)];
|
| 533 | UINTN CommSize;
|
| 534 | UINT64 MessageLength;
|
| 535 |
|
| 536 | //
|
| 537 | // Please aware that there is UINTN in EFI_SMM_COMMUNICATE_HEADER. It might be UINT64 in DXE, while it is UINT32 in PEI.
|
| 538 | // typedef struct {
|
| 539 | // EFI_GUID HeaderGuid;
|
| 540 | // UINTN MessageLength;
|
| 541 | // UINT8 Data[1];
|
| 542 | // } EFI_SMM_COMMUNICATE_HEADER;
|
| 543 | //
|
| 544 |
|
| 545 | DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib RestoreLockBox - Enter\n"));
|
| 546 |
|
| 547 | //
|
| 548 | // Basic check
|
| 549 | //
|
| 550 | if ((Guid == NULL) ||
|
| 551 | ((Buffer == NULL) && (Length != NULL)) ||
|
| 552 | ((Buffer != NULL) && (Length == NULL))) {
|
| 553 | return EFI_INVALID_PARAMETER;
|
| 554 | }
|
| 555 |
|
| 556 | //
|
| 557 | // Get needed resource
|
| 558 | //
|
| 559 | Status = PeiServicesLocatePpi (
|
| 560 | &gEfiPeiSmmCommunicationPpiGuid,
|
| 561 | 0,
|
| 562 | NULL,
|
| 563 | (VOID **)&SmmCommunicationPpi
|
| 564 | );
|
| 565 | if (EFI_ERROR (Status)) {
|
| 566 | return EFI_NOT_STARTED;
|
| 567 | }
|
| 568 |
|
| 569 | //
|
| 570 | // Prepare parameter
|
| 571 | //
|
| 572 | CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];
|
| 573 | CopyMem (&CommHeader->HeaderGuid, &gEfiSmmLockBoxCommunicationGuid, sizeof(gEfiSmmLockBoxCommunicationGuid));
|
| 574 | if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) {
|
| 575 | MessageLength = sizeof(*LockBoxParameterRestore);
|
| 576 | CopyMem (&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength)], &MessageLength, sizeof(MessageLength));
|
| 577 | } else {
|
| 578 | CommHeader->MessageLength = sizeof(*LockBoxParameterRestore);
|
| 579 | }
|
| 580 |
|
| 581 | DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib CommBuffer - %x\n", &CommBuffer[0]));
|
| 582 | if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) {
|
| 583 | LockBoxParameterRestore = (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength) + sizeof(UINT64)];
|
| 584 | } else {
|
| 585 | LockBoxParameterRestore = (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength) + sizeof(UINTN)];
|
| 586 | }
|
| 587 | DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib LockBoxParameterRestore - %x\n", LockBoxParameterRestore));
|
| 588 | LockBoxParameterRestore->Header.Command = EFI_SMM_LOCK_BOX_COMMAND_RESTORE;
|
| 589 | LockBoxParameterRestore->Header.DataLength = sizeof(*LockBoxParameterRestore);
|
| 590 | LockBoxParameterRestore->Header.ReturnStatus = (UINT64)-1;
|
| 591 | if (Guid != 0) {
|
| 592 | CopyMem (&LockBoxParameterRestore->Guid, Guid, sizeof(*Guid));
|
| 593 | } else {
|
| 594 | ZeroMem (&LockBoxParameterRestore->Guid, sizeof(*Guid));
|
| 595 | }
|
| 596 | LockBoxParameterRestore->Buffer = (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer;
|
| 597 | if (Length != NULL) {
|
| 598 | LockBoxParameterRestore->Length = (EFI_PHYSICAL_ADDRESS)*Length;
|
| 599 | } else {
|
| 600 | LockBoxParameterRestore->Length = 0;
|
| 601 | }
|
| 602 |
|
| 603 | //
|
| 604 | // Send command
|
| 605 | //
|
| 606 | CommSize = sizeof(CommBuffer);
|
| 607 | Status = SmmCommunicationPpi->Communicate (
|
| 608 | SmmCommunicationPpi,
|
| 609 | &CommBuffer[0],
|
| 610 | &CommSize
|
| 611 | );
|
| 612 | if (Status == EFI_NOT_STARTED) {
|
| 613 | //
|
| 614 | // Pei SMM communication not ready yet, so we access SMRAM directly
|
| 615 | //
|
| 616 | DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib Communicate - (%r)\n", Status));
|
| 617 | Status = InternalRestoreLockBoxFromSmram (Guid, Buffer, Length);
|
| 618 | LockBoxParameterRestore->Header.ReturnStatus = (UINT64)Status;
|
| 619 | if (Length != NULL) {
|
| 620 | LockBoxParameterRestore->Length = (UINT64)*Length;
|
| 621 | }
|
| 622 | }
|
| 623 | ASSERT_EFI_ERROR (Status);
|
| 624 |
|
| 625 | if (Length != NULL) {
|
| 626 | *Length = (UINTN)LockBoxParameterRestore->Length;
|
| 627 | }
|
| 628 |
|
| 629 | Status = (EFI_STATUS)LockBoxParameterRestore->Header.ReturnStatus;
|
| 630 | if (Status != EFI_SUCCESS) {
|
| 631 | // Need or MAX_BIT, because there might be case that SMM is X64 while PEI is IA32.
|
| 632 | Status |= MAX_BIT;
|
| 633 | }
|
| 634 |
|
| 635 | DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib RestoreLockBox - Exit (%r)\n", Status));
|
| 636 |
|
| 637 | //
|
| 638 | // Done
|
| 639 | //
|
| 640 | return Status;
|
| 641 | }
|
| 642 |
|
| 643 | /**
|
| 644 | This function will restore confidential information from all lockbox which have RestoreInPlace attribute.
|
| 645 |
|
| 646 | @retval RETURN_SUCCESS the information is restored successfully.
|
| 647 | @retval RETURN_NOT_STARTED it is too early to invoke this interface
|
| 648 | @retval RETURN_UNSUPPORTED the service is not supported by implementaion.
|
| 649 | **/
|
| 650 | RETURN_STATUS
|
| 651 | EFIAPI
|
| 652 | RestoreAllLockBoxInPlace (
|
| 653 | VOID
|
| 654 | )
|
| 655 | {
|
| 656 | EFI_STATUS Status;
|
| 657 | EFI_PEI_SMM_COMMUNICATION_PPI *SmmCommunicationPpi;
|
| 658 | EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *LockBoxParameterRestoreAllInPlace;
|
| 659 | EFI_SMM_COMMUNICATE_HEADER *CommHeader;
|
| 660 | UINT8 CommBuffer[sizeof(EFI_GUID) + sizeof(UINT64) + sizeof(EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE)];
|
| 661 | UINTN CommSize;
|
| 662 | UINT64 MessageLength;
|
| 663 |
|
| 664 | //
|
| 665 | // Please aware that there is UINTN in EFI_SMM_COMMUNICATE_HEADER. It might be UINT64 in DXE, while it is UINT32 in PEI.
|
| 666 | // typedef struct {
|
| 667 | // EFI_GUID HeaderGuid;
|
| 668 | // UINTN MessageLength;
|
| 669 | // UINT8 Data[1];
|
| 670 | // } EFI_SMM_COMMUNICATE_HEADER;
|
| 671 | //
|
| 672 |
|
| 673 | DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib RestoreAllLockBoxInPlace - Enter\n"));
|
| 674 |
|
| 675 | //
|
| 676 | // Get needed resource
|
| 677 | //
|
| 678 | Status = PeiServicesLocatePpi (
|
| 679 | &gEfiPeiSmmCommunicationPpiGuid,
|
| 680 | 0,
|
| 681 | NULL,
|
| 682 | (VOID **)&SmmCommunicationPpi
|
| 683 | );
|
| 684 | if (EFI_ERROR (Status)) {
|
| 685 | return EFI_NOT_STARTED;
|
| 686 | }
|
| 687 |
|
| 688 | //
|
| 689 | // Prepare parameter
|
| 690 | //
|
| 691 | CommHeader = (EFI_SMM_COMMUNICATE_HEADER *)&CommBuffer[0];
|
| 692 | CopyMem (&CommHeader->HeaderGuid, &gEfiSmmLockBoxCommunicationGuid, sizeof(gEfiSmmLockBoxCommunicationGuid));
|
| 693 | if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) {
|
| 694 | MessageLength = sizeof(*LockBoxParameterRestoreAllInPlace);
|
| 695 | CopyMem (&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength)], &MessageLength, sizeof(MessageLength));
|
| 696 | } else {
|
| 697 | CommHeader->MessageLength = sizeof(*LockBoxParameterRestoreAllInPlace);
|
| 698 | }
|
| 699 |
|
| 700 | if ((sizeof(UINTN) == sizeof(UINT32)) && (FeaturePcdGet (PcdDxeIplSwitchToLongMode)) ) {
|
| 701 | LockBoxParameterRestoreAllInPlace = (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength) + sizeof(UINT64)];
|
| 702 | } else {
|
| 703 | LockBoxParameterRestoreAllInPlace = (EFI_SMM_LOCK_BOX_PARAMETER_RESTORE_ALL_IN_PLACE *)&CommBuffer[OFFSET_OF (EFI_SMM_COMMUNICATE_HEADER, MessageLength) + sizeof(UINTN)];
|
| 704 | }
|
| 705 | LockBoxParameterRestoreAllInPlace->Header.Command = EFI_SMM_LOCK_BOX_COMMAND_RESTORE_ALL_IN_PLACE;
|
| 706 | LockBoxParameterRestoreAllInPlace->Header.DataLength = sizeof(*LockBoxParameterRestoreAllInPlace);
|
| 707 | LockBoxParameterRestoreAllInPlace->Header.ReturnStatus = (UINT64)-1;
|
| 708 |
|
| 709 | //
|
| 710 | // Send command
|
| 711 | //
|
| 712 | CommSize = sizeof(CommBuffer);
|
| 713 | Status = SmmCommunicationPpi->Communicate (
|
| 714 | SmmCommunicationPpi,
|
| 715 | &CommBuffer[0],
|
| 716 | &CommSize
|
| 717 | );
|
| 718 | if (Status == EFI_NOT_STARTED) {
|
| 719 | //
|
| 720 | // Pei SMM communication not ready yet, so we access SMRAM directly
|
| 721 | //
|
| 722 | DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib Communicate - (%r)\n", Status));
|
| 723 | Status = InternalRestoreAllLockBoxInPlaceFromSmram ();
|
| 724 | LockBoxParameterRestoreAllInPlace->Header.ReturnStatus = (UINT64)Status;
|
| 725 | }
|
| 726 | ASSERT_EFI_ERROR (Status);
|
| 727 |
|
| 728 | Status = (EFI_STATUS)LockBoxParameterRestoreAllInPlace->Header.ReturnStatus;
|
| 729 | if (Status != EFI_SUCCESS) {
|
| 730 | // Need or MAX_BIT, because there might be case that SMM is X64 while PEI is IA32.
|
| 731 | Status |= MAX_BIT;
|
| 732 | }
|
| 733 |
|
| 734 | DEBUG ((EFI_D_INFO, "SmmLockBoxPeiLib RestoreAllLockBoxInPlace - Exit (%r)\n", Status));
|
| 735 |
|
| 736 | //
|
| 737 | // Done
|
| 738 | //
|
| 739 | return Status;
|
| 740 | }
|
| 741 |
|