/** Dispatch function for SMM lock box update. Caution: This function may receive untrusted input. Restore buffer and length are external input, so this function will validate it is in SMRAM. @param LockBoxParameterUpdate parameter of lock box update **/ VOID SmmLockBoxUpdate ( IN EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *LockBoxParameterUpdate ) { EFI_STATUS Status; EFI_SMM_LOCK_BOX_PARAMETER_UPDATE TempLockBoxParameterUpdate; // // Sanity check // if (mLocked) { DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n")); LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; return ; } CopyMem (&TempLockBoxParameterUpdate, LockBoxParameterUpdate, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_UPDATE)); // // Sanity check // if (!SmmIsBufferOutsideSmmValid ((UINTN)TempLockBoxParameterUpdate.Buffer, (UINTN)TempLockBoxParameterUpdate.Length)) { DEBUG ((EFI_D_ERROR, "SmmLockBox Update address in SMRAM or buffer overflow!\n")); LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; return ; } // // The AsmLfence() call here is to ensure the above range check for the // CommBuffer have been completed before calling into UpdateLockBox(). // AsmLfence (); // // Update data // Status = UpdateLockBox ( &TempLockBoxParameterUpdate.Guid, (UINTN)TempLockBoxParameterUpdate.Offset, (VOID *)(UINTN)TempLockBoxParameterUpdate.Buffer, (UINTN)TempLockBoxParameterUpdate.Length ); LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)Status; return ; }
/** Dispatch function for SMM lock box update. Caution: This function may receive untrusted input. Restore buffer and length are external input, so this function will validate it is in SMRAM. @param LockBoxParameterUpdate parameter of lock box update **/ VOID SmmLockBoxUpdate ( IN EFI_SMM_LOCK_BOX_PARAMETER_UPDATE *LockBoxParameterUpdate ) { EFI_STATUS Status; EFI_SMM_LOCK_BOX_PARAMETER_UPDATE TempLockBoxParameterUpdate; // // Sanity check // if (mLocked) { DEBUG ((EFI_D_ERROR, "SmmLockBox Locked!\n")); LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; return ; } CopyMem (&TempLockBoxParameterUpdate, LockBoxParameterUpdate, sizeof (EFI_SMM_LOCK_BOX_PARAMETER_UPDATE)); // // Sanity check // if (!IsAddressValid ((UINTN)TempLockBoxParameterUpdate.Buffer, (UINTN)TempLockBoxParameterUpdate.Length)) { DEBUG ((EFI_D_ERROR, "SmmLockBox Update address in SMRAM or buffer overflow!\n")); LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)EFI_ACCESS_DENIED; return ; } // // Update data // Status = UpdateLockBox ( &TempLockBoxParameterUpdate.Guid, (UINTN)TempLockBoxParameterUpdate.Offset, (VOID *)(UINTN)TempLockBoxParameterUpdate.Buffer, (UINTN)TempLockBoxParameterUpdate.Length ); LockBoxParameterUpdate->Header.ReturnStatus = (UINT64)Status; return ; }
/** Report status code listener for SMM. This is used to record the performance data for S3 Suspend Start and S3 Suspend End in FPDT. @param[in] CodeType Indicates the type of status code being reported. @param[in] Value Describes the current status of a hardware or software entity. This included information about the class and subclass that is used to classify the entity as well as an operation. @param[in] Instance The enumeration of a hardware or software entity within the system. Valid instance numbers start with 1. @param[in] CallerId This optional parameter may be used to identify the caller. This parameter allows the status code driver to apply different rules to different callers. @param[in] Data This optional parameter may be used to pass additional data. @retval EFI_SUCCESS Status code is what we expected. @retval EFI_UNSUPPORTED Status code not supported. **/ EFI_STATUS EFIAPI FpdtStatusCodeListenerSmm ( IN EFI_STATUS_CODE_TYPE CodeType, IN EFI_STATUS_CODE_VALUE Value, IN UINT32 Instance, IN EFI_GUID *CallerId, IN EFI_STATUS_CODE_DATA *Data ) { EFI_STATUS Status; UINT64 CurrentTime; EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD S3SuspendRecord; UINT8 *NewRecordBuffer; // // Check whether status code is what we are interested in. // if ((CodeType & EFI_STATUS_CODE_TYPE_MASK) != EFI_PROGRESS_CODE) { return EFI_UNSUPPORTED; } // // Collect one or more Boot records in boot time // if (Data != NULL && CompareGuid (&Data->Type, &gEfiFirmwarePerformanceGuid)) { AcquireSpinLock (&mSmmFpdtLock); if (mBootRecordSize + Data->Size > mBootRecordMaxSize) { // // Try to allocate big SMRAM data to store Boot record. // if (mSmramIsOutOfResource) { ReleaseSpinLock (&mSmmFpdtLock); return EFI_OUT_OF_RESOURCES; } NewRecordBuffer = ReallocatePool (mBootRecordSize, mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE, mBootRecordBuffer); if (NewRecordBuffer == NULL) { ReleaseSpinLock (&mSmmFpdtLock); mSmramIsOutOfResource = TRUE; return EFI_OUT_OF_RESOURCES; } mBootRecordBuffer = NewRecordBuffer; mBootRecordMaxSize = mBootRecordSize + Data->Size + EXTENSION_RECORD_SIZE; } // // Save boot record into the temp memory space. // CopyMem (mBootRecordBuffer + mBootRecordSize, Data + 1, Data->Size); mBootRecordSize += Data->Size; ReleaseSpinLock (&mSmmFpdtLock); return EFI_SUCCESS; } if ((Value != PcdGet32 (PcdProgressCodeS3SuspendStart)) && (Value != PcdGet32 (PcdProgressCodeS3SuspendEnd))) { return EFI_UNSUPPORTED; } // // Retrieve current time. // CurrentTime = GetTimeInNanoSecond (GetPerformanceCounter ()); if (Value == PcdGet32 (PcdProgressCodeS3SuspendStart)) { // // S3 Suspend started, record the performance data and return. // mSuspendStartTime = CurrentTime; return EFI_SUCCESS; } // // We are going to S3 sleep, record S3 Suspend End performance data. // S3SuspendRecord.SuspendStart = mSuspendStartTime; S3SuspendRecord.SuspendEnd = CurrentTime; // // Save S3 suspend performance data to lock box, it will be used by Firmware Performance PEIM. // if (!mS3SuspendLockBoxSaved) { Status = SaveLockBox ( &gEfiFirmwarePerformanceGuid, &S3SuspendRecord, sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD) ); ASSERT_EFI_ERROR (Status); mS3SuspendLockBoxSaved = TRUE; } else { Status = UpdateLockBox ( &gEfiFirmwarePerformanceGuid, 0, &S3SuspendRecord, sizeof (EFI_ACPI_5_0_FPDT_S3_SUSPEND_RECORD) ); ASSERT_EFI_ERROR (Status); } return EFI_SUCCESS; }