1b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/** @file
2b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyThis is the driver that locates the MemoryConfigurationData HOB, if it
3b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneyexists, and saves the data to nvRAM.
4b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
5b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyCopyright (c) 2013-2015 Intel Corporation.
6b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
7b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyThis program and the accompanying materials
8b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneyare licensed and made available under the terms and conditions of the BSD License
9b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneywhich accompanies this distribution.  The full text of the license may be found at
10b303605e1b7e113b4311daf161c6c3289350447bMichael Kinneyhttp://opensource.org/licenses/bsd-license.php
11b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
12b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
15b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney**/
16b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
17b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney#include <Library/DebugLib.h>
18b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney#include <Library/HobLib.h>
19b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney#include <Library/MemoryAllocationLib.h>
20b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney#include <Library/UefiBootServicesTableLib.h>
21b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney#include <Library/UefiRuntimeServicesTableLib.h>
22b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney#include <Library/BaseMemoryLib.h>
23b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney#include <Library/UefiDriverEntryPoint.h>
24b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
25b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney#include <Guid/MemoryConfigData.h>
26b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney#include <Guid/DebugMask.h>
27b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
28b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFI_STATUS
29b303605e1b7e113b4311daf161c6c3289350447bMichael KinneyEFIAPI
30b303605e1b7e113b4311daf161c6c3289350447bMichael KinneySaveMemoryConfigEntryPoint (
31b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN EFI_HANDLE         ImageHandle,
32b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  IN EFI_SYSTEM_TABLE   *SystemTable
33b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  )
34b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney/*++
35b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
36b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Routine Description:
37b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    This is the standard EFI driver point that detects whether there is a
38b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    MemoryConfigurationData HOB and, if so, saves its data to nvRAM.
39b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
40b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Arguments:
41b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    ImageHandle   - Handle for the image of this driver
42b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    SystemTable   - Pointer to the EFI System Table
43b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
44b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Returns:
45b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    EFI_SUCCESS   - if the data is successfully saved or there was no data
46b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    EFI_NOT_FOUND - if the HOB list could not be located.
47b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    EFI_UNLOAD_IMAGE - It is not success
48b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
49b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney--*/
50b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney{
51b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_STATUS  Status;
52b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  VOID        *HobList;
53b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  EFI_HOB_GUID_TYPE *GuidHob;
54b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  VOID        *HobData;
55b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  VOID        *VariableData;
56b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN       DataSize;
57b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  UINTN       BufferSize;
58b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
59b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  DataSize      = 0;
60b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  VariableData  = NULL;
61b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  GuidHob = NULL;
62b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  HobList = NULL;
63b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  HobData = NULL;
64b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  Status  = EFI_UNSUPPORTED;
65b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
66b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
67b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Get the HOB list.  If it is not present, then ASSERT.
68b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
69b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  HobList = GetHobList ();
70b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  ASSERT (HobList != NULL);
71b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
72b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
73b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // Search for the Memory Configuration GUID HOB.  If it is not present, then
74b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // there's nothing we can do. It may not exist on the update path.
75b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
76b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  GuidHob = GetNextGuidHob (&gEfiMemoryConfigDataGuid, HobList);
77b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  if (GuidHob != NULL) {
78b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    HobData = GET_GUID_HOB_DATA (GuidHob);
79b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    DataSize = GET_GUID_HOB_DATA_SIZE (GuidHob);
80b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
81b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    // Use the HOB to save Memory Configuration Data
82b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    //
83b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    BufferSize = DataSize;
84b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    VariableData = AllocatePool (BufferSize);
85b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    ASSERT (VariableData != NULL);
86b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    Status = gRT->GetVariable (
87b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                    EFI_MEMORY_CONFIG_DATA_NAME,
88b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                    &gEfiMemoryConfigDataGuid,
89b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                    NULL,
90b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                    &BufferSize,
91b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                    VariableData
92b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                    );
93b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (Status == EFI_BUFFER_TOO_SMALL) {
94b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      gBS->FreePool (VariableData);
95b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      VariableData = AllocatePool (BufferSize);
96b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      ASSERT (VariableData != NULL);
97b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = gRT->GetVariable (
98b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                      EFI_MEMORY_CONFIG_DATA_NAME,
99b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                      &gEfiMemoryConfigDataGuid,
100b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                      NULL,
101b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                      &BufferSize,
102b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                      VariableData
103b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                      );
104b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
105b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
106b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    if (EFI_ERROR(Status) || BufferSize != DataSize || CompareMem (HobData, VariableData, DataSize) != 0) {
107b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      Status = gRT->SetVariable (
108b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                      EFI_MEMORY_CONFIG_DATA_NAME,
109b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                      &gEfiMemoryConfigDataGuid,
110b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                      (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS),
111b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                      DataSize,
112b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                      HobData
113b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney                      );
114b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney      ASSERT((Status == EFI_SUCCESS) || (Status == EFI_OUT_OF_RESOURCES));
115b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    }
116b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
117b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney    gBS->FreePool (VariableData);
118b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  }
119b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney
120b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
121b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  // This driver does not produce any protocol services, so always unload it.
122b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  //
123b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney  return Status;
124b303605e1b7e113b4311daf161c6c3289350447bMichael Kinney}
125