4 Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
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
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.
16 #include "LegacyRegion.h"
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
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
}
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}
70 // Handle used to install the Legacy Region Protocol
72 STATIC EFI_HANDLE mHandle
= NULL
;
75 // Instance of the Legacy Region Protocol to install into the handle database
77 STATIC EFI_LEGACY_REGION2_PROTOCOL mLegacyRegion2
= {
80 LegacyRegion2BootLock
,
87 LegacyRegionManipulationInternal (
90 IN BOOLEAN
*ReadEnable
,
91 IN BOOLEAN
*WriteEnable
,
92 OUT UINT32
*Granularity
100 // Validate input parameters.
102 if (Length
== 0 || Granularity
== NULL
) {
103 return EFI_INVALID_PARAMETER
;
105 EndAddress
= Start
+ Length
- 1;
106 if ((Start
< PAM_BASE_ADDRESS
) || EndAddress
> PAM_LIMIT_ADDRESS
) {
107 return EFI_INVALID_PARAMETER
;
111 // Loop to find the start PAM.
114 for (Index
= 0; Index
< (sizeof(mSectionArray
) / sizeof (mSectionArray
[0])); Index
++) {
115 if ((Start
>= mSectionArray
[Index
].Start
) && (Start
< (mSectionArray
[Index
].Start
+ mSectionArray
[Index
].Length
))) {
120 ASSERT (Index
< (sizeof(mSectionArray
) / sizeof (mSectionArray
[0])));
123 // Program PAM until end PAM is encountered
125 for (Index
= StartIndex
; Index
< (sizeof(mSectionArray
) / sizeof (mSectionArray
[0])); Index
++) {
126 if (ReadEnable
!= NULL
) {
129 PCI_LIB_ADDRESS(PAM_PCI_BUS
, PAM_PCI_DEV
, PAM_PCI_FUNC
, mRegisterValues
[Index
].PAMRegOffset
),
130 mRegisterValues
[Index
].ReadEnableData
134 PCI_LIB_ADDRESS(PAM_PCI_BUS
, PAM_PCI_DEV
, PAM_PCI_FUNC
, mRegisterValues
[Index
].PAMRegOffset
),
135 (UINT8
) (~mRegisterValues
[Index
].ReadEnableData
)
139 if (WriteEnable
!= NULL
) {
142 PCI_LIB_ADDRESS(PAM_PCI_BUS
, PAM_PCI_DEV
, PAM_PCI_FUNC
, mRegisterValues
[Index
].PAMRegOffset
),
143 mRegisterValues
[Index
].WriteEnableData
147 PCI_LIB_ADDRESS(PAM_PCI_BUS
, PAM_PCI_DEV
, PAM_PCI_FUNC
, mRegisterValues
[Index
].PAMRegOffset
),
148 (UINT8
) (~mRegisterValues
[Index
].WriteEnableData
)
154 // If the end PAM is encountered, record its length as granularity and jump out.
156 if ((EndAddress
>= mSectionArray
[Index
].Start
) && (EndAddress
< (mSectionArray
[Index
].Start
+ mSectionArray
[Index
].Length
))) {
157 *Granularity
= mSectionArray
[Index
].Length
;
161 ASSERT (Index
< (sizeof(mSectionArray
) / sizeof (mSectionArray
[0])));
168 LegacyRegionGetInfoInternal (
169 OUT UINT32
*DescriptorCount
,
170 OUT LEGACY_MEMORY_SECTION_INFO
**Descriptor
177 // Check input parameters
179 if (DescriptorCount
== NULL
|| Descriptor
== NULL
) {
180 return EFI_INVALID_PARAMETER
;
184 // Fill in current status of legacy region.
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
;
193 mSectionArray
[Index
].WriteEnabled
= FALSE
;
194 if ((PamValue
& mRegisterValues
[Index
].WriteEnableData
) != 0) {
195 mSectionArray
[Index
].WriteEnabled
= TRUE
;
199 *Descriptor
= mSectionArray
;
204 Modify the hardware to allow (decode) or disallow (not decode) memory reads in a region.
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).
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
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
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.
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.
229 LegacyRegion2Decode (
230 IN EFI_LEGACY_REGION2_PROTOCOL
*This
,
233 OUT UINT32
*Granularity
,
237 return LegacyRegionManipulationInternal (Start
, Length
, On
, NULL
, Granularity
);
242 Modify the hardware to disallow memory attribute changes in a region.
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.
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
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.
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
268 LegacyRegion2BootLock (
269 IN EFI_LEGACY_REGION2_PROTOCOL
*This
,
272 OUT UINT32
*Granularity
275 if ((Start
< 0xC0000) || ((Start
+ Length
- 1) > 0xFFFFF)) {
276 return EFI_INVALID_PARAMETER
;
279 return EFI_UNSUPPORTED
;
284 Modify the hardware to disallow memory writes in a region.
286 This function changes the attributes of a memory range to not allow writes.
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
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.
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.
306 IN EFI_LEGACY_REGION2_PROTOCOL
*This
,
309 OUT UINT32
*Granularity
315 return LegacyRegionManipulationInternal (Start
, Length
, NULL
, &WriteEnable
, Granularity
);
320 Modify the hardware to allow memory writes in a region.
322 This function changes the attributes of a memory range to allow writes.
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
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.
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.
341 LegacyRegion2Unlock (
342 IN EFI_LEGACY_REGION2_PROTOCOL
*This
,
345 OUT UINT32
*Granularity
351 return LegacyRegionManipulationInternal (Start
, Length
, NULL
, &WriteEnable
, Granularity
);
355 Get region information for the attributes of the Legacy Region.
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.
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
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.
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.
375 LegacyRegionGetInfo (
376 IN EFI_LEGACY_REGION2_PROTOCOL
*This
,
377 OUT UINT32
*DescriptorCount
,
378 OUT EFI_LEGACY_REGION_DESCRIPTOR
**Descriptor
381 LEGACY_MEMORY_SECTION_INFO
*SectionInfo
;
383 EFI_LEGACY_REGION_DESCRIPTOR
*DescriptorArray
;
385 UINTN DescriptorIndex
;
388 // Get section numbers and information
390 LegacyRegionGetInfoInternal (&SectionCount
, &SectionInfo
);
393 // Each section has 3 descriptors, corresponding to readability, writeability, and lock status.
395 DescriptorArray
= AllocatePool (sizeof (EFI_LEGACY_REGION_DESCRIPTOR
) * SectionCount
* 3);
396 if (DescriptorArray
== NULL
) {
397 return EFI_OUT_OF_RESOURCES
;
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
;
408 DescriptorArray
[DescriptorIndex
].Attribute
= LegacyRegionNotDecoded
;
413 // Create descriptor for writeability, according to lock status
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
;
421 DescriptorArray
[DescriptorIndex
].Attribute
= LegacyRegionWriteDisabled
;
426 // Chipset does not support bootlock.
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
;
435 *DescriptorCount
= (UINT32
) DescriptorIndex
;
436 *Descriptor
= DescriptorArray
;
442 Initialize Legacy Region support
444 @retval EFI_SUCCESS Successfully initialized
455 // Install the Legacy Region Protocol on a new handle
457 Status
= gBS
->InstallMultipleProtocolInterfaces (
459 &gEfiLegacyRegion2ProtocolGuid
, &mLegacyRegion2
,
462 ASSERT_EFI_ERROR (Status
);