| /* $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; |
| } |