/* $NoKeywords:$ */
/**
 * @file
 *
 * AMD CPU BrandId related functions.
 *
 * Contains code that provides CPU BrandId information
 *
 * @xrefitem bom "File Content Label" "Release Content"
 * @e project:      AGESA
 * @e sub-project:  CPU
 * @e \$Revision: 63425 $   @e \$Date: 2011-12-22 11:24:10 -0600 (Thu, 22 Dec 2011) $
 *
 */
/*****************************************************************************
 *
 * Copyright (c) 2008 - 2012, 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 "OptionPstate.h"
#include "cpuRegisters.h"
#include "cpuFamilyTranslation.h"
#include "cpuEarlyInit.h"
#include "cpuRegisters.h"
#include "heapManager.h"
#include "GeneralServices.h"
#include "Filecode.h"
CODE_GROUP (G1_PEICC)
RDATA_GROUP (G1_PEICC)
#define FILECODE PROC_CPU_CPUBRANDID_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
 *----------------------------------------------------------------------------------------
 */
CONST CHAR8 ROMDATA strEngSample[] = "AMD Engineering Sample";
CONST CHAR8 ROMDATA strTtkSample[] = "AMD Thermal Test Kit";
CONST CHAR8 ROMDATA strUnknown[] = "AMD Processor Model Unknown";

CONST AMD_CPU_BRAND ROMDATA EngSample_Str = {0, 0, 0, SOCKET_IGNORE, strEngSample, sizeof (strEngSample)};
CONST AMD_CPU_BRAND ROMDATA TtkSample_Str = {0, 1, 0, SOCKET_IGNORE, strTtkSample, sizeof (strTtkSample)};
CONST AMD_CPU_BRAND ROMDATA Dflt_Str1 = {0, 0, 0, SOCKET_IGNORE, strUnknown, sizeof (strUnknown)};
CONST AMD_CPU_BRAND ROMDATA Dflt_Str2 = {0, 0, 0, SOCKET_IGNORE, DR_NO_STRING, DR_NO_STRING};


/*----------------------------------------------------------------------------------------
 *           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
SetBrandIdRegistersAtEarly (
  IN       CPU_SPECIFIC_SERVICES  *FamilyServices,
  IN       AMD_CPU_EARLY_PARAMS   *EarlyParams,
  IN       AMD_CONFIG_PARAMS      *StdHeader
  );

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

/*---------------------------------------------------------------------------------------*/
/**
 * Program BrandID registers (CPUIDNameStringPtr[0-5])
 *
 * This function determines the appropriate brand string for the executing
 * core, and programs the namestring MSRs.
 *
 * @param[in,out] StdHeader   Config handle for library and services.
 *
 */
VOID
SetBrandIdRegisters (
  IN OUT   AMD_CONFIG_PARAMS *StdHeader
  )
{
  UINT8   SocketIndex;
  UINT8   SuffixStatus;
  UINT8   TableElements;
  UINT8   TableEntryCount;
  UINT8   TableEntryIndex;
  CHAR8   TempChar;
  CHAR8   *NameStringPtr;
  CHAR8   *SuffixStringPtr;
  CHAR8   *BrandStringPtr;
  CHAR8   *TempNameCharPtr;
  UINT32  MsrIndex;
  UINT32  Quotient;
  UINT32  Remainder;
  UINT64  *MsrNameStringPtrPtr;
  CPUID_DATA    CpuId;
  CPU_LOGICAL_ID CpuLogicalId;
  CPU_BRAND_TABLE *SocketTableEntry;
  CPU_BRAND_TABLE **SocketTableEntry1;
  AMD_CPU_BRAND *SocketTablePtr;
  AMD_CPU_BRAND_DATA Data;
  ALLOCATE_HEAP_PARAMS AllocHeapParams;
  CPU_SPECIFIC_SERVICES *FamilySpecificServices;

  SuffixStatus = 0;
  FamilySpecificServices = NULL;
  SocketTablePtr = NULL;
  SocketTableEntry = NULL;

  GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
  // Step1: Allocate 48 bytes from Heap space
  AllocHeapParams.RequestedBufferSize = CPU_BRAND_ID_LENGTH;
  AllocHeapParams.BufferHandle = AMD_BRAND_ID_BUFFER_HANDLE;
  AllocHeapParams.Persist = HEAP_LOCAL_CACHE;
  if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) {
    // Clear NameBuffer
    BrandStringPtr = (CHAR8 *) AllocHeapParams.BufferPtr;
    LibAmdMemFill (BrandStringPtr, 0, CPU_BRAND_ID_LENGTH, StdHeader);
  } else {
    PutEventLog (
      AGESA_ERROR,
      CPU_ERROR_BRANDID_HEAP_NOT_AVAILABLE,
      0, 0, 0, 0, StdHeader
      );
    return;
  }

  // Step2: Get brandid from model number and model string
  LibAmdCpuidRead (AMD_CPUID_FMF, &CpuId, StdHeader);

  // Step3: Figure out Socket/Page/Model/String1/String2/Core Number
  Data.String2 = (UINT8) (CpuId.EBX_Reg & 0x0f);
  Data.Model   = (UINT8) ((CpuId.EBX_Reg >> 4) & 0x7f);
  Data.String1 = (UINT8) ((CpuId.EBX_Reg >> 11) & 0x0f);
  Data.Page    = (UINT8) ((CpuId.EBX_Reg >> 15) & 0x01);
  Data.Socket  = (UINT8) ((CpuId.EBX_Reg >> 28) & 0x0f);
  Data.Cores = FamilySpecificServices->GetNumberOfPhysicalCores (FamilySpecificServices, StdHeader);

  // Step4: If NN = 0, we have an engineering sample, no suffix; then jump to Step6
  if (Data.Model == 0) {
    if (Data.Page == 0) {
      SocketTablePtr = (AMD_CPU_BRAND *)&EngSample_Str;
    } else {
      SocketTablePtr = (AMD_CPU_BRAND *)&TtkSample_Str;
    }
  } else {

    // Model is not equal to zero, so decrement it
    // For family 10 if PkgType[3:0] is greater than or equal to 2h and families >= 12h
    GetLogicalIdOfCurrentCore (&CpuLogicalId, StdHeader);
    if ((((CpuLogicalId.Family & AMD_FAMILY_10) != 0) && (Data.Socket >= DR_SOCKET_S1G3)) ||
        ((CpuLogicalId.Family & AMD_FAMILY_GE_12) != 0)) {
      Data.Model--;
    }

    // Step5: Search for String1 (there can be only 1)
    FamilySpecificServices->GetBrandString1 (FamilySpecificServices, (CONST VOID **) &SocketTableEntry, &TableEntryCount, StdHeader);
    SocketTableEntry1 = (CPU_BRAND_TABLE **) SocketTableEntry;
    for (TableEntryIndex = 0; ((TableEntryIndex < TableEntryCount)
         && (SuffixStatus == 0)); TableEntryIndex++, SocketTableEntry1++) {
      if (*SocketTableEntry1 == NULL) {
        break;
      }
      SocketTablePtr = (AMD_CPU_BRAND *) (*SocketTableEntry1)->Table;
      TableElements = (*SocketTableEntry1)->NumberOfEntries;
      for (SocketIndex = 0; (SocketIndex < TableElements)
           && SuffixStatus == 0; SocketIndex++) {
        if ((SocketTablePtr->Page == Data.Page) &&
            (SocketTablePtr->Index == Data.String1) &&
            (SocketTablePtr->Socket == Data.Socket) &&
            (SocketTablePtr->Cores == Data.Cores)) {
          SuffixStatus = 1;
        } else {
          SocketTablePtr++;
        }
      }
    }
    if (SuffixStatus == 0) {
      SocketTablePtr = (AMD_CPU_BRAND *)&Dflt_Str1;  // We did not find one, make 'Unknown'
    }
  }

  // Step6: Copy String into NameBuffer
  // We now have data structure pointing to correct type in (*SocketTablePtr)
  LibAmdMemCopy  (BrandStringPtr,
                  (CHAR8 *)SocketTablePtr->Stringstart,
                  SocketTablePtr->Stringlength,
                  StdHeader);

  // Step7: Get suffix, determine addition to BRANDSPEED
  if (SuffixStatus != 0) {
    // Turn our value into a decimal string
    // We have a value like 37d which we need to turn into '3' '7'
    // Divide by 10, store remainder as an ASCII char on stack, repeat until Quotient is 0
    NameStringPtr = BrandStringPtr + SocketTablePtr->Stringlength - 1;
    TempNameCharPtr = NameStringPtr;
    Quotient = Data.Model;
    do {
      Remainder = Quotient % 10;
      Quotient = Quotient / 10;
      *TempNameCharPtr++ = (CHAR8) (Remainder + '0');   // Put suffix into our NameBuffer
    } while (Quotient != 0);
    if (Data.Model < 10) {
      *TempNameCharPtr++ = '0';
    }

    // Step8: Reverse the string sequence and copy into NameBuffer
    SuffixStringPtr = TempNameCharPtr--;
    while (NameStringPtr < TempNameCharPtr) {
      TempChar = *NameStringPtr;
      *NameStringPtr = *TempNameCharPtr;
      *TempNameCharPtr = TempChar;
      NameStringPtr++;
      TempNameCharPtr--;
    }

    // Step9: Search for String2
    SuffixStatus = 0;
    FamilySpecificServices->GetBrandString2 (FamilySpecificServices, (CONST VOID **) &SocketTableEntry, &TableEntryCount, StdHeader);
    SocketTableEntry1 = (CPU_BRAND_TABLE **) SocketTableEntry;
    for (TableEntryIndex = 0; ((TableEntryIndex < TableEntryCount)
         && (SuffixStatus == 0)); TableEntryIndex++, SocketTableEntry1++) {
      if (*SocketTableEntry1 == NULL) {
        break;
      }
      SocketTablePtr = (AMD_CPU_BRAND *) (*SocketTableEntry1)->Table;
      TableElements = (*SocketTableEntry1)->NumberOfEntries;
      for (SocketIndex = 0; (SocketIndex < TableElements)
           && SuffixStatus == 0; SocketIndex++) {
        if ((SocketTablePtr->Page == Data.Page) &&
            (SocketTablePtr->Index == Data.String2) &&
            (SocketTablePtr->Socket == Data.Socket) &&
            (SocketTablePtr->Cores == Data.Cores)) {
          SuffixStatus = 1;
        } else {
          SocketTablePtr++;
        }
      }
    }
    if (SuffixStatus == 0) {
      SocketTablePtr = (AMD_CPU_BRAND *)&Dflt_Str2;
    }

    // Step10: Copy String2 into our NameBuffer
    if (SocketTablePtr->Stringlength != 0) {
      LibAmdMemCopy (SuffixStringPtr,
                      (CHAR8 *)SocketTablePtr->Stringstart,
                      SocketTablePtr->Stringlength,
                      StdHeader);
    }
  }

  // Step11: Put values into name MSRs,  Always write the full 48 bytes
  MsrNameStringPtrPtr = (UINT64 *) BrandStringPtr;
  for (MsrIndex = MSR_CPUID_NAME_STRING0; MsrIndex <= MSR_CPUID_NAME_STRING5; MsrIndex++) {
    LibAmdMsrWrite (MsrIndex, MsrNameStringPtrPtr, StdHeader);
    MsrNameStringPtrPtr++;
  }
  HeapDeallocateBuffer (AMD_BRAND_ID_BUFFER_HANDLE, StdHeader);
}

/*---------------------------------------------------------------------------------------*/
/**
 * Program BrandID registers (CPUIDNameStringPtr[0-5])
 *
 * This function acts as a wrapper for calling the SetBrandIdRegisters
 * routine at AmdInitEarly.
 *
 *  @param[in]   FamilyServices      The current Family Specific Services.
 *  @param[in]   EarlyParams         Service parameters.
 *  @param[in]   StdHeader           Config handle for library and services.
 *
 */
VOID
SetBrandIdRegistersAtEarly (
  IN       CPU_SPECIFIC_SERVICES  *FamilyServices,
  IN       AMD_CPU_EARLY_PARAMS   *EarlyParams,
  IN       AMD_CONFIG_PARAMS      *StdHeader
  )
{
  AGESA_TESTPOINT (TpProcCpuSetBrandID, StdHeader);
  SetBrandIdRegisters (StdHeader);
}
