]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Csm/CsmSupportLib/LegacyRegion.c
OvmfPkg: SmmCpuFeaturesLib: remove unnecessary bits
[mirror_edk2.git] / OvmfPkg / Csm / CsmSupportLib / LegacyRegion.c
CommitLineData
8016da21 1/** @file\r
2 Legacy Region Support\r
3\r
4 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>\r
5\r
6 This program and the accompanying materials are\r
7 licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "LegacyRegion.h"\r
17\r
18//\r
19// 440 PAM map.\r
20//\r
21// PAM Range Offset Bits Operation\r
22// =============== ====== ==== ===============================================================\r
23// 0xC0000-0xC3FFF 0x5a 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
24// 0xC4000-0xC7FFF 0x5a 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
25// 0xC8000-0xCBFFF 0x5b 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
26// 0xCC000-0xCFFFF 0x5b 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
27// 0xD0000-0xD3FFF 0x5c 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
28// 0xD4000-0xD7FFF 0x5c 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
29// 0xD8000-0xDBFFF 0x5d 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
30// 0xDC000-0xDFFFF 0x5d 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
31// 0xE0000-0xE3FFF 0x5e 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
32// 0xE4000-0xE7FFF 0x5e 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
33// 0xE8000-0xEBFFF 0x5f 1:0 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
34// 0xEC000-0xEFFFF 0x5f 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
35// 0xF0000-0xFFFFF 0x59 5:4 00 = DRAM Disabled, 01= Read Only, 10 = Write Only, 11 = Normal\r
36//\r
37STATIC LEGACY_MEMORY_SECTION_INFO mSectionArray[] = {\r
38 {0xC0000, SIZE_16KB, FALSE, FALSE},\r
39 {0xC4000, SIZE_16KB, FALSE, FALSE},\r
40 {0xC8000, SIZE_16KB, FALSE, FALSE},\r
41 {0xCC000, SIZE_16KB, FALSE, FALSE},\r
42 {0xD0000, SIZE_16KB, FALSE, FALSE},\r
43 {0xD4000, SIZE_16KB, FALSE, FALSE},\r
44 {0xD8000, SIZE_16KB, FALSE, FALSE},\r
45 {0xDC000, SIZE_16KB, FALSE, FALSE},\r
46 {0xE0000, SIZE_16KB, FALSE, FALSE},\r
47 {0xE4000, SIZE_16KB, FALSE, FALSE},\r
48 {0xE8000, SIZE_16KB, FALSE, FALSE},\r
49 {0xEC000, SIZE_16KB, FALSE, FALSE},\r
50 {0xF0000, SIZE_64KB, FALSE, FALSE}\r
51};\r
52\r
53STATIC PAM_REGISTER_VALUE mRegisterValues[] = {\r
54 {REG_PAM1_OFFSET, 0x01, 0x02},\r
55 {REG_PAM1_OFFSET, 0x10, 0x20},\r
56 {REG_PAM2_OFFSET, 0x01, 0x02},\r
57 {REG_PAM2_OFFSET, 0x10, 0x20},\r
58 {REG_PAM3_OFFSET, 0x01, 0x02},\r
59 {REG_PAM3_OFFSET, 0x10, 0x20},\r
60 {REG_PAM4_OFFSET, 0x01, 0x02},\r
61 {REG_PAM4_OFFSET, 0x10, 0x20},\r
62 {REG_PAM5_OFFSET, 0x01, 0x02},\r
63 {REG_PAM5_OFFSET, 0x10, 0x20},\r
64 {REG_PAM6_OFFSET, 0x01, 0x02},\r
65 {REG_PAM6_OFFSET, 0x10, 0x20},\r
66 {REG_PAM0_OFFSET, 0x10, 0x20}\r
67};\r
68\r
69//\r
70// Handle used to install the Legacy Region Protocol\r
71//\r
72STATIC EFI_HANDLE mHandle = NULL;\r
73\r
74//\r
75// Instance of the Legacy Region Protocol to install into the handle database\r
76//\r
77STATIC EFI_LEGACY_REGION2_PROTOCOL mLegacyRegion2 = {\r
78 LegacyRegion2Decode,\r
79 LegacyRegion2Lock,\r
80 LegacyRegion2BootLock,\r
81 LegacyRegion2Unlock,\r
82 LegacyRegionGetInfo\r
83};\r
84\r
85STATIC\r
86EFI_STATUS\r
87LegacyRegionManipulationInternal (\r
88 IN UINT32 Start,\r
89 IN UINT32 Length,\r
90 IN BOOLEAN *ReadEnable,\r
91 IN BOOLEAN *WriteEnable,\r
92 OUT UINT32 *Granularity\r
93 )\r
94{\r
95 UINT32 EndAddress;\r
96 UINTN Index;\r
97 UINTN StartIndex;\r
98\r
99 //\r
100 // Validate input parameters.\r
101 //\r
102 if (Length == 0 || Granularity == NULL) {\r
103 return EFI_INVALID_PARAMETER;\r
104 }\r
105 EndAddress = Start + Length - 1;\r
106 if ((Start < PAM_BASE_ADDRESS) || EndAddress > PAM_LIMIT_ADDRESS) {\r
107 return EFI_INVALID_PARAMETER;\r
108 }\r
109\r
110 //\r
111 // Loop to find the start PAM.\r
112 //\r
113 StartIndex = 0;\r
114 for (Index = 0; Index < (sizeof(mSectionArray) / sizeof (mSectionArray[0])); Index++) {\r
115 if ((Start >= mSectionArray[Index].Start) && (Start < (mSectionArray[Index].Start + mSectionArray[Index].Length))) {\r
116 StartIndex = Index;\r
117 break;\r
118 }\r
119 }\r
120 ASSERT (Index < (sizeof(mSectionArray) / sizeof (mSectionArray[0])));\r
121\r
122 //\r
123 // Program PAM until end PAM is encountered\r
124 //\r
125 for (Index = StartIndex; Index < (sizeof(mSectionArray) / sizeof (mSectionArray[0])); Index++) {\r
126 if (ReadEnable != NULL) {\r
127 if (*ReadEnable) {\r
128 PciOr8 (\r
129 PCI_LIB_ADDRESS(PAM_PCI_BUS, PAM_PCI_DEV, PAM_PCI_FUNC, mRegisterValues[Index].PAMRegOffset),\r
130 mRegisterValues[Index].ReadEnableData\r
131 );\r
132 } else {\r
133 PciAnd8 (\r
134 PCI_LIB_ADDRESS(PAM_PCI_BUS, PAM_PCI_DEV, PAM_PCI_FUNC, mRegisterValues[Index].PAMRegOffset),\r
135 (UINT8) (~mRegisterValues[Index].ReadEnableData)\r
136 );\r
137 }\r
138 }\r
139 if (WriteEnable != NULL) {\r
140 if (*WriteEnable) {\r
141 PciOr8 (\r
142 PCI_LIB_ADDRESS(PAM_PCI_BUS, PAM_PCI_DEV, PAM_PCI_FUNC, mRegisterValues[Index].PAMRegOffset),\r
143 mRegisterValues[Index].WriteEnableData\r
144 );\r
145 } else {\r
146 PciAnd8 (\r
147 PCI_LIB_ADDRESS(PAM_PCI_BUS, PAM_PCI_DEV, PAM_PCI_FUNC, mRegisterValues[Index].PAMRegOffset),\r
148 (UINT8) (~mRegisterValues[Index].WriteEnableData)\r
149 );\r
150 }\r
151 }\r
152\r
153 //\r
154 // If the end PAM is encountered, record its length as granularity and jump out.\r
155 //\r
156 if ((EndAddress >= mSectionArray[Index].Start) && (EndAddress < (mSectionArray[Index].Start + mSectionArray[Index].Length))) {\r
157 *Granularity = mSectionArray[Index].Length;\r
158 break;\r
159 }\r
160 }\r
161 ASSERT (Index < (sizeof(mSectionArray) / sizeof (mSectionArray[0])));\r
162\r
163 return EFI_SUCCESS;\r
164}\r
165\r
166STATIC\r
167EFI_STATUS\r
168LegacyRegionGetInfoInternal (\r
169 OUT UINT32 *DescriptorCount,\r
170 OUT LEGACY_MEMORY_SECTION_INFO **Descriptor\r
171 )\r
172{\r
173 UINTN Index;\r
174 UINT8 PamValue;\r
175\r
176 //\r
177 // Check input parameters\r
178 //\r
179 if (DescriptorCount == NULL || Descriptor == NULL) {\r
180 return EFI_INVALID_PARAMETER;\r
181 }\r
182\r
183 //\r
184 // Fill in current status of legacy region.\r
185 //\r
186 *DescriptorCount = sizeof(mSectionArray) / sizeof (mSectionArray[0]);\r
187 for (Index = 0; Index < *DescriptorCount; Index++) {\r
188 PamValue = PciRead8 (PCI_LIB_ADDRESS(PAM_PCI_BUS, PAM_PCI_DEV, PAM_PCI_FUNC, mRegisterValues[Index].PAMRegOffset));\r
189 mSectionArray[Index].ReadEnabled = FALSE;\r
190 if ((PamValue & mRegisterValues[Index].ReadEnableData) != 0) {\r
191 mSectionArray[Index].ReadEnabled = TRUE;\r
192 }\r
193 mSectionArray[Index].WriteEnabled = FALSE;\r
194 if ((PamValue & mRegisterValues[Index].WriteEnableData) != 0) {\r
195 mSectionArray[Index].WriteEnabled = TRUE;\r
196 }\r
197 }\r
198\r
199 *Descriptor = mSectionArray;\r
200 return EFI_SUCCESS;\r
201}\r
202\r
203/**\r
204 Modify the hardware to allow (decode) or disallow (not decode) memory reads in a region.\r
205\r
206 If the On parameter evaluates to TRUE, this function enables memory reads in the address range\r
207 Start to (Start + Length - 1).\r
208 If the On parameter evaluates to FALSE, this function disables memory reads in the address range\r
209 Start to (Start + Length - 1).\r
210\r
211 @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
212 @param Start[in] The beginning of the physical address of the region whose attributes\r
213 should be modified.\r
214 @param Length[in] The number of bytes of memory whose attributes should be modified.\r
215 The actual number of bytes modified may be greater than the number\r
216 specified.\r
217 @param Granularity[out] The number of bytes in the last region affected. This may be less\r
218 than the total number of bytes affected if the starting address\r
219 was not aligned to a region's starting address or if the length\r
220 was greater than the number of bytes in the first region.\r
221 @param On[in] Decode / Non-Decode flag.\r
222\r
223 @retval EFI_SUCCESS The region's attributes were successfully modified.\r
224 @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
225\r
226**/\r
227EFI_STATUS\r
228EFIAPI\r
229LegacyRegion2Decode (\r
230 IN EFI_LEGACY_REGION2_PROTOCOL *This,\r
231 IN UINT32 Start,\r
232 IN UINT32 Length,\r
233 OUT UINT32 *Granularity,\r
234 IN BOOLEAN *On\r
235 )\r
236{\r
237 return LegacyRegionManipulationInternal (Start, Length, On, NULL, Granularity);\r
238}\r
239\r
240\r
241/**\r
242 Modify the hardware to disallow memory attribute changes in a region.\r
243\r
244 This function makes the attributes of a region read only. Once a region is boot-locked with this\r
245 function, the read and write attributes of that region cannot be changed until a power cycle has\r
246 reset the boot-lock attribute. Calls to Decode(), Lock() and Unlock() will have no effect.\r
247\r
248 @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
249 @param Start[in] The beginning of the physical address of the region whose\r
250 attributes should be modified.\r
251 @param Length[in] The number of bytes of memory whose attributes should be modified.\r
252 The actual number of bytes modified may be greater than the number\r
253 specified.\r
254 @param Granularity[out] The number of bytes in the last region affected. This may be less\r
255 than the total number of bytes affected if the starting address was\r
256 not aligned to a region's starting address or if the length was\r
257 greater than the number of bytes in the first region.\r
258\r
259 @retval EFI_SUCCESS The region's attributes were successfully modified.\r
260 @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
261 @retval EFI_UNSUPPORTED The chipset does not support locking the configuration registers in\r
262 a way that will not affect memory regions outside the legacy memory\r
263 region.\r
264\r
265**/\r
266EFI_STATUS\r
267EFIAPI\r
268LegacyRegion2BootLock (\r
269 IN EFI_LEGACY_REGION2_PROTOCOL *This,\r
270 IN UINT32 Start,\r
271 IN UINT32 Length,\r
272 OUT UINT32 *Granularity\r
273 )\r
274{\r
275 if ((Start < 0xC0000) || ((Start + Length - 1) > 0xFFFFF)) {\r
276 return EFI_INVALID_PARAMETER;\r
277 }\r
278\r
279 return EFI_UNSUPPORTED;\r
280}\r
281\r
282\r
283/**\r
284 Modify the hardware to disallow memory writes in a region.\r
285\r
286 This function changes the attributes of a memory range to not allow writes.\r
287\r
288 @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
289 @param Start[in] The beginning of the physical address of the region whose\r
290 attributes should be modified.\r
291 @param Length[in] The number of bytes of memory whose attributes should be modified.\r
292 The actual number of bytes modified may be greater than the number\r
293 specified.\r
294 @param Granularity[out] The number of bytes in the last region affected. This may be less\r
295 than the total number of bytes affected if the starting address was\r
296 not aligned to a region's starting address or if the length was\r
297 greater than the number of bytes in the first region.\r
298\r
299 @retval EFI_SUCCESS The region's attributes were successfully modified.\r
300 @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
301\r
302**/\r
303EFI_STATUS\r
304EFIAPI\r
305LegacyRegion2Lock (\r
306 IN EFI_LEGACY_REGION2_PROTOCOL *This,\r
307 IN UINT32 Start,\r
308 IN UINT32 Length,\r
309 OUT UINT32 *Granularity\r
310 )\r
311{\r
312 BOOLEAN WriteEnable;\r
313\r
314 WriteEnable = FALSE;\r
315 return LegacyRegionManipulationInternal (Start, Length, NULL, &WriteEnable, Granularity);\r
316}\r
317\r
318\r
319/**\r
320 Modify the hardware to allow memory writes in a region.\r
321\r
322 This function changes the attributes of a memory range to allow writes.\r
323\r
324 @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
325 @param Start[in] The beginning of the physical address of the region whose\r
326 attributes should be modified.\r
327 @param Length[in] The number of bytes of memory whose attributes should be modified.\r
328 The actual number of bytes modified may be greater than the number\r
329 specified.\r
330 @param Granularity[out] The number of bytes in the last region affected. This may be less\r
331 than the total number of bytes affected if the starting address was\r
332 not aligned to a region's starting address or if the length was\r
333 greater than the number of bytes in the first region.\r
334\r
335 @retval EFI_SUCCESS The region's attributes were successfully modified.\r
336 @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
337\r
338**/\r
339EFI_STATUS\r
340EFIAPI\r
341LegacyRegion2Unlock (\r
342 IN EFI_LEGACY_REGION2_PROTOCOL *This,\r
343 IN UINT32 Start,\r
344 IN UINT32 Length,\r
345 OUT UINT32 *Granularity\r
346 )\r
347{\r
348 BOOLEAN WriteEnable;\r
349\r
350 WriteEnable = TRUE;\r
351 return LegacyRegionManipulationInternal (Start, Length, NULL, &WriteEnable, Granularity);\r
352}\r
353\r
354/**\r
355 Get region information for the attributes of the Legacy Region.\r
356\r
357 This function is used to discover the granularity of the attributes for the memory in the legacy\r
358 region. Each attribute may have a different granularity and the granularity may not be the same\r
359 for all memory ranges in the legacy region.\r
360\r
361 @param This[in] Indicates the EFI_LEGACY_REGION_PROTOCOL instance.\r
362 @param DescriptorCount[out] The number of region descriptor entries returned in the Descriptor\r
363 buffer.\r
364 @param Descriptor[out] A pointer to a pointer used to return a buffer where the legacy\r
365 region information is deposited. This buffer will contain a list of\r
366 DescriptorCount number of region descriptors. This function will\r
367 provide the memory for the buffer.\r
368\r
369 @retval EFI_SUCCESS The region's attributes were successfully modified.\r
370 @retval EFI_INVALID_PARAMETER If Start or Length describe an address not in the Legacy Region.\r
371\r
372**/\r
373EFI_STATUS\r
374EFIAPI\r
375LegacyRegionGetInfo (\r
376 IN EFI_LEGACY_REGION2_PROTOCOL *This,\r
377 OUT UINT32 *DescriptorCount,\r
378 OUT EFI_LEGACY_REGION_DESCRIPTOR **Descriptor\r
379 )\r
380{\r
381 LEGACY_MEMORY_SECTION_INFO *SectionInfo;\r
382 UINT32 SectionCount;\r
383 EFI_LEGACY_REGION_DESCRIPTOR *DescriptorArray;\r
384 UINTN Index;\r
385 UINTN DescriptorIndex;\r
386\r
387 //\r
388 // Get section numbers and information\r
389 //\r
390 LegacyRegionGetInfoInternal (&SectionCount, &SectionInfo);\r
391\r
392 //\r
393 // Each section has 3 descriptors, corresponding to readability, writeability, and lock status.\r
394 //\r
395 DescriptorArray = AllocatePool (sizeof (EFI_LEGACY_REGION_DESCRIPTOR) * SectionCount * 3);\r
396 if (DescriptorArray == NULL) {\r
397 return EFI_OUT_OF_RESOURCES;\r
398 }\r
399\r
400 DescriptorIndex = 0;\r
401 for (Index = 0; Index < SectionCount; Index++) {\r
402 DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start;\r
403 DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length;\r
404 DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length;\r
405 if (SectionInfo[Index].ReadEnabled) {\r
406 DescriptorArray[DescriptorIndex].Attribute = LegacyRegionDecoded;\r
407 } else {\r
408 DescriptorArray[DescriptorIndex].Attribute = LegacyRegionNotDecoded;\r
409 }\r
410 DescriptorIndex++;\r
411\r
412 //\r
413 // Create descriptor for writeability, according to lock status\r
414 //\r
415 DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start;\r
416 DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length;\r
417 DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length;\r
418 if (SectionInfo[Index].WriteEnabled) {\r
419 DescriptorArray[DescriptorIndex].Attribute = LegacyRegionWriteEnabled;\r
420 } else {\r
421 DescriptorArray[DescriptorIndex].Attribute = LegacyRegionWriteDisabled;\r
422 }\r
423 DescriptorIndex++;\r
424\r
425 //\r
426 // Chipset does not support bootlock.\r
427 //\r
428 DescriptorArray[DescriptorIndex].Start = SectionInfo[Index].Start;\r
429 DescriptorArray[DescriptorIndex].Length = SectionInfo[Index].Length;\r
430 DescriptorArray[DescriptorIndex].Granularity = SectionInfo[Index].Length;\r
431 DescriptorArray[DescriptorIndex].Attribute = LegacyRegionNotLocked;\r
432 DescriptorIndex++;\r
433 }\r
434\r
435 *DescriptorCount = (UINT32) DescriptorIndex;\r
436 *Descriptor = DescriptorArray;\r
437\r
438 return EFI_SUCCESS;\r
439}\r
440\r
441/**\r
442 Initialize Legacy Region support\r
443\r
444 @retval EFI_SUCCESS Successfully initialized\r
445\r
446**/\r
447EFI_STATUS\r
448LegacyRegionInit (\r
449 VOID\r
450 )\r
451{\r
452 EFI_STATUS Status;\r
453\r
454 //\r
455 // Install the Legacy Region Protocol on a new handle\r
456 //\r
457 Status = gBS->InstallMultipleProtocolInterfaces (\r
458 &mHandle,\r
459 &gEfiLegacyRegion2ProtocolGuid, &mLegacyRegion2,\r
460 NULL\r
461 );\r
462 ASSERT_EFI_ERROR (Status);\r
463\r
464 return Status;\r
465}\r
466\r