/**
  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 ;
}
Пример #2
0
/**
  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 ;
}
Пример #3
0
/**
  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;
}