1 /**@file
2 
3 Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution.  The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8 
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11 
12 Module Name:
13   WinNtAutoscan.c
14 
15 Abstract:
16   This PEIM to abstract memory auto-scan in a Windows NT environment.
17 
18 Revision History
19 
20 **/
21 
22 //
23 // The package level header files this module uses
24 //
25 #include <PiPei.h>
26 #include <WinNtPeim.h>
27 //
28 // The protocols, PPI and GUID defintions for this module
29 //
30 #include <Ppi/NtAutoscan.h>
31 #include <Ppi/ReadOnlyVariable2.h>
32 
33 #include <Guid/MemoryTypeInformation.h>
34 
35 //
36 // The Library classes this module consumes
37 //
38 #include <Library/DebugLib.h>
39 #include <Library/PeimEntryPoint.h>
40 #include <Library/HobLib.h>
41 #include <Library/PeiServicesLib.h>
42 
43 EFI_MEMORY_TYPE_INFORMATION mDefaultMemoryTypeInformation[] = {
44   { EfiReservedMemoryType,  0x0004 },
45   { EfiRuntimeServicesCode, 0x0040 },
46   { EfiRuntimeServicesData, 0x0040 },
47   { EfiBootServicesCode,    0x0300 },
48   { EfiBootServicesData,    0x1000 },
49   { EfiMaxMemoryType,       0      }
50 };
51 
52 /**
53    Validate variable data for the MemoryTypeInformation.
54 
55    @param MemoryData       Variable data.
56    @param MemoryDataSize   Variable data length.
57 
58    @return TRUE            The variable data is valid.
59    @return FALSE           The variable data is invalid.
60 
61 **/
62 BOOLEAN
ValidateMemoryTypeInfoVariable(IN EFI_MEMORY_TYPE_INFORMATION * MemoryData,IN UINTN MemoryDataSize)63 ValidateMemoryTypeInfoVariable (
64   IN EFI_MEMORY_TYPE_INFORMATION      *MemoryData,
65   IN UINTN                            MemoryDataSize
66   )
67 {
68   UINTN                       Count;
69   UINTN                       Index;
70 
71   // Check the input parameter.
72   if (MemoryData == NULL) {
73     return FALSE;
74   }
75 
76   // Get Count
77   Count = MemoryDataSize / sizeof (*MemoryData);
78 
79   // Check Size
80   if (Count * sizeof(*MemoryData) != MemoryDataSize) {
81     return FALSE;
82   }
83 
84   // Check last entry type filed.
85   if (MemoryData[Count - 1].Type != EfiMaxMemoryType) {
86     return FALSE;
87   }
88 
89   // Check the type filed.
90   for (Index = 0; Index < Count - 1; Index++) {
91     if (MemoryData[Index].Type >= EfiMaxMemoryType) {
92       return FALSE;
93     }
94   }
95 
96   return TRUE;
97 }
98 
99 EFI_STATUS
100 EFIAPI
PeimInitializeWinNtAutoScan(IN EFI_PEI_FILE_HANDLE FileHandle,IN CONST EFI_PEI_SERVICES ** PeiServices)101 PeimInitializeWinNtAutoScan (
102   IN       EFI_PEI_FILE_HANDLE       FileHandle,
103   IN CONST EFI_PEI_SERVICES          **PeiServices
104   )
105 /*++
106 
107 Routine Description:
108   Perform a call-back into the SEC simulator to get a memory value
109 
110 Arguments:
111   FfsHeader   - General purpose data available to every PEIM
112   PeiServices - General purpose services available to every PEIM.
113 
114 Returns:
115   None
116 
117 --*/
118 {
119   EFI_STATUS                  Status;
120   EFI_PEI_PPI_DESCRIPTOR      *PpiDescriptor;
121   PEI_NT_AUTOSCAN_PPI         *PeiNtService;
122   UINT64                      MemorySize;
123   EFI_PHYSICAL_ADDRESS        MemoryBase;
124   UINTN                       Index;
125   EFI_RESOURCE_ATTRIBUTE_TYPE Attributes;
126   EFI_PEI_READ_ONLY_VARIABLE2_PPI       *Variable;
127   UINTN                                 DataSize;
128   EFI_MEMORY_TYPE_INFORMATION           MemoryData [EfiMaxMemoryType + 1];
129 
130 
131   DEBUG ((EFI_D_ERROR, "NT 32 Autoscan PEIM Loaded\n"));
132 
133   //
134   // Get the PEI NT Autoscan PPI
135   //
136   Status = PeiServicesLocatePpi (
137              &gPeiNtAutoScanPpiGuid, // GUID
138              0,                      // INSTANCE
139              &PpiDescriptor,         // EFI_PEI_PPI_DESCRIPTOR
140              (VOID**)&PeiNtService           // PPI
141              );
142   ASSERT_EFI_ERROR (Status);
143 
144   Index = 0;
145   do {
146     Status = PeiNtService->NtAutoScan (Index, &MemoryBase, &MemorySize);
147     if (!EFI_ERROR (Status)) {
148       Attributes =
149         (
150           EFI_RESOURCE_ATTRIBUTE_PRESENT |
151           EFI_RESOURCE_ATTRIBUTE_INITIALIZED |
152           EFI_RESOURCE_ATTRIBUTE_UNCACHEABLE |
153           EFI_RESOURCE_ATTRIBUTE_WRITE_COMBINEABLE |
154           EFI_RESOURCE_ATTRIBUTE_WRITE_THROUGH_CACHEABLE |
155           EFI_RESOURCE_ATTRIBUTE_WRITE_BACK_CACHEABLE
156         );
157 
158       if (Index == 0) {
159         //
160         // Register the memory with the PEI Core
161         //
162         Status = PeiServicesInstallPeiMemory (MemoryBase, MemorySize);
163         ASSERT_EFI_ERROR (Status);
164 
165         Attributes |= EFI_RESOURCE_ATTRIBUTE_TESTED;
166       }
167 
168       BuildResourceDescriptorHob (
169         EFI_RESOURCE_SYSTEM_MEMORY,
170         Attributes,
171         MemoryBase,
172         MemorySize
173         );
174     }
175     Index++;
176   } while (!EFI_ERROR (Status));
177 
178   //
179   // Build the CPU hob with 36-bit addressing and 16-bits of IO space.
180   //
181   BuildCpuHob (36, 16);
182 
183   //
184   // Build GUIDed Hob that contains the Memory Type Information array
185   //
186   Status = PeiServicesLocatePpi (
187              &gEfiPeiReadOnlyVariable2PpiGuid,
188              0,
189              NULL,
190              (VOID **)&Variable
191              );
192   ASSERT_EFI_ERROR (Status);
193 
194   DataSize = sizeof (MemoryData);
195   Status = Variable->GetVariable (
196                        Variable,
197                        EFI_MEMORY_TYPE_INFORMATION_VARIABLE_NAME,
198                        &gEfiMemoryTypeInformationGuid,
199                        NULL,
200                        &DataSize,
201                        &MemoryData
202                        );
203   if (EFI_ERROR (Status) || !ValidateMemoryTypeInfoVariable(MemoryData, DataSize)) {
204     //
205     // Create Memory Type Information HOB
206     //
207     BuildGuidDataHob (
208       &gEfiMemoryTypeInformationGuid,
209       mDefaultMemoryTypeInformation,
210       sizeof(mDefaultMemoryTypeInformation)
211       );
212   } else {
213     //
214     // Create Memory Type Information HOB
215     //
216     BuildGuidDataHob (
217       &gEfiMemoryTypeInformationGuid,
218       MemoryData,
219       DataSize
220       );
221   }
222 
223   return Status;
224 }
225