/**
 * Single socket call to determine the frequency that the northbridges must run.
 *
 * This function simply returns the executing core's NB frequency, and that all
 * NB frequencies are equivalent.
 *
 * @param[in]  NbPstate                    NB P-state number to check (0 = fastest)
 * @param[in]  PlatformConfig              Platform profile/build option config structure.
 * @param[out] SystemNbCofNumerator        NB frequency numerator for the system in MHz
 * @param[out] SystemNbCofDenominator      NB frequency denominator for the system
 * @param[out] SystemNbCofsMatch           Whether or not all NB frequencies are equivalent
 * @param[out] NbPstateIsEnabledOnAllCPUs  Whether or not NbPstate is valid on all CPUs
 * @param[in]  StdHeader                   Config handle for library and services
 *
 * @retval     TRUE                        At least one processor has NbPstate enabled.
 * @retval     FALSE                       NbPstate is disabled on all CPUs
 *
 */
BOOLEAN
GetSystemNbCofSingle (
  IN       UINT32 NbPstate,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
     OUT   UINT32 *SystemNbCofNumerator,
     OUT   UINT32 *SystemNbCofDenominator,
     OUT   BOOLEAN *SystemNbCofsMatch,
     OUT   BOOLEAN *NbPstateIsEnabledOnAllCPUs,
  IN       AMD_CONFIG_PARAMS *StdHeader
  )
{
  UINT32 Ignored;
  PCI_ADDR PciAddress;
  CPU_SPECIFIC_SERVICES *FamilySpecificServices;

  PciAddress.AddressValue = MAKE_SBDFO (0, 0, 24, 0, 0);
  *SystemNbCofsMatch = TRUE;
  GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader);
  *NbPstateIsEnabledOnAllCPUs = FamilySpecificServices->GetNbPstateInfo (FamilySpecificServices,
                                                                         PlatformConfig,
                                                                         &PciAddress,
                                                                         NbPstate,
                                                                         SystemNbCofNumerator,
                                                                         SystemNbCofDenominator,
                                                                         &Ignored,
                                                                         StdHeader);
  return *NbPstateIsEnabledOnAllCPUs;
}
/**
 * Multisocket call to determine the frequency that the northbridges must run.
 *
 * This function loops through all possible socket locations, comparing the
 * maximum NB frequencies to determine the slowest.  This function also
 * determines if all coherent NB frequencies are equivalent.
 *
 * @param[in]  NbPstate                    NB P-state number to check (0 = fastest)
 * @param[in]  PlatformConfig              Platform profile/build option config structure.
 * @param[out] SystemNbCofNumerator        NB frequency numerator for the system in MHz
 * @param[out] SystemNbCofDenominator      NB frequency denominator for the system
 * @param[out] SystemNbCofsMatch           Whether or not all NB frequencies are equivalent
 * @param[out] NbPstateIsEnabledOnAllCPUs  Whether or not NbPstate is valid on all CPUs
 * @param[in]  StdHeader                   Config handle for library and services
 *
 * @retval     TRUE                        At least one processor has NbPstate enabled.
 * @retval     FALSE                       NbPstate is disabled on all CPUs
 *
 */
BOOLEAN
GetSystemNbCofMulti (
  IN       UINT32 NbPstate,
  IN       PLATFORM_CONFIGURATION *PlatformConfig,
     OUT   UINT32 *SystemNbCofNumerator,
     OUT   UINT32 *SystemNbCofDenominator,
     OUT   BOOLEAN *SystemNbCofsMatch,
     OUT   BOOLEAN *NbPstateIsEnabledOnAllCPUs,
  IN       AMD_CONFIG_PARAMS *StdHeader
  )
{
  UINT32   Socket;
  UINT8    Module;
  UINT32   CurrentNbCof;
  UINT32   CurrentDivisor;
  UINT32   CurrentFreq;
  UINT32   LowFrequency;
  UINT32   Ignored32;
  BOOLEAN  FirstCofNotFound;
  BOOLEAN  NbPstateDisabled;
  BOOLEAN  IsNbPstateEnabledOnAny;
  PCI_ADDR PciAddress;
  AGESA_STATUS Ignored;
  CPU_SPECIFIC_SERVICES *FamilySpecificServices;

  // Find the slowest NB COF in the system & whether or not all are equivalent
  LowFrequency = 0xFFFFFFFF;
  *SystemNbCofsMatch = TRUE;
  *NbPstateIsEnabledOnAllCPUs = FALSE;
  IsNbPstateEnabledOnAny = FALSE;
  FirstCofNotFound = TRUE;
  NbPstateDisabled = FALSE;
  for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) {
    if (IsProcessorPresent (Socket, StdHeader)) {
      GetCpuServicesOfSocket (Socket, (CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
      for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) {
        if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &Ignored)) {
          break;
        }
      }
      if (FamilySpecificServices->GetNbPstateInfo (FamilySpecificServices,
                                                   PlatformConfig,
                                                   &PciAddress,
                                                   NbPstate,
                                                   &CurrentNbCof,
                                                   &CurrentDivisor,
                                                   &Ignored32,
                                                   StdHeader)) {
        ASSERT (CurrentDivisor != 0);
        CurrentFreq = (CurrentNbCof / CurrentDivisor);
        if (FirstCofNotFound) {
          *SystemNbCofNumerator = CurrentNbCof;
          *SystemNbCofDenominator = CurrentDivisor;
          LowFrequency = CurrentFreq;
          IsNbPstateEnabledOnAny = TRUE;
          if (!NbPstateDisabled) {
            *NbPstateIsEnabledOnAllCPUs = TRUE;
          }
          FirstCofNotFound = FALSE;
        } else {
          if (CurrentFreq != LowFrequency) {
            *SystemNbCofsMatch = FALSE;
            if (CurrentFreq < LowFrequency) {
              LowFrequency = CurrentFreq;
              *SystemNbCofNumerator = CurrentNbCof;
              *SystemNbCofDenominator = CurrentDivisor;
            }
          }
        }
      } else {
        NbPstateDisabled = TRUE;
        *NbPstateIsEnabledOnAllCPUs = FALSE;
      }
    }
  }
  return IsNbPstateEnabledOnAny;
}