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