]>
Commit | Line | Data |
---|---|---|
a7a0f78b | 1 | /** @file\r |
2 | This is the driver that produce AcpiVariable hob and slit SmramReserve hob\r | |
3 | for ECP platform.\r | |
4 | \r | |
5 | Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>\r | |
6 | \r | |
7 | This program and the accompanying materials\r | |
8 | are licensed and made available under the terms and conditions\r | |
9 | of the BSD License which accompanies this distribution. The\r | |
10 | full text of the license may be found at\r | |
11 | http://opensource.org/licenses/bsd-license.php\r | |
12 | \r | |
13 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
14 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
15 | \r | |
16 | **/\r | |
17 | \r | |
18 | #include <PiPei.h>\r | |
19 | #include <Guid/SmramMemoryReserve.h>\r | |
1261fe23 | 20 | #include <Guid/AcpiS3Context.h>\r |
a7a0f78b | 21 | \r |
22 | #include <Library/MemoryAllocationLib.h>\r | |
23 | #include <Library/DebugLib.h>\r | |
24 | #include <Library/HobLib.h>\r | |
25 | #include <Library/PeiServicesLib.h>\r | |
26 | #include <Library/BaseMemoryLib.h>\r | |
27 | \r | |
28 | /**\r | |
29 | Retrieves the data structure associated witht he GUIDed HOB of type gEfiSmmPeiSmramMemoryReserveGuid\r | |
30 | \r | |
31 | @retval NULL A HOB of type gEfiSmmPeiSmramMemoryReserveGuid could not be found.\r | |
32 | @retval !NULL A pointer to the GUID data from a HIB of type gEfiSmmPeiSmramMemoryReserveGuid\r | |
33 | \r | |
34 | **/\r | |
35 | EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *\r | |
36 | GetSrmamHobData (\r | |
37 | VOID\r | |
38 | )\r | |
39 | {\r | |
40 | VOID *GuidHob;\r | |
41 | \r | |
42 | //\r | |
43 | // Search SmramMemoryReserve HOB that describes SMRAM region\r | |
44 | //\r | |
45 | GuidHob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);\r | |
46 | if (GuidHob == NULL) {\r | |
47 | return NULL;\r | |
48 | }\r | |
49 | return (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *)GET_GUID_HOB_DATA (GuidHob);\r | |
50 | }\r | |
51 | \r | |
52 | /**\r | |
53 | This routine will split SmramReserve hob to reserve 1 page for SMRAM content in S3 phase\r | |
8598a1ed | 54 | for PI SMM core.\r |
a7a0f78b | 55 | \r |
56 | @retval EFI_SUCCESS The gEfiSmmPeiSmramMemoryReserveGuid is splited successfully.\r | |
57 | @retval EFI_NOT_FOUND The gEfiSmmPeiSmramMemoryReserveGuid is not found.\r | |
58 | \r | |
59 | **/\r | |
60 | EFI_STATUS\r | |
61 | EFIAPI\r | |
62 | SplitSmramReserveHob (\r | |
63 | VOID\r | |
64 | )\r | |
65 | {\r | |
66 | EFI_HOB_GUID_TYPE *GuidHob;\r | |
67 | EFI_PEI_HOB_POINTERS Hob;\r | |
68 | EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;\r | |
69 | EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *NewDescriptorBlock;\r | |
70 | UINTN BufferSize;\r | |
71 | UINTN SmramRanges;\r | |
72 | UINTN Index;\r | |
73 | UINTN SubIndex;\r | |
74 | \r | |
75 | //\r | |
76 | // Retrieve the GUID HOB data that contains the set of SMRAM descriptyors\r | |
77 | //\r | |
78 | GuidHob = GetFirstGuidHob (&gEfiSmmPeiSmramMemoryReserveGuid);\r | |
79 | if (GuidHob == NULL) {\r | |
80 | return EFI_NOT_FOUND;\r | |
81 | }\r | |
82 | \r | |
83 | DescriptorBlock = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *)GET_GUID_HOB_DATA (GuidHob);\r | |
84 | \r | |
85 | //\r | |
86 | // Allocate one extra EFI_SMRAM_DESCRIPTOR to describe a page of SMRAM memory that contains a pointer\r | |
87 | // to the SMM Services Table that is required on the S3 resume path\r | |
88 | //\r | |
89 | SmramRanges = DescriptorBlock->NumberOfSmmReservedRegions;\r | |
90 | BufferSize = sizeof (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK) + (SmramRanges * sizeof (EFI_SMRAM_DESCRIPTOR));\r | |
91 | \r | |
92 | Hob.Raw = BuildGuidHob (\r | |
93 | &gEfiSmmPeiSmramMemoryReserveGuid,\r | |
94 | BufferSize\r | |
95 | );\r | |
96 | ASSERT (Hob.Raw);\r | |
97 | NewDescriptorBlock = (EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *)Hob.Raw;\r | |
98 | \r | |
99 | //\r | |
100 | // Copy old EFI_SMRAM_HOB_DESCRIPTOR_BLOCK to new allocated region\r | |
101 | //\r | |
102 | CopyMem ((VOID *)Hob.Raw, DescriptorBlock, BufferSize - sizeof(EFI_SMRAM_DESCRIPTOR));\r | |
103 | \r | |
104 | //\r | |
105 | // Increase the number of SMRAM descriptors by 1 to make room for the ALLOCATED descriptor of size EFI_PAGE_SIZE\r | |
106 | //\r | |
107 | NewDescriptorBlock->NumberOfSmmReservedRegions = (UINT32)(SmramRanges + 1);\r | |
108 | \r | |
109 | ASSERT (SmramRanges >= 1);\r | |
110 | //\r | |
8598a1ed | 111 | // Copy last entry to the end - we assume TSEG is last entry, which is same assumption as Framework CPU/SMM driver\r |
a7a0f78b | 112 | //\r |
113 | CopyMem (&NewDescriptorBlock->Descriptor[SmramRanges], &NewDescriptorBlock->Descriptor[SmramRanges - 1], sizeof(EFI_SMRAM_DESCRIPTOR));\r | |
114 | \r | |
115 | //\r | |
116 | // Update the last but 1 entry in the array with a size of EFI_PAGE_SIZE and put into the ALLOCATED state\r | |
117 | //\r | |
118 | NewDescriptorBlock->Descriptor[SmramRanges - 1].PhysicalSize = EFI_PAGE_SIZE;\r | |
119 | NewDescriptorBlock->Descriptor[SmramRanges - 1].RegionState |= EFI_ALLOCATED;\r | |
120 | \r | |
121 | //\r | |
122 | // Reduce the size of the last SMRAM descriptor by EFI_PAGE_SIZE \r | |
123 | //\r | |
124 | NewDescriptorBlock->Descriptor[SmramRanges].PhysicalStart += EFI_PAGE_SIZE;\r | |
125 | NewDescriptorBlock->Descriptor[SmramRanges].CpuStart += EFI_PAGE_SIZE;\r | |
126 | NewDescriptorBlock->Descriptor[SmramRanges].PhysicalSize -= EFI_PAGE_SIZE;\r | |
127 | \r | |
128 | //\r | |
8598a1ed | 129 | // Now, we have created SmramReserve Hob for SmmAccess drive. But the issue is that, Framework SmmAccess will assume there is 2 SmramReserve region only.\r |
a7a0f78b | 130 | // Reporting 3 SmramReserve region will cause buffer overflow. Moreover, we would like to filter AB-SEG or H-SEG to avoid SMM cache-poisoning issue.\r |
131 | // So we uses scan SmmReserve Hob to remove AB-SEG or H-SEG.\r | |
132 | //\r | |
133 | for (Index = 0; Index <= SmramRanges; Index++) {\r | |
134 | if (NewDescriptorBlock->Descriptor[Index].PhysicalSize == 0) {\r | |
135 | //\r | |
136 | // Skip zero entry\r | |
137 | //\r | |
138 | continue;\r | |
139 | }\r | |
140 | if (NewDescriptorBlock->Descriptor[Index].PhysicalStart < BASE_1MB) {\r | |
141 | //\r | |
142 | // Find AB-SEG or H-SEG\r | |
143 | // remove this region\r | |
144 | //\r | |
145 | for (SubIndex = Index; SubIndex < NewDescriptorBlock->NumberOfSmmReservedRegions - 1; SubIndex++) {\r | |
146 | CopyMem (&NewDescriptorBlock->Descriptor[SubIndex], &NewDescriptorBlock->Descriptor[SubIndex + 1], sizeof (EFI_SMRAM_DESCRIPTOR));\r | |
147 | }\r | |
148 | //\r | |
149 | // Zero last one\r | |
150 | //\r | |
151 | ZeroMem (&NewDescriptorBlock->Descriptor[SubIndex], sizeof(EFI_SMRAM_DESCRIPTOR));\r | |
152 | //\r | |
153 | // Decrease Number\r | |
154 | //\r | |
155 | NewDescriptorBlock->NumberOfSmmReservedRegions --;\r | |
156 | //\r | |
157 | // Decrease Index to let it test mew entry\r | |
158 | //\r | |
159 | Index --;\r | |
160 | }\r | |
161 | }\r | |
162 | \r | |
163 | //\r | |
164 | // Last step, we can scrub old one\r | |
165 | //\r | |
166 | ZeroMem (&GuidHob->Name, sizeof(GuidHob->Name));\r | |
167 | \r | |
168 | return EFI_SUCCESS;\r | |
169 | }\r | |
170 | \r | |
171 | /**\r | |
172 | This routine will create AcpiVariable hob to point the reserved smram in S3 phase\r | |
8598a1ed | 173 | for PI SMM core.\r |
a7a0f78b | 174 | \r |
175 | @retval EFI_SUCCESS The gEfiAcpiVariableGuid is created successfully.\r | |
176 | @retval EFI_NOT_FOUND The gEfiSmmPeiSmramMemoryReserveGuid is not found.\r | |
177 | \r | |
178 | **/\r | |
179 | EFI_STATUS\r | |
180 | EFIAPI\r | |
181 | CreateAcpiVariableHob (\r | |
182 | VOID\r | |
183 | )\r | |
184 | {\r | |
185 | EFI_PEI_HOB_POINTERS Hob;\r | |
186 | EFI_SMRAM_HOB_DESCRIPTOR_BLOCK *DescriptorBlock;\r | |
187 | UINTN SmramRanges;\r | |
188 | \r | |
189 | //\r | |
190 | // Retrieve the GUID HOB data that contains the set of SMRAM descriptyors\r | |
191 | //\r | |
192 | DescriptorBlock = GetSrmamHobData ();\r | |
193 | if (DescriptorBlock == NULL) {\r | |
194 | return EFI_NOT_FOUND;\r | |
195 | }\r | |
196 | \r | |
197 | Hob.Raw = BuildGuidHob (\r | |
198 | &gEfiAcpiVariableGuid,\r | |
199 | sizeof (EFI_SMRAM_DESCRIPTOR)\r | |
200 | );\r | |
201 | ASSERT (Hob.Raw);\r | |
202 | \r | |
203 | //\r | |
204 | // It should be already patch, so just copy last but 1 region directly.\r | |
205 | //\r | |
206 | SmramRanges = DescriptorBlock->NumberOfSmmReservedRegions;\r | |
207 | ASSERT (SmramRanges >= 2);\r | |
208 | if (SmramRanges >= 2) {\r | |
209 | CopyMem ((VOID *)Hob.Raw, &DescriptorBlock->Descriptor[SmramRanges - 2], sizeof (EFI_SMRAM_DESCRIPTOR));\r | |
210 | }\r | |
211 | \r | |
212 | return EFI_SUCCESS;\r | |
213 | }\r | |
214 | \r | |
215 | /**\r | |
216 | Driver Entry for AcpiVariableHobOnSmramReservHob PEIM\r | |
217 | \r | |
218 | @param FileHandle Handle of the file being invoked.\r | |
219 | @param PeiServices Describes the list of possible PEI Services.\r | |
220 | \r | |
221 | @retval EFI_SUCCESS Success create gEfiAcpiVariableGuid and\r | |
222 | split gEfiSmmPeiSmramMemoryReserveGuid.\r | |
223 | @retval EFI_NOT_FOUND Can not get gEfiSmmPeiSmramMemoryReserveGuid hob\r | |
224 | \r | |
225 | **/\r | |
226 | EFI_STATUS\r | |
227 | EFIAPI\r | |
228 | AcpiVariableHobEntry (\r | |
229 | IN EFI_PEI_FILE_HANDLE FileHandle,\r | |
230 | IN CONST EFI_PEI_SERVICES **PeiServices\r | |
231 | )\r | |
232 | {\r | |
233 | EFI_STATUS Status;\r | |
234 | \r | |
235 | //\r | |
8598a1ed | 236 | // Split SmramReserve hob, which is required for PI SMM Core for S3.\r |
a7a0f78b | 237 | //\r |
238 | Status = SplitSmramReserveHob ();\r | |
239 | if (EFI_ERROR (Status)) {\r | |
240 | return Status;\r | |
241 | }\r | |
242 | \r | |
243 | //\r | |
8598a1ed | 244 | // Create AcpiVariable hob, which is required for PI SMM Core for S3.\r |
a7a0f78b | 245 | //\r |
246 | Status = CreateAcpiVariableHob ();\r | |
247 | \r | |
248 | return Status;\r | |
249 | }\r |