/* $NoKeywords:$ */
/**
 * @file
 *
 * ACPI S3 Support routines
 *
 * Contains routines needed for supporting resume from the ACPI S3 sleep state.
 *
 * @xrefitem bom "File Content Label" "Release Content"
 * @e project:      AGESA
 * @e sub-project:  Interface
 * @e \$Revision: 84150 $   @e \$Date: 2012-12-12 15:46:25 -0600 (Wed, 12 Dec 2012) $
 *
 */
/*****************************************************************************
 *
 * Copyright (c) 2008 - 2013, Advanced Micro Devices, Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of Advanced Micro Devices, Inc. nor the names of
 *       its contributors may be used to endorse or promote products derived
 *       from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************
 */


/*----------------------------------------------------------------------------------------
 *                             M O D U L E S    U S E D
 *----------------------------------------------------------------------------------------
 */
#include "AGESA.h"
#include "amdlib.h"
#include "Ids.h"
#include "mm.h"
#include "mn.h"
#include "S3.h"
#include "mfs3.h"
#include "GeneralServices.h"
#include "cpuServices.h"
#include "Filecode.h"
CODE_GROUP (G1_PEICC)
RDATA_GROUP (G1_PEICC)

#define FILECODE PROC_CPU_S3_FILECODE
/*----------------------------------------------------------------------------------------
 *                   D E F I N I T I O N S    A N D    M A C R O S
 *----------------------------------------------------------------------------------------
 */


/*----------------------------------------------------------------------------------------
 *                  T Y P E D E F S     A N D     S T R U C T U R E S
 *----------------------------------------------------------------------------------------
 */


/*----------------------------------------------------------------------------------------
 *           P R O T O T Y P E S     O F     L O C A L     F U N C T I O N S
 *----------------------------------------------------------------------------------------
 */
VOID
SaveDeviceContext (
  IN       DEVICE_BLOCK_HEADER *DeviceList,
  IN       CALL_POINTS         CallPoint,
     OUT   UINT32              *ActualBufferSize,
  IN       AMD_CONFIG_PARAMS   *StdHeader
  );

VOID
SavePciDevice (
  IN       AMD_CONFIG_PARAMS     *StdHeader,
  IN       PCI_DEVICE_DESCRIPTOR *Device,
  IN       CALL_POINTS           CallPoint,
  IN OUT   VOID                  **OrMask
  );

VOID
SaveConditionalPciDevice (
  IN       AMD_CONFIG_PARAMS                 *StdHeader,
  IN       CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device,
  IN       CALL_POINTS                       CallPoint,
  IN OUT   VOID                              **OrMask
  );

VOID
SaveMsrDevice (
  IN       AMD_CONFIG_PARAMS     *StdHeader,
  IN       MSR_DEVICE_DESCRIPTOR *Device,
  IN       CALL_POINTS           CallPoint,
  IN OUT   UINT64                **OrMask
  );

VOID
SaveConditionalMsrDevice (
  IN       AMD_CONFIG_PARAMS                 *StdHeader,
  IN       CONDITIONAL_MSR_DEVICE_DESCRIPTOR *Device,
  IN       CALL_POINTS                       CallPoint,
  IN OUT   UINT64                            **OrMask
  );

VOID
RestorePciDevice (
  IN       AMD_CONFIG_PARAMS     *StdHeader,
  IN       PCI_DEVICE_DESCRIPTOR *Device,
  IN       CALL_POINTS           CallPoint,
  IN OUT   VOID                  **OrMask
  );

VOID
RestoreConditionalPciDevice (
  IN       AMD_CONFIG_PARAMS                 *StdHeader,
  IN       CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device,
  IN       CALL_POINTS                       CallPoint,
  IN OUT   VOID                              **OrMask
  );

VOID
RestoreMsrDevice (
  IN       AMD_CONFIG_PARAMS     *StdHeader,
  IN       MSR_DEVICE_DESCRIPTOR *Device,
  IN       CALL_POINTS           CallPoint,
  IN OUT   UINT64                **OrMask
  );

VOID
RestoreConditionalMsrDevice (
  IN       AMD_CONFIG_PARAMS                 *StdHeader,
  IN       CONDITIONAL_MSR_DEVICE_DESCRIPTOR *Device,
  IN       CALL_POINTS                       CallPoint,
  IN OUT   UINT64                            **OrMask
  );

/*----------------------------------------------------------------------------------------
 *                          E X P O R T E D    F U N C T I O N S
 *----------------------------------------------------------------------------------------
 */

/*---------------------------------------------------------------------------------------*/
/**
 * Saves all devices in the given device list.
 *
 * This traverses the entire device list twice.  In the first pass, we save
 * all devices identified as Pre ESR.  In the second pass, we save devices
 * marked as post ESR.
 *
 * @param[in]     DeviceList        Beginning of the device list to save.
 * @param[in]     Storage           Beginning of the context buffer.
 * @param[in]     CallPoint         Indicates whether this is AMD_INIT_RESUME or
 *                                  AMD_S3LATE_RESTORE.
 * @param[out]    ActualBufferSize  Actual size used in saving the device list.
 * @param[in]     StdHeader         AMD standard header config param.
 *
 */
VOID
SaveDeviceListContext (
  IN       DEVICE_BLOCK_HEADER *DeviceList,
  IN       VOID                *Storage,
  IN       CALL_POINTS         CallPoint,
     OUT   UINT32              *ActualBufferSize,
  IN       AMD_CONFIG_PARAMS   *StdHeader
  )
{
  // Copy device list over
  LibAmdMemCopy (Storage,
                 DeviceList,
                 (UINTN) DeviceList->RelativeOrMaskOffset,
                 StdHeader);
  SaveDeviceContext (Storage, CallPoint, ActualBufferSize, StdHeader);
}

/*---------------------------------------------------------------------------------------*/
/**
 * Saves all devices in the given device list.
 *
 * This traverses the entire device list twice.  In the first pass, we save
 * all devices identified as Pre ESR.  In the second pass, we save devices
 * marked as post ESR.
 *
 * @param[in,out] DeviceList        Beginning of the device list to save.
 * @param[in]     CallPoint         Indicates whether this is AMD_INIT_RESUME or
 *                                  AMD_S3LATE_RESTORE.
 * @param[out]    ActualBufferSize  Actual size used in saving the device list.
 * @param[in]     StdHeader         AMD standard header config param.
 *
 */
VOID
SaveDeviceContext (
  IN       DEVICE_BLOCK_HEADER *DeviceList,
  IN       CALL_POINTS         CallPoint,
     OUT   UINT32              *ActualBufferSize,
  IN       AMD_CONFIG_PARAMS   *StdHeader
  )
{
  DEVICE_DESCRIPTORS Device;
  UINT16 i;
  UINT64 StartAddress;
  UINT64 EndAddress;
  VOID *OrMask;

  StartAddress = (UINTN) DeviceList;
  Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];
  OrMask = (UINT8 *) DeviceList + DeviceList->RelativeOrMaskOffset;

  // Process Pre ESR List
  for (i = 0; i < DeviceList->NumDevices; i++) {
    switch (Device.CommonDeviceHeader->Type) {
    case DEV_TYPE_PCI_PRE_ESR:
      SavePciDevice (StdHeader, Device.PciDevice, CallPoint, &OrMask);
      // fall through - advance the pointer after saving context
    case DEV_TYPE_PCI:
      Device.PciDevice++;
      break;
    case DEV_TYPE_CPCI_PRE_ESR:
      SaveConditionalPciDevice (StdHeader, Device.CPciDevice, CallPoint, &OrMask);
      // fall through - advance the pointer after saving context
    case DEV_TYPE_CPCI:
      Device.CPciDevice++;
      break;
    case DEV_TYPE_MSR_PRE_ESR:
      SaveMsrDevice (StdHeader, Device.MsrDevice, CallPoint, (UINT64 **) &OrMask);
      // fall through - advance the pointer after saving context
    case DEV_TYPE_MSR:
      Device.MsrDevice++;
      break;
    case DEV_TYPE_CMSR_PRE_ESR:
      SaveConditionalMsrDevice (StdHeader, Device.CMsrDevice, CallPoint, (UINT64 **) &OrMask);
      // fall through - advance the pointer after saving context
    case DEV_TYPE_CMSR:
      Device.CMsrDevice++;
      break;
    }
  }

  Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];
  // Process Post ESR List
  for (i = 0; i < DeviceList->NumDevices; i++) {
    switch (Device.CommonDeviceHeader->Type) {
    case DEV_TYPE_PCI:
      SavePciDevice (StdHeader, Device.PciDevice, CallPoint, &OrMask);
      // fall through - advance the pointer after saving context
    case DEV_TYPE_PCI_PRE_ESR:
      Device.PciDevice++;
      break;
    case DEV_TYPE_CPCI:
      SaveConditionalPciDevice (StdHeader, Device.CPciDevice, CallPoint, &OrMask);
      // fall through - advance the pointer after saving context
    case DEV_TYPE_CPCI_PRE_ESR:
      Device.CPciDevice++;
      break;
    case DEV_TYPE_MSR:
      SaveMsrDevice (StdHeader, Device.MsrDevice, CallPoint, (UINT64 **) &OrMask);
      // fall through - advance the pointer after saving context
    case DEV_TYPE_MSR_PRE_ESR:
      Device.MsrDevice++;
      break;
    case DEV_TYPE_CMSR:
      SaveConditionalMsrDevice (StdHeader, Device.CMsrDevice, CallPoint, (UINT64 **) &OrMask);
      // fall through - advance the pointer after saving context
    case DEV_TYPE_CMSR_PRE_ESR:
      Device.CMsrDevice++;
      break;
    }
  }
  EndAddress = (UINTN) OrMask;
  *ActualBufferSize = (UINT32) (EndAddress - StartAddress);
}

/*---------------------------------------------------------------------------------------*/
/**
 * Saves the context of a PCI device.
 *
 * This traverses the provided register list saving PCI registers.
 *
 * @param[in]     StdHeader      AMD standard header config param.
 * @param[in]     Device         PCI device to restore.
 * @param[in]     CallPoint      Indicates whether this is AMD_INIT_RESUME or
 *                               AMD_S3LATE_RESTORE.
 * @param[in,out] OrMask         Current buffer pointer of raw register values.
 *
 */
VOID
SavePciDevice (
  IN       AMD_CONFIG_PARAMS     *StdHeader,
  IN       PCI_DEVICE_DESCRIPTOR *Device,
  IN       CALL_POINTS           CallPoint,
  IN OUT   VOID                  **OrMask
  )
{
  UINT8   RegSizeInBytes;
  UINT8   SpecialCaseIndex;
  UINT8   *IntermediatePtr;
  UINT16  i;
  UINT32  Socket;
  UINT32  Module;
  UINT32  AndMask;
  ACCESS_WIDTH AccessWidth;
  AGESA_STATUS IgnoredSts;
  PCI_ADDR PciAddress;
  PCI_REGISTER_BLOCK_HEADER *RegisterHdr;

  GetSocketModuleOfNode ((UINT32) Device->Node,
                               &Socket,
                               &Module,
                               StdHeader);
  GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts);

  if (CallPoint == INIT_RESUME) {
    MemFS3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  } else {
    S3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  }

  for (i = 0; i < RegisterHdr->NumRegisters; i++) {
    PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function;
    PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset;
    RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize;
    switch (RegSizeInBytes) {
    case 1:
      AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask);
      AccessWidth = AccessS3SaveWidth8;
      break;
    case 2:
      AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask);
      AccessWidth = AccessS3SaveWidth16;
      break;
    case 3:
      // In this case, we don't need to save a register. We just need to call a special
      // function to do certain things in the save and resume sequence.
      // This should not be used in a non-special case.
      AndMask = 0;
      RegSizeInBytes = 0;
      AccessWidth = 0;
      break;
    default:
      AndMask = RegisterHdr->RegisterList[i].AndMask;
      RegSizeInBytes = 4;
      AccessWidth = AccessS3SaveWidth32;
      break;
    }
    if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
      ASSERT ((AndMask != 0) && (RegSizeInBytes != 0) && (AccessWidth != 0));
      LibAmdPciRead (AccessWidth, PciAddress, *OrMask, StdHeader);
    } else {
      SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
      RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth, PciAddress, *OrMask, StdHeader);
    }
    if (AndMask != 0) {
      // If AndMask is 0, then it is a not-care. Don't need to apply it to the OrMask
      **((UINT32 **) OrMask) &= AndMask;
    }
    if ((RegSizeInBytes == 0) && (**((UINT32 **) OrMask) == RESTART_FROM_BEGINNING_LIST)) {
      // Restart from the beginning of the register list
      i = 0xFFFF;
    }
    IntermediatePtr = (UINT8 *) *OrMask;
    *OrMask = &IntermediatePtr[RegSizeInBytes]; // += RegSizeInBytes;
  }
}

/*---------------------------------------------------------------------------------------*/
/**
 * Saves the context of a 'conditional' PCI device.
 *
 * This traverses the provided register list saving PCI registers when appropriate.
 *
 * @param[in]     StdHeader      AMD standard header config param.
 * @param[in]     Device         'conditional' PCI device to restore.
 * @param[in]     CallPoint      Indicates whether this is AMD_INIT_RESUME or
 *                               AMD_S3LATE_RESTORE.
 * @param[in,out] OrMask         Current buffer pointer of raw register values.
 *
 */
VOID
SaveConditionalPciDevice (
  IN       AMD_CONFIG_PARAMS                 *StdHeader,
  IN       CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device,
  IN       CALL_POINTS                       CallPoint,
  IN OUT   VOID                              **OrMask
  )
{
  UINT8   RegSizeInBytes;
  UINT8   SpecialCaseIndex;
  UINT8   *IntermediatePtr;
  UINT16  i;
  UINT32  Socket;
  UINT32  Module;
  UINT32  AndMask;
  ACCESS_WIDTH AccessWidth;
  AGESA_STATUS IgnoredSts;
  PCI_ADDR PciAddress;
  CPCI_REGISTER_BLOCK_HEADER *RegisterHdr;

  GetSocketModuleOfNode ((UINT32) Device->Node,
                               &Socket,
                               &Module,
                               StdHeader);
  GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts);

  if (CallPoint == INIT_RESUME) {
    MemFS3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  } else {
    S3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  }

  for (i = 0; i < RegisterHdr->NumRegisters; i++) {
    if (((Device->Mask1 & RegisterHdr->RegisterList[i].Mask1) != 0) &&
        ((Device->Mask2 & RegisterHdr->RegisterList[i].Mask2) != 0)) {
      PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function;
      PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset;
      RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize;
      switch (RegSizeInBytes) {
      case 1:
        AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask);
        AccessWidth = AccessS3SaveWidth8;
        break;
      case 2:
        AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask);
        AccessWidth = AccessS3SaveWidth16;
        break;
      case 3:
        // In this case, we don't need to save a register. We just need to call a special
        // function to do certain things in the save and resume sequence.
        // This should not be used in a non-special case.
        AndMask = 0;
        RegSizeInBytes = 0;
        AccessWidth = 0;
        break;
      default:
        AndMask = RegisterHdr->RegisterList[i].AndMask;
        RegSizeInBytes = 4;
        AccessWidth = AccessS3SaveWidth32;
        break;
      }
      if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
        ASSERT ((AndMask != 0) && (RegSizeInBytes != 0) && (AccessWidth != 0));
        LibAmdPciRead (AccessWidth, PciAddress, *OrMask, StdHeader);
      } else {
        SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
        RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth, PciAddress, *OrMask, StdHeader);
      }
      if (AndMask != 0) {
        // If AndMask is 0, then it is a not-care. Don't need to apply it to the OrMask
        **((UINT32 **) OrMask) &= AndMask;
      }
      if ((RegSizeInBytes == 0) && (**((UINT32 **) OrMask) == RESTART_FROM_BEGINNING_LIST)) {
        // Restart from the beginning of the register list
        i = 0xFFFF;
      }
      IntermediatePtr = (UINT8 *) *OrMask;
      *OrMask = &IntermediatePtr[RegSizeInBytes]; // += RegSizeInBytes;
    }
  }
}

/*---------------------------------------------------------------------------------------*/
/**
 * Saves the context of an MSR device.
 *
 * This traverses the provided register list saving MSRs.
 *
 * @param[in]     StdHeader      AMD standard header config param.
 * @param[in]     Device         MSR device to restore.
 * @param[in]     CallPoint      Indicates whether this is AMD_INIT_RESUME or
 *                               AMD_S3LATE_RESTORE.
 * @param[in,out] OrMask         Current buffer pointer of raw register values.
 *
 */
VOID
SaveMsrDevice (
  IN       AMD_CONFIG_PARAMS     *StdHeader,
  IN       MSR_DEVICE_DESCRIPTOR *Device,
  IN       CALL_POINTS           CallPoint,
  IN OUT   UINT64                **OrMask
  )
{
  UINT8   SpecialCaseIndex;
  UINT16  i;
  MSR_REGISTER_BLOCK_HEADER *RegisterHdr;

  if (CallPoint == INIT_RESUME) {
    MemFS3GetMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  } else {
    S3GetMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  }

  for (i = 0; i < RegisterHdr->NumRegisters; i++) {
    if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
      LibAmdMsrRead (RegisterHdr->RegisterList[i].Address, *OrMask, StdHeader);
    } else {
      SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
      RegisterHdr->SpecialCases[SpecialCaseIndex].Save (RegisterHdr->RegisterList[i].Address, *OrMask, StdHeader);
    }
    **OrMask &= RegisterHdr->RegisterList[i].AndMask;
    (*OrMask)++;
  }
}

/*---------------------------------------------------------------------------------------*/
/**
 * Saves the context of a 'conditional' MSR device.
 *
 * This traverses the provided register list saving MSRs when appropriate.
 *
 * @param[in]     StdHeader      AMD standard header config param.
 * @param[in]     Device         'conditional' MSR device to restore.
 * @param[in]     CallPoint      Indicates whether this is AMD_INIT_RESUME or
 *                               AMD_S3LATE_RESTORE.
 * @param[in,out] OrMask         Current buffer pointer of raw register values.
 *
 */
VOID
SaveConditionalMsrDevice (
  IN       AMD_CONFIG_PARAMS                 *StdHeader,
  IN       CONDITIONAL_MSR_DEVICE_DESCRIPTOR *Device,
  IN       CALL_POINTS                       CallPoint,
  IN OUT   UINT64                            **OrMask
  )
{
  UINT8   SpecialCaseIndex;
  UINT16  i;
  CMSR_REGISTER_BLOCK_HEADER *RegisterHdr;

  if (CallPoint == INIT_RESUME) {
    MemFS3GetCMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  } else {
    S3GetCMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  }

  for (i = 0; i < RegisterHdr->NumRegisters; i++) {
    if (((Device->Mask1 & RegisterHdr->RegisterList[i].Mask1) != 0) &&
        ((Device->Mask2 & RegisterHdr->RegisterList[i].Mask2) != 0)) {
      if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
        LibAmdMsrRead (RegisterHdr->RegisterList[i].Address, (UINT64 *) *OrMask, StdHeader);
      } else {
        SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
        RegisterHdr->SpecialCases[SpecialCaseIndex].Save (RegisterHdr->RegisterList[i].Address, (UINT64 *) *OrMask, StdHeader);
      }
      **OrMask &= RegisterHdr->RegisterList[i].AndMask;
      (*OrMask)++;
    }
  }
}

/*---------------------------------------------------------------------------------------*/
/**
 * Determines the maximum amount of space required to store all raw register
 * values for the given device list.
 *
 * This traverses the entire device list, and calculates the worst case size
 * of each device in the device list.
 *
 * @param[in]     DeviceList     Beginning of the device list.
 * @param[in]     CallPoint      Indicates whether this is AMD_INIT_RESUME or
 *                               AMD_S3LATE_RESTORE.
 * @param[in]     StdHeader      AMD standard header config param.
 *
 * @retval        Size in bytes required for storing all registers.
 */
UINT32
GetWorstCaseContextSize (
  IN       DEVICE_BLOCK_HEADER *DeviceList,
  IN       CALL_POINTS         CallPoint,
  IN       AMD_CONFIG_PARAMS   *StdHeader
  )
{
  UINT32 WorstCaseSize;
  DEVICE_DESCRIPTORS Device;
  UINT16 i;
  REGISTER_BLOCK_HEADERS RegisterHdr;

  WorstCaseSize = DeviceList->RelativeOrMaskOffset;
  Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];

  // Process Device List
  for (i = 0; i < DeviceList->NumDevices; i++) {
    switch (Device.CommonDeviceHeader->Type) {
    case DEV_TYPE_PCI_PRE_ESR:
      // PRE_ESR and post ESR take the same amount of space
    case DEV_TYPE_PCI:
      if (CallPoint == INIT_RESUME) {
        MemFS3GetPciDeviceRegisterList (Device.PciDevice, &RegisterHdr.PciRegisters, StdHeader);
      } else {
        S3GetPciDeviceRegisterList (Device.PciDevice, &RegisterHdr.PciRegisters, StdHeader);
      }
      WorstCaseSize += (RegisterHdr.PciRegisters->NumRegisters * 4);
      Device.PciDevice++;
      break;
    case DEV_TYPE_CPCI_PRE_ESR:
      // PRE_ESR and post ESR take the same amount of space
    case DEV_TYPE_CPCI:
      if (CallPoint == INIT_RESUME) {
        MemFS3GetCPciDeviceRegisterList (Device.CPciDevice, &RegisterHdr.CPciRegisters, StdHeader);
      } else {
        S3GetCPciDeviceRegisterList (Device.CPciDevice, &RegisterHdr.CPciRegisters, StdHeader);
      }
      WorstCaseSize += (RegisterHdr.CPciRegisters->NumRegisters * 4);
      Device.CPciDevice++;
      break;
    case DEV_TYPE_MSR_PRE_ESR:
      // PRE_ESR and post ESR take the same amount of space
    case DEV_TYPE_MSR:
      if (CallPoint == INIT_RESUME) {
        MemFS3GetMsrDeviceRegisterList (Device.MsrDevice, &RegisterHdr.MsrRegisters, StdHeader);
      } else {
        S3GetMsrDeviceRegisterList (Device.MsrDevice, &RegisterHdr.MsrRegisters, StdHeader);
      }
      WorstCaseSize += (RegisterHdr.MsrRegisters->NumRegisters * 8);
      Device.MsrDevice++;
      break;
    case DEV_TYPE_CMSR_PRE_ESR:
      // PRE_ESR and post ESR take the same amount of space
    case DEV_TYPE_CMSR:
      if (CallPoint == INIT_RESUME) {
        MemFS3GetCMsrDeviceRegisterList (Device.CMsrDevice, &RegisterHdr.CMsrRegisters, StdHeader);
      } else {
        S3GetCMsrDeviceRegisterList (Device.CMsrDevice, &RegisterHdr.CMsrRegisters, StdHeader);
      }
      WorstCaseSize += (RegisterHdr.CMsrRegisters->NumRegisters * 8);
      Device.CMsrDevice++;
      break;
    default:
      ASSERT (FALSE);
    }
  }
  return (WorstCaseSize);
}

/*---------------------------------------------------------------------------------------*/
/**
 * Restores all devices marked as 'before exiting self-refresh.'
 *
 * This traverses the entire device list, restoring all devices identified
 * as Pre ESR.
 *
 * @param[in,out] OrMaskPtr      Current buffer pointer of raw register values.
 * @param[in]     Storage        Beginning of the device list.
 * @param[in]     CallPoint      Indicates whether this is AMD_INIT_RESUME or
 *                               AMD_S3LATE_RESTORE.
 * @param[in]     StdHeader      AMD standard header config param.
 *
 */
VOID
RestorePreESRContext (
     OUT   VOID              **OrMaskPtr,
  IN       VOID              *Storage,
  IN       CALL_POINTS       CallPoint,
  IN       AMD_CONFIG_PARAMS *StdHeader
  )
{
  DEVICE_DESCRIPTORS Device;
  UINT16 i;
  DEVICE_BLOCK_HEADER *DeviceList;

  DeviceList = (DEVICE_BLOCK_HEADER *) Storage;
  Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];
  *OrMaskPtr = (UINT8 *) DeviceList + DeviceList->RelativeOrMaskOffset;

  // Process Pre ESR List
  for (i = 0; i < DeviceList->NumDevices; i++) {
    switch (Device.CommonDeviceHeader->Type) {
    case DEV_TYPE_PCI_PRE_ESR:
      RestorePciDevice (StdHeader, Device.PciDevice, CallPoint, OrMaskPtr);
      // fall through - advance the pointer after restoring context
    case DEV_TYPE_PCI:
      Device.PciDevice++;
      break;
    case DEV_TYPE_CPCI_PRE_ESR:
      RestoreConditionalPciDevice (StdHeader, Device.CPciDevice, CallPoint, OrMaskPtr);
      // fall through - advance the pointer after restoring context
    case DEV_TYPE_CPCI:
      Device.CPciDevice++;
      break;
    case DEV_TYPE_MSR_PRE_ESR:
      RestoreMsrDevice (StdHeader, Device.MsrDevice, CallPoint, (UINT64 **) OrMaskPtr);
      // fall through - advance the pointer after restoring context
    case DEV_TYPE_MSR:
      Device.MsrDevice++;
      break;
    case DEV_TYPE_CMSR_PRE_ESR:
      RestoreConditionalMsrDevice (StdHeader, Device.CMsrDevice, CallPoint, (UINT64 **) OrMaskPtr);
      // fall through - advance the pointer after restoring context
    case DEV_TYPE_CMSR:
      Device.CMsrDevice++;
      break;
    }
  }
}

/*---------------------------------------------------------------------------------------*/
/**
 * Restores all devices marked as 'after exiting self-refresh.'
 *
 * This traverses the entire device list, restoring all devices identified
 * as Post ESR.
 *
 * @param[in]     OrMaskPtr      Current buffer pointer of raw register values.
 * @param[in]     Storage        Beginning of the device list.
 * @param[in]     CallPoint      Indicates whether this is AMD_INIT_RESUME or
 *                               AMD_S3LATE_RESTORE.
 * @param[in]     StdHeader      AMD standard header config param.
 *
 */
VOID
RestorePostESRContext (
  IN       VOID              *OrMaskPtr,
  IN       VOID              *Storage,
  IN       CALL_POINTS       CallPoint,
  IN       AMD_CONFIG_PARAMS *StdHeader
  )
{
  DEVICE_DESCRIPTORS Device;
  UINT16 i;
  DEVICE_BLOCK_HEADER *DeviceList;

  DeviceList = (DEVICE_BLOCK_HEADER *) Storage;
  Device.CommonDeviceHeader = (DEVICE_DESCRIPTOR *) &DeviceList[1];

  // Process Pre ESR List
  for (i = 0; i < DeviceList->NumDevices; i++) {
    switch (Device.CommonDeviceHeader->Type) {
    case DEV_TYPE_PCI:
      RestorePciDevice (StdHeader, Device.PciDevice, CallPoint, &OrMaskPtr);
      // fall through - advance the pointer after restoring context
    case DEV_TYPE_PCI_PRE_ESR:
      Device.PciDevice++;
      break;
    case DEV_TYPE_CPCI:
      RestoreConditionalPciDevice (StdHeader, Device.CPciDevice, CallPoint, &OrMaskPtr);
      // fall through - advance the pointer after restoring context
    case DEV_TYPE_CPCI_PRE_ESR:
      Device.CPciDevice++;
      break;
    case DEV_TYPE_MSR:
      RestoreMsrDevice (StdHeader, Device.MsrDevice, CallPoint, (UINT64 **) &OrMaskPtr);
      // fall through - advance the pointer after restoring context
    case DEV_TYPE_MSR_PRE_ESR:
      Device.MsrDevice++;
      break;
    case DEV_TYPE_CMSR:
      RestoreConditionalMsrDevice (StdHeader, Device.CMsrDevice, CallPoint, (UINT64 **) &OrMaskPtr);
      // fall through - advance the pointer after restoring context
    case DEV_TYPE_CMSR_PRE_ESR:
      Device.CMsrDevice++;
      break;
    }
  }
}

/*---------------------------------------------------------------------------------------*/
/**
 * Restores the context of a PCI device.
 *
 * This traverses the provided register list restoring PCI registers.
 *
 * @param[in]     StdHeader      AMD standard header config param.
 * @param[in]     Device         'conditional' PCI device to restore.
 * @param[in]     CallPoint      Indicates whether this is AMD_INIT_RESUME or
 *                               AMD_S3LATE_RESTORE.
 * @param[in,out] OrMask         Current buffer pointer of raw register values.
 *
 */
VOID
RestorePciDevice (
  IN       AMD_CONFIG_PARAMS     *StdHeader,
  IN       PCI_DEVICE_DESCRIPTOR *Device,
  IN       CALL_POINTS           CallPoint,
  IN OUT   VOID                  **OrMask
  )
{
  UINT8   RegSizeInBytes;
  UINT8   SpecialCaseIndex;
  UINT8   *IntermediatePtr;
  UINT8   BootMode;
  UINT16  i;
  UINT32  Socket;
  UINT32  Module;
  UINT32  AndMask;
  UINT32  RegValueRead;
  UINT32  RegValueWrite;
  ACCESS_WIDTH AccessWidth;
  AGESA_STATUS IgnoredSts;
  PCI_ADDR PciAddress;
  PCI_REGISTER_BLOCK_HEADER *RegisterHdr;

  GetSocketModuleOfNode ((UINT32) Device->Node,
                               &Socket,
                               &Module,
                               StdHeader);
  GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts);

  if (CallPoint == INIT_RESUME) {
    MemFS3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  } else {
    S3GetPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  }

  BootMode = S3_RESUME_MODE;
  if (StdHeader->Func == AMD_INIT_POST) {
    BootMode = RESTORE_TRAINING_MODE | CAPSULE_REBOOT_MODE;
  }

  for (i = 0; i < RegisterHdr->NumRegisters; i++) {
    PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function;
    PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset;
    RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize;
    switch (RegSizeInBytes) {
    case 1:
      AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask);
      RegValueWrite = **(UINT8 **)OrMask;
      AccessWidth = AccessS3SaveWidth8;
      break;
    case 2:
      AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask);
      RegValueWrite = **(UINT16 **)OrMask;
      AccessWidth = AccessS3SaveWidth16;
      break;
    case 3:
      // In this case, we don't need to restore a register. We just need to call a special
      // function to do certain things in the save and resume sequence.
      // This should not be used in a non-special case.
      AndMask = 0;
      RegValueWrite = 0;
      RegSizeInBytes = 0;
      AccessWidth = 0;
      break;
    default:
      AndMask = RegisterHdr->RegisterList[i].AndMask;
      RegSizeInBytes = 4;
      RegValueWrite = **(UINT32 **)OrMask;
      AccessWidth = AccessS3SaveWidth32;
      break;
    }
    if ((RegisterHdr->RegisterList[i].BootMode == 0) || ((BootMode & RegisterHdr->RegisterList[i].BootMode) != 0)) {
      // Do not restore the register if not in the right boot mode
      // Pointer to the saved data buffer still needs to be adjusted as data will be saved regardless of boot mode
      if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
        ASSERT ((AndMask != 0) && (RegSizeInBytes != 0) && (AccessWidth != 0));
        LibAmdPciRead (AccessWidth, PciAddress, &RegValueRead, StdHeader);
        RegValueWrite |= RegValueRead & (~AndMask);
        LibAmdPciWrite (AccessWidth, PciAddress, &RegValueWrite, StdHeader);
      } else {
        SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
        if (AndMask != 0) {
          RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth,
                                               PciAddress,
                                               &RegValueRead,
                                               StdHeader);
          RegValueWrite |= RegValueRead & (~AndMask);
        }
        RegisterHdr->SpecialCases[SpecialCaseIndex].Restore (AccessWidth,
                                               PciAddress,
                                               &RegValueWrite,
                                               StdHeader);
      }
      IDS_OPTION_HOOK (IDS_AFTER_RESTORING_PCI_REG, RegisterHdr, StdHeader);
    }
    IntermediatePtr = (UINT8 *) *OrMask;
    *OrMask = &IntermediatePtr[RegSizeInBytes]; // += RegSizeInBytes;
    if ((RegSizeInBytes == 0) && (RegValueWrite == RESTART_FROM_BEGINNING_LIST)) {
      // Restart from the beginning of the register list
      i = 0xFFFF;
    }
  }
}

/*---------------------------------------------------------------------------------------*/
/**
 * Restores the context of a 'conditional' PCI device.
 *
 * This traverses the provided register list restoring PCI registers when appropriate.
 *
 * @param[in]     StdHeader      AMD standard header config param.
 * @param[in]     Device         'conditional' PCI device to restore.
 * @param[in]     CallPoint      Indicates whether this is AMD_INIT_RESUME or
 *                               AMD_S3LATE_RESTORE.
 * @param[in,out] OrMask         Current buffer pointer of raw register values.
 *
 */
VOID
RestoreConditionalPciDevice (
  IN       AMD_CONFIG_PARAMS                 *StdHeader,
  IN       CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device,
  IN       CALL_POINTS                       CallPoint,
  IN OUT   VOID                              **OrMask
  )
{
  UINT8   RegSizeInBytes;
  UINT8   SpecialCaseIndex;
  UINT8   *IntermediatePtr;
  UINT8   BootMode;
  UINT16  i;
  UINT32  Socket;
  UINT32  Module;
  UINT32  RegValueRead;
  UINT32  RegValueWrite;
  UINT32  AndMask;
  ACCESS_WIDTH AccessWidth;
  AGESA_STATUS IgnoredSts;
  PCI_ADDR PciAddress;
  CPCI_REGISTER_BLOCK_HEADER *RegisterHdr;

  GetSocketModuleOfNode ((UINT32) Device->Node,
                               &Socket,
                               &Module,
                               StdHeader);
  GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts);

  if (CallPoint == INIT_RESUME) {
    MemFS3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  } else {
    S3GetCPciDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  }

  BootMode = S3_RESUME_MODE;
  if (StdHeader->Func == AMD_INIT_POST) {
    BootMode = RESTORE_TRAINING_MODE | CAPSULE_REBOOT_MODE;
  }

  for (i = 0; i < RegisterHdr->NumRegisters; i++) {
    if (((Device->Mask1 & RegisterHdr->RegisterList[i].Mask1) != 0) &&
        ((Device->Mask2 & RegisterHdr->RegisterList[i].Mask2) != 0)) {
      PciAddress.Address.Function = RegisterHdr->RegisterList[i].Function;
      PciAddress.Address.Register = RegisterHdr->RegisterList[i].Offset;
      RegSizeInBytes = RegisterHdr->RegisterList[i].Type.RegisterSize;
      switch (RegSizeInBytes) {
      case 1:
        AndMask = 0xFFFFFFFF & ((UINT8) RegisterHdr->RegisterList[i].AndMask);
        RegValueWrite = **(UINT8 **)OrMask;
        AccessWidth = AccessS3SaveWidth8;
        break;
      case 2:
        AndMask = 0xFFFFFFFF & ((UINT16) RegisterHdr->RegisterList[i].AndMask);
        RegValueWrite = **(UINT16 **)OrMask;
        AccessWidth = AccessS3SaveWidth16;
        break;
      case 3:
        // In this case, we don't need to restore a register. We just need to call a special
        //  function to do certain things in the save and resume sequence.
        // This should not be used in a non-special case.
        AndMask = 0;
        RegValueWrite = 0;
        RegSizeInBytes = 0;
        AccessWidth = 0;
        break;
      default:
        AndMask = RegisterHdr->RegisterList[i].AndMask;
        RegSizeInBytes = 4;
        RegValueWrite = **(UINT32 **)OrMask;
        AccessWidth = AccessS3SaveWidth32;
        break;
      }
      if ((RegisterHdr->RegisterList[i].BootMode == 0) || ((BootMode & RegisterHdr->RegisterList[i].BootMode) != 0)) {
        // Do not restore the register if not in the right boot mode
        // Pointer to the saved data buffer still needs to be adjusted as data will be saved regardless of boot mode
        if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
          LibAmdPciRead (AccessWidth, PciAddress, &RegValueRead, StdHeader);
          RegValueWrite |= RegValueRead & (~AndMask);
          LibAmdPciWrite (AccessWidth, PciAddress, &RegValueWrite, StdHeader);
        } else {
          SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
          if (AndMask != 0) {
            RegisterHdr->SpecialCases[SpecialCaseIndex].Save (AccessWidth,
                                               PciAddress,
                                               &RegValueRead,
                                               StdHeader);
            RegValueWrite |= RegValueRead & (~AndMask);
          }
          RegisterHdr->SpecialCases[SpecialCaseIndex].Restore (AccessWidth,
                                                 PciAddress,
                                                 &RegValueWrite,
                                                 StdHeader);
        }
        IDS_OPTION_HOOK (IDS_AFTER_RESTORING_PCI_REG, RegisterHdr, StdHeader);
      }
      IntermediatePtr = (UINT8 *) *OrMask;
      *OrMask = &IntermediatePtr[RegSizeInBytes];
      if ((RegSizeInBytes == 0) && (RegValueWrite == RESTART_FROM_BEGINNING_LIST)) {
        // Restart from the beginning of the register list
        i = 0xFFFF;
      }
    }
  }
}

/*---------------------------------------------------------------------------------------*/
/**
 * Restores the context of an MSR device.
 *
 * This traverses the provided register list restoring MSRs.
 *
 * @param[in]     StdHeader      AMD standard header config param.
 * @param[in]     Device         MSR device to restore.
 * @param[in]     CallPoint      Indicates whether this is AMD_INIT_RESUME or
 *                               AMD_S3LATE_RESTORE.
 * @param[in,out] OrMask         Current buffer pointer of raw register values.
 *
 */
VOID
RestoreMsrDevice (
  IN       AMD_CONFIG_PARAMS     *StdHeader,
  IN       MSR_DEVICE_DESCRIPTOR *Device,
  IN       CALL_POINTS           CallPoint,
  IN OUT   UINT64                **OrMask
  )
{
  UINT8   SpecialCaseIndex;
  UINT8   BootMode;
  UINT16  i;
  UINT64  RegValueRead;
  UINT64  RegValueWrite;
  MSR_REGISTER_BLOCK_HEADER *RegisterHdr;

  if (CallPoint == INIT_RESUME) {
    MemFS3GetMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  } else {
    S3GetMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  }

  BootMode = S3_RESUME_MODE;
  if (StdHeader->Func == AMD_INIT_POST) {
    BootMode = RESTORE_TRAINING_MODE | CAPSULE_REBOOT_MODE;
  }

  for (i = 0; i < RegisterHdr->NumRegisters; i++) {
    if ((RegisterHdr->RegisterList[i].BootMode == 0) || ((BootMode & RegisterHdr->RegisterList[i].BootMode) != 0)) {
      // Do not restore the register if not in the right boot mode
      // Pointer to the saved data buffer still needs to be adjusted as data will be saved regardless of boot mode
      RegValueWrite = **OrMask;
      if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
        LibAmdMsrRead (RegisterHdr->RegisterList[i].Address, &RegValueRead, StdHeader);
        RegValueWrite |= RegValueRead & (~RegisterHdr->RegisterList[i].AndMask);
        LibAmdMsrWrite (RegisterHdr->RegisterList[i].Address, &RegValueWrite, StdHeader);
      } else {
        SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
        RegisterHdr->SpecialCases[SpecialCaseIndex].Save (RegisterHdr->RegisterList[i].Address,
                                                             &RegValueRead,
                                                             StdHeader);
        RegValueWrite |= RegValueRead & (~RegisterHdr->RegisterList[i].AndMask);
        RegisterHdr->SpecialCases[SpecialCaseIndex].Restore (RegisterHdr->RegisterList[i].Address,
                                                             &RegValueWrite,
                                                             StdHeader);
      }
    }
    (*OrMask)++;
  }
}

/*---------------------------------------------------------------------------------------*/
/**
 * Restores the context of a 'conditional' MSR device.
 *
 * This traverses the provided register list restoring MSRs when appropriate.
 *
 * @param[in]     StdHeader      AMD standard header config param.
 * @param[in]     Device         'conditional' MSR device to restore.
 * @param[in]     CallPoint      Indicates whether this is AMD_INIT_RESUME or
 *                               AMD_S3LATE_RESTORE.
 * @param[in,out] OrMask         Current buffer pointer of raw register values.
 *
 */
VOID
RestoreConditionalMsrDevice (
  IN       AMD_CONFIG_PARAMS                 *StdHeader,
  IN       CONDITIONAL_MSR_DEVICE_DESCRIPTOR *Device,
  IN       CALL_POINTS                       CallPoint,
  IN OUT   UINT64                            **OrMask
  )
{
  UINT8   SpecialCaseIndex;
  UINT8   BootMode;
  UINT16  i;
  UINT64  RegValueRead;
  UINT64  RegValueWrite;
  CMSR_REGISTER_BLOCK_HEADER *RegisterHdr;

  if (CallPoint == INIT_RESUME) {
    MemFS3GetCMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  } else {
    S3GetCMsrDeviceRegisterList (Device, &RegisterHdr, StdHeader);
  }

  BootMode = S3_RESUME_MODE;
  if (StdHeader->Func == AMD_INIT_POST) {
    BootMode = RESTORE_TRAINING_MODE | CAPSULE_REBOOT_MODE;
  }

  for (i = 0; i < RegisterHdr->NumRegisters; i++) {
    if (((Device->Mask1 & RegisterHdr->RegisterList[i].Mask1) != 0) &&
        ((Device->Mask2 & RegisterHdr->RegisterList[i].Mask2) != 0)) {
      if ((RegisterHdr->RegisterList[i].BootMode == 0) || ((BootMode & RegisterHdr->RegisterList[i].BootMode) != 0)) {
        // Do not restore the register if not in the right boot mode
        // Pointer to the saved data buffer still needs to be adjusted as data will be saved regardless of boot mode
        RegValueWrite = **OrMask;
        if (RegisterHdr->RegisterList[i].Type.SpecialCaseFlag == 0) {
          LibAmdMsrRead (RegisterHdr->RegisterList[i].Address, &RegValueRead, StdHeader);
          RegValueWrite |= RegValueRead & (~RegisterHdr->RegisterList[i].AndMask);
          LibAmdMsrWrite (RegisterHdr->RegisterList[i].Address, &RegValueWrite, StdHeader);
        } else {
          SpecialCaseIndex = RegisterHdr->RegisterList[i].Type.SpecialCaseIndex;
          RegisterHdr->SpecialCases[SpecialCaseIndex].Save (RegisterHdr->RegisterList[i].Address,
                                                             &RegValueRead,
                                                             StdHeader);
          RegValueWrite |= RegValueRead & (~RegisterHdr->RegisterList[i].AndMask);
          RegisterHdr->SpecialCases[SpecialCaseIndex].Restore (RegisterHdr->RegisterList[i].Address,
                                                               &RegValueWrite,
                                                               StdHeader);
        }
      }
      (*OrMask)++;
    }
  }
}

/*---------------------------------------------------------------------------------------*/
/**
 * Unique device ID to PCI register list translator.
 *
 * This translates the given device header in storage to the appropriate list
 * of registers in the AGESA image.
 *
 * @param[out]   NonMemoryRelatedDeviceList  List of devices to save and restore
 *                                           during S3LateRestore.
 * @param[in]    StdHeader                   AMD standard header config param.
 *
 */
VOID
GetNonMemoryRelatedDeviceList (
     OUT   DEVICE_BLOCK_HEADER **NonMemoryRelatedDeviceList,
  IN       AMD_CONFIG_PARAMS   *StdHeader
  )
{
  *NonMemoryRelatedDeviceList = NULL;
}

/*---------------------------------------------------------------------------------------*/
/**
 * Unique device ID to PCI register list translator.
 *
 * This translates the given device header in storage to the appropriate list
 * of registers in the AGESA image.
 *
 * @param[in]     Device         Device header containing the unique ID.
 * @param[out]    RegisterHdr    Output PCI register list pointer.
 * @param[in]     StdHeader      AMD standard header config param.
 *
 * @retval        AGESA_SUCCESS  Always succeeds.
 */
AGESA_STATUS
S3GetPciDeviceRegisterList (
  IN       PCI_DEVICE_DESCRIPTOR     *Device,
     OUT   PCI_REGISTER_BLOCK_HEADER **RegisterHdr,
  IN       AMD_CONFIG_PARAMS         *StdHeader
  )
{
  *RegisterHdr = NULL;
  return AGESA_SUCCESS;
}

/*---------------------------------------------------------------------------------------*/
/**
 * Unique device ID to 'conditional' PCI register list translator.
 *
 * This translates the given device header in storage to the appropriate list
 * of registers in the AGESA image.
 *
 * @param[in]     Device         Device header containing the unique ID.
 * @param[out]    RegisterHdr    Output 'conditional' PCI register list pointer.
 * @param[in]     StdHeader      AMD standard header config param.
 *
 * @retval        AGESA_SUCCESS  Always succeeds.
 */
AGESA_STATUS
S3GetCPciDeviceRegisterList (
  IN       CONDITIONAL_PCI_DEVICE_DESCRIPTOR *Device,
     OUT   CPCI_REGISTER_BLOCK_HEADER        **RegisterHdr,
  IN       AMD_CONFIG_PARAMS                 *StdHeader
  )
{
  *RegisterHdr = NULL;
  return AGESA_SUCCESS;
}


/*---------------------------------------------------------------------------------------*/
/**
 * Unique device ID to MSR register list translator.
 *
 * This translates the given device header in storage to the appropriate list
 * of registers in the AGESA image.
 *
 * @param[in]     Device         Device header containing the unique ID.
 * @param[out]    RegisterHdr    Output MSR register list pointer.
 * @param[in]     StdHeader      AMD standard header config param.
 *
 * @retval        AGESA_SUCCESS  Always succeeds.
 */
AGESA_STATUS
S3GetMsrDeviceRegisterList (
  IN       MSR_DEVICE_DESCRIPTOR     *Device,
     OUT   MSR_REGISTER_BLOCK_HEADER **RegisterHdr,
  IN       AMD_CONFIG_PARAMS         *StdHeader
  )
{
  *RegisterHdr = NULL;
  return AGESA_SUCCESS;
}

/*---------------------------------------------------------------------------------------*/
/**
 * Unique device ID to 'conditional' MSR register list translator.
 *
 * This translates the given device header in storage to the appropriate list
 * of registers in the AGESA image.
 *
 * @param[in]     Device         Device header containing the unique ID.
 * @param[out]    RegisterHdr    Output 'conditional' MSR register list pointer.
 * @param[in]     StdHeader      AMD standard header config param.
 *
 * @retval        AGESA_SUCCESS  Always succeeds.
 */
AGESA_STATUS
S3GetCMsrDeviceRegisterList (
  IN       CONDITIONAL_MSR_DEVICE_DESCRIPTOR *Device,
     OUT   CMSR_REGISTER_BLOCK_HEADER        **RegisterHdr,
  IN       AMD_CONFIG_PARAMS                 *StdHeader
  )
{
  *RegisterHdr = NULL;
  return AGESA_SUCCESS;
}

/*---------------------------------------------------------------------------------------*/
/**
 * Constructor for the AMD_S3_PARAMS structure.
 *
 * This routine initializes failsafe values for the AMD_S3_PARAMS structure
 * to be used by the AMD_INIT_RESUME, AMD_S3_SAVE, and AMD_S3LATE_RESTORE
 * entry points.
 *
 * @param[in,out] S3Params       Required input parameter for the AMD_S3_SAVE,
 *                               AMD_INIT_RESUME, and AMD_S3_SAVE entry points.
 *
 */
VOID
AmdS3ParamsInitializer (
  OUT   AMD_S3_PARAMS *S3Params
  )
{
  S3Params->Signature = 0x52545341;
  S3Params->Version = 0x0000;
  S3Params->VolatileStorage = NULL;
  S3Params->VolatileStorageSize = 0x00000000;
  S3Params->Flags = 0x00000000;
  S3Params->NvStorage = NULL;
  S3Params->NvStorageSize = 0x00000000;
}
