13cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/**
23cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
33cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  This program and the accompanying materials
43cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  are licensed and made available under the terms and conditions of the BSD License
53cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  which accompanies this distribution.  The full text of the license may be found at
63cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  http://opensource.org/licenses/bsd-license.php
73cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
83cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
93cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
123cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiModule Name:
133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  SaveMemoryConfig.c
153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
163cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiAbstract:
173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  This is the driver that locates the MemoryConfigurationData HOB, if it
183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  exists, and saves the data to nvRAM.
193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei--*/
233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei#include "SaveMemoryConfig.h"
253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
263cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiCHAR16    EfiMemoryConfigVariable[] = L"MemoryConfig";
273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
293cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFI_STATUS
303cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiEFIAPI
313cbfba02fef9dae07a041fdbf2e89611d72d6f90David WeiSaveMemoryConfigEntryPoint (
323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN EFI_HANDLE         ImageHandle,
333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  IN EFI_SYSTEM_TABLE   *SystemTable
343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  )
353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei/*++
363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Routine Description:
383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    This is the standard EFI driver point that detects whether there is a
393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    MemoryConfigurationData HOB and, if so, saves its data to nvRAM.
403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Arguments:
423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    ImageHandle   - Handle for the image of this driver
433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    SystemTable   - Pointer to the EFI System Table
443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Returns:
463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    EFI_SUCCESS   - if the data is successfully saved or there was no data
473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    EFI_NOT_FOUND - if the HOB list could not be located.
483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    EFI_UNLOAD_IMAGE - It is not success
493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei--*/
513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei{
523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_STATUS                      Status=EFI_SUCCESS;
533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VOID                            *MemHobData;
543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VOID                            *VariableData;
553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINTN                           BufferSize;
563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  BOOLEAN                         MfgMode;
573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_PLATFORM_SETUP_ID           *BootModeBuffer;
583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_PLATFORM_INFO_HOB           *PlatformInfoHobPtr;
593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  MEM_INFO_PROTOCOL               *MemInfoProtocol;
603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  EFI_HANDLE                      Handle;
613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  UINT8							              Channel, Slot;
623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VOID                            *GuidHob;
633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  VariableData   = NULL;
653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  MfgMode        = FALSE;
663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  Handle         = NULL;
673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  BootModeBuffer = NULL;
683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  MemHobData     = NULL;
693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  PlatformInfoHobPtr = NULL;
703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  BufferSize     = 0;
713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Get Platform Info HOB
743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  GuidHob = GetFirstGuidHob (&gEfiPlatformInfoGuid);
763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (GuidHob == NULL) {
773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Status = EFI_NOT_FOUND;
783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  ASSERT_EFI_ERROR (Status);
803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  PlatformInfoHobPtr = GET_GUID_HOB_DATA (GuidHob);
823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Get the BootMode guid hob
853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  GuidHob = GetFirstGuidHob (&gEfiPlatformBootModeGuid);
873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (GuidHob == NULL) {
883cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Status = EFI_NOT_FOUND;
893cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
903cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  ASSERT_EFI_ERROR (Status);
913cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
923cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  BootModeBuffer = GET_GUID_HOB_DATA (GuidHob);
933cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
943cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
953cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
963cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  // Check whether in Manufacturing Mode
973cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  //
983cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (BootModeBuffer) {
993cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if ( !CompareMem (   //EfiCompareMem
1003cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei            &BootModeBuffer->SetupName,
1013cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei            MANUFACTURE_SETUP_NAME,
1023cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei            StrSize (MANUFACTURE_SETUP_NAME)  //EfiStrSize
1033cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei            ) ) {
1043cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      MfgMode = TRUE;
1053cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
1063cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  }
1073cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1083cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  if (MfgMode) {
1093cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
1103cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    // Don't save Memory Configuration in Manufacturing Mode. Clear memory configuration.
1113cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    //
1123cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Status = gRT->SetVariable (
1133cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei              EfiMemoryConfigVariable,
1143cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei              &gEfiVlv2VariableGuid,
1153cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei              EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1163cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei              0,
1173cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei              NULL
1183cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei              );
1193cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  } else {
1203cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1213cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    MemInfoProtocol = (MEM_INFO_PROTOCOL*)AllocateZeroPool(sizeof(MEM_INFO_PROTOCOL));
1223cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (PlatformInfoHobPtr != NULL) {
1233cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      MemInfoProtocol->MemInfoData.memSize  = 0;
1243cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      for (Channel = 0; Channel < CH_NUM; Channel ++){
1253cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        for (Slot = 0; Slot < DIMM_NUM; Slot ++){
1266f2ef18e8097c4fa11dd6ff5fdd0152c2c61ffc5Tim He          MemInfoProtocol->MemInfoData.dimmSize[Slot + (Channel * DIMM_NUM)] = PlatformInfoHobPtr->MemData.DimmSize[Slot + (Channel * DIMM_NUM)];
1273cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        }
1283cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      }
1293cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  	  MemInfoProtocol->MemInfoData.memSize       = PlatformInfoHobPtr->MemData.MemSize;
1303cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  	  MemInfoProtocol->MemInfoData.EccSupport    = PlatformInfoHobPtr->MemData.EccSupport;
1313cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      MemInfoProtocol->MemInfoData.ddrFreq       = PlatformInfoHobPtr->MemData.DdrFreq;
1323cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      MemInfoProtocol->MemInfoData.ddrType       = PlatformInfoHobPtr->MemData.DdrType;
1333cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      if (MemInfoProtocol->MemInfoData.memSize == 0){
1343cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        //
1353cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        // We hardcode if MRC didn't fill these info in
1363cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        //
1373cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        MemInfoProtocol->MemInfoData.memSize     = 0x800; //per 1MB
1383cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        MemInfoProtocol->MemInfoData.dimmSize[0] = 0x800;
1393cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        MemInfoProtocol->MemInfoData.dimmSize[1] = 0;
1403cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        MemInfoProtocol->MemInfoData.EccSupport  = FALSE;
1413cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        MemInfoProtocol->MemInfoData.ddrType     = 5; //DDRType_LPDDR3
1423cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      }
1433cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1443cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      Status = gBS->InstallMultipleProtocolInterfaces (
1453cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             &Handle,
1463cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             &gMemInfoProtocolGuid,
1473cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             MemInfoProtocol,
1483cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             NULL
1493cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei             );
1503cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
1513cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1523cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    Status = EFI_SUCCESS;
1533cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    if (BOOT_WITH_MINIMAL_CONFIGURATION != GetBootModeHob()){
1543cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      //
1553cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      // Get the Memory Config guid hob
1563cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      //
1573cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      GuidHob = GetFirstGuidHob (&gEfiMemoryConfigDataGuid);
1583cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      if (GuidHob == NULL) {
1593cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        Status = EFI_NOT_FOUND;
1603cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      }
1613cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      ASSERT_EFI_ERROR (Status);
1623cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1633cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      MemHobData = GET_GUID_HOB_DATA (GuidHob);
1643cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      BufferSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
1653cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1663cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      Status = gRT->GetVariable (
1673cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  EfiMemoryConfigVariable,
1683cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  &gEfiVlv2VariableGuid,
1693cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  NULL,
1703cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  &BufferSize,
1713cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  VariableData
1723cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                  );
1733cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      if (EFI_ERROR(Status) && (MemHobData != NULL)) {
1743cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei        Status = gRT->SetVariable (
1753cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                      EfiMemoryConfigVariable,
1763cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                      &gEfiVlv2VariableGuid,
1773cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                      (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS),
1783cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                      BufferSize,
1793cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                      MemHobData
1803cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei                      );
1813cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei      }
1823cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei    }
1833cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1843cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  } // if-else MfgMode
1853cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei
1863cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei  return EFI_SUCCESS;
1873cbfba02fef9dae07a041fdbf2e89611d72d6f90David Wei}
188