text: /* $NoKeywords:$ */
  /**
   * @file
   *
   * AMD AGESA Basic Level Public APIs
   *
   * Contains basic Level Initialization routines.
   *
   * @xrefitem bom "File Content Label" "Release Content"
   * @e project:      AGESA
   * @e sub-project:  Interface
   * @e \$Revision: 44324 $   @e \$Date: 2010-12-22 17:16:51 +0800 (Wed, 22 Dec 2010) $
   *
   */
  /*****************************************************************************
   *
   * Copyright (c) 2011, 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 "CommonInits.h"
  #include "AmdFch.h"
  #include "Filecode.h"
  #include "heapManager.h"
  #include "Topology.h"
  #include "CreateStruct.h"
  CODE_GROUP (G3_DXE)
  RDATA_GROUP (G3_DXE)
  
  #define FILECODE PROC_COMMON_AMDS3SAVE_FILECODE
  
  extern BLDOPT_FCH_FUNCTION  BldoptFchFunction;
  
  /*----------------------------------------------------------------------------------------
   *                   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
   *----------------------------------------------------------------------------------------
   */
  CONST UINT32 ROMDATA S3LateHeapTable[] =
  {
    EVENT_LOG_BUFFER_HANDLE,
    SOCKET_DIE_MAP_HANDLE,
    NODE_ID_MAP_HANDLE,
    LOCAL_AP_MAIL_BOX_CACHE_HANDLE,
    IDS_CONTROL_HANDLE,
    AMD_S3_SCRIPT_SAVE_TABLE_HANDLE,
    AMD_PCIE_COMPLEX_DATA_HANDLE
  };
  
  #define S3LATE_TABLE_SIZE (sizeof (S3LateHeapTable) / sizeof (UINT32)) //(sizeof (S3LateHeapTable) / sizeof (S3LATE_HEAP_ELEMENT))
  
  
  /*----------------------------------------------------------------------------------------
   *           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
   *----------------------------------------------------------------------------------------
   */
  AGESA_STATUS
  AmdS3SavePlatformConfigInit (
    IN OUT   PLATFORM_CONFIGURATION    *PlatformConfig,
    IN OUT   AMD_CONFIG_PARAMS         *StdHeader
    );
  
  /*----------------------------------------------------------------------------------------
   *                          E X P O R T E D    F U N C T I O N S
   *----------------------------------------------------------------------------------------
   */
  extern BUILD_OPT_CFG UserOptions;
  
  /*---------------------------------------------------------------------------------------*/
  /**
   * Main entry point for the AMD_S3_SAVE function.
   *
   * This entry point is responsible for saving silicon component registers to the
   * SMM save area in preparation of entering system suspend-to-RAM mode.
   *
   * @param[in,out] AmdS3SaveParams   Required input parameters for the AMD_S3_SAVE
   *                                  entry point.
   *
   * @return        Aggregated status across all internal AMD S3 save calls invoked.
   *
   */
  AGESA_STATUS
  AmdS3Save (
    IN OUT   AMD_S3SAVE_PARAMS *AmdS3SaveParams
    )
  {
    UINTN  i;
    UINT32 EarlyBufferSize;
    UINT32 LateBufferSize;
    UINT32 LateContextSize;
    UINT32 HeapSize;
    UINT8  *BufferPointer;
    UINT8  HeapStatus;
    ALLOCATE_HEAP_PARAMS HeapParams;
    LOCATE_HEAP_PTR LocateHeap;
    BUFFER_NODE *FreeSpaceNode;
    ALLOCATE_HEAP_PARAMS AllocParams;
    DEVICE_BLOCK_HEADER *MemoryRelatedDeviceList;
    DEVICE_BLOCK_HEADER *NonMemoryRelatedDeviceList;
    AGESA_STATUS ReturnStatus;
    VOID   *HeapPtrs[S3LATE_TABLE_SIZE];
    UINT32 HeapSizes[S3LATE_TABLE_SIZE];
    UINT32 HeapBuffersPresent;
    HEAP_MANAGER *HeapPtr;
  
    AGESA_TESTPOINT (TpIfAmdS3SaveEntry, &AmdS3SaveParams->StdHeader);
  
    ASSERT (AmdS3SaveParams != NULL);
  
    HeapBuffersPresent = 0;
    EarlyBufferSize = 0;
    LateBufferSize = 0;
    LateContextSize = 0;
    HeapSize = 0;
    NonMemoryRelatedDeviceList = NULL;
    MemoryRelatedDeviceList = NULL;
    ReturnStatus = AGESA_SUCCESS;
  
    IDS_SKIP_HOOK (IDS_BEFORE_S3_SAVE, AmdS3SaveParams, &(AmdS3SaveParams->StdHeader)) {
  
      // Get memory device list
      MemFS3GetDeviceList (&MemoryRelatedDeviceList, &AmdS3SaveParams->StdHeader);
      if (MemoryRelatedDeviceList != NULL) {
        // Determine size needed
        EarlyBufferSize = GetWorstCaseContextSize (MemoryRelatedDeviceList, INIT_RESUME, &AmdS3SaveParams->StdHeader);
      }
  
      if (UserOptions.CfgS3LateRestore) {
        for (i = 0; i < S3LATE_TABLE_SIZE; i++) {
          LocateHeap.BufferHandle = S3LateHeapTable[i];
          if (HeapLocateBuffer (&LocateHeap, &AmdS3SaveParams->StdHeader) == AGESA_SUCCESS) {
            HeapBuffersPresent++;
            HeapSize += LocateHeap.BufferSize;
            HeapPtrs[i] = LocateHeap.BufferPtr;
            HeapSizes[i] = LocateHeap.BufferSize;
          } else {
            HeapPtrs[i] = NULL;
            HeapSizes[i] = 0;
          }
        }
  
        // Determine heap data size requirements
        if (HeapBuffersPresent != 0) {
          HeapSize += ((sizeof (HEAP_MANAGER)) + (HeapBuffersPresent * ((sizeof (BUFFER_NODE)) + (NUM_OF_SENTINEL * SIZE_OF_SENTINEL) + 0xF))); // reserve 0xF per buffer node for 16 byte alignment
        }
  
        // Get non memory device list
        GetNonMemoryRelatedDeviceList (&NonMemoryRelatedDeviceList, &AmdS3SaveParams->StdHeader);
  
        if (NonMemoryRelatedDeviceList != NULL) {
          // Determine size needed
          LateContextSize = GetWorstCaseContextSize (NonMemoryRelatedDeviceList, S3_LATE_RESTORE, &AmdS3SaveParams->StdHeader);
        }
        LateBufferSize = HeapSize + LateContextSize;
        if (LateBufferSize != 0) {
          LateBufferSize += sizeof (S3_VOLATILE_STORAGE_HEADER);
        }
      }
  
      if ((EarlyBufferSize != 0) || (LateBufferSize != 0)) {
        //
        // Allocate a buffer
        //
        AllocParams.RequestedBufferSize = EarlyBufferSize + LateBufferSize;
        AllocParams.BufferHandle = AMD_S3_INFO_BUFFER_HANDLE;
  
        AGESA_TESTPOINT (TpIfBeforeAllocateS3SaveBuffer, &AmdS3SaveParams->StdHeader);
        if (HeapAllocateBuffer (&AllocParams, &AmdS3SaveParams->StdHeader) != AGESA_SUCCESS) {
          if (AGESA_ERROR > ReturnStatus) {
            ReturnStatus = AGESA_ERROR;
          }
        }
        AGESA_TESTPOINT (TpIfAfterAllocateS3SaveBuffer, &AmdS3SaveParams->StdHeader);
  
        if (EarlyBufferSize != 0) {
          AmdS3SaveParams->S3DataBlock.NvStorage = AllocParams.BufferPtr;
          SaveDeviceListContext (MemoryRelatedDeviceList,
                             AmdS3SaveParams->S3DataBlock.NvStorage,
                             INIT_RESUME,
                             &EarlyBufferSize,
                             &AmdS3SaveParams->StdHeader);
  
          AmdS3SaveParams->S3DataBlock.NvStorageSize = EarlyBufferSize;
        }
  
        if (LateBufferSize != 0) {
          BufferPointer = AllocParams.BufferPtr;
          AmdS3SaveParams->S3DataBlock.VolatileStorage = &(BufferPointer[EarlyBufferSize]);
  
          ((S3_VOLATILE_STORAGE_HEADER *) AmdS3SaveParams->S3DataBlock.VolatileStorage)->HeapOffset = (intptr_t) NULL;
          ((S3_VOLATILE_STORAGE_HEADER *) AmdS3SaveParams->S3DataBlock.VolatileStorage)->HeapSize = HeapSize;
          ((S3_VOLATILE_STORAGE_HEADER *) AmdS3SaveParams->S3DataBlock.VolatileStorage)->RegisterDataOffset = (intptr_t) NULL;
          ((S3_VOLATILE_STORAGE_HEADER *) AmdS3SaveParams->S3DataBlock.VolatileStorage)->RegisterDataSize = LateContextSize;
  
          if (HeapSize != 0) {
            // Transfer heap contents
            ((S3_VOLATILE_STORAGE_HEADER *) AmdS3SaveParams->S3DataBlock.VolatileStorage)->HeapOffset = sizeof (S3_VOLATILE_STORAGE_HEADER);
            HeapPtr = (HEAP_MANAGER *) &BufferPointer[EarlyBufferSize + sizeof (S3_VOLATILE_STORAGE_HEADER)];
            HeapPtr->UsedSize = sizeof (HEAP_MANAGER);
            HeapPtr->Signature = HEAP_SIGNATURE_VALID;
            HeapPtr->FirstActiveBufferOffset = AMD_HEAP_INVALID_HEAP_OFFSET;
            HeapPtr->FirstFreeSpaceOffset = sizeof (HEAP_MANAGER);
            FreeSpaceNode = (BUFFER_NODE *) ((UINT8 *) HeapPtr + sizeof (HEAP_MANAGER));
            FreeSpaceNode->BufferSize = HeapSize - sizeof (HEAP_MANAGER) - sizeof (BUFFER_NODE);
            FreeSpaceNode->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET;
  
            HeapStatus = AmdS3SaveParams->StdHeader.HeapStatus;
            AmdS3SaveParams->StdHeader.HeapStatus = HEAP_S3_RESUME;
            AmdS3SaveParams->StdHeader.HeapBasePtr = (UINT64) (intptr_t) HeapPtr;
  
            for (i = 0; i < S3LATE_TABLE_SIZE; i++) {
              if (HeapPtrs[i] != NULL) {
                HeapParams.RequestedBufferSize = HeapSizes[i]; // S3LateHeapTable[i].BufferLength;
                HeapParams.BufferHandle = S3LateHeapTable[i];
                HeapParams.Persist = HEAP_S3_RESUME;
                if (HeapAllocateBuffer (&HeapParams, &AmdS3SaveParams->StdHeader) == AGESA_SUCCESS) {
                  LibAmdMemCopy ((VOID *) HeapParams.BufferPtr, HeapPtrs[i], HeapSizes[i], &AmdS3SaveParams->StdHeader);
                }
              }
            }
  
            AmdS3SaveParams->StdHeader.HeapStatus = HeapStatus;
          }
  
  
          if (LateContextSize != 0) {
  
            ((S3_VOLATILE_STORAGE_HEADER *) AmdS3SaveParams->S3DataBlock.VolatileStorage)->RegisterDataOffset = HeapSize + sizeof (S3_VOLATILE_STORAGE_HEADER);
  
            SaveDeviceListContext (NonMemoryRelatedDeviceList,
                                  &(BufferPointer[EarlyBufferSize + HeapSize + sizeof (S3_VOLATILE_STORAGE_HEADER)]),
                                  S3_LATE_RESTORE,
                                  &LateContextSize,
                                  &AmdS3SaveParams->StdHeader);
          }
  
          AmdS3SaveParams->S3DataBlock.VolatileStorageSize = HeapSize + LateContextSize + sizeof (S3_VOLATILE_STORAGE_HEADER);
        }
      }
    }
  
    ReturnStatus = BldoptFchFunction.InitLate (AmdS3SaveParams);
  
    IDS_OPTION_HOOK (IDS_AFTER_S3_SAVE, AmdS3SaveParams, &AmdS3SaveParams->StdHeader);
    AGESA_TESTPOINT (TpIfAmdS3SaveExit, &AmdS3SaveParams->StdHeader);
    return  ReturnStatus;
  }
  
  /*---------------------------------------------------------------------------------------*/
  /**
   * Constructor for the AMD_S3_SAVE function.
   *
   * This routine is responsible for setting default values for the
   * input parameters needed by the AMD_S3_SAVE entry point.
   *
   * @param[in]    StdHeader       The standard header.
   * @param[in,out] S3SaveParams   Required input parameters for the AMD_S3_SAVE
   *                               entry point.
   *
   * @retval        AGESA_SUCCESS  Always Succeeds.
   *
   */
  AGESA_STATUS
  AmdS3SaveInitializer (
    IN OUT   AMD_CONFIG_PARAMS *StdHeader,
    IN OUT   AMD_S3SAVE_PARAMS *S3SaveParams
    )
  {
    ASSERT (StdHeader != NULL);
    ASSERT (S3SaveParams != NULL);
  
    S3SaveParams->StdHeader = *StdHeader;
  
    AmdS3ParamsInitializer (&S3SaveParams->S3DataBlock);
  
    AmdS3SavePlatformConfigInit (&S3SaveParams->PlatformConfig, &S3SaveParams->StdHeader);
    BldoptFchFunction.InitLateConstructor (S3SaveParams);
  
    return AGESA_SUCCESS;
  }
  
  /*---------------------------------------------------------------------------------------*/
  /**
   * Destructor for the AMD_S3_SAVE function.
   *
   * This routine is responsible for deallocation of heap space allocated during
   * AMD_S3_SAVE entry point.
   *
   * @param[in]     StdHeader       The standard header.
   * @param[in,out] S3SaveParams   Required input parameters for the AMD_INIT_RESUME
   *                               entry point.
   *
   * @retval        AGESA_STATUS
   *
   */
  AGESA_STATUS
  AmdS3SaveDestructor (
    IN       AMD_CONFIG_PARAMS *StdHeader,
    IN OUT   AMD_S3SAVE_PARAMS *S3SaveParams
    )
  {
    AGESA_STATUS ReturnStatus;
    AGESA_STATUS RetVal;
  
    ASSERT (S3SaveParams != NULL);
  
    ReturnStatus = AGESA_SUCCESS;
  
    // Deallocate heap space allocated during memory S3 save
    RetVal = MemS3Deallocate (&S3SaveParams->StdHeader);
    if (RetVal > ReturnStatus) {
      ReturnStatus = RetVal;
    }
  
    RetVal = HeapDeallocateBuffer (AMD_S3_NB_INFO_BUFFER_HANDLE, StdHeader);
    if (RetVal > ReturnStatus) {
      ReturnStatus = RetVal;
    }
  
    RetVal = HeapDeallocateBuffer (AMD_S3_INFO_BUFFER_HANDLE, StdHeader);
    if (RetVal > ReturnStatus) {
      ReturnStatus = RetVal;
    }
  
    return ReturnStatus;
  }
  
  /*------------------------------------------------------------------------------------*/
  /**
   * Initialize AmdS3Save stage platform profile and user option input.
   *
   * @param[in,out]   PlatformConfig   Platform profile/build option config structure
   * @param[in,out]   StdHeader        AMD standard header config param
   *
   * @retval          AGESA_SUCCESS    Always Succeeds.
   *
   */
  AGESA_STATUS
  AmdS3SavePlatformConfigInit (
    IN OUT   PLATFORM_CONFIGURATION    *PlatformConfig,
    IN OUT   AMD_CONFIG_PARAMS         *StdHeader
    )
  {
    CommonPlatformConfigInit (PlatformConfig, StdHeader);
  
    return AGESA_SUCCESS;
  }
  